📄 cs8900-2624.c
字号:
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 + -