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
50 static int sis900_debug = 0;
51
52 static unsigned short vendor, dev_id;
53 static unsigned long ioaddr;
54
55 static unsigned int cur_phy;
56
57 static unsigned int cur_rx;
58
59 static BufferDesc txd;
60 static 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
66 static unsigned char txb[TX_BUF_SIZE];
67 static unsigned char rxb[NUM_RX_DESC * RX_BUF_SIZE];
68 #endif
69
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. */
80 };
81
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);
86
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}
100 };
101
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;
108
109
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}
115 };
116
117 /* Function Prototypes */
118
119 struct nic *sis900_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci);
120
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);
126
127 static void sis900_init(struct nic *nic);
128
129 static void sis900_reset(struct nic *nic);
130
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);
136
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);
140
141 static 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
sis900_get_mac_addr(struct pci_device * pci_dev,struct nic * nic)152 static 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
sis630e_get_mac_addr(struct pci_device * pci_dev,struct nic * nic)180 static 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, ®);
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
sis900_probe(struct nic * nic,unsigned short * io_addrs,struct pci_device * pci)219 struct 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 */
sis900_read_eeprom(int location)338 static 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
sis900_mdio_idle(long mdio_addr)388 static 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. */
sis900_mdio_reset(long mdio_addr)396 static 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
sis900_mdio_read(int phy_id,int location)409 static 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
sis900_mdio_write(int phy_id,int location,int value)438 static 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
488 static void
sis900_init(struct nic * nic)489 sis900_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
517 static void
sis900_reset(struct nic * nic)518 sis900_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
546 static void
sis900_init_rxfilter(struct nic * nic)547 sis900_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
585 static void
sis900_init_txd(struct nic * nic)586 sis900_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
609 static void
sis900_init_rxd(struct nic * nic)610 sis900_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
sis900_set_rx_mode(struct nic * nic)647 static 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
676 static void
sis900_check_mode(struct nic * nic)677 sis900_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
716 static void
sis900_read_mode(struct nic * nic,int phy_addr,int * speed,int * duplex)717 sis900_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
757 static void
amd79c901_read_mode(struct nic * nic,int phy_addr,int * speed,int * duplex)758 amd79c901_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
ics1893_read_mode(struct nic * nic,int phy_addr,int * speed,int * duplex)811 static 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
rtl8201_read_mode(struct nic * nic,int phy_addr,int * speed,int * duplex)851 static 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
896 static void
sis900_transmit(struct nic * nic,const char * d,unsigned int t,unsigned int s,const char * p)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 */
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
973 static int
sis900_poll(struct nic * nic)974 sis900_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
1025 static void
sis900_disable(struct nic * nic)1026 sis900_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