📄 nmclan_cs.c
字号:
" 0x%X.\n", pkt_len, rx_status); skb = dev_alloc_skb(pkt_len+2); if (skb != NULL) { skb->dev = dev; skb_reserve(skb, 2); insw(ioaddr + AM2150_RCV, skb_put(skb, pkt_len), pkt_len>>1); if (pkt_len & 1) *(skb->tail-1) = inb(ioaddr + AM2150_RCV); skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); /* Send the packet to the upper (protocol) layers. */ dev->last_rx = jiffies; lp->linux_stats.rx_packets++; lp->linux_stats.rx_bytes += skb->len; outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ continue; } else { DEBUG(1, "%s: couldn't allocate a sk_buff of size" " %d.\n", dev->name, pkt_len); lp->linux_stats.rx_dropped++; } } outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */ } /* while */ return 0;} /* mace_rx *//* ----------------------------------------------------------------------------pr_linux_stats---------------------------------------------------------------------------- */static void pr_linux_stats(struct net_device_stats *pstats){ DEBUG(2, "pr_linux_stats\n"); DEBUG(2, " rx_packets=%-7ld tx_packets=%ld\n", (long)pstats->rx_packets, (long)pstats->tx_packets); DEBUG(2, " rx_errors=%-7ld tx_errors=%ld\n", (long)pstats->rx_errors, (long)pstats->tx_errors); DEBUG(2, " rx_dropped=%-7ld tx_dropped=%ld\n", (long)pstats->rx_dropped, (long)pstats->tx_dropped); DEBUG(2, " multicast=%-7ld collisions=%ld\n", (long)pstats->multicast, (long)pstats->collisions); DEBUG(2, " rx_length_errors=%-7ld rx_over_errors=%ld\n", (long)pstats->rx_length_errors, (long)pstats->rx_over_errors); DEBUG(2, " rx_crc_errors=%-7ld rx_frame_errors=%ld\n", (long)pstats->rx_crc_errors, (long)pstats->rx_frame_errors); DEBUG(2, " rx_fifo_errors=%-7ld rx_missed_errors=%ld\n", (long)pstats->rx_fifo_errors, (long)pstats->rx_missed_errors); DEBUG(2, " tx_aborted_errors=%-7ld tx_carrier_errors=%ld\n", (long)pstats->tx_aborted_errors, (long)pstats->tx_carrier_errors); DEBUG(2, " tx_fifo_errors=%-7ld tx_heartbeat_errors=%ld\n", (long)pstats->tx_fifo_errors, (long)pstats->tx_heartbeat_errors); DEBUG(2, " tx_window_errors=%ld\n", (long)pstats->tx_window_errors);} /* pr_linux_stats *//* ----------------------------------------------------------------------------pr_mace_stats---------------------------------------------------------------------------- */static void pr_mace_stats(mace_statistics *pstats){ DEBUG(2, "pr_mace_stats\n"); DEBUG(2, " xmtsv=%-7d uflo=%d\n", pstats->xmtsv, pstats->uflo); DEBUG(2, " lcol=%-7d more=%d\n", pstats->lcol, pstats->more); DEBUG(2, " one=%-7d defer=%d\n", pstats->one, pstats->defer); DEBUG(2, " lcar=%-7d rtry=%d\n", pstats->lcar, pstats->rtry); /* MACE_XMTRC */ DEBUG(2, " exdef=%-7d xmtrc=%d\n", pstats->exdef, pstats->xmtrc); /* RFS1--Receive Status (RCVSTS) */ DEBUG(2, " oflo=%-7d clsn=%d\n", pstats->oflo, pstats->clsn); DEBUG(2, " fram=%-7d fcs=%d\n", pstats->fram, pstats->fcs); /* RFS2--Runt Packet Count (RNTPC) */ /* RFS3--Receive Collision Count (RCVCC) */ DEBUG(2, " rfs_rntpc=%-7d rfs_rcvcc=%d\n", pstats->rfs_rntpc, pstats->rfs_rcvcc); /* MACE_IR */ DEBUG(2, " jab=%-7d babl=%d\n", pstats->jab, pstats->babl); DEBUG(2, " cerr=%-7d rcvcco=%d\n", pstats->cerr, pstats->rcvcco); DEBUG(2, " rntpco=%-7d mpco=%d\n", pstats->rntpco, pstats->mpco); /* MACE_MPC */ DEBUG(2, " mpc=%d\n", pstats->mpc); /* MACE_RNTPC */ DEBUG(2, " rntpc=%d\n", pstats->rntpc); /* MACE_RCVCC */ DEBUG(2, " rcvcc=%d\n", pstats->rcvcc);} /* pr_mace_stats *//* ----------------------------------------------------------------------------update_stats Update statistics. We change to register window 1, so this should be run single-threaded if the device is active. This is expected to be a rare operation, and it's simpler for the rest of the driver to assume that window 0 is always valid rather than use a special window-state variable. oflo & uflo should _never_ occur since it would mean the Xilinx was not able to transfer data between the MACE FIFO and the card's SRAM fast enough. If this happens, something is seriously wrong with the hardware.---------------------------------------------------------------------------- */static void update_stats(kio_addr_t ioaddr, struct net_device *dev){ mace_private *lp = netdev_priv(dev); lp->mace_stats.rcvcc += mace_read(lp, ioaddr, MACE_RCVCC); lp->mace_stats.rntpc += mace_read(lp, ioaddr, MACE_RNTPC); lp->mace_stats.mpc += mace_read(lp, ioaddr, MACE_MPC); /* At this point, mace_stats is fully updated for this call. We may now update the linux_stats. */ /* The MACE has no equivalent for linux_stats field which are commented out. */ /* lp->linux_stats.multicast; */ lp->linux_stats.collisions = lp->mace_stats.rcvcco * 256 + lp->mace_stats.rcvcc; /* Collision: The MACE may retry sending a packet 15 times before giving up. The retry count is in XMTRC. Does each retry constitute a collision? If so, why doesn't the RCVCC record these collisions? */ /* detailed rx_errors: */ lp->linux_stats.rx_length_errors = lp->mace_stats.rntpco * 256 + lp->mace_stats.rntpc; /* lp->linux_stats.rx_over_errors */ lp->linux_stats.rx_crc_errors = lp->mace_stats.fcs; lp->linux_stats.rx_frame_errors = lp->mace_stats.fram; lp->linux_stats.rx_fifo_errors = lp->mace_stats.oflo; lp->linux_stats.rx_missed_errors = lp->mace_stats.mpco * 256 + lp->mace_stats.mpc; /* detailed tx_errors */ lp->linux_stats.tx_aborted_errors = lp->mace_stats.rtry; lp->linux_stats.tx_carrier_errors = lp->mace_stats.lcar; /* LCAR usually results from bad cabling. */ lp->linux_stats.tx_fifo_errors = lp->mace_stats.uflo; lp->linux_stats.tx_heartbeat_errors = lp->mace_stats.cerr; /* lp->linux_stats.tx_window_errors; */ return;} /* update_stats *//* ----------------------------------------------------------------------------mace_get_stats Gathers ethernet statistics from the MACE chip.---------------------------------------------------------------------------- */static struct net_device_stats *mace_get_stats(struct net_device *dev){ mace_private *lp = netdev_priv(dev); update_stats(dev->base_addr, dev); DEBUG(1, "%s: updating the statistics.\n", dev->name); pr_linux_stats(&lp->linux_stats); pr_mace_stats(&lp->mace_stats); return &lp->linux_stats;} /* net_device_stats *//* ----------------------------------------------------------------------------updateCRC Modified from Am79C90 data sheet.---------------------------------------------------------------------------- */#ifdef BROKEN_MULTICASTstatic void updateCRC(int *CRC, int bit){ int poly[]={ 1,1,1,0, 1,1,0,1, 1,0,1,1, 1,0,0,0, 1,0,0,0, 0,0,1,1, 0,0,1,0, 0,0,0,0 }; /* CRC polynomial. poly[n] = coefficient of the x**n term of the CRC generator polynomial. */ int j; /* shift CRC and control bit (CRC[32]) */ for (j = 32; j > 0; j--) CRC[j] = CRC[j-1]; CRC[0] = 0; /* If bit XOR(control bit) = 1, set CRC = CRC XOR polynomial. */ if (bit ^ CRC[32]) for (j = 0; j < 32; j++) CRC[j] ^= poly[j];} /* updateCRC *//* ----------------------------------------------------------------------------BuildLAF Build logical address filter. Modified from Am79C90 data sheet.Input ladrf: logical address filter (contents initialized to 0) adr: ethernet address---------------------------------------------------------------------------- */static void BuildLAF(int *ladrf, int *adr){ int CRC[33]={1}; /* CRC register, 1 word/bit + extra control bit */ int i, byte; /* temporary array indices */ int hashcode; /* the output object */ CRC[32]=0; for (byte = 0; byte < 6; byte++) for (i = 0; i < 8; i++) updateCRC(CRC, (adr[byte] >> i) & 1); hashcode = 0; for (i = 0; i < 6; i++) hashcode = (hashcode << 1) + CRC[i]; byte = hashcode >> 3; ladrf[byte] |= (1 << (hashcode & 7));#ifdef PCMCIA_DEBUG if (pc_debug > 2) { printk(KERN_DEBUG " adr ="); for (i = 0; i < 6; i++) printk(" %02X", adr[i]); printk("\n" KERN_DEBUG " hashcode = %d(decimal), ladrf[0:63]" " =", hashcode); for (i = 0; i < 8; i++) printk(" %02X", ladrf[i]); printk("\n"); }#endif} /* BuildLAF *//* ----------------------------------------------------------------------------restore_multicast_list Restores the multicast filter for MACE chip to the last set_multicast_list() call.Input multicast_num_addrs multicast_ladrf[]---------------------------------------------------------------------------- */static void restore_multicast_list(struct net_device *dev){ mace_private *lp = netdev_priv(dev); int num_addrs = lp->multicast_num_addrs; int *ladrf = lp->multicast_ladrf; kio_addr_t ioaddr = dev->base_addr; int i; DEBUG(2, "%s: restoring Rx mode to %d addresses.\n", dev->name, num_addrs); if (num_addrs > 0) { DEBUG(1, "Attempt to restore multicast list detected.\n"); mace_write(lp, ioaddr, MACE_IAC, MACE_IAC_ADDRCHG | MACE_IAC_LOGADDR); /* Poll ADDRCHG bit */ while (mace_read(lp, ioaddr, MACE_IAC) & MACE_IAC_ADDRCHG) ; /* Set LADRF register */ for (i = 0; i < MACE_LADRF_LEN; i++) mace_write(lp, ioaddr, MACE_LADRF, ladrf[i]); mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_RCVFCSE | MACE_UTR_LOOP_EXTERNAL); mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); } else if (num_addrs < 0) { /* Promiscuous mode: receive all packets */ mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV ); } else { /* Normal mode */ mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); }} /* restore_multicast_list *//* ----------------------------------------------------------------------------set_multicast_list Set or clear the multicast filter for this adaptor.Input num_addrs == -1 Promiscuous mode, receive all packets num_addrs == 0 Normal mode, clear multicast list num_addrs > 0 Multicast mode, receive normal and MC packets, and do best-effort filtering.Output multicast_num_addrs multicast_ladrf[]---------------------------------------------------------------------------- */static void set_multicast_list(struct net_device *dev){ mace_private *lp = netdev_priv(dev); int adr[ETHER_ADDR_LEN] = {0}; /* Ethernet address */ int i; struct dev_mc_list *dmi = dev->mc_list;#ifdef PCMCIA_DEBUG if (pc_debug > 1) { static int old; if (dev->mc_count != old) { old = dev->mc_count; DEBUG(0, "%s: setting Rx mode to %d addresses.\n", dev->name, old); } }#endif /* Set multicast_num_addrs. */ lp->multicast_num_addrs = dev->mc_count; /* Set multicast_ladrf. */ if (num_addrs > 0) { /* Calculate multicast logical address filter */ memset(lp->multicast_ladrf, 0, MACE_LADRF_LEN); for (i = 0; i < dev->mc_count; i++) { memcpy(adr, dmi->dmi_addr, ETHER_ADDR_LEN); dmi = dmi->next; BuildLAF(lp->multicast_ladrf, adr); } } restore_multicast_list(dev);} /* set_multicast_list */#endif /* BROKEN_MULTICAST */static void restore_multicast_list(struct net_device *dev){ kio_addr_t ioaddr = dev->base_addr; mace_private *lp = netdev_priv(dev); DEBUG(2, "%s: restoring Rx mode to %d addresses.\n", dev->name, lp->multicast_num_addrs); if (dev->flags & IFF_PROMISC) { /* Promiscuous mode: receive all packets */ mace_write(lp,ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_PROM | MACE_MACCC_ENXMT | MACE_MACCC_ENRCV ); } else { /* Normal mode */ mace_write(lp, ioaddr, MACE_UTR, MACE_UTR_LOOP_EXTERNAL); mace_write(lp, ioaddr, MACE_MACCC, MACE_MACCC_ENXMT | MACE_MACCC_ENRCV); }} /* restore_multicast_list */static void set_multicast_list(struct net_device *dev){ mace_private *lp = netdev_priv(dev);#ifdef PCMCIA_DEBUG if (pc_debug > 1) { static int old; if (dev->mc_count != old) { old = dev->mc_count; DEBUG(0, "%s: setting Rx mode to %d addresses.\n", dev->name, old); } }#endif lp->multicast_num_addrs = dev->mc_count; restore_multicast_list(dev);} /* set_multicast_list */static struct pcmcia_driver nmclan_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "nmclan_cs", }, .attach = nmclan_attach, .detach = nmclan_detach,};static int __init init_nmclan_cs(void){ return pcmcia_register_driver(&nmclan_cs_driver);}static void __exit exit_nmclan_cs(void){ pcmcia_unregister_driver(&nmclan_cs_driver); BUG_ON(dev_list != NULL);}module_init(init_nmclan_cs);module_exit(exit_nmclan_cs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -