On 4/23/06, Herbert Xu <[EMAIL PROTECTED]> wrote: > On Thu, Apr 20, 2006 at 09:54:54AM +0800, Aubrey wrote: > Please send me a copy of the driver source that you were using when > this happened.
The driver is attached. > Could you please add a printk in checksum_udp to print out the pertinent > values such as the expected checksum and actual checksum? > It seems not only "checksum_udp" in "netpoll", a few other routines will call "__skb_checksum_complete", So the routine "__skb_checksum_complete" must be ok. And, The routine "csum_tcpudp_nofold" should be ok, too. Because it's called by many other routines, too. But, I don't understand, why assign "psum=csum_tcpudp_nofold()" to "skb->csum", and make "__skb_checksum_complete" to do the checksum? Thanks for your any hints Regards, -Aubrey ================================================================ static int checksum_udp(struct sk_buff *skb, struct udphdr *uh, unsigned short ulen, u32 saddr, u32 daddr) { unsigned int psum; if (uh->check == 0 || skb->ip_summed == CHECKSUM_UNNECESSARY) return 0; psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); if (skb->ip_summed == CHECKSUM_HW && !(u16)csum_fold(csum_add(psum, skb->csum))) return 0; skb->csum = psum; return __skb_checksum_complete(skb); } ==================================================================
static const char version[] = "bf53mac.c: v1.0, Aug 27 2005 by Luke Yang <[EMAIL PROTECTED]>\n"; /* Debugging level */ #ifndef BF537MAC_DEBUG #define BF537MAC_DEBUG 0 #endif #include <linux/config.h> #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/delay.h> #include <linux/timer.h> #include <linux/errno.h> #include <linux/ioport.h> #include <linux/crc32.h> #include <linux/device.h> #include <linux/spinlock.h> #include <linux/ethtool.h> #include <linux/mii.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> #include <linux/platform_device.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/dma.h> #include <linux/dma-mapping.h> #include "bfin_mac.h" #include <asm/irq.h> #include <asm/blackfin.h> #include <asm/delay.h> MODULE_LICENSE("GPL"); #define CARDNAME "bfin_mac" static void desc_list_free(void); /* transmit net_dma_desc numbers */ #define INIT_DESC_NUM 12 #define MAX_DESC_NUM 64 #define MAX_RX_DESC_NUM 8 /* pointers to maintain transmit list */ struct net_dma_desc *tx_list_head; struct net_dma_desc *tx_list_tail; struct net_dma_desc *rx_list_head; struct net_dma_desc *rx_list_tail; struct net_dma_desc *current_rx_ptr; struct net_dma_desc *current_tx_ptr; int current_desc_num; extern unsigned long l1_data_A_sram_alloc(unsigned long size); extern unsigned long l1_data_A_sram_free(unsigned long size); extern void get_bf537_ether_addr(char *addr); static int desc_list_init(void) { struct net_dma_desc *tmp_desc; int i; dma_addr_t dma_handle; /* init tx_list */ if (current_desc_num == 0) { for (i=0;i < INIT_DESC_NUM;i++) { tmp_desc = (struct net_dma_desc *)dma_alloc_coherent(NULL, sizeof(struct net_dma_desc), &dma_handle , GFP_DMA); //tmp_desc = (struct net_dma_desc *)l1_data_A_sram_alloc(sizeof(struct net_dma_desc)); if (tmp_desc == NULL) goto error; else memset(tmp_desc,0,sizeof(tmp_desc)); if (i == 0) { tx_list_head = tmp_desc; tx_list_tail = tmp_desc; } tmp_desc->desc_a.start_addr = (unsigned long)tmp_desc->packet; tmp_desc->desc_a.x_count = 0; tmp_desc->desc_a.config.b_DMA_EN = 0; //disabled tmp_desc->desc_a.config.b_WNR = 0; //read from memory tmp_desc->desc_a.config.b_WDSIZE = 2; //wordsize is 32 bits tmp_desc->desc_a.config.b_NDSIZE = 6; //6 half words is desc size. tmp_desc->desc_a.config.b_FLOW = 7; //large desc flow tmp_desc->desc_a.next_dma_desc = &(tmp_desc->desc_b); tmp_desc->desc_b.start_addr = (unsigned long)(&(tmp_desc->status)); tmp_desc->desc_b.x_count = 0; tmp_desc->desc_b.config.b_DMA_EN = 1; //disabled tmp_desc->desc_b.config.b_WNR = 1; //write to memory tmp_desc->desc_b.config.b_WDSIZE = 2; //wordsize is 32 bits tmp_desc->desc_b.config.b_DI_EN = 0; //disable interrupt tmp_desc->desc_b.config.b_NDSIZE = 6; tmp_desc->desc_b.config.b_FLOW = 7; //stop mode tx_list_tail->desc_b.next_dma_desc = &(tmp_desc->desc_a); tx_list_tail->next = tmp_desc; tx_list_tail = tmp_desc; } tx_list_tail->next = tx_list_head; /* tx_list is a circle */ tx_list_tail->desc_b.next_dma_desc = &(tx_list_head->desc_a); current_desc_num = INIT_DESC_NUM; current_tx_ptr = tx_list_head; } /* init rx_list */ for (i = 0; i < MAX_RX_DESC_NUM; i++) { //tmp_desc = (struct net_dma_desc *)dma_alloc_coherent(NULL, sizeof(struct net_dma_desc), &dma_handle , GFP_DMA); tmp_desc = (struct net_dma_desc *)l1_data_A_sram_alloc(sizeof(struct net_dma_desc)); if (tmp_desc == NULL) goto error; else memset(tmp_desc,0,sizeof(tmp_desc)); if (i == 0) { rx_list_head = tmp_desc; rx_list_tail = tmp_desc; } tmp_desc->desc_a.start_addr = (unsigned long)tmp_desc->packet; tmp_desc->desc_a.x_count = 0; tmp_desc->desc_a.config.b_DMA_EN = 1; //enabled tmp_desc->desc_a.config.b_WNR = 1; //Write to memory tmp_desc->desc_a.config.b_WDSIZE = 2; //wordsize is 32 bits tmp_desc->desc_a.config.b_NDSIZE = 6; //6 half words is desc size. tmp_desc->desc_a.config.b_FLOW = 7; //large desc flow tmp_desc->desc_a.next_dma_desc = &(tmp_desc->desc_b); tmp_desc->desc_b.start_addr = (unsigned long)(&(tmp_desc->status)); tmp_desc->desc_b.x_count = 0; tmp_desc->desc_b.config.b_DMA_EN = 1; //enabled tmp_desc->desc_b.config.b_WNR = 1; //Write to memory tmp_desc->desc_b.config.b_WDSIZE = 2; //wordsize is 32 bits tmp_desc->desc_b.config.b_NDSIZE = 6; tmp_desc->desc_b.config.b_DI_EN = 1; //enable interrupt tmp_desc->desc_b.config.b_FLOW = 7; //stop rx_list_tail->desc_b.next_dma_desc = &(tmp_desc->desc_a); rx_list_tail->next = tmp_desc; rx_list_tail = tmp_desc; } rx_list_tail->next = rx_list_head; /* rx_list is a circle */ rx_list_tail->desc_b.next_dma_desc = &(rx_list_head->desc_a); current_rx_ptr = rx_list_head; return 0; error: desc_list_free(); printk("bf537mac: kmalloc failed. \n"); return -ENOMEM; } static void desc_list_free(void) { struct net_dma_desc *tmp_desc; int i; dma_addr_t dma_handle = 0; tmp_desc = tx_list_head; for (i = 0; i < INIT_DESC_NUM; i++) { if (tmp_desc != NULL) dma_free_coherent(NULL, sizeof(struct net_dma_desc), tmp_desc, dma_handle); tmp_desc = tmp_desc->next; } tmp_desc = rx_list_head; for (i = 0; i < MAX_RX_DESC_NUM; i++) { if (tmp_desc != NULL) l1_data_A_sram_free((unsigned long)tmp_desc); tmp_desc = tmp_desc->next; } } /*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ // //Set FER regs to MUX in Ethernet pins // static void SetupPinMux(void) { unsigned int fer_val; // FER reg bug work-around // read it once fer_val = *pPORTH_FER; fer_val = 0xffff; // write it twice to the same value *pPORTH_FER = fer_val; *pPORTH_FER = fer_val; } // //Wait until the previous MDC/MDIO transaction has completed // static void PollMdcDone(void) { // poll the STABUSY bit while((*pEMAC_STAADD) & STABUSY) {}; } // //Read an off-chip register in a PHY through the MDC/MDIO port // static u16 RdPHYReg(u16 PHYAddr, u16 RegAddr) { PollMdcDone(); *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) | STABUSY; // read mode PollMdcDone(); return (u16)*pEMAC_STADAT; } // //Write an off-chip register in a PHY through the MDC/MDIO port // static void RawWrPHYReg(u16 PHYAddr, u16 RegAddr, u32 Data) { *pEMAC_STADAT = Data; *pEMAC_STAADD = SET_PHYAD(PHYAddr) | SET_REGAD(RegAddr) | STAOP | STABUSY; //write mode PollMdcDone(); } static void WrPHYReg(u16 PHYAddr, u16 RegAddr, u32 Data) { PollMdcDone(); RawWrPHYReg(PHYAddr,RegAddr,Data); } // //set up the phy // static int bf537mac_setphy(struct net_device *dev) { u16 phydat; u32 sysctl; struct bf537mac_local *lp = netdev_priv(dev); //printk("bf537_mac: start settting up phy\n"); //Program PHY registers phydat = 0; // issue a reset RawWrPHYReg(lp->PhyAddr, PHYREG_MODECTL, 0x8000); // wait half a second udelay(500); phydat = RdPHYReg(lp->PhyAddr, PHYREG_MODECTL); // advertise flow control supported phydat = RdPHYReg(lp->PhyAddr, PHYREG_ANAR); phydat |= (1 << 10); WrPHYReg(lp->PhyAddr, PHYREG_ANAR, phydat); phydat = 0; if (lp->Negotiate) { phydat |= 0x1000;// enable auto negotiation } else { if (lp->FullDuplex) { phydat |= (1 << 8);// full duplex } else { phydat &= (~(1 << 8));// half duplex } if (!lp->Port10) { phydat |= (1 << 13);// 100 Mbps } else { phydat &= (~(1 << 13));// 10 Mbps } } if (lp->Loopback) { phydat |= (1 << 14);// enable TX->RX loopback //WrPHYReg(lp->PhyAddr, PHYREG_MODECTL, phydat); } WrPHYReg(lp->PhyAddr, PHYREG_MODECTL, phydat); udelay(500); phydat = RdPHYReg(lp->PhyAddr, PHYREG_MODECTL); // check for SMSC PHY if ((RdPHYReg(lp->PhyAddr, PHYREG_PHYID1) == 0x7) && ((RdPHYReg(lp->PhyAddr, PHYREG_PHYID2)&0xfff0 ) == 0xC0A0)) { // we have SMSC PHY so reqest interrupt on link down condition WrPHYReg(lp->PhyAddr, 30, 0x0ff); // enable interrupts // enable PHY_INT sysctl = *pEMAC_SYSCTL; sysctl |= 0x1; //*pEMAC_SYSCTL = sysctl; } } /**************************************************************************/ void SetupSystemRegs(struct net_device *dev) { int PHYADDR; unsigned short sysctl, phydat; struct bf537mac_local *lp = netdev_priv(dev); PHYADDR = lp->PhyAddr; /* Enable PHY output */ *pVR_CTL |= PHYCLKOE; /* MDC = 2.5 MHz */ sysctl = SET_MDCDIV(24); /* Odd word alignment for Receive Frame DMA word */ /* Configure checksum support and rcve frame word alignment */ sysctl |= RXDWA; *pEMAC_SYSCTL = sysctl; /* auto negotiation on */ /* full duplex */ /* 100 Mbps */ phydat = PHY_ANEG_EN | PHY_DUPLEX | PHY_SPD_SET; WrPHYReg(PHYADDR, PHYREG_MODECTL, phydat); //*pEMAC_MMC_CTL = RSTC | CROLL | MMCE; *pEMAC_MMC_CTL = RSTC | CROLL; /* Initialize the TX DMA channel registers */ *pDMA2_X_COUNT = 0; *pDMA2_X_MODIFY = 4; *pDMA2_Y_COUNT = 0; *pDMA2_Y_MODIFY = 0; /* Initialize the RX DMA channel registers */ *pDMA1_X_COUNT = 0; *pDMA1_X_MODIFY = 4; *pDMA1_Y_COUNT = 0; *pDMA1_Y_MODIFY = 0; } void SetupMacAddr(u8 *mac_addr) { // this depends on a little-endian machine *pEMAC_ADDRLO = *(u32 *)&mac_addr[0]; *pEMAC_ADDRHI = *(u16 *)&mac_addr[4]; } static void adjust_tx_list(void) { int i = 0; /* current's next can not be the head, otherwise the dma will not stop as we want */ if (current_tx_ptr->next->next == tx_list_head) { while (tx_list_head->status.status_word == 0) { udelay(100); i++; if (i == 10) { //printk("tx list error!\n"); i = 0; tx_list_head->desc_a.config.b_DMA_EN = 0; tx_list_head = tx_list_head->next; break; } } } if ((tx_list_head->status.status_word != 0)) { tx_list_head->status.status_word = 0; tx_list_head->desc_a.config.b_DMA_EN = 0; tx_list_head = tx_list_head->next; } } static int bf537mac_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct bf537mac_local *lp = netdev_priv(dev); unsigned int data; /* warning: printk in this function may cause error */ // Is skb->data always 16-bit aligned? Do we need to memcpy((char *)(tail->packet + 2),skb->data,len)? if ( (((unsigned int)(skb->data))%4) == 2 ) { //move skb->data to current_tx_ptr payload data = (unsigned int)(skb->data); data -= 2; *((unsigned short *)data) = (unsigned short)(skb->len); current_tx_ptr->desc_a.start_addr = (unsigned long)data; blackfin_dcache_invalidate_range(data, (data+(skb->len)) + 2); //this is important! } else { *((unsigned short *)(current_tx_ptr->packet)) = (unsigned short)(skb->len); memcpy((char *)(current_tx_ptr->packet + 2),skb->data,(skb->len)); current_tx_ptr->desc_a.start_addr = (unsigned long)current_tx_ptr->packet; /*why we need to invalidate uncached memory? */ blackfin_dcache_invalidate_range((unsigned int)current_tx_ptr->packet, (unsigned int)(current_tx_ptr->packet + skb->len) + 2); } current_tx_ptr->desc_a.config.b_DMA_EN = 1; //enable this packet's dma if (*pDMA2_IRQ_STATUS & 0x08) { //tx dma is running, just return goto out; } else { //tx dma is not running *pDMA2_NEXT_DESC_PTR = (&(current_tx_ptr->desc_a)); *pDMA2_CONFIG = *((unsigned short *)(&(current_tx_ptr->desc_a.config)));; // dma enabled, read from memory, size is 6 // Turn on the EMAC tx *pEMAC_OPMODE |= TE; } out: adjust_tx_list(); current_tx_ptr = current_tx_ptr->next; dev->trans_start = jiffies; lp->stats.tx_packets++; lp->stats.tx_bytes += (skb->len); dev_kfree_skb(skb); //printk("sending one...\n"); return 0; } static void bf537mac_rx(struct net_device *dev, unsigned char *pkt, int len) { struct sk_buff *skb; struct bf537mac_local *lp = netdev_priv(dev); skb = dev_alloc_skb(len + 2); if (!skb) { printk(KERN_NOTICE "bf537mac rx: low on mem - packet dropped\n"); lp->stats.rx_dropped++; goto out; } skb_reserve(skb, 2); /* if (len >= 300) { printk("going to copy the big packet\n"); for (i=0;i<len;i++){ printk("%.2x-",((unsigned char *)pkt)[i]); if (((i%8)==0) && (i!=0)) printk("\n"); } printk("\n"); } */ memcpy(skb_put(skb, len), pkt+2, len); dev->last_rx = jiffies; skb->dev = dev; skb->protocol = eth_type_trans(skb, dev); skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx(skb); lp->stats.rx_packets++; lp->stats.rx_bytes += len; out: return; } /* interrupt routine to handle rx and error signal */ static irqreturn_t bf537mac_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct net_device *dev = dev_id; unsigned short len; // printk("in mac_int\n"); get_one_packet: if (current_rx_ptr->status.status_word == 0) { // no more new packet received *pDMA1_IRQ_STATUS |= DMA_DONE|DMA_ERR; //printk("now return..\n"); return IRQ_HANDLED; } len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN); bf537mac_rx(dev, (char *)(current_rx_ptr->packet), len); current_rx_ptr->status.status_word = 0x00000000; current_rx_ptr = current_rx_ptr->next; goto get_one_packet; } #ifdef CONFIG_NET_POLL_CONTROLLER static void bf537mac_poll(struct net_device* dev) { disable_irq(IRQ_MAC_RX); bf537mac_interrupt(IRQ_MAC_RX, dev, NULL); enable_irq(IRQ_MAC_RX); } #endif /* CONFIG_NET_POLL_CONTROLLER */ static void bf537mac_reset(void) { unsigned int opmode; opmode = *pEMAC_OPMODE; opmode &= (~RE); opmode &= (~TE); /* Turn off the EMAC */ *pEMAC_OPMODE &= opmode; } /* * Enable Interrupts, Receive, and Transmit */ static int bf537mac_enable(struct net_device *dev) { u32 opmode; //u32 pkt_status; //printk("%s: %s\n", dev->name, __FUNCTION__); /* Set RX DMA */ *pDMA1_NEXT_DESC_PTR = &(rx_list_head->desc_a); *pDMA1_CONFIG = *((unsigned short *)(&(rx_list_head->desc_a.config))); /* Wait MII done */ PollMdcDone(); /* We enable only RX here */ /* ASTP : Enable Automatic Pad Stripping PR : Promiscuous Mode for test PSF : Receive frames with total length less than 64 bytes. FDMODE : Full Duplex Mode LB : Internal Loopback for test RE : Receiver Enable */ opmode = FDMODE|PSF; opmode |= RE; /* Turn on the EMAC rx */ *pEMAC_OPMODE = opmode; return 0; } /* Our watchdog timed out. Called by the networking layer */ static void bf537mac_timeout(struct net_device *dev) { //printk("%s: %s\n", dev->name, __FUNCTION__); bf537mac_reset(); /* reset tx queue */ tx_list_tail = tx_list_head->next; bf537mac_enable(dev); /* We can accept TX packets again */ dev->trans_start = jiffies; netif_wake_queue(dev); } /* * Get the current statistics. * This may be called with the card open or closed. */ static struct net_device_stats *bf537mac_query_statistics(struct net_device *dev) { struct bf537mac_local *lp = netdev_priv(dev); //printk("%s: %s\n", dev->name, __FUNCTION__); return &lp->stats; } /* * This routine will, depending on the values passed to it, * either make it accept multicast packets, go into * promiscuous mode (for TCPDUMP and cousins) or accept * a select set of multicast packets */ static void bf537mac_set_multicast_list(struct net_device *dev) { u32 sysctl; if (dev->flags & IFF_PROMISC) { printk(KERN_INFO "%s: set to promisc mode\n", dev->name); sysctl = *pEMAC_OPMODE; sysctl |= RAF; *pEMAC_OPMODE = sysctl; } else if (dev->flags & IFF_ALLMULTI || dev->mc_count > 16) { /* accept all multicast */ sysctl = *pEMAC_OPMODE; sysctl |= PAM; *pEMAC_OPMODE = sysctl; } else if (dev->mc_count) { /* set multicast */ } else { /* clear promisc or multicast mode */ sysctl = *pEMAC_OPMODE; sysctl &= ~(RAF | PAM); *pEMAC_OPMODE = sysctl; } } /* * this puts the device in an inactive state */ static void bf537mac_shutdown(struct net_device *dev) { /* Turn off the EMAC */ *pEMAC_OPMODE = 0x00000000; /* Turn off the EMAC RX DMA */ *pDMA1_CONFIG = 0x0000; *pDMA2_CONFIG = 0x0000; } /* * Open and Initialize the interface * * Set up everything, reset the card, etc.. */ static int bf537mac_open(struct net_device *dev) { //printk("%s: %s\n", dev->name, __FUNCTION__); /* * Check that the address is valid. If its not, refuse * to bring the device up. The user must specify an * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx */ if (!is_valid_ether_addr(dev->dev_addr)) { printk((KERN_DEBUG "bf537mac_open: no valid ethernet hw addr\n")); return -EINVAL; } /* initial rx and tx list */ desc_list_init(); bf537mac_setphy(dev); SetupSystemRegs(dev); bf537mac_reset(); bf537mac_enable(dev); printk("bf537_mac: hardware init finished\n"); netif_start_queue(dev); netif_carrier_on(dev); return 0; } /* * * this makes the board clean up everything that it can * and not talk to the outside world. Caused by * an 'ifconfig ethX down' */ static int bf537mac_close(struct net_device *dev) { //printk("%s: %s\n", dev->name, __FUNCTION__); netif_stop_queue(dev); netif_carrier_off(dev); /* clear everything */ bf537mac_shutdown(dev); /* free the rx/tx buffers */ desc_list_free(); return 0; } static int __init bf537mac_probe(struct net_device *dev) { struct bf537mac_local *lp = netdev_priv(dev); int retval; /* Grab the MAC address in the MAC */ *(u32 *)(&(dev->dev_addr[0])) = *pEMAC_ADDRLO; *(u16 *)(&(dev->dev_addr[4])) = (u16)*pEMAC_ADDRHI; /* probe mac */ /*todo: how to proble? which is revision_register */ *pEMAC_ADDRLO = 0x12345678; if (*pEMAC_ADDRLO != 0x12345678) { //printk("bf537_mac: can't detect bf537 mac!\n"); retval = -ENODEV; goto err_out; } /*Is it valid? (Did bootloader initialize it?)*/ if (!is_valid_ether_addr(dev->dev_addr)) { /* Grab the MAC from the board somehow - this is done in the arch/blackfin/boards/bf537/boardname.c */ get_bf537_ether_addr(dev->dev_addr); } /* If still not valid, get a random one */ if (!is_valid_ether_addr(dev->dev_addr)) { random_ether_addr(dev->dev_addr); } SetupMacAddr(dev->dev_addr); /* Fill in the fields of the device structure with ethernet values. */ ether_setup(dev); dev->open = bf537mac_open; dev->stop = bf537mac_close; dev->hard_start_xmit = bf537mac_hard_start_xmit; dev->tx_timeout = bf537mac_timeout; dev->get_stats = bf537mac_query_statistics; dev->set_multicast_list = bf537mac_set_multicast_list; // dev->ethtool_ops = &bf537mac_ethtool_ops; #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = bf537mac_poll; #endif /* fill in some of the fields */ lp->version = 1; lp->PhyAddr = 0x01; lp->CLKIN = 25; lp->FullDuplex = 0; lp->Negotiate = 1; lp->FlowControl = 0; // set the GPIO pins to Ethernet mode SetupPinMux(); /* now, enable interrupts */ /* register irq handler */ if (request_irq(IRQ_MAC_RX, bf537mac_interrupt, SA_INTERRUPT|SA_SHIRQ, "BFIN537_MAC_RX",dev)) { printk("Unable to attach BlackFin MAC RX interrupt\n"); return -EBUSY; } retval = register_netdev(dev); if (retval == 0) { /* now, print out the card info, in a short format.. */ printk(KERN_INFO "Blackfin 537 mac net device registered.\n"); } err_out: return retval; } static int bf537mac_drv_probe(struct device *dev) { struct net_device *ndev; int ret=0; ndev = alloc_etherdev(sizeof(struct bf537mac_local)); if (!ndev) { printk("%s: could not allocate device.\n", CARDNAME); ret = -ENOMEM; return ret; } ret = bf537mac_probe(ndev); if (ret != 0) { dev_set_drvdata(dev, NULL); free_netdev(ndev); printk("%s: not found (%d).\n", CARDNAME, ret); } SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, dev); dev_set_drvdata(dev, ndev); //printk("bf537_mac: probe finished\n"); return ret; } static int bf537mac_drv_remove(struct device *dev) { struct net_device *ndev = dev_get_drvdata(dev); dev_set_drvdata(dev, NULL); unregister_netdev(ndev); free_irq(IRQ_MAC_RX, ndev); free_netdev(ndev); return 0; } static int bf537mac_drv_suspend(struct device *dev, u32 state, u32 level) { return 0; } static int bf537mac_drv_resume(struct device *dev, u32 level) { return 0; } static struct device_driver bf537mac_driver = { .name = CARDNAME, .bus = &platform_bus_type, .probe = bf537mac_drv_probe, .remove = bf537mac_drv_remove, .suspend = bf537mac_drv_suspend, .resume = bf537mac_drv_resume, }; static int __init bf537mac_init(void) { return driver_register(&bf537mac_driver); } static void __exit bf537mac_cleanup(void) { driver_unregister(&bf537mac_driver); } module_init(bf537mac_init); module_exit(bf537mac_cleanup);
// ----------------------------------------------------------------------- // PHY REGISTER NAMES // // ----------------------------------------------------------------------- #define PHYREG_MODECTL 0x0000 #define PHYREG_MODESTAT 0x0001 #define PHYREG_PHYID1 0x0002 #define PHYREG_PHYID2 0x0003 #define PHYREG_ANAR 0x0004 #define PHYREG_ANLPAR 0x0005 #define PHYREG_ANER 0x0006 #define PHYREG_NSR 0x0010 #define PHYREG_LBREMR 0x0011 #define PHYREG_REC 0x0012 #define PHYREG_10CFG 0x0013 #define PHYREG_PHY1_1 0x0014 #define PHYREG_PHY1_2 0x0015 #define PHYREG_PHY2 0x0016 #define PHYREG_TW_1 0x0017 #define PHYREG_TW_2 0x0018 #define PHYREG_TEST 0x0019 #define PHY_RESET 0x8000 #define PHY_ANEG_EN 0x1000 #define PHY_DUPLEX 0x0100 #define PHY_SPD_SET 0x2000 typedef struct _DMA_CONFIG { unsigned short b_DMA_EN:1; //Bit 0 : DMA Enable unsigned short b_WNR:1; //Bit 1 : DMA Direction unsigned short b_WDSIZE:2; //Bit 2 & 3 : DMA Tranfer Word size unsigned short b_DMA2D:1; //Bit 4 : DMA Mode 2D or 1D unsigned short b_RESTART:1; //Bit 5 : Retain the FIFO unsigned short b_DI_SEL:1; //Bit 6 : Data Interrupt Timing Select unsigned short b_DI_EN:1; //Bit 7 : Data Interrupt Enable unsigned short b_NDSIZE:4; //Bit 8 to 11 : Flex descriptor Size unsigned short b_FLOW:3; //Bit 12 to 14 : FLOW } DMA_CONFIG_REG; struct dma_descriptor { struct dma_descriptor *next_dma_desc; unsigned long start_addr; DMA_CONFIG_REG config; unsigned short x_count; }; /* struct status_area { unsigned short ip_hdr_chksum; // the IP header checksum unsigned short ip_payload_chksum; // the IP header and payload checksum unsigned long status_word; // the frame status word }; */ struct status_area { unsigned long status_word; // the frame status word }; /* use two descriptors for a packet */ struct net_dma_desc { struct net_dma_desc *next; struct dma_descriptor desc_a; struct dma_descriptor desc_b; volatile unsigned char packet[1560]; volatile struct status_area status; }; struct bf537mac_local { /* * these are things that the kernel wants me to keep, so users * can find out semi-useless statistics of how well the card is * performing */ struct net_device_stats stats; int version; int FlowEnabled; // record if data flow is active int EtherIntIVG; // IVG for the ethernet interrupt int RXIVG; // IVG for the RX completion int TXIVG; // IVG for the TX completion int PhyAddr; // PHY address int OpMode; // set these bits n the OPMODE regs int Port10; // set port speed to 10 Mbit/s int GenChksums; // IP checksums to be calculated int NoRcveLnth; // dont insert recv length at start of buffer int StripPads; // remove trailing pad bytes int FullDuplex; // set full duplex mode int Negotiate; // enable auto negotiation int Loopback; // loopback at the PHY int Cache; // Buffers may be cached int FlowControl; // flow control active int CLKIN; // clock in value in MHZ unsigned short IntMask; // interrupt mask unsigned char Mac[6]; // MAC address of the board };