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