📄 ns8390.c
字号:
/**************************************************************************ETHERBOOT - BOOTP/TFTP Bootstrap ProgramAuthor: Martin Renters Date: May/94 This code is based heavily on David Greenman's if_ed.c driver Copyright (C) 1993-1994, David Greenman, Martin Renters. This software may be used, modified, copied, distributed, and sold, in both source and binary form provided that the above copyright and these terms are retained. Under no circumstances are the authors responsible for the proper functioning of this software, nor do the authors assume any responsibility for damages incurred with its use.Multicast support added by Timothy Legge (timlegge@users.sourceforge.net) 09/28/2003Relocation support added by Ken Yap (ken_yap@users.sourceforge.net) 28/12/023c503 support added by Bill Paul (wpaul@ctr.columbia.edu) on 11/15/94SMC8416 support added by Bill Paul (wpaul@ctr.columbia.edu) on 12/25/943c503 PIO support added by Jim Hague (jim.hague@acm.org) on 2/17/98RX overrun by Klaus Espenlaub (espenlaub@informatik.uni-ulm.de) on 3/10/99 parts taken from the Linux 8390 driver (by Donald Becker and Paul Gortmaker)SMC8416 PIO support added by Andrew Bettison (andrewb@zip.com.au) on 4/3/02 based on the Linux 8390 driver (by Donald Becker and Paul Gortmaker)**************************************************************************/#include "etherboot.h"#include "nic.h"#include "ns8390.h"#ifdef INCLUDE_NS8390#include "pci.h"#else#include "isa.h"#endifstatic unsigned char eth_vendor, eth_flags;#ifdef INCLUDE_WDstatic unsigned char eth_laar;#endifstatic unsigned short eth_nic_base, eth_asic_base;static unsigned char eth_memsize, eth_rx_start, eth_tx_start;static Address eth_bmem, eth_rmem;static unsigned char eth_drain_receiver;#ifdef INCLUDE_WDstatic struct wd_board { const char *name; char id; char flags; char memsize;} wd_boards[] = { {"WD8003S", TYPE_WD8003S, 0, MEM_8192}, {"WD8003E", TYPE_WD8003E, 0, MEM_8192}, {"WD8013EBT", TYPE_WD8013EBT, FLAG_16BIT, MEM_16384}, {"WD8003W", TYPE_WD8003W, 0, MEM_8192}, {"WD8003EB", TYPE_WD8003EB, 0, MEM_8192}, {"WD8013W", TYPE_WD8013W, FLAG_16BIT, MEM_16384}, {"WD8003EP/WD8013EP", TYPE_WD8013EP, 0, MEM_8192}, {"WD8013WC", TYPE_WD8013WC, FLAG_16BIT, MEM_16384}, {"WD8013EPC", TYPE_WD8013EPC, FLAG_16BIT, MEM_16384}, {"SMC8216T", TYPE_SMC8216T, FLAG_16BIT | FLAG_790, MEM_16384}, {"SMC8216C", TYPE_SMC8216C, FLAG_16BIT | FLAG_790, MEM_16384}, {"SMC8416T", TYPE_SMC8416T, FLAG_16BIT | FLAG_790, MEM_8192}, {"SMC8416C/BT", TYPE_SMC8416C, FLAG_16BIT | FLAG_790, MEM_8192}, {"SMC8013EBP", TYPE_SMC8013EBP,FLAG_16BIT, MEM_16384}, {NULL, 0, 0, 0}};#endif#ifdef INCLUDE_3C503static unsigned char t503_output; /* AUI or internal xcvr (Thinnet) */#endif#if defined(INCLUDE_WD)#define ASIC_PIO WD_IAR#define eth_probe wd_probe#if defined(INCLUDE_3C503) || defined(INCLUDE_NE) || defined(INCLUDE_NS8390)Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390#endif#endif#if defined(INCLUDE_3C503)#define eth_probe t503_probe#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || defined(INCLUDE_WD)Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390#endif#endif#if defined(INCLUDE_NE)#define eth_probe ne_probe#if defined(INCLUDE_NS8390) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390#endif#endif#if defined(INCLUDE_NS8390)#define eth_probe nepci_probe#if defined(INCLUDE_NE) || defined(INCLUDE_3C503) || defined(INCLUDE_WD)Error you must only define one of INCLUDE_WD, INCLUDE_3C503, INCLUDE_NE, INCLUDE_NS8390#endif#endif#if defined(INCLUDE_3C503)#define ASIC_PIO _3COM_RFMSB#else#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390)#define ASIC_PIO NE_DATA#endif#endif#if defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))/**************************************************************************ETH_PIO_READ - Read a frame via Programmed I/O**************************************************************************/static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt){#ifdef INCLUDE_WD outb(src & 0xff, eth_asic_base + WD_GP2); outb(src >> 8, eth_asic_base + WD_GP2);#else outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND); outb(cnt, eth_nic_base + D8390_P0_RBCR0); outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1); outb(src, eth_nic_base + D8390_P0_RSAR0); outb(src>>8, eth_nic_base + D8390_P0_RSAR1); outb(D8390_COMMAND_RD0 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);#ifdef INCLUDE_3C503 outb(src & 0xff, eth_asic_base + _3COM_DALSB); outb(src >> 8, eth_asic_base + _3COM_DAMSB); outb(t503_output | _3COM_CR_START, eth_asic_base + _3COM_CR);#endif#endif if (eth_flags & FLAG_16BIT) cnt = (cnt + 1) >> 1; while(cnt--) {#ifdef INCLUDE_3C503 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0) ;#endif if (eth_flags & FLAG_16BIT) { *((unsigned short *)dst) = inw(eth_asic_base + ASIC_PIO); dst += 2; } else *(dst++) = inb(eth_asic_base + ASIC_PIO); }#ifdef INCLUDE_3C503 outb(t503_output, eth_asic_base + _3COM_CR);#endif}/**************************************************************************ETH_PIO_WRITE - Write a frame via Programmed I/O**************************************************************************/static void eth_pio_write(const unsigned char *src, unsigned int dst, unsigned int cnt){#ifdef COMPEX_RL2000_FIX unsigned int x;#endif /* COMPEX_RL2000_FIX */#ifdef INCLUDE_WD outb(dst & 0xff, eth_asic_base + WD_GP2); outb(dst >> 8, eth_asic_base + WD_GP2);#else outb(D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND); outb(D8390_ISR_RDC, eth_nic_base + D8390_P0_ISR); outb(cnt, eth_nic_base + D8390_P0_RBCR0); outb(cnt>>8, eth_nic_base + D8390_P0_RBCR1); outb(dst, eth_nic_base + D8390_P0_RSAR0); outb(dst>>8, eth_nic_base + D8390_P0_RSAR1); outb(D8390_COMMAND_RD1 | D8390_COMMAND_STA, eth_nic_base + D8390_P0_COMMAND);#ifdef INCLUDE_3C503 outb(dst & 0xff, eth_asic_base + _3COM_DALSB); outb(dst >> 8, eth_asic_base + _3COM_DAMSB); outb(t503_output | _3COM_CR_DDIR | _3COM_CR_START, eth_asic_base + _3COM_CR);#endif#endif if (eth_flags & FLAG_16BIT) cnt = (cnt + 1) >> 1; while(cnt--) {#ifdef INCLUDE_3C503 while((inb(eth_asic_base + _3COM_STREG) & _3COM_STREG_DPRDY) == 0) ;#endif if (eth_flags & FLAG_16BIT) { outw(*((unsigned short *)src), eth_asic_base + ASIC_PIO); src += 2; } else outb(*(src++), eth_asic_base + ASIC_PIO); }#ifdef INCLUDE_3C503 outb(t503_output, eth_asic_base + _3COM_CR);#else#ifdef COMPEX_RL2000_FIX for (x = 0; x < COMPEX_RL2000_TRIES && (inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) != D8390_ISR_RDC; ++x); if (x >= COMPEX_RL2000_TRIES) printf("Warning: Compex RL2000 aborted wait!\n");#endif /* COMPEX_RL2000_FIX */#ifndef INCLUDE_WD while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC) != D8390_ISR_RDC);#endif#endif}#else/**************************************************************************ETH_PIO_READ - Dummy routine when NE2000 not compiled in**************************************************************************/static void eth_pio_read(unsigned int src __unused, unsigned char *dst __unused, unsigned int cnt __unused) {}#endif/**************************************************************************enable_multycast - Enable Multicast**************************************************************************/static void enable_multicast(unsigned short eth_nic_base) { unsigned char mcfilter[8]; int i; memset(mcfilter, 0xFF, 8); outb(4, eth_nic_base+D8390_P0_RCR); outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS1, eth_nic_base + D8390_P0_COMMAND); for(i=0;i<8;i++) { outb(mcfilter[i], eth_nic_base + 8 + i); if(inb(eth_nic_base + 8 + i)!=mcfilter[i]) printf("Error SMC 83C690 Multicast filter read/write mishap %d\n",i); } outb(D8390_COMMAND_RD2 + D8390_COMMAND_PS0, eth_nic_base + D8390_P0_COMMAND); outb(4 | 0x08, eth_nic_base+D8390_P0_RCR);}/**************************************************************************NS8390_RESET - Reset adapter**************************************************************************/static void ns8390_reset(struct nic *nic){ int i; eth_drain_receiver = 0;#ifdef INCLUDE_WD if (eth_flags & FLAG_790) outb(D8390_COMMAND_PS0 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); else#endif outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); if (eth_flags & FLAG_16BIT) outb(0x49, eth_nic_base+D8390_P0_DCR); else outb(0x48, eth_nic_base+D8390_P0_DCR); outb(0, eth_nic_base+D8390_P0_RBCR0); outb(0, eth_nic_base+D8390_P0_RBCR1); outb(0x20, eth_nic_base+D8390_P0_RCR); /* monitor mode */ outb(2, eth_nic_base+D8390_P0_TCR); outb(eth_tx_start, eth_nic_base+D8390_P0_TPSR); outb(eth_rx_start, eth_nic_base+D8390_P0_PSTART);#ifdef INCLUDE_WD if (eth_flags & FLAG_790) {#ifdef WD_790_PIO outb(0x10, eth_asic_base + 0x06); /* disable interrupts, enable PIO */ outb(0x01, eth_nic_base + 0x09); /* enable ring read auto-wrap */#else outb(0, eth_nic_base + 0x09);#endif }#endif outb(eth_memsize, eth_nic_base+D8390_P0_PSTOP); outb(eth_memsize - 1, eth_nic_base+D8390_P0_BOUND); outb(0xFF, eth_nic_base+D8390_P0_ISR); outb(0, eth_nic_base+D8390_P0_IMR);#ifdef INCLUDE_WD if (eth_flags & FLAG_790) outb(D8390_COMMAND_PS1 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); else#endif outb(D8390_COMMAND_PS1 | D8390_COMMAND_RD2 | D8390_COMMAND_STP, eth_nic_base+D8390_P0_COMMAND); for (i=0; i<ETH_ALEN; i++) outb(nic->node_addr[i], eth_nic_base+D8390_P1_PAR0+i); for (i=0; i<ETH_ALEN; i++) outb(0xFF, eth_nic_base+D8390_P1_MAR0+i); outb(eth_rx_start, eth_nic_base+D8390_P1_CURR);#ifdef INCLUDE_WD if (eth_flags & FLAG_790) outb(D8390_COMMAND_PS0 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); else#endif outb(D8390_COMMAND_PS0 | D8390_COMMAND_RD2 | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND); outb(0xFF, eth_nic_base+D8390_P0_ISR); outb(0, eth_nic_base+D8390_P0_TCR); /* transmitter on */ outb(4, eth_nic_base+D8390_P0_RCR); /* allow rx broadcast frames */ enable_multicast(eth_nic_base);#ifdef INCLUDE_3C503 /* * No way to tell whether or not we're supposed to use * the 3Com's transceiver unless the user tells us. * 'flags' should have some compile time default value * which can be changed from the command menu. */ t503_output = (nic->flags) ? 0 : _3COM_CR_XSEL; outb(t503_output, eth_asic_base + _3COM_CR);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -