• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   01 March 2001  mdc     1.0
31      Initial Release.  Tested with PCI based sis900 card and ThinkNIC
32      computer.
33   20 March 2001 P.Koegel
34      added support for sis630e and PHY ICS1893 and RTL8201
35      Testet with SIS730S chipset + ICS1893
36 */
37 
38 
39 /* Includes */
40 
41 #include "etherboot.h"
42 #include "nic.h"
43 #include "pci.h"
44 #include "cards.h"
45 
46 #include "sis900.h"
47 
48 /* Globals */
49 
50 static int sis900_debug = 0;
51 
52 static unsigned short vendor, dev_id;
53 static unsigned long ioaddr;
54 
55 static unsigned int cur_phy;
56 
57 static unsigned int cur_rx;
58 
59 static BufferDesc txd;
60 static BufferDesc rxd[NUM_RX_DESC];
61 
62 #ifdef USE_LOWMEM_BUFFER
63 #define txb ((char *)0x10000 - TX_BUF_SIZE)
64 #define rxb ((char *)0x10000 - NUM_RX_DESC*RX_BUF_SIZE - TX_BUF_SIZE)
65 #else
66 static unsigned char txb[TX_BUF_SIZE];
67 static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
68 #endif
69 
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 
82 static void sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
83 static void amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
84 static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
85 static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
86 
87 static struct mii_chip_info {
88     const char * name;
89     u16 phy_id0;
90     u16 phy_id1;
91     void (*read_mode) (struct nic *nic, int phy_addr, int *speed, int *duplex);
92 } mii_chip_table[] = {
93     {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode},
94     {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode},
95     {"AMD 79C901 10BASE-T PHY",  0x0000, 0x35b9, amd79c901_read_mode},
96     {"AMD 79C901 HomePNA PHY",   0x0000, 0x35c8, amd79c901_read_mode},
97     {"ICS 1893 Integrated PHYceiver"   , 0x0015, 0xf441,ics1893_read_mode},
98     {"RTL 8201 10/100Mbps Phyceiver"   , 0x0000, 0x8201,rtl8201_read_mode},
99     {0,0,0,0}
100 };
101 
102 static struct mii_phy {
103     struct mii_phy * next;
104     struct mii_chip_info * chip_info;
105     int phy_addr;
106     u16 status;
107 } mii;
108 
109 
110 // PCI to ISA bridge for SIS640E access
111 static struct pci_device   pci_isa_bridge_list[] = {
112 	{ 0x1039, 0x0008,
113 		"SIS 85C503/5513 PCI to ISA bridge", 0, 0, 0, 0},
114 	{0, 0, NULL, 0, 0, 0, 0}
115 };
116 
117 /* Function Prototypes */
118 
119 struct nic *sis900_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci);
120 
121 static u16  sis900_read_eeprom(int location);
122 static void sis900_mdio_reset(long mdio_addr);
123 static void sis900_mdio_idle(long mdio_addr);
124 static u16  sis900_mdio_read(int phy_id, int location);
125 static void sis900_mdio_write(int phy_id, int location, int val);
126 
127 static void sis900_init(struct nic *nic);
128 
129 static void sis900_reset(struct nic *nic);
130 
131 static void sis900_init_rxfilter(struct nic *nic);
132 static void sis900_init_txd(struct nic *nic);
133 static void sis900_init_rxd(struct nic *nic);
134 static void sis900_set_rx_mode(struct nic *nic);
135 static void sis900_check_mode(struct nic *nic);
136 
137 static void sis900_transmit(struct nic *nic, const char *d,
138                             unsigned int t, unsigned int s, const char *p);
139 static int  sis900_poll(struct nic *nic);
140 
141 static void sis900_disable(struct nic *nic);
142 
143 /**
144  *	sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
145  *	@pci_dev: the sis900 pci device
146  *	@net_dev: the net device to get address for
147  *
148  *	Older SiS900 and friends, use EEPROM to store MAC address.
149  *	MAC address is read from read_eeprom() into @net_dev->dev_addr.
150  */
151 
sis900_get_mac_addr(struct pci_device * pci_dev,struct nic * nic)152 static int sis900_get_mac_addr(struct pci_device * pci_dev , struct nic *nic)
153 {
154 	u16 signature;
155 	int i;
156 
157 	/* check to see if we have sane EEPROM */
158 	signature = (u16) sis900_read_eeprom( EEPROMSignature);
159 	if (signature == 0xffff || signature == 0x0000) {
160 		printf ("sis900_probe: Error EERPOM read %hX\n", signature);
161 		return 0;
162 	}
163 
164 	/* get MAC address from EEPROM */
165 	for (i = 0; i < 3; i++)
166 			((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
167 	return 1;
168 }
169 
170 /**
171  *	sis630e_get_mac_addr: - Get MAC address for SiS630E model
172  *	@pci_dev: the sis900 pci device
173  *	@net_dev: the net device to get address for
174  *
175  *	SiS630E model, use APC CMOS RAM to store MAC address.
176  *	APC CMOS RAM is accessed through ISA bridge.
177  *	MAC address is read into @net_dev->dev_addr.
178  */
179 
sis630e_get_mac_addr(struct pci_device * pci_dev,struct nic * nic)180 static int sis630e_get_mac_addr(struct pci_device * pci_dev, struct nic *nic)
181 {
182 	u8 reg;
183 	int i;
184 	struct pci_device	*p;
185 
186 	// find PCI to ISA bridge
187 	eth_pci_init(pci_isa_bridge_list);
188 
189     /* the firts entry in this list should contain bus/devfn */
190     p = pci_isa_bridge_list;
191 
192 	pcibios_read_config_byte(p->bus,p->devfn, 0x48, &reg);
193 	pcibios_write_config_byte(p->bus,p->devfn, 0x48, reg | 0x40);
194 
195 	for (i = 0; i < ETH_ALEN; i++)
196 	{
197 		outb(0x09 + i, 0x70);
198 		((u8 *)(nic->node_addr))[i] = inb(0x71);
199 	}
200 	pcibios_write_config_byte(p->bus,p->devfn, 0x48, reg & ~0x40);
201 
202 	return 1;
203 }
204 
205 /*
206  * Function: sis900_probe
207  *
208  * Description: initializes initializes the NIC, retrieves the
209  *    MAC address of the card, and sets up some globals required by
210  *    other routines.
211  *
212  * Side effects:
213  *            leaves the ioaddress of the sis900 chip in the variable ioaddr.
214  *            leaves the sis900 initialized, and ready to recieve packets.
215  *
216  * Returns:   struct nic *:          pointer to NIC data structure
217  */
218 
sis900_probe(struct nic * nic,unsigned short * io_addrs,struct pci_device * pci)219 struct nic *sis900_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci)
220 {
221     int i;
222     int found=0;
223     int phy_addr;
224     u16 signature;
225     u8 revision;
226     int ret;
227 
228     if (io_addrs == 0 || *io_addrs == 0)
229         return NULL;
230 
231     ioaddr  = *io_addrs & ~3;
232     vendor  = pci->vendor;
233     dev_id  = pci->dev_id;
234 
235     /* wakeup chip */
236     pcibios_write_config_dword(pci->bus, pci->devfn, 0x40, 0x00000000);
237 
238     adjust_pci_device(pci);
239 
240     /* get MAC address */
241     ret = 0;
242     pcibios_read_config_byte(pci->bus,pci->devfn, PCI_REVISION, &revision);
243     if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV)
244        ret = sis630e_get_mac_addr(pci, nic);
245     else if (revision == SIS630S_900_REV)
246         ret = sis630e_get_mac_addr(pci, nic);
247     else
248         ret = sis900_get_mac_addr(pci, nic);
249 
250     if (ret == 0)
251     {
252         printf ("sis900_probe: Error MAC address not found\n");
253         return NULL;
254     }
255 
256     printf("\nsis900_probe: MAC addr %! at ioaddr %#hX\n",
257            nic->node_addr, ioaddr);
258     printf("sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id);
259 
260     /* probe for mii transceiver */
261     /* search for total of 32 possible mii phy addresses */
262 
263     found = 0;
264     for (phy_addr = 0; phy_addr < 32; phy_addr++) {
265         u16 mii_status;
266         u16 phy_id0, phy_id1;
267 
268         mii_status = sis900_mdio_read(phy_addr, MII_STATUS);
269         if (mii_status == 0xffff || mii_status == 0x0000)
270             /* the mii is not accessable, try next one */
271             continue;
272 
273         phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
274         phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
275 
276         /* search our mii table for the current mii */
277         for (i = 0; mii_chip_table[i].phy_id1; i++) {
278 
279             if (phy_id0 == mii_chip_table[i].phy_id0) {
280 
281                 printf("sis900_probe: %s transceiver found at address %d.\n",
282                        mii_chip_table[i].name, phy_addr);
283 
284                 mii.chip_info = &mii_chip_table[i];
285                 mii.phy_addr  = phy_addr;
286                 mii.status    = sis900_mdio_read(phy_addr, MII_STATUS);
287                 mii.next      = NULL;
288 
289                 found=1;
290                 break;
291             }
292         }
293     }
294 
295     if (found == 0) {
296         printf("sis900_probe: No MII transceivers found!\n");
297         return NULL;
298     }
299 
300     /* Arbitrarily select the last PHY found as current PHY */
301     cur_phy = mii.phy_addr;
302     printf("sis900_probe: Using %s as default\n",  mii.chip_info->name);
303 
304     /* initialize device */
305     sis900_init(nic);
306 
307     nic->reset    = sis900_init;
308     nic->poll     = sis900_poll;
309     nic->transmit = sis900_transmit;
310     nic->disable  = sis900_disable;
311 
312     return nic;
313 }
314 
315 
316 /*
317  * EEPROM Routines:  These functions read and write to EEPROM for
318  *    retrieving the MAC address and other configuration information about
319  *    the card.
320  */
321 
322 /* Delay between EEPROM clock transitions. */
323 #define eeprom_delay()  inl(ee_addr)
324 
325 
326 /* Function: sis900_read_eeprom
327  *
328  * Description: reads and returns a given location from EEPROM
329  *
330  * Arguments: int location:       requested EEPROM location
331  *
332  * Returns:   u16:                contents of requested EEPROM location
333  *
334  */
335 
336 /* Read Serial EEPROM through EEPROM Access Register, Note that location is
337    in word (16 bits) unit */
sis900_read_eeprom(int location)338 static u16 sis900_read_eeprom(int location)
339 {
340     int i;
341     u16 retval = 0;
342     long ee_addr = ioaddr + mear;
343     u32 read_cmd = location | EEread;
344 
345     outl(0, ee_addr);
346     eeprom_delay();
347     outl(EECLK, ee_addr);
348     eeprom_delay();
349 
350     /* Shift the read command (9) bits out. */
351     for (i = 8; i >= 0; i--) {
352         u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
353         outl(dataval, ee_addr);
354         eeprom_delay();
355         outl(dataval | EECLK, ee_addr);
356         eeprom_delay();
357     }
358     outb(EECS, ee_addr);
359     eeprom_delay();
360 
361     /* read the 16-bits data in */
362     for (i = 16; i > 0; i--) {
363         outl(EECS, ee_addr);
364         eeprom_delay();
365         outl(EECS | EECLK, ee_addr);
366         eeprom_delay();
367         retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
368         eeprom_delay();
369     }
370 
371     /* Terminate the EEPROM access. */
372     outl(0, ee_addr);
373     eeprom_delay();
374     outl(EECLK, ee_addr);
375 
376     return (retval);
377 }
378 
379 #define sis900_mdio_delay()    inl(mdio_addr)
380 
381 
382 /*
383    Read and write the MII management registers using software-generated
384    serial MDIO protocol. Note that the command bits and data bits are
385    send out seperately
386 */
387 
sis900_mdio_idle(long mdio_addr)388 static void sis900_mdio_idle(long mdio_addr)
389 {
390     outl(MDIO | MDDIR, mdio_addr);
391     sis900_mdio_delay();
392     outl(MDIO | MDDIR | MDC, mdio_addr);
393 }
394 
395 /* Syncronize the MII management interface by shifting 32 one bits out. */
sis900_mdio_reset(long mdio_addr)396 static void sis900_mdio_reset(long mdio_addr)
397 {
398     int i;
399 
400     for (i = 31; i >= 0; i--) {
401         outl(MDDIR | MDIO, mdio_addr);
402         sis900_mdio_delay();
403         outl(MDDIR | MDIO | MDC, mdio_addr);
404         sis900_mdio_delay();
405     }
406     return;
407 }
408 
sis900_mdio_read(int phy_id,int location)409 static u16 sis900_mdio_read(int phy_id, int location)
410 {
411     long mdio_addr = ioaddr + mear;
412     int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
413     u16 retval = 0;
414     int i;
415 
416     sis900_mdio_reset(mdio_addr);
417     sis900_mdio_idle(mdio_addr);
418 
419     for (i = 15; i >= 0; i--) {
420         int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
421         outl(dataval, mdio_addr);
422         sis900_mdio_delay();
423         outl(dataval | MDC, mdio_addr);
424         sis900_mdio_delay();
425     }
426 
427     /* Read the 16 data bits. */
428     for (i = 16; i > 0; i--) {
429         outl(0, mdio_addr);
430         sis900_mdio_delay();
431         retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
432         outl(MDC, mdio_addr);
433         sis900_mdio_delay();
434     }
435     return retval;
436 }
437 
sis900_mdio_write(int phy_id,int location,int value)438 static void sis900_mdio_write(int phy_id, int location, int value)
439 {
440     long mdio_addr = ioaddr + mear;
441     int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
442     int i;
443 
444     sis900_mdio_reset(mdio_addr);
445     sis900_mdio_idle(mdio_addr);
446 
447     /* Shift the command bits out. */
448     for (i = 15; i >= 0; i--) {
449         int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
450         outb(dataval, mdio_addr);
451         sis900_mdio_delay();
452         outb(dataval | MDC, mdio_addr);
453         sis900_mdio_delay();
454     }
455     sis900_mdio_delay();
456 
457     /* Shift the value bits out. */
458     for (i = 15; i >= 0; i--) {
459         int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
460         outl(dataval, mdio_addr);
461         sis900_mdio_delay();
462         outl(dataval | MDC, mdio_addr);
463         sis900_mdio_delay();
464     }
465     sis900_mdio_delay();
466 
467     /* Clear out extra bits. */
468     for (i = 2; i > 0; i--) {
469         outb(0, mdio_addr);
470         sis900_mdio_delay();
471         outb(MDC, mdio_addr);
472         sis900_mdio_delay();
473     }
474     return;
475 }
476 
477 
478 /* Function: sis900_init
479  *
480  * Description: resets the ethernet controller chip and various
481  *    data structures required for sending and receiving packets.
482  *
483  * Arguments: struct nic *nic:          NIC data structure
484  *
485  * returns:   void.
486  */
487 
488 static void
sis900_init(struct nic * nic)489 sis900_init(struct nic *nic)
490 {
491     /* Soft reset the chip. */
492     sis900_reset(nic);
493 
494     sis900_init_rxfilter(nic);
495 
496     sis900_init_txd(nic);
497     sis900_init_rxd(nic);
498 
499     sis900_set_rx_mode(nic);
500 
501     sis900_check_mode(nic);
502 
503     outl(RxENA, ioaddr + cr);
504 }
505 
506 
507 /*
508  * Function: sis900_reset
509  *
510  * Description: disables interrupts and soft resets the controller chip
511  *
512  * Arguments: struct nic *nic:          NIC data structure
513  *
514  * Returns:   void.
515  */
516 
517 static void
sis900_reset(struct nic * nic)518 sis900_reset(struct nic *nic)
519 {
520     int i = 0;
521     u32 status = TxRCMP | RxRCMP;
522 
523     outl(0, ioaddr + ier);
524     outl(0, ioaddr + imr);
525     outl(0, ioaddr + rfcr);
526 
527     outl(RxRESET | TxRESET | RESET, ioaddr + cr);
528 
529     /* Check that the chip has finished the reset. */
530     while (status && (i++ < 1000)) {
531         status ^= (inl(isr + ioaddr) & status);
532     }
533     outl(PESEL, ioaddr + cfg);
534 }
535 
536 
537 /* Function: sis_init_rxfilter
538  *
539  * Description: sets receive filter address to our MAC address
540  *
541  * Arguments: struct nic *nic:          NIC data structure
542  *
543  * returns:   void.
544  */
545 
546 static void
sis900_init_rxfilter(struct nic * nic)547 sis900_init_rxfilter(struct nic *nic)
548 {
549     u32 rfcrSave;
550     int i;
551 
552     rfcrSave = inl(rfcr + ioaddr);
553 
554     /* disable packet filtering before setting filter */
555     outl(rfcrSave & ~RFEN, rfcr);
556 
557     /* load MAC addr to filter data register */
558     for (i = 0 ; i < 3 ; i++) {
559         u32 w;
560 
561         w = (u32) *((u16 *)(nic->node_addr)+i);
562         outl((i << RFADDR_shift), ioaddr + rfcr);
563         outl(w, ioaddr + rfdr);
564 
565         if (sis900_debug > 0)
566             printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
567                    i, inl(ioaddr + rfdr));
568     }
569 
570     /* enable packet filitering */
571     outl(rfcrSave | RFEN, rfcr + ioaddr);
572 }
573 
574 
575 /*
576  * Function: sis_init_txd
577  *
578  * Description: initializes the Tx descriptor
579  *
580  * Arguments: struct nic *nic:          NIC data structure
581  *
582  * returns:   void.
583  */
584 
585 static void
sis900_init_txd(struct nic * nic)586 sis900_init_txd(struct nic *nic)
587 {
588     txd.link   = (u32) 0;
589     txd.cmdsts = (u32) 0;
590     txd.bufptr = (u32) &txb[0];
591 
592     /* load Transmit Descriptor Register */
593     outl((u32) &txd, ioaddr + txdp);
594     if (sis900_debug > 0)
595         printf("sis900_init_txd: TX descriptor register loaded with: %X\n",
596                inl(ioaddr + txdp));
597 }
598 
599 
600 /* Function: sis_init_rxd
601  *
602  * Description: initializes the Rx descriptor ring
603  *
604  * Arguments: struct nic *nic:          NIC data structure
605  *
606  * Returns:   void.
607  */
608 
609 static void
sis900_init_rxd(struct nic * nic)610 sis900_init_rxd(struct nic *nic)
611 {
612     int i;
613 
614     cur_rx = 0;
615 
616     /* init RX descriptor */
617     for (i = 0; i < NUM_RX_DESC; i++) {
618         rxd[i].link   = (i+1 < NUM_RX_DESC) ? (u32) &rxd[i+1] : (u32) &rxd[0];
619         rxd[i].cmdsts = (u32) RX_BUF_SIZE;
620         rxd[i].bufptr = (u32) &rxb[i*RX_BUF_SIZE];
621         if (sis900_debug > 0)
622             printf("sis900_init_rxd: rxd[%d]=%X link=%X cmdsts=%X bufptr=%X\n",
623                    i, &rxd[i], rxd[i].link, rxd[i].cmdsts, rxd[i].bufptr);
624     }
625 
626     /* load Receive Descriptor Register */
627     outl((u32) &rxd[0], ioaddr + rxdp);
628 
629     if (sis900_debug > 0)
630         printf("sis900_init_rxd: RX descriptor register loaded with: %X\n",
631                inl(ioaddr + rxdp));
632 
633 }
634 
635 
636 /* Function: sis_init_rxd
637  *
638  * Description:
639  *    sets the receive mode to accept all broadcast packets and packets
640  *    with our MAC address, and reject all multicast packets.
641  *
642  * Arguments: struct nic *nic:          NIC data structure
643  *
644  * Returns:   void.
645  */
646 
sis900_set_rx_mode(struct nic * nic)647 static void sis900_set_rx_mode(struct nic *nic)
648 {
649     int i;
650 
651     /* Configure Multicast Hash Table in Receive Filter
652        to reject all MCAST packets */
653     for (i = 0; i < 8; i++) {
654         /* why plus 0x04? That makes the correct value for hash table. */
655         outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
656         outl((u32)(0x0), ioaddr + rfdr);
657     }
658     /* Accept Broadcast packets, destination addresses that match
659        our MAC address */
660     outl(RFEN | RFAAB, ioaddr + rfcr);
661 
662     return;
663 }
664 
665 
666 /* Function: sis900_check_mode
667  *
668  * Description: checks the state of transmit and receive
669  *    parameters on the NIC, and updates NIC registers to match
670  *
671  * Arguments: struct nic *nic:          NIC data structure
672  *
673  * Returns:   void.
674  */
675 
676 static void
sis900_check_mode(struct nic * nic)677 sis900_check_mode (struct nic *nic)
678 {
679     int speed, duplex;
680     u32 tx_flags = 0, rx_flags = 0;
681 
682     mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex);
683 
684     tx_flags = TxATP | (TX_DMA_BURST << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
685     rx_flags = RX_DMA_BURST << RxMXDMA_shift;
686 
687     if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
688         rx_flags |= (RxDRNT_10 << RxDRNT_shift);
689         tx_flags |= (TxDRNT_10 << TxDRNT_shift);
690     }
691     else {
692         rx_flags |= (RxDRNT_100 << RxDRNT_shift);
693         tx_flags |= (TxDRNT_100 << TxDRNT_shift);
694     }
695 
696     if (duplex == FDX_CAPABLE_FULL_SELECTED) {
697         tx_flags |= (TxCSI | TxHBI);
698         rx_flags |= RxATX;
699     }
700 
701     outl (tx_flags, ioaddr + txcfg);
702     outl (rx_flags, ioaddr + rxcfg);
703 }
704 
705 
706 /* Function: sis900_read_mode
707  *
708  * Description: retrieves and displays speed and duplex
709  *    parameters from the NIC
710  *
711  * Arguments: struct nic *nic:          NIC data structure
712  *
713  * Returns:   void.
714  */
715 
716 static void
sis900_read_mode(struct nic * nic,int phy_addr,int * speed,int * duplex)717 sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
718 {
719     int i = 0;
720     u32 status;
721 
722     /* STSOUT register is Latched on Transition, read operation updates it */
723     while (i++ < 2)
724         status = sis900_mdio_read(phy_addr, MII_STSOUT);
725 
726     if (status & MII_STSOUT_SPD)
727         *speed = HW_SPEED_100_MBPS;
728     else
729         *speed = HW_SPEED_10_MBPS;
730 
731     if (status & MII_STSOUT_DPLX)
732         *duplex = FDX_CAPABLE_FULL_SELECTED;
733     else
734         *duplex = FDX_CAPABLE_HALF_SELECTED;
735 
736     if (status & MII_STSOUT_LINK_FAIL)
737         printf("sis900_read_mode: Media Link Off\n");
738     else
739         printf("sis900_read_mode: Media Link On %s %s-duplex \n",
740                *speed == HW_SPEED_100_MBPS ?
741                "100mbps" : "10mbps",
742                *duplex == FDX_CAPABLE_FULL_SELECTED ?
743                "full" : "half");
744 }
745 
746 
747 /* Function: amd79c901_read_mode
748  *
749  * Description: retrieves and displays speed and duplex
750  *    parameters from the NIC
751  *
752  * Arguments: struct nic *nic:          NIC data structure
753  *
754  * Returns:   void.
755  */
756 
757 static void
amd79c901_read_mode(struct nic * nic,int phy_addr,int * speed,int * duplex)758 amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
759 {
760     int i;
761     u16 status;
762 
763     for (i = 0; i < 2; i++)
764         status = sis900_mdio_read(phy_addr, MII_STATUS);
765 
766     if (status & MII_STAT_CAN_AUTO) {
767         /* 10BASE-T PHY */
768         for (i = 0; i < 2; i++)
769             status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY);
770         if (status & MII_STSSUM_SPD)
771             *speed = HW_SPEED_100_MBPS;
772         else
773             *speed = HW_SPEED_10_MBPS;
774         if (status & MII_STSSUM_DPLX)
775             *duplex = FDX_CAPABLE_FULL_SELECTED;
776         else
777             *duplex = FDX_CAPABLE_HALF_SELECTED;
778 
779         if (status & MII_STSSUM_LINK)
780             printf("amd79c901_read_mode: Media Link On %s %s-duplex \n",
781                    *speed == HW_SPEED_100_MBPS ?
782                    "100mbps" : "10mbps",
783                    *duplex == FDX_CAPABLE_FULL_SELECTED ?
784                    "full" : "half");
785         else
786             printf("amd79c901_read_mode: Media Link Off\n");
787     }
788     else {
789         /* HomePNA */
790         *speed = HW_SPEED_HOME;
791         *duplex = FDX_CAPABLE_HALF_SELECTED;
792         if (status & MII_STAT_LINK)
793             printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");
794         else
795             printf("amd79c901_read_mode: Media Link Off\n");
796     }
797 }
798 
799 
800 /**
801  *	ics1893_read_mode: - read media mode for ICS1893 PHY
802  *	@net_dev: the net device to read mode for
803  *	@phy_addr: mii phy address
804  *	@speed: the transmit speed to be determined
805  *	@duplex: the duplex mode to be determined
806  *
807  *	ICS1893 PHY use Quick Poll Detailed Status register
808  *	to determine the speed and duplex mode for sis900
809  */
810 
ics1893_read_mode(struct nic * nic,int phy_addr,int * speed,int * duplex)811 static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
812 {
813 	int i = 0;
814 	u32 status;
815 
816 	/* MII_QPDSTS is Latched, read twice in succession will reflect the current state */
817 	for (i = 0; i < 2; i++)
818 		status = sis900_mdio_read(phy_addr, MII_QPDSTS);
819 
820 	if (status & MII_STSICS_SPD)
821 		*speed = HW_SPEED_100_MBPS;
822 	else
823 		*speed = HW_SPEED_10_MBPS;
824 
825 	if (status & MII_STSICS_DPLX)
826 		*duplex = FDX_CAPABLE_FULL_SELECTED;
827 	else
828 		*duplex = FDX_CAPABLE_HALF_SELECTED;
829 
830 	if (status & MII_STSICS_LINKSTS)
831 		printf("ics1893_read_mode: Media Link On %s %s-duplex \n",
832 		       *speed == HW_SPEED_100_MBPS ?
833 		       "100mbps" : "10mbps",
834 		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
835 		       "full" : "half");
836 	else
837 		printf("ics1893_read_mode: Media Link Off\n");
838 }
839 
840 /**
841  *	rtl8201_read_mode: - read media mode for rtl8201 phy
842  *	@nic: the net device to read mode for
843  *	@phy_addr: mii phy address
844  *	@speed: the transmit speed to be determined
845  *	@duplex: the duplex mode to be determined
846  *
847  *	read MII_STATUS register from rtl8201 phy
848  *	to determine the speed and duplex mode for sis900
849  */
850 
rtl8201_read_mode(struct nic * nic,int phy_addr,int * speed,int * duplex)851 static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
852 {
853 	u32 status;
854 
855 	status = sis900_mdio_read(phy_addr, MII_STATUS);
856 
857 	if (status & MII_STAT_CAN_TX_FDX) {
858 		*speed = HW_SPEED_100_MBPS;
859 		*duplex = FDX_CAPABLE_FULL_SELECTED;
860 	}
861 	else if (status & MII_STAT_CAN_TX) {
862 		*speed = HW_SPEED_100_MBPS;
863 		*duplex = FDX_CAPABLE_HALF_SELECTED;
864 	}
865 	else if (status & MII_STAT_CAN_T_FDX) {
866 		*speed = HW_SPEED_10_MBPS;
867 		*duplex = FDX_CAPABLE_FULL_SELECTED;
868 	}
869 	else if (status & MII_STAT_CAN_T) {
870 		*speed = HW_SPEED_10_MBPS;
871 		*duplex = FDX_CAPABLE_HALF_SELECTED;
872 	}
873 
874 	if (status & MII_STAT_LINK)
875 		printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",
876 		       *speed == HW_SPEED_100_MBPS ?
877 		       "100mbps" : "10mbps",
878 		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
879 		       "full" : "half");
880 	else
881 		printf("rtl9201_read_config_mode: Media Link Off\n");
882 }
883 
884 /* Function: sis900_transmit
885  *
886  * Description: transmits a packet and waits for completion or timeout.
887  *
888  * Arguments: char d[6]:          destination ethernet address.
889  *            unsigned short t:   ethernet protocol type.
890  *            unsigned short s:   size of the data-part of the packet.
891  *            char *p:            the data for the packet.
892  *
893  * Returns:   void.
894  */
895 
896 static void
sis900_transmit(struct nic * nic,const char * d,unsigned int t,unsigned int s,const char * p)897 sis900_transmit(struct nic  *nic,
898                 const char  *d,     /* Destination */
899                 unsigned int t,     /* Type */
900                 unsigned int s,     /* size */
901                 const char  *p)     /* Packet */
902 {
903     u32 status, to, nstype;
904     u32 tx_status;
905 
906     /* Stop the transmitter */
907     outl(TxDIS, ioaddr + cr);
908 
909     /* load Transmit Descriptor Register */
910     outl((u32) &txd, ioaddr + txdp);
911     if (sis900_debug > 1)
912         printf("sis900_transmit: TX descriptor register loaded with: %X\n",
913                inl(ioaddr + txdp));
914 
915     memcpy(txb, d, ETH_ALEN);
916     memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
917     nstype = htons(t);
918     memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
919     memcpy(txb + ETH_HLEN, p, s);
920 
921     s += ETH_HLEN;
922     s &= DSIZE;
923 
924     if (sis900_debug > 1)
925         printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
926 
927     /* pad to minimum packet size */
928     while (s < ETH_ZLEN)
929         txb[s++] = '\0';
930 
931     /* set the transmit buffer descriptor and enable Transmit State Machine */
932     txd.bufptr = (u32) &txb[0];
933     txd.cmdsts = (u32) OWN | s;
934 
935     /* restart the transmitter */
936     outl(TxENA, ioaddr + cr);
937 
938     if (sis900_debug > 1)
939         printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);
940 
941     to = currticks() + TX_TIMEOUT;
942 
943     while ((((volatile u32) tx_status=txd.cmdsts) & OWN) && (currticks() < to))
944         /* wait */ ;
945 
946     if (currticks() >= to) {
947         printf("sis900_transmit: TX Timeout! Tx status %X.\n", tx_status);
948     }
949 
950     if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
951         /* packet unsuccessfully transmited */
952         printf("sis900_transmit: Transmit error, Tx status %X.\n", tx_status);
953     }
954     /* Disable interrupts by clearing the interrupt mask. */
955     outl(0, ioaddr + imr);
956 }
957 
958 
959 /* Function: sis900_poll
960  *
961  * Description: checks for a received packet and returns it if found.
962  *
963  * Arguments: struct nic *nic:          NIC data structure
964  *
965  * Returns:   1 if a packet was recieved.
966  *            0 if no pacet was recieved.
967  *
968  * Side effects:
969  *            Returns (copies) the packet to the array nic->packet.
970  *            Returns the length of the packet in nic->packetlen.
971  */
972 
973 static int
sis900_poll(struct nic * nic)974 sis900_poll(struct nic *nic)
975 {
976     u32 rx_status = rxd[cur_rx].cmdsts;
977     int retstat = 0;
978 
979     if (sis900_debug > 2)
980         printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx, rx_status);
981 
982     if (!(rx_status & OWN))
983         return retstat;
984 
985     if (sis900_debug > 1)
986         printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
987                cur_rx, rx_status);
988 
989     nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;
990 
991     if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
992         /* corrupted packet received */
993         printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
994                rx_status);
995         retstat = 0;
996     } else {
997         /* give packet to higher level routine */
998         memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
999         retstat = 1;
1000     }
1001 
1002     /* return the descriptor and buffer to receive ring */
1003     rxd[cur_rx].cmdsts = RX_BUF_SIZE;
1004     rxd[cur_rx].bufptr = (u32) &rxb[cur_rx*RX_BUF_SIZE];
1005 
1006     if (++cur_rx == NUM_RX_DESC)
1007         cur_rx = 0;
1008 
1009     /* re-enable the potentially idle receive state machine */
1010     outl(RxENA , ioaddr + cr);
1011 
1012     return retstat;
1013 }
1014 
1015 
1016 /* Function: sis900_disable
1017  *
1018  * Description: Turns off interrupts and stops Tx and Rx engines
1019  *
1020  * Arguments: struct nic *nic:          NIC data structure
1021  *
1022  * Returns:   void.
1023  */
1024 
1025 static void
sis900_disable(struct nic * nic)1026 sis900_disable(struct nic *nic)
1027 {
1028     /* Disable interrupts by clearing the interrupt mask. */
1029     outl(0, ioaddr + imr);
1030     outl(0, ioaddr + ier);
1031 
1032     /* Stop the chip's Tx and Rx Status Machine */
1033     outl(RxDIS | TxDIS, ioaddr + cr);
1034 }
1035