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