patch-2.2.12 linux/drivers/net/sis900.c
Next file: linux/drivers/pci/oldproc.c
Previous file: linux/drivers/net/sb1000.c
Back to the patch index
Back to the overall index
- Lines: 793
- Date:
Wed Aug 25 17:29:48 1999
- Orig file:
v2.2.11/linux/drivers/net/sis900.c
- Orig date:
Mon Aug 9 16:05:56 1999
diff -u --recursive --new-file v2.2.11/linux/drivers/net/sis900.c linux/drivers/net/sis900.c
@@ -33,6 +33,8 @@
static int multicast_filter_limit = 128;
#define MAX_UNITS 8 /* More are supported, limit only on options */
+static int speeds[MAX_UNITS] = {100, 100, 100, 100, 100, 100, 100, 100};
+static int full_duplex[MAX_UNITS] = {1, 1, 1, 1, 1, 1, 1, 1};
#define TX_BUF_SIZE 1536
#define RX_BUF_SIZE 1536
@@ -41,9 +43,9 @@
#define RX_DMA_BURST 0
#define TX_FIFO_THRESH 16
#define TxDRNT_100 (1536>>5)
-#define TxDRNT_10 16 //(1536>>5)
+#define TxDRNT_10 16
#define RxDRNT_100 8
-#define RxDRNT_10 8 //(1536>>5)
+#define RxDRNT_10 8
#define TRUE 1
#define FALSE 0
@@ -387,21 +389,23 @@
EuphLiteDesc rx_buf[NUM_RX_DESC];
unsigned char *rx_bufs;
unsigned char *tx_bufs; /* Tx bounce buffer region. */
- char phys[4]; /* MII device addresses. */
- int phy_idx;
+ char phys[4]; /* MII device addresses. */
+ int phy_idx; /* Support Max 4 PHY */
u16 pmd_status;
- unsigned int tx_full; /* The Tx queue is full. */
- u16 full_duplex; /* FullHalf-duplex. */
- u16 hunmbps; /* 10010 Mbps. */
+ unsigned int tx_full; /* The Tx queue is full. */
+ int MediaSpeed; /* user force speed */
+ int MediaDuplex; /* user force duplex */
+ int full_duplex; /* Full/Half-duplex. */
+ int speeds; /* 100/10 Mbps. */
u16 LinkOn;
u16 LinkChange;
};
#ifdef MODULE
#if LINUX_VERSION_CODE > 0x20115
-MODULE_AUTHOR("Silicon Integrated Systems Corporation");
+MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>");
MODULE_DESCRIPTION("SiS 900 PCI Fast Ethernet driver");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(speeds, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
MODULE_PARM(multicast_filter_limit, "i");
MODULE_PARM(max_interrupt_work, "i");
@@ -425,6 +429,7 @@
static void set_rx_mode(struct device *dev);
static void sis900_reset(struct device *dev);
static u16 elAutoNegotiate(struct device *dev, int phy_id, int *duplex, int *speed);
+static void elSetCapability(struct device *dev, int phy_id, int duplex, int speed);
static u16 elPMDreadMode(struct device *dev, int phy_id, int *speed, int *duplex);
static u16 elMIIpollBit(struct device *dev, int phy_id, int location, u16 mask, u16 polarity, u16 *value);
static void elSetMediaType(struct device *dev, int speed, int duplex);
@@ -544,14 +549,18 @@
{
static int did_version = 0; /* Already printed version info. */
struct sis900_private *tp;
- int duplex=0;
- int speed=0;
- int i;
+ u16 status;
+ int duplex = found_cnt < MAX_UNITS ? full_duplex[found_cnt] : 0 ;
+ int speed = found_cnt < MAX_UNITS ? speeds[found_cnt] : 0 ;
+ int phy=0, phy_idx=0, i;
if (did_version++ == 0)
printk(KERN_INFO "%s", version);
dev = init_etherdev(dev, 0);
+
+ if(dev==NULL)
+ return NULL;
printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ",
dev->name, pci_tbl[chip_idx].name, ioaddr, irq);
@@ -574,6 +583,11 @@
/* Some data structures must be quadword aligned. */
tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
+ if(tp==NULL)
+ {
+ releaseregion(ioaddr, pci_tbl[chip_idx].io_size);
+ return NULL;
+ }
memset(tp, 0, sizeof(*tp));
dev->priv = tp;
@@ -588,25 +602,11 @@
Doing this in open() would allow detecting external xcvrs later, but
takes too much time. */
if (sis_cap_tbl[chip_idx] & HAS_MII_XCVR) {
- int phy, phy_idx;
for (phy = 0, phy_idx = 0;
phy < 32 && phy_idx < sizeof(tp->phys); phy++)
{
- int mii_status = mdio_read(dev, phy, MII_STATUS);
- /*
- {
- int p;
- int l;
- for (p = 0 ; p < 4 ; p ++) {
- for (l=0 ; l<16 ; l++) {
- int status = mdio_read(dev, phy, l);
- status = mdio_read(dev, phy, l);
- printk(KERN_INFO "MII info addr[%d][%d]=%x\n",
- p, l, status);
- }
- }
- }
- */
+ int mii_status ;
+ mii_status = mdio_read(dev, phy, MII_STATUS);
if (mii_status != 0xffff && mii_status != 0x0000) {
tp->phy_idx = phy_idx;
@@ -620,45 +620,85 @@
}
if (phy_idx == 0) {
- printk(KERN_INFO "%s: No MII transceivers found!",
+ printk(KERN_INFO "%s: No MII transceivers found!\n",
dev->name);
- printk(KERN_INFO "Assuming SYM transceiver.\n");
tp->phys[0] = -1;
+ tp->pmd_status = 0;
}
} else {
- tp->phys[0] = 32;
+ tp->phys[0] = -1;
+ tp->pmd_status = 0;
}
- if (tp->pmd_status > 0) {
- tp->pmd_status=
- elAutoNegotiate(dev, tp->phys[tp->phy_idx], &duplex, &speed);
- if (tp->pmd_status & MIISTAT_LINK) {
- if (duplex == FDX_CAPABLE_FULL_SELECTED)
- tp->full_duplex=1;
- if (speed == HW_SPEED_100_MBPS)
- tp->hunmbps=1;
- tp->LinkOn = TRUE;
- } else {
+ if ((tp->pmd_status > 0) && (phy_idx > 0)) {
+ if (sis900_debug > 1) {
+ printk(KERN_INFO "duplex=%d, speed=%d\n",
+ duplex, speed);
+ }
+ if (!duplex && !speed) {
+ // auto-config media type
+ // Set full capability
+ if (sis900_debug > 1) {
+ printk(KERN_INFO "Auto Config ...\n");
+ }
+ elSetCapability(dev, tp->phys[tp->phy_idx], 1, 100);
+ tp->pmd_status=elAutoNegotiate(dev,
+ tp->phys[tp->phy_idx],
+ &tp->full_duplex,
+ &tp->speeds);
+ } else {
+ tp->MediaSpeed = speed;
+ tp->MediaDuplex = duplex;
+ elSetCapability(dev, tp->phys[tp->phy_idx],
+ duplex, speed);
+ elAutoNegotiate(dev, tp->phys[tp->phy_idx],
+ &tp->full_duplex,
+ &tp->speeds);
+ status = mdio_read(dev, phy, MII_ANLPAR);
+ if ( !(status & (MII_NWAY_T | MII_NWAY_T_FDX |
+ MII_NWAY_TX | MII_NWAY_TX_FDX )))
+ {
+ u16 cmd=0;
+ cmd |= ( speed == 100 ?
+ MIICNTL_SPEED : 0 );
+ cmd |= ( duplex ? MIICNTL_FDX : 0 );
+ mdio_write(dev, phy, MII_CONTROL, cmd);
+ elSetMediaType(dev, speed==100 ?
+ HW_SPEED_100_MBPS :
+ HW_SPEED_10_MBPS,
+ duplex ?
+ FDX_CAPABLE_FULL_SELECTED:
+ FDX_CAPABLE_HALF_SELECTED);
+ elMIIpollBit(dev, phy, MII_STATUS,
+ MIISTAT_LINK, TRUE, &status);
+ } else {
+ status = mdio_read(dev, phy, MII_STATUS);
+ }
+ }
+
+ if (tp->pmd_status & MIISTAT_LINK)
+ tp->LinkOn = TRUE;
+ else
tp->LinkOn = FALSE;
- }
- tp->LinkChange = FALSE;
- }
-
- /*
- if (found_cnt < MAX_UNITS && full_duplex[found_cnt] > 0)
- tp->full_duplex = full_duplex[found_cnt];
- if (tp->full_duplex) {
- printk(KERN_INFO "%s: Media type is Full Duplex.\n", dev->name);
- } else {
- printk(KERN_INFO "%s: Media type is Half Duplex.\n", dev->name);
- }
- if (tp->hunmbps) {
- printk(KERN_INFO "%s: Speed is 100mbps.\n", dev->name);
- } else {
- printk(KERN_INFO "%s: Speed is 10mbps.\n", dev->name);
+ tp->LinkChange = FALSE;
+
}
- */
+
+ if (sis900_debug > 1) {
+ if (tp->full_duplex == FDX_CAPABLE_FULL_SELECTED) {
+ printk(KERN_INFO "%s: Media type is Full Duplex.\n",
+ dev->name);
+ } else {
+ printk(KERN_INFO "%s: Media type is Half Duplex.\n",
+ dev->name);
+ }
+ if (tp->speeds == HW_SPEED_100_MBPS) {
+ printk(KERN_INFO "%s: Speed is 100mbps.\n", dev->name);
+ } else {
+ printk(KERN_INFO "%s: Speed is 10mbps.\n", dev->name);
+ }
+ }
/* The SiS900-specific entries in the device structure. */
dev->open = &sis900_open;
@@ -857,16 +897,23 @@
return -EAGAIN;
}
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
tp->tx_bufs = kmalloc(TX_BUF_SIZE * NUM_TX_DESC, GFP_KERNEL);
tp->rx_bufs = kmalloc(RX_BUF_SIZE * NUM_RX_DESC, GFP_KERNEL);
if (tp->tx_bufs == NULL || tp->rx_bufs == NULL) {
if (tp->tx_bufs)
kfree(tp->tx_bufs);
- if (sis900_debug > 0)
- printk(KERN_ERR "%s: Couldn't allocate a %d byte receive ring.\n",
+ if (tp->rx_bufs)
+ kfree(tp->rx_bufs);
+ if (!tp->tx_bufs) {
+ printk(KERN_ERR "%s: Can't allocate a %d byte TX Bufs.\n",
dev->name, TX_BUF_SIZE * NUM_TX_DESC);
+ }
+ if (!tp->rx_bufs) {
+ printk(KERN_ERR "%s: Can't allocate a %d byte RX Bufs.\n",
+ dev->name, RX_BUF_SIZE * NUM_RX_DESC);
+ }
return -ENOMEM;
}
@@ -886,15 +933,6 @@
i, inl(ioaddr + rfdr));
}
}
- /*
- for (i=0 ; i<3 ; i++) {
- outl((((u32) i) << RFEP_shift), ioaddr + rfcr);
- if (sis900_debug > 4) {
- printk(KERN_INFO "Read Filter Addr[%d]=%x\n",
- i, inl(ioaddr + rfdr));
- }
- }
- */
outl(rfcrSave, rfcr);
}
@@ -919,31 +957,28 @@
/* Must enable Tx/Rx before setting transfer thresholds! */
/*
- #define TX_DMA_BURST 0
- #define RX_DMA_BURST 0
- #define TX_FIFO_THRESH 16
- #define TxDRNT_100 (1536>>5)
- #define TxDRNT_10 (1536>>5)
- #define RxDRNT_100 (1536>>5)
- #define RxDRNT_10 (1536>>5)
- */
- //outl(RxENA | TxENA, ioaddr + cr);
+ * #define TX_DMA_BURST 0
+ * #define RX_DMA_BURST 0
+ * #define TX_FIFO_THRESH 16
+ * #define TxDRNT_100 (1536>>5)
+ * #define TxDRNT_10 (1536>>5)
+ * #define RxDRNT_100 (1536>>5)
+ * #define RxDRNT_10 (1536>>5)
+ */
outl((RX_DMA_BURST<<20) | (RxDRNT_10 << 1), ioaddr+rxcfg);
outl(TxATP | (TX_DMA_BURST << 20) | (TX_FIFO_THRESH<<8) | TxDRNT_10,
ioaddr + txcfg);
- //tp->full_duplex = tp->duplex_lock;
- if (tp->phys[tp->phy_idx] >= 0 ||
- (sis_cap_tbl[tp->chip_id] & HAS_MII_XCVR)) {
- if (sis900_debug > 1)
- if (tp->LinkOn) {
- printk(KERN_INFO"%s: Setting %s%s-duplex.\n",
+ if (sis900_debug > 1)
+ if (tp->LinkOn) {
+ printk(KERN_INFO"%s: Media Type %s%s-duplex.\n",
dev->name,
- tp->hunmbps ? "100mbps " : "10mbps ",
- tp->full_duplex ? "full" : "half");
- } else {
- printk(KERN_INFO"%s: Media Link Off\n", dev->name);
- }
- }
+ tp->speeds==HW_SPEED_100_MBPS ?
+ "100mbps " : "10mbps ",
+ tp->full_duplex== FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ } else {
+ printk(KERN_INFO"%s: Media Link Off\n", dev->name);
+ }
set_rx_mode(dev);
dev->tbusy = 0;
@@ -955,7 +990,7 @@
outl(RxENA, ioaddr + cr);
outl(IE, ioaddr + ier);
- if (sis900_debug > 1)
+ if (sis900_debug > 3)
printk(KERN_INFO "%s: sis900_open() ioaddr %#lx IRQ %d \n",
dev->name, ioaddr, dev->irq);
@@ -974,81 +1009,31 @@
{
struct device *dev = (struct device *)data;
struct sis900_private *tp = (struct sis900_private *)dev->priv;
- long ioaddr = dev->base_addr;
int next_tick = 0;
- int duplex, full_duplex=0;
- int speed, hunmbps=0;
u16 status;
-// printk(KERN_INFO "%s: SiS900 timer\n", dev->name);
- elMIIpollBit(dev, tp->phys[tp->phy_idx], MII_STATUS, MIISTAT_LINK, TRUE, &status);
- if (status & MIISTAT_LINK) {
-// printk(KERN_INFO "%s: SiS900 timer link\n", dev->name);
- /*
- if (!tp->LinkOn) {
- printk(KERN_INFO "%s: AutoNegotiate ...\n", dev->name);
- tp->LinkChange=TRUE;
- tp->pmd_status=
- elAutoNegotiate(dev, tp->phys[tp->phy_idx],
- &duplex, &speed);
- }
- else {
- printk(KERN_INFO "%s: Link Still On.\n", dev->name);
- elPMDreadMode(dev, tp->phys[tp->phy_idx],
- &speed, &duplex);
- }
- */
- elPMDreadMode(dev, tp->phys[tp->phy_idx],
- &speed, &duplex);
-
-
- if (duplex == FDX_CAPABLE_FULL_SELECTED) full_duplex=1;
- if (speed == HW_SPEED_100_MBPS) hunmbps=1;
- if (full_duplex != tp->full_duplex || hunmbps != tp->hunmbps)
- tp->LinkChange = TRUE;
- if (tp->LinkChange) {
- tp->full_duplex=full_duplex;
- tp->hunmbps=hunmbps;
- //elSetMediaType(dev, speed, duplex);
- printk(KERN_INFO "%s: Setting %s%s-duplex based on MII "
- "#%d link partner ability.\n",
+ if (!tp->LinkOn) {
+ status = mdio_read(dev, tp->phys[tp->phy_idx], MII_STATUS);
+ if (status & MIISTAT_LINK) {
+ elPMDreadMode(dev, tp->phys[tp->phy_idx],
+ &tp->speeds, &tp->full_duplex);
+ tp->LinkOn = TRUE;
+ printk(KERN_INFO "%s: Media Link On %s%s-duplex ",
dev->name,
- tp->hunmbps ? "100mbps " : "10mbps ",
- tp->full_duplex ? "full" : "half",
- tp->phys[0]);
- }
- tp->LinkOn=TRUE;
- tp->LinkChange = FALSE;
- } else {
- if (tp->LinkOn) {
- tp->LinkChange = TRUE;
- tp->pmd_status=
- elAutoNegotiate(dev, tp->phys[tp->phy_idx],
- &duplex, &speed);
- if (tp->pmd_status & MIISTAT_LINK) {
- if (duplex == FDX_CAPABLE_FULL_SELECTED)
- tp->full_duplex=1;
- if (speed == HW_SPEED_100_MBPS)
- tp->hunmbps=1;
- } else {
- tp->LinkOn = FALSE;
- printk(KERN_INFO "%s: Link Off\n", dev->name);
- }
- }
-// printk(KERN_INFO "%s: Link Off\n", dev->name);
+ tp->speeds == HW_SPEED_100_MBPS ?
+ "100mbps " : "10mbps ",
+ tp->full_duplex==FDX_CAPABLE_FULL_SELECTED ?
+ "full" : "half");
+ }
+ } else { // previous link on
+ status = mdio_read(dev, tp->phys[tp->phy_idx], MII_STATUS);
+ if (!(status & MIISTAT_LINK)) {
+ tp->LinkOn = FALSE;
+ printk(KERN_INFO "%s: Media Link Off\n", dev->name);
+ }
}
next_tick = 2*HZ;
- if (sis900_debug > 3) {
- printk(KERN_INFO "%s: Other registers are IntMask "
- "%4.4x IntStatus %4.4x"
- " RxStatus %4.4x.\n",
- dev->name,
- inw(ioaddr + imr),
- inw(ioaddr + isr),
- inl(ioaddr + rxcfg));
- }
-
if (next_tick) {
tp->timer.expires = RUN_AT(next_tick);
add_timer(&tp->timer);
@@ -1067,24 +1052,28 @@
/* Disable interrupts by clearing the interrupt mask. */
outl(0x0000, ioaddr + imr);
+
/* Emit info to figure out what went wrong. */
- printk(KERN_INFO "%s: Tx queue start entry %d dirty entry %d.\n",
- dev->name, tp->cur_tx, tp->dirty_tx);
- for (i = 0; i < NUM_TX_DESC; i++)
- printk(KERN_INFO "%s: Tx descriptor %d is %8.8x.%s\n",
- dev->name, i, (unsigned int)&tp->tx_buf[i],
- i == tp->dirty_tx % NUM_TX_DESC ?
- " (queue head)" : "");
- /*
- printk(KERN_DEBUG"%s: MII #%d registers are:", dev->name, tp->phys[0]);
- for (mii_reg = 0; mii_reg < 8; mii_reg++)
- printk(" %4.4x", mdio_read(dev, tp->phys[0], mii_reg));
- printk(".\n");
- */
+ if (sis900_debug > 1) {
+ printk(KERN_INFO "%s:Tx queue start entry %d dirty entry %d.\n",
+ dev->name, tp->cur_tx, tp->dirty_tx);
+ for (i = 0; i < NUM_TX_DESC; i++)
+ printk(KERN_INFO "%s: Tx descriptor %d is %8.8x.%s\n",
+ dev->name, i, (unsigned int)&tp->tx_buf[i],
+ i == tp->dirty_tx % NUM_TX_DESC ?
+ " (queue head)" : "");
+ }
/* Soft reset the chip. */
+ //outb(RESET, ioaddr + cr);
+ /* Check that the chip has finished the reset. */
+ /*
+ for (i = 1000; i > 0; i--)
+ if ((inb(ioaddr + cr) & RESET) == 0)
+ break;
+ */
- tp->cur_rx = 0; //??????
+ tp->cur_rx = 0;
/* Must enable Tx/Rx before setting transfer thresholds! */
/*
set_rx_mode(dev);
@@ -1145,10 +1134,6 @@
tp->tx_buf[i].buf = &tp->tx_bufs[i*TX_BUF_SIZE];
tp->tx_buf[i].bufPhys =
virt_to_bus(&tp->tx_bufs[i*TX_BUF_SIZE]);
- /*
- printk(KERN_INFO "tp->tx_buf[%d].bufPhys=%8.8x\n",
- i, tp->tx_buf[i].bufPhys);
- */
}
/* Tx Descriptor */
@@ -1161,11 +1146,6 @@
tp->tx_buf[i].physAddr=
virt_to_bus(&(tp->tx_buf[i].plink));
tp->tx_buf[i].cmdsts=0;
-
- /*
- printk(KERN_INFO "tp->tx_buf[%d].PhysAddr=%8.8x\n",
- i, tp->tx_buf[i].physAddr);
- */
}
/* Rx Buffer */
@@ -1173,10 +1153,6 @@
tp->rx_buf[i].buf = &tp->rx_bufs[i*RX_BUF_SIZE];
tp->rx_buf[i].bufPhys =
virt_to_bus(&tp->rx_bufs[i*RX_BUF_SIZE]);
- /*
- printk(KERN_INFO "tp->rx_buf[%d].bufPhys=%8.8x\n",
- i, tp->rx_buf[i].bufPhys);
- */
}
/* Rx Descriptor */
@@ -1189,10 +1165,6 @@
tp->rx_buf[i].physAddr=
virt_to_bus(&(tp->rx_buf[i].plink));
tp->rx_buf[i].cmdsts=RX_BUF_SIZE;
- /*
- printk(KERN_INFO "tp->tx_buf[%d].PhysAddr=%8.8x\n",
- i, tp->tx_buf[i].physAddr);
- */
}
}
@@ -1234,6 +1206,7 @@
tp->tx_buf[entry].cmdsts=(OWN | skb->len);
+ //tp->tx_buf[entry].plink = 0;
outl(TxENA, ioaddr + cr);
if (++tp->cur_tx - tp->dirty_tx < NUM_TX_DESC) {/* Typical path */
clear_bit(0, (void*)&dev->tbusy);
@@ -1347,11 +1320,6 @@
tp->stats.tx_errors++;
if (txstatus & ABORT) {
tp->stats.tx_aborted_errors++;
- /*
- outl((TX_DMA_BURST<<8)|
- 0x03000001,
- ioaddr + TxConfig);
- */
}
if (txstatus & NOCARRIER)
tp->stats.tx_carrier_errors++;
@@ -1366,27 +1334,21 @@
/* No count for tp->stats.tx_deferred */
#endif
if (txstatus & UNDERRUN) {
- if (sis900_debug > 1)
+ if (sis900_debug > 2)
printk(KERN_INFO "Tx UnderRun\n");
- /* Add 64 to the Tx FIFO threshold. */
- /*
- if (tp->tx_flag < 0x00300000)
- tp->tx_flag+=0x00020000;
- tp->stats.tx_fifo_errors++;
- */
}
tp->stats.collisions +=
(txstatus >> 16) & 0xF;
#if LINUX_VERSION_CODE > 0x20119
tp->stats.tx_bytes += txstatus & DSIZE;
#endif
- if (sis900_debug > 1)
+ if (sis900_debug > 2)
printk(KERN_INFO "Tx Transmit OK\n");
tp->stats.tx_packets++;
}
/* Free the original skb. */
- if (sis900_debug > 1)
+ if (sis900_debug > 2)
printk(KERN_INFO "Free original skb\n");
dev_free_skb(tp->tx_skbuff[entry]);
tp->tx_skbuff[entry] = 0;
@@ -1404,15 +1366,16 @@
if (tp->tx_full && dirty_tx > tp->cur_tx-NUM_TX_DESC) {
/* The ring is no longer full, clear tbusy. */
- //printk(KERN_INFO "Tx Ring NO LONGER Full\n");
+ if (sis900_debug > 3)
+ printk(KERN_INFO "Tx Ring NO LONGER Full\n");
tp->tx_full = 0;
dev->tbusy = 0;
mark_bh(NET_BH);
}
tp->dirty_tx = dirty_tx;
- if (sis900_debug > 1)
- printk(KERN_INFO "TxOK release, tp->cur_tx:%d, tp->dirty:%d\n",
+ if (sis900_debug > 2)
+ printk(KERN_INFO "TxOK,tp->cur_tx:%d,tp->dirty:%d\n",
tp->cur_tx, tp->dirty_tx);
} // if (TxOK | TxERR)
@@ -1424,25 +1387,18 @@
if (status == 0xffffffff)
break;
-
if (status & (RxORN | RxERR))
tp->stats.rx_errors++;
+
if (status & RxORN) {
tp->stats.rx_over_errors++;
- /*
- tp->cur_rx =
- inw(ioaddr + RxBufAddr) % RX_BUF_LEN;
- outw(tp->cur_rx - 16, ioaddr + RxBufPtr);
- */
}
}
if (--boguscnt < 0) {
printk(KERN_INFO "%s: Too much work at interrupt, "
"IntrStatus=0x%4.4x.\n",
dev->name, status);
- /* Clear all interrupt sources. */
- //outw(0xffff, ioaddr + IntrStatus);
break;
}
} while (1);
@@ -1478,7 +1434,6 @@
int rx_size = rx_status & DSIZE;
rx_size -= CRC_SIZE;
- //printk(KERN_INFO "Rx OWN\n");
if (sis900_debug > 4) {
int i;
printk(KERN_INFO "%s: sis900_rx, rx status %8.8x,"
@@ -1510,21 +1465,11 @@
if (rx_status & (RUNT | TOOLONG))
tp->stats.rx_length_errors++;
if (rx_status & CRCERR) tp->stats.rx_crc_errors++;
- /* Reset the receiver,
- based on RealTek recommendation. (Bug?) */
- /*
- tp->cur_rx = 0;
- outl(TxENA, ioaddr + cr);
- outl(CmdRxEnb | CmdTxEnb, ioaddr + ChipCmd);
- outl((RX_FIFO_THRESH << 13) | (RX_BUF_LEN_IDX << 11) |
- (RX_DMA_BURST<<8), ioaddr + RxConfig);
- */
} else {
/* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */
struct sk_buff *skb;
- //printk(KERN_INFO "Rx OK\n");
skb = dev_alloc_skb(rx_size + 2);
if (skb == NULL) {
printk(KERN_INFO "%s: Memory squeeze,"
@@ -1556,7 +1501,6 @@
memset(rx_bufs, 0xcc, 16);
}
*/
- //printk(KERN_INFO "Frame Wrap....\n");
} else {
#if 0 /* USE_IP_COPYSUM */
eth_copy_and_sum(skb,
@@ -1578,7 +1522,6 @@
cur_rx = ((cur_rx+1) % NUM_RX_DESC);
rx_status = tp->rx_buf[cur_rx].cmdsts;
- //outw(cur_rx - 16, ioaddr + RxBufPtr);
} // while
if (sis900_debug > 4)
printk(KERN_INFO "%s: Done sis900_rx(), current %4.4x "
@@ -1635,7 +1578,7 @@
switch(cmd) {
case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */
- data[0] = tp->phys[0] & 0x3f;
+ data[0] = tp->phys[tp->phy_idx];
/* Fall Through */
case SIOCDEVPRIVATE+1: /* Read the specified MII register. */
data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
@@ -1654,6 +1597,7 @@
sis900_get_stats(struct device *dev)
{
struct sis900_private *tp = (struct sis900_private *)dev->priv;
+
return &tp->stats;
}
@@ -1709,16 +1653,26 @@
int *speed,
int *duplex)
{
- u16 status;
+ u16 status, OurCap;
*speed = HW_SPEED_10_MBPS;
*duplex = FDX_CAPABLE_HALF_SELECTED;
status = mdio_read(dev, phy_id, MII_ANLPAR);
+ OurCap = mdio_read(dev, phy_id, MII_ANAR);
+ if (sis900_debug > 1) {
+ printk(KERN_INFO "Link Part Status %4X\n", status);
+ printk(KERN_INFO "Our Status %4X\n", OurCap);
+ printk(KERN_INFO "Status Reg %4X\n",
+ mdio_read(dev, phy_id, MII_STATUS));
+ }
+ status &= OurCap;
if ( !( status &
(MII_NWAY_T|MII_NWAY_T_FDX | MII_NWAY_TX | MII_NWAY_TX_FDX ))) {
-// printk(KERN_INFO "%s: Link Partner not detected.\n", dev->name);
+ if (sis900_debug > 1) {
+ printk(KERN_INFO "The other end NOT support NWAY...\n");
+ }
while (( status = mdio_read(dev, phy_id, 18)) & 0x4000) ;
while (( status = mdio_read(dev, phy_id, 18)) & 0x0020) ;
if (status & 0x80)
@@ -1734,7 +1688,10 @@
"full" : "half");
}
} else {
-// printk(KERN_INFO "%s: Link Partner detected\n", dev->name);
+ if (sis900_debug > 1) {
+ printk(KERN_INFO "The other end support NWAY...\n");
+ }
+
if (status & (MII_NWAY_TX_FDX | MII_NWAY_T_FDX)) {
*duplex = FDX_CAPABLE_FULL_SELECTED;
}
@@ -1756,19 +1713,56 @@
static u16 elAutoNegotiate(struct device *dev, int phy_id, int *duplex, int *speed)
{
- u16 status;
+ u16 status, retnVal;
+ if (sis900_debug > 1) {
+ printk(KERN_INFO "AutoNegotiate...\n");
+ }
mdio_write(dev, phy_id, MII_CONTROL, 0);
- mdio_write(dev, phy_id, MII_CONTROL, MIICNTL_AUTO |
- MIICNTL_RST_AUTO);
- elMIIpollBit(dev, phy_id, MII_CONTROL, MIICNTL_RST_AUTO, FALSE,&status);
- elMIIpollBit(dev, phy_id, MII_STATUS, MIISTAT_AUTO_DONE, TRUE, &status);
- elMIIpollBit(dev, phy_id, MII_STATUS, MIISTAT_LINK, TRUE, &status);
+ mdio_write(dev, phy_id, MII_CONTROL, MIICNTL_AUTO | MIICNTL_RST_AUTO);
+ retnVal = elMIIpollBit(dev, phy_id, MII_CONTROL, MIICNTL_RST_AUTO,
+ FALSE,&status);
+ if (!retnVal) {
+ printk(KERN_INFO "Not wait for Reset Complete\n");
+ }
+ retnVal = elMIIpollBit(dev, phy_id, MII_STATUS, MIISTAT_AUTO_DONE,
+ TRUE, &status);
+ if (!retnVal) {
+ printk(KERN_INFO "Not wait for AutoNego Complete\n");
+ }
+ retnVal = elMIIpollBit(dev, phy_id, MII_STATUS, MIISTAT_LINK,
+ TRUE, &status);
+ if (!retnVal) {
+ printk(KERN_INFO "Not wait for Link Complete\n");
+ }
if (status & MIISTAT_LINK) {
elPMDreadMode(dev, phy_id, speed, duplex);
elSetMediaType(dev, *speed, *duplex);
}
return(status);
+}
+
+static void elSetCapability(struct device *dev, int phy_id,
+ int duplex, int speed)
+{
+ u16 cap = ( MII_NWAY_T | MII_NWAY_T_FDX |
+ MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_CSMA_CD );
+
+ if (speed != 100) {
+ cap &= ~( MII_NWAY_TX | MII_NWAY_TX_FDX );
+ if (sis900_debug > 1) {
+ printk(KERN_INFO "UNSET 100Mbps\n");
+ }
+ }
+
+ if (!duplex) {
+ cap &= ~( MII_NWAY_T_FDX | MII_NWAY_TX_FDX );
+ if (sis900_debug > 1) {
+ printk(KERN_INFO "UNSET full-duplex\n");
+ }
+ }
+
+ mdio_write(dev, phy_id, MII_ANAR, cap);
}
static void elSetMediaType(struct device *dev, int speed, int duplex)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)