lan91.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. /*
  2. * Copyright (C) 2003-2006 by egnite Software GmbH.
  3. * Copyright (C) 2008 by egnite 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. /*
  37. * $Id: lan91.c 5472 2013-12-06 00:16:28Z olereinhardt $
  38. */
  39. #include <string.h>
  40. #include <cfg/os.h>
  41. #include <sys/atom.h>
  42. #include <sys/heap.h>
  43. #include <sys/thread.h>
  44. #include <sys/event.h>
  45. #include <sys/timer.h>
  46. #include <sys/confnet.h>
  47. #include <netinet/if_ether.h>
  48. #include <net/ether.h>
  49. #include <net/if.h>
  50. #include <net/if_var.h>
  51. #include <cfg/arch/gpio.h>
  52. #include <dev/irqreg.h>
  53. #include <dev/lan91.h>
  54. #ifdef NUTDEBUG
  55. #include <stdio.h>
  56. #endif
  57. /*
  58. * Determine interrupt settings.
  59. */
  60. #if (LAN91_SIGNAL_IRQ == INT0)
  61. #define LAN91_SIGNAL sig_INTERRUPT0
  62. #elif (LAN91_SIGNAL_IRQ == INT1)
  63. #define LAN91_SIGNAL sig_INTERRUPT1
  64. #elif (LAN91_SIGNAL_IRQ == INT2)
  65. #define LAN91_SIGNAL sig_INTERRUPT2
  66. #elif (LAN91_SIGNAL_IRQ == INT3)
  67. #define LAN91_SIGNAL sig_INTERRUPT3
  68. #elif (LAN91_SIGNAL_IRQ == INT4)
  69. #define LAN91_SIGNAL sig_INTERRUPT4
  70. #elif (LAN91_SIGNAL_IRQ == INT5)
  71. #define LAN91_SIGNAL sig_INTERRUPT5
  72. #elif (LAN91_SIGNAL_IRQ == INT6)
  73. #define LAN91_SIGNAL sig_INTERRUPT6
  74. #elif (LAN91_SIGNAL_IRQ == INT7)
  75. #define LAN91_SIGNAL sig_INTERRUPT7
  76. #endif
  77. /*
  78. * Determine poll timers.
  79. */
  80. #if !defined(LAN91_RX_POLLTIME)
  81. #if defined(LAN91_SIGNAL)
  82. #define LAN91_RX_POLLTIME 2000
  83. #else
  84. #define LAN91_RX_POLLTIME 200
  85. #endif
  86. #endif
  87. #if !defined(LAN91_TX_POLLTIME)
  88. #if defined(LAN91_SIGNAL)
  89. #define LAN91_TX_POLLTIME 5000
  90. #else
  91. #define LAN91_TX_POLLTIME 200
  92. #endif
  93. #endif
  94. /*!
  95. * \addtogroup xgNicLan91
  96. */
  97. /*@{*/
  98. #define nic_outlb(addr, val) (*(volatile uint8_t *)(addr) = (val))
  99. #define nic_outhb(addr, val) (*(volatile uint8_t *)((addr) + 1) = (val))
  100. #define nic_outwx(addr, val) (*(volatile uint16_t *)(addr) = (val))
  101. #define nic_outw(addr, val) { \
  102. *(volatile uint8_t *)(addr) = (uint8_t)(val); \
  103. *((volatile uint8_t *)(addr) + 1) = (uint8_t)((val) >> 8); \
  104. }
  105. #define nic_inlb(addr) (*(volatile uint8_t *)(addr))
  106. #define nic_inhb(addr) (*(volatile uint8_t *)((addr) + 1))
  107. #define nic_inw(addr) (*(volatile uint16_t *)(addr))
  108. #define nic_bs(bank) nic_outlb(LAN91_BSR, bank)
  109. /*!
  110. * \struct _NICINFO
  111. * \brief Network interface controller information structure.
  112. */
  113. struct _NICINFO {
  114. HANDLE volatile ni_rx_rdy; /*!< Receiver event queue. */
  115. uint16_t ni_tx_cnt; /*!< Number of bytes in transmission queue. */
  116. #ifdef NUT_PERFMON
  117. uint32_t ni_rx_packets; /*!< Number of packets received. */
  118. uint32_t ni_tx_packets; /*!< Number of packets sent. */
  119. uint32_t ni_interrupts; /*!< Number of interrupts. */
  120. uint32_t ni_overruns; /*!< Number of packet overruns. */
  121. uint32_t ni_rx_frame_errors; /*!< Number of frame errors. */
  122. uint32_t ni_rx_crc_errors; /*!< Number of CRC errors. */
  123. uint32_t ni_rx_missed_errors; /*!< Number of missed packets. */
  124. #endif
  125. };
  126. /*!
  127. * \brief Network interface controller information type.
  128. */
  129. typedef struct _NICINFO NICINFO;
  130. static HANDLE mutex;
  131. static HANDLE maq;
  132. /*!
  133. * \brief Select specified PHY register for reading or writing.
  134. *
  135. * \note NIC interrupts must have been disabled before calling this routine.
  136. *
  137. * \param reg PHY register number.
  138. * \param we Indicates type of access, 1 for write and 0 for read.
  139. *
  140. * \return Contents of the PHY interface rgister.
  141. */
  142. static uint8_t NicPhyRegSelect(uint8_t reg, uint8_t we)
  143. {
  144. uint8_t rs;
  145. uint8_t msk;
  146. uint_fast8_t i;
  147. nic_bs(3);
  148. rs = (nic_inlb(LAN91_MGMT) & ~(LAN91_MGMT_MCLK | LAN91_MGMT_MDO)) | LAN91_MGMT_MDOE;
  149. /* Send idle pattern. */
  150. for (i = 0; i < 33; i++) {
  151. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO);
  152. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO | LAN91_MGMT_MCLK);
  153. }
  154. /* Send start sequence. */
  155. nic_outlb(LAN91_MGMT, rs);
  156. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MCLK);
  157. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO);
  158. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO | LAN91_MGMT_MCLK);
  159. /* Write or read mode. */
  160. if (we) {
  161. nic_outlb(LAN91_MGMT, rs);
  162. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MCLK);
  163. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO);
  164. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO | LAN91_MGMT_MCLK);
  165. } else {
  166. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO);
  167. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO | LAN91_MGMT_MCLK);
  168. nic_outlb(LAN91_MGMT, rs);
  169. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MCLK);
  170. }
  171. /* Send PHY address. Zero is used for the internal PHY. */
  172. for (i = 0; i < 5; i++) {
  173. nic_outlb(LAN91_MGMT, rs);
  174. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MCLK);
  175. }
  176. /* Send PHY register number. */
  177. for (msk = 0x10; msk; msk >>= 1) {
  178. if (reg & msk) {
  179. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO);
  180. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO | LAN91_MGMT_MCLK);
  181. } else {
  182. nic_outlb(LAN91_MGMT, rs);
  183. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MCLK);
  184. }
  185. }
  186. nic_outlb(LAN91_MGMT, rs);
  187. return rs;
  188. }
  189. /*!
  190. * \brief Read contents of PHY register.
  191. *
  192. * \note NIC interrupts must have been disabled before calling this routine.
  193. *
  194. * \param reg PHY register number.
  195. *
  196. * \return Contents of the specified register.
  197. */
  198. static uint16_t NicPhyRead(uint8_t reg)
  199. {
  200. uint16_t rc = 0;
  201. uint8_t rs;
  202. uint_fast8_t i;
  203. /* Select register for reading. */
  204. rs = NicPhyRegSelect(reg, 0);
  205. /* Switch data direction. */
  206. rs &= ~LAN91_MGMT_MDOE;
  207. nic_outlb(LAN91_MGMT, rs);
  208. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MCLK);
  209. /* Clock data in. */
  210. for (i = 0; i < 16; i++) {
  211. nic_outlb(LAN91_MGMT, rs);
  212. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MCLK);
  213. rc <<= 1;
  214. rc |= (nic_inlb(LAN91_MGMT) & LAN91_MGMT_MDI) != 0;
  215. }
  216. /* This will set the clock line to low. */
  217. nic_outlb(LAN91_MGMT, rs);
  218. return rc;
  219. }
  220. /*!
  221. * \brief Write value to PHY register.
  222. *
  223. * \note NIC interrupts must have been disabled before calling this routine.
  224. *
  225. * \param reg PHY register number.
  226. * \param val Value to write.
  227. */
  228. static void NicPhyWrite(uint8_t reg, uint16_t val)
  229. {
  230. uint16_t msk;
  231. uint8_t rs;
  232. /* Select register for writing. */
  233. rs = NicPhyRegSelect(reg, 1);
  234. /* Switch data direction dummy. */
  235. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO);
  236. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO | LAN91_MGMT_MCLK);
  237. nic_outlb(LAN91_MGMT, rs);
  238. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MCLK);
  239. /* Clock data out. */
  240. for (msk = 0x8000; msk; msk >>= 1) {
  241. if (val & msk) {
  242. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO);
  243. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MDO | LAN91_MGMT_MCLK);
  244. } else {
  245. nic_outlb(LAN91_MGMT, rs);
  246. nic_outlb(LAN91_MGMT, rs | LAN91_MGMT_MCLK);
  247. }
  248. }
  249. /* Set clock line low and output line int z-state. */
  250. nic_outlb(LAN91_MGMT, rs & ~LAN91_MGMT_MDOE);
  251. }
  252. /*!
  253. * \brief Configure the internal PHY.
  254. *
  255. * Reset the PHY and initiate auto-negotiation.
  256. */
  257. static int NicPhyConfig(void)
  258. {
  259. uint16_t phy_sr;
  260. uint16_t phy_to;
  261. uint16_t mode;
  262. /*
  263. * Reset the PHY and wait until this self clearing bit
  264. * becomes zero. We sleep 63 ms before each poll and
  265. * give up after 3 retries.
  266. */
  267. NicPhyWrite(LAN91_PHYCR, LAN91_PHYCR_RST);
  268. for (phy_to = 0;; phy_to++) {
  269. NutSleep(63);
  270. if ((NicPhyRead(LAN91_PHYCR) & LAN91_PHYCR_RST) == 0)
  271. break;
  272. if (phy_to > 3)
  273. return -1;
  274. }
  275. /* Enable PHY interrupts. */
  276. NicPhyWrite(LAN91_PHYMSK, LAN91_PHYMSK_MLOSSSYN | LAN91_PHYMSK_MCWRD | LAN91_PHYMSK_MSSD |
  277. LAN91_PHYMSK_MESD | LAN91_PHYMSK_MRPOL | LAN91_PHYMSK_MJAB | LAN91_PHYMSK_MSPDDT | LAN91_PHYMSK_MDPLDT);
  278. /* Set RPC register. */
  279. mode = LAN91_RPCR_ANEG | LAN91_RPCR_LEDA_PAT | LAN91_RPCR_LEDB_PAT;
  280. nic_bs(0);
  281. nic_outw(LAN91_RPCR, mode);
  282. #ifdef LAN91_FIXED
  283. /* Disable link. */
  284. phy_sr = NicPhyRead(LAN91_PHYCFR1);
  285. NicPhyWrite(LAN91_PHYCFR1, phy_sr | 0x8000);
  286. NutSleep(63);
  287. /* Set fixed capabilities. */
  288. NicPhyWrite(LAN91_PHYCR, LAN91_FIXED);
  289. nic_bs(0);
  290. nic_outw(LAN91_RPCR, mode);
  291. /* Enable link. */
  292. phy_sr = NicPhyRead(LAN91_PHYCFR1);
  293. NicPhyWrite(LAN91_PHYCFR1, phy_sr & ~0x8000);
  294. phy_sr = NicPhyRead(LAN91_PHYCFR1);
  295. #else
  296. /*
  297. * Advertise our capabilities, initiate auto negotiation
  298. * and wait until this has been completed.
  299. */
  300. NicPhyWrite(LAN91_PHYANAD, LAN91_PHYANAD_TX_FDX | LAN91_PHYANAD_TX_HDX | LAN91_PHYANAD_10FDX | LAN91_PHYANAD_10_HDX | LAN91_PHYANAD_CSMA);
  301. NutSleep(63);
  302. for (phy_to = 0, phy_sr = 0;; phy_to++) {
  303. /* Give up after 10 seconds. */
  304. if (phy_to >= 1024)
  305. return -1;
  306. /* Restart auto negotiation every 4 seconds or on failures. */
  307. if ((phy_to & 127) == 0 /* || (phy_sr & LAN91_PHYSR_REM_FLT) != 0 */ ) {
  308. NicPhyWrite(LAN91_PHYCR, LAN91_PHYCR_ANEG_EN | LAN91_PHYCR_ANEG_RST);
  309. NutSleep(63);
  310. }
  311. /* Check if we are done. */
  312. phy_sr = NicPhyRead(LAN91_PHYSR);
  313. if (phy_sr & LAN91_PHYSR_ANEG_ACK)
  314. break;
  315. NutSleep(63);
  316. }
  317. #endif
  318. return 0;
  319. }
  320. /*!
  321. * \brief Wait until MMU is ready.
  322. *
  323. * Poll the MMU command register until \ref LAN91_MMUCR_BUSY
  324. * is cleared.
  325. *
  326. * \param tmo Timeout in milliseconds.
  327. *
  328. * \return 0 on success or -1 on timeout.
  329. */
  330. static INLINE int NicMmuWait(uint_fast16_t tmo)
  331. {
  332. while (tmo--) {
  333. if ((nic_inlb(LAN91_MMUCR) & LAN91_MMUCR_BUSY) == 0)
  334. break;
  335. NutDelay(1);
  336. }
  337. return tmo ? 0 : -1;
  338. }
  339. /*!
  340. * \brief Reset the Ethernet controller.
  341. *
  342. * \return 0 on success, -1 otherwise.
  343. */
  344. static int NicReset(void)
  345. {
  346. #ifdef LAN91_RESET_BIT
  347. GpioPinConfigSet(LAN91_RESET_GPIO_BANK, LAN91_RESET_GPIO_BIT, GPIO_CFG_OUTPUT);
  348. GpioPinSet(LAN91_RESET_GPIO_BANK, LAN91_RESET_GPIO_BIT, 1);
  349. NutDelay(10);
  350. GpioPinSet(LAN91_RESET_GPIO_BANK, LAN91_RESET_GPIO_BIT, 0);
  351. NutDelay(100);
  352. #endif
  353. /* Disable all interrupts. */
  354. nic_outlb(LAN91_MSK, 0);
  355. /* MAC and PHY software reset. */
  356. nic_bs(0);
  357. nic_outw(LAN91_RCR, LAN91_RCR_SOFT_RST);
  358. /* Enable Ethernet protocol handler. */
  359. nic_bs(1);
  360. nic_outw(LAN91_CR, LAN91_CR_EPH_EN);
  361. NutDelay(10);
  362. /* Disable transmit and receive. */
  363. nic_bs(0);
  364. nic_outw(LAN91_RCR, 0);
  365. nic_outw(LAN91_TCR, 0);
  366. /* Enable auto release. */
  367. nic_bs(1);
  368. nic_outw(LAN91_CTR, LAN91_CTR_AUTO_RELEASE);
  369. /* Reset MMU. */
  370. nic_bs(2);
  371. nic_outlb(LAN91_MMUCR, LAN91_MMU_RST);
  372. if (NicMmuWait(1000))
  373. return -1;
  374. return 0;
  375. }
  376. /*
  377. * Fires up the network interface. NIC interrupts
  378. * should have been disabled when calling this
  379. * function.
  380. *
  381. * \param mac Six byte unique MAC address.
  382. */
  383. static int NicStart(const uint8_t * mac)
  384. {
  385. uint_fast8_t i;
  386. if (NicReset())
  387. return -1;
  388. /* Enable receiver. */
  389. nic_bs(3);
  390. nic_outlb(LAN91_ERCV, 7);
  391. nic_bs(0);
  392. nic_outw(LAN91_RCR, LAN91_RCR_RXEN);
  393. /* Enable transmitter and padding. */
  394. nic_outw(LAN91_TCR, LAN91_TCR_PAD_EN | LAN91_TCR_TXENA);
  395. /* Configure the PHY. */
  396. if (NicPhyConfig())
  397. return -1;
  398. /* Set MAC address. */
  399. nic_bs(1);
  400. for (i = 0; i < 6; i++)
  401. nic_outlb(LAN91_IAR + i, mac[i]);
  402. /* Enable interrupts. */
  403. nic_bs(2);
  404. nic_outlb(LAN91_MSK, LAN91_INT_ERCV | LAN91_INT_RCV | LAN91_INT_RX_OVRN);
  405. return 0;
  406. }
  407. #if defined(LAN91_SIGNAL)
  408. /*
  409. * NIC interrupt entry.
  410. */
  411. static void NicInterrupt(void *arg)
  412. {
  413. uint8_t isr;
  414. uint8_t imr;
  415. NICINFO *ni = (NICINFO *) ((NUTDEVICE *) arg)->dev_dcb;
  416. #ifdef NUT_PERFMON
  417. ni->ni_interrupts++;
  418. #endif
  419. /* Read the interrupt mask and disable all interrupts. */
  420. nic_bs(2);
  421. imr = nic_inlb(LAN91_MSK);
  422. nic_outlb(LAN91_MSK, 0);
  423. /* Read the interrupt status and acknowledge all interrupts. */
  424. isr = nic_inlb(LAN91_IST);
  425. isr &= imr;
  426. /*
  427. * If this is a transmit interrupt, then a packet has been sent.
  428. * So we can clear the transmitter busy flag and wake up the
  429. * transmitter thread.
  430. */
  431. if (isr & LAN91_INT_TX_EMPTY) {
  432. nic_outlb(LAN91_ACK, LAN91_INT_TX_EMPTY);
  433. imr &= ~LAN91_INT_TX_EMPTY;
  434. }
  435. /* Transmit error. */
  436. else if (isr & LAN91_INT_TX) {
  437. /* re-enable transmit */
  438. nic_bs(0);
  439. nic_outw(LAN91_TCR, nic_inlb(LAN91_TCR) | LAN91_TCR_TXENA);
  440. nic_bs(2);
  441. nic_outlb(LAN91_ACK, LAN91_INT_TX);
  442. /* kill the packet */
  443. nic_outlb(LAN91_MMUCR, LAN91_MMU_PKT);
  444. }
  445. /*
  446. * If this is a receive interrupt, then wake up the receiver
  447. * thread.
  448. */
  449. if (isr & LAN91_INT_RX_OVRN) {
  450. nic_outlb(LAN91_ACK, LAN91_INT_RX_OVRN);
  451. NutEventPostFromIrq(&ni->ni_rx_rdy);
  452. }
  453. if (isr & LAN91_INT_ERCV) {
  454. nic_outlb(LAN91_ACK, LAN91_INT_ERCV);
  455. NutEventPostFromIrq(&ni->ni_rx_rdy);
  456. }
  457. if (isr & LAN91_INT_RCV) {
  458. nic_outlb(LAN91_ACK, LAN91_INT_RCV);
  459. imr &= ~LAN91_INT_RCV;
  460. NutEventPostFromIrq(&ni->ni_rx_rdy);
  461. }
  462. if (isr & LAN91_INT_ALLOC) {
  463. imr &= ~LAN91_INT_ALLOC;
  464. NutEventPostFromIrq(&maq);
  465. }
  466. nic_outlb(LAN91_MSK, imr);
  467. }
  468. #endif
  469. /*
  470. * Write data block to the NIC.
  471. */
  472. static void NicWrite(uint8_t * buf, uint16_t len)
  473. {
  474. register uint16_t l = len - 1;
  475. register uint8_t ih = (uint16_t) l >> 8;
  476. register uint8_t il = (uint8_t) l;
  477. if (!len)
  478. return;
  479. do {
  480. do {
  481. nic_outlb(LAN91_DATA, *buf++);
  482. } while (il-- != 0);
  483. } while (ih-- != 0);
  484. }
  485. /*
  486. * Read data block from the NIC.
  487. */
  488. static void NicRead(uint8_t * buf, uint16_t len)
  489. {
  490. register uint16_t l = len - 1;
  491. register uint8_t ih = (uint16_t) l >> 8;
  492. register uint8_t il = (uint8_t) l;
  493. if (!len)
  494. return;
  495. do {
  496. do {
  497. *buf++ = nic_inlb(LAN91_DATA);
  498. } while (il-- != 0);
  499. } while (ih-- != 0);
  500. }
  501. /*!
  502. * \brief Fetch the next packet out of the receive ring buffer.
  503. *
  504. * Nic interrupts must be disabled when calling this funtion.
  505. *
  506. * \return Pointer to an allocated ::NETBUF. If there is no
  507. * no data available, then the function returns a
  508. * null pointer. If the NIC's buffer seems to be
  509. * corrupted, a pointer to 0xFFFF is returned.
  510. */
  511. static NETBUF *NicGetPacket(void)
  512. {
  513. NETBUF *nb = 0;
  514. uint16_t fsw;
  515. uint16_t fbc;
  516. /* Check the fifo empty bit. If it is set, then there is
  517. nothing in the receiver fifo. */
  518. nic_bs(2);
  519. if (nic_inw(LAN91_FIFO) & 0x8000) {
  520. return 0;
  521. }
  522. /* Inialize pointer register. */
  523. nic_outw(LAN91_PTR, LAN91_PTR_READ | LAN91_PTR_RCV | LAN91_PTR_AUTO_INCR);
  524. _NOP();
  525. _NOP();
  526. _NOP();
  527. _NOP();
  528. /* Read status word and byte count. */
  529. fsw = nic_inw(LAN91_DATA);
  530. fbc = nic_inw(LAN91_DATA);
  531. /* Check for frame errors. */
  532. if (fsw & 0xAC00) {
  533. nb = (NETBUF *) 0xFFFF;
  534. }
  535. /* Check the byte count. */
  536. else if (fbc < 66 || fbc > 1524) {
  537. nb = (NETBUF *) 0xFFFF;
  538. }
  539. else {
  540. /*
  541. * Allocate a NETBUF.
  542. * Hack alert: Rev A chips never set the odd frame indicator.
  543. */
  544. fbc -= 3;
  545. nb = NutNetBufAlloc(0, NBAF_DATALINK, fbc);
  546. /* Perform the read. */
  547. if (nb)
  548. NicRead(nb->nb_dl.vp, fbc);
  549. }
  550. /* Release the packet. */
  551. nic_outlb(LAN91_MMUCR, LAN91_MMU_TOP);
  552. return nb;
  553. }
  554. /*!
  555. * \brief Load a packet into the nic's transmit ring buffer.
  556. *
  557. * Interupts must have been disabled when calling this function.
  558. *
  559. * \param nb Network buffer structure containing the packet to be sent.
  560. * The structure must have been allocated by a previous
  561. * call NutNetBufAlloc(). This routine will automatically
  562. * release the buffer in case of an error.
  563. *
  564. * \return 0 on success, -1 in case of any errors. Errors
  565. * will automatically release the network buffer
  566. * structure.
  567. */
  568. static int NicPutPacket(NETBUF * nb)
  569. {
  570. uint16_t sz;
  571. uint_fast8_t odd = 0;
  572. uint8_t imsk;
  573. /*
  574. * Calculate the number of bytes to be send. Do not send packets
  575. * larger than the Ethernet maximum transfer unit. The MTU
  576. * consist of 1500 data bytes plus the 14 byte Ethernet header
  577. * plus 4 bytes CRC. We check the data bytes only.
  578. */
  579. if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU)
  580. return -1;
  581. /* Disable all interrupts. */
  582. imsk = nic_inlb(LAN91_MSK);
  583. nic_outlb(LAN91_MSK, 0);
  584. /* Allocate packet buffer space. */
  585. nic_bs(2);
  586. nic_outlb(LAN91_MMUCR, LAN91_MMU_ALO);
  587. if (NicMmuWait(100))
  588. return -1;
  589. /* Enable interrupts including allocation success. */
  590. nic_outlb(LAN91_MSK, imsk | LAN91_INT_ALLOC);
  591. /* The MMU needs some time. Use it to calculate the byte count. */
  592. sz += nb->nb_dl.sz;
  593. sz += 6;
  594. if (sz & 1) {
  595. sz++;
  596. odd++;
  597. }
  598. /* Wait for allocation success. */
  599. while ((nic_inlb(LAN91_IST) & LAN91_INT_ALLOC) == 0) {
  600. if (NutEventWait(&maq, 125)) {
  601. nic_outlb(LAN91_MMUCR, LAN91_MMU_RST);
  602. NicMmuWait(1000);
  603. nic_outlb(LAN91_MMUCR, LAN91_MMU_ALO);
  604. if (NicMmuWait(100) || (nic_inlb(LAN91_IST) & LAN91_INT_ALLOC) == 0) {
  605. if (NutEventWait(&maq, 125)) {
  606. return -1;
  607. }
  608. }
  609. }
  610. }
  611. /* Disable interrupts. */
  612. imsk = nic_inlb(LAN91_MSK);
  613. nic_outlb(LAN91_MSK, 0);
  614. nic_outlb(LAN91_PNR, nic_inhb(LAN91_PNR));
  615. nic_outw(LAN91_PTR, 0x4000);
  616. /* Transfer control word. */
  617. nic_outlb(LAN91_DATA, 0);
  618. nic_outlb(LAN91_DATA, 0);
  619. /* Transfer the byte count. */
  620. nic_outw(LAN91_DATA, sz);
  621. /* Transfer the Ethernet frame. */
  622. NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);
  623. NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);
  624. NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);
  625. NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);
  626. if (odd)
  627. nic_outlb(LAN91_DATA, 0);
  628. /* Transfer the control word. */
  629. nic_outw(LAN91_DATA, 0);
  630. /* Enqueue packet. */
  631. if (NicMmuWait(100))
  632. return -1;
  633. nic_outlb(LAN91_MMUCR, LAN91_MMU_ENQ);
  634. /* Enable interrupts. */
  635. imsk |= LAN91_INT_TX | LAN91_INT_TX_EMPTY;
  636. nic_outlb(LAN91_MSK, imsk);
  637. return 0;
  638. }
  639. /*! \fn NicRxLanc(void *arg)
  640. * \brief NIC receiver thread.
  641. *
  642. */
  643. THREAD(NicRxLanc, arg)
  644. {
  645. NUTDEVICE *dev;
  646. IFNET *ifn;
  647. NICINFO *ni;
  648. NETBUF *nb;
  649. uint8_t imsk;
  650. dev = arg;
  651. ifn = (IFNET *) dev->dev_icb;
  652. ni = (NICINFO *) dev->dev_dcb;
  653. /*
  654. * This is a temporary hack. Due to a change in initialization,
  655. * we may not have got a MAC address yet. Wait until a valid one
  656. * has been set.
  657. */
  658. while (!ETHER_IS_UNICAST(ifn->if_mac)) {
  659. NutSleep(10);
  660. }
  661. /*
  662. * Do not continue unless we managed to start the NIC. We are
  663. * trapped here if the Ethernet link cannot be established.
  664. * This happens, for example, if no Ethernet cable is plugged
  665. * in.
  666. */
  667. while(NicStart(ifn->if_mac)) {
  668. NutSleep(1000);
  669. }
  670. #ifdef LAN91_SIGNAL
  671. NutIrqSetMode(&LAN91_SIGNAL, NUT_IRQMODE_RISINGEDGE);
  672. NutIrqEnable(&LAN91_SIGNAL);
  673. #endif
  674. NutEventPost(&mutex);
  675. /* Run at high priority. */
  676. NutThreadSetPriority(9);
  677. for (;;) {
  678. /*
  679. * Wait for the arrival of new packets or
  680. * check the receiver every two second.
  681. */
  682. NutEventWait(&ni->ni_rx_rdy, LAN91_RX_POLLTIME);
  683. /*
  684. * Fetch all packets from the NIC's internal
  685. * buffer and pass them to the registered handler.
  686. */
  687. imsk = nic_inlb(LAN91_MSK);
  688. nic_outlb(LAN91_MSK, 0);
  689. while ((nb = NicGetPacket()) != 0) {
  690. if (nb != (NETBUF *) 0xFFFF) {
  691. #ifdef NUT_PERFMON
  692. ni->ni_rx_packets++;
  693. #endif
  694. (*ifn->if_recv) (dev, nb);
  695. }
  696. }
  697. nic_outlb(LAN91_MSK, imsk | LAN91_INT_RCV | LAN91_INT_ERCV);
  698. }
  699. }
  700. /*!
  701. * \brief Send Ethernet packet.
  702. *
  703. * \param dev Identifies the device to use.
  704. * \param nb Network buffer structure containing the packet to be sent.
  705. * The structure must have been allocated by a previous
  706. * call NutNetBufAlloc().
  707. *
  708. * \return 0 on success, -1 in case of any errors.
  709. */
  710. static int Lan91Output(NUTDEVICE * dev, NETBUF * nb)
  711. {
  712. static uint_fast16_t mx_wait = LAN91_TX_POLLTIME;
  713. int rc = -1;
  714. /*
  715. * After initialization we are waiting for a long time to give
  716. * the PHY a chance to establish an Ethernet link.
  717. */
  718. if (NutEventWait(&mutex, mx_wait) == 0) {
  719. if (NicPutPacket(nb) == 0) {
  720. #ifdef NUT_PERFMON
  721. NICINFO *ni = (NICINFO *) dev->dev_dcb;
  722. ni->ni_tx_packets++;
  723. #endif
  724. rc = 0;
  725. /* Ethernet works. Set a long waiting time in case we
  726. temporarly lose the link next time. */
  727. mx_wait = LAN91_TX_POLLTIME;
  728. }
  729. NutEventPost(&mutex);
  730. }
  731. #if defined(LAN91_SIGNAL)
  732. /*
  733. * Probably no Ethernet link. Significantly reduce the waiting
  734. * time, so following transmission will soon return an error.
  735. */
  736. else {
  737. mx_wait = 500;
  738. }
  739. #endif
  740. return rc;
  741. }
  742. /*!
  743. * \brief Initialize Ethernet hardware.
  744. *
  745. * Resets the LAN91 Ethernet controller, initializes all required
  746. * hardware registers and starts a background thread for incoming
  747. * Ethernet traffic.
  748. *
  749. * Applications should do not directly call this function. It is
  750. * automatically executed during during device registration by
  751. * NutRegisterDevice().
  752. *
  753. * If the network configuration hasn't been set by the application
  754. * before registering the specified device, this function will
  755. * call NutNetLoadConfig() to get the MAC address.
  756. *
  757. * \param dev Identifies the device to initialize.
  758. */
  759. static int Lan91Init(NUTDEVICE * dev)
  760. {
  761. /* Disable NIC interrupt and clear NICINFO structure. */
  762. #ifdef LAN91_SIGNAL
  763. NutIrqDisable(&LAN91_SIGNAL);
  764. #endif
  765. memset(dev->dev_dcb, 0, sizeof(NICINFO));
  766. #ifdef LAN91_SIGNAL
  767. /* Register interrupt handler and enable interrupts. */
  768. if (NutRegisterIrqHandler(&LAN91_SIGNAL, NicInterrupt, dev))
  769. return -1;
  770. #endif
  771. /*
  772. * Start the receiver thread.
  773. */
  774. NutThreadCreate("lan91rx", NicRxLanc, dev, 640);
  775. return 0;
  776. }
  777. static int Lan91IOCtl(NUTDEVICE * dev, int req, void *conf)
  778. {
  779. int rc = 0;
  780. uint32_t *lvp = (uint32_t *) conf;
  781. IFNET *nif = (IFNET *) dev->dev_icb;
  782. switch (req) {
  783. case SIOCSIFFLAGS:
  784. /* Set interface flags. */
  785. if (*lvp & IFF_UP) {
  786. if ((nif->if_flags & IFF_UP) == 0) {
  787. /* Start interface. */
  788. }
  789. } else if (nif->if_flags & IFF_UP) {
  790. /* Stop interface. */
  791. }
  792. break;
  793. case SIOCGIFFLAGS:
  794. /* Get interface flags. */
  795. *lvp = nif->if_flags;
  796. break;
  797. case SIOCSIFADDR:
  798. /* Set interface hardware address. */
  799. memcpy(nif->if_mac, conf, sizeof(nif->if_mac));
  800. break;
  801. case SIOCGIFADDR:
  802. /* Get interface hardware address. */
  803. memcpy(conf, nif->if_mac, sizeof(nif->if_mac));
  804. break;
  805. default:
  806. rc = -1;
  807. break;
  808. }
  809. return rc;
  810. }
  811. static NICINFO dcb_eth0;
  812. /*!
  813. * \brief Network interface information structure.
  814. *
  815. * Used to call.
  816. */
  817. static IFNET ifn_eth0 = {
  818. IFT_ETHER, /*!< \brief Interface type, if_type. */
  819. 0, /*!< \brief Interface flags, if_flags. */
  820. {0, 0, 0, 0, 0, 0}, /*!< \brief Hardware net address, if_mac. */
  821. 0, /*!< \brief IP address, if_local_ip. */
  822. 0, /*!< \brief Remote IP address for point to point, if_remote_ip. */
  823. 0, /*!< \brief IP network mask, if_mask. */
  824. ETHERMTU, /*!< \brief Maximum size of a transmission unit, if_mtu. */
  825. 0, /*!< \brief Packet identifier, if_pkt_id. */
  826. 0, /*!< \brief Linked list of arp entries, arpTable. */
  827. 0, /*!< \brief Linked list of multicast address entries, if_mcast. */
  828. NutEtherInput, /*!< \brief Routine to pass received data to, if_recv(). */
  829. Lan91Output, /*!< \brief Driver output routine, if_send(). */
  830. NutEtherOutput, /*!< \brief Media output routine, if_output(). */
  831. NULL /*!< \brief Interface specific control function, if_ioctl(). */
  832. #ifdef NUT_PERFMON
  833. , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  834. #endif
  835. };
  836. /*!
  837. * \brief Device information structure.
  838. *
  839. * A pointer to this structure must be passed to NutRegisterDevice()
  840. * to bind this Ethernet device driver to the Nut/OS kernel.
  841. * An application may then call NutNetIfConfig() with the name \em eth0
  842. * of this driver to initialize the network interface.
  843. *
  844. */
  845. NUTDEVICE devLan91 = {
  846. 0, /* Pointer to next device. */
  847. {'e', 't', 'h', '0', 0, 0, 0, 0, 0}, /* Unique device name. */
  848. IFTYP_NET, /* Type of device. */
  849. 0, /* Base address. */
  850. 0, /* First interrupt number. */
  851. &ifn_eth0, /* Interface control block. */
  852. &dcb_eth0, /* Driver control block. */
  853. Lan91Init, /* Driver initialization routine. */
  854. Lan91IOCtl, /* Driver specific control function. */
  855. 0, /* Read from device. */
  856. 0, /* Write to device. */
  857. #ifdef __HARVARD_ARCH__
  858. 0, /* Write from program space data to device. */
  859. #endif
  860. 0, /* Open a device or file. */
  861. 0, /* Close a device or file. */
  862. 0, /* Request file size. */
  863. 0, /* Select function, optional, not yet implemented */
  864. };
  865. /*@}*/