📄 eepro.c
字号:
***************************************************************************/static void eepro_reset(struct nic *nic){ int temp_reg, i; /* put the card in its initial state */ eepro_sw2bank2(ioaddr); /* be careful, bank2 now */ temp_reg = inb(ioaddr + eeprom_reg);#ifdef DEBUG printf("Stepping %d\n", temp_reg >> 5);#endif if (temp_reg & 0x10) /* check the TurnOff Enable bit */ outb(temp_reg & 0xEF, ioaddr + eeprom_reg); for (i = 0; i < ETH_ALEN; i++) /* fill the MAC address */ outb(nic->node_addr[i], ioaddr + I_ADD_REG0 + i); temp_reg = inb(ioaddr + REG1); /* setup Transmit Chaining and discard bad RCV frames */ outb(temp_reg | XMT_Chain_Int | XMT_Chain_ErrStop | 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 */ eepro_sw2bank1(ioaddr); /* be careful, bank1 now */ /* initialise 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); eepro_sw2bank0(ioaddr); /* Switch back to bank 0 */ eepro_clear_int(ioaddr); /* Initialise RCV */ outw(rx_start = (RCV_LOWER_LIMIT << 8), ioaddr + RCV_BAR); outw(((RCV_UPPER_LIMIT << 8) | 0xFE), ioaddr + RCV_STOP); /* Intialise XMT */ outw((XMT_LOWER_LIMIT << 8), ioaddr + xmt_bar); eepro_sel_reset(ioaddr); tx_start = tx_end = (XMT_LOWER_LIMIT << 8); tx_last = 0; eepro_en_rx(ioaddr);}/**************************************************************************POLL - Wait for a frame***************************************************************************/static int eepro_poll(struct nic *nic){ int i; unsigned int rcv_car = rx_start; unsigned int rcv_event, rcv_status, rcv_next_frame, rcv_size; /* return true if there's an ethernet packet ready to read */ /* nic->packet should contain data on return */ /* nic->packetlen should contain length of data */#if 0 if ((inb(ioaddr + STATUS_REG) & 0x40) == 0) return (0); outb(0x40, ioaddr + STATUS_REG);#endif outw(rcv_car, ioaddr + HOST_ADDRESS_REG); rcv_event = inw(ioaddr + IO_PORT); if (rcv_event != RCV_DONE) return (0); rcv_status = inw(ioaddr + IO_PORT); rcv_next_frame = inw(ioaddr + IO_PORT); rcv_size = inw(ioaddr + IO_PORT);#if 0 printf("%hX %hX %d %hhX\n", rcv_status, rcv_next_frame, rcv_size, inb(ioaddr + STATUS_REG));#endif if ((rcv_status & (RX_OK|RX_ERROR)) != RX_OK) { printf("Receive error %hX\n", rcv_status); return (0); } rcv_size &= 0x3FFF; insw(ioaddr + IO_PORT, nic->packet, ((rcv_size + 3) >> 1));#if 0 for (i = 0; i < 48; i++) { printf("%hhX", nic->packet[i]); putchar(i % 16 == 15 ? '\n' : ' '); }#endif nic->packetlen = rcv_size; rcv_car = rx_start + RCV_HEADER + rcv_size; rx_start = rcv_next_frame; if (rcv_car == 0) rcv_car = ((RCV_UPPER_LIMIT << 8) | 0xff); outw(rcv_car - 1, ioaddr + RCV_STOP); return (1);}/**************************************************************************TRANSMIT - Transmit a frame***************************************************************************/static void eepro_transmit( struct nic *nic, const char *d, /* Destination */ unsigned int t, /* Type */ unsigned int s, /* size */ const char *p) /* Packet */{ unsigned int status, tx_available, last, end, length; unsigned short type; int boguscount = 20; length = s + ETH_HLEN; if (tx_end > tx_start) tx_available = XMT_RAM - (tx_end - tx_start); else if (tx_end < tx_start) tx_available = tx_start - tx_end; else tx_available = XMT_RAM; last = tx_end; end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; if (end >= (XMT_UPPER_LIMIT << 8)) { last = (XMT_LOWER_LIMIT << 8); end = last + (((length + 3) >> 1) << 1) + XMT_HEADER; } outw(last, ioaddr + HOST_ADDRESS_REG); outw(XMT_CMD, ioaddr + IO_PORT); outw(0, ioaddr + IO_PORT); outw(end, ioaddr + IO_PORT); outw(length, ioaddr + IO_PORT); outsw(ioaddr + IO_PORT, d, ETH_ALEN / 2); outsw(ioaddr + IO_PORT, nic->node_addr, ETH_ALEN / 2); type = htons(t); outsw(ioaddr + IO_PORT, &type, sizeof(type) / 2); outsw(ioaddr + IO_PORT, p, (s + 3) >> 1); /* A dummy read to flush the DRAM write pipeline */ status = inw(ioaddr + IO_PORT); outw(last, ioaddr + xmt_bar); outb(XMT_CMD, ioaddr); tx_start = last; tx_last = last; tx_end = end;#if 0 printf("%d %d\n", tx_start, tx_end);#endif while (boguscount > 0) { if (((status = inw(ioaddr + IO_PORT)) & TX_DONE_BIT) == 0) { udelay(40); boguscount--; continue; }#if DEBUG if ((status & 0x2000) == 0) printf("Transmit status %hX\n", status);#endif }}/**************************************************************************DISABLE - Turn off ethernet interface***************************************************************************/static void eepro_disable(struct nic *nic){ eepro_sw2bank0(ioaddr); /* Switch to bank 0 */ /* Flush the Tx and disable Rx */ outb(STOP_RCV_CMD, ioaddr); tx_start = tx_end = (XMT_LOWER_LIMIT << 8); tx_last = 0; /* Reset the 82595 */ eepro_full_reset(ioaddr);}static int read_eeprom(int location){ int i; unsigned short retval = 0; int ee_addr = ioaddr + eeprom_reg; int read_cmd = location | EE_READ_CMD; int ctrl_val = EECS; if (eepro == LAN595FX_10ISA) { eepro_sw2bank1(ioaddr); outb(0x00, ioaddr + STATUS_REG); } eepro_sw2bank2(ioaddr); outb(ctrl_val, ee_addr); /* shift the read command bits out */ for (i = 8; i >= 0; i--) { short outval = (read_cmd & (1 << i)) ? ctrl_val | EEDI : ctrl_val; outb(outval, ee_addr); outb(outval | EESK, ee_addr); /* EEPROM clock tick */ eeprom_delay(); outb(outval, ee_addr); /* finish EEPROM clock tick */ eeprom_delay(); } outb(ctrl_val, ee_addr); for (i = 16; i > 0; i--) { outb(ctrl_val | EESK, ee_addr); eeprom_delay(); retval = (retval << 1) | ((inb(ee_addr) & EEDO) ? 1 : 0); outb(ctrl_val, ee_addr); eeprom_delay(); } /* terminate the EEPROM access */ ctrl_val &= ~EECS; outb(ctrl_val | EESK, ee_addr); eeprom_delay(); outb(ctrl_val, ee_addr); eeprom_delay(); eepro_sw2bank0(ioaddr); return (retval);}static int eepro_probe1(struct nic *nic){ int i, id, counter, l_eepro = 0; union { unsigned char caddr[ETH_ALEN]; unsigned short saddr[ETH_ALEN/2]; } station_addr; char *name; id = inb(ioaddr + ID_REG); if ((id & ID_REG_MASK) != ID_REG_SIG) return (0); counter = id & R_ROBIN_BITS; if (((id = inb(ioaddr + ID_REG)) & R_ROBIN_BITS) != (counter + 0x40)) return (0); /* yes the 82595 has been found */ station_addr.saddr[2] = read_eeprom(2); if (station_addr.saddr[2] == 0x0000 || station_addr.saddr[2] == 0xFFFF) { l_eepro = 3; eepro = LAN595FX_10ISA; eeprom_reg= EEPROM_REG_10; rcv_start = RCV_START_10; xmt_lower_limit_reg = XMT_LOWER_LIMIT_REG_10; xmt_upper_limit_reg = XMT_UPPER_LIMIT_REG_10; station_addr.saddr[2] = read_eeprom(2); } station_addr.saddr[1] = read_eeprom(3); station_addr.saddr[0] = read_eeprom(4); if (l_eepro) name = "Intel EtherExpress 10 ISA"; else if (read_eeprom(7) == ee_FX_INT2IRQ) { name = "Intel EtherExpress Pro/10+ ISA"; l_eepro = 2; } else if (station_addr.saddr[0] == SA_ADDR1) { name = "Intel EtherExpress Pro/10 ISA"; l_eepro = 1; } else { l_eepro = 0; name = "Intel 82595-based LAN card"; } station_addr.saddr[0] = swap16(station_addr.saddr[0]); station_addr.saddr[1] = swap16(station_addr.saddr[1]); station_addr.saddr[2] = swap16(station_addr.saddr[2]); for (i = 0; i < ETH_ALEN; i++) { nic->node_addr[i] = station_addr.caddr[i]; } printf("\n%s ioaddr %#hX, addr %!", name, ioaddr, nic->node_addr); mem_start = RCV_LOWER_LIMIT << 8; if ((mem_end & 0x3F) < 3 || (mem_end & 0x3F) > 29) mem_end = RCV_UPPER_LIMIT << 8; else { mem_end = mem_end * 1024 + (RCV_LOWER_LIMIT << 8); rcv_ram = mem_end - (RCV_LOWER_LIMIT << 8); } printf(", Rx mem %dK, if %s\n", (mem_end - mem_start) >> 10, GetBit(read_eeprom(5), ee_BNC_TPE) ? "BNC" : "TP"); return (1);}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/struct nic *eepro_probe(struct nic *nic, unsigned short *probe_addrs){ unsigned short *p; /* same probe list as the Linux driver */ static unsigned short ioaddrs[] = { 0x300, 0x210, 0x240, 0x280, 0x2C0, 0x200, 0x320, 0x340, 0x360, 0}; if (probe_addrs == 0 || probe_addrs[0] == 0) probe_addrs = ioaddrs; for (p = probe_addrs; (ioaddr = *p) != 0; p++) { if (eepro_probe1(nic)) break; } if (*p == 0) return (0); eepro_reset(nic); /* point to NIC specific routines */ nic->reset = eepro_reset; nic->poll = eepro_poll; nic->transmit = eepro_transmit; nic->disable = eepro_disable; return (nic);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -