diff options
author | wpaul <wpaul@FreeBSD.org> | 2004-03-07 02:49:06 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2004-03-07 02:49:06 +0000 |
commit | 7a42ffc3827e0909266974acea6d4b243a8f11b7 (patch) | |
tree | df79482d38e8f2aa0c97025e5e25560eb1179c60 /sys | |
parent | 76c408916b6540382c7b773b88040e925dd6d20c (diff) | |
download | FreeBSD-src-7a42ffc3827e0909266974acea6d4b243a8f11b7.zip FreeBSD-src-7a42ffc3827e0909266974acea6d4b243a8f11b7.tar.gz |
Add preliminary support for PCMCIA devices in addition to PCI/cardbus.
if_ndis.c has been split into if_ndis_pci.c and if_ndis_pccard.c.
The ndiscvt(8) utility should be able to parse device info for PCMCIA
devices now. The ndis_alloc_amem() has moved from kern_ndis.c to
if_ndis_pccard.c so that kern_ndis.c no longer depends on pccard.
NOTE: this stuff is not guaranteed to work 100% correctly yet. So
far I have been able to load/init my PCMCIA Cisco Aironet 340 card,
but it crashes in the interrupt handler. The existing support for
PCI/cardbus devices should still work as before.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/ndis/kern_ndis.c | 47 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 240 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis_pccard.c | 307 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndis_pci.c | 315 | ||||
-rw-r--r-- | sys/dev/if_ndis/if_ndisvar.h | 8 | ||||
-rw-r--r-- | sys/modules/if_ndis/Makefile | 2 | ||||
-rw-r--r-- | sys/modules/ndis/Makefile | 2 |
7 files changed, 650 insertions, 271 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index 68c7ef3..ec771c6 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -66,9 +66,6 @@ __FBSDID("$FreeBSD$"); #include <net80211/ieee80211_var.h> #include <net80211/ieee80211_ioctl.h> -#include <dev/pccard/pccardvar.h> -#include "card_if.h" - #include <compat/ndis/pe_var.h> #include <compat/ndis/resource_var.h> #include <compat/ndis/ntoskrnl_var.h> @@ -536,50 +533,6 @@ ndis_resetdone_func(adapter, status, addressingreset) return; } -#define NDIS_AM_RID 3 - -int -ndis_alloc_amem(arg) - void *arg; -{ - struct ndis_softc *sc; - int error, rid; - - if (arg == NULL) - return(EINVAL); - - sc = arg; - rid = NDIS_AM_RID; - sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY, - &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE); - - if (sc->ndis_res_am == NULL) { - device_printf(sc->ndis_dev, - "failed to allocate attribute memory\n"); - return(ENXIO); - } - - error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev), - sc->ndis_dev, rid, 0, NULL); - - if (error) { - device_printf(sc->ndis_dev, - "CARD_SET_MEMORY_OFFSET() returned 0x%x\n", error); - return(error); - } - - error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev), - sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); - - if (error) { - device_printf(sc->ndis_dev, - "CARD_SET_RES_FLAGS() returned 0x%x\n", error); - return(error); - } - - return(0); -} - int ndis_create_sysctls(arg) void *arg; diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index f70d2ec..e9edb8b 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -75,29 +75,16 @@ __FBSDID("$FreeBSD$"); #include <compat/ndis/cfg_var.h> #include <dev/if_ndis/if_ndisvar.h> -#include "ndis_driver_data.h" - -MODULE_DEPEND(ndis, pci, 1, 1, 1); -MODULE_DEPEND(ndis, ether, 1, 1, 1); -MODULE_DEPEND(ndis, wlan, 1, 1, 1); -MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); +#define NDIS_IMAGE +#define NDIS_REGVALS -/* - * Various supported device vendors/types and their names. - * These are defined in the ndis_driver_data.h file. - */ -static struct ndis_type ndis_devs[] = { -#ifdef NDIS_DEV_TABLE - NDIS_DEV_TABLE -#endif - { 0, 0, 0, NULL } -}; +#include "ndis_driver_data.h" -static int ndis_probe (device_t); -static int ndis_attach (device_t); -static int ndis_detach (device_t); -static int ndis_suspend (device_t); -static int ndis_resume (device_t); +int ndis_attach (device_t); +int ndis_detach (device_t); +int ndis_suspend (device_t); +int ndis_resume (device_t); +void ndis_shutdown (device_t); static __stdcall void ndis_txeof (ndis_handle, ndis_packet *, ndis_status); @@ -119,7 +106,6 @@ static int ndis_wi_ioctl_set (struct ifnet *, u_long, caddr_t); static void ndis_init (void *); static void ndis_stop (struct ndis_softc *); static void ndis_watchdog (struct ifnet *); -static void ndis_shutdown (device_t); static int ndis_ifmedia_upd (struct ifnet *); static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *); static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex *); @@ -135,42 +121,6 @@ static void ndis_map_sclist (void *, bus_dma_segment_t *, extern struct mtx_pool *ndis_mtxpool; -static device_method_t ndis_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, ndis_probe), - DEVMETHOD(device_attach, ndis_attach), - DEVMETHOD(device_detach, ndis_detach), - DEVMETHOD(device_shutdown, ndis_shutdown), - DEVMETHOD(device_suspend, ndis_suspend), - DEVMETHOD(device_resume, ndis_resume), - - { 0, 0 } -}; - -static driver_t ndis_driver = { -#ifdef NDIS_DEVNAME - NDIS_DEVNAME, -#else - "ndis", -#endif - ndis_methods, - sizeof(struct ndis_softc) -}; - -static devclass_t ndis_devclass; - -#ifdef NDIS_MODNAME -#define NDIS_MODNAME_OVERRIDE_PCI(x) \ - DRIVER_MODULE(x, pci, ndis_driver, ndis_devclass, 0, 0) -#define NDIS_MODNAME_OVERRIDE_CARDBUS(x) \ - DRIVER_MODULE(x, cardbus, ndis_driver, ndis_devclass, 0, 0) -NDIS_MODNAME_OVERRIDE_PCI(NDIS_MODNAME); -NDIS_MODNAME_OVERRIDE_CARDBUS(NDIS_MODNAME); -#else -DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, 0, 0); -DRIVER_MODULE(ndis, cardbus, ndis_driver, ndis_devclass, 0, 0); -#endif - /* * Program the 64-bit multicast hash filter. */ @@ -246,32 +196,6 @@ out: return; } -/* - * Probe for an NDIS device. Check the PCI vendor and device - * IDs against our list and return a device name if we find a match. - */ -static int -ndis_probe(dev) - device_t dev; -{ - struct ndis_type *t; - - t = ndis_devs; - - while(t->ndis_name != NULL) { - if ((pci_get_vendor(dev) == t->ndis_vid) && - (pci_get_device(dev) == t->ndis_did) && - ((pci_read_config(dev, PCIR_SUBVEND_0, 4) == - t->ndis_subsys) || t->ndis_subsys == 0)) { - device_set_desc(dev, t->ndis_name); - return(0); - } - t++; - } - - return(ENXIO); -} - static int ndis_set_offload(sc) struct ndis_softc *sc; @@ -428,105 +352,22 @@ ndis_probe_offload(sc) * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. */ -static int +int ndis_attach(dev) device_t dev; { u_char eaddr[ETHER_ADDR_LEN]; - struct ndis_softc *sc; + struct ndis_softc *sc; struct ifnet *ifp = NULL; - int unit, error = 0, rid, len; void *img; - struct ndis_type *t; - int i, devidx = 0, defidx = 0; - struct resource_list *rl; - struct resource_list_entry *rle; + int error = 0, len; + int i; sc = device_get_softc(dev); - unit = device_get_unit(dev); - sc->ndis_dev = dev; sc->ndis_mtx = mtx_pool_alloc(ndis_mtxpool); sc->ndis_intrmtx = mtx_pool_alloc(ndis_mtxpool); - /* - * Map control/status registers. - */ - - pci_enable_busmaster(dev); - - rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); - if (rl != NULL) { - SLIST_FOREACH(rle, rl, link) { - switch (rle->type) { - case SYS_RES_IOPORT: - sc->ndis_io_rid = rle->rid; - sc->ndis_res_io = bus_alloc_resource(dev, - SYS_RES_IOPORT, &sc->ndis_io_rid, - 0, ~0, 1, RF_ACTIVE); - if (sc->ndis_res_io == NULL) { - device_printf(dev, - "couldn't map iospace\n"); - error = ENXIO; - goto fail; - } - break; - case SYS_RES_MEMORY: - if (sc->ndis_res_altmem != NULL && - sc->ndis_res_mem != NULL) { - device_printf(dev, - "too many memory resources\n"); - error = ENXIO; - goto fail; - } - if (rle->rid == PCIR_BAR(2)) { - sc->ndis_altmem_rid = rle->rid; - sc->ndis_res_altmem = - bus_alloc_resource(dev, - SYS_RES_MEMORY, - &sc->ndis_altmem_rid, - 0, ~0, 1, RF_ACTIVE); - if (sc->ndis_res_altmem == NULL) { - device_printf(dev, - "couldn't map alt " - "memory\n"); - error = ENXIO; - goto fail; - } - } else { - sc->ndis_mem_rid = rle->rid; - sc->ndis_res_mem = - bus_alloc_resource(dev, - SYS_RES_MEMORY, - &sc->ndis_mem_rid, - 0, ~0, 1, RF_ACTIVE); - if (sc->ndis_res_mem == NULL) { - device_printf(dev, - "couldn't map memory\n"); - error = ENXIO; - goto fail; - } - } - break; - case SYS_RES_IRQ: - rid = rle->rid; - sc->ndis_irq = bus_alloc_resource(dev, - SYS_RES_IRQ, &rid, 0, ~0, 1, - RF_SHAREABLE | RF_ACTIVE); - if (sc->ndis_irq == NULL) { - device_printf(dev, - "couldn't map interrupt\n"); - error = ENXIO; - goto fail; - } - break; - default: - break; - } - sc->ndis_rescnt++; - } - } - /* * Hook interrupt early, since calling the driver's * init routine may trigger an interrupt. @@ -540,51 +381,7 @@ ndis_attach(dev) goto fail; } - /* - * Allocate the parent bus DMA tag appropriate for PCI. - */ -#define NDIS_NSEG_NEW 32 - error = bus_dma_tag_create(NULL, /* parent */ - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - MAXBSIZE, NDIS_NSEG_NEW,/* maxsize, nsegments */ - BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->ndis_parent_tag); - - if (error) - goto fail; - - img = drv_data; sc->ndis_regvals = ndis_regvals; - sc->ndis_iftype = PCIBus; - - /* Figure out exactly which device we matched. */ - - t = ndis_devs; - - while(t->ndis_name != NULL) { - if ((pci_get_vendor(dev) == t->ndis_vid) && - (pci_get_device(dev) == t->ndis_did)) { - if (t->ndis_subsys == 0) - defidx = devidx; - else { - if (t->ndis_subsys == - pci_read_config(dev, PCIR_SUBVEND_0, 4)) - break; - } - } - t++; - devidx++; - } - - if (ndis_devs[devidx].ndis_name == NULL) - sc->ndis_devidx = defidx; - else - sc->ndis_devidx = devidx; sysctl_ctx_init(&sc->ndis_ctx); @@ -592,6 +389,7 @@ ndis_attach(dev) ndis_create_sysctls(sc); /* Set up driver image in memory. */ + img = drv_data; ndis_load_driver((vm_offset_t)img, sc); /* Tell the user what version of the API the driver is using. */ @@ -622,7 +420,6 @@ ndis_attach(dev) len = sizeof(eaddr); ndis_get_info(sc, OID_802_3_CURRENT_ADDRESS, &eaddr, &len); - sc->ndis_unit = unit; bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN); /* @@ -900,7 +697,7 @@ fail: * to be careful about only freeing resources that have actually been * allocated. */ -static int +int ndis_detach(dev) device_t dev; { @@ -947,14 +744,15 @@ ndis_detach(dev) ndis_unload_driver((void *)ifp); - bus_dma_tag_destroy(sc->ndis_parent_tag); + if (sc->ndis_iftype == PCIBus) + bus_dma_tag_destroy(sc->ndis_parent_tag); sysctl_ctx_free(&sc->ndis_ctx); return(0); } -static int +int ndis_suspend(dev) device_t dev; { @@ -972,7 +770,7 @@ ndis_suspend(dev) return(0); } -static int +int ndis_resume(dev) device_t dev; { @@ -2241,7 +2039,7 @@ ndis_stop(sc) * Stop all chip I/O so that the kernel's probe routines don't * get confused by errant DMAs when rebooting. */ -static void +void ndis_shutdown(dev) device_t dev; { diff --git a/sys/dev/if_ndis/if_ndis_pccard.c b/sys/dev/if_ndis/if_ndis_pccard.c new file mode 100644 index 0000000..5919ae7 --- /dev/null +++ b/sys/dev/if_ndis/if_ndis_pccard.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2003 + * Bill Paul <wpaul@windriver.com>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' 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 Bill Paul OR THE VOICES IN HIS HEAD + * 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/ctype.h> +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sockio.h> +#include <sys/mbuf.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/socket.h> +#include <sys/queue.h> +#include <sys/sysctl.h> + +#include <net/if.h> +#include <net/if_arp.h> +#include <net/ethernet.h> +#include <net/if_dl.h> +#include <net/if_media.h> + +#include <net/bpf.h> + +#include <machine/bus_memio.h> +#include <machine/bus_pio.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> +#include <sys/rman.h> + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_ioctl.h> + +#include <dev/wi/if_wavelan_ieee.h> + +#include <compat/ndis/pe_var.h> +#include <compat/ndis/resource_var.h> +#include <compat/ndis/ntoskrnl_var.h> +#include <compat/ndis/ndis_var.h> +#include <compat/ndis/cfg_var.h> +#include <dev/if_ndis/if_ndisvar.h> + +#include <dev/pccard/pccardvar.h> +#include "card_if.h" + +#include "ndis_driver_data.h" + +#ifdef NDIS_PCMCIA_DEV_TABLE + +MODULE_DEPEND(ndis, pccard, 1, 1, 1); +MODULE_DEPEND(ndis, ether, 1, 1, 1); +MODULE_DEPEND(ndis, wlan, 1, 1, 1); +MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); + +/* + * Various supported device vendors/types and their names. + * These are defined in the ndis_driver_data.h file. + */ +static struct ndis_pccard_type ndis_devs[] = { +#ifdef NDIS_PCMCIA_DEV_TABLE + NDIS_PCMCIA_DEV_TABLE +#endif + { NULL, NULL, NULL } +}; + +static int ndis_probe_pccard (device_t); +static int ndis_attach_pccard (device_t); +extern int ndis_attach (device_t); +extern int ndis_shutdown (device_t); +extern int ndis_detach (device_t); +extern int ndis_suspend (device_t); +extern int ndis_resume (device_t); + +static int my_strcasecmp (const char *, const char *, int); + +extern struct mtx_pool *ndis_mtxpool; + +static device_method_t ndis_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ndis_probe_pccard), + DEVMETHOD(device_attach, ndis_attach_pccard), + DEVMETHOD(device_detach, ndis_detach), + DEVMETHOD(device_shutdown, ndis_shutdown), + DEVMETHOD(device_suspend, ndis_suspend), + DEVMETHOD(device_resume, ndis_resume), + + { 0, 0 } +}; + +static driver_t ndis_driver = { +#ifdef NDIS_DEVNAME + NDIS_DEVNAME, +#else + "ndis", +#endif + ndis_methods, + sizeof(struct ndis_softc) +}; + +static devclass_t ndis_devclass; + +#ifdef NDIS_MODNAME +#define NDIS_MODNAME_OVERRIDE_PCMCIA(x) \ + DRIVER_MODULE(x, pccard, ndis_driver, ndis_devclass, 0, 0) +NDIS_MODNAME_OVERRIDE_PCMCIA(NDIS_MODNAME); +#else +DRIVER_MODULE(ndis, pccard, ndis_driver, ndis_devclass, 0, 0); +#endif + +static int my_strcasecmp(s1, s2, len) + const char *s1; + const char *s2; + int len; +{ + int i; + + for (i = 0; i < len; i++) { + if (toupper(s1[i]) != toupper(s2[i])) + return(0); + } + + return(1); +} + + +/* + * Probe for an NDIS device. Check the PCI vendor and device + * IDs against our list and return a device name if we find a match. + */ +static int +ndis_probe_pccard(dev) + device_t dev; +{ + struct ndis_pccard_type *t; + const char *prodstr, *vendstr; + int error; + + t = ndis_devs; + + error = pccard_get_product_str(dev, &prodstr); + if (error) + return(error); + error = pccard_get_vendor_str(dev, &vendstr); + if (error) + return(error); + + while(t->ndis_name != NULL) { + if (my_strcasecmp(vendstr, t->ndis_vid, strlen(vendstr)) && + my_strcasecmp(prodstr, t->ndis_did, strlen(prodstr))) { + device_set_desc(dev, t->ndis_name); + return(0); + } + t++; + } + + return(ENXIO); +} + +/* + * Attach the interface. Allocate softc structures, do ifmedia + * setup and ethernet/BPF attach. + */ +static int +ndis_attach_pccard(dev) + device_t dev; +{ + struct ndis_softc *sc; + int unit, error = 0, rid; + struct ndis_pccard_type *t; + int devidx = 0; + const char *prodstr, *vendstr; + struct resource_list *rl; + struct resource_list_entry *rle; + + sc = device_get_softc(dev); + unit = device_get_unit(dev); + sc->ndis_dev = dev; + + sc->ndis_io_rid = 0; + sc->ndis_res_io = bus_alloc_resource(dev, + SYS_RES_IOPORT, &sc->ndis_io_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->ndis_res_io == NULL) { + device_printf(dev, + "couldn't map iospace\n"); + error = ENXIO; + goto fail; + } + sc->ndis_rescnt++; + + rid = 0; + sc->ndis_irq = bus_alloc_resource(dev, + SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (sc->ndis_irq == NULL) { + device_printf(dev, + "couldn't map interrupt\n"); + error = ENXIO; + goto fail; + } + sc->ndis_rescnt++; + + sc->ndis_iftype = PCMCIABus; + + /* Figure out exactly which device we matched. */ + + t = ndis_devs; + + error = pccard_get_product_str(dev, &prodstr); + if (error) + return(error); + error = pccard_get_vendor_str(dev, &vendstr); + if (error) + return(error); + + while(t->ndis_name != NULL) { + if (my_strcasecmp(vendstr, t->ndis_vid, strlen(vendstr)) && + my_strcasecmp(prodstr, t->ndis_did, strlen(prodstr))) + break; + t++; + devidx++; + } + + sc->ndis_devidx = devidx; + + error = ndis_attach(dev); + +fail: + return(error); +} + +#endif /* NDIS_PCI_DEV_TABLE */ + +#define NDIS_AM_RID 3 + +int +ndis_alloc_amem(arg) + void *arg; +{ + struct ndis_softc *sc; + int error, rid; + + if (arg == NULL) + return(EINVAL); + + sc = arg; + rid = NDIS_AM_RID; + sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY, + &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE); + + if (sc->ndis_res_am == NULL) { + device_printf(sc->ndis_dev, + "failed to allocate attribute memory\n"); + return(ENXIO); + } + + error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev), + sc->ndis_dev, rid, 0, NULL); + + if (error) { + device_printf(sc->ndis_dev, + "CARD_SET_MEMORY_OFFSET() returned 0x%x\n", error); + return(error); + } + + error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev), + sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); + + if (error) { + device_printf(sc->ndis_dev, + "CARD_SET_RES_FLAGS() returned 0x%x\n", error); + return(error); + } + + return(0); +} diff --git a/sys/dev/if_ndis/if_ndis_pci.c b/sys/dev/if_ndis/if_ndis_pci.c new file mode 100644 index 0000000..6b293e5 --- /dev/null +++ b/sys/dev/if_ndis/if_ndis_pci.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2003 + * Bill Paul <wpaul@windriver.com>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' 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 Bill Paul OR THE VOICES IN HIS HEAD + * 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. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/sockio.h> +#include <sys/mbuf.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/socket.h> +#include <sys/queue.h> +#include <sys/sysctl.h> + +#include <net/if.h> +#include <net/if_arp.h> +#include <net/ethernet.h> +#include <net/if_dl.h> +#include <net/if_media.h> + +#include <net/bpf.h> + +#include <machine/bus_memio.h> +#include <machine/bus_pio.h> +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> +#include <sys/rman.h> + +#include <net80211/ieee80211_var.h> +#include <net80211/ieee80211_ioctl.h> + +#include <dev/wi/if_wavelan_ieee.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> + +#include <compat/ndis/pe_var.h> +#include <compat/ndis/resource_var.h> +#include <compat/ndis/ntoskrnl_var.h> +#include <compat/ndis/ndis_var.h> +#include <compat/ndis/cfg_var.h> +#include <dev/if_ndis/if_ndisvar.h> + +#include "ndis_driver_data.h" + +#ifdef NDIS_PCI_DEV_TABLE + +MODULE_DEPEND(ndis, pci, 1, 1, 1); +MODULE_DEPEND(ndis, ether, 1, 1, 1); +MODULE_DEPEND(ndis, wlan, 1, 1, 1); +MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); + +/* + * Various supported device vendors/types and their names. + * These are defined in the ndis_driver_data.h file. + */ +static struct ndis_pci_type ndis_devs[] = { +#ifdef NDIS_PCI_DEV_TABLE + NDIS_PCI_DEV_TABLE +#endif + { 0, 0, 0, NULL } +}; + +static int ndis_probe_pci (device_t); +static int ndis_attach_pci (device_t); +extern int ndis_attach (device_t); +extern int ndis_shutdown (device_t); +extern int ndis_detach (device_t); +extern int ndis_suspend (device_t); +extern int ndis_resume (device_t); + +extern struct mtx_pool *ndis_mtxpool; + +static device_method_t ndis_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ndis_probe_pci), + DEVMETHOD(device_attach, ndis_attach_pci), + DEVMETHOD(device_detach, ndis_detach), + DEVMETHOD(device_shutdown, ndis_shutdown), + DEVMETHOD(device_suspend, ndis_suspend), + DEVMETHOD(device_resume, ndis_resume), + + { 0, 0 } +}; + +static driver_t ndis_driver = { +#ifdef NDIS_DEVNAME + NDIS_DEVNAME, +#else + "ndis", +#endif + ndis_methods, + sizeof(struct ndis_softc) +}; + +static devclass_t ndis_devclass; + +#ifdef NDIS_MODNAME +#define NDIS_MODNAME_OVERRIDE_PCI(x) \ + DRIVER_MODULE(x, pci, ndis_driver, ndis_devclass, 0, 0) +#define NDIS_MODNAME_OVERRIDE_CARDBUS(x) \ + DRIVER_MODULE(x, cardbus, ndis_driver, ndis_devclass, 0, 0) +NDIS_MODNAME_OVERRIDE_PCI(NDIS_MODNAME); +NDIS_MODNAME_OVERRIDE_CARDBUS(NDIS_MODNAME); +#else +DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, 0, 0); +DRIVER_MODULE(ndis, cardbus, ndis_driver, ndis_devclass, 0, 0); +#endif + +/* + * Probe for an NDIS device. Check the PCI vendor and device + * IDs against our list and return a device name if we find a match. + */ +static int +ndis_probe_pci(dev) + device_t dev; +{ + struct ndis_pci_type *t; + + t = ndis_devs; + + while(t->ndis_name != NULL) { + if ((pci_get_vendor(dev) == t->ndis_vid) && + (pci_get_device(dev) == t->ndis_did) && + ((pci_read_config(dev, PCIR_SUBVEND_0, 4) == + t->ndis_subsys) || t->ndis_subsys == 0)) { + device_set_desc(dev, t->ndis_name); + return(0); + } + t++; + } + + return(ENXIO); +} + +/* + * Attach the interface. Allocate softc structures, do ifmedia + * setup and ethernet/BPF attach. + */ +static int +ndis_attach_pci(dev) + device_t dev; +{ + struct ndis_softc *sc; + int unit, error = 0, rid; + struct ndis_pci_type *t; + int devidx = 0, defidx = 0; + struct resource_list *rl; + struct resource_list_entry *rle; + + sc = device_get_softc(dev); + unit = device_get_unit(dev); + sc->ndis_dev = dev; + + /* + * Map control/status registers. + */ + + pci_enable_busmaster(dev); + + rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); + if (rl != NULL) { + SLIST_FOREACH(rle, rl, link) { + switch (rle->type) { + case SYS_RES_IOPORT: + sc->ndis_io_rid = rle->rid; + sc->ndis_res_io = bus_alloc_resource(dev, + SYS_RES_IOPORT, &sc->ndis_io_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->ndis_res_io == NULL) { + device_printf(dev, + "couldn't map iospace\n"); + error = ENXIO; + goto fail; + } + break; + case SYS_RES_MEMORY: + if (sc->ndis_res_altmem != NULL && + sc->ndis_res_mem != NULL) { + device_printf(dev, + "too many memory resources\n"); + error = ENXIO; + goto fail; + } + if (rle->rid == PCIR_BAR(2)) { + sc->ndis_altmem_rid = rle->rid; + sc->ndis_res_altmem = + bus_alloc_resource(dev, + SYS_RES_MEMORY, + &sc->ndis_altmem_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->ndis_res_altmem == NULL) { + device_printf(dev, + "couldn't map alt " + "memory\n"); + error = ENXIO; + goto fail; + } + } else { + sc->ndis_mem_rid = rle->rid; + sc->ndis_res_mem = + bus_alloc_resource(dev, + SYS_RES_MEMORY, + &sc->ndis_mem_rid, + 0, ~0, 1, RF_ACTIVE); + if (sc->ndis_res_mem == NULL) { + device_printf(dev, + "couldn't map memory\n"); + error = ENXIO; + goto fail; + } + } + break; + case SYS_RES_IRQ: + rid = rle->rid; + sc->ndis_irq = bus_alloc_resource(dev, + SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (sc->ndis_irq == NULL) { + device_printf(dev, + "couldn't map interrupt\n"); + error = ENXIO; + goto fail; + } + break; + default: + break; + } + sc->ndis_rescnt++; + } + } + + /* + * Allocate the parent bus DMA tag appropriate for PCI. + */ +#define NDIS_NSEG_NEW 32 + error = bus_dma_tag_create(NULL, /* parent */ + 1, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + MAXBSIZE, NDIS_NSEG_NEW,/* maxsize, nsegments */ + BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ + BUS_DMA_ALLOCNOW, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &sc->ndis_parent_tag); + + if (error) + goto fail; + + sc->ndis_iftype = PCIBus; + + /* Figure out exactly which device we matched. */ + + t = ndis_devs; + + while(t->ndis_name != NULL) { + if ((pci_get_vendor(dev) == t->ndis_vid) && + (pci_get_device(dev) == t->ndis_did)) { + if (t->ndis_subsys == 0) + defidx = devidx; + else { + if (t->ndis_subsys == + pci_read_config(dev, PCIR_SUBVEND_0, 4)) + break; + } + } + t++; + devidx++; + } + + if (ndis_devs[devidx].ndis_name == NULL) + sc->ndis_devidx = defidx; + else + sc->ndis_devidx = devidx; + + error = ndis_attach(dev); + +fail: + return(error); +} + +#endif /* NDIS_PCI_DEV_TABLE */ diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h index e98aa0b..c2bc6b6 100644 --- a/sys/dev/if_ndis/if_ndisvar.h +++ b/sys/dev/if_ndis/if_ndisvar.h @@ -32,13 +32,19 @@ * $FreeBSD$ */ -struct ndis_type { +struct ndis_pci_type { uint16_t ndis_vid; uint16_t ndis_did; uint32_t ndis_subsys; char *ndis_name; }; +struct ndis_pccard_type { + const char *ndis_vid; + const char *ndis_did; + char *ndis_name; +}; + struct ndis_shmem { bus_dma_tag_t ndis_stag; bus_dmamap_t ndis_smap; diff --git a/sys/modules/if_ndis/Makefile b/sys/modules/if_ndis/Makefile index 40ff238..47c3bb1 100644 --- a/sys/modules/if_ndis/Makefile +++ b/sys/modules/if_ndis/Makefile @@ -3,7 +3,7 @@ .PATH: ${.CURDIR}/../../dev/if_ndis KMOD= if_ndis -SRCS= if_ndis.c +SRCS= if_ndis.c if_ndis_pci.c if_ndis_pccard.c SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h card_if.h .include <bsd.kmod.mk> diff --git a/sys/modules/ndis/Makefile b/sys/modules/ndis/Makefile index fe9d308..9d5380b 100644 --- a/sys/modules/ndis/Makefile +++ b/sys/modules/ndis/Makefile @@ -4,6 +4,6 @@ KMOD= ndis SRCS= subr_pe.c subr_ndis.c subr_hal.c subr_ntoskrnl.c kern_ndis.c -SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h card_if.h vnode_if.h +SRCS+= opt_bdg.h device_if.h bus_if.h pci_if.h vnode_if.h .include <bsd.kmod.mk> |