xadapter.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. * Copyright (C) 2007 - 2019 Xilinx, Inc.
  3. * Copyright (C) 2021 WangHuachen.
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice,
  10. * this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. * 3. The name of the author may not be used to endorse or promote products
  15. * derived from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
  20. * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  21. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  22. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  25. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
  26. * OF SUCH DAMAGE.
  27. *
  28. * This file is part of the lwIP TCP/IP stack.
  29. *
  30. */
  31. #include "lwipopts.h"
  32. #include "xlwipconfig.h"
  33. #include "xemac_ieee_reg.h"
  34. #if !NO_SYS
  35. #ifdef OS_IS_XILKERNEL
  36. #include "xmk.h"
  37. #include "sys/process.h"
  38. #endif
  39. #endif
  40. #include "lwip/mem.h"
  41. #include "lwip/stats.h"
  42. #include "lwip/sys.h"
  43. #include "lwip/ip.h"
  44. #include "lwip/tcp.h"
  45. #include "lwip/udp.h"
  46. #include "lwip/priv/tcp_priv.h"
  47. #include "netif/etharp.h"
  48. #include "netif/xadapter.h"
  49. #ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
  50. #include "netif/xemacliteif.h"
  51. #endif
  52. #ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
  53. #include "netif/xaxiemacif.h"
  54. #endif
  55. #ifdef XLWIP_CONFIG_INCLUDE_GEM
  56. #include "netif/xemacpsif.h"
  57. #endif
  58. #if !NO_SYS
  59. #include "lwip/tcpip.h"
  60. #endif
  61. #ifdef OS_IS_FREERTOS
  62. #define THREAD_STACKSIZE 256
  63. #define LINK_DETECT_THREAD_INTERVAL 1000 /* one second */
  64. void link_detect_thread(void *p);
  65. #endif
  66. /* global lwip debug variable used for debugging */
  67. int lwip_runtime_debug = 0;
  68. enum ethernet_link_status eth_link_status = ETH_LINK_UNDEFINED;
  69. u32_t phyaddrforemac;
  70. void
  71. lwip_raw_init()
  72. {
  73. ip_init(); /* Doesn't do much, it should be called to handle future changes. */
  74. #if LWIP_UDP
  75. udp_init(); /* Clears the UDP PCB list. */
  76. #endif
  77. #if LWIP_TCP
  78. tcp_init(); /* Clears the TCP PCB list and clears some internal TCP timers. */
  79. /* Note: you must call tcp_fasttmr() and tcp_slowtmr() at the */
  80. /* predefined regular intervals after this initialization. */
  81. #endif
  82. }
  83. static enum xemac_types
  84. find_mac_type(unsigned base)
  85. {
  86. int i;
  87. for (i = 0; i < xtopology_n_emacs; i++) {
  88. if (xtopology[i].emac_baseaddr == base)
  89. return xtopology[i].emac_type;
  90. }
  91. return xemac_type_unknown;
  92. }
  93. int
  94. xtopology_find_index(unsigned base)
  95. {
  96. int i;
  97. for (i = 0; i < xtopology_n_emacs; i++) {
  98. if (xtopology[i].emac_baseaddr == base)
  99. return i;
  100. }
  101. return -1;
  102. }
  103. /*
  104. * xemac_add: this is a wrapper around lwIP's netif_add function.
  105. * The objective is to provide portability between the different Xilinx MAC's
  106. * This function can be used to add both xps_ethernetlite and xps_ll_temac
  107. * based interfaces
  108. */
  109. struct netif *
  110. xemac_add(struct netif *netif,
  111. ip_addr_t *ipaddr, ip_addr_t *netmask, ip_addr_t *gw,
  112. unsigned char *mac_ethernet_address,
  113. unsigned mac_baseaddr)
  114. {
  115. int i;
  116. #ifdef OS_IS_FREERTOS
  117. /* Start thread to detect link periodically for Hot Plug autodetect */
  118. sys_thread_new("link_detect_thread", link_detect_thread, netif,
  119. THREAD_STACKSIZE, tskIDLE_PRIORITY);
  120. #endif
  121. /* set mac address */
  122. netif->hwaddr_len = 6;
  123. for (i = 0; i < 6; i++)
  124. netif->hwaddr[i] = mac_ethernet_address[i];
  125. /* initialize based on MAC type */
  126. switch (find_mac_type(mac_baseaddr)) {
  127. case xemac_type_xps_emaclite:
  128. #ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
  129. return netif_add(netif, ipaddr, netmask, gw,
  130. (void*)(UINTPTR)mac_baseaddr,
  131. xemacliteif_init,
  132. #if NO_SYS
  133. ethernet_input
  134. #else
  135. tcpip_input
  136. #endif
  137. );
  138. #else
  139. return NULL;
  140. #endif
  141. case xemac_type_axi_ethernet:
  142. #ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
  143. return netif_add(netif, ipaddr, netmask, gw,
  144. (void*)(UINTPTR)mac_baseaddr,
  145. xaxiemacif_init,
  146. #if NO_SYS
  147. ethernet_input
  148. #else
  149. tcpip_input
  150. #endif
  151. );
  152. #else
  153. return NULL;
  154. #endif
  155. #if defined (__arm__) || defined (__aarch64__)
  156. case xemac_type_emacps:
  157. #ifdef XLWIP_CONFIG_INCLUDE_GEM
  158. return netif_add(netif, ipaddr, netmask, gw,
  159. (void*)(UINTPTR)mac_baseaddr,
  160. xemacpsif_init,
  161. #if NO_SYS
  162. ethernet_input
  163. #else
  164. tcpip_input
  165. #endif
  166. );
  167. #endif
  168. #endif
  169. default:
  170. xil_printf("unable to determine type of EMAC with baseaddress 0x%08x\r\n",
  171. mac_baseaddr);
  172. return NULL;
  173. }
  174. }
  175. int
  176. xemacif_input(struct netif *netif)
  177. {
  178. struct xemac_s *emac = (struct xemac_s *)netif->state;
  179. int n_packets = 0;
  180. switch (emac->type) {
  181. case xemac_type_xps_emaclite:
  182. #ifdef XLWIP_CONFIG_INCLUDE_EMACLITE
  183. n_packets = xemacliteif_input(netif);
  184. break;
  185. #else
  186. // print("incorrect configuration: xps_ethernetlite drivers not present?");
  187. while(1);
  188. return 0;
  189. #endif
  190. case xemac_type_axi_ethernet:
  191. #ifdef XLWIP_CONFIG_INCLUDE_AXI_ETHERNET
  192. n_packets = xaxiemacif_input(netif);
  193. break;
  194. #else
  195. // print("incorrect configuration: axi_ethernet drivers not present?");
  196. while(1);
  197. return 0;
  198. #endif
  199. #if defined (__arm__) || defined (__aarch64__)
  200. case xemac_type_emacps:
  201. #ifdef XLWIP_CONFIG_INCLUDE_GEM
  202. n_packets = xemacpsif_input(netif);
  203. break;
  204. #else
  205. xil_printf("incorrect configuration: ps7_ethernet drivers not present?\r\n");
  206. while(1);
  207. return 0;
  208. #endif
  209. #endif
  210. default:
  211. // print("incorrect configuration: unknown temac type");
  212. while(1);
  213. return 0;
  214. }
  215. return n_packets;
  216. }
  217. #if defined(XLWIP_CONFIG_INCLUDE_GEM)
  218. u32_t phy_link_detect(XEmacPs *xemacp, u32_t phy_addr)
  219. {
  220. u16_t status;
  221. /* Read Phy Status register twice to get the confirmation of the current
  222. * link status.
  223. */
  224. XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  225. XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  226. if (status & IEEE_STAT_LINK_STATUS)
  227. return 1;
  228. return 0;
  229. }
  230. #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
  231. static u32_t phy_link_detect(XAxiEthernet *xemacp, u32_t phy_addr)
  232. {
  233. u16_t status;
  234. /* Read Phy Status register twice to get the confirmation of the current
  235. * link status.
  236. */
  237. XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  238. XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  239. if (status & IEEE_STAT_LINK_STATUS)
  240. return 1;
  241. return 0;
  242. }
  243. #elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
  244. static u32_t phy_link_detect(XEmacLite *xemacp, u32_t phy_addr)
  245. {
  246. u16_t status;
  247. /* Read Phy Status register twice to get the confirmation of the current
  248. * link status.
  249. */
  250. XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  251. XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  252. if (status & IEEE_STAT_LINK_STATUS)
  253. return 1;
  254. return 0;
  255. }
  256. #endif
  257. #if defined(XLWIP_CONFIG_INCLUDE_GEM)
  258. u32_t phy_autoneg_status(XEmacPs *xemacp, u32_t phy_addr)
  259. {
  260. u16_t status;
  261. /* Read Phy Status register twice to get the confirmation of the current
  262. * link status.
  263. */
  264. XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  265. XEmacPs_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  266. if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
  267. return 1;
  268. return 0;
  269. }
  270. #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
  271. static u32_t phy_autoneg_status(XAxiEthernet *xemacp, u32_t phy_addr)
  272. {
  273. u16_t status;
  274. /* Read Phy Status register twice to get the confirmation of the current
  275. * link status.
  276. */
  277. XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  278. XAxiEthernet_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  279. if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
  280. return 1;
  281. return 0;
  282. }
  283. #elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
  284. static u32_t phy_autoneg_status(XEmacLite *xemacp, u32_t phy_addr)
  285. {
  286. u16_t status;
  287. /* Read Phy Status register twice to get the confirmation of the current
  288. * link status.
  289. */
  290. XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  291. XEmacLite_PhyRead(xemacp, phy_addr, IEEE_STATUS_REG_OFFSET, &status);
  292. if (status & IEEE_STAT_AUTONEGOTIATE_COMPLETE)
  293. return 1;
  294. return 0;
  295. }
  296. #endif
  297. void eth_link_detect(struct netif *netif)
  298. {
  299. u32_t link_speed, phy_link_status;
  300. struct xemac_s *xemac = (struct xemac_s *)(netif->state);
  301. #if defined(XLWIP_CONFIG_INCLUDE_GEM)
  302. xemacpsif_s *xemacs = (xemacpsif_s *)(xemac->state);
  303. XEmacPs *xemacp = &xemacs->emacps;
  304. #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
  305. xaxiemacif_s *xemacs = (xaxiemacif_s *)(xemac->state);
  306. XAxiEthernet *xemacp = &xemacs->axi_ethernet;
  307. #elif defined(XLWIP_CONFIG_INCLUDE_EMACLITE)
  308. xemacliteif_s *xemacs = (xemacliteif_s *)(xemac->state);
  309. XEmacLite *xemacp = xemacs->instance;
  310. #endif
  311. if ((xemacp->IsReady != (u32)XIL_COMPONENT_IS_READY) ||
  312. (eth_link_status == ETH_LINK_UNDEFINED))
  313. return;
  314. phy_link_status = phy_link_detect(xemacp, phyaddrforemac);
  315. if ((eth_link_status == ETH_LINK_UP) && (!phy_link_status))
  316. eth_link_status = ETH_LINK_DOWN;
  317. switch (eth_link_status) {
  318. case ETH_LINK_UNDEFINED:
  319. case ETH_LINK_UP:
  320. return;
  321. case ETH_LINK_DOWN:
  322. netif_set_link_down(netif);
  323. eth_link_status = ETH_LINK_NEGOTIATING;
  324. xil_printf("Ethernet Link down\r\n");
  325. break;
  326. case ETH_LINK_NEGOTIATING:
  327. if (phy_link_status &&
  328. phy_autoneg_status(xemacp, phyaddrforemac)) {
  329. /* Initiate Phy setup to get link speed */
  330. #if defined(XLWIP_CONFIG_INCLUDE_GEM)
  331. link_speed = phy_setup_emacps(xemacp,
  332. phyaddrforemac);
  333. XEmacPs_SetOperatingSpeed(xemacp, link_speed);
  334. #elif defined(XLWIP_CONFIG_INCLUDE_AXI_ETHERNET)
  335. link_speed = phy_setup_axiemac(xemacp);
  336. XAxiEthernet_SetOperatingSpeed(xemacp,
  337. link_speed);
  338. #endif
  339. netif_set_link_up(netif);
  340. eth_link_status = ETH_LINK_UP;
  341. xil_printf("Ethernet Link up\r\n");
  342. }
  343. break;
  344. }
  345. }
  346. #ifdef OS_IS_FREERTOS
  347. void link_detect_thread(void *p)
  348. {
  349. struct netif *netif = (struct netif *) p;
  350. while (1) {
  351. /* Call eth_link_detect() every second to detect Ethernet link
  352. * change.
  353. */
  354. eth_link_detect(netif);
  355. vTaskDelay(LINK_DETECT_THREAD_INTERVAL / portTICK_RATE_MS);
  356. }
  357. }
  358. #endif