--- via-rhine.c.org Sun May 12 21:53:41 2002 +++ via-rhine.c Thu May 16 05:04:49 2002 @@ -224,7 +224,8 @@ II. Board-specific settings Boards with this chip are functional only in a bus-master PCI slot. Many operational settings are loaded from the EEPROM to the Config word at -offset 0x78. This driver assumes that they are correct. +offset 0x78. For most of these settings, this driver assumes that they are +correct. If this driver is compiled to use PCI memory space operations the EEPROM must be configured to enable memory ops. @@ -376,6 +377,14 @@ enum register_offsets { StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC, }; +/* Bits in ConfigD (select backoff algorithm (Ethernet capture effect)) */ +enum backoff_bits { + BackOptional=0x01, + BackModify=0x02, + BackCaptureEffect=0x04, + BackRandom=0x08 +}; + #ifdef USE_MEM /* Registers we check that mmio and reg are the same. */ int mmio_verify_registers[] = { @@ -413,24 +422,27 @@ enum mii_status_bits { /* The Rx and Tx buffer descriptors. */ struct rx_desc { s32 rx_status; - u32 desc_length; + u32 desc_length; /* Chain flag, Buffer/frame length */ u32 addr; u32 next_desc; }; struct tx_desc { s32 tx_status; - u32 desc_length; + u32 desc_length; /* Chain flag, Tx Config, Frame length */ u32 addr; u32 next_desc; }; -/* Bits in *_desc.status */ +/* Initial value for tx_desc.desc_length, Buffer size goes to bits 0-10 */ +#define TXDESC 0x00e08000 + enum rx_status_bits { RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F }; +/* Bits in *_desc.*_status */ enum desc_status_bits { - DescOwn=0x80000000, DescEndPacket=0x4000, DescIntr=0x1000, + DescOwn=0x80000000 }; /* Bits in ChipCmd. */ @@ -476,13 +488,10 @@ struct netdev_private { u16 chip_cmd; /* Current setting for ChipCmd */ /* These values are keep track of the transceiver/media in use. */ - unsigned int full_duplex:1; /* Full-duplex operation requested. */ - unsigned int duplex_lock:1; unsigned int default_port:4; /* Last dev->if_port value. */ u8 tx_thresh, rx_thresh; /* MII transceiver section. */ - u16 advertising; /* NWay media advertisement */ unsigned char phys[MAX_MII_CNT]; /* MII device addresses. */ unsigned int mii_cnt; /* number of MIIs found, but only the first one is used */ u16 mii_status; /* last read MII status */ @@ -693,6 +702,9 @@ static int __devinit via_rhine_init_one writeb(readb(ioaddr + ConfigA) & 0xFE, ioaddr + ConfigA); } + /* Select backoff algorithm */ + writeb(readb(ioaddr + ConfigD) & (0xF0 | BackModify), ioaddr + ConfigD); + dev->irq = pdev->irq; np = dev->priv; @@ -784,7 +796,7 @@ static int __devinit via_rhine_init_one (option & 0x300 ? 100 : 10), (option & 0x220 ? "full" : "half")); if (np->mii_cnt) - mdio_write(dev, np->phys[0], 0, + mdio_write(dev, np->phys[0], MII_BMCR, ((option & 0x300) ? 0x2000 : 0) | /* 100mbps? */ ((option & 0x220) ? 0x0100 : 0)); /* Full duplex? */ } @@ -927,7 +939,7 @@ static void alloc_tbufs(struct net_devic for (i = 0; i < TX_RING_SIZE; i++) { np->tx_skbuff[i] = 0; np->tx_ring[i].tx_status = 0; - np->tx_ring[i].desc_length = cpu_to_le32(0x00e08000); + np->tx_ring[i].desc_length = cpu_to_le32(TXDESC); next += sizeof(struct tx_desc); np->tx_ring[i].next_desc = cpu_to_le32(next); np->tx_buf[i] = &np->tx_bufs[i * PKT_BUF_SZ]; @@ -943,7 +955,7 @@ static void free_tbufs(struct net_device for (i = 0; i < TX_RING_SIZE; i++) { np->tx_ring[i].tx_status = 0; - np->tx_ring[i].desc_length = cpu_to_le32(0x00e08000); + np->tx_ring[i].desc_length = cpu_to_le32(TXDESC); np->tx_ring[i].addr = cpu_to_le32(0xBADF00D0); /* An invalid address. */ if (np->tx_skbuff[i]) { if (np->tx_skbuff_dma[i]) { @@ -969,8 +981,8 @@ static void init_registers(struct net_de /* Initialize other registers. */ writew(0x0006, ioaddr + PCIBusConfig); /* Tune configuration??? */ - /* Configure the FIFO thresholds. */ - writeb(0x20, ioaddr + TxConfig); /* Initial threshold 32 bytes */ + /* Configure initial FIFO thresholds. */ + writeb(0x20, ioaddr + TxConfig); np->tx_thresh = 0x20; np->rx_thresh = 0x60; /* Written in via_rhine_set_rx_mode(). */ @@ -1029,13 +1041,13 @@ static void mdio_write(struct net_device if (phy_id == np->phys[0]) { switch (regnum) { - case 0: /* Is user forcing speed/duplex? */ + case MII_BMCR: /* Is user forcing speed/duplex? */ if (value & 0x9000) /* Autonegotiation. */ np->mii_if.duplex_lock = 0; else np->mii_if.full_duplex = (value & 0x0100) ? 1 : 0; break; - case 4: + case MII_ADVERTISE: np->mii_if.advertising = value; break; } @@ -1227,7 +1239,7 @@ static int via_rhine_start_tx(struct sk_ } np->tx_ring[entry].desc_length = - cpu_to_le32(0x00E08000 | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); + cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); /* lock eth irq */ spin_lock_irq (&np->lock); @@ -1492,8 +1504,14 @@ static void via_rhine_error(struct net_d clear_tally_counters(ioaddr); } if (intr_status & IntrTxAbort) { - /* Stats counted in Tx-done handler, just restart Tx. */ + /* No skipping frames we have no results for! Bad chip! */ + writel(virt_to_bus(&np->tx_ring[np->dirty_tx % TX_RING_SIZE]), + ioaddr + TxRingPtr); + /* Prevent hanging on a full queue */ writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd); + if (debug > 1) + printk(KERN_INFO "%s: Abort %4.4x, frame dropped.\n", + dev->name, intr_status); } if (intr_status & IntrTxUnderrun) { if (np->tx_thresh < 0xE0)