⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ns8390.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************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.3c503 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)**************************************************************************/#include "etherboot.h"#include "nic.h"#include "ns8390.h"#ifdef	INCLUDE_NS8390#include "pci.h"#endif#include "cards.h"static unsigned char	eth_vendor, eth_flags, eth_laar;static 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	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))/**************************************************************************ETH_PIO_READ - Read a frame via Programmed I/O**************************************************************************/static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt){	if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; }	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	if (eth_flags & FLAG_16BIT)		cnt >>= 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 */	if (eth_flags & FLAG_16BIT) { ++cnt; cnt &= ~1; }	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	if (eth_flags & FLAG_16BIT)		cnt >>= 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 */	while((inb(eth_nic_base + D8390_P0_ISR) & D8390_ISR_RDC)		!= D8390_ISR_RDC);#endif}#else/**************************************************************************ETH_PIO_READ - Dummy routine when NE2000 not compiled in**************************************************************************/static void eth_pio_read(unsigned int src, unsigned char *dst, unsigned int cnt) {}#endif/**************************************************************************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) outb(0, eth_nic_base + 0x09);#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);	outb(4, eth_nic_base+D8390_P0_RCR);	/* allow broadcast frames */#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}static int ns8390_poll(struct nic *nic);#ifndef	INCLUDE_3C503/**************************************************************************ETH_RX_OVERRUN - Bring adapter back to work after an RX overrun**************************************************************************/static void eth_rx_overrun(struct nic *nic){	int start_time;#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);	/* wait for at least 1.6ms - we wait one timer tick */	start_time = currticks();	while (currticks() - start_time <= 1)		/* Nothing */;	outb(0, eth_nic_base+D8390_P0_RBCR0);	/* reset byte counter */	outb(0, eth_nic_base+D8390_P0_RBCR1);	/*	 * Linux driver checks for interrupted TX here. This is not necessary,	 * because the transmit routine waits until the frame is sent.	 */	/* enter loopback mode and restart NIC */	outb(2, eth_nic_base+D8390_P0_TCR);#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);	/* clear the RX ring, acknowledge overrun interrupt */	eth_drain_receiver = 1;	while (ns8390_poll(nic))		/* Nothing */;	eth_drain_receiver = 0;	outb(D8390_ISR_OVW, eth_nic_base+D8390_P0_ISR);	/* leave loopback mode - no packets to be resent (see Linux driver) */	outb(0, eth_nic_base+D8390_P0_TCR);}#endif	/* INCLUDE_3C503 *//**************************************************************************NS8390_TRANSMIT - Transmit a frame**************************************************************************/static void ns8390_transmit(	struct nic *nic,	const char *d,			/* Destination */	unsigned int t,			/* Type */	unsigned int s,			/* size */	const char *p)			/* Packet */{#ifdef	INCLUDE_3C503        if (!(eth_flags & FLAG_PIO)) {                memcpy((char *)eth_bmem, d, ETH_ALEN);	/* dst */                memcpy((char *)eth_bmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */                *((char *)eth_bmem+12) = t>>8;		/* type */                *((char *)eth_bmem+13) = t;                memcpy((char *)eth_bmem+ETH_HLEN, p, s);                s += ETH_HLEN;                while (s < ETH_ZLEN) *((char *)eth_bmem+(s++)) = 0;        }#endif#ifdef	INCLUDE_WD	/* Memory interface */	if (eth_flags & FLAG_16BIT) {		outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);		inb(0x84);	}	if (eth_flags & FLAG_790) {		outb(WD_MSR_MENB, eth_asic_base + WD_MSR);		inb(0x84);	}	inb(0x84);	memcpy((char *)eth_bmem, d, ETH_ALEN);	/* dst */	memcpy((char *)eth_bmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */	*((char *)eth_bmem+12) = t>>8;		/* type */	*((char *)eth_bmem+13) = t;	memcpy((char *)eth_bmem+ETH_HLEN, p, s);	s += ETH_HLEN;	while (s < ETH_ZLEN) *((char *)eth_bmem+(s++)) = 0;	if (eth_flags & FLAG_790) {		outb(0, eth_asic_base + WD_MSR);		inb(0x84);	}	if (eth_flags & FLAG_16BIT) {		outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);		inb(0x84);	}#endif#if	defined(INCLUDE_3C503)	if (eth_flags & FLAG_PIO) {#endif#if	defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM))		/* Programmed I/O */		unsigned short type;		type = (t >> 8) | (t << 8);		eth_pio_write(d, eth_tx_start<<8, ETH_ALEN);		eth_pio_write(nic->node_addr, (eth_tx_start<<8)+ETH_ALEN, ETH_ALEN);		/* bcc generates worse code without (const+const) below */		eth_pio_write((unsigned char *)&type, (eth_tx_start<<8)+(ETH_ALEN+ETH_ALEN), 2);		eth_pio_write(p, (eth_tx_start<<8)+ETH_HLEN, s);		s += ETH_HLEN;		if (s < ETH_ZLEN) s = ETH_ZLEN;#endif#if	defined(INCLUDE_3C503)	}#endif#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(eth_tx_start, eth_nic_base+D8390_P0_TPSR);	outb(s, eth_nic_base+D8390_P0_TBCR0);	outb(s>>8, eth_nic_base+D8390_P0_TBCR1);#ifdef	INCLUDE_WD	if (eth_flags & FLAG_790)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -