📄 eepro100.c
字号:
if (eeprom[7] & 0x0700) printk(KERN_INFO " Secondary interface chip %s.\n", phys[(eeprom[7]>>8)&7]); if (((eeprom[6]>>8) & 0x3f) == DP83840 || ((eeprom[6]>>8) & 0x3f) == DP83840A) { int mdi_reg23 = mdio_read(dev, eeprom[6] & 0x1f, 23) | 0x0422; if (congenb) mdi_reg23 |= 0x0100; printk(KERN_INFO" DP83840 specific setup, setting register 23 to %4.4x.\n", mdi_reg23); mdio_write(dev, eeprom[6] & 0x1f, 23, mdi_reg23); } if ((option >= 0) && (option & 0x70)) { printk(KERN_INFO " Forcing %dMbs %s-duplex operation.\n", (option & 0x20 ? 100 : 10), (option & 0x10 ? "full" : "half")); mdio_write(dev, eeprom[6] & 0x1f, MII_BMCR, ((option & 0x20) ? 0x2000 : 0) | /* 100mbps? */ ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ } /* Perform a system self-test. */ self_test_results = (s32*) ((((long) tx_ring_space) + 15) & ~0xf); self_test_results[0] = 0; self_test_results[1] = -1; outl(tx_ring_dma | PortSelfTest, ioaddr + SCBPort); do { udelay(10); } while (self_test_results[1] == -1 && --boguscnt >= 0); if (boguscnt < 0) { /* Test optimized out. */ printk(KERN_ERR "Self test failed, status %8.8x:\n" KERN_ERR " Failure to initialize the i82557.\n" KERN_ERR " Verify that the card is a bus-master" " capable slot.\n", self_test_results[1]); } else printk(KERN_INFO " General self-test: %s.\n" KERN_INFO " Serial sub-system self-test: %s.\n" KERN_INFO " Internal registers self-test: %s.\n" KERN_INFO " ROM checksum self-test: %s (%#8.8x).\n", self_test_results[1] & 0x1000 ? "failed" : "passed", self_test_results[1] & 0x0020 ? "failed" : "passed", self_test_results[1] & 0x0008 ? "failed" : "passed", self_test_results[1] & 0x0004 ? "failed" : "passed", self_test_results[0]); }#endif /* kernel_bloat */ outl(PortReset, ioaddr + SCBPort); inl(ioaddr + SCBPort); udelay(10); /* Return the chip to its original power state. */ pci_set_power_state(pdev, acpi_idle_state); pci_set_drvdata (pdev, dev); SET_NETDEV_DEV(dev, &pdev->dev); dev->irq = pdev->irq; sp = netdev_priv(dev); sp->pdev = pdev; sp->msg_enable = DEBUG; sp->acpi_pwr = acpi_idle_state; sp->tx_ring = tx_ring_space; sp->tx_ring_dma = tx_ring_dma; sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE); sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE); init_timer(&sp->timer); /* used in ioctl() */ spin_lock_init(&sp->lock); sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0; if (card_idx >= 0) { if (full_duplex[card_idx] >= 0) sp->mii_if.full_duplex = full_duplex[card_idx]; } sp->default_port = option >= 0 ? (option & 0x0f) : 0; sp->phy[0] = eeprom[6]; sp->phy[1] = eeprom[7]; sp->mii_if.phy_id = eeprom[6] & 0x1f; sp->mii_if.phy_id_mask = 0x1f; sp->mii_if.reg_num_mask = 0x1f; sp->mii_if.dev = dev; sp->mii_if.mdio_read = mdio_read; sp->mii_if.mdio_write = mdio_write; sp->rx_bug = (eeprom[3] & 0x03) == 3 ? 0 : 1; if (((pdev->device > 0x1030 && (pdev->device < 0x103F))) || (pdev->device == 0x2449) || (pdev->device == 0x2459) || (pdev->device == 0x245D)) { sp->chip_id = 1; } if (sp->rx_bug) printk(KERN_INFO " Receiver lock-up workaround activated.\n"); /* The Speedo-specific entries in the device structure. */ dev->open = &speedo_open; dev->hard_start_xmit = &speedo_start_xmit; netif_set_tx_timeout(dev, &speedo_tx_timeout, TX_TIMEOUT); dev->stop = &speedo_close; dev->get_stats = &speedo_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &speedo_ioctl;#ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = &poll_speedo;#endif if (register_netdevice(dev)) goto err_free_unlock; rtnl_unlock(); return 0; err_free_unlock: rtnl_unlock(); free_netdev(dev); return -1;}static void do_slow_command(struct net_device *dev, int cmd){ long cmd_ioaddr = dev->base_addr + SCBCmd; int wait = 0; do if (inb(cmd_ioaddr) == 0) break; while(++wait <= 200); if (wait > 100) printk(KERN_ERR "Command %4.4x never accepted (%d polls)!\n", inb(cmd_ioaddr), wait); outb(cmd, cmd_ioaddr); for (wait = 0; wait <= 100; wait++) if (inb(cmd_ioaddr) == 0) return; for (; wait <= 20000; wait++) if (inb(cmd_ioaddr) == 0) return; else udelay(1); printk(KERN_ERR "Command %4.4x was not accepted after %d polls!" " Current status %8.8x.\n", cmd, wait, inl(dev->base_addr + SCBStatus));}/* Serial EEPROM section. A "bit" grungy, but we work our way through bit-by-bit :->. *//* EEPROM_Ctrl bits. */#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */#define EE_CS 0x02 /* EEPROM chip select. */#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */#define EE_DATA_READ 0x08 /* EEPROM chip data out. */#define EE_ENB (0x4800 | EE_CS)#define EE_WRITE_0 0x4802#define EE_WRITE_1 0x4806#define EE_OFFSET SCBeeprom/* The fixes for the code were kindly provided by Dragan Stancevic <visitor@valinux.com> to strictly follow Intel specifications of EEPROM access timing. The publicly available sheet 64486302 (sec. 3.1) specifies 1us access interval for serial EEPROM. However, it looks like that there is an additional requirement dictating larger udelay's in the code below. 2000/05/24 SAW */static int __devinit do_eeprom_cmd(long ioaddr, int cmd, int cmd_len){ unsigned retval = 0; long ee_addr = ioaddr + SCBeeprom; io_outw(EE_ENB, ee_addr); udelay(2); io_outw(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2); /* Shift the command bits out. */ do { short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; io_outw(dataval, ee_addr); udelay(2); io_outw(dataval | EE_SHIFT_CLK, ee_addr); udelay(2); retval = (retval << 1) | ((io_inw(ee_addr) & EE_DATA_READ) ? 1 : 0); } while (--cmd_len >= 0); io_outw(EE_ENB, ee_addr); udelay(2); /* Terminate the EEPROM access. */ io_outw(EE_ENB & ~EE_CS, ee_addr); return retval;}static int mdio_read(struct net_device *dev, int phy_id, int location){ long ioaddr = dev->base_addr; int val, boguscnt = 64*10; /* <64 usec. to complete, typ 27 ticks */ outl(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI); do { val = inl(ioaddr + SCBCtrlMDI); if (--boguscnt < 0) { printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val); break; } } while (! (val & 0x10000000)); return val & 0xffff;}static void mdio_write(struct net_device *dev, int phy_id, int location, int value){ long ioaddr = dev->base_addr; int val, boguscnt = 64*10; /* <64 usec. to complete, typ 27 ticks */ outl(0x04000000 | (location<<16) | (phy_id<<21) | value, ioaddr + SCBCtrlMDI); do { val = inl(ioaddr + SCBCtrlMDI); if (--boguscnt < 0) { printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val); break; } } while (! (val & 0x10000000));}static intspeedo_open(struct net_device *dev){ struct speedo_private *sp = netdev_priv(dev); long ioaddr = dev->base_addr; int retval; if (netif_msg_ifup(sp)) printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq); pci_set_power_state(sp->pdev, 0); /* Set up the Tx queue early.. */ sp->cur_tx = 0; sp->dirty_tx = 0; sp->last_cmd = NULL; sp->tx_full = 0; sp->in_interrupt = 0; /* .. we can safely take handler calls during init. */ retval = request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev); if (retval) { return retval; } dev->if_port = sp->default_port;#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us /* Retrigger negotiation to reset previous errors. */ if ((sp->phy[0] & 0x8000) == 0) { int phy_addr = sp->phy[0] & 0x1f ; /* Use 0x3300 for restarting NWay, other values to force xcvr: 0x0000 10-HD 0x0100 10-FD 0x2000 100-HD 0x2100 100-FD */#ifdef honor_default_port mdio_write(dev, phy_addr, MII_BMCR, mii_ctrl[dev->default_port & 7]);#else mdio_write(dev, phy_addr, MII_BMCR, 0x3300);#endif }#endif speedo_init_rx_ring(dev); /* Fire up the hardware. */ outw(SCBMaskAll, ioaddr + SCBCmd); speedo_resume(dev); netdevice_start(dev); netif_start_queue(dev); /* Setup the chip and configure the multicast list. */ sp->mc_setup_head = NULL; sp->mc_setup_tail = NULL; sp->flow_ctrl = sp->partner = 0; sp->rx_mode = -1; /* Invalid -> always reset the mode. */ set_rx_mode(dev); if ((sp->phy[0] & 0x8000) == 0) sp->mii_if.advertising = mdio_read(dev, sp->phy[0] & 0x1f, MII_ADVERTISE); mii_check_link(&sp->mii_if); if (netif_msg_ifup(sp)) { printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n", dev->name, inw(ioaddr + SCBStatus)); } /* Set the timer. The timer serves a dual purpose: 1) to monitor the media interface (e.g. link beat) and perhaps switch to an alternate media type 2) to monitor Rx activity, and restart the Rx process if the receiver hangs. */ sp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */ sp->timer.data = (unsigned long)dev; sp->timer.function = &speedo_timer; /* timer handler */ add_timer(&sp->timer); /* No need to wait for the command unit to accept here. */ if ((sp->phy[0] & 0x8000) == 0) mdio_read(dev, sp->phy[0] & 0x1f, MII_BMCR); return 0;}/* Start the chip hardware after a full reset. */static void speedo_resume(struct net_device *dev){ struct speedo_private *sp = netdev_priv(dev); long ioaddr = dev->base_addr; /* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */ sp->tx_threshold = 0x01208000; /* Set the segment registers to '0'. */ if (wait_for_cmd_done(dev) != 0) { outl(PortPartialReset, ioaddr + SCBPort); udelay(10); } outl(0, ioaddr + SCBPointer); inl(ioaddr + SCBPointer); /* Flush to PCI. */ udelay(10); /* Bogus, but it avoids the bug. */ /* Note: these next two operations can take a while. */ do_slow_command(dev, RxAddrLoad); do_slow_command(dev, CUCmdBase); /* Load the statistics block and rx ring addresses. */ outl(sp->lstats_dma, ioaddr + SCBPointer); inl(ioaddr + SCBPointer); /* Flush to PCI */ outb(CUStatsAddr, ioaddr + SCBCmd); sp->lstats->done_marker = 0; wait_for_cmd_done(dev); if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) { if (netif_msg_rx_err(sp)) printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n", dev->name); } else { outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE], ioaddr + SCBPointer); inl(ioaddr + SCBPointer); /* Flush to PCI */ } /* Note: RxStart should complete instantly. */ do_slow_command(dev, RxStart); do_slow_command(dev, CUDumpStats); /* Fill the first command with our physical address. */ { struct descriptor *ias_cmd; ias_cmd = (struct descriptor *)&sp->tx_ring[sp->cur_tx++ % TX_RING_SIZE]; /* Avoid a bug(?!) here by marking the command already completed. */ ias_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000); ias_cmd->link = cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE)); memcpy(ias_cmd->params, dev->dev_addr, 6); if (sp->last_cmd) clear_suspend(sp->last_cmd); sp->last_cmd = ias_cmd; } /* Start the chip's Tx process and unmask interrupts. */ outl(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE), ioaddr + SCBPointer); /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should remain masked --Dragan */ outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd);}/* * Sometimes the receiver stops making progress. This routine knows how to * get it going again, without losing packets or being otherwise nasty like * a chip reset would be. Previously the driver had a whole sequence * of if RxSuspended, if it's no buffers do one thing, if it's no resources, * do another, etc. But those things don't really matter. Separate logic * in the ISR provides for allocating buffers--the other half of operation * is just making sure the receiver is active. speedo_rx_soft_reset does that. * This problem with the old, more involved algorithm is shown up under * ping floods on the order of 60K packets/second on a 100Mbps fdx network. */static voidspeedo_rx_soft_reset(struct net_device *dev){ struct speedo_private *sp = netdev_priv(dev); struct RxFD *rfd; long ioaddr; ioaddr = dev->base_addr; if (wait_for_cmd_done(dev) != 0) { printk("%s: previous command stalled\n", dev->name); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -