📄 eepro100.c
字号:
printk(KERN_INFO " Receiver lock-up bug exists -- enabling" " work-around.\n"); printk(KERN_INFO " Board assembly %4.4x%2.2x-%3.3d, Physical" " connectors present:", eeprom[8], eeprom[9]>>8, eeprom[9] & 0xff); for (i = 0; i < 4; i++) if (eeprom[5] & (1<<i)) printk(connectors[i]); printk("\n"KERN_INFO" Primary interface chip %s PHY #%d.\n", phys[(eeprom[6]>>8)&15], eeprom[6] & 0x1f); 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(ioaddr, 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(ioaddr, 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(ioaddr, eeprom[6] & 0x1f, 0, ((option & 0x20) ? 0x2000 : 0) | /* 100mbps? */ ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */ } /* Perform a system self-test. */ self_test_results = (s32*) ((((long) str) + 15) & ~0xf); self_test_results[0] = 0; self_test_results[1] = -1; outl(virt_to_bus(self_test_results) | 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); /* Honor PortReset timing. */ udelay(10); /* We do a request_region() only to register /proc/ioports info. */ request_region(ioaddr, SPEEDO3_TOTAL_SIZE, "Intel Speedo3 Ethernet"); dev->base_addr = ioaddr; dev->irq = pdev->irq; sp = dev->priv; if (dev->priv == NULL) { void *mem = kmalloc(sizeof(*sp), GFP_KERNEL); dev->priv = sp = mem; /* Cache align here if kmalloc does not. */ sp->priv_addr = mem; } memset(sp, 0, sizeof(*sp)); sp->next_module = root_speedo_dev; root_speedo_dev = dev; sp->pci_bus = pci_bus; sp->pci_devfn = pci_devfn; sp->chip_id = chip_idx; sp->acpi_pwr = acpi_idle_state; sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0; if (card_idx >= 0) { if (full_duplex[card_idx] >= 0) sp->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->rx_bug = (eeprom[3] & 0x03) == 3 ? 0 : 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;#if defined(HAS_NETIF_QUEUE) dev->tx_timeout = &speedo_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT;#endif dev->stop = &speedo_close; dev->get_stats = &speedo_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &speedo_ioctl; return dev;}/* 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 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(long ioaddr, int phy_id, int location){ 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 int mdio_write(long ioaddr, int phy_id, int location, int value){ 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)); return val & 0xffff;}static intspeedo_open(struct net_device *dev){ struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; if (speedo_debug > 1) printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq); MOD_INC_USE_COUNT; /* Set up the Tx queue early.. */ sp->cur_tx = 0; sp->dirty_tx = 0; sp->last_cmd = 0; sp->tx_full = 0; sp->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; sp->in_interrupt = 0; /* .. we can safely take handler calls during init. */ if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) { MOD_DEC_USE_COUNT; return -EAGAIN; } 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(ioaddr, phy_addr, 0, mii_ctrl[dev->default_port & 7]);#else mdio_write(ioaddr, phy_addr, 0, 0x3300);#endif }#endif speedo_init_rx_ring(dev); /* Fire up the hardware. */ outw(SCBMaskAll, ioaddr + SCBCmd); speedo_resume(dev); dev->interrupt = 0; dev->start = 1; 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->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4); if (speedo_debug > 2) { 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. */ init_timer(&sp->timer); 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(ioaddr, sp->phy[0] & 0x1f, 0); return 0;}/* Start the chip hardware after a full reset. */static void speedo_resume(struct net_device *dev){ struct speedo_private *sp = (struct speedo_private *)dev->priv; 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'. */ wait_for_cmd_done(ioaddr + SCBCmd); outl(0, ioaddr + SCBPointer); /* impose a delay to avoid a bug */ inl(ioaddr + SCBPointer); udelay(10); outb(RxAddrLoad, ioaddr + SCBCmd); wait_for_cmd_done(ioaddr + SCBCmd); outb(CUCmdBase, ioaddr + SCBCmd); wait_for_cmd_done(ioaddr + SCBCmd); /* Load the statistics block and rx ring addresses. */ outl(virt_to_bus(&sp->lstats), ioaddr + SCBPointer); outb(CUStatsAddr, ioaddr + SCBCmd); sp->lstats.done_marker = 0; wait_for_cmd_done(ioaddr + SCBCmd); if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) { if (speedo_debug > 2) printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n", dev->name); } else { outl(virt_to_bus(sp->rx_ringp[sp->cur_rx % RX_RING_SIZE]), ioaddr + SCBPointer); outb(RxStart, ioaddr + SCBCmd); wait_for_cmd_done(ioaddr + SCBCmd); } outb(CUDumpStats, ioaddr + SCBCmd); /* 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 = virt_to_le32desc(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]); memcpy(ias_cmd->params, dev->dev_addr, 6); sp->last_cmd = ias_cmd; } /* Start the chip's Tx process and unmask interrupts. */ wait_for_cmd_done(ioaddr + SCBCmd); outl(virt_to_bus(&sp->tx_ring[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);}/* Media monitoring and control. */static void speedo_timer(unsigned long data){ struct net_device *dev = (struct net_device *)data; struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; int phy_num = sp->phy[0] & 0x1f; /* We have MII and lost link beat. */ if ((sp->phy[0] & 0x8000) == 0) { int partner = mdio_read(ioaddr, phy_num, 5); if (partner != sp->partner) { int flow_ctrl = sp->advertising & partner & 0x0400 ? 1 : 0; if (speedo_debug > 2) { printk(KERN_DEBUG "%s: Link status change.\n", dev->name); printk(KERN_DEBUG "%s: Old partner %x, new %x, adv %x.\n", dev->name, sp->partner, partner, sp->advertising); } sp->partner = partner; if (flow_ctrl != sp->flow_ctrl) { sp->flow_ctrl = flow_ctrl; sp->rx_mode = -1; /* Trigger a reload. */ } /* Clear sticky bit. */ mdio_read(ioaddr, phy_num, 1); /* If link beat has returned... */ if (mdio_read(ioaddr, phy_num, 1) & 0x0004) dev->flags |= IFF_RUNNING; else dev->flags &= ~IFF_RUNNING; } } if (speedo_debug > 3) { printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n", dev->name, inw(ioaddr + SCBStatus)); } if (sp->rx_mode < 0 || (sp->rx_bug && jiffies - sp->last_rx_time > 2*HZ)) { /* We haven't received a packet in a Long Time. We might have been bitten by the receiver hang bug. This can be cleared by sending a set multicast list command. */ if (speedo_debug > 2) printk(KERN_DEBUG "%s: Sending a multicast list set command" " from a timer routine.\n", dev->name); set_rx_mode(dev); } /* We must continue to monitor the media. */ sp->timer.expires = RUN_AT(2*HZ); /* 2.0 sec. */ add_timer(&sp->timer);}static void speedo_show_state(struct net_device *dev){ struct speedo_private *sp = (struct speedo_private *)dev->priv;#if 0 long ioaddr = dev->base_addr; int phy_num = sp->phy[0] & 0x1f;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -