📄 fmvj18x_cs.c
字号:
DEBUG(4, "%s: Transmitting a packet of length %lu.\n", dev->name, (unsigned long)skb->len); lp->stats.tx_bytes += skb->len; /* Disable both interrupts. */ outw(0x0000, ioaddr + TX_INTR); /* wait for a while */ udelay(1); outw(length, ioaddr + DATAPORT); outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1); lp->tx_queue++; lp->tx_queue_len += ((length+3) & ~1); if (lp->tx_started == 0) { /* If the Tx is idle, always trigger a transmit. */ outb(DO_TX | lp->tx_queue, ioaddr + TX_START); lp->sent = lp->tx_queue ; lp->tx_queue = 0; lp->tx_queue_len = 0; dev->trans_start = jiffies; lp->tx_started = 1; netif_start_queue(dev); } else { if( sram_config == 0 ) { if (lp->tx_queue_len < (4096 - (ETH_FRAME_LEN +2)) ) /* Yes, there is room for one more packet. */ netif_start_queue(dev); } else { if (lp->tx_queue_len < (8192 - (ETH_FRAME_LEN +2)) && lp->tx_queue < 127 ) /* Yes, there is room for one more packet. */ netif_start_queue(dev); } } /* Re-enable interrupts */ outb(D_TX_INTR, ioaddr + TX_INTR); outb(D_RX_INTR, ioaddr + RX_INTR); } dev_kfree_skb (skb); return 0;} /* fjn_start_xmit *//*====================================================================*/static void fjn_reset(struct net_device *dev){ struct local_info_t *lp = (struct local_info_t *)dev->priv; ioaddr_t ioaddr = dev->base_addr; int i; DEBUG(4, "fjn_reset(%s) called.\n",dev->name); /* Reset controller */ if( sram_config == 0 ) outb(CONFIG0_RST, ioaddr + CONFIG_0); else outb(CONFIG0_RST_1, ioaddr + CONFIG_0); /* Power On chip and select bank 0 */ if( lp->cardtype == UNGERMANN) outb(BANK_0U, ioaddr + CONFIG_1); else outb(BANK_0, ioaddr + CONFIG_1); /* Set Tx modes */ outb(D_TX_MODE, ioaddr + TX_MODE); /* set Rx modes */ outb(ID_MATCHED, ioaddr + RX_MODE); /* Set hardware address */ for (i = 0; i < 6; i++) outb(dev->dev_addr[i], ioaddr + NODE_ID + i); /* Switch to bank 1 */ if ( lp->cardtype == UNGERMANN ) outb(BANK_1U, ioaddr + CONFIG_1); else outb(BANK_1, ioaddr + CONFIG_1); /* set the multicast table to accept none. */ for (i = 0; i < 6; i++) outb(0x00, ioaddr + MAR_ADR + i); /* Switch to bank 2 (runtime mode) */ if ( lp->cardtype == UNGERMANN ) outb(BANK_2U, ioaddr + CONFIG_1); else outb(BANK_2, ioaddr + CONFIG_1); /* set 16col ctrl bits */ if( lp->cardtype == TDK || lp->cardtype == CONTEC) outb(TDK_AUTO_MODE, ioaddr + COL_CTRL); else outb(AUTO_MODE, ioaddr + COL_CTRL); /* clear Reserved Regs */ outb(0x00, ioaddr + BMPR12); outb(0x00, ioaddr + BMPR13); /* reset Skip packet reg. */ outb(0x01, ioaddr + RX_SKIP); /* Enable Tx and Rx */ if( sram_config == 0 ) outb(CONFIG0_DFL, ioaddr + CONFIG_0); else outb(CONFIG0_DFL_1, ioaddr + CONFIG_0); /* Init receive pointer ? */ inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT); /* Clear all status */ outb(0xff, ioaddr + TX_STATUS); outb(0xff, ioaddr + RX_STATUS); if( lp->cardtype != TDK ) outb(INTR_OFF, ioaddr + LAN_CTRL); /* Turn on Rx interrupts */ outb(D_TX_INTR, ioaddr + TX_INTR); outb(D_RX_INTR, ioaddr + RX_INTR); /* Turn on interrupts from LAN card controller */ if( lp->cardtype != TDK ) outb(INTR_ON, ioaddr + LAN_CTRL);} /* fjn_reset *//*====================================================================*/static void fjn_rx(struct net_device *dev){ struct local_info_t *lp = (struct local_info_t *)dev->priv; ioaddr_t ioaddr = dev->base_addr; int boguscount = 10; /* 5 -> 10: by agy 19940922 */ DEBUG(4, "%s: in rx_packet(), rx_status %02x.\n", dev->name, inb(ioaddr + RX_STATUS)); while ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == 0) { u_short status = inw(ioaddr + DATAPORT); DEBUG(4, "%s: Rxing packet mode %02x status %04x.\n", dev->name, inb(ioaddr + RX_MODE), status);#ifndef final_version if (status == 0) { outb(F_SKP_PKT, ioaddr + RX_SKIP); break; }#endif if ((status & 0xF0) != 0x20) { /* There was an error. */ lp->stats.rx_errors++; if (status & F_LEN_ERR) lp->stats.rx_length_errors++; if (status & F_ALG_ERR) lp->stats.rx_frame_errors++; if (status & F_CRC_ERR) lp->stats.rx_crc_errors++; if (status & F_OVR_FLO) lp->stats.rx_over_errors++; } else { u_short pkt_len = inw(ioaddr + DATAPORT); /* Malloc up new buffer. */ struct sk_buff *skb; if (pkt_len > 1550) { printk(KERN_NOTICE "%s: The FMV-18x claimed a very " "large packet, size %d.\n", dev->name, pkt_len); outb(F_SKP_PKT, ioaddr + RX_SKIP); lp->stats.rx_errors++; break; } skb = dev_alloc_skb(pkt_len+2); if (skb == NULL) { printk(KERN_NOTICE "%s: Memory squeeze, dropping " "packet (len %d).\n", dev->name, pkt_len); outb(F_SKP_PKT, ioaddr + RX_SKIP); lp->stats.rx_dropped++; break; } skb->dev = dev; skb_reserve(skb, 2); insw(ioaddr + DATAPORT, skb_put(skb, pkt_len), (pkt_len + 1) >> 1); skb->protocol = eth_type_trans(skb, dev);#ifdef PCMCIA_DEBUG if (pc_debug > 5) { int i; printk(KERN_DEBUG "%s: Rxed packet of length %d: ", dev->name, pkt_len); for (i = 0; i < 14; i++) printk(" %02x", skb->data[i]); printk(".\n"); }#endif netif_rx(skb); dev->last_rx = jiffies; lp->stats.rx_packets++; lp->stats.rx_bytes += pkt_len; } if (--boguscount <= 0) break; } /* If any worth-while packets have been received, dev_rint() has done a netif_wake_queue() for us and will work on them when we get to the bottom-half routine. *//* if( lp->cardtype != TDK ) { int i; for (i = 0; i < 20; i++) { if ((inb(ioaddr + RX_MODE) & F_BUF_EMP) == F_BUF_EMP) break; (void)inw(ioaddr + DATAPORT); /+ dummy status read +/ outb(F_SKP_PKT, ioaddr + RX_SKIP); } if (i > 0) DEBUG(5, "%s: Exint Rx packet with mode %02x after " "%d ticks.\n", dev->name, inb(ioaddr + RX_MODE), i); }*/ return;} /* fjn_rx *//*====================================================================*/static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr){ u32 ethcmd; /* dev_ioctl() in ../../net/core/dev.c has already checked capable(CAP_NET_ADMIN), so don't bother with that here. */ if (get_user(ethcmd, (u32 *)useraddr)) return -EFAULT; switch (ethcmd) { case ETHTOOL_GDRVINFO: { struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO }; strcpy (info.driver, DRV_NAME); strcpy (info.version, DRV_VERSION); sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr); if (copy_to_user (useraddr, &info, sizeof (info))) return -EFAULT; return 0; }#ifdef PCMCIA_DEBUG /* get message-level */ case ETHTOOL_GMSGLVL: { struct ethtool_value edata = {ETHTOOL_GMSGLVL}; edata.data = pc_debug; if (copy_to_user(useraddr, &edata, sizeof(edata))) return -EFAULT; return 0; } /* set message-level */ case ETHTOOL_SMSGLVL: { struct ethtool_value edata; if (copy_from_user(&edata, useraddr, sizeof(edata))) return -EFAULT; pc_debug = edata.data; return 0; }#endif default: break; } return -EOPNOTSUPP;}static int fjn_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){ switch (cmd) { case SIOCETHTOOL: return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data); default: return -EOPNOTSUPP; }}static int fjn_config(struct net_device *dev, struct ifmap *map){ return 0;}static int fjn_open(struct net_device *dev){ struct local_info_t *lp = (struct local_info_t *)dev->priv; dev_link_t *link = &lp->link; DEBUG(4, "fjn_open('%s').\n", dev->name); if (!DEV_OK(link)) return -ENODEV; link->open++; fjn_reset(dev); lp->tx_started = 0; lp->tx_queue = 0; lp->tx_queue_len = 0; lp->open_time = jiffies; netif_start_queue(dev); MOD_INC_USE_COUNT; return 0;} /* fjn_open *//*====================================================================*/static int fjn_close(struct net_device *dev){ struct local_info_t *lp = (struct local_info_t *)dev->priv; dev_link_t *link = &lp->link; ioaddr_t ioaddr = dev->base_addr; DEBUG(4, "fjn_close('%s').\n", dev->name); lp->open_time = 0; netif_stop_queue(dev); /* Set configuration register 0 to disable Tx and Rx. */ if( sram_config == 0 ) outb(CONFIG0_RST ,ioaddr + CONFIG_0); else outb(CONFIG0_RST_1 ,ioaddr + CONFIG_0); /* Update the statistics -- ToDo. */ /* Power-down the chip. Green, green, green! */ outb(CHIP_OFF ,ioaddr + CONFIG_1); /* Set the ethernet adaptor disable IRQ */ if( lp->cardtype != TDK ) outb(INTR_OFF, ioaddr + LAN_CTRL); link->open--; if (link->state & DEV_STALE_CONFIG) mod_timer(&link->release, jiffies + HZ/20); MOD_DEC_USE_COUNT; return 0;} /* fjn_close *//*====================================================================*/static struct net_device_stats *fjn_get_stats(struct net_device *dev){ local_info_t *lp = (local_info_t *)dev->priv; return &lp->stats;} /* fjn_get_stats *//*====================================================================*//* Set the multicast/promiscuous mode for this adaptor.*//* The little-endian AUTODIN II ethernet CRC calculation. N.B. Do not use for bulk data, use a table-based routine instead. This is common code and should be moved to net/core/crc.c */static unsigned const ethernet_polynomial_le = 0xedb88320U;static inline unsigned ether_crc_le(int length, unsigned char *data){ unsigned int crc = 0xffffffff; /* Initial value. */ while(--length >= 0) { unsigned char current_octet = *data++; int bit; for (bit = 8; --bit >= 0; current_octet >>= 1) { if ((crc ^ current_octet) & 1) { crc >>= 1; crc ^= ethernet_polynomial_le; } else crc >>= 1; } } return crc;}static void set_rx_mode(struct net_device *dev){ ioaddr_t ioaddr = dev->base_addr; struct local_info_t *lp = (struct local_info_t *)dev->priv; unsigned char mc_filter[8]; /* Multicast hash filter */ long flags; int i; if (dev->flags & IFF_PROMISC) { /* Unconditionally log net taps. */ printk("%s: Promiscuous mode enabled.\n", dev->name); memset(mc_filter, 0xff, sizeof(mc_filter)); outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */ } else if (dev->mc_count > MC_FILTERBREAK || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter perfectly -- accept all multicasts. */ memset(mc_filter, 0xff, sizeof(mc_filter)); outb(2, ioaddr + RX_MODE); /* Use normal mode. */ } else if (dev->mc_count == 0) { memset(mc_filter, 0x00, sizeof(mc_filter)); outb(1, ioaddr + RX_MODE); /* Ignore almost all multicasts. */ } else { struct dev_mc_list *mclist; int i; memset(mc_filter, 0, sizeof(mc_filter)); for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; i++, mclist = mclist->next) set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x3f, mc_filter); } save_flags(flags); cli(); if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) { int saved_bank = inb(ioaddr + CONFIG_1); /* Switch to bank 1 and set the multicast table. */ outb(0xe4, ioaddr + CONFIG_1); for (i = 0; i < 8; i++) outb(mc_filter[i], ioaddr + 8 + i); memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter)); outb(saved_bank, ioaddr + CONFIG_1); } restore_flags(flags);}MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -