Adding debian version 3.70~pre8+dfsg-1.
[syslinux-debian/hramrach.git] / gpxe / src / drivers / net / sis900.c
blob585265063233664572c23749882de32939ebcf36
1 /* -*- Mode:C; c-basic-offset:4; -*- */
3 /*
4 sis900.c: An SiS 900/7016 PCI Fast Ethernet driver for Etherboot
5 Copyright (C) 2001 Entity Cyber, Inc.
7 Revision: 1.0 March 1, 2001
9 Author: Marty Connor (mdc@etherboot.org)
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.
15 This software may be used and distributed according to the terms
16 of the GNU Public License (GPL), incorporated herein by reference.
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 */
27 /* Revision History */
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
44 /* Includes */
46 #include "etherboot.h"
47 #include <gpxe/pci.h>
48 #include "nic.h"
50 #include "sis900.h"
52 /* Globals */
54 static struct nic_operations sis900_operations;
56 static int sis900_debug = 0;
58 static unsigned short vendor, dev_id;
59 static unsigned long ioaddr;
60 static u8 pci_revision;
62 static unsigned int cur_phy;
64 static unsigned int cur_rx;
66 struct {
67 BufferDesc txd;
68 BufferDesc rxd[NUM_RX_DESC];
69 unsigned char txb[TX_BUF_SIZE];
70 unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
71 } sis900_bufs __shared;
72 #define txd sis900_bufs.txd
73 #define rxd sis900_bufs.rxd
74 #define txb sis900_bufs.txb
75 #define rxb sis900_bufs.rxb
77 #if 0
78 static struct mac_chip_info {
79 const char *name;
80 u16 vendor_id, device_id, flags;
81 int io_size;
82 } mac_chip_table[] = {
83 { "SiS 900 PCI Fast Ethernet", PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS900,
84 PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
85 { "SiS 7016 PCI Fast Ethernet",PCI_VENDOR_ID_SIS, PCI_DEVICE_ID_SIS7016,
86 PCI_COMMAND_IO|PCI_COMMAND_MASTER, SIS900_TOTAL_SIZE},
87 {0,0,0,0,0} /* 0 terminated list. */
89 #endif
91 static void sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
92 static void amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
93 static void ics1893_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
94 static void rtl8201_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
95 static void vt6103_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex);
97 static struct mii_chip_info {
98 const char * name;
99 u16 phy_id0;
100 u16 phy_id1;
101 void (*read_mode) (struct nic *nic, int phy_addr, int *speed, int *duplex);
102 } mii_chip_table[] = {
103 {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode},
104 {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode},
105 {"SiS 900 on Foxconn 661 7MI", 0x0143, 0xBC70, sis900_read_mode},
106 {"AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, amd79c901_read_mode},
107 {"AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, amd79c901_read_mode},
108 {"ICS 1893 Integrated PHYceiver" , 0x0015, 0xf440,ics1893_read_mode},
109 // {"NS 83851 PHY",0x2000, 0x5C20, MIX },
110 {"RTL 8201 10/100Mbps Phyceiver" , 0x0000, 0x8200,rtl8201_read_mode},
111 {"VIA 6103 10/100Mbps Phyceiver", 0x0101, 0x8f20,vt6103_read_mode},
112 {0,0,0,0}
115 static struct mii_phy {
116 struct mii_phy * next;
117 struct mii_chip_info * chip_info;
118 int phy_addr;
119 u16 status;
120 } mii;
124 #if 0
125 // PCI to ISA bridge for SIS640E access
126 static struct pci_device_id pci_isa_bridge_list[] = {
127 { .vendor = 0x1039, .device = 0x0008,
128 .name = "SIS 85C503/5513 PCI to ISA bridge"},
131 PCI_DRIVER( sis_bridge_pci_driver, pci_isa_bridge_list, PCI_NO_CLASS );
133 static struct device_driver sis_bridge_driver = {
134 .name = "SIS ISA bridge",
135 .bus_driver = &pci_driver,
136 .bus_driver_info = ( struct bus_driver_info * ) &sis_bridge_pci_driver,
138 #endif
140 /* Function Prototypes */
142 static int sis900_probe(struct nic *nic,struct pci_device *pci);
144 static u16 sis900_read_eeprom(int location);
145 static void sis900_mdio_reset(long mdio_addr);
146 static void sis900_mdio_idle(long mdio_addr);
147 static u16 sis900_mdio_read(int phy_id, int location);
148 #if 0
149 static void sis900_mdio_write(int phy_id, int location, int val);
150 #endif
151 static void sis900_init(struct nic *nic);
153 static void sis900_reset(struct nic *nic);
155 static void sis900_init_rxfilter(struct nic *nic);
156 static void sis900_init_txd(struct nic *nic);
157 static void sis900_init_rxd(struct nic *nic);
158 static void sis900_set_rx_mode(struct nic *nic);
159 static void sis900_check_mode(struct nic *nic);
161 static void sis900_transmit(struct nic *nic, const char *d,
162 unsigned int t, unsigned int s, const char *p);
163 static int sis900_poll(struct nic *nic, int retrieve);
165 static void sis900_disable(struct nic *nic);
167 static void sis900_irq(struct nic *nic, irq_action_t action);
170 * sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
171 * @pci_dev: the sis900 pci device
172 * @net_dev: the net device to get address for
174 * Older SiS900 and friends, use EEPROM to store MAC address.
175 * MAC address is read from read_eeprom() into @net_dev->dev_addr.
178 static int sis900_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
180 u16 signature;
181 int i;
183 /* check to see if we have sane EEPROM */
184 signature = (u16) sis900_read_eeprom( EEPROMSignature);
185 if (signature == 0xffff || signature == 0x0000) {
186 printf ("sis900_probe: Error EERPOM read %hX\n", signature);
187 return 0;
190 /* get MAC address from EEPROM */
191 for (i = 0; i < 3; i++)
192 ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
193 return 1;
197 * sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
198 * @pci_dev: the sis900 pci device
199 * @net_dev: the net device to get address for
201 * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
202 * is shared by
203 * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first
204 * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access
205 * by LAN, otherwise is not. After MAC address is read from EEPROM, send
206 * EEDONE signal to refuse EEPROM access by LAN.
207 * The EEPROM map of SiS962 or SiS963 is different to SiS900.
208 * The signature field in SiS962 or SiS963 spec is meaningless.
209 * MAC address is read into @net_dev->dev_addr.
212 static int sis96x_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
214 /* long ioaddr = net_dev->base_addr; */
215 long ee_addr = ioaddr + mear;
216 u32 waittime = 0;
217 int i;
219 printf("Alternate function\n");
221 outl(EEREQ, ee_addr);
222 while(waittime < 2000) {
223 if(inl(ee_addr) & EEGNT) {
225 /* get MAC address from EEPROM */
226 for (i = 0; i < 3; i++)
227 ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
229 outl(EEDONE, ee_addr);
230 return 1;
231 } else {
232 udelay(1);
233 waittime ++;
236 outl(EEDONE, ee_addr);
237 return 0;
241 * sis630e_get_mac_addr: - Get MAC address for SiS630E model
242 * @pci_dev: the sis900 pci device
243 * @net_dev: the net device to get address for
245 * SiS630E model, use APC CMOS RAM to store MAC address.
246 * APC CMOS RAM is accessed through ISA bridge.
247 * MAC address is read into @net_dev->dev_addr.
250 static int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
252 #if 0
253 u8 reg;
254 int i;
255 struct bus_loc bus_loc;
256 union {
257 struct bus_dev bus_dev;
258 struct pci_device isa_bridge;
259 } u;
261 /* find PCI to ISA bridge */
262 memset(&bus_loc, 0, sizeof(bus_loc));
263 if ( ! find_by_driver ( &bus_loc, &u.bus_dev, &sis_bridge_driver, 0 ) )
264 return 0;
266 pci_read_config_byte(&u.isa_bridge, 0x48, &reg);
267 pci_write_config_byte(&u.isa_bridge, 0x48, reg | 0x40);
269 for (i = 0; i < ETH_ALEN; i++)
271 outb(0x09 + i, 0x70);
272 ((u8 *)(nic->node_addr))[i] = inb(0x71);
274 pci_write_config_byte(&u.isa_bridge, 0x48, reg & ~0x40);
276 return 1;
277 #endif
279 /* Does not work with current bus/device model */
280 memset ( nic->node_addr, 0, sizeof ( nic->node_addr ) );
281 return 0;
285 * sis630e_get_mac_addr: - Get MAC address for SiS630E model
286 * @pci_dev: the sis900 pci device
287 * @net_dev: the net device to get address for
289 * SiS630E model, use APC CMOS RAM to store MAC address.
290 * APC CMOS RAM is accessed through ISA bridge.
291 * MAC address is read into @net_dev->dev_addr.
294 static int sis635_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
296 u32 rfcrSave;
297 u32 i;
300 rfcrSave = inl(rfcr + ioaddr);
302 outl(rfcrSave | RELOAD, ioaddr + cr);
303 outl(0, ioaddr + cr);
305 /* disable packet filtering before setting filter */
306 outl(rfcrSave & ~RFEN, rfcr + ioaddr);
308 /* load MAC addr to filter data register */
309 for (i = 0 ; i < 3 ; i++) {
310 outl((i << RFADDR_shift), ioaddr + rfcr);
311 *( ((u16 *)nic->node_addr) + i) = inw(ioaddr + rfdr);
314 /* enable packet filitering */
315 outl(rfcrSave | RFEN, rfcr + ioaddr);
317 return 1;
321 * Function: sis900_probe
323 * Description: initializes initializes the NIC, retrieves the
324 * MAC address of the card, and sets up some globals required by
325 * other routines.
327 * Side effects:
328 * leaves the ioaddress of the sis900 chip in the variable ioaddr.
329 * leaves the sis900 initialized, and ready to recieve packets.
331 * Returns: struct nic *: pointer to NIC data structure
334 static int sis900_probe ( struct nic *nic, struct pci_device *pci ) {
336 int i;
337 int found=0;
338 int phy_addr;
339 u8 revision;
340 int ret;
342 if (pci->ioaddr == 0)
343 return 0;
345 nic->irqno = 0;
346 nic->ioaddr = pci->ioaddr;
348 ioaddr = pci->ioaddr;
349 vendor = pci->vendor;
350 dev_id = pci->device;
352 /* wakeup chip */
353 pci_write_config_dword(pci, 0x40, 0x00000000);
355 adjust_pci_device(pci);
357 /* get MAC address */
358 ret = 0;
359 pci_read_config_byte(pci, PCI_REVISION, &revision);
361 /* save for use later in sis900_reset() */
362 pci_revision = revision;
364 if (revision == SIS630E_900_REV)
365 ret = sis630e_get_mac_addr(pci, nic);
366 else if ((revision > 0x81) && (revision <= 0x90))
367 ret = sis635_get_mac_addr(pci, nic);
368 else if (revision == SIS96x_900_REV)
369 ret = sis96x_get_mac_addr(pci, nic);
370 else
371 ret = sis900_get_mac_addr(pci, nic);
373 if (ret == 0)
375 printf ("sis900_probe: Error MAC address not found\n");
376 return 0;
379 /* 630ET : set the mii access mode as software-mode */
380 if (revision == SIS630ET_900_REV)
381 outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);
383 DBG( "sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id );
385 /* probe for mii transceiver */
386 /* search for total of 32 possible mii phy addresses */
388 found = 0;
389 for (phy_addr = 0; phy_addr < 32; phy_addr++) {
390 u16 mii_status;
391 u16 phy_id0, phy_id1;
393 mii_status = sis900_mdio_read(phy_addr, MII_STATUS);
394 if (mii_status == 0xffff || mii_status == 0x0000)
395 /* the mii is not accessable, try next one */
396 continue;
398 phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
399 phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
401 /* search our mii table for the current mii */
402 for (i = 0; mii_chip_table[i].phy_id1; i++) {
404 if ((phy_id0 == mii_chip_table[i].phy_id0) &&
405 ((phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){
407 printf("sis900_probe: %s transceiver found at address %d.\n",
408 mii_chip_table[i].name, phy_addr);
410 mii.chip_info = &mii_chip_table[i];
411 mii.phy_addr = phy_addr;
412 mii.status = sis900_mdio_read(phy_addr, MII_STATUS);
413 mii.next = NULL;
415 found=1;
416 break;
421 if (found == 0) {
422 printf("sis900_probe: No MII transceivers found!\n");
423 return 0;
426 /* Arbitrarily select the last PHY found as current PHY */
427 cur_phy = mii.phy_addr;
428 printf("sis900_probe: Using %s as default\n", mii.chip_info->name);
430 /* initialize device */
431 sis900_init(nic);
432 nic->nic_op = &sis900_operations;
434 return 1;
441 * EEPROM Routines: These functions read and write to EEPROM for
442 * retrieving the MAC address and other configuration information about
443 * the card.
446 /* Delay between EEPROM clock transitions. */
447 #define eeprom_delay() inl(ee_addr)
450 /* Function: sis900_read_eeprom
452 * Description: reads and returns a given location from EEPROM
454 * Arguments: int location: requested EEPROM location
456 * Returns: u16: contents of requested EEPROM location
460 /* Read Serial EEPROM through EEPROM Access Register, Note that location is
461 in word (16 bits) unit */
462 static u16 sis900_read_eeprom(int location)
464 int i;
465 u16 retval = 0;
466 long ee_addr = ioaddr + mear;
467 u32 read_cmd = location | EEread;
469 outl(0, ee_addr);
470 eeprom_delay();
471 outl(EECS, ee_addr);
472 eeprom_delay();
474 /* Shift the read command (9) bits out. */
475 for (i = 8; i >= 0; i--) {
476 u32 dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
477 outl(dataval, ee_addr);
478 eeprom_delay();
479 outl(dataval | EECLK, ee_addr);
480 eeprom_delay();
482 outl(EECS, ee_addr);
483 eeprom_delay();
485 /* read the 16-bits data in */
486 for (i = 16; i > 0; i--) {
487 outl(EECS, ee_addr);
488 eeprom_delay();
489 outl(EECS | EECLK, ee_addr);
490 eeprom_delay();
491 retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
492 eeprom_delay();
495 /* Terminate the EEPROM access. */
496 outl(0, ee_addr);
497 eeprom_delay();
498 // outl(EECLK, ee_addr);
500 return (retval);
503 #define sis900_mdio_delay() inl(mdio_addr)
507 Read and write the MII management registers using software-generated
508 serial MDIO protocol. Note that the command bits and data bits are
509 send out seperately
512 static void sis900_mdio_idle(long mdio_addr)
514 outl(MDIO | MDDIR, mdio_addr);
515 sis900_mdio_delay();
516 outl(MDIO | MDDIR | MDC, mdio_addr);
519 /* Syncronize the MII management interface by shifting 32 one bits out. */
520 static void sis900_mdio_reset(long mdio_addr)
522 int i;
524 for (i = 31; i >= 0; i--) {
525 outl(MDDIR | MDIO, mdio_addr);
526 sis900_mdio_delay();
527 outl(MDDIR | MDIO | MDC, mdio_addr);
528 sis900_mdio_delay();
530 return;
533 static u16 sis900_mdio_read(int phy_id, int location)
535 long mdio_addr = ioaddr + mear;
536 int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
537 u16 retval = 0;
538 int i;
540 sis900_mdio_reset(mdio_addr);
541 sis900_mdio_idle(mdio_addr);
543 for (i = 15; i >= 0; i--) {
544 int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
545 outl(dataval, mdio_addr);
546 sis900_mdio_delay();
547 outl(dataval | MDC, mdio_addr);
548 sis900_mdio_delay();
551 /* Read the 16 data bits. */
552 for (i = 16; i > 0; i--) {
553 outl(0, mdio_addr);
554 sis900_mdio_delay();
555 retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
556 outl(MDC, mdio_addr);
557 sis900_mdio_delay();
559 outl(0x00, mdio_addr);
560 return retval;
563 #if 0
564 static void sis900_mdio_write(int phy_id, int location, int value)
566 long mdio_addr = ioaddr + mear;
567 int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
568 int i;
570 sis900_mdio_reset(mdio_addr);
571 sis900_mdio_idle(mdio_addr);
573 /* Shift the command bits out. */
574 for (i = 15; i >= 0; i--) {
575 int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
576 outb(dataval, mdio_addr);
577 sis900_mdio_delay();
578 outb(dataval | MDC, mdio_addr);
579 sis900_mdio_delay();
581 sis900_mdio_delay();
583 /* Shift the value bits out. */
584 for (i = 15; i >= 0; i--) {
585 int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
586 outl(dataval, mdio_addr);
587 sis900_mdio_delay();
588 outl(dataval | MDC, mdio_addr);
589 sis900_mdio_delay();
591 sis900_mdio_delay();
593 /* Clear out extra bits. */
594 for (i = 2; i > 0; i--) {
595 outb(0, mdio_addr);
596 sis900_mdio_delay();
597 outb(MDC, mdio_addr);
598 sis900_mdio_delay();
600 outl(0x00, mdio_addr);
601 return;
603 #endif
606 /* Function: sis900_init
608 * Description: resets the ethernet controller chip and various
609 * data structures required for sending and receiving packets.
611 * Arguments: struct nic *nic: NIC data structure
613 * returns: void.
616 static void
617 sis900_init(struct nic *nic)
619 /* Soft reset the chip. */
620 sis900_reset(nic);
622 sis900_init_rxfilter(nic);
624 sis900_init_txd(nic);
625 sis900_init_rxd(nic);
627 sis900_set_rx_mode(nic);
629 sis900_check_mode(nic);
631 outl(RxENA| inl(ioaddr + cr), ioaddr + cr);
636 * Function: sis900_reset
638 * Description: disables interrupts and soft resets the controller chip
640 * Arguments: struct nic *nic: NIC data structure
642 * Returns: void.
645 static void
646 sis900_reset(struct nic *nic __unused)
648 int i = 0;
649 u32 status = TxRCMP | RxRCMP;
651 outl(0, ioaddr + ier);
652 outl(0, ioaddr + imr);
653 outl(0, ioaddr + rfcr);
655 outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr);
657 /* Check that the chip has finished the reset. */
658 while (status && (i++ < 1000)) {
659 status ^= (inl(isr + ioaddr) & status);
662 if( (pci_revision >= SIS635A_900_REV) || (pci_revision == SIS900B_900_REV) )
663 outl(PESEL | RND_CNT, ioaddr + cfg);
664 else
665 outl(PESEL, ioaddr + cfg);
669 /* Function: sis_init_rxfilter
671 * Description: sets receive filter address to our MAC address
673 * Arguments: struct nic *nic: NIC data structure
675 * returns: void.
678 static void
679 sis900_init_rxfilter(struct nic *nic)
681 u32 rfcrSave;
682 int i;
684 rfcrSave = inl(rfcr + ioaddr);
686 /* disable packet filtering before setting filter */
687 outl(rfcrSave & ~RFEN, rfcr + ioaddr);
689 /* load MAC addr to filter data register */
690 for (i = 0 ; i < 3 ; i++) {
691 u32 w;
693 w = (u32) *((u16 *)(nic->node_addr)+i);
694 outl((i << RFADDR_shift), ioaddr + rfcr);
695 outl(w, ioaddr + rfdr);
697 if (sis900_debug > 0)
698 printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%lX\n",
699 i, inl(ioaddr + rfdr));
702 /* enable packet filitering */
703 outl(rfcrSave | RFEN, rfcr + ioaddr);
708 * Function: sis_init_txd
710 * Description: initializes the Tx descriptor
712 * Arguments: struct nic *nic: NIC data structure
714 * returns: void.
717 static void
718 sis900_init_txd(struct nic *nic __unused)
720 txd.link = (u32) 0;
721 txd.cmdsts = (u32) 0;
722 txd.bufptr = virt_to_bus(&txb[0]);
724 /* load Transmit Descriptor Register */
725 outl(virt_to_bus(&txd), ioaddr + txdp);
726 if (sis900_debug > 0)
727 printf("sis900_init_txd: TX descriptor register loaded with: %lX\n",
728 inl(ioaddr + txdp));
732 /* Function: sis_init_rxd
734 * Description: initializes the Rx descriptor ring
736 * Arguments: struct nic *nic: NIC data structure
738 * Returns: void.
741 static void
742 sis900_init_rxd(struct nic *nic __unused)
744 int i;
746 cur_rx = 0;
748 /* init RX descriptor */
749 for (i = 0; i < NUM_RX_DESC; i++) {
750 rxd[i].link = virt_to_bus((i+1 < NUM_RX_DESC) ? &rxd[i+1] : &rxd[0]);
751 rxd[i].cmdsts = (u32) RX_BUF_SIZE;
752 rxd[i].bufptr = virt_to_bus(&rxb[i*RX_BUF_SIZE]);
753 if (sis900_debug > 0)
754 printf("sis900_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n",
755 i, &rxd[i], (unsigned int) rxd[i].link, (unsigned int) rxd[i].cmdsts,
756 (unsigned int) rxd[i].bufptr);
759 /* load Receive Descriptor Register */
760 outl(virt_to_bus(&rxd[0]), ioaddr + rxdp);
762 if (sis900_debug > 0)
763 printf("sis900_init_rxd: RX descriptor register loaded with: %lX\n",
764 inl(ioaddr + rxdp));
769 /* Function: sis_init_rxd
771 * Description:
772 * sets the receive mode to accept all broadcast packets and packets
773 * with our MAC address, and reject all multicast packets.
775 * Arguments: struct nic *nic: NIC data structure
777 * Returns: void.
780 static void sis900_set_rx_mode(struct nic *nic __unused)
782 int i, table_entries;
783 u32 rx_mode;
784 u16 mc_filter[16] = {0}; /* 256/128 bits multicast hash table */
786 if((pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV))
787 table_entries = 16;
788 else
789 table_entries = 8;
791 /* accept all multicast packet */
792 rx_mode = RFAAB | RFAAM;
793 for (i = 0; i < table_entries; i++)
794 mc_filter[i] = 0xffff;
796 /* update Multicast Hash Table in Receive Filter */
797 for (i = 0; i < table_entries; i++) {
798 /* why plus 0x04? That makes the correct value for hash table. */
799 outl((u32)(0x00000004+i) << RFADDR_shift, ioaddr + rfcr);
800 outl(mc_filter[i], ioaddr + rfdr);
803 /* Accept Broadcast and multicast packets, destination addresses that match
804 our MAC address */
805 outl(RFEN | rx_mode, ioaddr + rfcr);
807 return;
811 /* Function: sis900_check_mode
813 * Description: checks the state of transmit and receive
814 * parameters on the NIC, and updates NIC registers to match
816 * Arguments: struct nic *nic: NIC data structure
818 * Returns: void.
821 static void
822 sis900_check_mode(struct nic *nic)
824 int speed, duplex;
825 u32 tx_flags = 0, rx_flags = 0;
827 mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex);
829 if( inl(ioaddr + cfg) & EDB_MASTER_EN ) {
830 tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
831 rx_flags = DMA_BURST_64 << RxMXDMA_shift;
833 else {
834 tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
835 rx_flags = DMA_BURST_512 << RxMXDMA_shift;
838 if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
839 rx_flags |= (RxDRNT_10 << RxDRNT_shift);
840 tx_flags |= (TxDRNT_10 << TxDRNT_shift);
842 else {
843 rx_flags |= (RxDRNT_100 << RxDRNT_shift);
844 tx_flags |= (TxDRNT_100 << TxDRNT_shift);
847 if (duplex == FDX_CAPABLE_FULL_SELECTED) {
848 tx_flags |= (TxCSI | TxHBI);
849 rx_flags |= RxATX;
852 outl (tx_flags, ioaddr + txcfg);
853 outl (rx_flags, ioaddr + rxcfg);
857 /* Function: sis900_read_mode
859 * Description: retrieves and displays speed and duplex
860 * parameters from the NIC
862 * Arguments: struct nic *nic: NIC data structure
864 * Returns: void.
867 static void
868 sis900_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
870 int i = 0;
871 u32 status;
872 u16 phy_id0, phy_id1;
874 /* STSOUT register is Latched on Transition, read operation updates it */
875 do {
876 status = sis900_mdio_read(phy_addr, MII_STSOUT);
877 } while (i++ < 2);
879 *speed = HW_SPEED_10_MBPS;
880 *duplex = FDX_CAPABLE_HALF_SELECTED;
882 if (status & (MII_NWAY_TX | MII_NWAY_TX_FDX))
883 *speed = HW_SPEED_100_MBPS;
884 if (status & ( MII_NWAY_TX_FDX | MII_NWAY_T_FDX))
885 *duplex = FDX_CAPABLE_FULL_SELECTED;
887 /* Workaround for Realtek RTL8201 PHY issue */
888 phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
889 phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
890 if((phy_id0 == 0x0000) && ((phy_id1 & 0xFFF0) == 0x8200)){
891 if(sis900_mdio_read(phy_addr, MII_CONTROL) & MII_CNTL_FDX)
892 *duplex = FDX_CAPABLE_FULL_SELECTED;
893 if(sis900_mdio_read(phy_addr, 0x0019) & 0x01)
894 *speed = HW_SPEED_100_MBPS;
897 if (status & MII_STSOUT_LINK_FAIL)
898 printf("sis900_read_mode: Media Link Off\n");
899 else
900 printf("sis900_read_mode: Media Link On %s %s-duplex \n",
901 *speed == HW_SPEED_100_MBPS ?
902 "100mbps" : "10mbps",
903 *duplex == FDX_CAPABLE_FULL_SELECTED ?
904 "full" : "half");
908 /* Function: amd79c901_read_mode
910 * Description: retrieves and displays speed and duplex
911 * parameters from the NIC
913 * Arguments: struct nic *nic: NIC data structure
915 * Returns: void.
918 static void
919 amd79c901_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
921 int i;
922 u16 status;
924 for (i = 0; i < 2; i++)
925 status = sis900_mdio_read(phy_addr, MII_STATUS);
927 if (status & MII_STAT_CAN_AUTO) {
928 /* 10BASE-T PHY */
929 for (i = 0; i < 2; i++)
930 status = sis900_mdio_read(phy_addr, MII_STATUS_SUMMARY);
931 if (status & MII_STSSUM_SPD)
932 *speed = HW_SPEED_100_MBPS;
933 else
934 *speed = HW_SPEED_10_MBPS;
935 if (status & MII_STSSUM_DPLX)
936 *duplex = FDX_CAPABLE_FULL_SELECTED;
937 else
938 *duplex = FDX_CAPABLE_HALF_SELECTED;
940 if (status & MII_STSSUM_LINK)
941 printf("amd79c901_read_mode: Media Link On %s %s-duplex \n",
942 *speed == HW_SPEED_100_MBPS ?
943 "100mbps" : "10mbps",
944 *duplex == FDX_CAPABLE_FULL_SELECTED ?
945 "full" : "half");
946 else
947 printf("amd79c901_read_mode: Media Link Off\n");
949 else {
950 /* HomePNA */
951 *speed = HW_SPEED_HOME;
952 *duplex = FDX_CAPABLE_HALF_SELECTED;
953 if (status & MII_STAT_LINK)
954 printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");
955 else
956 printf("amd79c901_read_mode: Media Link Off\n");
962 * ics1893_read_mode: - read media mode for ICS1893 PHY
963 * @net_dev: the net device to read mode for
964 * @phy_addr: mii phy address
965 * @speed: the transmit speed to be determined
966 * @duplex: the duplex mode to be determined
968 * ICS1893 PHY use Quick Poll Detailed Status register
969 * to determine the speed and duplex mode for sis900
972 static void ics1893_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
974 int i = 0;
975 u32 status;
977 /* MII_QPDSTS is Latched, read twice in succession will reflect the current state */
978 for (i = 0; i < 2; i++)
979 status = sis900_mdio_read(phy_addr, MII_QPDSTS);
981 if (status & MII_STSICS_SPD)
982 *speed = HW_SPEED_100_MBPS;
983 else
984 *speed = HW_SPEED_10_MBPS;
986 if (status & MII_STSICS_DPLX)
987 *duplex = FDX_CAPABLE_FULL_SELECTED;
988 else
989 *duplex = FDX_CAPABLE_HALF_SELECTED;
991 if (status & MII_STSICS_LINKSTS)
992 printf("ics1893_read_mode: Media Link On %s %s-duplex \n",
993 *speed == HW_SPEED_100_MBPS ?
994 "100mbps" : "10mbps",
995 *duplex == FDX_CAPABLE_FULL_SELECTED ?
996 "full" : "half");
997 else
998 printf("ics1893_read_mode: Media Link Off\n");
1002 * rtl8201_read_mode: - read media mode for rtl8201 phy
1003 * @nic: the net device to read mode for
1004 * @phy_addr: mii phy address
1005 * @speed: the transmit speed to be determined
1006 * @duplex: the duplex mode to be determined
1008 * read MII_STATUS register from rtl8201 phy
1009 * to determine the speed and duplex mode for sis900
1012 static void rtl8201_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
1014 u32 status;
1016 status = sis900_mdio_read(phy_addr, MII_STATUS);
1018 if (status & MII_STAT_CAN_TX_FDX) {
1019 *speed = HW_SPEED_100_MBPS;
1020 *duplex = FDX_CAPABLE_FULL_SELECTED;
1022 else if (status & MII_STAT_CAN_TX) {
1023 *speed = HW_SPEED_100_MBPS;
1024 *duplex = FDX_CAPABLE_HALF_SELECTED;
1026 else if (status & MII_STAT_CAN_T_FDX) {
1027 *speed = HW_SPEED_10_MBPS;
1028 *duplex = FDX_CAPABLE_FULL_SELECTED;
1030 else if (status & MII_STAT_CAN_T) {
1031 *speed = HW_SPEED_10_MBPS;
1032 *duplex = FDX_CAPABLE_HALF_SELECTED;
1035 if (status & MII_STAT_LINK)
1036 printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",
1037 *speed == HW_SPEED_100_MBPS ?
1038 "100mbps" : "10mbps",
1039 *duplex == FDX_CAPABLE_FULL_SELECTED ?
1040 "full" : "half");
1041 else
1042 printf("rtl8201_read_config_mode: Media Link Off\n");
1046 * vt6103_read_mode: - read media mode for vt6103 phy
1047 * @nic: the net device to read mode for
1048 * @phy_addr: mii phy address
1049 * @speed: the transmit speed to be determined
1050 * @duplex: the duplex mode to be determined
1052 * read MII_STATUS register from rtl8201 phy
1053 * to determine the speed and duplex mode for sis900
1056 static void vt6103_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
1058 u32 status;
1060 status = sis900_mdio_read(phy_addr, MII_STATUS);
1062 if (status & MII_STAT_CAN_TX_FDX) {
1063 *speed = HW_SPEED_100_MBPS;
1064 *duplex = FDX_CAPABLE_FULL_SELECTED;
1066 else if (status & MII_STAT_CAN_TX) {
1067 *speed = HW_SPEED_100_MBPS;
1068 *duplex = FDX_CAPABLE_HALF_SELECTED;
1070 else if (status & MII_STAT_CAN_T_FDX) {
1071 *speed = HW_SPEED_10_MBPS;
1072 *duplex = FDX_CAPABLE_FULL_SELECTED;
1074 else if (status & MII_STAT_CAN_T) {
1075 *speed = HW_SPEED_10_MBPS;
1076 *duplex = FDX_CAPABLE_HALF_SELECTED;
1079 if (status & MII_STAT_LINK)
1080 printf("vt6103_read_mode: Media Link On %s %s-duplex \n",
1081 *speed == HW_SPEED_100_MBPS ?
1082 "100mbps" : "10mbps",
1083 *duplex == FDX_CAPABLE_FULL_SELECTED ?
1084 "full" : "half");
1085 else
1086 printf("vt6103_read_config_mode: Media Link Off\n");
1089 /* Function: sis900_transmit
1091 * Description: transmits a packet and waits for completion or timeout.
1093 * Arguments: char d[6]: destination ethernet address.
1094 * unsigned short t: ethernet protocol type.
1095 * unsigned short s: size of the data-part of the packet.
1096 * char *p: the data for the packet.
1098 * Returns: void.
1101 static void
1102 sis900_transmit(struct nic *nic,
1103 const char *d, /* Destination */
1104 unsigned int t, /* Type */
1105 unsigned int s, /* size */
1106 const char *p) /* Packet */
1108 u32 to, nstype;
1109 volatile u32 tx_status;
1111 /* Stop the transmitter */
1112 outl(TxDIS | inl(ioaddr + cr), ioaddr + cr);
1114 /* load Transmit Descriptor Register */
1115 outl(virt_to_bus(&txd), ioaddr + txdp);
1116 if (sis900_debug > 1)
1117 printf("sis900_transmit: TX descriptor register loaded with: %lX\n",
1118 inl(ioaddr + txdp));
1120 memcpy(txb, d, ETH_ALEN);
1121 memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
1122 nstype = htons(t);
1123 memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
1124 memcpy(txb + ETH_HLEN, p, s);
1126 s += ETH_HLEN;
1127 s &= DSIZE;
1129 if (sis900_debug > 1)
1130 printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
1132 /* pad to minimum packet size */
1133 while (s < ETH_ZLEN)
1134 txb[s++] = '\0';
1136 /* set the transmit buffer descriptor and enable Transmit State Machine */
1137 txd.bufptr = virt_to_bus(&txb[0]);
1138 txd.cmdsts = (u32) OWN | s;
1140 /* restart the transmitter */
1141 outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
1143 if (sis900_debug > 1)
1144 printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);
1146 to = currticks() + TX_TIMEOUT;
1148 while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
1149 /* wait */ ;
1151 if (currticks() >= to) {
1152 printf("sis900_transmit: TX Timeout! Tx status %X.\n",
1153 (unsigned int) tx_status);
1156 if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
1157 /* packet unsuccessfully transmited */
1158 printf("sis900_transmit: Transmit error, Tx status %X.\n",
1159 (unsigned int) tx_status);
1161 /* Disable interrupts by clearing the interrupt mask. */
1162 outl(0, ioaddr + imr);
1166 /* Function: sis900_poll
1168 * Description: checks for a received packet and returns it if found.
1170 * Arguments: struct nic *nic: NIC data structure
1172 * Returns: 1 if a packet was recieved.
1173 * 0 if no pacet was recieved.
1175 * Side effects:
1176 * Returns (copies) the packet to the array nic->packet.
1177 * Returns the length of the packet in nic->packetlen.
1180 static int
1181 sis900_poll(struct nic *nic, int retrieve)
1183 u32 rx_status = rxd[cur_rx].cmdsts;
1184 int retstat = 0;
1186 if (sis900_debug > 2)
1187 printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx,
1188 (unsigned int) rx_status);
1190 if (!(rx_status & OWN))
1191 return retstat;
1193 if (sis900_debug > 1)
1194 printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
1195 cur_rx, (unsigned int) rx_status);
1197 if ( ! retrieve ) return 1;
1199 nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;
1201 if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
1202 /* corrupted packet received */
1203 printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
1204 (unsigned int) rx_status);
1205 retstat = 0;
1206 } else {
1207 /* give packet to higher level routine */
1208 memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
1209 retstat = 1;
1212 /* return the descriptor and buffer to receive ring */
1213 rxd[cur_rx].cmdsts = RX_BUF_SIZE;
1214 rxd[cur_rx].bufptr = virt_to_bus(&rxb[cur_rx*RX_BUF_SIZE]);
1216 if (++cur_rx == NUM_RX_DESC)
1217 cur_rx = 0;
1219 /* re-enable the potentially idle receive state machine */
1220 outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
1222 return retstat;
1227 /* Function: sis900_disable
1229 * Description: Turns off interrupts and stops Tx and Rx engines
1231 * Arguments: struct nic *nic: NIC data structure
1233 * Returns: void.
1236 static void
1237 sis900_disable ( struct nic *nic ) {
1239 sis900_init(nic);
1241 /* Disable interrupts by clearing the interrupt mask. */
1242 outl(0, ioaddr + imr);
1243 outl(0, ioaddr + ier);
1245 /* Stop the chip's Tx and Rx Status Machine */
1246 outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
1250 /* Function: sis900_irq
1252 * Description: Enable, Disable, or Force, interrupts
1254 * Arguments: struct nic *nic: NIC data structure
1255 * irq_action_t action: Requested action
1257 * Returns: void.
1260 static void
1261 sis900_irq(struct nic *nic __unused, irq_action_t action __unused)
1263 switch ( action ) {
1264 case DISABLE :
1265 break;
1266 case ENABLE :
1267 break;
1268 case FORCE :
1269 break;
1273 static struct nic_operations sis900_operations = {
1274 .connect = dummy_connect,
1275 .poll = sis900_poll,
1276 .transmit = sis900_transmit,
1277 .irq = sis900_irq,
1280 static struct pci_device_id sis900_nics[] = {
1281 PCI_ROM(0x1039, 0x0900, "sis900", "SIS900"),
1282 PCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016"),
1285 PCI_DRIVER ( sis900_driver, sis900_nics, PCI_NO_CLASS );
1287 DRIVER ( "SIS900", nic_driver, pci_driver, sis900_driver,
1288 sis900_probe, sis900_disable );
1291 * Local variables:
1292 * c-basic-offset: 8
1293 * c-indent-level: 8
1294 * tab-width: 8
1295 * End: