diff options
Diffstat (limited to 'sys/compat/ndis/subr_ndis.c')
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 77 |
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; } |