void pnic2_lnk_change(/*RTnet*/struct rtnet_device *rtdev, int csr5) { struct net_device *dev = rtdev->dev; struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; int csr14; /* read the staus register to find out what is up */ int csr12 = inl(ioaddr + CSR12); if (tulip_debug > 1) /*RTnet*/rt_printk(KERN_INFO"%s: PNIC2 link status interrupt %8.8x, " " CSR5 %x, %8.8x.\n", dev->name, csr12, csr5, inl(ioaddr + CSR14)); /* If NWay finished and we have a negotiated partner capability. * check bits 14:12 for bit pattern 101 - all is good */ if (tp->nway && !tp->nwayset) { /* we did an auto negotiation */ if ((csr12 & 0x7000) == 0x5000) { /* negotiation ended successfully */ /* get the link partners reply and mask out all but * bits 24-21 which show the partners capabilites * and match those to what we advertised * * then begin to interpret the results of the negotiation. * Always go in this order : (we are ignoring T4 for now) * 100baseTx-FD, 100baseTx-HD, 10baseT-FD, 10baseT-HD */ int negotiated = ((csr12 >> 16) & 0x01E0) & tp->sym_advertise; tp->lpar = (csr12 >> 16); tp->nwayset = 1; if (negotiated & 0x0100) dev->if_port = 5; else if (negotiated & 0x0080) dev->if_port = 3; else if (negotiated & 0x0040) dev->if_port = 4; else if (negotiated & 0x0020) dev->if_port = 0; else { if (tulip_debug > 1) /*RTnet*/rt_printk(KERN_INFO "%s: funny autonegotiate result " "csr12 %8.8x advertising %4.4x\n", dev->name, csr12, tp->sym_advertise); tp->nwayset = 0; /* so check if 100baseTx link state is okay */ if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180)) dev->if_port = 3; } /* now record the duplex that was negotiated */ tp->full_duplex = 0; if ((dev->if_port == 4) || (dev->if_port == 5)) tp->full_duplex = 1; if (tulip_debug > 1) { if (tp->nwayset) /*RTnet*/rt_printk(KERN_INFO "%s: Switching to %s based on link " "negotiation %4.4x & %4.4x = %4.4x.\n", dev->name, medianame[dev->if_port], tp->sym_advertise, tp->lpar, negotiated); } /* remember to turn off bit 7 - autonegotiate * enable so we can properly end nway mode and * set duplex (ie. use csr6<9> again) */ csr14 = (inl(ioaddr + CSR14) & 0xffffff7f); outl(csr14,ioaddr + CSR14); /* now set the data port and operating mode * (see the Data Port Selection comments at * the top of the file */ /* get current csr6 and mask off bits not to touch */ /* see comment at top of file */ tp->csr6 = (inl(ioaddr + CSR6) & 0xfe3bd1fd); /* so if using if_port 3 or 5 then select the 100baseT * port else select the 10baseT port. * See the Data Port Selection table at the top * of the file which was taken from the PNIC_II.PDF * datasheet */ if (dev->if_port & 1) tp->csr6 |= 0x01840000; else tp->csr6 |= 0x00400000; /* now set the full duplex bit appropriately */ if (tp->full_duplex) tp->csr6 |= 0x00000200; outl(1, ioaddr + CSR13); if (tulip_debug > 2) /*RTnet*/rt_printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 " "%8.8x.\n", dev->name, tp->csr6, inl(ioaddr + CSR6), inl(ioaddr + CSR12)); /* now the following actually writes out the * new csr6 values */ tulip_start_rxtx(tp); return; } else {
void t21142_lnk_change(struct net_device *dev, int csr5) { struct tulip_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->base_addr; int csr12 = ioread32(ioaddr + CSR12); int csr14 = ioread32(ioaddr + CSR14); /* CSR12[LS10,LS100] are not reliable during autonegotiation */ if ((csr14 & 0x80) && (csr12 & 0x7000) != 0x5000) csr12 |= 6; if (tulip_debug > 1) dev_info(&dev->dev, "21143 link status interrupt %08x, CSR5 %x, %08x\n", csr12, csr5, csr14); /* If NWay finished and we have a negotiated partner capability. */ if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) { int setup_done = 0; int negotiated = tp->sym_advertise & (csr12 >> 16); tp->lpar = csr12 >> 16; tp->nwayset = 1; /* If partner cannot negotiate, it is 10Mbps Half Duplex */ if (!(csr12 & 0x8000)) dev->if_port = 0; else if (negotiated & 0x0100) dev->if_port = 5; else if (negotiated & 0x0080) dev->if_port = 3; else if (negotiated & 0x0040) dev->if_port = 4; else if (negotiated & 0x0020) dev->if_port = 0; else { tp->nwayset = 0; if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180)) dev->if_port = 3; } tp->full_duplex = (tulip_media_cap[dev->if_port] & MediaAlwaysFD) ? 1:0; if (tulip_debug > 1) { if (tp->nwayset) dev_info(&dev->dev, "Switching to %s based on link negotiation %04x & %04x = %04x\n", medianame[dev->if_port], tp->sym_advertise, tp->lpar, negotiated); else dev_info(&dev->dev, "Autonegotiation failed, using %s, link beat status %04x\n", medianame[dev->if_port], csr12); } if (tp->mtable) { int i; for (i = 0; i < tp->mtable->leafcount; i++) if (tp->mtable->mleaf[i].media == dev->if_port) { int startup = ! ((tp->chip_id == DC21143 && (tp->revision == 48 || tp->revision == 65))); tp->cur_index = i; tulip_select_media(dev, startup); setup_done = 1; break; } } if ( ! setup_done) { tp->csr6 = (dev->if_port & 1 ? 0x838E0000 : 0x82420000) | (tp->csr6 & 0x20ff); if (tp->full_duplex) tp->csr6 |= 0x0200; iowrite32(1, ioaddr + CSR13); } #if 0 /* Restart shouldn't be needed. */ iowrite32(tp->csr6 | RxOn, ioaddr + CSR6); if (tulip_debug > 2) netdev_dbg(dev, " Restarting Tx and Rx, CSR5 is %08x\n", ioread32(ioaddr + CSR5)); #endif tulip_start_rxtx(tp); if (tulip_debug > 2) netdev_dbg(dev, " Setting CSR6 %08x/%x CSR12 %08x\n", tp->csr6, ioread32(ioaddr + CSR6), ioread32(ioaddr + CSR12)); } else if ((tp->nwayset && (csr5 & 0x08000000) &&
static int tulip_rx(/*RTnet*/struct rtnet_device *rtdev, nanosecs_t *time_stamp) { struct tulip_private *tp = (struct tulip_private *)rtdev->priv; int entry = tp->cur_rx % RX_RING_SIZE; int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx; int received = 0; if (tulip_debug > 4) /*RTnet*/rtdm_printk(KERN_DEBUG " In tulip_rx(), entry %d %8.8x.\n", entry, tp->rx_ring[entry].status); /* If we own the next entry, it is a new packet. Send it up. */ while ( ! (tp->rx_ring[entry].status & cpu_to_le32(DescOwned))) { s32 status = le32_to_cpu(tp->rx_ring[entry].status); if (tulip_debug > 5) /*RTnet*/rtdm_printk(KERN_DEBUG "%s: In tulip_rx(), entry %d %8.8x.\n", rtdev->name, entry, status); if (--rx_work_limit < 0) break; if ((status & 0x38008300) != 0x0300) { if ((status & 0x38000300) != 0x0300) { /* Ingore earlier buffers. */ if ((status & 0xffff) != 0x7fff) { if (tulip_debug > 1) /*RTnet*/rtdm_printk(KERN_WARNING "%s: Oversized Ethernet frame " "spanned multiple buffers, status %8.8x!\n", rtdev->name, status); tp->stats.rx_length_errors++; } } else if (status & RxDescFatalErr) { /* There was a fatal error. */ if (tulip_debug > 2) /*RTnet*/rtdm_printk(KERN_DEBUG "%s: Receive error, Rx status %8.8x.\n", rtdev->name, status); tp->stats.rx_errors++; /* end of a packet.*/ if (status & 0x0890) tp->stats.rx_length_errors++; if (status & 0x0004) tp->stats.rx_frame_errors++; if (status & 0x0002) tp->stats.rx_crc_errors++; if (status & 0x0001) tp->stats.rx_fifo_errors++; } } else { /* Omit the four octet CRC from the length. */ short pkt_len = ((status >> 16) & 0x7ff) - 4; struct /*RTnet*/rtskb *skb; #ifndef final_version if (pkt_len > 1518) { /*RTnet*/rtdm_printk(KERN_WARNING "%s: Bogus packet size of %d (%#x).\n", rtdev->name, pkt_len, pkt_len); pkt_len = 1518; tp->stats.rx_length_errors++; } #endif #if 0 /*RTnet*/ /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ if (pkt_len < tulip_rx_copybreak && (skb = /*RTnet*/dev_alloc_rtskb(pkt_len + 2)) != NULL) { skb->rtdev = rtdev; /*RTnet*/rtskb_reserve(skb, 2); /* 16 byte align the IP header */ pci_dma_sync_single(tp->pdev, tp->rx_buffers[entry].mapping, pkt_len, PCI_DMA_FROMDEVICE); #if ! defined(__alpha__) //eth_copy_and_sum(skb, tp->rx_buffers[entry].skb->tail, // pkt_len, 0); memcpy(rtskb_put(skb, pkt_len), tp->rx_buffers[entry].skb->tail, pkt_len); #else memcpy(/*RTnet*/rtskb_put(skb, pkt_len), tp->rx_buffers[entry].skb->tail, pkt_len); #endif } else { /* Pass up the skb already on the Rx ring. */ #endif /*RTnet*/ { char *temp = /*RTnet*/rtskb_put(skb = tp->rx_buffers[entry].skb, pkt_len); #ifndef final_version if (tp->rx_buffers[entry].mapping != le32_to_cpu(tp->rx_ring[entry].buffer1)) { /*RTnet*/rtdm_printk(KERN_ERR "%s: Internal fault: The skbuff addresses " "do not match in tulip_rx: %08x vs. %08x ? / %p.\n", rtdev->name, le32_to_cpu(tp->rx_ring[entry].buffer1), tp->rx_buffers[entry].mapping, temp);/*RTnet*/ } #endif pci_unmap_single(tp->pdev, tp->rx_buffers[entry].mapping, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); tp->rx_buffers[entry].skb = NULL; tp->rx_buffers[entry].mapping = 0; } skb->protocol = /*RTnet*/rt_eth_type_trans(skb, rtdev); skb->time_stamp = *time_stamp; /*RTnet*/rtnetif_rx(skb); tp->stats.rx_packets++; tp->stats.rx_bytes += pkt_len; } received++; entry = (++tp->cur_rx) % RX_RING_SIZE; } return received; } /* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ int tulip_interrupt(rtdm_irq_t *irq_handle) { nanosecs_t time_stamp = rtdm_clock_read();/*RTnet*/ struct rtnet_device *rtdev = rtdm_irq_get_arg(irq_handle, struct rtnet_device);/*RTnet*/ struct tulip_private *tp = (struct tulip_private *)rtdev->priv; long ioaddr = rtdev->base_addr; unsigned int csr5; int entry; int missed; int rx = 0; int tx = 0; int oi = 0; int maxrx = RX_RING_SIZE; int maxtx = TX_RING_SIZE; int maxoi = TX_RING_SIZE; unsigned int work_count = tulip_max_interrupt_work; /* Let's see whether the interrupt really is for us */ csr5 = inl(ioaddr + CSR5); if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) { rtdm_printk("%s: unexpected IRQ!\n",rtdev->name); return 0; } tp->nir++; do { /* Acknowledge all of the current interrupt sources ASAP. */ outl(csr5 & 0x0001ffff, ioaddr + CSR5); if (tulip_debug > 4) /*RTnet*/rtdm_printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", rtdev->name, csr5, inl(rtdev->base_addr + CSR5)); if (csr5 & (RxIntr | RxNoBuf)) { rx += tulip_rx(rtdev, &time_stamp); tulip_refill_rx(rtdev); } if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { unsigned int dirty_tx; rtdm_lock_get(&tp->lock); for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { int entry = dirty_tx % TX_RING_SIZE; int status = le32_to_cpu(tp->tx_ring[entry].status); if (status < 0) break; /* It still has not been Txed */ /* Check for Rx filter setup frames. */ if (tp->tx_buffers[entry].skb == NULL) { /* test because dummy frames not mapped */ if (tp->tx_buffers[entry].mapping) pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, sizeof(tp->setup_frame), PCI_DMA_TODEVICE); continue; } if (status & 0x8000) { /* There was an major error, log it. */ #ifndef final_version if (tulip_debug > 1) /*RTnet*/rtdm_printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", rtdev->name, status); #endif tp->stats.tx_errors++; if (status & 0x4104) tp->stats.tx_aborted_errors++; if (status & 0x0C00) tp->stats.tx_carrier_errors++; if (status & 0x0200) tp->stats.tx_window_errors++; if (status & 0x0002) tp->stats.tx_fifo_errors++; if ((status & 0x0080) && tp->full_duplex == 0) tp->stats.tx_heartbeat_errors++; } else { tp->stats.tx_bytes += tp->tx_buffers[entry].skb->len; tp->stats.collisions += (status >> 3) & 15; tp->stats.tx_packets++; } pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, tp->tx_buffers[entry].skb->len, PCI_DMA_TODEVICE); /* Free the original skb. */ /*RTnet*/dev_kfree_rtskb(tp->tx_buffers[entry].skb); tp->tx_buffers[entry].skb = NULL; tp->tx_buffers[entry].mapping = 0; tx++; rtnetif_tx(rtdev); } #ifndef final_version if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { /*RTnet*/rtdm_printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", rtdev->name, dirty_tx, tp->cur_tx); dirty_tx += TX_RING_SIZE; } #endif if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) /*RTnet*/rtnetif_wake_queue(rtdev); tp->dirty_tx = dirty_tx; if (csr5 & TxDied) { if (tulip_debug > 2) /*RTnet*/rtdm_printk(KERN_WARNING "%s: The transmitter stopped." " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", rtdev->name, csr5, inl(ioaddr + CSR6), tp->csr6); tulip_restart_rxtx(tp); } rtdm_lock_put(&tp->lock); } /* Log errors. */ if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ if (csr5 == 0xffffffff) break; #if 0 /*RTnet*/ if (csr5 & TxJabber) tp->stats.tx_errors++; if (csr5 & TxFIFOUnderflow) { if ((tp->csr6 & 0xC000) != 0xC000) tp->csr6 += 0x4000; /* Bump up the Tx threshold */ else tp->csr6 |= 0x00200000; /* Store-n-forward. */ /* Restart the transmit process. */ tulip_restart_rxtx(tp); outl(0, ioaddr + CSR1); } if (csr5 & (RxDied | RxNoBuf)) { if (tp->flags & COMET_MAC_ADDR) { outl(tp->mc_filter[0], ioaddr + 0xAC); outl(tp->mc_filter[1], ioaddr + 0xB0); } } if (csr5 & RxDied) { /* Missed a Rx frame. */ tp->stats.rx_missed_errors += inl(ioaddr + CSR8) & 0xffff; tp->stats.rx_errors++; tulip_start_rxtx(tp); } /* * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this * call is ever done under the spinlock */ if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { if (tp->link_change) (tp->link_change)(rtdev, csr5); } if (csr5 & SytemError) { int error = (csr5 >> 23) & 7; /* oops, we hit a PCI error. The code produced corresponds * to the reason: * 0 - parity error * 1 - master abort * 2 - target abort * Note that on parity error, we should do a software reset * of the chip to get it back into a sane state (according * to the 21142/3 docs that is). * -- rmk */ /*RTnet*/rtdm_printk(KERN_ERR "%s: (%lu) System Error occured (%d)\n", rtdev->name, tp->nir, error); } #endif /*RTnet*/ /*RTnet*/rtdm_printk(KERN_ERR "%s: Error detected, " "device may not work any more (csr5=%08x)!\n", rtdev->name, csr5); /* Clear all error sources, included undocumented ones! */ outl(0x0800f7ba, ioaddr + CSR5); oi++; }
void t21142_lnk_change(struct net_device *dev, int csr5) { struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; int csr12 = inl(ioaddr + CSR12); if (tulip_debug > 1) printk(KERN_INFO"%s: 21143 link status interrupt %8.8x, CSR5 %x, " "%8.8x.\n", dev->name, csr12, csr5, inl(ioaddr + CSR14)); /* If NWay finished and we have a negotiated partner capability. */ if (tp->nway && !tp->nwayset && (csr12 & 0x7000) == 0x5000) { int setup_done = 0; int negotiated = tp->sym_advertise & (csr12 >> 16); tp->lpar = csr12 >> 16; tp->nwayset = 1; if (negotiated & 0x0100) dev->if_port = 5; else if (negotiated & 0x0080) dev->if_port = 3; else if (negotiated & 0x0040) dev->if_port = 4; else if (negotiated & 0x0020) dev->if_port = 0; else { tp->nwayset = 0; if ((csr12 & 2) == 0 && (tp->sym_advertise & 0x0180)) dev->if_port = 3; } tp->full_duplex = (tulip_media_cap[dev->if_port] & MediaAlwaysFD) ? 1:0; if (tulip_debug > 1) { if (tp->nwayset) printk(KERN_INFO "%s: Switching to %s based on link " "negotiation %4.4x & %4.4x = %4.4x.\n", dev->name, medianame[dev->if_port], tp->sym_advertise, tp->lpar, negotiated); else printk(KERN_INFO "%s: Autonegotiation failed, using %s," " link beat status %4.4x.\n", dev->name, medianame[dev->if_port], csr12); } if (tp->mtable) { int i; for (i = 0; i < tp->mtable->leafcount; i++) if (tp->mtable->mleaf[i].media == dev->if_port) { int startup = ! ((tp->chip_id == DC21143 && tp->revision == 65)); tp->cur_index = i; tulip_select_media(dev, startup); setup_done = 1; break; } } if ( ! setup_done) { tp->csr6 = (dev->if_port & 1 ? 0x838E0000 : 0x82420000) | (tp->csr6 & 0x20ff); if (tp->full_duplex) tp->csr6 |= 0x0200; outl(1, ioaddr + CSR13); } #if 0 /* Restart shouldn't be needed. */ outl(tp->csr6 | RxOn, ioaddr + CSR6); if (tulip_debug > 2) printk(KERN_DEBUG "%s: Restarting Tx and Rx, CSR5 is %8.8x.\n", dev->name, inl(ioaddr + CSR5)); #endif tulip_start_rxtx(tp); if (tulip_debug > 2) printk(KERN_DEBUG "%s: Setting CSR6 %8.8x/%x CSR12 %8.8x.\n", dev->name, tp->csr6, inl(ioaddr + CSR6), inl(ioaddr + CSR12)); } else if ((tp->nwayset && (csr5 & 0x08000000)
/* The interrupt handler does all of the Rx thread work and cleans up after the Tx thread. */ irqreturn_t tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs) { struct net_device *dev = (struct net_device *)dev_instance; struct tulip_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->base_addr; int csr5; int missed; int rx = 0; int tx = 0; int oi = 0; int maxrx = RX_RING_SIZE; int maxtx = TX_RING_SIZE; int maxoi = TX_RING_SIZE; #ifdef CONFIG_TULIP_NAPI int rxd = 0; #else int entry; #endif unsigned int work_count = tulip_max_interrupt_work; unsigned int handled = 0; /* Let's see whether the interrupt really is for us */ csr5 = ioread32(ioaddr + CSR5); if (tp->flags & HAS_PHY_IRQ) handled = phy_interrupt (dev); if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) return IRQ_RETVAL(handled); tp->nir++; do { #ifdef CONFIG_TULIP_NAPI if (!rxd && (csr5 & (RxIntr | RxNoBuf))) { rxd++; /* Mask RX intrs and add the device to poll list. */ iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7); netif_rx_schedule(dev); if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass))) break; } /* Acknowledge the interrupt sources we handle here ASAP the poll function does Rx and RxNoBuf acking */ iowrite32(csr5 & 0x0001ff3f, ioaddr + CSR5); #else /* Acknowledge all of the current interrupt sources ASAP. */ iowrite32(csr5 & 0x0001ffff, ioaddr + CSR5); if (csr5 & (RxIntr | RxNoBuf)) { rx += tulip_rx(dev); tulip_refill_rx(dev); } #endif /* CONFIG_TULIP_NAPI */ if (tulip_debug > 4) printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", dev->name, csr5, ioread32(ioaddr + CSR5)); if (csr5 & (TxNoBuf | TxDied | TxIntr | TimerInt)) { unsigned int dirty_tx; spin_lock(&tp->lock); for (dirty_tx = tp->dirty_tx; tp->cur_tx - dirty_tx > 0; dirty_tx++) { int entry = dirty_tx % TX_RING_SIZE; int status = le32_to_cpu(tp->tx_ring[entry].status); if (status < 0) break; /* It still has not been Txed */ /* Check for Rx filter setup frames. */ if (tp->tx_buffers[entry].skb == NULL) { /* test because dummy frames not mapped */ if (tp->tx_buffers[entry].mapping) pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, sizeof(tp->setup_frame), PCI_DMA_TODEVICE); continue; } if (status & 0x8000) { /* There was an major error, log it. */ #ifndef final_version if (tulip_debug > 1) printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n", dev->name, status); #endif tp->stats.tx_errors++; if (status & 0x4104) tp->stats.tx_aborted_errors++; if (status & 0x0C00) tp->stats.tx_carrier_errors++; if (status & 0x0200) tp->stats.tx_window_errors++; if (status & 0x0002) tp->stats.tx_fifo_errors++; if ((status & 0x0080) && tp->full_duplex == 0) tp->stats.tx_heartbeat_errors++; } else { tp->stats.tx_bytes += tp->tx_buffers[entry].skb->len; tp->stats.collisions += (status >> 3) & 15; tp->stats.tx_packets++; } pci_unmap_single(tp->pdev, tp->tx_buffers[entry].mapping, tp->tx_buffers[entry].skb->len, PCI_DMA_TODEVICE); /* Free the original skb. */ dev_kfree_skb_irq(tp->tx_buffers[entry].skb); tp->tx_buffers[entry].skb = NULL; tp->tx_buffers[entry].mapping = 0; tx++; } #ifndef final_version if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", dev->name, dirty_tx, tp->cur_tx); dirty_tx += TX_RING_SIZE; } #endif if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) netif_wake_queue(dev); tp->dirty_tx = dirty_tx; if (csr5 & TxDied) { if (tulip_debug > 2) printk(KERN_WARNING "%s: The transmitter stopped." " CSR5 is %x, CSR6 %x, new CSR6 %x.\n", dev->name, csr5, ioread32(ioaddr + CSR6), tp->csr6); tulip_restart_rxtx(tp); } spin_unlock(&tp->lock); } /* Log errors. */ if (csr5 & AbnormalIntr) { /* Abnormal error summary bit. */ if (csr5 == 0xffffffff) break; if (csr5 & TxJabber) tp->stats.tx_errors++; if (csr5 & TxFIFOUnderflow) { if ((tp->csr6 & 0xC000) != 0xC000) tp->csr6 += 0x4000; /* Bump up the Tx threshold */ else tp->csr6 |= 0x00200000; /* Store-n-forward. */ /* Restart the transmit process. */ tulip_restart_rxtx(tp); iowrite32(0, ioaddr + CSR1); } if (csr5 & (RxDied | RxNoBuf)) { if (tp->flags & COMET_MAC_ADDR) { iowrite32(tp->mc_filter[0], ioaddr + 0xAC); iowrite32(tp->mc_filter[1], ioaddr + 0xB0); } } if (csr5 & RxDied) { /* Missed a Rx frame. */ tp->stats.rx_missed_errors += ioread32(ioaddr + CSR8) & 0xffff; tp->stats.rx_errors++; tulip_start_rxtx(tp); } /* * NB: t21142_lnk_change() does a del_timer_sync(), so be careful if this * call is ever done under the spinlock */ if (csr5 & (TPLnkPass | TPLnkFail | 0x08000000)) { if (tp->link_change) (tp->link_change)(dev, csr5); } if (csr5 & SytemError) { int error = (csr5 >> 23) & 7; /* oops, we hit a PCI error. The code produced corresponds * to the reason: * 0 - parity error * 1 - master abort * 2 - target abort * Note that on parity error, we should do a software reset * of the chip to get it back into a sane state (according * to the 21142/3 docs that is). * -- rmk */ printk(KERN_ERR "%s: (%lu) System Error occurred (%d)\n", dev->name, tp->nir, error); } /* Clear all error sources, included undocumented ones! */ iowrite32(0x0800f7ba, ioaddr + CSR5); oi++; }
static void tulip_up(/*RTnet*/struct rtnet_device *rtdev) { struct tulip_private *tp = (struct tulip_private *)rtdev->priv; long ioaddr = rtdev->base_addr; int i; /* Wake the chip from sleep/snooze mode. */ tulip_set_power_state (tp, 0, 0); /* On some chip revs we must set the MII/SYM port before the reset!? */ if (tp->mii_cnt || (tp->mtable && tp->mtable->has_mii)) outl(0x00040000, ioaddr + CSR6); /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ outl(0x00000001, ioaddr + CSR0); udelay(100); /* Deassert reset. Wait the specified 50 PCI cycles after a reset by initializing Tx and Rx queues and the address filter list. */ outl(tp->csr0, ioaddr + CSR0); udelay(100); if (tulip_debug > 1) printk(KERN_DEBUG "%s: tulip_up(), irq==%d.\n", rtdev->name, rtdev->irq); outl(tp->rx_ring_dma, ioaddr + CSR3); outl(tp->tx_ring_dma, ioaddr + CSR4); tp->cur_rx = tp->cur_tx = 0; tp->dirty_rx = tp->dirty_tx = 0; if (tp->flags & MC_HASH_ONLY) { u32 addr_low = cpu_to_le32(get_unaligned((u32 *)rtdev->dev_addr)); u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(rtdev->dev_addr+4))); if (tp->chip_id == AX88140) { outl(0, ioaddr + CSR13); outl(addr_low, ioaddr + CSR14); outl(1, ioaddr + CSR13); outl(addr_high, ioaddr + CSR14); } else if (tp->flags & COMET_MAC_ADDR) { outl(addr_low, ioaddr + 0xA4); outl(addr_high, ioaddr + 0xA8); outl(0, ioaddr + 0xAC); outl(0, ioaddr + 0xB0); } } else { /* This is set_rx_mode(), but without starting the transmitter. */ u16 *eaddrs = (u16 *)rtdev->dev_addr; u16 *setup_frm = &tp->setup_frame[15*6]; dma_addr_t mapping; /* 21140 bug: you must add the broadcast address. */ memset(tp->setup_frame, 0xff, sizeof(tp->setup_frame)); /* Fill the final entry of the table with our physical address. */ *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; mapping = pci_map_single(tp->pdev, tp->setup_frame, sizeof(tp->setup_frame), PCI_DMA_TODEVICE); tp->tx_buffers[tp->cur_tx].skb = NULL; tp->tx_buffers[tp->cur_tx].mapping = mapping; /* Put the setup frame on the Tx list. */ tp->tx_ring[tp->cur_tx].length = cpu_to_le32(0x08000000 | 192); tp->tx_ring[tp->cur_tx].buffer1 = cpu_to_le32(mapping); tp->tx_ring[tp->cur_tx].status = cpu_to_le32(DescOwned); tp->cur_tx++; } tp->saved_if_port = rtdev->if_port; if (rtdev->if_port == 0) rtdev->if_port = tp->default_port; /* Allow selecting a default media. */ i = 0; if (tp->mtable == NULL) goto media_picked; if (rtdev->if_port) { int looking_for = tulip_media_cap[rtdev->if_port] & MediaIsMII ? 11 : (rtdev->if_port == 12 ? 0 : rtdev->if_port); for (i = 0; i < tp->mtable->leafcount; i++) if (tp->mtable->mleaf[i].media == looking_for) { printk(KERN_INFO "%s: Using user-specified media %s.\n", rtdev->name, medianame[rtdev->if_port]); goto media_picked; } } if ((tp->mtable->defaultmedia & 0x0800) == 0) { int looking_for = tp->mtable->defaultmedia & MEDIA_MASK; for (i = 0; i < tp->mtable->leafcount; i++) if (tp->mtable->mleaf[i].media == looking_for) { printk(KERN_INFO "%s: Using EEPROM-set media %s.\n", rtdev->name, medianame[looking_for]); goto media_picked; } } /* Start sensing first non-full-duplex media. */ for (i = tp->mtable->leafcount - 1; (tulip_media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--) ; media_picked: tp->csr6 = 0; tp->cur_index = i; tp->nwayset = 0; if (rtdev->if_port) { if (tp->chip_id == DC21143 && (tulip_media_cap[rtdev->if_port] & MediaIsMII)) { /* We must reset the media CSRs when we force-select MII mode. */ outl(0x0000, ioaddr + CSR13); outl(0x0000, ioaddr + CSR14); outl(0x0008, ioaddr + CSR15); } tulip_select_media(rtdev, 1); } else if (tp->chip_id == DC21041) { rtdev->if_port = 0; tp->nway = tp->mediasense = 1; tp->nwayset = tp->lpar = 0; outl(0x00000000, ioaddr + CSR13); outl(0xFFFFFFFF, ioaddr + CSR14); outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */ tp->csr6 = 0x80020000; if (tp->sym_advertise & 0x0040) tp->csr6 |= FullDuplex; outl(tp->csr6, ioaddr + CSR6); outl(0x0000EF01, ioaddr + CSR13); } else if (tp->chip_id == DC21142) { if (tp->mii_cnt) { tulip_select_media(rtdev, 1); if (tulip_debug > 1) printk(KERN_INFO "%s: Using MII transceiver %d, status %4.4x.\n", rtdev->name, tp->phys[0], tulip_mdio_read(rtdev, tp->phys[0], 1)); outl(csr6_mask_defstate, ioaddr + CSR6); tp->csr6 = csr6_mask_hdcap; rtdev->if_port = 11; outl(0x0000, ioaddr + CSR13); outl(0x0000, ioaddr + CSR14); } else t21142_start_nway(rtdev); } else if (tp->chip_id == PNIC2) { /* for initial startup advertise 10/100 Full and Half */ tp->sym_advertise = 0x01E0; /* enable autonegotiate end interrupt */ outl(inl(ioaddr+CSR5)| 0x00008010, ioaddr + CSR5); outl(inl(ioaddr+CSR7)| 0x00008010, ioaddr + CSR7); pnic2_start_nway(rtdev); } else if (tp->chip_id == LC82C168 && ! tp->medialock) { if (tp->mii_cnt) { rtdev->if_port = 11; tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0); outl(0x0001, ioaddr + CSR15); } else if (inl(ioaddr + CSR5) & TPLnkPass) pnic_do_nway(rtdev); else { /* Start with 10mbps to do autonegotiation. */ outl(0x32, ioaddr + CSR12); tp->csr6 = 0x00420000; outl(0x0001B078, ioaddr + 0xB8); outl(0x0201B078, ioaddr + 0xB8); } } else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881) && ! tp->medialock) { rtdev->if_port = 0; tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0); outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); } else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) { /* Provided by BOLO, Macronix - 12/10/1998. */ rtdev->if_port = 0; tp->csr6 = 0x01a80200; outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80); outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0); } else if (tp->chip_id == COMET) { /* Enable automatic Tx underrun recovery. */ outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88); rtdev->if_port = tp->mii_cnt ? 11 : 0; tp->csr6 = 0x00040000; } else if (tp->chip_id == AX88140) { tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100; } else tulip_select_media(rtdev, 1); /* Start the chip's Tx to process setup frame. */ tulip_stop_rxtx(tp); barrier(); udelay(5); outl(tp->csr6 | TxOn, ioaddr + CSR6); /* Enable interrupts by setting the interrupt mask. */ outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5); outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7); tulip_start_rxtx(tp); outl(0, ioaddr + CSR2); /* Rx poll demand */ if (tulip_debug > 2) { printk(KERN_DEBUG "%s: Done tulip_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n", rtdev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5), inl(ioaddr + CSR6)); } }