#define MAX_UNITS 8/* More are supported, limit only on options */ staticint options[MAX_UNITS]; staticint full_duplex[MAX_UNITS]; staticint homepna[MAX_UNITS];
/* The PCNET32 32-Bit initialization block, described in databook. */ struct pcnet32_init_block {
__le16 mode;
__le16 tlen_rlen;
u8 phys_addr[6];
__le16 reserved;
__le32 filter[2]; /* Receive and transmit ring base, along with extra bits. */
__le32 rx_ring;
__le32 tx_ring;
};
spin_lock_irqsave(&lp->lock, flags); if (lp->mii) {
r = mii_link_ok(&lp->mii_if);
} elseif (lp->chip_version == PCNET32_79C970A) {
ulong ioaddr = dev->base_addr; /* card base I/O address */ /* only read link if port is set to TP */ if (!lp->autoneg && lp->port_tp)
r = (lp->a->read_bcr(ioaddr, 4) != 0xc0); else/* link always up for AUI port or port auto select */
r = 1;
} elseif (lp->chip_version > PCNET32_79C970A) {
ulong ioaddr = dev->base_addr; /* card base I/O address */
r = (lp->a->read_bcr(ioaddr, 4) != 0xc0);
} else { /* can not detect link on really old chips */
r = 1;
}
spin_unlock_irqrestore(&lp->lock, flags);
/* set the minimum ring size to 4, to allow the loopback test to work *unchanged.
*/ for (i = 2; i <= PCNET32_LOG_MAX_TX_BUFFERS; i++) { if (size <= (1 << i)) break;
} if ((1 << i) != lp->tx_ring_size)
pcnet32_realloc_tx_ring(dev, lp, i);
size = min(ering->rx_pending, (unsignedint)RX_MAX_RING_SIZE); for (i = 2; i <= PCNET32_LOG_MAX_RX_BUFFERS; i++) { if (size <= (1 << i)) break;
} if ((1 << i) != lp->rx_ring_size)
pcnet32_realloc_rx_ring(dev, lp, i);
lp->napi.weight = lp->rx_ring_size / 2;
if (netif_running(dev)) {
pcnet32_netif_start(dev);
pcnet32_restart(dev, CSR0_NORMAL);
}
lp->a->write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
/* Initialize Transmit buffers. */
size = data_len + 15; for (x = 0; x < numbuffs; x++) {
skb = netdev_alloc_skb(dev, size); if (!skb) {
netif_printk(lp, hw, KERN_DEBUG, dev, "Cannot allocate skb at line: %d!\n",
__LINE__); goto clean_up;
}
packet = skb->data;
skb_put(skb, size); /* create space for data */
lp->tx_skbuff[x] = skb;
lp->tx_ring[x].length = cpu_to_le16(-skb->len);
lp->tx_ring[x].misc = 0;
/* put DA and SA into the skb */ for (i = 0; i < 6; i++)
*packet++ = dev->dev_addr[i]; for (i = 0; i < 6; i++)
*packet++ = dev->dev_addr[i]; /* type */
*packet++ = 0x08;
*packet++ = 0x06; /* packet number */
*packet++ = x; /* fill packet with data */ for (i = 0; i < data_len; i++)
*packet++ = i;
lp->tx_dma_addr[x] =
dma_map_single(&lp->pci_dev->dev, skb->data, skb->len,
DMA_TO_DEVICE); if (dma_mapping_error(&lp->pci_dev->dev, lp->tx_dma_addr[x])) {
netif_printk(lp, hw, KERN_DEBUG, dev, "DMA mapping error at line: %d!\n",
__LINE__); goto clean_up;
}
lp->tx_ring[x].base = cpu_to_le32(lp->tx_dma_addr[x]);
wmb(); /* Make sure owner changes after all others are visible */
lp->tx_ring[x].status = cpu_to_le16(status);
}
x = a->read_bcr(ioaddr, 32); /* set internal loopback in BCR32 */
a->write_bcr(ioaddr, 32, x | 0x0002);
/* set int loopback in CSR15 */
x = a->read_csr(ioaddr, CSR15) & 0xfffc;
lp->a->write_csr(ioaddr, CSR15, x | 0x0044);
teststatus = cpu_to_le16(0x8000);
lp->a->write_csr(ioaddr, CSR0, CSR0_START); /* Set STRT bit */
/* Check status of descriptors */ for (x = 0; x < numbuffs; x++) {
ticks = 0;
rmb(); while ((lp->rx_ring[x].status & teststatus) && (ticks < 200)) {
spin_unlock_irqrestore(&lp->lock, flags);
msleep(1);
spin_lock_irqsave(&lp->lock, flags);
rmb();
ticks++;
} if (ticks == 200) {
netif_err(lp, hw, dev, "Desc %d failed to reset!\n", x); break;
}
}
lp->a->write_csr(ioaddr, CSR0, CSR0_STOP); /* Set STOP bit */
wmb(); if (netif_msg_hw(lp) && netif_msg_pktdata(lp)) {
netdev_printk(KERN_DEBUG, dev, "RX loopback packets:\n");
for (x = 0; x < numbuffs; x++) {
netdev_printk(KERN_DEBUG, dev, "Packet %d: ", x);
skb = lp->rx_skbuff[x]; for (i = 0; i < size; i++)
pr_cont(" %02x", *(skb->data + i));
pr_cont("\n");
}
}
x = 0;
rc = 0; while (x < numbuffs && !rc) {
skb = lp->rx_skbuff[x];
packet = lp->tx_skbuff[x]->data; for (i = 0; i < size; i++) { if (*(skb->data + i) != packet[i]) {
netif_printk(lp, hw, KERN_DEBUG, dev, "Error in compare! %2x - %02x %02x\n",
i, *(skb->data + i), packet[i]);
rc = 1; break;
}
}
x++;
}
switch (state) { case ETHTOOL_ID_ACTIVE: /* Save the current value of the bcrs */
spin_lock_irqsave(&lp->lock, flags); for (i = 4; i < 8; i++)
lp->save_regs[i - 4] = a->read_bcr(ioaddr, i);
spin_unlock_irqrestore(&lp->lock, flags); return2; /* cycle on/off twice per second */
case ETHTOOL_ID_ON: case ETHTOOL_ID_OFF: /* Blink the led */
spin_lock_irqsave(&lp->lock, flags); for (i = 4; i < 8; i++)
a->write_bcr(ioaddr, i, a->read_bcr(ioaddr, i) ^ 0x4000);
spin_unlock_irqrestore(&lp->lock, flags); break;
case ETHTOOL_ID_INACTIVE: /* Restore the original value of the bcrs */
spin_lock_irqsave(&lp->lock, flags); for (i = 4; i < 8; i++)
a->write_bcr(ioaddr, i, lp->save_regs[i - 4]);
spin_unlock_irqrestore(&lp->lock, flags);
} return0;
}
/* *processonereceivedescriptorentry
*/
staticvoid pcnet32_rx_entry(struct net_device *dev, struct pcnet32_private *lp, struct pcnet32_rx_head *rxp, int entry)
{ int status = (short)le16_to_cpu(rxp->status) >> 8; int rx_in_place = 0; struct sk_buff *skb; short pkt_len;
if (status != 0x03) { /* There was an error. */ /* *ThereisatrickyerrornotedbyJohnMurphy, *<murf@perftech.com>toRussNelson:Evenwithfull-sized *buffersit'spossibleforajabberpackettousetwo *buffers,withonlythelastcorrectlynotingtheerror.
*/ if (status & 0x01) /* Only count a general error at the */
dev->stats.rx_errors++; /* end of a packet. */ if (status & 0x20)
dev->stats.rx_frame_errors++; if (status & 0x10)
dev->stats.rx_over_errors++; if (status & 0x08)
dev->stats.rx_crc_errors++; if (status & 0x04)
dev->stats.rx_fifo_errors++; return;
}
staticint pcnet32_rx(struct net_device *dev, int budget)
{ struct pcnet32_private *lp = netdev_priv(dev); int entry = lp->cur_rx & lp->rx_mod_mask; struct pcnet32_rx_head *rxp = &lp->rx_ring[entry]; int npackets = 0;
/* If we own the next entry, it's a new packet. Send it up. */ while (npackets < budget && (short)le16_to_cpu(rxp->status) >= 0) {
pcnet32_rx_entry(dev, lp, rxp, entry);
npackets += 1; /* *Thedocssaythatthebufferlengthisn'ttouched,butAndrew *BoydofQNXreportsthatsomerevsofthe79C965clearit.
*/
rxp->buf_length = cpu_to_le16(NEG_BUF_SIZE);
wmb(); /* Make sure owner changes after others are visible */
rxp->status = cpu_to_le16(0x8000);
entry = (++lp->cur_rx) & lp->rx_mod_mask;
rxp = &lp->rx_ring[entry];
}
return npackets;
}
staticint pcnet32_tx(struct net_device *dev)
{ struct pcnet32_private *lp = netdev_priv(dev); unsignedint dirty_tx = lp->dirty_tx; int delta; int must_restart = 0;
while (dirty_tx != lp->cur_tx) { int entry = dirty_tx & lp->tx_mod_mask; int status = (short)le16_to_cpu(lp->tx_ring[entry].status);
if (status < 0) break; /* It still hasn't been Txed */
lp->tx_ring[entry].base = 0;
if (status & 0x4000) { /* There was a major error, log it. */ int err_status = le32_to_cpu(lp->tx_ring[entry].misc);
dev->stats.tx_errors++;
netif_err(lp, tx_err, dev, "Tx error status=%04x err_status=%08x\n",
status, err_status); if (err_status & 0x04000000)
dev->stats.tx_aborted_errors++; if (err_status & 0x08000000)
dev->stats.tx_carrier_errors++; if (err_status & 0x10000000)
dev->stats.tx_window_errors++; #ifndef DO_DXSUFLO if (err_status & 0x40000000) {
dev->stats.tx_fifo_errors++; /* Ackk! On FIFO errors the Tx unit is turned off! */ /* Remove this verbosity later! */
netif_err(lp, tx_err, dev, "Tx FIFO error!\n");
must_restart = 1;
} #else if (err_status & 0x40000000) {
dev->stats.tx_fifo_errors++; if (!lp->dxsuflo) { /* If controller doesn't recover ... */ /* Ackk! On FIFO errors the Tx unit is turned off! */ /* Remove this verbosity later! */
netif_err(lp, tx_err, dev, "Tx FIFO error!\n");
must_restart = 1;
}
} #endif
} else { if (status & 0x1800)
dev->stats.collisions++;
dev->stats.tx_packets++;
}
/* We must free the original skb */ if (lp->tx_skbuff[entry]) {
dma_unmap_single(&lp->pci_dev->dev,
lp->tx_dma_addr[entry],
lp->tx_skbuff[entry]->len,
DMA_TO_DEVICE);
dev_kfree_skb_any(lp->tx_skbuff[entry]);
lp->tx_skbuff[entry] = NULL;
lp->tx_dma_addr[entry] = 0;
}
dirty_tx++;
}
spin_lock_irqsave(&lp->lock, flags); if (pcnet32_tx(dev)) { /* reset the chip to clear the error condition, then restart */
lp->a->reset(ioaddr);
lp->a->write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */
pcnet32_restart(dev, CSR0_START);
netif_wake_queue(dev);
}
if (work_done < budget && napi_complete_done(napi, work_done)) { /* clear interrupt masks */
val = lp->a->read_csr(ioaddr, CSR3);
val &= 0x00ff;
lp->a->write_csr(ioaddr, CSR3, val);
/* Set interrupt enable. */
lp->a->write_csr(ioaddr, CSR0, CSR0_INTEN);
}
err = pci_enable_device(pdev); if (err < 0) { if (pcnet32_debug & NETIF_MSG_PROBE)
pr_err("failed to enable device -- err=%d\n", err); return err;
}
pci_set_master(pdev);
if (!pci_resource_len(pdev, 0)) { if (pcnet32_debug & NETIF_MSG_PROBE)
pr_err("card has no PCI IO resources, aborting\n");
err = -ENODEV; goto err_disable_dev;
}
err = dma_set_mask(&pdev->dev, PCNET32_DMA_MASK); if (err) { if (pcnet32_debug & NETIF_MSG_PROBE)
pr_err("architecture does not support 32bit PCI busmaster DMA\n"); goto err_disable_dev;
}
ioaddr = pci_resource_start(pdev, 0); if (!request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci")) { if (pcnet32_debug & NETIF_MSG_PROBE)
pr_err("io address range already allocated\n");
err = -EBUSY; goto err_disable_dev;
}
err = pcnet32_probe1(ioaddr, 1, pdev);
err_disable_dev: if (err < 0)
pci_disable_device(pdev);
dev = alloc_etherdev(sizeof(*lp)); if (!dev) {
ret = -ENOMEM; goto err_release_region;
}
if (pdev)
SET_NETDEV_DEV(dev, &pdev->dev);
if (pcnet32_debug & NETIF_MSG_PROBE)
pr_info("%s at %#3lx,", chipname, ioaddr);
/* In most chips, after a chip reset, the ethernet address is read from the *stationaddressPROMatthebaseaddressandprogrammedintothe *"PhysicalAddressRegisters"CSR12-14. *Asaprecautionarymeasure,wereadthePROMvaluesandcomplainif *theydisagreewiththeCSRs.Iftheymiscompare,andthePROMaddr *isvalid,thenthePROMaddrisused.
*/ for (i = 0; i < 3; i++) { unsignedint val;
val = a->read_csr(ioaddr, i + 12) & 0x0ffff; /* There may be endianness issues here. */
addr[2 * i] = val & 0x0ff;
addr[2 * i + 1] = (val >> 8) & 0x0ff;
}
eth_hw_addr_set(dev, addr);
/* read PROM address and compare with CSR address */ for (i = 0; i < ETH_ALEN; i++)
promaddr[i] = inb(ioaddr + i);
if (!ether_addr_equal(promaddr, dev->dev_addr) ||
!is_valid_ether_addr(dev->dev_addr)) { if (is_valid_ether_addr(promaddr)) { if (pcnet32_debug & NETIF_MSG_PROBE) {
pr_cont(" warning: CSR address invalid,\n");
pr_info(" using instead PROM address of");
}
eth_hw_addr_set(dev, promaddr);
}
}
/* if the ethernet address is not valid, force to 00:00:00:00:00:00 */ if (!is_valid_ether_addr(dev->dev_addr)) { staticconst u8 zero_addr[ETH_ALEN] = {};
eth_hw_addr_set(dev, zero_addr);
}
if (pcnet32_debug & NETIF_MSG_PROBE) {
pr_cont(" %pM", dev->dev_addr);
/* Version 0x2623 and 0x2624 */ if (((chip_version + 1) & 0xfffe) == 0x2624) {
i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */
pr_info(" tx_start_pt(0x%04x):", i); switch (i >> 10) { case0:
pr_cont(" 20 bytes,"); break; case1:
pr_cont(" 64 bytes,"); break; case2:
pr_cont(" 128 bytes,"); break; case3:
pr_cont("~220 bytes,"); break;
}
i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */
pr_cont(" BCR18(%x):", i & 0xffff); if (i & (1 << 5))
pr_cont("BurstWrEn "); if (i & (1 << 6))
pr_cont("BurstRdEn "); if (i & (1 << 7))
pr_cont("DWordIO "); if (i & (1 << 11))
pr_cont("NoUFlow ");
i = a->read_bcr(ioaddr, 25);
pr_info(" SRAMSIZE=0x%04x,", i << 8);
i = a->read_bcr(ioaddr, 26);
pr_cont(" SRAM_BND=0x%04x,", i << 8);
i = a->read_bcr(ioaddr, 27); if (i & (1 << 14))
pr_cont("LowLatRx");
}
}
dev->base_addr = ioaddr;
lp = netdev_priv(dev); /* dma_alloc_coherent returns page-aligned memory, so we do not have to check the alignment */
lp->init_block = dma_alloc_coherent(&pdev->dev, sizeof(*lp->init_block),
&lp->init_dma_addr, GFP_KERNEL); if (!lp->init_block) { if (pcnet32_debug & NETIF_MSG_PROBE)
pr_err("Coherent memory allocation failed\n");
ret = -ENOMEM; goto err_free_netdev;
}
lp->pci_dev = pdev;
lp->dev = dev;
spin_lock_init(&lp->lock);
lp->name = chipname;
lp->shared_irq = shared;
lp->tx_ring_size = TX_RING_SIZE; /* default tx ring size */
lp->rx_ring_size = RX_RING_SIZE; /* default rx ring size */
lp->tx_mod_mask = lp->tx_ring_size - 1;
lp->rx_mod_mask = lp->rx_ring_size - 1;
lp->tx_len_bits = (PCNET32_LOG_TX_BUFFERS << 12);
lp->rx_len_bits = (PCNET32_LOG_RX_BUFFERS << 4);
lp->mii_if.full_duplex = fdx;
lp->mii_if.phy_id_mask = 0x1f;
lp->mii_if.reg_num_mask = 0x1f;
lp->dxsuflo = dxsuflo;
lp->mii = mii;
lp->chip_version = chip_version;
lp->msg_enable = pcnet32_debug; if ((cards_found >= MAX_UNITS) ||
(options[cards_found] >= sizeof(options_mapping)))
lp->options = PCNET32_PORT_ASEL; else
lp->options = options_mapping[options[cards_found]]; /* force default port to TP on 79C970A so link detection can work */ if (lp->chip_version == PCNET32_79C970A)
lp->options = PCNET32_PORT_10BT;
lp->mii_if.dev = dev;
lp->mii_if.mdio_read = mdio_read;
lp->mii_if.mdio_write = mdio_write;
/* napi.weight is used in both the napi and non-napi cases */
lp->napi.weight = lp->rx_ring_size / 2;
/* prior to register_netdev, dev->name is not yet correct */ if (pcnet32_alloc_ring(dev, pci_name(lp->pci_dev))) {
ret = -ENOMEM; goto err_free_ring;
} /* detect special T1/E1 WAN card by checking for MAC address */ if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 &&
dev->dev_addr[2] == 0x75)
lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
lp->init_block->mode = cpu_to_le16(0x0003); /* Disable Rx and Tx. */
lp->init_block->tlen_rlen =
cpu_to_le16(lp->tx_len_bits | lp->rx_len_bits); for (i = 0; i < 6; i++)
lp->init_block->phys_addr[i] = dev->dev_addr[i];
lp->init_block->filter[0] = 0x00000000;
lp->init_block->filter[1] = 0x00000000;
lp->init_block->rx_ring = cpu_to_le32(lp->rx_ring_dma_addr);
lp->init_block->tx_ring = cpu_to_le32(lp->tx_ring_dma_addr);
/* switch pcnet32 to 32bit mode */
a->write_bcr(ioaddr, 20, 2);
if (pdev) { /* use the IRQ provided by PCI */
dev->irq = pdev->irq; if (pcnet32_debug & NETIF_MSG_PROBE)
pr_cont(" assigned IRQ %d\n", dev->irq);
} else { unsignedlong irq_mask = probe_irq_on();
/* *Toauto-IRQweenabletheinitialization-doneandDMAerror *interrupts.ForISAboardswegetaDMAerror,butVLBandPCI *boardswillwork.
*/ /* Trigger an initialization just for the interrupt. */
a->write_csr(ioaddr, CSR0, CSR0_INTEN | CSR0_INIT);
mdelay(1);
dev->irq = probe_irq_off(irq_mask); if (!dev->irq) { if (pcnet32_debug & NETIF_MSG_PROBE)
pr_cont(", failed to detect IRQ line\n");
ret = -ENODEV; goto err_free_ring;
} if (pcnet32_debug & NETIF_MSG_PROBE)
pr_cont(", probed IRQ %d\n", dev->irq);
}
/* Set the mii phy_id so that we can query the link state */ if (lp->mii) { /* lp->phycount and lp->phymask are set to 0 by memset above */
lp->mii_if.phy_id = ((lp->a->read_bcr(ioaddr, 33)) >> 5) & 0x1f; /* scan for PHYs */ for (i = 0; i < PCNET32_MAX_PHYS; i++) { unsignedshort id1, id2;
id1 = mdio_read(dev, i, MII_PHYSID1); if (id1 == 0xffff) continue;
id2 = mdio_read(dev, i, MII_PHYSID2); if (id2 == 0xffff) continue; if (i == 31 && ((chip_version + 1) & 0xfffe) == 0x2624) continue; /* 79C971 & 79C972 have phantom phy at id 31 */
lp->phycount++;
lp->phymask |= (1 << i);
lp->mii_if.phy_id = i; if (pcnet32_debug & NETIF_MSG_PROBE)
pr_info("Found PHY %04x:%04x at address %d\n",
id1, id2, i);
}
lp->a->write_bcr(ioaddr, 33, (lp->mii_if.phy_id) << 5); if (lp->phycount > 1)
lp->options |= PCNET32_PORT_MII;
}
netdev_lock(dev);
spin_lock_irqsave(&lp->lock, flags); /* Check for a valid station address */ if (!is_valid_ether_addr(dev->dev_addr)) {
rc = -EINVAL; goto err_free_irq;
}
/* Reset the PCNET32 */
lp->a->reset(ioaddr);
/* switch pcnet32 to 32bit mode */
lp->a->write_bcr(ioaddr, 20, 2);
/* set/reset autoselect bit */
val = lp->a->read_bcr(ioaddr, 2) & ~2; if (lp->options & PCNET32_PORT_ASEL)
val |= 2;
lp->a->write_bcr(ioaddr, 2, val);
/* handle full duplex setting */ if (lp->mii_if.full_duplex) {
val = lp->a->read_bcr(ioaddr, 9) & ~3; if (lp->options & PCNET32_PORT_FD) {
val |= 1; if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI))
val |= 2;
} elseif (lp->options & PCNET32_PORT_ASEL) { /* workaround of xSeries250, turn on for 79C975 only */ if (lp->chip_version == 0x2627)
val |= 3;
}
lp->a->write_bcr(ioaddr, 9, val);
}
/* set/reset GPSI bit in test register */
val = lp->a->read_csr(ioaddr, 124) & ~0x10; if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI)
val |= 0x10;
lp->a->write_csr(ioaddr, 124, val);
/* Allied Telesyn AT 2700/2701 FX are 100Mbit only and do not negotiate */ if (pdev && pdev->subsystem_vendor == PCI_VENDOR_ID_AT &&
(pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
pdev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) { if (lp->options & PCNET32_PORT_ASEL) {
lp->options = PCNET32_PORT_FD | PCNET32_PORT_100;
netif_printk(lp, link, KERN_DEBUG, dev, "Setting 100Mb-Full Duplex\n");
}
} if (lp->phycount < 2) { /* *24Jun2004accordingAMD,inordertochangethePHY, *DANAS(orDISPMfor79C976)mustbeset;thenselectthespeed, *duplex,and/orenableautonegotiation,andclearDANAS
*/ if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
lp->a->write_bcr(ioaddr, 32,
lp->a->read_bcr(ioaddr, 32) | 0x0080); /* disable Auto Negotiation, set 10Mpbs, HD */
val = lp->a->read_bcr(ioaddr, 32) & ~0xb8; if (lp->options & PCNET32_PORT_FD)
val |= 0x10; if (lp->options & PCNET32_PORT_100)
val |= 0x08;
lp->a->write_bcr(ioaddr, 32, val);
} else { if (lp->options & PCNET32_PORT_ASEL) {
lp->a->write_bcr(ioaddr, 32,
lp->a->read_bcr(ioaddr, 32) | 0x0080); /* enable auto negotiate, setup, disable fd */
val = lp->a->read_bcr(ioaddr, 32) & ~0x98;
val |= 0x20;
lp->a->write_bcr(ioaddr, 32, val);
}
}
} else { int first_phy = -1;
u16 bmcr;
u32 bcr9; struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET };
/* *ThereisreallynogoodotherwaytohandlemultiplePHYs *otherthanturningoffallautomatics
*/
val = lp->a->read_bcr(ioaddr, 2);
lp->a->write_bcr(ioaddr, 2, val & ~2);
val = lp->a->read_bcr(ioaddr, 32);
lp->a->write_bcr(ioaddr, 32, val & ~(1 << 7)); /* stop MII manager */
if (pcnet32_init_ring(dev)) {
rc = -ENOMEM; goto err_free_ring;
}
napi_enable_locked(&lp->napi);
/* Re-initialize the PCNET32, and start it when done. */
lp->a->write_csr(ioaddr, 1, (lp->init_dma_addr & 0xffff));
lp->a->write_csr(ioaddr, 2, (lp->init_dma_addr >> 16));
lp->a->write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */
lp->a->write_csr(ioaddr, CSR0, CSR0_INIT);
netif_start_queue(dev);
if (lp->chip_version >= PCNET32_79C970A) { /* Print the link status and start the watchdog */
pcnet32_check_media(dev, 1);
mod_timer(&lp->watchdog_timer, PCNET32_WATCHDOG_TIMEOUT);
}
i = 0; while (i++ < 100) if (lp->a->read_csr(ioaddr, CSR0) & CSR0_IDON) break; /* *WeusedtocleartheInitDonebit,0x0100,herebutMarkStockton *reportsthatdoingsotriggersabuginthe'974.
*/
lp->a->write_csr(ioaddr, CSR0, CSR0_NORMAL);
netif_printk(lp, ifup, KERN_DEBUG, dev, "pcnet32 open after %d ticks, init block %#x csr0 %4.4x\n",
i,
(u32) (lp->init_dma_addr),
lp->a->read_csr(ioaddr, CSR0));
for (i = 0; i < lp->rx_ring_size; i++) { struct sk_buff *rx_skbuff = lp->rx_skbuff[i]; if (!rx_skbuff) {
lp->rx_skbuff[i] = netdev_alloc_skb(dev, PKT_BUF_SKB);
rx_skbuff = lp->rx_skbuff[i]; if (!rx_skbuff) { /* there is not much we can do at this point */
netif_err(lp, drv, dev, "%s netdev_alloc_skb failed\n",
__func__); return -1;
}
skb_reserve(rx_skbuff, NET_IP_ALIGN);
}
rmb(); if (lp->rx_dma_addr[i] == 0) {
lp->rx_dma_addr[i] =
dma_map_single(&lp->pci_dev->dev, rx_skbuff->data,
PKT_BUF_SIZE, DMA_FROM_DEVICE); if (dma_mapping_error(&lp->pci_dev->dev, lp->rx_dma_addr[i])) { /* there is not much we can do at this point */
netif_err(lp, drv, dev, "%s pci dma mapping error\n",
__func__); return -1;
}
}
lp->rx_ring[i].base = cpu_to_le32(lp->rx_dma_addr[i]);
lp->rx_ring[i].buf_length = cpu_to_le16(NEG_BUF_SIZE);
wmb(); /* Make sure owner changes after all others are visible */
lp->rx_ring[i].status = cpu_to_le16(0x8000);
} /* The Tx buffer address is filled in as needed, but we do need to clear
* the upper ownership bit. */ for (i = 0; i < lp->tx_ring_size; i++) {
lp->tx_ring[i].status = 0; /* CPU owns buffer */
wmb(); /* Make sure adapter sees owner change */
lp->tx_ring[i].base = 0;
lp->tx_dma_addr[i] = 0;
}
lp->init_block->tlen_rlen =
cpu_to_le16(lp->tx_len_bits | lp->rx_len_bits); for (i = 0; i < 6; i++)
lp->init_block->phys_addr[i] = dev->dev_addr[i];
lp->init_block->rx_ring = cpu_to_le32(lp->rx_ring_dma_addr);
lp->init_block->tx_ring = cpu_to_le32(lp->tx_ring_dma_addr);
wmb(); /* Make sure all changes are visible */ return0;
}
/* the pcnet32 has been issued a stop or reset. Wait for the stop bit *thenflushthependingtransmitoperations,re-initializethering, *andtellthechiptoinitialize.
*/ staticvoid pcnet32_restart(struct net_device *dev, unsignedint csr0_bits)
{ struct pcnet32_private *lp = netdev_priv(dev); unsignedlong ioaddr = dev->base_addr; int i;
/* wait for stop */ for (i = 0; i < 100; i++) if (lp->a->read_csr(ioaddr, CSR0) & CSR0_STOP) break;
if (i >= 100)
netif_err(lp, drv, dev, "%s timed out waiting for stop\n",
__func__);
pcnet32_purge_tx_ring(dev); if (pcnet32_init_ring(dev)) return;
/* ReInit Ring */
lp->a->write_csr(ioaddr, CSR0, CSR0_INIT);
i = 0; while (i++ < 1000) if (lp->a->read_csr(ioaddr, CSR0) & CSR0_IDON) break;
/* This routine assumes that the lp->lock is held */ staticint mdio_read(struct net_device *dev, int phy_id, int reg_num)
{ struct pcnet32_private *lp = netdev_priv(dev); unsignedlong ioaddr = dev->base_addr;
u16 val_out;
/* This routine assumes that the lp->lock is held */ staticvoid mdio_write(struct net_device *dev, int phy_id, int reg_num, int val)
{ struct pcnet32_private *lp = netdev_priv(dev); unsignedlong ioaddr = dev->base_addr;
staticint pcnet32_check_otherphy(struct net_device *dev)
{ struct pcnet32_private *lp = netdev_priv(dev); struct mii_if_info mii = lp->mii_if;
u16 bmcr; int i;
for (i = 0; i < PCNET32_MAX_PHYS; i++) { if (i == lp->mii_if.phy_id) continue; /* skip active phy */ if (lp->phymask & (1 << i)) {
mii.phy_id = i; if (mii_link_ok(&mii)) { /* found PHY with active link */
netif_info(lp, link, dev, "Using PHY number %d\n",
i);
/* Print the link status if it has changed */
spin_lock_irqsave(&lp->lock, flags);
pcnet32_check_media(dev, 0);
spin_unlock_irqrestore(&lp->lock, flags);
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.