Check for SYS/GL during library init. Reason is that
[AROS.git] / workbench / devs / networks / sis900 / sis900.c
blob7574e13f7e89105894c6ad03e9a323e69ab9aa5c
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>
42 #include <proto/oop.h>
43 #include <proto/exec.h>
44 #include <proto/dos.h>
45 #include <proto/battclock.h>
47 #include <hardware/intbits.h>
49 #include <stdlib.h>
51 #include "sis900.h"
52 #include "unit.h"
53 #include LC_LIBDEFS_FILE
55 /* A bit fixed linux stuff here :) */
57 #undef LIBBASE
58 #define LIBBASE (unit->sis900u_device)
60 #define net_device SiS900Unit
62 static struct mii_chip_info {
63 const char * name;
64 UWORD phy_id0;
65 UWORD phy_id1;
66 UBYTE phy_types;
67 #define HOME 0x0001
68 #define LAN 0x0002
69 #define MIX 0x0003
70 #define UNKNOWN 0x0
71 } mii_chip_table[] = {
72 { "SiS 900 Internal MII PHY", 0x001d, 0x8000, LAN },
73 { "SiS 7014 Physical Layer Solution", 0x0016, 0xf830, LAN },
74 { "Altimata AC101LF PHY", 0x0022, 0x5520, LAN },
75 { "AMD 79C901 10BASE-T PHY", 0x0000, 0x6B70, LAN },
76 { "AMD 79C901 HomePNA PHY", 0x0000, 0x6B90, HOME},
77 { "ICS LAN PHY", 0x0015, 0xF440, LAN },
78 { "NS 83851 PHY", 0x2000, 0x5C20, MIX },
79 { "NS 83847 PHY", 0x2000, 0x5C30, MIX },
80 { "Realtek RTL8201 PHY", 0x0000, 0x8200, LAN },
81 { "VIA 6103 PHY", 0x0101, 0x8f20, LAN },
82 {NULL,},
85 #define TIMER_RPROK 3599597124UL
87 const UBYTE byte_rev_table[256] = {
88 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
89 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
90 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
91 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
92 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
93 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
94 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
95 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
96 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
97 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
98 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
99 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
100 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
101 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
102 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
103 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
104 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
105 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
106 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
107 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
108 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
109 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
110 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
111 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
112 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
113 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
114 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
115 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
116 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
117 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
118 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
119 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
122 #define CRCPOLY_LE 0xedb88320
124 ULONG crc32_le(ULONG crc, unsigned char const *p, int len)
126 int i;
127 while (len--) {
128 crc ^= *p++;
129 for (i = 0; i < 8; i++)
130 crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0);
132 return crc;
135 static inline UBYTE bitrev8(UBYTE byte)
137 return byte_rev_table[byte];
140 UWORD bitrev16(UWORD x)
142 return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8);
146 * bitrev32 - reverse the order of bits in a u32 value
147 * @x: value to be bit-reversed
149 ULONG bitrev32(ULONG x)
151 return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16);
154 #define ether_crc(length, data) bitrev32(crc32_le(~0, data, length))
157 static ULONG usec2tick(ULONG usec)
159 ULONG ret, timer_rpr = TIMER_RPROK;
160 asm volatile("movl $0,%%eax; divl %2":"=a"(ret):"d"(usec),"m"(timer_rpr));
161 return ret;
164 void udelay(LONG usec)
166 int oldtick, tick;
167 usec = usec2tick(usec);
169 BYTEOUT(0x43, 0x80);
170 oldtick = BYTEIN(0x42);
171 oldtick += BYTEIN(0x42) << 8;
173 while (usec > 0)
175 BYTEOUT(0x43, 0x80);
176 tick = BYTEIN(0x42);
177 tick += BYTEIN(0x42) << 8;
179 usec -= (oldtick - tick);
180 if (tick > oldtick) usec -= 0x10000;
181 oldtick = tick;
185 /* sis900_mcast_bitnr - compute hashtable index
186 * @addr: multicast address
187 * @revision: revision id of chip
189 * SiS 900 uses the most sigificant 7 bits to index a 128 bits multicast
190 * hash table, which makes this function a little bit different from other drivers
191 * SiS 900 B0 & 635 M/B uses the most significat 8 bits to index 256 bits
192 * multicast hash table.
194 static inline UWORD sis900_mcast_bitnr(UBYTE *addr, UBYTE revision)
197 ULONG crc = ether_crc(6, addr);
199 /* leave 8 or 7 most siginifant bits */
200 if ((revision >= SIS635A_900_REV) || (revision == SIS900B_900_REV))
201 return ((int)(crc >> 24));
202 else
203 return ((int)(crc >> 25));
206 /* Delay between EEPROM clock transitions. */
207 #define eeprom_delay() LONGIN(ee_addr)
209 static UWORD read_eeprom(long ioaddr, int location)
211 int i;
212 UWORD retval = 0;
213 IPTR ee_addr = ioaddr + mear;
214 ULONG read_cmd = location | EEread;
216 LONGOUT(ee_addr, 0);
217 eeprom_delay();
218 LONGOUT(ee_addr, EECS);
219 eeprom_delay();
221 /* Shift the read command (9) bits out. */
222 for (i = 8; i >= 0; i--) {
223 ULONG dataval = (read_cmd & (1 << i)) ? EEDI | EECS : EECS;
224 LONGOUT(ee_addr, dataval);
225 eeprom_delay();
226 LONGOUT(ee_addr, dataval | EECLK);
227 eeprom_delay();
229 LONGOUT(ee_addr, EECS);
230 eeprom_delay();
232 /* read the 16-bits data in */
233 for (i = 16; i > 0; i--) {
234 LONGOUT(ee_addr, EECS);
235 eeprom_delay();
236 LONGOUT(ee_addr, EECS | EECLK);
237 eeprom_delay();
238 retval = (retval << 1) | ((LONGIN(ee_addr) & EEDO) ? 1 : 0);
239 eeprom_delay();
242 /* Terminate the EEPROM access. */
243 LONGOUT(ee_addr, 0);
244 eeprom_delay();
246 return (retval);
249 /* Read and write the MII management registers using software-generated
250 serial MDIO protocol. Note that the command bits and data bits are
251 send out separately */
252 #define mdio_delay() LONGIN(mdio_addr)
254 static void mdio_idle(long mdio_addr)
256 LONGOUT(mdio_addr, MDIO | MDDIR);
257 mdio_delay();
258 LONGOUT(mdio_addr, MDIO | MDDIR | MDC);
261 /* Syncronize the MII management interface by shifting 32 one bits out. */
262 static void mdio_reset(long mdio_addr)
264 int i;
266 for (i = 31; i >= 0; i--) {
267 LONGOUT(mdio_addr, MDDIR | MDIO);
268 mdio_delay();
269 LONGOUT(mdio_addr, MDDIR | MDIO | MDC);
270 mdio_delay();
272 return;
276 * mdio_read - read MII PHY register
277 * @unit: the net device to read
278 * @phy_id: the phy address to read
279 * @location: the phy regiester id to read
281 * Read MII registers through MDIO and MDC
282 * using MDIO management frame structure and protocol(defined by ISO/IEC).
283 * Please see SiS7014 or ICS spec
285 int mdio_read(struct net_device *unit, int phy_id, int location)
287 long mdio_addr = unit->sis900u_BaseMem + mear;
288 int mii_cmd = MIIread | (phy_id << MIIpmdShift) | (location << MIIregShift);
289 UWORD retval = 0;
290 int i;
292 mdio_reset(mdio_addr);
293 mdio_idle(mdio_addr);
295 for (i = 15; i >= 0; i--) {
296 int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
297 LONGOUT(mdio_addr, dataval);
298 mdio_delay();
299 LONGOUT(mdio_addr, dataval | MDC);
300 mdio_delay();
303 /* Read the 16 data bits. */
304 for (i = 16; i > 0; i--) {
305 LONGOUT(mdio_addr, 0);
306 mdio_delay();
307 retval = (retval << 1) | ((LONGIN(mdio_addr) & MDIO) ? 1 : 0);
308 LONGOUT(mdio_addr, MDC);
309 mdio_delay();
311 LONGOUT(mdio_addr, 0x00);
313 return retval;
317 * mdio_write - write MII PHY register
318 * @unit: the net device to write
319 * @phy_id: the phy address to write
320 * @location: the phy regiester id to write
321 * @value: the register value to write with
323 * Write MII registers with @value through MDIO and MDC
324 * using MDIO management frame structure and protocol(defined by ISO/IEC)
325 * please see SiS7014 or ICS spec
327 static void mdio_write(struct net_device *unit, int phy_id, int location, int value)
329 long mdio_addr = unit->sis900u_BaseMem + mear;
330 int mii_cmd = MIIwrite | (phy_id << MIIpmdShift) | (location << MIIregShift);
331 int i;
333 mdio_reset(mdio_addr);
334 mdio_idle(mdio_addr);
336 /* Shift the command bits out. */
337 for (i = 15; i >= 0; i--) {
338 int dataval = (mii_cmd & (1 << i)) ? MDDIR | MDIO : MDDIR;
339 BYTEOUT(mdio_addr, dataval);
340 mdio_delay();
341 BYTEOUT(mdio_addr, dataval | MDC);
342 mdio_delay();
344 mdio_delay();
346 /* Shift the value bits out. */
347 for (i = 15; i >= 0; i--) {
348 int dataval = (value & (1 << i)) ? MDDIR | MDIO : MDDIR;
349 LONGOUT(mdio_addr, dataval);
350 mdio_delay();
351 LONGOUT(mdio_addr, dataval | MDC);
352 mdio_delay();
354 mdio_delay();
356 /* Clear out extra bits. */
357 for (i = 2; i > 0; i--) {
358 BYTEOUT(mdio_addr, 0);
359 mdio_delay();
360 BYTEOUT(mdio_addr, MDC);
361 mdio_delay();
363 LONGOUT(mdio_addr, 0x00);
365 return;
369 * sis900_set_capability - set the media capability of network adapter.
370 * @unit : the net device to probe for
371 * @phy : default PHY
373 * Set the media capability of network adapter according to
374 * mii status register. It's necessary before auto-negotiate.
376 static void sis900_set_capability(struct net_device *unit, struct mii_phy *phy)
378 UWORD cap;
380 D(bug("[%s] sis900_set_capability(phy:%d)\n", unit->sis900u_name, phy->phy_addr));
382 mdio_read(unit, phy->phy_addr, MII_STATUS);
383 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 /* 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 /* 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 #if 0
632 static void sis900func_start_rx(struct net_device *unit)
634 D(bug("[%s]: sis900func_start_rx\n", unit->sis900u_name));
635 // Already running? Stop it.
636 /* TODO: Handle starting/stopping Rx */
639 static void sis900func_stop_rx(struct net_device *unit)
641 D(bug("[%s]: sis900func_stop_rx\n", unit->sis900u_name));
642 /* TODO: Handle starting/stopping Rx */
645 static void sis900func_start_tx(struct net_device *unit)
647 D(bug("[%s]: sis900func_start_tx()\n", unit->sis900u_name));
648 /* TODO: Handle starting/stopping Tx */
651 static void sis900func_stop_tx(struct net_device *unit)
653 D(bug("[%s]: sis900func_stop_tx()\n", unit->sis900u_name));
654 /* TODO: Handle starting/stopping Tx */
657 static void sis900func_txrx_reset(struct net_device *unit)
659 D(bug("[%s]: sis900func_txrx_reset()\n", unit->sis900u_name));
661 #endif
664 * sis900_get_mac_addr - Get MAC address for stand alone SiS900 model
665 * @unit: the net device to get address for
667 * Older SiS900 and friends, use EEPROM to store MAC address.
668 * MAC address is read from read_eeprom() into @net_dev->dev_addr.
670 static int sis900_get_mac_addr(struct net_device *unit)
672 UWORD signature;
673 int i;
675 D(bug("[%s] sis900_get_mac_addr()\n", unit->sis900u_name));
677 /* check to see if we have sane EEPROM */
678 signature = (UWORD) read_eeprom(unit->sis900u_BaseMem, EEPROMSignature);
679 if (signature == 0xffff || signature == 0x0000) {
680 D(bug("[%s]: sis900_get_mac_addr: Error EERPOM read %x\n", unit->sis900u_name, signature));
681 return 0;
684 /* get MAC address from EEPROM */
685 for (i = 0; i < 3; i++)
687 unit->sis900u_org_addr[i] = (UWORD)read_eeprom(unit->sis900u_BaseMem, i + EEPROMMACAddr);
690 return 1;
694 * sis630e_get_mac_addr - Get MAC address for SiS630E model
695 * @unit: the net device to get address for
697 * SiS630E model, use APC CMOS RAM to store MAC address.
698 * APC CMOS RAM is accessed through ISA bridge.
699 * MAC address is read into @net_dev->dev_addr.
701 static int sis630e_get_mac_addr(struct net_device *unit)
703 // struct pci_dev *isa_bridge = NULL;
704 // UBYTE reg;
705 int i;
707 D(bug("[%s] sis630e_get_mac_addr()\n", unit->sis900u_name));
709 // isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0008, isa_bridge);
710 // if (!isa_bridge)
711 // isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
712 // if (!isa_bridge) {
713 // printk(KERN_WARNING "%s: Can not find ISA bridge\n",
714 // pci_name(pci_dev));
715 // return 0;
716 // }
717 // pci_read_config_byte(isa_bridge, 0x48, &reg);
718 // pci_write_config_byte(isa_bridge, 0x48, reg | 0x40);
720 for (i = 0; i < 3; i++) {
721 BYTEOUT(0x70, 0x09 + (i * 2));
722 unit->sis900u_org_addr[i] = 0x0000 + (BYTEIN(0x71) << 8);
723 BYTEOUT(0x70, 0x09 + (i * 2) + 1);
724 unit->sis900u_org_addr[i] |= BYTEIN(0x71);
726 // pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40);
727 // pci_dev_put(isa_bridge);
729 return 1;
733 * sis635_get_mac_addr - Get MAC address for SIS635 model
734 * @unit: the net device to get address for
736 * SiS635 model, set MAC Reload Bit to load Mac address from APC
737 * to rfdr. rfdr is accessed through rfcr. MAC address is read into
738 * @net_dev->dev_addr.
740 static int sis635_get_mac_addr(struct net_device *unit)
742 long ioaddr = unit->sis900u_BaseMem;
743 ULONG rfcrSave;
744 ULONG i;
746 D(bug("[%s] sis635_get_mac_addr()\n", unit->sis900u_name));
748 rfcrSave = LONGIN(rfcr + ioaddr);
750 LONGOUT(ioaddr + cr, rfcrSave | RELOAD);
751 LONGOUT(ioaddr + cr, 0);
753 /* disable packet filtering before setting filter */
754 LONGOUT(rfcr + ioaddr, rfcrSave & ~RFEN);
756 /* load MAC addr to filter data register */
757 for (i = 0 ; i < 3 ; i++) {
758 LONGOUT(ioaddr + rfcr, i << RFADDR_shift);
759 unit->sis900u_org_addr[i] = WORDIN(ioaddr + rfdr);
762 /* enable packet filtering */
763 LONGOUT(rfcr + ioaddr, rfcrSave | RFEN);
765 return 1;
769 * sis96x_get_mac_addr - Get MAC address for SiS962 or SiS963 model
770 * @unit: the net device to get address for
772 * SiS962 or SiS963 model, use EEPROM to store MAC address. And EEPROM
773 * is shared by
774 * LAN and 1394. When access EEPROM, send EEREQ signal to hardware first
775 * and wait for EEGNT. If EEGNT is ON, EEPROM is permitted to be access
776 * by LAN, otherwise is not. After MAC address is read from EEPROM, send
777 * EEDONE signal to refuse EEPROM access by LAN.
778 * The EEPROM map of SiS962 or SiS963 is different to SiS900.
779 * The signature field in SiS962 or SiS963 spec is meaningless.
780 * MAC address is read into @net_dev->dev_addr.
782 static int sis96x_get_mac_addr(struct net_device *unit)
784 long ioaddr = unit->sis900u_BaseMem;
785 long ee_addr = ioaddr + mear;
786 ULONG waittime = 0;
787 int i;
789 D(bug("[%s] sis96x_get_mac_addr()\n", unit->sis900u_name));
791 LONGOUT(ee_addr, EEREQ);
792 while(waittime < 2000) {
793 if(LONGIN(ee_addr) & EEGNT) {
795 /* get MAC address from EEPROM */
796 for (i = 0; i < 3; i++)
797 unit->sis900u_org_addr[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
799 LONGOUT(ee_addr, EEDONE);
800 return 1;
801 } else {
802 udelay(1);
803 waittime ++;
806 LONGOUT(ee_addr, EEDONE);
807 return 0;
811 * sis900func_set_multicast: unit->set_multicast function
812 * Called with unit->xmit_lock held.
814 void sis900func_set_multicast(struct net_device *unit)
816 ULONG addr[2];
817 ULONG mask[2];
818 // ULONG pff;
820 D(bug("[%s]: sis900func_set_multicast()\n", unit->sis900u_name));
822 memset(addr, 0, sizeof(addr));
823 memset(mask, 0, sizeof(mask));
826 void sis900func_deinitialize(struct net_device *unit)
828 D(bug("[%s] sis900func_deinitialize()\n", unit->sis900u_name));
831 void sis900func_initialize(struct net_device *unit)
833 int ret;
834 // int i, config1;
836 D(bug("[%s] sis900func_initialize()\n", unit->sis900u_name));
838 ret = 0;
839 if (unit->sis900u_RevisionID == SIS630E_900_REV)
840 ret = sis630e_get_mac_addr(unit);
841 else if ((unit->sis900u_RevisionID > 0x81) && (unit->sis900u_RevisionID <= 0x90) )
842 ret = sis635_get_mac_addr(unit);
843 else if (unit->sis900u_RevisionID == SIS96x_900_REV)
844 ret = sis96x_get_mac_addr(unit);
845 else
846 ret = sis900_get_mac_addr(unit);
848 if (ret == 0) {
849 D(bug("[%s]: Cannot read MAC address.\n", unit->sis900u_name));
850 return;
853 unit->sis900u_dev_addr[0] = unit->sis900u_org_addr[0] & 0xff;
854 unit->sis900u_dev_addr[1] = (unit->sis900u_org_addr[0] >> 8) & 0xff;
856 unit->sis900u_dev_addr[2] = unit->sis900u_org_addr[1] & 0xff;
857 unit->sis900u_dev_addr[3] = (unit->sis900u_org_addr[1] >> 8) & 0xff;
859 unit->sis900u_dev_addr[4] = unit->sis900u_org_addr[2] & 0xff;
860 unit->sis900u_dev_addr[5] = (unit->sis900u_org_addr[2] >> 8) & 0xff;
862 D(bug("[%s]: MAC Address %02x:%02x:%02x:%02x:%02x:%02x\n", unit->sis900u_name,
863 unit->sis900u_dev_addr[0], unit->sis900u_dev_addr[1], unit->sis900u_dev_addr[2],
864 unit->sis900u_dev_addr[3], unit->sis900u_dev_addr[4], unit->sis900u_dev_addr[5]));
866 /* 630ET : set the mii access mode as software-mode */
867 if (unit->sis900u_RevisionID == SIS630ET_900_REV)
869 LONGOUT(unit->sis900u_BaseMem + cr, ACCESSMODE | LONGIN(unit->sis900u_BaseMem + cr));
872 /* probe for mii transceiver */
873 if (sis900_mii_probe(unit) == 0) {
874 D(bug("[%s]: Error probing MII device.\n", unit->sis900u_name));
875 return;
879 static void sis900func_drain_tx(struct net_device *unit)
881 int i;
882 for (i = 0; i < NUM_TX_DESC; i++) {
883 /* TODO: sis900func_drain_tx does nothing atm. */
887 static void sis900func_drain_rx(struct net_device *unit)
889 int i;
890 for (i = 0; i < NUM_RX_DESC; i++) {
891 /* TODO: sis900func_drain_rx does nothing atm. */
895 static void drain_ring(struct net_device *unit)
897 sis900func_drain_tx(unit);
898 sis900func_drain_rx(unit);
901 static int request_irq(struct net_device *unit)
903 D(bug("[%s]: request_irq()\n", unit->sis900u_name));
905 if (!unit->sis900u_IntsAdded)
907 AddIntServer(INTB_KERNEL + unit->sis900u_IRQ,
908 &unit->sis900u_irqhandler);
909 AddIntServer(INTB_VERTB, &unit->sis900u_touthandler);
910 unit->sis900u_IntsAdded = TRUE;
913 return 0;
916 static void free_irq(struct net_device *unit)
918 if (unit->sis900u_IntsAdded)
920 RemIntServer(INTB_KERNEL + unit->sis900u_IRQ,
921 &unit->sis900u_irqhandler);
922 RemIntServer(INTB_VERTB, &unit->sis900u_touthandler);
923 unit->sis900u_IntsAdded = FALSE;
927 void sis900func_set_mac(struct net_device *unit)
929 // int i;
931 D(bug("[%s]: sis900func_set_mac()\n", unit->sis900u_name));
933 /* BYTEOUT(base + RTLr_Cfg9346, 0xc0);
934 LONGOUT(base + RTLr_MAC0 + 0, (
935 ( unit->sis900u_dev_addr[3] << 24 ) |
936 ( unit->sis900u_dev_addr[2] << 16 ) |
937 ( unit->sis900u_dev_addr[1] << 8 ) |
938 unit->sis900u_dev_addr[0]
941 LONGOUT(base + RTLr_MAC0 + 4, (
942 ( unit->sis900u_dev_addr[5] << 8 ) |
943 unit->sis900u_dev_addr[4]
945 BYTEOUT(base + RTLr_Cfg9346, 0x00);*/
949 * sis900_reset - Reset sis900 MAC
950 * @unit: the net device to reset
952 * reset sis900 MAC and wait until finished
953 * reset through command register
954 * change backoff algorithm for 900B0 & 635 M/B
956 static void sis900_reset(struct net_device *unit)
958 long ioaddr = unit->sis900u_BaseMem;
959 int i = 0;
960 ULONG status = TxRCMP | RxRCMP;
962 D(bug("[%s]: sis900_reset()\n", unit->sis900u_name));
964 LONGOUT(ioaddr + ier, 0);
965 LONGOUT(ioaddr + imr, 0);
966 LONGOUT(ioaddr + rfcr, 0);
968 LONGOUT(ioaddr + cr, RxRESET | TxRESET | RESET | LONGIN(ioaddr + cr));
970 /* Check that the chip has finished the reset. */
971 while (status && (i++ < 1000)) {
972 status ^= (LONGIN(isr + ioaddr) & status);
975 if ( (unit->sis900u_RevisionID >= SIS635A_900_REV) || (unit->sis900u_RevisionID == SIS900B_900_REV) )
976 LONGOUT(ioaddr + cfg, PESEL | RND_CNT);
977 else
978 LONGOUT(ioaddr + cfg, PESEL);
982 * sis630_set_eq - set phy equalizer value for 630 LAN
983 * @unit: the net device to set equalizer value
984 * @revision: 630 LAN revision number
986 * 630E equalizer workaround rule(Cyrus Huang 08/15)
987 * PHY register 14h(Test)
988 * Bit 14: 0 -- Automatically dectect (default)
989 * 1 -- Manually set Equalizer filter
990 * Bit 13: 0 -- (Default)
991 * 1 -- Speed up convergence of equalizer setting
992 * Bit 9 : 0 -- (Default)
993 * 1 -- Disable Baseline Wander
994 * Bit 3~7 -- Equalizer filter setting
995 * Link ON: Set Bit 9, 13 to 1, Bit 14 to 0
996 * Then calculate equalizer value
997 * Then set equalizer value, and set Bit 14 to 1, Bit 9 to 0
998 * Link Off:Set Bit 13 to 1, Bit 14 to 0
999 * Calculate Equalizer value:
1000 * When Link is ON and Bit 14 is 0, SIS900PHY will auto-dectect proper equalizer value.
1001 * When the equalizer is stable, this value is not a fixed value. It will be within
1002 * a small range(eg. 7~9). Then we get a minimum and a maximum value(eg. min=7, max=9)
1003 * 0 <= max <= 4 --> set equalizer to max
1004 * 5 <= max <= 14 --> set equalizer to max+1 or set equalizer to max+2 if max == min
1005 * max >= 15 --> set equalizer to max+5 or set equalizer to max+6 if max == min
1007 static void sis630_set_eq(struct net_device *unit, UBYTE revision)
1009 UWORD reg14h, eq_value=0, max_value=0, min_value=0;
1010 int i, maxcount=10;
1012 D(bug("[%s]: sis630_set_eq()\n", unit->sis900u_name));
1014 if ( !(revision == SIS630E_900_REV || revision == SIS630EA1_900_REV ||
1015 revision == SIS630A_900_REV || revision == SIS630ET_900_REV) )
1017 D(bug("[%s]: sis630_set_eq: Skipping for revision %d chipset\n", unit->sis900u_name, revision));
1018 return;
1021 if (netif_carrier_ok(unit)) {
1022 reg14h = mdio_read(unit, unit->cur_phy, MII_RESV);
1023 mdio_write(unit, unit->cur_phy, MII_RESV,
1024 (0x2200 | reg14h) & 0xBFFF);
1025 for (i=0; i < maxcount; i++) {
1026 eq_value = (0x00F8 & mdio_read(unit,
1027 unit->cur_phy, MII_RESV)) >> 3;
1028 if (i == 0)
1029 max_value=min_value=eq_value;
1030 max_value = (eq_value > max_value) ?
1031 eq_value : max_value;
1032 min_value = (eq_value < min_value) ?
1033 eq_value : min_value;
1035 /* 630E rule to determine the equalizer value */
1036 if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV ||
1037 revision == SIS630ET_900_REV) {
1038 if (max_value < 5)
1039 eq_value = max_value;
1040 else if (max_value >= 5 && max_value < 15)
1041 eq_value = (max_value == min_value) ?
1042 max_value+2 : max_value+1;
1043 else if (max_value >= 15)
1044 eq_value=(max_value == min_value) ?
1045 max_value+6 : max_value+5;
1047 /* 630B0&B1 rule to determine the equalizer value */
1048 if (revision == SIS630A_900_REV &&
1049 (unit->sis900u_HostRevisionID == SIS630B0 ||
1050 unit->sis900u_HostRevisionID == SIS630B1)) {
1051 if (max_value == 0)
1052 eq_value = 3;
1053 else
1054 eq_value = (max_value + min_value + 1)/2;
1056 /* write equalizer value and setting */
1057 reg14h = mdio_read(unit, unit->cur_phy, MII_RESV);
1058 reg14h = (reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8);
1059 reg14h = (reg14h | 0x6000) & 0xFDFF;
1060 mdio_write(unit, unit->cur_phy, MII_RESV, reg14h);
1061 } else {
1062 reg14h = mdio_read(unit, unit->cur_phy, MII_RESV);
1063 if (revision == SIS630A_900_REV &&
1064 (unit->sis900u_HostRevisionID == SIS630B0 ||
1065 unit->sis900u_HostRevisionID == SIS630B1))
1066 mdio_write(unit, unit->cur_phy, MII_RESV,
1067 (reg14h | 0x2200) & 0xBFFF);
1068 else
1069 mdio_write(unit, unit->cur_phy, MII_RESV,
1070 (reg14h | 0x2000) & 0xBFFF);
1072 return;
1076 * sis900_init_rxfilter - Initialize the Rx filter
1077 * @unit: the net device to initialize for
1079 * Set receive filter address to our MAC address
1080 * and enable packet filtering.
1082 static void sis900_init_rxfilter(struct net_device *unit)
1084 long ioaddr = unit->sis900u_BaseMem;
1085 ULONG rfcrSave;
1086 ULONG i;
1088 D(bug("[%s]: sis900_init_rxfilter()\n", unit->sis900u_name));
1090 rfcrSave = LONGIN(rfcr + ioaddr);
1092 /* disable packet filtering before setting filter */
1093 LONGOUT(rfcr + ioaddr, rfcrSave & ~RFEN);
1095 /* load MAC addr to filter data register */
1096 for (i = 0 ; i < 3 ; i++) {
1097 ULONG w;
1099 w = (unit->sis900u_dev_addr[(i * 2)] << 8 ) + unit->sis900u_dev_addr[(i * 2) + 1];
1100 LONGOUT(ioaddr + rfcr, (i << RFADDR_shift));
1101 LONGOUT(ioaddr + rfdr, w);
1103 //if (netif_msg_hw(unit)) {
1104 D(bug("[%s]: sis900_init_rxfilter: Receive Filter Addrss[%d]=%x\n",unit->sis900u_name, i, LONGIN(ioaddr + rfdr)));
1108 /* enable packet filtering */
1109 LONGOUT(rfcr + ioaddr, rfcrSave | RFEN);
1113 * sis900_init_tx_ring - Initialize the Tx descriptor ring
1114 * @unit: the net device to initialize for
1116 * Initialize the Tx descriptor ring,
1118 static void sis900_init_tx_ring(struct net_device *unit)
1120 long ioaddr = unit->sis900u_BaseMem;
1121 int i, allocate = 1;
1123 D(bug("[%s]: sis900_init_tx_ring()\n", unit->sis900u_name));
1125 unit->tx_full = 0;
1126 unit->dirty_tx = unit->cur_tx = 0;
1128 for (i = 0; i < NUM_TX_DESC; i++) {
1129 APTR framebuffer = NULL;
1131 if ((allocate) && ((framebuffer = AllocMem(TX_BUF_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)) {
1132 /* not enough memory for framebuffer this makes a "hole"
1133 on the buffer ring, it is not clear how the
1134 hardware will react to this kind of degenerated
1135 buffer */
1136 allocate = 0;
1139 unit->tx_ring[i].link = (IPTR)unit->tx_ring_dma +
1140 ((i+1)%NUM_TX_DESC)*sizeof(BufferDesc);
1141 unit->tx_ring[i].cmdsts = 0;
1142 if (framebuffer)
1144 unit->tx_buffers[i] = framebuffer;
1145 unit->tx_ring[i].bufptr = (IPTR)HIDD_PCIDriver_CPUtoPCI(unit->sis900u_PCIDriver, framebuffer);
1147 D(bug("[%s]: sis900_init_tx_ring: Buffer %d @ %p\n", unit->sis900u_name, i, framebuffer));
1150 /* load Transmit Descriptor Register */
1151 LONGOUT(ioaddr + txdp, (IPTR)unit->tx_ring_dma);
1152 // if (netif_msg_hw(unit))
1153 D(bug("[%s]: sis900_init_tx_ring: TX descriptor register loaded with: %8.8x\n",unit->sis900u_name, LONGIN(ioaddr + txdp)));
1157 * sis900_init_rx_ring - Initialize the Rx descriptor ring
1158 * @unit: the net device to initialize for
1160 * Initialize the Rx descriptor ring,
1161 * and pre-allocate recevie buffers (socket buffer)
1163 static void sis900_init_rx_ring(struct net_device *unit)
1165 long ioaddr = unit->sis900u_BaseMem;
1166 int i, allocate = 1;
1168 D(bug("[%s]: sis900_init_rx_ring()\n", unit->sis900u_name));
1170 unit->cur_rx = 0;
1171 unit->dirty_rx = 0;
1173 /* init RX descriptor and allocate buffers */
1174 for (i = 0; i < NUM_RX_DESC; i++) {
1175 APTR framebuffer = NULL;
1177 if ((allocate) && ((framebuffer = AllocMem(RX_BUF_SIZE, MEMF_PUBLIC | MEMF_CLEAR)) == NULL)) {
1178 /* not enough memory for framebuffer this makes a "hole"
1179 on the buffer ring, it is not clear how the
1180 hardware will react to this kind of degenerated
1181 buffer */
1182 allocate = 0;
1184 unit->rx_ring[i].link = (IPTR)unit->rx_ring_dma +
1185 ((i+1)%NUM_RX_DESC)*sizeof(BufferDesc);
1186 unit->rx_ring[i].cmdsts = RX_BUF_SIZE;
1187 if (framebuffer)
1189 unit->rx_buffers[i] = framebuffer;
1190 unit->rx_ring[i].bufptr = (IPTR)HIDD_PCIDriver_CPUtoPCI(unit->sis900u_PCIDriver, framebuffer);
1192 D(bug("[%s]: sis900_init_rx_ring: Buffer %d @ %p\n", unit->sis900u_name, i, framebuffer));
1194 unit->dirty_rx = (unsigned int) (i - NUM_RX_DESC);
1196 /* load Receive Descriptor Register */
1197 LONGOUT(ioaddr + rxdp, (IPTR)unit->rx_ring_dma);
1198 // if (netif_msg_hw(sis_priv))
1199 D(bug("[%s]: sis900_init_rx_ring: RX descriptor register loaded with: %8.8x\n",unit->sis900u_name, LONGIN(ioaddr + rxdp)));
1204 * set_rx_mode - Set SiS900 receive mode
1205 * @unit: the net device to be set
1207 * Set SiS900 receive mode for promiscuous, multicast, or broadcast mode.
1208 * And set the appropriate multicast filter.
1209 * Multicast hash table changes from 128 to 256 bits for 635M/B & 900B0.
1211 static void set_rx_mode(struct net_device *unit)
1213 long ioaddr = unit->sis900u_BaseMem;
1214 UWORD mc_filter[16] = {0}; /* 256/128 bits multicast hash table */
1215 int i, table_entries;
1216 ULONG rx_mode;
1218 D(bug("[%s]: set_rx_mode()\n", unit->sis900u_name));
1220 /* 635 Hash Table entires = 256(2^16) */
1221 if((unit->sis900u_RevisionID >= SIS635A_900_REV) ||
1222 (unit->sis900u_RevisionID == SIS900B_900_REV))
1223 table_entries = 16;
1224 else
1225 table_entries = 8;
1227 /* TODO: Fix multicast settings */
1228 //if (unit->sis900u_ifflags & IFF_PROMISC) {
1229 // Accept any kinds of packets
1230 rx_mode = RFPromiscuous;
1231 for (i = 0; i < table_entries; i++)
1232 mc_filter[i] = 0xffff;
1233 /*} else if ((unit->mc_count > multicast_filter_limit) ||
1234 (unit->sis900u_ifflags & IFF_ALLMULTI)) {
1235 // too many multicast addresses or accept all multicast packet
1236 rx_mode = RFAAB | RFAAM;
1237 for (i = 0; i < table_entries; i++)
1238 mc_filter[i] = 0xffff;
1239 } else {
1240 // Accept Broadcast packet, destination address matchs our
1241 // MAC address, use Receive Filter to reject unwanted MCAST
1242 // packets
1243 struct dev_mc_list *mclist;
1244 rx_mode = RFAAB;
1245 for (i = 0, mclist = unit->mc_list;
1246 mclist && i < unit->mc_count;
1247 i++, mclist = mclist->next) {
1248 unsigned int bit_nr =
1249 sis900_mcast_bitnr(mclist->dmi_addr, unit->sis900u_RevisionID);
1250 mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf));
1254 /* update Multicast Hash Table in Receive Filter */
1255 for (i = 0; i < table_entries; i++) {
1256 /* why plus 0x04 ??, That makes the correct value for hash table. */
1257 LONGOUT(ioaddr + rfcr, (ULONG)(0x00000004+i) << RFADDR_shift);
1258 LONGOUT(ioaddr + rfdr, mc_filter[i]);
1261 LONGOUT(ioaddr + rfcr, RFEN | rx_mode);
1263 /* sis900 is capable of looping back packets at MAC level for
1264 * debugging purpose */
1265 if (unit->sis900u_ifflags & IFF_LOOPBACK) {
1266 ULONG cr_saved;
1267 /* We must disable Tx/Rx before setting loopback mode */
1268 cr_saved = LONGIN(ioaddr + cr);
1269 LONGOUT(ioaddr + cr, cr_saved | TxDIS | RxDIS);
1270 /* enable loopback */
1271 LONGOUT(ioaddr + txcfg, LONGIN(ioaddr + txcfg) | TxMLB);
1272 LONGOUT(ioaddr + rxcfg, LONGIN(ioaddr + rxcfg) | RxATX);
1273 /* restore cr */
1274 LONGOUT(ioaddr + cr, cr_saved);
1277 return;
1281 * sis900_set_mode - Set the media mode of mac register.
1282 * @ioaddr: the address of the device
1283 * @speed : the transmit speed to be determined
1284 * @duplex: the duplex mode to be determined
1286 * Set the media mode of mac register txcfg/rxcfg according to
1287 * speed and duplex of phy. Bit EDB_MASTER_EN indicates the EDB
1288 * bus is used instead of PCI bus. When this bit is set 1, the
1289 * Max DMA Burst Size for TX/RX DMA should be no larger than 16
1290 * double words.
1292 static void sis900_set_mode(long ioaddr, int speed, int duplex)
1294 ULONG tx_flags = 0, rx_flags = 0;
1296 //D(bug("[%s]: sis900_set_mode()\n", unit->sis900u_name));
1298 if (LONGIN(ioaddr + cfg) & EDB_MASTER_EN) {
1299 tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) |
1300 (TX_FILL_THRESH << TxFILLT_shift);
1301 rx_flags = DMA_BURST_64 << RxMXDMA_shift;
1302 } else {
1303 tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) |
1304 (TX_FILL_THRESH << TxFILLT_shift);
1305 rx_flags = DMA_BURST_512 << RxMXDMA_shift;
1308 if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
1309 rx_flags |= (RxDRNT_10 << RxDRNT_shift);
1310 tx_flags |= (TxDRNT_10 << TxDRNT_shift);
1311 } else {
1312 rx_flags |= (RxDRNT_100 << RxDRNT_shift);
1313 tx_flags |= (TxDRNT_100 << TxDRNT_shift);
1316 if (duplex == FDX_CAPABLE_FULL_SELECTED) {
1317 tx_flags |= (TxCSI | TxHBI);
1318 rx_flags |= RxATX;
1321 LONGOUT(ioaddr + txcfg, tx_flags);
1322 LONGOUT(ioaddr + rxcfg, rx_flags);
1326 * sis900_check_mode - check the media mode for sis900
1327 * @unit: the net device to be checked
1328 * @mii_phy: the mii phy
1330 * Older driver gets the media mode from mii status output
1331 * register. Now we set our media capability and auto-negotiate
1332 * to get the upper bound of speed and duplex between two ends.
1333 * If the types of mii phy is HOME, it doesn't need to auto-negotiate
1334 * and autong_complete should be set to 1.
1336 static void sis900_check_mode(struct net_device *unit, struct mii_phy *mii_phy)
1338 long ioaddr = unit->sis900u_BaseMem;
1339 int speed, duplex;
1341 D(bug("[%s]: sis900_check_mode()\n", unit->sis900u_name));
1343 if (mii_phy->phy_types == LAN) {
1344 LONGOUT(ioaddr + cfg, ~EXD & LONGIN(ioaddr + cfg));
1345 sis900_set_capability(unit, mii_phy);
1346 sis900_auto_negotiate(unit, unit->cur_phy);
1347 } else {
1348 LONGOUT(ioaddr + cfg, EXD | LONGIN(ioaddr + cfg));
1349 speed = HW_SPEED_HOME;
1350 duplex = FDX_CAPABLE_HALF_SELECTED;
1351 sis900_set_mode(ioaddr, speed, duplex);
1352 unit->autong_complete = 1;
1356 int sis900func_open(struct net_device *unit)
1358 int ret;
1359 // int i, rx_buf_len_idx;
1361 D(bug("[%s]: sis900func_open()\n", unit->sis900u_name));
1363 /* Soft reset the chip. */
1364 sis900_reset(unit);
1366 /* Equalizer workaround Rule */
1367 sis630_set_eq(unit, unit->sis900u_RevisionID);
1369 ret = request_irq(unit);
1370 if (ret)
1371 goto out_drain;
1373 sis900_init_rxfilter(unit);
1375 sis900_init_tx_ring(unit);
1376 sis900_init_rx_ring(unit);
1378 set_rx_mode(unit);
1380 // netif_start_queue(unit);
1382 /* Workaround for EDB */
1383 sis900_set_mode(unit->sis900u_BaseMem, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
1385 D(bug("[%s]: sis900func_open: Enabling NIC's interupts .. \n", unit->sis900u_name));
1386 /* Enable all known interrupts by setting the interrupt mask. */
1387 LONGOUT(unit->sis900u_BaseMem + imr, (RxSOVR|RxORN|RxERR|RxOK|TxURN|TxERR|TxIDLE));
1388 LONGOUT(unit->sis900u_BaseMem + cr, RxENA | LONGIN(unit->sis900u_BaseMem + cr));
1389 LONGOUT(unit->sis900u_BaseMem + ier, IE);
1391 sis900_check_mode(unit, unit->mii);
1393 unit->sis900u_ifflags |= IFF_UP;
1394 ReportEvents(LIBBASE, unit, S2EVENT_ONLINE);
1395 D(bug("[%s]: sis900func_open: Device set as ONLINE\n",unit->sis900u_name));
1397 return 0;
1399 out_drain:
1400 drain_ring(unit);
1401 return ret;
1404 int sis900func_close(struct net_device *unit)
1406 // UBYTE *base;
1408 D(bug("[%s]: sis900func_close()\n", unit->sis900u_name));
1410 unit->sis900u_ifflags &= ~IFF_UP;
1412 // ObtainSemaphore(&np->lock);
1413 // np->in_shutdown = 1;
1414 // ReleaseSemaphore(&np->lock);
1416 // unit->sis900u_toutNEED = FALSE;
1418 netif_stop_queue(unit);
1419 // ObtainSemaphore(&np->lock);
1421 sis900func_deinitialize(unit); // Stop the chipset and set it in 16bit-mode
1423 // base = get_hwbase(unit);
1425 // ReleaseSemaphore(&np->lock);
1427 free_irq(unit);
1429 drain_ring(unit);
1431 // HIDD_PCIDriver_FreePCIMem(unit->sis900u_PCIDriver, np->rx_buffer);
1432 // HIDD_PCIDriver_FreePCIMem(unit->sis900u_PCIDriver, np->tx_buffer);
1434 ReportEvents(LIBBASE, unit, S2EVENT_OFFLINE);
1436 return 0;