lpc17xx_emac.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. /*
  2. * Copyright (C) 2012 by Ole Reinhardt (ole.reinhardt@embedded-it.de)
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of the copyright holders nor the names of
  16. * contributors may be used to endorse or promote products derived
  17. * from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  22. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  23. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  25. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  26. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  27. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  28. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  29. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30. * SUCH DAMAGE.
  31. *
  32. * For additional information see http://www.ethernut.de/
  33. */
  34. /*
  35. * \verbatim
  36. * $Id: $
  37. * \endverbatim
  38. */
  39. #include <stdio.h>
  40. #include <arch/cm3.h>
  41. #include <cfg/arch.h>
  42. #include <cfg/os.h>
  43. #include <cfg/dev.h>
  44. #include <cfg/arch/gpio.h>
  45. #include <stdlib.h>
  46. #include <string.h>
  47. #include <sys/atom.h>
  48. #include <sys/heap.h>
  49. #include <sys/thread.h>
  50. #include <sys/event.h>
  51. #include <sys/timer.h>
  52. #include <sys/confnet.h>
  53. #if defined(MCU_LPC176x)
  54. #include <arch/cm3/nxp/lpc176x.h>
  55. #include <arch/cm3/nxp/lpc176x_clk.h>
  56. #include <arch/cm3/nxp/lpc176x_gpio.h>
  57. #elif defined(MCU_LPC177x_8x)
  58. #include <arch/cm3/nxp/lpc177x_8x.h>
  59. #include <arch/cm3/nxp/lpc177x_8x_clk.h>
  60. #include <arch/cm3/nxp/lpc177x_8x_gpio.h>
  61. #elif defined(MCU_LPC407x_8x)
  62. #include <arch/cm3/nxp/lpc407x_8x.h>
  63. #include <arch/cm3/nxp/lpc407x_8x_clk.h>
  64. #include <arch/cm3/nxp/lpc177x_8x_gpio.h>
  65. #else
  66. #warning "Unknown LPC familiy"
  67. #endif
  68. #include <netinet/if_ether.h>
  69. #include <net/ether.h>
  70. #include <net/if_var.h>
  71. #include <dev/gpio.h>
  72. #include <dev/irqreg.h>
  73. #include <dev/phy.h>
  74. #include <arch/cm3/nxp/lpc17xx_emac.h>
  75. /* WARNING: Variadic macros are C99 and may fail with C89 compilers. */
  76. #ifdef NUTDEBUG
  77. #include <stdio.h>
  78. #include <arpa/inet.h>
  79. #define EMPRINTF(args,...) printf(args,##__VA_ARGS__);
  80. #else
  81. #define EMPRINTF(args,...)
  82. #endif
  83. #define NUT_THREAD_NICLINKSTACK 512
  84. #ifndef NUT_THREAD_NICRXSTACK
  85. #define NUT_THREAD_NICRXSTACK 768
  86. #endif
  87. #ifndef EMAC_LINK_LOOPS
  88. #define EMAC_LINK_LOOPS 1000
  89. #endif
  90. /*!
  91. * \brief PHY address.
  92. *
  93. * Any other than 0 seems to create problems with Atmel's evaluation kits.
  94. */
  95. #ifndef NIC_PHY_ADDR
  96. #define NIC_PHY_ADDR 0
  97. #endif
  98. #ifndef TRUE
  99. #define TRUE 1
  100. #endif
  101. #ifndef FALSE
  102. #define FALSE 0
  103. #endif
  104. #define min(a,b) ((a>b)?b:a)
  105. /* MII Mgmt Configuration register - Clock divider setting */
  106. const uint8_t emac_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28, 36, 40, 44, 48, 52, 56, 60, 64 };
  107. typedef struct _BufDescriptor {
  108. unsigned int addr;
  109. unsigned int stat;
  110. } BufDescriptor;
  111. /*!
  112. * \brief Network interface controller information structure.
  113. */
  114. struct _EMACINFO {
  115. #ifdef NUT_PERFMON
  116. #warning not yet implemented
  117. uint32_t ni_rx_packets; /*!< Number of packets received. */
  118. uint32_t ni_tx_packets; /*!< Number of packets sent. */
  119. uint32_t ni_overruns; /*!< Number of packet overruns. */
  120. uint32_t ni_rx_frame_errors; /*!< Number of frame errors. */
  121. uint32_t ni_rx_crc_errors; /*!< Number of CRC errors. */
  122. uint32_t ni_rx_missed_errors; /*!< Number of missed packets. */
  123. #endif
  124. HANDLE volatile ni_rx_rdy; /*!< Receiver event queue. */
  125. HANDLE volatile ni_tx_rdy; /*!< Transmitter event queue. */
  126. HANDLE ni_mutex; /*!< Access mutex semaphore. */
  127. volatile int ni_insane; /*!< Set by error detection. */
  128. };
  129. /*!
  130. * \brief Network interface controller information type.
  131. */
  132. typedef struct _EMACINFO EMACINFO;
  133. /*!
  134. * \addtogroup xgNutArchCm3Lpc17xxEmac
  135. */
  136. /*@{*/
  137. /*!
  138. * \brief Read contents of PHY register.
  139. *
  140. * \param reg PHY register number.
  141. *
  142. * \return Contents of the specified register.
  143. */
  144. static uint16_t phy_inw(uint8_t reg)
  145. {
  146. unsigned int tout;
  147. LPC_EMAC->MADR = (NIC_PHY_ADDR << 8) | reg;
  148. LPC_EMAC->MCMD = EMAC_MCMD_READ;
  149. /* Wait until operation completed */
  150. tout = 0;
  151. for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) {
  152. if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
  153. break;
  154. }
  155. }
  156. LPC_EMAC->MCMD = 0;
  157. return (LPC_EMAC->MRDD);
  158. }
  159. /*!
  160. * \brief Write value to PHY register.
  161. *
  162. * \param reg PHY register number.
  163. * \param val Value to write.
  164. */
  165. static void phy_outw(uint8_t reg, uint16_t val)
  166. {
  167. unsigned int tout;
  168. LPC_EMAC->MADR = (NIC_PHY_ADDR << 8) | reg;
  169. LPC_EMAC->MWTD = val;
  170. /* Wait utill operation completed */
  171. tout = 0;
  172. for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) {
  173. if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
  174. break;
  175. }
  176. }
  177. }
  178. /*!
  179. * \brief Set the emac duplex mode.
  180. *
  181. * \param full 1: full duplex, 0: half duplex
  182. *
  183. * \return none;
  184. */
  185. static void Lpc17xxEmacSetDuplex(int full)
  186. {
  187. if(full) {
  188. LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
  189. LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
  190. LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
  191. } else {
  192. LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
  193. }
  194. }
  195. /*!
  196. * \brief Set the emac speed.
  197. *
  198. * \param full 1: 100MBit, 0: 10 MBit
  199. *
  200. * \return none;
  201. */
  202. static void Lpc17xxEmacSetSpeed(int enable_100mBit)
  203. {
  204. if(enable_100mBit) {
  205. LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
  206. } else {
  207. LPC_EMAC->SUPP = 0;
  208. }
  209. }
  210. /*!
  211. * \brief Set the emac station address.
  212. *
  213. * \param mac MAC address (station address)
  214. *
  215. * \return none;
  216. */
  217. static void Lpc17xxEmacSetMACAddr(const uint8_t * mac)
  218. {
  219. /* Set the Ethernet MAC Address registers */
  220. LPC_EMAC->SA0 = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4];
  221. LPC_EMAC->SA1 = ((uint32_t)mac[3] << 8) | (uint32_t)mac[2];
  222. LPC_EMAC->SA2 = ((uint32_t)mac[1] << 8) | (uint32_t)mac[0];
  223. }
  224. /*! \fn Lpc17xxEmacWaitLinkThread(void *arg)
  225. * \brief Wait for link establishment and configure the NIC
  226. * accordingly.
  227. */
  228. THREAD(Lpc17xxEmacWaitLinkThread, arg)
  229. {
  230. uint32_t phyval;
  231. int link_wait;
  232. for (;;) {
  233. /* Restart autonegotiation */
  234. phyval = 1;
  235. NutPhyCtl(PHY_CTL_AUTONEG_RE, &phyval);
  236. /* Wait for auto negotiation completed and link established. */
  237. for (link_wait = EMAC_LINK_LOOPS;; link_wait--) {
  238. phyval = 0;
  239. NutPhyCtl(PHY_GET_STATUS, &phyval);
  240. if((phyval & PHY_STATUS_HAS_LINK) && (phyval & PHY_STATUS_AUTONEG_OK)) {
  241. /* Check link state and configure EMAC accordingly */
  242. if (phyval & PHY_STATUS_100M) {
  243. Lpc17xxEmacSetSpeed(TRUE);
  244. EMPRINTF("EMAC: Got link: 100 MBit ");
  245. } else {
  246. Lpc17xxEmacSetSpeed(FALSE);
  247. EMPRINTF("Link: Got link: 10 MBit ");
  248. }
  249. if (phyval & PHY_STATUS_FULLDUPLEX) {
  250. Lpc17xxEmacSetDuplex(TRUE);
  251. EMPRINTF("Full Duplex\n");
  252. } else {
  253. Lpc17xxEmacSetDuplex(FALSE);
  254. EMPRINTF("Half Duplex\n");
  255. }
  256. NutThreadExit();
  257. break;
  258. }
  259. if (link_wait == 0) {
  260. EMPRINTF("NO LINK!\n");
  261. }
  262. NutSleep(10);
  263. }
  264. }
  265. }
  266. /*!
  267. * \brief Reset the Ethernet controller.
  268. *
  269. * \return 0 on success, -1 on error
  270. */
  271. static int Lpc17xxEmacReset(NUTDEVICE *dev)
  272. {
  273. int rc = 0;
  274. uint32_t phyval;
  275. int idx;
  276. int32_t tmp;
  277. IFNET *ifn = (IFNET *) dev->dev_icb;
  278. EMPRINTF("Lpc17xxEmacReset\n");
  279. /* Reset all EMAC internal modules */
  280. LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX |
  281. EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES;
  282. LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM;
  283. /* A short delay after reset. */
  284. NutSleep(10);
  285. /* Initialize MAC control registers. */
  286. LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
  287. LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN;
  288. /* Set maximum frame size. */
  289. LPC_EMAC->MAXF = ifn->if_mtu + ETHER_HDR_LEN + ETHER_HDR_LEN;
  290. /* Find the clock that close to desired target clock */
  291. tmp = NutArchClockGet(NUT_HWCLK_CPU) / EMAC_MCFG_MII_MAXCLK;
  292. for (idx = 0; idx < sizeof (emac_clkdiv); idx++) {
  293. if (emac_clkdiv[idx] >= tmp) {
  294. break;
  295. }
  296. }
  297. if(idx >= sizeof (emac_clkdiv)) {
  298. return -1;
  299. }
  300. idx++;
  301. /* Write to MAC configuration register and reset */
  302. LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(idx) | EMAC_MCFG_RES_MII;
  303. /* release reset */
  304. LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
  305. LPC_EMAC->CLRT = EMAC_CLRT_DEF;
  306. LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;
  307. #ifdef PHY_MODE_RMII
  308. /* Enable Reduced MII interface. */
  309. LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM;
  310. #endif
  311. NutSleep(10);
  312. LPC_EMAC->SUPP = 0;
  313. /* Wait for PHY ready. */
  314. NutSleep(255);
  315. /* Register PHY
  316. PHY driver memory is only allocated one, but as NutRegisterPhy reads the
  317. PHY ID we need to have the (R)MII hardware initialised first
  318. */
  319. rc = NutRegisterPhy(1, phy_outw, phy_inw);
  320. #ifndef PHY_MODE_RMII
  321. /* Clear MII isolate. */
  322. phyval = 0;
  323. NutPhyCtl(PHY_CTL_ISOLATE, &phyval);
  324. #endif
  325. /* Restart autonegotiation */
  326. phyval = 1;
  327. NutPhyCtl(PHY_CTL_AUTONEG_RE, &phyval);
  328. if (NutThreadCreate("emaclink", Lpc17xxEmacWaitLinkThread, NULL,
  329. (NUT_THREAD_NICLINKSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == NULL) {
  330. EMPRINTF("Lpc17xxEmacReset() Could not create link establishment thread\n");
  331. rc = -1;
  332. }
  333. EMPRINTF("Lpc17xxEmacReset() DONE\n");
  334. return rc;
  335. }
  336. /*!
  337. * \brief Initialise the Emac RX descriptors.
  338. *
  339. * RX descriptors are located in the extra 16K internal SRAM of the CPU
  340. * and will be used for DMA operations.
  341. *
  342. * \param nb Network buffer structure containing the packet to be sent.
  343. * The structure must have been allocated by a previous
  344. * call NutNetBufAlloc(). This routine will automatically
  345. * release the buffer in case of an error.
  346. *
  347. * \return none
  348. */
  349. static void Lpc17xxEmacRxDescriptorInit(void)
  350. {
  351. unsigned int i;
  352. for (i = 0; i < EMAC_NUM_RX_FRAG; i++) {
  353. RX_DESC_PACKET(i) = RX_BUF(i);
  354. RX_DESC_CTRL(i) = EMAC_RCTRL_INT | (EMAC_ETH_RX_FRAG_SIZE-1);
  355. RX_STAT_INFO(i) = 0;
  356. RX_STAT_HASHCRC(i) = 0;
  357. }
  358. /* Set EMAC Receive Descriptor Registers. */
  359. LPC_EMAC->RxDescriptor = RX_DESC_BASE;
  360. LPC_EMAC->RxStatus = RX_STAT_BASE;
  361. LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG-1;
  362. /* Rx Descriptors Point to 0 */
  363. LPC_EMAC->RxConsumeIndex = 0;
  364. }
  365. /*!
  366. * \brief Initialise the Emac TX descriptors.
  367. *
  368. * RX descriptors are located in the extra 16K internal SRAM of the CPU
  369. * and will be used for DMA operations.
  370. *
  371. * \param nb Network buffer structure containing the packet to be sent.
  372. * The structure must have been allocated by a previous
  373. * call NutNetBufAlloc(). This routine will automatically
  374. * release the buffer in case of an error.
  375. *
  376. * \return none
  377. */
  378. static void Lpc17xxEmacTxDescriptorInit (void)
  379. {
  380. unsigned int i;
  381. for (i = 0; i < EMAC_NUM_TX_FRAG; i++)
  382. {
  383. TX_DESC_PACKET(i) = TX_BUF(i);
  384. TX_DESC_CTRL(i) = 0;
  385. TX_STAT_INFO(i) = 0;
  386. }
  387. /* Set EMAC Transmit Descriptor Registers. */
  388. LPC_EMAC->TxDescriptor = TX_DESC_BASE;
  389. LPC_EMAC->TxStatus = TX_STAT_BASE;
  390. LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG-1;
  391. /* Tx Descriptors Point to 0 */
  392. LPC_EMAC->TxProduceIndex = 0;
  393. }
  394. /*
  395. * NIC interrupt entry.
  396. */
  397. static void Lpc17xxEmacInterrupt(void *arg)
  398. {
  399. uint32_t isr;
  400. EMACINFO *ni = (EMACINFO *) ((NUTDEVICE *) arg)->dev_dcb;
  401. /* EMAC Ethernet Controller Interrupt function. */
  402. /* Get EMAC interrupt status */
  403. isr = (LPC_EMAC->IntStatus & LPC_EMAC->IntEnable);
  404. if (isr != 0) {
  405. /* Clear interrupt status */
  406. LPC_EMAC->IntClear = isr;
  407. if (isr & EMAC_INT_RX_OVERRUN) {
  408. /* An RX overrun error is fatal. We have to soft-reset the RX Datapath */
  409. LPC_EMAC->Command |= EMAC_CR_RX_RES;
  410. /* Anyway post the RX queue so the receiver thread can read the just received frames */
  411. NutEventPostFromIrq(&ni->ni_rx_rdy);
  412. } else
  413. if (isr & (EMAC_INT_RX_DONE | EMAC_INT_RX_ERR)) {
  414. LPC_EMAC->IntEnable &= ~(EMAC_INT_RX_ERR | EMAC_INT_RX_DONE);
  415. NutEventPostFromIrq(&ni->ni_rx_rdy);
  416. }
  417. if (isr & EMAC_INT_TX_UNDERRUN) {
  418. /* An TX underrun error is fatal. We have to soft-reset the TX Datapath */
  419. LPC_EMAC->Command |= EMAC_CR_TX_RES;
  420. /* Anyway post the TX queue so the transmitter can rwrite new frames */
  421. NutEventPostFromIrq(&ni->ni_tx_rdy);
  422. } else
  423. if (isr & (EMAC_INT_TX_DONE | EMAC_INT_TX_ERR)) {
  424. NutEventPostFromIrq(&ni->ni_tx_rdy);
  425. }
  426. }
  427. }
  428. /*!
  429. * \brief Fetch the next packet out of the receive buffers.
  430. *
  431. * \return 0 on success, -1 otherwise.
  432. */
  433. static int Lpc17xxEmacGetPacket(NUTDEVICE *dev, NETBUF ** nbp)
  434. {
  435. int rc = -1;
  436. uint32_t idx;
  437. uint32_t produce_idx;
  438. uint32_t new_consume_idx;
  439. int32_t rxlen;
  440. register uint32_t status;
  441. EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
  442. *nbp = NULL;
  443. produce_idx = LPC_EMAC->RxProduceIndex;
  444. idx = LPC_EMAC->RxConsumeIndex;
  445. rxlen = 0;
  446. if (idx != produce_idx) {
  447. int32_t size = 0;
  448. status = RX_STAT_INFO(idx);
  449. while (status && idx != produce_idx) {
  450. size += (status & EMAC_RINFO_SIZE) + 1;
  451. if (++idx == EMAC_NUM_RX_FRAG) {
  452. idx = 0;
  453. }
  454. new_consume_idx = idx;
  455. if (status & EMAC_RINFO_LAST_FLAG) {
  456. rxlen = size;
  457. break;
  458. }
  459. status = RX_STAT_INFO(idx);
  460. }
  461. }
  462. /* Check if there was any data received */
  463. if(rxlen > 0) {
  464. idx = LPC_EMAC->RxConsumeIndex;
  465. /* substract 4 bytes CTC. */
  466. rxlen -= 4;
  467. /* "status" represents the status flag of the last frame fragment */
  468. /* Check if the frame was correctly received */
  469. if((status & EMAC_RINFO_ERR_MASK) == 0) {
  470. /*
  471. * Receiving long packets is unexpected. Let's declare the
  472. * chip insane. Short packets will be handled by the caller.
  473. */
  474. if (rxlen < 0) {
  475. ni->ni_insane = 1;
  476. } else {
  477. *nbp = NutNetBufAlloc(0, NBAF_DATALINK + (2 & (NUTMEM_ALIGNMENT - 1)), (uint16_t)rxlen);
  478. if (*nbp != NULL) {
  479. uint8_t *bp = (uint8_t *) (* nbp)->nb_dl.vp;
  480. unsigned int len;
  481. idx = LPC_EMAC->RxConsumeIndex;
  482. while (rxlen) {
  483. if (rxlen > EMAC_ETH_RX_FRAG_SIZE) {
  484. len = EMAC_ETH_RX_FRAG_SIZE;
  485. } else {
  486. len = rxlen;
  487. }
  488. /* Copy received data from current frame fragment */
  489. memcpy(bp, (void*)RX_DESC_PACKET(idx), len);
  490. /* Clear status info and crc hash from current frame fragment */
  491. RX_STAT_INFO(idx) = 0;
  492. RX_STAT_HASHCRC(idx) = 0;
  493. if (++idx == EMAC_NUM_RX_FRAG) {
  494. idx = 0;
  495. }
  496. rxlen -= len;
  497. bp += len;
  498. }
  499. rc = 0;
  500. }
  501. }
  502. } else {
  503. /* Silently discard the frame from EMAC buffer, update the Rx consume index */
  504. }
  505. /* Release frame from EMAC buffer, update the Rx consume index */
  506. LPC_EMAC->RxConsumeIndex = new_consume_idx;
  507. }
  508. return rc;
  509. }
  510. /*!
  511. * \brief Load a packet into the nic's transmit ring buffer.
  512. *
  513. * \param nb Network buffer structure containing the packet to be sent.
  514. * The structure must have been allocated by a previous
  515. * call NutNetBufAlloc(). This routine will automatically
  516. * release the buffer in case of an error.
  517. *
  518. * \return 0 on success, -1 in case of any errors. Errors
  519. * will automatically release the network buffer
  520. * structure.
  521. */
  522. static inline int Lpc17xxEmacPutPacket(NUTDEVICE *dev, NETBUF * nb)
  523. {
  524. int rc = -1;
  525. uint16_t sz;
  526. uint8_t *buf;
  527. uint32_t idx;
  528. IFNET *ifn = (IFNET *) dev->dev_icb;
  529. EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
  530. /*
  531. * Calculate the number of bytes to be send. Do not send packets
  532. * larger than the Ethernet maximum transfer unit. The MTU
  533. * consist of 1500 data bytes plus the 14 byte Ethernet header
  534. * plus 4 bytes CRC. We check the data bytes only.
  535. */
  536. if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ifn->if_mtu) {
  537. return -1;
  538. }
  539. sz += nb->nb_dl.sz;
  540. /* Disable EMAC interrupts. */
  541. NutIrqDisable(&sig_EMAC);
  542. /* TODO: Check for link. */
  543. if (ni->ni_insane == 0) {
  544. int32_t txlen = sz;
  545. int32_t offs = 0;
  546. /* Allocate a descriptors for sending frame and get the coressponding
  547. buffer address NIC interrupts must be disabled.
  548. */
  549. idx = LPC_EMAC->TxProduceIndex;
  550. while (txlen > 0) {
  551. /* Get the current transmit fragment data pointer */
  552. buf = (uint8_t*)TX_DESC_PACKET(idx);
  553. if (txlen > EMAC_ETH_TX_FRAG_SIZE) {
  554. /* This is not the last fragment, it is completely filled */
  555. TX_DESC_CTRL(idx) = ((EMAC_ETH_TX_FRAG_SIZE - 1) & EMAC_TCTRL_SIZE) | EMAC_TCTRL_INT;
  556. } else {
  557. /* Round up the len to the next even number and mark this as the last fragment */
  558. TX_DESC_CTRL(idx) = ((txlen - 1) & EMAC_TCTRL_SIZE) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST);
  559. }
  560. if (txlen == sz) {
  561. /* This is the first fragment, copy the header bytes and then the application data */
  562. memcpy(buf, nb->nb_dl.vp, nb->nb_dl.sz);
  563. buf += nb->nb_dl.sz;
  564. txlen -= nb->nb_dl.sz;
  565. memcpy(buf, nb->nb_nw.vp, nb->nb_nw.sz);
  566. buf += nb->nb_nw.sz;
  567. txlen -= nb->nb_nw.sz;
  568. memcpy(buf, nb->nb_tp.vp, nb->nb_tp.sz);
  569. buf += nb->nb_tp.sz;
  570. txlen -= nb->nb_tp.sz;
  571. offs = min (EMAC_ETH_TX_FRAG_SIZE - nb->nb_dl.sz - nb->nb_nw.sz - nb->nb_tp.sz, nb->nb_ap.sz);
  572. memcpy(buf, nb->nb_ap.vp, offs);
  573. buf += offs;
  574. txlen -= offs;
  575. } else {
  576. register int len = min(EMAC_ETH_TX_FRAG_SIZE, nb->nb_ap.sz - offs);
  577. /* Continue copying the application data */
  578. memcpy(buf, (uint8_t *)nb->nb_ap.vp + offs, len);
  579. offs += len;
  580. txlen -= len;
  581. }
  582. /* Increment produce index counter, taking wrap around into account */
  583. if (++idx == LPC_EMAC->TxDescriptorNumber + 1) {
  584. idx = 0;
  585. }
  586. }
  587. /* Update tx produce index
  588. Increase the TxProduceIndex (after writting to the Transmit buffer
  589. to enable the Transmit buffer)
  590. */
  591. LPC_EMAC->TxProduceIndex = idx;
  592. rc = 0;
  593. #ifdef NUT_PERFMON
  594. ni->ni_tx_packets++;
  595. #endif
  596. }
  597. /* Enable EMAC interrupts. */
  598. NutIrqEnable(&sig_EMAC);
  599. return rc;
  600. }
  601. /*!
  602. * \brief Fire up the network interface.
  603. *
  604. * NIC interrupts must be disabled when calling this function.
  605. *
  606. * \param mac Six byte unique MAC address.
  607. */
  608. static int Lpc17xxEmacStart(NUTDEVICE *dev)
  609. {
  610. IFNET *ifn = (IFNET *) dev->dev_icb;
  611. /* Set local MAC address. */
  612. Lpc17xxEmacSetMACAddr(ifn->if_mac);
  613. /* Initialize the rx and tx buffer descriptors */
  614. Lpc17xxEmacRxDescriptorInit();
  615. Lpc17xxEmacTxDescriptorInit();
  616. /* Set Receive Filter register: enable broadcast and multicast */
  617. LPC_EMAC->RxFilterCtrl = EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;
  618. /* Reset all interrupts, Interrupts will be enabled in the RX-Thread */
  619. LPC_EMAC->IntClear = 0xFFFF;
  620. /* Enable Transmitter and receiver */
  621. LPC_EMAC->Command |= EMAC_CR_TX_EN | EMAC_CR_RX_EN;
  622. LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN;
  623. EMPRINTF("Lpc17xxEmacStart() DONE\n");
  624. return 0;
  625. }
  626. /*! \fn EmacRxThread(void *arg)
  627. * \brief NIC receiver thread.
  628. *
  629. */
  630. THREAD(Lpc17xxEmacRxThread, arg)
  631. {
  632. NUTDEVICE *dev = arg;
  633. IFNET *ifn = (IFNET *) dev->dev_icb;
  634. EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
  635. NETBUF *nb;
  636. EMPRINTF("Lpc17xxEmacRxThread() INIT\n");
  637. /*
  638. * This is a temporary hack. Due to a change in initialization,
  639. * we may not have got a MAC address yet. Wait until a valid one
  640. * has been set.
  641. */
  642. while (!ETHER_IS_UNICAST(ifn->if_mac)) {
  643. NutSleep(10);
  644. }
  645. /*
  646. * Do not continue unless we managed to start the NIC. We are
  647. * trapped here if the Ethernet link cannot be established.
  648. * This happens, for example, if no Ethernet cable is plugged
  649. * in.
  650. */
  651. Lpc17xxEmacStart(dev);
  652. /* Initialize the access mutex. */
  653. NutEventPost(&ni->ni_mutex);
  654. /* Run at high priority. */
  655. NutThreadSetPriority(9);
  656. /* Enable receive and transmit interrupts. */
  657. LPC_EMAC->IntEnable |= EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_DONE |
  658. EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR | EMAC_INT_TX_DONE;
  659. NutIrqEnable(&sig_EMAC);
  660. for (;;) {
  661. /*
  662. * Wait for the arrival of new packets or poll the receiver every
  663. * 2 seconds. The timeout can be modified if there are interrupt problems.
  664. */
  665. NutEventWait(&ni->ni_rx_rdy, 2000);
  666. /*
  667. * Fetch all packets from the NIC's internal buffer and pass
  668. * them to the registered handler.
  669. */
  670. while (Lpc17xxEmacGetPacket(dev, &nb) == 0) {
  671. /* Discard short packets. */
  672. if (nb->nb_dl.sz < 60) {
  673. NutNetBufFree(nb);
  674. } else {
  675. (*ifn->if_recv) (dev, nb);
  676. }
  677. }
  678. LPC_EMAC->IntEnable |= EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_FIN | EMAC_INT_RX_DONE;
  679. /* We got a weird chip, try to restart it. */
  680. while (ni->ni_insane) {
  681. if (Lpc17xxEmacReset(dev)) {
  682. NutSleep(500);
  683. } else {
  684. Lpc17xxEmacStart(dev);
  685. ni->ni_insane = 0;
  686. NutIrqEnable(&sig_EMAC);
  687. }
  688. }
  689. }
  690. }
  691. /*!
  692. * \brief Send Ethernet packet.
  693. *
  694. * \param dev Identifies the device to use.
  695. * \param nb Network buffer structure containing the packet to be sent.
  696. * The structure must have been allocated by a previous
  697. * call NutNetBufAlloc().
  698. *
  699. * \return 0 on success, -1 in case of any errors.
  700. */
  701. int Lpc17xxEmacOutput(NUTDEVICE * dev, NETBUF * nb)
  702. {
  703. static uint32_t mx_wait = 5000;
  704. uint32_t consume_idx;
  705. uint32_t produce_idx;
  706. uint32_t num_fragments;
  707. int rc = -1;
  708. EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
  709. size_t space;
  710. size_t pkg_size;
  711. /*
  712. * After initialization we are waiting for a long time to give
  713. * the PHY a chance to establish an Ethernet link.
  714. */
  715. while (rc) {
  716. /* Check if we stay in an error condition */
  717. if (ni->ni_insane) {
  718. break;
  719. }
  720. if (NutEventWait(&ni->ni_mutex, mx_wait)) {
  721. break;
  722. }
  723. /* Check for packet queue space. */
  724. consume_idx = LPC_EMAC->TxConsumeIndex;
  725. produce_idx = LPC_EMAC->TxProduceIndex;
  726. num_fragments = LPC_EMAC->TxDescriptorNumber + 1;
  727. /* empty */
  728. if (consume_idx == produce_idx) {
  729. space = num_fragments * EMAC_ETH_TX_FRAG_SIZE;
  730. } else
  731. /* full */
  732. if ((consume_idx == 0) && (produce_idx == num_fragments - 1)) {
  733. space = 0;
  734. } else
  735. /* Wrap-around */
  736. if (consume_idx == produce_idx + 1) {
  737. space = 0;
  738. } else {
  739. /* Calc free space */
  740. if (consume_idx > produce_idx) {
  741. space = consume_idx - produce_idx;
  742. } else {
  743. space = num_fragments - (produce_idx - consume_idx);
  744. }
  745. space *= EMAC_ETH_TX_FRAG_SIZE;
  746. }
  747. pkg_size = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz + nb->nb_dl.sz;
  748. if (space < pkg_size) {
  749. if (NutEventWait(&ni->ni_tx_rdy, 500)) {
  750. /* No queue space. Release the lock and give up. */
  751. NutEventPost(&ni->ni_mutex);
  752. break;
  753. }
  754. } else
  755. if (Lpc17xxEmacPutPacket(dev, nb) == 0) {
  756. /* Ethernet works. Set a long waiting time in case we
  757. temporarly lose the link next time. */
  758. rc = 0;
  759. }
  760. NutEventPost(&ni->ni_mutex);
  761. }
  762. /*
  763. * Probably no Ethernet link. Significantly reduce the waiting
  764. * time, so following transmission will soon return an error.
  765. */
  766. if (rc) {
  767. mx_wait = 500;
  768. } else {
  769. /* Ethernet works. Set a long waiting time in case we
  770. temporarily lose the link next time. */
  771. mx_wait = 5000;
  772. }
  773. return rc;
  774. }
  775. /*!
  776. * \brief Calculate CRC of a number of bytes (e.g. of an ethernet frame)
  777. *
  778. * \param data Pointer to the first byte of the data buffer
  779. * \param len length of the data
  780. *
  781. * \return Calculated CRC (32 bit)
  782. */
  783. static int32_t Lpc17xxEmacCalcCrc(uint8_t *data, int32_t len)
  784. {
  785. int i, j;
  786. char byte;
  787. int crc;
  788. int q0, q1, q2, q3;
  789. crc = 0xFFFFFFFF;
  790. for (i = 0; i < len; i++) {
  791. byte = *(data++);
  792. for (j = 0; j < 2; j++) {
  793. if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) {
  794. q3 = 0x04C11DB7;
  795. } else {
  796. q3 = 0x00000000;
  797. }
  798. if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) {
  799. q2 = 0x09823B6E;
  800. } else {
  801. q2 = 0x00000000;
  802. }
  803. if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) {
  804. q1 = 0x130476DC;
  805. } else {
  806. q1 = 0x00000000;
  807. }
  808. if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) {
  809. q0 = 0x2608EDB8;
  810. } else {
  811. q0 = 0x00000000;
  812. }
  813. crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0;
  814. byte >>= 4;
  815. }
  816. }
  817. return crc;
  818. }
  819. /*!
  820. * \brief Update the multicast hash.
  821. *
  822. * This function must be called after the multicast list changed.
  823. *
  824. * \param mclst Pointer to the first entry of the linked list of
  825. * multicast entries.
  826. */
  827. static void Lpc17xxEmacHashUpdate(MCASTENTRY *mclst)
  828. {
  829. uint32_t idx;
  830. uint32_t hash[2] = { 0, 0 };
  831. /* Determine the hash bit for each entry. */
  832. while (mclst) {
  833. /* Calc CRC of the hash entry. Bits 23-28 are used as hash index */
  834. idx = (Lpc17xxEmacCalcCrc(mclst->mca_ha, 6) >> 23) & 0x3F;
  835. /* Set the bit given by the 6 bit index. */
  836. hash[idx > 31] |= 1 << (idx & 31);
  837. mclst = mclst->mca_next;
  838. }
  839. /* Set result in the hash register. */
  840. LPC_EMAC->HashFilterL = hash[0];
  841. LPC_EMAC->HashFilterH = hash[1];
  842. /* Enable or disable multicast hash. */
  843. if (hash[0] || hash[1]) {
  844. LPC_EMAC->RxFilterCtrl |= EMAC_RFC_MCAST_HASH_EN;
  845. } else {
  846. LPC_EMAC->RxFilterCtrl &= ~EMAC_RFC_MCAST_HASH_EN;
  847. }
  848. }
  849. /*!
  850. * \brief Get multicast entry of a given IP address.
  851. *
  852. * \todo This function should be shared by all Ethernet drivers.
  853. *
  854. * \param ifn Pointer to the network interface structure.
  855. * \param ip IP address of the entry to retrieve.
  856. *
  857. * \return Pointer to the entry or NULL if none exists.
  858. */
  859. static MCASTENTRY *McastIpEntry(IFNET *ifn, uint32_t ip)
  860. {
  861. MCASTENTRY *mca = ifn->if_mcast;
  862. while (mca) {
  863. if (ip == mca->mca_ip) {
  864. break;
  865. }
  866. mca = mca->mca_next;
  867. }
  868. return mca;
  869. }
  870. /*!
  871. * \brief Add a given IP address to the multicast list.
  872. *
  873. * \todo This function should be shared by all Ethernet drivers.
  874. *
  875. * \param ifn Pointer to the network interface structure.
  876. * \param ip IP address of the new entry.
  877. *
  878. * \return Pointer to the requested entry, either a new one or
  879. * an already existing entry. In case of a failure, NULL
  880. * is returned.
  881. */
  882. static MCASTENTRY *McastAddEntry(IFNET *ifn, uint32_t ip)
  883. {
  884. MCASTENTRY *mca;
  885. mca = McastIpEntry(ifn, ip);
  886. if (mca == NULL) {
  887. mca = malloc(sizeof(MCASTENTRY));
  888. if (mca) {
  889. mca->mca_ip = ip;
  890. /* Set the IANA OUI. */
  891. mca->mca_ha[0] = 0x01;
  892. mca->mca_ha[1] = 0x00;
  893. mca->mca_ha[2] = 0x5e;
  894. /* Map the lower 23 bits of the IP address to the MAC address.
  895. Note that Nut/Net IP addresses are in network byte order. */
  896. mca->mca_ha[3] = (ip >> 8) & 0x7f;
  897. mca->mca_ha[4] = (ip >> 16) & 0xff;
  898. mca->mca_ha[5] = (ip >> 24) & 0xff;
  899. /* Add the new entry to the front of the list. */
  900. mca->mca_next = ifn->if_mcast;
  901. ifn->if_mcast = mca;
  902. /* Update the EMAC's multicast hash. */
  903. Lpc17xxEmacHashUpdate(mca);
  904. }
  905. }
  906. return mca;
  907. }
  908. /*!
  909. * \brief Remove multicast entry of a given IP address.
  910. *
  911. * \param ifn Pointer to the network interface structure.
  912. * \param ip IP address of the entry to remove.
  913. */
  914. static void McastDelEntry(IFNET *ifn, uint32_t ip)
  915. {
  916. MCASTENTRY *mca = ifn->if_mcast;
  917. MCASTENTRY **lnk = &ifn->if_mcast;
  918. while (mca) {
  919. if (mca->mca_ip == ip) {
  920. *lnk = mca->mca_next;
  921. free(mca);
  922. break;
  923. }
  924. lnk = &mca->mca_next;
  925. mca = *lnk;
  926. }
  927. /* Update the EMAC's multicast hash. */
  928. Lpc17xxEmacHashUpdate(mca);
  929. }
  930. /*!
  931. * \brief Perform Ethernet control functions.
  932. *
  933. * \param dev Identifies the device that receives the device-control
  934. * function.
  935. * \param req Requested control function. May be set to one of the
  936. * following constants:
  937. * - SIOCSIFADDR sets interface MAC address passed in buffer.
  938. * - SIOCGIFADDR copies current interface MAC address to buffer.
  939. * - SIOCADDMULTI adds multicast entry for IP in buffer.
  940. * - SIOCDELMULTI removes multicast entry of IP in buffer.
  941. * \param conf Points to a buffer that contains any data required for
  942. * the given control function or receives data from that
  943. * function.
  944. * \return 0 on success, -1 otherwise.
  945. *
  946. */
  947. static int Lpc17xxEmacIoCtl(NUTDEVICE * dev, int req, void *conf)
  948. {
  949. int rc = 0;
  950. IFNET *ifn = (IFNET *) dev->dev_icb;
  951. uint32_t ip;
  952. switch (req) {
  953. case SIOCSIFADDR:
  954. /* Set interface hardware address. */
  955. memcpy(ifn->if_mac, conf, sizeof(ifn->if_mac));
  956. break;
  957. case SIOCGIFADDR:
  958. /* Get interface hardware address. */
  959. memcpy(conf, ifn->if_mac, sizeof(ifn->if_mac));
  960. break;
  961. case SIOCADDMULTI:
  962. /* Add multicast address. */
  963. memcpy(&ip, conf, sizeof(ip));
  964. if (McastAddEntry(ifn, ip) == NULL) {
  965. rc = -1;
  966. }
  967. break;
  968. case SIOCDELMULTI:
  969. /* Delete multicast address. */
  970. memcpy(&ip, conf, sizeof(ip));
  971. McastDelEntry(ifn, ip);
  972. break;
  973. default:
  974. rc = -1;
  975. break;
  976. }
  977. return rc;
  978. }
  979. /*!
  980. * \brief Initialize Ethernet hardware.
  981. *
  982. * Applications should do not directly call this function. It is
  983. * automatically executed during during device registration by
  984. * NutRegisterDevice().
  985. *
  986. * \param dev Identifies the device to initialize.
  987. */
  988. int Lpc17xxEmacInit(NUTDEVICE * dev)
  989. {
  990. EMACINFO *ni = (EMACINFO *) dev->dev_dcb;
  991. EMPRINTF("Lpc17xxEmacInit()\n");
  992. SysCtlPeripheralClkEnable(CLKPWR_PCONP_PCENET);
  993. /* Configure P1 Ethernet pins for RMII interface. */
  994. /* on rev. 'A' and later, P1.6 should NOT be set. */
  995. GpioPinConfigSet(NUTGPIO_PORT1, 0, GPIO_CFG_PERIPHERAL1); /* ETH_TXD0 */
  996. GpioPinConfigSet(NUTGPIO_PORT1, 1, GPIO_CFG_PERIPHERAL1); /* ETH_TXD1 */
  997. GpioPinConfigSet(NUTGPIO_PORT1, 4, GPIO_CFG_PERIPHERAL1); /* ETH_TXEN */
  998. GpioPinConfigSet(NUTGPIO_PORT1, 8, GPIO_CFG_PERIPHERAL1); /* ETH_CRS */
  999. GpioPinConfigSet(NUTGPIO_PORT1, 9, GPIO_CFG_PERIPHERAL1); /* ETH_RXD0 */
  1000. GpioPinConfigSet(NUTGPIO_PORT1, 10, GPIO_CFG_PERIPHERAL1); /* ETH_RXD1 */
  1001. GpioPinConfigSet(NUTGPIO_PORT1, 14, GPIO_CFG_PERIPHERAL1); /* ETH_RXER */
  1002. GpioPinConfigSet(NUTGPIO_PORT1, 15, GPIO_CFG_PERIPHERAL1); /* ETH_RXCLK */
  1003. GpioPinConfigSet(NUTGPIO_PORT1, 16, GPIO_CFG_PERIPHERAL1); /* ETH_MDC */
  1004. GpioPinConfigSet(NUTGPIO_PORT1, 17, GPIO_CFG_PERIPHERAL1); /* ETH_MDIO */
  1005. #ifndef PHY_MODE_RMII
  1006. /* Configure further I/O pins for MII interface */
  1007. GpioPinConfigSet(NUTGPIO_PORT1, 2, GPIO_CFG_PERIPHERAL1); /* ETH_TXD2 */
  1008. GpioPinConfigSet(NUTGPIO_PORT1, 3, GPIO_CFG_PERIPHERAL1); /* ETH_TXD3 */
  1009. GpioPinConfigSet(NUTGPIO_PORT1, 5, GPIO_CFG_PERIPHERAL1); /* ETH_TXER */
  1010. GpioPinConfigSet(NUTGPIO_PORT1, 6, GPIO_CFG_PERIPHERAL1); /* ETH_TXCLK */
  1011. GpioPinConfigSet(NUTGPIO_PORT1, 7, GPIO_CFG_PERIPHERAL1); /* ETH_COL */
  1012. GpioPinConfigSet(NUTGPIO_PORT1, 11, GPIO_CFG_PERIPHERAL1); /* ETH_RXD2 */
  1013. GpioPinConfigSet(NUTGPIO_PORT1, 12, GPIO_CFG_PERIPHERAL1); /* ETH_RXD3 */
  1014. GpioPinConfigSet(NUTGPIO_PORT1, 13, GPIO_CFG_PERIPHERAL1); /* ETH_RXDV */
  1015. #endif
  1016. /* Reset the controller. */
  1017. if (Lpc17xxEmacReset(dev) == -1) {
  1018. return -1;
  1019. }
  1020. /* Clear EMACINFO structure. */
  1021. memset(ni, 0, sizeof(EMACINFO));
  1022. /* Register interrupt handler. */
  1023. if (NutRegisterIrqHandler(&sig_EMAC, Lpc17xxEmacInterrupt, dev)) {
  1024. EMPRINTF("EMAC: Registering IRQ failed\n");
  1025. return -1;
  1026. }
  1027. /* Start the receiver thread. */
  1028. if (NutThreadCreate("emacrx", Lpc17xxEmacRxThread, dev,
  1029. (NUT_THREAD_NICRXSTACK * NUT_THREAD_STACK_MULT) + NUT_THREAD_STACK_ADD) == NULL) {
  1030. EMPRINTF("EMAC: Registering RX Thread failed\n");
  1031. return -1;
  1032. }
  1033. EMPRINTF("Lpc17xxEmacInit() DONE\n");
  1034. return 0;
  1035. }
  1036. static EMACINFO dcb_eth0;
  1037. /*!
  1038. * \brief Network interface information structure.
  1039. *
  1040. * Used to call.
  1041. */
  1042. static IFNET ifn_eth0 = {
  1043. IFT_ETHER, /*!< \brief Interface type, if_type. */
  1044. 0, /*!< \brief Interface flags, if_flags. */
  1045. {0, 0, 0, 0, 0, 0}, /*!< \brief Hardware net address, if_mac. */
  1046. 0, /*!< \brief IP address, if_local_ip. */
  1047. 0, /*!< \brief Remote IP address for point to point, if_remote_ip. */
  1048. 0, /*!< \brief IP network mask, if_mask. */
  1049. ETHERMTU, /*!< \brief Maximum size of a transmission unit, if_mtu. */
  1050. 0, /*!< \brief Packet identifier, if_pkt_id. */
  1051. 0, /*!< \brief Linked list of arp entries, arpTable. */
  1052. 0, /*!< \brief Linked list of multicast address entries, if_mcast. */
  1053. NutEtherInput, /*!< \brief Routine to pass received data to, if_recv(). */
  1054. Lpc17xxEmacOutput, /*!< \brief Driver output routine, if_send(). */
  1055. NutEtherOutput, /*!< \brief Media output routine, if_output(). */
  1056. NULL /*!< \brief Interface specific control function, if_ioctl(). */
  1057. #ifdef NUT_PERFMON
  1058. , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  1059. #endif
  1060. };
  1061. /*!
  1062. * \brief Device information structure.
  1063. *
  1064. * A pointer to this structure must be passed to NutRegisterDevice()
  1065. * to bind this Ethernet device driver to the Nut/OS kernel.
  1066. * An application may then call NutNetIfConfig() with the name \em eth0
  1067. * of this driver to initialize the network interface.
  1068. *
  1069. */
  1070. NUTDEVICE devLpc17xxEmac = {
  1071. 0, /*!< \brief Pointer to next device. */
  1072. {'e', 't', 'h', '0', 0, 0, 0, 0, 0}, /*!< \brief Unique device name. */
  1073. IFTYP_NET, /*!< \brief Type of device. */
  1074. 0, /*!< \brief Base address. */
  1075. 0, /*!< \brief First interrupt number. */
  1076. &ifn_eth0, /*!< \brief Interface control block. */
  1077. &dcb_eth0, /*!< \brief Driver control block. */
  1078. Lpc17xxEmacInit, /*!< \brief Driver initialization routine. */
  1079. Lpc17xxEmacIoCtl, /*!< \brief Driver specific control function. */
  1080. 0, /*!< \brief Read from device. */
  1081. 0, /*!< \brief Write to device. */
  1082. #ifdef __HARVARD_ARCH__
  1083. 0, /*!< \brief Write from program space data to device. */
  1084. #endif
  1085. 0, /*!< \brief Open a device or file. */
  1086. 0, /*!< \brief Close a device or file. */
  1087. 0, /*!< \brief Request file size. */
  1088. 0, /*!< \brief Select function, optional, not yet implemented */
  1089. };
  1090. /*@}*/