Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / devs / networks / sis900 / sis900.c
blob1f69a78ebf2f7b7d7fb4c728327392e578d59284
1 /*
2 * $Id$
3 */
5 /*
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 MA 02111-1307, USA.
22 #include <exec/types.h>
23 #include <exec/resident.h>
24 #include <exec/io.h>
25 #include <exec/ports.h>
27 #include <aros/libcall.h>
28 #include <aros/macros.h>
29 #include <aros/io.h>
31 #include <oop/oop.h>
33 #include <devices/sana2.h>
34 #include <devices/sana2specialstats.h>
36 #include <utility/utility.h>
37 #include <utility/tagitem.h>
38 #include <utility/hooks.h>
40 #include <hidd/pci.h>
41 #include <hidd/irq.h>
43 #include <proto/oop.h>
44 #include <proto/exec.h>
45 #include <proto/dos.h>
46 #include <proto/battclock.h>
48 #include <stdlib.h>
50 #include "sis900.h"
51 #include "unit.h"
52 #include LC_LIBDEFS_FILE
54 /* A bit fixed linux stuff here :) */
56 #undef LIBBASE
57 #define LIBBASE (unit->sis900u_device)
59 #define net_device SiS900Unit
61 static struct mii_chip_info {
62 const char * name;
63 UWORD phy_id0;
64 UWORD phy_id1;
65 UBYTE phy_types;
66 #define HOME 0x0001
67 #define LAN 0x0002
68 #define MIX 0x0003
69 #define UNKNOWN 0x0
70 } mii_chip_table[] = {
71 { "SiS 900 Internal MII PHY", 0x001d, 0x8000, LAN },
72 { "SiS 7014 Physical Layer Solution", 0x0016, 0xf830, LAN },
73 { "Altimata AC101LF PHY", 0x0022, 0x5520, LAN },
74 { "AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, LAN },
75 { "AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, HOME},
76 { "ICS LAN PHY", 0x0015, 0xF440, LAN },
77 { "NS 83851 PHY", 0x2000, 0x5C20, MIX },
78 { "NS 83847 PHY", 0x2000, 0x5C30, MIX },
79 { "Realtek RTL8201 PHY", 0x0000, 0x8200, LAN },
80 { "VIA 6103 PHY", 0x0101, 0x8f20, LAN },
81 {NULL,},
84 #define TIMER_RPROK 3599597124UL
86 const UBYTE byte_rev_table[256] = {
87 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
88 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
89 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
90 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
91 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
92 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
93 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
94 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
95 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
96 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
97 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
98 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
99 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
100 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
101 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
102 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
103 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
104 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
105 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
106 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
107 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
108 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
109 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
110 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
111 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
112 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
113 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
114 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
115 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
116 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
117 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
118 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
121 #define CRCPOLY_LE 0xedb88320
123 ULONG crc32_le(ULONG crc, unsigned char const *p, int len)
125 int i;
126 while (len--) {
127 crc ^= *p++;
128 for (i = 0; i < 8; i++)
129 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
131 return crc;
134 static inline UBYTE bitrev8(UBYTE byte)
136 return byte_rev_table[byte];
139 UWORD bitrev16(UWORD x)
141 return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8);
145 * bitrev32 - reverse the order of bits in a u32 value
146 * @x: value to be bit-reversed
148 ULONG bitrev32(ULONG x)
150 return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16);
153 #define ether_crc(length, data) bitrev32(crc32_le(~0, data, length))
156 static ULONG usec2tick(ULONG usec)
158 ULONG ret, timer_rpr = TIMER_RPROK;
159 asm volatile("movl $0,%%eax; divl %2":"=a"(ret):"d"(usec),"m"(timer_rpr));
160 return ret;
163 void udelay(LONG usec)
165 int oldtick, tick;
166 usec = usec2tick(usec);
168 BYTEOUT(0x43, 0x80);
169 oldtick = BYTEIN(0x42);
170 oldtick += BYTEIN(0x42) << 8;
172 while (usec > 0)
174 BYTEOUT(0x43, 0x80);
175 tick = BYTEIN(0x42);
176 tick += BYTEIN(0x42) << 8;
178 usec -= (oldtick - tick);
179 if (tick > oldtick) usec -= 0x10000;
180 oldtick = tick;
184 /* sis900_mcast_bitnr - compute hashtable index
185 * @addr: multicast address
186 * @revision: revision id of chip
188 * SiS 900 uses the most sigificant 7 bits to index a 128 bits multicast
189 * hash table, which makes this function a little bit different from other drivers
190 * SiS 900 B0 & 635 M/B uses the most significat 8 bits to index 256 bits
191 * multicast hash table.
193 static inline UWORD sis900_mcast_bitnr(UBYTE *addr, UBYTE revision)
196 ULONG crc = ether_crc(6, addr);
198 /* leave 8 or 7 most siginifant bits */
199 if ((revision >= SIS635A_900_REV) || (revision == SIS900B_900_REV))
200 return ((int)(crc >> 24));
201 else
202 return ((int)(crc >> 25));
205 /* Delay between EEPROM clock transitions. */
206 #define eeprom_delay() LONGIN(ee_addr)
208 static UWORD read_eeprom(long ioaddr, int location)
210 int i;
211 UWORD retval = 0;
212 IPTR ee_addr = ioaddr + mear;
213 ULONG read_cmd = location | EEread;
215 LONGOUT(ee_addr, 0);
216 eeprom_delay();
217 LONGOUT(ee_addr, EECS);
218 eeprom_delay();
220 /* Shift the read command (9) bits out. */
221 for (i = 8; i >= 0; i--) {
222 ULONG dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
223 LONGOUT(ee_addr, dataval);
224 eeprom_delay();
225 LONGOUT(ee_addr, dataval | EECLK);
226 eeprom_delay();
228 LONGOUT(ee_addr, EECS);
229 eeprom_delay();
231 /* read the 16-bits data in */
232 for (i = 16; i > 0; i--) {
233 LONGOUT(ee_addr, EECS);
234 eeprom_delay();
235 LONGOUT(ee_addr, EECS | EECLK);
236 eeprom_delay();
237 retval = (retval << 1) | ((LONGIN(ee_addr) & EEDO) ? 1 : 0);
238 eeprom_delay();
241 /* Terminate the EEPROM access. */
242 LONGOUT(ee_addr, 0);
243 eeprom_delay();
245 return (retval);
248 /* Read and write the MII management registers using software-generated
249 serial MDIO protocol. Note that the command bits and data bits are
250 send out separately */
251 #define mdio_delay() LONGIN(mdio_addr)
253 static void mdio_idle(long mdio_addr)
255 LONGOUT(mdio_addr, MDIO | MDDIR);
256 mdio_delay();
257 LONGOUT(mdio_addr, MDIO | MDDIR | MDC);
260 /* Syncronize the MII management interface by shifting 32 one bits out. */
261 static void mdio_reset(long mdio_addr)
263 int i;
265 for (i = 31; i >= 0; i--) {
266 LONGOUT(mdio_addr, MDDIR | MDIO);
267 mdio_delay();
268 LONGOUT(mdio_addr, MDDIR | MDIO | MDC);
269 mdio_delay();
271 return;
275 * mdio_read - read MII PHY register
276 * @unit: the net device to read
277 * @phy_id: the phy address to read
278 * @location: the phy regiester id to read
280 * Read MII registers through MDIO and MDC
281 * using MDIO management frame structure and protocol(defined by ISO/IEC).
282 * Please see SiS7014 or ICS spec
284 int mdio_read(struct net_device *unit, int phy_id, int location)
286 long mdio_addr = unit->sis900u_BaseMem + mear;
287 int mii_cmd = MIIread | (phy_id << MIIpmdShift) | (location << MIIregShift);
288 UWORD retval = 0;
289 int i;
291 mdio_reset(mdio_addr);
292 mdio_idle(mdio_addr);
294 for (i = 15; i >= 0; i--) {
295 int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
296 LONGOUT(mdio_addr, dataval);
297 mdio_delay();
298 LONGOUT(mdio_addr, dataval | MDC);
299 mdio_delay();
302 /* Read the 16 data bits. */
303 for (i = 16; i > 0; i--) {
304 LONGOUT(mdio_addr, 0);
305 mdio_delay();
306 retval = (retval << 1) | ((LONGIN(mdio_addr) & MDIO) ? 1 : 0);
307 LONGOUT(mdio_addr, MDC);
308 mdio_delay();
310 LONGOUT(mdio_addr, 0x00);
312 return retval;
316 * mdio_write - write MII PHY register
317 * @unit: the net device to write
318 * @phy_id: the phy address to write
319 * @location: the phy regiester id to write
320 * @value: the register value to write with
322 * Write MII registers with @value through MDIO and MDC
323 * using MDIO management frame structure and protocol(defined by ISO/IEC)
324 * please see SiS7014 or ICS spec
326 static void mdio_write(struct net_device *unit, int phy_id, int location, int value)
328 long mdio_addr = unit->sis900u_BaseMem + mear;
329 int mii_cmd = MIIwrite | (phy_id << MIIpmdShift) | (location << MIIregShift);
330 int i;
332 mdio_reset(mdio_addr);
333 mdio_idle(mdio_addr);
335 /* Shift the command bits out. */
336 for (i = 15; i >= 0; i--) {
337 int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
338 BYTEOUT(mdio_addr, dataval);
339 mdio_delay();
340 BYTEOUT(mdio_addr, dataval | MDC);
341 mdio_delay();
343 mdio_delay();
345 /* Shift the value bits out. */
346 for (i = 15; i >= 0; i--) {
347 int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
348 LONGOUT(mdio_addr, dataval);
349 mdio_delay();
350 LONGOUT(mdio_addr, dataval | MDC);
351 mdio_delay();
353 mdio_delay();
355 /* Clear out extra bits. */
356 for (i = 2; i > 0; i--) {
357 BYTEOUT(mdio_addr, 0);
358 mdio_delay();
359 BYTEOUT(mdio_addr, MDC);
360 mdio_delay();
362 LONGOUT(mdio_addr, 0x00);
364 return;
368 * sis900_set_capability - set the media capability of network adapter.
369 * @unit : the net device to probe for
370 * @phy : default PHY
372 * Set the media capability of network adapter according to
373 * mii status register. It's necessary before auto-negotiate.
375 static void sis900_set_capability(struct net_device *unit, struct mii_phy *phy)
377 UWORD cap;
378 UWORD status;
380 D(bug("[%s] sis900_set_capability(phy:%d)\n", unit->sis900u_name, phy->phy_addr));
382 status = mdio_read(unit, phy->phy_addr, MII_STATUS);
383 status = mdio_read(unit, phy->phy_addr, MII_STATUS);
385 cap = MII_NWAY_CSMA_CD |
386 ((phy->status & MII_STAT_CAN_TX_FDX)? MII_NWAY_TX_FDX:0) |
387 ((phy->status & MII_STAT_CAN_TX) ? MII_NWAY_TX:0) |
388 ((phy->status & MII_STAT_CAN_T_FDX) ? MII_NWAY_T_FDX:0)|
389 ((phy->status & MII_STAT_CAN_T) ? MII_NWAY_T:0);
391 mdio_write(unit, phy->phy_addr, MII_ANADV, cap);
395 * sis900_auto_negotiate - Set the Auto-Negotiation Enable/Reset bit.
396 * @unit: the net device to read mode for
397 * @phy_addr: mii phy address
399 * If the adapter is link-on, set the auto-negotiate enable/reset bit.
400 * autong_complete should be set to 0 when starting auto-negotiation.
401 * autong_complete should be set to 1 if we didn't start auto-negotiation.
402 * sis900_timer will wait for link on again if autong_complete = 0.
404 static void sis900_auto_negotiate(struct net_device *unit, int phy_addr)
406 int i = 0;
407 ULONG status;
409 D(bug("[%s] sis900_auto_negotiate(phy:%d)\n", unit->sis900u_name, phy_addr));
411 while (i++ < 2)
412 status = mdio_read(unit, phy_addr, MII_STATUS);
414 if (!(status & MII_STAT_LINK)){
415 //if(netif_msg_link(sis_priv))
416 D(bug("[%s]: sis900_auto_negotiate: Media Link Off\n", unit->sis900u_name));
417 unit->autong_complete = 1;
418 netif_carrier_off(unit);
419 return;
422 /* (Re)start AutoNegotiate */
423 mdio_write(unit, phy_addr, MII_CONTROL, MII_CNTL_AUTO | MII_CNTL_RST_AUTO);
424 unit->autong_complete = 0;
428 * sis900_default_phy - Select default PHY for sis900 mac.
429 * @unit: the net device to probe for
431 * Select first detected PHY with link as default.
432 * If no one is link on, select PHY whose types is HOME as default.
433 * If HOME doesn't exist, select LAN.
435 static UWORD sis900_default_phy(struct net_device *unit)
437 struct mii_phy *phy = NULL, *phy_home = NULL, *default_phy = NULL, *phy_lan = NULL;
438 UWORD status;
440 D(bug("[%s] sis900_default_phy()\n", unit->sis900u_name));
442 for (phy = unit->first_mii; phy; phy = phy->next)
444 status = mdio_read(unit, phy->phy_addr, MII_STATUS);
445 status = mdio_read(unit, phy->phy_addr, MII_STATUS);
447 /* Link ON & Not select default PHY & not ghost PHY */
448 if ((status & MII_STAT_LINK) && !default_phy && (phy->phy_types != UNKNOWN))
449 default_phy = phy;
450 else {
451 status = mdio_read(unit, phy->phy_addr, MII_CONTROL);
452 mdio_write(unit, phy->phy_addr, MII_CONTROL, status | MII_CNTL_AUTO | MII_CNTL_ISOLATE);
453 if (phy->phy_types == HOME)
454 phy_home = phy;
455 else if(phy->phy_types == LAN)
456 phy_lan = phy;
460 if (!default_phy && phy_home)
461 default_phy = phy_home;
462 else if (!default_phy && phy_lan)
463 default_phy = phy_lan;
464 else if (!default_phy)
465 default_phy = unit->first_mii;
467 if (unit->mii != default_phy) {
468 unit->mii = default_phy;
469 unit->cur_phy = default_phy->phy_addr;
470 D(bug("[%s]: sis900_default_phy: Using transceiver found at address %d as default\n", unit->sis900u_name, unit->cur_phy));
473 // unit->mii_info.phy_id = unit->cur_phy;
475 status = mdio_read(unit, unit->cur_phy, MII_CONTROL);
476 status &= (~MII_CNTL_ISOLATE);
478 mdio_write(unit, unit->cur_phy, MII_CONTROL, status);
479 status = mdio_read(unit, unit->cur_phy, MII_STATUS);
480 status = mdio_read(unit, unit->cur_phy, MII_STATUS);
482 return status;
486 * sis900_reset_phy - reset sis900 mii phy.
487 * @unit: the net device to write
488 * @phy_addr: default phy address
490 * Some specific phy can't work properly without reset.
491 * This function will be called during initialization and
492 * link status change from ON to DOWN.
494 static UWORD sis900_reset_phy(struct net_device *unit, int phy_addr)
496 int i = 0;
497 UWORD status;
499 D(bug("[%s] sis900_reset_phy(phy:%d)\n", unit->sis900u_name, phy_addr));
501 while (i++ < 2)
502 status = mdio_read(unit, phy_addr, MII_STATUS);
504 mdio_write(unit, phy_addr, MII_CONTROL, MII_CNTL_RESET);
506 return status;
510 * sis900_mii_probe - Probe MII PHY for sis900
511 * @unit: the net device to probe for
513 * Search for total of 32 possible mii phy addresses.
514 * Identify and set current phy if found one,
515 * return error if it failed to found.
517 static int sis900_mii_probe(struct net_device *unit)
519 UWORD poll_bit = MII_STAT_LINK, status = 0;
520 #warning "TODO: Replace jiffies"
521 #define jiffies 10
522 unsigned long timeout = jiffies + 5 * HZ;
523 int phy_addr;
525 D(bug("[%s] sis900_mii_probe()\n", unit->sis900u_name));
527 unit->mii = NULL;
529 /* search for total of 32 possible mii phy addresses */
530 for (phy_addr = 0; phy_addr < 32; phy_addr++) {
531 struct mii_phy * mii_phy = NULL;
532 UWORD mii_status;
533 int i;
535 mii_phy = NULL;
536 for(i = 0; i < 2; i++)
537 mii_status = mdio_read(unit, phy_addr, MII_STATUS);
539 if (mii_status == 0xffff || mii_status == 0x0000) {
540 D(bug("[%s]: sis900_mii_probe: MII at address %d not accessible\n", unit->sis900u_name, phy_addr));
541 continue;
544 if ((mii_phy = AllocMem(sizeof(struct mii_phy), MEMF_PUBLIC | MEMF_CLEAR)) == NULL) {
545 D(bug("[%s]: sis900_mii_probe: MII %d: Cannot allocate mem for struct mii_phy\n", unit->sis900u_name, phy_addr));
546 mii_phy = unit->first_mii;
547 while (mii_phy) {
548 struct mii_phy *phy;
549 phy = mii_phy;
550 mii_phy = mii_phy->next;
551 FreeMem(phy, sizeof(struct mii_phy));
553 return 0;
556 mii_phy->phy_id0 = mdio_read(unit, phy_addr, MII_PHY_ID0);
557 mii_phy->phy_id1 = mdio_read(unit, phy_addr, MII_PHY_ID1);
558 mii_phy->phy_addr = phy_addr;
559 mii_phy->status = mii_status;
560 mii_phy->next = unit->mii;
561 unit->mii = mii_phy;
562 unit->first_mii = mii_phy;
564 for (i = 0; mii_chip_table[i].phy_id1; i++)
565 if ((mii_phy->phy_id0 == mii_chip_table[i].phy_id0 ) &&
566 ((mii_phy->phy_id1 & 0xFFF0) == mii_chip_table[i].phy_id1)){
567 mii_phy->phy_types = mii_chip_table[i].phy_types;
568 if (mii_chip_table[i].phy_types == MIX)
569 mii_phy->phy_types =
570 (mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME;
571 D(bug("[%s]: sis900_mii_probe: %s transceiver found at address %d.\n", unit->sis900u_name, mii_chip_table[i].name, phy_addr));
572 break;
575 if( !mii_chip_table[i].phy_id1 ) {
576 D(bug("[%s]: sis900_mii_probe: Unknown PHY transceiver found at address %d.\n", unit->sis900u_name, phy_addr));
577 mii_phy->phy_types = UNKNOWN;
581 if (unit->mii == NULL) {
582 D(bug("[%s]: sis900_mii_probe: No MII transceivers found!\n", unit->sis900u_name));
583 return 0;
586 /* select default PHY for mac */
587 unit->mii = NULL;
588 sis900_default_phy(unit);
590 /* Reset phy if default phy is internal sis900 */
591 if ((unit->mii->phy_id0 == 0x001D) &&
592 ((unit->mii->phy_id1&0xFFF0) == 0x8000))
593 status = sis900_reset_phy(unit, unit->cur_phy);
595 /* workaround for ICS1893 PHY */
596 if ((unit->mii->phy_id0 == 0x0015) &&
597 ((unit->mii->phy_id1&0xFFF0) == 0xF440))
598 mdio_write(unit, unit->cur_phy, 0x0018, 0xD200);
600 if(status & MII_STAT_LINK){
601 while (poll_bit) {
602 // yield();
604 poll_bit ^= (mdio_read(unit, unit->cur_phy, MII_STATUS) & poll_bit);
605 // if (time_after_eq(jiffies, timeout)) {
606 //D(bug("[%s]: sis900_mii_probe: reset phy and link down now\n", unit->sis900u_name));
607 #warning "TODO: Return -ETIME!"
608 //return -ETIME;
609 // return 0;
610 // }
614 if (unit->sis900u_RevisionID == SIS630E_900_REV) {
615 /* SiS 630E has some bugs on default value of PHY registers */
616 mdio_write(unit, unit->cur_phy, MII_ANADV, 0x05e1);
617 mdio_write(unit, unit->cur_phy, MII_CONFIG1, 0x22);
618 mdio_write(unit, unit->cur_phy, MII_CONFIG2, 0xff00);
619 mdio_write(unit, unit->cur_phy, MII_MASK, 0xffc0);
620 //mdio_write(unit, unit->cur_phy, MII_CONTROL, 0x1000);
623 if (unit->mii->status & MII_STAT_LINK)
624 netif_carrier_on(unit);
625 else
626 netif_carrier_off(unit);
628 return 1;
631 static void sis900func_start_rx(struct net_device *unit)
633 D(bug("[%s]: sis900func_start_rx\n", unit->sis900u_name));
634 // Already running? Stop it.
635 #warning "TODO: Handle starting/stopping Rx"
638 static void sis900func_stop_rx(struct net_device *unit)
640 D(bug("[%s]: sis900func_stop_rx\n", unit->sis900u_name));
641 #warning "TODO: Handle starting/stopping Rx"
644 static void sis900func_start_tx(struct net_device *unit)
646 D(bug("[%s]: sis900func_start_tx()\n", unit->sis900u_name));
647 #warning "TODO: Handle starting/stopping Tx"
650 static void sis900func_stop_tx(struct net_device *unit)
652 D(bug("[%s]: sis900func_stop_tx()\n", unit->sis900u_name));
653 #warning "TODO: Handle starting/stopping Tx"
656 static void sis900func_txrx_reset(struct net_device *unit)
658 D(bug("[%s]: sis900func_txrx_reset()\n", unit->sis900u_name));
662 * sis900_get_mac_addr - Get MAC address for stand alone SiS900 model
663 * @unit: the net device to get address for
665 * Older SiS900 and friends, use EEPROM to store MAC address.
666 * MAC address is read from read_eeprom() into @net_dev->dev_addr.
668 static int sis900_get_mac_addr(struct net_device *unit)
670 UWORD signature;
671 int i;
673 D(bug("[%s] sis900_get_mac_addr()\n", unit->sis900u_name));
675 /* check to see if we have sane EEPROM */
676 signature = (UWORD) read_eeprom(unit->sis900u_BaseMem, EEPROMSignature);
677 if (signature == 0xffff || signature == 0x0000) {
678 D(bug("[%s]: sis900_get_mac_addr: Error EERPOM read %x\n", unit->sis900u_name, signature));
679 return 0;
682 /* get MAC address from EEPROM */
683 for (i = 0; i < 3; i++)
685 unit->sis900u_org_addr[i] = (UWORD)read_eeprom(unit->sis900u_BaseMem, i + EEPROMMACAddr);
688 return 1;
692 * sis630e_get_mac_addr - Get MAC address for SiS630E model
693 * @unit: the net device to get address for
695 * SiS630E model, use APC CMOS RAM to store MAC address.
696 * APC CMOS RAM is accessed through ISA bridge.
697 * MAC address is read into @net_dev->dev_addr.
699 static int sis630e_get_mac_addr(struct net_device *unit)
701 // struct pci_dev *isa_bridge = NULL;
702 UBYTE reg;
703 int i;
705 D(bug("[%s] sis630e_get_mac_addr()\n", unit->sis900u_name));
707 // isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge);
708 // if (!isa_bridge)
709 // isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
710 // if (!isa_bridge) {
711 // printk(KERN_WARNING "%s: Can not find ISA bridge\n",
712 // pci_name(pci_dev));
713 // return 0;
714 // }
715 // pci_read_config_byte(isa_bridge, 0x48, &reg);
716 // pci_write_config_byte(isa_bridge, 0x48, reg | 0x40);
718 for (i = 0; i < 3; i++) {
719 BYTEOUT(0x70, 0x09 + (i * 2));
720 unit->sis900u_org_addr[i] = 0x0000 + (BYTEIN(0x71) << 8);
721 BYTEOUT(0x70, 0x09 + (i * 2) + 1);
722 unit->sis900u_org_addr[i] |= BYTEIN(0x71);
724 // pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40);
725 // pci_dev_put(isa_bridge);
727 return 1;
731 * sis635_get_mac_addr - Get MAC address for SIS635 model
732 * @unit: the net device to get address for
734 * SiS635 model, set MAC Reload Bit to load Mac address from APC
735 * to rfdr. rfdr is accessed through rfcr. MAC address is read into
736 * @net_dev->dev_addr.
738 static int sis635_get_mac_addr(struct net_device *unit)
740 long ioaddr = unit->sis900u_BaseMem;
741 ULONG rfcrSave;
742 ULONG i;
744 D(bug("[%s] sis635_get_mac_addr()\n", unit->sis900u_name));
746 rfcrSave = LONGIN(rfcr + ioaddr);
748 LONGOUT(ioaddr + cr, rfcrSave | RELOAD);
749 LONGOUT(ioaddr + cr, 0);
751 /* disable packet filtering before setting filter */
752 LONGOUT(rfcr + ioaddr, rfcrSave & ~RFEN);
754 /* load MAC addr to filter data register */
755 for (i = 0 ; i < 3 ; i++) {
756 LONGOUT(ioaddr + rfcr, i << RFADDR_shift);
757 unit->sis900u_org_addr[i] = WORDIN(ioaddr + rfdr);
760 /* enable packet filtering */
761 LONGOUT(rfcr + ioaddr, rfcrSave | RFEN);
763 return 1;
767 * sis96x_get_mac_addr - Get MAC address for SiS962 or SiS963 model
768 * @unit: the net device to get address for
770 * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
771 * is shared by
772 * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first
773 * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access
774 * by LAN, otherwise is not. After MAC address is read from EEPROM, send
775 * EEDONE signal to refuse EEPROM access by LAN.
776 * The EEPROM map of SiS962 or SiS963 is different to SiS900.
777 * The signature field in SiS962 or SiS963 spec is meaningless.
778 * MAC address is read into @net_dev->dev_addr.
780 static int sis96x_get_mac_addr(struct net_device *unit)
782 long ioaddr = unit->sis900u_BaseMem;
783 long ee_addr = ioaddr + mear;
784 ULONG waittime = 0;
785 int i;
787 D(bug("[%s] sis96x_get_mac_addr()\n", unit->sis900u_name));
789 LONGOUT(ee_addr, EEREQ);
790 while(waittime < 2000) {
791 if(LONGIN(ee_addr) & EEGNT) {
793 /* get MAC address from EEPROM */
794 for (i = 0; i < 3; i++)
795 unit->sis900u_org_addr[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
797 LONGOUT(ee_addr, EEDONE);
798 return 1;
799 } else {
800 udelay(1);
801 waittime ++;
804 LONGOUT(ee_addr, EEDONE);
805 return 0;
809 * sis900func_set_multicast: unit->set_multicast function
810 * Called with unit->xmit_lock held.
812 void sis900func_set_multicast(struct net_device *unit)
814 ULONG addr[2];
815 ULONG mask[2];
816 ULONG pff;
818 D(bug("[%s]: sis900func_set_multicast()\n", unit->sis900u_name));
820 memset(addr, 0, sizeof(addr));
821 memset(mask, 0, sizeof(mask));
824 void sis900func_deinitialize(struct net_device *unit)
826 D(bug("[%s] sis900func_deinitialize()\n", unit->sis900u_name));
829 void sis900func_initialize(struct net_device *unit)
831 int i, ret, config1;
833 D(bug("[%s] sis900func_initialize()\n", unit->sis900u_name));
835 ret = 0;
836 if (unit->sis900u_RevisionID == SIS630E_900_REV)
837 ret = sis630e_get_mac_addr(unit);
838 else if ((unit->sis900u_RevisionID > 0x81) && (unit->sis900u_RevisionID <= 0x90) )
839 ret = sis635_get_mac_addr(unit);
840 else if (unit->sis900u_RevisionID == SIS96x_900_REV)
841 ret = sis96x_get_mac_addr(unit);
842 else
843 ret = sis900_get_mac_addr(unit);
845 if (ret == 0) {
846 D(bug("[%s]: Cannot read MAC address.\n", unit->sis900u_name));
847 return;
850 unit->sis900u_dev_addr[0] = unit->sis900u_org_addr[0] & 0xff;
851 unit->sis900u_dev_addr[1] = (unit->sis900u_org_addr[0] >> 8) & 0xff;
853 unit->sis900u_dev_addr[2] = unit->sis900u_org_addr[1] & 0xff;
854 unit->sis900u_dev_addr[3] = (unit->sis900u_org_addr[1] >> 8) & 0xff;
856 unit->sis900u_dev_addr[4] = unit->sis900u_org_addr[2] & 0xff;
857 unit->sis900u_dev_addr[5] = (unit->sis900u_org_addr[2] >> 8) & 0xff;
859 D(bug("[%s]: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->sis900u_name,
860 unit->sis900u_dev_addr[0], unit->sis900u_dev_addr[1], unit->sis900u_dev_addr[2],
861 unit->sis900u_dev_addr[3], unit->sis900u_dev_addr[4], unit->sis900u_dev_addr[5]));
863 /* 630ET : set the mii access mode as software-mode */
864 if (unit->sis900u_RevisionID == SIS630ET_900_REV)
866 LONGOUT(unit->sis900u_BaseMem + cr, ACCESSMODE | LONGIN(unit->sis900u_BaseMem + cr));
869 /* probe for mii transceiver */
870 if (sis900_mii_probe(unit) == 0) {
871 D(bug("[%s]: Error probing MII device.\n", unit->sis900u_name));
872 return;
876 static void sis900func_drain_tx(struct net_device *unit)
878 int i;
879 for (i = 0; i < NUM_TX_DESC; i++) {
880 #warning "TODO: sis900func_drain_tx does nothing atm."
884 static void sis900func_drain_rx(struct net_device *unit)
886 int i;
887 for (i = 0; i < NUM_RX_DESC; i++) {
888 #warning "TODO: sis900func_drain_rx does nothing atm."
892 static void drain_ring(struct net_device *unit)
894 sis900func_drain_tx(unit);
895 sis900func_drain_rx(unit);
898 static int request_irq(struct net_device *unit)
900 OOP_Object *irq = OOP_NewObject(NULL, CLID_Hidd_IRQ, NULL);
901 BOOL ret;
903 D(bug("[%s]: request_irq()\n", unit->sis900u_name));
905 if (irq)
907 ret = HIDD_IRQ_AddHandler(irq, unit->sis900u_irqhandler, unit->sis900u_IRQ);
908 HIDD_IRQ_AddHandler(irq, unit->sis900u_touthandler, vHidd_IRQ_Timer);
910 D(bug("[%s]: request_irq: IRQ Handlers configured\n", unit->sis900u_name));
912 OOP_DisposeObject(irq);
914 if (ret)
916 return 0;
919 return 1;
922 static void free_irq(struct net_device *unit)
924 OOP_Object *irq = OOP_NewObject(NULL, CLID_Hidd_IRQ, NULL);
925 if (irq)
927 HIDD_IRQ_RemHandler(irq, unit->sis900u_irqhandler);
928 HIDD_IRQ_RemHandler(irq, unit->sis900u_touthandler);
929 OOP_DisposeObject(irq);
933 void sis900func_set_mac(struct net_device *unit)
935 int i;
937 D(bug("[%s]: sis900func_set_mac()\n", unit->sis900u_name));
939 /* BYTEOUT(base + RTLr_Cfg9346, 0xc0);
940 LONGOUT(base + RTLr_MAC0 + 0, (
941 ( unit->sis900u_dev_addr[3] << 24 ) |
942 ( unit->sis900u_dev_addr[2] << 16 ) |
943 ( unit->sis900u_dev_addr[1] << 8 ) |
944 unit->sis900u_dev_addr[0]
947 LONGOUT(base + RTLr_MAC0 + 4, (
948 ( unit->sis900u_dev_addr[5] << 8 ) |
949 unit->sis900u_dev_addr[4]
951 BYTEOUT(base + RTLr_Cfg9346, 0x00);*/
955 * sis900_reset - Reset sis900 MAC
956 * @unit: the net device to reset
958 * reset sis900 MAC and wait until finished
959 * reset through command register
960 * change backoff algorithm for 900B0 & 635 M/B
962 static void sis900_reset(struct net_device *unit)
964 long ioaddr = unit->sis900u_BaseMem;
965 int i = 0;
966 ULONG status = TxRCMP | RxRCMP;
968 D(bug("[%s]: sis900_reset()\n", unit->sis900u_name));
970 LONGOUT(ioaddr + ier, 0);
971 LONGOUT(ioaddr + imr, 0);
972 LONGOUT(ioaddr + rfcr, 0);
974 LONGOUT(ioaddr + cr, RxRESET | TxRESET | RESET | LONGIN(ioaddr + cr));
976 /* Check that the chip has finished the reset. */
977 while (status && (i++ < 1000)) {
978 status ^= (LONGIN(isr + ioaddr) & status);
981 if( (unit->sis900u_RevisionID >= SIS635A_900_REV) || (unit->sis900u_RevisionID == SIS900B_900_REV) )
982 LONGOUT(ioaddr + cfg, PESEL | RND_CNT);
983 else
984 LONGOUT(ioaddr + cfg, PESEL);
988 * sis630_set_eq - set phy equalizer value for 630 LAN
989 * @unit: the net device to set equalizer value
990 * @revision: 630 LAN revision number
992 * 630E equalizer workaround rule(Cyrus Huang 08/15)
993 * PHY register 14h(Test)
994 * Bit 14: 0 -- Automatically dectect (default)
995 * 1 -- Manually set Equalizer filter
996 * Bit 13: 0 -- (Default)
997 * 1 -- Speed up convergence of equalizer setting
998 * Bit 9 : 0 -- (Default)
999 * 1 -- Disable Baseline Wander
1000 * Bit 3~7 -- Equalizer filter setting
1001 * Link ON: Set Bit 9, 13 to 1, Bit 14 to 0
1002 * Then calculate equalizer value
1003 * Then set equalizer value, and set Bit 14 to 1, Bit 9 to 0
1004 * Link Off:Set Bit 13 to 1, Bit 14 to 0
1005 * Calculate Equalizer value:
1006 * When Link is ON and Bit 14 is 0, SIS900PHY will auto-dectect proper equalizer value.
1007 * When the equalizer is stable, this value is not a fixed value. It will be within
1008 * a small range(eg. 7~9). Then we get a minimum and a maximum value(eg. min=7, max=9)
1009 * 0 <= max <= 4 --> set equalizer to max
1010 * 5 <= max <= 14 --> set equalizer to max+1 or set equalizer to max+2 if max == min
1011 * max >= 15 --> set equalizer to max+5 or set equalizer to max+6 if max == min
1013 static void sis630_set_eq(struct net_device *unit, UBYTE revision)
1015 UWORD reg14h, eq_value=0, max_value=0, min_value=0;
1016 int i, maxcount=10;
1018 D(bug("[%s]: sis630_set_eq()\n", unit->sis900u_name));
1020 if ( !(revision == SIS630E_900_REV || revision == SIS630EA1_900_REV ||
1021 revision == SIS630A_900_REV || revision == SIS630ET_900_REV) )
1023 D(bug("[%s]: sis630_set_eq: Skipping for revision %d chipset\n", unit->sis900u_name, revision));
1024 return;
1027 if (netif_carrier_ok(unit)) {
1028 reg14h = mdio_read(unit, unit->cur_phy, MII_RESV);
1029 mdio_write(unit, unit->cur_phy, MII_RESV,
1030 (0x2200 | reg14h) & 0xBFFF);
1031 for (i=0; i < maxcount; i++) {
1032 eq_value = (0x00F8 & mdio_read(unit,
1033 unit->cur_phy, MII_RESV)) >> 3;
1034 if (i == 0)
1035 max_value=min_value=eq_value;
1036 max_value = (eq_value > max_value) ?
1037 eq_value : max_value;
1038 min_value = (eq_value < min_value) ?
1039 eq_value : min_value;
1041 /* 630E rule to determine the equalizer value */
1042 if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV ||
1043 revision == SIS630ET_900_REV) {
1044 if (max_value < 5)
1045 eq_value = max_value;
1046 else if (max_value >= 5 && max_value < 15)
1047 eq_value = (max_value == min_value) ?
1048 max_value+2 : max_value+1;
1049 else if (max_value >= 15)
1050 eq_value=(max_value == min_value) ?
1051 max_value+6 : max_value+5;
1053 /* 630B0&B1 rule to determine the equalizer value */
1054 if (revision == SIS630A_900_REV &&
1055 (unit->sis900u_HostRevisionID == SIS630B0 ||
1056 unit->sis900u_HostRevisionID == SIS630B1)) {
1057 if (max_value == 0)
1058 eq_value = 3;
1059 else
1060 eq_value = (max_value + min_value + 1)/2;
1062 /* write equalizer value and setting */
1063 reg14h = mdio_read(unit, unit->cur_phy, MII_RESV);
1064 reg14h = (reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8);
1065 reg14h = (reg14h | 0x6000) & 0xFDFF;
1066 mdio_write(unit, unit->cur_phy, MII_RESV, reg14h);
1067 } else {
1068 reg14h = mdio_read(unit, unit->cur_phy, MII_RESV);
1069 if (revision == SIS630A_900_REV &&
1070 (unit->sis900u_HostRevisionID == SIS630B0 ||
1071 unit->sis900u_HostRevisionID == SIS630B1))
1072 mdio_write(unit, unit->cur_phy, MII_RESV,
1073 (reg14h | 0x2200) & 0xBFFF);
1074 else
1075 mdio_write(unit, unit->cur_phy, MII_RESV,
1076 (reg14h | 0x2000) & 0xBFFF);
1078 return;
1082 * sis900_init_rxfilter - Initialize the Rx filter
1083 * @unit: the net device to initialize for
1085 * Set receive filter address to our MAC address
1086 * and enable packet filtering.
1088 static void sis900_init_rxfilter(struct net_device *unit)
1090 long ioaddr = unit->sis900u_BaseMem;
1091 ULONG rfcrSave;
1092 ULONG i;
1094 D(bug("[%s]: sis900_init_rxfilter()\n", unit->sis900u_name));
1096 rfcrSave = LONGIN(rfcr + ioaddr);
1098 /* disable packet filtering before setting filter */
1099 LONGOUT(rfcr + ioaddr, rfcrSave & ~RFEN);
1101 /* load MAC addr to filter data register */
1102 for (i = 0 ; i < 3 ; i++) {
1103 ULONG w;
1105 w = (unit->sis900u_dev_addr[(i * 2)] << 8 ) + unit->sis900u_dev_addr[(i * 2) + 1];
1106 LONGOUT(ioaddr + rfcr, (i << RFADDR_shift));
1107 LONGOUT(ioaddr + rfdr, w);
1109 //if (netif_msg_hw(unit)) {
1110 D(bug("[%s]: sis900_init_rxfilter: Receive Filter Addrss[%d]=%x\n",unit->sis900u_name, i, LONGIN(ioaddr + rfdr)));
1114 /* enable packet filtering */
1115 LONGOUT(rfcr + ioaddr, rfcrSave | RFEN);
1119 * sis900_init_tx_ring - Initialize the Tx descriptor ring
1120 * @unit: the net device to initialize for
1122 * Initialize the Tx descriptor ring,
1124 static void sis900_init_tx_ring(struct net_device *unit)
1126 long ioaddr = unit->sis900u_BaseMem;
1127 int i, allocate = 1;
1129 D(bug("[%s]: sis900_init_tx_ring()\n", unit->sis900u_name));
1131 unit->tx_full = 0;
1132 unit->dirty_tx = unit->cur_tx = 0;
1134 for (i = 0; i < NUM_TX_DESC; i++) {
1135 APTR framebuffer;
1137 if ((allocate) && ((framebuffer = AllocMem(TX_BUF_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)) {
1138 /* not enough memory for framebuffer this makes a "hole"
1139 on the buffer ring, it is not clear how the
1140 hardware will react to this kind of degenerated
1141 buffer */
1142 allocate = 0;
1145 unit->tx_ring[i].link = unit->tx_ring_dma +
1146 ((i+1)%NUM_TX_DESC)*sizeof(BufferDesc);
1147 unit->tx_ring[i].cmdsts = 0;
1148 if (framebuffer)
1150 unit->tx_buffers[i] = framebuffer;
1151 unit->tx_ring[i].bufptr = HIDD_PCIDriver_CPUtoPCI(unit->sis900u_PCIDriver, framebuffer);
1153 D(bug("[%s]: sis900_init_tx_ring: Buffer %d @ %p\n", unit->sis900u_name, i, framebuffer));
1156 /* load Transmit Descriptor Register */
1157 LONGOUT(ioaddr + txdp, unit->tx_ring_dma);
1158 // if (netif_msg_hw(unit))
1159 D(bug("[%s]: sis900_init_tx_ring: TX descriptor register loaded with: %8.8x\n",unit->sis900u_name, LONGIN(ioaddr + txdp)));
1163 * sis900_init_rx_ring - Initialize the Rx descriptor ring
1164 * @unit: the net device to initialize for
1166 * Initialize the Rx descriptor ring,
1167 * and pre-allocate recevie buffers (socket buffer)
1169 static void sis900_init_rx_ring(struct net_device *unit)
1171 long ioaddr = unit->sis900u_BaseMem;
1172 int i, allocate = 1;
1174 D(bug("[%s]: sis900_init_rx_ring()\n", unit->sis900u_name));
1176 unit->cur_rx = 0;
1177 unit->dirty_rx = 0;
1179 /* init RX descriptor and allocate buffers */
1180 for (i = 0; i < NUM_RX_DESC; i++) {
1181 APTR framebuffer;
1183 if ((allocate) && ((framebuffer = AllocMem(RX_BUF_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)) {
1184 /* not enough memory for framebuffer this makes a "hole"
1185 on the buffer ring, it is not clear how the
1186 hardware will react to this kind of degenerated
1187 buffer */
1188 allocate = 0;
1190 unit->rx_ring[i].link = unit->rx_ring_dma +
1191 ((i+1)%NUM_RX_DESC)*sizeof(BufferDesc);
1192 unit->rx_ring[i].cmdsts = RX_BUF_SIZE;
1193 if (framebuffer)
1195 unit->rx_buffers[i] = framebuffer;
1196 unit->rx_ring[i].bufptr = HIDD_PCIDriver_CPUtoPCI(unit->sis900u_PCIDriver, framebuffer);
1198 D(bug("[%s]: sis900_init_rx_ring: Buffer %d @ %p\n", unit->sis900u_name, i, framebuffer));
1200 unit->dirty_rx = (unsigned int) (i - NUM_RX_DESC);
1202 /* load Receive Descriptor Register */
1203 LONGOUT(ioaddr + rxdp, unit->rx_ring_dma);
1204 // if (netif_msg_hw(sis_priv))
1205 D(bug("[%s]: sis900_init_rx_ring: RX descriptor register loaded with: %8.8x\n",unit->sis900u_name, LONGIN(ioaddr + rxdp)));
1210 * set_rx_mode - Set SiS900 receive mode
1211 * @unit: the net device to be set
1213 * Set SiS900 receive mode for promiscuous, multicast, or broadcast mode.
1214 * And set the appropriate multicast filter.
1215 * Multicast hash table changes from 128 to 256 bits for 635M/B & 900B0.
1217 static void set_rx_mode(struct net_device *unit)
1219 long ioaddr = unit->sis900u_BaseMem;
1220 UWORD mc_filter[16] = {0}; /* 256/128 bits multicast hash table */
1221 int i, table_entries;
1222 ULONG rx_mode;
1224 D(bug("[%s]: set_rx_mode()\n", unit->sis900u_name));
1226 /* 635 Hash Table entires = 256(2^16) */
1227 if((unit->sis900u_RevisionID >= SIS635A_900_REV) ||
1228 (unit->sis900u_RevisionID == SIS900B_900_REV))
1229 table_entries = 16;
1230 else
1231 table_entries = 8;
1233 #warning "TODO: Fix multicast settings"
1234 //if (unit->sis900u_ifflags & IFF_PROMISC) {
1235 // Accept any kinds of packets
1236 rx_mode = RFPromiscuous;
1237 for (i = 0; i < table_entries; i++)
1238 mc_filter[i] = 0xffff;
1239 /*} else if ((unit->mc_count > multicast_filter_limit) ||
1240 (unit->sis900u_ifflags & IFF_ALLMULTI)) {
1241 // too many multicast addresses or accept all multicast packet
1242 rx_mode = RFAAB | RFAAM;
1243 for (i = 0; i < table_entries; i++)
1244 mc_filter[i] = 0xffff;
1245 } else {
1246 // Accept Broadcast packet, destination address matchs our
1247 // MAC address, use Receive Filter to reject unwanted MCAST
1248 // packets
1249 struct dev_mc_list *mclist;
1250 rx_mode = RFAAB;
1251 for (i = 0, mclist = unit->mc_list;
1252 mclist && i < unit->mc_count;
1253 i++, mclist = mclist->next) {
1254 unsigned int bit_nr =
1255 sis900_mcast_bitnr(mclist->dmi_addr, unit->sis900u_RevisionID);
1256 mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf));
1260 /* update Multicast Hash Table in Receive Filter */
1261 for (i = 0; i < table_entries; i++) {
1262 /* why plus 0x04 ??, That makes the correct value for hash table. */
1263 LONGOUT(ioaddr + rfcr, (ULONG)(0x00000004+i) << RFADDR_shift);
1264 LONGOUT(ioaddr + rfdr, mc_filter[i]);
1267 LONGOUT(ioaddr + rfcr, RFEN | rx_mode);
1269 /* sis900 is capable of looping back packets at MAC level for
1270 * debugging purpose */
1271 if (unit->sis900u_ifflags & IFF_LOOPBACK) {
1272 ULONG cr_saved;
1273 /* We must disable Tx/Rx before setting loopback mode */
1274 cr_saved = LONGIN(ioaddr + cr);
1275 LONGOUT(ioaddr + cr, cr_saved | TxDIS | RxDIS);
1276 /* enable loopback */
1277 LONGOUT(ioaddr + txcfg, LONGIN(ioaddr + txcfg) | TxMLB);
1278 LONGOUT(ioaddr + rxcfg, LONGIN(ioaddr + rxcfg) | RxATX);
1279 /* restore cr */
1280 LONGOUT(ioaddr + cr, cr_saved);
1283 return;
1287 * sis900_set_mode - Set the media mode of mac register.
1288 * @ioaddr: the address of the device
1289 * @speed : the transmit speed to be determined
1290 * @duplex: the duplex mode to be determined
1292 * Set the media mode of mac register txcfg/rxcfg according to
1293 * speed and duplex of phy. Bit EDB_MASTER_EN indicates the EDB
1294 * bus is used instead of PCI bus. When this bit is set 1, the
1295 * Max DMA Burst Size for TX/RX DMA should be no larger than 16
1296 * double words.
1298 static void sis900_set_mode(long ioaddr, int speed, int duplex)
1300 ULONG tx_flags = 0, rx_flags = 0;
1302 //D(bug("[%s]: sis900_set_mode()\n", unit->sis900u_name));
1304 if (LONGIN(ioaddr + cfg) & EDB_MASTER_EN) {
1305 tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) |
1306 (TX_FILL_THRESH << TxFILLT_shift);
1307 rx_flags = DMA_BURST_64 << RxMXDMA_shift;
1308 } else {
1309 tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) |
1310 (TX_FILL_THRESH << TxFILLT_shift);
1311 rx_flags = DMA_BURST_512 << RxMXDMA_shift;
1314 if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
1315 rx_flags |= (RxDRNT_10 << RxDRNT_shift);
1316 tx_flags |= (TxDRNT_10 << TxDRNT_shift);
1317 } else {
1318 rx_flags |= (RxDRNT_100 << RxDRNT_shift);
1319 tx_flags |= (TxDRNT_100 << TxDRNT_shift);
1322 if (duplex == FDX_CAPABLE_FULL_SELECTED) {
1323 tx_flags |= (TxCSI | TxHBI);
1324 rx_flags |= RxATX;
1327 LONGOUT(ioaddr + txcfg, tx_flags);
1328 LONGOUT(ioaddr + rxcfg, rx_flags);
1332 * sis900_check_mode - check the media mode for sis900
1333 * @unit: the net device to be checked
1334 * @mii_phy: the mii phy
1336 * Older driver gets the media mode from mii status output
1337 * register. Now we set our media capability and auto-negotiate
1338 * to get the upper bound of speed and duplex between two ends.
1339 * If the types of mii phy is HOME, it doesn't need to auto-negotiate
1340 * and autong_complete should be set to 1.
1342 static void sis900_check_mode(struct net_device *unit, struct mii_phy *mii_phy)
1344 long ioaddr = unit->sis900u_BaseMem;
1345 int speed, duplex;
1347 D(bug("[%s]: sis900_check_mode()\n", unit->sis900u_name));
1349 if (mii_phy->phy_types == LAN) {
1350 LONGOUT(ioaddr + cfg, ~EXD & LONGIN(ioaddr + cfg));
1351 sis900_set_capability(unit, mii_phy);
1352 sis900_auto_negotiate(unit, unit->cur_phy);
1353 } else {
1354 LONGOUT(ioaddr + cfg, EXD | LONGIN(ioaddr + cfg));
1355 speed = HW_SPEED_HOME;
1356 duplex = FDX_CAPABLE_HALF_SELECTED;
1357 sis900_set_mode(ioaddr, speed, duplex);
1358 unit->autong_complete = 1;
1362 int sis900func_open(struct net_device *unit)
1364 int ret, i, rx_buf_len_idx;
1366 D(bug("[%s]: sis900func_open()\n", unit->sis900u_name));
1368 /* Soft reset the chip. */
1369 sis900_reset(unit);
1371 /* Equalizer workaround Rule */
1372 sis630_set_eq(unit, unit->sis900u_RevisionID);
1374 ret = request_irq(unit);
1375 if (ret)
1376 goto out_drain;
1378 sis900_init_rxfilter(unit);
1380 sis900_init_tx_ring(unit);
1381 sis900_init_rx_ring(unit);
1383 set_rx_mode(unit);
1385 // netif_start_queue(unit);
1387 /* Workaround for EDB */
1388 sis900_set_mode(unit->sis900u_BaseMem, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
1390 D(bug("[%s]: sis900func_open: Enabling NIC's interupts .. \n", unit->sis900u_name));
1391 /* Enable all known interrupts by setting the interrupt mask. */
1392 LONGOUT(unit->sis900u_BaseMem + imr, (RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE));
1393 LONGOUT(unit->sis900u_BaseMem + cr, RxENA | LONGIN(unit->sis900u_BaseMem + cr));
1394 LONGOUT(unit->sis900u_BaseMem + ier, IE);
1396 sis900_check_mode(unit, unit->mii);
1398 unit->sis900u_ifflags |= IFF_UP;
1399 ReportEvents(LIBBASE, unit, S2EVENT_ONLINE);
1400 D(bug("[%s]: sis900func_open: Device set as ONLINE\n",unit->sis900u_name));
1402 return 0;
1404 out_drain:
1405 drain_ring(unit);
1406 return ret;
1409 int sis900func_close(struct net_device *unit)
1411 UBYTE *base;
1413 D(bug("[%s]: sis900func_close()\n", unit->sis900u_name));
1415 unit->sis900u_ifflags &= ~IFF_UP;
1417 // ObtainSemaphore(&np->lock);
1418 // np->in_shutdown = 1;
1419 // ReleaseSemaphore(&np->lock);
1421 // unit->sis900u_toutNEED = FALSE;
1423 netif_stop_queue(unit);
1424 // ObtainSemaphore(&np->lock);
1426 sis900func_deinitialize(unit); // Stop the chipset and set it in 16bit-mode
1428 // base = get_hwbase(unit);
1430 // ReleaseSemaphore(&np->lock);
1432 free_irq(unit);
1434 drain_ring(unit);
1436 // HIDD_PCIDriver_FreePCIMem(unit->sis900u_PCIDriver, np->rx_buffer);
1437 // HIDD_PCIDriver_FreePCIMem(unit->sis900u_PCIDriver, np->tx_buffer);
1439 ReportEvents(LIBBASE, unit, S2EVENT_OFFLINE);
1441 return 0;