summaryrefslogtreecommitdiffstats
path: root/sys/dev/if_ndis/if_ndis.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/if_ndis/if_ndis.c')
-rw-r--r--sys/dev/if_ndis/if_ndis.c112
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;
}
OpenPOWER on IntegriCloud