ether_bf537.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  1. /*
  2. * ADI Blackfin 537 MAC Ethernet
  3. *
  4. * Copyright (c) 2005 Analog Device, Inc.
  5. *
  6. * See file CREDITS for list of people who contributed to this
  7. * project.
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22. * MA 02111-1307 USA
  23. */
  24. #include <common.h>
  25. #include <config.h>
  26. #include <asm/blackfin.h>
  27. #include <net.h>
  28. #include <command.h>
  29. #include <malloc.h>
  30. #include "ether_bf537.h"
  31. #include <asm/mach-common/bits/dma.h>
  32. #include <asm/mach-common/bits/emac.h>
  33. #include <asm/mach-common/bits/pll.h>
  34. #ifdef CONFIG_POST
  35. #include <post.h>
  36. #endif
  37. #undef DEBUG_ETHERNET
  38. #ifdef DEBUG_ETHERNET
  39. #define DEBUGF(fmt,args...) printf(fmt,##args)
  40. #else
  41. #define DEBUGF(fmt,args...)
  42. #endif
  43. #if defined(CONFIG_CMD_NET)
  44. #define RXBUF_BASE_ADDR 0xFF900000
  45. #define TXBUF_BASE_ADDR 0xFF800000
  46. #define TX_BUF_CNT 1
  47. #define TOUT_LOOP 1000000
  48. ADI_ETHER_BUFFER *txbuf[TX_BUF_CNT];
  49. ADI_ETHER_BUFFER *rxbuf[PKTBUFSRX];
  50. static u16 txIdx; /* index of the current RX buffer */
  51. static u16 rxIdx; /* index of the current TX buffer */
  52. u8 SrcAddr[6];
  53. u16 PHYregs[NO_PHY_REGS]; /* u16 PHYADDR; */
  54. /* DMAx_CONFIG values at DMA Restart */
  55. const ADI_DMA_CONFIG_REG rxdmacfg = { 1, 1, 2, 0, 0, 0, 0, 5, 7 };
  56. #if 0
  57. rxdmacfg.b_DMA_EN = 1; /* enabled */
  58. rxdmacfg.b_WNR = 1; /* write to memory */
  59. rxdmacfg.b_WDSIZE = 2; /* wordsize is 32 bits */
  60. rxdmacfg.b_DMA2D = 0; /* N/A */
  61. rxdmacfg.b_RESTART= 0; /* N/A */
  62. rxdmacfg.b_DI_SEL = 0; /* N/A */
  63. rxdmacfg.b_DI_EN = 0; /* no interrupt */
  64. rxdmacfg.b_NDSIZE = 5; /* 5 half words is desc size. */
  65. rxdmacfg.b_FLOW = 7; /* large desc flow */
  66. #endif
  67. const ADI_DMA_CONFIG_REG txdmacfg = { 1, 0, 2, 0, 0, 0, 0, 5, 7 };
  68. #if 0
  69. txdmacfg.b_DMA_EN = 1; /* enabled */
  70. txdmacfg.b_WNR = 0; /* read from memory */
  71. txdmacfg.b_WDSIZE = 2; /* wordsize is 32 bits */
  72. txdmacfg.b_DMA2D = 0; /* N/A */
  73. txdmacfg.b_RESTART= 0; /* N/A */
  74. txdmacfg.b_DI_SEL = 0; /* N/A */
  75. txdmacfg.b_DI_EN = 0; /* no interrupt */
  76. txdmacfg.b_NDSIZE = 5; /* 5 half words is desc size. */
  77. txdmacfg.b_FLOW = 7; /* large desc flow */
  78. #endif
  79. ADI_ETHER_BUFFER *SetupRxBuffer(int no);
  80. ADI_ETHER_BUFFER *SetupTxBuffer(int no);
  81. static int bfin_EMAC_init(struct eth_device *dev, bd_t * bd);
  82. static void bfin_EMAC_halt(struct eth_device *dev);
  83. static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet,
  84. int length);
  85. static int bfin_EMAC_recv(struct eth_device *dev);
  86. int bfin_EMAC_initialize(bd_t * bis)
  87. {
  88. struct eth_device *dev;
  89. dev = (struct eth_device *)malloc(sizeof(*dev));
  90. if (dev == NULL)
  91. hang();
  92. memset(dev, 0, sizeof(*dev));
  93. sprintf(dev->name, "BF537 ETHERNET");
  94. dev->iobase = 0;
  95. dev->priv = 0;
  96. dev->init = bfin_EMAC_init;
  97. dev->halt = bfin_EMAC_halt;
  98. dev->send = bfin_EMAC_send;
  99. dev->recv = bfin_EMAC_recv;
  100. eth_register(dev);
  101. return 1;
  102. }
  103. static int bfin_EMAC_send(struct eth_device *dev, volatile void *packet,
  104. int length)
  105. {
  106. int i;
  107. int result = 0;
  108. unsigned int *buf;
  109. buf = (unsigned int *)packet;
  110. if (length <= 0) {
  111. printf("Ethernet: bad packet size: %d\n", length);
  112. goto out;
  113. }
  114. if ((*pDMA2_IRQ_STATUS & DMA_ERR) != 0) {
  115. printf("Ethernet: tx DMA error\n");
  116. goto out;
  117. }
  118. for (i = 0; (*pDMA2_IRQ_STATUS & DMA_RUN) != 0; i++) {
  119. if (i > TOUT_LOOP) {
  120. puts("Ethernet: tx time out\n");
  121. goto out;
  122. }
  123. }
  124. txbuf[txIdx]->FrmData->NoBytes = length;
  125. memcpy(txbuf[txIdx]->FrmData->Dest, (void *)packet, length);
  126. txbuf[txIdx]->Dma[0].START_ADDR = (u32) txbuf[txIdx]->FrmData;
  127. *pDMA2_NEXT_DESC_PTR = &txbuf[txIdx]->Dma[0];
  128. *pDMA2_CONFIG = *(u16 *) (void *)(&txdmacfg);
  129. *pEMAC_OPMODE |= TE;
  130. for (i = 0; (txbuf[txIdx]->StatusWord & TX_COMP) == 0; i++) {
  131. if (i > TOUT_LOOP) {
  132. puts("Ethernet: tx error\n");
  133. goto out;
  134. }
  135. }
  136. result = txbuf[txIdx]->StatusWord;
  137. txbuf[txIdx]->StatusWord = 0;
  138. if ((txIdx + 1) >= TX_BUF_CNT)
  139. txIdx = 0;
  140. else
  141. txIdx++;
  142. out:
  143. DEBUGF("BFIN EMAC send: length = %d\n", length);
  144. return result;
  145. }
  146. static int bfin_EMAC_recv(struct eth_device *dev)
  147. {
  148. int length = 0;
  149. for (;;) {
  150. if ((rxbuf[rxIdx]->StatusWord & RX_COMP) == 0) {
  151. length = -1;
  152. break;
  153. }
  154. if ((rxbuf[rxIdx]->StatusWord & RX_DMAO) != 0) {
  155. printf("Ethernet: rx dma overrun\n");
  156. break;
  157. }
  158. if ((rxbuf[rxIdx]->StatusWord & RX_OK) == 0) {
  159. printf("Ethernet: rx error\n");
  160. break;
  161. }
  162. length = rxbuf[rxIdx]->StatusWord & 0x000007FF;
  163. if (length <= 4) {
  164. printf("Ethernet: bad frame\n");
  165. break;
  166. }
  167. NetRxPackets[rxIdx] =
  168. (volatile uchar *)(rxbuf[rxIdx]->FrmData->Dest);
  169. NetReceive(NetRxPackets[rxIdx], length - 4);
  170. *pDMA1_IRQ_STATUS |= DMA_DONE | DMA_ERR;
  171. rxbuf[rxIdx]->StatusWord = 0x00000000;
  172. if ((rxIdx + 1) >= PKTBUFSRX)
  173. rxIdx = 0;
  174. else
  175. rxIdx++;
  176. }
  177. return length;
  178. }
  179. /**************************************************************
  180. *
  181. * Ethernet Initialization Routine
  182. *
  183. *************************************************************/
  184. static int bfin_EMAC_init(struct eth_device *dev, bd_t * bd)
  185. {
  186. u32 opmode;
  187. int dat;
  188. int i;
  189. DEBUGF("Eth_init: ......\n");
  190. txIdx = 0;
  191. rxIdx = 0;
  192. /* Initialize System Register */
  193. if (SetupSystemRegs(&dat) < 0)
  194. return -1;
  195. /* Initialize EMAC address */
  196. SetupMacAddr(SrcAddr);
  197. /* Initialize TX and RX buffer */
  198. for (i = 0; i < PKTBUFSRX; i++) {
  199. rxbuf[i] = SetupRxBuffer(i);
  200. if (i > 0) {
  201. rxbuf[i - 1]->Dma[1].NEXT_DESC_PTR =
  202. &(rxbuf[i]->Dma[0]);
  203. if (i == (PKTBUFSRX - 1))
  204. rxbuf[i]->Dma[1].NEXT_DESC_PTR =
  205. &(rxbuf[0]->Dma[0]);
  206. }
  207. }
  208. for (i = 0; i < TX_BUF_CNT; i++) {
  209. txbuf[i] = SetupTxBuffer(i);
  210. if (i > 0) {
  211. txbuf[i - 1]->Dma[1].NEXT_DESC_PTR =
  212. &(txbuf[i]->Dma[0]);
  213. if (i == (TX_BUF_CNT - 1))
  214. txbuf[i]->Dma[1].NEXT_DESC_PTR =
  215. &(txbuf[0]->Dma[0]);
  216. }
  217. }
  218. /* Set RX DMA */
  219. *pDMA1_NEXT_DESC_PTR = &rxbuf[0]->Dma[0];
  220. *pDMA1_CONFIG = *((u16 *) (void *)&rxbuf[0]->Dma[0].CONFIG);
  221. /* Wait MII done */
  222. PollMdcDone();
  223. /* We enable only RX here */
  224. /* ASTP : Enable Automatic Pad Stripping
  225. PR : Promiscuous Mode for test
  226. PSF : Receive frames with total length less than 64 bytes.
  227. FDMODE : Full Duplex Mode
  228. LB : Internal Loopback for test
  229. RE : Receiver Enable */
  230. if (dat == FDMODE)
  231. opmode = ASTP | FDMODE | PSF;
  232. else
  233. opmode = ASTP | PSF;
  234. opmode |= RE;
  235. #ifdef CONFIG_BFIN_MAC_RMII
  236. opmode |= TE | RMII;
  237. #endif
  238. /* Turn on the EMAC */
  239. *pEMAC_OPMODE = opmode;
  240. return 0;
  241. }
  242. static void bfin_EMAC_halt(struct eth_device *dev)
  243. {
  244. DEBUGF("Eth_halt: ......\n");
  245. /* Turn off the EMAC */
  246. *pEMAC_OPMODE = 0x00000000;
  247. /* Turn off the EMAC RX DMA */
  248. *pDMA1_CONFIG = 0x0000;
  249. *pDMA2_CONFIG = 0x0000;
  250. }
  251. void SetupMacAddr(u8 * MACaddr)
  252. {
  253. char *tmp, *end;
  254. int i;
  255. /* this depends on a little-endian machine */
  256. tmp = getenv("ethaddr");
  257. if (tmp) {
  258. for (i = 0; i < 6; i++) {
  259. MACaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
  260. if (tmp)
  261. tmp = (*end) ? end + 1 : end;
  262. }
  263. #ifndef CONFIG_NETCONSOLE
  264. printf("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n",
  265. MACaddr[0], MACaddr[1],
  266. MACaddr[2], MACaddr[3], MACaddr[4], MACaddr[5]);
  267. #endif
  268. *pEMAC_ADDRLO = MACaddr[0] | MACaddr[1] << 8 |
  269. MACaddr[2] << 16 | MACaddr[3] << 24;
  270. *pEMAC_ADDRHI = MACaddr[4] | MACaddr[5] << 8;
  271. }
  272. }
  273. void PollMdcDone(void)
  274. {
  275. /* poll the STABUSY bit */
  276. while (*pEMAC_STAADD & STABUSY) ;
  277. }
  278. void WrPHYReg(u16 PHYAddr, u16 RegAddr, u16 Data)
  279. {
  280. PollMdcDone();
  281. *pEMAC_STADAT = Data;
  282. *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
  283. STAOP | STAIE | STABUSY;
  284. }
  285. /*********************************************************************************
  286. * Read an off-chip register in a PHY through the MDC/MDIO port *
  287. *********************************************************************************/
  288. u16 RdPHYReg(u16 PHYAddr, u16 RegAddr)
  289. {
  290. u16 Data;
  291. PollMdcDone();
  292. *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) |
  293. STAIE | STABUSY;
  294. PollMdcDone();
  295. Data = (u16) * pEMAC_STADAT;
  296. PHYregs[RegAddr] = Data; /* save shadow copy */
  297. return Data;
  298. }
  299. void SoftResetPHY(void)
  300. {
  301. u16 phydat;
  302. /* set the reset bit */
  303. WrPHYReg(PHYADDR, PHY_MODECTL, PHY_RESET);
  304. /* and clear it again */
  305. WrPHYReg(PHYADDR, PHY_MODECTL, 0x0000);
  306. do {
  307. /* poll until reset is complete */
  308. phydat = RdPHYReg(PHYADDR, PHY_MODECTL);
  309. } while ((phydat & PHY_RESET) != 0);
  310. }
  311. int SetupSystemRegs(int *opmode)
  312. {
  313. u16 sysctl, phydat;
  314. int count = 0;
  315. /* Enable PHY output */
  316. *pVR_CTL |= CLKBUFOE;
  317. /* MDC = 2.5 MHz */
  318. sysctl = SET_MDCDIV(24);
  319. /* Odd word alignment for Receive Frame DMA word */
  320. /* Configure checksum support and rcve frame word alignment */
  321. sysctl |= RXDWA | RXCKS;
  322. *pEMAC_SYSCTL = sysctl;
  323. /* auto negotiation on */
  324. /* full duplex */
  325. /* 100 Mbps */
  326. phydat = PHY_ANEG_EN | PHY_DUPLEX | PHY_SPD_SET;
  327. WrPHYReg(PHYADDR, PHY_MODECTL, phydat);
  328. do {
  329. udelay(1000);
  330. phydat = RdPHYReg(PHYADDR, PHY_MODESTAT);
  331. if (count > 3000) {
  332. printf
  333. ("Link is down, please check your network connection\n");
  334. return -1;
  335. }
  336. count++;
  337. } while (!(phydat & 0x0004));
  338. phydat = RdPHYReg(PHYADDR, PHY_ANLPAR);
  339. if ((phydat & 0x0100) || (phydat & 0x0040))
  340. *opmode = FDMODE;
  341. else
  342. *opmode = 0;
  343. *pEMAC_MMC_CTL = RSTC | CROLL;
  344. /* Initialize the TX DMA channel registers */
  345. *pDMA2_X_COUNT = 0;
  346. *pDMA2_X_MODIFY = 4;
  347. *pDMA2_Y_COUNT = 0;
  348. *pDMA2_Y_MODIFY = 0;
  349. /* Initialize the RX DMA channel registers */
  350. *pDMA1_X_COUNT = 0;
  351. *pDMA1_X_MODIFY = 4;
  352. *pDMA1_Y_COUNT = 0;
  353. *pDMA1_Y_MODIFY = 0;
  354. return 0;
  355. }
  356. ADI_ETHER_BUFFER *SetupRxBuffer(int no)
  357. {
  358. ADI_ETHER_FRAME_BUFFER *frmbuf;
  359. ADI_ETHER_BUFFER *buf;
  360. int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */
  361. int total_size = nobytes_buffer + RECV_BUFSIZE;
  362. buf = (ADI_ETHER_BUFFER *) (RXBUF_BASE_ADDR + no * total_size);
  363. frmbuf =
  364. (ADI_ETHER_FRAME_BUFFER *) (RXBUF_BASE_ADDR + no * total_size +
  365. nobytes_buffer);
  366. memset(buf, 0x00, nobytes_buffer);
  367. buf->FrmData = frmbuf;
  368. memset(frmbuf, 0xfe, RECV_BUFSIZE);
  369. /* set up first desc to point to receive frame buffer */
  370. buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]);
  371. buf->Dma[0].START_ADDR = (u32) buf->FrmData;
  372. buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */
  373. buf->Dma[0].CONFIG.b_WNR = 1; /* Write to memory */
  374. buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */
  375. buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */
  376. buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */
  377. /* set up second desc to point to status word */
  378. buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]);
  379. buf->Dma[1].START_ADDR = (u32) & buf->IPHdrChksum;
  380. buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */
  381. buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */
  382. buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */
  383. buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */
  384. buf->Dma[1].CONFIG.b_NDSIZE = 5; /* must be 0 when FLOW is 0 */
  385. buf->Dma[1].CONFIG.b_FLOW = 7; /* stop */
  386. return buf;
  387. }
  388. ADI_ETHER_BUFFER *SetupTxBuffer(int no)
  389. {
  390. ADI_ETHER_FRAME_BUFFER *frmbuf;
  391. ADI_ETHER_BUFFER *buf;
  392. int nobytes_buffer = sizeof(ADI_ETHER_BUFFER[2]) / 2; /* ensure a multi. of 4 */
  393. int total_size = nobytes_buffer + RECV_BUFSIZE;
  394. buf = (ADI_ETHER_BUFFER *) (TXBUF_BASE_ADDR + no * total_size);
  395. frmbuf =
  396. (ADI_ETHER_FRAME_BUFFER *) (TXBUF_BASE_ADDR + no * total_size +
  397. nobytes_buffer);
  398. memset(buf, 0x00, nobytes_buffer);
  399. buf->FrmData = frmbuf;
  400. memset(frmbuf, 0x00, RECV_BUFSIZE);
  401. /* set up first desc to point to receive frame buffer */
  402. buf->Dma[0].NEXT_DESC_PTR = &(buf->Dma[1]);
  403. buf->Dma[0].START_ADDR = (u32) buf->FrmData;
  404. buf->Dma[0].CONFIG.b_DMA_EN = 1; /* enabled */
  405. buf->Dma[0].CONFIG.b_WNR = 0; /* Read to memory */
  406. buf->Dma[0].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */
  407. buf->Dma[0].CONFIG.b_NDSIZE = 5; /* 5 half words is desc size. */
  408. buf->Dma[0].CONFIG.b_FLOW = 7; /* large desc flow */
  409. /* set up second desc to point to status word */
  410. buf->Dma[1].NEXT_DESC_PTR = &(buf->Dma[0]);
  411. buf->Dma[1].START_ADDR = (u32) & buf->StatusWord;
  412. buf->Dma[1].CONFIG.b_DMA_EN = 1; /* enabled */
  413. buf->Dma[1].CONFIG.b_WNR = 1; /* Write to memory */
  414. buf->Dma[1].CONFIG.b_WDSIZE = 2; /* wordsize is 32 bits */
  415. buf->Dma[1].CONFIG.b_DI_EN = 1; /* enable interrupt */
  416. buf->Dma[1].CONFIG.b_NDSIZE = 0; /* must be 0 when FLOW is 0 */
  417. buf->Dma[1].CONFIG.b_FLOW = 0; /* stop */
  418. return buf;
  419. }
  420. #if defined(CONFIG_POST) && defined(CFG_POST_ETHER)
  421. int ether_post_test(int flags)
  422. {
  423. uchar buf[64];
  424. int i, value = 0;
  425. int length;
  426. printf("\n--------");
  427. bfin_EMAC_init(NULL, NULL);
  428. /* construct the package */
  429. buf[0] = buf[6] = (unsigned char)(*pEMAC_ADDRLO & 0xFF);
  430. buf[1] = buf[7] = (unsigned char)((*pEMAC_ADDRLO & 0xFF00) >> 8);
  431. buf[2] = buf[8] = (unsigned char)((*pEMAC_ADDRLO & 0xFF0000) >> 16);
  432. buf[3] = buf[9] = (unsigned char)((*pEMAC_ADDRLO & 0xFF000000) >> 24);
  433. buf[4] = buf[10] = (unsigned char)(*pEMAC_ADDRHI & 0xFF);
  434. buf[5] = buf[11] = (unsigned char)((*pEMAC_ADDRHI & 0xFF00) >> 8);
  435. buf[12] = 0x08; /* Type: ARP */
  436. buf[13] = 0x06;
  437. buf[14] = 0x00; /* Hardware type: Ethernet */
  438. buf[15] = 0x01;
  439. buf[16] = 0x08; /* Protocal type: IP */
  440. buf[17] = 0x00;
  441. buf[18] = 0x06; /* Hardware size */
  442. buf[19] = 0x04; /* Protocol size */
  443. buf[20] = 0x00; /* Opcode: request */
  444. buf[21] = 0x01;
  445. for (i = 0; i < 42; i++)
  446. buf[i + 22] = i;
  447. printf("--------Send 64 bytes......\n");
  448. bfin_EMAC_send(NULL, (volatile void *)buf, 64);
  449. for (i = 0; i < 100; i++) {
  450. udelay(10000);
  451. if ((rxbuf[rxIdx]->StatusWord & RX_COMP) != 0) {
  452. value = 1;
  453. break;
  454. }
  455. }
  456. if (value == 0) {
  457. printf("--------EMAC can't receive any data\n");
  458. eth_halt();
  459. return -1;
  460. }
  461. length = rxbuf[rxIdx]->StatusWord & 0x000007FF - 4;
  462. for (i = 0; i < length; i++) {
  463. if (rxbuf[rxIdx]->FrmData->Dest[i] != buf[i]) {
  464. printf("--------EMAC receive error data!\n");
  465. eth_halt();
  466. return -1;
  467. }
  468. }
  469. printf("--------receive %d bytes, matched\n", length);
  470. bfin_EMAC_halt(NULL);
  471. return 0;
  472. }
  473. #endif
  474. #endif