📄 depca.c
字号:
lp->init_block.mode = 0x0000; /* Enable the Tx and Rx */ return;}/* ** Writes a socket buffer to TX descriptor ring and starts transmission */static intdepca_start_xmit(struct sk_buff *skb, struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_long ioaddr = dev->base_addr; int status = 0; /* Transmitter timeout, serious problems. */ if (dev->tbusy) { int tickssofar = jiffies - dev->trans_start; if (tickssofar < 1*HZ) { status = -1; } else { printk("%s: transmit timed out, status %04x, resetting.\n", dev->name, inw(DEPCA_DATA)); STOP_DEPCA; depca_init_ring(dev); LoadCSRs(dev); dev->interrupt = UNMASK_INTERRUPTS; dev->start = 1; dev->tbusy=0; dev->trans_start = jiffies; InitRestartDepca(dev); } return status; } else if (skb->len > 0) { /* Enforce 1 process per h/w access */ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { printk("%s: Transmitter access conflict.\n", dev->name); status = -1; } else { if (TX_BUFFS_AVAIL) { /* Fill in a Tx ring entry */ status = load_packet(dev, skb); if (!status) { /* Trigger an immediate send demand. */ outw(CSR0, DEPCA_ADDR); outw(INEA | TDMD, DEPCA_DATA); dev->trans_start = jiffies; dev_kfree_skb(skb); } if (TX_BUFFS_AVAIL) { dev->tbusy=0; } } else { status = -1; } } } return status;}/*** The DEPCA interrupt handler. */static voiddepca_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct device *dev = dev_id; struct depca_private *lp; s16 csr0, nicsr; u_long ioaddr; if (dev == NULL) { printk ("depca_interrupt(): irq %d for unknown device.\n", irq); } else { lp = (struct depca_private *)dev->priv; ioaddr = dev->base_addr; if (dev->interrupt) printk("%s: Re-entering the interrupt handler.\n", dev->name); dev->interrupt = MASK_INTERRUPTS; /* mask the DEPCA board interrupts and turn on the LED */ nicsr = inb(DEPCA_NICSR); nicsr |= (IM|LED); outb(nicsr, DEPCA_NICSR); outw(CSR0, DEPCA_ADDR); csr0 = inw(DEPCA_DATA); /* Acknowledge all of the current interrupt sources ASAP. */ outw(csr0 & INTE, DEPCA_DATA); if (csr0 & RINT) /* Rx interrupt (packet arrived) */ depca_rx(dev); if (csr0 & TINT) /* Tx interrupt (packet sent) */ depca_tx(dev); if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) { /* any resources available? */ dev->tbusy = 0; /* clear TX busy flag */ mark_bh(NET_BH); } /* Unmask the DEPCA board interrupts and turn off the LED */ nicsr = (nicsr & ~IM & ~LED); outb(nicsr, DEPCA_NICSR); dev->interrupt = UNMASK_INTERRUPTS; } return;}static intdepca_rx(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; int i, entry; s32 status; for (entry=lp->rx_new; !(readl(&lp->rx_ring[entry].base) & R_OWN); entry=lp->rx_new){ status = readl(&lp->rx_ring[entry].base) >> 16 ; if (status & R_STP) { /* Remember start of frame */ lp->rx_old = entry; } if (status & R_ENP) { /* Valid frame status */ if (status & R_ERR) { /* There was an error. */ lp->stats.rx_errors++; /* Update the error stats. */ if (status & R_FRAM) lp->stats.rx_frame_errors++; if (status & R_OFLO) lp->stats.rx_over_errors++; if (status & R_CRC) lp->stats.rx_crc_errors++; if (status & R_BUFF) lp->stats.rx_fifo_errors++; } else { short len, pkt_len = readw(&lp->rx_ring[entry].msg_length); struct sk_buff *skb; skb = dev_alloc_skb(pkt_len+2); if (skb != NULL) { unsigned char *buf; skb_reserve(skb,2); /* 16 byte align the IP header */ buf = skb_put(skb,pkt_len); skb->dev = dev; if (entry < lp->rx_old) { /* Wrapped buffer */ len = (lp->rxRingMask - lp->rx_old + 1) * RX_BUFF_SZ; memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], len); memcpy_fromio(buf + len, lp->rx_memcpy[0], pkt_len-len); } else { /* Linear buffer */ memcpy_fromio(buf, lp->rx_memcpy[lp->rx_old], pkt_len); } /* ** Notify the upper protocol layers that there is another ** packet to handle */ skb->protocol=eth_type_trans(skb,dev); netif_rx(skb); /* ** Update stats */ lp->stats.rx_packets++; for (i=1; i<DEPCA_PKT_STAT_SZ-1; i++) { if (pkt_len < (i*DEPCA_PKT_BIN_SZ)) { lp->pktStats.bins[i]++; i = DEPCA_PKT_STAT_SZ; } } if (buf[0] & 0x01) { /* Multicast/Broadcast */ if ((*(s16 *)&buf[0] == -1) && (*(s16 *)&buf[2] == -1) && (*(s16 *)&buf[4] == -1)) { lp->pktStats.broadcast++; } else { lp->pktStats.multicast++; } } else if ((*(s16 *)&buf[0] == *(s16 *)&dev->dev_addr[0]) && (*(s16 *)&buf[2] == *(s16 *)&dev->dev_addr[2]) && (*(s16 *)&buf[4] == *(s16 *)&dev->dev_addr[4])) { lp->pktStats.unicast++; } lp->pktStats.bins[0]++; /* Duplicates stats.rx_packets */ if (lp->pktStats.bins[0] == 0) { /* Reset counters */ memset((char *)&lp->pktStats, 0, sizeof(lp->pktStats)); } } else { printk("%s: Memory squeeze, deferring packet.\n", dev->name); lp->stats.rx_dropped++; /* Really, deferred. */ break; } } /* Change buffer ownership for this last frame, back to the adapter */ for (; lp->rx_old!=entry; lp->rx_old=(++lp->rx_old)&lp->rxRingMask) { writel(readl(&lp->rx_ring[lp->rx_old].base) | R_OWN, &lp->rx_ring[lp->rx_old].base); } writel(readl(&lp->rx_ring[entry].base) | R_OWN, &lp->rx_ring[entry].base); } /* ** Update entry information */ lp->rx_new = (++lp->rx_new) & lp->rxRingMask; } return 0;}/*** Buffer sent - check for buffer errors.*/static intdepca_tx(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; int entry; s32 status; u_long ioaddr = dev->base_addr; for (entry = lp->tx_old; entry != lp->tx_new; entry = lp->tx_old) { status = readl(&lp->tx_ring[entry].base) >> 16 ; if (status < 0) { /* Packet not yet sent! */ break; } else if (status & T_ERR) { /* An error occurred. */ status = readl(&lp->tx_ring[entry].misc); lp->stats.tx_errors++; if (status & TMD3_RTRY) lp->stats.tx_aborted_errors++; if (status & TMD3_LCAR) lp->stats.tx_carrier_errors++; if (status & TMD3_LCOL) lp->stats.tx_window_errors++; if (status & TMD3_UFLO) lp->stats.tx_fifo_errors++; if (status & (TMD3_BUFF | TMD3_UFLO)) { /* Trigger an immediate send demand. */ outw(CSR0, DEPCA_ADDR); outw(INEA | TDMD, DEPCA_DATA); } } else if (status & (T_MORE | T_ONE)) { lp->stats.collisions++; } else { lp->stats.tx_packets++; } /* Update all the pointers */ lp->tx_old = (++lp->tx_old) & lp->txRingMask; } return 0;}static intdepca_close(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; s16 nicsr; u_long ioaddr = dev->base_addr; dev->start = 0; dev->tbusy = 1; outw(CSR0, DEPCA_ADDR); if (depca_debug > 1) { printk("%s: Shutting down ethercard, status was %2.2x.\n", dev->name, inw(DEPCA_DATA)); } /* ** We stop the DEPCA here -- it occasionally polls ** memory if we don't. */ outw(STOP, DEPCA_DATA); /* ** Give back the ROM in case the user wants to go to DOS */ if (lp->adapter != DEPCA) { nicsr = inb(DEPCA_NICSR); nicsr &= ~SHE; outb(nicsr, DEPCA_NICSR); } /* ** Free the associated irq */ free_irq(dev->irq, dev); MOD_DEC_USE_COUNT; return 0;}static void LoadCSRs(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_long ioaddr = dev->base_addr; outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */ outw((u16)(lp->sh_mem & LA_MASK), DEPCA_DATA); outw(CSR2, DEPCA_ADDR); /* initialisation block address MSW */ outw((u16)((lp->sh_mem & LA_MASK) >> 16), DEPCA_DATA); outw(CSR3, DEPCA_ADDR); /* ALE control */ outw(ACON, DEPCA_DATA); outw(CSR0, DEPCA_ADDR); /* Point back to CSR0 */ return;}static int InitRestartDepca(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_long ioaddr = dev->base_addr; int i, status=0; /* Copy the shadow init_block to shared memory */ memcpy_toio((char *)lp->sh_mem, &lp->init_block, sizeof(struct depca_init)); outw(CSR0, DEPCA_ADDR); /* point back to CSR0 */ outw(INIT, DEPCA_DATA); /* initialize DEPCA */ /* wait for lance to complete initialisation */ for (i=0;(i<100) && !(inw(DEPCA_DATA) & IDON); i++); if (i!=100) { /* clear IDON by writing a "1", enable interrupts and start lance */ outw(IDON | INEA | STRT, DEPCA_DATA); if (depca_debug > 2) { printk("%s: DEPCA open after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); } } else { printk("%s: DEPCA unopen after %d ticks, init block 0x%08lx csr0 %4.4x.\n", dev->name, i, lp->sh_mem, inw(DEPCA_DATA)); status = -1; } return status;}static struct net_device_stats *depca_get_stats(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; /* Null body since there is no framing error counter */ return &lp->stats;}/*** Set or clear the multicast filter for this adaptor.*/static voidset_multicast_list(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; u_long ioaddr = dev->base_addr; if (dev) { while(dev->tbusy) barrier(); /* Stop ring access */ set_bit(0, (void*)&dev->tbusy); while(lp->tx_old != lp->tx_new); /* Wait for the ring to empty */ STOP_DEPCA; /* Temporarily stop the depca. */ depca_init_ring(dev); /* Initialize the descriptor rings */ if (dev->flags & IFF_PROMISC) { /* Set promiscuous mode */ lp->init_block.mode |= PROM; } else { SetMulticastFilter(dev); lp->init_block.mode &= ~PROM; /* Unset promiscuous mode */ } LoadCSRs(dev); /* Reload CSR3 */ InitRestartDepca(dev); /* Resume normal operation. */ dev->tbusy = 0; /* Unlock the TX ring */ }}/*** Calculate the hash code and update the logical address filter** from a list of ethernet multicast addresses.** Big endian crc one liner is mine, all mine, ha ha ha ha!** LANCE calculates its hash codes big endian.*/static void SetMulticastFilter(struct device *dev){ struct depca_private *lp = (struct depca_private *)dev->priv; struct dev_mc_list *dmi=dev->mc_list; char *addrs; int i, j, bit, byte; u16 hashcode; s32 crc, poly = CRC_POLYNOMIAL_BE; if (dev->flags & IFF_ALLMULTI) { /* Set all multicast bits */ for (i=0; i<(HASH_TABLE_LEN>>3); i++) { lp->init_block.mcast_table[i] = (char)0xff; } } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -