diff options
Diffstat (limited to 'sys/compat/ndis/subr_ndis.c')
-rw-r--r-- | sys/compat/ndis/subr_ndis.c | 555 |
1 files changed, 330 insertions, 225 deletions
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c index 5dfe8e5..7813515 100644 --- a/sys/compat/ndis/subr_ndis.c +++ b/sys/compat/ndis/subr_ndis.c @@ -104,6 +104,13 @@ __FBSDID("$FreeBSD$"); #include <compat/ndis/ndis_var.h> #include <dev/if_ndis/if_ndisvar.h> +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <vm/uma.h> +#include <vm/vm_kern.h> +#include <vm/vm_map.h> + static char ndis_filepath[MAXPATHLEN]; extern struct nd_head ndis_devhead; @@ -124,17 +131,17 @@ static ndis_status NdisMSetAttributesEx(ndis_handle, ndis_handle, static void NdisOpenConfiguration(ndis_status *, ndis_handle *, ndis_handle); static void NdisOpenConfigurationKeyByIndex(ndis_status *, - ndis_handle, uint32_t, ndis_unicode_string *, ndis_handle *); + ndis_handle, uint32_t, unicode_string *, ndis_handle *); static void NdisOpenConfigurationKeyByName(ndis_status *, - ndis_handle, ndis_unicode_string *, ndis_handle *); + ndis_handle, unicode_string *, ndis_handle *); static ndis_status ndis_encode_parm(ndis_miniport_block *, struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); static ndis_status ndis_decode_parm(ndis_miniport_block *, ndis_config_parm *, char *); static void NdisReadConfiguration(ndis_status *, ndis_config_parm **, - ndis_handle, ndis_unicode_string *, ndis_parm_type); + ndis_handle, unicode_string *, ndis_parm_type); static void NdisWriteConfiguration(ndis_status *, ndis_handle, - ndis_unicode_string *, ndis_config_parm *); + unicode_string *, ndis_config_parm *); static void NdisCloseConfiguration(ndis_handle); static void NdisAllocateSpinLock(ndis_spin_lock *); static void NdisFreeSpinLock(ndis_spin_lock *); @@ -213,11 +220,10 @@ static void NdisInitializeEvent(ndis_event *); static void NdisSetEvent(ndis_event *); static void NdisResetEvent(ndis_event *); static uint8_t NdisWaitEvent(ndis_event *, uint32_t); -static ndis_status NdisUnicodeStringToAnsiString(ndis_ansi_string *, - ndis_unicode_string *); +static ndis_status NdisUnicodeStringToAnsiString(ansi_string *, + unicode_string *); static ndis_status - NdisAnsiStringToUnicodeString(ndis_unicode_string *, - ndis_ansi_string *); + NdisAnsiStringToUnicodeString(unicode_string *, ansi_string *); static ndis_status NdisMPciAssignResources(ndis_handle, uint32_t, ndis_resource_list **); static ndis_status NdisMRegisterInterrupt(ndis_miniport_interrupt *, @@ -248,11 +254,10 @@ static uint8_t void *, void *); static void NdisGetCurrentSystemTime(uint64_t *); static void NdisGetSystemUpTime(uint32_t *); -static void NdisInitializeString(ndis_unicode_string *, char *); -static void NdisInitAnsiString(ndis_ansi_string *, char *); -static void NdisInitUnicodeString(ndis_unicode_string *, - uint16_t *); -static void NdisFreeString(ndis_unicode_string *); +static void NdisInitializeString(unicode_string *, char *); +static void NdisInitAnsiString(ansi_string *, char *); +static void NdisInitUnicodeString(unicode_string *, uint16_t *); +static void NdisFreeString(unicode_string *); static ndis_status NdisMRemoveMiniport(ndis_handle *); static void NdisTerminateWrapper(ndis_handle, void *); static void NdisMGetDeviceProperty(ndis_handle, device_object **, @@ -264,7 +269,7 @@ static void NdisGetFirstBufferFromPacketSafe(ndis_packet *, ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t); static int ndis_find_sym(linker_file_t, char *, char *, caddr_t *); static void NdisOpenFile(ndis_status *, ndis_handle *, uint32_t *, - ndis_unicode_string *, ndis_physaddr); + unicode_string *, ndis_physaddr); static void NdisMapFile(ndis_status *, void **, ndis_handle); static void NdisUnmapFile(ndis_handle); static void NdisCloseFile(ndis_handle); @@ -272,18 +277,19 @@ static uint8_t NdisSystemProcessorCount(void); static void NdisMIndicateStatusComplete(ndis_handle); static void NdisMIndicateStatus(ndis_handle, ndis_status, void *, uint32_t); +static void ndis_intr(void *); +static void ndis_intrhand(kdpc *, ndis_miniport_interrupt *, void *, void *); static funcptr ndis_findwrap(funcptr); static void NdisCopyFromPacketToPacket(ndis_packet *, uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *); static void NdisCopyFromPacketToPacketSafe(ndis_packet *, uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t); static ndis_status NdisMRegisterDevice(ndis_handle, - ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **, + unicode_string *, unicode_string *, driver_dispatch **, void **, ndis_handle *); static ndis_status NdisMDeregisterDevice(ndis_handle); static ndis_status - NdisMQueryAdapterInstanceName(ndis_unicode_string *, - ndis_handle); + NdisMQueryAdapterInstanceName(unicode_string *, ndis_handle); static void NdisMRegisterUnloadHandler(ndis_handle, void *); static void dummy(void); @@ -346,57 +352,6 @@ ndis_findwrap(func) } /* - * NDIS deals with strings in unicode format, so we have - * do deal with them that way too. For now, we only handle - * conversion between unicode and ASCII since that's all - * that device drivers care about. - */ - -int -ndis_ascii_to_unicode(ascii, unicode) - char *ascii; - uint16_t **unicode; -{ - uint16_t *ustr; - int i; - - if (*unicode == NULL) - *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_NOWAIT); - - if (*unicode == NULL) - return(ENOMEM); - ustr = *unicode; - for (i = 0; i < strlen(ascii); i++) { - *ustr = (uint16_t)ascii[i]; - ustr++; - } - - return(0); -} - -int -ndis_unicode_to_ascii(unicode, ulen, ascii) - uint16_t *unicode; - int ulen; - char **ascii; -{ - uint8_t *astr; - int i; - - if (*ascii == NULL) - *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_NOWAIT|M_ZERO); - if (*ascii == NULL) - return(ENOMEM); - astr = *ascii; - for (i = 0; i < ulen / 2; i++) { - *astr = (uint8_t)unicode[i]; - astr++; - } - - return(0); -} - -/* * This routine does the messy Windows Driver Model device attachment * stuff on behalf of NDIS drivers. We register our own AddDevice * routine here @@ -465,8 +420,10 @@ NdisMRegisterMiniport(handle, characteristics, len) if (IoAllocateDriverObjectExtension(drv, (void *)1, sizeof(ndis_miniport_characteristics), (void **)&ch) != - STATUS_SUCCESS) + STATUS_SUCCESS) { + printf("register error\n"); return(NDIS_STATUS_RESOURCES); + } bzero((char *)ch, sizeof(ndis_miniport_characteristics)); @@ -489,10 +446,10 @@ NdisAllocateMemoryWithTag(vaddr, len, tag) { void *mem; - mem = ExAllocatePoolWithTag(NonPagedPool, len, tag); - if (mem == NULL) + if (mem == NULL) { return(NDIS_STATUS_RESOURCES); + } *vaddr = mem; return(NDIS_STATUS_SUCCESS); @@ -568,7 +525,7 @@ static void NdisOpenConfigurationKeyByName(status, cfg, subkey, subhandle) ndis_status *status; ndis_handle cfg; - ndis_unicode_string *subkey; + unicode_string *subkey; ndis_handle *subhandle; { *subhandle = cfg; @@ -582,7 +539,7 @@ NdisOpenConfigurationKeyByIndex(status, cfg, idx, subkey, subhandle) ndis_status *status; ndis_handle cfg; uint32_t idx; - ndis_unicode_string *subkey; + unicode_string *subkey; ndis_handle *subhandle; { *status = NDIS_STATUS_FAILURE; @@ -597,36 +554,58 @@ ndis_encode_parm(block, oid, type, parm) ndis_parm_type type; ndis_config_parm **parm; { - uint16_t *unicode; - ndis_unicode_string *ustr; + ndis_config_parm *p; + ndis_parmlist_entry *np; + unicode_string *us; + ansi_string as; int base = 0; + uint32_t val; + char tmp[32]; - unicode = (uint16_t *)&block->nmb_dummybuf; + np = ExAllocatePoolWithTag(NonPagedPool, + sizeof(ndis_parmlist_entry), 0); + if (np == NULL) + return(NDIS_STATUS_RESOURCES); + InsertHeadList((&block->nmb_parmlist), (&np->np_list)); + *parm = p = &np->np_parm; switch(type) { case ndis_parm_string: - ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode); - (*parm)->ncp_type = ndis_parm_string; - ustr = &(*parm)->ncp_parmdata.ncp_stringdata; - ustr->us_len = strlen((char *)oid->oid_arg1) * 2; - ustr->us_buf = unicode; + /* See if this might be a number. */ + val = strtoul((char *)oid->oid_arg1, NULL, 10); + us = &p->ncp_parmdata.ncp_stringdata; + p->ncp_type = ndis_parm_string; + if (val) { + snprintf(tmp, 32, "%x", val); + RtlInitAnsiString(&as, tmp); + } else { + RtlInitAnsiString(&as, (char *)oid->oid_arg1); + } + + if (RtlAnsiStringToUnicodeString(us, &as, TRUE)) { + ExFreePool(np); + return(NDIS_STATUS_RESOURCES); + } 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 = + p->ncp_type = ndis_parm_int; + p->ncp_parmdata.ncp_intdata = strtol((char *)oid->oid_arg1, NULL, base); break; case ndis_parm_hexint: +#ifdef notdef 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 = +#endif + base = 16; + p->ncp_type = ndis_parm_hexint; + p->ncp_parmdata.ncp_intdata = strtoul((char *)oid->oid_arg1, NULL, base); break; default: @@ -689,15 +668,15 @@ NdisReadConfiguration(status, parm, cfg, key, type) ndis_status *status; ndis_config_parm **parm; ndis_handle cfg; - ndis_unicode_string *key; + unicode_string *key; ndis_parm_type type; { char *keystr = NULL; - uint16_t *unicode; ndis_miniport_block *block; struct ndis_softc *sc; struct sysctl_oid *oidp; struct sysctl_ctx_entry *e; + ansi_string as; block = (ndis_miniport_block *)cfg; sc = device_get_softc(block->nmb_physdeviceobj->do_devext); @@ -707,10 +686,12 @@ NdisReadConfiguration(status, parm, cfg, key, type) return; } - ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr); - *parm = &block->nmb_replyparm; - bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm)); - unicode = (uint16_t *)&block->nmb_dummybuf; + if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { + *status = NDIS_STATUS_RESOURCES; + return; + } + + keystr = as.as_buf; /* * See if registry key is already in a list of known keys @@ -724,12 +705,13 @@ NdisReadConfiguration(status, parm, cfg, key, type) oidp = e->entry; if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) { if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { - free(keystr, M_DEVBUF); + RtlFreeAnsiString(&as); *status = NDIS_STATUS_FAILURE; return; } + *status = ndis_encode_parm(block, oidp, type, parm); - free(keystr, M_DEVBUF); + RtlFreeAnsiString(&as); return; } } @@ -753,7 +735,7 @@ NdisReadConfiguration(status, parm, cfg, key, type) ndis_add_sysctl(sc, keystr, "(dynamic string key)", "UNSET", CTLFLAG_RW); - free(keystr, M_DEVBUF); + RtlFreeAnsiString(&as); *status = NDIS_STATUS_FAILURE; return; @@ -765,15 +747,16 @@ ndis_decode_parm(block, parm, val) ndis_config_parm *parm; char *val; { - ndis_unicode_string *ustr; - char *astr = NULL; + unicode_string *ustr; + ansi_string as; switch(parm->ncp_type) { case ndis_parm_string: ustr = &parm->ncp_parmdata.ncp_stringdata; - ndis_unicode_to_ascii(ustr->us_buf, ustr->us_len, &astr); - bcopy(astr, val, 254); - free(astr, M_DEVBUF); + if (RtlUnicodeStringToAnsiString(&as, ustr, TRUE)) + return(NDIS_STATUS_RESOURCES); + bcopy(as.as_buf, val, as.as_len); + RtlFreeAnsiString(&as); break; case ndis_parm_int: sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata); @@ -792,9 +775,10 @@ static void NdisWriteConfiguration(status, cfg, key, parm) ndis_status *status; ndis_handle cfg; - ndis_unicode_string *key; + unicode_string *key; ndis_config_parm *parm; { + ansi_string as; char *keystr = NULL; ndis_miniport_block *block; struct ndis_softc *sc; @@ -805,13 +789,18 @@ NdisWriteConfiguration(status, cfg, key, parm) block = (ndis_miniport_block *)cfg; sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr); + if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { + *status = NDIS_STATUS_RESOURCES; + return; + } + + keystr = as.as_buf; /* Decode the parameter into a string. */ bzero(val, sizeof(val)); *status = ndis_decode_parm(block, parm, val); if (*status != NDIS_STATUS_SUCCESS) { - free(keystr, M_DEVBUF); + RtlFreeAnsiString(&as); return; } @@ -826,7 +815,7 @@ NdisWriteConfiguration(status, cfg, key, parm) if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) { /* Found it, set the value. */ strcpy((char *)oidp->oid_arg1, val); - free(keystr, M_DEVBUF); + RtlFreeAnsiString(&as); return; } } @@ -835,7 +824,7 @@ NdisWriteConfiguration(status, cfg, key, parm) ndis_add_sysctl(sc, keystr, "(dynamically set key)", val, CTLFLAG_RW); - free(keystr, M_DEVBUF); + RtlFreeAnsiString(&as); *status = NDIS_STATUS_SUCCESS; return; } @@ -844,6 +833,22 @@ static void NdisCloseConfiguration(cfg) ndis_handle cfg; { + list_entry *e; + ndis_parmlist_entry *pe; + ndis_miniport_block *block; + ndis_config_parm *p; + + block = (ndis_miniport_block *)cfg; + + while (!IsListEmpty(&block->nmb_parmlist)) { + e = RemoveHeadList(&block->nmb_parmlist); + pe = CONTAINING_RECORD(e, ndis_parmlist_entry, np_list); + p = &pe->np_parm; + if (p->ncp_type == ndis_parm_string) + RtlFreeUnicodeString(&p->ncp_parmdata.ncp_stringdata); + ExFreePool(e); + } + return; } @@ -1038,6 +1043,7 @@ NdisWritePciSlotInformation(adapter, slot, offset, buf, len) * The errorlog routine uses a variable argument list, so we * have to declare it this way. */ + #define ERRMSGLEN 512 static void NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, @@ -1046,13 +1052,15 @@ NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, ndis_miniport_block *block; va_list ap; int i, error; - char *str = NULL, *ustr = NULL; + char *str = NULL; uint16_t flags; char msgbuf[ERRMSGLEN]; device_t dev; driver_object *drv; struct ndis_softc *sc; struct ifnet *ifp; + unicode_string us; + ansi_string as; block = (ndis_miniport_block *)adapter; dev = block->nmb_physdeviceobj->do_devext; @@ -1064,10 +1072,10 @@ NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, code, &str, &i, &flags); if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE && ifp->if_flags & IFF_DEBUG) { - ustr = msgbuf; - ndis_unicode_to_ascii((uint16_t *)str, - ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr); - str = ustr; + RtlInitUnicodeString(&us, (uint16_t *)msgbuf); + if (RtlUnicodeStringToAnsiString(&as, &us, TRUE)) + return; + str = as.as_buf; } device_printf (dev, "NDIS ERROR: %x (%s)\n", code, @@ -1082,6 +1090,9 @@ NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, va_end(ap); } + if (str != NULL) + RtlFreeAnsiString(&as); + return; } @@ -1404,10 +1415,18 @@ NdisReadNetworkAddress(status, addr, addrlen, adapter) block = (ndis_miniport_block *)adapter; sc = device_get_softc(block->nmb_physdeviceobj->do_devext); +#ifdef IFP2ENADDR if (bcmp(IFP2ENADDR(sc->ifp), empty, ETHER_ADDR_LEN) == 0) +#else + if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0) +#endif *status = NDIS_STATUS_FAILURE; else { +#ifdef IFP2ENADDR *addr = IFP2ENADDR(sc->ifp); +#else + *addr = sc->arpcom.ac_enaddr; +#endif *addrlen = ETHER_ADDR_LEN; *status = NDIS_STATUS_SUCCESS; } @@ -1530,6 +1549,8 @@ NdisMAllocateSharedMemory(adapter, len, cached, vaddr, paddr) if (sh == NULL) return; + InitializeListHead(&sh->ndis_list); + /* * When performing shared memory allocations, create a tag * with a lowaddr limit that restricts physical memory mappings @@ -1582,10 +1603,11 @@ NdisMAllocateSharedMemory(adapter, len, cached, vaddr, paddr) * searching based on the virtual address fails. */ + NDIS_LOCK(sc); sh->ndis_paddr.np_quad = paddr->np_quad; sh->ndis_saddr = *vaddr; - sh->ndis_next = sc->ndis_shlist; - sc->ndis_shlist = sh; + InsertHeadList((&sc->ndis_shlist), (&sh->ndis_list)); + NDIS_UNLOCK(sc); return; } @@ -1674,21 +1696,24 @@ NdisMFreeSharedMemory(adapter, len, cached, vaddr, paddr) { ndis_miniport_block *block; struct ndis_softc *sc; - struct ndis_shmem *sh, *prev; + struct ndis_shmem *sh = NULL; + list_entry *l; if (vaddr == NULL || adapter == NULL) return; block = (ndis_miniport_block *)adapter; sc = device_get_softc(block->nmb_physdeviceobj->do_devext); - sh = prev = sc->ndis_shlist; /* Sanity check: is list empty? */ - if (sh == NULL) + if (IsListEmpty(&sc->ndis_shlist)) return; - while (sh) { + NDIS_LOCK(sc); + l = sc->ndis_shlist.nle_flink; + while (l != &sc->ndis_shlist) { + sh = CONTAINING_RECORD(l, struct ndis_shmem, ndis_list); if (sh->ndis_saddr == vaddr) break; /* @@ -1697,26 +1722,25 @@ NdisMFreeSharedMemory(adapter, len, cached, vaddr, paddr) */ if (sh->ndis_paddr.np_quad == paddr.np_quad) break; - prev = sh; - sh = sh->ndis_next; + l = l->nle_flink; } if (sh == NULL) { + NDIS_UNLOCK(sc); printf("NDIS: buggy driver tried to free " "invalid shared memory: vaddr: %p paddr: 0x%jx\n", vaddr, (uintmax_t)paddr.np_quad); return; } + RemoveEntryList(&sh->ndis_list); + + NDIS_UNLOCK(sc); + bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); bus_dmamem_free(sh->ndis_stag, sh->ndis_saddr, sh->ndis_smap); bus_dma_tag_destroy(sh->ndis_stag); - if (sh == sc->ndis_shlist) - sc->ndis_shlist = sh->ndis_next; - else - prev->ndis_next = sh->ndis_next; - free(sh, M_DEVBUF); return; @@ -2077,6 +2101,7 @@ NdisAllocateBufferPool(status, pool, descnum) ndis_handle *pool; uint32_t descnum; { + /* * The only thing we can really do here is verify that descnum * is a reasonable value, but I really don't know what to check @@ -2111,6 +2136,8 @@ NdisAllocateBuffer(status, buffer, pool, vaddr, len) return; } + MmBuildMdlForNonPagedPool(buf); + *buffer = buf; *status = NDIS_STATUS_SUCCESS; @@ -2260,37 +2287,35 @@ NdisWaitEvent(event, msecs) static ndis_status NdisUnicodeStringToAnsiString(dstr, sstr) - ndis_ansi_string *dstr; - ndis_unicode_string *sstr; + ansi_string *dstr; + unicode_string *sstr; { - if (dstr == NULL || sstr == NULL) - return(NDIS_STATUS_FAILURE); - if (ndis_unicode_to_ascii(sstr->us_buf, - sstr->us_len, &dstr->nas_buf)) + uint32_t rval; + + rval = RtlUnicodeStringToAnsiString(dstr, sstr, FALSE); + + if (rval == STATUS_INSUFFICIENT_RESOURCES) + return(NDIS_STATUS_RESOURCES); + if (rval) return(NDIS_STATUS_FAILURE); - dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf); + return (NDIS_STATUS_SUCCESS); } static ndis_status NdisAnsiStringToUnicodeString(dstr, sstr) - ndis_unicode_string *dstr; - ndis_ansi_string *sstr; + unicode_string *dstr; + ansi_string *sstr; { - char *str; - if (dstr == NULL || sstr == NULL) - return(NDIS_STATUS_FAILURE); - str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT); - if (str == NULL) - return(NDIS_STATUS_FAILURE); - strncpy(str, sstr->nas_buf, sstr->nas_len); - *(str + sstr->nas_len) = '\0'; - if (ndis_ascii_to_unicode(str, &dstr->us_buf)) { - free(str, M_DEVBUF); + uint32_t rval; + + rval = RtlAnsiStringToUnicodeString(dstr, sstr, FALSE); + + if (rval == STATUS_INSUFFICIENT_RESOURCES) + return(NDIS_STATUS_RESOURCES); + if (rval) return(NDIS_STATUS_FAILURE); - } - dstr->us_len = dstr->us_maxlen = sstr->nas_len * 2; - free(str, M_DEVBUF); + return (NDIS_STATUS_SUCCESS); } @@ -2311,6 +2336,77 @@ NdisMPciAssignResources(adapter, slot, list) return (NDIS_STATUS_SUCCESS); } +static void +ndis_intr(arg) + void *arg; +{ + struct ndis_softc *sc; + struct ifnet *ifp; + int is_our_intr = 0; + int call_isr = 0; + ndis_miniport_interrupt *intr; + + sc = arg; + ifp = sc->ifp; + intr = sc->ndis_block->nmb_interrupt; + + if (intr == NULL || sc->ndis_block->nmb_miniportadapterctx == NULL) + return; + + if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE) + ndis_isr(sc, &is_our_intr, &call_isr); + else { + ndis_disable_intr(sc); + call_isr = 1; + } + + if ((is_our_intr || call_isr)) + IoRequestDpc(sc->ndis_block->nmb_deviceobj, NULL, sc); + + return; +} + +static void +ndis_intrhand(dpc, intr, sysarg1, sysarg2) + kdpc *dpc; + ndis_miniport_interrupt *intr; + void *sysarg1; + void *sysarg2; +{ + struct ndis_softc *sc; + ndis_miniport_block *block; + ndis_handle adapter; + + block = intr->ni_block; + adapter = block->nmb_miniportadapterctx; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + + if (NDIS_SERIALIZED(sc->ndis_block)) + KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); + + MSCALL1(intr->ni_isrfunc, adapter); + + /* If there's a MiniportEnableInterrupt() routine, call it. */ + + ndis_enable_intr(sc); + + if (NDIS_SERIALIZED(sc->ndis_block)) + KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); + + /* + * Set the completion event if we've drained all + * pending interrupts. + */ + + KeAcquireSpinLockAtDpcLevel(&intr->ni_dpccountlock); + intr->ni_dpccnt--; + if (intr->ni_dpccnt == 0) + KeSetEvent(&intr->ni_dpcevt, IO_NO_INCREMENT, FALSE); + KeReleaseSpinLockFromDpcLevel(&intr->ni_dpccountlock); + + return; +} + static ndis_status NdisMRegisterInterrupt(intr, adapter, ivec, ilevel, reqisr, shared, imode) ndis_miniport_interrupt *intr; @@ -2322,15 +2418,40 @@ NdisMRegisterInterrupt(intr, adapter, ivec, ilevel, reqisr, shared, imode) ndis_interrupt_mode imode; { ndis_miniport_block *block; + ndis_miniport_characteristics *ch; + struct ndis_softc *sc; + int error; block = adapter; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + ch = IoGetDriverObjectExtension(block->nmb_deviceobj->do_drvobj, + (void *)1); + + intr->ni_rsvd = ExAllocatePoolWithTag(NonPagedPool, + sizeof(struct mtx), 0); + if (intr->ni_rsvd == NULL) + return(NDIS_STATUS_RESOURCES); intr->ni_block = adapter; intr->ni_isrreq = reqisr; intr->ni_shared = shared; - block->nmb_interrupt = intr; + intr->ni_dpccnt = 0; + intr->ni_isrfunc = ch->nmc_interrupt_func; + intr->ni_dpcfunc = ch->nmc_isr_func; + + KeInitializeEvent(&intr->ni_dpcevt, EVENT_TYPE_NOTIFY, TRUE); + KeInitializeDpc(&intr->ni_dpc, + ndis_findwrap((funcptr)ndis_intrhand), intr); + KeSetImportanceDpc(&intr->ni_dpc, KDPC_IMPORTANCE_LOW); - KeInitializeSpinLock(&intr->ni_dpccountlock); + error = IoConnectInterrupt(&intr->ni_introbj, + ndis_findwrap((funcptr)ndis_intr), sc, NULL, + ivec, ilevel, 0, imode, shared, 0, FALSE); + + if (error != STATUS_SUCCESS) + return(NDIS_STATUS_FAILURE); + + block->nmb_interrupt = intr; return(NDIS_STATUS_SUCCESS); } @@ -2339,6 +2460,29 @@ static void NdisMDeregisterInterrupt(intr) ndis_miniport_interrupt *intr; { + ndis_miniport_block *block; + struct ndis_softc *sc; + uint8_t irql; + + block = intr->ni_block; + sc = device_get_softc(block->nmb_physdeviceobj->do_devext); + + /* Should really be KeSynchronizeExecution() */ + + KeAcquireSpinLock(intr->ni_introbj->ki_lock, &irql); + block->nmb_interrupt = NULL; + KeReleaseSpinLock(intr->ni_introbj->ki_lock, irql); +/* + KeFlushQueuedDpcs(); +*/ + /* Disconnect our ISR */ + + IoDisconnectInterrupt(intr->ni_introbj); + + KeWaitForSingleObject((nt_dispatch_header *)&intr->ni_dpcevt, + 0, 0, FALSE, NULL); + KeResetEvent(&intr->ni_dpcevt); + return; } @@ -2429,23 +2573,22 @@ static void NdisMSleep(usecs) uint32_t usecs; { - struct timeval tv; + ktimer timer; /* * During system bootstrap, (i.e. cold == 1), we aren't - * allowed to msleep(), so calling ndis_thsuspend() here - * will return 0, and we won't actually have delayed. This - * is a problem because some drivers expect NdisMSleep() - * to always wait, and might fail if the expected delay - * period does not in fact elapse. As a workaround, if the - * attempt to sleep delay fails, we do a hard DELAY() instead. + * allowed to sleep, so we have to do a hard DELAY() + * instead. */ - tv.tv_sec = 0; - tv.tv_usec = usecs; - if (ndis_thsuspend(curthread->td_proc, NULL, tvtohz(&tv)) == 0) + if (cold) DELAY(usecs); - + else { + KeInitializeTimer(&timer); + KeSetTimer(&timer, ((int64_t)usecs * -10), NULL); + KeWaitForSingleObject((nt_dispatch_header *)&timer, + 0, 0, FALSE, NULL); + } return; } @@ -2571,19 +2714,7 @@ NdisMSynchronizeWithInterrupt(intr, syncfunc, syncctx) void *syncfunc; void *syncctx; { - uint8_t (*sync)(void *); - uint8_t rval; - uint8_t irql; - - if (syncfunc == NULL || syncctx == NULL) - return(0); - - sync = syncfunc; - KeAcquireSpinLock(&intr->ni_dpccountlock, &irql); - rval = MSCALL1(sync, syncctx); - KeReleaseSpinLock(&intr->ni_dpccountlock, irql); - - return(rval); + return(KeSynchronizeExecution(intr->ni_introbj, syncfunc, syncctx)); } /* @@ -2620,28 +2751,20 @@ NdisGetSystemUpTime(tval) static void NdisInitializeString(dst, src) - ndis_unicode_string *dst; + unicode_string *dst; char *src; { - ndis_unicode_string *u; - - u = dst; - u->us_buf = NULL; - if (ndis_ascii_to_unicode(src, &u->us_buf)) - return; - u->us_len = u->us_maxlen = strlen(src) * 2; + ansi_string as; + RtlInitAnsiString(&as, src); + RtlAnsiStringToUnicodeString(dst, &as, TRUE); return; } static void NdisFreeString(str) - ndis_unicode_string *str; + unicode_string *str; { - if (str == NULL) - return; - if (str->us_buf != NULL) - free(str->us_buf, M_DEVBUF); - free(str, M_DEVBUF); + RtlFreeUnicodeString(str); return; } @@ -2654,47 +2777,19 @@ NdisMRemoveMiniport(adapter) static void NdisInitAnsiString(dst, src) - ndis_ansi_string *dst; + ansi_string *dst; char *src; { - ndis_ansi_string *a; - - a = dst; - if (a == NULL) - return; - if (src == NULL) { - a->nas_len = a->nas_maxlen = 0; - a->nas_buf = NULL; - } else { - a->nas_buf = src; - a->nas_len = a->nas_maxlen = strlen(src); - } - + RtlInitAnsiString(dst, src); return; } static void NdisInitUnicodeString(dst, src) - ndis_unicode_string *dst; + unicode_string *dst; uint16_t *src; { - ndis_unicode_string *u; - int i; - - u = dst; - if (u == NULL) - return; - if (src == NULL) { - u->us_len = u->us_maxlen = 0; - u->us_buf = NULL; - } else { - i = 0; - while(src[i] != 0) - i++; - u->us_buf = src; - u->us_len = u->us_maxlen = i * 2; - } - + RtlInitUnicodeString(dst, src); return; } @@ -2806,9 +2901,10 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr) ndis_status *status; ndis_handle *filehandle; uint32_t *filelength; - ndis_unicode_string *filename; + unicode_string *filename; ndis_physaddr highestaddr; { + ansi_string as; char *afilename = NULL; struct thread *td = curthread; struct nameidata nd; @@ -2820,8 +2916,13 @@ NdisOpenFile(status, filehandle, filelength, filename, highestaddr) linker_file_t head, lf; caddr_t kldstart, kldend; - ndis_unicode_to_ascii(filename->us_buf, - filename->us_len, &afilename); + if (RtlUnicodeStringToAnsiString(&as, filename, TRUE)) { + *status = NDIS_STATUS_RESOURCES; + return; + } + + afilename = strdup(as.as_buf, M_DEVBUF); + RtlFreeAnsiString(&as); fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0); if (fh == NULL) { @@ -3120,6 +3221,7 @@ NdisScheduleWorkItem(work) ExInitializeWorkItem(wqi, (work_item_func)work->nwi_func, work->nwi_ctx); ExQueueWorkItem(wqi, WORKQUEUE_DELAYED); + return(NDIS_STATUS_SUCCESS); } @@ -3230,8 +3332,8 @@ NdisCopyFromPacketToPacketSafe(dpkt, doff, reqlen, spkt, soff, cpylen, prio) static ndis_status NdisMRegisterDevice(handle, devname, symname, majorfuncs, devobj, devhandle) ndis_handle handle; - ndis_unicode_string *devname; - ndis_unicode_string *symname; + unicode_string *devname; + unicode_string *symname; driver_dispatch *majorfuncs[]; void **devobj; ndis_handle *devhandle; @@ -3260,18 +3362,19 @@ NdisMDeregisterDevice(handle) static ndis_status NdisMQueryAdapterInstanceName(name, handle) - ndis_unicode_string *name; + unicode_string *name; ndis_handle handle; { ndis_miniport_block *block; device_t dev; + ansi_string as; block = (ndis_miniport_block *)handle; dev = block->nmb_physdeviceobj->do_devext; - ndis_ascii_to_unicode(__DECONST(char *, - device_get_nameunit(dev)), &name->us_buf); - name->us_len = strlen(device_get_nameunit(dev)) * 2; + RtlInitAnsiString(&as, __DECONST(char *, device_get_nameunit(dev))); + if (RtlAnsiStringToUnicodeString(name, &as, TRUE)) + return(NDIS_STATUS_RESOURCES); return(NDIS_STATUS_SUCCESS); } @@ -3422,6 +3525,8 @@ image_patch_table ndis_functbl[] = { IMPORT_SFUNC(NdisMRegisterUnloadHandler, 2), IMPORT_SFUNC(ndis_timercall, 4), IMPORT_SFUNC(ndis_asyncmem_complete, 2), + IMPORT_SFUNC(ndis_intr, 1), + IMPORT_SFUNC(ndis_intrhand, 4), /* * This last entry is a catch-all for any function we haven't |