revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-pc / boot / grub / netboot / sis900.c
blob6208a26a44c8dcd92af0ba9306a0acdcef47cc76
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@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.
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 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
39 /* Includes */
41 #include "etherboot.h"
42 #include "nic.h"
43 #include "pci.h"
44 #include "cards.h"
46 #include "sis900.h"
48 /* Globals */
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)
65 #else
66 static unsigned char txb[TX_BUF_SIZE];
67 static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
68 #endif
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. */
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 {
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}
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;
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}
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)
154 u16 signature;
155 int i;
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;
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;
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)
182 u8 reg;
183 int i;
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, &reg);
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);
202 return 1;
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
210 * other routines.
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.
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)
221 int i;
222 int found=0;
223 int phy_addr;
224 u16 signature;
225 u8 revision;
226 int ret;
228 if (io_addrs == 0 || *io_addrs == 0)
229 return NULL;
231 ioaddr = *io_addrs & ~3;
232 vendor = pci->vendor;
233 dev_id = pci->dev_id;
235 /* wakeup chip */
236 pcibios_write_config_dword(pci->bus, pci->devfn, 0x40, 0x00000000);
238 adjust_pci_device(pci);
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);
250 if (ret == 0)
252 printf ("sis900_probe: Error MAC address not found\n");
253 return NULL;
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 */
263 found = 0;
264 for (phy_addr = 0; phy_addr < 32; phy_addr++) {
265 u16 mii_status;
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 */
271 continue;
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);
287 mii.next = NULL;
289 found=1;
290 break;
295 if (found == 0) {
296 printf("sis900_probe: No MII transceivers found!\n");
297 return NULL;
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 */
305 sis900_init(nic);
307 nic->reset = sis900_init;
308 nic->poll = sis900_poll;
309 nic->transmit = sis900_transmit;
310 nic->disable = sis900_disable;
312 return nic;
317 * EEPROM Routines: These functions read and write to EEPROM for
318 * retrieving the MAC address and other configuration information about
319 * the card.
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)
340 int i;
341 u16 retval = 0;
342 long ee_addr = ioaddr + mear;
343 u32 read_cmd = location | EEread;
345 outl(0, ee_addr);
346 eeprom_delay();
347 outl(EECLK, ee_addr);
348 eeprom_delay();
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();
358 outb(EECS, ee_addr);
359 eeprom_delay();
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();
371 /* Terminate the EEPROM access. */
372 outl(0, ee_addr);
373 eeprom_delay();
374 outl(EECLK, ee_addr);
376 return (retval);
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
385 send out seperately
388 static void sis900_mdio_idle(long mdio_addr)
390 outl(MDIO | MDDIR, mdio_addr);
391 sis900_mdio_delay();
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)
398 int i;
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();
406 return;
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);
413 u16 retval = 0;
414 int i;
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);
422 sis900_mdio_delay();
423 outl(dataval | MDC, mdio_addr);
424 sis900_mdio_delay();
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();
435 return retval;
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);
442 int i;
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);
451 sis900_mdio_delay();
452 outb(dataval | MDC, mdio_addr);
453 sis900_mdio_delay();
455 sis900_mdio_delay();
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();
465 sis900_mdio_delay();
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();
474 return;
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
485 * returns: void.
488 static void
489 sis900_init(struct nic *nic)
491 /* Soft reset the chip. */
492 sis900_reset(nic);
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
514 * Returns: void.
517 static void
518 sis900_reset(struct nic *nic)
520 int i = 0;
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
543 * returns: void.
546 static void
547 sis900_init_rxfilter(struct nic *nic)
549 u32 rfcrSave;
550 int i;
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++) {
559 u32 w;
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
582 * returns: void.
585 static void
586 sis900_init_txd(struct nic *nic)
588 txd.link = (u32) 0;
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",
596 inl(ioaddr + txdp));
600 /* Function: sis_init_rxd
602 * Description: initializes the Rx descriptor ring
604 * Arguments: struct nic *nic: NIC data structure
606 * Returns: void.
609 static void
610 sis900_init_rxd(struct nic *nic)
612 int i;
614 cur_rx = 0;
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",
631 inl(ioaddr + rxdp));
636 /* Function: sis_init_rxd
638 * Description:
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
644 * Returns: void.
647 static void sis900_set_rx_mode(struct nic *nic)
649 int i;
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
659 our MAC address */
660 outl(RFEN | RFAAB, ioaddr + rfcr);
662 return;
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
673 * Returns: void.
676 static void
677 sis900_check_mode (struct nic *nic)
679 int speed, duplex;
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);
691 else {
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);
698 rx_flags |= RxATX;
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
713 * Returns: void.
716 static void
717 sis900_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
719 int i = 0;
720 u32 status;
722 /* STSOUT register is Latched on Transition, read operation updates it */
723 while (i++ < 2)
724 status = sis900_mdio_read(phy_addr, MII_STSOUT);
726 if (status & MII_STSOUT_SPD)
727 *speed = HW_SPEED_100_MBPS;
728 else
729 *speed = HW_SPEED_10_MBPS;
731 if (status & MII_STSOUT_DPLX)
732 *duplex = FDX_CAPABLE_FULL_SELECTED;
733 else
734 *duplex = FDX_CAPABLE_HALF_SELECTED;
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");
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
754 * Returns: void.
757 static void
758 amd79c901_read_mode(struct nic *nic, int phy_addr, int *speed, int *duplex)
760 int i;
761 u16 status;
763 for (i = 0; i < 2; i++)
764 status = sis900_mdio_read(phy_addr, MII_STATUS);
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;
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");
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");
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)
813 int i = 0;
814 u32 status;
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;
822 else
823 *speed = HW_SPEED_10_MBPS;
825 if (status & MII_STSICS_DPLX)
826 *duplex = FDX_CAPABLE_FULL_SELECTED;
827 else
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 ?
835 "full" : "half");
836 else
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)
853 u32 status;
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 ?
879 "full" : "half");
880 else
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.
893 * Returns: void.
896 static void
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;
904 u32 tx_status;
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",
913 inl(ioaddr + txdp));
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);
921 s += ETH_HLEN;
922 s &= DSIZE;
924 if (sis900_debug > 1)
925 printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
927 /* pad to minimum packet size */
928 while (s < ETH_ZLEN)
929 txb[s++] = '\0';
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))
944 /* wait */ ;
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.
968 * Side effects:
969 * Returns (copies) the packet to the array nic->packet.
970 * Returns the length of the packet in nic->packetlen.
973 static int
974 sis900_poll(struct nic *nic)
976 u32 rx_status = rxd[cur_rx].cmdsts;
977 int retstat = 0;
979 if (sis900_debug > 2)
980 printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx, rx_status);
982 if (!(rx_status & OWN))
983 return retstat;
985 if (sis900_debug > 1)
986 printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
987 cur_rx, rx_status);
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",
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;
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)
1007 cur_rx = 0;
1009 /* re-enable the potentially idle receive state machine */
1010 outl(RxENA , ioaddr + cr);
1012 return retstat;
1016 /* Function: sis900_disable
1018 * Description: Turns off interrupts and stops Tx and Rx engines
1020 * Arguments: struct nic *nic: NIC data structure
1022 * Returns: void.
1025 static void
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);