📄 3c575_cb.c
字号:
Media_LnkBeat = 0x0800,};enum Window7 { /* Window 7: Bus Master control. */ Wn7_MasterAddr = 0, Wn7_MasterLen = 6, Wn7_MasterStatus = 12,};/* Boomerang bus master control registers. */enum MasterCtrl { PktStatus = 0x20, DownListPtr = 0x24, FragAddr = 0x28, FragLen = 0x2c, DownBurstThresh=0x2a, DownPollRate = 0x2d, TxFreeThreshold = 0x2f, UpPktStatus = 0x30, UpListPtr = 0x38,};/* The Rx and Tx descriptor lists. Caution Alpha hackers: these types are 32 bits! Note also the 8 byte alignment contraint on tx_ring[] and rx_ring[]. */#define LAST_FRAG 0x80000000 /* Last Addr/Len pair in descriptor. */struct boom_rx_desc { u32 next; /* Last entry points to 0. */ s32 status; u32 addr; /* Up to 63 addr/len pairs possible. */ s32 length; /* Set LAST_FRAG to indicate last pair. */};/* Values for the Rx status entry. */enum rx_desc_status { RxDComplete=0x00008000, RxDError=0x4000, /* See boomerang_rx() for actual error bits */ IPChksumErr=1<<25, TCPChksumErr=1<<26, UDPChksumErr=1<<27, IPChksumValid=1<<29, TCPChksumValid=1<<30, UDPChksumValid=1<<31,};struct boom_tx_desc { u32 next; /* Last entry points to 0. */ s32 status; /* bits 0:12 length, others see below. */ u32 addr; s32 length;};/* Values for the Tx status entry. */enum tx_desc_status { CRCDisable=0x2000, TxDComplete=0x8000, AddIPChksum=0x02000000, AddTCPChksum=0x04000000, AddUDPChksum=0x08000000, TxIntrUploaded=0x80000000, /* IRQ when in FIFO, but maybe not sent. */};/* Chip features we care about in vp->capabilities, read from the EEPROM. */enum ChipCaps { CapBusMaster=0x20, CapPwrMgmt=0x2000 };#define PRIV_ALIGN 15 /* Required alignment mask */struct vortex_private { /* The Rx and Tx rings should be quad-word-aligned. */ struct boom_rx_desc rx_ring[RX_RING_SIZE]; struct boom_tx_desc tx_ring[TX_RING_SIZE]; /* The addresses of transmit- and receive-in-place skbuffs. */ struct sk_buff* rx_skbuff[RX_RING_SIZE]; struct sk_buff* tx_skbuff[TX_RING_SIZE]; struct net_device *next_module; void *priv_addr; /* Keep the Rx and Tx variables grouped on their own cache lines. */ struct boom_rx_desc *rx_head_desc; unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned int rx_buf_sz; /* Based on MTU+slack. */ struct boom_tx_desc *tx_desc_tail; unsigned int cur_tx, dirty_tx; struct sk_buff *tx_skb; /* Packet being eaten by bus master ctrl. */ long last_reset; struct net_device_stats stats; char *cb_fn_base; /* CardBus function status addr space. */ int chip_id, drv_flags; u8 pci_bus, pci_devfn; /* PCI configuration space information. */ /* The remainder are related to chip state, mostly media selection. */ struct timer_list timer; /* Media selection timer. */ int options; /* User-settable misc. driver options. */ unsigned int media_override:4, /* Passed-in media type. */ default_media:4, /* Read from the EEPROM/Wn3_Config. */ full_duplex:1, medialock:1, autoselect:1, bus_master:1, /* Vortex can only do a fragment bus-m. */ full_bus_master_tx:1, full_bus_master_rx:2, /* Boomerang */ hw_csums:1, /* Has hardware checksums. */ tx_full:1, restart_tx:1, open:1, reap:1, polling:1; u16 status_enable; u16 intr_enable; u16 available_media; /* From Wn3_Options. */ u16 capabilities, info1, info2; /* Various, from EEPROM. */ u16 advertising; /* NWay media advertisement */ unsigned char phys[2]; /* MII device addresses. */ u16 deferred_irqs; spinlock_t lock;};/* The action to take with a media selection timer tick. Note that we deviate from the 3Com order by checking 10base2 before AUI. */enum xcvr_types { XCVR_10baseT=0, XCVR_AUI, XCVR_10baseTOnly, XCVR_10base2, XCVR_100baseTx, XCVR_100baseFx, XCVR_MII=6, XCVR_NWAY=8, XCVR_ExtMII=9, XCVR_Default=10,};static struct media_table { char *name; unsigned int media_bits:16, /* Bits to set in Wn4_Media register. */ mask:8, /* The transceiver-present bit in Wn3_Config.*/ next:8; /* The media type to try next. */ int wait; /* Time before we check media status. */} media_tbl[] = { { "10baseT", Media_10TP,0x08, XCVR_10base2, (14*HZ)/10}, { "10Mbs AUI", Media_SQE, 0x20, XCVR_Default, (1*HZ)/10}, { "undefined", 0, 0x80, XCVR_10baseT, 10000}, { "10base2", 0, 0x10, XCVR_AUI, (1*HZ)/10}, { "100baseTX", Media_Lnk, 0x02, XCVR_100baseFx, (14*HZ)/10}, { "100baseFX", Media_Lnk, 0x04, XCVR_MII, (14*HZ)/10}, { "MII", 0, 0x41, XCVR_10baseT, 3*HZ }, { "undefined", 0, 0x01, XCVR_10baseT, 10000}, { "Autonegotiate", 0, 0x41, XCVR_10baseT, 3*HZ}, { "MII-External", 0, 0x41, XCVR_10baseT, 3*HZ }, { "Default", 0, 0xFF, XCVR_10baseT, 10000},};static void vortex_up(struct net_device *dev);static void vortex_down(struct net_device *dev);static int vortex_open(struct net_device *dev);static void set_media_type(struct net_device *dev);static void activate_xcvr(struct net_device *dev);static void start_operation(struct net_device *dev);static void mdio_sync(long ioaddr, int bits);static int mdio_read(long ioaddr, int phy_id, int location);static void mdio_write(long ioaddr, int phy_id, int location, int value);static void vortex_timer(unsigned long arg);static void vortex_tx_timeout(struct net_device *dev);static int vortex_start_xmit(struct sk_buff *skb, struct net_device *dev);static int boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev);static int vortex_rx(struct net_device *dev);static int boomerang_rx(struct net_device *dev);static void vortex_interrupt(int irq, void *dev_id, struct pt_regs *regs);static int vortex_close(struct net_device *dev);static void update_stats(long ioaddr, struct net_device *dev);static struct net_device_stats *vortex_get_stats(struct net_device *dev);static void set_rx_mode(struct net_device *dev);static int vortex_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static void acpi_wake(int pci_bus, int pci_devfn);static void acpi_set_WOL(struct net_device *dev);/* A list of all installed Vortex devices, for removing the driver module. */static struct net_device *root_vortex_dev = NULL;#include <pcmcia/driver_ops.h>static void vortex_reap(void){ struct net_device **devp, **next; for (devp = &root_vortex_dev; *devp; devp = next) { struct vortex_private *vp = (*devp)->priv; next = &vp->next_module; if (vp->open || !vp->reap) continue; unregister_netdev(*devp); if (vp->cb_fn_base) iounmap(vp->cb_fn_base); kfree(*devp); *devp = *next; next = devp; kfree(vp->priv_addr); }}static dev_node_t *vortex_attach(dev_locator_t *loc){ u16 dev_id, vendor_id; u32 io; u8 bus, devfn, irq; struct net_device *dev; int chip_idx; vortex_reap(); if (loc->bus != LOC_PCI) return NULL; bus = loc->b.pci.bus; devfn = loc->b.pci.devfn; pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io); pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq); pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor_id); pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id); printk(KERN_INFO "vortex_attach(device %02x:%02x.%d)\n", bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); io &= ~3; if (io == 0 || irq == 0) { printk(KERN_ERR "The 3Com CardBus Ethernet interface was not " "assigned an %s.\n" KERN_ERR " It will not be activated.\n", io == 0 ? "I/O address" : "IRQ"); return NULL; } for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) if (vendor_id == pci_tbl[chip_idx].vendor_id && (dev_id & pci_tbl[chip_idx].device_id_mask) == pci_tbl[chip_idx].device_id) break; if (pci_tbl[chip_idx].vendor_id == 0) { /* Compiled out! */ printk(KERN_INFO "Unable to match chip type %4.4x %4.4x in " "vortex_attach().\n", vendor_id, dev_id); return NULL; } dev = vortex_probe1(bus, devfn, NULL, io, irq, chip_idx, MAX_UNITS+1); if (dev) { dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL); strcpy(node->dev_name, dev->name); node->major = node->minor = 0; node->next = NULL; MOD_INC_USE_COUNT; return node; } return NULL;}static void vortex_detach(dev_node_t *node){ struct net_device *dev, *next; printk(KERN_DEBUG "vortex_detach(%s)\n", node->dev_name); for (dev = root_vortex_dev; dev; dev = next) { next = ((struct vortex_private *)dev->priv)->next_module; if (strcmp(dev->name, node->dev_name) == 0) break; } if (dev && dev->priv) { struct vortex_private *vp = dev->priv; netif_device_detach(dev); if (vp->open) vortex_down(dev); vp->reap = 1; kfree(node); MOD_DEC_USE_COUNT; }}static void vortex_suspend(dev_node_t *node){ struct net_device *dev, *next; printk(KERN_DEBUG "vortex_suspend(%s)\n", node->dev_name); for (dev = root_vortex_dev; dev; dev = next) { next = ((struct vortex_private *)dev->priv)->next_module; if (strcmp(dev->name, node->dev_name) == 0) break; } if (dev && dev->priv) { struct vortex_private *vp = (struct vortex_private *)dev->priv; netif_device_detach(dev); if (vp->open) vortex_down(dev); }}static void vortex_resume(dev_node_t *node){ struct net_device *dev, *next; printk(KERN_DEBUG "vortex_resume(%s)\n", node->dev_name); for (dev = root_vortex_dev; dev; dev = next) { next = ((struct vortex_private *)dev->priv)->next_module; if (strcmp(dev->name, node->dev_name) == 0) break; } if (dev && dev->priv) { struct vortex_private *vp = (struct vortex_private *)dev->priv; if (vp->open) vortex_up(dev); netif_device_attach(dev); }}struct driver_operations vortex_ops = { "3c575_cb", vortex_attach, vortex_suspend, vortex_resume, vortex_detach};int init_module(void){ if (debug) printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); register_driver(&vortex_ops); return 0;}static struct net_device *vortex_probe1(int pci_bus, int pci_devfn, struct net_device *dev, long ioaddr, int irq, int chip_idx, int find_cnt){ struct vortex_private *vp; void *priv_mem; int option; unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */ int drv_flags = pci_tbl[chip_idx].drv_flags; int i, step; dev = init_etherdev(dev, 0); printk(KERN_INFO "%s: 3Com %s at 0x%lx,", dev->name, pci_tbl[chip_idx].name, ioaddr); /* Make certain elements e.g. descriptor lists are aligned. */ priv_mem = kmalloc(sizeof(*vp) + PRIV_ALIGN, GFP_KERNEL); /* Check for the very unlikely case of no memory. */ if (priv_mem == NULL) { printk(" INTERFACE MEMORY ALLOCATION FAILURE.\n"); return NULL; } dev->base_addr = ioaddr; dev->irq = irq; dev->mtu = mtu; dev->priv = vp = (void *)(((long)priv_mem + PRIV_ALIGN) & ~PRIV_ALIGN); memset(vp, 0, sizeof(*vp)); vp->lock = SPIN_LOCK_UNLOCKED; vp->priv_addr = priv_mem; vp->next_module = root_vortex_dev; root_vortex_dev = dev; vp->chip_id = chip_idx; vp->pci_bus = pci_bus; vp->pci_devfn = pci_devfn; vp->drv_flags = drv_flags; /* The lower four bits are the media type. */ if (dev->mem_start) option = dev->mem_start; else if (find_cnt < MAX_UNITS) option = options[find_cnt]; else option = -1; if (option >= 0) { vp->media_override = ((option & 7) == 2) ? 0 : option & 15; vp->full_duplex = (option & 0x200) ? 1 : 0; vp->bus_master = (option & 16) ? 1 : 0; } else { vp->media_override = 7; vp->full_duplex = 0; vp->bus_master = 0; } if (find_cnt < MAX_UNITS && full_duplex[find_cnt] > 0) vp->full_duplex = 1; if (vp->full_duplex) vp->medialock = 1; vp->options = option; /* Read the station address from the EEPROM. */ EL3WINDOW(0); for (i = 0; i < 0x40; i++) { int timer; outw((drv_flags & EEPROM_8BIT ? 0x230 : EEPROM_Read) + i, ioaddr + Wn0EepromCmd); /* The read may take up to 162 usec, timed with PCI cycles. */ for (timer = 162*5; timer >= 0; timer--) { if ((inw(ioaddr + Wn0EepromCmd) & 0x8000) == 0) break; } eeprom[i] = inw(ioaddr + Wn0EepromData); } for (i = 0; i < 0x18; i++) checksum ^= eeprom[i]; checksum = (checksum ^ (checksum >> 8)) & 0xff; if (checksum != 0x00) { /* Grrr, needless incompatible change 3Com. */ while (i < 0x21) checksum ^= eeprom[i++]; checksum = (checksum ^ (checksum >> 8)) & 0xff; } if (checksum != 0x00 && !(drv_flags & IS_TORNADO)) printk(" ***INVALID CHECKSUM %4.4x*** ", checksum); for (i = 0; i < 3; i++) ((u16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]); for (i = 0; i < 6; i++) printk("%c%2.2x", i ? ':' : ' ', dev->dev_addr[i]); EL3WINDOW(2); for (i = 0; i < 6; i++) outb(dev->dev_addr[i], ioaddr + i);#ifdef __sparc__ printk(", irq %s\n", __irq_itoa(dev->irq));#else printk(", irq %d\n", dev->irq); /* Tell them about an invalid IRQ. */ if (vortex_debug && (dev->irq <= 0)) printk(KERN_WARNING " *** Warning: IRQ %d is unlikely to work! ***\n", dev->irq);#endif EL3WINDOW(4); step = (inb(ioaddr + Wn4_NetDiag) & 0x1e) >> 1; printk(KERN_INFO " product code '%c%c' rev %02x.%d date %02d-" "%02d-%02d\n", eeprom[6]&0xff, eeprom[6]>>8, eeprom[0x14], step, (eeprom[4]>>5) & 15, eeprom[4] & 31, eeprom[4]>>9); if ((eeprom[0x14] == 0x07) && (step == 1)) vp->drv_flags = drv_flags |= HAS_FIFO_BUG; if (drv_flags & HAS_CB_FNS) { u32 fn_st_addr; /* Cardbus function status space */ pcibios_read_config_dword(pci_bus, pci_devfn, PCI_BASE_ADDRESS_2,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -