summaryrefslogtreecommitdiffstats
path: root/sys/compat/ndis/subr_ndis.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/compat/ndis/subr_ndis.c')
-rw-r--r--sys/compat/ndis/subr_ndis.c77
1 files changed, 76 insertions, 1 deletions
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
index e0f1f99..ac9d8da 100644
--- a/sys/compat/ndis/subr_ndis.c
+++ b/sys/compat/ndis/subr_ndis.c
@@ -95,6 +95,8 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
#include <compat/ndis/pe_var.h>
#include <compat/ndis/cfg_var.h>
@@ -302,6 +304,15 @@ static void dummy(void);
*/
#define NDIS_POOL_EXTRA 16
+struct ktimer_list {
+ ktimer *kl_timer;
+ list_entry kl_next;
+};
+
+static struct list_entry ndis_timerlist;
+static kspin_lock ndis_timerlock;
+static int ndis_isusbdev;
+
int
ndis_libinit()
{
@@ -317,6 +328,9 @@ ndis_libinit()
patch++;
}
+ KeInitializeSpinLock(&ndis_timerlock);
+ InitializeListHead(&ndis_timerlist);
+
return(0);
}
@@ -1215,6 +1229,16 @@ NdisMInitializeTimer(timer, handle, func, ctx)
ndis_timer_function func;
void *ctx;
{
+ ndis_miniport_block *block;
+ struct ktimer_list *kl;
+ struct ndis_softc *sc;
+ uint8_t irql;
+
+ block = (ndis_miniport_block *)handle;
+ sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
+ if (sc->ndis_iftype == PNPBus && ndis_isusbdev == 0)
+ ndis_isusbdev = 1;
+
/* Save the driver's funcptr and context */
timer->nmt_timerfunc = func;
@@ -1232,7 +1256,38 @@ NdisMInitializeTimer(timer, handle, func, ctx)
ndis_findwrap((funcptr)ndis_timercall), timer);
timer->nmt_ktimer.k_dpc = &timer->nmt_kdpc;
- return;
+ if (ndis_isusbdev == 1) {
+ kl = (struct ktimer_list *)malloc(sizeof(*kl), M_DEVBUF,
+ M_NOWAIT | M_ZERO);
+ if (kl == NULL)
+ panic("out of memory"); /* no way to report errors */
+
+ kl->kl_timer = &timer->nmt_ktimer;
+ KeAcquireSpinLock(&ndis_timerlock, &irql);
+ InsertHeadList((&ndis_timerlist), (&kl->kl_next));
+ KeReleaseSpinLock(&ndis_timerlock, irql);
+ }
+}
+
+void
+ndis_cancel_timerlist(void)
+{
+ list_entry *l;
+ struct ktimer_list *kl;
+ uint8_t cancelled, irql;
+
+ KeAcquireSpinLock(&ndis_timerlock, &irql);
+
+ while(!IsListEmpty(&ndis_timerlist)) {
+ l = RemoveHeadList(&ndis_timerlist);
+ kl = CONTAINING_RECORD(l, struct ktimer_list, kl_next);
+ KeReleaseSpinLock(&ndis_timerlock, irql);
+ cancelled = KeCancelTimer(kl->kl_timer);
+ free(kl, M_DEVBUF);
+ KeAcquireSpinLock(&ndis_timerlock, &irql);
+ }
+
+ KeReleaseSpinLock(&ndis_timerlock, irql);
}
/*
@@ -1277,6 +1332,26 @@ NdisMCancelTimer(timer, cancelled)
ndis_timer *timer;
uint8_t *cancelled;
{
+ list_entry *l;
+ struct ktimer_list *kl;
+ uint8_t irql;
+
+ if (ndis_isusbdev == 1) {
+ KeAcquireSpinLock(&ndis_timerlock, &irql);
+ l = ndis_timerlist.nle_flink;
+ while(l != &ndis_timerlist) {
+ kl = CONTAINING_RECORD(l, struct ktimer_list, kl_next);
+ if (kl->kl_timer == &timer->nt_ktimer) {
+ RemoveEntryList((&kl->kl_next));
+ l = l->nle_flink;
+ free(kl, M_DEVBUF);
+ continue;
+ }
+ l = l->nle_flink;
+ }
+ KeReleaseSpinLock(&ndis_timerlock, irql);
+ }
+
*cancelled = KeCancelTimer(&timer->nt_ktimer);
return;
}
OpenPOWER on IntegriCloud