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