iPXE
Data Structures | Defines | Functions | Variables
sis900.c File Reference
#include "etherboot.h"
#include <ipxe/pci.h>
#include "nic.h"
#include "sis900.h"

Go to the source code of this file.

Data Structures

struct  mii_chip_info
struct  mii_phy

Defines

#define txd   sis900_bufs.txd
#define rxd   sis900_bufs.rxd
#define txb   sis900_bufs.txb
#define rxb   sis900_bufs.rxb
#define eeprom_delay()   inl(ee_addr)
#define sis900_mdio_delay()   inl(mdio_addr)

Functions

 FILE_LICENCE (GPL_ANY)
static void sis900_read_mode (struct nic *nic, int phy_addr, int *speed, int *duplex)
static void amd79c901_read_mode (struct nic *nic, int phy_addr, int *speed, int *duplex)
static void ics1893_read_mode (struct nic *nic, int phy_addr, int *speed, int *duplex)
static void rtl8201_read_mode (struct nic *nic, int phy_addr, int *speed, int *duplex)
static void vt6103_read_mode (struct nic *nic, int phy_addr, int *speed, int *duplex)
static int sis900_probe (struct nic *nic, struct pci_device *pci)
static u16 sis900_read_eeprom (int location)
static void sis900_mdio_reset (long mdio_addr)
static void sis900_mdio_idle (long mdio_addr)
static u16 sis900_mdio_read (int phy_id, int location)
static void sis900_init (struct nic *nic)
static void sis900_reset (struct nic *nic)
static void sis900_init_rxfilter (struct nic *nic)
static void sis900_init_txd (struct nic *nic)
static void sis900_init_rxd (struct nic *nic)
static void sis900_set_rx_mode (struct nic *nic)
static void sis900_check_mode (struct nic *nic)
static void sis900_transmit (struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p)
static int sis900_poll (struct nic *nic, int retrieve)
static void sis900_disable (struct nic *nic)
static void sis900_irq (struct nic *nic, irq_action_t action)
static int sis900_get_mac_addr (struct pci_device *pci_dev __unused, struct nic *nic)
 sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model : the sis900 pci device : the net device to get address for
static int sis96x_get_mac_addr (struct pci_device *pci_dev __unused, struct nic *nic)
 sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model : the sis900 pci device : the net device to get address for
static int sis630e_get_mac_addr (struct pci_device *pci_dev __unused, struct nic *nic __unused)
 sis630e_get_mac_addr: - Get MAC address for SiS630E model : the sis900 pci device : the net device to get address for
static int sis635_get_mac_addr (struct pci_device *pci_dev __unused, struct nic *nic)
 sis630e_get_mac_addr: - Get MAC address for SiS630E model : the sis900 pci device : the net device to get address for
