📄 i82586.c
字号:
*(short *)(mem_start + rx_tail + 2) = 0; rx_tail = rx_head; rx_head = next_rx_frame; ack_status(); return (status);}/************************************************************************** TRANSMIT - Transmit a frame ***************************************************************************/static void i82586_transmit( struct nic *nic, const char *d, /* Destination */ unsigned int t, /* Type */ unsigned int s, /* size */ const char *p) /* Packet */{ Address bptr; unsigned short type, z; static unsigned short tx_cmd[11] = { 0x0, /* Tx status */ CmdTx, /* Tx command */ TX_BUF_START+16, /* Next command is a NoOp */ TX_BUF_START+8, /* Data Buffer offset */ 0x8000, /* | with size */ 0xffff, /* No next data buffer */ TX_BUF_START+22, /* + scb_base */ 0x0, /* Buffer address high bits (always zero) */ 0x0, /* Nop status */ CmdNOp, /* Nop command */ TX_BUF_START+16 /* Next is myself */ }; unsigned short *shmem = (short *)mem_start + TX_BUF_START; /* send the packet to destination */ /* adjust some contents */ type = htons(t); if (s < ETH_ZLEN) s = ETH_ZLEN; tx_cmd[4] = (s + ETH_HLEN) | 0x8000; tx_cmd[6] = TX_BUF_START + 22 + scb_base; bptr = mem_start + TX_BUF_START; memcpy((char *)bptr, (char *)tx_cmd, sizeof(tx_cmd)); bptr += sizeof(tx_cmd); memcpy((char *)bptr, d, ETH_ALEN); bptr += ETH_ALEN; memcpy((char *)bptr, nic->node_addr, ETH_ALEN); bptr += ETH_ALEN; memcpy((char *)bptr, (char *)&type, sizeof(type)); bptr += sizeof(type); memcpy((char *)bptr, p, s); /* Change the offset in the IDLELOOP */ *(unsigned short *)(mem_start + IDLELOOP + 4) = TX_BUF_START; /* Wait for transmit completion */ while ( (shmem[0] & 0x2000) == 0) ; /* Change the offset in the IDLELOOP back and change the final loop to point here */ *(unsigned short *)(mem_start + IDLELOOP + 4) = IDLELOOP; *(unsigned short *)(mem_start + TX_BUF_START + 20) = IDLELOOP; ack_status();}/************************************************************************** DISABLE - Turn off ethernet interface ***************************************************************************/static void i82586_disable(struct nic *nic){ unsigned short *shmem = (short *)mem_start;#if 0 /* Flush the Tx and disable Rx. */ shmem[iSCB_CMD>>1] = RX_SUSPEND | CUC_SUSPEND; outb(0, ioaddr + I82586_ATTN);#ifdef INCLUDE_NI5210 outb(0, ioaddr + NI52_RESET);#endif#endif /* 0 */}#ifdef INCLUDE_3C507static int t507_probe1(struct nic *nic, unsigned short ioaddr){ int i; Address size; char mem_config; char if_port; if (inb(ioaddr) != '*' || inb(ioaddr+1) != '3' || inb(ioaddr+2) != 'C' || inb(ioaddr+3) != 'O') return (0); irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; mem_config = inb(ioaddr + MEM_CONFIG); if (mem_config & 0x20) { size = 65536L; mem_start = 0xf00000L + (mem_config & 0x08 ? 0x080000L : (((Address)mem_config & 0x3) << 17)); } else { size = ((((Address)mem_config & 0x3) + 1) << 14); mem_start = 0x0c0000L + (((Address)mem_config & 0x18) << 12); } mem_end = mem_start + size; scb_base = 65536L - size; if_port = inb(ioaddr + ROM_CONFIG) & 0x80; /* Get station address */ outb(0x01, ioaddr + MISC_CTRL); for (i = 0; i < ETH_ALEN; ++i) { nic->node_addr[i] = inb(ioaddr+i); } printf("\n3c507 ioaddr %#hX, IRQ %d, mem [%#X-%#X], %sternal xcvr, addr %!\n", ioaddr, irq, mem_start, mem_end, if_port ? "in" : "ex", nic->node_addr); return (1);}/**************************************************************************PROBE - Look for an adapter, this routine's visible to the outside***************************************************************************/struct nic *t507_probe(struct nic *nic, unsigned short *probe_addrs){ static unsigned char init_ID_done = 0; unsigned short lrs_state = 0xff; static unsigned short io_addrs[] = { 0x300, 0x320, 0x340, 0x280, 0 }; unsigned short *p; int i; if (init_ID_done == 0) { /* Send the ID sequence to the ID_PORT to enable the board */ outb(0x00, ID_PORT); for (i = 0; i < 255; ++i) { outb(lrs_state, ID_PORT); lrs_state <<= 1; if (lrs_state & 0x100) lrs_state ^= 0xe7; } outb(0x00, ID_PORT); init_ID_done = 1; } /* if probe_addrs is 0, then routine can use a hardwired default */ if (probe_addrs == 0) probe_addrs = io_addrs; for (p = probe_addrs; (ioaddr = *p) != 0; ++p) if (t507_probe1(nic, ioaddr)) break; if (ioaddr != 0) { /* point to NIC specific routines */ i82586_reset(nic); nic->reset = i82586_reset; nic->poll = i82586_poll; nic->transmit = i82586_transmit; nic->disable = i82586_disable; return nic; } /* else */ { return 0; }}#endif#ifdef INCLUDE_NI5210static int ni5210_probe2(void){ unsigned short i; unsigned short shmem[10]; /* Fix the ISCP address and base. */ init_words[3] = scb_base; init_words[7] = scb_base; /* Write the words at 0xfff6. */ /* Write the words at 0x0000. */ memcpy((char *)(mem_end - 10), (char *)init_words, 10); memcpy((char *)mem_start, (char *)&init_words[5], sizeof(init_words) - 10); if (*(unsigned short *)mem_start != 1) return (0); outb(0, ioaddr + NI52_RESET); outb(0, ioaddr + I82586_ATTN); udelay(32); i = 50; while ( shmem[iSCB_STATUS>>1] == 0) { if (--i == 0) { printf("i82586 initialisation timed out with status %hX, cmd %hX\n", shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]); break; } } /* Issue channel-attn -- the 82586 won't start. */ outb(0, ioaddr + I82586_ATTN); if (*(unsigned short *)mem_start != 0) return (0); return (1);}static int ni5210_probe1(struct nic *nic){ int i; static Address mem_addrs[] = { 0xc0000, 0xc4000, 0xc8000, 0xcc000, 0xd0000, 0xd4000, 0xd8000, 0xdc000, 0xe0000, 0xe4000, 0xe8000, 0xec000, 0 }; Address *p; if (inb(ioaddr + 6) != 0x0 || inb(ioaddr + 7) != 0x55) return (0); scb_base = -8192; /* assume 8k memory */ for (p = mem_addrs; (mem_start = *p) != 0; ++p) if (mem_end = mem_start + 8192, ni5210_probe2()) break; if (mem_start == 0) return (0); /* Get station address */ for (i = 0; i < ETH_ALEN; ++i) { nic->node_addr[i] = inb(ioaddr+i); } printf("\nNI5210 ioaddr %#hX, mem [%#X-%#X], addr %!\n", ioaddr, mem_start, mem_end, nic->node_addr); return (1);}struct nic *ni5210_probe(struct nic *nic, unsigned short *probe_addrs){ /* missing entries are addresses usually already used */ static unsigned short io_addrs[] = { 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230, 0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270, /*Par*/ 0x280, 0x288, 0x290, 0x298, 0x2A0, 0x2A8, 0x2B0, 0x2B8, 0x2C0, 0x2C8, 0x2D0, 0x2D8, 0x2E0, 0x2E8, 0x2F0, /*Ser*/ 0x300, 0x308, 0x310, 0x318, 0x320, 0x328, 0x330, 0x338, 0x340, 0x348, 0x350, 0x358, 0x360, 0x368, 0x370, /*Par*/ 0x380, 0x388, 0x390, 0x398, 0x3A0, 0x3A8, /*Vid,Par*/ 0x3C0, 0x3C8, 0x3D0, 0x3D8, 0x3E0, 0x3E8, /*Ser*/ 0x0 }; unsigned short *p; int i; /* if probe_addrs is 0, then routine can use a hardwired default */ if (probe_addrs == 0) probe_addrs = io_addrs; for (p = probe_addrs; (ioaddr = *p) != 0; ++p) if (ni5210_probe1(nic)) break; if (ioaddr != 0) { /* point to NIC specific routines */ i82586_reset(nic); nic->reset = i82586_reset; nic->poll = i82586_poll; nic->transmit = i82586_transmit; nic->disable = i82586_disable; return nic; } /* else */ { return 0; }}#endif#ifdef INCLUDE_EXOS205/* * Code to download to I186 in EXOS205 */static unsigned char exos_i186_init[] ={0x08,0x00,0x14,0x00,0x00,0x00,0xaa,0xfa,0x33,0xc0,0xba,0xfe,0xff,0xef,0xb8,0xf8,0xff,0xe7,0xa0,0xb8,0x7c,0x00,0xe7,0xa4,0xb8,0xbc,0x80,0xe7,0xa8,0x8c,0xc8,0x8e,0xd8,0xbb,0x2f,0x0e,0xc6,0x07,0xa5,0x33,0xc9,0xeb,0x00,0xeb,0x00,0xeb,0x00,0xe2,0xf8,0xbe,0x2c,0x0e,0xba,0x02,0x05,0x33,0xdb,0xb9,0x03,0x00,0xec,0x24,0x0f,0x8a,0xe0,0x02,0xd8,0x42,0x42,0xec,0x02,0xd8,0xd0,0xe0,0xd0,0xe0,0xd0,0xe0,0xd0,0xe0,0x0a,0xc4,0x88,0x04,0x42,0x42,0x46,0xe2,0xe3,0x8a,0xe3,0xd0,0xec,0xd0,0xec,0xd0,0xec,0xd0,0xec,0x80,0xe3,0x0f,0x02,0xe3,0x80,0xf4,0x05,0xec,0x3a,0xe0,0x74,0x05,0xc6,0x04,0x5a,0xeb,0xfe,0xc6,0x04,0x55,0x33,0xc0,0x8e,0xd8,0xbe,0x38,0x00,0xc7,0x04,0xce,0x0e,0x46,0x46,0xc7,0x04,0x00,0xff,0xfb,0xba,0x3c,0x00,0xb8,0x03,0x00,0xef,0x33,0xdb,0x33,0xc9,0xbd,0x04,0x0f,0x90,0x90,0x90,0x90,0xe2,0xfa,0x43,0x2e,0x89,0x5e,0x00,0xeb,0xf3,0x52,0xba,0x00,0x06,0xef,0x50,0x53,0x55,0xbd,0xf8,0x0e,0x2e,0x8b,0x5e,0x00,0x43,0x2e,0x89,0x5e,0x00,0xba,0x22,0x00,0xb8,0x00,0x80,0xef,0x5d,0x5b,0x58,0x5a,0xcf,0x49,0x4e,0x54,0x52,0x20,0x63,0x6e,0x74,0x2d,0x3e,0x00,0x00,0x4c,0x4f,0x4f,0x50,0x20,0x63,0x6e,0x74,0x2d,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xea,0x30,0x0e,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,00};/* These offsets are from the end of the i186 download code */#define OFFSET_SEMA 0x1D1#define OFFSET_ADDR 0x1D7static int exos205_probe2(void){ unsigned short i; unsigned short shmem[10]; /* Fix the ISCP address and base. */ init_words[3] = scb_base; init_words[7] = scb_base; /* Write the words at 0xfff6. */ /* Write the words at 0x0000. */ memcpy((char *)(mem_end - 10), (char *)init_words, 10); memcpy((char *)mem_start, (char *)&init_words[5], sizeof(init_words) - 10); if (*(unsigned short *)mem_start != 1) return (0); outb(0, ioaddr + EXOS205_RESET); outb(0, ioaddr + I82586_ATTN); i = 50; while ( shmem[iSCB_STATUS>>1] == 0) { if (--i == 0) { printf("i82586 initialisation timed out with status %hX, cmd %hX\n", shmem[iSCB_STATUS>>1], shmem[iSCB_CMD>>1]); break; } } /* Issue channel-attn -- the 82586 won't start. */ outb(0, ioaddr + I82586_ATTN); if (*(unsigned short *)mem_start != 0) return (0); return (1);}static int exos205_probe1(struct nic *nic){ int i; /* If you know the other addresses please let me know */ static Address mem_addrs[] = { 0xcc000, 0 }; Address *p; scb_base = -16384; /* assume 8k memory */ for (p = mem_addrs; (mem_start = *p) != 0; ++p) if (mem_end = mem_start + 16384, exos205_probe2()) break; if (mem_start == 0) return (0); /* Get station address */ for (i = 0; i < ETH_ALEN; ++i) { nic->node_addr[i] = inb(ioaddr+i); } printf("\nEXOS205 ioaddr %#hX, mem [%#X-%#X], addr %!\n", ioaddr, mem_start, mem_end, nic->node_addr); return (1);}struct nic *exos205_probe(struct nic *nic, unsigned short *probe_addrs){ /* If you know the other addresses, please let me know */ static unsigned short io_addrs[] = { 0x310, 0x0 }; unsigned short *p; int i; /* if probe_addrs is 0, then routine can use a hardwired default */ if (probe_addrs == 0) probe_addrs = io_addrs; for (p = probe_addrs; (ioaddr = *p) != 0; ++p) if (exos205_probe1(nic)) break; if (ioaddr != 0) { /* point to NIC specific routines */ i82586_reset(nic); nic->reset = i82586_reset; nic->poll = i82586_poll; nic->transmit = i82586_transmit; nic->disable = i82586_disable; return nic; } /* else */ { return 0; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -