Annotation of qemu/roms/ipxe/src/drivers/net/sis900.c, revision 1.1.1.1

1.1       root        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 ([email protected])
                     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: FILE_LICENCE ( GPL_ANY );
                     28: 
                     29: /* Revision History */
                     30: 
                     31: /*
                     32:   07 Dec 2003  timlegge - Enabled Multicast Support
                     33:   06 Dec 2003  timlegge - Fixed relocation issue in 5.2
                     34:   04 Jan 2002  Chien-Yu Chen, Doug Ambrisko, Marty Connor  Patch to Etherboot 5.0.5
                     35:      Added support for the SiS 630ET plus various bug fixes from linux kernel
                     36:      source 2.4.17.
                     37:   01 March 2001  mdc     1.0
                     38:      Initial Release.  Tested with PCI based sis900 card and ThinkNIC
                     39:      computer.
                     40:   20 March 2001 P.Koegel
                     41:      added support for sis630e and PHY ICS1893 and RTL8201
                     42:      Testet with SIS730S chipset + ICS1893
                     43: */
                     44: 
                     45: 
                     46: /* Includes */
                     47: 
                     48: #include "etherboot.h"
                     49: #include <ipxe/pci.h>
                     50: #include "nic.h"
                     51: 
                     52: #include "sis900.h"
                     53: 
                     54: /* Globals */
                     55: 
                     56: static struct nic_operations sis900_operations;
                     57: 
                     58: static int sis900_debug = 0;
                     59: 
                     60: static unsigned short vendor, dev_id;
                     61: static unsigned long ioaddr;
                     62: static u8 pci_revision;
                     63: 
                     64: static unsigned int cur_phy;
                     65: 
                     66: static unsigned int cur_rx;
                     67: 
                     68: struct {
                     69:     BufferDesc txd;
                     70:     BufferDesc rxd[NUM_RX_DESC];
                     71:     unsigned char txb[TX_BUF_SIZE];
                     72:     unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
                     73: } sis900_bufs __shared;
                     74: #define txd sis900_bufs.txd
                     75: #define rxd sis900_bufs.rxd
                     76: #define txb sis900_bufs.txb
                     77: #define rxb sis900_bufs.rxb
                     78: 
                     79: #if 0
                     80: static struct mac_chip_info {
                     81:     const char *name;
                     82:     u16 vendor_id, device_id, flags;
                     83:     int io_size;
                     84: } mac_chip_table[] = {
                     85:     { "SiS 900 PCI Fast Ethernet", PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900,
                     86:       PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
                     87:     { "SiS 7016 PCI Fast Ethernet",PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016,
                     88:       PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
                     89:     {0,0,0,0,0} /* 0 terminated list. */
                     90: };
                     91: #endif
                     92: 
                     93: static void sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
                     94: static void amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
                     95: static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
                     96: static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
                     97: static void vt6103_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
                     98: 
                     99: static struct mii_chip_info {
                    100:     const char * name;
                    101:     u16 phy_id0;
                    102:     u16 phy_id1;
                    103:     void (*read_mode) (struct nic *nic, int phy_addr, int *speed, int *duplex);
                    104: } mii_chip_table[] = {
                    105:     {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode},
                    106:     {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode},
                    107:     {"SiS 900 on Foxconn 661 7MI", 0x0143, 0xBC70, sis900_read_mode},
                    108:     {"AMD 79C901 10BASE-T PHY",  0x0000, 0x6B70, amd79c901_read_mode},
                    109:     {"AMD 79C901 HomePNA PHY",   0x0000, 0x6B90, amd79c901_read_mode},
                    110:     {"ICS 1893 Integrated PHYceiver"   , 0x0015, 0xf440,ics1893_read_mode},
                    111: //  {"NS 83851 PHY",0x2000, 0x5C20, MIX },
                    112:     {"RTL 8201 10/100Mbps Phyceiver"   , 0x0000, 0x8200,rtl8201_read_mode},
                    113:     {"VIA 6103 10/100Mbps Phyceiver", 0x0101, 0x8f20,vt6103_read_mode},
                    114:     {0,0,0,0}
                    115: };
                    116: 
                    117: static struct mii_phy {
                    118:     struct mii_phy * next;
                    119:     struct mii_chip_info * chip_info;
                    120:     int phy_addr;
                    121:     u16 status;
                    122: } mii;
                    123: 
                    124: 
                    125: 
                    126: #if 0
                    127: // PCI to ISA bridge for SIS640E access
                    128: static struct pci_device_id pci_isa_bridge_list[] = {
                    129:        { .vendor = 0x1039, .device = 0x0008,
                    130:                .name = "SIS 85C503/5513 PCI to ISA bridge"},
                    131: };
                    132: 
                    133: PCI_DRIVER( sis_bridge_pci_driver, pci_isa_bridge_list, PCI_NO_CLASS );
                    134: 
                    135: static struct device_driver sis_bridge_driver = {
                    136:     .name = "SIS ISA bridge",
                    137:     .bus_driver = &pci_driver,
                    138:     .bus_driver_info = ( struct bus_driver_info * ) &sis_bridge_pci_driver,
                    139: };
                    140: #endif
                    141: 
                    142: /* Function Prototypes */
                    143: 
                    144: static int sis900_probe(struct nic *nic,struct pci_device *pci);
                    145: 
                    146: static u16  sis900_read_eeprom(int location);
                    147: static void sis900_mdio_reset(long mdio_addr);
                    148: static void sis900_mdio_idle(long mdio_addr);
                    149: static u16  sis900_mdio_read(int phy_id, int location);
                    150: #if 0
                    151: static void sis900_mdio_write(int phy_id, int location, int val);
                    152: #endif
                    153: static void sis900_init(struct nic *nic);
                    154: 
                    155: static void sis900_reset(struct nic *nic);
                    156: 
                    157: static void sis900_init_rxfilter(struct nic *nic);
                    158: static void sis900_init_txd(struct nic *nic);
                    159: static void sis900_init_rxd(struct nic *nic);
                    160: static void sis900_set_rx_mode(struct nic *nic);
                    161: static void sis900_check_mode(struct nic *nic);
                    162: 
                    163: static void sis900_transmit(struct nic *nic, const char *d, 
                    164:                             unsigned int t, unsigned int s, const char *p);
                    165: static int  sis900_poll(struct nic *nic, int retrieve);
                    166: 
                    167: static void sis900_disable(struct nic *nic);
                    168: 
                    169: static void sis900_irq(struct nic *nic, irq_action_t action);
                    170: 
                    171: /**
                    172:  *     sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
                    173:  *     @pci_dev: the sis900 pci device
                    174:  *     @net_dev: the net device to get address for
                    175:  *
                    176:  *     Older SiS900 and friends, use EEPROM to store MAC address.
                    177:  *     MAC address is read from read_eeprom() into @net_dev->dev_addr.
                    178:  */
                    179: 
                    180: static int sis900_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
                    181: {
                    182:        u16 signature;
                    183:        int i;
                    184: 
                    185:        /* check to see if we have sane EEPROM */
                    186:        signature = (u16) sis900_read_eeprom( EEPROMSignature);
                    187:        if (signature == 0xffff || signature == 0x0000) {
                    188:                printf ("sis900_probe: Error EERPOM read %hX\n", signature);
                    189:                return 0;
                    190:        }
                    191: 
                    192:        /* get MAC address from EEPROM */
                    193:        for (i = 0; i < 3; i++)
                    194:                        ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
                    195:        return 1;
                    196: }
                    197: 
                    198: /**
                    199:  *     sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
                    200:  *     @pci_dev: the sis900 pci device
                    201:  *     @net_dev: the net device to get address for 
                    202:  *
                    203:  *     SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM 
                    204:  *     is shared by
                    205:  *     LAN and 1394. When access EEPROM, send EEREQ signal to hardware first 
                    206:  *     and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access 
                    207:  *     by LAN, otherwise is not. After MAC address is read from EEPROM, send
                    208:  *     EEDONE signal to refuse EEPROM access by LAN. 
                    209:  *     The EEPROM map of SiS962 or SiS963 is different to SiS900. 
                    210:  *     The signature field in SiS962 or SiS963 spec is meaningless. 
                    211:  *     MAC address is read into @net_dev->dev_addr.
                    212:  */
                    213: 
                    214: static int sis96x_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
                    215: {
                    216: /*     long ioaddr = net_dev->base_addr; */
                    217:        long ee_addr = ioaddr + mear;
                    218:        u32 waittime = 0;
                    219:        int i;
                    220:        
                    221:        printf("Alternate function\n");
                    222: 
                    223:        outl(EEREQ, ee_addr);
                    224:        while(waittime < 2000) {
                    225:                if(inl(ee_addr) & EEGNT) {
                    226: 
                    227:                        /* get MAC address from EEPROM */
                    228:                        for (i = 0; i < 3; i++)
                    229:                                ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
                    230: 
                    231:                        outl(EEDONE, ee_addr);
                    232:                        return 1;
                    233:                } else {
                    234:                        udelay(1);      
                    235:                        waittime ++;
                    236:                }
                    237:        }
                    238:        outl(EEDONE, ee_addr);
                    239:        return 0;
                    240: }
                    241: 
                    242: /**
                    243:  *     sis630e_get_mac_addr: - Get MAC address for SiS630E model
                    244:  *     @pci_dev: the sis900 pci device
                    245:  *     @net_dev: the net device to get address for
                    246:  *
                    247:  *     SiS630E model, use APC CMOS RAM to store MAC address.
                    248:  *     APC CMOS RAM is accessed through ISA bridge.
                    249:  *     MAC address is read into @net_dev->dev_addr.
                    250:  */
                    251: 
                    252: static int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
                    253: {
                    254: #if 0
                    255:        u8 reg;
                    256:        int i;
                    257:        struct bus_loc bus_loc;
                    258:        union {
                    259:            struct bus_dev bus_dev;
                    260:            struct pci_device isa_bridge;
                    261:        } u;
                    262: 
                    263:        /* find PCI to ISA bridge */
                    264:        memset(&bus_loc, 0, sizeof(bus_loc));
                    265:        if ( ! find_by_driver ( &bus_loc, &u.bus_dev, &sis_bridge_driver, 0 ) )
                    266:            return 0;
                    267: 
                    268:        pci_read_config_byte(&u.isa_bridge, 0x48, &reg);
                    269:        pci_write_config_byte(&u.isa_bridge, 0x48, reg | 0x40);
                    270: 
                    271:        for (i = 0; i < ETH_ALEN; i++)
                    272:        {
                    273:                outb(0x09 + i, 0x70);
                    274:                ((u8 *)(nic->node_addr))[i] = inb(0x71);
                    275:        }
                    276:        pci_write_config_byte(&u.isa_bridge, 0x48, reg & ~0x40);
                    277: 
                    278:        return 1;
                    279: #endif
                    280: 
                    281:        /* Does not work with current bus/device model */
                    282:        memset ( nic->node_addr, 0, sizeof ( nic->node_addr ) );
                    283:        return 0;
                    284: }
                    285: 
                    286: /**
                    287:  *      sis630e_get_mac_addr: - Get MAC address for SiS630E model
                    288:  *      @pci_dev: the sis900 pci device
                    289:  *      @net_dev: the net device to get address for
                    290:  *
                    291:  *      SiS630E model, use APC CMOS RAM to store MAC address.
                    292:  *      APC CMOS RAM is accessed through ISA bridge.
                    293:  *      MAC address is read into @net_dev->dev_addr.
                    294:  */
                    295: 
                    296: static int sis635_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
                    297: {
                    298:         u32 rfcrSave;
                    299:         u32 i;
                    300:        
                    301:        
                    302:         rfcrSave = inl(rfcr + ioaddr);
                    303: 
                    304:         outl(rfcrSave | RELOAD, ioaddr + cr);
                    305:         outl(0, ioaddr + cr);
                    306: 
                    307:         /* disable packet filtering before setting filter */
                    308:         outl(rfcrSave & ~RFEN, rfcr + ioaddr);
                    309: 
                    310:         /* load MAC addr to filter data register */
                    311:         for (i = 0 ; i < 3 ; i++) {
                    312:                 outl((i << RFADDR_shift), ioaddr + rfcr);
                    313:                 *( ((u16 *)nic->node_addr) + i) = inw(ioaddr + rfdr);
                    314:         }
                    315: 
                    316:         /* enable packet filitering */
                    317:         outl(rfcrSave | RFEN, rfcr + ioaddr);
                    318: 
                    319:         return 1;
                    320: }
                    321: 
                    322: /* 
                    323:  * Function: sis900_probe
                    324:  *
                    325:  * Description: initializes initializes the NIC, retrieves the
                    326:  *    MAC address of the card, and sets up some globals required by 
                    327:  *    other routines.
                    328:  *
                    329:  * Side effects:
                    330:  *            leaves the ioaddress of the sis900 chip in the variable ioaddr.
                    331:  *            leaves the sis900 initialized, and ready to recieve packets.
                    332:  *
                    333:  * Returns:   struct nic *:          pointer to NIC data structure
                    334:  */
                    335: 
                    336: static int sis900_probe ( struct nic *nic, struct pci_device *pci ) {
                    337: 
                    338:     int i;
                    339:     int found=0;
                    340:     int phy_addr;
                    341:     u8 revision;
                    342:     int ret;
                    343: 
                    344:     if (pci->ioaddr == 0)
                    345:         return 0;
                    346: 
                    347:     nic->irqno  = 0;
                    348:     nic->ioaddr = pci->ioaddr;
                    349: 
                    350:     ioaddr  = pci->ioaddr;
                    351:     vendor  = pci->vendor;
                    352:     dev_id  = pci->device;
                    353: 
                    354:     /* wakeup chip */
                    355:     pci_write_config_dword(pci, 0x40, 0x00000000);
                    356: 
                    357:     adjust_pci_device(pci);
                    358: 
                    359:     /* get MAC address */
                    360:     ret = 0;
                    361:     pci_read_config_byte(pci, PCI_REVISION, &revision);
                    362:     
                    363:     /* save for use later in sis900_reset() */
                    364:     pci_revision = revision; 
                    365: 
                    366:     if (revision == SIS630E_900_REV)
                    367:         ret = sis630e_get_mac_addr(pci, nic);
                    368:     else if ((revision > 0x81) && (revision <= 0x90))
                    369:         ret = sis635_get_mac_addr(pci, nic);
                    370:     else if (revision == SIS96x_900_REV)
                    371:        ret = sis96x_get_mac_addr(pci, nic);
                    372:     else
                    373:         ret = sis900_get_mac_addr(pci, nic);
                    374: 
                    375:     if (ret == 0)
                    376:     {
                    377:         printf ("sis900_probe: Error MAC address not found\n");
                    378:         return 0;
                    379:     }
                    380: 
                    381:     /* 630ET : set the mii access mode as software-mode */
                    382:     if (revision == SIS630ET_900_REV)
                    383:        outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);
                    384: 
                    385:     DBG( "sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id );
                    386: 
                    387:     /* probe for mii transceiver */
                    388:     /* search for total of 32 possible mii phy addresses */
                    389: 
                    390:     found = 0;
                    391:     for (phy_addr = 0; phy_addr < 32; phy_addr++) {
                    392:         u16 mii_status;
                    393:         u16 phy_id0, phy_id1;
                    394: 
                    395:         mii_status = sis900_mdio_read(phy_addr, MII_STATUS);
                    396:         if (mii_status == 0xffff || mii_status == 0x0000)
                    397:             /* the mii is not accessable, try next one */
                    398:             continue;
                    399:                 
                    400:         phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
                    401:         phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
                    402: 
                    403:         /* search our mii table for the current mii */ 
                    404:         for (i = 0; mii_chip_table[i].phy_id1; i++) {
                    405: 
                    406:             if ((phy_id0 == mii_chip_table[i].phy_id0) &&
                    407:                 ((phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){
                    408: 
                    409:                 printf("sis900_probe: %s transceiver found at address %d.\n",
                    410:                        mii_chip_table[i].name, phy_addr);
                    411: 
                    412:                 mii.chip_info = &mii_chip_table[i];
                    413:                 mii.phy_addr  = phy_addr;
                    414:                 mii.status    = sis900_mdio_read(phy_addr, MII_STATUS);
                    415:                 mii.next      = NULL;
                    416: 
                    417:                 found=1;
                    418:                 break;
                    419:             }
                    420:         }
                    421:     }
                    422:         
                    423:     if (found == 0) {
                    424:         printf("sis900_probe: No MII transceivers found!\n");
                    425:         return 0;
                    426:     }
                    427: 
                    428:     /* Arbitrarily select the last PHY found as current PHY */
                    429:     cur_phy = mii.phy_addr;
                    430:     printf("sis900_probe: Using %s as default\n",  mii.chip_info->name);
                    431: 
                    432:     /* initialize device */
                    433:     sis900_init(nic);
                    434:     nic->nic_op        = &sis900_operations;
                    435: 
                    436:     return 1;
                    437: }
                    438: 
                    439: 
                    440: 
                    441: 
                    442: /* 
                    443:  * EEPROM Routines:  These functions read and write to EEPROM for 
                    444:  *    retrieving the MAC address and other configuration information about 
                    445:  *    the card.
                    446:  */
                    447: 
                    448: /* Delay between EEPROM clock transitions. */
                    449: #define eeprom_delay()  inl(ee_addr)
                    450: 
                    451: 
                    452: /* Function: sis900_read_eeprom
                    453:  *
                    454:  * Description: reads and returns a given location from EEPROM
                    455:  *
                    456:  * Arguments: int location:       requested EEPROM location
                    457:  *
                    458:  * Returns:   u16:                contents of requested EEPROM location
                    459:  *
                    460:  */
                    461: 
                    462: /* Read Serial EEPROM through EEPROM Access Register, Note that location is 
                    463:    in word (16 bits) unit */
                    464: static u16 sis900_read_eeprom(int location)
                    465: {
                    466:     int i;
                    467:     u16 retval = 0;
                    468:     long ee_addr = ioaddr + mear;
                    469:     u32 read_cmd = location | EEread;
                    470: 
                    471:     outl(0, ee_addr);
                    472:     eeprom_delay();
                    473:     outl(EECS, ee_addr);
                    474:     eeprom_delay();
                    475: 
                    476:     /* Shift the read command (9) bits out. */
                    477:     for (i = 8; i >= 0; i--) {
                    478:         u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
                    479:         outl(dataval, ee_addr);
                    480:         eeprom_delay();
                    481:         outl(dataval | EECLK, ee_addr);
                    482:         eeprom_delay();
                    483:     }
                    484:     outl(EECS, ee_addr);
                    485:     eeprom_delay();
                    486: 
                    487:     /* read the 16-bits data in */
                    488:     for (i = 16; i > 0; i--) {
                    489:         outl(EECS, ee_addr);
                    490:         eeprom_delay();
                    491:         outl(EECS | EECLK, ee_addr);
                    492:         eeprom_delay();
                    493:         retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
                    494:         eeprom_delay();
                    495:     }
                    496:                 
                    497:     /* Terminate the EEPROM access. */
                    498:     outl(0, ee_addr);
                    499:     eeprom_delay();
                    500: //  outl(EECLK, ee_addr);
                    501: 
                    502:     return (retval);
                    503: }
                    504: 
                    505: #define sis900_mdio_delay()    inl(mdio_addr)
                    506: 
                    507: 
                    508: /* 
                    509:    Read and write the MII management registers using software-generated
                    510:    serial MDIO protocol. Note that the command bits and data bits are
                    511:    send out seperately 
                    512: */
                    513: 
                    514: static void sis900_mdio_idle(long mdio_addr)
                    515: {
                    516:     outl(MDIO | MDDIR, mdio_addr);
                    517:     sis900_mdio_delay();
                    518:     outl(MDIO | MDDIR | MDC, mdio_addr);
                    519: }
                    520: 
                    521: /* Syncronize the MII management interface by shifting 32 one bits out. */
                    522: static void sis900_mdio_reset(long mdio_addr)
                    523: {
                    524:     int i;
                    525: 
                    526:     for (i = 31; i >= 0; i--) {
                    527:         outl(MDDIR | MDIO, mdio_addr);
                    528:         sis900_mdio_delay();
                    529:         outl(MDDIR | MDIO | MDC, mdio_addr);
                    530:         sis900_mdio_delay();
                    531:     }
                    532:     return;
                    533: }
                    534: 
                    535: static u16 sis900_mdio_read(int phy_id, int location)
                    536: {
                    537:     long mdio_addr = ioaddr + mear;
                    538:     int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
                    539:     u16 retval = 0;
                    540:     int i;
                    541: 
                    542:     sis900_mdio_reset(mdio_addr);
                    543:     sis900_mdio_idle(mdio_addr);
                    544: 
                    545:     for (i = 15; i >= 0; i--) {
                    546:         int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
                    547:         outl(dataval, mdio_addr);
                    548:         sis900_mdio_delay();
                    549:         outl(dataval | MDC, mdio_addr);
                    550:         sis900_mdio_delay();
                    551:     }
                    552: 
                    553:     /* Read the 16 data bits. */
                    554:     for (i = 16; i > 0; i--) {
                    555:         outl(0, mdio_addr);
                    556:         sis900_mdio_delay();
                    557:         retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
                    558:         outl(MDC, mdio_addr);
                    559:         sis900_mdio_delay();
                    560:     }
                    561:     outl(0x00, mdio_addr);
                    562:     return retval;
                    563: }
                    564: 
                    565: #if 0
                    566: static void sis900_mdio_write(int phy_id, int location, int value)
                    567: {
                    568:     long mdio_addr = ioaddr + mear;
                    569:     int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
                    570:     int i;
                    571: 
                    572:     sis900_mdio_reset(mdio_addr);
                    573:     sis900_mdio_idle(mdio_addr);
                    574: 
                    575:     /* Shift the command bits out. */
                    576:     for (i = 15; i >= 0; i--) {
                    577:         int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
                    578:         outb(dataval, mdio_addr);
                    579:         sis900_mdio_delay();
                    580:         outb(dataval | MDC, mdio_addr);
                    581:         sis900_mdio_delay();
                    582:     }
                    583:     sis900_mdio_delay();
                    584: 
                    585:     /* Shift the value bits out. */
                    586:     for (i = 15; i >= 0; i--) {
                    587:         int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
                    588:         outl(dataval, mdio_addr);
                    589:         sis900_mdio_delay();
                    590:         outl(dataval | MDC, mdio_addr);
                    591:         sis900_mdio_delay();
                    592:     }
                    593:     sis900_mdio_delay();
                    594:         
                    595:     /* Clear out extra bits. */
                    596:     for (i = 2; i > 0; i--) {
                    597:         outb(0, mdio_addr);
                    598:         sis900_mdio_delay();
                    599:         outb(MDC, mdio_addr);
                    600:         sis900_mdio_delay();
                    601:     }
                    602:     outl(0x00, mdio_addr);
                    603:     return;
                    604: }
                    605: #endif
                    606: 
                    607: 
                    608: /* Function: sis900_init
                    609:  *
                    610:  * Description: resets the ethernet controller chip and various
                    611:  *    data structures required for sending and receiving packets.
                    612:  *    
                    613:  * Arguments: struct nic *nic:          NIC data structure
                    614:  *
                    615:  * returns:   void.
                    616:  */
                    617: 
                    618: static void
                    619: sis900_init(struct nic *nic)
                    620: {
                    621:     /* Soft reset the chip. */
                    622:     sis900_reset(nic);
                    623: 
                    624:     sis900_init_rxfilter(nic);
                    625: 
                    626:     sis900_init_txd(nic);
                    627:     sis900_init_rxd(nic);
                    628: 
                    629:     sis900_set_rx_mode(nic);
                    630: 
                    631:     sis900_check_mode(nic);
                    632: 
                    633:     outl(RxENA| inl(ioaddr + cr), ioaddr + cr);
                    634: }
                    635: 
                    636: 
                    637: /* 
                    638:  * Function: sis900_reset
                    639:  *
                    640:  * Description: disables interrupts and soft resets the controller chip
                    641:  *
                    642:  * Arguments: struct nic *nic:          NIC data structure
                    643:  *
                    644:  * Returns:   void.
                    645:  */
                    646: 
                    647: static void 
                    648: sis900_reset(struct nic *nic __unused)
                    649: {
                    650:     int i = 0;
                    651:     u32 status = TxRCMP | RxRCMP;
                    652: 
                    653:     outl(0, ioaddr + ier);
                    654:     outl(0, ioaddr + imr);
                    655:     outl(0, ioaddr + rfcr);
                    656: 
                    657:     outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr);
                    658: 
                    659:     /* Check that the chip has finished the reset. */
                    660:     while (status && (i++ < 1000)) {
                    661:         status ^= (inl(isr + ioaddr) & status);
                    662:     }
                    663: 
                    664:     if( (pci_revision >= SIS635A_900_REV) || (pci_revision == SIS900B_900_REV) )
                    665:             outl(PESEL | RND_CNT, ioaddr + cfg);
                    666:     else
                    667:             outl(PESEL, ioaddr + cfg);
                    668: }
                    669: 
                    670: 
                    671: /* Function: sis_init_rxfilter
                    672:  *
                    673:  * Description: sets receive filter address to our MAC address
                    674:  *
                    675:  * Arguments: struct nic *nic:          NIC data structure
                    676:  *
                    677:  * returns:   void.
                    678:  */
                    679: 
                    680: static void
                    681: sis900_init_rxfilter(struct nic *nic)
                    682: {
                    683:     u32 rfcrSave;
                    684:     int i;
                    685:         
                    686:     rfcrSave = inl(rfcr + ioaddr);
                    687: 
                    688:     /* disable packet filtering before setting filter */
                    689:     outl(rfcrSave & ~RFEN, rfcr + ioaddr);
                    690: 
                    691:     /* load MAC addr to filter data register */
                    692:     for (i = 0 ; i < 3 ; i++) {
                    693:         u32 w;
                    694: 
                    695:         w = (u32) *((u16 *)(nic->node_addr)+i);
                    696:         outl((i << RFADDR_shift), ioaddr + rfcr);
                    697:         outl(w, ioaddr + rfdr);
                    698: 
                    699:         if (sis900_debug > 0)
                    700:             printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
                    701:                    i, inl(ioaddr + rfdr));
                    702:     }
                    703: 
                    704:     /* enable packet filitering */
                    705:     outl(rfcrSave | RFEN, rfcr + ioaddr);
                    706: }
                    707: 
                    708: 
                    709: /* 
                    710:  * Function: sis_init_txd
                    711:  *
                    712:  * Description: initializes the Tx descriptor
                    713:  *
                    714:  * Arguments: struct nic *nic:          NIC data structure
                    715:  *
                    716:  * returns:   void.
                    717:  */
                    718: 
                    719: static void
                    720: sis900_init_txd(struct nic *nic __unused)
                    721: {
                    722:     txd.link   = (u32) 0;
                    723:     txd.cmdsts = (u32) 0;
                    724:     txd.bufptr = virt_to_bus(&txb[0]);
                    725: 
                    726:     /* load Transmit Descriptor Register */
                    727:     outl(virt_to_bus(&txd), ioaddr + txdp); 
                    728:     if (sis900_debug > 0)
                    729:         printf("sis900_init_txd: TX descriptor register loaded with: %X\n", 
                    730:                inl(ioaddr + txdp));
                    731: }
                    732: 
                    733: 
                    734: /* Function: sis_init_rxd
                    735:  *
                    736:  * Description: initializes the Rx descriptor ring
                    737:  *    
                    738:  * Arguments: struct nic *nic:          NIC data structure
                    739:  *
                    740:  * Returns:   void.
                    741:  */
                    742: 
                    743: static void 
                    744: sis900_init_rxd(struct nic *nic __unused) 
                    745: { 
                    746:     int i;
                    747: 
                    748:     cur_rx = 0; 
                    749: 
                    750:     /* init RX descriptor */
                    751:     for (i = 0; i < NUM_RX_DESC; i++) {
                    752:         rxd[i].link   = virt_to_bus((i+1 < NUM_RX_DESC) ? &rxd[i+1] : &rxd[0]);
                    753:         rxd[i].cmdsts = (u32) RX_BUF_SIZE;
                    754:         rxd[i].bufptr = virt_to_bus(&rxb[i*RX_BUF_SIZE]);
                    755:         if (sis900_debug > 0)
                    756:             printf("sis900_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n", 
                    757:                    i, &rxd[i], (unsigned int) rxd[i].link, (unsigned int) rxd[i].cmdsts,
                    758:                   (unsigned int) rxd[i].bufptr);
                    759:     }
                    760: 
                    761:     /* load Receive Descriptor Register */
                    762:     outl(virt_to_bus(&rxd[0]), ioaddr + rxdp);
                    763: 
                    764:     if (sis900_debug > 0)
                    765:         printf("sis900_init_rxd: RX descriptor register loaded with: %X\n", 
                    766:                inl(ioaddr + rxdp));
                    767: 
                    768: }
                    769: 
                    770: 
                    771: /* Function: sis_init_rxd
                    772:  *
                    773:  * Description: 
                    774:  *    sets the receive mode to accept all broadcast packets and packets
                    775:  *    with our MAC address, and reject all multicast packets.      
                    776:  *    
                    777:  * Arguments: struct nic *nic:          NIC data structure
                    778:  *
                    779:  * Returns:   void.
                    780:  */
                    781: 
                    782: static void sis900_set_rx_mode(struct nic *nic __unused)
                    783: {
                    784:     int i, table_entries;
                    785:     u32 rx_mode; 
                    786:     u16 mc_filter[16] = {0};   /* 256/128 bits multicast hash table */
                    787:        
                    788:     if((pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV))
                    789:        table_entries = 16;
                    790:     else
                    791:        table_entries = 8;
                    792: 
                    793:     /* accept all multicast packet */
                    794:     rx_mode = RFAAB | RFAAM;
                    795:     for (i = 0; i < table_entries; i++)
                    796:                mc_filter[i] = 0xffff;
                    797:                                        
                    798:     /* update Multicast Hash Table in Receive Filter */
                    799:     for (i = 0; i < table_entries; i++) {
                    800:         /* why plus 0x04? That makes the correct value for hash table. */
                    801:         outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
                    802:         outl(mc_filter[i], ioaddr + rfdr);
                    803:     }
                    804: 
                    805:     /* Accept Broadcast and multicast packets, destination addresses that match 
                    806:        our MAC address */
                    807:     outl(RFEN | rx_mode, ioaddr + rfcr);
                    808: 
                    809:     return;
                    810: }
                    811: 
                    812: 
                    813: /* Function: sis900_check_mode
                    814:  *
                    815:  * Description: checks the state of transmit and receive
                    816:  *    parameters on the NIC, and updates NIC registers to match
                    817:  *    
                    818:  * Arguments: struct nic *nic:          NIC data structure
                    819:  *
                    820:  * Returns:   void.
                    821:  */
                    822: 
                    823: static void
                    824: sis900_check_mode(struct nic *nic)
                    825: {
                    826:     int speed, duplex;
                    827:     u32 tx_flags = 0, rx_flags = 0;
                    828: 
                    829:     mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex);
                    830: 
                    831:     if( inl(ioaddr + cfg) & EDB_MASTER_EN ) {
                    832:         tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
                    833:        rx_flags = DMA_BURST_64 << RxMXDMA_shift;
                    834:     }
                    835:     else {
                    836:             tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
                    837:             rx_flags = DMA_BURST_512 << RxMXDMA_shift;
                    838:     }
                    839: 
                    840:     if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
                    841:         rx_flags |= (RxDRNT_10 << RxDRNT_shift);
                    842:         tx_flags |= (TxDRNT_10 << TxDRNT_shift);
                    843:     }
                    844:     else {
                    845:         rx_flags |= (RxDRNT_100 << RxDRNT_shift);
                    846:         tx_flags |= (TxDRNT_100 << TxDRNT_shift);
                    847:     }
                    848: 
                    849:     if (duplex == FDX_CAPABLE_FULL_SELECTED) {
                    850:         tx_flags |= (TxCSI | TxHBI);
                    851:         rx_flags |= RxATX;
                    852:     }
                    853: 
                    854:     outl (tx_flags, ioaddr + txcfg);
                    855:     outl (rx_flags, ioaddr + rxcfg);
                    856: }
                    857: 
                    858: 
                    859: /* Function: sis900_read_mode
                    860:  *
                    861:  * Description: retrieves and displays speed and duplex
                    862:  *    parameters from the NIC
                    863:  *    
                    864:  * Arguments: struct nic *nic:          NIC data structure
                    865:  *
                    866:  * Returns:   void.
                    867:  */
                    868: 
                    869: static void
                    870: sis900_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
                    871: {
                    872:     int i = 0;
                    873:     u32 status;
                    874:     u16 phy_id0, phy_id1;
                    875:         
                    876:     /* STSOUT register is Latched on Transition, read operation updates it */
                    877:     do {
                    878:         status = sis900_mdio_read(phy_addr, MII_STSOUT);
                    879:     } while (i++ < 2);
                    880: 
                    881:     *speed = HW_SPEED_10_MBPS;
                    882:     *duplex = FDX_CAPABLE_HALF_SELECTED;
                    883:     
                    884:     if (status & (MII_NWAY_TX | MII_NWAY_TX_FDX))
                    885:        *speed = HW_SPEED_100_MBPS;
                    886:     if (status & ( MII_NWAY_TX_FDX | MII_NWAY_T_FDX))
                    887:        *duplex = FDX_CAPABLE_FULL_SELECTED;
                    888:        
                    889:     /* Workaround for Realtek RTL8201 PHY issue */
                    890:     phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
                    891:     phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
                    892:     if((phy_id0 == 0x0000) && ((phy_id1 & 0xFFF0) == 0x8200)){
                    893:        if(sis900_mdio_read(phy_addr, MII_CONTROL) & MII_CNTL_FDX)
                    894:            *duplex = FDX_CAPABLE_FULL_SELECTED;
                    895:        if(sis900_mdio_read(phy_addr, 0x0019) & 0x01)
                    896:            *speed = HW_SPEED_100_MBPS;
                    897:     }
                    898: 
                    899:     if (status & MII_STSOUT_LINK_FAIL)
                    900:         printf("sis900_read_mode: Media Link Off\n");
                    901:     else
                    902:         printf("sis900_read_mode: Media Link On %s %s-duplex \n", 
                    903:                *speed == HW_SPEED_100_MBPS ? 
                    904:                "100mbps" : "10mbps",
                    905:                *duplex == FDX_CAPABLE_FULL_SELECTED ?
                    906:                "full" : "half");
                    907: }
                    908: 
                    909: 
                    910: /* Function: amd79c901_read_mode
                    911:  *
                    912:  * Description: retrieves and displays speed and duplex
                    913:  *    parameters from the NIC
                    914:  *    
                    915:  * Arguments: struct nic *nic:          NIC data structure
                    916:  *
                    917:  * Returns:   void.
                    918:  */
                    919: 
                    920: static void
                    921: amd79c901_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
                    922: {
                    923:     int i;
                    924:     u16 status;
                    925:         
                    926:     for (i = 0; i < 2; i++)
                    927:         status = sis900_mdio_read(phy_addr, MII_STATUS);
                    928: 
                    929:     if (status & MII_STAT_CAN_AUTO) {
                    930:         /* 10BASE-T PHY */
                    931:         for (i = 0; i < 2; i++)
                    932:             status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY);
                    933:         if (status & MII_STSSUM_SPD)
                    934:             *speed = HW_SPEED_100_MBPS;
                    935:         else
                    936:             *speed = HW_SPEED_10_MBPS;
                    937:         if (status & MII_STSSUM_DPLX)
                    938:             *duplex = FDX_CAPABLE_FULL_SELECTED;
                    939:         else
                    940:             *duplex = FDX_CAPABLE_HALF_SELECTED;
                    941: 
                    942:         if (status & MII_STSSUM_LINK)
                    943:             printf("amd79c901_read_mode: Media Link On %s %s-duplex \n", 
                    944:                    *speed == HW_SPEED_100_MBPS ? 
                    945:                    "100mbps" : "10mbps",
                    946:                    *duplex == FDX_CAPABLE_FULL_SELECTED ?
                    947:                    "full" : "half");
                    948:         else
                    949:             printf("amd79c901_read_mode: Media Link Off\n");
                    950:     }
                    951:     else {
                    952:         /* HomePNA */
                    953:         *speed = HW_SPEED_HOME;
                    954:         *duplex = FDX_CAPABLE_HALF_SELECTED;
                    955:         if (status & MII_STAT_LINK)
                    956:             printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");
                    957:         else
                    958:             printf("amd79c901_read_mode: Media Link Off\n");
                    959:     }
                    960: }
                    961: 
                    962: 
                    963: /**
                    964:  *     ics1893_read_mode: - read media mode for ICS1893 PHY
                    965:  *     @net_dev: the net device to read mode for
                    966:  *     @phy_addr: mii phy address
                    967:  *     @speed: the transmit speed to be determined
                    968:  *     @duplex: the duplex mode to be determined
                    969:  *
                    970:  *     ICS1893 PHY use Quick Poll Detailed Status register
                    971:  *     to determine the speed and duplex mode for sis900
                    972:  */
                    973: 
                    974: static void ics1893_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
                    975: {
                    976:        int i = 0;
                    977:        u32 status;
                    978: 
                    979:        /* MII_QPDSTS is Latched, read twice in succession will reflect the current state */
                    980:        for (i = 0; i < 2; i++)
                    981:                status = sis900_mdio_read(phy_addr, MII_QPDSTS);
                    982: 
                    983:        if (status & MII_STSICS_SPD)
                    984:                *speed = HW_SPEED_100_MBPS;
                    985:        else
                    986:                *speed = HW_SPEED_10_MBPS;
                    987: 
                    988:        if (status & MII_STSICS_DPLX)
                    989:                *duplex = FDX_CAPABLE_FULL_SELECTED;
                    990:        else
                    991:                *duplex = FDX_CAPABLE_HALF_SELECTED;
                    992: 
                    993:        if (status & MII_STSICS_LINKSTS)
                    994:                printf("ics1893_read_mode: Media Link On %s %s-duplex \n",
                    995:                       *speed == HW_SPEED_100_MBPS ?
                    996:                       "100mbps" : "10mbps",
                    997:                       *duplex == FDX_CAPABLE_FULL_SELECTED ?
                    998:                       "full" : "half");
                    999:        else
                   1000:                printf("ics1893_read_mode: Media Link Off\n");
                   1001: }
                   1002: 
                   1003: /**
                   1004:  *     rtl8201_read_mode: - read media mode for rtl8201 phy
                   1005:  *     @nic: the net device to read mode for
                   1006:  *     @phy_addr: mii phy address
                   1007:  *     @speed: the transmit speed to be determined
                   1008:  *     @duplex: the duplex mode to be determined
                   1009:  *
                   1010:  *     read MII_STATUS register from rtl8201 phy
                   1011:  *     to determine the speed and duplex mode for sis900
                   1012:  */
                   1013: 
                   1014: static void rtl8201_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
                   1015: {
                   1016:        u32 status;
                   1017: 
                   1018:        status = sis900_mdio_read(phy_addr, MII_STATUS);
                   1019: 
                   1020:        if (status & MII_STAT_CAN_TX_FDX) {
                   1021:                *speed = HW_SPEED_100_MBPS;
                   1022:                *duplex = FDX_CAPABLE_FULL_SELECTED;
                   1023:        }
                   1024:        else if (status & MII_STAT_CAN_TX) {
                   1025:                *speed = HW_SPEED_100_MBPS;
                   1026:                *duplex = FDX_CAPABLE_HALF_SELECTED;
                   1027:        }
                   1028:        else if (status & MII_STAT_CAN_T_FDX) {
                   1029:                *speed = HW_SPEED_10_MBPS;
                   1030:                *duplex = FDX_CAPABLE_FULL_SELECTED;
                   1031:        }
                   1032:        else if (status & MII_STAT_CAN_T) {
                   1033:                *speed = HW_SPEED_10_MBPS;
                   1034:                *duplex = FDX_CAPABLE_HALF_SELECTED;
                   1035:        }
                   1036: 
                   1037:        if (status & MII_STAT_LINK)
                   1038:                printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",
                   1039:                       *speed == HW_SPEED_100_MBPS ?
                   1040:                       "100mbps" : "10mbps",
                   1041:                       *duplex == FDX_CAPABLE_FULL_SELECTED ?
                   1042:                       "full" : "half");
                   1043:        else
                   1044:                printf("rtl8201_read_config_mode: Media Link Off\n");
                   1045: }
                   1046: 
                   1047: /**
                   1048:  *     vt6103_read_mode: - read media mode for vt6103 phy
                   1049:  *     @nic: the net device to read mode for
                   1050:  *     @phy_addr: mii phy address
                   1051:  *     @speed: the transmit speed to be determined
                   1052:  *     @duplex: the duplex mode to be determined
                   1053:  *
                   1054:  *     read MII_STATUS register from rtl8201 phy
                   1055:  *     to determine the speed and duplex mode for sis900
                   1056:  */
                   1057: 
                   1058: static void vt6103_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
                   1059: {
                   1060:        u32 status;
                   1061: 
                   1062:        status = sis900_mdio_read(phy_addr, MII_STATUS);
                   1063: 
                   1064:        if (status & MII_STAT_CAN_TX_FDX) {
                   1065:                *speed = HW_SPEED_100_MBPS;
                   1066:                *duplex = FDX_CAPABLE_FULL_SELECTED;
                   1067:        }
                   1068:        else if (status & MII_STAT_CAN_TX) {
                   1069:                *speed = HW_SPEED_100_MBPS;
                   1070:                *duplex = FDX_CAPABLE_HALF_SELECTED;
                   1071:        }
                   1072:        else if (status & MII_STAT_CAN_T_FDX) {
                   1073:                *speed = HW_SPEED_10_MBPS;
                   1074:                *duplex = FDX_CAPABLE_FULL_SELECTED;
                   1075:        }
                   1076:        else if (status & MII_STAT_CAN_T) {
                   1077:                *speed = HW_SPEED_10_MBPS;
                   1078:                *duplex = FDX_CAPABLE_HALF_SELECTED;
                   1079:        }
                   1080: 
                   1081:        if (status & MII_STAT_LINK)
                   1082:                printf("vt6103_read_mode: Media Link On %s %s-duplex \n",
                   1083:                       *speed == HW_SPEED_100_MBPS ?
                   1084:                       "100mbps" : "10mbps",
                   1085:                       *duplex == FDX_CAPABLE_FULL_SELECTED ?
                   1086:                       "full" : "half");
                   1087:        else
                   1088:                printf("vt6103_read_config_mode: Media Link Off\n");
                   1089: }
                   1090: 
                   1091: /* Function: sis900_transmit
                   1092:  *
                   1093:  * Description: transmits a packet and waits for completion or timeout.
                   1094:  *
                   1095:  * Arguments: char d[6]:          destination ethernet address.
                   1096:  *            unsigned short t:   ethernet protocol type.
                   1097:  *            unsigned short s:   size of the data-part of the packet.
                   1098:  *            char *p:            the data for the packet.
                   1099:  *    
                   1100:  * Returns:   void.
                   1101:  */
                   1102: 
                   1103: static void
                   1104: sis900_transmit(struct nic  *nic,
                   1105:                 const char  *d,     /* Destination */
                   1106:                 unsigned int t,     /* Type */
                   1107:                 unsigned int s,     /* size */
                   1108:                 const char  *p)     /* Packet */
                   1109: {
                   1110:     u32 to, nstype;
                   1111:     volatile u32 tx_status;
                   1112:     
                   1113:     /* Stop the transmitter */
                   1114:     outl(TxDIS | inl(ioaddr + cr), ioaddr + cr);
                   1115: 
                   1116:     /* load Transmit Descriptor Register */
                   1117:     outl(virt_to_bus(&txd), ioaddr + txdp); 
                   1118:     if (sis900_debug > 1)
                   1119:         printf("sis900_transmit: TX descriptor register loaded with: %X\n", 
                   1120:                inl(ioaddr + txdp));
                   1121: 
                   1122:     memcpy(txb, d, ETH_ALEN);
                   1123:     memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
                   1124:     nstype = htons(t);
                   1125:     memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
                   1126:     memcpy(txb + ETH_HLEN, p, s);
                   1127: 
                   1128:     s += ETH_HLEN;
                   1129:     s &= DSIZE;
                   1130: 
                   1131:     if (sis900_debug > 1)
                   1132:         printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
                   1133: 
                   1134:     /* pad to minimum packet size */
                   1135:     while (s < ETH_ZLEN)  
                   1136:         txb[s++] = '\0';
                   1137: 
                   1138:     /* set the transmit buffer descriptor and enable Transmit State Machine */
                   1139:     txd.bufptr = virt_to_bus(&txb[0]);
                   1140:     txd.cmdsts = (u32) OWN | s;
                   1141: 
                   1142:     /* restart the transmitter */
                   1143:     outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
                   1144: 
                   1145:     if (sis900_debug > 1)
                   1146:         printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);
                   1147: 
                   1148:     to = currticks() + TX_TIMEOUT;
                   1149: 
                   1150:     while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
                   1151:         /* wait */ ;
                   1152: 
                   1153:     if (currticks() >= to) {
                   1154:         printf("sis900_transmit: TX Timeout! Tx status %X.\n", 
                   1155:               (unsigned int) tx_status);
                   1156:     }
                   1157:     
                   1158:     if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
                   1159:         /* packet unsuccessfully transmited */
                   1160:         printf("sis900_transmit: Transmit error, Tx status %X.\n", 
                   1161:               (unsigned int) tx_status);
                   1162:     }
                   1163:     /* Disable interrupts by clearing the interrupt mask. */
                   1164:     outl(0, ioaddr + imr);
                   1165: }
                   1166: 
                   1167: 
                   1168: /* Function: sis900_poll
                   1169:  *
                   1170:  * Description: checks for a received packet and returns it if found.
                   1171:  *
                   1172:  * Arguments: struct nic *nic:          NIC data structure
                   1173:  *
                   1174:  * Returns:   1 if a packet was recieved.
                   1175:  *            0 if no pacet was recieved.
                   1176:  *
                   1177:  * Side effects:
                   1178:  *            Returns (copies) the packet to the array nic->packet.
                   1179:  *            Returns the length of the packet in nic->packetlen.
                   1180:  */
                   1181: 
                   1182: static int
                   1183: sis900_poll(struct nic *nic, int retrieve)
                   1184: {
                   1185:     u32 rx_status = rxd[cur_rx].cmdsts;
                   1186:     int retstat = 0;
                   1187: 
                   1188:      /* acknowledge interrupts by reading interrupt status register */
                   1189:     inl(ioaddr + isr);
                   1190: 
                   1191:     if (sis900_debug > 2)
                   1192:         printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx, 
                   1193:               (unsigned int) rx_status);
                   1194: 
                   1195:     if (!(rx_status & OWN))
                   1196:         return retstat;
                   1197: 
                   1198:     if (sis900_debug > 1)
                   1199:         printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
                   1200:                cur_rx, (unsigned int) rx_status);
                   1201: 
                   1202:     if ( ! retrieve ) return 1;
                   1203:     
                   1204:     nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;
                   1205: 
                   1206:     if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
                   1207:         /* corrupted packet received */
                   1208:         printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
                   1209:                (unsigned int) rx_status);
                   1210:         retstat = 0;
                   1211:     } else {
                   1212:         /* give packet to higher level routine */
                   1213:         memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
                   1214:         retstat = 1;
                   1215:     }
                   1216: 
                   1217:     /* return the descriptor and buffer to receive ring */
                   1218:     rxd[cur_rx].cmdsts = RX_BUF_SIZE;
                   1219:     rxd[cur_rx].bufptr = virt_to_bus(&rxb[cur_rx*RX_BUF_SIZE]);
                   1220:         
                   1221:     if (++cur_rx == NUM_RX_DESC)
                   1222:         cur_rx = 0;
                   1223: 
                   1224:     /* re-enable the potentially idle receive state machine */
                   1225:     outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
                   1226: 
                   1227:     return retstat;
                   1228: 
                   1229: }
                   1230: 
                   1231: 
                   1232: /* Function: sis900_disable
                   1233:  *
                   1234:  * Description: Turns off interrupts and stops Tx and Rx engines
                   1235:  *    
                   1236:  * Arguments: struct nic *nic:          NIC data structure
                   1237:  *
                   1238:  * Returns:   void.
                   1239:  */
                   1240: 
                   1241: static void
                   1242: sis900_disable ( struct nic *nic ) {
                   1243: 
                   1244:     sis900_init(nic);
                   1245: 
                   1246:     /* Disable interrupts by clearing the interrupt mask. */
                   1247:     outl(0, ioaddr + imr);
                   1248:     outl(0, ioaddr + ier);
                   1249:     
                   1250:     /* Stop the chip's Tx and Rx Status Machine */
                   1251:     outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
                   1252: }
                   1253: 
                   1254: 
                   1255: /* Function: sis900_irq
                   1256:  *
                   1257:  * Description: Enable, Disable, or Force, interrupts
                   1258:  *    
                   1259:  * Arguments: struct nic *nic:          NIC data structure
                   1260:  *            irq_action_t action:      Requested action       
                   1261:  *
                   1262:  * Returns:   void.
                   1263:  */
                   1264: 
                   1265: static void
                   1266: sis900_irq(struct nic *nic __unused, irq_action_t action __unused)
                   1267: {
                   1268:   switch ( action ) {
                   1269:   case DISABLE :
                   1270:     outl(0, ioaddr + imr);
                   1271:     break;
                   1272:   case ENABLE :
                   1273:     outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
                   1274:     break;
                   1275:   case FORCE :
                   1276:     break;
                   1277:   }
                   1278: }
                   1279: 
                   1280: static struct nic_operations sis900_operations = {
                   1281:        .connect        = dummy_connect,
                   1282:        .poll           = sis900_poll,
                   1283:        .transmit       = sis900_transmit,
                   1284:        .irq            = sis900_irq,
                   1285: };
                   1286: 
                   1287: static struct pci_device_id sis900_nics[] = {
                   1288: PCI_ROM(0x1039, 0x0900, "sis900",  "SIS900", 0),
                   1289: PCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016", 0),
                   1290: };
                   1291: 
                   1292: PCI_DRIVER ( sis900_driver, sis900_nics, PCI_NO_CLASS );
                   1293: 
                   1294: DRIVER ( "SIS900", nic_driver, pci_driver, sis900_driver,
                   1295:         sis900_probe, sis900_disable );
                   1296: 
                   1297: /*
                   1298:  * Local variables:
                   1299:  *  c-basic-offset: 8
                   1300:  *  c-indent-level: 8
                   1301:  *  tab-width: 8
                   1302:  * End:
                   1303:  */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.