static void sis900_reset (struct nic *nic __unused)
static void sis900_init_txd (struct nic *nic __unused)
static void sis900_init_rxd (struct nic *nic __unused)
static void sis900_set_rx_mode (struct nic *nic __unused)
static void sis900_read_mode (struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
static void amd79c901_read_mode (struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
static void ics1893_read_mode (struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
 ics1893_read_mode: - read media mode for ICS1893 PHY : the net device to read mode for : mii phy address : the transmit speed to be determined : the duplex mode to be determined
static void rtl8201_read_mode (struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
 rtl8201_read_mode: - read media mode for rtl8201 phy : the net device to read mode for : mii phy address : the transmit speed to be determined : the duplex mode to be determined
static void vt6103_read_mode (struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
 vt6103_read_mode: - read media mode for vt6103 phy : the net device to read mode for : mii phy address : the transmit speed to be determined : the duplex mode to be determined
static void sis900_irq (struct nic *nic __unused, irq_action_t action __unused)
 PCI_DRIVER (sis900_driver, sis900_nics, PCI_NO_CLASS)
 DRIVER ("SIS900", nic_driver, pci_driver, sis900_driver, sis900_probe, sis900_disable)

Variables

static struct nic_operations sis900_operations
static int sis900_debug = 0
static unsigned short vendor
static unsigned short dev_id
static unsigned long ioaddr
static u8 pci_revision
static unsigned int cur_phy
static unsigned int cur_rx
struct {
   BufferDesc   txd
   BufferDesc   rxd [NUM_RX_DESC]
   unsigned char   txb [TX_BUF_SIZE]
   unsigned char   rxb [NUM_RX_DESC *RX_BUF_SIZE]
__shared
static struct mii_chip_info mii_chip_table []
static struct mii_phy mii
static struct pci_device_id sis900_nics []

Define Documentation

#define txd   sis900_bufs.txd

Definition at line 74 of file sis900.c.

#define rxd   sis900_bufs.rxd

Definition at line 75 of file sis900.c.

#define txb   sis900_bufs.txb

Definition at line 76 of file sis900.c.

#define rxb   sis900_bufs.rxb

Definition at line 77 of file sis900.c.

#define eeprom_delay ( )    inl(ee_addr)

Definition at line 448 of file sis900.c.

Referenced by sis900_read_eeprom().

#define sis900_mdio_delay ( )    inl(mdio_addr)

Definition at line 504 of file sis900.c.

Referenced by sis900_mdio_idle(), sis900_mdio_read(), and sis900_mdio_reset().


Function Documentation

FILE_LICENCE ( GPL_ANY  )
static void sis900_read_mode ( struct nic nic,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]
static void amd79c901_read_mode ( struct nic nic,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]
static void ics1893_read_mode ( struct nic nic,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]
static void rtl8201_read_mode ( struct nic nic,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]
static void vt6103_read_mode ( struct nic nic,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]
static int sis900_probe ( struct nic nic,
struct pci_device pci 
) [static]

Definition at line 335 of file sis900.c.

References ACCESSMODE, adjust_pci_device(), mii_phy::chip_info, cr, cur_phy, DBG, dev_id, pci_device::device, inl(), ioaddr, pci_device::ioaddr, mii, mii_chip_table, MII_PHY_ID0, MII_PHY_ID1, MII_STATUS, mii_chip_info::name, name, mii_phy::next, NULL, outl(), pci_read_config_byte(), PCI_REVISION, pci_revision, pci_write_config_dword(), mii_phy::phy_addr, mii_chip_info::phy_id1, printf(), ret, revision, SIS630E_900_REV, sis630e_get_mac_addr(), SIS630ET_900_REV, sis635_get_mac_addr(), sis900_get_mac_addr(), sis900_init(), sis900_mdio_read(), sis900_operations, SIS96x_900_REV, sis96x_get_mac_addr(), mii_phy::status, vendor, and pci_device::vendor.

                                                                    {

    int i;
    int found=0;
    int phy_addr;
    u8 revision;
    int ret;

    if (pci->ioaddr == 0)
        return 0;

    nic->irqno  = 0;
    nic->ioaddr = pci->ioaddr;

    ioaddr  = pci->ioaddr;
    vendor  = pci->vendor;
    dev_id  = pci->device;

    /* wakeup chip */
    pci_write_config_dword(pci, 0x40, 0x00000000);

    adjust_pci_device(pci);

    /* get MAC address */
    ret = 0;
    pci_read_config_byte(pci, PCI_REVISION, &revision);
    
    /* save for use later in sis900_reset() */
    pci_revision = revision; 

    if (revision == SIS630E_900_REV)
        ret = sis630e_get_mac_addr(pci, nic);
    else if ((revision > 0x81) && (revision <= 0x90))
        ret = sis635_get_mac_addr(pci, nic);
    else if (revision == SIS96x_900_REV)
        ret = sis96x_get_mac_addr(pci, nic);
    else
        ret = sis900_get_mac_addr(pci, nic);

    if (ret == 0)
    {
        printf ("sis900_probe: Error MAC address not found\n");
        return 0;
    }

    /* 630ET : set the mii access mode as software-mode */
    if (revision == SIS630ET_900_REV)
        outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);

    DBG( "sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id );

    /* probe for mii transceiver */
    /* search for total of 32 possible mii phy addresses */

    found = 0;
    for (phy_addr = 0; phy_addr < 32; phy_addr++) {
        u16 mii_status;
        u16 phy_id0, phy_id1;

        mii_status = sis900_mdio_read(phy_addr, MII_STATUS);
        if (mii_status == 0xffff || mii_status == 0x0000)
            /* the mii is not accessible, try next one */
            continue;
                
        phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
        phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);

        /* search our mii table for the current mii */ 
        for (i = 0; mii_chip_table[i].phy_id1; i++) {

            if ((phy_id0 == mii_chip_table[i].phy_id0) &&
                ((phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){

                printf("sis900_probe: %s transceiver found at address %d.\n",
                       mii_chip_table[i].name, phy_addr);

                mii.chip_info = &mii_chip_table[i];
                mii.phy_addr  = phy_addr;
                mii.status    = sis900_mdio_read(phy_addr, MII_STATUS);
                mii.next      = NULL;

                found=1;
                break;
            }
        }
    }
        
    if (found == 0) {
        printf("sis900_probe: No MII transceivers found!\n");
        return 0;
    }

    /* Arbitrarily select the last PHY found as current PHY */
    cur_phy = mii.phy_addr;
    printf("sis900_probe: Using %s as default\n",  mii.chip_info->name);

    /* initialize device */
    sis900_init(nic);
    nic->nic_op = &sis900_operations;

    return 1;
}
static u16 sis900_read_eeprom ( int  location) [static]

Definition at line 463 of file sis900.c.

References EECLK, EECS, EEDI, EEDO, eeprom_delay, EEread, inl(), ioaddr, mear, and outl().

Referenced by sis900_get_mac_addr(), and sis96x_get_mac_addr().

{
    int i;
    u16 retval = 0;
    long ee_addr = ioaddr + mear;
    u32 read_cmd = location | EEread;

    outl(0, ee_addr);
    eeprom_delay();
    outl(EECS, ee_addr);
    eeprom_delay();

    /* Shift the read command (9) bits out. */
    for (i = 8; i >= 0; i--) {
        u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
        outl(dataval, ee_addr);
        eeprom_delay();
        outl(dataval | EECLK, ee_addr);
        eeprom_delay();
    }
    outl(EECS, ee_addr);
    eeprom_delay();

    /* read the 16-bits data in */
    for (i = 16; i > 0; i--) {
        outl(EECS, ee_addr);
        eeprom_delay();
        outl(EECS | EECLK, ee_addr);
        eeprom_delay();
        retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
        eeprom_delay();
    }
                
    /* Terminate the EEPROM access. */
    outl(0, ee_addr);
    eeprom_delay();
//  outl(EECLK, ee_addr);

    return (retval);
}
static void sis900_mdio_reset ( long  mdio_addr) [static]

Definition at line 521 of file sis900.c.

References MDC, MDDIR, MDIO, outl(), and sis900_mdio_delay.

Referenced by sis900_mdio_read().

{
    int i;

    for (i = 31; i >= 0; i--) {
        outl(MDDIR | MDIO, mdio_addr);
        sis900_mdio_delay();
        outl(MDDIR | MDIO | MDC, mdio_addr);
        sis900_mdio_delay();
    }
    return;
}
static void sis900_mdio_idle ( long  mdio_addr) [static]

Definition at line 513 of file sis900.c.

References MDC, MDDIR, MDIO, outl(), and sis900_mdio_delay.

Referenced by sis900_mdio_read().

{
    outl(MDIO | MDDIR, mdio_addr);
    sis900_mdio_delay();
    outl(MDIO | MDDIR | MDC, mdio_addr);
}
static u16 sis900_mdio_read ( int  phy_id,
int  location 
) [static]

Definition at line 534 of file sis900.c.

References inl(), ioaddr, MDC, MDDIR, MDIO, mear, MIIpmdShift, MIIread, MIIregShift, outl(), sis900_mdio_delay, sis900_mdio_idle(), and sis900_mdio_reset().

Referenced by amd79c901_read_mode(), ics1893_read_mode(), rtl8201_read_mode(), sis900_probe(), sis900_read_mode(), and vt6103_read_mode().

{
    long mdio_addr = ioaddr + mear;
    int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
    u16 retval = 0;
    int i;

    sis900_mdio_reset(mdio_addr);
    sis900_mdio_idle(mdio_addr);

    for (i = 15; i >= 0; i--) {
        int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
        outl(dataval, mdio_addr);
        sis900_mdio_delay();
        outl(dataval | MDC, mdio_addr);
        sis900_mdio_delay();
    }

    /* Read the 16 data bits. */
    for (i = 16; i > 0; i--) {
        outl(0, mdio_addr);
        sis900_mdio_delay();
        retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
        outl(MDC, mdio_addr);
        sis900_mdio_delay();
    }
    outl(0x00, mdio_addr);
    return retval;
}
static void sis900_init ( struct nic nic) [static]
static void sis900_reset ( struct nic nic) [static]

Referenced by sis900_init().

static void sis900_init_rxfilter ( struct nic nic) [static]

Definition at line 680 of file sis900.c.

References inl(), ioaddr, outl(), printf(), RFADDR_shift, rfcr, rfdr, RFEN, and sis900_debug.

Referenced by sis900_init().

{
    u32 rfcrSave;
    int i;
        
    rfcrSave = inl(rfcr + ioaddr);

    /* disable packet filtering before setting filter */
    outl(rfcrSave & ~RFEN, rfcr + ioaddr);

    /* load MAC addr to filter data register */
    for (i = 0 ; i < 3 ; i++) {
        u32 w;

        w = (u32) *((u16 *)(nic->node_addr)+i);
        outl((i << RFADDR_shift), ioaddr + rfcr);
        outl(w, ioaddr + rfdr);

        if (sis900_debug > 0)
            printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
                   i, inl(ioaddr + rfdr));
    }

    /* enable packet filitering */
    outl(rfcrSave | RFEN, rfcr + ioaddr);
}
static void sis900_init_txd ( struct nic nic) [static]

Referenced by sis900_init().

static void sis900_init_rxd ( struct nic nic) [static]

Referenced by sis900_init().

static void sis900_set_rx_mode ( struct nic nic) [static]

Referenced by sis900_init().

static void sis900_check_mode ( struct nic nic) [static]

Definition at line 823 of file sis900.c.

References cfg, mii_phy::chip_info, cur_phy, DMA_BURST_512, DMA_BURST_64, EDB_MASTER_EN, FDX_CAPABLE_FULL_SELECTED, HW_SPEED_10_MBPS, HW_SPEED_HOME, inl(), ioaddr, mii, outl(), mii_chip_info::read_mode, RxATX, rxcfg, RxDRNT_10, RxDRNT_100, RxDRNT_shift, RxMXDMA_shift, speed, TX_FILL_THRESH, TxATP, txcfg, TxCSI, TxDRNT_10, TxDRNT_100, TxDRNT_shift, TxFILLT_shift, TxHBI, and TxMXDMA_shift.

Referenced by sis900_init().

{
    int speed, duplex;
    u32 tx_flags = 0, rx_flags = 0;

    mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex);

    if( inl(ioaddr + cfg) & EDB_MASTER_EN ) {
        tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
        rx_flags = DMA_BURST_64 << RxMXDMA_shift;
    }
    else {
            tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
            rx_flags = DMA_BURST_512 << RxMXDMA_shift;
    }

    if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
        rx_flags |= (RxDRNT_10 << RxDRNT_shift);
        tx_flags |= (TxDRNT_10 << TxDRNT_shift);
    }
    else {
        rx_flags |= (RxDRNT_100 << RxDRNT_shift);
        tx_flags |= (TxDRNT_100 << TxDRNT_shift);
    }

    if (duplex == FDX_CAPABLE_FULL_SELECTED) {
        tx_flags |= (TxCSI | TxHBI);
        rx_flags |= RxATX;
    }

    outl (tx_flags, ioaddr + txcfg);
    outl (rx_flags, ioaddr + rxcfg);
}
static void sis900_transmit ( struct nic nic,
const char *  d,
unsigned int  t,
unsigned int  s,
const char *  p 
) [static]

Definition at line 1103 of file sis900.c.

References ABORT, cr, currticks(), DSIZE, ETH_ALEN, ETH_HLEN, ETH_ZLEN, htons, imr, inl(), ioaddr, memcpy(), outl(), OWCOLL, OWN, printf(), sis900_debug, TX_TIMEOUT, txb, txd, TxDIS, txdp, TxENA, UNDERRUN, and virt_to_bus().

{
    u32 to, nstype;
    volatile u32 tx_status;
    
    /* Stop the transmitter */
    outl(TxDIS | inl(ioaddr + cr), ioaddr + cr);

    /* load Transmit Descriptor Register */
    outl(virt_to_bus(&txd), ioaddr + txdp); 
    if (sis900_debug > 1)
        printf("sis900_transmit: TX descriptor register loaded with: %X\n", 
               inl(ioaddr + txdp));

    memcpy(txb, d, ETH_ALEN);
    memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
    nstype = htons(t);
    memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
    memcpy(txb + ETH_HLEN, p, s);

    s += ETH_HLEN;
    s &= DSIZE;

    if (sis900_debug > 1)
        printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);

    /* pad to minimum packet size */
    while (s < ETH_ZLEN)  
        txb[s++] = '\0';

    /* set the transmit buffer descriptor and enable Transmit State Machine */
    txd.bufptr = virt_to_bus(&txb[0]);
    txd.cmdsts = (u32) OWN | s;

    /* restart the transmitter */
    outl(TxENA | inl(ioaddr + cr), ioaddr + cr);

    if (sis900_debug > 1)
        printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);

    to = currticks() + TX_TIMEOUT;

    while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
        /* wait */ ;

    if (currticks() >= to) {
        printf("sis900_transmit: TX Timeout! Tx status %X.\n", 
               (unsigned int) tx_status);
    }
    
    if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
        /* packet unsuccessfully transmited */
        printf("sis900_transmit: Transmit error, Tx status %X.\n", 
               (unsigned int) tx_status);
    }
    /* Disable interrupts by clearing the interrupt mask. */
    outl(0, ioaddr + imr);
}
static int sis900_poll ( struct nic nic,
int  retrieve 
) [static]

Definition at line 1182 of file sis900.c.

References ABORT, cr, CRC_SIZE, CRCERR, cur_rx, DSIZE, FAERR, inl(), ioaddr, isr, memcpy(), NUM_RX_DESC, outl(), OVERRUN, OWN, printf(), RUNT, RX_BUF_SIZE, rxb, rxd, RxENA, RXISERR, sis900_debug, TOOLONG, and virt_to_bus().

{
    u32 rx_status = rxd[cur_rx].cmdsts;
    int retstat = 0;

     /* acknowledge interrupts by reading interrupt status register */
    inl(ioaddr + isr);

    if (sis900_debug > 2)
        printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx, 
               (unsigned int) rx_status);

    if (!(rx_status & OWN))
        return retstat;

    if (sis900_debug > 1)
        printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
               cur_rx, (unsigned int) rx_status);

    if ( ! retrieve ) return 1;
    
    nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;

    if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
        /* corrupted packet received */
        printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
               (unsigned int) rx_status);
        retstat = 0;
    } else {
        /* give packet to higher level routine */
        memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
        retstat = 1;
    }

    /* return the descriptor and buffer to receive ring */
    rxd[cur_rx].cmdsts = RX_BUF_SIZE;
    rxd[cur_rx].bufptr = virt_to_bus(&rxb[cur_rx*RX_BUF_SIZE]);
        
    if (++cur_rx == NUM_RX_DESC)
        cur_rx = 0;

    /* re-enable the potentially idle receive state machine */
    outl(RxENA | inl(ioaddr + cr), ioaddr + cr);

    return retstat;

}
static void sis900_disable ( struct nic nic) [static]

