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

📄 if_wlp.c

📁 WaveLAN无线网卡Linux驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1997 Carnegie Mellon University. All Rights Reserved. *  * Permission to use, copy, modify, and distribute this software and its * documentation is hereby granted (including for commercial or for-profit * use), 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, and that credit is given to Carnegie Mellon * University in all publications reporting on direct or indirect use of this * code or its derivatives. *  * THIS IMPLEMENTATION IS EXPERIMENTAL AND MAY HAVE BUGS, SOME OF WHICH MAY HAVE * SERIOUS CONSEQUENCES.  CARNEGIE MELLON PROVIDES THIS SOFTWARE IN ITS "AS * IS" CONDITION, AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON * UNIVERSITY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *  * Carnegie Mellon encourages (but does not require) users of this software to * return any improvements or extensions that they make, and to grant * Carnegie Mellon the rights to redistribute these changes without * encumbrance. *  *  */#include "card.h"#include "wlp.h"#include "bpfilter.h"		/* /sys/compile/<___>/bpfilter.h */#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/conf.h>#include <sys/errno.h>#include <sys/ioctl.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/syslog.h>#include <sys/time.h>#include <net/if.h>#include <net/if_dl.h>#include <net/if_types.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#endif#ifdef INET6#include <netinet/if_ether6.h>#include <netinet/if_ndp6.h>#endif#ifdef MONARCH_ADHOC#include <dsr/dsr_ifqueue.h>#endif#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endif#include <machine/clock.h>#include <i386/isa/isa_device.h>struct wlp_softc wlp_softc[NWLP];#include <i386/isa/ic/i82593.h>		/* Intel 82593 Definitions */#include <i386/isa/if_wlp_ir.h>		/* IBM Infrared Definitions */#include <i386/isa/if_wlp_wavelan.h>	/* Lucent WaveLAN Definitions */#include <i386/isa/if_wlp.h>		/* Shared code */#ifdef WAVELAN_ROAMING#include <i386/isa/if_wlp_wavelan_roam.h>#endif/* * ====================================================================== * Common Routines * ====================================================================== */int             wlp_isa_probe(struct isa_device *);int             wlp_isa_attach(struct isa_device *);int             wlpattach(struct isa_device *);static void     wlpstart(struct ifnet *);int             wlpioctl(struct ifnet * ifp, int cmd, caddr_t data);static void     wlpread(struct wlp_softc *, u_int32_t, u_int32_t, u_int32_t);static void     wlpstop(struct wlp_softc *);void            wlpwatchdog(struct ifnet *);#if 0static void     wlpdump(struct wlp_softc *);#endifstatic void     get_ifstats(struct wlp_softc *, struct ifreq *);static void     dump_bytes(caddr_t, u_int32_t);struct isa_driver wlpdriver = {wlp_isa_probe, wlp_isa_attach, "wlp", 0};/* * ====================================================================== * Intel 82593 Specific Routines * ====================================================================== */static voidi82593_default_config(struct i82593_conf *cfg);static voidi82593_default_config(struct i82593_conf *cfg){	cfg->byte_count_low = sizeof(cfg->data.cfgblock);	cfg->byte_count_high = 0;	cfg->data.bytes[0]  = 0x2A;  cfg->data.bytes[1]  = 0x00;	cfg->data.bytes[2]  = 0x26;  cfg->data.bytes[3]  = 0x00;	cfg->data.bytes[4]  = 0x60;  cfg->data.bytes[5]  = 0x00;	cfg->data.bytes[6]  = 0xF2;  cfg->data.bytes[7]  = 0x00;	cfg->data.bytes[8]  = 0x00;  cfg->data.bytes[9]  = 0x40;	cfg->data.bytes[10] = 0xFF;  cfg->data.bytes[11] = 0x00;	cfg->data.bytes[12] = 0x3F;  cfg->data.bytes[13] = 0x07;	cfg->data.bytes[14] = 0x00;  cfg->data.bytes[15] = 0x00;}intProbeIntel82593(struct isa_device * is, int iftype){	struct wlp_softc *sc = &wlp_softc[is->id_unit];	struct i82593_conf cfg;	u_int8_t        status;#ifdef WLP_DEBUG	printf("ProbeIntel82593() resetting chip...\n");#endif	/*	 * Reset the 82593.	 */	IOWrite1(0x00, P0_RESET);	DELAY(1000);#if 0	status = IORead1(0x00);	if (status != 0x10) {		printf("wlp%d: could not reset the 82593 (status = %x)\n",		       is->id_unit, status);		goto bad;	}#endif	/*	 * Configure the 82593 with default values	 */	i82593_default_config(&cfg);	if (iftype == IFTYPE_REDWING) {		RW_ResetTXDMA();		MEMWrite((caddr_t) &cfg, RW_RXWINDOW, sizeof(cfg));	} else if (iftype == IFTYPE_WAVELAN) {		WLP_ResetTXDMA();		WLP_PointTXBUF(WLP_TXBASE);		IOWrite(0x04, (caddr_t) &cfg, sizeof(cfg));	}#ifdef WLP_DEBUG	printf("ProbeIntel82593() configuring chip...\n");#endif	IOWrite1(0x00, P0_CONFIGURE);	status = I82593_wait(sc, P0_CONFIGURE);	if (status != (P0_CONFIGURE | P0_S0_INT | P0_S0_EXEC)) {		printf("wlp%d: Configure of the Intel 82593 failed (status = %x)\n",		       is->id_unit, status);		goto bad;	}#ifdef WLP_DEBUG	else {		IOWrite1(0x00, P0_NOP | P0_STATUS1);		printf("wlp%d: Intel 82593 configured successfully, Chip Signature: %x\n",		       is->id_unit, IORead1(0x00));	}#endif	/*	 * Perform self-diagnostics on the 82593	 */#ifdef WLP_DEBUG	printf("ProbeIntel82593() performing diagnostics...\n");#endif	IOWrite1(0x00, P0_DIAGNOSE);	DELAY(10000);	status = I82593_wait(sc, DIAGNOSE_PASSED);	if (status != (DIAGNOSE_PASSED | P0_S0_INT | P0_S0_EXEC)) {		printf("wlp%d: self diagnostics failed (status = %x)\n",		       is->id_unit, status);		goto bad;	}#ifdef WLP_DEBUG	else {		printf("wlp%d: self diagnostics passed\n", is->id_unit);	}#endif	return 0;bad:	return ENODEV;}u_int8_tI82593_wait(sc, cmd)	struct wlp_softc *sc;	u_int8_t        cmd;{	u_int32_t       count = 0;	u_int8_t        status = cmd | P0_S0_INT | P0_S0_EXEC;	u_int8_t        val = 0;#ifdef WLP_DEBUG	printf("I82593_wait() ENTRY\n");#endif	DELAY(200);	while ((val != status) && (count++ < 100)) {		IOWrite1(0x00, P0_NOP);	/* resets register pointer */		DELAY(100);		val = IORead1(0x00);		if (val & P0_S0_INT) {#ifdef WLP_DEBUG			printf("%s(): got %x from the Intel 82593\n", __FUNCTION__, val);#endif			IOWrite1(0x00, P0_INT_ACK);		}		DELAY(1000);	}#ifdef WLP_DEBUG	printf("I82593_wait() EXIT\n");#endif	return val;}/* * ====================================================================== * PCMCIA SPECIFIC CODE * ====================================================================== */#if NCARD > 0/* * PC-Card (PCMCIA) specific code. */static int      card_intr(struct pccard_devinfo *);	/* Interrupt handler */static void     wlpunload(struct pccard_devinfo *);	/* Disable driver */static int      wlpcrdinit(struct pccard_devinfo *);	/* init device */struct pccard_device wlppccdrv = {	"wlp",	wlpcrdinit,		/* Initialization */	wlpunload,		/* Disable */	card_intr,		/* Interrupt Handler */	0,			/* Attributes - presently unused */	&net_imask		/* Interrupt mask for device */};DATA_SET(pccarddrv_set, wlppccdrv);static intcard_intr(struct pccard_devinfo * dp){#ifdef WLP_DEBUG	printf("wlp%d: ENTRY card_intr()\n", dp->isahd.id_unit);#endif	wlpintr(dp->isahd.id_unit);#ifdef WLP_DEBUG	printf("wlp%d: EXIT card_intr()\n", dp->isahd.id_unit);#endif	return 1;}static voidwlpunload(struct pccard_devinfo * dp){	struct isa_device *is = &dp->isahd;	struct wlp_softc *sc = &wlp_softc[is->id_unit];	struct ifnet   *ifp = &sc->sc_ac.ac_if;	if (sc->sc_gone) {		printf("wlp%d: already unloaded\n", is->id_unit);		return;	}	ifp->if_flags &= ~IFF_RUNNING;	if_down(ifp);	sc->sc_gone = 1;#ifdef WAVELAN_ROAMING	if (sc->sc_iftype == IFTYPE_WAVELAN) {		RoamOnOff(sc, ROAM_OFF);	}#endif	printf("wlp%d: unload\n", is->id_unit);}/* ======================================================================	The "pccard_devinfo" structure contains the following fields:        	struct pccard_device *drv;		struct isa_device isahd;        	int running;		u_char  misc[128];		struct slot *slt;		struct pccard_devinfo *next;====================================================================== */#ifdef WLP_DEBUGstatic void dump_pccard_devinfo(struct pccard_devinfo*);static void dump_isa_device(struct isa_device*);static void dump_slot(struct slot*);static voiddump_pccard_devinfo(dp)	struct pccard_devinfo *dp;{	printf("PCCARD_DEVINFO dp: %08x\n", dp);	printf("\tdrv:     %08x\n", dp->drv);	printf("\trunning: %8x\n", dp->running);	dump_isa_device(&dp->isahd);	dump_slot(dp->slt);	printf("--------------------------------------------------\n");}static voiddump_isa_device(is)	struct isa_device *is;{	printf("ISA_DEVICE is: %08x\n", is);	printf("\tid_id:        %8x\n", is->id_id);	printf("\tid_driver:    %08x\n", is->id_driver);	printf("\tid_iobase:    %8x\n", is->id_iobase);	printf("\tid_irq:       %8x\n", is->id_irq);	printf("\tid_drq:       %8x\n", is->id_drq);	printf("\tid_maddr:     %08x\n", is->id_maddr);	printf("\tid_msize:     %8x\n", is->id_msize);	printf("\tid_intr:      %08x\n", is->id_intr);	printf("\tid_unit:      %8x\n", is->id_unit);	printf("\tid_flags:     %8x\n", is->id_flags);	printf("\tid_scsiid:    %8x\n", is->id_scsiid);	printf("\tid_alive:     %8x\n", is->id_alive);	printf("\tid_ri_flags:  %8x\n", is->id_ri_flags);	printf("\tid_reconfig:  %8x\n", is->id_reconfig);	printf("\tid_enabled:   %8x\n", is->id_enabled);	printf("\tid_conflicts: %8x\n", is->id_conflicts);	printf("\tid_next:      %08x\n", is->id_next);}static voiddump_slot(slt)	struct slot *slt;{	printf("SLOT slt: %08x\n", slt);	printf("\tslotnum:         %8x\n", slt->slotnum);	printf("\tflags:           %8x\n", slt->flags);	printf("\trwmem:           %8x\n", slt->rwmem);	printf("\tirq:             %8x\n", slt->irq);	printf("\tirqref:          %8x\n", slt->irqref);	printf("\tdevices:         %08x\n", slt->devices);	printf("\tinsert_seq:      %8x\n", slt->insert_seq);	// state	// laststate	// selp	// mem	// io	// pwr	printf("\tctrl:            %08x\n", slt->ctrl);	printf("\tcdata:           %08x\n", slt->cdata);	printf("\tpwr_off_pending: %8x\n", slt->pwr_off_pending);	// printf("\tdevfs_token:     %08x\n", slt->devfs_token);	printf("\tnext:            %08x\n", slt->next);}#endif /* WLP_DEBUG *//* ====================================================================== */static intwlpcrdinit(struct pccard_devinfo * dp){	struct isa_device *is = &dp->isahd;	struct wlp_softc *sc = &wlp_softc[is->id_unit];#ifdef WLP_DEBUG	printf("wlp%d: ENTRY wlpcrdinit()\n", is->id_unit);	printf("\tirq:    0x%04x\n", is->id_irq);	printf("\tiobase: 0x%04x\n", is->id_iobase);#endif	/*	 * Make sure that PCCARD gives us a valid IO Address	 */	if(is->id_iobase == 0x00) {		printf("wlp%d: invalid IO address\n", is->id_unit);		return ENODEV;	}	/*	 * Check to make sure that "unit" is within range.	 */	if ((is->id_unit < 0) || (is->id_unit > NWLP - 1)) {		printf("wlp%d: board out of range [0..%d]\n", is->id_unit, NWLP);		return ENODEV;	}	sc->sc_irq = is->id_irq;	sc->sc_iobase = is->id_iobase;	sc->sc_maddr = is->id_maddr;	sc->sc_msize = is->id_msize;	sc->sc_unit = is->id_unit;	sc->sc_gone = 0;	if (rwprobe(is) == RW_IOSIZE) {		sc->sc_iftype = IFTYPE_REDWING;		sc->sc_ifconfig = rwconfig;#ifdef WLP_DEBUG		printf("wlp%d: found a IBM Infrared card\n", is->id_unit);#endif	} else if (wlpprobe(is, dp) == WLP_IOSIZE) {		sc->sc_iftype = IFTYPE_WAVELAN;		sc->sc_ifconfig = wlpconfig;#ifdef WLP_DEBUG		printf("wlp%d: found a WaveLAN card\n", is->id_unit);#endif	} else {		printf("wlp%d: probe failed\n", is->id_unit);		return ENXIO;	}	if (wlpattach(is) == 0) {		printf("wlp%d: attach failed\n", is->id_unit);		return ENXIO;	}	sc->sc_ac.ac_if.if_snd.ifq_maxlen = ifqmaxlen;#ifdef WLP_DEBUG	printf("wlp%d: EXIT wlpcrdinit()\n", is->id_unit);#endif	return 0;}#endif				/* NCARD > 0 *//* * ====================================================================== * DEVICE INITIALIZATION ROUTINES * ====================================================================== */intwlp_isa_probe(is)	struct isa_device *is;{	struct wlp_softc *sc = &wlp_softc[is->id_unit];	/*	 * Check to make sure that "unit" is within range.	 */	if ((is->id_unit < 0) || (is->id_unit > NWLP - 1)) {		printf("wlp%d: board out of range [0..%d]\n", is->id_unit, NWLP);		return 0;	}	bzero(sc, sizeof(*sc));#if NCARD > 0	return 0;#endif	sc->sc_irq = is->id_irq;	sc->sc_iobase = is->id_iobase;	sc->sc_maddr = is->id_maddr;	sc->sc_msize = is->id_msize;	sc->sc_unit = is->id_unit;	sc->sc_gone = 0;	if (rwprobe(is) == RW_IOSIZE) {		u_int8_t        status;		sc->sc_iftype = IFTYPE_REDWING;		sc->sc_ifconfig = rwconfig;		/*		 * Verify that the IRQ setting specified in kernel, matches		 * the dip switch on the card.		 */		status = IORead1(0x0C);		if ((status & P12_ISA_IRQ) && (sc->sc_irq != 0x8000)) {			printf("wlp%d: Dip switch 4 is incorrectly set to IRQ 15\n", is->id_unit);			goto bad;		} else if (!(status & P12_ISA_IRQ) && (sc->sc_irq != 0x0400)) {			printf("wlp%d: Dip switch 4 is incorrectly set to IRQ 10\n", is->id_unit);			goto bad;		}		return RW_IOSIZE;	}	/* Don't support ISA WaveLAN Cards */bad:	return 0;}intwlp_isa_attach(struct isa_device * is){	return wlpattach(is);}intwlpattach(struct isa_device * is){	struct wlp_softc *sc = &wlp_softc[is->id_unit];	struct ifnet   *ifp;	/*	 * Configure the Card	 */	if (sc->sc_ifconfig(sc)) {		printf("wlp%d: failed to configure the card.\n", sc->sc_unit);		return 0;	/* ERROR */	}	ifp = &sc->sc_ac.ac_if;	if (ifp->if_name == 0) {		ifp->if_name = "wlp";		ifp->if_unit = sc->sc_unit;		ifp->if_ioctl = wlpioctl;		ifp->if_output = ether_output;		ifp->if_start = wlpstart;		ifp->if_watchdog = wlpwatchdog;		ifp->if_softc = sc;		ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;		if_attach(ifp);		ether_ifattach(ifp);#if NBPFILTER > 0		bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header));#endif	}	if (sc->sc_iftype == IFTYPE_REDWING) {		printf("wlp%d: address %02x:%02x:%02x:%02x:%02x:%02x\n",		       sc->sc_unit, ETHER_ADDR_FORMAT(sc->sc_ac.ac_enaddr));	} else if (sc->sc_iftype == IFTYPE_WAVELAN) {		printf("wlp%d: nwid: %x:%x, address %02x:%02x:%02x:%02x:%02x:%02x\n",		       sc->sc_unit, sc->sc_nwid[0], sc->sc_nwid[1],		       ETHER_ADDR_FORMAT(sc->sc_ac.ac_enaddr));	}	return 1;}

⌨️ 快捷键说明

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