📄 eepro100.c
字号:
} else { ee_size = 0x40; read_cmd = EE_READ_CMD << 22; } for (j = 0, i = 0, sum = 0; i < ee_size; i++) { u16 value = do_eeprom_cmd(iobase, read_cmd | (i << 16), 27); eeprom[i] = value; sum += value; if (i < 3) { dev->dev_addr[j++] = value; dev->dev_addr[j++] = value >> 8; } } if (sum != 0xBABA) printk(KERN_WARNING "%s: Invalid EEPROM checksum %#4.4x, " "check settings before activating this device!\n", dev->name, sum); /* Don't unregister_netdev(dev); as the EEPro may actually be usable, especially if the MAC address is set later. On the other hand, it may be unusable if MDI data is corrupted. */ } /* Reset the chip: stop Tx and Rx processes and clear counters. This takes less than 10usec and will easily finish before the next action. */ outl(PortReset, ioaddr + SCBPort); inl(ioaddr + SCBPort); /* Honor PortReset timing. */ udelay(10); if (eeprom[3] & 0x0100) product = "OEM i82557/i82558 10/100 Ethernet"; else product = pci_tbl[chip_idx].name; printk(KERN_INFO "%s: %s, ", dev->name, product); for (i = 0; i < 5; i++) printk("%2.2X:", dev->dev_addr[i]); printk("%2.2X, ", dev->dev_addr[i]);#ifdef USE_IO printk("I/O at %#3lx, ", ioaddr);#endif printk("IRQ %d.\n", pdev->irq);#if 1 || defined(kernel_bloat) /* OK, this is pure kernel bloat. I don't like it when other drivers waste non-pageable kernel space to emit similar messages, but I need them for bug reports. */ { const char *connectors[] = {" RJ45", " BNC", " AUI", " MII"}; /* The self-test results must be paragraph aligned. */ s32 str[6], *volatile self_test_results; int boguscnt = 16000; /* Timeout for set-test. */ if ((eeprom[3] & 0x03) != 0x03) 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -