diff options
Diffstat (limited to 'sys/dev/if_ndis/if_ndis.c')
-rw-r--r-- | sys/dev/if_ndis/if_ndis.c | 112 |
1 files changed, 87 insertions, 25 deletions
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index c6223db..aed5e4b 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/socket.h> #include <sys/queue.h> +#include <sys/module.h> #if __FreeBSD_version < 502113 #include <sys/sysctl.h> #endif @@ -90,6 +91,8 @@ int ndis_suspend (device_t); int ndis_resume (device_t); void ndis_shutdown (device_t); +int ndisdrv_modevent (module_t, int, void *); + static __stdcall void ndis_txeof (ndis_handle, ndis_packet *, ndis_status); static __stdcall void ndis_rxeof (ndis_handle, @@ -123,7 +126,45 @@ static void ndis_setmulti (struct ndis_softc *); static void ndis_map_sclist (void *, bus_dma_segment_t *, int, bus_size_t, int); -extern struct mtx_pool *ndis_mtxpool; +static int ndisdrv_loaded = 0; + +/* + * This routine should call windrv_load() once for each driver + * image. This will do the relocation and dynalinking for the + * image, and create a Windows driver object which will be + * saved in our driver database. + */ + +int +ndisdrv_modevent(mod, cmd, arg) + module_t mod; + int cmd; + void *arg; +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD: + ndisdrv_loaded++; + if (ndisdrv_loaded > 1) + break; + windrv_load(mod, (vm_offset_t)drv_data, 0); + break; + case MOD_UNLOAD: + ndisdrv_loaded--; + if (ndisdrv_loaded > 0) + break; + windrv_unload(mod, (vm_offset_t)drv_data, 0); + break; + case MOD_SHUTDOWN: + break; + default: + error = EINVAL; + break; + } + + return (error); +} /* * Program the 64-bit multicast hash filter. @@ -364,6 +405,8 @@ ndis_attach(dev) { u_char eaddr[ETHER_ADDR_LEN]; struct ndis_softc *sc; + driver_object *drv; + device_object *pdo; struct ifnet *ifp = NULL; void *img; int error = 0, len; @@ -407,21 +450,32 @@ ndis_attach(dev) /* Create sysctl registry nodes */ ndis_create_sysctls(sc); - /* Set up driver image in memory. */ + /* + * Create a new functional device object for this + * device. This is what creates the miniport block + * for this device instance. + */ + img = drv_data; - ndis_load_driver((vm_offset_t)img, sc); + drv = windrv_lookup((vm_offset_t)img); + pdo = windrv_find_pdo(drv, dev); + if (NdisAddDevice(drv, pdo) != STATUS_SUCCESS) { + device_printf(dev, "failed to create FDO!\n"); + error = ENXIO; + goto fail; + } /* Tell the user what version of the API the driver is using. */ device_printf(dev, "NDIS API version: %d.%d\n", - sc->ndis_chars.nmc_version_major, - sc->ndis_chars.nmc_version_minor); + sc->ndis_chars->nmc_version_major, + sc->ndis_chars->nmc_version_minor); /* Do resource conversion. */ ndis_convert_res(sc); /* Install our RX and TX interrupt handlers. */ - sc->ndis_block.nmb_senddone_func = ndis_txeof; - sc->ndis_block.nmb_pktind_func = ndis_rxeof; + sc->ndis_block->nmb_senddone_func = ndis_txeof; + sc->ndis_block->nmb_pktind_func = ndis_rxeof; /* Call driver's init routine. */ if (ndis_init_nic(sc)) { @@ -443,8 +497,8 @@ ndis_attach(dev) * with this driver, and if so, how many. */ - if (sc->ndis_chars.nmc_sendsingle_func && - sc->ndis_chars.nmc_sendmulti_func == NULL) { + if (sc->ndis_chars->nmc_sendsingle_func && + sc->ndis_chars->nmc_sendmulti_func == NULL) { sc->ndis_maxpkts = 1; } else { len = sizeof(sc->ndis_maxpkts); @@ -692,8 +746,8 @@ nonettypes: } /* Override the status handler so we can detect link changes. */ - sc->ndis_block.nmb_status_func = ndis_linksts; - sc->ndis_block.nmb_statusdone_func = ndis_linksts_done; + sc->ndis_block->nmb_status_func = ndis_linksts; + sc->ndis_block->nmb_statusdone_func = ndis_linksts_done; fail: if (error) ndis_detach(dev); @@ -717,6 +771,7 @@ ndis_detach(dev) { struct ndis_softc *sc; struct ifnet *ifp; + driver_object *drv; sc = device_get_softc(dev); KASSERT(mtx_initialized(&sc->ndis_mtx), @@ -767,6 +822,13 @@ ndis_detach(dev) ndis_unload_driver(sc); + /* Destroy the PDO for this device. */ + + drv = windrv_lookup((vm_offset_t)drv_data); + if (drv == NULL) + panic("couldn't find driver object"); + windrv_destroy_pdo(drv, dev); + if (sc->ndis_iftype == PCIBus) bus_dma_tag_destroy(sc->ndis_parent_tag); @@ -849,8 +911,8 @@ ndis_rxeof(adapter, packets, pktcnt) int i; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)(block->nmb_ifp->if_softc); - ifp = block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ifp = &sc->arpcom.ac_if; for (i = 0; i < pktcnt; i++) { p = packets[i]; @@ -927,8 +989,8 @@ ndis_txeof(adapter, packet, status) struct mbuf *m; block = (ndis_miniport_block *)adapter; - sc = (struct ndis_softc *)block->nmb_ifp->if_softc; - ifp = block->nmb_ifp; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ifp = &sc->arpcom.ac_if; m = packet->np_m0; idx = packet->np_txidx; @@ -979,8 +1041,8 @@ ndis_linksts_done(adapter) struct ifnet *ifp; block = adapter; - ifp = block->nmb_ifp; - sc = ifp->if_softc; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ifp = &sc->arpcom.ac_if; NDIS_LOCK(sc); if (!NDIS_INITIALIZED(sc)) { @@ -1038,11 +1100,11 @@ ndis_intr(arg) sc = arg; ifp = &sc->arpcom.ac_if; - if (sc->ndis_block.nmb_miniportadapterctx == NULL) + if (sc->ndis_block->nmb_miniportadapterctx == NULL) return; mtx_lock(&sc->ndis_intrmtx); - if (sc->ndis_block.nmb_interrupt->ni_isrreq == TRUE) + if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE) ndis_isr(sc, &is_our_intr, &call_isr); else { ndis_disable_intr(sc); @@ -1068,7 +1130,7 @@ ndis_tick(xsc) ndis_sched(ndis_ticktask, sc, NDIS_TASKQUEUE); sc->ndis_stat_ch = timeout(ndis_tick, sc, hz * - sc->ndis_block.nmb_checkforhangsecs); + sc->ndis_block->nmb_checkforhangsecs); mtx_lock(&Giant); @@ -1087,10 +1149,10 @@ ndis_ticktask(xsc) sc = xsc; - hangfunc = sc->ndis_chars.nmc_checkhang_func; + hangfunc = sc->ndis_chars->nmc_checkhang_func; if (hangfunc != NULL) { - rval = hangfunc(sc->ndis_block.nmb_miniportadapterctx); + rval = hangfunc(sc->ndis_block->nmb_miniportadapterctx); if (rval == TRUE) { ndis_reset_nic(sc); return; @@ -1391,11 +1453,11 @@ ndis_init(xsc) * drivers, exactly 2 seconds is too fast. */ - if (sc->ndis_block.nmb_checkforhangsecs == 0) - sc->ndis_block.nmb_checkforhangsecs = 3; + if (sc->ndis_block->nmb_checkforhangsecs == 0) + sc->ndis_block->nmb_checkforhangsecs = 3; sc->ndis_stat_ch = timeout(ndis_tick, sc, - hz * sc->ndis_block.nmb_checkforhangsecs); + hz * sc->ndis_block->nmb_checkforhangsecs); return; } |