at91sam7x_emac.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783
  1. /*
  2. * Copyright (C) 2006 by egnite Software GmbH. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holders nor the names of
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  24. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  25. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  26. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  27. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. /*
  34. * $Log$
  35. * Revision 1.9 2009/02/06 15:37:39 haraldkipp
  36. * Added stack space multiplier and addend. Adjusted stack space.
  37. *
  38. * Revision 1.8 2009/01/17 11:26:37 haraldkipp
  39. * Getting rid of two remaining BSD types in favor of stdint.
  40. * Replaced 'u_int' by 'unsinged int' and 'uptr_t' by 'uintptr_t'.
  41. *
  42. * Revision 1.7 2008/08/28 11:12:15 haraldkipp
  43. * Added interface flags, which will be required to implement Ethernet ioctl
  44. * functions.
  45. *
  46. * Revision 1.6 2008/08/11 06:59:05 haraldkipp
  47. * BSD types replaced by stdint types (feature request #1282721).
  48. *
  49. * Revision 1.5 2007/05/02 11:28:47 haraldkipp
  50. * Added multicast table entry.
  51. *
  52. * Revision 1.4 2006/08/31 19:19:55 haraldkipp
  53. * No time to write comments. ;-)
  54. *
  55. * Revision 1.3 2006/07/18 14:01:38 haraldkipp
  56. * Transmitter buffer handling was buggy and delayed any second packet.
  57. * Added handling of receiver overflow events.
  58. *
  59. * Revision 1.2 2006/07/15 11:11:44 haraldkipp
  60. * PHY initialization disabled user reset. Packet receiver routine filled
  61. * wrong buffer and always returned an error.
  62. * Many thanks to Andras Albert for fixing this.
  63. *
  64. * Revision 1.1 2006/07/05 07:38:44 haraldkipp
  65. * New Ethernet driver for the AT91SAM7X EMAC and the Davicom DM9161A.
  66. * This driver is not yet finished. Ethernet link auto-negotiation works
  67. * and receive interrupts are generated when sending packets to the
  68. * board. But transmitting packets fails, nothing is sent out.
  69. *
  70. */
  71. #include <cfg/os.h>
  72. #include <arch/arm.h>
  73. #include <string.h>
  74. #include <sys/atom.h>
  75. #include <sys/heap.h>
  76. #include <sys/thread.h>
  77. #include <sys/event.h>
  78. #include <sys/timer.h>
  79. #include <sys/confnet.h>
  80. #include <netinet/if_ether.h>
  81. #include <net/ether.h>
  82. #include <net/if_var.h>
  83. #include <dev/irqreg.h>
  84. #include <dev/phy.h>
  85. #include <dev/at91sam7x_emac.h>
  86. #define NUTDEBUG
  87. /* WARNING: Variadic macros are C99 and may fail with C89 compilers. */
  88. #ifdef NUTDEBUG
  89. #include <stdio.h>
  90. #define EMPRINTF(args,...) printf(args,##__VA_ARGS__)
  91. #else
  92. #define EMPRINTF(args,...)
  93. #endif
  94. #ifndef NUT_THREAD_NICRXSTACK
  95. #define NUT_THREAD_NICRXSTACK 768
  96. #endif
  97. #ifndef EMAC_RX_BUFFERS
  98. #define EMAC_RX_BUFFERS 32
  99. #endif
  100. #define EMAC_RX_BUFSIZ 128
  101. #define EMAC_TX_BUFFERS 2
  102. #ifndef EMAC_TX_BUFSIZ
  103. #define EMAC_TX_BUFSIZ 1536
  104. #endif
  105. #define NIC_PHY_ADDR 31
  106. #define PHY_TXCLK_ISOLATE_BIT 0
  107. #define PHY_REFCLK_XT2_BIT 0
  108. #define PHY_TXEN_BIT 1
  109. #define PHY_TXD0_BIT 2
  110. #define PHY_TXD1_BIT 3
  111. #define PHY_CRS_AD4_BIT 4
  112. #define PHY_RXD0_AD0_BIT 5
  113. #define PHY_RXD1_AD1_BIT 6
  114. #define PHY_RXER_RXD4_RPTR_BIT 7
  115. #define PHY_MDC_BIT 8
  116. #define PHY_MDIO_BIT 9
  117. #define PHY_TXD2_BIT 10
  118. #define PHY_TXD3_BIT 11
  119. #define PHY_TXER_TXD4_BIT 12
  120. #define PHY_RXD2_AD2_BIT 13
  121. #define PHY_RXD3_AD3_BIT 14
  122. #define PHY_RXDV_TESTMODE_BIT 15
  123. #define PHY_COL_RMII_BIT 16
  124. #define PHY_RXCLK_10BTSER_BIT 17
  125. #define PHY_PWRDN_BIT 18
  126. #define PHY_MDINTR_BIT 26
  127. #define PHY_MII_PINS _BV(PHY_REFCLK_XT2_BIT) \
  128. | _BV(PHY_TXEN_BIT) \
  129. | _BV(PHY_TXD0_BIT) \
  130. | _BV(PHY_TXD1_BIT) \
  131. | _BV(PHY_CRS_AD4_BIT) \
  132. | _BV(PHY_RXD0_AD0_BIT) \
  133. | _BV(PHY_RXD1_AD1_BIT) \
  134. | _BV(PHY_RXER_RXD4_RPTR_BIT) \
  135. | _BV(PHY_MDC_BIT) \
  136. | _BV(PHY_MDIO_BIT) \
  137. | _BV(PHY_TXD2_BIT) \
  138. | _BV(PHY_TXD3_BIT) \
  139. | _BV(PHY_TXER_TXD4_BIT) \
  140. | _BV(PHY_RXD2_AD2_BIT) \
  141. | _BV(PHY_RXD3_AD3_BIT) \
  142. | _BV(PHY_RXDV_TESTMODE_BIT) \
  143. | _BV(PHY_COL_RMII_BIT) \
  144. | _BV(PHY_RXCLK_10BTSER_BIT)
  145. /*!
  146. * \brief Network interface controller information structure.
  147. */
  148. struct _EMACINFO {
  149. #ifdef NUT_PERFMON
  150. uint32_t ni_rx_packets; /*!< Number of packets received. */
  151. uint32_t ni_tx_packets; /*!< Number of packets sent. */
  152. uint32_t ni_overruns; /*!< Number of packet overruns. */
  153. uint32_t ni_rx_frame_errors; /*!< Number of frame errors. */
  154. uint32_t ni_rx_crc_errors; /*!< Number of CRC errors. */
  155. uint32_t ni_rx_missed_errors; /*!< Number of missed packets. */
  156. #endif
  157. HANDLE volatile ni_rx_rdy; /*!< Receiver event queue. */
  158. HANDLE volatile ni_tx_rdy; /*!< Transmitter event queue. */
  159. HANDLE ni_mutex; /*!< Access mutex semaphore. */
  160. volatile int ni_tx_queued; /*!< Number of packets in transmission queue. */
  161. volatile int ni_tx_quelen; /*!< Number of bytes in transmission queue not sent. */
  162. volatile int ni_insane; /*!< Set by error detection. */
  163. int ni_iomode; /*!< 8 or 16 bit access. 32 bit is not supported. */
  164. };
  165. /*!
  166. * \brief Network interface controller information type.
  167. */
  168. typedef struct _EMACINFO EMACINFO;
  169. /*
  170. * TODO: Buffers and their descriptors should be part of the EMACINFO
  171. * structure. Actually there will be no dual Ethernet chip (sure?),
  172. * but just to keep the code clean.
  173. */
  174. typedef struct _BufDescriptor {
  175. unsigned int addr;
  176. unsigned int stat;
  177. } BufDescriptor;
  178. static volatile BufDescriptor txBufTab[2];
  179. static volatile uint8_t txBuf[EMAC_TX_BUFFERS * EMAC_TX_BUFSIZ] NUT_ALIGNED_TYPE(8);
  180. static unsigned int txBufIdx;
  181. static volatile BufDescriptor rxBufTab[EMAC_RX_BUFFERS];
  182. static volatile uint8_t rxBuf[EMAC_RX_BUFFERS * EMAC_RX_BUFSIZ] NUT_ALIGNED_TYPE(8);
  183. static unsigned int rxBufIdx;
  184. #define RXBUF_OWNERSHIP 0x00000001
  185. #define RXBUF_WRAP 0x00000002
  186. #define RXBUF_ADDRMASK 0xFFFFFFFC
  187. #define RXS_BROADCAST_ADDR 0x80000000 /*!< \brief Broadcast address detected. */
  188. #define RXS_MULTICAST_HASH 0x40000000 /*!< \brief Multicast hash match. */
  189. #define RXS_UNICAST_HASH 0x20000000 /*!< \brief Unicast hash match. */
  190. #define RXS_EXTERNAL_ADDR 0x10000000 /*!< \brief External address match. */
  191. #define RXS_SA1_ADDR 0x04000000 /*!< \brief Specific address register 1 match. */
  192. #define RXS_SA2_ADDR 0x02000000 /*!< \brief Specific address register 2 match. */
  193. #define RXS_SA3_ADDR 0x01000000 /*!< \brief Specific address register 3 match. */
  194. #define RXS_SA4_ADDR 0x00800000 /*!< \brief Specific address register 4 match. */
  195. #define RXS_TYPE_ID 0x00400000 /*!< \brief Type ID match. */
  196. #define RXS_VLAN_TAG 0x00200000 /*!< \brief VLAN tag detected. */
  197. #define RXS_PRIORITY_TAG 0x00100000 /*!< \brief Priority tag detected. */
  198. #define RXS_VLAN_PRIORITY 0x000E0000 /*!< \brief VLAN priority. */
  199. #define RXS_CFI_IND 0x00010000 /*!< \brief Concatenation format indicator. */
  200. #define RXS_EOF 0x00008000 /*!< \brief End of frame. */
  201. #define RXS_SOF 0x00004000 /*!< \brief Start of frame. */
  202. #define RXS_RBF_OFFSET 0x00003000 /*!< \brief Receive buffer offset mask. */
  203. #define RXS_LENGTH_FRAME 0x000007FF /*!< \brief Length of frame including FCS. */
  204. #define TXS_USED 0x80000000 /*!< \brief Used buffer. */
  205. #define TXS_WRAP 0x40000000 /*!< \brief Last descriptor. */
  206. #define TXS_ERROR 0x20000000 /*!< \brief Retry limit exceeded. */
  207. #define TXS_UNDERRUN 0x10000000 /*!< \brief Transmit underrun. */
  208. #define TXS_NO_BUFFER 0x08000000 /*!< \brief Buffer exhausted. */
  209. #define TXS_NO_CRC 0x00010000 /*!< \brief CRC not appended. */
  210. #define TXS_LAST_BUFF 0x00008000 /*!< \brief Last buffer of frame. */
  211. /*!
  212. * \addtogroup xgEmacSam7x
  213. */
  214. /*@{*/
  215. /*!
  216. * \brief Read contents of PHY register.
  217. *
  218. * \param reg PHY register number.
  219. *
  220. * \return Contents of the specified register.
  221. */
  222. static int phy_inw(uint8_t reg, uint16_t *val)
  223. {
  224. /* PHY read command. */
  225. outr(EMAC_MAN, _BV(30) | _BV(29) | _BV(17) | ((NIC_PHY_ADDR) << 23) | ((reg & 0x1F) << 18));
  226. /* Wait until PHY logic completed. */
  227. while ((inr(EMAC_NSR) & EMAC_IDLE) == 0);
  228. /* Get data from PHY maintenance register. */
  229. *val = (uint16_t) inr(EMAC_MAN);
  230. return 0;
  231. }
  232. /*!
  233. * \brief Write value to PHY register.
  234. *
  235. * \param reg PHY register number.
  236. * \param val Value to write.
  237. */
  238. static int phy_outw(uint8_t reg, uint16_t *val)
  239. {
  240. /* PHY write command. */
  241. outr(EMAC_MAN, _BV(30) | _BV(28) | _BV(17) | ((NIC_PHY_ADDR) << 23) | ((reg & 0x1F) << 18) | *val);
  242. /* Wait until PHY logic completed. */
  243. while ((inr(EMAC_NSR) & EMAC_IDLE) == 0);
  244. }
  245. /*!
  246. * \brief Reset the Ethernet controller.
  247. *
  248. * \return 0 on success, -1 otherwise.
  249. */
  250. static int EmacReset(void)
  251. {
  252. int rc = 0;
  253. uint16_t phy = 0;
  254. int link_wait;
  255. outr(PMC_PCER, _BV(PIOA_ID));
  256. outr(PMC_PCER, _BV(PIOB_ID));
  257. outr(PMC_PCER, _BV(EMAC_ID));
  258. /* Disable RMII and TESTMODE by disabling pull-ups. */
  259. outr(PIOB_PUDR, _BV(PHY_COL_RMII_BIT) | _BV(PHY_RXDV_TESTMODE_BIT));
  260. /* Disable PHY power down. */
  261. outr(PIOB_PER, _BV(PHY_PWRDN_BIT));
  262. outr(PIOB_OER, _BV(PHY_PWRDN_BIT));
  263. outr(PIOB_CODR, _BV(PHY_PWRDN_BIT));
  264. /* Toggle external hardware reset pin. */
  265. outr(RSTC_MR, RSTC_KEY | 0x00000100 | RSTC_URSTEN);
  266. outr(RSTC_CR, RSTC_KEY | RSTC_EXTRST);
  267. while ((inr(RSTC_SR) & RSTC_NRSTL) == 0);
  268. /* Configure MII port. */
  269. outr(PIOB_ASR, PHY_MII_PINS);
  270. outr(PIOB_BSR, 0);
  271. outr(PIOB_PDR, PHY_MII_PINS);
  272. /* Enable management port. */
  273. outr(EMAC_NCR, inr(EMAC_NCR) | EMAC_MPE);
  274. outr(EMAC_NCFGR, inr(EMAC_NCFGR) | EMAC_CLK_HCLK_32);
  275. /* Wait for PHY ready. */
  276. NutDelay(255);
  277. /* Register PHY */
  278. rc = NutRegisterPhy( 1, phy_outw, phy_inw);
  279. EMPRINTF("EMRPHY rc = %d\n", rc);
  280. /* Clear MII isolate. */
  281. NutPhyCtl(PHY_CTL_ISOLATE, &phy);
  282. /* Wait for auto negotiation completed. */
  283. /* Wait for link. */
  284. for (link_wait = 20;; link_wait--) {
  285. NutPhyCtl(PHY_GET_LINK, &phy);
  286. if (phy==0)
  287. break;
  288. }
  289. if (link_wait == 0) {
  290. return -1;
  291. }
  292. NutSleep(200);
  293. }
  294. /* Disable management port. */
  295. outr(EMAC_NCR, inr(EMAC_NCR) & ~EMAC_MPE);
  296. /* Enable receive and transmit clocks. */
  297. outr(EMAC_USRIO, EMAC_CLKEN);
  298. return rc;
  299. }
  300. /*
  301. * NIC interrupt entry.
  302. */
  303. static void EmacInterrupt(void *arg)
  304. {
  305. unsigned int isr;
  306. EMACINFO *ni = (EMACINFO *) ((NUTDEVICE *) arg)->dev_dcb;
  307. /* Read interrupt status and disable interrupts. */
  308. isr = inr(EMAC_ISR);
  309. /* Receiver interrupt. */
  310. if ((isr & EMAC_RCOMP) != 0 || (isr & EMAC_ROVR) != 0 || (inr(EMAC_RSR) & EMAC_REC) != 0) {
  311. outr(EMAC_RSR, EMAC_REC);
  312. NutEventPostFromIrq(&ni->ni_rx_rdy);
  313. }
  314. /* Transmitter interrupt. */
  315. if ((isr & EMAC_TCOMP) != 0 || (inr(EMAC_TSR) & EMAC_COMP) != 0) {
  316. outr(EMAC_TSR, EMAC_COMP);
  317. NutEventPostFromIrq(&ni->ni_tx_rdy);
  318. }
  319. }
  320. /*!
  321. * \brief Fetch the next packet out of the receive buffers.
  322. *
  323. * \return 0 on success, -1 otherwise.
  324. */
  325. static int EmacGetPacket(EMACINFO * ni, NETBUF ** nbp)
  326. {
  327. int rc = -1;
  328. uint16_t fbc = 0;
  329. unsigned int i;
  330. *nbp = NULL;
  331. /*
  332. * Search the next frame start. Release any fragment.
  333. */
  334. while ((rxBufTab[rxBufIdx].addr & RXBUF_OWNERSHIP) != 0 && (rxBufTab[rxBufIdx].stat & RXS_SOF) == 0) {
  335. rxBufTab[rxBufIdx].addr &= ~(RXBUF_OWNERSHIP);
  336. rxBufIdx++;
  337. if (rxBufIdx >= EMAC_RX_BUFFERS) {
  338. rxBufIdx = 0;
  339. }
  340. }
  341. /*
  342. * Determine the size of the next frame.
  343. */
  344. i = rxBufIdx;
  345. while (rxBufTab[i].addr & RXBUF_OWNERSHIP) {
  346. if ((fbc = rxBufTab[i].stat & RXS_LENGTH_FRAME) != 0) {
  347. break;
  348. }
  349. i++;
  350. if (i >= EMAC_RX_BUFFERS) {
  351. i = 0;
  352. }
  353. }
  354. if (fbc) {
  355. /*
  356. * Receiving long packets is unexpected. Let's declare the
  357. * chip insane. Short packets will be handled by the caller.
  358. */
  359. if (fbc > EMAC_TX_BUFSIZ) {
  360. ni->ni_insane = 1;
  361. } else {
  362. *nbp = NutNetBufAlloc(0, NBAF_DATALINK, fbc);
  363. if (*nbp != NULL) {
  364. uint8_t *bp = (uint8_t *) (* nbp)->nb_dl.vp;
  365. unsigned int len;
  366. while (fbc) {
  367. if (fbc > EMAC_RX_BUFSIZ) {
  368. len = EMAC_RX_BUFSIZ;
  369. } else {
  370. len = fbc;
  371. }
  372. memcpy(bp, (void *) (rxBufTab[rxBufIdx].addr & RXBUF_ADDRMASK), len);
  373. rxBufTab[rxBufIdx].addr &= ~RXBUF_OWNERSHIP;
  374. rxBufIdx++;
  375. if (rxBufIdx >= EMAC_RX_BUFFERS) {
  376. rxBufIdx = 0;
  377. }
  378. fbc -= len;
  379. bp += len;
  380. }
  381. rc = 0;
  382. }
  383. }
  384. }
  385. return rc;
  386. }
  387. /*!
  388. * \brief Load a packet into the nic's transmit ring buffer.
  389. *
  390. * \todo This routine simply does not work. Any idea?
  391. *
  392. * \param nb Network buffer structure containing the packet to be sent.
  393. * The structure must have been allocated by a previous
  394. * call NutNetBufAlloc(). This routine will automatically
  395. * release the buffer in case of an error.
  396. *
  397. * \return 0 on success, -1 in case of any errors. Errors
  398. * will automatically release the network buffer
  399. * structure.
  400. */
  401. static int EmacPutPacket(int bufnum, EMACINFO * ni, NETBUF * nb)
  402. {
  403. int rc = -1;
  404. unsigned int sz;
  405. uint8_t *buf;
  406. /*
  407. * Calculate the number of bytes to be send. Do not send packets
  408. * larger than the Ethernet maximum transfer unit. The MTU
  409. * consist of 1500 data bytes plus the 14 byte Ethernet header
  410. * plus 4 bytes CRC. We check the data bytes only.
  411. */
  412. if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU) {
  413. return -1;
  414. }
  415. sz += nb->nb_dl.sz;
  416. if (sz & 1) {
  417. sz++;
  418. }
  419. /* Disable EMAC interrupts. */
  420. NutIrqDisable(&sig_EMAC);
  421. /* TODO: Check for link. */
  422. if (ni->ni_insane == 0) {
  423. buf = (uint8_t *) txBufTab[bufnum].addr;
  424. memcpy(buf, nb->nb_dl.vp, nb->nb_dl.sz);
  425. buf += nb->nb_dl.sz;
  426. memcpy(buf, nb->nb_nw.vp, nb->nb_nw.sz);
  427. buf += nb->nb_nw.sz;
  428. memcpy(buf, nb->nb_tp.vp, nb->nb_tp.sz);
  429. buf += nb->nb_tp.sz;
  430. memcpy(buf, nb->nb_ap.vp, nb->nb_ap.sz);
  431. sz |= TXS_LAST_BUFF;
  432. if (bufnum) {
  433. sz |= TXS_WRAP;
  434. }
  435. txBufTab[bufnum].stat = sz;
  436. outr(EMAC_NCR, inr(EMAC_NCR) | EMAC_TSTART);
  437. rc = 0;
  438. #ifdef NUT_PERFMON
  439. ni->ni_tx_packets++;
  440. #endif
  441. }
  442. /* Enable EMAC interrupts. */
  443. NutIrqEnable(&sig_EMAC);
  444. return rc;
  445. }
  446. /*!
  447. * \brief Fire up the network interface.
  448. *
  449. * NIC interrupts must be disabled when calling this function.
  450. *
  451. * \param mac Six byte unique MAC address.
  452. */
  453. static int EmacStart(const uint8_t * mac)
  454. {
  455. int i;
  456. if (EmacReset()) {
  457. return -1;
  458. }
  459. /* Set local MAC address. */
  460. outr(EMAC_SA1L, (mac[3] << 24) | (mac[2] << 16) | (mac[1] << 8) | mac[0]);
  461. outr(EMAC_SA1H, (mac[5] << 8) | mac[4]);
  462. /* Initialize receive buffer descriptors. */
  463. for (i = 0; i < EMAC_RX_BUFFERS - 1; i++) {
  464. rxBufTab[i].addr = (unsigned int) (&rxBuf[i * EMAC_RX_BUFSIZ]) & RXBUF_ADDRMASK;
  465. }
  466. rxBufTab[i].addr = ((unsigned int) (&rxBuf[i * EMAC_RX_BUFSIZ]) & RXBUF_ADDRMASK) | RXBUF_WRAP;
  467. outr(EMAC_RBQP, (unsigned int) rxBufTab);
  468. /* Initialize transmit buffer descriptors. */
  469. txBufTab[0].addr = (unsigned int) (&txBuf[0]);
  470. txBufTab[0].stat = TXS_USED;
  471. txBufTab[1].addr = (unsigned int) (&txBuf[EMAC_TX_BUFSIZ]);
  472. txBufTab[1].stat = TXS_USED | TXS_WRAP;
  473. outr(EMAC_TBQP, (unsigned int) txBufTab);
  474. /* Clear receiver status. */
  475. outr(EMAC_RSR, EMAC_OVR | EMAC_REC | EMAC_BNA);
  476. /* Copy all frames and discard FCS. */
  477. outr(EMAC_NCFGR, inr(EMAC_NCFGR) | EMAC_CAF | EMAC_DRFCS);
  478. /* Enable receiver, transmitter and statistics. */
  479. outr(EMAC_NCR, inr(EMAC_NCR) | EMAC_TE | EMAC_RE | EMAC_WESTAT);
  480. return 0;
  481. }
  482. /*! \fn EmacRxThread(void *arg)
  483. * \brief NIC receiver thread.
  484. *
  485. */
  486. THREAD(EmacRxThread, arg)
  487. {
  488. NUTDEVICE *dev;
  489. IFNET *ifn;
  490. EMACINFO *ni;
  491. NETBUF *nb;
  492. dev = arg;
  493. ifn = (IFNET *) dev->dev_icb;
  494. ni = (EMACINFO *) dev->dev_dcb;
  495. /*
  496. * This is a temporary hack. Due to a change in initialization,
  497. * we may not have got a MAC address yet. Wait until a valid one
  498. * has been set.
  499. */
  500. while (!ETHER_IS_UNICAST(ifn->if_mac)) {
  501. NutSleep(10);
  502. }
  503. /*
  504. * Do not continue unless we managed to start the NIC. We are
  505. * trapped here if the Ethernet link cannot be established.
  506. * This happens, for example, if no Ethernet cable is plugged
  507. * in.
  508. */
  509. while (EmacStart(ifn->if_mac)) {
  510. NutSleep(1000);
  511. }
  512. /* Initialize the access mutex. */
  513. NutEventPost(&ni->ni_mutex);
  514. /* Run at high priority. */
  515. NutThreadSetPriority(9);
  516. /* Enable receive interrupts. */
  517. outr(EMAC_IER, EMAC_RCOMP | EMAC_TCOMP | EMAC_ROVR);
  518. NutIrqEnable(&sig_EMAC);
  519. for (;;) {
  520. /*
  521. * Wait for the arrival of new packets or poll the receiver
  522. * every two seconds.
  523. */
  524. NutEventWait(&ni->ni_rx_rdy, 2000);
  525. /*
  526. * Fetch all packets from the NIC's internal buffer and pass
  527. * them to the registered handler.
  528. */
  529. while (EmacGetPacket(ni, &nb) == 0) {
  530. /* Discard short packets. */
  531. if (nb->nb_dl.sz < 60) {
  532. NutNetBufFree(nb);
  533. } else {
  534. (*ifn->if_recv) (dev, nb);
  535. }
  536. }
  537. /* We got a weird chip, try to restart it. */
  538. while (ni->ni_insane) {
  539. if (EmacStart(ifn->if_mac) == 0) {
  540. ni->ni_insane = 0;
  541. ni->ni_tx_queued = 0;
  542. ni->ni_tx_quelen = 0;
  543. NutIrqEnable(&sig_EMAC);
  544. } else {
  545. NutSleep(1000);
  546. }
  547. }
  548. }
  549. }
  550. /*!
  551. * \brief Send Ethernet packet.
  552. *
  553. * \todo This routine does not work.
  554. *
  555. * \param dev Identifies the device to use.
  556. * \param nb Network buffer structure containing the packet to be sent.
  557. * The structure must have been allocated by a previous
  558. * call NutNetBufAlloc().
  559. *
  560. * \return 0 on success, -1 in case of any errors.
  561. */
  562. int EmacOutput(NUTDEVICE * dev, NETBUF * nb)
  563. {
  564. static uint32_t mx_wait = 5000;
  565. int rc = -1;
  566. EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
  567. /*
  568. * After initialization we are waiting for a long time to give
  569. * the PHY a chance to establish an Ethernet link.
  570. */
  571. while (rc) {
  572. if (ni->ni_insane) {
  573. break;
  574. }
  575. if (NutEventWait(&ni->ni_mutex, mx_wait)) {
  576. break;
  577. }
  578. /* Check for packet queue space. */
  579. if ((txBufTab[txBufIdx].stat & TXS_USED) == 0) {
  580. if (NutEventWait(&ni->ni_tx_rdy, 500) && (txBufTab[txBufIdx].stat & TXS_USED) == 0) {
  581. /* No queue space. Release the lock and give up. */
  582. NutEventPost(&ni->ni_mutex);
  583. break;
  584. }
  585. } else {
  586. if ((rc = EmacPutPacket(txBufIdx, ni, nb)) == 0) {
  587. txBufIdx++;
  588. txBufIdx &= 1;
  589. }
  590. }
  591. NutEventPost(&ni->ni_mutex);
  592. }
  593. /*
  594. * Probably no Ethernet link. Significantly reduce the waiting
  595. * time, so following transmission will soon return an error.
  596. */
  597. if (rc) {
  598. mx_wait = 500;
  599. } else {
  600. /* Ethernet works. Set a long waiting time in case we
  601. temporarly lose the link next time. */
  602. mx_wait = 5000;
  603. }
  604. return rc;
  605. }
  606. /*!
  607. * \brief Initialize Ethernet hardware.
  608. *
  609. * Applications should do not directly call this function. It is
  610. * automatically executed during during device registration by
  611. * NutRegisterDevice().
  612. *
  613. * \param dev Identifies the device to initialize.
  614. */
  615. int EmacInit(NUTDEVICE * dev)
  616. {
  617. EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
  618. /* Reset the controller. */
  619. if (EmacReset()) {
  620. return -1;
  621. }
  622. /* Clear EMACINFO structure. */
  623. memset(ni, 0, sizeof(EMACINFO));
  624. /* Register interrupt handler. */
  625. if (NutRegisterIrqHandler(&sig_EMAC, EmacInterrupt, dev)) {
  626. return -1;
  627. }
  628. /* Start the receiver thread. */
  629. if (NutThreadCreate("emacrx", EmacRxThread, dev,
  630. (NUT_THREAD_NICRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == NULL) {
  631. return -1;
  632. }
  633. return 0;
  634. }
  635. static EMACINFO dcb_eth0;
  636. /*!
  637. * \brief Network interface information structure.
  638. *
  639. * Used to call.
  640. */
  641. static IFNET ifn_eth0 = {
  642. IFT_ETHER, /*!< \brief Interface type, if_type. */
  643. 0, /*!< \brief Interface flags, if_flags. */
  644. {0, 0, 0, 0, 0, 0}, /*!< \brief Hardware net address, if_mac. */
  645. 0, /*!< \brief IP address, if_local_ip. */
  646. 0, /*!< \brief Remote IP address for point to point, if_remote_ip. */
  647. 0, /*!< \brief IP network mask, if_mask. */
  648. ETHERMTU, /*!< \brief Maximum size of a transmission unit, if_mtu. */
  649. 0, /*!< \brief Packet identifier, if_pkt_id. */
  650. 0, /*!< \brief Linked list of arp entries, arpTable. */
  651. 0, /*!< \brief Linked list of multicast address entries, if_mcast. */
  652. NutEtherInput, /*!< \brief Routine to pass received data to, if_recv(). */
  653. EmacOutput, /*!< \brief Driver output routine, if_send(). */
  654. NutEtherOutput, /*!< \brief Media output routine, if_output(). */
  655. NULL /*!< \brief Interface specific control function, if_ioctl(). */
  656. #ifdef NUT_PERFMON
  657. , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  658. #endif
  659. };
  660. /*!
  661. * \brief Device information structure.
  662. *
  663. * A pointer to this structure must be passed to NutRegisterDevice()
  664. * to bind this Ethernet device driver to the Nut/OS kernel.
  665. * An application may then call NutNetIfConfig() with the name \em eth0
  666. * of this driver to initialize the network interface.
  667. *
  668. */
  669. NUTDEVICE devAt91Emac = {
  670. 0, /*!< \brief Pointer to next device. */
  671. {'e', 't', 'h', '0', 0, 0, 0, 0, 0}, /*!< \brief Unique device name. */
  672. IFTYP_NET, /*!< \brief Type of device. */
  673. 0, /*!< \brief Base address. */
  674. 0, /*!< \brief First interrupt number. */
  675. &ifn_eth0, /*!< \brief Interface control block. */
  676. &dcb_eth0, /*!< \brief Driver control block. */
  677. EmacInit, /*!< \brief Driver initialization routine. */
  678. 0, /*!< \brief Driver specific control function. */
  679. 0, /*!< \brief Read from device. */
  680. 0, /*!< \brief Write to device. */
  681. #ifdef __HARVARD_ARCH__
  682. 0, /*!< \brief Write from program space data to device. */
  683. #endif
  684. 0, /*!< \brief Open a device or file. */
  685. 0, /*!< \brief Close a device or file. */
  686. 0, /*!< \brief Request file size. */
  687. 0, /*!< \brief Select function, optional, not yet implemented */
  688. };
  689. /*@}*/