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