/* Used to pass the full-duplex flag, etc. */ #define MAX_UNITS 8/* More are supported, limit only on options */ staticint options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1}; staticint full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
/* Set the copy breakpoint for the copy-only-tiny-frames scheme.
Setting to > 1518 effectively disables this feature. */ staticint rx_copybreak;
/* Operational parameters that are set at compile time. */
/* Keep the ring sizes a power of two for operational efficiency. Thecompilerwillconvert<unsigned>'%'<2^N>intoabitmask. MakingtheTxringtoolargedecreasestheeffectivenessofchannel bondingandpacketpriority.
There are no ill effects from too-large receive rings. */ #define TX_RING_SIZE 256 #define TX_QUEUE_LEN 240/* Limit ring entries actually used. */ #define RX_RING_SIZE 256 #define TX_TOTAL_SIZE TX_RING_SIZE*sizeof(struct epic_tx_desc) #define RX_TOTAL_SIZE RX_RING_SIZE*sizeof(struct epic_rx_desc)
/* Operational parameters that usually are not changed. */ /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (2*HZ)
#define PKT_BUF_SZ 1536/* Size of each temporary Rx buffer.*/
/* Bytes transferred to chip before transmission starts. */ /* Initial threshold, increased on underflow, rounded down to 4 byte units. */ #define TX_FIFO_THRESH 256 #define RX_FIFO_THRESH 1/* 0-3, 0==32, 64,96, or 3==128 bytes */
/* These identify the driver base version and may not be removed. */ staticchar version[] =
DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>"; staticchar version2[] = " (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")";
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
MODULE_LICENSE("GPL");
module_param(debug, int, 0);
module_param(rx_copybreak, int, 0);
module_param_array(options, int, NULL, 0);
module_param_array(full_duplex, int, NULL, 0);
MODULE_PARM_DESC(debug, "EPIC/100 debug level (0-5)");
MODULE_PARM_DESC(options, "EPIC/100: Bits 0-3: media type, bit 4: full duplex");
MODULE_PARM_DESC(rx_copybreak, "EPIC/100 copy breakpoint for copy-only-tiny-frames");
MODULE_PARM_DESC(full_duplex, "EPIC/100 full duplex setting(s) (1)");
/* Bring the chip out of low-power mode. */
ew32(GENCTL, 0x4200); /* Magic?! If we don't set this bit the MII interface won't work. */ /* This magic is documented in SMSC app note 7.15 */ for (i = 16; i > 0; i--)
ew32(TEST1, 0x0008);
/* Turn on the MII transceiver. */
ew32(MIICfg, 0x12); if (chip_idx == 1)
ew32(NVCTL, (er32(NVCTL) & ~0x003c) | 0x4800);
ew32(GENCTL, 0x0200);
/* Note: the '175 does not have a serial EEPROM. */ for (i = 0; i < 3; i++)
addr[i] = cpu_to_le16(er16(LAN0 + i*4));
eth_hw_addr_set(dev, (u8 *)addr);
if (debug > 2) {
dev_dbg(&pdev->dev, "EEPROM contents:\n"); for (i = 0; i < 64; i++)
pr_cont(" %4.4x%s", read_eeprom(ep, i),
i % 16 == 15 ? "\n" : "");
}
/* Find the connected MII xcvrs. Doingthisinopen()wouldallowdetectingexternalxcvrslater,but
takes much time and no cards have external MII. */
{ int phy, phy_idx = 0; for (phy = 1; phy < 32 && phy_idx < sizeof(ep->phys); phy++) { int mii_status = mdio_read(dev, phy, MII_BMSR); if (mii_status != 0xffff && mii_status != 0x0000) {
ep->phys[phy_idx++] = phy;
dev_info(&pdev->dev, "MII transceiver #%d control " "%4.4x status %4.4x.\n",
phy, mdio_read(dev, phy, 0), mii_status);
}
}
ep->mii_phy_cnt = phy_idx; if (phy_idx != 0) {
phy = ep->phys[0];
ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE);
dev_info(&pdev->dev, "Autonegotiation advertising %4.4x link " "partner %4.4x.\n",
ep->mii.advertising, mdio_read(dev, phy, 5));
} elseif ( ! (ep->chip_flags & NO_MII)) {
dev_warn(&pdev->dev, "***WARNING***: No MII transceiver found!\n"); /* Use the known PHY address of the EPII. */
ep->phys[0] = 3;
}
ep->mii.phy_id = ep->phys[0];
}
/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */ if (ep->chip_flags & MII_PWRDWN)
ew32(NVCTL, er32(NVCTL) & ~0x483c);
ew32(GENCTL, 0x0008);
/* The lower four bits are the media type. */ if (duplex) {
ep->mii.force_media = ep->mii.full_duplex = 1;
dev_info(&pdev->dev, "Forced full duplex requested.\n");
}
dev->if_port = ep->default_port = option;
/* The Epic-specific entries in the device structure. */
dev->netdev_ops = &epic_netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
dev->watchdog_timeo = TX_TIMEOUT;
netif_napi_add(dev, &ep->napi, epic_poll);
ret = register_netdev(dev); if (ret < 0) goto err_out_unmap_rx;
/* Set the timer to switch to check for link beat and perhaps switch
to an alternate media type. */
timer_setup(&ep->timer, epic_timer, 0);
ep->timer.expires = jiffies + 3*HZ;
add_timer(&ep->timer);
return rc;
}
/* Reset the chip to recover from a PCI transaction error.
This may occur at interrupt time. */ staticvoid epic_pause(struct net_device *dev)
{ struct net_device_stats *stats = &dev->stats; struct epic_private *ep = netdev_priv(dev); void __iomem *ioaddr = ep->ioaddr;
netif_stop_queue (dev);
/* Disable interrupts by clearing the interrupt mask. */
ew32(INTMASK, 0x00000000); /* Stop the chip's Tx and Rx DMA processes. */
ew16(COMMAND, StopRx | StopTxDMA | StopRxDMA);
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */ staticvoid epic_init_ring(struct net_device *dev)
{ struct epic_private *ep = netdev_priv(dev); int i;
/* Initialize all Rx descriptors. */ for (i = 0; i < RX_RING_SIZE; i++) {
ep->rx_ring[i].rxstatus = 0;
ep->rx_ring[i].buflength = ep->rx_buf_sz;
ep->rx_ring[i].next = ep->rx_ring_dma +
(i+1)*sizeof(struct epic_rx_desc);
ep->rx_skbuff[i] = NULL;
} /* Mark the last entry as wrapping the ring. */
ep->rx_ring[i-1].next = ep->rx_ring_dma;
/* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = netdev_alloc_skb(dev, ep->rx_buf_sz + 2);
ep->rx_skbuff[i] = skb; if (skb == NULL) break;
skb_reserve(skb, 2); /* 16 byte align the IP header. */
ep->rx_ring[i].bufaddr = dma_map_single(&ep->pci_dev->dev,
skb->data,
ep->rx_buf_sz,
DMA_FROM_DEVICE);
ep->rx_ring[i].rxstatus = DescOwn;
}
ep->dirty_rx = (unsignedint)(i - RX_RING_SIZE);
/* The Tx buffer descriptor is filled in as needed, but we
do need to clear the ownership bit. */ for (i = 0; i < TX_RING_SIZE; i++) {
ep->tx_skbuff[i] = NULL;
ep->tx_ring[i].txstatus = 0x0000;
ep->tx_ring[i].next = ep->tx_ring_dma +
(i+1)*sizeof(struct epic_tx_desc);
}
ep->tx_ring[i-1].next = ep->tx_ring_dma;
}
#ifndef final_version /* There was an major error, log it. */ if (debug > 1)
netdev_dbg(dev, "Transmit error, Tx status %8.8x.\n",
status); #endif
stats->tx_errors++; if (status & 0x1050)
stats->tx_aborted_errors++; if (status & 0x0008)
stats->tx_carrier_errors++; if (status & 0x0040)
stats->tx_window_errors++; if (status & 0x0010)
stats->tx_fifo_errors++;
}
/* Free the original skb. */
skb = ep->tx_skbuff[entry];
dma_unmap_single(&ep->pci_dev->dev,
ep->tx_ring[entry].bufaddr, skb->len,
DMA_TO_DEVICE);
dev_consume_skb_irq(skb);
ep->tx_skbuff[entry] = NULL;
}
#ifndef final_version if (cur_tx - dirty_tx > TX_RING_SIZE) {
netdev_warn(dev, "Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
dirty_tx, cur_tx, ep->tx_full);
dirty_tx += TX_RING_SIZE;
} #endif
ep->dirty_tx = dirty_tx; if (ep->tx_full && cur_tx - dirty_tx < TX_QUEUE_LEN - 4) { /* The ring is no longer full, allow new TX entries. */
ep->tx_full = 0;
netif_wake_queue(dev);
}
}
/* The interrupt handler does all of the Rx thread work and cleans up
after the Tx thread. */ static irqreturn_t epic_interrupt(int irq, void *dev_instance)
{ struct net_device *dev = dev_instance; struct epic_private *ep = netdev_priv(dev); void __iomem *ioaddr = ep->ioaddr; unsignedint handled = 0; int status;
status = er32(INTSTAT); /* Acknowledge all of the current interrupt sources ASAP. */
ew32(INTSTAT, status & EpicNormalEvent);
if (debug > 4) {
netdev_dbg(dev, "Interrupt, status=%#8.8x new intstat=%#8.8x.\n",
status, er32(INTSTAT));
}
if ((status & IntrSummary) == 0) goto out;
handled = 1;
if (status & EpicNapiEvent) {
spin_lock(&ep->napi_lock); if (napi_schedule_prep(&ep->napi)) {
epic_napi_irq_off(dev, ep);
__napi_schedule(&ep->napi);
}
spin_unlock(&ep->napi_lock);
}
status &= ~EpicNapiEvent;
/* Check uncommon events all at once. */ if (status & (CntFull | TxUnderrun | PCIBusErr170 | PCIBusErr175)) { struct net_device_stats *stats = &dev->stats;
if (status == EpicRemoved) goto out;
/* Always update the error counts to avoid overhead later. */
stats->rx_missed_errors += er8(MPCNT);
stats->rx_frame_errors += er8(ALICNT);
stats->rx_crc_errors += er8(CRCCNT);
if (status & TxUnderrun) { /* Tx FIFO underflow. */
stats->tx_fifo_errors++;
ew32(TxThresh, ep->tx_threshold += 128); /* Restart the transmit process. */
ew32(COMMAND, RestartTx);
} if (status & PCIBusErr170) {
netdev_err(dev, "PCI Bus Error! status %4.4x.\n",
status);
epic_pause(dev);
epic_restart(dev);
} /* Clear all error sources. */
ew32(INTSTAT, status & 0x7f18);
}
staticint epic_rx(struct net_device *dev, int budget)
{ struct epic_private *ep = netdev_priv(dev); int entry = ep->cur_rx % RX_RING_SIZE; int rx_work_limit = ep->dirty_rx + RX_RING_SIZE - ep->cur_rx; int work_done = 0;
if (debug > 4)
netdev_dbg(dev, " In epic_rx(), entry %d %8.8x.\n", entry,
ep->rx_ring[entry].rxstatus);
if (rx_work_limit > budget)
rx_work_limit = budget;
/* If we own the next entry, it's a new packet. Send it up. */ while ((ep->rx_ring[entry].rxstatus & DescOwn) == 0) { int status = ep->rx_ring[entry].rxstatus;
if (debug > 4)
netdev_dbg(dev, " epic_rx() status was %8.8x.\n",
status); if (--rx_work_limit < 0) break; if (status & 0x2006) { if (debug > 2)
netdev_dbg(dev, "epic_rx() error status was %8.8x.\n",
status); if (status & 0x2000) {
netdev_warn(dev, "Oversized Ethernet frame spanned multiple buffers, status %4.4x!\n",
status);
dev->stats.rx_length_errors++;
} elseif (status & 0x0006) /* Rx Frame errors are counted in hardware. */
dev->stats.rx_errors++;
} else { /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */ short pkt_len = (status >> 16) - 4; struct sk_buff *skb;
if (pkt_len > PKT_BUF_SZ - 4) {
netdev_err(dev, "Oversized Ethernet frame, status %x %d bytes.\n",
status, pkt_len);
pkt_len = 1514;
} /* Check if the packet is long enough to accept without copying
to a minimally-sized skbuff. */ if (pkt_len < rx_copybreak &&
(skb = netdev_alloc_skb(dev, pkt_len + 2)) != NULL) {
skb_reserve(skb, 2); /* 16 byte align the IP header */
dma_sync_single_for_cpu(&ep->pci_dev->dev,
ep->rx_ring[entry].bufaddr,
ep->rx_buf_sz,
DMA_FROM_DEVICE);
skb_copy_to_linear_data(skb, ep->rx_skbuff[entry]->data, pkt_len);
skb_put(skb, pkt_len);
dma_sync_single_for_device(&ep->pci_dev->dev,
ep->rx_ring[entry].bufaddr,
ep->rx_buf_sz,
DMA_FROM_DEVICE);
} else {
dma_unmap_single(&ep->pci_dev->dev,
ep->rx_ring[entry].bufaddr,
ep->rx_buf_sz,
DMA_FROM_DEVICE);
skb_put(skb = ep->rx_skbuff[entry], pkt_len);
ep->rx_skbuff[entry] = NULL;
}
skb->protocol = eth_type_trans(skb, dev);
netif_receive_skb(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
work_done++;
entry = (++ep->cur_rx) % RX_RING_SIZE;
}
/* Refill the Rx ring buffers. */ for (; ep->cur_rx - ep->dirty_rx > 0; ep->dirty_rx++) {
entry = ep->dirty_rx % RX_RING_SIZE; if (ep->rx_skbuff[entry] == NULL) { struct sk_buff *skb;
skb = ep->rx_skbuff[entry] = netdev_alloc_skb(dev, ep->rx_buf_sz + 2); if (skb == NULL) break;
skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
ep->rx_ring[entry].bufaddr = dma_map_single(&ep->pci_dev->dev,
skb->data,
ep->rx_buf_sz,
DMA_FROM_DEVICE);
work_done++;
} /* AV: shouldn't we add a barrier here? */
ep->rx_ring[entry].rxstatus = DescOwn;
} return work_done;
}
/* Set or clear the multicast filter for this adaptor. Notethatweonlyuseexclusionaroundactuallyqueueingthe newframe,notaroundfillingep->setup_frame.Thisisnon-deterministic
when re-entered but still correct. */
if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
ew32(RxCtrl, 0x002c); /* Unconditionally log net taps. */
memset(mc_filter, 0xff, sizeof(mc_filter));
} elseif ((!netdev_mc_empty(dev)) || (dev->flags & IFF_ALLMULTI)) { /* There is apparently a chip bug, so the multicast filter
is never enabled. */ /* Too many to filter perfectly -- accept all multicasts. */
memset(mc_filter, 0xff, sizeof(mc_filter));
ew32(RxCtrl, 0x000c);
} elseif (netdev_mc_empty(dev)) {
ew32(RxCtrl, 0x0004); return;
} else { /* Never executed, for now. */ struct netdev_hw_addr *ha;
memset(mc_filter, 0, sizeof(mc_filter));
netdev_for_each_mc_addr(ha, dev) { unsignedint bit_nr =
ether_crc_le(ETH_ALEN, ha->addr) & 0x3f;
mc_filter[bit_nr >> 3] |= (1 << bit_nr);
}
} /* ToDo: perhaps we need to stop the Tx and Rx process here? */ if (memcmp(mc_filter, ep->mc_filter, sizeof(mc_filter))) { for (i = 0; i < 4; i++)
ew16(MC0 + i*4, ((u16 *)mc_filter)[i]);
memcpy(ep->mc_filter, mc_filter, sizeof(mc_filter));
}
}
if (!netif_running(dev)) return0;
epic_pause(dev); /* Put the chip into low-power mode. */
ew32(GENCTL, 0x0008); /* pci_power_off(pdev, -1); */ return0;
}
staticint __init epic_init (void)
{ /* when a module, this is printed whether or not devices are found in probe */ #ifdef MODULE
pr_info("%s%s\n", version, version2); #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.