Definition at line 1241 of file sis900.c.

References cr, ier, imr, inl(), ioaddr, outl(), RxDIS, sis900_init(), and TxDIS.

                                   {

    sis900_init(nic);

    /* Disable interrupts by clearing the interrupt mask. */
    outl(0, ioaddr + imr);
    outl(0, ioaddr + ier);
    
    /* Stop the chip's Tx and Rx Status Machine */
    outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
}
static void sis900_irq ( struct nic nic,
irq_action_t  action 
) [static]
static int sis900_get_mac_addr ( struct pci_device *pci_dev  __unused,
struct nic nic 
) [static]

sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model : the sis900 pci device : the net device to get address for

Older SiS900 and friends, use EEPROM to store MAC address. MAC address is read from read_eeprom() into ->dev_addr.

Definition at line 180 of file sis900.c.

References EEPROMMACAddr, EEPROMSignature, printf(), signature, sis900_read_eeprom(), and u16.

Referenced by sis900_probe().

{
        u16 signature;
        int i;

        /* check to see if we have sane EEPROM */
        signature = (u16) sis900_read_eeprom( EEPROMSignature);
        if (signature == 0xffff || signature == 0x0000) {
                printf ("sis900_probe: Error EERPOM read %hX\n", signature);
                return 0;
        }

        /* get MAC address from EEPROM */
        for (i = 0; i < 3; i++)
                        ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
        return 1;
}
static int sis96x_get_mac_addr ( struct pci_device *pci_dev  __unused,
struct nic nic 
) [static]

sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model : the sis900 pci device : the net device to get address for

SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM is shared by LAN and 1394. When access EEPROM, send EEREQ signal to hardware first and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access by LAN, otherwise is not. After MAC address is read from EEPROM, send EEDONE signal to refuse EEPROM access by LAN. The EEPROM map of SiS962 or SiS963 is different to SiS900. The signature field in SiS962 or SiS963 spec is meaningless. MAC address is read into ->dev_addr.

Definition at line 214 of file sis900.c.

References EEDONE, EEGNT, EEPROMMACAddr, EEREQ, inl(), ioaddr, mear, outl(), printf(), sis900_read_eeprom(), and udelay().

Referenced by sis900_probe().

{
/*      long ioaddr = net_dev->base_addr; */
        long ee_addr = ioaddr + mear;
        u32 waittime = 0;
        int i;
        
        printf("Alternate function\n");

        outl(EEREQ, ee_addr);
        while(waittime < 2000) {
                if(inl(ee_addr) & EEGNT) {

                        /* get MAC address from EEPROM */
                        for (i = 0; i < 3; i++)
                                ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);

                        outl(EEDONE, ee_addr);
                        return 1;
                } else {
                        udelay(1);      
                        waittime ++;
                }
        }
        outl(EEDONE, ee_addr);
        return 0;
}
static int sis630e_get_mac_addr ( struct pci_device *pci_dev  __unused,
struct nic *nic  __unused 
) [static]

sis630e_get_mac_addr: - Get MAC address for SiS630E model : the sis900 pci device : the net device to get address for

SiS630E model, use APC CMOS RAM to store MAC address. APC CMOS RAM is accessed through ISA bridge. MAC address is read into ->dev_addr.

Definition at line 252 of file sis900.c.

References ETH_ALEN, inb(), memset(), nic, outb(), pci_read_config_byte(), pci_write_config_byte(), reg, and u.

Referenced by sis900_probe().

{
#if 0
        u8 reg;
        int i;
        struct bus_loc bus_loc;
        union {
            struct bus_dev bus_dev;
            struct pci_device isa_bridge;
        } u;

        /* find PCI to ISA bridge */
        memset(&bus_loc, 0, sizeof(bus_loc));
        if ( ! find_by_driver ( &bus_loc, &u.bus_dev, &sis_bridge_driver, 0 ) )
            return 0;

        pci_read_config_byte(&u.isa_bridge, 0x48, &reg);
        pci_write_config_byte(&u.isa_bridge, 0x48, reg | 0x40);

        for (i = 0; i < ETH_ALEN; i++)
        {
                outb(0x09 + i, 0x70);
                ((u8 *)(nic->node_addr))[i] = inb(0x71);
        }
        pci_write_config_byte(&u.isa_bridge, 0x48, reg & ~0x40);

        return 1;
#endif

        /* Does not work with current bus/device model */
        return 0;
}
static int sis635_get_mac_addr ( struct pci_device *pci_dev  __unused,
struct nic nic 
) [static]

sis630e_get_mac_addr: - Get MAC address for SiS630E model : the sis900 pci device : the net device to get address for

SiS630E model, use APC CMOS RAM to store MAC address. APC CMOS RAM is accessed through ISA bridge. MAC address is read into ->dev_addr.

Definition at line 295 of file sis900.c.

References cr, inl(), inw(), ioaddr, outl(), RELOAD, RFADDR_shift, rfcr, rfdr, and RFEN.

Referenced by sis900_probe().

{
        u32 rfcrSave;
        u32 i;
        
        
        rfcrSave = inl(rfcr + ioaddr);

        outl(rfcrSave | RELOAD, ioaddr + cr);
        outl(0, ioaddr + cr);

        /* disable packet filtering before setting filter */
        outl(rfcrSave & ~RFEN, rfcr + ioaddr);

        /* load MAC addr to filter data register */
        for (i = 0 ; i < 3 ; i++) {
                outl((i << RFADDR_shift), ioaddr + rfcr);
                *( ((u16 *)nic->node_addr) + i) = inw(ioaddr + rfdr);
        }

        /* enable packet filitering */
        outl(rfcrSave | RFEN, rfcr + ioaddr);

        return 1;
}
static void sis900_reset ( struct nic *nic  __unused) [static]

Definition at line 647 of file sis900.c.

References cfg, cr, ier, imr, inl(), ioaddr, isr, outl(), pci_revision, PESEL, RESET, rfcr, RND_CNT, RxRCMP, RxRESET, SIS635A_900_REV, SIS900B_900_REV, status, TxRCMP, and TxRESET.

{
    int i = 0;
    u32 status = TxRCMP | RxRCMP;

    outl(0, ioaddr + ier);
    outl(0, ioaddr + imr);
    outl(0, ioaddr + rfcr);

    outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr);

    /* Check that the chip has finished the reset. */
    while (status && (i++ < 1000)) {
        status ^= (inl(isr + ioaddr) & status);
    }

    if( (pci_revision >= SIS635A_900_REV) || (pci_revision == SIS900B_900_REV) )
            outl(PESEL | RND_CNT, ioaddr + cfg);
    else
            outl(PESEL, ioaddr + cfg);
}
static void sis900_init_txd ( struct nic *nic  __unused) [static]

Definition at line 719 of file sis900.c.

References inl(), ioaddr, outl(), printf(), sis900_debug, txb, txd, txdp, and virt_to_bus().

{
    txd.link   = (u32) 0;
    txd.cmdsts = (u32) 0;
    txd.bufptr = virt_to_bus(&txb[0]);

    /* load Transmit Descriptor Register */
    outl(virt_to_bus(&txd), ioaddr + txdp); 
    if (sis900_debug > 0)
        printf("sis900_init_txd: TX descriptor register loaded with: %X\n", 
               inl(ioaddr + txdp));
}
static void sis900_init_rxd ( struct nic *nic  __unused) [static]

Definition at line 743 of file sis900.c.

References bufptr, cmdsts, cur_rx, inl(), ioaddr, link, NUM_RX_DESC, outl(), printf(), RX_BUF_SIZE, rxb, rxd, rxdp, sis900_debug, and virt_to_bus().

{ 
    int i;

    cur_rx = 0; 

    /* init RX descriptor */
    for (i = 0; i < NUM_RX_DESC; i++) {
        rxd[i].link   = virt_to_bus((i+1 < NUM_RX_DESC) ? &rxd[i+1] : &rxd[0]);
        rxd[i].cmdsts = (u32) RX_BUF_SIZE;
        rxd[i].bufptr = virt_to_bus(&rxb[i*RX_BUF_SIZE]);
        if (sis900_debug > 0)
            printf("sis900_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n", 
                   i, &rxd[i], (unsigned int) rxd[i].link, (unsigned int) rxd[i].cmdsts,
                   (unsigned int) rxd[i].bufptr);
    }

    /* load Receive Descriptor Register */
    outl(virt_to_bus(&rxd[0]), ioaddr + rxdp);

    if (sis900_debug > 0)
        printf("sis900_init_rxd: RX descriptor register loaded with: %X\n", 
               inl(ioaddr + rxdp));

}
static void sis900_set_rx_mode ( struct nic *nic  __unused) [static]

Definition at line 781 of file sis900.c.

References ioaddr, outl(), pci_revision, RFAAB, RFAAM, RFADDR_shift, rfcr, rfdr, RFEN, SIS635A_900_REV, and SIS900B_900_REV.

{
    int i, table_entries;
    u32 rx_mode; 
    u16 mc_filter[16] = {0};    /* 256/128 bits multicast hash table */
        
    if((pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV))
        table_entries = 16;
    else
        table_entries = 8;

    /* accept all multicast packet */
    rx_mode = RFAAB | RFAAM;
    for (i = 0; i < table_entries; i++)
                mc_filter[i] = 0xffff;
                                        
    /* update Multicast Hash Table in Receive Filter */
    for (i = 0; i < table_entries; i++) {
        /* why plus 0x04? That makes the correct value for hash table. */
        outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
        outl(mc_filter[i], ioaddr + rfdr);
    }

    /* Accept Broadcast and multicast packets, destination addresses that match 
       our MAC address */
    outl(RFEN | rx_mode, ioaddr + rfcr);

    return;
}
static void sis900_read_mode ( struct nic *nic  __unused,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]

Definition at line 869 of file sis900.c.

References FDX_CAPABLE_FULL_SELECTED, FDX_CAPABLE_HALF_SELECTED, HW_SPEED_100_MBPS, HW_SPEED_10_MBPS, MII_CNTL_FDX, MII_CONTROL, MII_NWAY_T_FDX, MII_NWAY_TX, MII_NWAY_TX_FDX, MII_PHY_ID0, MII_PHY_ID1, MII_STSOUT, MII_STSOUT_LINK_FAIL, printf(), sis900_mdio_read(), and status.

{
    int i = 0;
    u32 status;
    u16 phy_id0, phy_id1;
        
    /* STSOUT register is Latched on Transition, read operation updates it */
    do {
        status = sis900_mdio_read(phy_addr, MII_STSOUT);
    } while (i++ < 2);

    *speed = HW_SPEED_10_MBPS;
    *duplex = FDX_CAPABLE_HALF_SELECTED;
    
    if (status & (MII_NWAY_TX | MII_NWAY_TX_FDX))
        *speed = HW_SPEED_100_MBPS;
    if (status & ( MII_NWAY_TX_FDX | MII_NWAY_T_FDX))
        *duplex = FDX_CAPABLE_FULL_SELECTED;
        
    /* Workaround for Realtek RTL8201 PHY issue */
    phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
    phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
    if((phy_id0 == 0x0000) && ((phy_id1 & 0xFFF0) == 0x8200)){
        if(sis900_mdio_read(phy_addr, MII_CONTROL) & MII_CNTL_FDX)
            *duplex = FDX_CAPABLE_FULL_SELECTED;
        if(sis900_mdio_read(phy_addr, 0x0019) & 0x01)
            *speed = HW_SPEED_100_MBPS;
    }

    if (status & MII_STSOUT_LINK_FAIL)
        printf("sis900_read_mode: Media Link Off\n");
    else
        printf("sis900_read_mode: Media Link On %s %s-duplex \n", 
               *speed == HW_SPEED_100_MBPS ? 
               "100mbps" : "10mbps",
               *duplex == FDX_CAPABLE_FULL_SELECTED ?
               "full" : "half");
}
static void amd79c901_read_mode ( struct nic *nic  __unused,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]

