drv_eth.c 46 KB

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