drv_eth.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  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. * 2021-03-09 Carl the first version
  9. */
  10. #include "board.h"
  11. #include <netif/ethernetif.h>
  12. #include "lwipopts.h"
  13. #include "ft_parameters.h"
  14. #include "ft_gmac.h"
  15. #include "ft_cache.h"
  16. #include "ft_gmac_hw.h"
  17. #include "ft_status.h"
  18. #include "ft_io.h"
  19. #include "drv_eth.h"
  20. #ifdef BSP_USING_GMAC
  21. #define LOG_TAG "drv.gmac"
  22. #include <drv_log.h>
  23. #define MAX_ADDR_LEN 6
  24. #define LINK_THREAD_STACK_LENGTH 0x400
  25. struct drv_gmac
  26. {
  27. struct eth_device parent; /* inherit from ethernet device */
  28. Ft_Gmac_t Gmac; /* Gmac driver */
  29. #ifndef PHY_USING_INTERRUPT_MODE
  30. rt_timer_t poll_link_timer;
  31. #endif
  32. rt_uint8_t *rx_buffer; /* Buffer for RxDesc */
  33. rt_uint8_t *tx_buffer; /* Buffer for TxDesc */
  34. uint32_t eth_speed; /* eth_speed */
  35. uint32_t eth_mode; /* ETH_Duplex_Mode */
  36. rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* MAC address */
  37. struct rt_event link_event;
  38. struct rt_thread _link_thread;
  39. rt_uint8_t _link_thread_stack[LINK_THREAD_STACK_LENGTH];
  40. rt_thread_t _debug_tid;
  41. };
  42. static void rt_ft2004_status_check(void *Args, u32 MacPhyStatus);
  43. //
  44. #if defined(RAW_DATA_PRINT)
  45. #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
  46. #define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
  47. static void dump_hex(const rt_uint8_t *ptr, rt_size_t buflen)
  48. {
  49. unsigned char *buf = (unsigned char *)ptr;
  50. int i, j;
  51. for (i = 0; i < buflen; i += 16)
  52. {
  53. rt_kprintf("%08X: ", i);
  54. for (j = 0; j < 16; j++)
  55. if (i + j < buflen)
  56. rt_kprintf("%02X ", buf[i + j]);
  57. else
  58. rt_kprintf(" ");
  59. rt_kprintf(" ");
  60. for (j = 0; j < 16; j++)
  61. if (i + j < buflen)
  62. rt_kprintf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
  63. rt_kprintf("\n");
  64. }
  65. }
  66. #endif
  67. #endif
  68. /**
  69. * @name: rt_gmacmem_create
  70. * @msg: Initialize the Gmac TX/Rx Describe Memory 。
  71. * @param {*}
  72. * @return {*}
  73. */
  74. static void rt_gmacmem_create(struct drv_gmac *pOsGmac)
  75. {
  76. pOsGmac->rx_buffer = rt_calloc(1, RX_DESCNUM * GMAC_MAX_PACKET_SIZE);
  77. if (pOsGmac->rx_buffer == NULL)
  78. {
  79. LOG_E("rx_buffer Malloc is error ");
  80. RT_ASSERT(0)
  81. }
  82. pOsGmac->tx_buffer = rt_calloc(1, TX_DESCNUM * GMAC_MAX_PACKET_SIZE);
  83. if (pOsGmac->tx_buffer == NULL)
  84. {
  85. LOG_E("tx_buffer Malloc is error ");
  86. RT_ASSERT(0)
  87. }
  88. pOsGmac->Gmac.TxDesc = rt_calloc(1, TX_DESCNUM * sizeof(FGmac_DmaDesc_t));
  89. if (pOsGmac->Gmac.TxDesc == NULL)
  90. {
  91. LOG_E("TxDesc Malloc is error ");
  92. RT_ASSERT(0)
  93. }
  94. pOsGmac->Gmac.RxDesc = rt_calloc(1, RX_DESCNUM * sizeof(FGmac_DmaDesc_t) + 128);
  95. if (pOsGmac->Gmac.RxDesc == NULL)
  96. {
  97. LOG_E("RxDesc Malloc is error ");
  98. RT_ASSERT(0)
  99. }
  100. #define ROUND_UP(x, align) (((long)(x) + ((long)align - 1)) & \
  101. ~((long)align - 1))
  102. pOsGmac->Gmac.RxDesc = (FGmac_DmaDesc_t *)ROUND_UP(pOsGmac->Gmac.RxDesc, 128);
  103. LOG_D("RxDesc fit after addr %x ", pOsGmac->Gmac.RxDesc);
  104. }
  105. static void rt_gmacmem_free(struct drv_gmac *pOsGmac)
  106. {
  107. if (pOsGmac->rx_buffer)
  108. {
  109. rt_free(pOsGmac->rx_buffer);
  110. }
  111. if (pOsGmac->tx_buffer)
  112. {
  113. rt_free(pOsGmac->tx_buffer);
  114. }
  115. if (pOsGmac->Gmac.RxDesc)
  116. {
  117. rt_free(pOsGmac->Gmac.RxDesc);
  118. }
  119. if (pOsGmac->Gmac.TxDesc)
  120. {
  121. rt_free(pOsGmac->Gmac.TxDesc);
  122. }
  123. }
  124. static void rt_hw_gmac_isr(int irqno, void *param)
  125. {
  126. FGmac_IntrHandler(param);
  127. }
  128. static void rt_hw_gmac_recv_isr(void *Args)
  129. {
  130. struct drv_gmac *pOsMac;
  131. rt_err_t result = 0;
  132. if (RT_NULL == Args)
  133. {
  134. LOG_E("Args is NULL");
  135. return;
  136. }
  137. pOsMac = (struct drv_gmac *)Args;
  138. result = eth_device_ready(&(pOsMac->parent));
  139. if (result != RT_EOK)
  140. {
  141. LOG_I("RxCpltCallback err = %d", result);
  142. }
  143. }
  144. static rt_err_t
  145. rt_ft2004_gmac_start(struct drv_gmac *pOsMac)
  146. {
  147. Ft_Gmac_t *pGmac;
  148. pGmac = &pOsMac->Gmac;
  149. if (FST_SUCCESS != Ft_Gmac_HwInitialize(pGmac))
  150. {
  151. return -RT_ERROR;
  152. }
  153. FGmac_SetHandler(pGmac, FT_GMAC_RX_COMPLETE_CB_ID, rt_hw_gmac_recv_isr, pOsMac);
  154. FGmac_SetHandler(pGmac, FT_GMAC_MAC_PHY_STATUS_CB_ID, rt_ft2004_status_check, pOsMac);
  155. /* Initialize Rx Description list : ring Mode */
  156. FGmac_DmaRxDescRingInit(pGmac, pGmac->RxDesc, pOsMac->rx_buffer, GMAC_MAX_PACKET_SIZE, RX_DESCNUM);
  157. /* Initialize Tx Description list : ring Mode */
  158. FGmac_DmaTxDescRingInit(pGmac, pGmac->TxDesc, pOsMac->tx_buffer, GMAC_MAX_PACKET_SIZE, TX_DESCNUM);
  159. Ft_Gmac_Start(pGmac);
  160. /* Gmac interrupt init */
  161. rt_hw_interrupt_install(pGmac->Config.IRQ_NUM, rt_hw_gmac_isr, pGmac, "Gmac");
  162. rt_hw_interrupt_umask(pGmac->Config.IRQ_NUM);
  163. return RT_EOK;
  164. }
  165. void rt_ft2004_gmac_stop(struct drv_gmac *pOsMac)
  166. {
  167. Ft_Gmac_t *pGmac;
  168. pGmac = &pOsMac->Gmac;
  169. Ft_Gmac_Stop(pGmac);
  170. }
  171. /* GMAC initialization function */
  172. static rt_err_t rt_ft2004_gmac_init(rt_device_t dev)
  173. {
  174. struct drv_gmac *pOsMac;
  175. struct eth_device *pGmacParent;
  176. FGmac_Config_t *pConfig;
  177. pGmacParent = rt_container_of(dev, struct eth_device, parent);
  178. if (NULL == pGmacParent)
  179. {
  180. return -RT_ENOMEM;
  181. }
  182. pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
  183. if (NULL == pOsMac)
  184. {
  185. return -RT_ENOMEM;
  186. }
  187. pConfig = Ft_Gmac_LookupConfig(pOsMac->Gmac.Config.InstanceId);
  188. if (NULL == pConfig)
  189. {
  190. return -RT_ENOMEM;
  191. }
  192. Ft_Gmac_UseDefaultMacAddr(&pOsMac->Gmac, pOsMac->Gmac.Config.MacAddr);
  193. if (FST_SUCCESS != Ft_GmacCfgInitialize(&pOsMac->Gmac, pConfig))
  194. {
  195. return -RT_ERROR;
  196. }
  197. return rt_ft2004_gmac_start(pOsMac);
  198. }
  199. static rt_err_t rt_ft2004_gmac_open(rt_device_t dev, rt_uint16_t oflag)
  200. {
  201. LOG_D("gmac open");
  202. return RT_EOK;
  203. }
  204. static rt_err_t rt_ft2004_gmac_close(rt_device_t dev)
  205. {
  206. LOG_D("gmac close");
  207. return RT_EOK;
  208. }
  209. static rt_size_t rt_ft2004_gmac_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  210. {
  211. LOG_D("gmac read");
  212. rt_set_errno(-RT_ENOSYS);
  213. return 0;
  214. }
  215. static rt_size_t rt_ft2004_gmac_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  216. {
  217. LOG_D("gmac write");
  218. rt_set_errno(-RT_ENOSYS);
  219. return 0;
  220. }
  221. static rt_err_t rt_ft2004_gmac_control(rt_device_t dev, int cmd, void *args)
  222. {
  223. struct drv_gmac *pOsMac;
  224. struct eth_device *pGmacParent;
  225. pGmacParent = rt_container_of(dev, struct eth_device, parent);
  226. if (NULL == pGmacParent)
  227. {
  228. return -RT_ENOMEM;
  229. }
  230. pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
  231. if (NULL == pOsMac)
  232. {
  233. return -RT_ENOMEM;
  234. }
  235. switch (cmd)
  236. {
  237. case NIOCTL_GADDR:
  238. /* get mac address */
  239. if (args)
  240. rt_memcpy(args, pOsMac->dev_addr, 6);
  241. else
  242. return -RT_ERROR;
  243. break;
  244. default:
  245. break;
  246. }
  247. return RT_EOK;
  248. }
  249. rt_err_t rt_ft2004_gmac_tx(rt_device_t dev, struct pbuf *p)
  250. {
  251. struct drv_gmac *pOsMac;
  252. Ft_Gmac_t *pGmac;
  253. struct eth_device *pGmacParent;
  254. err_t errval;
  255. struct pbuf *q;
  256. u8 *Buffer = NULL;
  257. volatile FGmac_DmaDesc_t *DmaTxDesc;
  258. u32 FrameLength = 0;
  259. u32 BufferOffset = 0;
  260. u32 BytesLeftToCopy = 0;
  261. u32 PayLoadOffset = 0;
  262. pGmacParent = rt_container_of(dev, struct eth_device, parent);
  263. if (NULL == pGmacParent)
  264. {
  265. return -RT_ENOMEM;
  266. }
  267. pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
  268. if (NULL == pOsMac)
  269. {
  270. return -RT_ENOMEM;
  271. }
  272. pGmac = &pOsMac->Gmac;
  273. DmaTxDesc = &pGmac->TxDesc[pGmac->TxDescRingData.DescBufIndex];
  274. Buffer = (u8 *)DmaTxDesc->Buffer1Addr;
  275. if (Buffer == NULL)
  276. {
  277. LOG_E("Buffer is NULL \r\n");
  278. RT_ASSERT(0)
  279. }
  280. #if RT_LWIP_ETH_PAD_SIZE
  281. pbuf_header(p, -RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
  282. #endif
  283. for (q = p; q != NULL; q = q->next)
  284. {
  285. /* Is this buffer available? If not, goto error */
  286. if ((DmaTxDesc->Status & DMA_TDES0_OWN) != 0)
  287. {
  288. errval = ERR_USE;
  289. LOG_E("error errval = ERR_USE; \r\n");
  290. goto error;
  291. }
  292. /* Get bytes in current lwIP buffer */
  293. BytesLeftToCopy = q->len;
  294. PayLoadOffset = 0;
  295. /* Check if the length of data to copy is bigger than Tx buffer size*/
  296. while ((BytesLeftToCopy + BufferOffset) > GMAC_MAX_PACKET_SIZE)
  297. {
  298. /* Copy data to Tx buffer*/
  299. memcpy((u8 *)((u8 *)Buffer + BufferOffset), (u8 *)((u8 *)q->payload + PayLoadOffset), (GMAC_MAX_PACKET_SIZE - BufferOffset));
  300. FCache_cpuDcacheClean((rt_uint32_t *)DmaTxDesc->Buffer1Addr, GMAC_MAX_PACKET_SIZE);
  301. GMAC_INC_DESC(pGmac->TxDescRingData.DescBufIndex, pGmac->TxDescRingData.DescMaxNumber);
  302. /* Point to next descriptor */
  303. DmaTxDesc = &pGmac->TxDesc[pGmac->TxDescRingData.DescBufIndex];
  304. /* Check if the Bufferis available */
  305. if ((DmaTxDesc->Status & DMA_TDES0_OWN) != (u32)0)
  306. {
  307. errval = ERR_USE;
  308. LOG_E("Check if the Bufferis available \r\n");
  309. goto error;
  310. }
  311. Buffer = (u8 *)(DmaTxDesc->Buffer1Addr);
  312. BytesLeftToCopy = BytesLeftToCopy - (GMAC_MAX_PACKET_SIZE - BufferOffset);
  313. PayLoadOffset = PayLoadOffset + (GMAC_MAX_PACKET_SIZE - BufferOffset);
  314. FrameLength = FrameLength + (GMAC_MAX_PACKET_SIZE - BufferOffset);
  315. BufferOffset = 0;
  316. if (Buffer == NULL)
  317. {
  318. LOG_E(" error Buffer is 0 \r\n");
  319. RT_ASSERT(0)
  320. }
  321. }
  322. /* Copy the remaining bytes */
  323. memcpy((u8 *)((u8 *)Buffer + BufferOffset), (u8 *)((u8 *)q->payload + PayLoadOffset), BytesLeftToCopy);
  324. BufferOffset = BufferOffset + BytesLeftToCopy;
  325. FrameLength = FrameLength + BytesLeftToCopy;
  326. }
  327. /* 指向下一个位置 */
  328. FCache_cpuDcacheClean((rt_uint32_t *)DmaTxDesc->Buffer1Addr, GMAC_MAX_PACKET_SIZE);
  329. GMAC_INC_DESC(pGmac->TxDescRingData.DescBufIndex, pGmac->TxDescRingData.DescMaxNumber);
  330. #if RT_LWIP_ETH_PAD_SIZE
  331. pbuf_header(p, RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
  332. #endif
  333. #ifdef ETH_TX_DUMP
  334. dump_hex(Buffer, p->tot_len);
  335. #endif
  336. FGmac_TransmitframeRingPoll(pGmac, FrameLength);
  337. error:
  338. FGmac_SetTransmitUnderflow(pGmac);
  339. return errval;
  340. }
  341. struct pbuf *rt_ft2004_gmac_rx(rt_device_t dev)
  342. {
  343. struct drv_gmac *pOsMac;
  344. Ft_Gmac_t *pGmac;
  345. struct eth_device *pGmacParent;
  346. struct pbuf *p = NULL;
  347. struct pbuf *q = NULL;
  348. u16 Length = 0;
  349. u8 *Buffer;
  350. volatile FGmac_DmaDesc_t *DmaRxDesc;
  351. u32 BufferOffset = 0;
  352. u32 PayLoadOffset = 0;
  353. u32 BytesLeftToCopy = 0;
  354. u32 DescBufIndex; /* For Current Desc buffer buf position */
  355. pGmacParent = rt_container_of(dev, struct eth_device, parent);
  356. if (NULL == pGmacParent)
  357. {
  358. return RT_NULL;
  359. }
  360. pOsMac = rt_container_of(pGmacParent, struct drv_gmac, parent);
  361. if (NULL == pOsMac)
  362. {
  363. return RT_NULL;
  364. }
  365. pGmac = &pOsMac->Gmac;
  366. /* get received frame */
  367. if (FST_SUCCESS != FGmac_RingGetReceivedFrame_IT(pGmac))
  368. {
  369. return NULL;
  370. }
  371. DescBufIndex = pGmac->RxDescRingData.DescBufIndex;
  372. Length = (pGmac->RxDesc[DescBufIndex].Status & DMA_RDES0_FRAME_LEN_MASK) >> DMA_RDES0_FRAME_LEN_SHIFT;
  373. Buffer = (u8 *)pGmac->RxDesc[DescBufIndex].Buffer1Addr;
  374. #if RT_LWIP_ETH_PAD_SIZE
  375. Length += RT_LWIP_ETH_PAD_SIZE; /* allow room for Ethernet padding */
  376. #endif
  377. if (Length > 0)
  378. {
  379. /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
  380. p = pbuf_alloc(PBUF_RAW, Length, PBUF_POOL);
  381. }
  382. #ifdef ETH_RX_DUMP
  383. dump_hex(Buffer, (u32)Length);
  384. #endif
  385. if (p != NULL)
  386. {
  387. #if RT_LWIP_ETH_PAD_SIZE
  388. pbuf_header(p, -RT_LWIP_ETH_PAD_SIZE); /* drop the padding word */
  389. #endif
  390. DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
  391. BufferOffset = 0;
  392. for (q = p; q != NULL; q = q->next)
  393. {
  394. BytesLeftToCopy = q->len;
  395. PayLoadOffset = 0;
  396. /* Check if the length of bytes to copy in current pbuf is bigger than Rx buffer size*/
  397. while ((BytesLeftToCopy + BufferOffset) > GMAC_MAX_PACKET_SIZE)
  398. {
  399. /* Copy data to pbuf */
  400. memcpy((u8 *)((u8 *)q->payload + PayLoadOffset), (u8 *)((u8 *)Buffer + BufferOffset), (GMAC_MAX_PACKET_SIZE - BufferOffset));
  401. /* Point to next descriptor */
  402. GMAC_INC_DESC(DescBufIndex, pGmac->RxDescRingData.DescMaxNumber);
  403. if (DescBufIndex == pGmac->RxDescRingData.DescIndex)
  404. {
  405. break;
  406. }
  407. DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
  408. Buffer = (u8 *)(DmaRxDesc->Buffer1Addr);
  409. BytesLeftToCopy = BytesLeftToCopy - (GMAC_MAX_PACKET_SIZE - BufferOffset);
  410. PayLoadOffset = PayLoadOffset + (GMAC_MAX_PACKET_SIZE - BufferOffset);
  411. BufferOffset = 0;
  412. }
  413. /* Copy remaining data in pbuf */
  414. memcpy((u8 *)((u8 *)q->payload + PayLoadOffset), (u8 *)((u8 *)Buffer + BufferOffset), BytesLeftToCopy);
  415. BufferOffset = BufferOffset + BytesLeftToCopy;
  416. }
  417. #if RT_LWIP_ETH_PAD_SIZE
  418. pbuf_header(p, RT_LWIP_ETH_PAD_SIZE); /* reclaim the padding word */
  419. #endif
  420. }
  421. /* Release descriptors to DMA */
  422. /* Point to first descriptor */
  423. DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
  424. /* Set Own bit in Rx descriptors: gives the buffers back to DMA */
  425. for (DescBufIndex = pGmac->RxDescRingData.DescBufIndex; DescBufIndex != pGmac->RxDescRingData.DescIndex; GMAC_INC_DESC(DescBufIndex, pGmac->RxDescRingData.DescMaxNumber))
  426. {
  427. FCache_cpuDcacheInvalidate((rt_uint32_t *)pGmac->RxDesc[DescBufIndex].Buffer1Addr, GMAC_MAX_PACKET_SIZE);
  428. DmaRxDesc->Status |= DMA_RDES0_OWN;
  429. DmaRxDesc = &pGmac->RxDesc[DescBufIndex];
  430. }
  431. /* Sync index */
  432. pGmac->RxDescRingData.DescBufIndex = pGmac->RxDescRingData.DescIndex;
  433. FGmac_ResumeTransmissionReception(pGmac);
  434. return p;
  435. }
  436. static void rt_ft2004_status_check(void *Args, u32 MacPhyStatus)
  437. {
  438. struct drv_gmac *pOsMac;
  439. pOsMac = (struct drv_gmac *)Args;
  440. if (MacPhyStatus & 0x8)
  441. {
  442. rt_event_send(&pOsMac->link_event, FT_NETIF_LINKUP);
  443. }
  444. else
  445. {
  446. rt_event_send(&pOsMac->link_event, FT_NETIF_DOWN);
  447. }
  448. }
  449. static void ethernet_link_thread(void *Args)
  450. {
  451. struct drv_gmac *pOsMac;
  452. rt_uint32_t status;
  453. u32 LastStatus = FT_NETIF_DOWN;
  454. u32 Flg;
  455. if (RT_NULL == Args)
  456. {
  457. return;
  458. }
  459. pOsMac = (struct drv_gmac *)Args;
  460. while (1)
  461. {
  462. status = 0;
  463. if (rt_event_recv(&pOsMac->link_event, FT_NETIF_LINKUP | FT_NETIF_DOWN, RT_EVENT_FLAG_CLEAR | RT_EVENT_FLAG_OR,
  464. RT_WAITING_FOREVER, &status) != RT_EOK)
  465. {
  466. LOG_E("wait completed timeout");
  467. continue;
  468. }
  469. if (status & FT_NETIF_DOWN)
  470. {
  471. eth_device_linkchange(&pOsMac->parent, RT_FALSE);
  472. LastStatus = FT_NETIF_DOWN;
  473. }
  474. else if (status & FT_NETIF_LINKUP)
  475. {
  476. Flg = (LastStatus == FT_NETIF_LINKUP) ? 0 : 1;
  477. LastStatus = FT_NETIF_LINKUP;
  478. }
  479. else
  480. {
  481. LOG_I(" EventGroup is error \r\n");
  482. RT_ASSERT(0)
  483. }
  484. if (Flg)
  485. {
  486. Flg = 0;
  487. // eth_device_linkchange(&pOsMac->parent, RT_FALSE);
  488. LOG_I(" Start Linkup \r\n");
  489. rt_ft2004_gmac_stop(pOsMac);
  490. rt_ft2004_gmac_start(pOsMac);
  491. LOG_I(" HardWare is ok \r\n");
  492. if (LastStatus == FT_NETIF_LINKUP)
  493. {
  494. rt_thread_mdelay(5000);
  495. eth_device_linkchange(&pOsMac->parent, RT_TRUE);
  496. }
  497. }
  498. }
  499. }
  500. #ifdef BSP_USING_GMAC0
  501. struct drv_gmac os_drv_gmac0;
  502. static char *os_drv_gmac0_name = "gmac0";
  503. #endif
  504. #ifdef BSP_USING_GMAC1
  505. struct drv_gmac os_drv_gmac1;
  506. static char *os_drv_gmac1_name = "gmac1";
  507. #endif
  508. static int rt_hw_gmac_init(struct drv_gmac *pOsMac, const char *name)
  509. {
  510. rt_err_t state = RT_EOK;
  511. // rt_thread_t tid;
  512. rt_gmacmem_free(pOsMac);
  513. rt_gmacmem_create(pOsMac);
  514. pOsMac->eth_speed = GMAC_SPEED_1000M;
  515. pOsMac->eth_mode = GMAC_MODE_FULLDUPLEX;
  516. pOsMac->parent.parent.init = rt_ft2004_gmac_init;
  517. pOsMac->parent.parent.open = rt_ft2004_gmac_open;
  518. pOsMac->parent.parent.close = rt_ft2004_gmac_close;
  519. pOsMac->parent.parent.read = rt_ft2004_gmac_read;
  520. pOsMac->parent.parent.write = rt_ft2004_gmac_write;
  521. pOsMac->parent.parent.control = rt_ft2004_gmac_control;
  522. pOsMac->parent.parent.user_data = RT_NULL;
  523. pOsMac->parent.eth_rx = rt_ft2004_gmac_rx;
  524. pOsMac->parent.eth_tx = rt_ft2004_gmac_tx;
  525. Ft_Gmac_UseDefaultMacAddr(&pOsMac->Gmac, pOsMac->dev_addr);
  526. state = rt_event_init(&pOsMac->link_event, name, RT_IPC_FLAG_FIFO);
  527. LOG_I("rt_event_init is ok \r\n");
  528. if (RT_EOK != state)
  529. {
  530. rt_kprintf("init gmac0 event failed.\n");
  531. return -RT_ERROR;
  532. }
  533. /* register eth device */
  534. state = eth_device_init(&(pOsMac->parent), name);
  535. if (RT_EOK != state)
  536. {
  537. LOG_E("gmac device init faild: %d", state);
  538. return -RT_ERROR;
  539. }
  540. state = rt_thread_init(&pOsMac->_link_thread,
  541. name,
  542. ethernet_link_thread,
  543. pOsMac,
  544. &pOsMac->_link_thread_stack[0],
  545. sizeof(pOsMac->_link_thread_stack),
  546. 10, 2);
  547. if (RT_EOK == state)
  548. {
  549. rt_thread_startup(&pOsMac->_link_thread);
  550. }
  551. else
  552. {
  553. LOG_E("rt_thread_init is error");
  554. return -RT_ERROR;
  555. }
  556. return RT_EOK;
  557. }
  558. static int rt_hw_ft2004_eth_init(void)
  559. {
  560. rt_err_t state = RT_EOK;
  561. #ifdef BSP_USING_GMAC0
  562. os_drv_gmac0.Gmac.Config.InstanceId = 0;
  563. state = rt_hw_gmac_init(&os_drv_gmac0, os_drv_gmac0_name);
  564. if (RT_EOK != state)
  565. {
  566. goto __exit;
  567. }
  568. #endif
  569. #ifdef BSP_USING_GMAC1
  570. os_drv_gmac1.Gmac.Config.InstanceId = 1;
  571. state = rt_hw_gmac_init(&os_drv_gmac1, os_drv_gmac1_name);
  572. if (RT_EOK != state)
  573. {
  574. goto __exit;
  575. }
  576. #endif
  577. __exit:
  578. return state;
  579. }
  580. INIT_DEVICE_EXPORT(rt_hw_ft2004_eth_init);
  581. #endif