📄 eepro100_cb.c
字号:
product = pci_id_tbl[chip_idx].name; printk(KERN_INFO "%s: %s at %#3lx, ", dev->name, product, ioaddr); for (i = 0; i < 5; i++) printk("%2.2X:", dev->dev_addr[i]); printk("%2.2X, IRQ %d.\n", dev->dev_addr[i], irq);#ifndef 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) 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); /* Return the chip to its original power state. */ acpi_set_pwr_state(pdev, acpi_idle_state); /* We do a request_region() only to register /proc/ioports info. */ request_region(ioaddr, pci_id_tbl[chip_idx].io_size, "Intel Speedo3 Ethernet"); dev->base_addr = ioaddr; dev->irq = 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_dev = pdev; 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; dev->stop = &speedo_close; dev->get_stats = &speedo_get_stats; dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &speedo_ioctl;#ifdef HAVE_TX_TIMEOUT dev->watchdog_timeo = TX_TIMEOUT; dev->tx_timeout = speedo_tx_timeout;#endif 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/* Delay between EEPROM clock transitions. The code works with no delay on 33Mhz PCI. */#define eeprom_delay() inw(ee_addr)static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len){ unsigned retval = 0; long ee_addr = ioaddr + SCBeeprom; outw(EE_ENB | EE_SHIFT_CLK, ee_addr); /* Shift the command bits out. */ do { short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; outw(dataval, ee_addr); eeprom_delay(); outw(dataval | EE_SHIFT_CLK, ee_addr); eeprom_delay(); retval = (retval << 1) | ((inw(ee_addr) & EE_DATA_READ) ? 1 : 0); } while (--cmd_len >= 0); outw(EE_ENB, ee_addr); /* Terminate the EEPROM access. */ 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; acpi_set_pwr_state(sp->pci_dev, ACPI_D0); if (speedo_debug > 1) printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq); /* 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; /* .. we can safely take handler calls during init. */ if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) { return -EAGAIN; } MOD_INC_USE_COUNT; dev->if_port = sp->default_port;#if 0 /* With some transceivers we must retrigger negotiation to reset power-up 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. */ speedo_resume(dev); netif_start_queue(dev); netif_mark_up(dev); /* Setup the chip and configure the multicast list. */ sp->mc_setup_frm = NULL; sp->mc_setup_frm_len = 0; sp->mc_setup_busy = 0; sp->rx_mode = -1; /* Invalid -> always reset the mode. */ sp->flow_ctrl = sp->partner = 0; 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 = jiffies + 3*HZ; 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; outw(SCBMaskAll, ioaddr + SCBCmd); /* 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); 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); 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. */ { int entry = sp->cur_tx++ % TX_RING_SIZE; struct descriptor *cur_cmd = (struct descriptor *)&sp->tx_ring[entry]; /* Avoid a bug(?!) here by marking the command already completed. */ cur_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000); cur_cmd->link = virt_to_le32desc(&sp->tx_ring[sp->cur_tx % TX_RING_SIZE]); memcpy(cur_cmd->params, dev->dev_addr, 6); if (sp->last_cmd) clear_suspend(sp->last_cmd); sp->last_cmd = cur_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); outw(CUStart, 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; 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)); } /* This no longer has a false-trigger window. */ if (sp->cur_tx - sp->dirty_tx > 1 && (jiffies - dev->trans_start) > TX_TIMEOUT && (jiffies - sp->last_cmd_time) > TX_TIMEOUT) { printk(KERN_DEBUG "%d %d %d %d\n", sp->cur_tx - sp->dirty_tx, jiffies - dev->trans_start, jiffies - sp->last_cmd_time, TX_TIMEOUT); speedo_tx_timeout(dev); sp->last_reset = jiffies; } if (sp->rx_mode < 0 || (sp->rx_bug && jiffies - sp->last_rx_time > 2*HZ)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -