drv_eth.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  1. /*
  2. * File : drv_eth.c
  3. * This file is part of RT-Thread RTOS
  4. * COPYRIGHT (C) 2009-2013 RT-Thread Develop Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date Author Notes
  12. * 2014-07-25 ArdaFu Port to TM4C129X
  13. */
  14. /**
  15. * @file - tivaif.c
  16. * lwIP Ethernet interface for Stellaris LM4F Devices
  17. *
  18. */
  19. /**
  20. * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
  21. * All rights reserved.
  22. *
  23. * Redistribution and use in source and binary forms, with or without modification,
  24. * are permitted provided that the following conditions are met:
  25. *
  26. * 1. Redistributions of source code must retain the above copyright notice,
  27. * this list of conditions and the following disclaimer.
  28. * 2. Redistributions in binary form must reproduce the above copyright notice,
  29. * this list of conditions and the following disclaimer in the documentation
  30. * and/or other materials provided with the distribution.
  31. * 3. The name of the author may not be used to endorse or promote products
  32. * derived from this software without specific prior written permission.
  33. *
  34. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  35. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  36. * MERCHANTABILITY AND FITNESS FOR A PARTICui32AR PURPOSE ARE DISCLAIMED. IN NO EVENT
  37. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  38. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  39. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  40. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  41. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  42. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  43. * OF SUCH DAMAGE.
  44. *
  45. * This file is part of the lwIP TCP/IP stack.
  46. *
  47. * Author: Adam Dunkels <adam@sics.se>
  48. *
  49. */
  50. /**
  51. * Copyright (c) 2008-2012 Texas Instruments Incorporated
  52. *
  53. * This file is derived from the ``ethernetif.c'' skeleton Ethernet network
  54. * interface driver for lwIP.
  55. *
  56. */
  57. #include "lwip/opt.h"
  58. #include "lwip/def.h"
  59. #include "lwip/mem.h"
  60. #include "lwip/pbuf.h"
  61. #include "lwip/sys.h"
  62. #include <lwip/stats.h>
  63. #include <lwip/snmp.h>
  64. #include "lwip/tcpip.h"
  65. #include "netif/etharp.h"
  66. #include "netif/ppp_oe.h"
  67. /**
  68. * Sanity Check: This interface driver will NOT work if the following defines
  69. * are incorrect.
  70. *
  71. */
  72. #if (PBUF_LINK_HLEN != 16)
  73. #error "PBUF_LINK_HLEN must be 16 for this interface driver!"
  74. #endif
  75. #if (ETH_PAD_SIZE != 0)
  76. #error "ETH_PAD_SIZE must be 0 for this interface driver!"
  77. #endif
  78. #if (!SYS_LIGHTWEIGHT_PROT)
  79. #error "SYS_LIGHTWEIGHT_PROT must be enabled for this interface driver!"
  80. #endif
  81. /**
  82. * Set the physical address of the PHY we will be using if this is not
  83. * specified in lwipopts.h. We assume 0 for the internal PHY.
  84. */
  85. #ifndef PHY_PHYS_ADDR
  86. #define PHY_PHYS_ADDR 0
  87. #endif
  88. #ifndef EMAC_PHY_CONFIG
  89. #define EMAC_PHY_CONFIG (EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_INT_MDIX_EN | \
  90. EMAC_PHY_AN_100B_T_FULL_DUPLEX)
  91. #endif
  92. /**
  93. * If necessary, set the defaui32t number of transmit and receive DMA descriptors
  94. * used by the Ethernet MAC.
  95. *
  96. */
  97. #ifndef NUM_RX_DESCRIPTORS
  98. #define NUM_RX_DESCRIPTORS 4
  99. #endif
  100. #ifndef NUM_TX_DESCRIPTORS
  101. #define NUM_TX_DESCRIPTORS 8
  102. #endif
  103. /**
  104. * Setup processing for PTP (IEEE-1588).
  105. *
  106. */
  107. #if LWIP_PTPD
  108. extern uint32_t g_ui32SysClk;
  109. extern uint32_t g_ui32PTPTickRate;
  110. extern void lwIPHostGetTime(u32_t *time_s, u32_t *time_ns);
  111. #endif
  112. /**
  113. * Stellaris DriverLib Header Files required for this interface driver.
  114. *
  115. */
  116. #include <stdint.h>
  117. #include <stdbool.h>
  118. #include "inc/hw_emac.h"
  119. #include "inc/hw_ints.h"
  120. #include "inc/hw_memmap.h"
  121. #include "inc/hw_types.h"
  122. #include "driverlib/emac.h"
  123. #include "driverlib/interrupt.h"
  124. #include "driverlib/sysctl.h"
  125. #include "driverlib/flash.h"
  126. #include "driverlib/interrupt.h"
  127. #include "driverlib/pin_map.h"
  128. #include "driverlib/rom_map.h"
  129. #include "driverlib/gpio.h"
  130. #include <netif/ethernetif.h>
  131. #include "lwipopts.h"
  132. #include "drv_eth.h"
  133. /**
  134. * A structure used to keep track of driver state and error counts.
  135. */
  136. typedef struct {
  137. uint32_t ui32TXCount;
  138. uint32_t ui32TXCopyCount;
  139. uint32_t ui32TXCopyFailCount;
  140. uint32_t ui32TXNoDescCount;
  141. uint32_t ui32TXBufQueuedCount;
  142. uint32_t ui32TXBufFreedCount;
  143. uint32_t ui32RXBufReadCount;
  144. uint32_t ui32RXPacketReadCount;
  145. uint32_t ui32RXPacketErrCount;
  146. uint32_t ui32RXPacketCBErrCount;
  147. uint32_t ui32RXNoBufCount;
  148. }
  149. tDriverStats;
  150. tDriverStats g_sDriverStats;
  151. #ifdef DEBUG
  152. /**
  153. * Note: This rather weird construction where we invoke the macro with the
  154. * name of the field minus its Hungarian prefix is a workaround for a problem
  155. * experienced with GCC which does not like concatenating tokens after an
  156. * operator, specifically '.' or '->', in a macro.
  157. */
  158. #define DRIVER_STATS_INC(x) do{ g_sDriverStats.ui32##x++; } while(0)
  159. #define DRIVER_STATS_DEC(x) do{ g_sDriverStats.ui32##x--; } while(0)
  160. #define DRIVER_STATS_ADD(x, inc) do{ g_sDriverStats.ui32##x += (inc); } while(0)
  161. #define DRIVER_STATS_SUB(x, dec) do{ g_sDriverStats.ui32##x -= (dec); } while(0)
  162. #else
  163. #define DRIVER_STATS_INC(x)
  164. #define DRIVER_STATS_DEC(x)
  165. #define DRIVER_STATS_ADD(x, inc)
  166. #define DRIVER_STATS_SUB(x, dec)
  167. #endif
  168. /**
  169. * Helper struct holding a DMA descriptor and the pbuf it currently refers
  170. * to.
  171. */
  172. typedef struct {
  173. tEMACDMADescriptor Desc;
  174. struct pbuf *pBuf;
  175. } tDescriptor;
  176. typedef struct {
  177. tDescriptor *pDescriptors;
  178. uint32_t ui32NumDescs;
  179. uint32_t ui32Read;
  180. uint32_t ui32Write;
  181. } tDescriptorList;
  182. /**
  183. * Helper struct to hold private data used to operate your ethernet interface.
  184. * Keeping the ethernet address of the MAC in this struct is not necessary
  185. * as it is already kept in the struct netif.
  186. * But this is only an example, anyway...
  187. */
  188. typedef struct {
  189. struct eth_addr *ethaddr;
  190. /* Add whatever per-interface state that is needed here. */
  191. tDescriptorList *pTxDescList;
  192. tDescriptorList *pRxDescList;
  193. } tStellarisIF;
  194. /**
  195. * Global variable for this interface's private data. Needed to allow
  196. * the interrupt handlers access to this information outside of the
  197. * context of the lwIP netif.
  198. *
  199. */
  200. tDescriptor g_pTxDescriptors[NUM_TX_DESCRIPTORS];
  201. tDescriptor g_pRxDescriptors[NUM_RX_DESCRIPTORS];
  202. tDescriptorList g_TxDescList = {
  203. g_pTxDescriptors, NUM_TX_DESCRIPTORS, 0, 0
  204. };
  205. tDescriptorList g_RxDescList = {
  206. g_pRxDescriptors, NUM_RX_DESCRIPTORS, 0, 0
  207. };
  208. static tStellarisIF g_StellarisIFData = {
  209. 0, &g_TxDescList, &g_RxDescList
  210. };
  211. /**
  212. * Interrupt counters (for debug purposes).
  213. */
  214. volatile uint32_t g_ui32NormalInts;
  215. volatile uint32_t g_ui32AbnormalInts;
  216. /**
  217. * A macro which determines whether a pointer is within the SRAM address
  218. * space and, hence, points to a buffer that the Ethernet MAC can directly
  219. * DMA from.
  220. */
  221. #define PTR_SAFE_FOR_EMAC_DMA(ptr) (((uint32_t)(ptr) >= 0x2000000) && \
  222. ((uint32_t)(ptr) < 0x20070000))
  223. typedef struct
  224. {
  225. /* inherit from ethernet device */
  226. struct eth_device parent;
  227. tStellarisIF* dma_if;
  228. /* for rx_thread async get pbuf */
  229. rt_mailbox_t rx_pbuf_mb;
  230. } net_device;
  231. typedef net_device* net_device_t;
  232. static char rx_pbuf_mb_pool[8*4];
  233. static struct rt_mailbox eth_rx_pbuf_mb;
  234. static net_device eth_dev_entry;
  235. static net_device_t eth_dev = &eth_dev_entry;
  236. /**
  237. * Initialize the transmit and receive DMA descriptor lists.
  238. */
  239. void
  240. InitDMADescriptors(void)
  241. {
  242. uint32_t ui32Loop;
  243. /* Transmit list - mark all descriptors as not owned by the hardware */
  244. for(ui32Loop = 0; ui32Loop < NUM_TX_DESCRIPTORS; ui32Loop++)
  245. {
  246. g_pTxDescriptors[ui32Loop].pBuf = (struct pbuf *)0;
  247. g_pTxDescriptors[ui32Loop].Desc.ui32Count = 0;
  248. g_pTxDescriptors[ui32Loop].Desc.pvBuffer1 = 0;
  249. g_pTxDescriptors[ui32Loop].Desc.DES3.pLink =
  250. ((ui32Loop == (NUM_TX_DESCRIPTORS - 1)) ?
  251. &g_pTxDescriptors[0].Desc : &g_pTxDescriptors[ui32Loop + 1].Desc);
  252. g_pTxDescriptors[ui32Loop].Desc.ui32CtrlStatus = DES0_TX_CTRL_INTERRUPT |
  253. DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_IP_ALL_CKHSUMS;
  254. }
  255. g_TxDescList.ui32Read = 0;
  256. g_TxDescList.ui32Write = 0;
  257. /* Receive list - tag each descriptor with a pbuf and set all fields to
  258. * allow packets to be received.
  259. */
  260. for(ui32Loop = 0; ui32Loop < NUM_RX_DESCRIPTORS; ui32Loop++)
  261. {
  262. g_pRxDescriptors[ui32Loop].pBuf = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE,
  263. PBUF_POOL);
  264. g_pRxDescriptors[ui32Loop].Desc.ui32Count = DES1_RX_CTRL_CHAINED;
  265. if(g_pRxDescriptors[ui32Loop].pBuf)
  266. {
  267. /* Set the DMA to write directly into the pbuf payload. */
  268. g_pRxDescriptors[ui32Loop].Desc.pvBuffer1 =
  269. g_pRxDescriptors[ui32Loop].pBuf->payload;
  270. g_pRxDescriptors[ui32Loop].Desc.ui32Count |=
  271. (g_pRxDescriptors[ui32Loop].pBuf->len << DES1_RX_CTRL_BUFF1_SIZE_S);
  272. g_pRxDescriptors[ui32Loop].Desc.ui32CtrlStatus = DES0_RX_CTRL_OWN;
  273. }
  274. else
  275. {
  276. LWIP_DEBUGF(NETIF_DEBUG, ("tivaif_init: pbuf_alloc error\n"));
  277. /* No pbuf available so leave the buffer pointer empty. */
  278. g_pRxDescriptors[ui32Loop].Desc.pvBuffer1 = 0;
  279. g_pRxDescriptors[ui32Loop].Desc.ui32CtrlStatus = 0;
  280. }
  281. g_pRxDescriptors[ui32Loop].Desc.DES3.pLink =
  282. ((ui32Loop == (NUM_RX_DESCRIPTORS - 1)) ?
  283. &g_pRxDescriptors[0].Desc : &g_pRxDescriptors[ui32Loop + 1].Desc);
  284. }
  285. g_TxDescList.ui32Read = 0;
  286. g_TxDescList.ui32Write = 0;
  287. //
  288. // Set the descriptor pointers in the hardware.
  289. //
  290. EMACRxDMADescriptorListSet(EMAC0_BASE, &g_pRxDescriptors[0].Desc);
  291. EMACTxDMADescriptorListSet(EMAC0_BASE, &g_pTxDescriptors[0].Desc);
  292. }
  293. /**
  294. * In this function, the hardware should be initialized.
  295. * Called from tivaif_init().
  296. *
  297. * @param netif the already initialized lwip network interface structure
  298. * for this ethernetif
  299. */
  300. static void
  301. tivaif_hwinit(struct netif *psNetif)
  302. {
  303. uint16_t ui16Val;
  304. /* Initialize the DMA descriptors. */
  305. InitDMADescriptors();
  306. /* Clear any stray PHY interrupts that may be set. */
  307. ui16Val = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_MISR1);
  308. ui16Val = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_MISR2);
  309. /* Configure and enable the link status change interrupt in the PHY. */
  310. ui16Val = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_SCR);
  311. ui16Val |= (EPHY_SCR_INTEN_EXT | EPHY_SCR_INTOE_EXT);
  312. EMACPHYWrite(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_SCR, ui16Val);
  313. EMACPHYWrite(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_MISR1, (EPHY_MISR1_LINKSTATEN |
  314. EPHY_MISR1_SPEEDEN | EPHY_MISR1_DUPLEXMEN | EPHY_MISR1_ANCEN));
  315. /* Read the PHY interrupt status to clear any stray events. */
  316. ui16Val = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_MISR1);
  317. /**
  318. * Set MAC filtering options. We receive all broadcast and mui32ticast
  319. * packets along with those addressed specifically for us.
  320. */
  321. EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_HASH_AND_PERFECT |
  322. EMAC_FRMFILTER_PASS_MULTICAST));
  323. #if LWIP_PTPD
  324. //
  325. // Enable timestamping on all received packets.
  326. //
  327. // We set the fine clock adjustment mode and configure the subsecond
  328. // increment to half the 25MHz PTPD clock. This will give us maximum control
  329. // over the clock rate adjustment and keep the arithmetic easy later. It
  330. // should be possible to synchronize with higher accuracy than this with
  331. // appropriate juggling of the subsecond increment count and the addend
  332. // register value, though.
  333. //
  334. EMACTimestampConfigSet(EMAC0_BASE, (EMAC_TS_ALL_RX_FRAMES |
  335. EMAC_TS_DIGITAL_ROLLOVER |
  336. EMAC_TS_PROCESS_IPV4_UDP | EMAC_TS_ALL |
  337. EMAC_TS_PTP_VERSION_1 | EMAC_TS_UPDATE_FINE),
  338. (1000000000 / (25000000 / 2)));
  339. EMACTimestampAddendSet(EMAC0_BASE, 0x80000000);
  340. EMACTimestampEnable(EMAC0_BASE);
  341. #endif
  342. /* Clear any pending MAC interrupts. */
  343. EMACIntClear(EMAC0_BASE, EMACIntStatus(EMAC0_BASE, false));
  344. /* Enable the Ethernet MAC transmitter and receiver. */
  345. EMACTxEnable(EMAC0_BASE);
  346. EMACRxEnable(EMAC0_BASE);
  347. /* Enable the Ethernet RX and TX interrupt source. */
  348. EMACIntEnable(EMAC0_BASE, (EMAC_INT_RECEIVE | EMAC_INT_TRANSMIT |
  349. EMAC_INT_TX_STOPPED | EMAC_INT_RX_NO_BUFFER |
  350. EMAC_INT_RX_STOPPED | EMAC_INT_PHY));
  351. /* Enable the Ethernet interrupt. */
  352. IntEnable(INT_EMAC0);
  353. /* Enable all processor interrupts. */
  354. IntMasterEnable();
  355. /* Tell the PHY to start an auto-negotiation cycle. */
  356. EMACPHYWrite(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_BMCR, (EPHY_BMCR_ANEN |
  357. EPHY_BMCR_RESTARTAN));
  358. }
  359. #ifdef DEBUG
  360. /**
  361. * Dump the chain of pbuf pointers to the debug output.
  362. */
  363. void
  364. tivaif_trace_pbuf(const char *pcTitle, struct pbuf *p)
  365. {
  366. LWIP_DEBUGF(NETIF_DEBUG, ("%s %08x (%d, %d)", pcTitle, p, p->tot_len,
  367. p->len));
  368. do
  369. {
  370. p = p->next;
  371. if(p)
  372. {
  373. LWIP_DEBUGF(NETIF_DEBUG, ("->%08x(%d)", p, p->len));
  374. }
  375. else
  376. {
  377. LWIP_DEBUGF(NETIF_DEBUG, ("->%08x", p));
  378. }
  379. } while((p != NULL) && (p->tot_len != p->len));
  380. LWIP_DEBUGF(NETIF_DEBUG, ("\n"));
  381. }
  382. #endif
  383. /**
  384. * This function is used to check whether a passed pbuf contains only buffers
  385. * resident in regions of memory that the Ethernet MAC can access. If any
  386. * buffers in the chain are outside a directly-DMAable section of memory,
  387. * the pbuf is copied to SRAM and a different pointer returned. If all
  388. * buffers are safe, the pbuf reference count is incremented and the original
  389. * pointer returned.
  390. */
  391. static struct pbuf *
  392. tivaif_check_pbuf(struct pbuf *p)
  393. {
  394. struct pbuf *pBuf;
  395. rt_err_t Err;
  396. pBuf = p;
  397. #ifdef DEBUG
  398. tivaif_trace_pbuf("Original:", p);
  399. #endif
  400. /* Walk the list of buffers in the pbuf checking each. */
  401. do
  402. {
  403. /* Does this pbuf's payload reside in memory that the Ethernet DMA
  404. * can access?
  405. */
  406. if(!PTR_SAFE_FOR_EMAC_DMA(pBuf->payload))
  407. {
  408. /* This buffer is outside the DMA-able memory space so we need
  409. * to copy the pbuf.
  410. */
  411. pBuf = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_POOL);
  412. /* If we got a new pbuf... */
  413. if(pBuf)
  414. {
  415. /* ...copy the old pbuf into the new one. */
  416. Err = pbuf_copy(pBuf, p);
  417. /* If we failed to copy the pbuf, free the newly allocated one
  418. * and make sure we return a NULL to show a problem.
  419. */
  420. if(Err != RT_EOK)
  421. {
  422. DRIVER_STATS_INC(TXCopyFailCount);
  423. pbuf_free(pBuf);
  424. pBuf = NULL;
  425. }
  426. else
  427. {
  428. #ifdef DEBUG
  429. tivaif_trace_pbuf("Copied:", pBuf);
  430. #endif
  431. DRIVER_STATS_INC(TXCopyCount);
  432. /* Reduce the reference count on the original pbuf since
  433. * we're not going to hold on to it after returning from
  434. * tivaif_transmit. Note that we already bumped
  435. * the reference count at the top of tivaif_transmit.
  436. */
  437. pbuf_free(p);
  438. }
  439. }
  440. /* Send back the new pbuf pointer or NULL if an error occurred. */
  441. return(pBuf);
  442. }
  443. /* Move on to the next buffer in the queue */
  444. pBuf = pBuf->next;
  445. }
  446. while(pBuf);
  447. /**
  448. * If we get here, the passed pbuf can be safely used without needing to
  449. * be copied.
  450. */
  451. return(p);
  452. }
  453. /**
  454. * This function should do the actual transmission of the packet. The packet is
  455. * contained in the pbuf that is passed to the function. This pbuf might be
  456. * chained.
  457. *
  458. * @param psNetif the lwip network interface structure for this ethernetif
  459. * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
  460. * @return RT_EOK if the packet coui32d be sent
  461. * an err_t value if the packet coui32dn't be sent
  462. */
  463. static rt_err_t
  464. tivaif_transmit(net_device_t dev, struct pbuf *p)
  465. {
  466. tStellarisIF *pIF;
  467. tDescriptor *pDesc;
  468. struct pbuf *pBuf;
  469. uint32_t ui32NumChained, ui32NumDescs;
  470. bool bFirst;
  471. SYS_ARCH_DECL_PROTECT(lev);
  472. LWIP_DEBUGF(NETIF_DEBUG, ("tivaif_transmit 0x%08x, len %d\n", p,
  473. p->tot_len));
  474. /**
  475. * This entire function must run within a "critical section" to preserve
  476. * the integrity of the transmit pbuf queue.
  477. */
  478. SYS_ARCH_PROTECT(lev);
  479. /* Update our transmit attempt counter. */
  480. DRIVER_STATS_INC(TXCount);
  481. /**
  482. * Increase the reference count on the packet provided so that we can
  483. * hold on to it until we are finished transmitting its content.
  484. */
  485. pbuf_ref(p);
  486. /**
  487. * Determine whether all buffers passed are within SRAM and, if not, copy
  488. * the pbuf into SRAM-resident buffers so that the Ethernet DMA can access
  489. * the data.
  490. */
  491. p = tivaif_check_pbuf(p);
  492. /* Make sure we still have a valid buffer (it may have been copied) */
  493. if(!p)
  494. {
  495. LINK_STATS_INC(link.memerr);
  496. SYS_ARCH_UNPROTECT(lev);
  497. return(-RT_ENOMEM);
  498. }
  499. /* Get our state data from the netif structure we were passed. */
  500. //pIF = (tStellarisIF *)psNetif->state;
  501. pIF = dev->dma_if;
  502. /* Make sure that the transmit descriptors are not all in use */
  503. pDesc = &(pIF->pTxDescList->pDescriptors[pIF->pTxDescList->ui32Write]);
  504. if(pDesc->pBuf)
  505. {
  506. /**
  507. * The current write descriptor has a pbuf attached to it so this
  508. * implies that the ring is fui32l. Reject this transmit request with a
  509. * memory error since we can't satisfy it just now.
  510. */
  511. pbuf_free(p);
  512. LINK_STATS_INC(link.memerr);
  513. DRIVER_STATS_INC(TXNoDescCount);
  514. SYS_ARCH_UNPROTECT(lev);
  515. return (-RT_ENOMEM);
  516. }
  517. /* How many pbufs are in the chain passed? */
  518. ui32NumChained = (uint32_t)pbuf_clen(p);
  519. /* How many free transmit descriptors do we have? */
  520. ui32NumDescs = (pIF->pTxDescList->ui32Read > pIF->pTxDescList->ui32Write) ?
  521. (pIF->pTxDescList->ui32Read - pIF->pTxDescList->ui32Write) :
  522. ((NUM_TX_DESCRIPTORS - pIF->pTxDescList->ui32Write) +
  523. pIF->pTxDescList->ui32Read);
  524. /* Do we have enough free descriptors to send the whole packet? */
  525. if(ui32NumDescs < ui32NumChained)
  526. {
  527. /* No - we can't transmit this whole packet so return an error. */
  528. pbuf_free(p);
  529. LINK_STATS_INC(link.memerr);
  530. DRIVER_STATS_INC(TXNoDescCount);
  531. SYS_ARCH_UNPROTECT(lev);
  532. return (-RT_ENOMEM);
  533. }
  534. /* Tag the first descriptor as the start of the packet. */
  535. bFirst = true;
  536. pDesc->Desc.ui32CtrlStatus = DES0_TX_CTRL_FIRST_SEG;
  537. /* Here, we know we can send the packet so write it to the descriptors */
  538. pBuf = p;
  539. while(ui32NumChained)
  540. {
  541. /* Get a pointer to the descriptor we will write next. */
  542. pDesc = &(pIF->pTxDescList->pDescriptors[pIF->pTxDescList->ui32Write]);
  543. /* Fill in the buffer pointer and length */
  544. pDesc->Desc.ui32Count = (uint32_t)pBuf->len;
  545. pDesc->Desc.pvBuffer1 = pBuf->payload;
  546. /* Tag the first descriptor as the start of the packet. */
  547. if(bFirst)
  548. {
  549. bFirst = false;
  550. pDesc->Desc.ui32CtrlStatus = DES0_TX_CTRL_FIRST_SEG;
  551. }
  552. else
  553. {
  554. pDesc->Desc.ui32CtrlStatus = 0;
  555. }
  556. #ifdef RT_LWIP_USING_HW_CHECKSUM
  557. pDesc->Desc.ui32CtrlStatus |= (DES0_TX_CTRL_IP_ALL_CKHSUMS |
  558. DES0_TX_CTRL_CHAINED);
  559. #else
  560. pDesc->Desc.ui32CtrlStatus |= (DES0_TX_CTRL_NO_CHKSUM |
  561. DES0_TX_CTRL_CHAINED);
  562. #endif
  563. /* Decrement our descriptor counter, move on to the next buffer in the
  564. * pbuf chain. */
  565. ui32NumChained--;
  566. pBuf = pBuf->next;
  567. /* Update the descriptor list write index. */
  568. pIF->pTxDescList->ui32Write++;
  569. if(pIF->pTxDescList->ui32Write == NUM_TX_DESCRIPTORS)
  570. {
  571. pIF->pTxDescList->ui32Write = 0;
  572. }
  573. /* If this is the last descriptor, mark it as the end of the packet. */
  574. if(!ui32NumChained)
  575. {
  576. pDesc->Desc.ui32CtrlStatus |= (DES0_TX_CTRL_LAST_SEG |
  577. DES0_TX_CTRL_INTERRUPT);
  578. /* Tag the descriptor with the original pbuf pointer. */
  579. pDesc->pBuf = p;
  580. }
  581. else
  582. {
  583. /* Set the lsb of the pbuf pointer. We use this as a signal that
  584. * we should not free the pbuf when we are walking the descriptor
  585. * list while processing the transmit interrupt. We only free the
  586. * pbuf when processing the last descriptor used to transmit its
  587. * chain.
  588. */
  589. pDesc->pBuf = (struct pbuf *)((uint32_t)p + 1);
  590. }
  591. DRIVER_STATS_INC(TXBufQueuedCount);
  592. /* Hand the descriptor over to the hardware. */
  593. pDesc->Desc.ui32CtrlStatus |= DES0_TX_CTRL_OWN;
  594. }
  595. /* Tell the transmitter to start (in case it had stopped). */
  596. EMACTxDMAPollDemand(EMAC0_BASE);
  597. /* Update lwIP statistics */
  598. LINK_STATS_INC(link.xmit);
  599. SYS_ARCH_UNPROTECT(lev);
  600. return(RT_EOK);
  601. }
  602. /**
  603. * This function will process all transmit descriptors and free pbufs attached
  604. * to any that have been transmitted since we last checked.
  605. *
  606. * This function is called only from the Ethernet interrupt handler.
  607. *
  608. * @param netif the lwip network interface structure for this ethernetif
  609. * @return None.
  610. */
  611. static void
  612. tivaif_process_transmit(tStellarisIF *pIF)
  613. {
  614. tDescriptorList *pDescList;
  615. uint32_t ui32NumDescs;
  616. /* Get a pointer to the transmit descriptor list. */
  617. pDescList = pIF->pTxDescList;
  618. /* Walk the list until we have checked all descriptors or we reach the
  619. * write pointer or find a descriptor that the hardware is still working
  620. * on.
  621. */
  622. for(ui32NumDescs = 0; ui32NumDescs < pDescList->ui32NumDescs; ui32NumDescs++)
  623. {
  624. /* Has the buffer attached to this descriptor been transmitted? */
  625. if(pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32CtrlStatus &
  626. DES0_TX_CTRL_OWN)
  627. {
  628. /* No - we're finished. */
  629. break;
  630. }
  631. /* Does this descriptor have a buffer attached to it? */
  632. if(pDescList->pDescriptors[pDescList->ui32Read].pBuf)
  633. {
  634. /* Yes - free it if it's not marked as an intermediate pbuf */
  635. if(!((uint32_t)(pDescList->pDescriptors[pDescList->ui32Read].pBuf) & 1))
  636. {
  637. pbuf_free(pDescList->pDescriptors[pDescList->ui32Read].pBuf);
  638. DRIVER_STATS_INC(TXBufFreedCount);
  639. }
  640. pDescList->pDescriptors[pDescList->ui32Read].pBuf = NULL;
  641. }
  642. else
  643. {
  644. /* If the descriptor has no buffer, we are finished. */
  645. break;
  646. }
  647. /* Move on to the next descriptor. */
  648. pDescList->ui32Read++;
  649. if(pDescList->ui32Read == pDescList->ui32NumDescs)
  650. {
  651. pDescList->ui32Read = 0;
  652. }
  653. }
  654. }
  655. /**
  656. * This function will process all receive descriptors that contain newly read
  657. * data and pass complete frames up the lwIP stack as they are found. The
  658. * timestamp of the packet will be placed into the pbuf structure if PTPD is
  659. * enabled.
  660. *
  661. * This function is called only from the Ethernet interrupt handler.
  662. *
  663. * @param psNetif the lwip network interface structure for this ethernetif
  664. * @return None.
  665. */
  666. static void
  667. tivaif_receive(net_device_t dev)
  668. {
  669. tDescriptorList *pDescList;
  670. tStellarisIF *pIF;
  671. struct pbuf *pBuf;
  672. uint32_t ui32DescEnd;
  673. /* Get a pointer to our state data */
  674. pIF = dev->dma_if;
  675. /* Get a pointer to the receive descriptor list. */
  676. pDescList = pIF->pRxDescList;
  677. /* Start with a NULL pbuf so that we don't try to link chain the first
  678. * time round.
  679. */
  680. pBuf = NULL;
  681. /* Determine where we start and end our walk of the descriptor list */
  682. ui32DescEnd = pDescList->ui32Read ? (pDescList->ui32Read - 1) : (pDescList->ui32NumDescs - 1);
  683. /* Step through the descriptors that are marked for CPU attention. */
  684. while(pDescList->ui32Read != ui32DescEnd)
  685. {
  686. /* Does the current descriptor have a buffer attached to it? */
  687. if(pDescList->pDescriptors[pDescList->ui32Read].pBuf)
  688. {
  689. /* Yes - determine if the host has filled it yet. */
  690. if(pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32CtrlStatus &
  691. DES0_RX_CTRL_OWN)
  692. {
  693. /* The DMA engine still owns the descriptor so we are finished */
  694. break;
  695. }
  696. DRIVER_STATS_INC(RXBufReadCount);
  697. /* If this descriptor contains the end of the packet, fix up the
  698. * buffer size accordingly.
  699. */
  700. if(pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32CtrlStatus &
  701. DES0_RX_STAT_LAST_DESC)
  702. {
  703. /* This is the last descriptor for the frame so fix up the
  704. * length. It is safe for us to modify the internal fields
  705. * directly here (rather than calling pbuf_realloc) since we
  706. * know each of these pbufs is never chained.
  707. */
  708. pDescList->pDescriptors[pDescList->ui32Read].pBuf->len =
  709. (pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32CtrlStatus &
  710. DES0_RX_STAT_FRAME_LENGTH_M) >>
  711. DES0_RX_STAT_FRAME_LENGTH_S;
  712. pDescList->pDescriptors[pDescList->ui32Read].pBuf->tot_len =
  713. pDescList->pDescriptors[pDescList->ui32Read].pBuf->len;
  714. }
  715. if(pBuf)
  716. {
  717. /* Link this pbuf to the last one we looked at since this buffer
  718. * is a continuation of an existing frame (split across mui32tiple
  719. * pbufs). Note that we use pbuf_cat() here rather than
  720. * pbuf_chain() since we don't want to increase the reference
  721. * count of either pbuf - we only want to link them together.
  722. */
  723. pbuf_cat(pBuf, pDescList->pDescriptors[pDescList->ui32Read].pBuf);
  724. pDescList->pDescriptors[pDescList->ui32Read].pBuf = pBuf;
  725. }
  726. /* Remember the buffer associated with this descriptor. */
  727. pBuf = pDescList->pDescriptors[pDescList->ui32Read].pBuf;
  728. /* Is this the last descriptor for the current frame? */
  729. if(pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32CtrlStatus &
  730. DES0_RX_STAT_LAST_DESC)
  731. {
  732. /* Yes - does the frame contain errors? */
  733. if(pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32CtrlStatus &
  734. DES0_RX_STAT_ERR)
  735. {
  736. /* This is a bad frame so discard it and update the relevant
  737. * statistics.
  738. */
  739. LWIP_DEBUGF(NETIF_DEBUG, ("tivaif_receive: packet error\n"));
  740. pbuf_free(pBuf);
  741. LINK_STATS_INC(link.drop);
  742. DRIVER_STATS_INC(RXPacketErrCount);
  743. }
  744. else
  745. {
  746. /* This is a good frame so pass it up the stack. */
  747. LINK_STATS_INC(link.recv);
  748. DRIVER_STATS_INC(RXPacketReadCount);
  749. #if LWIP_PTPD
  750. /* Place the timestamp in the PBUF if PTPD is enabled */
  751. pBuf->time_s =
  752. pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32IEEE1588TimeHi;
  753. pBuf->time_ns =
  754. pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32IEEE1588TimeLo;
  755. #endif
  756. #if NO_SYS
  757. if(ethernet_input(pBuf, psNetif) != RT_EOK)
  758. {
  759. #else
  760. //if(tcpip_input(pBuf, psNetif) != RT_EOK)
  761. if((rt_mb_send(dev->rx_pbuf_mb, (rt_uint32_t)pBuf) != RT_EOK) ||
  762. (eth_device_ready(&(dev->parent)) != RT_EOK))
  763. {
  764. #endif
  765. /* drop the packet */
  766. LWIP_DEBUGF(NETIF_DEBUG, ("tivaif_input: input error\n"));
  767. pbuf_free(pBuf);
  768. /* Adjust the link statistics */
  769. LINK_STATS_INC(link.memerr);
  770. LINK_STATS_INC(link.drop);
  771. DRIVER_STATS_INC(RXPacketCBErrCount);
  772. }
  773. /* We're finished with this packet so make sure we don't try
  774. * to link the next buffer to it.
  775. */
  776. pBuf = NULL;
  777. }
  778. }
  779. }
  780. /* Allocate a new buffer for this descriptor */
  781. pDescList->pDescriptors[pDescList->ui32Read].pBuf = pbuf_alloc(PBUF_RAW,
  782. PBUF_POOL_BUFSIZE,
  783. PBUF_POOL);
  784. pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32Count =
  785. DES1_RX_CTRL_CHAINED;
  786. if(pDescList->pDescriptors[pDescList->ui32Read].pBuf)
  787. {
  788. /* We got a buffer so fill in the payload pointer and size. */
  789. pDescList->pDescriptors[pDescList->ui32Read].Desc.pvBuffer1 =
  790. pDescList->pDescriptors[pDescList->ui32Read].pBuf->payload;
  791. pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32Count |=
  792. (pDescList->pDescriptors[pDescList->ui32Read].pBuf->len <<
  793. DES1_RX_CTRL_BUFF1_SIZE_S);
  794. /* Give this descriptor back to the hardware */
  795. pDescList->pDescriptors[pDescList->ui32Read].Desc.ui32CtrlStatus =
  796. DES0_RX_CTRL_OWN;
  797. }
  798. else
  799. {
  800. LWIP_DEBUGF(NETIF_DEBUG, ("tivaif_receive: pbuf_alloc error\n"));
  801. pDescList->pDescriptors[pDescList->ui32Read].Desc.pvBuffer1 = 0;
  802. /* Update the stats to show we coui32dn't allocate a pbuf. */
  803. DRIVER_STATS_INC(RXNoBufCount);
  804. LINK_STATS_INC(link.memerr);
  805. /* Stop parsing here since we can't leave a broken descriptor in
  806. * the chain.
  807. */
  808. break;
  809. }
  810. /* Move on to the next descriptor in the chain, taking care to wrap. */
  811. pDescList->ui32Read++;
  812. if(pDescList->ui32Read == pDescList->ui32NumDescs)
  813. {
  814. pDescList->ui32Read = 0;
  815. }
  816. }
  817. }
  818. /**
  819. * Process interrupts from the PHY.
  820. *
  821. * should be called from the Stellaris Ethernet Interrupt Handler. This
  822. * function will read packets from the Stellaris Ethernet fifo and place them
  823. * into a pbuf queue. If the transmitter is idle and there is at least one packet
  824. * on the transmit queue, it will place it in the transmit fifo and start the
  825. * transmitter.
  826. *
  827. */
  828. void
  829. tivaif_process_phy_interrupt(net_device_t dev)
  830. {
  831. uint16_t ui16Val, ui16Status;
  832. uint32_t ui32Config, ui32Mode, ui32RxMaxFrameSize;
  833. /* Read the PHY interrupt status. This clears all interrupt sources.
  834. * Note that we are only enabling sources in EPHY_MISR1 so we don't
  835. * read EPHY_MISR2.
  836. */
  837. ui16Val = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_MISR1);
  838. /*
  839. * Dummy read PHY REG EPHY_BMSR, it will force update the EPHY_STS register
  840. */
  841. EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_BMSR);
  842. /* Read the current PHY status. */
  843. ui16Status = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, EPHY_STS);
  844. /* Has the link status changed? */
  845. if(ui16Val & EPHY_MISR1_LINKSTAT)
  846. {
  847. /* Is link up or down now? */
  848. if(ui16Status & EPHY_STS_LINK)
  849. {
  850. /* Tell lwIP the link is up. */
  851. #if NO_SYS
  852. netif_set_link_up(psNetif);
  853. #else
  854. //tcpip_callback((tcpip_callback_fn)netif_set_link_up, psNetif);
  855. eth_device_linkchange(&(dev->parent), RT_TRUE);
  856. #endif
  857. /* In this case we drop through since we may need to reconfigure
  858. * the MAC depending upon the speed and half/fui32l-duplex settings.
  859. */
  860. }
  861. else
  862. {
  863. /* Tell lwIP the link is down */
  864. #if NO_SYS
  865. netif_set_link_down(psNetif);
  866. #else
  867. //tcpip_callback((tcpip_callback_fn)netif_set_link_down, psNetif);
  868. eth_device_linkchange(&(dev->parent), RT_FALSE);
  869. #endif
  870. }
  871. }
  872. /* Has the speed or duplex status changed? */
  873. if(ui16Val & (EPHY_MISR1_SPEED | EPHY_MISR1_SPEED | EPHY_MISR1_ANC))
  874. {
  875. /* Get the current MAC configuration. */
  876. EMACConfigGet(EMAC0_BASE, &ui32Config, &ui32Mode,
  877. &ui32RxMaxFrameSize);
  878. /* What speed is the interface running at now?
  879. */
  880. if(ui16Status & EPHY_STS_SPEED)
  881. {
  882. /* 10Mbps is selected */
  883. ui32Config &= ~EMAC_CONFIG_100MBPS;
  884. }
  885. else
  886. {
  887. /* 100Mbps is selected */
  888. ui32Config |= EMAC_CONFIG_100MBPS;
  889. }
  890. /* Are we in fui32l- or half-duplex mode? */
  891. if(ui16Status & EPHY_STS_DUPLEX)
  892. {
  893. /* Fui32l duplex. */
  894. ui32Config |= EMAC_CONFIG_FULL_DUPLEX;
  895. }
  896. else
  897. {
  898. /* Half duplex. */
  899. ui32Config &= ~EMAC_CONFIG_FULL_DUPLEX;
  900. }
  901. /* Reconfigure the MAC */
  902. EMACConfigSet(EMAC0_BASE, ui32Config, ui32Mode, ui32RxMaxFrameSize);
  903. }
  904. }
  905. /**
  906. * Process tx and rx packets at the low-level interrupt.
  907. *
  908. * should be called from the Stellaris Ethernet Interrupt Handler. This
  909. * function will read packets from the Stellaris Ethernet fifo and place them
  910. * into a pbuf queue. If the transmitter is idle and there is at least one packet
  911. * on the transmit queue, it will place it in the transmit fifo and start the
  912. * transmitter.
  913. *
  914. */
  915. void
  916. tivaif_interrupt(net_device_t dev, uint32_t ui32Status)
  917. {
  918. /* Update our debug interrupt counters. */
  919. if(ui32Status & EMAC_INT_NORMAL_INT)
  920. {
  921. g_ui32NormalInts++;
  922. }
  923. if(ui32Status & EMAC_INT_ABNORMAL_INT)
  924. {
  925. g_ui32AbnormalInts++;
  926. }
  927. /* Is this an interrupt from the PHY? */
  928. if(ui32Status & EMAC_INT_PHY)
  929. {
  930. tivaif_process_phy_interrupt(dev);
  931. }
  932. /* Process the transmit DMA list, freeing any buffers that have been
  933. * transmitted since our last interrupt.
  934. */
  935. if(ui32Status & EMAC_INT_TRANSMIT)
  936. {
  937. tivaif_process_transmit(dev->dma_if);
  938. }
  939. /**
  940. * Process the receive DMA list and pass all successfui32ly received packets
  941. * up the stack. We also call this function in cases where the receiver has
  942. * stalled due to missing buffers since the receive function will attempt to
  943. * allocate new pbufs for descriptor entries which have none.
  944. */
  945. if(ui32Status & (EMAC_INT_RECEIVE | EMAC_INT_RX_NO_BUFFER |
  946. EMAC_INT_RX_STOPPED))
  947. {
  948. tivaif_receive(dev);
  949. }
  950. }
  951. #if NETIF_DEBUG
  952. /* Print an IP header by using LWIP_DEBUGF
  953. * @param p an IP packet, p->payload pointing to the IP header
  954. */
  955. void
  956. tivaif_debug_print(struct pbuf *p)
  957. {
  958. struct eth_hdr *ethhdr = (struct eth_hdr *)p->payload;
  959. u16_t *plen = (u16_t *)p->payload;
  960. LWIP_DEBUGF(NETIF_DEBUG, ("ETH header:\n"));
  961. LWIP_DEBUGF(NETIF_DEBUG, ("Packet Length:%5"U16_F" \n",*plen));
  962. LWIP_DEBUGF(NETIF_DEBUG, ("Destination: %02"X8_F"-%02"X8_F"-%02"X8_F"-%02"X8_F"-%02"X8_F"-%02"X8_F"\n",
  963. ethhdr->dest.addr[0],
  964. ethhdr->dest.addr[1],
  965. ethhdr->dest.addr[2],
  966. ethhdr->dest.addr[3],
  967. ethhdr->dest.addr[4],
  968. ethhdr->dest.addr[5]));
  969. LWIP_DEBUGF(NETIF_DEBUG, ("Source: %02"X8_F"-%02"X8_F"-%02"X8_F"-%02"X8_F"-%02"X8_F"-%02"X8_F"\n",
  970. ethhdr->src.addr[0],
  971. ethhdr->src.addr[1],
  972. ethhdr->src.addr[2],
  973. ethhdr->src.addr[3],
  974. ethhdr->src.addr[4],
  975. ethhdr->src.addr[5]));
  976. LWIP_DEBUGF(NETIF_DEBUG, ("Packet Type:0x%04"U16_F" \n", ethhdr->type));
  977. }
  978. #endif /* NETIF_DEBUG */
  979. void lwIPEthernetIntHandler(void)
  980. {
  981. uint32_t ui32Status;
  982. #ifdef DEF_INT_TEMPSTAMP
  983. uint32_t ui32TimerStatus;
  984. #endif
  985. //
  986. // Read and Clear the interrupt.
  987. //
  988. ui32Status = MAP_EMACIntStatus(EMAC0_BASE, true);
  989. //
  990. // If the interrupt really came from the Ethernet and not our
  991. // timer, clear it.
  992. //
  993. if(ui32Status)
  994. {
  995. MAP_EMACIntClear(EMAC0_BASE, ui32Status);
  996. }
  997. #ifdef DEF_INT_TEMPSTAMP
  998. //
  999. // Check to see whether a hardware timer interrupt has been reported.
  1000. //
  1001. if(ui32Status & EMAC_INT_TIMESTAMP)
  1002. {
  1003. //
  1004. // Yes - read and clear the timestamp interrupt status.
  1005. //
  1006. ui32TimerStatus = EMACTimestampIntStatus(EMAC0_BASE);
  1007. //
  1008. // If a timer interrupt handler has been registered, call it.
  1009. //
  1010. if(g_pfnTimerHandler)
  1011. {
  1012. g_pfnTimerHandler(EMAC0_BASE, ui32TimerStatus);
  1013. }
  1014. }
  1015. #endif
  1016. //
  1017. // The handling of the interrupt is different based on the use of a RTOS.
  1018. //
  1019. //
  1020. // No RTOS is being used. If a transmit/receive interrupt was active,
  1021. // run the low-level interrupt handler.
  1022. //
  1023. if(ui32Status)
  1024. {
  1025. tivaif_interrupt(eth_dev, ui32Status);
  1026. }
  1027. //
  1028. // Service the lwIP timers.
  1029. //
  1030. //lwIPServiceTimers();
  1031. }
  1032. // OUI:00-12-37 (hex) Texas Instruments, only for test
  1033. static int tiva_eth_mac_addr_init(void)
  1034. {
  1035. int retVal =0;
  1036. uint32_t ulUser[2];
  1037. uint8_t mac_addr[6];
  1038. MAP_FlashUserGet(&ulUser[0], &ulUser[1]);
  1039. if((ulUser[0] == 0xffffffff) || (ulUser[1] == 0xffffffff))
  1040. {
  1041. rt_kprintf("Fail to get mac address from eeprom.\n");
  1042. rt_kprintf("Using default mac address\n");
  1043. // OUI:00-12-37 (hex) Texas Instruments, only for test
  1044. // Configure the hardware MAC address
  1045. ulUser[0] = 0x00371200;
  1046. ulUser[1] = 0x00563412;
  1047. //FlashUserSet(ulUser0, ulUser1);
  1048. retVal =-1;
  1049. }
  1050. //Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
  1051. //address needed to program the hardware registers, then program the MAC
  1052. //address into the Ethernet Controller registers.
  1053. mac_addr[0] = ((ulUser[0] >> 0) & 0xff);
  1054. mac_addr[1] = ((ulUser[0] >> 8) & 0xff);
  1055. mac_addr[2] = ((ulUser[0] >> 16) & 0xff);
  1056. mac_addr[3] = ((ulUser[1] >> 0) & 0xff);
  1057. mac_addr[4] = ((ulUser[1] >> 8) & 0xff);
  1058. mac_addr[5] = ((ulUser[1] >> 16) & 0xff);
  1059. //
  1060. // Program the hardware with its MAC address (for filtering).
  1061. //
  1062. MAP_EMACAddrSet(EMAC0_BASE, 0, mac_addr);
  1063. return retVal;
  1064. }
  1065. void tiva_eth_lowlevel_init(void)
  1066. {
  1067. MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
  1068. //
  1069. // PF1/PK4/PK6 are used for Ethernet LEDs.
  1070. //
  1071. MAP_GPIOPinConfigure(GPIO_PF0_EN0LED0);
  1072. MAP_GPIOPinConfigure(GPIO_PF4_EN0LED1);
  1073. GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0);
  1074. GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_4);
  1075. //
  1076. // Enable the ethernet peripheral.
  1077. //
  1078. MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
  1079. MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EMAC0);
  1080. //
  1081. // Enable the internal PHY if it's present and we're being
  1082. // asked to use it.
  1083. //
  1084. if((EMAC_PHY_CONFIG & EMAC_PHY_TYPE_MASK) == EMAC_PHY_TYPE_INTERNAL)
  1085. {
  1086. //
  1087. // We've been asked to configure for use with the internal
  1088. // PHY. Is it present?
  1089. //
  1090. if(SysCtlPeripheralPresent(SYSCTL_PERIPH_EPHY0))
  1091. {
  1092. //
  1093. // Yes - enable and reset it.
  1094. //
  1095. MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
  1096. MAP_SysCtlPeripheralReset(SYSCTL_PERIPH_EPHY0);
  1097. }
  1098. else
  1099. {
  1100. //
  1101. // Internal PHY is not present on this part so hang here.
  1102. //
  1103. rt_kprintf("Internal PHY is not present on this part.\n");
  1104. while(1)
  1105. {
  1106. }
  1107. }
  1108. }
  1109. //
  1110. // Wait for the MAC to come out of reset.
  1111. //
  1112. while(!MAP_SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0))
  1113. {
  1114. }
  1115. //
  1116. // Configure for use with whichever PHY the user requires.
  1117. //
  1118. MAP_EMACPHYConfigSet(EMAC0_BASE, EMAC_PHY_CONFIG);
  1119. //
  1120. // Initialize the MAC and set the DMA mode.
  1121. //
  1122. MAP_EMACInit(EMAC0_BASE, 120000000, //system clock = 120MHz
  1123. EMAC_BCONFIG_MIXED_BURST | EMAC_BCONFIG_PRIORITY_FIXED,
  1124. 4, 4, 0);
  1125. //
  1126. // Set MAC configuration options.
  1127. //
  1128. MAP_EMACConfigSet(EMAC0_BASE, (EMAC_CONFIG_FULL_DUPLEX |
  1129. EMAC_CONFIG_CHECKSUM_OFFLOAD |
  1130. EMAC_CONFIG_7BYTE_PREAMBLE |
  1131. EMAC_CONFIG_IF_GAP_96BITS |
  1132. EMAC_CONFIG_USE_MACADDR0 |
  1133. EMAC_CONFIG_SA_FROM_DESCRIPTOR |
  1134. EMAC_CONFIG_BO_LIMIT_1024),
  1135. (EMAC_MODE_RX_STORE_FORWARD |
  1136. EMAC_MODE_TX_STORE_FORWARD |
  1137. EMAC_MODE_TX_THRESHOLD_64_BYTES |
  1138. EMAC_MODE_RX_THRESHOLD_64_BYTES), 0);
  1139. EMACIntRegister(EMAC0_BASE, lwIPEthernetIntHandler);
  1140. }
  1141. static rt_err_t eth_dev_init(rt_device_t device)
  1142. {
  1143. net_device_t net_dev = (net_device_t)device;
  1144. struct netif *psNetif = (net_dev->parent.netif);
  1145. LWIP_ASSERT("psNetif != NULL", (psNetif != NULL));
  1146. #if LWIP_NETIF_HOSTNAME
  1147. /* Initialize interface hostname */
  1148. psNetif->hostname = "t4mc";
  1149. #endif /* LWIP_NETIF_HOSTNAME */
  1150. /*
  1151. * Initialize the snmp variables and counters inside the struct netif.
  1152. * The last argument should be replaced with your link speed, in units
  1153. * of bits per second.
  1154. */
  1155. //NETIF_INIT_SNMP(psNetif, snmp_ifType_ethernet_csmacd, 1000000);
  1156. net_dev->dma_if = &g_StellarisIFData;
  1157. /* Remember our MAC address. */
  1158. g_StellarisIFData.ethaddr = (struct eth_addr *)&(psNetif->hwaddr[0]);
  1159. /* Initialize the hardware */
  1160. tivaif_hwinit(psNetif);
  1161. return RT_EOK;
  1162. }
  1163. /* control the interface */
  1164. static rt_err_t eth_dev_control(rt_device_t dev, int cmd, void *args)
  1165. {
  1166. switch(cmd)
  1167. {
  1168. case NIOCTL_GADDR:
  1169. /* get mac address */
  1170. if(args)
  1171. MAP_EMACAddrGet(EMAC0_BASE, 0, (uint8_t*)args);
  1172. else
  1173. return -RT_ERROR;
  1174. break;
  1175. default :
  1176. break;
  1177. }
  1178. return RT_EOK;
  1179. }
  1180. /* Open the interface */
  1181. static rt_err_t eth_dev_open(rt_device_t dev, rt_uint16_t oflag)
  1182. {
  1183. return RT_EOK;
  1184. }
  1185. /* Close the interface */
  1186. static rt_err_t eth_dev_close(rt_device_t dev)
  1187. {
  1188. return RT_EOK;
  1189. }
  1190. /* Read */
  1191. static rt_size_t eth_dev_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  1192. {
  1193. rt_set_errno(-RT_ENOSYS);
  1194. return 0;
  1195. }
  1196. /* Write */
  1197. static rt_size_t eth_dev_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
  1198. {
  1199. rt_set_errno(-RT_ENOSYS);
  1200. return 0;
  1201. }
  1202. static rt_err_t eth_dev_tx(rt_device_t dev, struct pbuf *p)
  1203. {
  1204. return tivaif_transmit((net_device_t)dev, p);
  1205. }
  1206. static struct pbuf* eth_dev_rx(rt_device_t dev)
  1207. {
  1208. rt_err_t result;
  1209. rt_uint32_t temp =0;
  1210. net_device_t net_dev = (net_device_t)dev;
  1211. result = rt_mb_recv(net_dev->rx_pbuf_mb, (rt_ubase_t *)&temp, RT_WAITING_NO);
  1212. return (result == RT_EOK)? (struct pbuf*)temp : RT_NULL;
  1213. }
  1214. int rt_hw_tiva_eth_init(void)
  1215. {
  1216. rt_err_t result;
  1217. /* Clock GPIO and etc */
  1218. tiva_eth_lowlevel_init();
  1219. tiva_eth_mac_addr_init();
  1220. /* init rt-thread device interface */
  1221. eth_dev->parent.parent.init = eth_dev_init;
  1222. eth_dev->parent.parent.open = eth_dev_open;
  1223. eth_dev->parent.parent.close = eth_dev_close;
  1224. eth_dev->parent.parent.read = eth_dev_read;
  1225. eth_dev->parent.parent.write = eth_dev_write;
  1226. eth_dev->parent.parent.control = eth_dev_control;
  1227. eth_dev->parent.eth_rx = eth_dev_rx;
  1228. eth_dev->parent.eth_tx = eth_dev_tx;
  1229. result = rt_mb_init(&eth_rx_pbuf_mb, "epbuf",
  1230. &rx_pbuf_mb_pool[0], sizeof(rx_pbuf_mb_pool)/4,
  1231. RT_IPC_FLAG_FIFO);
  1232. RT_ASSERT(result == RT_EOK);
  1233. eth_dev->rx_pbuf_mb = &eth_rx_pbuf_mb;
  1234. result = eth_device_init(&(eth_dev->parent), "e0");
  1235. return result;
  1236. }
  1237. // eth_device_init using malloc
  1238. // We use INIT_COMPONENT_EXPORT insted of INIT_BOARD_EXPORT
  1239. INIT_COMPONENT_EXPORT(rt_hw_tiva_eth_init);
  1240. #if 0
  1241. #ifdef RT_USING_FINSH
  1242. #include "finsh.h"
  1243. void PHY_Read(uint8_t addr)
  1244. {
  1245. uint16_t data = EMACPHYRead(EMAC0_BASE, PHY_PHYS_ADDR, addr);
  1246. rt_kprintf("R PHY_REG[0x%02X] = 0x%04X\n", addr, data);
  1247. }
  1248. FINSH_FUNCTION_EXPORT(PHY_Read, (add));
  1249. void PHY_Write(uint8_t addr , uint16_t data)
  1250. {
  1251. EMACPHYWrite(EMAC0_BASE, PHY_PHYS_ADDR, addr, data);
  1252. rt_kprintf("W PHY_REG[0x%02X] = 0x%04X\n", addr, data);
  1253. }
  1254. FINSH_FUNCTION_EXPORT(PHY_Write, (add, data));
  1255. void PHY_SetAdd(uint8_t addr0, uint8_t addr1, uint8_t addr2,
  1256. uint8_t addr3, uint8_t addr4, uint8_t addr5)
  1257. {
  1258. uint32_t ulUser[2];
  1259. ulUser[0] = (((addr2<<8)|addr1)<<8)|addr0;
  1260. ulUser[1] = (((addr5<<8)|addr4)<<8)|addr3;
  1261. MAP_FlashUserSet(ulUser[0], ulUser[1]);
  1262. MAP_FlashUserSave();
  1263. rt_kprintf("Save to EEPROM. please reboot.");
  1264. }
  1265. FINSH_FUNCTION_EXPORT(PHY_SetAdd, (add0-add5));
  1266. #endif //RT_USING_FINSH
  1267. #endif