|
|
1.1 root 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 ([email protected])
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: FILE_LICENCE ( GPL_ANY );
28:
29: /* Revision History */
30:
31: /*
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
36: source 2.4.17.
37: 01 March 2001 mdc 1.0
38: Initial Release. Tested with PCI based sis900 card and ThinkNIC
39: computer.
40: 20 March 2001 P.Koegel
41: added support for sis630e and PHY ICS1893 and RTL8201
42: Testet with SIS730S chipset + ICS1893
43: */
44:
45:
46: /* Includes */
47:
48: #include "etherboot.h"
49: #include <ipxe/pci.h>
50: #include "nic.h"
51:
52: #include "sis900.h"
53:
54: /* Globals */
55:
56: static struct nic_operations sis900_operations;
57:
58: static int sis900_debug = 0;
59:
60: static unsigned short vendor, dev_id;
61: static unsigned long ioaddr;
62: static u8 pci_revision;
63:
64: static unsigned int cur_phy;
65:
66: static unsigned int cur_rx;
67:
68: struct {
69: BufferDesc txd;
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
78:
79: #if 0
80: static struct mac_chip_info {
81: const char *name;
82: u16 vendor_id, device_id, flags;
83: int io_size;
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. */
90: };
91: #endif
92:
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);
98:
99: static struct mii_chip_info {
100: const char * name;
101: u16 phy_id0;
102: u16 phy_id1;
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},
114: {0,0,0,0}
115: };
116:
117: static struct mii_phy {
118: struct mii_phy * next;
119: struct mii_chip_info * chip_info;
120: int phy_addr;
121: u16 status;
122: } mii;
123:
124:
125:
126: #if 0
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"},
131: };
132:
133: PCI_DRIVER( sis_bridge_pci_driver, pci_isa_bridge_list, PCI_NO_CLASS );
134:
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,
139: };
140: #endif
141:
142: /* Function Prototypes */
143:
144: static int sis900_probe(struct nic *nic,struct pci_device *pci);
145:
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);
150: #if 0
151: static void sis900_mdio_write(int phy_id, int location, int val);
152: #endif
153: static void sis900_init(struct nic *nic);
154:
155: static void sis900_reset(struct nic *nic);
156:
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);
162:
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);
166:
167: static void sis900_disable(struct nic *nic);
168:
169: static void sis900_irq(struct nic *nic, irq_action_t action);
170:
171: /**
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
175: *
176: * Older SiS900 and friends, use EEPROM to store MAC address.
177: * MAC address is read from read_eeprom() into @net_dev->dev_addr.
178: */
179:
180: static int sis900_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
181: {
182: u16 signature;
183: int i;
184:
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);
189: return 0;
190: }
191:
192: /* get MAC address from EEPROM */
193: for (i = 0; i < 3; i++)
194: ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
195: return 1;
196: }
197:
198: /**
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
202: *
203: * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
204: * is shared by
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.
212: */
213:
214: static int sis96x_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
215: {
216: /* long ioaddr = net_dev->base_addr; */
217: long ee_addr = ioaddr + mear;
218: u32 waittime = 0;
219: int i;
220:
221: printf("Alternate function\n");
222:
223: outl(EEREQ, ee_addr);
224: while(waittime < 2000) {
225: if(inl(ee_addr) & EEGNT) {
226:
227: /* get MAC address from EEPROM */
228: for (i = 0; i < 3; i++)
229: ((u16 *)(nic->node_addr))[i] = sis900_read_eeprom(i+EEPROMMACAddr);
230:
231: outl(EEDONE, ee_addr);
232: return 1;
233: } else {
234: udelay(1);
235: waittime ++;
236: }
237: }
238: outl(EEDONE, ee_addr);
239: return 0;
240: }
241:
242: /**
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
246: *
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.
250: */
251:
252: static int sis630e_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
253: {
254: #if 0
255: u8 reg;
256: int i;
257: struct bus_loc bus_loc;
258: union {
259: struct bus_dev bus_dev;
260: struct pci_device isa_bridge;
261: } u;
262:
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 ) )
266: return 0;
267:
268: pci_read_config_byte(&u.isa_bridge, 0x48, ®);
269: pci_write_config_byte(&u.isa_bridge, 0x48, reg | 0x40);
270:
271: for (i = 0; i < ETH_ALEN; i++)
272: {
273: outb(0x09 + i, 0x70);
274: ((u8 *)(nic->node_addr))[i] = inb(0x71);
275: }
276: pci_write_config_byte(&u.isa_bridge, 0x48, reg & ~0x40);
277:
278: return 1;
279: #endif
280:
281: /* Does not work with current bus/device model */
282: memset ( nic->node_addr, 0, sizeof ( nic->node_addr ) );
283: return 0;
284: }
285:
286: /**
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
290: *
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.
294: */
295:
296: static int sis635_get_mac_addr(struct pci_device * pci_dev __unused, struct nic *nic)
297: {
298: u32 rfcrSave;
299: u32 i;
300:
301:
302: rfcrSave = inl(rfcr + ioaddr);
303:
304: outl(rfcrSave | RELOAD, ioaddr + cr);
305: outl(0, ioaddr + cr);
306:
307: /* disable packet filtering before setting filter */
308: outl(rfcrSave & ~RFEN, rfcr + ioaddr);
309:
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);
314: }
315:
316: /* enable packet filitering */
317: outl(rfcrSave | RFEN, rfcr + ioaddr);
318:
319: return 1;
320: }
321:
322: /*
323: * Function: sis900_probe
324: *
325: * Description: initializes initializes the NIC, retrieves the
326: * MAC address of the card, and sets up some globals required by
327: * other routines.
328: *
329: * Side effects:
330: * leaves the ioaddress of the sis900 chip in the variable ioaddr.
331: * leaves the sis900 initialized, and ready to recieve packets.
332: *
333: * Returns: struct nic *: pointer to NIC data structure
334: */
335:
336: static int sis900_probe ( struct nic *nic, struct pci_device *pci ) {
337:
338: int i;
339: int found=0;
340: int phy_addr;
341: u8 revision;
342: int ret;
343:
344: if (pci->ioaddr == 0)
345: return 0;
346:
347: nic->irqno = 0;
348: nic->ioaddr = pci->ioaddr;
349:
350: ioaddr = pci->ioaddr;
351: vendor = pci->vendor;
352: dev_id = pci->device;
353:
354: /* wakeup chip */
355: pci_write_config_dword(pci, 0x40, 0x00000000);
356:
357: adjust_pci_device(pci);
358:
359: /* get MAC address */
360: ret = 0;
361: pci_read_config_byte(pci, PCI_REVISION, &revision);
362:
363: /* save for use later in sis900_reset() */
364: pci_revision = revision;
365:
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);
372: else
373: ret = sis900_get_mac_addr(pci, nic);
374:
375: if (ret == 0)
376: {
377: printf ("sis900_probe: Error MAC address not found\n");
378: return 0;
379: }
380:
381: /* 630ET : set the mii access mode as software-mode */
382: if (revision == SIS630ET_900_REV)
383: outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);
384:
385: DBG( "sis900_probe: Vendor:%#hX Device:%#hX\n", vendor, dev_id );
386:
387: /* probe for mii transceiver */
388: /* search for total of 32 possible mii phy addresses */
389:
390: found = 0;
391: for (phy_addr = 0; phy_addr < 32; phy_addr++) {
392: u16 mii_status;
393: u16 phy_id0, phy_id1;
394:
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 */
398: continue;
399:
400: phy_id0 = sis900_mdio_read(phy_addr, MII_PHY_ID0);
401: phy_id1 = sis900_mdio_read(phy_addr, MII_PHY_ID1);
402:
403: /* search our mii table for the current mii */
404: for (i = 0; mii_chip_table[i].phy_id1; i++) {
405:
406: if ((phy_id0 == mii_chip_table[i].phy_id0) &&
407: ((phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){
408:
409: printf("sis900_probe: %s transceiver found at address %d.\n",
410: mii_chip_table[i].name, phy_addr);
411:
412: mii.chip_info = &mii_chip_table[i];
413: mii.phy_addr = phy_addr;
414: mii.status = sis900_mdio_read(phy_addr, MII_STATUS);
415: mii.next = NULL;
416:
417: found=1;
418: break;
419: }
420: }
421: }
422:
423: if (found == 0) {
424: printf("sis900_probe: No MII transceivers found!\n");
425: return 0;
426: }
427:
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);
431:
432: /* initialize device */
433: sis900_init(nic);
434: nic->nic_op = &sis900_operations;
435:
436: return 1;
437: }
438:
439:
440:
441:
442: /*
443: * EEPROM Routines: These functions read and write to EEPROM for
444: * retrieving the MAC address and other configuration information about
445: * the card.
446: */
447:
448: /* Delay between EEPROM clock transitions. */
449: #define eeprom_delay() inl(ee_addr)
450:
451:
452: /* Function: sis900_read_eeprom
453: *
454: * Description: reads and returns a given location from EEPROM
455: *
456: * Arguments: int location: requested EEPROM location
457: *
458: * Returns: u16: contents of requested EEPROM location
459: *
460: */
461:
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)
465: {
466: int i;
467: u16 retval = 0;
468: long ee_addr = ioaddr + mear;
469: u32 read_cmd = location | EEread;
470:
471: outl(0, ee_addr);
472: eeprom_delay();
473: outl(EECS, ee_addr);
474: eeprom_delay();
475:
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);
480: eeprom_delay();
481: outl(dataval | EECLK, ee_addr);
482: eeprom_delay();
483: }
484: outl(EECS, ee_addr);
485: eeprom_delay();
486:
487: /* read the 16-bits data in */
488: for (i = 16; i > 0; i--) {
489: outl(EECS, ee_addr);
490: eeprom_delay();
491: outl(EECS | EECLK, ee_addr);
492: eeprom_delay();
493: retval = (retval << 1) | ((inl(ee_addr) & EEDO) ? 1 : 0);
494: eeprom_delay();
495: }
496:
497: /* Terminate the EEPROM access. */
498: outl(0, ee_addr);
499: eeprom_delay();
500: // outl(EECLK, ee_addr);
501:
502: return (retval);
503: }
504:
505: #define sis900_mdio_delay() inl(mdio_addr)
506:
507:
508: /*
509: Read and write the MII management registers using software-generated
510: serial MDIO protocol. Note that the command bits and data bits are
511: send out seperately
512: */
513:
514: static void sis900_mdio_idle(long mdio_addr)
515: {
516: outl(MDIO | MDDIR, mdio_addr);
517: sis900_mdio_delay();
518: outl(MDIO | MDDIR | MDC, mdio_addr);
519: }
520:
521: /* Syncronize the MII management interface by shifting 32 one bits out. */
522: static void sis900_mdio_reset(long mdio_addr)
523: {
524: int i;
525:
526: for (i = 31; i >= 0; i--) {
527: outl(MDDIR | MDIO, mdio_addr);
528: sis900_mdio_delay();
529: outl(MDDIR | MDIO | MDC, mdio_addr);
530: sis900_mdio_delay();
531: }
532: return;
533: }
534:
535: static u16 sis900_mdio_read(int phy_id, int location)
536: {
537: long mdio_addr = ioaddr + mear;
538: int mii_cmd = MIIread|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
539: u16 retval = 0;
540: int i;
541:
542: sis900_mdio_reset(mdio_addr);
543: sis900_mdio_idle(mdio_addr);
544:
545: for (i = 15; i >= 0; i--) {
546: int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
547: outl(dataval, mdio_addr);
548: sis900_mdio_delay();
549: outl(dataval | MDC, mdio_addr);
550: sis900_mdio_delay();
551: }
552:
553: /* Read the 16 data bits. */
554: for (i = 16; i > 0; i--) {
555: outl(0, mdio_addr);
556: sis900_mdio_delay();
557: retval = (retval << 1) | ((inl(mdio_addr) & MDIO) ? 1 : 0);
558: outl(MDC, mdio_addr);
559: sis900_mdio_delay();
560: }
561: outl(0x00, mdio_addr);
562: return retval;
563: }
564:
565: #if 0
566: static void sis900_mdio_write(int phy_id, int location, int value)
567: {
568: long mdio_addr = ioaddr + mear;
569: int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
570: int i;
571:
572: sis900_mdio_reset(mdio_addr);
573: sis900_mdio_idle(mdio_addr);
574:
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);
579: sis900_mdio_delay();
580: outb(dataval | MDC, mdio_addr);
581: sis900_mdio_delay();
582: }
583: sis900_mdio_delay();
584:
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);
589: sis900_mdio_delay();
590: outl(dataval | MDC, mdio_addr);
591: sis900_mdio_delay();
592: }
593: sis900_mdio_delay();
594:
595: /* Clear out extra bits. */
596: for (i = 2; i > 0; i--) {
597: outb(0, mdio_addr);
598: sis900_mdio_delay();
599: outb(MDC, mdio_addr);
600: sis900_mdio_delay();
601: }
602: outl(0x00, mdio_addr);
603: return;
604: }
605: #endif
606:
607:
608: /* Function: sis900_init
609: *
610: * Description: resets the ethernet controller chip and various
611: * data structures required for sending and receiving packets.
612: *
613: * Arguments: struct nic *nic: NIC data structure
614: *
615: * returns: void.
616: */
617:
618: static void
619: sis900_init(struct nic *nic)
620: {
621: /* Soft reset the chip. */
622: sis900_reset(nic);
623:
624: sis900_init_rxfilter(nic);
625:
626: sis900_init_txd(nic);
627: sis900_init_rxd(nic);
628:
629: sis900_set_rx_mode(nic);
630:
631: sis900_check_mode(nic);
632:
633: outl(RxENA| inl(ioaddr + cr), ioaddr + cr);
634: }
635:
636:
637: /*
638: * Function: sis900_reset
639: *
640: * Description: disables interrupts and soft resets the controller chip
641: *
642: * Arguments: struct nic *nic: NIC data structure
643: *
644: * Returns: void.
645: */
646:
647: static void
648: sis900_reset(struct nic *nic __unused)
649: {
650: int i = 0;
651: u32 status = TxRCMP | RxRCMP;
652:
653: outl(0, ioaddr + ier);
654: outl(0, ioaddr + imr);
655: outl(0, ioaddr + rfcr);
656:
657: outl(RxRESET | TxRESET | RESET | inl(ioaddr + cr), ioaddr + cr);
658:
659: /* Check that the chip has finished the reset. */
660: while (status && (i++ < 1000)) {
661: status ^= (inl(isr + ioaddr) & status);
662: }
663:
664: if( (pci_revision >= SIS635A_900_REV) || (pci_revision == SIS900B_900_REV) )
665: outl(PESEL | RND_CNT, ioaddr + cfg);
666: else
667: outl(PESEL, ioaddr + cfg);
668: }
669:
670:
671: /* Function: sis_init_rxfilter
672: *
673: * Description: sets receive filter address to our MAC address
674: *
675: * Arguments: struct nic *nic: NIC data structure
676: *
677: * returns: void.
678: */
679:
680: static void
681: sis900_init_rxfilter(struct nic *nic)
682: {
683: u32 rfcrSave;
684: int i;
685:
686: rfcrSave = inl(rfcr + ioaddr);
687:
688: /* disable packet filtering before setting filter */
689: outl(rfcrSave & ~RFEN, rfcr + ioaddr);
690:
691: /* load MAC addr to filter data register */
692: for (i = 0 ; i < 3 ; i++) {
693: u32 w;
694:
695: w = (u32) *((u16 *)(nic->node_addr)+i);
696: outl((i << RFADDR_shift), ioaddr + rfcr);
697: outl(w, ioaddr + rfdr);
698:
699: if (sis900_debug > 0)
700: printf("sis900_init_rxfilter: Receive Filter Addrss[%d]=%X\n",
701: i, inl(ioaddr + rfdr));
702: }
703:
704: /* enable packet filitering */
705: outl(rfcrSave | RFEN, rfcr + ioaddr);
706: }
707:
708:
709: /*
710: * Function: sis_init_txd
711: *
712: * Description: initializes the Tx descriptor
713: *
714: * Arguments: struct nic *nic: NIC data structure
715: *
716: * returns: void.
717: */
718:
719: static void
720: sis900_init_txd(struct nic *nic __unused)
721: {
722: txd.link = (u32) 0;
723: txd.cmdsts = (u32) 0;
724: txd.bufptr = virt_to_bus(&txb[0]);
725:
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",
730: inl(ioaddr + txdp));
731: }
732:
733:
734: /* Function: sis_init_rxd
735: *
736: * Description: initializes the Rx descriptor ring
737: *
738: * Arguments: struct nic *nic: NIC data structure
739: *
740: * Returns: void.
741: */
742:
743: static void
744: sis900_init_rxd(struct nic *nic __unused)
745: {
746: int i;
747:
748: cur_rx = 0;
749:
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);
759: }
760:
761: /* load Receive Descriptor Register */
762: outl(virt_to_bus(&rxd[0]), ioaddr + rxdp);
763:
764: if (sis900_debug > 0)
765: printf("sis900_init_rxd: RX descriptor register loaded with: %X\n",
766: inl(ioaddr + rxdp));
767:
768: }
769:
770:
771: /* Function: sis_init_rxd
772: *
773: * Description:
774: * sets the receive mode to accept all broadcast packets and packets
775: * with our MAC address, and reject all multicast packets.
776: *
777: * Arguments: struct nic *nic: NIC data structure
778: *
779: * Returns: void.
780: */
781:
782: static void sis900_set_rx_mode(struct nic *nic __unused)
783: {
784: int i, table_entries;
785: u32 rx_mode;
786: u16 mc_filter[16] = {0}; /* 256/128 bits multicast hash table */
787:
788: if((pci_revision == SIS635A_900_REV) || (pci_revision == SIS900B_900_REV))
789: table_entries = 16;
790: else
791: table_entries = 8;
792:
793: /* accept all multicast packet */
794: rx_mode = RFAAB | RFAAM;
795: for (i = 0; i < table_entries; i++)
796: mc_filter[i] = 0xffff;
797:
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);
803: }
804:
805: /* Accept Broadcast and multicast packets, destination addresses that match
806: our MAC address */
807: outl(RFEN | rx_mode, ioaddr + rfcr);
808:
809: return;
810: }
811:
812:
813: /* Function: sis900_check_mode
814: *
815: * Description: checks the state of transmit and receive
816: * parameters on the NIC, and updates NIC registers to match
817: *
818: * Arguments: struct nic *nic: NIC data structure
819: *
820: * Returns: void.
821: */
822:
823: static void
824: sis900_check_mode(struct nic *nic)
825: {
826: int speed, duplex;
827: u32 tx_flags = 0, rx_flags = 0;
828:
829: mii.chip_info->read_mode(nic, cur_phy, &speed, &duplex);
830:
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;
834: }
835: else {
836: tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift);
837: rx_flags = DMA_BURST_512 << RxMXDMA_shift;
838: }
839:
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);
843: }
844: else {
845: rx_flags |= (RxDRNT_100 << RxDRNT_shift);
846: tx_flags |= (TxDRNT_100 << TxDRNT_shift);
847: }
848:
849: if (duplex == FDX_CAPABLE_FULL_SELECTED) {
850: tx_flags |= (TxCSI | TxHBI);
851: rx_flags |= RxATX;
852: }
853:
854: outl (tx_flags, ioaddr + txcfg);
855: outl (rx_flags, ioaddr + rxcfg);
856: }
857:
858:
859: /* Function: sis900_read_mode
860: *
861: * Description: retrieves and displays speed and duplex
862: * parameters from the NIC
863: *
864: * Arguments: struct nic *nic: NIC data structure
865: *
866: * Returns: void.
867: */
868:
869: static void
870: sis900_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
871: {
872: int i = 0;
873: u32 status;
874: u16 phy_id0, phy_id1;
875:
876: /* STSOUT register is Latched on Transition, read operation updates it */
877: do {
878: status = sis900_mdio_read(phy_addr, MII_STSOUT);
879: } while (i++ < 2);
880:
881: *speed = HW_SPEED_10_MBPS;
882: *duplex = FDX_CAPABLE_HALF_SELECTED;
883:
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;
888:
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;
897: }
898:
899: if (status & MII_STSOUT_LINK_FAIL)
900: printf("sis900_read_mode: Media Link Off\n");
901: else
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 ?
906: "full" : "half");
907: }
908:
909:
910: /* Function: amd79c901_read_mode
911: *
912: * Description: retrieves and displays speed and duplex
913: * parameters from the NIC
914: *
915: * Arguments: struct nic *nic: NIC data structure
916: *
917: * Returns: void.
918: */
919:
920: static void
921: amd79c901_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
922: {
923: int i;
924: u16 status;
925:
926: for (i = 0; i < 2; i++)
927: status = sis900_mdio_read(phy_addr, MII_STATUS);
928:
929: if (status & MII_STAT_CAN_AUTO) {
930: /* 10BASE-T PHY */
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;
935: else
936: *speed = HW_SPEED_10_MBPS;
937: if (status & MII_STSSUM_DPLX)
938: *duplex = FDX_CAPABLE_FULL_SELECTED;
939: else
940: *duplex = FDX_CAPABLE_HALF_SELECTED;
941:
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 ?
947: "full" : "half");
948: else
949: printf("amd79c901_read_mode: Media Link Off\n");
950: }
951: else {
952: /* HomePNA */
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");
957: else
958: printf("amd79c901_read_mode: Media Link Off\n");
959: }
960: }
961:
962:
963: /**
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
969: *
970: * ICS1893 PHY use Quick Poll Detailed Status register
971: * to determine the speed and duplex mode for sis900
972: */
973:
974: static void ics1893_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
975: {
976: int i = 0;
977: u32 status;
978:
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);
982:
983: if (status & MII_STSICS_SPD)
984: *speed = HW_SPEED_100_MBPS;
985: else
986: *speed = HW_SPEED_10_MBPS;
987:
988: if (status & MII_STSICS_DPLX)
989: *duplex = FDX_CAPABLE_FULL_SELECTED;
990: else
991: *duplex = FDX_CAPABLE_HALF_SELECTED;
992:
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 ?
998: "full" : "half");
999: else
1000: printf("ics1893_read_mode: Media Link Off\n");
1001: }
1002:
1003: /**
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
1009: *
1010: * read MII_STATUS register from rtl8201 phy
1011: * to determine the speed and duplex mode for sis900
1012: */
1013:
1014: static void rtl8201_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
1015: {
1016: u32 status;
1017:
1018: status = sis900_mdio_read(phy_addr, MII_STATUS);
1019:
1020: if (status & MII_STAT_CAN_TX_FDX) {
1021: *speed = HW_SPEED_100_MBPS;
1022: *duplex = FDX_CAPABLE_FULL_SELECTED;
1023: }
1024: else if (status & MII_STAT_CAN_TX) {
1025: *speed = HW_SPEED_100_MBPS;
1026: *duplex = FDX_CAPABLE_HALF_SELECTED;
1027: }
1028: else if (status & MII_STAT_CAN_T_FDX) {
1029: *speed = HW_SPEED_10_MBPS;
1030: *duplex = FDX_CAPABLE_FULL_SELECTED;
1031: }
1032: else if (status & MII_STAT_CAN_T) {
1033: *speed = HW_SPEED_10_MBPS;
1034: *duplex = FDX_CAPABLE_HALF_SELECTED;
1035: }
1036:
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 ?
1042: "full" : "half");
1043: else
1044: printf("rtl8201_read_config_mode: Media Link Off\n");
1045: }
1046:
1047: /**
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
1053: *
1054: * read MII_STATUS register from rtl8201 phy
1055: * to determine the speed and duplex mode for sis900
1056: */
1057:
1058: static void vt6103_read_mode(struct nic *nic __unused, int phy_addr, int *speed, int *duplex)
1059: {
1060: u32 status;
1061:
1062: status = sis900_mdio_read(phy_addr, MII_STATUS);
1063:
1064: if (status & MII_STAT_CAN_TX_FDX) {
1065: *speed = HW_SPEED_100_MBPS;
1066: *duplex = FDX_CAPABLE_FULL_SELECTED;
1067: }
1068: else if (status & MII_STAT_CAN_TX) {
1069: *speed = HW_SPEED_100_MBPS;
1070: *duplex = FDX_CAPABLE_HALF_SELECTED;
1071: }
1072: else if (status & MII_STAT_CAN_T_FDX) {
1073: *speed = HW_SPEED_10_MBPS;
1074: *duplex = FDX_CAPABLE_FULL_SELECTED;
1075: }
1076: else if (status & MII_STAT_CAN_T) {
1077: *speed = HW_SPEED_10_MBPS;
1078: *duplex = FDX_CAPABLE_HALF_SELECTED;
1079: }
1080:
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 ?
1086: "full" : "half");
1087: else
1088: printf("vt6103_read_config_mode: Media Link Off\n");
1089: }
1090:
1091: /* Function: sis900_transmit
1092: *
1093: * Description: transmits a packet and waits for completion or timeout.
1094: *
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.
1099: *
1100: * Returns: void.
1101: */
1102:
1103: static void
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 */
1109: {
1110: u32 to, nstype;
1111: volatile u32 tx_status;
1112:
1113: /* Stop the transmitter */
1114: outl(TxDIS | inl(ioaddr + cr), ioaddr + cr);
1115:
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));
1121:
1122: memcpy(txb, d, ETH_ALEN);
1123: memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);
1124: nstype = htons(t);
1125: memcpy(txb + 2 * ETH_ALEN, (char*)&nstype, 2);
1126: memcpy(txb + ETH_HLEN, p, s);
1127:
1128: s += ETH_HLEN;
1129: s &= DSIZE;
1130:
1131: if (sis900_debug > 1)
1132: printf("sis900_transmit: sending %d bytes ethtype %hX\n", (int) s, t);
1133:
1134: /* pad to minimum packet size */
1135: while (s < ETH_ZLEN)
1136: txb[s++] = '\0';
1137:
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;
1141:
1142: /* restart the transmitter */
1143: outl(TxENA | inl(ioaddr + cr), ioaddr + cr);
1144:
1145: if (sis900_debug > 1)
1146: printf("sis900_transmit: Queued Tx packet size %d.\n", (int) s);
1147:
1148: to = currticks() + TX_TIMEOUT;
1149:
1150: while (((tx_status=txd.cmdsts) & OWN) && (currticks() < to))
1151: /* wait */ ;
1152:
1153: if (currticks() >= to) {
1154: printf("sis900_transmit: TX Timeout! Tx status %X.\n",
1155: (unsigned int) tx_status);
1156: }
1157:
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);
1162: }
1163: /* Disable interrupts by clearing the interrupt mask. */
1164: outl(0, ioaddr + imr);
1165: }
1166:
1167:
1168: /* Function: sis900_poll
1169: *
1170: * Description: checks for a received packet and returns it if found.
1171: *
1172: * Arguments: struct nic *nic: NIC data structure
1173: *
1174: * Returns: 1 if a packet was recieved.
1175: * 0 if no pacet was recieved.
1176: *
1177: * Side effects:
1178: * Returns (copies) the packet to the array nic->packet.
1179: * Returns the length of the packet in nic->packetlen.
1180: */
1181:
1182: static int
1183: sis900_poll(struct nic *nic, int retrieve)
1184: {
1185: u32 rx_status = rxd[cur_rx].cmdsts;
1186: int retstat = 0;
1187:
1188: /* acknowledge interrupts by reading interrupt status register */
1189: inl(ioaddr + isr);
1190:
1191: if (sis900_debug > 2)
1192: printf("sis900_poll: cur_rx:%d, status:%X\n", cur_rx,
1193: (unsigned int) rx_status);
1194:
1195: if (!(rx_status & OWN))
1196: return retstat;
1197:
1198: if (sis900_debug > 1)
1199: printf("sis900_poll: got a packet: cur_rx:%d, status:%X\n",
1200: cur_rx, (unsigned int) rx_status);
1201:
1202: if ( ! retrieve ) return 1;
1203:
1204: nic->packetlen = (rx_status & DSIZE) - CRC_SIZE;
1205:
1206: if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
1207: /* corrupted packet received */
1208: printf("sis900_poll: Corrupted packet received, buffer status = %X\n",
1209: (unsigned int) rx_status);
1210: retstat = 0;
1211: } else {
1212: /* give packet to higher level routine */
1213: memcpy(nic->packet, (rxb + cur_rx*RX_BUF_SIZE), nic->packetlen);
1214: retstat = 1;
1215: }
1216:
1217: /* return the descriptor and buffer to receive ring */
1218: rxd[cur_rx].cmdsts = RX_BUF_SIZE;
1219: rxd[cur_rx].bufptr = virt_to_bus(&rxb[cur_rx*RX_BUF_SIZE]);
1220:
1221: if (++cur_rx == NUM_RX_DESC)
1222: cur_rx = 0;
1223:
1224: /* re-enable the potentially idle receive state machine */
1225: outl(RxENA | inl(ioaddr + cr), ioaddr + cr);
1226:
1227: return retstat;
1228:
1229: }
1230:
1231:
1232: /* Function: sis900_disable
1233: *
1234: * Description: Turns off interrupts and stops Tx and Rx engines
1235: *
1236: * Arguments: struct nic *nic: NIC data structure
1237: *
1238: * Returns: void.
1239: */
1240:
1241: static void
1242: sis900_disable ( struct nic *nic ) {
1243:
1244: sis900_init(nic);
1245:
1246: /* Disable interrupts by clearing the interrupt mask. */
1247: outl(0, ioaddr + imr);
1248: outl(0, ioaddr + ier);
1249:
1250: /* Stop the chip's Tx and Rx Status Machine */
1251: outl(RxDIS | TxDIS | inl(ioaddr + cr), ioaddr + cr);
1252: }
1253:
1254:
1255: /* Function: sis900_irq
1256: *
1257: * Description: Enable, Disable, or Force, interrupts
1258: *
1259: * Arguments: struct nic *nic: NIC data structure
1260: * irq_action_t action: Requested action
1261: *
1262: * Returns: void.
1263: */
1264:
1265: static void
1266: sis900_irq(struct nic *nic __unused, irq_action_t action __unused)
1267: {
1268: switch ( action ) {
1269: case DISABLE :
1270: outl(0, ioaddr + imr);
1271: break;
1272: case ENABLE :
1273: outl((RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE), ioaddr + imr);
1274: break;
1275: case FORCE :
1276: break;
1277: }
1278: }
1279:
1280: static struct nic_operations sis900_operations = {
1281: .connect = dummy_connect,
1282: .poll = sis900_poll,
1283: .transmit = sis900_transmit,
1284: .irq = sis900_irq,
1285: };
1286:
1287: static struct pci_device_id sis900_nics[] = {
1288: PCI_ROM(0x1039, 0x0900, "sis900", "SIS900", 0),
1289: PCI_ROM(0x1039, 0x7016, "sis7016", "SIS7016", 0),
1290: };
1291:
1292: PCI_DRIVER ( sis900_driver, sis900_nics, PCI_NO_CLASS );
1293:
1294: DRIVER ( "SIS900", nic_driver, pci_driver, sis900_driver,
1295: sis900_probe, sis900_disable );
1296:
1297: /*
1298: * Local variables:
1299: * c-basic-offset: 8
1300: * c-indent-level: 8
1301: * tab-width: 8
1302: * End:
1303: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.