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

📄 dm9000x.c

📁 这个源码相信对很多用arm开发板开发的人会有用的
💻 C
📖 第 1 页 / 共 3 页
字号:
#if 0 	/* comment by mhfan */    spin_lock(&db->lock);#else    spin_lock_irq(&db->lock);#endif	/* comment by mhfan */    /* Save previous register address */    reg_save = inb(db->ioaddr);    /* Disable all interrupt */    iow(db, 0xff, 0x80);//by he    /* Got DM9000 interrupt status */    int_status = ior(db, 0xfe);	/* Got ISR */    iow(db, 0xfe, int_status);	/* Clear ISR status *///by he	    if (int_status & DM9000_TX_INTR) {	/* Trnasmit Interrupt check */	dmfe_tx_done(0);    }    if (int_status & DM9000_RX_INTR) {		/* Received the coming packet */	rxintrflag++;#if 0	/* comment by mhfan */	tasklet_schedule(&dmfe_rx_tasklet);#else	dmfe_packet_receive(0);#endif	/* comment by mhfan */    }    /* Re-enable interrupt mask */    iow(db, 0xff, 0x83);    /* Restore previous register address */    outb(reg_save, db->ioaddr);#if 0 	/* comment by mhfan */    spin_unlock(&db->lock);#else    spin_unlock_irq(&db->lock);#endif	/* comment by mhfan */    return IRQ_HANDLED;}/*  Get statistics from driver.*/static struct net_device_stats *dmfe_get_stats(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    DMFE_DBUG(0, "dmfe_get_stats", 0);    return &db->stats;}/*  Process the upper socket ioctl command*/static int dmfe_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){    DMFE_DBUG(0, "dmfe_do_ioctl()", 0);    return 0;}/*  A periodic timer routine  Dynamic media sense, allocated Rx buffer...*/static void dmfe_timer(unsigned long data){    struct net_device *dev = (struct net_device *) data;    board_info_t *db = (board_info_t *) dev->priv;    u8 reg_save, tmp_reg;//      DMFE_DBUG(0, "dmfe_timer()", 0);    /* Save previous register address */    reg_save = inb(db->ioaddr);    /* TX timeout check */    if (dev->trans_start && ((jiffies - dev->trans_start) > DMFE_TX_TIMEOUT)) {	db->device_wait_reset = 1;	db->reset_tx_timeout++;    }    /* DM9000 dynamic RESET check and do */    if (db->device_wait_reset) {	netif_stop_queue(dev);	db->reset_counter++;	db->device_wait_reset = 0;	dev->trans_start = 0;	dmfe_init_dm9000(dev);	netif_wake_queue(dev);    }    /* Auto Sense Media mode policy: FastEthernet NIC: don't need to do     * anything. Media Force mode: don't need to do anything. HomeRun/LongRun      * NIC and AUTO_Mode: INT_MII not link, select EXT_MII EXT_MII not link,     * select INT_MII */    if ((db->nic_type != FASTETHER_NIC) & (db->op_mode == DM9000_AUTO)) {	tmp_reg = ior(db, 0x01);	/* Got link status */	if (!(tmp_reg & 0x40)) {	/* not link */	    db->reg0 ^= 0x80;	    iow(db, 0x00, db->reg0);	}    }    /* Restore previous register address */    outb(reg_save, db->ioaddr);    /* Set timer again */    db->timer.expires = DMFE_TIMER_WUT;    add_timer(&db->timer);}#if defined(AUTOMDIX)static void dmfe_mdix_timer(unsigned long data){    struct net_device *dev = (struct net_device *) data;    board_info_t *db = (board_info_t *) dev->priv;    /* support AUTO-MDIX */    db->mdix = ior(db, DM9000_GPR);    db->link_status = ior(db, DM9000_NSR);    db->link_status = test_bit(6, &db->link_status);    udelay(2000);    if (!db->link_status) {	switch (db->mdix) {	case 0x7c:		// use parallel line change to cross line	    if (netif_carrier_ok(dev))		netif_carrier_off(dev);	    iow(db, DM9000_GPCR, 0x03);	    iow(db, DM9000_GPR, 0x02);	    break;	case 0x7e:		// use cross line change to parallel line	    if (netif_carrier_ok(dev))		netif_carrier_off(dev);	    iow(db, DM9000_GPCR, 0x03);	    iow(db, DM9000_GPR, 0x00);	    break;	default:	    break;	}    } else {	if (!netif_carrier_ok(dev))	    netif_carrier_on(dev);    }    /* Set timer again */    db->mdix_timer.expires = DMFE_TIMER_MDIX;    add_timer(&db->mdix_timer);}#endif/* Received a packet and pass to upper layer */static void dmfe_packet_receive(unsigned long unused){    struct net_device *dev = dmfe_dev;    board_info_t *db = (board_info_t *) dev->priv;    struct sk_buff *skb;    u8 rxbyte, *rdptr;    u16 i, RxStatus, RxLen, GoodPacket, tmplen;    u32 tmpdata;    DMFE_DBUG(0, "dmfe_packet_receive()", 0);    do {				/* Check packet ready or not */	ior(db, 0xf0);			/* Dummy read */	rxbyte = inb(db->io_data);	/* Got most updated data */	if (rxbyte == DM9000_PKT_RDY) { /* packet ready to receive check */	    /* A packet ready now & Get status/length */	    GoodPacket = TRUE;	    outb(0xf2, db->ioaddr);	    /* Selecting io mode */	    RxStatus = RxLen = (u16) 0;	    /* modify Select io mode by jackal 10/28/2003 */	    switch (db->io_mode) {	    case DM9000_BYTE_MODE:		RxStatus = inb(db->io_data) + (inb(db->io_data) << 8);		RxLen = inb(db->io_data) + (inb(db->io_data) << 8);		break;	    case DM9000_WORD_MODE:		RxStatus = inw(db->io_data);#ifndef	CONFIG_BLKFIN_DCACHEoutb(0xf2, db->ioaddr);#endif	/* comment by mhfan */		RxLen = inw(db->io_data);		break;	    case DM9000_DWORD_MODE:		tmpdata = inl(db->io_data);		RxStatus = tmpdata;		RxLen = tmpdata >> 16;		break;	    default:		break;	    }	    /* Packet Status check */	    if (RxLen < 0x40) {		GoodPacket = FALSE;		db->runt_length_counter++;	    } else if (RxLen > DM9000_PKT_MAX) {		printk("<DM9000> RST: RX Len:%x(%x)\n", RxLen, RxStatus);		db->device_wait_reset = TRUE;		db->long_length_counter++;	    }	    if (RxStatus & 0xbf00) {		GoodPacket = FALSE;		if (RxStatus & 0x100)		    db->stats.rx_fifo_errors++;		if (RxStatus & 0x200)		    db->stats.rx_crc_errors++;		if (RxStatus & 0x8000)		    db->stats.rx_length_errors++;	    }	    if (!db->device_wait_reset) {	/* Move data from DM9000 */		if (GoodPacket && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {		    skb->dev = dev;		    skb_reserve(skb, 2);		    rdptr = (u8 *) skb_put(skb, RxLen - 4);		    /* Read received packet from RX SARM */		    if (db->io_mode == DM9000_BYTE_MODE) {  /* Byte mode */			for (i = 0; i < RxLen; i++)			    rdptr[i] = inb(db->io_data);		    } else if (db->io_mode == DM9000_WORD_MODE) {			/* Word mode */			tmplen = (RxLen + 1) / 2;			for (i = 0; i < tmplen; i++)			    ((u16 *) rdptr)[i] = inw(db->io_data);#if 0	/* comment by mhfan */{    int j = 0;    printk("\n\033[32mRxStatus=%04x, RxLen=%04x\n", RxStatus, RxLen);    for (i = 0; i < tmplen; i++) {	printk("%04x ", ((u16 *) rdptr)[i]);	if (++j == 16) { printk("\n"); j = 0; }    }    printk("\n\033[0m");}#endif	/* comment by mhfan */		    } else {				    /* DWord mode */			tmplen = (RxLen + 3) / 4;			for (i = 0; i < tmplen; i++)			    ((u32 *) rdptr)[i] = inl(db->io_data);		    }		    /* Pass to upper layer */		    skb->protocol = eth_type_trans(skb, dev);		    netif_rx(skb);		    db->stats.rx_packets++;		} else {	    /* Without buffer or error packet */		    if (db->io_mode == DM9000_BYTE_MODE) {  /* Byte mode */			for (i = 0; i < RxLen; i++)			    inb(db->io_data);		    } else if (db->io_mode == DM9000_WORD_MODE) {			/* Word mode */			tmplen = (RxLen + 1) / 2;			for (i = 0; i < tmplen; i++)			    inw(db->io_data);		    } else {				    /* DWord mode */			tmplen = (RxLen + 3) / 4;			for (i = 0; i < tmplen; i++)			    inl(db->io_data);		    }		}	    }	} else if (rxbyte > DM9000_PKT_RDY) {	    /* Status check: this byte must be 0 or 1 */	    printk("RX SRAM 1st byte(%02x) != 01, must reset.\n", rxbyte);	    iow(db, 0x05, 0x00);	/* Stop Device */	    iow(db, 0xfe, 0x80);	/* Stop INT request */	    db->device_wait_reset = TRUE;	    db->reset_rx_status++;	}    } while (rxbyte == DM9000_PKT_RDY && !db->device_wait_reset); #if 0 	// Spenser    if (!db->device_wait_reset) {	dmfe_tx_done(0);	iow(db, 0xff, 0x83);    }#endif	/* comment by mhfan */}#if 0	/* comment by mhfan *//* Read a word data from SROM */static u16 read_srom_word(board_info_t * db, int offset){    iow(db, 0xc, offset);    iow(db, 0xb, 0x4);    udelay(200);    iow(db, 0xb, 0x0);    return (ior(db, 0xd) + (ior(db, 0xe) << 8));}#endif	/* comment by mhfan *//* Set DM9000 multicast address */static void dm9000_hash_table(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    struct dev_mc_list *mcptr = dev->mc_list;    int mc_cnt = dev->mc_count;    u32 hash_val;    u16 i, oft, hash_table[4];    DMFE_DBUG(0, "dm9000_hash_table()", 0);    /* Set Node address */    for (i = 0, oft = 0x10; i < 6; i++, oft++)	iow(db, oft, dev->dev_addr[i]);    /* Clear Hash Table */    for (i = 0; i < 4; i++) hash_table[i] = 0x0;    /* broadcast address */    hash_table[3] = 0x8000;    /* the multicast address in Hash Table : 64 bits */    for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {	hash_val = cal_CRC((char *) mcptr->dmi_addr, 6, 0) & 0x3f;	hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16);    }    /* Write the hash table to MAC MD table */    for (i = 0, oft = 0x16; i < 4; i++) {	iow(db, oft++, hash_table[i] & 0xff);	iow(db, oft++, (hash_table[i] >> 8) & 0xff);    }}/* Calculate the CRC valude of the Rx packet * flag = 1 : return the reverse CRC (for the received packet CRC) *	  0 : return the  normal CRC (for Hash Table index) */static unsigned long cal_CRC(unsigned char *Data, unsigned int Len, u8 flag){    u32 crc = ether_crc_le(Len, Data);    if (flag) return ~crc;    return crc;}/* Read a byte from I/O port */static u8 ior(board_info_t * db, int reg){    outb(reg, db->ioaddr);    return inb(db->io_data);}/* Write a byte to I/O port */static void iow(board_info_t * db, int reg, u8 value){    outb(reg, db->ioaddr);    outb(value, db->io_data);}/* Read a word from phyxcer */static u16 phy_read(board_info_t * db, int reg){    /* Fill the phyxcer register into REG_0C */    iow(db, 0xc, DM9000_PHY | reg);    iow(db, 0xb, 0xc);		/* Issue phyxcer read command */    udelay(100);		/* Wait read complete */    iow(db, 0xb, 0x0);		/* Clear phyxcer read command */    /* The read data keeps on REG_0D & REG_0E */    return (ior(db, 0xe) << 8) | ior(db, 0xd);}/* Write a word to phyxcer */static void phy_write(board_info_t * db, int reg, u16 value){    /* Fill the phyxcer register into REG_0C */    iow(db, 0xc, DM9000_PHY | reg);    /* Fill the written data into REG_0D & REG_0E */    iow(db, 0xd, (value & 0xff));    iow(db, 0xe, ((value >> 8) & 0xff));    iow(db, 0xb, 0xa);		/* Issue phyxcer write command */    udelay(500);		/* Wait write complete */    iow(db, 0xb, 0x0);		/* Clear phyxcer write command */}#ifdef	MODULEMODULE_LICENSE("GPL");MODULE_AUTHOR("Sten Wang, sten_wang@davicom.com.tw");MODULE_DESCRIPTION("Davicom DM9000 ISA/uP Fast Ethernet Driver");MODULE_PARM(debug, "i");MODULE_PARM(mode, "i");MODULE_PARM(reg5, "i");MODULE_PARM(reg9, "i");MODULE_PARM(rega, "i");MODULE_PARM(nfloor, "i");//MODULE_PARM(SF_mode, "i");/* Description:  * when user used insmod to add module, * system invoked init_module() to initilize and register. */int init_module(void){    DMFE_DBUG(0, "init_module() ", debug);   printk("\n\nsun----init_module\n\n");    if (debug) dmfe_debug = debug;	/* set debug flag */    switch (mode) {    case DM9000_10MHD:    case DM9000_100MHD:    case DM9000_10MFD:    case DM9000_100MFD:    case DM9000_1M_HPNA:    media_mode = mode;	    break;    default:		    media_mode = DM9000_AUTO;    }    nfloor = (nfloor > 15) ? 0 : nfloor;    return dmfe_probe(0);	/* search board and register */}/* Description:  * when user used rmmod to delete module, * system invoked clean_module() to  un-register DEVICE. */void cleanup_module(void){    board_info_t *db;       printk("\n\nsun----cleanup_module\n\n");    DMFE_DBUG(0, "clean_module()", 0);    unregister_netdev(dmfe_dev);    db = (board_info_t *) dmfe_dev->priv;    release_region(dmfe_dev->base_addr, 2);    kfree(db);			/* free board information */    kfree(dmfe_dev);		/* free device structure */    DMFE_DBUG(0, "clean_module() exit", 0);}#elsestatic int __init dmfe_init_module(void){    int err;	 //printk("\n\nsun----dmfe_init_module\n\n");    dmfe_dev = alloc_etherdev(sizeof(*dmfe_dev));    dmfe_dev->init = dmfe_probe;    /* Find a name for this unit */    err = dev_alloc_name(dmfe_dev, "eth%d");    if (err < 0)    	{    	printk("\nsun---dev_alloc_name error\n");	return err;    	}    err = register_netdev(dmfe_dev);    if (err < 0)     	{    		printk("\n sun----register_netdev error\n");		return err;    	}    return 0;}static void __exit dmfe_cleanup_module(void){     printk("\n\nsun----dmfe_cleanup_module\n\n");    unregister_netdev(dmfe_dev);    kfree(dmfe_dev->priv);    memset(dmfe_dev, 0, sizeof (*dmfe_dev));    dmfe_dev->init = dmfe_probe;}module_init(dmfe_init_module);module_exit(dmfe_cleanup_module);#endif//MODULE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -