📄 eepro100_cb.c
字号:
/* How to wait for the command unit to accept a command. Typically this takes 0 ticks. */static inline void wait_for_cmd_done(long cmd_ioaddr){ int wait = 1000; do ; while(inb(cmd_ioaddr) && --wait >= 0);}/* Offsets to the various registers. All accesses need not be longword aligned. */enum speedo_offsets { SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */ SCBPointer = 4, /* General purpose pointer. */ SCBPort = 8, /* Misc. commands and operands. */ SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */ SCBCtrlMDI = 16, /* MDI interface control. */ SCBEarlyRx = 20, /* Early receive byte count. */};/* Commands that can be put in a command list entry. */enum commands { CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000, CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000, CmdDump = 0x60000, CmdDiagnose = 0x70000, CmdSuspend = 0x40000000, /* Suspend after completion. */ CmdIntr = 0x20000000, /* Interrupt after completion. */ CmdTxFlex = 0x00080000, /* Use "Flexible mode" for CmdTx command. */};/* Do atomically if possible. */#if defined(__i386__)#define clear_suspend(cmd) ((char *)(&(cmd)->cmd_status))[3] &= ~0x40#elif defined(__alpha__)#define clear_suspend(cmd) clear_bit(30, &(cmd)->cmd_status)#elif defined(__powerpc__) || defined(__sparc__) || (__BIG_ENDIAN)#define clear_suspend(cmd) clear_bit(6, &(cmd)->cmd_status)#else#warning Undefined architecture.#define clear_suspend(cmd) (cmd)->cmd_status &= cpu_to_le32(~CmdSuspend)#endifenum SCBCmdBits { SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000, SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400, SCBTriggerIntr=0x0200, SCBMaskAll=0x0100, /* The rest are Rx and Tx commands. */ CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050, CUCmdBase=0x0060, /* CU Base address (set to zero) . */ CUDumpStats=0x0070, /* Dump then reset stats counters. */ RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006, RxResumeNoResources=0x0007,};enum SCBPort_cmds { PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3,};/* The Speedo3 Rx and Tx frame/buffer descriptors. */struct descriptor { /* A generic descriptor. */ s32 cmd_status; /* All command and status fields. */ u32 link; /* struct descriptor * */ unsigned char params[0];};/* The Speedo3 Rx and Tx buffer descriptors. */struct RxFD { /* Receive frame descriptor. */ s32 status; u32 link; /* struct RxFD * */ u32 rx_buf_addr; /* void * */ u32 count;};/* Selected elements of the Tx/RxFD.status word. */enum RxFD_bits { RxComplete=0x8000, RxOK=0x2000, RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010, RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002, TxUnderrun=0x1000, StatusComplete=0x8000,};struct TxFD { /* Transmit frame descriptor set. */ s32 status; u32 link; /* void * */ u32 tx_desc_addr; /* Always points to the tx_buf_addr element. */ s32 count; /* # of TBD (=1), Tx start thresh., etc. */ /* This constitutes two "TBD" entries -- we only use one. */ u32 tx_buf_addr0; /* void *, frame to be transmitted. */ s32 tx_buf_size0; /* Length of Tx frame. */ u32 tx_buf_addr1; /* void *, frame to be transmitted. */ s32 tx_buf_size1; /* Length of Tx frame. */};/* Elements of the dump_statistics block. This block must be lword aligned. */struct speedo_stats { u32 tx_good_frames; u32 tx_coll16_errs; u32 tx_late_colls; u32 tx_underruns; u32 tx_lost_carrier; u32 tx_deferred; u32 tx_one_colls; u32 tx_multi_colls; u32 tx_total_colls; u32 rx_good_frames; u32 rx_crc_errs; u32 rx_align_errs; u32 rx_resource_errs; u32 rx_overrun_errs; u32 rx_colls_errs; u32 rx_runt_errs; u32 done_marker;};/* Do not change the position (alignment) of the first few elements! The later elements are grouped for cache locality. */struct speedo_private { struct TxFD tx_ring[TX_RING_SIZE]; /* Commands (usually CmdTxPacket). */ struct RxFD *rx_ringp[RX_RING_SIZE]; /* Rx descriptor, used as ring. */ /* The addresses of a Tx/Rx-in-place packets/buffers. */ struct sk_buff* tx_skbuff[TX_RING_SIZE]; struct sk_buff* rx_skbuff[RX_RING_SIZE]; struct descriptor *last_cmd; /* Last command sent. */ unsigned int cur_tx, dirty_tx; /* The ring entries to be free()ed. */ spinlock_t lock; /* Group with Tx control cache line. */ u32 tx_threshold; /* The value for txdesc.count. */ unsigned long last_cmd_time; struct RxFD *last_rxf; /* Last command sent. */ unsigned int cur_rx, dirty_rx; /* The next free ring entry */ long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */ const char *product_name; struct net_device *next_module; void *priv_addr; /* Unaligned address for kfree */ struct net_device_stats stats; struct speedo_stats lstats; int chip_id; struct pci_dev *pci_dev; unsigned char acpi_pwr; struct timer_list timer; /* Media selection timer. */ int mc_setup_frm_len; /* The length of an allocated.. */ struct descriptor *mc_setup_frm; /* ..multicast setup frame. */ int mc_setup_busy; /* Avoid double-use of setup frame. */ char rx_mode; /* Current PROMISC/ALLMULTI setting. */ unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ unsigned int flow_ctrl:1; /* Use 802.3x flow control. */ unsigned int rx_bug:1; /* Work around receiver hang errata. */ unsigned int rx_bug10:1; /* Receiver might hang at 10mbps. */ unsigned int rx_bug100:1; /* Receiver might hang at 100mbps. */ unsigned char default_port:8; /* Last dev->if_port value. */ unsigned short phy[2]; /* PHY media interfaces available. */ unsigned short advertising; /* Current PHY advertised caps. */ unsigned short partner; /* Link partner caps. */ long last_reset;};/* The parameters for a CmdConfigure operation. There are so many options that it would be difficult to document each bit. We mostly use the default or recommended settings. */const char i82557_config_cmd[22] = { 22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ 0, 0x2E, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */ 0x3f, 0x05, };const char i82558_config_cmd[22] = { 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ 0, 0x2E, 0, 0x60, 0x08, 0x88, 0x68, 0, 0x40, 0xf2, 0xBD, /* 0xBD->0xFD=Force full-duplex */ 0x31, 0x05, };/* PHY media interface chips. */static const char *phys[] = { "None", "i82553-A/B", "i82553-C", "i82503", "DP83840", "80c240", "80c24", "i82555", "unknown-8", "unknown-9", "DP83840A", "unknown-11", "unknown-12", "unknown-13", "unknown-14", "unknown-15", };enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240, S80C24, I82555, DP83840A=10, };static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };#define EE_READ_CMD (6)static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len);static int mdio_read(long ioaddr, int phy_id, int location);static int mdio_write(long ioaddr, int phy_id, int location, int value);static int speedo_open(struct net_device *dev);static void speedo_resume(struct net_device *dev);static void speedo_timer(unsigned long data);static void speedo_init_rx_ring(struct net_device *dev);static void speedo_tx_timeout(struct net_device *dev);static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev);static int speedo_rx(struct net_device *dev);static void speedo_interrupt(int irq, void *dev_instance, struct pt_regs *regs);static int speedo_close(struct net_device *dev);static struct net_device_stats *speedo_get_stats(struct net_device *dev);static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static void set_rx_mode(struct net_device *dev);#ifdef honor_default_port/* Optional driver feature to allow forcing the transceiver setting. Not recommended. */static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100, 0x2000, 0x2100, 0x0400, 0x3100};#endif/* A list of all installed Speedo devices, for removing the driver module. */static struct net_device *root_speedo_dev = NULL;#if ! defined(HAS_PCI_NETIF)const int min_pci_latency = 32;static int pci_drv_register(struct drv_id_info *drv_id, void *initial_device){ int pci_index, cards_found = 0; unsigned char pci_bus, pci_device_fn; struct pci_dev *pdev; struct pci_id_info *pci_tbl = drv_id->pci_dev_tbl; void *newdev; if ( ! pcibios_present()) return -ENODEV; for (pci_index = 0; pci_index < 0xff; pci_index++) { u32 pci_id, subsys_id, pci_class_rev; u16 pci_command, new_command; int chip_idx, irq, pci_flags; long pciaddr; long ioaddr; if (pcibios_find_class (drv_id->pci_class, pci_index, &pci_bus, &pci_device_fn) != PCIBIOS_SUCCESSFUL) break; pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_VENDOR_ID, &pci_id); pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_SUBSYSTEM_ID, &subsys_id); pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_REVISION_ID, &pci_class_rev); for (chip_idx = 0; pci_tbl[chip_idx].name; chip_idx++) { struct pci_id_info *chip = &pci_tbl[chip_idx]; if ((pci_id & chip->id.pci_mask) == chip->id.pci && (subsys_id & chip->id.subsystem_mask) == chip->id.subsystem && (pci_class_rev&chip->id.revision_mask) == chip->id.revision) break; } if (pci_tbl[chip_idx].name == 0) /* Compiled out! */ continue; pci_flags = pci_tbl[chip_idx].pci_flags; pdev = pci_find_slot(pci_bus, pci_device_fn);#if LINUX_VERSION_CODE >= 0x020328 pciaddr = pdev->resource[0].start; irq = pdev->irq;#elif LINUX_VERSION_CODE >= 0x20155 pciaddr = pdev->base_address[(pci_flags >> 4) & 7]; irq = pdev->irq;#else { u32 pci_busaddr; u8 pci_irq_line; pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq_line); pcibios_read_config_dword(pci_bus, pci_device_fn, ((pci_flags >> 2) & 0x1C) + 0x10, &pci_busaddr); irq = pci_irq_line; pciaddr = pci_busaddr; }#endif if (debug > 2) printk(KERN_INFO "Found %s at PCI address %#lx, IRQ %d.\n", pci_tbl[chip_idx].name, pciaddr, irq); if ((pciaddr & PCI_BASE_ADDRESS_SPACE_IO)) { ioaddr = pciaddr & PCI_BASE_ADDRESS_IO_MASK; if (check_region(ioaddr, pci_tbl[chip_idx].io_size)) continue; } else if ((ioaddr = (long)ioremap(pciaddr & PCI_BASE_ADDRESS_MEM_MASK, pci_tbl[chip_idx].io_size)) == 0) { printk(KERN_INFO "Failed to map PCI address %#lx.\n", pciaddr); continue; } pcibios_read_config_word(pci_bus, pci_device_fn, PCI_COMMAND, &pci_command); new_command = pci_command | (pci_flags & 7); if (pci_command != new_command) { printk(KERN_INFO " The PCI BIOS has not enabled the" " device at %d/%d! Updating PCI command %4.4x->%4.4x.\n", pci_bus, pci_device_fn, pci_command, new_command); pcibios_write_config_word(pci_bus, pci_device_fn, PCI_COMMAND, new_command); } newdev = drv_id->probe1(pdev, initial_device, ioaddr, irq, chip_idx, cards_found); if (newdev && (pci_flags & PCI_COMMAND_MASTER)) { u8 pci_latency; pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, &pci_latency); if (pci_latency < min_pci_latency) { printk(KERN_INFO " PCI latency timer (CFLT) is " "unreasonably low at %d. Setting to %d clocks.\n", pci_latency, min_pci_latency); pcibios_write_config_byte(pci_bus, pci_device_fn, PCI_LATENCY_TIMER, min_pci_latency); } } initial_device = 0; cards_found++; } return cards_found ? 0 : -ENODEV;}#define pci_drv_unregister(drv_id) do { } while(0)#endifstatic void *speedo_found1(struct pci_dev *pdev, void *init_dev, long ioaddr, int irq, int chip_idx, int card_idx){ struct net_device *dev; struct speedo_private *sp; const char *product; int i, option; u16 eeprom[0x100]; int acpi_idle_state = 0; dev = init_etherdev(init_dev, sizeof(struct speedo_private)); if (dev->mem_start > 0) option = dev->mem_start; else if (card_idx >= 0 && options[card_idx] >= 0) option = options[card_idx]; else option = 0; acpi_idle_state = acpi_set_pwr_state(pdev, ACPI_D0); /* Read the station address EEPROM before doing the reset. Nominally his should even be done before accepting the device, but then we wouldn't have a device name with which to report the error. The size test is for 6 bit vs. 8 bit address serial EEPROMs. */ { u16 sum = 0; int j; int read_cmd, ee_size; if ((do_eeprom_cmd(ioaddr, EE_READ_CMD << 24, 27) & 0xffe0000) == 0xffe0000) { ee_size = 0x100; read_cmd = EE_READ_CMD << 24; } else { ee_size = 0x40; read_cmd = EE_READ_CMD << 22; } for (j = 0, i = 0; i < ee_size; i++) { u16 value = do_eeprom_cmd(ioaddr, 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. */ } /* 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); if (eeprom[3] & 0x0100) product = "OEM i82557/i82558 10/100 Ethernet"; else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -