Home | History | Annotate | Download | only in netboot
      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, &reg);
    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