drv_eth.c 44 KB

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