📄 eepro100.c
字号:
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,};#define CONFIG_DATA_SIZE 22struct 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. */#define TX_DESCR_BUF_OFFSET 16 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. */ /* the structure must have space for at least CONFIG_DATA_SIZE starting * from tx_desc_addr field */};/* Multicast filter setting block. --SAW */struct speedo_mc_block { struct speedo_mc_block *next; unsigned int tx; dma_addr_t frame_dma; unsigned int len; struct descriptor frame __attribute__ ((__aligned__(16)));};/* 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;};enum Rx_ring_state_bits { RrNoMem=1, RrPostponed=2, RrNoResources=4, RrOOMReported=8,};/* Do not change the position (alignment) of the first few elements! The later elements are grouped for cache locality. Unfortunately, all the positions have been shifted since there. A new re-alignment is required. 2000/03/06 SAW */struct speedo_private { struct TxFD *tx_ring; /* 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]; /* Mapped addresses of the rings. */ dma_addr_t tx_ring_dma;#define TX_RING_ELEM_DMA(sp, n) ((sp)->tx_ring_dma + (n)*sizeof(struct TxFD)) dma_addr_t rx_ring_dma[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. */ struct RxFD *last_rxf; /* Last filled RX buffer. */ dma_addr_t last_rxf_dma; unsigned int cur_rx, dirty_rx; /* The next free ring entry */ long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */ struct net_device_stats stats; struct speedo_stats *lstats; dma_addr_t lstats_dma; int chip_id; struct pci_dev *pdev; struct timer_list timer; /* Media selection timer. */ struct speedo_mc_block *mc_setup_head;/* Multicast setup frame list head. */ struct speedo_mc_block *mc_setup_tail;/* Multicast setup frame list tail. */ long in_interrupt; /* Word-aligned dev->interrupt */ unsigned char acpi_pwr; signed 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 char default_port:8; /* Last dev->if_port value. */ unsigned char rx_ring_state; /* RX ring status flags. */ unsigned short phy[2]; /* PHY media interfaces available. */ unsigned short advertising; /* Current PHY advertised caps. */ unsigned short partner; /* Link partner caps. */#ifdef CONFIG_PM u32 pm_state[16];#endif};/* 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. */static const char i82557_config_cmd[CONFIG_DATA_SIZE] = { 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, };static const char i82558_config_cmd[CONFIG_DATA_SIZE] = { 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, 0x84, /* Disable FC */ 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 eepro100_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);static void eepro100_remove_one (struct pci_dev *pdev);#ifdef CONFIG_PMstatic int eepro100_suspend (struct pci_dev *pdev, u32 state);static int eepro100_resume (struct pci_dev *pdev);#endifstatic 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 void speedo_refill_rx_buffers(struct net_device *dev, int force);static int speedo_rx(struct net_device *dev);static void speedo_tx_buffer_gc(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);static void speedo_show_state(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};#endifstatic int __devinit eepro100_init_one (struct pci_dev *pdev, const struct pci_device_id *ent){ unsigned long ioaddr; int irq; int acpi_idle_state = 0, pm; static int cards_found /* = 0 */; static int did_version /* = 0 */; /* Already printed version info. */ if (speedo_debug > 0 && did_version++ == 0) printk(version); if (!request_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1), "eepro100")) { printk (KERN_ERR "eepro100: cannot reserve I/O ports\n"); goto err_out_none; } if (!request_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0), "eepro100")) { printk (KERN_ERR "eepro100: cannot reserve MMIO region\n"); goto err_out_free_pio_region; } irq = pdev->irq;#ifdef USE_IO ioaddr = pci_resource_start(pdev, 1); if (speedo_debug > 2) printk("Found Intel i82557 PCI Speedo at I/O %#lx, IRQ %d.\n", ioaddr, irq);#else ioaddr = (unsigned long)ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!ioaddr) { printk (KERN_ERR "eepro100: cannot remap MMIO region %lx @ %lx\n", pci_resource_len(pdev, 0), pci_resource_start(pdev, 0)); goto err_out_free_mmio_region; } if (speedo_debug > 2) printk("Found Intel i82557 PCI Speedo, MMIO at %#lx, IRQ %d.\n", pci_resource_start(pdev, 0), irq);#endif /* save power state b4 pci_enable_device overwrites it */ pm = pci_find_capability(pdev, PCI_CAP_ID_PM); if (pm) { u16 pwr_command; pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command); acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK; } if (pci_enable_device(pdev)) goto err_out_free_mmio_region; pci_set_master(pdev); if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0) cards_found++; else goto err_out_iounmap; return 0;err_out_iounmap: ;#ifndef USE_IO iounmap ((void *)ioaddr);#endiferr_out_free_mmio_region: release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));err_out_free_pio_region: release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));err_out_none: return -ENODEV;}static int speedo_found1(struct pci_dev *pdev, long ioaddr, int card_idx, int acpi_idle_state){ struct net_device *dev; struct speedo_private *sp; const char *product; int i, option; u16 eeprom[0x100]; int size; void *tx_ring_space; dma_addr_t tx_ring_dma; size = TX_RING_SIZE * sizeof(struct TxFD) + sizeof(struct speedo_stats); tx_ring_space = pci_alloc_consistent(pdev, size, &tx_ring_dma); if (tx_ring_space == NULL) return -1; dev = init_etherdev(NULL, sizeof(struct speedo_private)); if (dev == NULL) { printk(KERN_ERR "eepro100: Could not allocate ethernet device.\n"); pci_free_consistent(pdev, size, tx_ring_space, tx_ring_dma); return -1; } 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; /* 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. */ { unsigned long iobase; int read_cmd, ee_size; u16 sum; int j; /* Use IO only to avoid postponed writes and satisfy EEPROM timing requirements. */ iobase = pci_resource_start(pdev, 1); if ((do_eeprom_cmd(iobase, 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, 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); udelay(10); if (eeprom[3] & 0x0100) product = "OEM i82557/i82558 10/100 Ethernet"; else product = pdev->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. */ volatile s32 *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) 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -