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@thinguin.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 /* Revision History */
31 Initial Release. Tested with PCI based sis900 card and ThinkNIC
33 20 March 2001 P.Koegel
34 added support for sis630e and PHY ICS1893 and RTL8201
35 Testet with SIS730S chipset + ICS1893
41 #include "etherboot.h"
50 static int sis900_debug
= 0;
52 static unsigned short vendor
, dev_id
;
53 static unsigned long ioaddr
;
55 static unsigned int cur_phy
;
57 static unsigned int cur_rx
;
59 static BufferDesc txd
;
60 static BufferDesc rxd
[NUM_RX_DESC
];
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)
66 static unsigned char txb
[TX_BUF_SIZE
];
67 static unsigned char rxb
[NUM_RX_DESC
* RX_BUF_SIZE
];
70 static struct mac_chip_info
{
72 u16 vendor_id
, device_id
, flags
;
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. */
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
);
87 static struct mii_chip_info
{
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
},
102 static struct mii_phy
{
103 struct mii_phy
* next
;
104 struct mii_chip_info
* chip_info
;
110 // PCI to ISA bridge for SIS640E access
111 static struct pci_device pci_isa_bridge_list
[] = {
113 "SIS 85C503/5513 PCI to ISA bridge", 0, 0, 0, 0},
114 {0, 0, NULL
, 0, 0, 0, 0}
117 /* Function Prototypes */
119 struct nic
*sis900_probe(struct nic
*nic
, unsigned short *io_addrs
, struct pci_device
*pci
);
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
);
127 static void sis900_init(struct nic
*nic
);
129 static void sis900_reset(struct nic
*nic
);
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
);
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
);
141 static void sis900_disable(struct nic
*nic
);
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
148 * Older SiS900 and friends, use EEPROM to store MAC address.
149 * MAC address is read from read_eeprom() into @net_dev->dev_addr.
152 static int sis900_get_mac_addr(struct pci_device
* pci_dev
, struct nic
*nic
)
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
);
164 /* get MAC address from EEPROM */
165 for (i
= 0; i
< 3; i
++)
166 ((u16
*)(nic
->node_addr
))[i
] = sis900_read_eeprom(i
+EEPROMMACAddr
);
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
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.
180 static int sis630e_get_mac_addr(struct pci_device
* pci_dev
, struct nic
*nic
)
184 struct pci_device
*p
;
186 // find PCI to ISA bridge
187 eth_pci_init(pci_isa_bridge_list
);
189 /* the firts entry in this list should contain bus/devfn */
190 p
= pci_isa_bridge_list
;
192 pcibios_read_config_byte(p
->bus
,p
->devfn
, 0x48, ®
);
193 pcibios_write_config_byte(p
->bus
,p
->devfn
, 0x48, reg
| 0x40);
195 for (i
= 0; i
< ETH_ALEN
; i
++)
197 outb(0x09 + i
, 0x70);
198 ((u8
*)(nic
->node_addr
))[i
] = inb(0x71);
200 pcibios_write_config_byte(p
->bus
,p
->devfn
, 0x48, reg
& ~0x40);
206 * Function: sis900_probe
208 * Description: initializes initializes the NIC, retrieves the
209 * MAC address of the card, and sets up some globals required by
213 * leaves the ioaddress of the sis900 chip in the variable ioaddr.
214 * leaves the sis900 initialized, and ready to recieve packets.
216 * Returns: struct nic *: pointer to NIC data structure
219 struct nic
*sis900_probe(struct nic
*nic
, unsigned short *io_addrs
, struct pci_device
*pci
)
228 if (io_addrs
== 0 || *io_addrs
== 0)
231 ioaddr
= *io_addrs
& ~3;
232 vendor
= pci
->vendor
;
233 dev_id
= pci
->dev_id
;
236 pcibios_write_config_dword(pci
->bus
, pci
->devfn
, 0x40, 0x00000000);
238 adjust_pci_device(pci
);
240 /* get MAC address */
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
);
248 ret
= sis900_get_mac_addr(pci
, nic
);
252 printf ("sis900_probe: Error MAC address not found\n");
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
);
260 /* probe for mii transceiver */
261 /* search for total of 32 possible mii phy addresses */
264 for (phy_addr
= 0; phy_addr
< 32; phy_addr
++) {
266 u16 phy_id0
, phy_id1
;
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 */
273 phy_id0
= sis900_mdio_read(phy_addr
, MII_PHY_ID0
);
274 phy_id1
= sis900_mdio_read(phy_addr
, MII_PHY_ID1
);
276 /* search our mii table for the current mii */
277 for (i
= 0; mii_chip_table
[i
].phy_id1
; i
++) {
279 if (phy_id0
== mii_chip_table
[i
].phy_id0
) {
281 printf("sis900_probe: %s transceiver found at address %d.\n",
282 mii_chip_table
[i
].name
, phy_addr
);
284 mii
.chip_info
= &mii_chip_table
[i
];
285 mii
.phy_addr
= phy_addr
;
286 mii
.status
= sis900_mdio_read(phy_addr
, MII_STATUS
);
296 printf("sis900_probe: No MII transceivers found!\n");
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
);
304 /* initialize device */
307 nic
->reset
= sis900_init
;
308 nic
->poll
= sis900_poll
;
309 nic
->transmit
= sis900_transmit
;
310 nic
->disable
= sis900_disable
;
317 * EEPROM Routines: These functions read and write to EEPROM for
318 * retrieving the MAC address and other configuration information about
322 /* Delay between EEPROM clock transitions. */
323 #define eeprom_delay() inl(ee_addr)
326 /* Function: sis900_read_eeprom
328 * Description: reads and returns a given location from EEPROM
330 * Arguments: int location: requested EEPROM location
332 * Returns: u16: contents of requested EEPROM location
336 /* Read Serial EEPROM through EEPROM Access Register, Note that location is
337 in word (16 bits) unit */
338 static u16
sis900_read_eeprom(int location
)
342 long ee_addr
= ioaddr
+ mear
;
343 u32 read_cmd
= location
| EEread
;
347 outl(EECLK
, ee_addr
);
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
);
355 outl(dataval
| EECLK
, ee_addr
);
361 /* read the 16-bits data in */
362 for (i
= 16; i
> 0; i
--) {
365 outl(EECS
| EECLK
, ee_addr
);
367 retval
= (retval
<< 1) | ((inl(ee_addr
) & EEDO
) ? 1 : 0);
371 /* Terminate the EEPROM access. */
374 outl(EECLK
, ee_addr
);
379 #define sis900_mdio_delay() inl(mdio_addr)
383 Read and write the MII management registers using software-generated
384 serial MDIO protocol. Note that the command bits and data bits are
388 static void sis900_mdio_idle(long mdio_addr
)
390 outl(MDIO
| MDDIR
, mdio_addr
);
392 outl(MDIO
| MDDIR
| MDC
, mdio_addr
);
395 /* Syncronize the MII management interface by shifting 32 one bits out. */
396 static void sis900_mdio_reset(long mdio_addr
)
400 for (i
= 31; i
>= 0; i
--) {
401 outl(MDDIR
| MDIO
, mdio_addr
);
403 outl(MDDIR
| MDIO
| MDC
, mdio_addr
);
409 static u16
sis900_mdio_read(int phy_id
, int location
)
411 long mdio_addr
= ioaddr
+ mear
;
412 int mii_cmd
= MIIread
|(phy_id
<<MIIpmdShift
)|(location
<<MIIregShift
);
416 sis900_mdio_reset(mdio_addr
);
417 sis900_mdio_idle(mdio_addr
);
419 for (i
= 15; i
>= 0; i
--) {
420 int dataval
= (mii_cmd
& (1 << i
)) ? MDDIR
| MDIO
: MDDIR
;
421 outl(dataval
, mdio_addr
);
423 outl(dataval
| MDC
, mdio_addr
);
427 /* Read the 16 data bits. */
428 for (i
= 16; i
> 0; i
--) {
431 retval
= (retval
<< 1) | ((inl(mdio_addr
) & MDIO
) ? 1 : 0);
432 outl(MDC
, mdio_addr
);
438 static void sis900_mdio_write(int phy_id
, int location
, int value
)
440 long mdio_addr
= ioaddr
+ mear
;
441 int mii_cmd
= MIIwrite
|(phy_id
<<MIIpmdShift
)|(location
<<MIIregShift
);
444 sis900_mdio_reset(mdio_addr
);
445 sis900_mdio_idle(mdio_addr
);
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
);
452 outb(dataval
| MDC
, mdio_addr
);
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
);
462 outl(dataval
| MDC
, mdio_addr
);
467 /* Clear out extra bits. */
468 for (i
= 2; i
> 0; i
--) {
471 outb(MDC
, mdio_addr
);
478 /* Function: sis900_init
480 * Description: resets the ethernet controller chip and various
481 * data structures required for sending and receiving packets.
483 * Arguments: struct nic *nic: NIC data structure
489 sis900_init(struct nic
*nic
)
491 /* Soft reset the chip. */
494 sis900_init_rxfilter(nic
);
496 sis900_init_txd(nic
);
497 sis900_init_rxd(nic
);
499 sis900_set_rx_mode(nic
);
501 sis900_check_mode(nic
);
503 outl(RxENA
, ioaddr
+ cr
);
508 * Function: sis900_reset
510 * Description: disables interrupts and soft resets the controller chip
512 * Arguments: struct nic *nic: NIC data structure
518 sis900_reset(struct nic
*nic
)
521 u32 status
= TxRCMP
| RxRCMP
;
523 outl(0, ioaddr
+ ier
);
524 outl(0, ioaddr
+ imr
);
525 outl(0, ioaddr
+ rfcr
);
527 outl(RxRESET
| TxRESET
| RESET
, ioaddr
+ cr
);
529 /* Check that the chip has finished the reset. */
530 while (status
&& (i
++ < 1000)) {
531 status
^= (inl(isr
+ ioaddr
) & status
);
533 outl(PESEL
, ioaddr
+ cfg
);
537 /* Function: sis_init_rxfilter
539 * Description: sets receive filter address to our MAC address
541 * Arguments: struct nic *nic: NIC data structure
547 sis900_init_rxfilter(struct nic
*nic
)
552 rfcrSave
= inl(rfcr
+ ioaddr
);
554 /* disable packet filtering before setting filter */
555 outl(rfcrSave
& ~RFEN
, rfcr
);
557 /* load MAC addr to filter data register */
558 for (i
= 0 ; i
< 3 ; i
++) {
561 w
= (u32
) *((u16
*)(nic
->node_addr
)+i
);
562 outl((i
<< RFADDR_shift
), ioaddr
+ rfcr
);
563 outl(w
, ioaddr
+ rfdr
);
565 if (sis900_debug
> 0)
566 printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
567 i
, inl(ioaddr
+ rfdr
));
570 /* enable packet filitering */
571 outl(rfcrSave
| RFEN
, rfcr
+ ioaddr
);
576 * Function: sis_init_txd
578 * Description: initializes the Tx descriptor
580 * Arguments: struct nic *nic: NIC data structure
586 sis900_init_txd(struct nic
*nic
)
589 txd
.cmdsts
= (u32
) 0;
590 txd
.bufptr
= (u32
) &txb
[0];
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",
600 /* Function: sis_init_rxd
602 * Description: initializes the Rx descriptor ring
604 * Arguments: struct nic *nic: NIC data structure
610 sis900_init_rxd(struct nic
*nic
)
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
);
626 /* load Receive Descriptor Register */
627 outl((u32
) &rxd
[0], ioaddr
+ rxdp
);
629 if (sis900_debug
> 0)
630 printf("sis900_init_rxd: RX descriptor register loaded with: %X\n",
636 /* Function: sis_init_rxd
639 * sets the receive mode to accept all broadcast packets and packets
640 * with our MAC address, and reject all multicast packets.
642 * Arguments: struct nic *nic: NIC data structure
647 static void sis900_set_rx_mode(struct nic
*nic
)
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
);
658 /* Accept Broadcast packets, destination addresses that match
660 outl(RFEN
| RFAAB
, ioaddr
+ rfcr
);
666 /* Function: sis900_check_mode
668 * Description: checks the state of transmit and receive
669 * parameters on the NIC, and updates NIC registers to match
671 * Arguments: struct nic *nic: NIC data structure
677 sis900_check_mode (struct nic
*nic
)
680 u32 tx_flags
= 0, rx_flags
= 0;
682 mii
.chip_info
->read_mode(nic
, cur_phy
, &speed
, &duplex
);
684 tx_flags
= TxATP
| (TX_DMA_BURST
<< TxMXDMA_shift
) | (TX_FILL_THRESH
<< TxFILLT_shift
);
685 rx_flags
= RX_DMA_BURST
<< RxMXDMA_shift
;
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
);
692 rx_flags
|= (RxDRNT_100
<< RxDRNT_shift
);
693 tx_flags
|= (TxDRNT_100
<< TxDRNT_shift
);
696 if (duplex
== FDX_CAPABLE_FULL_SELECTED
) {
697 tx_flags
|= (TxCSI
| TxHBI
);
701 outl (tx_flags
, ioaddr
+ txcfg
);
702 outl (rx_flags
, ioaddr
+ rxcfg
);
706 /* Function: sis900_read_mode
708 * Description: retrieves and displays speed and duplex
709 * parameters from the NIC
711 * Arguments: struct nic *nic: NIC data structure
717 sis900_read_mode(struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
)
722 /* STSOUT register is Latched on Transition, read operation updates it */
724 status
= sis900_mdio_read(phy_addr
, MII_STSOUT
);
726 if (status
& MII_STSOUT_SPD
)
727 *speed
= HW_SPEED_100_MBPS
;
729 *speed
= HW_SPEED_10_MBPS
;
731 if (status
& MII_STSOUT_DPLX
)
732 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
734 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
736 if (status
& MII_STSOUT_LINK_FAIL
)
737 printf("sis900_read_mode: Media Link Off\n");
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
?
747 /* Function: amd79c901_read_mode
749 * Description: retrieves and displays speed and duplex
750 * parameters from the NIC
752 * Arguments: struct nic *nic: NIC data structure
758 amd79c901_read_mode(struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
)
763 for (i
= 0; i
< 2; i
++)
764 status
= sis900_mdio_read(phy_addr
, MII_STATUS
);
766 if (status
& MII_STAT_CAN_AUTO
) {
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
;
773 *speed
= HW_SPEED_10_MBPS
;
774 if (status
& MII_STSSUM_DPLX
)
775 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
777 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
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
?
786 printf("amd79c901_read_mode: Media Link Off\n");
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");
795 printf("amd79c901_read_mode: Media Link Off\n");
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
807 * ICS1893 PHY use Quick Poll Detailed Status register
808 * to determine the speed and duplex mode for sis900
811 static void ics1893_read_mode(struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
)
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
);
820 if (status
& MII_STSICS_SPD
)
821 *speed
= HW_SPEED_100_MBPS
;
823 *speed
= HW_SPEED_10_MBPS
;
825 if (status
& MII_STSICS_DPLX
)
826 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
828 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
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
?
837 printf("ics1893_read_mode: Media Link Off\n");
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
847 * read MII_STATUS register from rtl8201 phy
848 * to determine the speed and duplex mode for sis900
851 static void rtl8201_read_mode(struct nic
*nic
, int phy_addr
, int *speed
, int *duplex
)
855 status
= sis900_mdio_read(phy_addr
, MII_STATUS
);
857 if (status
& MII_STAT_CAN_TX_FDX
) {
858 *speed
= HW_SPEED_100_MBPS
;
859 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
861 else if (status
& MII_STAT_CAN_TX
) {
862 *speed
= HW_SPEED_100_MBPS
;
863 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
865 else if (status
& MII_STAT_CAN_T_FDX
) {
866 *speed
= HW_SPEED_10_MBPS
;
867 *duplex
= FDX_CAPABLE_FULL_SELECTED
;
869 else if (status
& MII_STAT_CAN_T
) {
870 *speed
= HW_SPEED_10_MBPS
;
871 *duplex
= FDX_CAPABLE_HALF_SELECTED
;
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
?
881 printf("rtl9201_read_config_mode: Media Link Off\n");
884 /* Function: sis900_transmit
886 * Description: transmits a packet and waits for completion or timeout.
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.
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 */
903 u32 status
, to
, nstype
;
906 /* Stop the transmitter */
907 outl(TxDIS
, ioaddr
+ cr
);
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",
915 memcpy(txb
, d
, ETH_ALEN
);
916 memcpy(txb
+ ETH_ALEN
, nic
->node_addr
, ETH_ALEN
);
918 memcpy(txb
+ 2 * ETH_ALEN
, (char*)&nstype
, 2);
919 memcpy(txb
+ ETH_HLEN
, p
, s
);
924 if (sis900_debug
> 1)
925 printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s
, t
);
927 /* pad to minimum packet size */
931 /* set the transmit buffer descriptor and enable Transmit State Machine */
932 txd
.bufptr
= (u32
) &txb
[0];
933 txd
.cmdsts
= (u32
) OWN
| s
;
935 /* restart the transmitter */
936 outl(TxENA
, ioaddr
+ cr
);
938 if (sis900_debug
> 1)
939 printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s
);
941 to
= currticks() + TX_TIMEOUT
;
943 while ((((volatile u32
) tx_status
=txd
.cmdsts
) & OWN
) && (currticks() < to
))
946 if (currticks() >= to
) {
947 printf("sis900_transmit: TX Timeout! Tx status %X.\n", tx_status
);
950 if (tx_status
& (ABORT
| UNDERRUN
| OWCOLL
)) {
951 /* packet unsuccessfully transmited */
952 printf("sis900_transmit: Transmit error, Tx status %X.\n", tx_status
);
954 /* Disable interrupts by clearing the interrupt mask. */
955 outl(0, ioaddr
+ imr
);
959 /* Function: sis900_poll
961 * Description: checks for a received packet and returns it if found.
963 * Arguments: struct nic *nic: NIC data structure
965 * Returns: 1 if a packet was recieved.
966 * 0 if no pacet was recieved.
969 * Returns (copies) the packet to the array nic->packet.
970 * Returns the length of the packet in nic->packetlen.
974 sis900_poll(struct nic
*nic
)
976 u32 rx_status
= rxd
[cur_rx
].cmdsts
;
979 if (sis900_debug
> 2)
980 printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx
, rx_status
);
982 if (!(rx_status
& OWN
))
985 if (sis900_debug
> 1)
986 printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
989 nic
->packetlen
= (rx_status
& DSIZE
) - CRC_SIZE
;
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",
997 /* give packet to higher level routine */
998 memcpy(nic
->packet
, (rxb
+ cur_rx
*RX_BUF_SIZE
), nic
->packetlen
);
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
];
1006 if (++cur_rx
== NUM_RX_DESC
)
1009 /* re-enable the potentially idle receive state machine */
1010 outl(RxENA
, ioaddr
+ cr
);
1016 /* Function: sis900_disable
1018 * Description: Turns off interrupts and stops Tx and Rx engines
1020 * Arguments: struct nic *nic: NIC data structure
1026 sis900_disable(struct nic
*nic
)
1028 /* Disable interrupts by clearing the interrupt mask. */
1029 outl(0, ioaddr
+ imr
);
1030 outl(0, ioaddr
+ ier
);
1032 /* Stop the chip's Tx and Rx Status Machine */
1033 outl(RxDIS
| TxDIS
, ioaddr
+ cr
);