dm9000e.c 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342
  1. /*
  2. * Copyright (C) 2008 by egnite GmbH. All rights reserved.
  3. * Copyright (C) 2003-2005 by egnite Software GmbH. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the copyright holders nor the names of
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  22. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  23. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  24. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  25. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  26. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  27. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  28. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. * SUCH DAMAGE.
  30. *
  31. * For additional information see http://www.ethernut.de/
  32. *
  33. */
  34. /*
  35. * $Log$
  36. * Revision 1.12 2009/02/06 15:37:39 haraldkipp
  37. * Added stack space multiplier and addend. Adjusted stack space.
  38. *
  39. * Revision 1.11 2008/08/28 11:12:15 haraldkipp
  40. * Added interface flags, which will be required to implement Ethernet ioctl
  41. * functions.
  42. *
  43. * Revision 1.10 2008/08/11 06:59:07 haraldkipp
  44. * BSD types replaced by stdint types (feature request #1282721).
  45. *
  46. * Revision 1.9 2008/02/15 17:09:44 haraldkipp
  47. * Added support for the Elektor Internet Radio.
  48. *
  49. * Revision 1.8 2007/08/17 11:43:46 haraldkipp
  50. * Enable multicast.
  51. *
  52. * Revision 1.7 2007/05/24 07:26:44 haraldkipp
  53. * Added some delay befor reading the status of the received packet. Fixes
  54. * bug #1672527, thanks to Andreas Helmcke.
  55. *
  56. * Revision 1.6 2007/05/02 11:22:51 haraldkipp
  57. * Added multicast table entry.
  58. *
  59. * Revision 1.5 2006/06/28 17:10:15 haraldkipp
  60. * Include more general header file for ARM.
  61. *
  62. * Revision 1.4 2006/03/16 19:04:48 haraldkipp
  63. * Adding a short delay before reading the status word makes it work with
  64. * compiler optimization. On receiver overflow interrupts the chip is
  65. * declared insane. The output routine will no more enter NutEventWait()
  66. * on insane chips.
  67. *
  68. * Revision 1.3 2006/03/02 19:51:16 haraldkipp
  69. * Replaced GCC specific inline specifications with their portable
  70. * counterparts.
  71. *
  72. * Revision 1.2 2006/01/23 17:33:14 haraldkipp
  73. * Possible memory alignment problem may start network interface too early.
  74. *
  75. * Revision 1.1 2005/10/24 08:49:05 haraldkipp
  76. * Initial check in.
  77. *
  78. */
  79. #include <cfg/os.h>
  80. #include <arch/arm.h>
  81. #include <string.h>
  82. #include <stdlib.h>
  83. #include <sys/atom.h>
  84. #include <sys/heap.h>
  85. #include <sys/thread.h>
  86. #include <sys/event.h>
  87. #include <sys/timer.h>
  88. #include <sys/confnet.h>
  89. #include <netinet/if_ether.h>
  90. #include <net/ether.h>
  91. #include <net/if_var.h>
  92. #include <dev/irqreg.h>
  93. #include <dev/phy.h>
  94. #include <dev/dm9000e.h>
  95. /* WARNING: Variadic macros are C99 and may fail with C89 compilers. */
  96. #ifdef NUTDEBUG
  97. #include <stdio.h>
  98. #define DMPRINTF(args,...) printf(args,##__VA_ARGS__)
  99. #else
  100. #define DMPRINTF(args,...)
  101. #endif
  102. #ifndef NUT_THREAD_NICRXSTACK
  103. /* arm-elf-gcc size optimized code used 160 bytes. */
  104. #define NUT_THREAD_NICRXSTACK 384
  105. #endif
  106. /*
  107. * Determine ports, which had not been explicitely configured.
  108. */
  109. #if defined(ETHERNUT3)
  110. #ifndef NIC_BASE_ADDR
  111. #define NIC_BASE_ADDR 0x20000000
  112. #endif
  113. #ifndef NIC_SIGNAL_IRQ
  114. #define NIC_SIGNAL_IRQ INT1
  115. #endif
  116. #ifndef NIC_SIGNAL_PDR
  117. #define NIC_SIGNAL_PDR PIO_PDR
  118. #endif
  119. #ifndef NIC_SIGNAL_BIT
  120. #define NIC_SIGNAL_BIT 10
  121. #endif
  122. #elif defined(ELEKTOR_IR1)
  123. #ifndef NIC_BASE_ADDR
  124. #define NIC_BASE_ADDR 0x30000000
  125. #endif
  126. #ifndef NIC_SIGNAL_IRQ
  127. #define NIC_SIGNAL_IRQ INT0
  128. #endif
  129. #ifndef NIC_SIGNAL_PDR
  130. #define NIC_SIGNAL_PDR PIOB_PDR
  131. #endif
  132. #ifndef NIC_SIGNAL_XSR
  133. #define NIC_SIGNAL_XSR PIOB_ASR
  134. #endif
  135. #ifndef NIC_SIGNAL_BIT
  136. #define NIC_SIGNAL_BIT PB20_IRQ0_A
  137. #endif
  138. #endif
  139. #ifdef NIC_BASE_ADDR
  140. #ifndef NIC_DATA_ADDR
  141. #define NIC_DATA_ADDR (NIC_BASE_ADDR + 4)
  142. #endif
  143. #define INT0 0
  144. #define INT1 1
  145. #define INT2 2
  146. #define INT3 3
  147. #define INT4 4
  148. #define INT5 5
  149. #define INT6 6
  150. #define INT7 7
  151. #ifdef NIC_RESET_BIT
  152. #if (NIC_RESET_AVRPORT == AVRPORTB)
  153. #define NIC_RESET_PORT PORTB
  154. #define NIC_RESET_DDR DDRB
  155. #elif (NIC_RESET_AVRPORT == AVRPORTD)
  156. #define NIC_RESET_PORT PORTD
  157. #define NIC_RESET_DDR DDRD
  158. #elif (NIC_RESET_AVRPORT == AVRPORTE)
  159. #define NIC_RESET_PORT PORTE
  160. #define NIC_RESET_DDR DDRE
  161. #elif (NIC_RESET_AVRPORT == AVRPORTF)
  162. #define NIC_RESET_PORT PORTF
  163. #define NIC_RESET_DDR DDRF
  164. #endif /* NIC_RESET_AVRPORT */
  165. #endif /* NIC_RESET_BIT */
  166. /*
  167. * Determine interrupt settings.
  168. * DOES NOT WORK
  169. */
  170. #if (NIC_SIGNAL_IRQ == INT0)
  171. #define NIC_SIGNAL sig_INTERRUPT0
  172. #elif (NIC_SIGNAL_IRQ == INT2)
  173. #define NIC_SIGNAL sig_INTERRUPT2
  174. #elif (NIC_SIGNAL_IRQ == INT3)
  175. #define NIC_SIGNAL sig_INTERRUPT3
  176. #elif (NIC_SIGNAL_IRQ == INT4)
  177. #define NIC_SIGNAL sig_INTERRUPT4
  178. #elif (NIC_SIGNAL_IRQ == INT5)
  179. #define NIC_SIGNAL sig_INTERRUPT5
  180. #elif (NIC_SIGNAL_IRQ == INT6)
  181. #define NIC_SIGNAL sig_INTERRUPT6
  182. #elif (NIC_SIGNAL_IRQ == INT7)
  183. #define NIC_SIGNAL sig_INTERRUPT7
  184. #else
  185. #define NIC_SIGNAL sig_INTERRUPT1
  186. #endif
  187. /*!
  188. * \addtogroup xgDm9000eRegs
  189. */
  190. /*@{*/
  191. #define NIC_NCR 0x00 /* Network control register (0x00). */
  192. #define NIC_NCR_LBM 0x06 /* Loopback mode. */
  193. #define NIC_NCR_LBNORM 0x00 /* Normal mode. */
  194. #define NIC_NCR_LBMAC 0x02 /* MAC loopback. */
  195. #define NIC_NCR_LBPHY 0x04 /* PHY loopback. */
  196. #define NIC_NCR_RST 0x01 /* Software reset, auto clear. */
  197. #define NIC_NSR 0x01 /* Network status register (0x00). */
  198. #define NIC_NSR_SPEED 0x80
  199. #define NIC_NSR_LINKST 0x40
  200. #define NIC_NSR_WAKEST 0x20
  201. #define NIC_NSR_TX2END 0x08
  202. #define NIC_NSR_TX1END 0x04
  203. #define NIC_NSR_RXOV 0x02
  204. #define NIC_TCR 0x02 /* TX control register (0x00). */
  205. #define NIC_TCR_TXREQ 0x01 /* TX request */
  206. #define NIC_TSR1 0x03 /* TX status register I (0x00). */
  207. #define NIC_TSR2 0x04 /* TX status register II (0x00). */
  208. #define NIC_RCR 0x05 /* RX control register (0x00). */
  209. #define NIC_RCR_DIS_LONG 0x20 /* Discard long packets. */
  210. #define NIC_RCR_DIS_CRC 0x10 /* Discard CRC error packets. */
  211. #define NIC_RCR_ALL 0x08 /* Pass all multicast */
  212. #define NIC_RCR_PRMSC 0x02 /* Enable promiscuous mode. */
  213. #define NIC_RCR_RXEN 0x01 /* Enable receiver. */
  214. #define NIC_RSR 0x06 /* RX status register (0x00). */
  215. #define NIC_RSR_ERRORS 0xBF /* Error bit mask. */
  216. #define NIC_RSR_RF 0x80 /* Runt frame. */
  217. #define NIC_RSR_MF 0x40 /* Multicast frame. */
  218. #define NIC_RSR_LCS 0x20 /* Late collision. */
  219. #define NIC_RSR_RWTO 0x10 /* Receiver watchdog time out. */
  220. #define NIC_RSR_PLE 0x08 /* Physical layer error. */
  221. #define NIC_RSR_AE 0x04 /* Alignment error. */
  222. #define NIC_RSR_CE 0x02 /* CRC error. */
  223. #define NIC_RSR_FOE 0x01 /* FIFO overflow error. */
  224. #define NIC_ROCR 0x07 /* Receive overflow counter register (0x00). */
  225. #define NIC_BPTR 0x08 /* Back pressure threshold register (0x37). */
  226. #define NIC_FCTR 0x09 /* Flow control threshold register (0x38). */
  227. #define NIC_FCR 0x0A /* RX flow control register (0x00). */
  228. #define NIC_EPCR 0x0B /* EEPROM and PHY control register. */
  229. #define NIC_EPAR 0x0C /* EEPROM and PHY address register. */
  230. #define NIC_EPDRL 0x0D /* EEPROM and PHY low byte data register. */
  231. #define NIC_EPDRH 0x0E /* EEPROM and PHY high byte data register. */
  232. #define NIC_WCR 0x0F /* Wake up control register (0x00). */
  233. #define NIC_PAR 0x10 /* 6 byte physical address register. */
  234. #define NIC_MAR 0x16 /* 8 byte multicast address register. */
  235. #define NIC_GPCR 0x1E /* General purpose control register (?). */
  236. #define NIC_GPR 0x1F /* General purpose register (?). */
  237. #define NIC_TRPA 0x22 /* 2 byte TX SRAM read pointer address, low/high (0x0000). */
  238. #define NIC_RWPA 0x24 /* 2 byte RX SRAM write pointer address, low/high (0x0000). */
  239. #define NIC_VID 0x28 /* 2 byte vendor ID (0x0A46). */
  240. #define NIC_PID 0x2A /* 2 byte product ID (0x0900). */
  241. #define NIC_CHIPR 0x2C /* Chip revision (0x00). */
  242. #define NIC_SMCR 0x2F /* Special mode register (0x00). */
  243. #define NIC_MRCMDX 0xF0 /* Memory data read command w/o increment (?). */
  244. #define NIC_MRCMD 0xF2 /* Memory data read command with increment (?). */
  245. #define NIC_MRR 0xF4 /* 2 byte memory data read register, low/high (?). */
  246. #define NIC_MWCMDX 0xF6 /* Memory data write command register w/o increment (?). */
  247. #define NIC_MWCMD 0xF8 /* Memory data write command register with increment (?). */
  248. #define NIC_MWR 0xFA /* Memory data write command register with increment (?). */
  249. #define NIC_TXPL 0xFC /* 2 byte TX packet length register. (?). */
  250. #define NIC_ISR 0xFE /* Interrupt status register (0x00). */
  251. #define NIC_ISR_IOM 0xC0 /* I/O mode mask */
  252. #define NIC_ISR_M16 0x00 /* 16-bit I/O mode */
  253. #define NIC_ISR_M32 0x40 /* 32-bit I/O mode */
  254. #define NIC_ISR_M8 0x80 /* 8-bit I/O mode */
  255. #define NIC_ISR_ROOS 0x08 /* Receiver overflow counter interrupt. */
  256. #define NIC_ISR_ROS 0x04 /* Receiver overflow interrupt. */
  257. #define NIC_ISR_PTS 0x02 /* Transmitter interrupt. */
  258. #define NIC_ISR_PRS 0x01 /* Receiver interrupt. */
  259. #define NIC_IMR 0xFF /* Interrupt mask register (0x00). */
  260. #define NIC_IMR_PAR 0x80 /* Enable read/write pointer wrap around. */
  261. #define NIC_IMR_ROOM 0x08 /* Enable receiver overflow counter interrupts. */
  262. #define NIC_IMR_ROM 0x04 /* Enable receiver overflow interrupts. */
  263. #define NIC_IMR_PTM 0x02 /* Enable transmitter interrupts. */
  264. #define NIC_IMR_PRM 0x01 /* Enable receiver interrupts. */
  265. /*!
  266. * \brief Network interface controller information structure.
  267. */
  268. struct _NICINFO {
  269. #ifdef NUT_PERFMON
  270. uint32_t ni_rx_packets; /*!< Number of packets received. */
  271. uint32_t ni_tx_packets; /*!< Number of packets sent. */
  272. uint32_t ni_overruns; /*!< Number of packet overruns. */
  273. uint32_t ni_rx_frame_errors; /*!< Number of frame errors. */
  274. uint32_t ni_rx_crc_errors; /*!< Number of CRC errors. */
  275. uint32_t ni_rx_missed_errors; /*!< Number of missed packets. */
  276. #endif
  277. HANDLE volatile ni_rx_rdy; /*!< Receiver event queue. */
  278. HANDLE volatile ni_tx_rdy; /*!< Transmitter event queue. */
  279. HANDLE ni_mutex; /*!< Access mutex semaphore. */
  280. volatile int ni_tx_queued; /*!< Number of packets in transmission queue. */
  281. volatile int ni_tx_quelen; /*!< Number of bytes in transmission queue not sent. */
  282. volatile int ni_insane; /*!< Set by error detection. */
  283. int ni_iomode; /*!< 8 or 16 bit access. 32 bit is not supported. */
  284. uint8_t ni_mar[8]; /*!< Multicast Address Register. */
  285. };
  286. /*!
  287. * \brief Network interface controller information type.
  288. */
  289. typedef struct _NICINFO NICINFO;
  290. /*@}*/
  291. /*!
  292. * \addtogroup xgNicDm9000e
  293. */
  294. /*@{*/
  295. /*
  296. * ether_crc32_le based on FreeBSD code from if_ethersubr.c
  297. */
  298. static const uint32_t crctab[] = {
  299. 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
  300. 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
  301. 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
  302. 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
  303. };
  304. static uint32_t ether_crc32_le(const uint8_t *buf, uint8_t len)
  305. {
  306. uint32_t crc;
  307. uint8_t i;
  308. crc = 0xffffffff; /* initial value */
  309. for (i = 0; i < len; i++) {
  310. crc ^= buf[i];
  311. crc = (crc >> 4) ^ crctab[crc & 0xf];
  312. crc = (crc >> 4) ^ crctab[crc & 0xf];
  313. }
  314. return (crc);
  315. }
  316. static INLINE void nic_outb(uint8_t reg, uint8_t val)
  317. {
  318. outb(NIC_BASE_ADDR, reg);
  319. outb(NIC_DATA_ADDR, val);
  320. }
  321. static INLINE uint8_t nic_inb(uint16_t reg)
  322. {
  323. outb(NIC_BASE_ADDR, reg);
  324. return inb(NIC_DATA_ADDR);
  325. }
  326. /*!
  327. * \brief Read contents of PHY register.
  328. *
  329. * \param reg PHY register number.
  330. *
  331. * \return Contents of the specified register.
  332. */
  333. static uint16_t phy_inw( uint8_t reg)
  334. {
  335. /* Select PHY register */
  336. nic_outb(NIC_EPAR, 0x40 | reg);
  337. /* PHY read command. */
  338. nic_outb(NIC_EPCR, 0x0C);
  339. NutDelay(1);
  340. nic_outb(NIC_EPCR, 0x00);
  341. /* Get data from PHY data register. */
  342. return ((uint16_t) nic_inb(NIC_EPDRH) << 8) | (uint16_t) nic_inb(NIC_EPDRL);
  343. }
  344. /*!
  345. * \brief Write value to PHY register.
  346. *
  347. * \note NIC interrupts must have been disabled before calling this routine.
  348. *
  349. * \param reg PHY register number.
  350. * \param val Value to write.
  351. */
  352. static void phy_outw(uint8_t reg, uint16_t val)
  353. {
  354. /* Select PHY register */
  355. nic_outb(NIC_EPAR, 0x40 | reg);
  356. /* Store value in PHY data register. */
  357. nic_outb(NIC_EPDRL, (uint8_t) (val));
  358. nic_outb(NIC_EPDRH, (uint8_t) (val >> 8));
  359. /* PHY write command. */
  360. nic_outb(NIC_EPCR, 0x0A);
  361. NutDelay(1);
  362. nic_outb(NIC_EPCR, 0x00);
  363. }
  364. static int NicPhyInit(void)
  365. {
  366. uint32_t phy = 1;
  367. /* Restart auto negotiation. */
  368. NutPhyCtl(PHY_CTL_AUTONEG_RE, &phy);
  369. nic_outb(NIC_GPCR, 1);
  370. nic_outb(NIC_GPR, 0);
  371. return 0;
  372. }
  373. /*!
  374. * \brief Reset the Ethernet controller.
  375. *
  376. * \return 0 on success, -1 otherwise.
  377. */
  378. static int NicReset(void)
  379. {
  380. /* Hardware reset. */
  381. #ifdef undef_NIC_RESET_BIT
  382. sbi(NIC_RESET_DDR, NIC_RESET_BIT);
  383. sbi(NIC_RESET_PORT, NIC_RESET_BIT);
  384. NutDelay(WAIT100);
  385. cbi(NIC_RESET_PORT, NIC_RESET_BIT);
  386. NutDelay(WAIT250);
  387. NutDelay(WAIT250);
  388. #else
  389. /* Software reset. */
  390. nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
  391. NutDelay(1);
  392. /* FIXME: Delay required. */
  393. #endif
  394. DMPRINTF("\n*DMRES*\n");
  395. return NicPhyInit();
  396. }
  397. /*
  398. * NIC interrupt entry.
  399. */
  400. static void NicInterrupt(void *arg)
  401. {
  402. uint_fast8_t isr;
  403. NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
  404. /* Read interrupt status and disable interrupts. */
  405. isr = nic_inb(NIC_ISR);
  406. DMPRINTF("*DMIRQ %02x:", isr);
  407. /* Receiver interrupt. */
  408. if (isr & NIC_ISR_PRS) {
  409. DMPRINTF("RX*");
  410. nic_outb(NIC_ISR, NIC_ISR_PRS);
  411. NutEventPostFromIrq(&ni->ni_rx_rdy);
  412. }
  413. /* Transmitter interrupt. */
  414. if (isr & NIC_ISR_PTS) {
  415. DMPRINTF("TX*");
  416. if (ni->ni_tx_queued) {
  417. if (ni->ni_tx_quelen) {
  418. /* Initiate transfer of a queued packet. */
  419. nic_outb(NIC_TXPL, (uint8_t) ni->ni_tx_quelen);
  420. nic_outb(NIC_TXPL + 1, (uint8_t) (ni->ni_tx_quelen >> 8));
  421. ni->ni_tx_quelen = 0;
  422. nic_outb(NIC_TCR, NIC_TCR_TXREQ);
  423. }
  424. ni->ni_tx_queued--;
  425. }
  426. nic_outb(NIC_ISR, NIC_ISR_PTS);
  427. NutEventPostFromIrq(&ni->ni_tx_rdy);
  428. }
  429. /* Receiver overflow interrupt. */
  430. if (isr & NIC_ISR_ROS) {
  431. DMPRINTF("OVI*");
  432. nic_outb(NIC_ISR, NIC_ISR_ROS);
  433. ni->ni_insane = 1;
  434. NutEventPostFromIrq(&ni->ni_rx_rdy);
  435. }
  436. /* Receiver overflow counter interrupt. */
  437. if (isr & NIC_ISR_ROOS) {
  438. DMPRINTF("OVC*");
  439. nic_outb(NIC_ISR, NIC_ISR_ROOS);
  440. NutEventPostFromIrq(&ni->ni_rx_rdy);
  441. }
  442. if( ni->ni_insane)
  443. DMPRINTF("INS\n");
  444. else
  445. DMPRINTF("\n");
  446. }
  447. /*!
  448. * \brief Write data block to the NIC.
  449. *
  450. * NIC interrupts must be disabled when calling this function.
  451. */
  452. static void NicWrite8(uint8_t * buf, uint16_t len)
  453. {
  454. while (len--) {
  455. outb(NIC_DATA_ADDR, *buf);
  456. buf++;
  457. }
  458. }
  459. /*!
  460. * \brief Write data block to the NIC.
  461. *
  462. * NIC interrupts must be disabled when calling this function.
  463. */
  464. static void NicWrite16(uint8_t * buf, uint16_t len)
  465. {
  466. uint16_t *wp = (uint16_t *) buf;
  467. len = (len + 1) / 2;
  468. while (len--) {
  469. outw(NIC_DATA_ADDR, *wp);
  470. wp++;
  471. }
  472. }
  473. /*!
  474. * \brief Read data block from the NIC.
  475. *
  476. * NIC interrupts must be disabled when calling this function.
  477. */
  478. static void NicRead8(uint8_t * buf, uint16_t len)
  479. {
  480. while (len--) {
  481. *buf++ = inb(NIC_DATA_ADDR);
  482. }
  483. }
  484. /*!
  485. * \brief Read data block from the NIC.
  486. *
  487. * NIC interrupts must be disabled when calling this function.
  488. */
  489. static void NicRead16(uint8_t * buf, uint16_t len)
  490. {
  491. uint16_t *wp = (uint16_t *) buf;
  492. len = (len + 1) / 2;
  493. while (len--) {
  494. *wp++ = inw(NIC_DATA_ADDR);
  495. }
  496. }
  497. /*!
  498. * \brief Fetch the next packet out of the receive ring buffer.
  499. *
  500. * \return Pointer to an allocated ::NETBUF. If there is no
  501. * no data available, then the function returns a
  502. * null pointer. If the NIC's buffer seems to be
  503. * corrupted, a pointer to 0xFFFF is returned.
  504. */
  505. static int NicGetPacket(NICINFO * ni, NETBUF ** nbp)
  506. {
  507. int rc = -1;
  508. uint16_t fsw;
  509. uint16_t fbc;
  510. *nbp = NULL;
  511. /* Disable NIC interrupts. */
  512. NutIrqDisable(&NIC_SIGNAL);
  513. /*
  514. * Read the status word w/o auto increment. If zero, no packet is
  515. * available. Otherwise it should be set to one. Any other value
  516. * indicates a weird chip crying for reset.
  517. */
  518. nic_inb(NIC_MRCMDX);
  519. /* Add some delay befor reading the status of the received packet. */
  520. _NOP(); _NOP(); _NOP(); _NOP();
  521. fsw = inb(NIC_DATA_ADDR);
  522. if (fsw > 1) {
  523. ni->ni_insane = 1;
  524. } else if (fsw) {
  525. /* Now read status word and byte count with auto increment. */
  526. outb(NIC_BASE_ADDR, NIC_MRCMD);
  527. if (ni->ni_iomode == NIC_ISR_M16) {
  528. fsw = inw(NIC_DATA_ADDR);
  529. _NOP(); _NOP(); _NOP(); _NOP();
  530. fbc = inw(NIC_DATA_ADDR);
  531. } else {
  532. fsw = inb(NIC_DATA_ADDR) + ((uint16_t) inb(NIC_DATA_ADDR) << 8);
  533. _NOP(); _NOP(); _NOP(); _NOP();
  534. fbc = inb(NIC_DATA_ADDR) + ((uint16_t) inb(NIC_DATA_ADDR) << 8);
  535. }
  536. /*
  537. * Receiving long packets is unexpected, because we disabled
  538. * this during initialization. Let's declare the chip insane.
  539. * Short packets will be handled by the caller.
  540. */
  541. if (fbc > 1536) {
  542. ni->ni_insane = 1;
  543. } else {
  544. /*
  545. * The high byte of the status word contains a copy of the
  546. * receiver status register.
  547. */
  548. fsw >>= 8;
  549. fsw &= NIC_RSR_ERRORS;
  550. #ifdef NUT_PERMON
  551. /* Update statistics. */
  552. if (fsw) {
  553. if (RxStatus & NIC_RSR_CE) {
  554. ni->ni_crc_errors++;
  555. } else if (RxStatus & NIC_RSR_FOE) {
  556. ni->ni_overruns++;
  557. } else {
  558. ni->ni_rx_missed_errors++;
  559. }
  560. } else {
  561. ni->ni_rx_packets++;
  562. }
  563. #endif
  564. /*
  565. * If we got an error packet or failed to allocated the
  566. * buffer, then silently discard the packet.
  567. */
  568. if (fsw || (*nbp = NutNetBufAlloc(0, NBAF_DATALINK, fbc - 4)) == NULL) {
  569. if (ni->ni_iomode == NIC_ISR_M16) {
  570. fbc = (fbc + 1) / 2;
  571. while (fbc--) {
  572. fsw = inw(NIC_DATA_ADDR);
  573. }
  574. } else {
  575. while (fbc--) {
  576. fsw = inb(NIC_DATA_ADDR);
  577. }
  578. }
  579. } else {
  580. if (ni->ni_iomode == NIC_ISR_M16) {
  581. /* Read packet data from 16 bit bus. */
  582. NicRead16((*nbp)->nb_dl.vp, (*nbp)->nb_dl.sz);
  583. /* Read packet CRC. */
  584. fsw = inw(NIC_DATA_ADDR);
  585. fsw = inw(NIC_DATA_ADDR);
  586. } else {
  587. /* Read packet data from 8 bit bus. */
  588. NicRead8((*nbp)->nb_dl.vp, (*nbp)->nb_dl.sz);
  589. /* Read packet CRC. */
  590. fsw = inb(NIC_DATA_ADDR);
  591. fsw = inb(NIC_DATA_ADDR);
  592. fsw = inb(NIC_DATA_ADDR);
  593. fsw = inb(NIC_DATA_ADDR);
  594. }
  595. /* Return success. */
  596. rc = 0;
  597. }
  598. }
  599. }
  600. /* Enable NIC interrupts if the chip is sane. */
  601. if (ni->ni_insane == 0) {
  602. NutIrqEnable(&NIC_SIGNAL);
  603. }
  604. return rc;
  605. }
  606. /*!
  607. * \brief Load a packet into the nic's transmit ring buffer.
  608. *
  609. * \param nb Network buffer structure containing the packet to be sent.
  610. * The structure must have been allocated by a previous
  611. * call NutNetBufAlloc(). This routine will automatically
  612. * release the buffer in case of an error.
  613. *
  614. * \return 0 on success, -1 in case of any errors. Errors
  615. * will automatically release the network buffer
  616. * structure.
  617. */
  618. static int NicPutPacket(NICINFO * ni, NETBUF * nb)
  619. {
  620. int rc = -1;
  621. uint16_t sz;
  622. /*
  623. * Calculate the number of bytes to be send. Do not send packets
  624. * larger than the Ethernet maximum transfer unit. The MTU
  625. * consist of 1500 data bytes plus the 14 byte Ethernet header
  626. * plus 4 bytes CRC. We check the data bytes only.
  627. */
  628. if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU) {
  629. return -1;
  630. }
  631. sz += nb->nb_dl.sz;
  632. if (sz & 1) {
  633. sz++;
  634. }
  635. /* Disable interrupts. */
  636. NutIrqDisable(&NIC_SIGNAL);
  637. /* TODO: Check for link. */
  638. if (ni->ni_insane == 0) {
  639. /* Enable data write. */
  640. outb(NIC_BASE_ADDR, NIC_MWCMD);
  641. /* Transfer the Ethernet frame. */
  642. if (ni->ni_iomode == NIC_ISR_M16) {
  643. NicWrite16(nb->nb_dl.vp, nb->nb_dl.sz);
  644. NicWrite16(nb->nb_nw.vp, nb->nb_nw.sz);
  645. NicWrite16(nb->nb_tp.vp, nb->nb_tp.sz);
  646. NicWrite16(nb->nb_ap.vp, nb->nb_ap.sz);
  647. } else {
  648. NicWrite8(nb->nb_dl.vp, nb->nb_dl.sz);
  649. NicWrite8(nb->nb_nw.vp, nb->nb_nw.sz);
  650. NicWrite8(nb->nb_tp.vp, nb->nb_tp.sz);
  651. NicWrite8(nb->nb_ap.vp, nb->nb_ap.sz);
  652. }
  653. /* If no packet is queued, start the transmission. */
  654. if (ni->ni_tx_queued == 0) {
  655. nic_outb(NIC_TXPL, (uint8_t) sz);
  656. nic_outb(NIC_TXPL + 1, (uint8_t) (sz >> 8));
  657. nic_outb(NIC_TCR, NIC_TCR_TXREQ);
  658. }
  659. /* ...otherwise mark this packet queued. */
  660. else {
  661. ni->ni_tx_quelen = sz;
  662. }
  663. ni->ni_tx_queued++;
  664. rc = 0;
  665. #ifdef NUT_PERFMON
  666. ni->ni_tx_packets++;
  667. #endif
  668. }
  669. /* Enable interrupts. */
  670. NutIrqEnable(&NIC_SIGNAL);
  671. /* If the controller buffer is filled with two packets, then
  672. wait for the first being sent out. */
  673. if (rc == 0 && ni->ni_tx_queued > 1) {
  674. NutEventWait(&ni->ni_tx_rdy, 500);
  675. }
  676. return rc;
  677. }
  678. /*!
  679. * \brief Update the multicast register.
  680. *
  681. * \param Network interface controller information.
  682. */
  683. static void NicUpdateMCHardware(NICINFO *ni)
  684. {
  685. int i;
  686. /* Enable broadcast receive. */
  687. ni->ni_mar[7] |= 0x80;
  688. /* Set multicast address register */
  689. for (i = 0; i < 7; i++) {
  690. nic_outb(NIC_MAR + i, ni->ni_mar[i]);
  691. }
  692. }
  693. /*!
  694. * \brief Fire up the network interface.
  695. *
  696. * NIC interrupts must be disabled when calling this function.
  697. *
  698. * \param mac Six byte unique MAC address.
  699. */
  700. static int NicStart(const uint8_t * mac, NICINFO * ni)
  701. {
  702. int i;
  703. int link_wait = 20;
  704. uint32_t phy;
  705. /* Power up the PHY. */
  706. nic_outb(NIC_GPR, 0);
  707. NutDelay(5);
  708. /* Software reset with MAC loopback. */
  709. nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
  710. NutDelay(5);
  711. nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
  712. NutDelay(5);
  713. /*
  714. * PHY power down followed by PHY power up. This should activate
  715. * the auto sense link.
  716. */
  717. nic_outb(NIC_GPR, 1);
  718. nic_outb(NIC_GPR, 0);
  719. /* Set MAC address. */
  720. for (i = 0; i < 6; i++) {
  721. nic_outb(NIC_PAR + i, mac[i]);
  722. }
  723. /* Set multicast address register */
  724. NicUpdateMCHardware(ni);
  725. /* Clear interrupts. */
  726. nic_outb(NIC_ISR, NIC_ISR_ROOS | NIC_ISR_ROS | NIC_ISR_PTS | NIC_ISR_PRS);
  727. /* Enable late collision retries on the DM9000A. */
  728. if (nic_inb(NIC_CHIPR) == 0x19) {
  729. nic_outb(0x2D, 0x40);
  730. }
  731. /* Enable receiver. */
  732. nic_outb(NIC_RCR, NIC_RCR_DIS_LONG | NIC_RCR_DIS_CRC | NIC_RCR_RXEN | NIC_RCR_ALL);
  733. /* Restart autonegotiation */
  734. phy = 1;
  735. NutPhyCtl(PHY_CTL_AUTONEG_RE, &phy);
  736. /* Wait for auto negotiation completed and link established. */
  737. for (link_wait = 25;; link_wait--) {
  738. NutPhyCtl(PHY_GET_STATUS, &phy);
  739. if((phy & PHY_STATUS_HAS_LINK) && (phy & PHY_STATUS_AUTONEG_OK)) {
  740. break;
  741. }
  742. if (link_wait == 0) {
  743. return -1;
  744. }
  745. NutSleep(200);
  746. }
  747. /* Enable interrupts. */
  748. nic_outb(NIC_IMR, NIC_IMR_PAR | NIC_IMR_PTM | NIC_IMR_PRM);
  749. return 0;
  750. }
  751. /*! \fn NicRxLanc(void *arg)
  752. * \brief NIC receiver thread.
  753. *
  754. */
  755. THREAD(NicRxLanc, arg)
  756. {
  757. NUTDEVICE *dev;
  758. IFNET *ifn;
  759. NICINFO *ni;
  760. NETBUF *nb;
  761. dev = arg;
  762. ifn = (IFNET *) dev->dev_icb;
  763. ni = (NICINFO *) dev->dev_dcb;
  764. /*
  765. * This is a temporary hack. Due to a change in initialization,
  766. * we may not have got a MAC address yet. Wait until a valid one
  767. * has been set.
  768. */
  769. while (!ETHER_IS_UNICAST(ifn->if_mac)) {
  770. NutSleep(10);
  771. }
  772. /*
  773. * Do not continue unless we managed to start the NIC. We are
  774. * trapped here if the Ethernet link cannot be established.
  775. * This happens, for example, if no Ethernet cable is plugged
  776. * in.
  777. */
  778. while (NicStart(ifn->if_mac, ni)) {
  779. NutSleep(1000);
  780. }
  781. /* Initialize the access mutex. */
  782. NutEventPost(&ni->ni_mutex);
  783. /* Run at high priority. */
  784. NutThreadSetPriority(9);
  785. /* Enable interrupts. */
  786. #ifdef NIC_SIGNAL_XSR
  787. outr(NIC_SIGNAL_XSR, _BV(NIC_SIGNAL_BIT));
  788. #if defined(ELEKTOR_IR1)
  789. /* Ugly code alarm: Should be configurable. */
  790. outr(PMC_PCER, _BV(IRQ0_ID));
  791. #endif
  792. #endif
  793. outr(NIC_SIGNAL_PDR, _BV(NIC_SIGNAL_BIT));
  794. NutIrqEnable(&NIC_SIGNAL);
  795. #if defined(ELEKTOR_IR1)
  796. /* Ugly code alarm: Should be configurable. */
  797. NutIrqSetMode(&NIC_SIGNAL, NUT_IRQMODE_HIGHLEVEL);
  798. #endif
  799. for (;;) {
  800. /*
  801. * Wait for the arrival of new packets or poll the receiver
  802. * every two seconds.
  803. */
  804. NutEventWait(&ni->ni_rx_rdy, 2000);
  805. /*
  806. * Fetch all packets from the NIC's internal buffer and pass
  807. * them to the registered handler.
  808. */
  809. while (NicGetPacket(ni, &nb) == 0) {
  810. /* Discard short packets. */
  811. if (nb->nb_dl.sz < 60) {
  812. NutNetBufFree(nb);
  813. } else {
  814. (*ifn->if_recv) (dev, nb);
  815. }
  816. }
  817. /* We got a weird chip, try to restart it. */
  818. while (ni->ni_insane) {
  819. if (NicStart(ifn->if_mac, ni) == 0) {
  820. ni->ni_insane = 0;
  821. ni->ni_tx_queued = 0;
  822. ni->ni_tx_quelen = 0;
  823. NutIrqEnable(&NIC_SIGNAL);
  824. } else {
  825. NutSleep(1000);
  826. }
  827. }
  828. }
  829. }
  830. /*!
  831. * \brief Send Ethernet packet.
  832. *
  833. * \param dev Identifies the device to use.
  834. * \param nb Network buffer structure containing the packet to be sent.
  835. * The structure must have been allocated by a previous
  836. * call NutNetBufAlloc().
  837. *
  838. * \return 0 on success, -1 in case of any errors.
  839. */
  840. int DmOutput(NUTDEVICE * dev, NETBUF * nb)
  841. {
  842. static uint32_t mx_wait = 5000;
  843. int rc = -1;
  844. NICINFO *ni = (NICINFO *) dev->dev_dcb;
  845. /*
  846. * After initialization we are waiting for a long time to give
  847. * the PHY a chance to establish an Ethernet link.
  848. */
  849. while (rc) {
  850. if (ni->ni_insane) {
  851. break;
  852. }
  853. if (NutEventWait(&ni->ni_mutex, mx_wait)) {
  854. break;
  855. }
  856. /* Check for packet queue space. */
  857. if (ni->ni_tx_queued > 1) {
  858. if (NutEventWait(&ni->ni_tx_rdy, 500)) {
  859. /* No queue space. Release the lock and give up. */
  860. NutEventPost(&ni->ni_mutex);
  861. break;
  862. }
  863. } else if (NicPutPacket(ni, nb) == 0) {
  864. /* Ethernet works. Set a long waiting time in case we
  865. temporarly lose the link next time. */
  866. rc = 0;
  867. mx_wait = 5000;
  868. }
  869. NutEventPost(&ni->ni_mutex);
  870. }
  871. /*
  872. * Probably no Ethernet link. Significantly reduce the waiting
  873. * time, so following transmission will soon return an error.
  874. */
  875. if (rc) {
  876. mx_wait = 500;
  877. }
  878. return rc;
  879. }
  880. /*!
  881. * \brief Initialize Ethernet hardware.
  882. *
  883. * Resets the LAN91C111 Ethernet controller, initializes all required
  884. * hardware registers and starts a background thread for incoming
  885. * Ethernet traffic.
  886. *
  887. * Applications should do not directly call this function. It is
  888. * automatically executed during during device registration by
  889. * NutRegisterDevice().
  890. *
  891. * If the network configuration hasn't been set by the application
  892. * before registering the specified device, this function will
  893. * call NutNetLoadConfig() to get the MAC address.
  894. *
  895. * \param dev Identifies the device to initialize.
  896. */
  897. int DmInit(NUTDEVICE * dev)
  898. {
  899. uint32_t id;
  900. NICINFO *ni = (NICINFO *) dev->dev_dcb;
  901. #if defined(ELEKTOR_IR1)
  902. /* @@MF: "Power on reset" the Ethernet controller */
  903. outr(PIOC_SODR, _BV(PC17_NANDOE_B));
  904. outr(PIOC_PER, _BV(PC17_NANDOE_B));
  905. outr(PIOC_OER, _BV(PC17_NANDOE_B));
  906. outr(PIOC_CODR, _BV(PC17_NANDOE_B));
  907. NutDelay(WAIT250);
  908. NutDelay(WAIT250);
  909. NutDelay(WAIT250);
  910. NutDelay(WAIT250);
  911. outr(PIOC_SODR, _BV(PC17_NANDOE_B));
  912. NutDelay(WAIT250);
  913. NutDelay(WAIT250);
  914. NutDelay(WAIT250);
  915. NutDelay(WAIT250);
  916. /**************************************************/
  917. outr(PIOA_BSR, _BV(PA20_NCS2_B));
  918. outr(PIOA_PDR, _BV(PA20_NCS2_B));
  919. outr(PIOC_BSR, _BV(PC16_NWAIT_B) | _BV(PC21_NWR0_B) | _BV(PC22_NRD_B));
  920. outr(PIOC_PDR, _BV(PC16_NWAIT_B) | _BV(PC21_NWR0_B) | _BV(PC22_NRD_B));
  921. outr(SMC_CSR(2)
  922. , (1 << SMC_NWS_LSB)
  923. | SMC_WSEN
  924. | (2 << SMC_TDF_LSB)
  925. | SMC_BAT
  926. | SMC_DBW_16
  927. | (1 << SMC_RWSETUP_LSB)
  928. | (1 << SMC_RWHOLD_LSB)
  929. );
  930. #endif
  931. /* Probe chip by verifying the identifier registers. */
  932. id = (uint32_t) nic_inb(NIC_VID);
  933. id |= (uint32_t) nic_inb(NIC_VID + 1) << 8;
  934. id |= (uint32_t) nic_inb(NIC_PID) << 16;
  935. id |= (uint32_t) nic_inb(NIC_PID + 1) << 24;
  936. if (id != 0x90000A46) {
  937. return -1;
  938. }
  939. /* Register PHY */
  940. NutRegisterPhy( 1, phy_outw, phy_inw);
  941. /* Reset chip. */
  942. if (NicReset()) {
  943. return -1;
  944. }
  945. /* Clear NICINFO structure. */
  946. memset(ni, 0, sizeof(NICINFO));
  947. /* Determine bus mode. We do not support 32 bit access. */
  948. ni->ni_iomode = nic_inb(NIC_ISR) & NIC_ISR_IOM;
  949. if (ni->ni_iomode == NIC_ISR_M32) {
  950. return -1;
  951. }
  952. /* Register interrupt handler. */
  953. if (NutRegisterIrqHandler(&NIC_SIGNAL, NicInterrupt, dev)) {
  954. return -1;
  955. }
  956. /* Start the receiver thread. */
  957. if (NutThreadCreate("rxi1", NicRxLanc, dev,
  958. (NUT_THREAD_NICRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == NULL) {
  959. return -1;
  960. }
  961. return 0;
  962. }
  963. static int DmIOCtl(NUTDEVICE * dev, int req, void *conf)
  964. {
  965. int rc = 0;
  966. int i;
  967. IFNET *nif = (IFNET *) dev->dev_icb;
  968. NICINFO *ni = (NICINFO *) dev->dev_dcb;
  969. uint32_t index;
  970. uint32_t ip_addr;
  971. MCASTENTRY *mcast;
  972. MCASTENTRY *mcast_prev;
  973. MCASTENTRY *mcast_next;
  974. uint8_t mac[6];
  975. switch (req) {
  976. /* Set interface address */
  977. case SIOCSIFADDR:
  978. /* Set interface hardware address. */
  979. memcpy(nif->if_mac, conf, sizeof(nif->if_mac));
  980. break;
  981. /* Add multicast address */
  982. case SIOCADDMULTI:
  983. ip_addr = *((uint32_t*)conf);
  984. /* Test if the address is still in the list */
  985. mcast = nif->if_mcast;
  986. while(mcast)
  987. {
  988. if (ip_addr == mcast->mca_ip)
  989. {
  990. /* The address is still in the list, do nothing */
  991. return -1;
  992. }
  993. mcast = mcast->mca_next;
  994. }
  995. /* Create MAC address */
  996. mac[0] = 0x01;
  997. mac[1] = 0x00;
  998. mac[2] = 0x5E;
  999. mac[3] = ((uint8_t*)conf)[1] & 0x7f;
  1000. mac[4] = ((uint8_t*)conf)[2];
  1001. mac[5] = ((uint8_t*)conf)[3];
  1002. mcast = malloc(sizeof(MCASTENTRY));
  1003. if (mcast != NULL) {
  1004. /* Calculate MAR index, range 0...63 */
  1005. index = ether_crc32_le(&mac[0], 6);
  1006. index &= 0x3F;
  1007. /* Set multicast bit */
  1008. ni->ni_mar[index / 8] |= (1 << (index % 8));
  1009. /* Add new mcast to the mcast list */
  1010. memcpy(mcast->mca_ha, mac, 6);
  1011. mcast->mca_ip = *((uint32_t*)conf);
  1012. mcast->mca_next = nif->if_mcast;
  1013. nif->if_mcast = mcast;
  1014. /* Update the MC hardware */
  1015. NicUpdateMCHardware(ni);
  1016. }
  1017. else {
  1018. rc = -1;
  1019. }
  1020. break;
  1021. /* Delete multicast address */
  1022. case SIOCDELMULTI:
  1023. ip_addr = *((uint32_t*)conf);
  1024. /* Test if the address is still in the list */
  1025. mcast = nif->if_mcast;
  1026. mcast_prev = mcast;
  1027. while(mcast)
  1028. {
  1029. if (ip_addr == mcast->mca_ip)
  1030. {
  1031. /* The address is in the list, leave the loop */
  1032. break;
  1033. }
  1034. mcast_prev = mcast;
  1035. mcast = mcast->mca_next;
  1036. }
  1037. if (NULL == mcast)
  1038. {
  1039. /* The address is not in the list */
  1040. return -1;
  1041. }
  1042. /*
  1043. * Remove the address from the list
  1044. */
  1045. mcast_next = mcast->mca_next;
  1046. /* Check if the first element must be removed */
  1047. if (nif->if_mcast == mcast)
  1048. {
  1049. /*
  1050. * The element is the first one
  1051. */
  1052. /* The first element is now the "next" element */
  1053. nif->if_mcast = mcast_next;
  1054. free(mcast);
  1055. } else {
  1056. /*
  1057. * The element is in the middle of the list
  1058. */
  1059. /* The next element of the previous is the "next" element */
  1060. mcast_prev->mca_next = mcast_next;
  1061. free(mcast);
  1062. }
  1063. /*
  1064. * Clear the multicast filter, and rebuild it
  1065. */
  1066. /* Clear */
  1067. for (i = 0; i < 7; i++) {
  1068. ni->ni_mar[i] = 0;
  1069. }
  1070. /* Rebuild */
  1071. mcast = nif->if_mcast;
  1072. while(mcast)
  1073. {
  1074. /* Calculate MAR index, range 0...63 */
  1075. index = ether_crc32_le(&mcast->mca_ha[0], 6);
  1076. index &= 0x3F;
  1077. /* Set multicast bit */
  1078. ni->ni_mar[index / 8] |= (1 << (index % 8));
  1079. mcast = mcast->mca_next;
  1080. }
  1081. /* Update the MC hardware */
  1082. NicUpdateMCHardware(ni);
  1083. break;
  1084. default:
  1085. rc = -1;
  1086. break;
  1087. }
  1088. return rc;
  1089. }
  1090. static NICINFO dcb_eth0;
  1091. /*!
  1092. * \brief Network interface information structure.
  1093. *
  1094. * Used to call.
  1095. */
  1096. static IFNET ifn_eth0 = {
  1097. IFT_ETHER, /*!< \brief Interface type, if_type. */
  1098. 0, /*!< \brief Interface flags, if_flags. */
  1099. {0, 0, 0, 0, 0, 0}, /*!< \brief Hardware net address, if_mac. */
  1100. 0, /*!< \brief IP address, if_local_ip. */
  1101. 0, /*!< \brief Remote IP address for point to point, if_remote_ip. */
  1102. 0, /*!< \brief IP network mask, if_mask. */
  1103. ETHERMTU, /*!< \brief Maximum size of a transmission unit, if_mtu. */
  1104. 0, /*!< \brief Packet identifier, if_pkt_id. */
  1105. 0, /*!< \brief Linked list of arp entries, arpTable. */
  1106. 0, /*!< \brief Linked list of multicast address entries, if_mcast. */
  1107. NutEtherInput, /*!< \brief Routine to pass received data to, if_recv(). */
  1108. DmOutput, /*!< \brief Driver output routine, if_send(). */
  1109. NutEtherOutput, /*!< \brief Media output routine, if_output(). */
  1110. NULL /*!< \brief Interface specific control function, if_ioctl(). */
  1111. #ifdef NUT_PERFMON
  1112. , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  1113. #endif
  1114. };
  1115. /*!
  1116. * \brief Device information structure.
  1117. *
  1118. * A pointer to this structure must be passed to NutRegisterDevice()
  1119. * to bind this Ethernet device driver to the Nut/OS kernel.
  1120. * An application may then call NutNetIfConfig() with the name \em eth0
  1121. * of this driver to initialize the network interface.
  1122. *
  1123. */
  1124. NUTDEVICE devDM9000E = {
  1125. 0, /*!< \brief Pointer to next device. */
  1126. {'e', 't', 'h', '0', 0, 0, 0, 0, 0}, /*!< \brief Unique device name. */
  1127. IFTYP_NET, /*!< \brief Type of device. */
  1128. 0, /*!< \brief Base address. */
  1129. 0, /*!< \brief First interrupt number. */
  1130. &ifn_eth0, /*!< \brief Interface control block. */
  1131. &dcb_eth0, /*!< \brief Driver control block. */
  1132. DmInit, /*!< \brief Driver initialization routine. */
  1133. DmIOCtl, /*!< \brief Driver specific control function. */
  1134. 0, /*!< \brief Read from device. */
  1135. 0, /*!< \brief Write to device. */
  1136. #ifdef __HARVARD_ARCH__
  1137. 0, /*!< \brief Write from program space data to device. */
  1138. #endif
  1139. 0, /*!< \brief Open a device or file. */
  1140. 0, /*!< \brief Close a device or file. */
  1141. 0, /*!< \brief Request file size. */
  1142. 0, /*!< \brief Select function, optional, not yet implemented */
  1143. };
  1144. #endif /* NIC_BASE_ADDR */
  1145. /*@}*/