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

📄 ns8390.c

📁 linux下从网卡远程启动
💻 C
📖 第 1 页 / 共 3 页
字号:
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 */{#if defined(INCLUDE_3C503) || (defined(INCLUDE_WD) && ! defined(WD_790_PIO))	Address		eth_vmem = bus_to_virt(eth_bmem);#endif#ifdef	INCLUDE_3C503        if (!(eth_flags & FLAG_PIO)) {                memcpy((char *)eth_vmem, d, ETH_ALEN);	/* dst */                memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */                *((char *)eth_vmem+12) = t>>8;		/* type */                *((char *)eth_vmem+13) = t;                memcpy((char *)eth_vmem+ETH_HLEN, p, s);                s += ETH_HLEN;                while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;        }#endif#ifdef	INCLUDE_WD	if (eth_flags & FLAG_16BIT) {		outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);		inb(0x84);	}#ifndef	WD_790_PIO	/* Memory interface */	if (eth_flags & FLAG_790) {		outb(WD_MSR_MENB, eth_asic_base + WD_MSR);		inb(0x84);	}	inb(0x84);	memcpy((char *)eth_vmem, d, ETH_ALEN);	/* dst */	memcpy((char *)eth_vmem+ETH_ALEN, nic->node_addr, ETH_ALEN); /* src */	*((char *)eth_vmem+12) = t>>8;		/* type */	*((char *)eth_vmem+13) = t;	memcpy((char *)eth_vmem+ETH_HLEN, p, s);	s += ETH_HLEN;	while (s < ETH_ZLEN) *((char *)eth_vmem+(s++)) = 0;	if (eth_flags & FLAG_790) {		outb(0, eth_asic_base + WD_MSR);		inb(0x84);	}#else	inb(0x84);#endif#endif#if	defined(INCLUDE_3C503)	if (eth_flags & FLAG_PIO)#endif#if	defined(INCLUDE_NE) || defined(INCLUDE_NS8390) || (defined(INCLUDE_3C503) && !defined(T503_SHMEM)) || (defined(INCLUDE_WD) && defined(WD_790_PIO))	{		/* 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_16BIT) {		outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);		inb(0x84);	}	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)		outb(D8390_COMMAND_PS0 |			D8390_COMMAND_TXP | D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);	else#endif		outb(D8390_COMMAND_PS0 |			D8390_COMMAND_TXP | D8390_COMMAND_RD2 |			D8390_COMMAND_STA, eth_nic_base+D8390_P0_COMMAND);}/**************************************************************************NS8390_POLL - Wait for a frame**************************************************************************/static int ns8390_poll(struct nic *nic){	int ret = 0;	unsigned char rstat, curr, next;	unsigned short len, frag;	unsigned short pktoff;	unsigned char *p;	struct ringbuffer pkthdr;#ifndef	INCLUDE_3C503	/* avoid infinite recursion: see eth_rx_overrun() */	if (!eth_drain_receiver && (inb(eth_nic_base+D8390_P0_ISR) & D8390_ISR_OVW)) {		eth_rx_overrun(nic);		return(0);	}#endif	/* INCLUDE_3C503 */	rstat = inb(eth_nic_base+D8390_P0_RSR);	if (!(rstat & D8390_RSTAT_PRX)) return(0);	next = inb(eth_nic_base+D8390_P0_BOUND)+1;	if (next >= eth_memsize) next = eth_rx_start;	outb(D8390_COMMAND_PS1, eth_nic_base+D8390_P0_COMMAND);	curr = inb(eth_nic_base+D8390_P1_CURR);	outb(D8390_COMMAND_PS0, eth_nic_base+D8390_P0_COMMAND);	if (curr >= eth_memsize) curr=eth_rx_start;	if (curr == next) return(0);#ifdef	INCLUDE_WD	if (eth_flags & FLAG_16BIT) {		outb(eth_laar | WD_LAAR_M16EN, eth_asic_base + WD_LAAR);		inb(0x84);	}#ifndef	WD_790_PIO	if (eth_flags & FLAG_790) {		outb(WD_MSR_MENB, eth_asic_base + WD_MSR);		inb(0x84);	}#endif	inb(0x84);#endif	pktoff = next << 8;	if (eth_flags & FLAG_PIO)		eth_pio_read(pktoff, (char *)&pkthdr, 4);	else		memcpy(&pkthdr, bus_to_virt(eth_rmem + pktoff), 4);	pktoff += sizeof(pkthdr);	/* incoming length includes FCS so must sub 4 */	len = pkthdr.len - 4;	if ((pkthdr.status & D8390_RSTAT_PRX) == 0 || len < ETH_ZLEN		|| len > ETH_FRAME_LEN) {		printf("Bogus packet, ignoring\n");		return (0);	}	else {		p = nic->packet;		nic->packetlen = len;		/* available to caller */		frag = (eth_memsize << 8) - pktoff;		if (len > frag) {		/* We have a wrap-around */			/* read first part */			if (eth_flags & FLAG_PIO)				eth_pio_read(pktoff, p, frag);			else				memcpy(p, bus_to_virt(eth_rmem + pktoff), frag);			pktoff = eth_rx_start << 8;			p += frag;			len -= frag;		}		/* read second part */		if (eth_flags & FLAG_PIO)			eth_pio_read(pktoff, p, len);		else			memcpy(p, bus_to_virt(eth_rmem + pktoff), len);		ret = 1;	}#ifdef	INCLUDE_WD#ifndef	WD_790_PIO	if (eth_flags & FLAG_790) {		outb(0, eth_asic_base + WD_MSR);		inb(0x84);	}#endif	if (eth_flags & FLAG_16BIT) {		outb(eth_laar & ~WD_LAAR_M16EN, eth_asic_base + WD_LAAR);		inb(0x84);	}	inb(0x84);#endif	next = pkthdr.next;		/* frame number of next packet */	if (next == eth_rx_start)		next = eth_memsize;	outb(next-1, eth_nic_base+D8390_P0_BOUND);	return(ret);}/**************************************************************************NS8390_DISABLE - Turn off adapter**************************************************************************/static void ns8390_disable(struct dev *dev){	struct nic *nic = (struct nic *)dev;	/* reset and disable merge */	ns8390_reset(nic);}/**************************************************************************ETH_PROBE - Look for an adapter**************************************************************************/#ifdef	INCLUDE_NS8390static int eth_probe (struct dev *dev, struct pci_device *pci)#elsestatic int eth_probe (struct dev *dev, unsigned short *probe_addrs __unused)#endif{	struct nic *nic = (struct nic *)dev;	int i;#ifdef INCLUDE_NS8390	unsigned short pci_probe_addrs[] = { pci->ioaddr, 0 };	unsigned short *probe_addrs = pci_probe_addrs;#endif	eth_vendor = VENDOR_NONE;	eth_drain_receiver = 0;#ifdef	INCLUDE_WD{	/******************************************************************	Search for WD/SMC cards	******************************************************************/	struct wd_board *brd;	unsigned short chksum;	unsigned char c;	for (eth_asic_base = WD_LOW_BASE; eth_asic_base <= WD_HIGH_BASE;		eth_asic_base += 0x20) {		chksum = 0;		for (i=8; i<16; i++)			chksum += inb(eth_asic_base+i);		/* Extra checks to avoid soundcard */		if ((chksum & 0xFF) == 0xFF &&			inb(eth_asic_base+8) != 0xFF &&			inb(eth_asic_base+9) != 0xFF)			break;	}	if (eth_asic_base > WD_HIGH_BASE)		return (0);	/* We've found a board */	eth_vendor = VENDOR_WD;	eth_nic_base = eth_asic_base + WD_NIC_ADDR;	c = inb(eth_asic_base+WD_BID);	/* Get board id */	for (brd = wd_boards; brd->name; brd++)		if (brd->id == c) break;	if (!brd->name) {		printf("Unknown WD/SMC NIC type %hhX\n", c);		return (0);	/* Unknown type */	}	eth_flags = brd->flags;	eth_memsize = brd->memsize;	eth_tx_start = 0;	eth_rx_start = D8390_TXBUF_SIZE;	if ((c == TYPE_WD8013EP) &&		(inb(eth_asic_base + WD_ICR) & WD_ICR_16BIT)) {			eth_flags = FLAG_16BIT;			eth_memsize = MEM_16384;	}	if ((c & WD_SOFTCONFIG) && (!(eth_flags & FLAG_790))) {		eth_bmem = (0x80000 |		 ((inb(eth_asic_base + WD_MSR) & 0x3F) << 13));	} else		eth_bmem = WD_DEFAULT_MEM;	if (brd->id == TYPE_SMC8216T || brd->id == TYPE_SMC8216C) {		/* from Linux driver, 8416BT detects as 8216 sometimes */		unsigned int addr = inb(eth_asic_base + 0xb);		if (((addr >> 4) & 3) == 0) {			brd += 2;			eth_memsize = brd->memsize;		}	}	outb(0x80, eth_asic_base + WD_MSR);	/* Reset */	for (i=0; i<ETH_ALEN; i++) {

⌨️ 快捷键说明

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