Definition at line 920 of file sis900.c.

References FDX_CAPABLE_FULL_SELECTED, FDX_CAPABLE_HALF_SELECTED, HW_SPEED_100_MBPS, HW_SPEED_10_MBPS, HW_SPEED_HOME, MII_STAT_CAN_AUTO, MII_STAT_LINK, MII_STATUS, MII_STATUS_SUMMARY, MII_STSSUM_DPLX, MII_STSSUM_LINK, MII_STSSUM_SPD, printf(), sis900_mdio_read(), and status.

{
    int i;
    u16 status;
        
    for (i = 0; i < 2; i++)
        status = sis900_mdio_read(phy_addr, MII_STATUS);

    if (status & MII_STAT_CAN_AUTO) {
        /* 10BASE-T PHY */
        for (i = 0; i < 2; i++)
            status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY);
        if (status & MII_STSSUM_SPD)
            *speed = HW_SPEED_100_MBPS;
        else
            *speed = HW_SPEED_10_MBPS;
        if (status & MII_STSSUM_DPLX)
            *duplex = FDX_CAPABLE_FULL_SELECTED;
        else
            *duplex = FDX_CAPABLE_HALF_SELECTED;

        if (status & MII_STSSUM_LINK)
            printf("amd79c901_read_mode: Media Link On %s %s-duplex \n", 
                   *speed == HW_SPEED_100_MBPS ? 
                   "100mbps" : "10mbps",
                   *duplex == FDX_CAPABLE_FULL_SELECTED ?
                   "full" : "half");
        else
            printf("amd79c901_read_mode: Media Link Off\n");
    }
    else {
        /* HomePNA */
        *speed = HW_SPEED_HOME;
        *duplex = FDX_CAPABLE_HALF_SELECTED;
        if (status & MII_STAT_LINK)
            printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");
        else
            printf("amd79c901_read_mode: Media Link Off\n");
    }
}
static void ics1893_read_mode ( struct nic *nic  __unused,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]

ics1893_read_mode: - read media mode for ICS1893 PHY : the net device to read mode for : mii phy address : the transmit speed to be determined : the duplex mode to be determined

ICS1893 PHY use Quick Poll Detailed Status register to determine the speed and duplex mode for sis900

Definition at line 973 of file sis900.c.

References FDX_CAPABLE_FULL_SELECTED, FDX_CAPABLE_HALF_SELECTED, HW_SPEED_100_MBPS, HW_SPEED_10_MBPS, MII_QPDSTS, MII_STSICS_DPLX, MII_STSICS_LINKSTS, MII_STSICS_SPD, printf(), sis900_mdio_read(), and status.

{
        int i = 0;
        u32 status;

        /* MII_QPDSTS is Latched, read twice in succession will reflect the current state */
        for (i = 0; i < 2; i++)
                status = sis900_mdio_read(phy_addr, MII_QPDSTS);

        if (status & MII_STSICS_SPD)
                *speed = HW_SPEED_100_MBPS;
        else
                *speed = HW_SPEED_10_MBPS;

        if (status & MII_STSICS_DPLX)
                *duplex = FDX_CAPABLE_FULL_SELECTED;
        else
                *duplex = FDX_CAPABLE_HALF_SELECTED;

        if (status & MII_STSICS_LINKSTS)
                printf("ics1893_read_mode: Media Link On %s %s-duplex \n",
                       *speed == HW_SPEED_100_MBPS ?
                       "100mbps" : "10mbps",
                       *duplex == FDX_CAPABLE_FULL_SELECTED ?
                       "full" : "half");
        else
                printf("ics1893_read_mode: Media Link Off\n");
}
static void rtl8201_read_mode ( struct nic *nic  __unused,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]

rtl8201_read_mode: - read media mode for rtl8201 phy : the net device to read mode for : mii phy address : the transmit speed to be determined : the duplex mode to be determined

read MII_STATUS register from rtl8201 phy to determine the speed and duplex mode for sis900

Definition at line 1013 of file sis900.c.

References FDX_CAPABLE_FULL_SELECTED, FDX_CAPABLE_HALF_SELECTED, HW_SPEED_100_MBPS, HW_SPEED_10_MBPS, MII_STAT_CAN_T, MII_STAT_CAN_T_FDX, MII_STAT_CAN_TX, MII_STAT_CAN_TX_FDX, MII_STAT_LINK, MII_STATUS, printf(), sis900_mdio_read(), and status.

