diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c index 8cc3a18ec12b..cebe300401a6 100644 --- a/sys/compat/ndis/kern_ndis.c +++ b/sys/compat/ndis/kern_ndis.c @@ -1152,7 +1152,6 @@ ndis_halt_nic(arg) ndis_handle adapter; __stdcall ndis_halt_handler haltfunc; struct ifnet *ifp; - struct ndis_timer_entry *ne; sc = arg; ifp = &sc->arpcom.ac_if; @@ -1178,14 +1177,6 @@ ndis_halt_nic(arg) NDIS_LOCK(sc); sc->ndis_block.nmb_miniportadapterctx = NULL; NDIS_UNLOCK(sc); - /* Clobber all the timers in case the driver left one running. */ - - while (!TAILQ_EMPTY(&sc->ndis_block.nmb_timerlist)) { - ne = TAILQ_FIRST(&sc->ndis_block.nmb_timerlist); - TAILQ_REMOVE(&sc->ndis_block.nmb_timerlist, ne, link); - callout_stop(&ne->nte_ch); - free(ne, M_DEVBUF); - } return(0); } diff --git a/sys/compat/ndis/ndis_var.h b/sys/compat/ndis/ndis_var.h index 4068816b8a4a..47106d5ce1f9 100644 --- a/sys/compat/ndis/ndis_var.h +++ b/sys/compat/ndis/ndis_var.h @@ -835,7 +835,7 @@ struct ndis_kevent { }; struct ndis_event { - struct ndis_kevent ne_event; + struct nt_kevent ne_event; }; typedef struct ndis_event ndis_event; @@ -858,8 +858,8 @@ struct ndis_kdpc { }; struct ndis_timer { - struct ndis_ktimer nt_timer; - struct ndis_kdpc nt_dpc; + struct ktimer nt_ktimer; + struct kdpc nt_kdpc; }; typedef struct ndis_timer ndis_timer; @@ -867,10 +867,11 @@ typedef struct ndis_timer ndis_timer; typedef void (*ndis_timer_function)(void *, void *, void *, void *); struct ndis_miniport_timer { - struct ndis_ktimer nmt_ktimer; - struct ndis_kdpc nmt_dpc; + struct ktimer nmt_ktimer; + struct kdpc nmt_kdpc; ndis_timer_function nmt_timerfunc; void *nmt_timerctx; + ndis_miniport_block *nmt_block; struct ndis_miniport_timer *nmt_nexttimer; }; diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h index 56970c00c4c8..33e0d389eb21 100644 --- a/sys/compat/ndis/ntoskrnl_var.h +++ b/sys/compat/ndis/ntoskrnl_var.h @@ -472,7 +472,21 @@ extern struct mtx *ntoskrnl_dispatchlock; __BEGIN_DECLS extern int ntoskrnl_libinit(void); extern int ntoskrnl_libfini(void); -extern void ntoskrnl_wakeup(void *); +__stdcall extern void ntoskrnl_init_dpc(kdpc *, void *, void *); +__stdcall extern void ntoskrnl_init_timer(ktimer *); +__stdcall extern void ntoskrnl_init_timer_ex(ktimer *, uint32_t); +__stdcall extern uint8_t ntoskrnl_set_timer(ktimer *, int64_t, kdpc *); +__stdcall extern uint8_t ntoskrnl_set_timer_ex(ktimer *, int64_t, + uint32_t, kdpc *); +__stdcall extern uint8_t ntoskrnl_cancel_timer(ktimer *); +__stdcall extern uint8_t ntoskrnl_read_timer(ktimer *); +__stdcall uint32_t ntoskrnl_waitforobj(nt_dispatch_header *, uint32_t, + uint32_t, uint8_t, int64_t *); +__stdcall void ntoskrnl_init_event(nt_kevent *, uint32_t, uint8_t); +__stdcall void ntoskrnl_clear_event(nt_kevent *); +__stdcall uint32_t ntoskrnl_read_event(nt_kevent *); +__stdcall uint32_t ntoskrnl_set_event(nt_kevent *, uint32_t, uint8_t); +__stdcall uint32_t ntoskrnl_reset_event(nt_kevent *); __END_DECLS #endif /* _NTOSKRNL_VAR_H_ */ diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index 8543c8d8b0b0..9fa87e9030b3 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -148,15 +148,13 @@ static void ndis_map_cb(void *, bus_dma_segment_t *, int, int); __stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); __stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t); -__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *, +__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle, ndis_timer_function, void *); __stdcall static void ndis_init_timer(ndis_timer *, ndis_timer_function, void *); -static void ndis_timercall(void *); -__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t); -static void ndis_tick(void *); +__stdcall static void ndis_set_timer(ndis_timer *, uint32_t); __stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t); -__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *); +__stdcall static void ndis_cancel_timer(ndis_timer *, uint8_t *); __stdcall static void ndis_query_resources(ndis_status *, ndis_handle, ndis_resource_list *, uint32_t *); __stdcall static ndis_status ndis_register_ioport(void **, @@ -521,6 +519,7 @@ ndis_encode_parm(block, oid, type, parm) { uint16_t *unicode; ndis_unicode_string *ustr; + int base = 0; unicode = (uint16_t *)&block->nmb_dummybuf; @@ -533,14 +532,22 @@ ndis_encode_parm(block, oid, type, parm) ustr->nus_buf = unicode; break; case ndis_parm_int: + if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) + base = 16; + else + base = 10; (*parm)->ncp_type = ndis_parm_int; (*parm)->ncp_parmdata.ncp_intdata = - strtol((char *)oid->oid_arg1, NULL, 10); + strtol((char *)oid->oid_arg1, NULL, base); break; case ndis_parm_hexint: + if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) + base = 16; + else + base = 10; (*parm)->ncp_type = ndis_parm_hexint; (*parm)->ncp_parmdata.ncp_intdata = - strtoul((char *)oid->oid_arg1, NULL, 16); + strtoul((char *)oid->oid_arg1, NULL, base); break; default: return(NDIS_STATUS_FAILURE); @@ -936,30 +943,8 @@ ndis_init_timer(timer, func, ctx) ndis_timer_function func; void *ctx; { - struct ndis_timer_entry *ne = NULL; - ndis_miniport_block *block = NULL; - - TAILQ_FOREACH(block, &ndis_devhead, link) { - if (block->nmb_miniportadapterctx == ctx) - break; - } - - if (block->nmb_miniportadapterctx != ctx) - panic("NDIS driver timer context didn't " - "match any adapter contexts"); - - ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT); - callout_init(&ne->nte_ch, CALLOUT_MPSAFE); - TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link); - ne->nte_timer = (ndis_miniport_timer *)timer; - - INIT_LIST_HEAD((&timer->nt_timer.nk_header.dh_waitlisthead)); - timer->nt_timer.nk_header.dh_sigstate = FALSE; - timer->nt_timer.nk_header.dh_type = EVENT_TYPE_NOTIFY; - timer->nt_timer.nk_header.dh_size = OTYPE_TIMER; - timer->nt_dpc.nk_sysarg1 = &ne->nte_ch; - timer->nt_dpc.nk_deferedfunc = (ndis_kdpc_func)func; - timer->nt_dpc.nk_deferredctx = ctx; + ntoskrnl_init_timer(&timer->nt_ktimer); + ntoskrnl_init_dpc(&timer->nt_kdpc, func, ctx); return; } @@ -967,97 +952,37 @@ ndis_init_timer(timer, func, ctx) __stdcall static void ndis_create_timer(timer, handle, func, ctx) ndis_miniport_timer *timer; - ndis_handle *handle; + ndis_handle handle; ndis_timer_function func; void *ctx; { - struct ndis_timer_entry *ne = NULL; - ndis_miniport_block *block; - block = (ndis_miniport_block *)handle; + /* Save the funcptr and context */ - ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT); - callout_init(&ne->nte_ch, CALLOUT_MPSAFE); - TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link); - ne->nte_timer = timer; + timer->nmt_timerfunc = func; + timer->nmt_timerctx = ctx; + timer->nmt_block = handle; - INIT_LIST_HEAD((&timer->nmt_ktimer.nk_header.dh_waitlisthead)); - timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; - timer->nmt_ktimer.nk_header.dh_type = EVENT_TYPE_NOTIFY; - timer->nmt_ktimer.nk_header.dh_size = OTYPE_TIMER; - timer->nmt_dpc.nk_sysarg1 = &ne->nte_ch; - timer->nmt_dpc.nk_deferedfunc = (ndis_kdpc_func)func; - timer->nmt_dpc.nk_deferredctx = ctx; + ntoskrnl_init_timer(&timer->nmt_ktimer); + ntoskrnl_init_dpc(&timer->nmt_kdpc, func, ctx); return; } /* - * The driver's timer callout is __stdcall function, so we need this - * intermediate step. - */ - -static void -ndis_timercall(arg) - void *arg; -{ - ndis_miniport_timer *timer; - __stdcall ndis_timer_function timerfunc; - - timer = arg; - - timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc; - timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL); - ntoskrnl_wakeup(&timer->nmt_ktimer.nk_header); - - return; -} - -/* - * Windows specifies timeouts in milliseconds. We specify timeouts - * in hz, so some conversion is required. + * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(), + * but the former is just a macro wrapper around the latter. */ __stdcall static void ndis_set_timer(timer, msecs) - ndis_miniport_timer *timer; + ndis_timer *timer; uint32_t msecs; { - struct callout *ch; - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = msecs * 1000; - - ch = timer->nmt_dpc.nk_sysarg1; - timer->nmt_dpc.nk_sysarg2 = ndis_timercall; - timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; - callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); - - return; -} - -static void -ndis_tick(arg) - void *arg; -{ - ndis_miniport_timer *timer; - struct callout *ch; - __stdcall ndis_timer_function timerfunc; - struct timeval tv; - - timer = arg; - - /* Automatically reload timer. */ - - tv.tv_sec = 0; - tv.tv_usec = timer->nmt_ktimer.nk_period * 1000; - ch = timer->nmt_dpc.nk_sysarg1; - timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; - timer->nmt_dpc.nk_sysarg2 = ndis_tick; - callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); - - timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc; - timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL); - ntoskrnl_wakeup(&timer->nmt_ktimer.nk_header); + /* + * KeSetTimer() wants the period in + * hundred nanosecond intervals. + */ + ntoskrnl_set_timer(&timer->nt_ktimer, + ((int64_t)msecs * -10000), &timer->nt_kdpc); return; } @@ -1067,35 +992,25 @@ ndis_set_periodic_timer(timer, msecs) ndis_miniport_timer *timer; uint32_t msecs; { - struct callout *ch; - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = msecs * 1000; - - timer->nmt_ktimer.nk_period = msecs; - ch = timer->nmt_dpc.nk_sysarg1; - timer->nmt_dpc.nk_sysarg2 = ndis_tick; - timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; - callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); + ntoskrnl_set_timer_ex(&timer->nmt_ktimer, + ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc); return; } +/* + * Technically, this is really NdisCancelTimer(), but we also + * (ab)use it for NdisMCancelTimer(), since in our implementation + * we don't need the extra info in the ndis_miniport_timer + * structure. + */ + __stdcall static void ndis_cancel_timer(timer, cancelled) - ndis_miniport_timer *timer; + ndis_timer *timer; uint8_t *cancelled; { - struct callout *ch; - - if (timer == NULL) - return; - ch = timer->nmt_dpc.nk_sysarg1; - if (ch == NULL) - return; - callout_stop(ch); - *cancelled = timer->nmt_ktimer.nk_header.dh_sigstate; + *cancelled = ntoskrnl_cancel_timer(&timer->nt_ktimer); return; } @@ -1990,10 +1905,13 @@ __stdcall static void ndis_init_event(event) ndis_event *event; { - event->ne_event.nk_header.dh_sigstate = FALSE; - event->ne_event.nk_header.dh_size = OTYPE_EVENT; - event->ne_event.nk_header.dh_type = EVENT_TYPE_NOTIFY; - INIT_LIST_HEAD((&event->ne_event.nk_header.dh_waitlisthead)); + /* + * NDIS events are always synchronization + * events, and should be initialized to the + * not signaled state. + */ + + ntoskrnl_init_event(&event->ne_event, EVENT_TYPE_SYNC, FALSE); return; } @@ -2001,7 +1919,7 @@ __stdcall static void ndis_set_event(event) ndis_event *event; { - ntoskrnl_wakeup(event); + ntoskrnl_set_event(&event->ne_event, 0, 0); return; } @@ -2009,56 +1927,27 @@ __stdcall static void ndis_reset_event(event) ndis_event *event; { - event->ne_event.nk_header.dh_sigstate = FALSE; + ntoskrnl_reset_event(&event->ne_event); return; } -/* - * This is a stripped-down version of KeWaitForSingleObject(). - * Maybe it ought to just call ntoskrnl_waitforobj() to reduce - * code duplication. - */ - __stdcall static uint8_t ndis_wait_event(event, msecs) ndis_event *event; uint32_t msecs; { - int error; - struct timeval tv; - wait_block w; - struct thread *td = curthread; + int64_t duetime; + uint32_t rval; - mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock); + duetime = ((int64_t)msecs * -10000); - if (event->ne_event.nk_header.dh_sigstate == TRUE) { - mtx_pool_unlock(ndis_mtxpool, ntoskrnl_dispatchlock); - return(TRUE); - } + rval = ntoskrnl_waitforobj((nt_dispatch_header *)event, + 0, 0, TRUE, msecs ? &duetime : NULL); - INSERT_LIST_TAIL((&event->ne_event.nk_header.dh_waitlisthead), - (&w.wb_waitlist)); + if (rval == STATUS_TIMEOUT) + return(FALSE); - tv.tv_sec = 0; - tv.tv_usec = msecs * 1000; - - w.wb_kthread = td; - w.wb_object = &event->ne_event.nk_header; - - mtx_pool_unlock(ndis_mtxpool, ntoskrnl_dispatchlock); - - if (td->td_proc->p_flag & P_KTHREAD) - error = kthread_suspend(td->td_proc, tvtohz(&tv)); - else - error = tsleep(td, PPAUSE|PCATCH, "ndiswe", tvtohz(&tv)); - - mtx_pool_lock(ndis_mtxpool, ntoskrnl_dispatchlock); - - REMOVE_LIST_ENTRY((&w.wb_waitlist)); - - mtx_pool_unlock(ndis_mtxpool, ntoskrnl_dispatchlock); - - return(event->ne_event.nk_header.dh_sigstate); + return(TRUE); } __stdcall static ndis_status diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c index 18f5662a79a9..cc656c0803de 100644 --- a/sys/compat/ndis/subr_ntoskrnl.c +++ b/sys/compat/ndis/subr_ntoskrnl.c @@ -80,25 +80,11 @@ __stdcall static void *ntoskrnl_iobuildsynchfsdreq(uint32_t, void *, void *, uint32_t, uint32_t *, void *, void *); __stdcall static uint32_t ntoskrnl_iofcalldriver(/*void *, void * */ void); __stdcall static void ntoskrnl_iofcompletereq(/*void *, uint8_t*/ void); -__stdcall static uint32_t ntoskrnl_waitforobj(nt_dispatch_header *, uint32_t, - uint32_t, uint8_t, int64_t *); __stdcall static uint32_t ntoskrnl_waitforobjs(uint32_t, nt_dispatch_header **, uint32_t, uint32_t, uint32_t, uint8_t, int64_t *, wait_block *); -__stdcall static void ntoskrnl_init_event(nt_kevent *, uint32_t, uint8_t); -__stdcall static void ntoskrnl_clear_event(nt_kevent *); -__stdcall static uint32_t ntoskrnl_read_event(nt_kevent *); -__stdcall static uint32_t ntoskrnl_set_event(nt_kevent *, uint32_t, uint8_t); -__stdcall static uint32_t ntoskrnl_reset_event(nt_kevent *); +static void ntoskrnl_wakeup(void *); static void ntoskrnl_timercall(void *); -__stdcall static void ntoskrnl_init_dpc(kdpc *, void *, void *); -__stdcall static void ntoskrnl_init_timer(ktimer *); -__stdcall static void ntoskrnl_init_timer_ex(ktimer *, uint32_t); -__stdcall static uint8_t ntoskrnl_set_timer(ktimer *, int64_t, kdpc *); -__stdcall static uint8_t ntoskrnl_set_timer_ex(ktimer *, int64_t, - uint32_t, kdpc *); -__stdcall static uint8_t ntoskrnl_cancel_timer(ktimer *); -__stdcall static uint8_t ntoskrnl_read_timer(ktimer *); __stdcall static void ntoskrnl_writereg_ushort(uint16_t *, uint16_t); __stdcall static uint16_t ntoskrnl_readreg_ushort(uint16_t *); __stdcall static void ntoskrnl_writereg_ulong(uint32_t *, uint32_t); @@ -325,7 +311,7 @@ ntoskrnl_iofcompletereq(/*irp, prioboost*/) return; } -void +static void ntoskrnl_wakeup(arg) void *arg; { @@ -430,7 +416,7 @@ ntoskrnl_time(tval) * EINVAL, we need to use tsleep() instead. */ -__stdcall static uint32_t +__stdcall uint32_t ntoskrnl_waitforobj(obj, reason, mode, alertable, duetime) nt_dispatch_header *obj; uint32_t reason; @@ -1448,7 +1434,7 @@ ntoskrnl_read_mutex(kmutex) return(kmutex->km_header.dh_sigstate); } -__stdcall static void +__stdcall void ntoskrnl_init_event(kevent, type, state) nt_kevent *kevent; uint32_t type; @@ -1461,7 +1447,7 @@ ntoskrnl_init_event(kevent, type, state) return; } -__stdcall static uint32_t +__stdcall uint32_t ntoskrnl_reset_event(kevent) nt_kevent *kevent; { @@ -1475,7 +1461,7 @@ ntoskrnl_reset_event(kevent) return(prevstate); } -__stdcall static uint32_t +__stdcall uint32_t ntoskrnl_set_event(kevent, increment, kwait) nt_kevent *kevent; uint32_t increment; @@ -1489,7 +1475,7 @@ ntoskrnl_set_event(kevent, increment, kwait) return(prevstate); } -__stdcall static void +__stdcall void ntoskrnl_clear_event(kevent) nt_kevent *kevent; { @@ -1497,7 +1483,7 @@ ntoskrnl_clear_event(kevent) return; } -__stdcall static uint32_t +__stdcall uint32_t ntoskrnl_read_event(kevent) nt_kevent *kevent; { @@ -1669,7 +1655,11 @@ ntoskrnl_timercall(arg) /* * If this is a periodic timer, re-arm it - * so it will fire again. + * so it will fire again. We do this before + * calling any deferred procedure calls because + * it's possible the DPC might cancel the timer, + * in which case it would be wrong for us to + * re-arm it again afterwards. */ if (timer->k_period) { @@ -1690,7 +1680,7 @@ ntoskrnl_timercall(arg) return; } -__stdcall static void +__stdcall void ntoskrnl_init_timer(timer) ktimer *timer; { @@ -1706,7 +1696,7 @@ ntoskrnl_init_timer(timer) return; } -__stdcall static void +__stdcall void ntoskrnl_init_timer_ex(timer, type) ktimer *timer; uint32_t type; @@ -1723,7 +1713,7 @@ ntoskrnl_init_timer_ex(timer, type) return; } -__stdcall static void +__stdcall void ntoskrnl_init_dpc(dpc, dpcfunc, dpcctx) kdpc *dpc; void *dpcfunc; @@ -1738,7 +1728,7 @@ ntoskrnl_init_dpc(dpc, dpcfunc, dpcctx) return; } -__stdcall static uint8_t +__stdcall uint8_t ntoskrnl_set_timer_ex(timer, duetime, period, dpc) ktimer *timer; int64_t duetime; @@ -1784,7 +1774,7 @@ ntoskrnl_set_timer_ex(timer, duetime, period, dpc) return(pending); } -__stdcall static uint8_t +__stdcall uint8_t ntoskrnl_set_timer(timer, duetime, dpc) ktimer *timer; int64_t duetime; @@ -1793,7 +1783,7 @@ ntoskrnl_set_timer(timer, duetime, dpc) return (ntoskrnl_set_timer_ex(timer, duetime, 0, dpc)); } -__stdcall static uint8_t +__stdcall uint8_t ntoskrnl_cancel_timer(timer) ktimer *timer; { @@ -1813,7 +1803,7 @@ ntoskrnl_cancel_timer(timer) return(pending); } -__stdcall static uint8_t +__stdcall uint8_t ntoskrnl_read_timer(timer) ktimer *timer; { diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c index 75303ef1dd99..4c92c26e967b 100644 --- a/sys/dev/if_ndis/if_ndis.c +++ b/sys/dev/if_ndis/if_ndis.c @@ -1596,7 +1596,7 @@ ndis_setstate_80211(sc) ic->ic_wep_mode = IEEE80211_WEP_8021X; } #endif - arg = NDIS_80211_AUTHMODE_AUTO; + arg = NDIS_80211_AUTHMODE_OPEN; } else { arg = NDIS_80211_WEPSTAT_DISABLED; len = sizeof(arg);