Commit 38b41d68 authored by Jeff Garzik's avatar Jeff Garzik

Merge pobox.com:/garz/repo/netdev-2.6/sis900

into pobox.com:/garz/repo/net-drivers-2.6
parents 37f110c4 955f5c33
...@@ -140,9 +140,9 @@ struct mii_phy { ...@@ -140,9 +140,9 @@ struct mii_phy {
}; };
typedef struct _BufferDesc { typedef struct _BufferDesc {
u32 link; u32 link;
u32 cmdsts; u32 cmdsts;
u32 bufptr; u32 bufptr;
} BufferDesc; } BufferDesc;
struct sis900_private { struct sis900_private {
...@@ -156,7 +156,7 @@ struct sis900_private { ...@@ -156,7 +156,7 @@ struct sis900_private {
unsigned int cur_phy; unsigned int cur_phy;
struct timer_list timer; /* Link status detection timer. */ struct timer_list timer; /* Link status detection timer. */
u8 autong_complete; /* 1: auto-negotiate complete */ u8 autong_complete; /* 1: auto-negotiate complete */
unsigned int cur_rx, dirty_rx; /* producer/comsumer pointers for Tx/Rx ring */ unsigned int cur_rx, dirty_rx; /* producer/comsumer pointers for Tx/Rx ring */
unsigned int cur_tx, dirty_tx; unsigned int cur_tx, dirty_tx;
...@@ -170,7 +170,7 @@ struct sis900_private { ...@@ -170,7 +170,7 @@ struct sis900_private {
dma_addr_t tx_ring_dma; dma_addr_t tx_ring_dma;
dma_addr_t rx_ring_dma; dma_addr_t rx_ring_dma;
unsigned int tx_full; /* The Tx queue is full. */ unsigned int tx_full; /* The Tx queue is full. */
u8 host_bridge_rev; u8 host_bridge_rev;
}; };
...@@ -255,7 +255,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de ...@@ -255,7 +255,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
* MAC address is read into @net_dev->dev_addr. * MAC address is read into @net_dev->dev_addr.
*/ */
static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
struct net_device *net_dev)
{ {
struct pci_dev *isa_bridge = NULL; struct pci_dev *isa_bridge = NULL;
u8 reg; u8 reg;
...@@ -292,7 +293,8 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_d ...@@ -292,7 +293,8 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_d
* @net_dev->dev_addr. * @net_dev->dev_addr.
*/ */
static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
struct net_device *net_dev)
{ {
long ioaddr = net_dev->base_addr; long ioaddr = net_dev->base_addr;
u32 rfcrSave; u32 rfcrSave;
...@@ -334,7 +336,8 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, struct net_de ...@@ -334,7 +336,8 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev, struct net_de
* MAC address is read into @net_dev->dev_addr. * MAC address is read into @net_dev->dev_addr.
*/ */
static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
struct net_device *net_dev)
{ {
long ioaddr = net_dev->base_addr; long ioaddr = net_dev->base_addr;
long ee_addr = ioaddr + mear; long ee_addr = ioaddr + mear;
...@@ -371,7 +374,8 @@ static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, struct net_de ...@@ -371,7 +374,8 @@ static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev, struct net_de
* ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc. * ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc.
*/ */
static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id) static int __devinit sis900_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{ {
struct sis900_private *sis_priv; struct sis900_private *sis_priv;
struct net_device *net_dev; struct net_device *net_dev;
...@@ -522,7 +526,7 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev ...@@ -522,7 +526,7 @@ static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_dev
* return error if it failed to found. * return error if it failed to found.
*/ */
static int __init sis900_mii_probe (struct net_device * net_dev) static int __init sis900_mii_probe(struct net_device * net_dev)
{ {
struct sis900_private * sis_priv = net_dev->priv; struct sis900_private * sis_priv = net_dev->priv;
u16 poll_bit = MII_STAT_LINK, status = 0; u16 poll_bit = MII_STAT_LINK, status = 0;
...@@ -572,9 +576,10 @@ static int __init sis900_mii_probe (struct net_device * net_dev) ...@@ -572,9 +576,10 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
mii_phy->phy_types = mii_chip_table[i].phy_types; mii_phy->phy_types = mii_chip_table[i].phy_types;
if (mii_chip_table[i].phy_types == MIX) if (mii_chip_table[i].phy_types == MIX)
mii_phy->phy_types = mii_phy->phy_types =
(mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME; (mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME;
printk(KERN_INFO "%s: %s transceiver found at address %d.\n", printk(KERN_INFO "%s: %s transceiver found at address %d.\n",
net_dev->name, mii_chip_table[i].name, phy_addr); net_dev->name, mii_chip_table[i].name,
phy_addr);
break; break;
} }
...@@ -587,7 +592,7 @@ static int __init sis900_mii_probe (struct net_device * net_dev) ...@@ -587,7 +592,7 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
if (sis_priv->mii == NULL) { if (sis_priv->mii == NULL) {
printk(KERN_INFO "%s: No MII transceivers found!\n", printk(KERN_INFO "%s: No MII transceivers found!\n",
net_dev->name); net_dev->name);
return 0; return 0;
} }
...@@ -611,7 +616,8 @@ static int __init sis900_mii_probe (struct net_device * net_dev) ...@@ -611,7 +616,8 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit); poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit);
if (time_after_eq(jiffies, timeout)) { if (time_after_eq(jiffies, timeout)) {
printk(KERN_WARNING "%s: reset phy and link down now\n", net_dev->name); printk(KERN_WARNING "%s: reset phy and link down now\n",
net_dev->name);
return -ETIME; return -ETIME;
} }
} }
...@@ -647,38 +653,41 @@ static int __init sis900_mii_probe (struct net_device * net_dev) ...@@ -647,38 +653,41 @@ static int __init sis900_mii_probe (struct net_device * net_dev)
static u16 sis900_default_phy(struct net_device * net_dev) static u16 sis900_default_phy(struct net_device * net_dev)
{ {
struct sis900_private * sis_priv = net_dev->priv; struct sis900_private * sis_priv = net_dev->priv;
struct mii_phy *phy = NULL, *phy_home = NULL, *default_phy = NULL, *phy_lan = NULL; struct mii_phy *phy = NULL, *phy_home = NULL,
*default_phy = NULL, *phy_lan = NULL;
u16 status; u16 status;
for( phy=sis_priv->first_mii; phy; phy=phy->next ){ for (phy=sis_priv->first_mii; phy; phy=phy->next) {
status = mdio_read(net_dev, phy->phy_addr, MII_STATUS); status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);
status = mdio_read(net_dev, phy->phy_addr, MII_STATUS); status = mdio_read(net_dev, phy->phy_addr, MII_STATUS);
/* Link ON & Not select default PHY & not ghost PHY */ /* Link ON & Not select default PHY & not ghost PHY */
if ( (status & MII_STAT_LINK) && !default_phy && (phy->phy_types != UNKNOWN) ) if ((status & MII_STAT_LINK) && !default_phy &&
(phy->phy_types != UNKNOWN))
default_phy = phy; default_phy = phy;
else{ else {
status = mdio_read(net_dev, phy->phy_addr, MII_CONTROL); status = mdio_read(net_dev, phy->phy_addr, MII_CONTROL);
mdio_write(net_dev, phy->phy_addr, MII_CONTROL, mdio_write(net_dev, phy->phy_addr, MII_CONTROL,
status | MII_CNTL_AUTO | MII_CNTL_ISOLATE); status | MII_CNTL_AUTO | MII_CNTL_ISOLATE);
if( phy->phy_types == HOME ) if (phy->phy_types == HOME)
phy_home = phy; phy_home = phy;
else if (phy->phy_types == LAN) else if(phy->phy_types == LAN)
phy_lan = phy; phy_lan = phy;
} }
} }
if( !default_phy && phy_home ) if (!default_phy && phy_home)
default_phy = phy_home; default_phy = phy_home;
else if( !default_phy && phy_lan ) else if (!default_phy && phy_lan)
default_phy = phy_lan; default_phy = phy_lan;
else if ( !default_phy ) else if (!default_phy)
default_phy = sis_priv->first_mii; default_phy = sis_priv->first_mii;
if( sis_priv->mii != default_phy ){ if (sis_priv->mii != default_phy) {
sis_priv->mii = default_phy; sis_priv->mii = default_phy;
sis_priv->cur_phy = default_phy->phy_addr; sis_priv->cur_phy = default_phy->phy_addr;
printk(KERN_INFO "%s: Using transceiver found at address %d as default\n", net_dev->name,sis_priv->cur_phy); printk(KERN_INFO "%s: Using transceiver found at address %d as default\n",
net_dev->name,sis_priv->cur_phy);
} }
status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL); status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
...@@ -701,7 +710,7 @@ static u16 sis900_default_phy(struct net_device * net_dev) ...@@ -701,7 +710,7 @@ static u16 sis900_default_phy(struct net_device * net_dev)
* mii status register. It's necessary before auto-negotiate. * mii status register. It's necessary before auto-negotiate.
*/ */
static void sis900_set_capability( struct net_device *net_dev , struct mii_phy *phy ) static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *phy)
{ {
u16 cap; u16 cap;
u16 status; u16 status;
...@@ -851,7 +860,8 @@ static u16 mdio_read(struct net_device *net_dev, int phy_id, int location) ...@@ -851,7 +860,8 @@ static u16 mdio_read(struct net_device *net_dev, int phy_id, int location)
* please see SiS7014 or ICS spec * please see SiS7014 or ICS spec
*/ */
static void mdio_write(struct net_device *net_dev, int phy_id, int location, int value) static void mdio_write(struct net_device *net_dev, int phy_id, int location,
int value)
{ {
long mdio_addr = net_dev->base_addr + mear; long mdio_addr = net_dev->base_addr + mear;
int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift); int mii_cmd = MIIwrite|(phy_id<<MIIpmdShift)|(location<<MIIregShift);
...@@ -939,7 +949,8 @@ sis900_open(struct net_device *net_dev) ...@@ -939,7 +949,8 @@ sis900_open(struct net_device *net_dev)
pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision); pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
sis630_set_eq(net_dev, revision); sis630_set_eq(net_dev, revision);
ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev); ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ,
net_dev->name, net_dev);
if (ret) if (ret)
return ret; return ret;
...@@ -1136,48 +1147,55 @@ static void sis630_set_eq(struct net_device *net_dev, u8 revision) ...@@ -1136,48 +1147,55 @@ static void sis630_set_eq(struct net_device *net_dev, u8 revision)
return; return;
if (netif_carrier_ok(net_dev)) { if (netif_carrier_ok(net_dev)) {
reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV); reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (0x2200 | reg14h) & 0xBFFF); mdio_write(net_dev, sis_priv->cur_phy, MII_RESV,
(0x2200 | reg14h) & 0xBFFF);
for (i=0; i < maxcount; i++) { for (i=0; i < maxcount; i++) {
eq_value=(0x00F8 & mdio_read(net_dev, sis_priv->cur_phy, MII_RESV)) >> 3; eq_value = (0x00F8 & mdio_read(net_dev,
sis_priv->cur_phy, MII_RESV)) >> 3;
if (i == 0) if (i == 0)
max_value=min_value=eq_value; max_value=min_value=eq_value;
max_value=(eq_value > max_value) ? eq_value : max_value; max_value = (eq_value > max_value) ?
min_value=(eq_value < min_value) ? eq_value : min_value; eq_value : max_value;
min_value = (eq_value < min_value) ?
eq_value : min_value;
} }
/* 630E rule to determine the equalizer value */ /* 630E rule to determine the equalizer value */
if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV || if (revision == SIS630E_900_REV || revision == SIS630EA1_900_REV ||
revision == SIS630ET_900_REV) { revision == SIS630ET_900_REV) {
if (max_value < 5) if (max_value < 5)
eq_value=max_value; eq_value = max_value;
else if (max_value >= 5 && max_value < 15) else if (max_value >= 5 && max_value < 15)
eq_value=(max_value == min_value) ? max_value+2 : max_value+1; eq_value = (max_value == min_value) ?
max_value+2 : max_value+1;
else if (max_value >= 15) else if (max_value >= 15)
eq_value=(max_value == min_value) ? max_value+6 : max_value+5; eq_value=(max_value == min_value) ?
max_value+6 : max_value+5;
} }
/* 630B0&B1 rule to determine the equalizer value */ /* 630B0&B1 rule to determine the equalizer value */
if (revision == SIS630A_900_REV && if (revision == SIS630A_900_REV &&
(sis_priv->host_bridge_rev == SIS630B0 || (sis_priv->host_bridge_rev == SIS630B0 ||
sis_priv->host_bridge_rev == SIS630B1)) { sis_priv->host_bridge_rev == SIS630B1)) {
if (max_value == 0) if (max_value == 0)
eq_value=3; eq_value = 3;
else else
eq_value=(max_value+min_value+1)/2; eq_value = (max_value + min_value + 1)/2;
} }
/* write equalizer value and setting */ /* write equalizer value and setting */
reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV); reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
reg14h=(reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8); reg14h = (reg14h & 0xFF07) | ((eq_value << 3) & 0x00F8);
reg14h=(reg14h | 0x6000) & 0xFDFF; reg14h = (reg14h | 0x6000) & 0xFDFF;
mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, reg14h); mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, reg14h);
} } else {
else { reg14h = mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV);
if (revision == SIS630A_900_REV && if (revision == SIS630A_900_REV &&
(sis_priv->host_bridge_rev == SIS630B0 || (sis_priv->host_bridge_rev == SIS630B0 ||
sis_priv->host_bridge_rev == SIS630B1)) sis_priv->host_bridge_rev == SIS630B1))
mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (reg14h | 0x2200) & 0xBFFF); mdio_write(net_dev, sis_priv->cur_phy, MII_RESV,
(reg14h | 0x2200) & 0xBFFF);
else else
mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (reg14h | 0x2000) & 0xBFFF); mdio_write(net_dev, sis_priv->cur_phy, MII_RESV,
(reg14h | 0x2000) & 0xBFFF);
} }
return; return;
} }
...@@ -1205,7 +1223,8 @@ static void sis900_timer(unsigned long data) ...@@ -1205,7 +1223,8 @@ static void sis900_timer(unsigned long data)
sis900_read_mode(net_dev, &speed, &duplex); sis900_read_mode(net_dev, &speed, &duplex);
if (duplex){ if (duplex){
sis900_set_mode(net_dev->base_addr, speed, duplex); sis900_set_mode(net_dev->base_addr, speed, duplex);
pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision); pci_read_config_byte(sis_priv->pci_dev,
PCI_CLASS_REVISION, &revision);
sis630_set_eq(net_dev, revision); sis630_set_eq(net_dev, revision);
netif_start_queue(net_dev); netif_start_queue(net_dev);
} }
...@@ -1229,9 +1248,8 @@ static void sis900_timer(unsigned long data) ...@@ -1229,9 +1248,8 @@ static void sis900_timer(unsigned long data)
sis900_check_mode(net_dev, mii_phy); sis900_check_mode(net_dev, mii_phy);
netif_carrier_on(net_dev); netif_carrier_on(net_dev);
} }
} } else {
/* Link ON -> OFF */ /* Link ON -> OFF */
else {
if (!(status & MII_STAT_LINK)){ if (!(status & MII_STAT_LINK)){
netif_carrier_off(net_dev); netif_carrier_off(net_dev);
printk(KERN_INFO "%s: Media Link Off\n", net_dev->name); printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
...@@ -1241,7 +1259,8 @@ static void sis900_timer(unsigned long data) ...@@ -1241,7 +1259,8 @@ static void sis900_timer(unsigned long data)
((mii_phy->phy_id1 & 0xFFF0) == 0x8000)) ((mii_phy->phy_id1 & 0xFFF0) == 0x8000))
sis900_reset_phy(net_dev, sis_priv->cur_phy); sis900_reset_phy(net_dev, sis_priv->cur_phy);
pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision); pci_read_config_byte(sis_priv->pci_dev,
PCI_CLASS_REVISION, &revision);
sis630_set_eq(net_dev, revision); sis630_set_eq(net_dev, revision);
goto LookForLink; goto LookForLink;
...@@ -1264,18 +1283,18 @@ static void sis900_timer(unsigned long data) ...@@ -1264,18 +1283,18 @@ static void sis900_timer(unsigned long data)
* and autong_complete should be set to 1. * and autong_complete should be set to 1.
*/ */
static void sis900_check_mode (struct net_device *net_dev, struct mii_phy *mii_phy) static void sis900_check_mode(struct net_device *net_dev, struct mii_phy *mii_phy)
{ {
struct sis900_private *sis_priv = net_dev->priv; struct sis900_private *sis_priv = net_dev->priv;
long ioaddr = net_dev->base_addr; long ioaddr = net_dev->base_addr;
int speed, duplex; int speed, duplex;
if( mii_phy->phy_types == LAN ){ if (mii_phy->phy_types == LAN) {
outl( ~EXD & inl( ioaddr + cfg ), ioaddr + cfg); outl(~EXD & inl(ioaddr + cfg), ioaddr + cfg);
sis900_set_capability(net_dev , mii_phy); sis900_set_capability(net_dev , mii_phy);
sis900_auto_negotiate(net_dev, sis_priv->cur_phy); sis900_auto_negotiate(net_dev, sis_priv->cur_phy);
}else{ } else {
outl(EXD | inl( ioaddr + cfg ), ioaddr + cfg); outl(EXD | inl(ioaddr + cfg), ioaddr + cfg);
speed = HW_SPEED_HOME; speed = HW_SPEED_HOME;
duplex = FDX_CAPABLE_HALF_SELECTED; duplex = FDX_CAPABLE_HALF_SELECTED;
sis900_set_mode(ioaddr, speed, duplex); sis900_set_mode(ioaddr, speed, duplex);
...@@ -1300,20 +1319,20 @@ static void sis900_set_mode (long ioaddr, int speed, int duplex) ...@@ -1300,20 +1319,20 @@ static void sis900_set_mode (long ioaddr, int speed, int duplex)
{ {
u32 tx_flags = 0, rx_flags = 0; u32 tx_flags = 0, rx_flags = 0;
if( inl(ioaddr + cfg) & EDB_MASTER_EN ){ if (inl(ioaddr + cfg) & EDB_MASTER_EN) {
tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift); tx_flags = TxATP | (DMA_BURST_64 << TxMXDMA_shift) |
(TX_FILL_THRESH << TxFILLT_shift);
rx_flags = DMA_BURST_64 << RxMXDMA_shift; rx_flags = DMA_BURST_64 << RxMXDMA_shift;
} } else {
else{ tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) |
tx_flags = TxATP | (DMA_BURST_512 << TxMXDMA_shift) | (TX_FILL_THRESH << TxFILLT_shift); (TX_FILL_THRESH << TxFILLT_shift);
rx_flags = DMA_BURST_512 << RxMXDMA_shift; rx_flags = DMA_BURST_512 << RxMXDMA_shift;
} }
if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS ) { if (speed == HW_SPEED_HOME || speed == HW_SPEED_10_MBPS) {
rx_flags |= (RxDRNT_10 << RxDRNT_shift); rx_flags |= (RxDRNT_10 << RxDRNT_shift);
tx_flags |= (TxDRNT_10 << TxDRNT_shift); tx_flags |= (TxDRNT_10 << TxDRNT_shift);
} } else {
else {
rx_flags |= (RxDRNT_100 << RxDRNT_shift); rx_flags |= (RxDRNT_100 << RxDRNT_shift);
tx_flags |= (TxDRNT_100 << TxDRNT_shift); tx_flags |= (TxDRNT_100 << TxDRNT_shift);
} }
...@@ -1403,19 +1422,19 @@ static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex ...@@ -1403,19 +1422,19 @@ static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex
sis_priv->autong_complete = 1; sis_priv->autong_complete = 1;
/* Workaround for Realtek RTL8201 PHY issue */ /* Workaround for Realtek RTL8201 PHY issue */
if((phy->phy_id0 == 0x0000) && ((phy->phy_id1 & 0xFFF0) == 0x8200)){ if ((phy->phy_id0 == 0x0000) && ((phy->phy_id1 & 0xFFF0) == 0x8200)) {
if(mdio_read(net_dev, phy_addr, MII_CONTROL) & MII_CNTL_FDX) if (mdio_read(net_dev, phy_addr, MII_CONTROL) & MII_CNTL_FDX)
*duplex = FDX_CAPABLE_FULL_SELECTED; *duplex = FDX_CAPABLE_FULL_SELECTED;
if(mdio_read(net_dev, phy_addr, 0x0019) & 0x01) if (mdio_read(net_dev, phy_addr, 0x0019) & 0x01)
*speed = HW_SPEED_100_MBPS; *speed = HW_SPEED_100_MBPS;
} }
printk(KERN_INFO "%s: Media Link On %s %s-duplex \n", printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
net_dev->name, net_dev->name,
*speed == HW_SPEED_100_MBPS ? *speed == HW_SPEED_100_MBPS ?
"100mbps" : "10mbps", "100mbps" : "10mbps",
*duplex == FDX_CAPABLE_FULL_SELECTED ? *duplex == FDX_CAPABLE_FULL_SELECTED ?
"full" : "half"); "full" : "half");
} }
/** /**
...@@ -1677,13 +1696,13 @@ static int sis900_rx(struct net_device *net_dev) ...@@ -1677,13 +1696,13 @@ static int sis900_rx(struct net_device *net_dev)
sis_priv->stats.rx_bytes += rx_size; sis_priv->stats.rx_bytes += rx_size;
sis_priv->stats.rx_packets++; sis_priv->stats.rx_packets++;
/* refill the Rx buffer, what if there is not enought memory for /* refill the Rx buffer, what if there is not enought
new socket buffer ?? */ * memory for new socket buffer ?? */
if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
/* not enough memory for skbuff, this makes a "hole" /* not enough memory for skbuff, this makes a
on the buffer ring, it is not clear how the * "hole" on the buffer ring, it is not clear
hardware will react to this kind of degenerated * how the hardware will react to this kind
buffer */ * of degenerated buffer */
printk(KERN_INFO "%s: Memory squeeze," printk(KERN_INFO "%s: Memory squeeze,"
"deferring packet.\n", "deferring packet.\n",
net_dev->name); net_dev->name);
...@@ -1707,8 +1726,8 @@ static int sis900_rx(struct net_device *net_dev) ...@@ -1707,8 +1726,8 @@ static int sis900_rx(struct net_device *net_dev)
rx_status = sis_priv->rx_ring[entry].cmdsts; rx_status = sis_priv->rx_ring[entry].cmdsts;
} // while } // while
/* refill the Rx buffer, what if the rate of refilling is slower than /* refill the Rx buffer, what if the rate of refilling is slower
consuming ?? */ * than consuming ?? */
for (;sis_priv->cur_rx - sis_priv->dirty_rx > 0; sis_priv->dirty_rx++) { for (;sis_priv->cur_rx - sis_priv->dirty_rx > 0; sis_priv->dirty_rx++) {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1716,10 +1735,10 @@ static int sis900_rx(struct net_device *net_dev) ...@@ -1716,10 +1735,10 @@ static int sis900_rx(struct net_device *net_dev)
if (sis_priv->rx_skbuff[entry] == NULL) { if (sis_priv->rx_skbuff[entry] == NULL) {
if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) { if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
/* not enough memory for skbuff, this makes a "hole" /* not enough memory for skbuff, this makes a
on the buffer ring, it is not clear how the * "hole" on the buffer ring, it is not clear
hardware will react to this kind of degenerated * how the hardware will react to this kind
buffer */ * of degenerated buffer */
printk(KERN_INFO "%s: Memory squeeze," printk(KERN_INFO "%s: Memory squeeze,"
"deferring packet.\n", "deferring packet.\n",
net_dev->name); net_dev->name);
...@@ -1764,8 +1783,8 @@ static void sis900_finish_xmit (struct net_device *net_dev) ...@@ -1764,8 +1783,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
if (tx_status & OWN) { if (tx_status & OWN) {
/* The packet is not transmitted yet (owned by hardware) ! /* The packet is not transmitted yet (owned by hardware) !
Note: the interrupt is generated only when Tx Machine * Note: the interrupt is generated only when Tx Machine
is idle, so this is an almost impossible case */ * is idle, so this is an almost impossible case */
break; break;
} }
...@@ -1803,8 +1822,8 @@ static void sis900_finish_xmit (struct net_device *net_dev) ...@@ -1803,8 +1822,8 @@ static void sis900_finish_xmit (struct net_device *net_dev)
if (sis_priv->tx_full && netif_queue_stopped(net_dev) && if (sis_priv->tx_full && netif_queue_stopped(net_dev) &&
sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) { sis_priv->cur_tx - sis_priv->dirty_tx < NUM_TX_DESC - 4) {
/* The ring is no longer full, clear tx_full and schedule more transmission /* The ring is no longer full, clear tx_full and schedule
by netif_wake_queue(net_dev) */ * more transmission by netif_wake_queue(net_dev) */
sis_priv->tx_full = 0; sis_priv->tx_full = 0;
netif_wake_queue (net_dev); netif_wake_queue (net_dev);
} }
...@@ -1818,8 +1837,7 @@ static void sis900_finish_xmit (struct net_device *net_dev) ...@@ -1818,8 +1837,7 @@ static void sis900_finish_xmit (struct net_device *net_dev)
* free Tx and RX socket buffer * free Tx and RX socket buffer
*/ */
static int static int sis900_close(struct net_device *net_dev)
sis900_close(struct net_device *net_dev)
{ {
long ioaddr = net_dev->base_addr; long ioaddr = net_dev->base_addr;
struct sis900_private *sis_priv = net_dev->priv; struct sis900_private *sis_priv = net_dev->priv;
...@@ -1955,27 +1973,28 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1955,27 +1973,28 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map)
if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {
/* we switch on the ifmap->port field. I couldn't find anything /* we switch on the ifmap->port field. I couldn't find anything
like a definition or standard for the values of that field. * like a definition or standard for the values of that field.
I think the meaning of those values is device specific. But * I think the meaning of those values is device specific. But
since I would like to change the media type via the ifconfig * since I would like to change the media type via the ifconfig
command I use the definition from linux/netdevice.h * command I use the definition from linux/netdevice.h
(which seems to be different from the ifport(pcmcia) definition) * (which seems to be different from the ifport(pcmcia) definition) */
*/
switch(map->port){ switch(map->port){
case IF_PORT_UNKNOWN: /* use auto here */ case IF_PORT_UNKNOWN: /* use auto here */
dev->if_port = map->port; dev->if_port = map->port;
/* we are going to change the media type, so the Link will /* we are going to change the media type, so the Link
be temporary down and we need to reflect that here. When * will be temporary down and we need to reflect that
the Link comes up again, it will be sensed by the sis_timer * here. When the Link comes up again, it will be
procedure, which also does all the rest for us */ * sensed by the sis_timer procedure, which also does
* all the rest for us */
netif_carrier_off(dev); netif_carrier_off(dev);
/* read current state */ /* read current state */
status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL); status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
/* enable auto negotiation and reset the negotioation /* enable auto negotiation and reset the negotioation
(I don't really know what the auto negatiotiation reset * (I don't really know what the auto negatiotiation
really means, but it sounds for me right to do one here)*/ * reset really means, but it sounds for me right to
* do one here) */
mdio_write(dev, mii_phy->phy_addr, mdio_write(dev, mii_phy->phy_addr,
MII_CONTROL, status | MII_CNTL_AUTO | MII_CNTL_RST_AUTO); MII_CONTROL, status | MII_CNTL_AUTO | MII_CNTL_RST_AUTO);
...@@ -1984,10 +2003,11 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1984,10 +2003,11 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map)
case IF_PORT_10BASET: /* 10BaseT */ case IF_PORT_10BASET: /* 10BaseT */
dev->if_port = map->port; dev->if_port = map->port;
/* we are going to change the media type, so the Link will /* we are going to change the media type, so the Link
be temporary down and we need to reflect that here. When * will be temporary down and we need to reflect that
the Link comes up again, it will be sensed by the sis_timer * here. When the Link comes up again, it will be
procedure, which also does all the rest for us */ * sensed by the sis_timer procedure, which also does
* all the rest for us */
netif_carrier_off(dev); netif_carrier_off(dev);
/* set Speed to 10Mbps */ /* set Speed to 10Mbps */
...@@ -1996,24 +2016,27 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map) ...@@ -1996,24 +2016,27 @@ static int sis900_set_config(struct net_device *dev, struct ifmap *map)
/* disable auto negotiation and force 10MBit mode*/ /* disable auto negotiation and force 10MBit mode*/
mdio_write(dev, mii_phy->phy_addr, mdio_write(dev, mii_phy->phy_addr,
MII_CONTROL, status & ~(MII_CNTL_SPEED | MII_CNTL_AUTO)); MII_CONTROL, status & ~(MII_CNTL_SPEED |
MII_CNTL_AUTO));
break; break;
case IF_PORT_100BASET: /* 100BaseT */ case IF_PORT_100BASET: /* 100BaseT */
case IF_PORT_100BASETX: /* 100BaseTx */ case IF_PORT_100BASETX: /* 100BaseTx */
dev->if_port = map->port; dev->if_port = map->port;
/* we are going to change the media type, so the Link will /* we are going to change the media type, so the Link
be temporary down and we need to reflect that here. When * will be temporary down and we need to reflect that
the Link comes up again, it will be sensed by the sis_timer * here. When the Link comes up again, it will be
procedure, which also does all the rest for us */ * sensed by the sis_timer procedure, which also does
* all the rest for us */
netif_carrier_off(dev); netif_carrier_off(dev);
/* set Speed to 100Mbps */ /* set Speed to 100Mbps */
/* disable auto negotiation and enable 100MBit Mode */ /* disable auto negotiation and enable 100MBit Mode */
status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL); status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL);
mdio_write(dev, mii_phy->phy_addr, mdio_write(dev, mii_phy->phy_addr,
MII_CONTROL, (status & ~MII_CNTL_SPEED) | MII_CNTL_SPEED); MII_CONTROL, (status & ~MII_CNTL_SPEED) |
MII_CNTL_SPEED);
break; break;
...@@ -2093,12 +2116,14 @@ static void set_rx_mode(struct net_device *net_dev) ...@@ -2093,12 +2116,14 @@ static void set_rx_mode(struct net_device *net_dev)
for (i = 0; i < table_entries; i++) for (i = 0; i < table_entries; i++)
mc_filter[i] = 0xffff; mc_filter[i] = 0xffff;
} else { } else {
/* Accept Broadcast packet, destination address matchs our MAC address, /* Accept Broadcast packet, destination address matchs our
use Receive Filter to reject unwanted MCAST packet */ * MAC address, use Receive Filter to reject unwanted MCAST
* packets */
struct dev_mc_list *mclist; struct dev_mc_list *mclist;
rx_mode = RFAAB; rx_mode = RFAAB;
for (i = 0, mclist = net_dev->mc_list; mclist && i < net_dev->mc_count; for (i = 0, mclist = net_dev->mc_list;
i++, mclist = mclist->next) { mclist && i < net_dev->mc_count;
i++, mclist = mclist->next) {
unsigned int bit_nr = unsigned int bit_nr =
sis900_mcast_bitnr(mclist->dmi_addr, revision); sis900_mcast_bitnr(mclist->dmi_addr, revision);
mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf)); mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf));
...@@ -2114,7 +2139,8 @@ static void set_rx_mode(struct net_device *net_dev) ...@@ -2114,7 +2139,8 @@ static void set_rx_mode(struct net_device *net_dev)
outl(RFEN | rx_mode, ioaddr + rfcr); outl(RFEN | rx_mode, ioaddr + rfcr);
/* sis900 is capatable of looping back packet at MAC level for debugging purpose */ /* sis900 is capable of looping back packets at MAC level for
* debugging purpose */
if (net_dev->flags & IFF_LOOPBACK) { if (net_dev->flags & IFF_LOOPBACK) {
u32 cr_saved; u32 cr_saved;
/* We must disable Tx/Rx before setting loopback mode */ /* We must disable Tx/Rx before setting loopback mode */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment