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

📄 dm9000.c

📁 一个针对linux-2.6.24.4和s3c2440平台已移植好的DM9000A的网卡驱动程序。 本人自己移植的
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* setup board info structure */	db = (struct board_info *) ndev->priv;	memset(db, 0, sizeof (*db));//-----------yangdk------------------------------------------------->/*	#define	INTMOD	0x4A000008	static void *intmod;	intmod = ioremap_nocache(INTMOD,0x4);	writel(0x0,intmod);	printk("intmod:0x%08x%\n",intmod);*/static void *bwscon,*bankcon4,*bankcon5;static void *gpfcon,*gpfcon1;static void *extint0,*extint01;static void *intmsk;static void *dsc0,*dsc1;#define BWSCON           (0x48000000)#define BANKCON4	 (0x48000014)#define BANKCON5	 (0x48000018)#define GPFCON           (0x56000060)  //infact: GPGCON=0X56000060#define GPFCON1          (0x56000050)//#define EXTINT0           (0x56000088)#define EXTINT0          (0x5600008C)                 //fla in fact :EXTINT1=0X5600008C#define EXTINT01         (0x56000088)#define INTMSK           (0x4A000008)#define DSC0		 (0x560000c4)#define DSC1		 (0x560000c8)	bwscon=ioremap_nocache(BWSCON,0x0000004);	bankcon4=ioremap_nocache(BANKCON4,0x0000004);	bankcon5=ioremap_nocache(BANKCON5,0x0000004);		gpfcon=ioremap_nocache(GPFCON,0x0000004);		gpfcon1=ioremap_nocache(GPFCON1,0x0000004);	//extint0=ioremap_nocache(EXTINT0,0x0000004);	extint0=ioremap_nocache(EXTINT0,0x0000004);//fla	extint01=ioremap_nocache(EXTINT01,0x0000004);//fla		intmsk=ioremap_nocache(INTMSK,0x0000004);	dsc0=ioremap_nocache(DSC0,0x0000004);	dsc1=ioremap_nocache(DSC1,0x0000004);	               	//important!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!	writel(readl(bwscon)|0xc0000,bwscon);//	writel(readl(bankcon5)&0x0,bankcon5);//	writel(readl(bankcon5)|0x2ed0,bankcon5);	writel(readl(dsc1)|(0xf<<8),dsc1);	//writel(readl(gpfcon)|0xaa,gpfcon); //old  fla    //for u-sbc2440	s3c2410_gpio_cfgpin(S3C2410_GPF3, S3C2410_GPF3_EINT3);   //for u-sbc2440	writel((readl(extint01)&(~(3<<13)))|(1<<12),extint01); //eint3 high level	writel(readl(intmsk)&(~(1<<3)),intmsk); //	//<-----------yangdk------------------------------------------------	spin_lock_init(&db->lock);	if (pdev->num_resources < 2) {		ret = -ENODEV;		goto out;	} else if (pdev->num_resources == 2) {		base = pdev->resource[0].start;		if (!request_mem_region(base, 4, ndev->name)) {			ret = -EBUSY;			goto out;		}		ndev->base_addr = base;		ndev->irq = pdev->resource[1].start;		db->io_addr = (void __iomem *)base;		db->io_data = (void __iomem *)(base + 4);		/* ensure at least we have a default set of IO routines */		dm9000_set_io(db, 2);	} else {		db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);		db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);		db->irq_res  = platform_get_resource(pdev, IORESOURCE_IRQ, 0);		if (db->addr_res == NULL || db->data_res == NULL ||		    db->irq_res == NULL) {			printk(KERN_ERR PFX "insufficient resources\n");			ret = -ENOENT;			goto out;		}		i = res_size(db->addr_res);		db->addr_req = request_mem_region(db->addr_res->start, i,						  pdev->name);		if (db->addr_req == NULL) {			printk(KERN_ERR PFX "cannot claim address reg area\n");			ret = -EIO;			goto out;		}		db->io_addr = ioremap(db->addr_res->start, i);		if (db->io_addr == NULL) {			printk(KERN_ERR "failed to ioremap address reg\n");			ret = -EINVAL;			goto out;		}		iosize = res_size(db->data_res);		db->data_req = request_mem_region(db->data_res->start, iosize,						  pdev->name);		if (db->data_req == NULL) {			printk(KERN_ERR PFX "cannot claim data reg area\n");			ret = -EIO;			goto out;		}		db->io_data = ioremap(db->data_res->start, iosize);		if (db->io_data == NULL) {			printk(KERN_ERR "failed to ioremap data reg\n");			ret = -EINVAL;			goto out;		}		/* fill in parameters for net-dev structure */		ndev->base_addr = (unsigned long)db->io_addr;		ndev->irq	= db->irq_res->start;		/* ensure at least we have a default set of IO routines */		dm9000_set_io(db, iosize);	}	/* check to see if anything is being over-ridden */	if (pdata != NULL) {		/* check to see if the driver wants to over-ride the		 * default IO width */		if (pdata->flags & DM9000_PLATF_8BITONLY)			dm9000_set_io(db, 1);		if (pdata->flags & DM9000_PLATF_16BITONLY)			dm9000_set_io(db, 2);		if (pdata->flags & DM9000_PLATF_32BITONLY)			dm9000_set_io(db, 4);		/* check to see if there are any IO routine		 * over-rides */		if (pdata->inblk != NULL)			db->inblk = pdata->inblk;		if (pdata->outblk != NULL)			db->outblk = pdata->outblk;		if (pdata->dumpblk != NULL)			db->dumpblk = pdata->dumpblk;	}	dm9000_reset(db);	/* try two times, DM9000 sometimes gets the first read wrong */	for (i = 0; i < 2; i++) {		id_val  = ior(db, DM9000_VIDL);		id_val |= (u32)ior(db, DM9000_VIDH) << 8;		id_val |= (u32)ior(db, DM9000_PIDL) << 16;		id_val |= (u32)ior(db, DM9000_PIDH) << 24;		if (id_val == DM9000_ID)			break;		printk("%s: read wrong id 0x%08x\n", CARDNAME, id_val);	}	if (id_val != DM9000_ID) {		printk("%s: wrong id: 0x%08x\n", CARDNAME, id_val);		ret = -ENODEV;		goto out;	}	/* from this point we assume that we have found a DM9000 */	/* driver system function */	ether_setup(ndev);	ndev->open		 = &dm9000_open;	ndev->hard_start_xmit    = &dm9000_start_xmit;	ndev->tx_timeout         = &dm9000_timeout;	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);	ndev->stop		 = &dm9000_stop;	ndev->set_multicast_list = &dm9000_hash_table;#ifdef CONFIG_NET_POLL_CONTROLLER	ndev->poll_controller	 = &dm9000_poll_controller;#endif#ifdef DM9000_PROGRAM_EEPROM	program_eeprom(db);#endif	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	     = ndev;	db->mii.mdio_read    = dm9000_phy_read;	db->mii.mdio_write   = dm9000_phy_write;	/* 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++)		ndev->dev_addr[i] = db->srom[i];	if (!is_valid_ether_addr(ndev->dev_addr)) {		/* try reading from mac */		for (i = 0; i < 6; i++)			//ndev->dev_addr[i] = ior(db, i+DM9000_PAR);	//yangdk			ndev->dev_addr[i] = ne_def_eth_mac_addr[i];	}	if (!is_valid_ether_addr(ndev->dev_addr))		printk("%s: Invalid ethernet MAC address.  Please "		       "set using ifconfig\n", ndev->name);	platform_set_drvdata(pdev, ndev);	ret = register_netdev(ndev);	if (ret == 0) {		DECLARE_MAC_BUF(mac);		printk("%s: dm9000 at %p,%p IRQ %d MAC: %s\n",		       ndev->name,  db->io_addr, db->io_data, ndev->irq,		       print_mac(mac, ndev->dev_addr));	}	return 0;out:	printk("%s: not found (%d).\n", CARDNAME, ret);	dm9000_release_board(pdev, db);	free_netdev(ndev);	return ret;}/* *  Open the interface. *  The interface is opened whenever "ifconfig" actives it. */static intdm9000_open(struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	PRINTK2("entering dm9000_open\n");	if (request_irq(dev->irq, &dm9000_interrupt, DM9000_IRQ_FLAGS, dev->name, dev))		return -EAGAIN;	/* Initialize DM9000 board */	dm9000_reset(db);	dm9000_init_dm9000(dev);	/* Init driver variable */	db->dbug_cnt = 0;	/* set and active a timer process */	init_timer(&db->timer);	db->timer.expires  = DM9000_TIMER_WUT;	db->timer.data     = (unsigned long) dev;	db->timer.function = &dm9000_timer;	add_timer(&db->timer);	mii_check_media(&db->mii, netif_msg_link(db), 1);	netif_start_queue(dev);	return 0;}/* * Initilize dm9000 board */static voiddm9000_init_dm9000(struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	PRINTK1("entering %s\n",__FUNCTION__);	/* I/O mode */	db->io_mode = ior(db, DM9000_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */	/* GPIO0 on pre-activate PHY */	iow(db, DM9000_GPR, 0);	/* REG_1F bit0 activate phyxcer */	iow(db, DM9000_GPCR, GPCR_GEP_CNTL);	/* Let GPIO0 output */	iow(db, DM9000_GPR, 0);	/* Enable PHY */	/* Program operating register */	iow(db, DM9000_TCR, 0);	        /* TX Polling clear */	iow(db, DM9000_BPTR, 0x3f);	/* Less 3Kb, 200us */	iow(db, DM9000_FCR, 0xff);	/* Flow Control */	iow(db, DM9000_SMCR, 0);        /* Special Mode */	/* clear TX status */	iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);	iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */	/* Set address filter table */	dm9000_hash_table(dev);	/* Activate DM9000 */	iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);	/* Enable TX/RX interrupt mask */	iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);	/* Init Driver variable */	db->tx_pkt_cnt = 0;	db->queue_pkt_len = 0;	dev->trans_start = 0;}/* *  Hardware start transmission. *  Send a packet to media from the upper layer. */static intdm9000_start_xmit(struct sk_buff *skb, struct net_device *dev){	unsigned long flags;	board_info_t *db = (board_info_t *) dev->priv;	PRINTK3("dm9000_start_xmit\n");	if (db->tx_pkt_cnt > 1)		return 1;	spin_lock_irqsave(&db->lock, flags);	/* Move data to DM9000 TX RAM */	writeb(DM9000_MWCMD, db->io_addr);	(db->outblk)(db->io_data, skb->data, skb->len);	dev->stats.tx_bytes += skb->len;	db->tx_pkt_cnt++;	/* TX control: First packet immediately send, second packet queue */	if (db->tx_pkt_cnt == 1) {		/* Set TX length to DM9000 */		iow(db, DM9000_TXPLL, skb->len & 0xff);		iow(db, DM9000_TXPLH, (skb->len >> 8) & 0xff);		/* Issue TX polling command */		iow(db, DM9000_TCR, TCR_TXREQ);	/* Cleared after TX complete */		dev->trans_start = jiffies;	/* save the time stamp */	} else {		/* Second packet */		db->queue_pkt_len = skb->len;		netif_stop_queue(dev);	}	spin_unlock_irqrestore(&db->lock, flags);	/* free this SKB */	dev_kfree_skb(skb);	return 0;}static voiddm9000_shutdown(struct net_device *dev){	board_info_t *db = (board_info_t *) dev->priv;	/* RESET device */	dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET);	/* PHY RESET */	iow(db, DM9000_GPR, 0x01);	/* Power-Down PHY */	iow(db, DM9000_IMR, IMR_PAR);	/* Disable all interrupt */	iow(db, DM9000_RCR, 0x00);	/* Disable RX */}/* * Stop the interface. * The interface is stopped when it is brought. */static intdm9000_stop(struct net_device *ndev){	board_info_t *db = (board_info_t *) ndev->priv;	PRINTK1("entering %s\n",__FUNCTION__);	/* deleted timer */	del_timer(&db->timer);	netif_stop_queue(ndev);	netif_carrier_off(ndev);	/* free interrupt */	free_irq(ndev->irq, ndev);	dm9000_shutdown(ndev);	return 0;}/* * DM9000 interrupt handler * receive the packet to upper layer, free the transmitted packet */static voiddm9000_tx_done(struct net_device *dev, board_info_t * db){	int tx_status = ior(db, DM9000_NSR);	/* Got TX status */	if (tx_status & (NSR_TX2END | NSR_TX1END)) {		/* One packet sent complete */		db->tx_pkt_cnt--;		dev->stats.tx_packets++;		/* Queue packet check & send */		if (db->tx_pkt_cnt > 0) {

⌨️ 快捷键说明

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