📄 3c575_cb.c
字号:
&fn_st_addr); if (fn_st_addr) vp->cb_fn_base = ioremap(fn_st_addr & ~3, 128); if (vortex_debug > 1) printk(KERN_DEBUG "%s: CardBus functions mapped %8.8x->%p.\n", dev->name, fn_st_addr, vp->cb_fn_base); } /* Extract our information from the EEPROM data. */ vp->info1 = eeprom[13]; vp->info2 = eeprom[15]; vp->capabilities = eeprom[16]; if (vp->info1 & 0x8000) vp->full_duplex = 1; /* Turn on the transceiver. */ activate_xcvr(dev); { char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"}; union wn3_config config; EL3WINDOW(3); vp->available_media = inw(ioaddr + Wn3_Options); if ((vp->available_media & 0xff) == 0) /* Broken 3c916 */ vp->available_media = 0x40; config.i = inl(ioaddr + Wn3_Config); if (vortex_debug > 1) printk(KERN_DEBUG " Internal config register is %4.4x, " "transceivers %#x.\n", config.i, inw(ioaddr + Wn3_Options)); printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n", 8 << config.u.ram_size, config.u.ram_width ? "word" : "byte", ram_split[config.u.ram_split], config.u.autoselect ? "autoselect/" : "", config.u.xcvr > XCVR_ExtMII ? "<invalid transceiver>" : media_tbl[config.u.xcvr].name); vp->default_media = config.u.xcvr; vp->autoselect = config.u.autoselect; } if (vp->media_override != 7) { printk(KERN_INFO " Media override to transceiver type %d (%s).\n", vp->media_override, media_tbl[vp->media_override].name); dev->if_port = vp->media_override; } else dev->if_port = vp->default_media; if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { int phy, phy_idx = 0; EL3WINDOW(4); mii_preamble_required++; mii_preamble_required++; mdio_read(ioaddr, 24, 1); for (phy = 1; phy <= 32 && phy_idx < sizeof(vp->phys); phy++) { int mii_status, phyx = phy & 0x1f; mii_status = mdio_read(ioaddr, phyx, 1); if (mii_status && mii_status != 0xffff) { vp->phys[phy_idx++] = phyx; if (vortex_debug > 1) printk(KERN_DEBUG " MII transceiver found at address %d," " status %4x.\n", phyx, mii_status); if ((mii_status & 0x0040) == 0) mii_preamble_required++; } } mii_preamble_required--; if (phy_idx == 0) { printk(KERN_WARNING" ***WARNING*** No MII transceivers found!\n"); vp->phys[0] = 24; } else { vp->advertising = mdio_read(ioaddr, vp->phys[0], 4); if (vp->full_duplex) { /* Only advertise the FD media types. */ vp->advertising &= ~0x02A0; mdio_write(ioaddr, vp->phys[0], 4, vp->advertising); } } } if (vp->capabilities & CapPwrMgmt) acpi_set_WOL(dev); if (vp->capabilities & CapBusMaster) { vp->full_bus_master_tx = 1; if (vortex_debug > 1) printk(KERN_DEBUG " Enabling bus-master transmits and %s " "receives.\n", (vp->info2 & 1) ? "early" : "whole-frame" ); vp->full_bus_master_rx = (vp->info2 & 1) ? 1 : 2; } /* We do a request_region() to register /proc/ioports info. */ request_region(ioaddr, pci_tbl[chip_idx].io_size, dev->name); /* The 3c59x-specific entries in the device structure. */ dev->open = &vortex_open; dev->hard_start_xmit = &vortex_start_xmit; dev->stop = &vortex_close; dev->get_stats = &vortex_get_stats; dev->do_ioctl = &vortex_ioctl; dev->set_multicast_list = &set_rx_mode;#ifdef HAVE_TX_TIMEOUT dev->tx_timeout = vortex_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT;#endif return dev;}static void issue_and_wait(struct net_device *dev, int cmd){ int i = 2000; outw(cmd, dev->base_addr + EL3_CMD); while (--i > 0) if (!(inw(dev->base_addr + EL3_STATUS) & CmdInProgress)) break; if (i == 0) printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n", dev->name, cmd);}static voidvortex_up(struct net_device *dev){ struct vortex_private *vp = (struct vortex_private *)dev->priv; long ioaddr = dev->base_addr; int i; acpi_wake(vp->pci_bus, vp->pci_devfn); activate_xcvr(dev); /* Before initializing select the active media port. */ if (vp->media_override != 7) { if (vortex_debug > 1) printk(KERN_INFO "%s: Media override to transceiver %d (%s).\n", dev->name, vp->media_override, media_tbl[vp->media_override].name); dev->if_port = vp->media_override; } else if (vp->autoselect) { if (vp->drv_flags & HAS_NWAY) dev->if_port = XCVR_NWAY; else { /* Find first available media type, starting with 100baseTx. */ dev->if_port = XCVR_100baseTx; while (! (vp->available_media & media_tbl[dev->if_port].mask)) dev->if_port = media_tbl[dev->if_port].next; } } else dev->if_port = vp->default_media; if (! vp->medialock) vp->full_duplex = 0; vp->status_enable = SetStatusEnb | HostError|IntReq|StatsFull|TxComplete| (vp->full_bus_master_tx ? DownComplete : TxAvailable) | (vp->full_bus_master_rx ? UpComplete : RxComplete) | (vp->bus_master ? DMADone : 0); vp->intr_enable = SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull | HostError | TxComplete | IntReq | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete; if (vortex_debug > 1) printk(KERN_DEBUG "%s: Initial media type %s %s-duplex.\n", dev->name, media_tbl[dev->if_port].name, vp->full_duplex ? "full":"half"); set_media_type(dev); start_operation(dev); spin_lock(&vp->lock); if (vortex_debug > 1) { EL3WINDOW(4); printk(KERN_DEBUG "%s: vortex_open() irq %d media status %4.4x.\n", dev->name, dev->irq, inw(ioaddr + Wn4_Media)); } /* Switch to the stats window, and clear all stats by reading. */ outw(StatsDisable, ioaddr + EL3_CMD); EL3WINDOW(6); for (i = 0; i < 10; i++) inb(ioaddr + i); inw(ioaddr + 10); inw(ioaddr + 12); /* New: On the Vortex we must also clear the BadSSD counter. */ EL3WINDOW(4); inb(ioaddr + 12); /* ..and on the Boomerang we enable the extra statistics bits. */ outw(0x0040, ioaddr + Wn4_NetDiag); /* Switch to register set 7 for normal use. */ EL3WINDOW(7); spin_unlock(&vp->lock); vp->tx_full = 0; if (vp->full_bus_master_rx) { /* Boomerang bus master. */ vp->cur_rx = vp->dirty_rx = 0; /* Initialize the RxEarly register as recommended. */ outw(SetRxThreshold + (1536>>2), ioaddr + EL3_CMD); outl(0x0020, ioaddr + PktStatus); for (i = 0; i < RX_RING_SIZE; i++) vp->rx_ring[i].status = 0; vp->rx_head_desc = &vp->rx_ring[0]; outl(virt_to_bus(vp->rx_head_desc), ioaddr + UpListPtr); } if (vp->full_bus_master_tx) { /* Boomerang bus master Tx. */ vp->cur_tx = vp->dirty_tx = 0; vp->tx_desc_tail = &vp->tx_ring[TX_RING_SIZE - 1]; if ((vp->drv_flags & IS_BOOMERANG) || !down_poll_rate) { /* Room for a packet, to avoid long DownStall delays. */ outb(PKT_BUF_SZ>>8, ioaddr + TxFreeThreshold); } else outb(down_poll_rate, ioaddr + DownPollRate); /* Clear the Tx ring. */ for (i = 0; i < TX_RING_SIZE; i++) vp->tx_skbuff[i] = 0; outl(0, ioaddr + DownListPtr); vp->restart_tx = 1; } /* Set receiver mode: presumably accept b-cast and phys addr only. */ set_rx_mode(dev); outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */ if (vp->drv_flags & HAS_FIFO_BUG) /* max out the tx fifo threshold */ outb(0x1f, ioaddr + DownBurstThresh); outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */ outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */ /* Allow status bits to be seen. */ outw(vp->status_enable, ioaddr + EL3_CMD); /* Ack all pending events, and set active indicator mask. */ outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq, ioaddr + EL3_CMD); outw(vp->intr_enable, ioaddr + EL3_CMD); if (vp->cb_fn_base) /* The PCMCIA people are idiots. */ writel(0x8000, vp->cb_fn_base + 4); init_timer(&vp->timer); vp->timer.expires = jiffies + media_tbl[dev->if_port].wait; vp->timer.data = (unsigned long)dev; vp->timer.function = &vortex_timer; /* timer handler */ add_timer(&vp->timer);}static void set_media_type(struct net_device *dev){ struct vortex_private *vp = (struct vortex_private *)dev->priv; long ioaddr = dev->base_addr; union wn3_config config; EL3WINDOW(3); config.i = inl(ioaddr + Wn3_Config); config.u.xcvr = dev->if_port; if ( ! (vp->drv_flags & HAS_NWAY)) outl(config.i, ioaddr + Wn3_Config); if (dev->if_port == XCVR_MII || dev->if_port == XCVR_NWAY) { int mii_reg1, mii_reg5; EL3WINDOW(4); /* Read BMSR (reg1) only to clear old status. */ mii_reg1 = mdio_read(ioaddr, vp->phys[0], 1); mii_reg5 = mdio_read(ioaddr, vp->phys[0], 5); if (mii_reg5 == 0xffff || mii_reg5 == 0x0000) { ; /* No MII device or no link partner report */ } else { mii_reg5 &= vp->advertising; if ((mii_reg5 & 0x0100) || /* 100baseTx-FD */ (mii_reg5 & 0x00C0) == 0x0040) /* 10T-FD, but not 100-HD */ vp->full_duplex = 1; } if (vortex_debug > 1) printk(KERN_INFO "%s: MII #%d status %4.4x, link partner capability %4.4x," " setting %s-duplex.\n", dev->name, vp->phys[0], mii_reg1, mii_reg5, vp->full_duplex ? "full" : "half"); if (!auto_polarity) { /* works for TDK 78Q2120 series MII's */ int i = mdio_read(ioaddr, vp->phys[0], 16) | 0x20; mdio_write(ioaddr, vp->phys[0], 16, i); } } if (dev->if_port == XCVR_10base2) /* Start the thinnet transceiver. We should really wait 50ms...*/ outw(StartCoax, ioaddr + EL3_CMD); if (dev->if_port != XCVR_NWAY) { EL3WINDOW(4); outw((inw(ioaddr + Wn4_Media) & ~(Media_10TP|Media_SQE)) | media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media); } /* Set the full-duplex bit. */ EL3WINDOW(3); outb(((vp->info1 & 0x8000) || vp->full_duplex ? 0x20 : 0) | (dev->mtu > 1500 ? 0x40 : 0), ioaddr + Wn3_MAC_Ctrl);}static void activate_xcvr(struct net_device *dev){ struct vortex_private *vp = (struct vortex_private *)dev->priv; long ioaddr = dev->base_addr; int reset_opts; /* Correct some magic bits. */ EL3WINDOW(2); reset_opts = inw(ioaddr + Wn2_ResetOptions); if (vp->drv_flags & INVERT_LED_PWR) reset_opts |= 0x0010; if (vp->drv_flags & MII_XCVR_PWR) reset_opts |= 0x4000; outw(reset_opts, ioaddr + Wn2_ResetOptions);}static void start_operation(struct net_device *dev){ long ioaddr = dev->base_addr; int i; issue_and_wait(dev, TxReset); issue_and_wait(dev, RxReset); outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); /* Reset the station address and mask. */ EL3WINDOW(2); for (i = 0; i < 6; i++) outb(dev->dev_addr[i], ioaddr + i); for (; i < 12; i+=2) outw(0, ioaddr + i);}static intvortex_open(struct net_device *dev){ struct vortex_private *vp = (struct vortex_private *)dev->priv; int i;#ifdef CARDBUS if (vp->reap) return -ENODEV;#endif /* Use the now-standard shared IRQ implementation. */ if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev)) { return -EAGAIN; } if (vp->full_bus_master_rx) { /* Boomerang bus master. */ if (vortex_debug > 2) printk(KERN_DEBUG "%s: Filling in the Rx ring.\n", dev->name); vp->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32); for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb; vp->rx_ring[i].length = cpu_to_le32(vp->rx_buf_sz | LAST_FRAG); vp->rx_ring[i].next = virt_to_le32desc(&vp->rx_ring[i+1]); skb = dev_alloc_skb(vp->rx_buf_sz); vp->rx_skbuff[i] = skb; if (skb == NULL) break; /* Bad news! */ skb->dev = dev; /* Mark as being used by this device. */ skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */ vp->rx_ring[i].addr = virt_to_le32desc(skb->tail); } /* Wrap the ring. */ vp->rx_ring[i-1].next = virt_to_le32desc(&vp->rx_ring[0]); } if (vp->full_bus_master_tx) dev->hard_start_xmit = &boomerang_start_xmit; vortex_up(dev); vp->open = 1; netif_start_queue(dev); netif_mark_up(dev); MOD_INC_USE_COUNT; return 0;}static void vortex_timer(unsigned long data){ struct net_device *dev = (struct net_device *)data; struct vortex_private *vp = (struct vortex_private *)dev->priv; long ioaddr = dev->base_addr; int next_tick = 60*HZ; int ok = 0; int media_status, mii_status, old_window; unsigned long flags; if (vortex_debug > 1) printk(KERN_DEBUG "%s: Media selection timer tick happened, %s.\n", dev->name, media_tbl[dev->if_port].name); /* This only works with bus-master (non-3c590) chips. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -