1 /* -*- Mode:C; c-basic-offset:4; -*- */ 2 3 /* 4 natsemi.c: An Etherboot driver for the NatSemi DP8381x series. 5 6 Copyright (C) 2001 Entity Cyber, Inc. 7 8 This development of this Etherboot driver was funded by 9 10 Sicom Systems: http://www.sicompos.com/ 11 12 Author: Marty Connor (mdc (at) thinguin.org) 13 Adapted from a Linux driver which was written by Donald Becker 14 15 This software may be used and distributed according to the terms 16 of the GNU Public License (GPL), incorporated herein by reference. 17 18 Original Copyright Notice: 19 20 Written/copyright 1999-2001 by Donald Becker. 21 22 This software may be used and distributed according to the terms of 23 the GNU General Public License (GPL), incorporated herein by reference. 24 Drivers based on or derived from this code fall under the GPL and must 25 retain the authorship, copyright and license notice. This file is not 26 a complete program and may only be used when the entire operating 27 system is licensed under the GPL. License for under other terms may be 28 available. Contact the original author for details. 29 30 The original author may be reached as becker (at) scyld.com, or at 31 Scyld Computing Corporation 32 410 Severn Ave., Suite 210 33 Annapolis MD 21403 34 35 Support information and updates available at 36 http://www.scyld.com/network/netsemi.html 37 38 References: 39 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 44 45 */ 46 47 /* Revision History */ 48 49 /* 50 29 May 2001 mdc 1.0 51 Initial Release. Tested with Netgear FA311 and FA312 boards 52 */ 53 /* Includes */ 55 56 #include "etherboot.h" 57 #include "nic.h" 58 #include "pci.h" 59 #include "cards.h" 60 61 /* defines */ 62 63 #define OWN 0x80000000 64 #define DSIZE 0x00000FFF 65 #define CRC_SIZE 4 66 67 /* Time in ticks before concluding the transmitter is hung. */ 68 #define TX_TIMEOUT (4*TICKS_PER_SEC) 69 70 #define TX_BUF_SIZE 1536 71 #define RX_BUF_SIZE 1536 72 73 #define NUM_RX_DESC 4 /* Number of Rx descriptor registers. */ 74 75 typedef unsigned char u8; 76 typedef signed char s8; 77 typedef unsigned short u16; 78 typedef signed short s16; 79 typedef unsigned int u32; 80 typedef signed int s32; 81 82 /* helpful macroes if on a big_endian machine for changing byte order. 83 not strictly needed on Intel */ 84 #define le16_to_cpu(val) (val) 85 #define cpu_to_le32(val) (val) 86 #define get_unaligned(ptr) (*(ptr)) 87 #define put_unaligned(val, ptr) ((void)( *(ptr) = (val) )) 88 #define get_u16(ptr) (*(u16 *)(ptr)) 89 #define virt_to_bus(x) ((unsigned long)x) 90 #define virt_to_le32desc(addr) virt_to_bus(addr) 91 92 enum pcistuff { 93 PCI_USES_IO = 0x01, 94 PCI_USES_MEM = 0x02, 95 PCI_USES_MASTER = 0x04, 96 PCI_ADDR0 = 0x08, 97 PCI_ADDR1 = 0x10, 98 }; 99 100 /* MMIO operations required */ 101 #define PCI_IOTYPE (PCI_USES_MASTER | PCI_USES_MEM | PCI_ADDR1) 102 103 /* Offsets to the device registers. 104 Unlike software-only systems, device drivers interact with complex hardware. 105 It's not useful to define symbolic names for every register bit in the 106 device. 107 */ 108 enum register_offsets { 109 ChipCmd = 0x00, 110 ChipConfig = 0x04, 111 EECtrl = 0x08, 112 PCIBusCfg = 0x0C, 113 IntrStatus = 0x10, 114 IntrMask = 0x14, 115 IntrEnable = 0x18, 116 TxRingPtr = 0x20, 117 TxConfig = 0x24, 118 RxRingPtr = 0x30, 119 RxConfig = 0x34, 120 ClkRun = 0x3C, 121 WOLCmd = 0x40, 122 PauseCmd = 0x44, 123 RxFilterAddr = 0x48, 124 RxFilterData = 0x4C, 125 BootRomAddr = 0x50, 126 BootRomData = 0x54, 127 SiliconRev = 0x58, 128 StatsCtrl = 0x5C, 129 StatsData = 0x60, 130 RxPktErrs = 0x60, 131 RxMissed = 0x68, 132 RxCRCErrs = 0x64, 133 PCIPM = 0x44, 134 PhyStatus = 0xC0, 135 MIntrCtrl = 0xC4, 136 MIntrStatus = 0xC8, 137 138 /* These are from the spec, around page 78... on a separate table. */ 139 PGSEL = 0xCC, 140 PMDCSR = 0xE4, 141 TSTDAT = 0xFC, 142 DSPCFG = 0xF4, 143 SDCFG = 0x8C 144 }; 145 146 /* Bit in ChipCmd. */ 147 enum ChipCmdBits { 148 ChipReset = 0x100, 149 RxReset = 0x20, 150 TxReset = 0x10, 151 RxOff = 0x08, 152 RxOn = 0x04, 153 TxOff = 0x02, 154 TxOn = 0x01 155 }; 156 157 /* Bits in the RxMode register. */ 158 enum rx_mode_bits { 159 AcceptErr = 0x20, 160 AcceptRunt = 0x10, 161 AcceptBroadcast = 0xC0000000, 162 AcceptMulticast = 0x00200000, 163 AcceptAllMulticast = 0x20000000, 164 AcceptAllPhys = 0x10000000, 165 AcceptMyPhys = 0x08000000 166 }; 167 168 typedef struct _BufferDesc { 169 u32 link; 170 volatile u32 cmdsts; 171 u32 bufptr; 172 u32 software_use; 173 } BufferDesc; 174 175 /* Bits in network_desc.status */ 176 enum desc_status_bits { 177 DescOwn = 0x80000000, 178 DescMore = 0x40000000, 179 DescIntr = 0x20000000, 180 DescNoCRC = 0x10000000, 181 DescPktOK = 0x08000000, 182 RxTooLong = 0x00400000 183 }; 184 185 /* Globals */ 186 187 static int natsemi_debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ 188 189 const char *nic_name; 190 191 static u32 SavedClkRun; 192 193 194 static unsigned short vendor, dev_id; 195 static unsigned long ioaddr; 196 197 static unsigned int cur_rx; 198 199 static unsigned int advertising; 200 201 static unsigned int rx_config; 202 static unsigned int tx_config; 203 204 /* Note: transmit and receive buffers and descriptors must be 205 longword aligned 206 */ 207 208 static BufferDesc txd __attribute__ ((aligned(4))); 209 static BufferDesc rxd[NUM_RX_DESC] __attribute__ ((aligned(4))); 210 211 #ifdef USE_LOWMEM_BUFFER 212 #define txb ((char *)0x10000 - TX_BUF_SIZE) 213 #define rxb ((char *)0x10000 - NUM_RX_DESC*RX_BUF_SIZE - TX_BUF_SIZE) 214 #else 215 static unsigned char txb[TX_BUF_SIZE] __attribute__ ((aligned(4))); 216 static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE] __attribute__ ((aligned(4))); 217 #endif 218 219 /* Function Prototypes */ 220 221 struct nic *natsemi_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci); 222 static int eeprom_read(long addr, int location); 223 static int mdio_read(int phy_id, int location); 224 static void natsemi_init(struct nic *nic); 225 static void natsemi_reset(struct nic *nic); 226 static void natsemi_init_rxfilter(struct nic *nic); 227 static void natsemi_init_txd(struct nic *nic); 228 static void natsemi_init_rxd(struct nic *nic); 229 static void natsemi_set_rx_mode(struct nic *nic); 230 static void natsemi_check_duplex(struct nic *nic); 231 static void natsemi_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p); 232 static int natsemi_poll(struct nic *nic); 233 static void natsemi_disable(struct nic *nic); 234 235 /* 236 * Function: natsemi_probe 237 * 238 * Description: Retrieves the MAC address of the card, and sets up some 239 * globals required by other routines, and initializes the NIC, making it 240 * ready to send and receive packets. 241 * 242 * Side effects: 243 * leaves the ioaddress of the natsemi chip in the variable ioaddr. 244 * leaves the natsemi initialized, and ready to recieve packets. 245 * 246 * Returns: struct nic *: pointer to NIC data structure 247 */ 248 249 struct nic * 250 natsemi_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci) 251 { 252 int i; 253 int prev_eedata; 254 u32 tmp; 255 256 if (io_addrs == 0 || *io_addrs == 0) 257 return NULL; 258 259 /* initialize some commonly used globals */ 260 261 ioaddr = *io_addrs & ~3; 262 vendor = pci->vendor; 263 dev_id = pci->dev_id; 264 nic_name = pci->name; 265 266 adjust_pci_device(pci); 267 268 /* natsemi has a non-standard PM control register 269 * in PCI config space. Some boards apparently need 270 * to be brought to D0 in this manner. 271 */ 272 pcibios_read_config_dword(pci->bus, pci->devfn, PCIPM, &tmp); 273 if (tmp & (0x03|0x100)) { 274 /* D0 state, disable PME assertion */ 275 u32 newtmp = tmp & ~(0x03|0x100); 276 pcibios_write_config_dword(pci->bus, pci->devfn, PCIPM, newtmp); 277 } 278 279 /* get MAC address */ 280 281 prev_eedata = eeprom_read(ioaddr, 6); 282 for (i = 0; i < 3; i++) { 283 int eedata = eeprom_read(ioaddr, i + 7); 284 nic->node_addr[i*2] = (eedata << 1) + (prev_eedata >> 15); 285 nic->node_addr[i*2+1] = eedata >> 7; 286 prev_eedata = eedata; 287 } 288 289 printf("\nnatsemi_probe: MAC addr %! at ioaddr %#hX\n", 290 nic->node_addr, ioaddr); 291 printf("natsemi_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id); 292 293 /* Reset the chip to erase any previous misconfiguration. */ 294 outl(ChipReset, ioaddr + ChipCmd); 295 296 advertising = mdio_read(1, 4); 297 { 298 u32 chip_config = inl(ioaddr + ChipConfig); 299 printf("%s: Transceiver default autoneg. %s " 300 "10%s %s duplex.\n", 301 nic_name, 302 chip_config & 0x2000 ? "enabled, advertise" : "disabled, force", 303 chip_config & 0x4000 ? "0" : "", 304 chip_config & 0x8000 ? "full" : "half"); 305 } 306 printf("%s: Transceiver status %hX advertising %hX\n", 307 nic_name, (int)inl(ioaddr + 0x84), advertising); 308 309 /* Disable PME: 310 * The PME bit is initialized from the EEPROM contents. 311 * PCI cards probably have PME disabled, but motherboard 312 * implementations may have PME set to enable WakeOnLan. 313 * With PME set the chip will scan incoming packets but 314 * nothing will be written to memory. */ 315 SavedClkRun = inl(ioaddr + ClkRun); 316 outl(SavedClkRun & ~0x100, ioaddr + ClkRun); 317 318 /* initialize device */ 319 natsemi_init(nic); 320 321 nic->reset = natsemi_init; 322 nic->poll = natsemi_poll; 323 nic->transmit = natsemi_transmit; 324 nic->disable = natsemi_disable; 325 326 return nic; 327 } 328 329 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. 330 The EEPROM code is for the common 93c06/46 EEPROMs with 6 bit addresses. 331 */ 332 333 /* Delay between EEPROM clock transitions. 334 No extra delay is needed with 33Mhz PCI, but future 66Mhz access may need 335 a delay. */ 336 #define eeprom_delay(ee_addr) inl(ee_addr) 337 338 enum EEPROM_Ctrl_Bits { 339 EE_ShiftClk = 0x04, 340 EE_DataIn = 0x01, 341 EE_ChipSelect = 0x08, 342 EE_DataOut = 0x02 343 }; 344 345 #define EE_Write0 (EE_ChipSelect) 346 #define EE_Write1 (EE_ChipSelect | EE_DataIn) 347 348 /* The EEPROM commands include the alway-set leading bit. */ 349 enum EEPROM_Cmds { 350 EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), 351 }; 352 353 static int eeprom_read(long addr, int location) 354 { 355 int i; 356 int retval = 0; 357 int ee_addr = addr + EECtrl; 358 int read_cmd = location | EE_ReadCmd; 359 outl(EE_Write0, ee_addr); 360 361 /* Shift the read command bits out. */ 362 for (i = 10; i >= 0; i--) { 363 short dataval = (read_cmd & (1 << i)) ? EE_Write1 : EE_Write0; 364 outl(dataval, ee_addr); 365 eeprom_delay(ee_addr); 366 outl(dataval | EE_ShiftClk, ee_addr); 367 eeprom_delay(ee_addr); 368 } 369 outl(EE_ChipSelect, ee_addr); 370 eeprom_delay(ee_addr); 371 372 for (i = 0; i < 16; i++) { 373 outl(EE_ChipSelect | EE_ShiftClk, ee_addr); 374 eeprom_delay(ee_addr); 375 retval |= (inl(ee_addr) & EE_DataOut) ? 1 << i : 0; 376 outl(EE_ChipSelect, ee_addr); 377 eeprom_delay(ee_addr); 378 } 379 380 /* Terminate the EEPROM access. */ 381 outl(EE_Write0, ee_addr); 382 outl(0, ee_addr); 383 384 return retval; 385 } 386 387 /* MII transceiver control section. 388 The 83815 series has an internal transceiver, and we present the 389 management registers as if they were MII connected. */ 390 391 static int mdio_read(int phy_id, int location) 392 { 393 if (phy_id == 1 && location < 32) 394 return inl(ioaddr + 0x80 + (location<<2)) & 0xffff; 395 else 396 return 0xffff; 397 } 398 399 /* Function: natsemi_init 400 * 401 * Description: resets the ethernet controller chip and configures 402 * registers and data structures required for sending and receiving packets. 403 * 404 * Arguments: struct nic *nic: NIC data structure 405 * 406 * returns: void. 407 */ 408 409 static void 410 natsemi_init(struct nic *nic) 411 { 412 natsemi_reset(nic); 413 414 /* Disable PME: 415 * The PME bit is initialized from the EEPROM contents. 416 * PCI cards probably have PME disabled, but motherboard 417 * implementations may have PME set to enable WakeOnLan. 418 * With PME set the chip will scan incoming packets but 419 * nothing will be written to memory. */ 420 outl(SavedClkRun & ~0x100, ioaddr + ClkRun); 421 422 natsemi_init_rxfilter(nic); 423 424 natsemi_init_txd(nic); 425 natsemi_init_rxd(nic); 426 427 /* Initialize other registers. */ 428 /* Configure the PCI bus bursts and FIFO thresholds. */ 429 /* Configure for standard, in-spec Ethernet. */ 430 if (inl(ioaddr + ChipConfig) & 0x20000000) { /* Full duplex */ 431 tx_config = 0xD0801002; 432 rx_config = 0x10000020; 433 } else { 434 tx_config = 0x10801002; 435 rx_config = 0x0020; 436 } 437 outl(tx_config, ioaddr + TxConfig); 438 outl(rx_config, ioaddr + RxConfig); 439 440 natsemi_check_duplex(nic); 441 natsemi_set_rx_mode(nic); 442 443 outl(RxOn, ioaddr + ChipCmd); 444 } 445 446 /* 447 * Function: natsemi_reset 448 * 449 * Description: soft resets the controller chip 450 * 451 * Arguments: struct nic *nic: NIC data structure 452 * 453 * Returns: void. 454 */ 455 static void 456 natsemi_reset(struct nic *nic) 457 { 458 outl(ChipReset, ioaddr + ChipCmd); 459 460 /* On page 78 of the spec, they recommend some settings for "optimum 461 performance" to be done in sequence. These settings optimize some 462 of the 100Mbit autodetection circuitry. Also, we only want to do 463 this for rev C of the chip. 464 */ 465 if (inl(ioaddr + SiliconRev) == 0x302) { 466 outw(0x0001, ioaddr + PGSEL); 467 outw(0x189C, ioaddr + PMDCSR); 468 outw(0x0000, ioaddr + TSTDAT); 469 outw(0x5040, ioaddr + DSPCFG); 470 outw(0x008C, ioaddr + SDCFG); 471 } 472 /* Disable interrupts using the mask. */ 473 outl(0, ioaddr + IntrMask); 474 outl(0, ioaddr + IntrEnable); 475 } 476 477 /* Function: natsemi_init_rxfilter 478 * 479 * Description: sets receive filter address to our MAC address 480 * 481 * Arguments: struct nic *nic: NIC data structure 482 * 483 * returns: void. 484 */ 485 486 static void 487 natsemi_init_rxfilter(struct nic *nic) 488 { 489 int i; 490 491 for (i = 0; i < ETH_ALEN; i += 2) { 492 outl(i, ioaddr + RxFilterAddr); 493 outw(nic->node_addr[i] + (nic->node_addr[i+1] << 8), ioaddr + RxFilterData); 494 } 495 } 496 497 /* 498 * Function: natsemi_init_txd 499 * 500 * Description: initializes the Tx descriptor 501 * 502 * Arguments: struct nic *nic: NIC data structure 503 * 504 * returns: void. 505 */ 506 507 static void 508 natsemi_init_txd(struct nic *nic) 509 { 510 txd.link = (u32) 0; 511 txd.cmdsts = (u32) 0; 512 txd.bufptr = (u32) &txb[0]; 513 514 /* load Transmit Descriptor Register */ 515 outl((u32) &txd, ioaddr + TxRingPtr); 516 if (natsemi_debug > 1) 517 printf("natsemi_init_txd: TX descriptor register loaded with: %X\n", 518 inl(ioaddr + TxRingPtr)); 519 } 520 521 /* Function: natsemi_init_rxd 522 * 523 * Description: initializes the Rx descriptor ring 524 * 525 * Arguments: struct nic *nic: NIC data structure 526 * 527 * Returns: void. 528 */ 529 530 static void 531 natsemi_init_rxd(struct nic *nic) 532 { 533 int i; 534 535 cur_rx = 0; 536 537 /* init RX descriptor */ 538 for (i = 0; i < NUM_RX_DESC; i++) { 539 rxd[i].link = (i+1 < NUM_RX_DESC) ? (u32) &rxd[i+1] : (u32) &rxd[0]; 540 rxd[i].cmdsts = (u32) RX_BUF_SIZE; 541 rxd[i].bufptr = (u32) &rxb[i*RX_BUF_SIZE]; 542 if (natsemi_debug > 1) 543 printf("natsemi_init_rxd: rxd[%d]=%X link=%X cmdsts=%X bufptr=%X\n", 544 i, &rxd[i], rxd[i].link, rxd[i].cmdsts, rxd[i].bufptr); 545 } 546 547 /* load Receive Descriptor Register */ 548 outl((u32) &rxd[0], ioaddr + RxRingPtr); 549 550 if (natsemi_debug > 1) 551 printf("natsemi_init_rxd: RX descriptor register loaded with: %X\n", 552 inl(ioaddr + RxRingPtr)); 553 } 554 555 /* Function: natsemi_set_rx_mode 556 * 557 * Description: 558 * sets the receive mode to accept all broadcast packets and packets 559 * with our MAC address, and reject all multicast packets. 560 * 561 * Arguments: struct nic *nic: NIC data structure 562 * 563 * Returns: void. 564 */ 565 566 static void natsemi_set_rx_mode(struct nic *nic) 567 { 568 u32 rx_mode = AcceptBroadcast | AcceptMyPhys; 569 570 outl(rx_mode, ioaddr + RxFilterAddr); 571 } 572 573 static void natsemi_check_duplex(struct nic *nic) 574 { 575 int duplex = inl(ioaddr + ChipConfig) & 0x20000000 ? 1 : 0; 576 577 if (natsemi_debug) 578 printf("%s: Setting %s-duplex based on negotiated link" 579 " capability.\n", nic_name, 580 duplex ? "full" : "half"); 581 if (duplex) { 582 rx_config |= 0x10000000; 583 tx_config |= 0xC0000000; 584 } else { 585 rx_config &= ~0x10000000; 586 tx_config &= ~0xC0000000; 587 } 588 outl(tx_config, ioaddr + TxConfig); 589 outl(rx_config, ioaddr + RxConfig); 590 } 591 592 /* Function: natsemi_transmit 593 * 594 * Description: transmits a packet and waits for completion or timeout. 595 * 596 * Arguments: char d[6]: destination ethernet address. 597 * unsigned short t: ethernet protocol type. 598 * unsigned short s: size of the data-part of the packet. 599 * char *p: the data for the packet. 600 * 601 * Returns: void. 602 */ 603 604 static void 605 natsemi_transmit(struct nic *nic, 606 const char *d, /* Destination */ 607 unsigned int t, /* Type */ 608 unsigned int s, /* size */ 609 const char *p) /* Packet */ 610 { 611 u32 status, to, nstype; 612 u32 tx_status; 613 614 /* Stop the transmitter */ 615 outl(TxOff, ioaddr + ChipCmd); 616 617 /* load Transmit Descriptor Register */ 618 outl((u32) &txd, ioaddr + TxRingPtr); 619 if (natsemi_debug > 1) 620 printf("natsemi_transmit: TX descriptor register loaded with: %X\n", 621 inl(ioaddr + TxRingPtr)); 622 623 memcpy(txb, d, ETH_ALEN); 624 memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN); 625 nstype = htons(t); 626 memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2); 627 memcpy(txb + ETH_HLEN, p, s); 628 629 s += ETH_HLEN; 630 s &= DSIZE; 631 632 if (natsemi_debug > 1) 633 printf("natsemi_transmit: sending %d bytes ethtype %hX\n", (int) s, t); 634 635 /* pad to minimum packet size */ 636 while (s < ETH_ZLEN) 637 txb[s++] = '\0'; 638 639 /* set the transmit buffer descriptor and enable Transmit State Machine */ 640 txd.bufptr = (u32) &txb[0]; 641 txd.cmdsts = (u32) OWN | s; 642 643 /* restart the transmitter */ 644 outl(TxOn, ioaddr + ChipCmd); 645 646 if (natsemi_debug > 1) 647 printf("natsemi_transmit: Queued Tx packet size %d.\n", (int) s); 648 649 to = currticks() + TX_TIMEOUT; 650 651 while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to)) 652 /* wait */ ; 653 654 if (currticks() >= to) { 655 printf("natsemi_transmit: TX Timeout! Tx status %X.\n", tx_status); 656 } 657 658 if (!(tx_status & 0x08000000)) { 659 printf("natsemi_transmit: Transmit error, Tx status %X.\n", tx_status); 660 } 661 } 662 663 /* Function: natsemi_poll 664 * 665 * Description: checks for a received packet and returns it if found. 666 * 667 * Arguments: struct nic *nic: NIC data structure 668 * 669 * Returns: 1 if packet was received. 670 * 0 if no packet was received. 671 * 672 * Side effects: 673 * Returns (copies) the packet to the array nic->packet. 674 * Returns the length of the packet in nic->packetlen. 675 */ 676 677 static int 678 natsemi_poll(struct nic *nic) 679 { 680 u32 rx_status = rxd[cur_rx].cmdsts; 681 int retstat = 0; 682 683 if (natsemi_debug > 2) 684 printf("natsemi_poll: cur_rx:%d, status:%X\n", cur_rx, rx_status); 685 686 if (!(rx_status & OWN)) 687 return retstat; 688 689 if (natsemi_debug > 1) 690 printf("natsemi_poll: got a packet: cur_rx:%d, status:%X\n", 691 cur_rx, rx_status); 692 693 nic->packetlen = (rx_status & DSIZE) - CRC_SIZE; 694 695 if ((rx_status & (DescMore|DescPktOK|RxTooLong)) != DescPktOK) { 696 /* corrupted packet received */ 697 printf("natsemi_poll: Corrupted packet received, buffer status = %X\n", 698 rx_status); 699 retstat = 0; 700 } else { 701 /* give packet to higher level routine */ 702 memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen); 703 retstat = 1; 704 } 705 706 /* return the descriptor and buffer to receive ring */ 707 rxd[cur_rx].cmdsts = RX_BUF_SIZE; 708 rxd[cur_rx].bufptr = (u32) &rxb[cur_rx*RX_BUF_SIZE]; 709 710 if (++cur_rx == NUM_RX_DESC) 711 cur_rx = 0; 712 713 /* re-enable the potentially idle receive state machine */ 714 outl(RxOn, ioaddr + ChipCmd); 715 716 return retstat; 717 } 718 719 /* Function: natsemi_disable 720 * 721 * Description: Turns off interrupts and stops Tx and Rx engines 722 * 723 * Arguments: struct nic *nic: NIC data structure 724 * 725 * Returns: void. 726 */ 727 728 static void 729 natsemi_disable(struct nic *nic) 730 { 731 /* Disable interrupts using the mask. */ 732 outl(0, ioaddr + IntrMask); 733 outl(0, ioaddr + IntrEnable); 734 735 /* Stop the chip's Tx and Rx processes. */ 736 outl(RxOff | TxOff, ioaddr + ChipCmd); 737 738 /* Restore PME enable bit */ 739 outl(SavedClkRun, ioaddr + ClkRun); 740 } 741