1 /* -*- Mode:C; c-basic-offset:4; -*- */
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.
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 FILE_LICENCE ( GPL_ANY
);
29 /* Revision History */
32 07 Dec 2003 timlegge - Enabled Multicast Support
33 06 Dec 2003 timlegge - Fixed relocation issue in 5.2
34 04 Jan 2002 Chien-Yu Chen, Doug Ambrisko, Marty Connor Patch to Etherboot 5.0.5
35 Added support for the SiS 630ET plus various bug fixes from linux kernel
38 Initial Release. Tested with PCI based sis900 card and ThinkNIC
40 20 March 2001 P.Koegel
41 added support for sis630e and PHY ICS1893 and RTL8201
42 Testet with SIS730S chipset + ICS1893
48 #include "etherboot.h"
56 static struct nic_operations sis900_operations
;
58 static int sis900_debug
= 0;
60 static unsigned short vendor
, dev_id
;
61 static unsigned long ioaddr
;
62 static u8 pci_revision
;
64 static unsigned int cur_phy
;
66 static unsigned int cur_rx
;
70 BufferDesc rxd
[NUM_RX_DESC
];
71 unsigned char txb
[TX_BUF_SIZE
];
72 unsigned char rxb
[NUM_RX_DESC
* RX_BUF_SIZE
];
73 } sis900_bufs __shared
;
74 #define txd sis900_bufs.txd
75 #define rxd sis900_bufs.rxd
76 #define txb sis900_bufs.txb
77 #define rxb sis900_bufs.rxb
80 static struct mac_chip_info
{
82 u16 vendor_id
, device_id
, flags
;
84 } mac_chip_table
[] = {
85 { "SiS 900 PCI Fast Ethernet", PCI_VENDOR_ID_SIS
, PCI_DEVICE_ID_SIS900
,
86 PCI_COMMAND_IO
|PCI_COMMAND_MASTER
, SIS900_TOTAL_SIZE
},
87 { "SiS 7016 PCI Fast Ethernet",PCI_VENDOR_ID_SIS
, PCI_DEVICE_ID_SIS7016
,
88 PCI_COMMAND_IO
|PCI_COMMAND_MASTER
, SIS900_TOTAL_SIZE
},
89 {0,0,0,0,0} /* 0 terminated list. */
93 static void sis900_read_mode(struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
);
94 static void amd79c901_read_mode(struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
);
95 static void ics1893_read_mode(struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
);
96 static void rtl8201_read_mode(struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
);
97 static void vt6103_read_mode(struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
);
99 static struct mii_chip_info
{
103 void (*read_mode
) (struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
);
104 } mii_chip_table
[] = {
105 {"SiS 900 Internal MII PHY", 0x001d, 0x8000, sis900_read_mode
},
106 {"SiS 7014 Physical Layer Solution", 0x0016, 0xf830,sis900_read_mode
},
107 {"SiS 900 on Foxconn 661 7MI", 0x0143, 0xBC70, sis900_read_mode
},
108 {"AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, amd79c901_read_mode
},
109 {"AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, amd79c901_read_mode
},
110 {"ICS 1893 Integrated PHYceiver" , 0x0015, 0xf440,ics1893_read_mode
},
111 // {"NS 83851 PHY",0x2000, 0x5C20, MIX },
112 {"RTL 8201 10/100Mbps Phyceiver" , 0x0000, 0x8200,rtl8201_read_mode
},
113 {"VIA 6103 10/100Mbps Phyceiver", 0x0101, 0x8f20,vt6103_read_mode
},
117 static struct mii_phy
{
118 struct mii_phy
* next
;
119 struct mii_chip_info
* chip_info
;
127 // PCI to ISA bridge for SIS640E access
128 static struct pci_device_id pci_isa_bridge_list
[] = {
129 { .vendor
= 0x1039, .device
= 0x0008,
130 .name
= "SIS 85C503/5513 PCI to ISA bridge"},
133 PCI_DRIVER( sis_bridge_pci_driver
, pci_isa_bridge_list
, PCI_NO_CLASS
);
135 static struct device_driver sis_bridge_driver
= {
136 .name
= "SIS ISA bridge",
137 .bus_driver
= &pci_driver
,
138 .bus_driver_info
= ( struct bus_driver_info
* ) &sis_bridge_pci_driver
,
142 /* Function Prototypes */
144 static int sis900_probe(struct nic
*nic
,struct pci_device
*pci
);
146 static u16
sis900_read_eeprom(int location
);
147 static void sis900_mdio_reset(long mdio_addr
);
148 static void sis900_mdio_idle(long mdio_addr
);
149 static u16
sis900_mdio_read(int phy_id
, int location
);
151 static void sis900_mdio_write(int phy_id
, int location
, int val
);
153 static void sis900_init(struct nic
*nic
);
155 static void sis900_reset(struct nic
*nic
);
157 static void sis900_init_rxfilter(struct nic
*nic
);
158 static void sis900_init_txd(struct nic
*nic
);
159 static void sis900_init_rxd(struct nic
*nic
);
160 static void sis900_set_rx_mode(struct nic
*nic
);
161 static void sis900_check_mode(struct nic
*nic
);
163 static void sis900_transmit(struct nic
*nic
, const char *d
,
164 unsigned int t
, unsigned int s
, const char *p
);
165 static int sis900_poll(struct nic
*nic
, int retrieve
);
167 static void sis900_disable(struct nic
*nic
);
169 static void sis900_irq(struct nic
*nic
, irq_action_t action
);
172 * sis900_get_mac_addr: - Get MAC address for stand alone SiS900 model
173 * @pci_dev: the sis900 pci device
174 * @net_dev: the net device to get address for
176 * Older SiS900 and friends, use EEPROM to store MAC address.
177 * MAC address is read from read_eeprom() into @net_dev->dev_addr.
180 static int sis900_get_mac_addr(struct pci_device
* pci_dev __unused
, struct nic
*nic
)
185 /* check to see if we have sane EEPROM */
186 signature
= (u16
) sis900_read_eeprom( EEPROMSignature
);
187 if (signature
== 0xffff || signature
== 0x0000) {
188 printf ("sis900_probe: Error EERPOM read %hX\n", signature
);
192 /* get MAC address from EEPROM */
193 for (i
= 0; i
< 3; i
++)
194 ((u16
*)(nic
->node_addr
))[i
] = sis900_read_eeprom(i
+EEPROMMACAddr
);
199 * sis96x_get_mac_addr: - Get MAC address for SiS962 or SiS963 model
200 * @pci_dev: the sis900 pci device
201 * @net_dev: the net device to get address for
203 * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
205 * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first
206 * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access
207 * by LAN, otherwise is not. After MAC address is read from EEPROM, send
208 * EEDONE signal to refuse EEPROM access by LAN.
209 * The EEPROM map of SiS962 or SiS963 is different to SiS900.
210 * The signature field in SiS962 or SiS963 spec is meaningless.
211 * MAC address is read into @net_dev->dev_addr.
214 static int sis96x_get_mac_addr(struct pci_device
* pci_dev __unused
, struct nic
*nic
)
216 /* long ioaddr = net_dev->base_addr; */
217 long ee_addr
= ioaddr
+ mear
;
221 printf("Alternate function\n");
223 outl(EEREQ
, ee_addr
);
224 while(waittime
< 2000) {
225 if(inl(ee_addr
) & EEGNT
) {
227 /* get MAC address from EEPROM */
228 for (i
= 0; i
< 3; i
++)
229 ((u16
*)(nic
->node_addr
))[i
] = sis900_read_eeprom(i
+EEPROMMACAddr
);
231 outl(EEDONE
, ee_addr
);
238 outl(EEDONE
, ee_addr
);
243 * sis630e_get_mac_addr: - Get MAC address for SiS630E model
244 * @pci_dev: the sis900 pci device
245 * @net_dev: the net device to get address for
247 * SiS630E model, use APC CMOS RAM to store MAC address.
248 * APC CMOS RAM is accessed through ISA bridge.
249 * MAC address is read into @net_dev->dev_addr.
252 static int sis630e_get_mac_addr(struct pci_device
* pci_dev __unused
, struct nic
*nic
)
257 struct bus_loc bus_loc
;
259 struct bus_dev bus_dev
;
260 struct pci_device isa_bridge
;
263 /* find PCI to ISA bridge */
264 memset(&bus_loc
, 0, sizeof(bus_loc
));
265 if ( ! find_by_driver ( &bus_loc
, &u
.bus_dev
, &sis_bridge_driver
, 0 ) )
268 pci_read_config_byte(&u
.isa_bridge
, 0x48, ®
);
269 pci_write_config_byte(&u
.isa_bridge
, 0x48, reg
| 0x40);
271 for (i
= 0; i
< ETH_ALEN
; i
++)
273 outb(0x09 + i
, 0x70);
274 ((u8
*)(nic
->node_addr
))[i
] = inb(0x71);
276 pci_write_config_byte(&u
.isa_bridge
, 0x48, reg
& ~0x40);
281 /* Does not work with current bus/device model */
282 memset ( nic
->node_addr
, 0, sizeof ( nic
->node_addr
) );
287 * sis630e_get_mac_addr: - Get MAC address for SiS630E model
288 * @pci_dev: the sis900 pci device
289 * @net_dev: the net device to get address for
291 * SiS630E model, use APC CMOS RAM to store MAC address.
292 * APC CMOS RAM is accessed through ISA bridge.
293 * MAC address is read into @net_dev->dev_addr.
296 static int sis635_get_mac_addr(struct pci_device
* pci_dev __unused
, struct nic
*nic
)
302 rfcrSave
= inl(rfcr
+ ioaddr
);
304 outl(rfcrSave
| RELOAD
, ioaddr
+ cr
);
305 outl(0, ioaddr
+ cr
);
307 /* disable packet filtering before setting filter */
308 outl(rfcrSave
& ~RFEN
, rfcr
+ ioaddr
);
310 /* load MAC addr to filter data register */
311 for (i
= 0 ; i
< 3 ; i
++) {
312 outl((i
<< RFADDR_shift
), ioaddr
+ rfcr
);
313 *( ((u16
*)nic
->node_addr
) + i
) = inw(ioaddr
+ rfdr
);
316 /* enable packet filitering */
317 outl(rfcrSave
| RFEN
, rfcr
+ ioaddr
);
323 * Function: sis900_probe
325 * Description: initializes initializes the NIC, retrieves the
326 * MAC address of the card, and sets up some globals required by
330 * leaves the ioaddress of the sis900 chip in the variable ioaddr.
331 * leaves the sis900 initialized, and ready to recieve packets.
333 * Returns: struct nic *: pointer to NIC data structure
336 static int sis900_probe ( struct nic
*nic
, struct pci_device
*pci
) {
344 if (pci
->ioaddr
== 0)
348 nic
->ioaddr
= pci
->ioaddr
;
350 ioaddr
= pci
->ioaddr
;
351 vendor
= pci
->vendor
;
352 dev_id
= pci
->device
;
355 pci_write_config_dword(pci
, 0x40, 0x00000000);
357 adjust_pci_device(pci
);
359 /* get MAC address */
361 pci_read_config_byte(pci
, PCI_REVISION
, &revision
);
363 /* save for use later in sis900_reset() */
364 pci_revision
= revision
;
366 if (revision
== SIS630E_900_REV
)
367 ret
= sis630e_get_mac_addr(pci
, nic
);
368 else if ((revision
> 0x81) && (revision
<= 0x90))
369 ret
= sis635_get_mac_addr(pci
, nic
);
370 else if (revision
== SIS96x_900_REV
)
371 ret
= sis96x_get_mac_addr(pci
, nic
);
373 ret
= sis900_get_mac_addr(pci
, nic
);
377 printf ("sis900_probe: Error MAC address not found\n");
381 /* 630ET : set the mii access mode as software-mode */
382 if (revision
== SIS630ET_900_REV
)
383 outl(ACCESSMODE
| inl(ioaddr
+ cr
), ioaddr
+ cr
);
385 DBG( "sis900_probe: Vendor:%#hX Device:%#hX\n", vendor
, dev_id
);
387 /* probe for mii transceiver */
388 /* search for total of 32 possible mii phy addresses */
391 for (phy_addr
= 0; phy_addr
< 32; phy_addr
++) {
393 u16 phy_id0
, phy_id1
;
395 mii_status
= sis900_mdio_read(phy_addr
, MII_STATUS
);
396 if (mii_status
== 0xffff || mii_status
== 0x0000)
397 /* the mii is not accessable, try next one */
400 phy_id0
= sis900_mdio_read(phy_addr
, MII_PHY_ID0
);
401 phy_id1
= sis900_mdio_read(phy_addr
, MII_PHY_ID1
);
403 /* search our mii table for the current mii */
404 for (i
= 0; mii_chip_table
[i
].phy_id1
; i
++) {
406 if ((phy_id0
== mii_chip_table
[i
].phy_id0
) &&
407 ((phy_id1
& 0xFFF0) == mii_chip_table
[i
].phy_id1
)){
409 printf("sis900_probe: %s transceiver found at address %d.\n",
410 mii_chip_table
[i
].name
, phy_addr
);
412 mii
.chip_info
= &mii_chip_table
[i
];
413 mii
.phy_addr
= phy_addr
;
414 mii
.status
= sis900_mdio_read(phy_addr
, MII_STATUS
);
424 printf("sis900_probe: No MII transceivers found!\n");
428 /* Arbitrarily select the last PHY found as current PHY */
429 cur_phy
= mii
.phy_addr
;
430 printf("sis900_probe: Using %s as default\n", mii
.chip_info
->name
);
432 /* initialize device */
434 nic
->nic_op
= &sis900_operations
;
443 * EEPROM Routines: These functions read and write to EEPROM for
444 * retrieving the MAC address and other configuration information about
448 /* Delay between EEPROM clock transitions. */
449 #define eeprom_delay() inl(ee_addr)
452 /* Function: sis900_read_eeprom
454 * Description: reads and returns a given location from EEPROM
456 * Arguments: int location: requested EEPROM location
458 * Returns: u16: contents of requested EEPROM location
462 /* Read Serial EEPROM through EEPROM Access Register, Note that location is
463 in word (16 bits) unit */
464 static u16
sis900_read_eeprom(int location
)
468 long ee_addr
= ioaddr
+ mear
;
469 u32 read_cmd
= location
| EEread
;
476 /* Shift the read command (9) bits out. */
477 for (i
= 8; i
>= 0; i
--) {
478 u32 dataval
= (read_cmd
& (1 << i
)) ? EEDI
| EECS
: EECS
;
479 outl(dataval
, ee_addr
);
481 outl(dataval
| EECLK
, ee_addr
);
487 /* read the 16-bits data in */
488 for (i
= 16; i
> 0; i
--) {
491 outl(EECS
| EECLK
, ee_addr
);
493 retval
= (retval
<< 1) | ((inl(ee_addr
) & EEDO
) ? 1 : 0);
497 /* Terminate the EEPROM access. */
500 // outl(EECLK, ee_addr);
505 #define sis900_mdio_delay() inl(mdio_addr)
509 Read and write the MII management registers using software-generated
510 serial MDIO protocol. Note that the command bits and data bits are
514 static void sis900_mdio_idle(long mdio_addr
)
516 outl(MDIO
| MDDIR
, mdio_addr
);
518 outl(MDIO
| MDDIR
| MDC
, mdio_addr
);
521 /* Syncronize the MII management interface by shifting 32 one bits out. */
522 static void sis900_mdio_reset(long mdio_addr
)
526 for (i
= 31; i
>= 0; i
--) {
527 outl(MDDIR
| MDIO
, mdio_addr
);
529 outl(MDDIR
| MDIO
| MDC
, mdio_addr
);
535 static u16
sis900_mdio_read(int phy_id
, int location
)
537 long mdio_addr
= ioaddr
+ mear
;
538 int mii_cmd
= MIIread
|(phy_id
<<MIIpmdShift
)|(location
<<MIIregShift
);
542 sis900_mdio_reset(mdio_addr
);
543 sis900_mdio_idle(mdio_addr
);
545 for (i
= 15; i
>= 0; i
--) {
546 int dataval
= (mii_cmd
& (1 << i
)) ? MDDIR
| MDIO
: MDDIR
;
547 outl(dataval
, mdio_addr
);
549 outl(dataval
| MDC
, mdio_addr
);
553 /* Read the 16 data bits. */
554 for (i
= 16; i
> 0; i
--) {
557 retval
= (retval
<< 1) | ((inl(mdio_addr
) & MDIO
) ? 1 : 0);
558 outl(MDC
, mdio_addr
);
561 outl(0x00, mdio_addr
);
566 static void sis900_mdio_write(int phy_id
, int location
, int value
)
568 long mdio_addr
= ioaddr
+ mear
;
569 int mii_cmd
= MIIwrite
|(phy_id
<<MIIpmdShift
)|(location
<<MIIregShift
);
572 sis900_mdio_reset(mdio_addr
);
573 sis900_mdio_idle(mdio_addr
);
575 /* Shift the command bits out. */
576 for (i
= 15; i
>= 0; i
--) {
577 int dataval
= (mii_cmd
& (1 << i
)) ? MDDIR
| MDIO
: MDDIR
;
578 outb(dataval
, mdio_addr
);
580 outb(dataval
| MDC
, mdio_addr
);
585 /* Shift the value bits out. */
586 for (i
= 15; i
>= 0; i
--) {
587 int dataval
= (value
& (1 << i
)) ? MDDIR
| MDIO
: MDDIR
;
588 outl(dataval
, mdio_addr
);
590 outl(dataval
| MDC
, mdio_addr
);
595 /* Clear out extra bits. */
596 for (i
= 2; i
> 0; i
--) {
599 outb(MDC
, mdio_addr
);
602 outl(0x00, mdio_addr
);
608 /* Function: sis900_init
610 * Description: resets the ethernet controller chip and various
611 * data structures required for sending and receiving packets.
613 * Arguments: struct nic *nic: NIC data structure
619 sis900_init(struct nic
*nic
)
621 /* Soft reset the chip. */
624 sis900_init_rxfilter(nic
);
626 sis900_init_txd(nic
);
627 sis900_init_rxd(nic
);
629 sis900_set_rx_mode(nic
);
631 sis900_check_mode(nic
);
633 outl(RxENA
| inl(ioaddr
+ cr
), ioaddr
+ cr
);
638 * Function: sis900_reset
640 * Description: disables interrupts and soft resets the controller chip
642 * Arguments: struct nic *nic: NIC data structure
648 sis900_reset(struct nic
*nic __unused
)
651 u32 status
= TxRCMP
| RxRCMP
;
653 outl(0, ioaddr
+ ier
);
654 outl(0, ioaddr
+ imr
);
655 outl(0, ioaddr
+ rfcr
);
657 outl(RxRESET
| TxRESET
| RESET
| inl(ioaddr
+ cr
), ioaddr
+ cr
);
659 /* Check that the chip has finished the reset. */
660 while (status
&& (i
++ < 1000)) {
661 status
^= (inl(isr
+ ioaddr
) & status
);
664 if( (pci_revision
>= SIS635A_900_REV
) || (pci_revision
== SIS900B_900_REV
) )
665 outl(PESEL
| RND_CNT
, ioaddr
+ cfg
);
667 outl(PESEL
, ioaddr
+ cfg
);
671 /* Function: sis_init_rxfilter
673 * Description: sets receive filter address to our MAC address
675 * Arguments: struct nic *nic: NIC data structure
681 sis900_init_rxfilter(struct nic
*nic
)
686 rfcrSave
= inl(rfcr
+ ioaddr
);
688 /* disable packet filtering before setting filter */
689 outl(rfcrSave
& ~RFEN
, rfcr
+ ioaddr
);
691 /* load MAC addr to filter data register */
692 for (i
= 0 ; i
< 3 ; i
++) {
695 w
= (u32
) *((u16
*)(nic
->node_addr
)+i
);
696 outl((i
<< RFADDR_shift
), ioaddr
+ rfcr
);
697 outl(w
, ioaddr
+ rfdr
);
699 if (sis900_debug
> 0)
700 printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
701 i
, inl(ioaddr
+ rfdr
));
704 /* enable packet filitering */
705 outl(rfcrSave
| RFEN
, rfcr
+ ioaddr
);
710 * Function: sis_init_txd
712 * Description: initializes the Tx descriptor
714 * Arguments: struct nic *nic: NIC data structure
720 sis900_init_txd(struct nic
*nic __unused
)
723 txd
.cmdsts
= (u32
) 0;
724 txd
.bufptr
= virt_to_bus(&txb
[0]);
726 /* load Transmit Descriptor Register */
727 outl(virt_to_bus(&txd
), ioaddr
+ txdp
);
728 if (sis900_debug
> 0)
729 printf("sis900_init_txd: TX descriptor register loaded with: %X\n",
734 /* Function: sis_init_rxd
736 * Description: initializes the Rx descriptor ring
738 * Arguments: struct nic *nic: NIC data structure
744 sis900_init_rxd(struct nic
*nic __unused
)
750 /* init RX descriptor */
751 for (i
= 0; i
< NUM_RX_DESC
; i
++) {
752 rxd
[i
].link
= virt_to_bus((i
+1 < NUM_RX_DESC
) ? &rxd
[i
+1] : &rxd
[0]);
753 rxd
[i
].cmdsts
= (u32
) RX_BUF_SIZE
;
754 rxd
[i
].bufptr
= virt_to_bus(&rxb
[i
*RX_BUF_SIZE
]);
755 if (sis900_debug
> 0)
756 printf("sis900_init_rxd: rxd[%d]=%p link=%X cmdsts=%X bufptr=%X\n",
757 i
, &rxd
[i
], (unsigned int) rxd
[i
].link
, (unsigned int) rxd
[i
].cmdsts
,
758 (unsigned int) rxd
[i
].bufptr
);
761 /* load Receive Descriptor Register */
762 outl(virt_to_bus(&rxd
[0]), ioaddr
+ rxdp
);
764 if (sis900_debug
> 0)
765 printf("sis900_init_rxd: RX descriptor register loaded with: %X\n",
771 /* Function: sis_init_rxd
774 * sets the receive mode to accept all broadcast packets and packets
775 * with our MAC address, and reject all multicast packets.
777 * Arguments: struct nic *nic: NIC data structure
782 static void sis900_set_rx_mode(struct nic
*nic __unused
)
784 int i
, table_entries
;
786 u16 mc_filter
[16] = {0}; /* 256/128 bits multicast hash table */
788 if((pci_revision
== SIS635A_900_REV
) || (pci_revision
== SIS900B_900_REV
))
793 /* accept all multicast packet */
794 rx_mode
= RFAAB
| RFAAM
;
795 for (i
= 0; i
< table_entries
; i
++)
796 mc_filter
[i
] = 0xffff;
798 /* update Multicast Hash Table in Receive Filter */
799 for (i
= 0; i
< table_entries
; i
++) {
800 /* why plus 0x04? That makes the correct value for hash table. */
801 outl((u32
)(0x00000004+i
) << RFADDR_shift
, ioaddr
+ rfcr
);
802 outl(mc_filter
[i
], ioaddr
+ rfdr
);
805 /* Accept Broadcast and multicast packets, destination addresses that match
807 outl(RFEN
| rx_mode
, ioaddr
+ rfcr
);
813 /* Function: sis900_check_mode
815 * Description: checks the state of transmit and receive
816 * parameters on the NIC, and updates NIC registers to match
818 * Arguments: struct nic *nic: NIC data structure
824 sis900_check_mode(struct nic
*nic
)
827 u32 tx_flags
= 0, rx_flags
= 0;
829 mii
.chip_info
->read_mode(nic
, cur_phy
, &speed
, &duplex
);
831 if( inl(ioaddr
+ cfg
) & EDB_MASTER_EN
) {
832 tx_flags
= TxATP
| (DMA_BURST_64
<< TxMXDMA_shift
) | (TX_FILL_THRESH
<< TxFILLT_shift
);
833 rx_flags
= DMA_BURST_64
<< RxMXDMA_shift
;
836 tx_flags
= TxATP
| (DMA_BURST_512
<< TxMXDMA_shift
) | (TX_FILL_THRESH
<< TxFILLT_shift
);
837 rx_flags
= DMA_BURST_512
<< RxMXDMA_shift
;
840 if (speed
== HW_SPEED_HOME
|| speed
== HW_SPEED_10_MBPS
) {
841 rx_flags
|= (RxDRNT_10
<< RxDRNT_shift
);
842 tx_flags
|= (TxDRNT_10
<< TxDRNT_shift
);
845 rx_flags
|= (RxDRNT_100
<< RxDRNT_shift
);
846 tx_flags
|= (TxDRNT_100
<< TxDRNT_shift
);
849 if (duplex
== FDX_CAPABLE_FULL_SELECTED
) {
850 tx_flags
|= (TxCSI
| TxHBI
);
854 outl (tx_flags
, ioaddr
+ txcfg
);
855 outl (rx_flags
, ioaddr
+ rxcfg
);
859 /* Function: sis900_read_mode
861 * Description: retrieves and displays speed and duplex
862 * parameters from the NIC
864 * Arguments: struct nic *nic: NIC data structure
870 sis900_read_mode(struct nic
*nic __unused
, int phy_addr
, int *speed
, int *duplex
)
874 u16 phy_id0
, phy_id1
;
876 /* STSOUT register is Latched on Transition, read operation updates it */
878 status
= sis900_mdio_read(phy_addr
, MII_STSOUT
);
881 *speed
= HW_SPEED_10_MBPS
;
882 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
884 if (status
& (MII_NWAY_TX
| MII_NWAY_TX_FDX
))
885 *speed
= HW_SPEED_100_MBPS
;
886 if (status
& ( MII_NWAY_TX_FDX
| MII_NWAY_T_FDX
))
887 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
889 /* Workaround for Realtek RTL8201 PHY issue */
890 phy_id0
= sis900_mdio_read(phy_addr
, MII_PHY_ID0
);
891 phy_id1
= sis900_mdio_read(phy_addr
, MII_PHY_ID1
);
892 if((phy_id0
== 0x0000) && ((phy_id1
& 0xFFF0) == 0x8200)){
893 if(sis900_mdio_read(phy_addr
, MII_CONTROL
) & MII_CNTL_FDX
)
894 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
895 if(sis900_mdio_read(phy_addr
, 0x0019) & 0x01)
896 *speed
= HW_SPEED_100_MBPS
;
899 if (status
& MII_STSOUT_LINK_FAIL
)
900 printf("sis900_read_mode: Media Link Off\n");
902 printf("sis900_read_mode: Media Link On %s %s-duplex \n",
903 *speed
== HW_SPEED_100_MBPS
?
904 "100mbps" : "10mbps",
905 *duplex
== FDX_CAPABLE_FULL_SELECTED
?
910 /* Function: amd79c901_read_mode
912 * Description: retrieves and displays speed and duplex
913 * parameters from the NIC
915 * Arguments: struct nic *nic: NIC data structure
921 amd79c901_read_mode(struct nic
*nic __unused
, int phy_addr
, int *speed
, int *duplex
)
926 for (i
= 0; i
< 2; i
++)
927 status
= sis900_mdio_read(phy_addr
, MII_STATUS
);
929 if (status
& MII_STAT_CAN_AUTO
) {
931 for (i
= 0; i
< 2; i
++)
932 status
= sis900_mdio_read(phy_addr
, MII_STATUS_SUMMARY
);
933 if (status
& MII_STSSUM_SPD
)
934 *speed
= HW_SPEED_100_MBPS
;
936 *speed
= HW_SPEED_10_MBPS
;
937 if (status
& MII_STSSUM_DPLX
)
938 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
940 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
942 if (status
& MII_STSSUM_LINK
)
943 printf("amd79c901_read_mode: Media Link On %s %s-duplex \n",
944 *speed
== HW_SPEED_100_MBPS
?
945 "100mbps" : "10mbps",
946 *duplex
== FDX_CAPABLE_FULL_SELECTED
?
949 printf("amd79c901_read_mode: Media Link Off\n");
953 *speed
= HW_SPEED_HOME
;
954 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
955 if (status
& MII_STAT_LINK
)
956 printf("amd79c901_read_mode:Media Link On 1mbps half-duplex \n");
958 printf("amd79c901_read_mode: Media Link Off\n");
964 * ics1893_read_mode: - read media mode for ICS1893 PHY
965 * @net_dev: the net device to read mode for
966 * @phy_addr: mii phy address
967 * @speed: the transmit speed to be determined
968 * @duplex: the duplex mode to be determined
970 * ICS1893 PHY use Quick Poll Detailed Status register
971 * to determine the speed and duplex mode for sis900
974 static void ics1893_read_mode(struct nic
*nic __unused
, int phy_addr
, int *speed
, int *duplex
)
979 /* MII_QPDSTS is Latched, read twice in succession will reflect the current state */
980 for (i
= 0; i
< 2; i
++)
981 status
= sis900_mdio_read(phy_addr
, MII_QPDSTS
);
983 if (status
& MII_STSICS_SPD
)
984 *speed
= HW_SPEED_100_MBPS
;
986 *speed
= HW_SPEED_10_MBPS
;
988 if (status
& MII_STSICS_DPLX
)
989 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
991 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
993 if (status
& MII_STSICS_LINKSTS
)
994 printf("ics1893_read_mode: Media Link On %s %s-duplex \n",
995 *speed
== HW_SPEED_100_MBPS
?
996 "100mbps" : "10mbps",
997 *duplex
== FDX_CAPABLE_FULL_SELECTED
?
1000 printf("ics1893_read_mode: Media Link Off\n");
1004 * rtl8201_read_mode: - read media mode for rtl8201 phy
1005 * @nic: the net device to read mode for
1006 * @phy_addr: mii phy address
1007 * @speed: the transmit speed to be determined
1008 * @duplex: the duplex mode to be determined
1010 * read MII_STATUS register from rtl8201 phy
1011 * to determine the speed and duplex mode for sis900
1014 static void rtl8201_read_mode(struct nic
*nic __unused
, int phy_addr
, int *speed
, int *duplex
)
1018 status
= sis900_mdio_read(phy_addr
, MII_STATUS
);
1020 if (status
& MII_STAT_CAN_TX_FDX
) {
1021 *speed
= HW_SPEED_100_MBPS
;
1022 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
1024 else if (status
& MII_STAT_CAN_TX
) {
1025 *speed
= HW_SPEED_100_MBPS
;
1026 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
1028 else if (status
& MII_STAT_CAN_T_FDX
) {
1029 *speed
= HW_SPEED_10_MBPS
;
1030 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
1032 else if (status
& MII_STAT_CAN_T
) {
1033 *speed
= HW_SPEED_10_MBPS
;
1034 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
1037 if (status
& MII_STAT_LINK
)
1038 printf("rtl8201_read_mode: Media Link On %s %s-duplex \n",
1039 *speed
== HW_SPEED_100_MBPS
?
1040 "100mbps" : "10mbps",
1041 *duplex
== FDX_CAPABLE_FULL_SELECTED
?
1044 printf("rtl8201_read_config_mode: Media Link Off\n");
1048 * vt6103_read_mode: - read media mode for vt6103 phy
1049 * @nic: the net device to read mode for
1050 * @phy_addr: mii phy address
1051 * @speed: the transmit speed to be determined
1052 * @duplex: the duplex mode to be determined
1054 * read MII_STATUS register from rtl8201 phy
1055 * to determine the speed and duplex mode for sis900
1058 static void vt6103_read_mode(struct nic
*nic __unused
, int phy_addr
, int *speed
, int *duplex
)
1062 status
= sis900_mdio_read(phy_addr
, MII_STATUS
);
1064 if (status
& MII_STAT_CAN_TX_FDX
) {
1065 *speed
= HW_SPEED_100_MBPS
;
1066 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
1068 else if (status
& MII_STAT_CAN_TX
) {
1069 *speed
= HW_SPEED_100_MBPS
;
1070 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
1072 else if (status
& MII_STAT_CAN_T_FDX
) {
1073 *speed
= HW_SPEED_10_MBPS
;
1074 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
1076 else if (status
& MII_STAT_CAN_T
) {
1077 *speed
= HW_SPEED_10_MBPS
;
1078 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
1081 if (status
& MII_STAT_LINK
)
1082 printf("vt6103_read_mode: Media Link On %s %s-duplex \n",
1083 *speed
== HW_SPEED_100_MBPS
?
1084 "100mbps" : "10mbps",
1085 *duplex
== FDX_CAPABLE_FULL_SELECTED
?
1088 printf("vt6103_read_config_mode: Media Link Off\n");
1091 /* Function: sis900_transmit
1093 * Description: transmits a packet and waits for completion or timeout.
1095 * Arguments: char d[6]: destination ethernet address.
1096 * unsigned short t: ethernet protocol type.
1097 * unsigned short s: size of the data-part of the packet.
1098 * char *p: the data for the packet.
1104 sis900_transmit(struct nic
*nic
,
1105 const char *d
, /* Destination */
1106 unsigned int t
, /* Type */
1107 unsigned int s
, /* size */
1108 const char *p
) /* Packet */
1111 volatile u32 tx_status
;
1113 /* Stop the transmitter */
1114 outl(TxDIS
| inl(ioaddr
+ cr
), ioaddr
+ cr
);
1116 /* load Transmit Descriptor Register */
1117 outl(virt_to_bus(&txd
), ioaddr
+ txdp
);
1118 if (sis900_debug
> 1)
1119 printf("sis900_transmit: TX descriptor register loaded with: %X\n",
1120 inl(ioaddr
+ txdp
));
1122 memcpy(txb
, d
, ETH_ALEN
);
1123 memcpy(txb
+ ETH_ALEN
, nic
->node_addr
, ETH_ALEN
);
1125 memcpy(txb
+ 2 * ETH_ALEN
, (char*)&nstype
, 2);
1126 memcpy(txb
+ ETH_HLEN
, p
, s
);
1131 if (sis900_debug
> 1)
1132 printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s
, t
);
1134 /* pad to minimum packet size */
1135 while (s
< ETH_ZLEN
)
1138 /* set the transmit buffer descriptor and enable Transmit State Machine */
1139 txd
.bufptr
= virt_to_bus(&txb
[0]);
1140 txd
.cmdsts
= (u32
) OWN
| s
;
1142 /* restart the transmitter */
1143 outl(TxENA
| inl(ioaddr
+ cr
), ioaddr
+ cr
);
1145 if (sis900_debug
> 1)
1146 printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s
);
1148 to
= currticks() + TX_TIMEOUT
;
1150 while (((tx_status
=txd
.cmdsts
) & OWN
) && (currticks() < to
))
1153 if (currticks() >= to
) {
1154 printf("sis900_transmit: TX Timeout! Tx status %X.\n",
1155 (unsigned int) tx_status
);
1158 if (tx_status
& (ABORT
| UNDERRUN
| OWCOLL
)) {
1159 /* packet unsuccessfully transmited */
1160 printf("sis900_transmit: Transmit error, Tx status %X.\n",
1161 (unsigned int) tx_status
);
1163 /* Disable interrupts by clearing the interrupt mask. */
1164 outl(0, ioaddr
+ imr
);
1168 /* Function: sis900_poll
1170 * Description: checks for a received packet and returns it if found.
1172 * Arguments: struct nic *nic: NIC data structure
1174 * Returns: 1 if a packet was recieved.
1175 * 0 if no pacet was recieved.
1178 * Returns (copies) the packet to the array nic->packet.
1179 * Returns the length of the packet in nic->packetlen.
1183 sis900_poll(struct nic
*nic
, int retrieve
)
1185 u32 rx_status
= rxd
[cur_rx
].cmdsts
;
1189 /* acknowledge interrupts by reading interrupt status register */
1190 intr_status
= inl(ioaddr
+ isr
);
1192 if (sis900_debug
> 2)
1193 printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx
,
1194 (unsigned int) rx_status
);
1196 if (!(rx_status
& OWN
))
1199 if (sis900_debug
> 1)
1200 printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
1201 cur_rx
, (unsigned int) rx_status
);
1203 if ( ! retrieve
) return 1;
1205 nic
->packetlen
= (rx_status
& DSIZE
) - CRC_SIZE
;
1207 if (rx_status
& (ABORT
|OVERRUN
|TOOLONG
|RUNT
|RXISERR
|CRCERR
|FAERR
)) {
1208 /* corrupted packet received */
1209 printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
1210 (unsigned int) rx_status
);
1213 /* give packet to higher level routine */
1214 memcpy(nic
->packet
, (rxb
+ cur_rx
*RX_BUF_SIZE
), nic
->packetlen
);
1218 /* return the descriptor and buffer to receive ring */
1219 rxd
[cur_rx
].cmdsts
= RX_BUF_SIZE
;
1220 rxd
[cur_rx
].bufptr
= virt_to_bus(&rxb
[cur_rx
*RX_BUF_SIZE
]);
1222 if (++cur_rx
== NUM_RX_DESC
)
1225 /* re-enable the potentially idle receive state machine */
1226 outl(RxENA
| inl(ioaddr
+ cr
), ioaddr
+ cr
);
1233 /* Function: sis900_disable
1235 * Description: Turns off interrupts and stops Tx and Rx engines
1237 * Arguments: struct nic *nic: NIC data structure
1243 sis900_disable ( struct nic
*nic
) {
1247 /* Disable interrupts by clearing the interrupt mask. */
1248 outl(0, ioaddr
+ imr
);
1249 outl(0, ioaddr
+ ier
);
1251 /* Stop the chip's Tx and Rx Status Machine */
1252 outl(RxDIS
| TxDIS
| inl(ioaddr
+ cr
), ioaddr
+ cr
);
1256 /* Function: sis900_irq
1258 * Description: Enable, Disable, or Force, interrupts
1260 * Arguments: struct nic *nic: NIC data structure
1261 * irq_action_t action: Requested action
1267 sis900_irq(struct nic
*nic __unused
, irq_action_t action __unused
)
1271 outl(0, ioaddr
+ imr
);
1274 outl((RxSOVR
|RxORN
|RxERR
|RxOK
|TxURN
|TxERR
|TxIDLE
), ioaddr
+ imr
);
1281 static struct nic_operations sis900_operations
= {
1282 .connect
= dummy_connect
,
1283 .poll
= sis900_poll
,
1284 .transmit
= sis900_transmit
,
1288 static struct pci_device_id sis900_nics
[] = {
1289 PCI_ROM(0x1039, 0x0900, "sis900", "SIS900", 0),
1290 PCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016", 0),
1293 PCI_DRIVER ( sis900_driver
, sis900_nics
, PCI_NO_CLASS
);
1295 DRIVER ( "SIS900", nic_driver
, pci_driver
, sis900_driver
,
1296 sis900_probe
, sis900_disable
);