2 natsemi.c: A U-Boot driver for the NatSemi DP8381x series.
3 Author: Mark A. Rakes (mark_rakes@vivato.net)
5 Adapted from an Etherboot driver written by:
7 Copyright (C) 2001 Entity Cyber, Inc.
9 This development of this Etherboot driver was funded by
11 Sicom Systems: http://www.sicompos.com/
13 Author: Marty Connor (mdc@thinguin.org)
14 Adapted from a Linux driver which was written by Donald Becker
16 This software may be used and distributed according to the terms
17 of the GNU Public License (GPL), incorporated herein by reference.
19 Original Copyright Notice:
21 Written/copyright 1999-2001 by Donald Becker.
23 This software may be used and distributed according to the terms of
24 the GNU General Public License (GPL), incorporated herein by reference.
25 Drivers based on or derived from this code fall under the GPL and must
26 retain the authorship, copyright and license notice. This file is not
27 a complete program and may only be used when the entire operating
28 system is licensed under the GPL. License for under other terms may be
29 available. Contact the original author for details.
31 The original author may be reached as becker@scyld.com, or at
32 Scyld Computing Corporation
33 410 Severn Ave., Suite 210
36 Support information and updates available at
37 http://www.scyld.com/network/netsemi.html
40 http://www.scyld.com/expert/100mbps.html
41 http://www.scyld.com/expert/NWay.html
42 Datasheet is available from:
43 http://www.national.com/pf/DP/DP83815.html
47 * October 2002 mar 1.0
48 * Initial U-Boot Release. Tested with Netgear FA311 board
49 * and dp83815 chipset on custom board
60 #define EEPROM_SIZE 0xb /*12 16-bit chunks, or 24 bytes*/
62 #define DSIZE 0x00000FFF
65 #define TOUT_LOOP 500000
66 #define TX_BUF_SIZE 1536
67 #define RX_BUF_SIZE 1536
68 #define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */
70 /* Offsets to the device registers.
71 Unlike software-only systems, device drivers interact with complex hardware.
72 It's not useful to define symbolic names for every register bit in the
74 enum register_offsets {
91 /* These are from the spec, around page 78... on a separate table. */
110 enum ChipConfigBits {
111 LinkSts = 0x80000000,
112 HundSpeed = 0x40000000,
113 FullDuplex = 0x20000000,
114 TenPolarity = 0x10000000,
115 AnegDone = 0x08000000,
116 AnegEnBothBoth = 0x0000E000,
117 AnegDis100Full = 0x0000C000,
118 AnegEn100Both = 0x0000A000,
119 AnegDis100Half = 0x00008000,
120 AnegEnBothHalf = 0x00006000,
121 AnegDis10Full = 0x00004000,
122 AnegEn10Both = 0x00002000,
123 DuplexMask = 0x00008000,
124 SpeedMask = 0x00004000,
125 AnegMask = 0x00002000,
126 AnegDis10Half = 0x00000000,
130 BootRomDisable = 0x00000004,
137 TxMxdmaMask = 0x700000,
139 TxMxdma_4 = 0x100000,
140 TxMxdma_8 = 0x200000,
141 TxMxdma_16 = 0x300000,
142 TxMxdma_32 = 0x400000,
143 TxMxdma_64 = 0x500000,
144 TxMxdma_128 = 0x600000,
145 TxMxdma_256 = 0x700000,
146 TxCollRetry = 0x800000,
147 TxAutoPad = 0x10000000,
148 TxMacLoop = 0x20000000,
149 TxHeartIgn = 0x40000000,
150 TxCarrierIgn = 0x80000000
155 RxMxdmaMask = 0x700000,
157 RxMxdma_4 = 0x100000,
158 RxMxdma_8 = 0x200000,
159 RxMxdma_16 = 0x300000,
160 RxMxdma_32 = 0x400000,
161 RxMxdma_64 = 0x500000,
162 RxMxdma_128 = 0x600000,
163 RxMxdma_256 = 0x700000,
164 RxAcceptLong = 0x8000000,
165 RxAcceptTx = 0x10000000,
166 RxAcceptRunt = 0x40000000,
167 RxAcceptErr = 0x80000000
170 /* Bits in the RxMode register. */
174 AcceptBroadcast = 0xC0000000,
175 AcceptMulticast = 0x00200000,
176 AcceptAllMulticast = 0x20000000,
177 AcceptAllPhys = 0x10000000,
178 AcceptMyPhys = 0x08000000
181 typedef struct _BufferDesc {
188 /* Bits in network_desc.status */
189 enum desc_status_bits {
190 DescOwn = 0x80000000, DescMore = 0x40000000, DescIntr = 0x20000000,
191 DescNoCRC = 0x10000000, DescPktOK = 0x08000000,
192 DescSizeMask = 0xfff,
194 DescTxAbort = 0x04000000, DescTxFIFO = 0x02000000,
195 DescTxCarrier = 0x01000000, DescTxDefer = 0x00800000,
196 DescTxExcDefer = 0x00400000, DescTxOOWCol = 0x00200000,
197 DescTxExcColl = 0x00100000, DescTxCollCount = 0x000f0000,
199 DescRxAbort = 0x04000000, DescRxOver = 0x02000000,
200 DescRxDest = 0x01800000, DescRxLong = 0x00400000,
201 DescRxRunt = 0x00200000, DescRxInvalid = 0x00100000,
202 DescRxCRC = 0x00080000, DescRxAlign = 0x00040000,
203 DescRxLoop = 0x00020000, DesRxColl = 0x00010000,
208 static int natsemi_debug = 0; /* 1 verbose debugging, 0 normal */
210 static u32 SavedClkRun;
211 static unsigned int cur_rx;
212 static unsigned int advertising;
213 static unsigned int rx_config;
214 static unsigned int tx_config;
216 /* Note: transmit and receive buffers and descriptors must be
218 static BufferDesc txd __attribute__ ((aligned(4)));
219 static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(4)));
221 static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(4)));
222 static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE]
223 __attribute__ ((aligned(4)));
225 /* Function Prototypes */
227 static void write_eeprom(struct eth_device *dev, long addr, int location,
230 static int read_eeprom(struct eth_device *dev, long addr, int location);
231 static int mdio_read(struct eth_device *dev, int phy_id, int location);
232 static int natsemi_init(struct eth_device *dev, bd_t * bis);
233 static void natsemi_reset(struct eth_device *dev);
234 static void natsemi_init_rxfilter(struct eth_device *dev);
235 static void natsemi_init_txd(struct eth_device *dev);
236 static void natsemi_init_rxd(struct eth_device *dev);
237 static void natsemi_set_rx_mode(struct eth_device *dev);
238 static void natsemi_check_duplex(struct eth_device *dev);
239 static int natsemi_send(struct eth_device *dev, volatile void *packet,
241 static int natsemi_poll(struct eth_device *dev);
242 static void natsemi_disable(struct eth_device *dev);
244 static struct pci_device_id supported[] = {
245 {PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_83815},
249 #define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, a)
250 #define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a)
253 INW(struct eth_device *dev, u_long addr)
255 return le16_to_cpu(*(vu_short *) (addr + dev->iobase));
259 INL(struct eth_device *dev, u_long addr)
261 return le32_to_cpu(*(vu_long *) (addr + dev->iobase));
265 OUTW(struct eth_device *dev, int command, u_long addr)
267 *(vu_short *) ((addr + dev->iobase)) = cpu_to_le16(command);
271 OUTL(struct eth_device *dev, int command, u_long addr)
273 *(vu_long *) ((addr + dev->iobase)) = cpu_to_le32(command);
277 * Function: natsemi_initialize
279 * Description: Retrieves the MAC address of the card, and sets up some
280 * globals required by other routines, and initializes the NIC, making it
281 * ready to send and receive packets.
284 * leaves the natsemi initialized, and ready to recieve packets.
286 * Returns: struct eth_device *: pointer to NIC data structure
290 natsemi_initialize(bd_t * bis)
294 struct eth_device *dev;
295 u32 iobase, status, chip_config;
301 /* Find PCI device(s) */
302 if ((devno = pci_find_devices(supported, idx++)) < 0) {
306 pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &iobase);
307 iobase &= ~0x3; /* bit 1: unused and bit 0: I/O Space Indicator */
309 pci_write_config_dword(devno, PCI_COMMAND,
310 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
312 /* Check if I/O accesses and Bus Mastering are enabled. */
313 pci_read_config_dword(devno, PCI_COMMAND, &status);
314 if (!(status & PCI_COMMAND_MEMORY)) {
315 printf("Error: Can not enable MEM access.\n");
317 } else if (!(status & PCI_COMMAND_MASTER)) {
318 printf("Error: Can not enable Bus Mastering.\n");
322 dev = (struct eth_device *) malloc(sizeof *dev);
324 sprintf(dev->name, "dp83815#%d", card_number);
325 dev->iobase = bus_to_phys(iobase);
327 printf("natsemi: NatSemi ns8381[56] @ %#x\n", dev->iobase);
329 dev->priv = (void *) devno;
330 dev->init = natsemi_init;
331 dev->halt = natsemi_disable;
332 dev->send = natsemi_send;
333 dev->recv = natsemi_poll;
339 /* Set the latency timer for value. */
340 pci_write_config_byte(devno, PCI_LATENCY_TIMER, 0x20);
344 /* natsemi has a non-standard PM control register
345 * in PCI config space. Some boards apparently need
346 * to be brought to D0 in this manner. */
347 pci_read_config_dword(devno, PCIPM, &tmp);
348 if (tmp & (0x03 | 0x100)) {
349 /* D0 state, disable PME assertion */
350 u32 newtmp = tmp & ~(0x03 | 0x100);
351 pci_write_config_dword(devno, PCIPM, newtmp);
354 printf("natsemi: EEPROM contents:\n");
355 for (i = 0; i <= EEPROM_SIZE; i++) {
356 short eedata = read_eeprom(dev, EECtrl, i);
357 printf(" %04hx", eedata);
361 /* get MAC address */
362 prev_eedata = read_eeprom(dev, EECtrl, 6);
363 for (i = 0; i < 3; i++) {
364 int eedata = read_eeprom(dev, EECtrl, i + 7);
365 dev->enetaddr[i*2] = (eedata << 1) + (prev_eedata >> 15);
366 dev->enetaddr[i*2+1] = eedata >> 7;
367 prev_eedata = eedata;
370 /* Reset the chip to erase any previous misconfiguration. */
371 OUTL(dev, ChipReset, ChipCmd);
373 advertising = mdio_read(dev, 1, 4);
374 chip_config = INL(dev, ChipConfig);
376 printf("%s: Transceiver status %#08X advertising %#08X\n",
377 dev->name, (int) INL(dev, BasicStatus), advertising);
378 printf("%s: Transceiver default autoneg. %s 10%s %s duplex.\n",
379 dev->name, chip_config & AnegMask ? "enabled, advertise" :
380 "disabled, force", chip_config & SpeedMask ? "0" : "",
381 chip_config & DuplexMask ? "full" : "half");
383 chip_config |= AnegEnBothBoth;
385 printf("%s: changed to autoneg. %s 10%s %s duplex.\n",
386 dev->name, chip_config & AnegMask ? "enabled, advertise" :
387 "disabled, force", chip_config & SpeedMask ? "0" : "",
388 chip_config & DuplexMask ? "full" : "half");
390 /*write new autoneg bits, reset phy*/
391 OUTL(dev, (chip_config | PhyRst), ChipConfig);
393 OUTL(dev, chip_config, ChipConfig);
396 * The PME bit is initialized from the EEPROM contents.
397 * PCI cards probably have PME disabled, but motherboard
398 * implementations may have PME set to enable WakeOnLan.
399 * With PME set the chip will scan incoming packets but
400 * nothing will be written to memory. */
401 SavedClkRun = INL(dev, ClkRun);
402 OUTL(dev, SavedClkRun & ~0x100, ClkRun);
407 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces.
408 The EEPROM code is for common 93c06/46 EEPROMs w/ 6bit addresses. */
410 /* Delay between EEPROM clock transitions.
411 No extra delay is needed with 33Mhz PCI, but future 66Mhz
412 access may need a delay. */
413 #define eeprom_delay(ee_addr) INL(dev, ee_addr)
415 enum EEPROM_Ctrl_Bits {
418 EE_ChipSelect = 0x08,
422 #define EE_Write0 (EE_ChipSelect)
423 #define EE_Write1 (EE_ChipSelect | EE_DataIn)
424 /* The EEPROM commands include the alway-set leading bit. */
426 EE_WrEnCmd = (4 << 6), EE_WriteCmd = (5 << 6),
427 EE_ReadCmd = (6 << 6), EE_EraseCmd = (7 << 6),
432 write_eeprom(struct eth_device *dev, long addr, int location, short value)
435 int ee_addr = (typeof(ee_addr))addr;
436 short wren_cmd = EE_WrEnCmd | 0x30; /*wren is 100 + 11XXXX*/
437 short write_cmd = location | EE_WriteCmd;
440 printf("write_eeprom: %08x, %04hx, %04hx\n",
441 dev->iobase + ee_addr, write_cmd, value);
443 /* Shift the write enable command bits out. */
444 for (i = 9; i >= 0; i--) {
445 short cmdval = (wren_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
446 OUTL(dev, cmdval, ee_addr);
447 eeprom_delay(ee_addr);
448 OUTL(dev, cmdval | EE_ShiftClk, ee_addr);
449 eeprom_delay(ee_addr);
452 OUTL(dev, 0, ee_addr); /*bring chip select low*/
453 OUTL(dev, EE_ShiftClk, ee_addr);
454 eeprom_delay(ee_addr);
456 /* Shift the write command bits out. */
457 for (i = 9; i >= 0; i--) {
458 short cmdval = (write_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
459 OUTL(dev, cmdval, ee_addr);
460 eeprom_delay(ee_addr);
461 OUTL(dev, cmdval | EE_ShiftClk, ee_addr);
462 eeprom_delay(ee_addr);
465 for (i = 0; i < 16; i++) {
466 short cmdval = (value & (1 << i)) ? EE_Write1 : EE_Write0;
467 OUTL(dev, cmdval, ee_addr);
468 eeprom_delay(ee_addr);
469 OUTL(dev, cmdval | EE_ShiftClk, ee_addr);
470 eeprom_delay(ee_addr);
473 OUTL(dev, 0, ee_addr); /*bring chip select low*/
474 OUTL(dev, EE_ShiftClk, ee_addr);
475 for (i = 0; i < 200000; i++) {
476 OUTL(dev, EE_Write0, ee_addr); /*poll for done*/
477 if (INL(dev, ee_addr) & EE_DataOut) {
481 eeprom_delay(ee_addr);
483 /* Terminate the EEPROM access. */
484 OUTL(dev, EE_Write0, ee_addr);
485 OUTL(dev, 0, ee_addr);
491 read_eeprom(struct eth_device *dev, long addr, int location)
495 int ee_addr = (typeof(ee_addr))addr;
496 int read_cmd = location | EE_ReadCmd;
498 OUTL(dev, EE_Write0, ee_addr);
500 /* Shift the read command bits out. */
501 for (i = 10; i >= 0; i--) {
502 short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0;
503 OUTL(dev, dataval, ee_addr);
504 eeprom_delay(ee_addr);
505 OUTL(dev, dataval | EE_ShiftClk, ee_addr);
506 eeprom_delay(ee_addr);
508 OUTL(dev, EE_ChipSelect, ee_addr);
509 eeprom_delay(ee_addr);
511 for (i = 0; i < 16; i++) {
512 OUTL(dev, EE_ChipSelect | EE_ShiftClk, ee_addr);
513 eeprom_delay(ee_addr);
514 retval |= (INL(dev, ee_addr) & EE_DataOut) ? 1 << i : 0;
515 OUTL(dev, EE_ChipSelect, ee_addr);
516 eeprom_delay(ee_addr);
519 /* Terminate the EEPROM access. */
520 OUTL(dev, EE_Write0, ee_addr);
521 OUTL(dev, 0, ee_addr);
524 printf("read_eeprom: %08x, %08x, retval %08x\n",
525 dev->iobase + ee_addr, read_cmd, retval);
530 /* MII transceiver control section.
531 The 83815 series has an internal transceiver, and we present the
532 management registers as if they were MII connected. */
535 mdio_read(struct eth_device *dev, int phy_id, int location)
537 if (phy_id == 1 && location < 32)
538 return INL(dev, BasicControl+(location<<2))&0xffff;
543 /* Function: natsemi_init
545 * Description: resets the ethernet controller chip and configures
546 * registers and data structures required for sending and receiving packets.
548 * Arguments: struct eth_device *dev: NIC data structure
554 natsemi_init(struct eth_device *dev, bd_t * bis)
560 * The PME bit is initialized from the EEPROM contents.
561 * PCI cards probably have PME disabled, but motherboard
562 * implementations may have PME set to enable WakeOnLan.
563 * With PME set the chip will scan incoming packets but
564 * nothing will be written to memory. */
565 OUTL(dev, SavedClkRun & ~0x100, ClkRun);
567 natsemi_init_rxfilter(dev);
568 natsemi_init_txd(dev);
569 natsemi_init_rxd(dev);
571 /* Configure the PCI bus bursts and FIFO thresholds. */
572 tx_config = TxAutoPad | TxCollRetry | TxMxdma_256 | (0x1002);
573 rx_config = RxMxdma_256 | 0x20;
576 printf("%s: Setting TxConfig Register %#08X\n", dev->name, tx_config);
577 printf("%s: Setting RxConfig Register %#08X\n", dev->name, rx_config);
579 OUTL(dev, tx_config, TxConfig);
580 OUTL(dev, rx_config, RxConfig);
582 natsemi_check_duplex(dev);
583 natsemi_set_rx_mode(dev);
585 OUTL(dev, (RxOn | TxOn), ChipCmd);
590 * Function: natsemi_reset
592 * Description: soft resets the controller chip
594 * Arguments: struct eth_device *dev: NIC data structure
599 natsemi_reset(struct eth_device *dev)
601 OUTL(dev, ChipReset, ChipCmd);
603 /* On page 78 of the spec, they recommend some settings for "optimum
604 performance" to be done in sequence. These settings optimize some
605 of the 100Mbit autodetection circuitry. Also, we only want to do
606 this for rev C of the chip. */
607 if (INL(dev, SiliconRev) == 0x302) {
608 OUTW(dev, 0x0001, PGSEL);
609 OUTW(dev, 0x189C, PMDCSR);
610 OUTW(dev, 0x0000, TSTDAT);
611 OUTW(dev, 0x5040, DSPCFG);
612 OUTW(dev, 0x008C, SDCFG);
614 /* Disable interrupts using the mask. */
615 OUTL(dev, 0, IntrMask);
616 OUTL(dev, 0, IntrEnable);
619 /* Function: natsemi_init_rxfilter
621 * Description: sets receive filter address to our MAC address
623 * Arguments: struct eth_device *dev: NIC data structure
629 natsemi_init_rxfilter(struct eth_device *dev)
633 for (i = 0; i < ETH_ALEN; i += 2) {
634 OUTL(dev, i, RxFilterAddr);
635 OUTW(dev, dev->enetaddr[i] + (dev->enetaddr[i + 1] << 8),
641 * Function: natsemi_init_txd
643 * Description: initializes the Tx descriptor
645 * Arguments: struct eth_device *dev: NIC data structure
651 natsemi_init_txd(struct eth_device *dev)
654 txd.cmdsts = (u32) 0;
655 txd.bufptr = (u32) & txb[0];
657 /* load Transmit Descriptor Register */
658 OUTL(dev, (u32) & txd, TxRingPtr);
660 printf("natsemi_init_txd: TX descriptor reg loaded with: %#08X\n",
661 INL(dev, TxRingPtr));
665 /* Function: natsemi_init_rxd
667 * Description: initializes the Rx descriptor ring
669 * Arguments: struct eth_device *dev: NIC data structure
675 natsemi_init_rxd(struct eth_device *dev)
681 /* init RX descriptor */
682 for (i = 0; i < NUM_RX_DESC; i++) {
685 NUM_RX_DESC) ? (u32) & rxd[i +
688 rxd[i].cmdsts = cpu_to_le32((u32) RX_BUF_SIZE);
689 rxd[i].bufptr = cpu_to_le32((u32) & rxb[i * RX_BUF_SIZE]);
692 ("natsemi_init_rxd: rxd[%d]=%p link=%X cmdsts=%lX bufptr=%X\n",
693 i, &rxd[i], le32_to_cpu(rxd[i].link),
694 rxd[i].cmdsts, rxd[i].bufptr);
698 /* load Receive Descriptor Register */
699 OUTL(dev, (u32) & rxd[0], RxRingPtr);
702 printf("natsemi_init_rxd: RX descriptor register loaded with: %X\n",
703 INL(dev, RxRingPtr));
707 /* Function: natsemi_set_rx_mode
710 * sets the receive mode to accept all broadcast packets and packets
711 * with our MAC address, and reject all multicast packets.
713 * Arguments: struct eth_device *dev: NIC data structure
719 natsemi_set_rx_mode(struct eth_device *dev)
721 u32 rx_mode = AcceptBroadcast | AcceptMyPhys;
723 OUTL(dev, rx_mode, RxFilterAddr);
727 natsemi_check_duplex(struct eth_device *dev)
729 int duplex = INL(dev, ChipConfig) & FullDuplex ? 1 : 0;
732 printf("%s: Setting %s-duplex based on negotiated link"
733 " capability.\n", dev->name, duplex ? "full" : "half");
736 rx_config |= RxAcceptTx;
737 tx_config |= (TxCarrierIgn | TxHeartIgn);
739 rx_config &= ~RxAcceptTx;
740 tx_config &= ~(TxCarrierIgn | TxHeartIgn);
742 OUTL(dev, tx_config, TxConfig);
743 OUTL(dev, rx_config, RxConfig);
746 /* Function: natsemi_send
748 * Description: transmits a packet and waits for completion or timeout.
752 natsemi_send(struct eth_device *dev, volatile void *packet, int length)
756 vu_long *res = (vu_long *)&tx_status;
758 /* Stop the transmitter */
759 OUTL(dev, TxOff, ChipCmd);
763 printf("natsemi_send: sending %d bytes\n", (int) length);
766 /* set the transmit buffer descriptor and enable Transmit State Machine */
767 txd.link = cpu_to_le32(0);
768 txd.bufptr = cpu_to_le32(phys_to_bus((u32) packet));
769 txd.cmdsts = cpu_to_le32(DescOwn | length);
771 /* load Transmit Descriptor Register */
772 OUTL(dev, phys_to_bus((u32) & txd), TxRingPtr);
775 printf("natsemi_send: TX descriptor register loaded with: %#08X\n",
776 INL(dev, TxRingPtr));
778 /* restart the transmitter */
779 OUTL(dev, TxOn, ChipCmd);
782 (*res = le32_to_cpu(txd.cmdsts)) & DescOwn;
784 if (i >= TOUT_LOOP) {
786 ("%s: tx error buffer not ready: txd.cmdsts == %#X\n",
787 dev->name, tx_status);
792 if (!(tx_status & DescPktOK)) {
793 printf("natsemi_send: Transmit error, Tx status %X.\n",
803 /* Function: natsemi_poll
805 * Description: checks for a received packet and returns it if found.
807 * Arguments: struct eth_device *dev: NIC data structure
809 * Returns: 1 if packet was received.
810 * 0 if no packet was received.
813 * Returns (copies) the packet to the array dev->packet.
814 * Returns the length of the packet.
818 natsemi_poll(struct eth_device *dev)
822 u32 rx_status = le32_to_cpu(rxd[cur_rx].cmdsts);
824 if (!(rx_status & (u32) DescOwn))
828 printf("natsemi_poll: got a packet: cur_rx:%d, status:%X\n",
831 length = (rx_status & DSIZE) - CRC_SIZE;
833 if ((rx_status & (DescMore | DescPktOK | DescRxLong)) != DescPktOK) {
835 ("natsemi_poll: Corrupted packet received, buffer status = %X\n",
838 } else { /* give packet to higher level routine */
839 NetReceive((rxb + cur_rx * RX_BUF_SIZE), length);
843 /* return the descriptor and buffer to receive ring */
844 rxd[cur_rx].cmdsts = cpu_to_le32(RX_BUF_SIZE);
845 rxd[cur_rx].bufptr = cpu_to_le32((u32) & rxb[cur_rx * RX_BUF_SIZE]);
847 if (++cur_rx == NUM_RX_DESC)
850 /* re-enable the potentially idle receive state machine */
851 OUTL(dev, RxOn, ChipCmd);
856 /* Function: natsemi_disable
858 * Description: Turns off interrupts and stops Tx and Rx engines
860 * Arguments: struct eth_device *dev: NIC data structure
866 natsemi_disable(struct eth_device *dev)
868 /* Disable interrupts using the mask. */
869 OUTL(dev, 0, IntrMask);
870 OUTL(dev, 0, IntrEnable);
872 /* Stop the chip's Tx and Rx processes. */
873 OUTL(dev, RxOff | TxOff, ChipCmd);
875 /* Restore PME enable bit */
876 OUTL(dev, SavedClkRun, ClkRun);