📄 ns8390.c
字号:
}/**************************************************************************ETH_RESET - Reset adapter**************************************************************************/eth_reset(){ int i; if (eth_flags & FLAG_790) outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_STP); else outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STP); if (eth_flags & FLAG_16BIT) outb(eth_nic_base+D8390_P0_DCR, 0x49); else outb(eth_nic_base+D8390_P0_DCR, 0x48); outb(eth_nic_base+D8390_P0_RBCR0, 0); outb(eth_nic_base+D8390_P0_RBCR1, 0); outb(eth_nic_base+D8390_P0_RCR, 4); /* allow broadcast frames */ outb(eth_nic_base+D8390_P0_TCR, 2); outb(eth_nic_base+D8390_P0_TPSR, eth_tx_start); outb(eth_nic_base+D8390_P0_PSTART, eth_tx_start + D8390_TXBUF_SIZE); if (eth_flags & FLAG_790) outb(eth_nic_base + 0x09, 0); outb(eth_nic_base+D8390_P0_PSTOP, eth_memsize); outb(eth_nic_base+D8390_P0_BOUND, eth_tx_start + D8390_TXBUF_SIZE); outb(eth_nic_base+D8390_P0_ISR, 0xFF); outb(eth_nic_base+D8390_P0_IMR, 0); if (eth_flags & FLAG_790) outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS1 | D8390_COMMAND_STP); else outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS1 | D8390_COMMAND_RD2 | D8390_COMMAND_STP); for (i=0; i<6; i++)#ifdef INCLUDE_EGY outb(eth_nic_base+D8390_P1_PAR0+i*2, eth_node_addr[i]); /* for EGY-98 XXX HN2 */#else outb(eth_nic_base+D8390_P1_PAR0+i, eth_node_addr[i]);#endif for (i=0; i<6; i++) outb(eth_nic_base+D8390_P1_MAR0+i, 0xFF); outb(eth_nic_base+D8390_P1_CURR, eth_tx_start + D8390_TXBUF_SIZE+1); if (eth_flags & FLAG_790) outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_STA); else outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STA); outb(eth_nic_base+D8390_P0_ISR, 0xFF); outb(eth_nic_base+D8390_P0_TCR, 0);#ifdef INCLUDE_3COM if (eth_vendor == VENDOR_3COM) { /* * No way to tell whether or not we're supposed to use * the 3Com's transceiver unless the user tells us. * 'aui' should have some compile time default value * which can be changed from the command menu. */ if (aui) outb(eth_asic_base + _3COM_CR, 0); else outb(eth_asic_base + _3COM_CR, _3COM_CR_XSEL); }#endif return(1);}/**************************************************************************ETH_TRANSMIT - Transmit a frame**************************************************************************/eth_transmit(d,t,s,p) char *d; /* Destination */ unsigned short t; /* Type */ unsigned short s; /* size */ char *p; /* Packet */{ unsigned char c;#ifdef INCLUDE_3COM if (eth_vendor == VENDOR_3COM) { bcopy(d, eth_bmem, 6); /* dst */ bcopy(eth_node_addr, eth_bmem+6, ETHER_ADDR_LEN); /* src */ *(eth_bmem+12) = t>>8; /* type */ *(eth_bmem+13) = t; bcopy(p, eth_bmem+14, s); s += 14; while (s < ETHER_MIN_LEN) *(eth_bmem+(s++)) = 0; }#endif#ifdef INCLUDE_WD if (eth_vendor == VENDOR_WD) { /* Memory interface */ if (eth_flags & FLAG_16BIT) { outb(eth_asic_base + WD_LAAR, eth_laar | WD_LAAR_M16EN);#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif } if (eth_flags & FLAG_790) { outb(eth_asic_base + WD_MSR, WD_MSR_MENB);#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif }#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif bcopy(d, eth_bmem, 6); /* dst */ bcopy(eth_node_addr, eth_bmem+6, ETHER_ADDR_LEN); /* src */ *(eth_bmem+12) = t>>8; /* type */ *(eth_bmem+13) = t; bcopy(p, eth_bmem+14, s); s += 14; while (s < ETHER_MIN_LEN) *(eth_bmem+(s++)) = 0; if (eth_flags & FLAG_790) { outb(eth_asic_base + WD_MSR, 0);#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif } if (eth_flags & FLAG_16BIT) { outb(eth_asic_base + WD_LAAR, eth_laar & ~WD_LAAR_M16EN);#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif } }#endif#if defined(INCLUDE_NE) || defined(INCLUDE_LGY) || defined(INCLUDE_EGY) if (eth_vendor == VENDOR_NOVELL) { /* Programmed I/O */ unsigned short type; type = (t >> 8) | (t << 8); eth_pio_write(d, eth_tx_start<<8, 6); eth_pio_write(eth_node_addr, (eth_tx_start<<8)+6, 6); eth_pio_write(&type, (eth_tx_start<<8)+12, 2); eth_pio_write(p, (eth_tx_start<<8)+14, s); s += 14; if (s < ETHER_MIN_LEN) s = ETHER_MIN_LEN; }#endif#ifndef PC98 twiddle();#else if (twiddle_counter-- <= 0) { twiddle(); twiddle_counter = twiddle_max; }#endif if (eth_flags & FLAG_790) outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_STA); else outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STA); outb(eth_nic_base+D8390_P0_TPSR, eth_tx_start); outb(eth_nic_base+D8390_P0_TBCR0, s); outb(eth_nic_base+D8390_P0_TBCR1, s>>8); if (eth_flags & FLAG_790) outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_TXP | D8390_COMMAND_STA); else outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0 | D8390_COMMAND_TXP | D8390_COMMAND_RD2 | D8390_COMMAND_STA); return(0);}voidset_twiddle_max(int max){ twiddle_max = max;}/**************************************************************************ETH_POLL - Wait for a frame**************************************************************************/eth_poll(){ int ret = 0; unsigned short type = 0; unsigned char bound,curr,rstat; unsigned short len, copylen; unsigned short pktoff; unsigned char *p; struct ringbuffer pkthdr; rstat = inb(eth_nic_base+D8390_P0_RSR); if (rstat & D8390_RSTAT_OVER) { eth_reset(); return(0); } if (!(rstat & D8390_RSTAT_PRX)) return(0); bound = inb(eth_nic_base+D8390_P0_BOUND)+1; if (bound == eth_memsize) bound = eth_tx_start + D8390_TXBUF_SIZE; outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS1); curr = inb(eth_nic_base+D8390_P1_CURR); outb(eth_nic_base+D8390_P0_COMMAND, D8390_COMMAND_PS0); if (curr == eth_memsize) curr=eth_tx_start + D8390_TXBUF_SIZE; if (curr == bound) return(0); if (eth_vendor == VENDOR_WD) { if (eth_flags & FLAG_16BIT) { outb(eth_asic_base + WD_LAAR, eth_laar | WD_LAAR_M16EN);#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif } if (eth_flags & FLAG_790) { outb(eth_asic_base + WD_MSR, WD_MSR_MENB);#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif }#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif } pktoff = (bound << 8); if (eth_flags & FLAG_PIO) eth_pio_read(pktoff, &pkthdr, 4); else bcopy(eth_rmem + pktoff, &pkthdr, 4); len = pkthdr.len - 4; /* sub CRC */ pktoff += 4; if (len > 1514) len = 1514; bound = pkthdr.bound; /* New bound ptr */ if ( (pkthdr.status & D8390_RSTAT_PRX) && (len > 14) && (len < 1518)) { p = packet; packetlen = copylen = len; len = (eth_memsize << 8) - pktoff; if (packetlen > len) { /* We have a wrap-around */ if (eth_flags & FLAG_PIO) eth_pio_read(pktoff, p, len); else bcopy(eth_rmem + pktoff, p, len); pktoff = (eth_tx_start + D8390_TXBUF_SIZE) << 8; p += len; copylen -= len; } if (eth_flags & FLAG_PIO) eth_pio_read(pktoff, p, copylen); else bcopy(eth_rmem + pktoff, p, copylen); type = (packet[12]<<8) | packet[13]; ret = 1; } if (eth_vendor == VENDOR_WD) { if (eth_flags & FLAG_790) { outb(eth_asic_base + WD_MSR, 0);#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif } if (eth_flags & FLAG_16BIT) { outb(eth_asic_base + WD_LAAR, eth_laar & ~WD_LAAR_M16EN);#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif }#ifndef PC98 inb(0x84);#else (void)outb(0x5f,0);#endif } if (bound == (eth_tx_start + D8390_TXBUF_SIZE)) bound = eth_memsize; outb(eth_nic_base+D8390_P0_BOUND, bound-1); if (ret && (type == ARP)) { struct arprequest *arpreq; unsigned long reqip; arpreq = (struct arprequest *)&packet[ETHER_HDR_LEN]; convert_ipaddr(&reqip, arpreq->tipaddr); if ((ntohs(arpreq->opcode) == ARP_REQUEST) && (reqip == arptable[ARP_CLIENT].ipaddr)) { arpreq->opcode = htons(ARP_REPLY); bcopy(arpreq->sipaddr, arpreq->tipaddr, 4); bcopy(arpreq->shwaddr, arpreq->thwaddr, 6); bcopy(arptable[ARP_CLIENT].node, arpreq->shwaddr, 6); convert_ipaddr(arpreq->sipaddr, &reqip); eth_transmit(arpreq->thwaddr, ARP, sizeof(struct arprequest), arpreq); return(0); } } return(ret);}#if defined(INCLUDE_NE) || defined(INCLUDE_LGY) || defined(INCLUDE_EGY)/**************************************************************************ETH_PIO_READ - Read a frame via Programmed I/O**************************************************************************/eth_pio_read(src, dst, cnt) unsigned short src; unsigned char *dst; unsigned short cnt;{ if (cnt & 1) cnt++; outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD2 | D8390_COMMAND_STA); outb(eth_nic_base + D8390_P0_RBCR0, cnt); outb(eth_nic_base + D8390_P0_RBCR1, cnt>>8); outb(eth_nic_base + D8390_P0_RSAR0, src); outb(eth_nic_base + D8390_P0_RSAR1, src>>8); outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD0 | D8390_COMMAND_STA); if (eth_flags & FLAG_16BIT) { while (cnt) { *((unsigned short *)dst) = inw(eth_asic_base + NE_DATA); dst += 2; cnt -= 2; } } else { while (cnt--) *(dst++) = inb(eth_asic_base + NE_DATA); }}/**************************************************************************ETH_PIO_WRITE - Write a frame via Programmed I/O**************************************************************************/eth_pio_write(src, dst, cnt) unsigned char *src; unsigned short dst; unsigned short cnt;{ outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD2 | D8390_COMMAND_STA); outb(eth_nic_base + D8390_P0_ISR, D8390_ISR_RDC); outb(eth_nic_base + D8390_P0_RBCR0, cnt); outb(eth_nic_base + D8390_P0_RBCR1, cnt>>8); outb(eth_nic_base + D8390_P0_RSAR0, dst); outb(eth_nic_base + D8390_P0_RSAR1, dst>>8); outb(eth_nic_base + D8390_P0_COMMAND, D8390_COMMAND_RD1 | D8390_COMMAND_STA); if (eth_flags & FLAG_16BIT) { if (cnt & 1) cnt++; /* Round up */ while (cnt) { outw(eth_asic_base + NE_DATA, *((unsigned short *)src)); src += 2; cnt -= 2; } } else { while (cnt--) outb(eth_asic_base + NE_DATA, *(src++)); } cnt = 200; while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) != D8390_ISR_RDC && --cnt);}#else/**************************************************************************ETH_PIO_READ - Dummy routine when NE2000 not compiled in**************************************************************************/eth_pio_read() {}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -