dm9000.c 36 KB

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