⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fmvj18x_cs.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -