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

📄 if_ns.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * Copyright (c) 1994 Shantanu Goel * All Rights Reserved. *  * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. *  * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION.  THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. *//* * Written 1992,1993 by Donald Becker. *  * Copyright 1993 United States Government as represented by the * Director, National Security Agency.	 This software may be used and * distributed according to the terms of the GNU Public License, * incorporated herein by reference. * * The Author may be reached as becker@super.org or * C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 */#include <ul.h>#include <wd.h>#include <hpp.h>#if NUL > 0 || NWD > 0 || NHPP > 0/* * Generic NS8390 routines. * Derived from the Linux driver by Donald Becker. * * Shantanu Goel (goel@cs.columbia.edu) */#include <sys/types.h>#include <device/device_types.h>#include <device/errno.h>#include <device/io_req.h>#include <device/if_hdr.h>#include <device/if_ether.h>#include <device/net_status.h>#include <device/net_io.h>#include <chips/busses.h>#include <i386/machspl.h>#include <i386/pio.h>#include <i386at/gpl/if_nsreg.h>#define IO_DELAY	__asm__ __volatile__ ("outb %al,$0x80")#define outb_p(p, v)	{ outb(p, v); IO_DELAY; }#define inb_p(p)	({ unsigned char _v; _v = inb(p); IO_DELAY; _v; })#define NSDEBUG#ifdef NSDEBUGint	nsdebug = 0;#define DEBUGF(stmt)	{ if (nsdebug) stmt; }#else#define DEBUGF(stmt)#endifvoid	nsxint(struct nssoftc *);void	nsrint(struct nssoftc *);void	nsxmit(struct nssoftc *, unsigned, int);void	nsrxoverrun(struct nssoftc *);/* * Initialize the NIC. * Must be called at splimp(). */voidnsinit(sc)	struct nssoftc *sc;{	int port = sc->sc_port, i, rxconfig;	int endcfg = sc->sc_word16 ? (0x48 | ENDCFG_WTS) : 0x48;	struct ifnet *ifp = &sc->sc_if;	/*	 * Reset the board.	 */	(*sc->sc_reset)(sc);	sc->sc_oactive = 0;	sc->sc_txing = 0;	sc->sc_timer = 0;	sc->sc_tx1 = sc->sc_tx2 = 0;	sc->sc_curpg = sc->sc_rxstrtpg;	/*	 * Follow National Semiconductor's recommendations for	 * initializing the DP83902.	 */	outb_p(port, E8390_NODMA+E8390_PAGE0+E8390_STOP);	/* 0x21 */	outb_p(port + EN0_DCFG, endcfg);	/* 0x48 or 0x49 */	/*	 * Clear remote byte count registers.	 */	outb_p(port + EN0_RCNTLO, 0);	outb_p(port + EN0_RCNTHI, 0);	/*	 * Set to monitor and loopback mode -- this is vital!	 */	outb_p(port + EN0_RXCR, E8390_RXOFF);	/* 0x20 */	outb_p(port + EN0_TXCR, E8390_TXOFF);	/* 0x02 */	/*	 * Set transmit page and receive ring.	 */	outb_p(port + EN0_TPSR, sc->sc_txstrtpg);	outb_p(port + EN0_STARTPG, sc->sc_rxstrtpg);	outb_p(port + EN0_BOUNDARY, sc->sc_stoppg - 1);	outb_p(port + EN0_STOPPG, sc->sc_stoppg);	/*	 * Clear pending interrupts and mask.	 */	outb_p(port + EN0_ISR, 0xff);	/*         * Enable the following interrupts: receive/transmit complete,         * receive/transmit error, and Receiver OverWrite.         *         * Counter overflow and Remote DMA complete are *not* enabled.         */	outb_p(port + EN0_IMR, ENISR_RX | ENISR_TX | ENISR_RX_ERR |              ENISR_TX_ERR | ENISR_OVER );	/*	 * Copy station address into 8390 registers.	 */	outb_p(port, E8390_NODMA + E8390_PAGE1 + E8390_STOP);	/* 0x61 */	for (i = 0; i < ETHER_ADDR_LEN; i++)		outb_p(port + EN1_PHYS + i, sc->sc_addr[i]);	/*	 * Set up to accept all multicast packets.	 */	for (i = 0; i < 8; i++)		outb_p(port + EN1_MULT + i, 0xff);	/*	 * Initialize CURRent pointer	 */	outb_p(port + EN1_CURPAG, sc->sc_rxstrtpg);	/*	 * Program command register for page 0.	 */	outb_p(port, E8390_NODMA + E8390_PAGE0 + E8390_STOP);#if 0	outb_p(port + EN0_ISR, 0xff);	outb_p(port + EN0_IMR, ENISR_ALL);#endif	outb_p(port + E8390_CMD, E8390_NODMA + E8390_PAGE0 + E8390_START);	outb_p(port + EN0_TXCR, E8390_TXCONFIG);	/* xmit on */	/* 3c503 TechMan says rxconfig only after the NIC is started. */	rxconfig = E8390_RXCONFIG;	if (ifp->if_flags & IFF_ALLMULTI)		rxconfig |= 0x08;	if (ifp->if_flags & IFF_PROMISC)		rxconfig |= 0x10;	outb_p(port + EN0_RXCR, rxconfig);	/* rx on */	/*	 * Mark interface as up and start output.	 */	ifp->if_flags |= IFF_RUNNING;	nsstart(sc);}/* * Start output on interface. * Must be called at splimp(). */voidnsstart(sc)	struct nssoftc *sc;{	io_req_t ior;	struct ifnet *ifp = &sc->sc_if;	/*	 * Drop packets if interface is down.	 */	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {		while (1) {			IF_DEQUEUE(&ifp->if_snd, ior);			if (ior == 0)				return;			iodone(ior);		}	}	/*	 * If transmitter is busy, bail out.	 */	if (sc->sc_oactive)		return;	/*	 * Dequeue a packet.	 */	IF_DEQUEUE(&ifp->if_snd, ior);	if (ior == 0)		return;	/* Mask interrupts from the ethercard. */    	outb( sc->sc_port + EN0_IMR, 0x00);	if (sc->sc_pingpong) {		int count, output_page;		if (sc->sc_tx1 == 0) {			output_page = sc->sc_txstrtpg;			sc->sc_tx1 = count = (*sc->sc_output)(sc,							      ior->io_count,							      ior->io_data,							      sc->sc_txstrtpg);		} else if (sc->sc_tx2 == 0) {			output_page = sc->sc_txstrtpg + 6;			sc->sc_tx2 = count = (*sc->sc_output)(sc,							      ior->io_count,							      ior->io_data,							      output_page);		} else {			sc->sc_oactive = 1;			IF_PREPEND(&ifp->if_snd, ior);			return;		}		DEBUGF({			struct ether_header *eh;			eh =  (struct ether_header *)ior->io_data;			printf("send: %s%d: %x:%x:%x:%x:%x:%x, "			       "olen %d, len %d\n",			       sc->sc_name, sc->sc_unit,			       eh->ether_dhost[0], eh->ether_dhost[1],			       eh->ether_dhost[2], eh->ether_dhost[3],			       eh->ether_dhost[4], eh->ether_dhost[5],			       ior->io_count, count);		});		if (!sc->sc_txing) {			nsxmit(sc, count, output_page);			if (output_page == sc->sc_txstrtpg)				sc->sc_tx1 = -1, sc->sc_lasttx = -1;			else				sc->sc_tx2 = -1, sc->sc_lasttx = -2;		}		sc->sc_oactive = (sc->sc_tx1 && sc->sc_tx2);	} else {		int count;		count = (*sc->sc_output)(sc, ior->io_count,					 ior->io_data, sc->sc_txstrtpg);		DEBUGF({			struct ether_header *eh;			eh =  (struct ether_header *)ior->io_data;			printf("send: %s%d: %x:%x:%x:%x:%x:%x, "			       "olen %d, len %d\n",			       sc->sc_name, sc->sc_unit,			       eh->ether_dhost[0], eh->ether_dhost[1],			       eh->ether_dhost[2], eh->ether_dhost[3],			       eh->ether_dhost[4], eh->ether_dhost[5],			       ior->io_count, count);		});		nsxmit(sc, count, sc->sc_txstrtpg);		sc->sc_oactive = 1;	}	/* reenable 8390 interrupts. */		outb_p(sc->sc_port + EN0_IMR, ENISR_ALL);		iodone(ior);}/* * Interrupt routine. * Called by board level driver. */voidnsintr(sc)	struct nssoftc *sc;{	int port = sc->sc_port;	int interrupts, boguscount = 0;	struct ifnet *ifp = &sc->sc_if;	if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) {		DEBUGF(printf("nsintr: %s%d: interface down\n",			      sc->sc_name, sc->sc_unit));		return;	}	/*	 * Change to page 0 and read intr status reg.	 */	outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0);	while ((interrupts = inb_p(port + EN0_ISR)) != 0 && ++boguscount < 9) {		if (interrupts & ENISR_RDC) {			/*			 * Ack meaningless DMA complete.			 */			outb_p(port + EN0_ISR, ENISR_RDC);		}				if (interrupts & ENISR_OVER) 			nsrxoverrun(sc);		else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) {			nsrint(sc);		}

⌨️ 快捷键说明

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