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