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

📄 dm9000x.c

📁 S3C2440开发板
💻 C
📖 第 1 页 / 共 3 页
字号:
	id_val |= inb(iobase + 4) << 16;	outb(DM9000_PID_H, iobase);	id_val |= inb(iobase + 4) << 24;	//printk("id_val is %x\n",id_val);	if (id_val == DM9000_ID) {	    printk("DM9000 ethernet driver V1.26 I/O: %x, VID: %x \n",		    iobase, id_val);	    dm9000_found = TRUE;	    /* Init network device *///                      dev = init_etherdev(dev, 0);	    //modify by he	    /* Allocated board information structure */	    db = (void *) (kmalloc(sizeof (*db), GFP_KERNEL));	    memset(db, 0, sizeof (*db));	    dev->priv		    = db;	/* link device and board info */	    dmfe_dev		    = dev;	    db->ioaddr		    = iobase;	    db->io_data		    = iobase + 4;	    /* driver system function */	    ether_setup(dev);	    dev->base_addr	    = iobase;	    ////dev->irq		    = 10;	    //dev->irq		    = SMDK2410_ETH_IRQ; //--	   // dev->irq		    = IRQ_EINT0; //--	   // dev->irq		    = IRQ_EINT1; //--1,3---0k	    dev->irq		    = IRQ_EINT3;//14 for evalue board.3 for u-sbc2440	    dev->open		    = &dmfe_open;	    dev->hard_start_xmit    = &dmfe_start_xmit;	    dev->stop		    = &dmfe_stop;	    dev->get_stats	    = &dmfe_get_stats;	    dev->set_multicast_list = &dm9000_hash_table;	    dev->do_ioctl	    = &dmfe_do_ioctl;	    SET_MODULE_OWNER(dev);			    db->msg_enable       = NETIF_MSG_LINK;	    db->mii.phy_id_mask  = 0x1f;	    db->mii.reg_num_mask = 0x1f;	    db->mii.force_media  = 0;	    db->mii.full_duplex  = 0;	    db->mii.dev	     = dev;	    db->mii.mdio_read    = dm9000_phy_read;	    db->mii.mdio_write   = dm9000_phy_write;#if 0	/* comment by mhfan */	    /* Read SROM content */	    for (i = 0; i < 64; i++)		((u16 *) db->srom)[i] = read_srom_word(db, i);	    /* Set Node Address */	    for (i = 0; i < 6; i++)		dev->dev_addr[i] = db->srom[i];#else	    //random_ether_addr(dev->dev_addr);	// mhfan	{	    ////unsigned char enet_addr[]={0x26, 0xdc, 0x6c, 0x11, 0x7b, 0xbb}; //origion	    unsigned char  enet_addr[6] = {0x00, 0x12, 0x34, 0x56, 0x80, 0x49}; //from 2.4	    for (i=0; i < 6; i++) dev->dev_addr[i] = enet_addr[i];	}#endif	/* comment by mhfan */	    /* Request IO from system */	    request_region(iobase, 2, dev->name);	}    } while (!dm9000_found && (iobase+=0x10) <= DM9000_MAX_IO);	       return (dm9000_found ? 0 : -ENODEV);}/* Open the interface. * The interface is opened whenever "ifconfig" actives it. */static int dmfe_open(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;	        DMFE_DBUG(0, "dmfe_open", 0);    //MOD_INC_USE_COUNT;	//printk("net irq num is %d\n",dev->irq);         //dev->irq=0;  //--        // dev->irq=IRQ_EINT0 ;  //--        // printk("net irq num is %d\n",dev->irq);	 //printk("dev->name  is %s\n",dev->name);	// set_irq_type(dev->irq, IRQT_RISING);	 										//net irq num is 0										//dev->name  is eth0    //if (request_irq(dev->irq, &dmfe_interrupt, SA_INTERRUPT/*SA_SHIRQ*/, dev->name, dev))    if (request_irq(dev->irq, &dmfe_interrupt, /*SA_INTERRUPT*/SA_SHIRQ, dev->name/*"DM9000 device"*/, dev))    	{    	  //printk("\nequest_irq failure\n\n");  //   if (request_irq(dev->irq, &dmfe_interrupt, SA_INTERRUPT, dev->name, dev))	return -EAGAIN;    	}     	 //printk("sun-----requets irq exit\n");		 /*		//writel(0x04|0x4,extint0);  //OLD   	writel(readl(extint0)|0x4444,extint0); //rising edge	//writel(readl(intmsk)&0xfff7,intmsk);   //OLD    	  writel(readl(intmsk)&0xfffffff0,intmsk); //mask open		 printk("sun-----set irq register exit\n");	 */    /* Initilize DM910X board */    dmfe_init_dm9000(dev);    /* Init driver variable */    db->dbug_cnt	    = 0;    db->runt_length_counter = 0;    db->long_length_counter = 0;    db->reset_counter	    = 0;    /* set and active a timer process */    init_timer(&db->timer);    db->timer.expires	    = DMFE_TIMER_WUT * 2;    db->timer.data	    = (unsigned long) dev;    db->timer.function	    = &dmfe_timer;    add_timer(&db->timer);	// Move to DM9000 initiallization was finished.#if defined(AUTOMDIX)    /* set and active a timer process for Auto-MDIX */    init_timer(&db->mdix_timer);    db->mdix_timer.expires  = DMFE_TIMER_MDIX;    db->mdix_timer.data	    = (unsigned long) dev;    db->mdix_timer.function = &dmfe_mdix_timer;    add_timer(&db->mdix_timer);#endif    mii_check_media(&db->mii, netif_msg_link(db), 1);    netif_start_queue(dev);    enable_irq(dev->irq);    return 0;}/* Set PHY operationg mode */static void set_PHY_mode(board_info_t * db){    u16 phy_reg0 = 0x1000;	/* Auto-negotiation & non-duplux mode */    u16 phy_reg4 = 0x01e1;	/* Default non flow control */    if (!(db->op_mode & DM9000_AUTO)) {	// op_mode didn't auto sense */	switch (db->op_mode) {	case DM9000_10MHD:	    phy_reg4 = 0x21;	    phy_reg0 = 0x0000;	    break;	case DM9000_10MFD:	    phy_reg4 = 0x41;	    phy_reg0 = 0x1100;	    break;	case DM9000_100MHD:	    phy_reg4 = 0x81;	    phy_reg0 = 0x2000;	    break;	case DM9000_100MFD:	    phy_reg4 = 0x101;	    phy_reg0 = 0x3100;	    break;	}			// end of switch    }				// end of if    phy_write(db, 0, phy_reg0);    phy_write(db, 4, 0x0400 | phy_reg4);    db->Preg0 = phy_reg0;    db->Preg4 = phy_reg4 + 0x0400;}/* Init HomeRun DM9801 */static void program_dm9801(board_info_t * db, u16 HPNA_rev){    __u16 reg16, reg17, reg24, reg25;    if (!nfloor) nfloor = DM9801_NOISE_FLOOR;    reg16 = phy_read(db, 16);    reg17 = phy_read(db, 17);    reg24 = phy_read(db, 24);    reg25 = phy_read(db, 25);    switch (HPNA_rev) {    case 0xb900:		/* DM9801 E3 */	reg16 |= 0x1000;	reg25 = ((reg24 + nfloor) & 0x00ff) | 0xf000;	break;    case 0xb901:		/* DM9801 E4 */	reg25 = ((reg24 + nfloor) & 0x00ff) | 0xc200;	reg17 = (reg17 & 0xfff0) + nfloor + 3;	break;    case 0xb902:		/* DM9801 E5 */    case 0xb903:		/* DM9801 E6 */    default:	reg16 |= 0x1000;	reg25 = ((reg24 + nfloor - 3) & 0x00ff) | 0xc200;	reg17 = (reg17 & 0xfff0) + nfloor;    }    phy_write(db, 16, reg16);    phy_write(db, 17, reg17);    phy_write(db, 25, reg25);}/* Init LongRun DM9802 */static void program_dm9802(board_info_t * db){    __u16 reg25;    if (!nfloor) nfloor = DM9802_NOISE_FLOOR;    reg25 = phy_read(db, 25);    reg25 = (reg25 & 0xff00) + nfloor;    phy_write(db, 25, reg25);}/* Identify NIC type */static void identify_nic(board_info_t * db){    u16 phy_reg3;    iow(db, 0, DM9000_EXT_MII);    phy_reg3 = phy_read(db, 3);    switch (phy_reg3 & 0xfff0) {    case 0xb900:	if (phy_read(db, 31) == 0x4404) {	    db->nic_type = HOMERUN_NIC;	    program_dm9801(db, phy_reg3);	} else {	    db->nic_type = LONGRUN_NIC;	    program_dm9802(db);	}	break;    default:	db->nic_type = FASTETHER_NIC;	break;    }    iow(db, 0, DM9000_INT_MII);}/* Initilize dm9000 board */static void dmfe_init_dm9000(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    //printk("\n\nsun----dmfe_init_dm9000\n\n");    DMFE_DBUG(0, "dmfe_init_dm9000()", 0);    /* set the internal PHY power-on, GPIOs normal, and wait 2ms */    iow(db, 0x1F, 0);		/* GPR (reg_1Fh)bit GPIO0=0 pre-activate PHY */    udelay(20);			/* wait 2ms for PHY power-on ready */    /* do a software reset and wait 20us */    iow(db, DM9000_NCR, 3);    udelay(20);			/* wait 20us at least for software reset ok */    iow(db, 0, 3);		/* NCR (reg_00h) bit[0] RST=1 & Loopback=1,				 * reset on. Added by SPenser */    udelay(20);			/* wait 20us at least for software reset ok */// Marked by Spenser    /* set GPIO0=1 then GPIO0=0 to turn off and on the internal PHY */    iow(db, 0x1F, 1);		/* GPR (reg_1Fh) bit[0] GPIO0=1 turn-off PHY  */    iow(db, 0x1F, 0);		/* GPR (reg_1Fh) bit[0] GPIO0=0 activate PHY  *///modify by he    udelay(1000);		/* wait 4ms linking PHY (AUTO sense) if RX/TX */    udelay(1000);    udelay(1000);    udelay(1000);    /* I/O mode */    db->io_mode = ior(db, 0xfe) >> 6;	/* ISR bit7:6 keeps I/O mode */    /* NIC Type: FASTETHER, HOMERUN, LONGRUN */    identify_nic(db);    /* Set PHY */    db->op_mode = media_mode;    set_PHY_mode(db);    /* Init needed register value */    db->reg0 = DM9000_NCR;    if ((db->nic_type != FASTETHER_NIC) && (db->op_mode & DM9000_1M_HPNA))	db->reg0 |= DM9000_EXT_MII;    /* User passed argument */    db->reg5 = reg5;    db->reg8 = reg8;    db->reg9 = reg9;    db->rega = rega;    /* Program operating register */    iow(db, 0x00, 0x08);    iow(db, 0x02, 0);		/* TX Polling clear */    iow(db, 0x2f, 0);		/* Special Mode */    iow(db, 0x01, 0x2c);	/* clear TX status */    iow(db, 0xfe, 0x0f);	/* Clear interrupt status */    iow(db, 0x08, 0x37);    iow(db, 0x09, 0x38);	/* Flow control: High/Low water */    iow(db, 0x0a, 0x29);	/* flow control */    /* Set address filter table */    dm9000_hash_table(dev);    /* Activate DM9000 */    iow(db, 0x05, db->reg5 | 1);	/* RX enable */    iow(db, 0xff, DM9000_REGFF);	/* Enable TX/RX interrupt mask */    /* Init Driver variable */    db->link_failed	= 1;    db->tx_pkt_cnt	= 0;    db->queue_pkt_len	= 0;    dev->trans_start	= 0;    netif_carrier_on(dev);    spin_lock_init(&db->lock);}#if 0	/* comment by mhfan *//* Reset dm9000 board due to 32bits mode while excess collision * or late collision. */static void dmfe_reset_dm9000(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    DMFE_DBUG(0, "dmfe_reset_dm9000()", 0);    iow(db, 0, 1);		/* NCR (reg_00h) bit[0] RST=1, reset on.				 * Added by SPenser */    udelay(1);			/* wait 20us at least for software reset ok */    iow(db, 0, 0);    /* software reset 2 times */    iow(db, DM9000_NCR, 3);    udelay(20);    iow(db, DM9000_NCR, 3);    udelay(20);    /* Program operating register */    iow(db, 0x00, db->reg0);    iow(db, 0x02, 0);		/* TX Polling clear */    iow(db, 0x08, 0x3f);	/* Less 3Kb, 200us */    iow(db, 0x09, 0x38);	/* Flow Control : High/Low Water */    iow(db, 0x0a, 0x29);	/* TX Pause packet */    iow(db, 0x2f, 0);		/* Special Mode */    iow(db, 0x01, 0x2c);	/* clear TX status */    iow(db, 0xfe, 0x0f);	/* Clear interrupt status */    /* Activate DM9000 */    iow(db, 0x05, db->reg5 | 1);	/* RX enable */    iow(db, 0xff, DM9000_REGFF);	/* Enable TX/RX interrupt mask */    /* Init Driver variable */    db->link_failed = 1;    db->tx_pkt_cnt = 0;    db->queue_pkt_len = 0;    dev->trans_start = 0;    netif_carrier_on(dev);}#endif	/* comment by mhfan *//* Hardware start transmission. * Send a packet to media from the upper layer. */static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    char *data_ptr;    int i, tmplen;  //printk("\n\nsun----dmfe_start_xmit\n\n");    DMFE_DBUG(0, "dmfe_start_xmit", 0);    if (db->tx_pkt_cnt > 1) return 1;    netif_stop_queue(dev);    /* Disable all interrupt */    iow(db, 0xff, 0x80);    /* Move data to DM9000 TX RAM */    data_ptr = (char *) skb->data;    outb(0xf8, db->ioaddr);    db->sent_pkt_len = skb->len;    if (db->io_mode == DM9000_BYTE_MODE) {	    /* Byte mode */	for (i = 0; i < skb->len; i++)	    outb((data_ptr[i] & 0xff), db->io_data);    } else if (db->io_mode == DM9000_WORD_MODE) {   /* Word mode */	tmplen = (skb->len + 1) / 2;#if 0 	/* comment by mhfan */{    int j = 0;    for (i = 0; i < tmplen; i++) {	printk("%04x ", ((u16 *) data_ptr)[i]);	if (++j == 16) { printk("\n"); j = 0; }    }    printk("\n\033[0m");}#endif	/* comment by mhfan */	for (i = 0; i < tmplen; i++)	    outw(((u16 *) data_ptr)[i], db->io_data);    } else {					    /* DWord mode */	tmplen = (skb->len + 3) / 4;	for (i = 0; i < tmplen; i++)	    outl(((u32 *) data_ptr)[i], db->io_data);    }    /* TX control: First packet immediately send, second packet queue */    if (db->tx_pkt_cnt == 0) {			/* First Packet */	db->tx_pkt_cnt++;	/* Set TX length to DM9000 */	iow(db, 0xfc, skb->len & 0xff);	iow(db, 0xfd, (skb->len >> 8) & 0xff);	/* Issue TX polling command */	iow(db, 0x2, 0x1);			/* Cleared after TX complete */	/* saved the time stamp */	dev->trans_start = jiffies;    } else {					/* Second packet */	db->tx_pkt_cnt++;	db->queue_pkt_len = skb->len;    }    /* free this SKB */    dev_kfree_skb(skb);    /* Re-enable resource check */    if (db->tx_pkt_cnt == 1) netif_wake_queue(dev);    /* Re-enable interrupt */iow(db, 0xff, 0x83);    return 0;}/* Stop the interface. * The interface is stopped when it is brought. */static int dmfe_stop(struct net_device *dev){    board_info_t *db = (board_info_t *) dev->priv;    //printk("\n\nsun----dmfe_stop\n\n");    DMFE_DBUG(0, "dmfe_stop", 0);    /* deleted timer */    del_timer(&db->timer);    del_timer(&db->mdix_timer);    netif_stop_queue(dev);    /* free interrupt */    free_irq(dev->irq, dev);    /* RESET devie */    phy_write(db, 0x00, 0x8000);	/* PHY RESET */    iow(db, 0x1f, 0x01);	/* Power-Down PHY */    iow(db, 0xff, 0x80);	/* Disable all interrupt */    iow(db, 0x05, 0x00);	/* Disable RX */    //MOD_DEC_USE_COUNT;#if FALSE /* Dump Statistic counter */    printk("\nRX FIFO OVERFLOW %lx\n", db->stats.rx_fifo_errors);    printk("RX CRC %lx\n", db->stats.rx_crc_errors);    printk("RX LEN Err %lx\n", db->stats.rx_length_errors);    printk("RX LEN < 64byte %x\n", db->runt_length_counter);    printk("RX LEN > 1514byte %x\n", db->long_length_counter);    printk("RESET %x\n", db->reset_counter);    printk("RESET: TX Timeout %x\n", db->reset_tx_timeout);    printk("RESET: RX Status Wrong %x\n", db->reset_rx_status);#endif    return 0;}static void dmfe_tx_done(unsigned long unused){    struct net_device *dev = dmfe_dev;    board_info_t *db = (board_info_t *) dev->priv;    int tx_status = ior(db, 0x01);	/* Got TX status */    DMFE_DBUG(0, "dmfe_tx_done()", 0);    if (tx_status & 0xc) {		/* One packet sent complete */	db->tx_pkt_cnt--;	dev->trans_start = 0;	db->stats.tx_packets++;	if (db->tx_pkt_cnt > 0) {	/* Queue packet check & send */	    /* Set TX length to DM9000 */	    iow(db, 0xfc, db->queue_pkt_len & 0xff);	    iow(db, 0xfd, (db->queue_pkt_len >> 8) & 0xff);	    /* Issue TX polling command */	    iow(db, 0x2, 0x1);		/* Cleared after TX complete */	    dev->trans_start = jiffies;	/* saved the time stamp */	}	netif_wake_queue(dev);    }}/* DM9102 insterrupt handler. * receive the packet to upper layer, free the transmitted packet */static irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs){    struct net_device *dev = dev_id;    board_info_t *db;    int int_status;    u8 reg_save;   //printk("\n\nsun----dmfe_interrupt\n\n");#if 0	/* comment by mhfan */    DMFE_DBUG(0, "dmfe_interrupt()", 0);

⌨️ 快捷键说明

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