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