keymile_hdlc_enet.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. /*
  2. * (C) Copyright 2008
  3. * Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de.
  4. *
  5. * Based in part on cpu/mpc8260/ether_scc.c.
  6. *
  7. * See file CREDITS for list of people who contributed to this
  8. * project.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation; either version 2 of
  13. * the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  23. * MA 02111-1307 USA
  24. */
  25. #include <common.h>
  26. #include <malloc.h>
  27. #include <net.h>
  28. #ifdef CONFIG_KEYMILE_HDLC_ENET
  29. #ifdef TEST_IT
  30. #include <command.h>
  31. #endif
  32. #include "keymile_hdlc_enet.h"
  33. extern char keymile_slot; /* our slot number in the backplane */
  34. /* Allow up to about 50 ms for sending */
  35. #define TOUT_LOOP 50000
  36. /*
  37. * Since, except during initialization, ethact is always HDLC ETHERNET
  38. * while we're in the driver, just use serial_printf() everywhere for
  39. * output. This avoids possible conflicts when netconsole is being
  40. * used.
  41. */
  42. #define dprintf(fmt, args...) serial_printf(fmt, ##args)
  43. /* Cannot use the storage from net.c because we allocate larger buffers */
  44. static volatile uchar MyPktBuf[HDLC_PKTBUFSRX * PKT_MAXBLR_SIZE + PKTALIGN];
  45. static volatile uchar *MyRxPackets[HDLC_PKTBUFSRX]; /* Receive packet */
  46. static unsigned int keymile_rxIdx; /* index of the current RX buffer */
  47. static IPaddr_t cachedNumbers[CACHEDNUMBERS]; /* 4 bytes per entry */
  48. void initCachedNumbers(int);
  49. /*
  50. * SCC Ethernet Tx and Rx buffer descriptors allocated at the
  51. * immr->udata_bd address on Dual-Port RAM
  52. * Provide for Double Buffering
  53. */
  54. typedef volatile struct CommonBufferDescriptor {
  55. cbd_t txbd; /* Tx BD */
  56. cbd_t rxbd[HDLC_PKTBUFSRX]; /* Rx BD */
  57. } RTXBD;
  58. /*
  59. * This must be extern because it is allocated in DPRAM using CPM-sepcific
  60. * code.
  61. */
  62. static RTXBD *rtx;
  63. static int keymile_hdlc_enet_send(struct eth_device *, volatile void *, int);
  64. static int keymile_hdlc_enet_recv(struct eth_device *);
  65. void keymile_hdlc_enet_init_bds(RTXBD *);
  66. extern int keymile_hdlc_enet_init(struct eth_device *, bd_t *);
  67. extern void keymile_hdlc_enet_halt(struct eth_device *);
  68. /* flags in the buffer descriptor not defined anywhere else */
  69. #define BD_SC_CT BD_SC_CD
  70. #define BD_SC_CR 0x04
  71. #define BD_SC_DE 0x80
  72. #ifndef BD_SC_TC
  73. #define BD_SC_TC ((ushort)0x0400) /* Transmit CRC */
  74. #endif
  75. #define BD_SC_FIRST BD_SC_TC
  76. #define BD_SC_STATS (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_CR | BD_SC_CD \
  77. | BD_SC_OV | BD_SC_DE)
  78. #if defined(TEST_RX) || defined(TEST_TX) || defined(TEST_IT)
  79. static void hexdump(unsigned char *buf, int len)
  80. {
  81. int i;
  82. const int bytesPerLine = 32;
  83. if (len > 4 * bytesPerLine)
  84. len = 4 * bytesPerLine;
  85. dprintf("\t address: %08x\n", (unsigned int)buf);
  86. for (i = 0; i < len; i++) {
  87. if (i % bytesPerLine == 0)
  88. dprintf("%04x: ", (unsigned short)i);
  89. dprintf("%02x ", buf[i]);
  90. if ((i + 1) % bytesPerLine == 0) {
  91. dprintf("\n");
  92. continue;
  93. }
  94. if ((i + 1) % 8 == 0)
  95. printf(" ");
  96. }
  97. if (len % bytesPerLine)
  98. dprintf("\n");
  99. }
  100. #endif
  101. int keymile_hdlc_enet_initialize(bd_t *bis)
  102. {
  103. struct eth_device *dev;
  104. dev = (struct eth_device *) malloc(sizeof *dev);
  105. memset(dev, 0, sizeof *dev);
  106. #ifdef TEST_IT
  107. seth = dev;
  108. #endif
  109. sprintf(dev->name, "HDLC ETHERNET");
  110. dev->init = keymile_hdlc_enet_init;
  111. dev->halt = keymile_hdlc_enet_halt;
  112. dev->send = keymile_hdlc_enet_send;
  113. dev->recv = keymile_hdlc_enet_recv;
  114. eth_register(dev);
  115. return 1;
  116. }
  117. /*
  118. * This is called from the board-specific driver after rtx is allocated.
  119. */
  120. void keymile_hdlc_enet_init_bds(RTXBD *board_rtx)
  121. {
  122. volatile cbd_t *bdp;
  123. int i;
  124. rtx = board_rtx;
  125. keymile_rxIdx = 0;
  126. /*
  127. * Initialize the buffer descriptors.
  128. */
  129. bdp = &rtx->txbd;
  130. bdp->cbd_sc = 0;
  131. bdp->cbd_bufaddr = 0;
  132. bdp->cbd_sc = BD_SC_WRAP;
  133. /*
  134. * Setup RX packet buffers, aligned correctly.
  135. * Borrowed from net/net.c.
  136. */
  137. MyRxPackets[0] = &MyPktBuf[0] + (PKTALIGN - 1);
  138. MyRxPackets[0] -= (ulong)MyRxPackets[0] % PKTALIGN;
  139. for (i = 1; i < HDLC_PKTBUFSRX; i++)
  140. MyRxPackets[i] = MyRxPackets[0] + i * PKT_MAXBLR_SIZE;
  141. bdp = &rtx->rxbd[0];
  142. for (i = 0; i < HDLC_PKTBUFSRX; i++) {
  143. bdp->cbd_sc = BD_SC_EMPTY;
  144. /* Leave space at the start for INET header. */
  145. bdp->cbd_bufaddr = (unsigned int)(MyRxPackets[i] +
  146. INET_HDR_ALIGN);
  147. bdp++;
  148. }
  149. bdp--;
  150. bdp->cbd_sc |= BD_SC_WRAP;
  151. }
  152. /*
  153. * This returns the current port number for NETCONSOLE. If nc_port
  154. * in netconsole.c weren't declared static we wouldn't need this.
  155. */
  156. static short get_netcons_port(void)
  157. {
  158. char *p;
  159. short nc_port;
  160. nc_port = 6666; /* default */
  161. p = getenv("ncip");
  162. if (p != NULL) {
  163. p = strchr(p, ':');
  164. if (p != NULL)
  165. nc_port = simple_strtoul(p + 1, NULL, 10);
  166. }
  167. return htons(nc_port);
  168. }
  169. /*
  170. * Read the port numbers from the variables
  171. */
  172. void initCachedNumbers(int verbose)
  173. {
  174. char *str;
  175. ushort port;
  176. /* already in network order */
  177. cachedNumbers[IP_ADDR] = getenv_IPaddr("ipaddr");
  178. /* already in network order */
  179. cachedNumbers[IP_SERVER] = getenv_IPaddr("serverip");
  180. str = getenv("tftpsrcp");
  181. if (str != NULL) {
  182. /* avoid doing htons() again and again */
  183. port = htons((ushort)simple_strtol(str, NULL, 10));
  184. cachedNumbers[TFTP_SRC_PORT] = port;
  185. } else
  186. /* this can never be a valid port number */
  187. cachedNumbers[TFTP_SRC_PORT] = (ulong)-1;
  188. str = getenv("tftpdstp");
  189. if (str != NULL) {
  190. /* avoid doing htons() again and again */
  191. port = htons((ushort)simple_strtol(str, NULL, 10));
  192. cachedNumbers[TFTP_DST_PORT] = port;
  193. } else
  194. /* this is the default value */
  195. cachedNumbers[TFTP_DST_PORT] = htons(WELL_KNOWN_PORT);
  196. /* already in network order */
  197. cachedNumbers[NETCONS_PORT] = get_netcons_port();
  198. if (verbose) {
  199. dprintf("\nIP Number Initialization:\n");
  200. dprintf(" ip address %08lx\n", cachedNumbers[IP_ADDR]);
  201. dprintf(" server ip address %08lx\n",
  202. cachedNumbers[IP_SERVER]);
  203. dprintf(" tftp client port %ld\n",
  204. cachedNumbers[TFTP_SRC_PORT]);
  205. dprintf(" tftp server port %ld\n",
  206. cachedNumbers[TFTP_DST_PORT]);
  207. dprintf(" netcons port %ld\n",
  208. cachedNumbers[NETCONS_PORT]);
  209. dprintf(" slot number (hex) %02x\n", keymile_slot);
  210. }
  211. }
  212. static void keymile_hdlc_enet_doarp(volatile void *packet, int len)
  213. {
  214. ARP_t *arp;
  215. IPaddr_t src_ip; /* U-Boot's IP */
  216. IPaddr_t dest_ip; /* the mgcoge's IP */
  217. unsigned char *packet_copy = malloc(len);
  218. /*
  219. * Handling an ARP request means that a new transfer has started.
  220. * Update our cached parameters now.
  221. */
  222. initCachedNumbers(0); /* may reinit port numbers */
  223. /* special handling required for ARP */
  224. arp = (ARP_t *)(packet + ETHER_HDR_SIZE);
  225. /*
  226. * XXXX
  227. * This is pretty dirty! NetReceive only uses
  228. * a few fields when handling an ARP reply, so
  229. * we only modify those here. This could
  230. * result in catastrophic failure at a later
  231. * time if the handler is modified!
  232. */
  233. arp->ar_op = htons(ARPOP_REPLY);
  234. /* save his/our IP */
  235. src_ip = NetReadIP(&arp->ar_data[6]);
  236. dest_ip = NetReadIP(&arp->ar_data[16]);
  237. /* copy target IP to source IP */
  238. NetCopyIP(&arp->ar_data[6], &dest_ip);
  239. /* copy our IP to the right place */
  240. NetCopyIP(&arp->ar_data[16], &src_ip);
  241. /* always use 0x7f as the MAC for the coge */
  242. arp->ar_data[0] = HDLC_UACUA;
  243. /*
  244. * copy the packet
  245. * if NetReceive wants to write to stdout, it may overwrite packet
  246. * especially if stdout is set to nc!
  247. *
  248. * However, if the malloc() above fails then we can still try the
  249. * original packet, rather than causing the transfer to fail.
  250. */
  251. if (packet_copy != NULL) {
  252. memcpy(packet_copy, (char *)packet, len);
  253. NetReceive(packet_copy, len);
  254. free(packet_copy);
  255. } else
  256. NetReceive(packet, len);
  257. }
  258. /*
  259. * NOTE all callers ignore the returned value!
  260. * At the moment this only handles ARP Requests, TFTP and NETCONSOLE.
  261. */
  262. static int keymile_hdlc_enet_send(struct eth_device *dev, volatile void *packet,
  263. int len)
  264. {
  265. int j;
  266. uint data_addr;
  267. int data_len;
  268. struct icn_hdr header;
  269. struct icn_frame *frame;
  270. Ethernet_t *et;
  271. ARP_t *arp;
  272. IP_t *ip;
  273. if (len > (MAX_FRAME_LENGTH - sizeof(header)))
  274. return -1;
  275. frame = NULL;
  276. et = NULL;
  277. arp = NULL;
  278. ip = NULL;
  279. j = 0;
  280. while ((rtx->txbd.cbd_sc & BD_SC_READY) && (j < TOUT_LOOP)) {
  281. /* will also trigger Wd if needed, but maybe too often */
  282. udelay(1);
  283. j++;
  284. }
  285. if (j >= TOUT_LOOP) {
  286. dprintf("TX not ready sc %x\n", rtx->txbd.cbd_sc);
  287. return -1;
  288. }
  289. /*
  290. * First check for an ARP Request since this requires special handling.
  291. */
  292. if (len >= (ARP_HDR_SIZE + ETHER_HDR_SIZE)) {
  293. et = (Ethernet_t *)packet;
  294. arp = (ARP_t *)(((char *)et) + ETHER_HDR_SIZE);
  295. /* ARP and REQUEST? */
  296. if (et->et_protlen == PROT_ARP &&
  297. arp->ar_op == htons(ARPOP_REQUEST)) {
  298. /* just short-circuit the request on the U-Boot side */
  299. keymile_hdlc_enet_doarp(packet, len);
  300. return 0;
  301. }
  302. }
  303. /*
  304. * GJ - I suppose the assumption here that len will always be
  305. * > INET_HDR_SIZE is alright as long as the network stack
  306. * isn't changed.
  307. * Do not send INET header.
  308. */
  309. data_len = len + sizeof(header) - INET_HDR_SIZE;
  310. frame = (struct icn_frame *) (((char *)packet) + INET_HDR_SIZE -
  311. sizeof(header));
  312. #ifdef TEST_TX
  313. printf("frame: %08x, ", frame);
  314. hexdump((unsigned char *)packet, data_len + INET_HDR_SIZE);
  315. #endif
  316. data_addr = (uint)frame;
  317. if (len >= (IP_HDR_SIZE + ETHER_HDR_SIZE))
  318. ip = (IP_t *)(packet + ETHER_HDR_SIZE);
  319. /* Is it TFTP? TFTP always uses UDP and the cached dport */
  320. if (ip != NULL && ip->ip_p == IPPROTO_UDP && ip->udp_dst ==
  321. (ushort)cachedNumbers[TFTP_DST_PORT]) {
  322. /* just in case the port wasn't set in the environment */
  323. if (cachedNumbers[TFTP_SRC_PORT] == (ulong)-1)
  324. cachedNumbers[TFTP_SRC_PORT] = ip->udp_src;
  325. frame->hdr.application = MGS_TFTP;
  326. }
  327. /*
  328. * Is it NETCONSOLE? NETCONSOLE always uses UDP.
  329. */
  330. else if (ip != NULL && ip->ip_p == IPPROTO_UDP
  331. && ip->udp_dst == (ushort)cachedNumbers[NETCONS_PORT]) {
  332. frame->hdr.application = MGS_NETCONS;
  333. } else {
  334. /* reject unknown packets */
  335. /* may do some check on frame->hdr.application */
  336. dprintf("Unknown packet type in %s, rejected\n",
  337. __func__);
  338. return -1;
  339. }
  340. /*
  341. * Could extract the target's slot ID from its MAC here,
  342. * but u-boot only wants to talk to the active server.
  343. *
  344. * avoid setting new source address when moving to another slot
  345. */
  346. frame->hdr.src_addr = keymile_slot;
  347. frame->hdr.dest_addr = HDLC_UACUA;
  348. #ifdef TEST_TX
  349. {
  350. dprintf("TX: ");
  351. hexdump((unsigned char *)data_addr, data_len);
  352. }
  353. #endif
  354. flush_cache(data_addr, data_len);
  355. rtx->txbd.cbd_bufaddr = data_addr;
  356. rtx->txbd.cbd_datlen = data_len;
  357. rtx->txbd.cbd_sc |= (BD_SC_READY | BD_SC_TC | BD_SC_LAST | BD_SC_WRAP);
  358. while ((rtx->txbd.cbd_sc & BD_SC_READY) && (j < TOUT_LOOP)) {
  359. /* will also trigger Wd if needed, but maybe too often */
  360. udelay(1);
  361. j++;
  362. }
  363. if (j >= TOUT_LOOP)
  364. dprintf("TX timeout\n");
  365. #ifdef ET_DEBUG
  366. dprintf("cycles: %d status: %x\n", j, rtx->txbd.cbd_sc);
  367. #endif
  368. j = (rtx->txbd.cbd_sc & BD_SC_STATS); /* return only status bits */
  369. return j;
  370. }
  371. /*
  372. * During a receive, the RxIdx points to the current incoming buffer.
  373. * When we update through the ring, if the next incoming buffer has
  374. * not been given to the system, we just set the empty indicator,
  375. * effectively tossing the packet.
  376. */
  377. static int keymile_hdlc_enet_recv(struct eth_device *dev)
  378. {
  379. int length;
  380. unsigned char app;
  381. struct icn_frame *fp;
  382. Ethernet_t *ep;
  383. IP_t *ip;
  384. for (;;) {
  385. if (rtx->rxbd[keymile_rxIdx].cbd_sc & BD_SC_EMPTY) {
  386. length = -1;
  387. break; /* nothing received - leave for() loop */
  388. }
  389. length = rtx->rxbd[keymile_rxIdx].cbd_datlen;
  390. #ifdef TEST_RX
  391. dprintf("packet %d bytes long\n", length);
  392. #endif
  393. /*
  394. * BD_SC_BR -> LG bit
  395. * BD_SC_FR -> NO bit
  396. * BD_SC_PR -> AB bit
  397. * BD_SC_NAK -> CR bit
  398. * 0x80 -> DE bit
  399. */
  400. if (rtx->rxbd[keymile_rxIdx].cbd_sc & BD_SC_STATS) {
  401. #ifdef ET_DEBUG
  402. dprintf("err: %x\n", rtx->rxbd[keymile_rxIdx].cbd_sc);
  403. #endif
  404. } else if (length > MAX_FRAME_LENGTH) { /* can't happen */
  405. #ifdef ET_DEBUG
  406. dprintf("err: packet too big\n");
  407. #endif
  408. } else {
  409. fp = (struct icn_frame *)(MyRxPackets[keymile_rxIdx] +
  410. INET_HDR_ALIGN - INET_HDR_SIZE);
  411. #ifdef TEST_RX
  412. dprintf("RX %d: ", keymile_rxIdx);
  413. hexdump((unsigned char *)MyRxPackets[keymile_rxIdx],
  414. INET_HDR_ALIGN + INET_HDR_SIZE + 4);
  415. #endif
  416. /* copy icn header to the beginning */
  417. memcpy(fp, ((char *)fp + INET_HDR_SIZE),
  418. sizeof(struct icn_hdr));
  419. app = fp->hdr.application;
  420. if (app == MGS_NETCONS || app == MGS_TFTP) {
  421. struct icn_hdr *ih = &fp->hdr;
  422. unsigned char icn_src_addr = ih->src_addr;
  423. unsigned char icn_dest_addr = ih->dest_addr;
  424. /*
  425. * expand header by INET_HDR_SIZE
  426. */
  427. length += INET_HDR_SIZE;
  428. /* initalize header */
  429. memset((char *)fp->data, 0x00, INET_HDR_SIZE);
  430. ep = (Ethernet_t *)fp->data;
  431. /* set MACs */
  432. ep->et_dest[0] = icn_dest_addr;
  433. ep->et_src[0] = icn_src_addr;
  434. ep->et_protlen = htons(PROT_IP);
  435. /* set ip stuff */
  436. ip = (IP_t *)(fp->data + ETHER_HDR_SIZE);
  437. /* set ip addresses */
  438. ip->ip_src = cachedNumbers[IP_SERVER];
  439. ip->ip_dst = cachedNumbers[IP_ADDR];
  440. /* ip length */
  441. ip->ip_len = htons(length - ETHER_HDR_SIZE -
  442. REMOVE);
  443. /* ip proto */
  444. ip->ip_p = IPPROTO_UDP;
  445. switch (app) {
  446. case MGS_TFTP:
  447. /* swap src/dst port numbers */
  448. ip->udp_src = (ushort)
  449. cachedNumbers[TFTP_DST_PORT];
  450. ip->udp_dst = (ushort)
  451. cachedNumbers[TFTP_SRC_PORT];
  452. ip->udp_len = ip->ip_len -
  453. IP_HDR_SIZE_NO_UDP;
  454. ip->udp_xsum = 0;
  455. break;
  456. case MGS_NETCONS:
  457. ip->udp_src = (ushort)
  458. cachedNumbers[NETCONS_PORT];
  459. /*
  460. * in drivers/net/netconsole.c src port
  461. * equals dest port
  462. */
  463. ip->udp_dst = ip->udp_src;
  464. ip->udp_len = ip->ip_len -
  465. IP_HDR_SIZE_NO_UDP;
  466. ip->udp_xsum = 0;
  467. break;
  468. }
  469. /* ip version */
  470. ip->ip_hl_v = (0x40) | (0x0f &
  471. (IP_HDR_SIZE_NO_UDP / 4));
  472. ip->ip_tos = 0;
  473. ip->ip_id = 0;
  474. /* flags, fragment offset */
  475. ip->ip_off = htons(0x4000);
  476. ip->ip_ttl = 255; /* time to live */
  477. /* have to fixup the checksum */
  478. ip->ip_sum = ~NetCksum((uchar *)ip,
  479. IP_HDR_SIZE_NO_UDP / 2);
  480. /*
  481. * Pass the packet up to the protocol layers
  482. * but remove dest_addr, src_addr, application
  483. * and the CRC.
  484. */
  485. #ifdef TEST_RX
  486. hexdump((unsigned char *)fp->data,
  487. INET_HDR_SIZE + 4);
  488. #endif
  489. NetReceive(fp->data, length - REMOVE);
  490. } else {
  491. /*
  492. * the other application types are not yet
  493. * supported by u-boot.
  494. */
  495. /* normally drop it */
  496. #ifdef TEST_NO
  497. /* send it anyway */
  498. fp = (struct icn_frame *)
  499. (MyRxPackets[keymile_rxIdx] +
  500. INET_HDR_ALIGN);
  501. NetReceive(fp->data, length - REMOVE);
  502. #endif
  503. }
  504. }
  505. /* Give the buffer back to the SCC. */
  506. rtx->rxbd[keymile_rxIdx].cbd_datlen = 0;
  507. /* wrap around buffer index when necessary */
  508. if ((keymile_rxIdx + 1) >= HDLC_PKTBUFSRX) {
  509. rtx->rxbd[HDLC_PKTBUFSRX - 1].cbd_sc =
  510. (BD_SC_WRAP | BD_SC_EMPTY);
  511. keymile_rxIdx = 0;
  512. } else {
  513. rtx->rxbd[keymile_rxIdx].cbd_sc = BD_SC_EMPTY;
  514. keymile_rxIdx++;
  515. }
  516. }
  517. return length;
  518. }
  519. #ifdef TEST_IT
  520. /* simple send test routine */
  521. int hdlc_enet_stest(struct cmd_tbl_s *a, int b, int c, char **d)
  522. {
  523. unsigned char pkt[2];
  524. int ret;
  525. dprintf("enter stest\n");
  526. /* may have to initialize things */
  527. if (seth->state != ETH_STATE_ACTIVE) {
  528. /* the bd_t* is not used */
  529. if (seth->init(seth, NULL) >= 0)
  530. seth->state = ETH_STATE_ACTIVE;
  531. }
  532. pkt[0] = 0xea;
  533. pkt[1] = 0xae;
  534. ret = keymile_hdlc_enet_send(seth, pkt, 2);
  535. dprintf("return from send %x\n", ret);
  536. dprintf("exit stest\n");
  537. return ret;
  538. }
  539. U_BOOT_CMD(
  540. stest, 1, 1, hdlc_enet_stest,
  541. "simple send test for hdlc_enet",
  542. "no arguments\n"
  543. );
  544. /* simple receive test routine */
  545. int hdlc_enet_rtest(struct cmd_tbl_s *a, int b, int c, char **d)
  546. {
  547. int ret;
  548. dprintf("enter rtest\n");
  549. /* may have to initialize things */
  550. if (seth->state != ETH_STATE_ACTIVE) {
  551. /* the bd_t* is not used */
  552. if (seth->init(seth, NULL) >= 0)
  553. seth->state = ETH_STATE_ACTIVE;
  554. }
  555. ret = keymile_hdlc_enet_recv(seth);
  556. dprintf("return from recv %x\n", ret);
  557. dprintf("exit rtest\n");
  558. return ret;
  559. }
  560. U_BOOT_CMD(
  561. rtest, 1, 1, hdlc_enet_rtest,
  562. "simple receive test for hdlc_enet",
  563. "no arguments\n"
  564. );
  565. #endif
  566. #endif /* CONFIG_KEYMILE_HDLC_ENET */