{
        u32 status;

        status = sis900_mdio_read(phy_addr, MII_STATUS);

        if (status & MII_STAT_CAN_TX_FDX) {
                *speed = HW_SPEED_100_MBPS;
                *duplex = FDX_CAPABLE_FULL_SELECTED;
        }
        else if (status & MII_STAT_CAN_TX) {
                *speed = HW_SPEED_100_MBPS;
                *duplex = FDX_CAPABLE_HALF_SELECTED;
        }
        else if (status & MII_STAT_CAN_T_FDX) {
                *speed = HW_SPEED_10_MBPS;
                *duplex = FDX_CAPABLE_FULL_SELECTED;
        }
        else if (status & MII_STAT_CAN_T) {
                *speed = HW_SPEED_10_MBPS;
                *duplex = FDX_CAPABLE_HALF_SELECTED;
        }

        if (status & MII_STAT_LINK)
                printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",
                       *speed == HW_SPEED_100_MBPS ?
                       "100mbps" : "10mbps",
                       *duplex == FDX_CAPABLE_FULL_SELECTED ?
                       "full" : "half");
        else
                printf("rtl8201_read_config_mode: Media Link Off\n");
}
static void vt6103_read_mode ( struct nic *nic  __unused,
int  phy_addr,
int *  speed,
int *  duplex 
) [static]

vt6103_read_mode: - read media mode for vt6103 phy : the net device to read mode for : mii phy address : the transmit speed to be determined : the duplex mode to be determined

read MII_STATUS register from rtl8201 phy to determine the speed and duplex mode for sis900

Definition at line 1057 of file sis900.c.

References FDX_CAPABLE_FULL_SELECTED, FDX_CAPABLE_HALF_SELECTED, HW_SPEED_100_MBPS, HW_SPEED_10_MBPS, MII_STAT_CAN_T, MII_STAT_CAN_T_FDX, MII_STAT_CAN_TX, MII_STAT_CAN_TX_FDX, MII_STAT_LINK, MII_STATUS, printf(), sis900_mdio_read(), and status.

{
        u32 status;

        status = sis900_mdio_read(phy_addr, MII_STATUS);

        if (status & MII_STAT_CAN_TX_FDX) {
                *speed = HW_SPEED_100_MBPS;
                *duplex = FDX_CAPABLE_FULL_SELECTED;
        }
        else if (status & MII_STAT_CAN_TX) {
                *speed = HW_SPEED_100_MBPS;
                *duplex = FDX_CAPABLE_HALF_SELECTED;
        }
        else if (status & MII_STAT_CAN_T_FDX) {
                *speed = HW_SPEED_10_MBPS;
                *duplex = FDX_CAPABLE_FULL_SELECTED;
        }
        else if (status & MII_STAT_CAN_T) {
                *speed = HW_SPEED_10_MBPS;
                *duplex = FDX_CAPABLE_HALF_SELECTED;
        }

        if (status & MII_STAT_LINK)
                printf("vt6103_read_mode: Media Link On %s %s-duplex \n",
                       *speed == HW_SPEED_100_MBPS ?
                       "100mbps" : "10mbps",
                       *duplex == FDX_CAPABLE_FULL_SELECTED ?
                       "full" : "half");
        else
                printf("vt6103_read_config_mode: Media Link Off\n");
}
static void sis900_irq ( struct nic *nic  __unused,
irq_action_t action  __unused 
) [static]

Definition at line 1265 of file sis900.c.

References imr, ioaddr, outl(), RxERR, RxOK, RxORN, RxSOVR, TxERR, TxIDLE, and TxURN.

{
  switch ( action ) {
  case DISABLE :
    outl(0, ioaddr + imr);
    break;
  case ENABLE :
    outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
    break;
  case FORCE :
    break;
  }
}
PCI_DRIVER ( sis900_driver  ,
sis900_nics  ,
PCI_NO_CLASS   
)
DRIVER ( "SIS900"  ,
nic_driver  ,
pci_driver  ,
sis900_driver  ,
sis900_probe  ,
sis900_disable   
)

Variable Documentation

static struct nic_operations sis900_operations [static]
Initial value:
 {
        .connect        = dummy_connect,
        .poll           = sis900_poll,
        .transmit       = sis900_transmit,
        .irq            = sis900_irq,
}

Definition at line 56 of file sis900.c.

Referenced by sis900_probe().

int sis900_debug = 0 [static]
unsigned short vendor [static]

Definition at line 60 of file sis900.c.

unsigned short dev_id [static]

Definition at line 60 of file sis900.c.

Referenced by sis900_probe().

unsigned long ioaddr [static]
u8 pci_revision [static]

Definition at line 62 of file sis900.c.

Referenced by sis900_probe(), sis900_reset(), and sis900_set_rx_mode().

unsigned int cur_phy [static]

Definition at line 64 of file sis900.c.

Referenced by sis900_check_mode(), and sis900_probe().

unsigned int cur_rx [static]

Definition at line 66 of file sis900.c.

Referenced by sis900_init_rxd(), and sis900_poll().

Definition at line 69 of file sis900.c.

Definition at line 70 of file sis900.c.

unsigned char txb[TX_BUF_SIZE]

Definition at line 71 of file sis900.c.

unsigned char rxb[NUM_RX_DESC *RX_BUF_SIZE]

Definition at line 72 of file sis900.c.

struct { ... } __shared
struct mii_chip_info mii_chip_table[] [static]

Referenced by sis900_probe().

struct mii_phy mii [static]
struct pci_device_id sis900_nics[] [static]
Initial value:
 {
PCI_ROM(0x1039, 0x0900, "sis900",  "SIS900", 0),
PCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016", 0),
}

Definition at line 1286 of file sis900.c.