📄 eepro.c
字号:
case 4: dev->irq = 9; break; case 5: dev->irq = 10; break; case 6: dev->irq = 11; break; case 7: dev->irq = 12; break; } } else if (dev->irq == 2) dev->irq = 9; if (dev->irq > 2) { printk(", IRQ %d, %s.\n", dev->irq, ifmap[dev->if_port]); if (request_irq(dev->irq, &eepro_interrupt, 0, "eepro", NULL)) { printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; } } else printk(", %s.\n", ifmap[dev->if_port]); if ((dev->mem_start & 0xf) > 0) /* I don't know if this is */ net_debug = dev->mem_start & 7; /* still useful or not */ if (net_debug > 3) { i = read_eeprom(ioaddr, 5); if (i & 0x2000) /* bit 13 of EEPROM word 5 */ printk("%s: Concurrent Processing is enabled but not used!\n", dev->name); } if (net_debug) printk(version); /* Grab the region so we can find another board if autoIRQ fails. */ request_region(ioaddr, EEPRO_IO_EXTENT, "eepro"); /* Initialize the device structure */ dev->priv = kmalloc(sizeof(struct eepro_local), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; memset(dev->priv, 0, sizeof(struct eepro_local)); dev->open = eepro_open; dev->stop = eepro_close; dev->hard_start_xmit = eepro_send_packet; dev->get_stats = eepro_get_stats; dev->set_multicast_list = &set_multicast_list; /* Fill in the fields of the device structure with ethernet generic values */ ether_setup(dev); outb(RESET_CMD, ioaddr); /* RESET the 82595 */ return 0; } else return ENODEV; } else if (net_debug > 3) printk ("EtherExpress Pro probed failed!\n"); return ENODEV;}/* Open/initialize the board. This is called (in the current kernel) sometime after booting when the 'ifconfig' program is run. This routine should set everything up anew at each open, even registers that "should" only need to be set once at boot, so that there is non-reboot way to recover if something goes wrong. */static char irqrmap[] = {-1,-1,0,1,-1,2,-1,-1,-1,0,3,4,-1,-1,-1,-1};static char irqrmap2[] = {-1,-1,4,0,1,2,-1,3,-1,4,5,6,7,-1,-1,-1};static int eepro_grab_irq(struct device *dev){ int irqlist[] = { 3, 4, 5, 7, 9, 10, 11, 12 }; int *irqp = irqlist, temp_reg, ioaddr = dev->base_addr; outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ /* Enable the interrupt line. */ temp_reg = inb(ioaddr + REG1); outb(temp_reg | INT_ENABLE, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */ /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); /* Let EXEC event to interrupt */ outb(ALL_MASK & ~(EXEC_MASK), ioaddr + INT_MASK_REG); do { outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ temp_reg = inb(ioaddr + INT_NO_REG); outb((temp_reg & 0xf8) | irqrmap[*irqp], ioaddr + INT_NO_REG); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ if (request_irq (*irqp, NULL, 0, "bogus", NULL) != EBUSY) { /* Twinkle the interrupt, and check if it's seen */ autoirq_setup(0); outb(DIAGNOSE_CMD, ioaddr); /* RESET the 82595 */ if (*irqp == autoirq_report(2) && /* It's a good IRQ line */ (request_irq(dev->irq = *irqp, &eepro_interrupt, 0, "eepro", NULL) == 0)) break; /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); } } while (*++irqp); outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */ /* Disable the physical interrupt line. */ temp_reg = inb(ioaddr + REG1); outb(temp_reg & 0x7f, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ /* Mask all the interrupts. */ outb(ALL_MASK, ioaddr + INT_MASK_REG); /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); return dev->irq;}static inteepro_open(struct device *dev){ unsigned short temp_reg, old8, old9; int i, ioaddr = dev->base_addr, rcv_ram = dev->mem_end; struct eepro_local *lp = (struct eepro_local *)dev->priv; if (net_debug > 3) printk("eepro: entering eepro_open routine.\n"); if ((dev->dev_addr[0] == SA_ADDR0 && dev->dev_addr[1] == SA_ADDR1 && dev->dev_addr[2] == SA_ADDR2)&& (dev->dev_addr[3] != SA3_ADDR3)) { lp->eepro = 1; if (net_debug > 3) printk("p->eepro = 1;\n"); } /* Yes, an Intel EtherExpress Pro/10 */ else if ((dev->dev_addr[0] == SA2_ADDR0 && dev->dev_addr[1] == SA2_ADDR1 && dev->dev_addr[2] == SA2_ADDR2)|| (dev->dev_addr[0] == SA3_ADDR0 && dev->dev_addr[1] == SA3_ADDR1 && dev->dev_addr[2] == SA3_ADDR2 && dev->dev_addr[3] == SA3_ADDR3)) { lp->eepro = 2; /* Yes, an Intel EtherExpress Pro/10+ */ if (net_debug > 3) printk("p->eepro = 2;\n"); } else lp->eepro = 0; /* No, it is a generic 82585 lan card */ /* Get the interrupt vector for the 82595 */ if (dev->irq < 2 && eepro_grab_irq(dev) == 0) { printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); return -EAGAIN; } if (irq2dev_map[dev->irq] != 0 || (irq2dev_map[dev->irq] = dev) == 0) return -EAGAIN; /* Initialize the 82595. */ outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ temp_reg = inb(ioaddr + EEPROM_REG); lp->stepping = temp_reg >> 5; /* Get the stepping number of the 595 */ if (net_debug > 3) printk("The stepping of the 82595 is %d\n", lp->stepping); if (temp_reg & 0x10) /* Check the TurnOff Enable bit */ outb(temp_reg & 0xef, ioaddr + EEPROM_REG); for (i=0; i < 6; i++) outb(dev->dev_addr[i] , ioaddr + I_ADD_REG0 + i); temp_reg = inb(ioaddr + REG1); /* Setup Transmit Chaining */ outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop /* and discard bad RCV frames */ | RCV_Discard_BadFrame, ioaddr + REG1); temp_reg = inb(ioaddr + REG2); /* Match broadcast */ outb(temp_reg | 0x14, ioaddr + REG2); temp_reg = inb(ioaddr + REG3); outb(temp_reg & 0x3f, ioaddr + REG3); /* clear test mode */ /* Set the receiving mode */ outb(BANK1_SELECT, ioaddr); /* be CAREFUL, BANK 1 now */ /* Set the interrupt vector */ temp_reg = inb(ioaddr + INT_NO_REG); if (lp->eepro == 2) outb((temp_reg & 0xf8) | irqrmap2[dev->irq], ioaddr + INT_NO_REG); else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); temp_reg = inb(ioaddr + INT_NO_REG); if (lp->eepro == 2) outb((temp_reg & 0xf0) | irqrmap2[dev->irq] | 0x08,ioaddr+INT_NO_REG); else outb((temp_reg & 0xf8) | irqrmap[dev->irq], ioaddr + INT_NO_REG); if (net_debug > 3) printk("eepro_open: content of INT Reg is %x\n", temp_reg); /* Initialize the RCV and XMT upper and lower limits */ outb(RCV_LOWER_LIMIT, ioaddr + RCV_LOWER_LIMIT_REG); outb(RCV_UPPER_LIMIT, ioaddr + RCV_UPPER_LIMIT_REG); outb(XMT_LOWER_LIMIT, ioaddr + XMT_LOWER_LIMIT_REG); outb(XMT_UPPER_LIMIT, ioaddr + XMT_UPPER_LIMIT_REG); /* Enable the interrupt line. */ temp_reg = inb(ioaddr + REG1); outb(temp_reg | INT_ENABLE, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ /* Let RX and TX events to interrupt */ outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); /* Initialize RCV */ outw(RCV_LOWER_LIMIT << 8, ioaddr + RCV_BAR); lp->rx_start = (RCV_LOWER_LIMIT << 8) ; outw((RCV_UPPER_LIMIT << 8) | 0xfe, ioaddr + RCV_STOP); /* Initialize XMT */ outw(XMT_LOWER_LIMIT << 8, ioaddr + XMT_BAR); /* Check for the i82595TX and i82595FX */ old8 = inb(ioaddr + 8); outb(~old8, ioaddr + 8); if ((temp_reg = inb(ioaddr + 8)) == old8) { if (net_debug > 3) printk("i82595 detected!\n"); lp->version = LAN595; } else { lp->version = LAN595TX; outb(old8, ioaddr + 8); old9 = inb(ioaddr + 9); outb(~old9, ioaddr + 9); if (((temp_reg = inb(ioaddr + 9)) == ( (~old9)&0xff) )) { enum iftype { AUI=0, BNC=1, TPE=2 }; if (net_debug > 3) { printk("temp_reg: %#x ~old9: %#x\n",temp_reg, ~old9); printk("i82595FX detected!\n"); } lp->version = LAN595FX; outb(old9, ioaddr + 9); if (dev->if_port != TPE) { /* Hopefully, this will fix the problem of using Pentiums and pro/10 w/ BNC. */ outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */ temp_reg = inb(ioaddr + REG13); /* disable the full duplex mode since it is not applicable with the 10Base2 cable. */ outb(temp_reg & ~(FDX | A_N_ENABLE), REG13); outb(BANK0_SELECT, ioaddr); /* be CAREFUL, BANK 0 now */ } } else if (net_debug > 3) { printk("temp_reg: %#x ~old9: %#x\n",temp_reg,((~old9)&0xff)); printk("i82595TX detected!\n"); } } outb(SEL_RESET_CMD, ioaddr); /* We are supposed to wait for 2 us after a SEL_RESET */ SLOW_DOWN_IO; SLOW_DOWN_IO; lp->tx_start = lp->tx_end = XMT_LOWER_LIMIT << 8; /* or = RCV_RAM */ lp->tx_last = 0; dev->tbusy = 0; dev->interrupt = 0; dev->start = 1; if (net_debug > 3) printk("eepro: exiting eepro_open routine.\n"); outb(RCV_ENABLE_CMD, ioaddr); MOD_INC_USE_COUNT; return 0;}static inteepro_send_packet(struct sk_buff *skb, struct device *dev){ struct eepro_local *lp = (struct eepro_local *)dev->priv; int ioaddr = dev->base_addr; int rcv_ram = dev->mem_end; if (net_debug > 5) printk("eepro: entering eepro_send_packet routine.\n"); if (dev->tbusy) { /* If we get here, some higher level has decided we are broken. There should really be a "kick me" function call instead. */ int tickssofar = jiffies - dev->trans_start; if (tickssofar < 40) return 1; if (net_debug > 1) printk("%s: transmit timed out, %s?\n", dev->name, "network cable problem"); lp->stats.tx_errors++; /* Try to restart the adaptor. */ outb(SEL_RESET_CMD, ioaddr); /* We are supposed to wait for 2 us after a SEL_RESET */ SLOW_DOWN_IO; SLOW_DOWN_IO; /* Do I also need to flush the transmit buffers here? YES? */ lp->tx_start = lp->tx_end = rcv_ram; lp->tx_last = 0; dev->tbusy=0; dev->trans_start = jiffies; outb(RCV_ENABLE_CMD, ioaddr); } /* If some higher layer thinks we've missed an tx-done interrupt we are passed NULL. Caution: dev_tint() handles the cli()/sti() itself. */ if (skb == NULL) { dev_tint(dev); return 0; } /* Block a timer-based transmit from overlapping. */ if (set_bit(0, (void*)&dev->tbusy) != 0) printk("%s: Transmitter access conflict.\n", dev->name); else { short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; unsigned char *buf = skb->data; hardware_send_packet(dev, buf, length); dev->trans_start = jiffies; } dev_kfree_skb (skb, FREE_WRITE); /* You might need to clean up and record Tx statistics here. */ /* lp->stats.tx_aborted_errors++; */ if (net_debug > 5) printk("eepro: exiting eepro_send_packet routine.\n"); return 0;}/* The typical workload of the driver: Handle the network interface interrupts. */static voideepro_interrupt(int irq, void *dev_id, struct pt_regs * regs){ struct device *dev = (struct device *)(irq2dev_map[irq]); int ioaddr, status, boguscount = 20; if (net_debug > 5) printk("eepro: entering eepro_interrupt routine.\n"); if (dev == NULL) { printk ("eepro_interrupt(): irq %d for unknown device.\n", irq); return; } dev->interrupt = 1; ioaddr = dev->base_addr; do { status = inb(ioaddr + STATUS_REG); if (status & RX_INT) { if (net_debug > 4) printk("eepro: packet received interrupt.\n"); /* Acknowledge the RX_INT */ outb(RX_INT, ioaddr + STATUS_REG); /* Get the received packets */ eepro_rx(dev); } else if (status & TX_INT) { if (net_debug > 4) printk("eepro: packet transmit interrupt.\n"); /* Acknowledge the TX_INT */ outb(TX_INT, ioaddr + STATUS_REG); /* Process the status of transmitted packets */ eepro_transmit_interrupt(dev); } } while ((boguscount-- > 0) && (status & 0x06)); dev->interrupt = 0; if (net_debug > 5) printk("eepro: exiting eepro_interrupt routine.\n"); return;}static inteepro_close(struct device *dev){ struct eepro_local *lp = (struct eepro_local *)dev->priv; int ioaddr = dev->base_addr; int rcv_ram = dev->mem_end; short temp_reg; dev->tbusy = 1; dev->start = 0; outb(BANK1_SELECT, ioaddr); /* Switch back to Bank 1 */ /* Disable the physical interrupt line. */ temp_reg = inb(ioaddr + REG1); outb(temp_reg & 0x7f, ioaddr + REG1); outb(BANK0_SELECT, ioaddr); /* Switch back to Bank 0 */ /* Flush the Tx and disable Rx. */ outb(STOP_RCV_CMD, ioaddr); lp->tx_start = lp->tx_end = rcv_ram ; lp->tx_last = 0; /* Mask all the interrupts. */ outb(ALL_MASK, ioaddr + INT_MASK_REG); /* clear all interrupts */ outb(ALL_MASK, ioaddr + STATUS_REG); /* Reset the 82595 */ outb(RESET_CMD, ioaddr); /* release the interrupt */ free_irq(dev->irq, NULL); irq2dev_map[dev->irq] = 0; /* Update the statistics here. What statistics? */ /* We are supposed to wait for 200 us after a RESET */ SLOW_DOWN_IO; SLOW_DOWN_IO; /* May not be enough? */ MOD_DEC_USE_COUNT; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -