📄 em86xx_eth.c
字号:
#endif /*BOOTLOADER*/ } desc_ptr->desc0 = DescOwnByDma; } private->last_rxidx = count; /* This is the last desc we read */ /* make sure rx is not suspended */ em86xx_write_reg(EM86XX_RPDR_REG, 0x0); return 0;}/* Resetting rx descriptor: error recovery for "rx buf unavailable" */static void em86xx_eth_reset_rx_buf(struct net_device *dev){ register int i; volatile struct em86xx_desc *desc_ptr = NULL; /* Reset rx desc */ desc_ptr = (struct em86xx_desc *)(rxdsc); for (i = 0; i < num_rxdesc; i++, desc_ptr++) desc_ptr->desc0 = DescOwnByDma; em86xx_write_reg(EM86XX_RPDR_REG, 0x0); em86xx_set_reg(EM86XX_CR_REG, DmaRxStart); }#ifndef BOOTLOADER/* Get the stats information */static struct net_device_stats *em86xx_eth_stats(struct net_device *dev){ if (dev != NULL) return(&(((EM86XX_ETH_PRIV *)dev->priv)->stats)); else return(NULL);}#endif/* Ethernet interrupt handler */#ifdef BOOTLOADERstatic void em86xx_eth_intr_handler(int irq, void *dev_id)#elsestatic void em86xx_eth_intr_handler(int irq, void *dev_id, struct pt_regs *regs)#endif{ unsigned long status; struct net_device *dev = (struct net_device *)dev_id;#ifdef BOOTLOADER if( memcmp(dev->name,DRIVER, sizeof(DRIVER)) != 0) return;#else if (dev_id != (void *)&em86xx_eth_dev) return;#endif /* Check status */ status = em86xx_read_reg(EM86XX_SR_REG); //clear all interrupt requests em86xx_write_reg(EM86XX_SR_REG, status) ; if (status & DmaIntNormal) { if (status & DmaIntRxCompleted) em86xx_eth_rx((struct net_device *)dev_id); else ERR_PRINT("%s: unhandled NIS 0x%08lx\n", dev->name, status); } if (status & DmaIntAbnormal) { if (status & DmaIntRxNoBuffer) { ERR_PRINT("%s: receive buffer unavailable 0x%08lx\n", dev->name, status); em86xx_eth_reset_rx_buf((struct net_device *)dev_id); } else if (status & DmaIntRxStopped) { ERR_PRINT("%s: receive process stopped\n", dev->name); em86xx_set_reg(EM86XX_CR_REG, DmaRxStart); } else if (status & DmaIntTxStopped ) { ERR_PRINT("%s: transmit process stopped\n", dev->name); em86xx_write_reg(EM86XX_CR_REG, DmaRxStart); } else if (status & DmaIntTxUnderflow) { ERR_PRINT("%s: transmit underflow\n", dev->name); } else if (status & DmaIntEarlyTx ) { ERR_PRINT("%s: Early transmit interrupt\n", dev->name); } else if (status & DmaIntBusError ) { ERR_PRINT("%s: Fatal bus error\n", dev->name); } else { ERR_PRINT("%s: unhandled AIS 0x%08lx\n", dev->name, status); } } if (((status & DmaIntAbnormal) == 0) && ((status & DmaIntNormal) == 0)) { ERR_PRINT("%s: Unknown SR 0x%08lx\n", dev->name, status); } return;}#ifndef BOOTLOADER/* Handling ioctl call */static int em86xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){ /* TODO: Not implemented yet */ struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; switch(cmd) { case SIOCGMIIREG: /* Read MII PHY register. */ data->val_out = em86xx_mii_read(data->phy_id & 0x1f, data->reg_num & 0x1f); return 0; case SIOCSMIIREG: /* Write MII PHY register. */ em86xx_mii_write(data->phy_id, data->reg_num, data->val_in); return 0; default: return -EOPNOTSUPP; } return(-EIO);}#endif/* Kernel level ethernet initialization */static int em86xx_eth_init(struct net_device *dev){ DBG_PRINT("em86xx_eth_init\n"); if (dev == NULL) goto failed; rxdsc = (volatile struct em86xx_desc *)NON_CACHED((u32)eth_rxdsc); txdsc = (volatile struct em86xx_desc *)NON_CACHED((u32)eth_txdsc); rxbuf = (volatile unsigned char *)NON_CACHED((u32)eth_rxbuf); txbuf = (volatile unsigned char *)NON_CACHED((u32)eth_txbuf); /* Ethernet device initialization */#ifdef BOOTLOADER /* Fill in the fields of the device structure with ethernet-generic values.*/// dev->type = ARPHRD_ETHER; dev->mtu = ETH_DATA_LEN; /* eth_mtu */ dev->addr_len = ETH_ALEN; memset(dev->broadcast, 0xff, ETH_ALEN); dev->hard_header_len = ETH_HLEN;#else ether_setup(dev);#endif if (em86xx_set_mac(dev)) goto failed; /* Hook up with handlers */#ifdef BOOTLOADER dev->send_packet = em86xx_eth_tx; dev->open = em86xx_eth_open; dev->close = em86xx_eth_close;#else dev->get_stats = em86xx_eth_stats; dev->hard_start_xmit = em86xx_eth_tx; dev->open = em86xx_eth_open; dev->stop = em86xx_eth_close; dev->set_multicast_list = em86xx_eth_set_multicast_list; dev->do_ioctl = em86xx_eth_ioctl; dev->set_mac_address = em86xx_eth_set_macaddr; dev->tx_queue_len = num_txdesc; dev->flags &= ~IFF_MULTICAST; dev->flags |= IFF_DEBUG;#endif return 0;failed: return(-EIO);}static int em86xx_eth_reset_desc(struct net_device *dev, int *reset){ EM86XX_ETH_PRIV *private; if (dev == NULL) return(-EIO); else private = (EM86XX_ETH_PRIV *)dev->priv; if (*reset) memset(dev->priv, 0, sizeof(EM86XX_ETH_PRIV)); *reset = 0; /* Clear all tx/rx buffer memory */ memset((void *)(rxbuf), 0, num_rxdesc * R_BUF_SIZE); memset((void *)(txbuf), 0, num_txdesc * T_BUF_SIZE); /* Initialize the indices */ private->last_rxidx = 0; private->next_txidx = 0; /* Intialize the descriptors */ em86xx_eth_setup_desc(); return 0;}/* Driver installation: this is where the thing starts */#ifdef BOOTLOADERint em86xx_eth_probe(struct net_device *dev)#elsestatic int __init em86xx_eth_startup(void)#endif{#ifndef BOOTLOADER struct net_device *dev = &em86xx_eth_dev;#endif int err = 0, i; EM86XX_ETH_PRIV *private= NULL;#ifndef STATIC_BUF_ALLOC unsigned long max_num_rxdsc, max_num_txdsc; unsigned long rxbuf_size, txbuf_size;#endif if (dev_count != 0) { err = -EIO; goto failed; } #ifndef STATIC_BUF_ALLOC /* Validating module parameters */ max_num_rxdsc = max_num_txdsc = PAGE_SIZE / (2 * sizeof(struct em86xx_desc)); if (((num_rxdesc < MIN_NUM_RDESC) || (num_rxdesc > max_num_rxdsc)) || ((num_txdesc < MIN_NUM_TDESC) || (num_txdesc > max_num_txdsc))) { err = -EIO; goto failed; } else if ((desc_page = __get_free_page(GFP_KERNEL | GFP_DMA)) == 0) { err = -ENOMEM; goto failed; } /* Split a page for both rx/tx descriptor */ eth_rxdsc = (struct em86xx_desc *)desc_page; eth_txdsc = (struct em86xx_desc *)(desc_page + ((1 << PAGE_SHIFT) / 2)); /* Calculate the size needed for tx/rx -- aligned by pages */ rxbuf_size = num_rxdesc * R_BUF_SIZE; txbuf_size = num_txdesc * T_BUF_SIZE; if ((rxbuf_size & (PAGE_SIZE - 1)) != 0) rxbuf_size = (rxbuf_size & PAGE_MASK) + PAGE_SIZE; if ((txbuf_size & (PAGE_SIZE - 1)) != 0) txbuf_size = (txbuf_size & PAGE_MASK) + PAGE_SIZE; DBG_PRINT("txbuf_size = 0x%08lx, rxbuf_size = 0x%08lx\n", txbuf_size, rxbuf_size); /* Calculate the order needed for tx/rx */ for (rxbuf_order = 0; rxbuf_order < MAX_ORDER; rxbuf_order++) { if ((PAGE_SIZE * (1 << rxbuf_order)) >= rxbuf_size) break; } for (txbuf_order = 0; txbuf_order < MAX_ORDER; txbuf_order++) { if ((PAGE_SIZE * (1 << txbuf_order)) >= txbuf_size) break; } if ((rxbuf_order >= MAX_ORDER) || (txbuf_order >= MAX_ORDER)) { err = -ENOMEM; goto failed; } DBG_PRINT("txbuf_order = 0x%08lx, rxbuf_order = 0x%08lx\n", txbuf_order, rxbuf_order); if ((rxbuf_pages = __get_free_pages(GFP_KERNEL | GFP_DMA, rxbuf_order)) == 0) { err = -ENOMEM; goto failed; } else if ((txbuf_pages = __get_free_pages(GFP_KERNEL | GFP_DMA, txbuf_order)) == 0) { err = -ENOMEM; goto failed; } eth_rxbuf = (unsigned char *)rxbuf_pages; eth_txbuf = (unsigned char *)txbuf_pages;#endif#ifndef BOOTLOADER SET_MODULE_OWNER(&em86xx_eth_dev);#endif MSG_PRINT("Ethernet driver for EM86XX (v1.0)"); dev->priv = NULL; /* Set up default mac address and others */ max_link_loop = DEF_LINK_LOOP; ld_count = 1; reset_flag = 1; /* Get a device name: normally it'll be eth0 */#ifdef BOOTLOADER memcpy( dev->name, DRIVER, sizeof(DRIVER)); /* Register ISR */ dev->irq = IRQ_ETHERNET; em86xx_request_irq(IRQ_ETHERNET, em86xx_eth_intr_handler, dev);#else if ((err = dev_alloc_name(&em86xx_eth_dev, "eth%d")) < 0) goto failed; /* Register ISR */ if ((err = request_irq(IRQ_ETHERNET, em86xx_eth_intr_handler, 0, "ethernet", &em86xx_eth_dev)) != 0) { err = -EIO; goto failed; } else#endif MSG_PRINT(" on %s (IRQ: %d)", dev->name, IRQ_ETHERNET); if (em86xx_get_macaddr(dev->dev_addr)) { err = -EIO; goto failed; } MSG_PRINT("\n(MAC %02x", dev->dev_addr[0]); for (i = 1; i < 6; i++) MSG_PRINT(":%02x", dev->dev_addr[i]); MSG_PRINT(", tx_desc/rx_desc = %ld/%ld)\n", num_txdesc, num_rxdesc); /* Allocate memory for private data */#ifdef BOOTLOADER dev->priv = private = (EM86XX_ETH_PRIV *)malloc(sizeof(EM86XX_ETH_PRIV));//, GFP_KERNEL);#else dev->priv = private = (EM86XX_ETH_PRIV *)kmalloc(sizeof(EM86XX_ETH_PRIV), GFP_KERNEL);#endif if (dev->priv == NULL) { err = -ENOMEM; goto failed; } /* Point to driver initialization routine and register the device with kernel */ dev->init = em86xx_eth_init;#ifdef BOOTLOADER em86xx_eth_init(dev); dev->state = NETDEV_DOWN;#else if (register_netdev(dev) != 0) { err = -EIO; goto failed; }#endif MSG_PRINT("%s: driver installation completed.\n", dev->name); dev_count++; return 0;failed: if (dev->priv != NULL) {#ifdef BOOTLOADER free(dev->priv);#else kfree(dev->priv);#endif dev->priv = NULL; }#ifndef STATIC_BUF_ALLOC if (desc_page != 0) free_page(desc_page); if (rxbuf_pages != 0) free_pages(rxbuf_pages, rxbuf_order); if (txbuf_pages != 0) free_pages(txbuf_pages, txbuf_order);#endif MSG_PRINT("%s: driver installation failed.\n", dev->name); return(err);}#ifndef BOOTLOADER/* Uninstallation of drive */static void __exit em86xx_eth_shutdown(void){ if (dev_count != 0) { /* Turn off IRQ and stop receive/transmit */ em86xx_write_reg(EM86XX_CR_REG, 0); em86xx_write_reg(EM86XX_IER_REG, 0); /* Unregister the device and ISR */ free_irq(IRQ_ETHERNET, &em86xx_eth_dev); unregister_netdev(&em86xx_eth_dev); /* Set desc base address registers to 0 */ em86xx_write_reg(EM86XX_RLBAR_REG, 0); em86xx_write_reg(EM86XX_TLBAR_REG, 0);#ifndef STATIC_BUF_ALLOC if (desc_page != 0) free_page(desc_page); if (rxbuf_pages != 0) free_pages(rxbuf_pages, rxbuf_order); if (txbuf_pages != 0) free_pages(txbuf_pages, txbuf_order);#endif /* Free up memory */ if (em86xx_eth_dev.priv != NULL) { kfree(em86xx_eth_dev.priv); em86xx_eth_dev.priv = NULL; } } }/* Register startup/shutdown routines */module_init(em86xx_eth_startup);module_exit(em86xx_eth_shutdown);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -