1/* -*- Mode:C; c-basic-offset:4; -*- */ 2 3/* 4 sis900.c: An SiS 900/7016 PCI Fast Ethernet driver for Etherboot 5 Copyright (C) 2001 Entity Cyber, Inc. 6 7 Revision: 1.0 March 1, 2001 8 9 Author: Marty Connor (mdc@thinguin.org) 10 11 Adapted from a Linux driver which was written by Donald Becker 12 and modified by Ollie Lho and Chin-Shan Li of SiS Corporation. 13 Rewritten for Etherboot by Marty Connor. 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 References: 19 SiS 7016 Fast Ethernet PCI Bus 10/100 Mbps LAN Controller with OnNow Support, 20 preliminary Rev. 1.0 Jan. 14, 1998 21 SiS 900 Fast Ethernet PCI Bus 10/100 Mbps LAN Single Chip with OnNow Support, 22 preliminary Rev. 1.0 Nov. 10, 1998 23 SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution, 24 preliminary Rev. 1.0 Jan. 18, 1998 25 http://www.sis.com.tw/support/databook.htm */ 26 27/* Revision History */ 28 29/* 30 01 March 2001 mdc 1.0 31 Initial Release. Tested with PCI based sis900 card and ThinkNIC 32 computer. 33 20 March 2001 P.Koegel 34 added support for sis630e and PHY ICS1893 and RTL8201 35 Testet with SIS730S chipset + ICS1893 36*/ 37 38 39/* Includes */ 40 41#include "etherboot.h" 42#include "nic.h" 43#include "pci.h" 44#include "cards.h" 45 46#include "sis900.h" 47 48/* Globals */ 49 50static int sis900_debug = 0; 51 52static unsigned short vendor, dev_id; 53static unsigned long ioaddr; 54 55static unsigned int cur_phy; 56 57static unsigned int cur_rx; 58 59static BufferDesc txd; 60static BufferDesc rxd[NUM_RX_DESC]; 61 62#ifdef USE_LOWMEM_BUFFER 63#define txb ((char *)0x10000 - TX_BUF_SIZE) 64#define rxb ((char *)0x10000 - NUM_RX_DESC*RX_BUF_SIZE - TX_BUF_SIZE) 65#else 66static unsigned char txb[TX_BUF_SIZE]; 67static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE]; 68#endif 69 70static struct mac_chip_info { 71 const char *name; 72 u16 vendor_id, device_id, flags; 73 int io_size; 74} mac_chip_table[] = { 75 { "SiS 900 PCI Fast Ethernet", PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900, 76 PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE}, 77 { "SiS 7016 PCI Fast Ethernet",PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016, 78 PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE}, 79 {0,0,0,0,0} /* 0 terminated list. */ 80}; 81 82static void sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex); 83static void amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex); 84static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex); 85static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex); 86 87static struct mii_chip_info { 88 const char * name; 89 u16 phy_id0; 90 u16 phy_id1; 91 void (*read_mode) (struct nic *nic, int phy_addr, int *speed, int *duplex); 92} mii_chip_table[] = { 93 {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode}, 94 {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode}, 95 {"AMD 79C901 10BASE-T PHY", 0x0000, 0x35b9, amd79c901_read_mode}, 96 {"AMD 79C901 HomePNA PHY", 0x0000, 0x35c8, amd79c901_read_mode}, 97 {"ICS 1893 Integrated PHYceiver" , 0x0015, 0xf441,ics1893_read_mode}, 98 {"RTL 8201 10/100Mbps Phyceiver" , 0x0000, 0x8201,rtl8201_read_mode}, 99 {0,0,0,0} 100}; 101 102static struct mii_phy { 103 struct mii_phy * next; 104 struct mii_chip_info * chip_info; 105 int phy_addr; 106 u16 status; 107} mii; 108 109 110// PCI to ISA bridge for SIS640E access 111static struct pci_device pci_isa_bridge_list[] = { 112 { 0x1039, 0x0008, 113 "SIS 85C503/5513 PCI to ISA bridge", 0, 0, 0, 0}, 114 {0, 0, NULL, 0, 0, 0, 0} 115}; 116 117/* Function Prototypes */ 118 119struct nic *sis900_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci); 120 121static u16 sis900_read_eeprom(int location); 122static void sis900_mdio_reset(long mdio_addr); 123static void sis900_mdio_idle(long mdio_addr); 124static u16 sis900_mdio_read(int phy_id, int location); 125static void sis900_mdio_write(int phy_id, int location, int val); 126 127static void sis900_init(struct nic *nic); 128 129static void sis900_reset(struct nic *nic); 130 131static void sis900_init_rxfilter(struct nic *nic); 132static void sis900_init_txd(struct nic *nic); 133static void sis900_init_rxd(struct nic *nic); 134static void sis900_set_rx_mode(struct nic *nic); 135static void sis900_check_mode(struct nic *nic); 136 137static void sis900_transmit(struct nic *nic, const char *d, 138 unsigned int t, unsigned int s, const char *p); 139static int sis900_poll(struct nic *nic); 140 141static void sis900_disable(struct nic *nic); 142 143/** 144 * sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model 145 * @pci_dev: the sis900 pci device 146 * @net_dev: the net device to get address for 147 * 148 * Older SiS900 and friends, use EEPROM to store MAC address. 149 * MAC address is read from read_eeprom() into @net_dev->dev_addr. 150 */ 151 152static int sis900_get_mac_addr(struct pci_device * pci_dev , struct nic *nic) 153{ 154 u16 signature; 155 int i; 156 157 /* check to see if we have sane EEPROM */ 158 signature = (u16) sis900_read_eeprom( EEPROMSignature); 159 if (signature == 0xffff || signature == 0x0000) { 160 printf ("sis900_probe: Error EERPOM read %hX\n", signature); 161 return 0; 162 } 163 164 /* get MAC address from EEPROM */ 165 for (i = 0; i < 3; i++) 166 ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr); 167 return 1; 168} 169 170/** 171 * sis630e_get_mac_addr: - Get MAC address for SiS630E model 172 * @pci_dev: the sis900 pci device 173 * @net_dev: the net device to get address for 174 * 175 * SiS630E model, use APC CMOS RAM to store MAC address. 176 * APC CMOS RAM is accessed through ISA bridge. 177 * MAC address is read into @net_dev->dev_addr. 178 */ 179 180static int sis630e_get_mac_addr(struct pci_device * pci_dev, struct nic *nic) 181{ 182 u8 reg; 183 int i; 184 struct pci_device *p; 185 186 // find PCI to ISA bridge 187 eth_pci_init(pci_isa_bridge_list); 188 189 /* the firts entry in this list should contain bus/devfn */ 190 p = pci_isa_bridge_list; 191 192 pcibios_read_config_byte(p->bus,p->devfn, 0x48, ®); 193 pcibios_write_config_byte(p->bus,p->devfn, 0x48, reg | 0x40); 194 195 for (i = 0; i < ETH_ALEN; i++) 196 { 197 outb(0x09 + i, 0x70); 198 ((u8 *)(nic->node_addr))[i] = inb(0x71); 199 } 200 pcibios_write_config_byte(p->bus,p->devfn, 0x48, reg & ~0x40); 201 202 return 1; 203} 204 205/* 206 * Function: sis900_probe 207 * 208 * Description: initializes initializes the NIC, retrieves the 209 * MAC address of the card, and sets up some globals required by 210 * other routines. 211 * 212 * Side effects: 213 * leaves the ioaddress of the sis900 chip in the variable ioaddr. 214 * leaves the sis900 initialized, and ready to recieve packets. 215 * 216 * Returns: struct nic *: pointer to NIC data structure 217 */ 218 219struct nic *sis900_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci) 220{ 221 int i; 222 int found=0; 223 int phy_addr; 224 u16 signature; 225 u8 revision; 226 int ret; 227 228 if (io_addrs == 0 || *io_addrs == 0) 229 return NULL; 230 231 ioaddr = *io_addrs & ~3; 232 vendor = pci->vendor; 233 dev_id = pci->dev_id; 234 235 /* wakeup chip */ 236 pcibios_write_config_dword(pci->bus, pci->devfn, 0x40, 0x00000000); 237 238 adjust_pci_device(pci); 239 240 /* get MAC address */ 241 ret = 0; 242 pcibios_read_config_byte(pci->bus,pci->devfn, PCI_REVISION, &revision); 243 if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV) 244 ret = sis630e_get_mac_addr(pci, nic); 245 else if (revision == SIS630S_900_REV) 246 ret = sis630e_get_mac_addr(pci, nic); 247 else 248 ret = sis900_get_mac_addr(pci, nic); 249 250 if (ret == 0) 251 { 252 printf ("sis900_probe: Error MAC address not found\n"); 253 return NULL; 254 } 255 256 printf("\nsis900_probe: MAC addr %! at ioaddr %#hX\n", 257 nic->node_addr, ioaddr); 258 printf("sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id); 259 260 /* probe for mii transceiver */ 261 /* search for total of 32 possible mii phy addresses */ 262 263 found = 0; 264 for (phy_addr = 0; phy_addr < 32; phy_addr++) { 265 u16 mii_status; 266 u16 phy_id0, phy_id1; 267 268 mii_status = sis900_mdio_read(phy_addr, MII_STATUS); 269 if (mii_status == 0xffff || mii_status == 0x0000) 270 /* the mii is not accessable, try next one */ 271 continue; 272 273 phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0); 274 phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1); 275 276 /* search our mii table for the current mii */ 277 for (i = 0; mii_chip_table[i].phy_id1; i++) { 278 279 if (phy_id0 == mii_chip_table[i].phy_id0) { 280 281 printf("sis900_probe: %s transceiver found at address %d.\n", 282 mii_chip_table[i].name, phy_addr); 283 284 mii.chip_info = &mii_chip_table[i]; 285 mii.phy_addr = phy_addr; 286 mii.status = sis900_mdio_read(phy_addr, MII_STATUS); 287 mii.next = NULL; 288 289 found=1; 290 break; 291 } 292 } 293 } 294 295 if (found == 0) { 296 printf("sis900_probe: No MII transceivers found!\n"); 297 return NULL; 298 } 299 300 /* Arbitrarily select the last PHY found as current PHY */ 301 cur_phy = mii.phy_addr; 302 printf("sis900_probe: Using %s as default\n", mii.chip_info->name); 303 304 /* initialize device */ 305 sis900_init(nic); 306 307 nic->reset = sis900_init; 308 nic->poll = sis900_poll; 309 nic->transmit = sis900_transmit; 310 nic->disable = sis900_disable; 311 312 return nic; 313} 314 315 316/* 317 * EEPROM Routines: These functions read and write to EEPROM for 318 * retrieving the MAC address and other configuration information about 319 * the card. 320 */ 321 322/* Delay between EEPROM clock transitions. */ 323#define eeprom_delay() inl(ee_addr) 324 325 326/* Function: sis900_read_eeprom 327 * 328 * Description: reads and returns a given location from EEPROM 329 * 330 * Arguments: int location: requested EEPROM location 331 * 332 * Returns: u16: contents of requested EEPROM location 333 * 334 */ 335 336/* Read Serial EEPROM through EEPROM Access Register, Note that location is 337 in word (16 bits) unit */ 338static u16 sis900_read_eeprom(int location) 339{ 340 int i; 341 u16 retval = 0; 342 long ee_addr = ioaddr + mear; 343 u32 read_cmd = location | EEread; 344 345 outl(0, ee_addr); 346 eeprom_delay(); 347 outl(EECLK, ee_addr); 348 eeprom_delay(); 349 350 /* Shift the read command (9) bits out. */ 351 for (i = 8; i >= 0; i--) { 352 u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS; 353 outl(dataval, ee_addr); 354 eeprom_delay(); 355 outl(dataval | EECLK, ee_addr); 356 eeprom_delay(); 357 } 358 outb(EECS, ee_addr); 359 eeprom_delay(); 360 361 /* read the 16-bits data in */ 362 for (i = 16; i > 0; i--) { 363 outl(EECS, ee_addr); 364 eeprom_delay(); 365 outl(EECS | EECLK, ee_addr); 366 eeprom_delay(); 367 retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0); 368 eeprom_delay(); 369 } 370 371 /* Terminate the EEPROM access. */ 372 outl(0, ee_addr); 373 eeprom_delay(); 374 outl(EECLK, ee_addr); 375 376 return (retval); 377} 378 379#define sis900_mdio_delay() inl(mdio_addr) 380 381 382/* 383 Read and write the MII management registers using software-generated 384 serial MDIO protocol. Note that the command bits and data bits are 385 send out seperately 386*/ 387 388static void sis900_mdio_idle(long mdio_addr) 389{ 390 outl(MDIO | MDDIR, mdio_addr); 391 sis900_mdio_delay(); 392 outl(MDIO | MDDIR | MDC, mdio_addr); 393} 394 395/* Syncronize the MII management interface by shifting 32 one bits out. */ 396static void sis900_mdio_reset(long mdio_addr) 397{ 398 int i; 399 400 for (i = 31; i >= 0; i--) { 401 outl(MDDIR | MDIO, mdio_addr); 402 sis900_mdio_delay(); 403 outl(MDDIR | MDIO | MDC, mdio_addr); 404 sis900_mdio_delay(); 405 } 406 return; 407} 408 409static u16 sis900_mdio_read(int phy_id, int location) 410{ 411 long mdio_addr = ioaddr + mear; 412 int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift); 413 u16 retval = 0; 414 int i; 415 416 sis900_mdio_reset(mdio_addr); 417 sis900_mdio_idle(mdio_addr); 418 419 for (i = 15; i >= 0; i--) { 420 int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR; 421 outl(dataval, mdio_addr); 422 sis900_mdio_delay(); 423 outl(dataval | MDC, mdio_addr); 424 sis900_mdio_delay(); 425 } 426 427 /* Read the 16 data bits. */ 428 for (i = 16; i > 0; i--) { 429 outl(0, mdio_addr); 430 sis900_mdio_delay(); 431 retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0); 432 outl(MDC, mdio_addr); 433 sis900_mdio_delay(); 434 } 435 return retval; 436} 437 438static void sis900_mdio_write(int phy_id, int location, int value) 439{ 440 long mdio_addr = ioaddr + mear; 441 int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift); 442 int i; 443 444 sis900_mdio_reset(mdio_addr); 445 sis900_mdio_idle(mdio_addr); 446 447 /* Shift the command bits out. */ 448 for (i = 15; i >= 0; i--) { 449 int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR; 450 outb(dataval, mdio_addr); 451 sis900_mdio_delay(); 452 outb(dataval | MDC, mdio_addr); 453 sis900_mdio_delay(); 454 } 455 sis900_mdio_delay(); 456 457 /* Shift the value bits out. */ 458 for (i = 15; i >= 0; i--) { 459 int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR; 460 outl(dataval, mdio_addr); 461 sis900_mdio_delay(); 462 outl(dataval | MDC, mdio_addr); 463 sis900_mdio_delay(); 464 } 465 sis900_mdio_delay(); 466 467 /* Clear out extra bits. */ 468 for (i = 2; i > 0; i--) { 469 outb(0, mdio_addr); 470 sis900_mdio_delay(); 471 outb(MDC, mdio_addr); 472 sis900_mdio_delay(); 473 } 474 return; 475} 476 477 478/* Function: sis900_init 479 * 480 * Description: resets the ethernet controller chip and various 481 * data structures required for sending and receiving packets. 482 * 483 * Arguments: struct nic *nic: NIC data structure 484 * 485 * returns: void. 486 */ 487 488static void 489sis900_init(struct nic *nic) 490{ 491 /* Soft reset the chip. */ 492 sis900_reset(nic); 493 494 sis900_init_rxfilter(nic); 495 496 sis900_init_txd(nic); 497 sis900_init_rxd(nic); 498 499 sis900_set_rx_mode(nic); 500 501 sis900_check_mode(nic); 502 503 outl(RxENA, ioaddr + cr); 504} 505 506 507/* 508 * Function: sis900_reset 509 * 510 * Description: disables interrupts and soft resets the controller chip 511 * 512 * Arguments: struct nic *nic: NIC data structure 513 * 514 * Returns: void. 515 */ 516 517static void 518sis900_reset(struct nic *nic) 519{ 520 int i = 0; 521 u32 status = TxRCMP | RxRCMP; 522 523 outl(0, ioaddr + ier); 524 outl(0, ioaddr + imr); 525 outl(0, ioaddr + rfcr); 526 527 outl(RxRESET | TxRESET | RESET, ioaddr + cr); 528 529 /* Check that the chip has finished the reset. */ 530 while (status && (i++ < 1000)) { 531 status ^= (inl(isr + ioaddr) & status); 532 } 533 outl(PESEL, ioaddr + cfg); 534} 535 536 537/* Function: sis_init_rxfilter 538 * 539 * Description: sets receive filter address to our MAC address 540 * 541 * Arguments: struct nic *nic: NIC data structure 542 * 543 * returns: void. 544 */ 545 546static void 547sis900_init_rxfilter(struct nic *nic) 548{ 549 u32 rfcrSave; 550 int i; 551 552 rfcrSave = inl(rfcr + ioaddr); 553 554 /* disable packet filtering before setting filter */ 555 outl(rfcrSave & ~RFEN, rfcr); 556 557 /* load MAC addr to filter data register */ 558 for (i = 0 ; i < 3 ; i++) { 559 u32 w; 560 561 w = (u32) *((u16 *)(nic->node_addr)+i); 562 outl((i << RFADDR_shift), ioaddr + rfcr); 563 outl(w, ioaddr + rfdr); 564 565 if (sis900_debug > 0) 566 printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n", 567 i, inl(ioaddr + rfdr)); 568 } 569 570 /* enable packet filitering */ 571 outl(rfcrSave | RFEN, rfcr + ioaddr); 572} 573 574 575/* 576 * Function: sis_init_txd 577 * 578 * Description: initializes the Tx descriptor 579 * 580 * Arguments: struct nic *nic: NIC data structure 581 * 582 * returns: void. 583 */ 584 585static void 586sis900_init_txd(struct nic *nic) 587{ 588 txd.link = (u32) 0; 589 txd.cmdsts = (u32) 0; 590 txd.bufptr = (u32) &txb[0]; 591 592 /* load Transmit Descriptor Register */ 593 outl((u32) &txd, ioaddr + txdp); 594 if (sis900_debug > 0) 595 printf("sis900_init_txd: TX descriptor register loaded with: %X\n", 596 inl(ioaddr + txdp)); 597} 598 599 600/* Function: sis_init_rxd 601 * 602 * Description: initializes the Rx descriptor ring 603 * 604 * Arguments: struct nic *nic: NIC data structure 605 * 606 * Returns: void. 607 */ 608 609static void 610sis900_init_rxd(struct nic *nic) 611{ 612 int i; 613 614 cur_rx = 0; 615 616 /* init RX descriptor */ 617 for (i = 0; i < NUM_RX_DESC; i++) { 618 rxd[i].link = (i+1 < NUM_RX_DESC) ? (u32) &rxd[i+1] : (u32) &rxd[0]; 619 rxd[i].cmdsts = (u32) RX_BUF_SIZE; 620 rxd[i].bufptr = (u32) &rxb[i*RX_BUF_SIZE]; 621 if (sis900_debug > 0) 622 printf("sis900_init_rxd: rxd[%d]=%X link=%X cmdsts=%X bufptr=%X\n", 623 i, &rxd[i], rxd[i].link, rxd[i].cmdsts, rxd[i].bufptr); 624 } 625 626 /* load Receive Descriptor Register */ 627 outl((u32) &rxd[0], ioaddr + rxdp); 628 629 if (sis900_debug > 0) 630 printf("sis900_init_rxd: RX descriptor register loaded with: %X\n", 631 inl(ioaddr + rxdp)); 632 633} 634 635 636/* Function: sis_init_rxd 637 * 638 * Description: 639 * sets the receive mode to accept all broadcast packets and packets 640 * with our MAC address, and reject all multicast packets. 641 * 642 * Arguments: struct nic *nic: NIC data structure 643 * 644 * Returns: void. 645 */ 646 647static void sis900_set_rx_mode(struct nic *nic) 648{ 649 int i; 650 651 /* Configure Multicast Hash Table in Receive Filter 652 to reject all MCAST packets */ 653 for (i = 0; i < 8; i++) { 654 /* why plus 0x04? That makes the correct value for hash table. */ 655 outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr); 656 outl((u32)(0x0), ioaddr + rfdr); 657 } 658 /* Accept Broadcast packets, destination addresses that match 659 our MAC address */ 660 outl(RFEN | RFAAB, ioaddr + rfcr); 661 662 return; 663} 664 665 666/* Function: sis900_check_mode 667 * 668 * Description: checks the state of transmit and receive 669 * parameters on the NIC, and updates NIC registers to match 670 * 671 * Arguments: struct nic *nic: NIC data structure 672 * 673 * Returns: void. 674 */ 675 676static void 677sis900_check_mode (struct nic *nic) 678{ 679 int speed, duplex; 680 u32 tx_flags = 0, rx_flags = 0; 681 682 mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex); 683 684 tx_flags = TxATP | (TX_DMA_BURST << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift); 685 rx_flags = RX_DMA_BURST << RxMXDMA_shift; 686 687 if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) { 688 rx_flags |= (RxDRNT_10 << RxDRNT_shift); 689 tx_flags |= (TxDRNT_10 << TxDRNT_shift); 690 } 691 else { 692 rx_flags |= (RxDRNT_100 << RxDRNT_shift); 693 tx_flags |= (TxDRNT_100 << TxDRNT_shift); 694 } 695 696 if (duplex == FDX_CAPABLE_FULL_SELECTED) { 697 tx_flags |= (TxCSI | TxHBI); 698 rx_flags |= RxATX; 699 } 700 701 outl (tx_flags, ioaddr + txcfg); 702 outl (rx_flags, ioaddr + rxcfg); 703} 704 705 706/* Function: sis900_read_mode 707 * 708 * Description: retrieves and displays speed and duplex 709 * parameters from the NIC 710 * 711 * Arguments: struct nic *nic: NIC data structure 712 * 713 * Returns: void. 714 */ 715 716static void 717sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex) 718{ 719 int i = 0; 720 u32 status; 721 722 /* STSOUT register is Latched on Transition, read operation updates it */ 723 while (i++ < 2) 724 status = sis900_mdio_read(phy_addr, MII_STSOUT); 725 726 if (status & MII_STSOUT_SPD) 727 *speed = HW_SPEED_100_MBPS; 728 else 729 *speed = HW_SPEED_10_MBPS; 730 731 if (status & MII_STSOUT_DPLX) 732 *duplex = FDX_CAPABLE_FULL_SELECTED; 733 else 734 *duplex = FDX_CAPABLE_HALF_SELECTED; 735 736 if (status & MII_STSOUT_LINK_FAIL) 737 printf("sis900_read_mode: Media Link Off\n"); 738 else 739 printf("sis900_read_mode: Media Link On %s %s-duplex \n", 740 *speed == HW_SPEED_100_MBPS ? 741 "100mbps" : "10mbps", 742 *duplex == FDX_CAPABLE_FULL_SELECTED ? 743 "full" : "half"); 744} 745 746 747/* Function: amd79c901_read_mode 748 * 749 * Description: retrieves and displays speed and duplex 750 * parameters from the NIC 751 * 752 * Arguments: struct nic *nic: NIC data structure 753 * 754 * Returns: void. 755 */ 756 757static void 758amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex) 759{ 760 int i; 761 u16 status; 762 763 for (i = 0; i < 2; i++) 764 status = sis900_mdio_read(phy_addr, MII_STATUS); 765 766 if (status & MII_STAT_CAN_AUTO) { 767 /* 10BASE-T PHY */ 768 for (i = 0; i < 2; i++) 769 status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY); 770 if (status & MII_STSSUM_SPD) 771 *speed = HW_SPEED_100_MBPS; 772 else 773 *speed = HW_SPEED_10_MBPS; 774 if (status & MII_STSSUM_DPLX) 775 *duplex = FDX_CAPABLE_FULL_SELECTED; 776 else 777 *duplex = FDX_CAPABLE_HALF_SELECTED; 778 779 if (status & MII_STSSUM_LINK) 780 printf("amd79c901_read_mode: Media Link On %s %s-duplex \n", 781 *speed == HW_SPEED_100_MBPS ? 782 "100mbps" : "10mbps", 783 *duplex == FDX_CAPABLE_FULL_SELECTED ? 784 "full" : "half"); 785 else 786 printf("amd79c901_read_mode: Media Link Off\n"); 787 } 788 else { 789 /* HomePNA */ 790 *speed = HW_SPEED_HOME; 791 *duplex = FDX_CAPABLE_HALF_SELECTED; 792 if (status & MII_STAT_LINK) 793 printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n"); 794 else 795 printf("amd79c901_read_mode: Media Link Off\n"); 796 } 797} 798 799 800/** 801 * ics1893_read_mode: - read media mode for ICS1893 PHY 802 * @net_dev: the net device to read mode for 803 * @phy_addr: mii phy address 804 * @speed: the transmit speed to be determined 805 * @duplex: the duplex mode to be determined 806 * 807 * ICS1893 PHY use Quick Poll Detailed Status register 808 * to determine the speed and duplex mode for sis900 809 */ 810 811static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex) 812{ 813 int i = 0; 814 u32 status; 815 816 /* MII_QPDSTS is Latched, read twice in succession will reflect the current state */ 817 for (i = 0; i < 2; i++) 818 status = sis900_mdio_read(phy_addr, MII_QPDSTS); 819 820 if (status & MII_STSICS_SPD) 821 *speed = HW_SPEED_100_MBPS; 822 else 823 *speed = HW_SPEED_10_MBPS; 824 825 if (status & MII_STSICS_DPLX) 826 *duplex = FDX_CAPABLE_FULL_SELECTED; 827 else 828 *duplex = FDX_CAPABLE_HALF_SELECTED; 829 830 if (status & MII_STSICS_LINKSTS) 831 printf("ics1893_read_mode: Media Link On %s %s-duplex \n", 832 *speed == HW_SPEED_100_MBPS ? 833 "100mbps" : "10mbps", 834 *duplex == FDX_CAPABLE_FULL_SELECTED ? 835 "full" : "half"); 836 else 837 printf("ics1893_read_mode: Media Link Off\n"); 838} 839 840/** 841 * rtl8201_read_mode: - read media mode for rtl8201 phy 842 * @nic: the net device to read mode for 843 * @phy_addr: mii phy address 844 * @speed: the transmit speed to be determined 845 * @duplex: the duplex mode to be determined 846 * 847 * read MII_STATUS register from rtl8201 phy 848 * to determine the speed and duplex mode for sis900 849 */ 850 851static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex) 852{ 853 u32 status; 854 855 status = sis900_mdio_read(phy_addr, MII_STATUS); 856 857 if (status & MII_STAT_CAN_TX_FDX) { 858 *speed = HW_SPEED_100_MBPS; 859 *duplex = FDX_CAPABLE_FULL_SELECTED; 860 } 861 else if (status & MII_STAT_CAN_TX) { 862 *speed = HW_SPEED_100_MBPS; 863 *duplex = FDX_CAPABLE_HALF_SELECTED; 864 } 865 else if (status & MII_STAT_CAN_T_FDX) { 866 *speed = HW_SPEED_10_MBPS; 867 *duplex = FDX_CAPABLE_FULL_SELECTED; 868 } 869 else if (status & MII_STAT_CAN_T) { 870 *speed = HW_SPEED_10_MBPS; 871 *duplex = FDX_CAPABLE_HALF_SELECTED; 872 } 873 874 if (status & MII_STAT_LINK) 875 printf("rtl8201_read_mode: Media Link On %s %s-duplex \n", 876 *speed == HW_SPEED_100_MBPS ? 877 "100mbps" : "10mbps", 878 *duplex == FDX_CAPABLE_FULL_SELECTED ? 879 "full" : "half"); 880 else 881 printf("rtl9201_read_config_mode: Media Link Off\n"); 882} 883 884/* Function: sis900_transmit 885 * 886 * Description: transmits a packet and waits for completion or timeout. 887 * 888 * Arguments: char d[6]: destination ethernet address. 889 * unsigned short t: ethernet protocol type. 890 * unsigned short s: size of the data-part of the packet. 891 * char *p: the data for the packet. 892 * 893 * Returns: void. 894 */ 895 896static void 897sis900_transmit(struct nic *nic, 898 const char *d, /* Destination */ 899 unsigned int t, /* Type */ 900 unsigned int s, /* size */ 901 const char *p) /* Packet */ 902{ 903 u32 status, to, nstype; 904 u32 tx_status; 905 906 /* Stop the transmitter */ 907 outl(TxDIS, ioaddr + cr); 908 909 /* load Transmit Descriptor Register */ 910 outl((u32) &txd, ioaddr + txdp); 911 if (sis900_debug > 1) 912 printf("sis900_transmit: TX descriptor register loaded with: %X\n", 913 inl(ioaddr + txdp)); 914 915 memcpy(txb, d, ETH_ALEN); 916 memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN); 917 nstype = htons(t); 918 memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2); 919 memcpy(txb + ETH_HLEN, p, s); 920 921 s += ETH_HLEN; 922 s &= DSIZE; 923 924 if (sis900_debug > 1) 925 printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t); 926 927 /* pad to minimum packet size */ 928 while (s < ETH_ZLEN) 929 txb[s++] = '\0'; 930 931 /* set the transmit buffer descriptor and enable Transmit State Machine */ 932 txd.bufptr = (u32) &txb[0]; 933 txd.cmdsts = (u32) OWN | s; 934 935 /* restart the transmitter */ 936 outl(TxENA, ioaddr + cr); 937 938 if (sis900_debug > 1) 939 printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s); 940 941 to = currticks() + TX_TIMEOUT; 942 943 while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to)) 944 /* wait */ ; 945 946 if (currticks() >= to) { 947 printf("sis900_transmit: TX Timeout! Tx status %X.\n", tx_status); 948 } 949 950 if (tx_status & (ABORT | UNDERRUN | OWCOLL)) { 951 /* packet unsuccessfully transmited */ 952 printf("sis900_transmit: Transmit error, Tx status %X.\n", tx_status); 953 } 954 /* Disable interrupts by clearing the interrupt mask. */ 955 outl(0, ioaddr + imr); 956} 957 958 959/* Function: sis900_poll 960 * 961 * Description: checks for a received packet and returns it if found. 962 * 963 * Arguments: struct nic *nic: NIC data structure 964 * 965 * Returns: 1 if a packet was recieved. 966 * 0 if no pacet was recieved. 967 * 968 * Side effects: 969 * Returns (copies) the packet to the array nic->packet. 970 * Returns the length of the packet in nic->packetlen. 971 */ 972 973static int 974sis900_poll(struct nic *nic) 975{ 976 u32 rx_status = rxd[cur_rx].cmdsts; 977 int retstat = 0; 978 979 if (sis900_debug > 2) 980 printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx, rx_status); 981 982 if (!(rx_status & OWN)) 983 return retstat; 984 985 if (sis900_debug > 1) 986 printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n", 987 cur_rx, rx_status); 988 989 nic->packetlen = (rx_status & DSIZE) - CRC_SIZE; 990 991 if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) { 992 /* corrupted packet received */ 993 printf("sis900_poll: Corrupted packet received, buffer status = %X\n", 994 rx_status); 995 retstat = 0; 996 } else { 997 /* give packet to higher level routine */ 998 memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen); 999 retstat = 1; 1000 } 1001 1002 /* return the descriptor and buffer to receive ring */ 1003 rxd[cur_rx].cmdsts = RX_BUF_SIZE; 1004 rxd[cur_rx].bufptr = (u32) &rxb[cur_rx*RX_BUF_SIZE]; 1005 1006 if (++cur_rx == NUM_RX_DESC) 1007 cur_rx = 0; 1008 1009 /* re-enable the potentially idle receive state machine */ 1010 outl(RxENA , ioaddr + cr); 1011 1012 return retstat; 1013} 1014 1015 1016/* Function: sis900_disable 1017 * 1018 * Description: Turns off interrupts and stops Tx and Rx engines 1019 * 1020 * Arguments: struct nic *nic: NIC data structure 1021 * 1022 * Returns: void. 1023 */ 1024 1025static void 1026sis900_disable(struct nic *nic) 1027{ 1028 /* Disable interrupts by clearing the interrupt mask. */ 1029 outl(0, ioaddr + imr); 1030 outl(0, ioaddr + ier); 1031 1032 /* Stop the chip's Tx and Rx Status Machine */ 1033 outl(RxDIS | TxDIS, ioaddr + cr); 1034} 1035