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

📄 cs8900-2624.c

📁 cs8900网卡驱动。运行环境为ARM9+LINUX
💻 C
📖 第 1 页 / 共 2 页
字号:
	printk("In %s, Transmit ok, kfree skb\n", __FUNCTION__);	return 0;}/**************************************** * cs8900_interrupt * interrupt routine for cs8900 irqnumber(53) ***************************************/static irqreturn_t cs8900_interrupt(int irq, void *dev_id){	struct net_device *ndev = (struct net_device *)dev_id;	volatile u16 status, missed, collision;	int handled = 0;	status = cs8900_read(ndev, PP_ISQ);	printk("Enter irq, status = 0x%x\n", status);	if (0 == status)		return IRQ_RETVAL(handled);	/* It's our irq, handle it. In every event register, all bits cleared upon readout */	handled = 1;	switch(RegNum(status)) { 		case RxEvent:			/* Receive event handler */			cs8900_irq_receive(ndev, status);			break;		case TxEvent:			/* Transmit event handler */			cs8900_irq_transmit(ndev, status);			break;		case BufEvent:			/* Buffer event handler */			cs8900_irq_buffer(ndev, status);			break;		case TxCOL:			collision = ColCount(cs8900_read(ndev, PP_TxCOL));			if (0 == collision)				collision = ColCount(status);			ndev->stats.collisions += collision;			break;		case RxMISS:			missed = MissCount(cs8900_read(ndev, PP_RxMISS));			if (0 == missed)				missed = MissCount(status);			ndev->stats.rx_errors += missed;			ndev->stats.rx_missed_errors += missed;			break;	}	return IRQ_RETVAL(handled);}/***************************************** * cs8900_irq_receive * Handled Receive Event, called from cs8900_interrupt *****************************************/static void cs8900_irq_receive(struct net_device *ndev, u16 status){	struct sk_buff *skb;	u16 rx_status, length;	rx_status = cs8900_read(ndev, PP_RxEvent);	if (0 == rx_status)		printk("If you read ISQ, related bits in RxEvent has been also cleared \n");	/* Get rx frame status and length */	rx_status = cs8900_read(ndev, PP_RxStatus);	length = cs8900_read(ndev, PP_RxLength);	/* Receive frame error */	if (!(rx_status & RxOK)) {		ndev->stats.rx_errors++;		if (rx_status & (Runt | Extradata))			ndev->stats.rx_length_errors++;		if ((rx_status & CRCerror))			ndev->stats.rx_crc_errors++;		return;	}		/* Receive frame ok */	skb = dev_alloc_skb(length + 2);	if (NULL == skb) {		ndev->stats.rx_dropped++;		return;	}	/* configure sk_buff */	skb_reserve(skb, 2); /* make ip header align */	/* Receive one frame */	cs8900_frame_read(ndev, skb, length);	/* Recognize frame type */	skb->protocol = eth_type_trans(skb, ndev);	/* Update net_device_stats */	ndev->last_rx = jiffies;	ndev->stats.rx_packets++;	ndev->stats.rx_bytes += length;	/* Upload to network subsustem */	netif_rx(skb);}/***************************************** * cs8900_irq_transmit * handled transmit event ****************************************/static void cs8900_irq_transmit(struct net_device *ndev, u16 status){	struct cs8900_dev *priv = netdev_priv(ndev);	if (!(RegContent(status) & TxOK)) {		if (RegContent(status) & Out_of_window)			ndev->stats.tx_window_errors++;		if (RegContent(status) & Jabber)			ndev->stats.tx_aborted_errors++;		if (RegContent(status) & T16coll) 			ndev->stats.collisions += ColCount(cs8900_read(ndev, PP_TxCOL));	} else {		ndev->stats.tx_packets++;		spin_lock(&priv->lock);		ndev->stats.tx_bytes += priv->txlen;		priv->txlen = 0;		spin_unlock(&priv->lock);	}	/* wakeup tx queue */	netif_wake_queue(ndev);}/***************************************** * cs8900_irq_buffer * handled buffer event ****************************************/static void cs8900_irq_buffer(struct net_device *ndev, u16 status){	struct cs8900_dev *priv = netdev_priv(ndev);	u16 missed;	/* If Tx underrun, wake up tx queue, retransmit */	if (RegContent(status) & TxUnderrun) {		ndev->stats.tx_errors++;		ndev->stats.tx_fifo_errors++;		spin_lock(&priv->lock);		priv->txlen = 0;		spin_unlock(&priv->lock);		/* wake up tx queue */		netif_wake_queue(ndev);	}	/* Rx missed */	if (RegContent(status) & RxMISS) {		missed = MissCount(cs8900_read(ndev, PP_RxMISS));		ndev->stats.rx_errors += missed;		ndev->stats.rx_missed_errors += missed;	};		/* Ready for tx */	if (RegContent(status) & Rdy4Tx)		netif_wake_queue(ndev);		}/****************************************** * cs8900_probe: allocate and initialize net_device and cs8900_dev ******************************************/static int __devinit cs8900_probe(struct platform_device *pdev){	struct net_device *ndev;	struct cs8900_dev *priv;	int i, ret;	u16 value;	u32 iovalue;	struct resource *res;	printk(VER_STR"\n");	/* Set band3 width as 16bits, enable WAIT */	iovalue = ioread32(S3C2410_BWSCON);	iovalue &= ~(0xf<<12);	iovalue |= 0xd << 12;	iowrite32(iovalue, S3C2410_BWSCON);	/* Set bank3 access time 	 * Tacs: 0 clock;  Tcos: 4 clock;	 * Tacc: 14 clock; Tcoh: 1 clock;	 * Tcah: 4 clock;  Tacp: 6 clock;	 * Page mode: normal   	 */	iowrite32(0x1f7c, S3C2410_BANKCON3);	/* Initialize net_device */	ndev = alloc_etherdev(sizeof(struct cs8900_dev));	if (!ndev) {		printk("%s: could not allocate net_dev.\nh", DRV_NAME);		return -ENOMEM;	}	//SET_MODULE_OWNER(ndev);	SET_NETDEV_DEV(ndev, &pdev->dev);	platform_set_drvdata(pdev, ndev);	/* setup cs8900_dev */	//priv = (struct cs8900_dev *)ndev->priv;	priv = netdev_priv(ndev);	memset(priv, 0, sizeof(struct cs8900_dev));	spin_lock_init(&priv->lock);	priv->netdev = ndev;	/* get io address and irq number from pdev */	if (pdev->num_resources != 2) {		printk("cs8900 platform_device error.\n");		ret = -EBUSY;		goto out;	} 	 	/* get irq num */        ndev->irq = (unsigned int)platform_get_irq(pdev, 0);        if (0 == ndev->irq) {                ret = -EBUSY;                goto out;        }	printk("CS8900a irq num is %d\n", ndev->irq);	/* get io address */	res = platform_get_resource(pdev, IORESOURCE_IO, 0);        if (NULL == res) {                ret = -EBUSY;		goto out;        }        priv->phy_addr = res->start + CS8900_REGOFF;	priv->addr_len = res->end - res->start + 1;	printk("cs8900 phy address is 0x%x, len is %d\n", priv->phy_addr, priv->addr_len);	/* allocate iomem */	if (!request_mem_region(priv->phy_addr, priv->addr_len, pdev->name)) {		priv->phy_addr = 0;		ret = -EBUSY;		goto out;	}	/* ioremap */	priv->ioaddr = ioremap(priv->phy_addr, priv->addr_len);	if (NULL == priv->ioaddr) {		printk(KERN_ERR "%s: Failed to ioremap.\n", DRV_NAME);		ret = -EINVAL;		goto out;	}	ndev->base_addr = (unsigned long)priv->ioaddr;	printk("cs8900 base_addr is 0x%x\n", ndev->base_addr);	/* Verify EISA indentification for CS8900A */	if ((value = cs8900_read(ndev, PP_ProductID)) != EISA_REG_CODE) {		printk(KERN_ERR "%s: incorrect identification. 0x%.4x\n", ndev->name, value);		ret = -ENXIO;		goto out;	}		/* Verify chip version */	value = cs8900_read(ndev, (PP_ProductID + 2));	printk("version value is 0x%x\n", value);	if (PRODUCT_ID(value) != CS8900A) {		printk(KERN_ERR "%s: unknown chip revision 0x %.4x\n", ndev->name, REVISION(value));		ret = -ENXIO;		goto out;	}	ether_setup(ndev);	/* Configure net_device */	ndev->open 		= cs8900_open;	ndev->stop		= cs8900_stop;	ndev->hard_start_xmit 	= cs8900_send_start;	ndev->get_stats		= cs8900_get_stats;	ndev->tx_timeout	= cs8900_transmit_timeout;	ndev->watchdog_timeo	= 2*HZ;  /* for tx timeout */	/* set cs8900's physical interface */	ndev->if_port 	= IF_PORT_10BASET;	/* set net_device's feature */	ndev->features = NETIF_F_HW_CSUM;	/* choose cs8900's irq pin */	cs8900_write(ndev, PP_IntNum, INTRQ0);	/* save mac address to net_device and cs8900 */	ndev->dev_addr[0] = 0x08;	ndev->dev_addr[1] = 0x00;	ndev->dev_addr[2] = 0x3e;	ndev->dev_addr[3] = 0x26;	ndev->dev_addr[4] = 0x0a;	ndev->dev_addr[5] = 0x5b;		for (i = 0; i < ETH_ALEN; i += 2) 		cs8900_write(ndev, (PP_IA + i), (ndev->dev_addr[i] | (ndev->dev_addr[i+1]<<8)));	/* print mac address */	printk("MAC address:");	for (i=0; i<ETH_ALEN; i+=2) {		u16 mac = cs8900_read(ndev, PP_IA+i);		printk("%02X : %02X :", mac&0xff, mac>>8);	}		printk("\n"); 	memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);		/* reset cs8900 chip */	cs8900_reset(ndev);	/* register net_device */	ret = register_netdev(ndev);	if (ret) {		printk("%s: Register net_device failed.\n", ndev->name);		goto out;	}	printk("%s: Register net_device ok.\n", ndev->name);	return 0;//out_err://	unregister_netdev(ndev);out:	cs8900_cleanup(ndev);	free_netdev(ndev);	return ret;}/* cs8900_remove: free everything */static int __devexitcs8900_remove(struct platform_device *pdev){	struct net_device *ndev = platform_get_drvdata(pdev);	unregister_netdev(ndev);	cs8900_cleanup(ndev);	free_netdev(ndev);	return 0;}static struct platform_driver cs8900_drv = {	.probe 	= cs8900_probe,	.remove = cs8900_remove,	.driver = {		.owner = THIS_MODULE,		.name = DRV_NAME,	},};/* module init */static int __init cs8900_init(void){	printk(KERN_INFO "Register %s driver\n", DRV_NAME);	return platform_driver_register(&cs8900_drv);}/* module exit */static void __exitcs8900_exit(void){	printk(KERN_INFO "Unregister %s driver\n", DRV_NAME);	platform_driver_unregister(&cs8900_drv);}module_init(cs8900_init);module_exit(cs8900_exit);MODULE_LICENSE("GPL");MODULE_VERSION("0.2");MODULE_AUTHOR("Nolan");MODULE_DESCRIPTION(VER_STR);

⌨️ 快捷键说明

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