📄 de4x5.c
字号:
static void enable_ast(struct net_device *dev, u32 time_out);static long de4x5_switch_mac_port(struct net_device *dev);static int gep_rd(struct net_device *dev);static void gep_wr(s32 data, struct net_device *dev);static void timeout(struct net_device *dev, void (*fn)(u_long data), u_long data, u_long msec);static void yawn(struct net_device *dev, int state);static void de4x5_parse_params(struct net_device *dev);static void de4x5_dbg_open(struct net_device *dev);static void de4x5_dbg_mii(struct net_device *dev, int k);static void de4x5_dbg_media(struct net_device *dev);static void de4x5_dbg_srom(struct de4x5_srom *p);static void de4x5_dbg_rx(struct sk_buff *skb, int len);static int de4x5_strncmp(char *a, char *b, int n);static int dc21041_infoleaf(struct net_device *dev);static int dc21140_infoleaf(struct net_device *dev);static int dc21142_infoleaf(struct net_device *dev);static int dc21143_infoleaf(struct net_device *dev);static int type0_infoblock(struct net_device *dev, u_char count, u_char *p);static int type1_infoblock(struct net_device *dev, u_char count, u_char *p);static int type2_infoblock(struct net_device *dev, u_char count, u_char *p);static int type3_infoblock(struct net_device *dev, u_char count, u_char *p);static int type4_infoblock(struct net_device *dev, u_char count, u_char *p);static int type5_infoblock(struct net_device *dev, u_char count, u_char *p);static int compact_infoblock(struct net_device *dev, u_char count, u_char *p);/*** Note now that module autoprobing is allowed under EISA and PCI. The** IRQ lines will not be auto-detected; instead I'll rely on the BIOSes** to "do the right thing".*/static int io=0x0;/* EDIT THIS LINE FOR YOUR CONFIGURATION IF NEEDED */module_param(io, int, 0);module_param(de4x5_debug, int, 0);module_param(dec_only, int, 0);module_param(args, charp, 0);MODULE_PARM_DESC(io, "de4x5 I/O base address");MODULE_PARM_DESC(de4x5_debug, "de4x5 debug mask");MODULE_PARM_DESC(dec_only, "de4x5 probe only for Digital boards (0-1)");MODULE_PARM_DESC(args, "de4x5 full duplex and media type settings; see de4x5.c for details");MODULE_LICENSE("GPL");/*** List the SROM infoleaf functions and chipsets*/struct InfoLeaf { int chipset; int (*fn)(struct net_device *);};static struct InfoLeaf infoleaf_array[] = { {DC21041, dc21041_infoleaf}, {DC21140, dc21140_infoleaf}, {DC21142, dc21142_infoleaf}, {DC21143, dc21143_infoleaf}};#define INFOLEAF_SIZE (sizeof(infoleaf_array)/(sizeof(int)+sizeof(int *)))/*** List the SROM info block functions*/static int (*dc_infoblock[])(struct net_device *dev, u_char, u_char *) = { type0_infoblock, type1_infoblock, type2_infoblock, type3_infoblock, type4_infoblock, type5_infoblock, compact_infoblock};#define COMPACT (sizeof(dc_infoblock)/sizeof(int *) - 1)/*** Miscellaneous defines...*/#define RESET_DE4X5 {\ int i;\ i=inl(DE4X5_BMR);\ mdelay(1);\ outl(i | BMR_SWR, DE4X5_BMR);\ mdelay(1);\ outl(i, DE4X5_BMR);\ mdelay(1);\ for (i=0;i<5;i++) {inl(DE4X5_BMR); mdelay(1);}\ mdelay(1);\}#define PHY_HARD_RESET {\ outl(GEP_HRST, DE4X5_GEP); /* Hard RESET the PHY dev. */\ mdelay(1); /* Assert for 1ms */\ outl(0x00, DE4X5_GEP);\ mdelay(2); /* Wait for 2ms */\}static int __devinit de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev){ char name[DE4X5_NAME_LENGTH + 1]; struct de4x5_private *lp = netdev_priv(dev); struct pci_dev *pdev = NULL; int i, status=0; gendev->driver_data = dev; /* Ensure we're not sleeping */ if (lp->bus == EISA) { outb(WAKEUP, PCI_CFPM); } else { pdev = to_pci_dev (gendev); pci_write_config_byte(pdev, PCI_CFDA_PSM, WAKEUP); } mdelay(10); RESET_DE4X5; if ((inl(DE4X5_STS) & (STS_TS | STS_RS)) != 0) { return -ENXIO; /* Hardware could not reset */ } /* ** Now find out what kind of DC21040/DC21041/DC21140 board we have. */ lp->useSROM = FALSE; if (lp->bus == PCI) { PCI_signature(name, lp); } else { EISA_signature(name, gendev); } if (*name == '\0') { /* Not found a board signature */ return -ENXIO; } dev->base_addr = iobase; printk ("%s: %s at 0x%04lx", gendev->bus_id, name, iobase); printk(", h/w address "); status = get_hw_addr(dev); for (i = 0; i < ETH_ALEN - 1; i++) { /* get the ethernet addr. */ printk("%2.2x:", dev->dev_addr[i]); } printk("%2.2x,\n", dev->dev_addr[i]); if (status != 0) { printk(" which has an Ethernet PROM CRC error.\n"); return -ENXIO; } else { lp->cache.gepc = GEP_INIT; lp->asBit = GEP_SLNK; lp->asPolarity = GEP_SLNK; lp->asBitValid = TRUE; lp->timeout = -1; lp->gendev = gendev; spin_lock_init(&lp->lock); init_timer(&lp->timer); de4x5_parse_params(dev); /* ** Choose correct autosensing in case someone messed up */ lp->autosense = lp->params.autosense; if (lp->chipset != DC21140) { if ((lp->chipset==DC21040) && (lp->params.autosense&TP_NW)) { lp->params.autosense = TP; } if ((lp->chipset==DC21041) && (lp->params.autosense&BNC_AUI)) { lp->params.autosense = BNC; } } lp->fdx = lp->params.fdx; sprintf(lp->adapter_name,"%s (%s)", name, gendev->bus_id); lp->dma_size = (NUM_RX_DESC + NUM_TX_DESC) * sizeof(struct de4x5_desc);#if defined(__alpha__) || defined(__powerpc__) || defined(__sparc_v9__) || defined(DE4X5_DO_MEMCPY) lp->dma_size += RX_BUFF_SZ * NUM_RX_DESC + DE4X5_ALIGN;#endif lp->rx_ring = dma_alloc_coherent(gendev, lp->dma_size, &lp->dma_rings, GFP_ATOMIC); if (lp->rx_ring == NULL) { return -ENOMEM; } lp->tx_ring = lp->rx_ring + NUM_RX_DESC; /* ** Set up the RX descriptor ring (Intels) ** Allocate contiguous receive buffers, long word aligned (Alphas) */#if !defined(__alpha__) && !defined(__powerpc__) && !defined(__sparc_v9__) && !defined(DE4X5_DO_MEMCPY) for (i=0; i<NUM_RX_DESC; i++) { lp->rx_ring[i].status = 0; lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); lp->rx_ring[i].buf = 0; lp->rx_ring[i].next = 0; lp->rx_skb[i] = (struct sk_buff *) 1; /* Dummy entry */ }#else { dma_addr_t dma_rx_bufs; dma_rx_bufs = lp->dma_rings + (NUM_RX_DESC + NUM_TX_DESC) * sizeof(struct de4x5_desc); dma_rx_bufs = (dma_rx_bufs + DE4X5_ALIGN) & ~DE4X5_ALIGN; lp->rx_bufs = (char *)(((long)(lp->rx_ring + NUM_RX_DESC + NUM_TX_DESC) + DE4X5_ALIGN) & ~DE4X5_ALIGN); for (i=0; i<NUM_RX_DESC; i++) { lp->rx_ring[i].status = 0; lp->rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); lp->rx_ring[i].buf = cpu_to_le32(dma_rx_bufs+i*RX_BUFF_SZ); lp->rx_ring[i].next = 0; lp->rx_skb[i] = (struct sk_buff *) 1; /* Dummy entry */ } }#endif barrier(); lp->rxRingSize = NUM_RX_DESC; lp->txRingSize = NUM_TX_DESC; /* Write the end of list marker to the descriptor lists */ lp->rx_ring[lp->rxRingSize - 1].des1 |= cpu_to_le32(RD_RER); lp->tx_ring[lp->txRingSize - 1].des1 |= cpu_to_le32(TD_TER); /* Tell the adapter where the TX/RX rings are located. */ outl(lp->dma_rings, DE4X5_RRBA); outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc), DE4X5_TRBA); /* Initialise the IRQ mask and Enable/Disable */ lp->irq_mask = IMR_RIM | IMR_TIM | IMR_TUM | IMR_UNM; lp->irq_en = IMR_NIM | IMR_AIM; /* Create a loopback packet frame for later media probing */ create_packet(dev, lp->frame, sizeof(lp->frame)); /* Check if the RX overflow bug needs testing for */ i = lp->cfrv & 0x000000fe; if ((lp->chipset == DC21140) && (i == 0x20)) { lp->rx_ovf = 1; } /* Initialise the SROM pointers if possible */ if (lp->useSROM) { lp->state = INITIALISED; if (srom_infoleaf_info(dev)) { dma_free_coherent (gendev, lp->dma_size, lp->rx_ring, lp->dma_rings); return -ENXIO; } srom_init(dev); } lp->state = CLOSED; /* ** Check for an MII interface */ if ((lp->chipset != DC21040) && (lp->chipset != DC21041)) { mii_get_phy(dev); } #ifndef __sparc_v9__ printk(" and requires IRQ%d (provided by %s).\n", dev->irq,#else printk(" and requires IRQ%x (provided by %s).\n", dev->irq,#endif ((lp->bus == PCI) ? "PCI BIOS" : "EISA CNFG")); } if (de4x5_debug & DEBUG_VERSION) { printk(version); } /* The DE4X5-specific entries in the device structure. */ SET_MODULE_OWNER(dev); SET_NETDEV_DEV(dev, gendev); dev->open = &de4x5_open; dev->hard_start_xmit = &de4x5_queue_pkt; dev->stop = &de4x5_close; dev->get_stats = &de4x5_get_stats; dev->set_multicast_list = &set_multicast_list; dev->do_ioctl = &de4x5_ioctl; dev->mem_start = 0; /* Fill in the generic fields of the device structure. */ if ((status = register_netdev (dev))) { dma_free_coherent (gendev, lp->dma_size, lp->rx_ring, lp->dma_rings); return status; } /* Let the adapter sleep to save power */ yawn(dev, SLEEP); return status;}static intde4x5_open(struct net_device *dev){ struct de4x5_private *lp = netdev_priv(dev); u_long iobase = dev->base_addr; int i, status = 0; s32 omr; /* Allocate the RX buffers */ for (i=0; i<lp->rxRingSize; i++) { if (de4x5_alloc_rx_buff(dev, i, 0) == NULL) { de4x5_free_rx_buffs(dev); return -EAGAIN; } } /* ** Wake up the adapter */ yawn(dev, WAKEUP); /* ** Re-initialize the DE4X5...
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -