ether.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. /*
  2. * Copyright (C) 2001-2007 by egnite Software GmbH
  3. * Copyright (C) 2010 by egnite GmbH
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. */
  35. /*
  36. * $Id: ether.c 4115 2012-04-12 21:06:13Z olereinhardt $
  37. */
  38. #include "dialog.h"
  39. #include "arp.h"
  40. #include "ether.h"
  41. #include "bootmon.h"
  42. #define PIO_BASE 0xFFFF0000 /*!< \brief PIO base address. */
  43. #define PIO_OER (PIO_BASE + 0x10) /*!< \brief Output enable register. */
  44. #define PIO_ODR (PIO_BASE + 0x14) /*!< \brief Output disable register. */
  45. #define PIO_SODR (PIO_BASE + 0x30) /*!< \brief Set output data register. */
  46. #define PIO_CODR (PIO_BASE + 0x34) /*!< \brief Clear output data register. */
  47. #ifndef NIC_BASE_ADDR
  48. #define NIC_BASE_ADDR 0x20000000
  49. #endif
  50. #ifndef NIC_DATA_ADDR
  51. #define NIC_DATA_ADDR (NIC_BASE_ADDR + 4)
  52. #endif
  53. #define NIC_NCR 0x00 /* Network control register (0x00). */
  54. #define NIC_NCR_LBM 0x06 /* Loopback mode. */
  55. #define NIC_NCR_LBNORM 0x00 /* Normal mode. */
  56. #define NIC_NCR_LBMAC 0x02 /* MAC loopback. */
  57. #define NIC_NCR_LBPHY 0x04 /* PHY loopback. */
  58. #define NIC_NCR_RST 0x01 /* Software reset, auto clear. */
  59. #define NIC_NSR 0x01 /* Network status register (0x00). */
  60. #define NIC_NSR_SPEED 0x80
  61. #define NIC_NSR_LINKST 0x40
  62. #define NIC_NSR_WAKEST 0x20
  63. #define NIC_NSR_TX2END 0x08
  64. #define NIC_NSR_TX1END 0x04
  65. #define NIC_NSR_RXOV 0x02
  66. #define NIC_TCR 0x02 /* TX control register (0x00). */
  67. #define NIC_TCR_TXREQ 0x01 /* TX request */
  68. #define NIC_TSR1 0x03 /* TX status register I (0x00). */
  69. #define NIC_TSR2 0x04 /* TX status register II (0x00). */
  70. #define NIC_RCR 0x05 /* RX control register (0x00). */
  71. #define NIC_RCR_DIS_LONG 0x20 /* Discard long packets. */
  72. #define NIC_RCR_DIS_CRC 0x10 /* Discard CRC error packets. */
  73. #define NIC_RCR_PRMSC 0x02 /* Enable promiscuous mode. */
  74. #define NIC_RCR_RXEN 0x01 /* Enable receiver. */
  75. #define NIC_RSR 0x06 /* RX status register (0x00). */
  76. #define NIC_RSR_ERRORS 0xBF /* Error bit mask. */
  77. #define NIC_RSR_RF 0x80 /* Runt frame. */
  78. #define NIC_RSR_MF 0x40 /* Multicast frame. */
  79. #define NIC_RSR_LCS 0x20 /* Late collision. */
  80. #define NIC_RSR_RWTO 0x10 /* Receiver watchdog time out. */
  81. #define NIC_RSR_PLE 0x08 /* Physical layer error. */
  82. #define NIC_RSR_AE 0x04 /* Alignment error. */
  83. #define NIC_RSR_CE 0x02 /* CRC error. */
  84. #define NIC_RSR_FOE 0x01 /* FIFO overflow error. */
  85. #define NIC_ROCR 0x07 /* Receive overflow counter register (0x00). */
  86. #define NIC_BPTR 0x08 /* Back pressure threshold register (0x37). */
  87. #define NIC_FCTR 0x09 /* Flow control threshold register (0x38). */
  88. #define NIC_FCR 0x0A /* RX flow control register (0x00). */
  89. #define NIC_EPCR 0x0B /* EEPROM and PHY control register. */
  90. #define NIC_EPAR 0x0C /* EEPROM and PHY address register. */
  91. #define NIC_EPDRL 0x0D /* EEPROM and PHY low byte data register. */
  92. #define NIC_EPDRH 0x0E /* EEPROM and PHY high byte data register. */
  93. #define NIC_WCR 0x0F /* Wake up control register (0x00). */
  94. #define NIC_PAR 0x10 /* 6 byte physical address register. */
  95. #define NIC_MAR 0x16 /* 8 byte multicast address register. */
  96. #define NIC_GPCR 0x1E /* General purpose control register (?). */
  97. #define NIC_GPR 0x1F /* General purpose register (?). */
  98. #define NIC_TRPA 0x22 /* 2 byte TX SRAM read pointer address, low/high (0x0000). */
  99. #define NIC_RWPA 0x24 /* 2 byte RX SRAM write pointer address, low/high (0x0000). */
  100. #define NIC_VID 0x28 /* 2 byte vendor ID (0x0A46). */
  101. #define NIC_PID 0x2A /* 2 byte product ID (0x0900). */
  102. #define NIC_CHIPR 0x2C /* Chip revision (0x00). */
  103. #define NIC_SMCR 0x2F /* Special mode register (0x00). */
  104. #define NIC_MRCMDX 0xF0 /* Memory data read command w/o increment (?). */
  105. #define NIC_MRCMD 0xF2 /* Memory data read command with increment (?). */
  106. #define NIC_MRR 0xF4 /* 2 byte memory data read register, low/high (?). */
  107. #define NIC_MWCMDX 0xF6 /* Memory data write command register w/o increment (?). */
  108. #define NIC_MWCMD 0xF8 /* Memory data write command register with increment (?). */
  109. #define NIC_MWR 0xFA /* Memory data write command register with increment (?). */
  110. #define NIC_TXPL 0xFC /* 2 byte TX packet length register. (?). */
  111. #define NIC_ISR 0xFE /* Interrupt status register (0x00). */
  112. #define NIC_ISR_IOM 0xC0 /* I/O mode mask */
  113. #define NIC_ISR_M16 0x00 /* 16-bit I/O mode */
  114. #define NIC_ISR_M32 0x40 /* 32-bit I/O mode */
  115. #define NIC_ISR_M8 0x80 /* 8-bit I/O mode */
  116. #define NIC_ISR_ROOS 0x08 /* Receiver overflow counter interrupt. */
  117. #define NIC_ISR_ROS 0x04 /* Receiver overflow interrupt. */
  118. #define NIC_ISR_PTS 0x02 /* Transmitter interrupt. */
  119. #define NIC_ISR_PRS 0x01 /* Receiver interrupt. */
  120. #define NIC_IMR 0xFF /* Interrupt mask register (0x00). */
  121. #define NIC_IMR_PAR 0x80 /* Enable read/write pointer wrap around. */
  122. #define NIC_IMR_ROOM 0x08 /* Enable receiver overflow counter interrupts. */
  123. #define NIC_IMR_ROM 0x04 /* Enable receiver overflow interrupts. */
  124. #define NIC_IMR_PTM 0x02 /* Enable transmitter interrupts. */
  125. #define NIC_IMR_PRM 0x01 /* Enable receiver interrupts. */
  126. #define NIC_PHY_BMCR 0x00 /* Basic mode control register. */
  127. #define NIC_PHY_BMSR 0x01 /* Basic mode status register. */
  128. #define NIC_PHY_BMSR_ANCOMPL 0x0020 /* Auto negotiation complete. */
  129. #define NIC_PHY_BMSR_LINKSTAT 0x0004 /* Link status. */
  130. #define NIC_PHY_ID1 0x02 /* PHY identifier register 1. */
  131. #define NIC_PHY_ID2 0x03 /* PHY identifier register 2. */
  132. #define NIC_PHY_ANAR 0x04 /* Auto negotiation advertisement register. */
  133. #define NIC_PHY_ANLPAR 0x05 /* Auto negotiation link partner availability register. */
  134. #define NIC_PHY_ANER 0x06 /* Auto negotiation expansion register. */
  135. #define NIC_PHY_DSCR 0x10 /* Davicom specified configuration register. */
  136. #define NIC_PHY_DSCSR 0x11 /* Davicom specified configuration and status register. */
  137. #define NIC_PHY_10BTCSR 0x12 /* 10BASE-T configuration and status register. */
  138. #define outb(_reg, _val) (*((volatile unsigned char *)(_reg)) = (_val))
  139. #define outw(_reg, _val) (*((volatile unsigned short *)(_reg)) = (_val))
  140. #define outr(_reg, _val) (*((volatile unsigned int *)(_reg)) = (_val))
  141. #define inb(_reg) (*((volatile unsigned char *)(_reg)))
  142. #define inw(_reg) (*((volatile unsigned short *)(_reg)))
  143. #define inr(_reg) (*((volatile unsigned int *)(_reg)))
  144. #define _BV(bit) (1 << bit)
  145. static inline void nic_outb(unsigned char reg, unsigned char val)
  146. {
  147. outb(NIC_BASE_ADDR, reg);
  148. outb(NIC_DATA_ADDR, val);
  149. }
  150. static inline void nic_outw(unsigned char reg, unsigned short val)
  151. {
  152. outb(NIC_BASE_ADDR, reg);
  153. outb(NIC_DATA_ADDR, (unsigned char)val);
  154. outb(NIC_BASE_ADDR, reg + 1);
  155. outb(NIC_DATA_ADDR, (unsigned char)(val >> 8));
  156. }
  157. static inline unsigned char nic_inb(unsigned short reg)
  158. {
  159. outb(NIC_BASE_ADDR, reg);
  160. return inb(NIC_DATA_ADDR);
  161. }
  162. static inline unsigned short nic_inw(unsigned short reg)
  163. {
  164. unsigned short val;
  165. outb(NIC_BASE_ADDR, reg);
  166. val = inb(NIC_DATA_ADDR);
  167. outb(NIC_BASE_ADDR, reg + 1);
  168. val |= inb(NIC_DATA_ADDR) << 8;
  169. return val;
  170. }
  171. /*!
  172. * \brief Read contents of PHY register.
  173. *
  174. * \param reg PHY register number.
  175. *
  176. * \return Contents of the specified register.
  177. */
  178. static unsigned short phy_inw(unsigned char reg)
  179. {
  180. /* Select PHY register */
  181. nic_outb(NIC_EPAR, 0x40 | reg);
  182. /* PHY read command. */
  183. nic_outb(NIC_EPCR, 0x0C);
  184. MicroDelay(100);
  185. nic_outb(NIC_EPCR, 0x00);
  186. /* Get data from PHY data register. */
  187. return nic_inw(NIC_EPDRL);
  188. }
  189. /*!
  190. * \brief Write value to PHY register.
  191. *
  192. * \note NIC interrupts must have been disabled before calling this routine.
  193. *
  194. * \param reg PHY register number.
  195. * \param val Value to write.
  196. */
  197. static void phy_outw(unsigned char reg, unsigned short val)
  198. {
  199. /* Select PHY register */
  200. nic_outb(NIC_EPAR, 0x40 | reg);
  201. /* Store value in PHY data register. */
  202. nic_outw(NIC_EPDRL, val);
  203. /* PHY write command. */
  204. nic_outb(NIC_EPCR, 0x0A);
  205. MicroDelay(100);
  206. nic_outb(NIC_EPCR, 0x00);
  207. }
  208. static int NicPhyInit(void)
  209. {
  210. /* Restart auto negotiation. */
  211. phy_outw(NIC_PHY_ANAR, 0x01E1);
  212. phy_outw(NIC_PHY_BMCR, 0x1200);
  213. nic_outb(NIC_GPCR, 1);
  214. nic_outb(NIC_GPR, 0);
  215. return 0;
  216. }
  217. /*!
  218. * \brief Write data block to the NIC.
  219. *
  220. * NIC interrupts must be disabled when calling this function.
  221. */
  222. static void NicWrite16(unsigned char *buf, unsigned int len)
  223. {
  224. unsigned short val;
  225. /* Make sure that the total size is an even value. */
  226. len = (len + 1) / 2;
  227. while (len--) {
  228. val = *buf++;
  229. val |= *buf++ << 8;
  230. outw(NIC_DATA_ADDR, val);
  231. }
  232. }
  233. /*!
  234. * \brief Read data block from the NIC.
  235. *
  236. * NIC interrupts must be disabled when calling this function.
  237. */
  238. static void NicRead16(unsigned char *buf, unsigned short len)
  239. {
  240. unsigned short val;
  241. /* Make sure that the total size is an even value. */
  242. len = (len + 1) / 2;
  243. while (len--) {
  244. val = inw(NIC_DATA_ADDR);
  245. *buf++ = (unsigned char) val;
  246. *buf++ = (unsigned char) (val >> 8);
  247. }
  248. }
  249. /*!
  250. * \brief Reset the Ethernet controller.
  251. *
  252. * \return 0 on success, -1 otherwise.
  253. */
  254. static int NicReset(void)
  255. {
  256. /* Software reset. */
  257. nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
  258. MicroDelay(10000);
  259. return NicPhyInit();
  260. }
  261. /*!
  262. * \brief Initialize the NIC.
  263. *
  264. * \return 0 on success, -1 otherwise.
  265. */
  266. int EtherInit(void)
  267. {
  268. unsigned long id;
  269. int link_wait;
  270. int i;
  271. unsigned char val;
  272. /* Software reset. */
  273. nic_outb(NIC_NCR, NIC_NCR_RST);
  274. MicroDelay(10000);
  275. /* Probe chip by verifying the identifier registers. */
  276. id = (unsigned long) nic_inw(NIC_VID);
  277. id |= ((unsigned long) nic_inw(NIC_PID)) << 16;
  278. DEBUG("[ID=");
  279. DEBUGULONG(id);
  280. DEBUG("]");
  281. if (id != 0x90000A46) {
  282. return -1;
  283. }
  284. /* NIC reset. */
  285. if (NicReset()) {
  286. DEBUG("[RESET-ERR]");
  287. return -1;
  288. }
  289. /* Determine bus mode. We do not support 32 bit access. */
  290. val = nic_inb(NIC_ISR);
  291. if ((val & NIC_ISR_IOM) != NIC_ISR_M16) {
  292. DEBUG("[BUS-ERR ISR=0x");
  293. DEBUGUCHAR(val);
  294. DEBUG("]");
  295. return -1;
  296. }
  297. /* Power up the PHY. */
  298. nic_outb(NIC_GPR, 0);
  299. MicroDelay(5000);
  300. /* Software reset with MAC loopback. */
  301. nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
  302. MicroDelay(5000);
  303. nic_outb(NIC_NCR, NIC_NCR_RST | NIC_NCR_LBMAC);
  304. MicroDelay(5000);
  305. /*
  306. * PHY power down followed by PHY power up. This should activate
  307. * the auto sense link.
  308. */
  309. nic_outb(NIC_GPR, 1);
  310. nic_outb(NIC_GPR, 0);
  311. /* Set MAC address. */
  312. DEBUG("[MAC=");
  313. for (i = 0; i < 6; i++) {
  314. DEBUGUCHAR(confnet.cdn_mac[i]);
  315. nic_outb(NIC_PAR + i, confnet.cdn_mac[i]);
  316. }
  317. DEBUG("]");
  318. /* Enable broadcast receive. */
  319. for (i = 0; i < 7; i++) {
  320. nic_outb(NIC_MAR + i, 0);
  321. }
  322. nic_outb(NIC_MAR + 7, 0x80);
  323. /* Clear interrupts. */
  324. nic_outb(NIC_ISR, NIC_ISR_ROOS | NIC_ISR_ROS | NIC_ISR_PTS | NIC_ISR_PRS);
  325. /* Enable late collision retries on the DM9000A. */
  326. if (nic_inb(NIC_CHIPR) == 0x19) {
  327. nic_outb(0x2D, 0x40);
  328. }
  329. /* Enable receiver. */
  330. nic_outb(NIC_RCR, NIC_RCR_DIS_LONG | NIC_RCR_DIS_CRC | NIC_RCR_RXEN);
  331. /* Wait for link. */
  332. for (link_wait = 50;; link_wait--) {
  333. unsigned short bmsr;
  334. bmsr = phy_inw(NIC_PHY_BMSR);
  335. DEBUG("[BMSR=");
  336. DEBUGUSHORT(bmsr);
  337. DEBUG("]");
  338. if (bmsr & NIC_PHY_BMSR_ANCOMPL) {
  339. break;
  340. }
  341. if (link_wait == 0) {
  342. DEBUG("[LINK-ERR]");
  343. return -1;
  344. }
  345. MicroDelay(100000);
  346. }
  347. /* Enable interrupts. */
  348. nic_outb(NIC_IMR, NIC_IMR_PAR | NIC_IMR_PTM | NIC_IMR_PRM);
  349. DEBUG("[OK]");
  350. return 0;
  351. }
  352. /*!
  353. * \brief Send an Ethernet frame.
  354. *
  355. * \param dmac Destination MAC address, NULL for broadcast.
  356. * \param type Frame type.
  357. * \param len Frame size.
  358. *
  359. * \return 0 on success, -1 otherwise.
  360. */
  361. int EtherOutput(const unsigned char *dmac, unsigned int type, unsigned int len)
  362. {
  363. ETHERHDR *eh;
  364. unsigned char *ed;
  365. /*
  366. * Set the Ethernet header.
  367. */
  368. if (type == ETHERTYPE_ARP) {
  369. eh = &arpheader;
  370. ed = (unsigned char *) &arpframe;
  371. } else {
  372. eh = &sheader;
  373. ed = (unsigned char *) &sframe;
  374. }
  375. memcpy_(eh->ether_shost, confnet.cdn_mac, 6);
  376. if (dmac) {
  377. memcpy_(eh->ether_dhost, dmac, 6);
  378. } else {
  379. memset_(eh->ether_dhost, 0xFF, 6);
  380. }
  381. eh->ether_type = (unsigned short)type;
  382. DEBUG("\nTx(");
  383. DEBUGUSHORT(len);
  384. DEBUG(")");
  385. /* Enable data write. */
  386. outb(NIC_BASE_ADDR, NIC_MWCMD);
  387. /* Transfer the Ethernet frame. */
  388. NicWrite16((unsigned char *)eh, sizeof(ETHERHDR));
  389. NicWrite16(ed, len);
  390. /* Start the transmission. */
  391. nic_outw(NIC_TXPL, len + sizeof(ETHERHDR));
  392. nic_outb(NIC_TCR, NIC_TCR_TXREQ);
  393. return 0;
  394. }
  395. /*!
  396. * \brief Receive an Ethernet frame.
  397. *
  398. * \param type Unused?
  399. * \param tms Return with timeout after the specified number of polling loops.
  400. *
  401. * \return The number of bytes received, 0 on timeout or -1 in case of
  402. * a failure.
  403. */
  404. int EtherInput(unsigned short type, unsigned int tms)
  405. {
  406. unsigned short fsw;
  407. unsigned short fbc;
  408. unsigned char isr;
  409. for (;;) {
  410. /* Read the status word w/o auto increment. */
  411. nic_inb(NIC_MRCMDX);
  412. fsw = inb(NIC_DATA_ADDR);
  413. if (fsw != 1) {
  414. DEBUG("[ETH-POLL]");
  415. DEBUGUSHORT(tms);
  416. while (tms) {
  417. tms--;
  418. random_id++;
  419. DEBUG(".");
  420. isr = nic_inb(NIC_ISR);
  421. nic_outb(NIC_ISR, isr);
  422. /* Receiver interrupt. */
  423. if (isr & NIC_ISR_PRS) {
  424. nic_inb(NIC_MRCMDX);
  425. fsw = inb(NIC_DATA_ADDR);
  426. if (fsw == 1) {
  427. break;
  428. }
  429. }
  430. MicroDelay(10000);
  431. }
  432. }
  433. if (fsw != 1) {
  434. return 0;
  435. }
  436. /* Now read status word and byte count with auto increment. */
  437. outb(NIC_BASE_ADDR, NIC_MRCMD);
  438. fsw = inw(NIC_DATA_ADDR);
  439. fbc = inw(NIC_DATA_ADDR);
  440. /*
  441. * Receiving long packets is unexpected, because we disabled
  442. * this during initialization. Let's declare the chip insane.
  443. * Short packets will be handled by the caller.
  444. */
  445. if (fbc > 1536) {
  446. //ni->ni_insane = 1;
  447. DEBUG("[FBC ");
  448. DEBUGUSHORT(fbc);
  449. DEBUG("]");
  450. return -1;
  451. }
  452. /*
  453. * The high byte of the status word contains a copy of the
  454. * receiver status register.
  455. */
  456. fsw >>= 8;
  457. fsw &= NIC_RSR_ERRORS;
  458. /* Discard error packets. */
  459. if (fsw) {
  460. DEBUG(" RxError(");
  461. DEBUGUSHORT(fbc);
  462. DEBUG(")");
  463. fbc = (fbc + 1) / 2;
  464. while (fbc--) {
  465. fsw = inw(NIC_DATA_ADDR);
  466. }
  467. return -1;
  468. }
  469. DEBUG(" Rx(");
  470. DEBUGUSHORT(fbc);
  471. DEBUG(")");
  472. /* Read packet data from 16 bit bus. */
  473. fbc -= 4;
  474. NicRead16((unsigned char *) &rheader, sizeof(ETHERHDR));
  475. NicRead16((unsigned char *) &rframe, fbc - sizeof(ETHERHDR));
  476. /* Read packet CRC. */
  477. fsw = inw(NIC_DATA_ADDR);
  478. fsw = inw(NIC_DATA_ADDR);
  479. if (rheader.ether_type == type) {
  480. break;
  481. }
  482. /*
  483. * Handle incoming ARP requests.
  484. */
  485. if (rheader.ether_type == ETHERTYPE_ARP)
  486. ArpRespond();
  487. }
  488. return fbc;
  489. }