[BACK]Return to subr_ndis.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / compat / ndis

Annotation of src/sys/compat/ndis/subr_ndis.c, Revision 1.15

1.1       rittera     1: /*-
                      2:  * Copyright (c) 2003
                      3:  *     Bill Paul <wpaul@windriver.com>.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by Bill Paul.
                     16:  * 4. Neither the name of the author nor the names of any co-contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     30:  * THE POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: #include <sys/cdefs.h>
1.2       rittera    34: #ifdef __FreeBSD__
1.1       rittera    35: __FBSDID("$FreeBSD: src/sys/compat/ndis/subr_ndis.c,v 1.67.2.7 2005/03/31 21:50:11 wpaul Exp $");
1.2       rittera    36: #endif
                     37: #ifdef __NetBSD__
1.15    ! dsl        38: __KERNEL_RCSID(0, "$NetBSD: subr_ndis.c,v 1.14 2008/11/13 12:09:52 ad Exp $");
1.2       rittera    39: #endif
1.1       rittera    40:
                     41: /*
                     42:  * This file implements a translation layer between the BSD networking
                     43:  * infrasturcture and Windows(R) NDIS network driver modules. A Windows
                     44:  * NDIS driver calls into several functions in the NDIS.SYS Windows
                     45:  * kernel module and exports a table of functions designed to be called
                     46:  * by the NDIS subsystem. Using the PE loader, we can patch our own
                     47:  * versions of the NDIS routines into a given Windows driver module and
                     48:  * convince the driver that it is in fact running on Windows.
                     49:  *
                     50:  * We provide a table of all our implemented NDIS routines which is patched
                     51:  * into the driver object code. All our exported routines must use the
                     52:  * _stdcall calling convention, since that's what the Windows object code
                     53:  * expects.
                     54:  */
                     55:
1.2       rittera    56: #ifdef __FreeBSD__
1.1       rittera    57: #include <sys/ctype.h>
1.2       rittera    58: #endif
1.1       rittera    59: #include <sys/param.h>
                     60: #include <sys/types.h>
                     61: #include <sys/errno.h>
                     62:
                     63: #include <sys/callout.h>
                     64: #include <sys/kernel.h>
                     65: #include <sys/systm.h>
                     66: #include <sys/malloc.h>
                     67: #include <sys/lock.h>
1.2       rittera    68: #ifdef __FreeBSD__
1.1       rittera    69: #include <sys/mutex.h>
1.2       rittera    70: #endif
1.1       rittera    71: #include <sys/socket.h>
                     72: #include <sys/sysctl.h>
1.2       rittera    73: #ifdef __FreeBSD__
1.1       rittera    74: #include <sys/timespec.h>
                     75: #include <sys/smp.h>
1.2       rittera    76: #endif
1.1       rittera    77: #include <sys/queue.h>
                     78: #include <sys/proc.h>
                     79: #include <sys/filedesc.h>
                     80: #include <sys/namei.h>
                     81: #include <sys/fcntl.h>
                     82: #include <sys/vnode.h>
                     83: #include <sys/kthread.h>
1.2       rittera    84: #ifdef __FreeBSD__
1.1       rittera    85: #include <sys/linker.h>
1.2       rittera    86: #include <sys/sysproto.h>
                     87: #endif
1.1       rittera    88: #include <sys/mount.h>
                     89:
                     90: #include <net/if.h>
                     91: #include <net/if_arp.h>
1.2       rittera    92: #ifdef __FreeBSD__
1.1       rittera    93: #include <net/ethernet.h>
1.2       rittera    94: #else
                     95: #include <net/if_ether.h>
                     96: #endif
1.1       rittera    97: #include <net/if_dl.h>
                     98: #include <net/if_media.h>
                     99:
1.11      ad        100: #include <sys/atomic.h>
1.2       rittera   101: #ifdef __FreeBSD__
1.1       rittera   102: #include <machine/bus_memio.h>
                    103: #include <machine/bus_pio.h>
                    104: #include <machine/resource.h>
                    105: #include <sys/bus.h>
                    106: #include <sys/rman.h>
1.2       rittera   107: #endif
1.10      ad        108: #include <sys/bus.h>
1.1       rittera   109:
                    110: #include <machine/stdarg.h>
                    111:
                    112: #include <net80211/ieee80211_var.h>
                    113: #include <net80211/ieee80211_ioctl.h>
                    114:
                    115: #include <dev/pci/pcireg.h>
                    116: #include <dev/pci/pcivar.h>
                    117:
                    118: #include <compat/ndis/pe_var.h>
                    119: #include <compat/ndis/resource_var.h>
                    120: #include <compat/ndis/ntoskrnl_var.h>
                    121: #include <compat/ndis/hal_var.h>
                    122: #include <compat/ndis/ndis_var.h>
                    123: #include <compat/ndis/cfg_var.h>
                    124: #include <dev/if_ndis/if_ndisvar.h>
                    125:
1.3       rittera   126: #ifdef __NetBSD__
                    127: #include "nbcompat.h"
                    128: #endif
                    129:
                    130: #ifdef __NetBSD__
                    131: #define PN(name) /* printf(#name "\n"); */
                    132: #endif
                    133:
1.1       rittera   134: static char ndis_filepath[MAXPATHLEN];
                    135: extern struct nd_head ndis_devhead;
                    136:
1.2       rittera   137: #ifdef __FreeBSD__
1.1       rittera   138: SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
                    139:         MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
1.2       rittera   140: #endif
1.1       rittera   141:
                    142: __stdcall static void NdisInitializeWrapper(ndis_handle *,
                    143:        driver_object *, void *, void *);
                    144: __stdcall static ndis_status NdisMRegisterMiniport(ndis_handle,
                    145:        ndis_miniport_characteristics *, int);
                    146: __stdcall static ndis_status NdisAllocateMemoryWithTag(void **,
                    147:        uint32_t, uint32_t);
                    148: __stdcall static ndis_status NdisAllocateMemory(void **,
                    149:        uint32_t, uint32_t, ndis_physaddr);
                    150: __stdcall static void NdisFreeMemory(void *, uint32_t, uint32_t);
                    151: __stdcall static ndis_status NdisMSetAttributesEx(ndis_handle, ndis_handle,
                    152:        uint32_t, uint32_t, ndis_interface_type);
                    153: __stdcall static void NdisOpenConfiguration(ndis_status *,
                    154:        ndis_handle *, ndis_handle);
                    155: __stdcall static void NdisOpenConfigurationKeyByIndex(ndis_status *,
                    156:        ndis_handle, uint32_t, ndis_unicode_string *, ndis_handle *);
                    157: __stdcall static void NdisOpenConfigurationKeyByName(ndis_status *,
                    158:        ndis_handle, ndis_unicode_string *, ndis_handle *);
1.2       rittera   159: #ifdef __FreeBSD__
1.1       rittera   160: static ndis_status ndis_encode_parm(ndis_miniport_block *,
                    161:        struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
                    162: static ndis_status ndis_decode_parm(ndis_miniport_block *,
                    163:        ndis_config_parm *, char *);
1.3       rittera   164: #else /* __NetBSD__ */
                    165: static ndis_status ndis_encode_parm(ndis_miniport_block *,
                    166:        void *, ndis_parm_type, ndis_config_parm **);
                    167: #endif
1.1       rittera   168: __stdcall static void NdisReadConfiguration(ndis_status *, ndis_config_parm **,
                    169:        ndis_handle, ndis_unicode_string *, ndis_parm_type);
                    170: __stdcall static void NdisWriteConfiguration(ndis_status *, ndis_handle,
                    171:        ndis_unicode_string *, ndis_config_parm *);
                    172: __stdcall static void NdisCloseConfiguration(ndis_handle);
                    173: __stdcall static void NdisAllocateSpinLock(ndis_spin_lock *);
                    174: __stdcall static void NdisFreeSpinLock(ndis_spin_lock *);
                    175: __stdcall static void NdisAcquireSpinLock(ndis_spin_lock *);
                    176: __stdcall static void NdisReleaseSpinLock(ndis_spin_lock *);
                    177: __stdcall static void NdisDprAcquireSpinLock(ndis_spin_lock *);
                    178: __stdcall static void NdisDprReleaseSpinLock(ndis_spin_lock *);
                    179: __stdcall static uint32_t NdisReadPciSlotInformation(ndis_handle, uint32_t,
                    180:        uint32_t, void *, uint32_t);
                    181: __stdcall static uint32_t NdisWritePciSlotInformation(ndis_handle, uint32_t,
                    182:        uint32_t, void *, uint32_t);
                    183: static void NdisWriteErrorLogEntry(ndis_handle, ndis_error_code, uint32_t, ...);
                    184: static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
                    185: __stdcall static void NdisMStartBufferPhysicalMapping(ndis_handle,
                    186:        ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
                    187: __stdcall static void NdisMCompleteBufferPhysicalMapping(ndis_handle,
                    188:        ndis_buffer *, uint32_t);
                    189: __stdcall static void NdisMInitializeTimer(ndis_miniport_timer *, ndis_handle,
                    190:        ndis_timer_function, void *);
                    191: __stdcall static void NdisInitializeTimer(ndis_timer *,
                    192:        ndis_timer_function, void *);
                    193: __stdcall static void NdisSetTimer(ndis_timer *, uint32_t);
                    194: __stdcall static void NdisMSetPeriodicTimer(ndis_miniport_timer *, uint32_t);
                    195: __stdcall static void NdisMCancelTimer(ndis_timer *, uint8_t *);
                    196: __stdcall static void ndis_timercall(kdpc *, ndis_miniport_timer *,
                    197:        void *, void *);
                    198: __stdcall static void NdisMQueryAdapterResources(ndis_status *, ndis_handle,
                    199:        ndis_resource_list *, uint32_t *);
                    200: __stdcall static ndis_status NdisMRegisterIoPortRange(void **,
                    201:        ndis_handle, uint32_t, uint32_t);
                    202: __stdcall static void NdisMDeregisterIoPortRange(ndis_handle,
                    203:        uint32_t, uint32_t, void *);
                    204: __stdcall static void NdisReadNetworkAddress(ndis_status *, void **,
                    205:        uint32_t *, ndis_handle);
                    206: __stdcall static ndis_status NdisQueryMapRegisterCount(uint32_t, uint32_t *);
                    207: __stdcall static ndis_status NdisMAllocateMapRegisters(ndis_handle,
                    208:        uint32_t, uint8_t, uint32_t, uint32_t);
                    209: __stdcall static void NdisMFreeMapRegisters(ndis_handle);
                    210: static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
                    211: __stdcall static void NdisMAllocateSharedMemory(ndis_handle, uint32_t,
                    212:        uint8_t, void **, ndis_physaddr *);
                    213: static void ndis_asyncmem_complete(void *);
                    214: __stdcall static ndis_status NdisMAllocateSharedMemoryAsync(ndis_handle,
                    215:        uint32_t, uint8_t, void *);
                    216: __stdcall static void NdisMFreeSharedMemory(ndis_handle, uint32_t,
                    217:        uint8_t, void *, ndis_physaddr);
                    218: __stdcall static ndis_status NdisMMapIoSpace(void **, ndis_handle,
                    219:        ndis_physaddr, uint32_t);
                    220: __stdcall static void NdisMUnmapIoSpace(ndis_handle, void *, uint32_t);
                    221: __stdcall static uint32_t NdisGetCacheFillSize(void);
                    222: __stdcall static uint32_t NdisMGetDmaAlignment(ndis_handle);
                    223: __stdcall static ndis_status NdisMInitializeScatterGatherDma(ndis_handle,
                    224:        uint8_t, uint32_t);
                    225: __stdcall static void NdisUnchainBufferAtFront(ndis_packet *, ndis_buffer **);
                    226: __stdcall static void NdisUnchainBufferAtBack(ndis_packet *, ndis_buffer **);
                    227: __stdcall static void NdisAllocateBufferPool(ndis_status *,
                    228:        ndis_handle *, uint32_t);
                    229: __stdcall static void NdisFreeBufferPool(ndis_handle);
                    230: __stdcall static void NdisAllocateBuffer(ndis_status *, ndis_buffer **,
                    231:        ndis_handle, void *, uint32_t);
                    232: __stdcall static void NdisFreeBuffer(ndis_buffer *);
                    233: __stdcall static uint32_t NdisBufferLength(ndis_buffer *);
                    234: __stdcall static void NdisQueryBuffer(ndis_buffer *, void **, uint32_t *);
                    235: __stdcall static void NdisQueryBufferSafe(ndis_buffer *, void **,
                    236:        uint32_t *, uint32_t);
                    237: __stdcall static void *NdisBufferVirtualAddress(ndis_buffer *);
                    238: __stdcall static void *NdisBufferVirtualAddressSafe(ndis_buffer *, uint32_t);
                    239: __stdcall static void NdisAdjustBufferLength(ndis_buffer *, int);
                    240: __stdcall static uint32_t NdisInterlockedIncrement(uint32_t *);
                    241: __stdcall static uint32_t NdisInterlockedDecrement(uint32_t *);
                    242: __stdcall static void NdisInitializeEvent(ndis_event *);
                    243: __stdcall static void NdisSetEvent(ndis_event *);
                    244: __stdcall static void NdisResetEvent(ndis_event *);
                    245: __stdcall static uint8_t NdisWaitEvent(ndis_event *, uint32_t);
                    246: __stdcall static ndis_status NdisUnicodeStringToAnsiString(ndis_ansi_string *,
                    247:        ndis_unicode_string *);
                    248: __stdcall static ndis_status
                    249:        NdisAnsiStringToUnicodeString(ndis_unicode_string *,
                    250:        ndis_ansi_string *);
                    251: __stdcall static ndis_status NdisMPciAssignResources(ndis_handle,
                    252:        uint32_t, ndis_resource_list **);
                    253: __stdcall static ndis_status NdisMRegisterInterrupt(ndis_miniport_interrupt *,
                    254:        ndis_handle, uint32_t, uint32_t, uint8_t,
                    255:        uint8_t, ndis_interrupt_mode);
                    256: __stdcall static void NdisMDeregisterInterrupt(ndis_miniport_interrupt *);
                    257: __stdcall static void NdisMRegisterAdapterShutdownHandler(ndis_handle, void *,
                    258:        ndis_shutdown_handler);
                    259: __stdcall static void NdisMDeregisterAdapterShutdownHandler(ndis_handle);
                    260: __stdcall static uint32_t NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *);
                    261: __stdcall static void NdisGetBufferPhysicalArraySize(ndis_buffer *,
                    262:        uint32_t *);
                    263: __stdcall static void NdisQueryBufferOffset(ndis_buffer *,
                    264:        uint32_t *, uint32_t *);
                    265: __stdcall static void NdisMSleep(uint32_t);
                    266: __stdcall static uint32_t NdisReadPcmciaAttributeMemory(ndis_handle,
                    267:        uint32_t, void *, uint32_t);
                    268: __stdcall static uint32_t NdisWritePcmciaAttributeMemory(ndis_handle,
                    269:        uint32_t, void *, uint32_t);
                    270: __stdcall static list_entry *NdisInterlockedInsertHeadList(list_entry *,
                    271:        list_entry *, ndis_spin_lock *);
                    272: __stdcall static list_entry *NdisInterlockedRemoveHeadList(list_entry *,
                    273:        ndis_spin_lock *);
                    274: __stdcall static list_entry *NdisInterlockedInsertTailList(list_entry *,
                    275:        list_entry *, ndis_spin_lock *);
                    276: __stdcall static uint8_t
                    277:        NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *,
                    278:        void *, void *);
                    279: __stdcall static void NdisGetCurrentSystemTime(uint64_t *);
                    280: __stdcall static void NdisGetSystemUpTime(uint32_t *);
                    281: __stdcall static void NdisInitializeString(ndis_unicode_string *, char *);
                    282: __stdcall static void NdisInitAnsiString(ndis_ansi_string *, char *);
                    283: __stdcall static void NdisInitUnicodeString(ndis_unicode_string *,
                    284:        uint16_t *);
                    285: __stdcall static void NdisFreeString(ndis_unicode_string *);
                    286: __stdcall static ndis_status NdisMRemoveMiniport(ndis_handle *);
                    287: __stdcall static void NdisTerminateWrapper(ndis_handle, void *);
                    288: __stdcall static void NdisMGetDeviceProperty(ndis_handle, device_object **,
                    289:        device_object **, device_object **, cm_resource_list *,
                    290:        cm_resource_list *);
                    291: __stdcall static void NdisGetFirstBufferFromPacket(ndis_packet *,
                    292:        ndis_buffer **, void **, uint32_t *, uint32_t *);
                    293: __stdcall static void NdisGetFirstBufferFromPacketSafe(ndis_packet *,
                    294:        ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t);
1.2       rittera   295: #ifdef __FreeBSD__
1.7       christos  296: static int ndis_find_sym(linker_file_t, char *, char *, void **);
1.1       rittera   297: __stdcall static void NdisOpenFile(ndis_status *, ndis_handle *, uint32_t *,
                    298:        ndis_unicode_string *, ndis_physaddr);
                    299: __stdcall static void NdisMapFile(ndis_status *, void **, ndis_handle);
                    300: __stdcall static void NdisUnmapFile(ndis_handle);
                    301: __stdcall static void NdisCloseFile(ndis_handle);
1.2       rittera   302: #endif
1.1       rittera   303: __stdcall static uint8_t NdisSystemProcessorCount(void);
                    304: __stdcall static void NdisMIndicateStatusComplete(ndis_handle);
                    305: __stdcall static void NdisMIndicateStatus(ndis_handle, ndis_status,
                    306:         void *, uint32_t);
                    307: static void ndis_workfunc(void *);
                    308: static funcptr ndis_findwrap(funcptr);
                    309: __stdcall static ndis_status NdisScheduleWorkItem(ndis_work_item *);
                    310: __stdcall static void NdisCopyFromPacketToPacket(ndis_packet *,
                    311:        uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *);
                    312: __stdcall static void NdisCopyFromPacketToPacketSafe(ndis_packet *,
                    313:        uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t);
                    314: __stdcall static ndis_status NdisMRegisterDevice(ndis_handle,
                    315:        ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **,
                    316:        void **, ndis_handle *);
                    317: __stdcall static ndis_status NdisMDeregisterDevice(ndis_handle);
                    318: __stdcall static ndis_status
                    319:        NdisMQueryAdapterInstanceName(ndis_unicode_string *,
                    320:        ndis_handle);
                    321: __stdcall static void NdisMRegisterUnloadHandler(ndis_handle, void *);
                    322: __stdcall static void dummy(void);
                    323:
                    324: /*
                    325:  * Some really old drivers do not properly check the return value
                    326:  * from NdisAllocatePacket() and NdisAllocateBuffer() and will
                    327:  * sometimes allocate few more buffers/packets that they originally
                    328:  * requested when they created the pool. To prevent this from being
                    329:  * a problem, we allocate a few extra buffers/packets beyond what
                    330:  * the driver asks for. This #define controls how many.
                    331:  */
                    332: #define NDIS_POOL_EXTRA                16
                    333:
                    334: int
                    335: ndis_libinit()
                    336: {
                    337:        image_patch_table       *patch;
                    338:
                    339:        strcpy(ndis_filepath, "/compat/ndis");
                    340:
                    341:        patch = ndis_functbl;
                    342:        while (patch->ipt_func != NULL) {
                    343:                windrv_wrap((funcptr)patch->ipt_func,
                    344:                    (funcptr *)&patch->ipt_wrap);
                    345:                patch++;
                    346:        }
                    347:
                    348:        return(0);
                    349: }
                    350:
                    351: int
                    352: ndis_libfini()
                    353: {
                    354:        image_patch_table       *patch;
                    355:
                    356:        patch = ndis_functbl;
                    357:        while (patch->ipt_func != NULL) {
                    358:                windrv_unwrap(patch->ipt_wrap);
                    359:                patch++;
                    360:        }
                    361:
                    362:        return(0);
                    363: }
                    364:
                    365: static funcptr
1.15    ! dsl       366: ndis_findwrap(funcptr func)
1.1       rittera   367: {
                    368:        image_patch_table       *patch;
                    369:
                    370:        patch = ndis_functbl;
                    371:        while (patch->ipt_func != NULL) {
                    372:                if ((funcptr)patch->ipt_func == func)
                    373:                        return((funcptr)patch->ipt_wrap);
                    374:                patch++;
                    375:        }
                    376:
                    377:        return(NULL);
                    378: }
                    379:
                    380: /*
                    381:  * NDIS deals with strings in unicode format, so we have
                    382:  * do deal with them that way too. For now, we only handle
                    383:  * conversion between unicode and ASCII since that's all
                    384:  * that device drivers care about.
                    385:  */
                    386:
                    387: int
1.15    ! dsl       388: ndis_ascii_to_unicode(const char *ascii, uint16_t **unicode)
1.1       rittera   389: {
                    390:        uint16_t                *ustr;
                    391:        int                     i;
                    392:
                    393:        if (*unicode == NULL)
                    394:                *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_NOWAIT);
                    395:
                    396:        if (*unicode == NULL)
                    397:                return(ENOMEM);
                    398:        ustr = *unicode;
                    399:        for (i = 0; i < strlen(ascii); i++) {
                    400:                *ustr = (uint16_t)ascii[i];
                    401:                ustr++;
                    402:        }
                    403:
                    404:        return(0);
                    405: }
                    406:
                    407: int
1.15    ! dsl       408: ndis_unicode_to_ascii(uint16_t *unicode, int ulen, char **ascii)
1.1       rittera   409: {
                    410:        uint8_t                 *astr;
                    411:        int                     i;
                    412:
                    413:        if (*ascii == NULL)
                    414:                *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_NOWAIT|M_ZERO);
                    415:        if (*ascii == NULL)
                    416:                return(ENOMEM);
                    417:        astr = *ascii;
                    418:        for (i = 0; i < ulen / 2; i++) {
                    419:                *astr = (uint8_t)unicode[i];
                    420:                astr++;
                    421:        }
                    422:
                    423:        return(0);
                    424: }
                    425:
                    426: /*
                    427:  * This routine does the messy Windows Driver Model device attachment
                    428:  * stuff on behalf of NDIS drivers. We register our own AddDevice
                    429:  * routine here
                    430:  */
                    431: __stdcall static void
1.5       christos  432: NdisInitializeWrapper(
1.6       christos  433:        ndis_handle             *wrapper,
1.5       christos  434:        driver_object           *drv,
1.6       christos  435:        void                    *path,
                    436:        void                    *unused)
1.1       rittera   437: {
1.3       rittera   438:        PN(NdisInitializeWrapper)
1.1       rittera   439:        /*
                    440:         * As of yet, I haven't come up with a compelling
                    441:         * reason to define a private NDIS wrapper structure,
                    442:         * so we use a pointer to the driver object as the
                    443:         * wrapper handle. The driver object has the miniport
                    444:         * characteristics struct for this driver hung off it
                    445:         * via IoAllocateDriverObjectExtension(), and that's
                    446:         * really all the private data we need.
                    447:         */
                    448:
                    449:        *wrapper = drv;
                    450:
                    451:        /*
                    452:         * If this was really Windows, we'd be registering dispatch
                    453:         * routines for the NDIS miniport module here, but we're
                    454:         * not Windows so all we really need to do is set up an
                    455:         * AddDevice function that'll be invoked when a new device
                    456:         * instance appears.
                    457:         */
                    458:
                    459:        drv->dro_driverext->dre_adddevicefunc = NdisAddDevice;
                    460:
                    461:        return;
                    462: }
                    463:
                    464: __stdcall static void
1.5       christos  465: NdisTerminateWrapper(
1.6       christos  466:        ndis_handle             handle,
                    467:        void                    *syspec)
1.1       rittera   468: {
                    469:        /* Nothing to see here, move along. */
                    470:        return;
                    471: }
                    472:
                    473: __stdcall static ndis_status
1.15    ! dsl       474: NdisMRegisterMiniport(ndis_handle handle, ndis_miniport_characteristics *characteristics, int len)
1.1       rittera   475: {
1.3       rittera   476:        ndis_miniport_characteristics   *pch = NULL;
                    477:        void *ch = NULL;
1.1       rittera   478:        driver_object           *drv;
                    479:
1.3       rittera   480:        PN(NdisMRegisterMiniport);
                    481:
1.1       rittera   482:        drv = (driver_object *)handle;
                    483:
                    484:        /*
                    485:         * We need to save the NDIS miniport characteristics
                    486:         * somewhere. This data is per-driver, not per-device
                    487:         * (all devices handled by the same driver have the
                    488:         * same characteristics) so we hook it onto the driver
                    489:         * object using IoAllocateDriverObjectExtension().
                    490:         * The extra extension info is automagically deleted when
                    491:         * the driver is unloaded (see windrv_unload()).
                    492:         */
                    493:        if (IoAllocateDriverObjectExtension(drv, (void *)1,
1.3       rittera   494:                sizeof(ndis_miniport_characteristics), /*(void **)*/&ch) !=
1.1       rittera   495:            STATUS_SUCCESS)
                    496:                return(NDIS_STATUS_RESOURCES);
1.3       rittera   497:    pch = (ndis_miniport_characteristics *)ch;
1.1       rittera   498:
1.3       rittera   499:        bzero((char *)pch, sizeof(ndis_miniport_characteristics));
1.1       rittera   500:
1.3       rittera   501: #ifdef __FreeBSD__
                    502:        bcopy((char *)characteristics, (char *)pch, len);
                    503: #else /* __NetBSD__ */
                    504:        memcpy(pch, characteristics, len);
                    505: #endif
                    506:
                    507:        if (pch->nmc_version_major < 5 || pch->nmc_version_minor < 1) {
                    508:                pch->nmc_shutdown_handler = NULL;
                    509:                pch->nmc_canceltxpkts_handler = NULL;
                    510:                pch->nmc_pnpevent_handler = NULL;
1.1       rittera   511:        }
                    512:
                    513:        return(NDIS_STATUS_SUCCESS);
                    514: }
                    515:
                    516: __stdcall static ndis_status
1.15    ! dsl       517: NdisAllocateMemoryWithTag(void **vaddr, uint32_t len, uint32_t tag)
1.1       rittera   518: {
                    519:        void                    *mem;
                    520:
                    521:
                    522:        mem = ExAllocatePoolWithTag(NonPagedPool, len, tag);
                    523:        if (mem == NULL)
                    524:                return(NDIS_STATUS_RESOURCES);
                    525:        *vaddr = mem;
                    526:
                    527:        return(NDIS_STATUS_SUCCESS);
                    528: }
                    529:
                    530: __stdcall static ndis_status
1.5       christos  531: NdisAllocateMemory(
                    532:        void                    **vaddr,
                    533:        uint32_t                len,
1.6       christos  534:        uint32_t                flags,
                    535:        ndis_physaddr           highaddr)
1.1       rittera   536: {
                    537:        void                    *mem;
                    538:
                    539:        mem = ExAllocatePoolWithTag(NonPagedPool, len, 0);
                    540:        if (mem == NULL)
                    541:                return(NDIS_STATUS_RESOURCES);
                    542:        *vaddr = mem;
                    543:
                    544:        return(NDIS_STATUS_SUCCESS);
                    545: }
                    546:
                    547: __stdcall static void
1.5       christos  548: NdisFreeMemory(
                    549:        void                    *vaddr,
                    550:        uint32_t                len,
1.6       christos  551:        uint32_t                flags)
1.1       rittera   552: {
                    553:        if (len == 0)
                    554:                return;
                    555:
                    556:        ExFreePool(vaddr);
                    557:
                    558:        return;
                    559: }
                    560:
                    561: __stdcall static ndis_status
1.5       christos  562: NdisMSetAttributesEx(
                    563:        ndis_handle                     adapter_handle,
                    564:        ndis_handle                     adapter_ctx,
                    565:        uint32_t                        hangsecs,
                    566:        uint32_t                        flags,
1.6       christos  567:        ndis_interface_type             iftype)
1.1       rittera   568: {
                    569:        ndis_miniport_block             *block;
                    570:
1.3       rittera   571:        PN(NdisMSetAttributesEx)
1.1       rittera   572:        /*
                    573:         * Save the adapter context, we need it for calling
                    574:         * the driver's internal functions.
                    575:         */
                    576:        block = (ndis_miniport_block *)adapter_handle;
                    577:        block->nmb_miniportadapterctx = adapter_ctx;
                    578:        block->nmb_checkforhangsecs = hangsecs;
                    579:        block->nmb_flags = flags;
                    580:
                    581:        return(NDIS_STATUS_SUCCESS);
                    582: }
                    583:
                    584: __stdcall static void
1.15    ! dsl       585: NdisOpenConfiguration(ndis_status *status, ndis_handle *cfg, ndis_handle wrapctx)
1.1       rittera   586: {
1.3       rittera   587:        PN(NdisOpenConfiguration)
1.1       rittera   588:        *cfg = wrapctx;
                    589:        *status = NDIS_STATUS_SUCCESS;
                    590:
                    591:        return;
                    592: }
                    593:
                    594: __stdcall static void
1.5       christos  595: NdisOpenConfigurationKeyByName(
                    596:        ndis_status             *status,
                    597:        ndis_handle             cfg,
1.6       christos  598:        ndis_unicode_string     *subkey,
1.5       christos  599:        ndis_handle             *subhandle)
1.1       rittera   600: {
1.3       rittera   601:        PN(NdisOpenConfiguration)
1.1       rittera   602:        *subhandle = cfg;
                    603:        *status = NDIS_STATUS_SUCCESS;
                    604:        return;
                    605: }
                    606:
                    607: __stdcall static void
1.5       christos  608: NdisOpenConfigurationKeyByIndex(
                    609:        ndis_status             *status,
1.6       christos  610:        ndis_handle             cfg,
                    611:        uint32_t                idx,
                    612:        ndis_unicode_string     *subkey,
                    613:        ndis_handle             *subhandle)
1.1       rittera   614: {
                    615:        *status = NDIS_STATUS_FAILURE;
                    616:        return;
                    617: }
                    618:
1.3       rittera   619: static ndis_status
1.2       rittera   620: #ifdef __FreeBSD__
1.1       rittera   621: ndis_encode_parm(block, oid, type, parm)
1.3       rittera   622:        ndis_miniport_block     *block;
                    623:     struct sysctl_oid  *oid;
                    624:        ndis_parm_type          type;
                    625:        ndis_config_parm        **parm;
                    626: #else /* __NetBSD__ */
                    627: ndis_encode_parm(block, data, type, parm)
                    628:        ndis_miniport_block     *block;
                    629:     void                               *data;
1.1       rittera   630:        ndis_parm_type          type;
                    631:        ndis_config_parm        **parm;
1.3       rittera   632: #endif
1.1       rittera   633: {
                    634:        uint16_t                *unicode;
                    635:        ndis_unicode_string     *ustr;
                    636:        int                     base = 0;
                    637:
1.3       rittera   638:        PN(ndis_encode_parm)
                    639:
1.1       rittera   640:        unicode = (uint16_t *)&block->nmb_dummybuf;
                    641:
                    642:        switch(type) {
                    643:        case ndis_parm_string:
1.3       rittera   644: #ifdef __FreeBSD__
1.1       rittera   645:                ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
1.3       rittera   646: #else /* __NetBSD__ */
                    647:                ndis_ascii_to_unicode((char *)data, &unicode);
                    648: #endif
1.1       rittera   649:                (*parm)->ncp_type = ndis_parm_string;
                    650:                ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
1.3       rittera   651: #ifdef __FreeBSD__
1.1       rittera   652:                ustr->us_len = strlen((char *)oid->oid_arg1) * 2;
1.3       rittera   653: #else /* __NetBSD__ */
                    654:                ustr->us_len = strlen((char *)data) * 2;
                    655: #endif
1.1       rittera   656:                ustr->us_buf = unicode;
                    657:                break;
                    658:        case ndis_parm_int:
1.3       rittera   659: #ifdef __FreeBSD__
                    660:                if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) {
                    661: #else /* __NetBSD__ */
                    662:                if (strncmp((char *)data, "0x", 2) == 0) {
                    663: #endif
1.1       rittera   664:                        base = 16;
1.3       rittera   665:                }
1.1       rittera   666:                else
                    667:                        base = 10;
                    668:                (*parm)->ncp_type = ndis_parm_int;
                    669:                (*parm)->ncp_parmdata.ncp_intdata =
1.3       rittera   670: #ifdef __FreeBSD__
1.1       rittera   671:                    strtol((char *)oid->oid_arg1, NULL, base);
1.3       rittera   672: #else /* __NetBSD__ */
                    673: /* TODO: NetBSD dosen't seem to have a strtol in sys/lib/libkern I hope strtoul is OK */
                    674:                    strtoul((char *)data, NULL, base);
                    675: #endif
1.1       rittera   676:                break;
                    677:        case ndis_parm_hexint:
1.3       rittera   678: #ifdef __FreeBSD__
                    679:                if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) {
                    680: #else /* __NetBSD__ */
                    681:                if (strncmp((char *)data, "0x", 2) == 0) {
                    682: #endif
1.1       rittera   683:                        base = 16;
1.3       rittera   684:                }
1.1       rittera   685:                else
                    686:                        base = 10;
                    687:                (*parm)->ncp_type = ndis_parm_hexint;
                    688:                (*parm)->ncp_parmdata.ncp_intdata =
1.3       rittera   689: #ifdef __FreeBSD__
1.1       rittera   690:                    strtoul((char *)oid->oid_arg1, NULL, base);
1.3       rittera   691: #else /* __NetBSD__ */
                    692:                    strtoul((char *)data, NULL, base);
                    693: #endif
1.1       rittera   694:                break;
                    695:        default:
                    696:                return(NDIS_STATUS_FAILURE);
                    697:                break;
                    698:        }
                    699:
                    700:        return(NDIS_STATUS_SUCCESS);
                    701: }
                    702:
                    703: int
1.15    ! dsl       704: ndis_strcasecmp(const char *s1, const char *s2)
1.1       rittera   705: {
                    706:        char                    a, b;
                    707:
                    708:        /*
                    709:         * In the kernel, toupper() is a macro. Have to be careful
                    710:         * not to use pointer arithmetic when passing it arguments.
                    711:         */
                    712:
                    713:        while(1) {
                    714:                a = *s1;
                    715:                b = *s2++;
                    716:                if (toupper(a) != toupper(b))
                    717:                        break;
                    718:                if (*s1++ == '\0')
                    719:                        return(0);
                    720:        }
                    721:
                    722:        return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
                    723: }
                    724:
                    725: int
1.15    ! dsl       726: ndis_strncasecmp(const char *s1, const char *s2, size_t n)
1.1       rittera   727: {
                    728:        char                    a, b;
                    729:
                    730:        if (n != 0) {
                    731:                do {
                    732:                        a = *s1;
                    733:                        b = *s2++;
                    734:                        if (toupper(a) != toupper(b))
                    735:                                return (*(const unsigned char *)s1 -
                    736:                                    *(const unsigned char *)(s2 - 1));
                    737:                        if (*s1++ == '\0')
                    738:                                break;
                    739:                } while (--n != 0);
                    740:        }
                    741:
                    742:        return(0);
                    743: }
                    744:
                    745: __stdcall static void
1.15    ! dsl       746: NdisReadConfiguration(ndis_status *status, ndis_config_parm **parm, ndis_handle cfg, ndis_unicode_string *key, ndis_parm_type type)
1.1       rittera   747: {
                    748:        char                    *keystr = NULL;
                    749:        uint16_t                *unicode;
                    750:        ndis_miniport_block     *block;
                    751:        struct ndis_softc       *sc;
1.3       rittera   752: #ifdef __FreeBSD__
                    753:     struct sysctl_oid  *oidp;
1.1       rittera   754:        struct sysctl_ctx_entry *e;
1.3       rittera   755: #endif
                    756:
                    757: #ifdef __NetBSD__
                    758:        const struct sysctlnode *pnode = NULL;
                    759:        struct sysctlnode *ndiscld = NULL;
                    760:        int error;
                    761:        int numcld;
                    762:        int mib[1];
                    763:        int i;
                    764:        char new_keystr[MAX_SYSCTL_LEN+1];
                    765:        char *old_keystr;
                    766: #endif
1.1       rittera   767:
                    768:        block = (ndis_miniport_block *)cfg;
1.3       rittera   769: #ifdef __FreeBSD__
1.1       rittera   770:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera   771: #else /* __NetBSD__ */
                    772:        sc = block->nmb_physdeviceobj->pdo_sc;
                    773: #endif
                    774:        PN(NdisReadConfiguration)
1.1       rittera   775:
                    776:        if (key->us_len == 0 || key->us_buf == NULL) {
                    777:                *status = NDIS_STATUS_FAILURE;
                    778:                return;
                    779:        }
                    780:
                    781:        ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr);
                    782:        *parm = &block->nmb_replyparm;
                    783:        bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
                    784:        unicode = (uint16_t *)&block->nmb_dummybuf;
1.3       rittera   785:
                    786: #ifdef __NetBSD__
                    787:        if(strlen(keystr) + strlen("ndis_") > MAX_SYSCTL_LEN) {
                    788:                panic("sysctl name too long: %s\n", keystr);
                    789:        }
                    790:        strcpy(new_keystr, "ndis_");
                    791:        strcpy(new_keystr + strlen("ndis_"), keystr);
                    792:        old_keystr = keystr;
                    793:        keystr = new_keystr;
                    794: #endif
1.1       rittera   795:
                    796:        /*
                    797:         * See if registry key is already in a list of known keys
                    798:         * included with the driver.
                    799:         */
1.3       rittera   800: #ifdef __FreeBSD__
1.1       rittera   801: #if __FreeBSD_version < 502113
                    802:        TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
                    803: #else
                    804:        TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
                    805: #endif
                    806:                oidp = e->entry;
1.3       rittera   807: #ifdef __FreeBSD__
1.1       rittera   808:                if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
1.3       rittera   809: #else /* __NetBSD__ */
                    810:                if (ndis_strcasecmp(oidp->ctl_name, keystr) == 0) {
                    811: #endif
1.1       rittera   812:                        if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
                    813:                                free(keystr, M_DEVBUF);
                    814:                                *status = NDIS_STATUS_FAILURE;
                    815:                                return;
1.3       rittera   816:                        }
                    817:                        *status = ndis_encode_parm(block, oidp, type, parm);
                    818:
                    819:                        free(keystr, M_DEVBUF);
                    820:                        return;
                    821:                }
                    822:        }
                    823: #else /* __NetBSD__ */
                    824:        mib[0] = sc->ndis_sysctl_mib;
                    825:
1.13      ad        826:        sysctl_lock(false);
1.3       rittera   827:                error = sysctl_locate(curlwp, &mib[0], 1, &pnode, NULL);
                    828:
                    829:                numcld  = pnode->sysctl_csize;
                    830:                ndiscld = pnode->sysctl_child;
                    831:
                    832:                /* find the node whose name is keystr */
                    833:                for(i=0; i < numcld; i++) {
                    834:                        if(strcmp(keystr, ndiscld->sysctl_name) == 0) {
                    835:                                /* Found it */
                    836:                                break;
1.1       rittera   837:                        }
1.3       rittera   838:                        ndiscld++;
                    839:                }
1.13      ad        840:        sysctl_unlock();
1.3       rittera   841:
                    842:        if(i < numcld) {
                    843:                /* Found it */
                    844:                if(strcmp(ndiscld->sysctl_data, "UNSET") == 0) {
1.1       rittera   845:                        free(keystr, M_DEVBUF);
1.3       rittera   846:                        *status = NDIS_STATUS_FAILURE;
1.1       rittera   847:                        return;
                    848:                }
1.3       rittera   849:
                    850:                *status = ndis_encode_parm(block, ndiscld->sysctl_data, type,  parm);
                    851:                free(keystr, M_DEVBUF);
                    852:                return;
1.1       rittera   853:        }
1.3       rittera   854:
                    855: #endif
                    856:
                    857: #ifdef __NetBSD__
                    858:        free(keystr, M_DEVBUF);
                    859:        keystr = old_keystr;
                    860: #endif
1.1       rittera   861:
                    862:        /*
                    863:         * If the key didn't match, add it to the list of dynamically
                    864:         * created ones. Sometimes, drivers refer to registry keys
                    865:         * that aren't documented in their .INF files. These keys
                    866:         * are supposed to be created by some sort of utility or
                    867:         * control panel snap-in that comes with the driver software.
                    868:         * Sometimes it's useful to be able to manipulate these.
                    869:         * If the driver requests the key in the form of a string,
                    870:         * make its default value an empty string, otherwise default
                    871:         * it to "0".
                    872:         */
                    873:        if (type == ndis_parm_int || type == ndis_parm_hexint)
                    874:                ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
                    875:                    "UNSET", CTLFLAG_RW);
                    876:        else
                    877:                ndis_add_sysctl(sc, keystr, "(dynamic string key)",
1.3       rittera   878:                    "UNSET", CTLFLAG_RW);
1.1       rittera   879:
                    880:        free(keystr, M_DEVBUF);
                    881:        *status = NDIS_STATUS_FAILURE;
                    882:        return;
                    883: }
                    884:
1.3       rittera   885: #ifdef __FreeBSD__
1.1       rittera   886: static ndis_status
1.15    ! dsl       887: ndis_decode_parm(ndis_miniport_block *block, ndis_config_parm *parm, char *val)
1.1       rittera   888: {
                    889:        ndis_unicode_string     *ustr;
                    890:        char                    *astr = NULL;
                    891:
1.3       rittera   892:        PN(ndis_decode_parm)
                    893:
1.1       rittera   894:        switch(parm->ncp_type) {
                    895:        case ndis_parm_string:
                    896:                ustr = &parm->ncp_parmdata.ncp_stringdata;
                    897:                ndis_unicode_to_ascii(ustr->us_buf, ustr->us_len, &astr);
                    898:                bcopy(astr, val, 254);
                    899:                free(astr, M_DEVBUF);
                    900:                break;
                    901:        case ndis_parm_int:
                    902:                sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
                    903:                break;
                    904:        case ndis_parm_hexint:
                    905:                sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
                    906:                break;
                    907:        default:
                    908:                return(NDIS_STATUS_FAILURE);
                    909:                break;
                    910:        }
                    911:        return(NDIS_STATUS_SUCCESS);
                    912: }
1.3       rittera   913: #endif
1.1       rittera   914:
                    915: __stdcall static void
1.5       christos  916: NdisWriteConfiguration(
                    917:        ndis_status             *status,
1.6       christos  918:        ndis_handle             cfg,
                    919:        ndis_unicode_string     *key,
                    920:        ndis_config_parm        *parm)
1.1       rittera   921: {
1.2       rittera   922: #ifdef __FreeBSD__
1.1       rittera   923:        char                    *keystr = NULL;
                    924:        ndis_miniport_block     *block;
                    925:        struct ndis_softc       *sc;
                    926:         struct sysctl_oid      *oidp;
                    927:        struct sysctl_ctx_entry *e;
                    928:        char                    val[256];
                    929:
                    930:        block = (ndis_miniport_block *)cfg;
1.2       rittera   931:
1.3       rittera   932:        PN(NdisWriteConfiguration)
                    933:
                    934: #ifdef __FreeBSD__
1.1       rittera   935:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera   936: #else /* __NetBSD__ */
                    937:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                    938: #endif
1.1       rittera   939:
                    940:        ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr);
                    941:
                    942:        /* Decode the parameter into a string. */
                    943:        bzero(val, sizeof(val));
                    944:        *status = ndis_decode_parm(block, parm, val);
                    945:        if (*status != NDIS_STATUS_SUCCESS) {
                    946:                free(keystr, M_DEVBUF);
                    947:                return;
                    948:        }
                    949:
                    950:        /* See if the key already exists. */
                    951:
1.2       rittera   952: #if __FreeBSD_version < 502113 || !defined(__FreeBSD__)
1.1       rittera   953:        TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
                    954: #else
                    955:        TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
                    956: #endif
                    957:                oidp = e->entry;
                    958:                if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
                    959:                        /* Found it, set the value. */
                    960:                        strcpy((char *)oidp->oid_arg1, val);
                    961:                        free(keystr, M_DEVBUF);
                    962:                        return;
                    963:                }
                    964:        }
                    965:
                    966:        /* Not found, add a new key with the specified value. */
                    967:        ndis_add_sysctl(sc, keystr, "(dynamically set key)",
                    968:                    val, CTLFLAG_RW);
                    969:
                    970:        free(keystr, M_DEVBUF);
                    971:        *status = NDIS_STATUS_SUCCESS;
                    972:        return;
1.2       rittera   973: #else /* __FreeBSD__ */
                    974:        *status = NDIS_STATUS_SUCCESS;
                    975:        return;
                    976: #endif
1.1       rittera   977: }
                    978:
                    979: __stdcall static void
1.6       christos  980: NdisCloseConfiguration(ndis_handle cfg)
1.1       rittera   981: {
                    982:        return;
                    983: }
                    984:
                    985: /*
                    986:  * Initialize a Windows spinlock.
                    987:  */
                    988: __stdcall static void
1.15    ! dsl       989: NdisAllocateSpinLock(ndis_spin_lock *lock)
1.1       rittera   990: {
                    991:        KeInitializeSpinLock(&lock->nsl_spinlock);
                    992:        lock->nsl_kirql = 0;
                    993:
                    994:        return;
                    995: }
                    996:
                    997: /*
                    998:  * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
                    999:  * for this. One is that it's sort of superfluous: we don't have to do anything
                   1000:  * special to deallocate the spinlock. The other is that there are some buggy
                   1001:  * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
                   1002:  * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
                   1003:  * talking to you.)
                   1004:  */
                   1005: __stdcall static void
1.6       christos 1006: NdisFreeSpinLock(ndis_spin_lock *lock)
1.1       rittera  1007: {
                   1008: #ifdef notdef
                   1009:        KeInitializeSpinLock(&lock->nsl_spinlock);
                   1010:        lock->nsl_kirql = 0;
                   1011: #endif
                   1012:        return;
                   1013: }
                   1014:
                   1015: /*
                   1016:  * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
                   1017:  */
                   1018:
                   1019: __stdcall static void
1.15    ! dsl      1020: NdisAcquireSpinLock(ndis_spin_lock *lock)
1.1       rittera  1021: {
                   1022:        KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
                   1023:        return;
                   1024: }
                   1025:
                   1026: /*
                   1027:  * Release a spinlock from IRQL == DISPATCH_LEVEL.
                   1028:  */
                   1029:
                   1030: __stdcall static void
1.15    ! dsl      1031: NdisReleaseSpinLock(ndis_spin_lock *lock)
1.1       rittera  1032: {
                   1033:        KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
                   1034:        return;
                   1035: }
                   1036:
                   1037: /*
                   1038:  * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
                   1039:  */
                   1040: __stdcall static void
1.15    ! dsl      1041: NdisDprAcquireSpinLock(ndis_spin_lock *lock)
1.1       rittera  1042: {
                   1043:        KeAcquireSpinLockAtDpcLevel(&lock->nsl_spinlock);
                   1044:        return;
                   1045: }
                   1046:
                   1047: /*
                   1048:  * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
                   1049:  */
                   1050: __stdcall static void
1.15    ! dsl      1051: NdisDprReleaseSpinLock(ndis_spin_lock *lock)
1.1       rittera  1052: {
                   1053:        KeReleaseSpinLockFromDpcLevel(&lock->nsl_spinlock);
                   1054:        return;
                   1055: }
                   1056:
                   1057: __stdcall static uint32_t
1.5       christos 1058: NdisReadPciSlotInformation(
                   1059:        ndis_handle             adapter,
1.6       christos 1060:        uint32_t                slot,
1.5       christos 1061:        uint32_t                offset,
                   1062:        void                    *buf,
                   1063:        uint32_t                len)
1.1       rittera  1064: {
                   1065:        ndis_miniport_block     *block;
                   1066:        int                     i;
1.3       rittera  1067: #ifdef __FreeBSD__
                   1068:      char                    *dest;
                   1069: #else
                   1070:    pcireg_t    *dest;
                   1071: #endif
                   1072:
                   1073:        /* PN(NdisReadPciSlotInformation) */
1.1       rittera  1074:        device_t                dev;
1.3       rittera  1075:     struct ndis_softc  *sc;
1.1       rittera  1076:
                   1077:        block = (ndis_miniport_block *)adapter;
                   1078:        dest = buf;
                   1079:        if (block == NULL)
                   1080:                return(0);
                   1081:
1.2       rittera  1082:        dev = (device_t)block->nmb_physdeviceobj->do_devext;
1.3       rittera  1083: #ifdef __FreeBSD__
                   1084:     sc = device_get_softc(dev);
                   1085: #else /* __NetBSD__ */
                   1086:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1087: #endif
1.1       rittera  1088:
                   1089:        /*
                   1090:         * I have a test system consisting of a Sun w2100z
                   1091:         * dual 2.4Ghz Opteron machine and an Atheros 802.11a/b/g
                   1092:         * "Aries" miniPCI NIC. (The NIC is installed in the
                   1093:         * machine using a miniPCI to PCI bus adapter card.)
                   1094:         * When running in SMP mode, I found that
                   1095:         * performing a large number of consecutive calls to
                   1096:         * NdisReadPciSlotInformation() would result in a
                   1097:         * sudden system reset (or in some cases a freeze).
                   1098:         * My suspicion is that the multiple reads are somehow
                   1099:         * triggering a fatal PCI bus error that leads to a
                   1100:         * machine check. The 1us delay in the loop below
                   1101:         * seems to prevent this problem.
                   1102:         */
                   1103:
1.3       rittera  1104: #ifdef __FreeBSD__
1.1       rittera  1105:        for (i = 0; i < len; i++) {
1.3       rittera  1106: #else /* __NetBSD__ */
                   1107:        for (i = 0; i < len/4; i += 4) {
                   1108: #endif
1.1       rittera  1109:                DELAY(1);
1.3       rittera  1110: #ifdef __FreeBSD__
                   1111:       dest[i] = pci_read_config(dev, i + offset, 1);
                   1112: #else
                   1113:       dest[i/4] = pci_conf_read(sc->ndis_res_pc,sc->ndis_res_pctag, (i + offset));
                   1114: #endif
                   1115:
1.1       rittera  1116:        }
                   1117:
                   1118:        return(len);
                   1119: }
                   1120:
                   1121: __stdcall static uint32_t
1.5       christos 1122: NdisWritePciSlotInformation(
                   1123:        ndis_handle             adapter,
1.6       christos 1124:        uint32_t                slot,
1.5       christos 1125:        uint32_t                offset,
                   1126:        void                    *buf,
                   1127:        uint32_t                len)
1.1       rittera  1128: {
                   1129:        ndis_miniport_block     *block;
                   1130:        int                     i;
1.3       rittera  1131: #ifdef __FreeBSD__
                   1132:     char                    *dest;
                   1133: #else
                   1134:     pcireg_t    *dest;
                   1135: #endif
                   1136:
1.1       rittera  1137:        device_t                dev;
                   1138:
1.3       rittera  1139:        /* PN(NdisWritePciSlotInformation) */
                   1140:
1.1       rittera  1141:        block = (ndis_miniport_block *)adapter;
                   1142:        dest = buf;
1.3       rittera  1143:     struct ndis_softc      *sc;
                   1144:
1.1       rittera  1145:
                   1146:        if (block == NULL)
                   1147:                return(0);
                   1148:
                   1149:        dev = block->nmb_physdeviceobj->do_devext;
1.3       rittera  1150: #ifdef __FreeBSD__
                   1151:     sc = device_get_softc(dev);
                   1152: #else /* __NetBSD__ */
                   1153:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1154: #endif
                   1155:
                   1156: #ifdef __FreeBSD__
1.1       rittera  1157:        for (i = 0; i < len; i++) {
1.3       rittera  1158: #else /* __NetBSD__ */
                   1159:        for (i = 0; i < len/4; i++) {
                   1160: #endif
1.1       rittera  1161:                DELAY(1);
1.3       rittera  1162: #ifdef __FreeBSD__
                   1163:         pci_write_config(dev, i + offset, dest[i], 1);
                   1164: #else
                   1165:         pci_conf_write(sc->ndis_res_pc,sc->ndis_res_pctag,
                   1166:                                           (i + offset), dest[i/4]);
                   1167: #endif
                   1168:
1.1       rittera  1169:        }
                   1170:
                   1171:        return(len);
                   1172: }
                   1173:
                   1174: /*
                   1175:  * The errorlog routine uses a variable argument list, so we
                   1176:  * have to declare it this way.
                   1177:  */
                   1178: #define ERRMSGLEN 512
                   1179: static void
                   1180: NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code,
                   1181:        uint32_t numerrors, ...)
                   1182: {
                   1183:        ndis_miniport_block     *block;
                   1184:        va_list                 ap;
                   1185:        int                     i, error;
                   1186:        char                    *str = NULL, *ustr = NULL;
                   1187:        uint16_t                flags;
                   1188:        char                    msgbuf[ERRMSGLEN];
                   1189:        device_t                dev;
                   1190:        driver_object           *drv;
                   1191:
1.3       rittera  1192:        PN(NdisWriteErrorLogEntry)
                   1193:
1.1       rittera  1194:        block = (ndis_miniport_block *)adapter;
                   1195:        dev = block->nmb_physdeviceobj->do_devext;
                   1196:        drv = block->nmb_physdeviceobj->do_drvobj;
                   1197:
                   1198:        error = pe_get_message((vm_offset_t)drv->dro_driverstart,
                   1199:            code, &str, &i, &flags);
                   1200:        if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
                   1201:                ustr = msgbuf;
                   1202:                ndis_unicode_to_ascii((uint16_t *)str,
                   1203:                    ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
                   1204:                str = ustr;
                   1205:        }
1.3       rittera  1206:
1.4       rittera  1207:        printf ("%s: NDIS ERROR: %x (%s)\n", dev->dv_xname, code,
                   1208:                str == NULL ? "unknown error" : str);
                   1209:        printf ("%s: NDIS NUMERRORS: %x\n",  dev->dv_xname, numerrors);
1.1       rittera  1210:
                   1211:        va_start(ap, numerrors);
                   1212:        for (i = 0; i < numerrors; i++)
1.4       rittera  1213:                printf ("%s: argptr: %p\n",
                   1214:                        dev->dv_xname,
                   1215:                        va_arg(ap, void *));
                   1216:
1.1       rittera  1217:        va_end(ap);
                   1218:
                   1219:        return;
                   1220: }
                   1221:
                   1222: static void
1.15    ! dsl      1223: ndis_map_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1.1       rittera  1224: {
                   1225:        struct ndis_map_arg     *ctx;
                   1226:        int                     i;
                   1227:
1.3       rittera  1228:        PN(ndis_map_cb)
                   1229:
1.1       rittera  1230:        if (error)
                   1231:                return;
                   1232:
                   1233:        ctx = arg;
                   1234:
                   1235:        for (i = 0; i < nseg; i++) {
                   1236:                ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
                   1237:                ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
                   1238:        }
                   1239:
                   1240:        ctx->nma_cnt = nseg;
                   1241:
                   1242:        return;
                   1243: }
                   1244:
                   1245: __stdcall static void
1.15    ! dsl      1246: NdisMStartBufferPhysicalMapping(ndis_handle adapter, ndis_buffer *buf, uint32_t mapreg, uint8_t writedev, ndis_paddr_unit *addrarray, uint32_t *arraysize)
1.1       rittera  1247: {
                   1248:        ndis_miniport_block     *block;
                   1249:        struct ndis_softc       *sc;
                   1250:        struct ndis_map_arg     nma;
                   1251:        bus_dmamap_t            map;
                   1252:        int                     error;
                   1253:
1.3       rittera  1254:        PN(NdisMStartBufferPhysicalMapping)
                   1255:
1.1       rittera  1256:        if (adapter == NULL)
                   1257:                return;
                   1258:
                   1259:        block = (ndis_miniport_block *)adapter;
1.3       rittera  1260: #ifdef __FreeBSD__
1.1       rittera  1261:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1262: #else /* __NetBSD__ */
                   1263:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1264: #endif
1.1       rittera  1265:
                   1266:        if (mapreg > sc->ndis_mmapcnt)
                   1267:                return;
                   1268:
                   1269:        map = sc->ndis_mmaps[mapreg];
                   1270:        nma.nma_fraglist = addrarray;
                   1271:
1.2       rittera  1272: #ifdef __FreeBSD__
1.1       rittera  1273:        error = bus_dmamap_load(sc->ndis_mtag, map,
                   1274:            MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf), ndis_map_cb,
                   1275:            (void *)&nma, BUS_DMA_NOWAIT);
1.2       rittera  1276: #else
                   1277:        error = bus_dmamap_load(sc->ndis_mtag, map,
                   1278:            MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf),
                   1279:                                NULL /* kernel space */, BUS_DMA_NOWAIT);
                   1280:        /* callback function called "by hand" */
                   1281:        ndis_map_cb((void *)&nma, map->dm_segs, map->dm_nsegs, error);
                   1282: #endif
1.1       rittera  1283:        if (error)
                   1284:                return;
                   1285:
1.2       rittera  1286: #ifdef __FreeBSD__
1.1       rittera  1287:        bus_dmamap_sync(sc->ndis_mtag, map,
                   1288:            writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
1.2       rittera  1289: #else
                   1290:        bus_dmamap_sync(sc->ndis_mtag, map, 0, map->dm_mapsize,
                   1291:                writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
                   1292: #endif
1.1       rittera  1293:        *arraysize = nma.nma_cnt;
                   1294:
                   1295:        return;
                   1296: }
                   1297:
                   1298: __stdcall static void
1.5       christos 1299: NdisMCompleteBufferPhysicalMapping(
                   1300:        ndis_handle             adapter,
1.6       christos 1301:        ndis_buffer             *buf,
1.5       christos 1302:        uint32_t                mapreg)
1.1       rittera  1303: {
                   1304:        ndis_miniport_block     *block;
                   1305:        struct ndis_softc       *sc;
                   1306:        bus_dmamap_t            map;
                   1307:
1.3       rittera  1308:        PN(NdisMCompleteBufferPhysicalMapping)
                   1309:
1.1       rittera  1310:        if (adapter == NULL)
                   1311:                return;
                   1312:
                   1313:        block = (ndis_miniport_block *)adapter;
1.3       rittera  1314: #ifdef __FreeBSD__
1.1       rittera  1315:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1316: #else /* __NetBSD__ */
                   1317:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1318: #endif
1.1       rittera  1319:
                   1320:        if (mapreg > sc->ndis_mmapcnt)
                   1321:                return;
                   1322:
                   1323:        map = sc->ndis_mmaps[mapreg];
                   1324:
1.2       rittera  1325: #ifdef __FreeBSD__
1.1       rittera  1326:        bus_dmamap_sync(sc->ndis_mtag, map,
                   1327:            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1.2       rittera  1328: #else
                   1329:        bus_dmamap_sync(sc->ndis_mtag, map, 0, map->dm_mapsize,
                   1330:            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
                   1331: #endif
1.1       rittera  1332:        bus_dmamap_unload(sc->ndis_mtag, map);
                   1333:
                   1334:        return;
                   1335: }
                   1336:
                   1337: /*
                   1338:  * This is an older (?) timer init routine which doesn't
                   1339:  * accept a miniport context handle. Serialized miniports should
                   1340:  * never call this function.
                   1341:  */
                   1342:
                   1343: __stdcall static void
1.15    ! dsl      1344: NdisInitializeTimer(ndis_timer *timer, ndis_timer_function func, void *ctx)
1.1       rittera  1345: {
                   1346:        KeInitializeTimer(&timer->nt_ktimer);
                   1347:        KeInitializeDpc(&timer->nt_kdpc, func, ctx);
                   1348:
                   1349:        return;
                   1350: }
                   1351:
                   1352: __stdcall static void
1.15    ! dsl      1353: ndis_timercall(kdpc *dpc, ndis_miniport_timer *timer, void *sysarg1, void *sysarg2)
1.1       rittera  1354: {
1.3       rittera  1355:        //PN(ndis_timercall)
                   1356:
1.1       rittera  1357:        /*
                   1358:         * Since we're called as a DPC, we should be running
                   1359:         * at DISPATCH_LEVEL here. This means to acquire the
                   1360:         * spinlock, we can use KeAcquireSpinLockAtDpcLevel()
                   1361:         * rather than KeAcquireSpinLock().
                   1362:         */
                   1363:        if (NDIS_SERIALIZED(timer->nmt_block))
                   1364:                KeAcquireSpinLockAtDpcLevel(&timer->nmt_block->nmb_lock);
                   1365:
                   1366:        MSCALL4(timer->nmt_timerfunc, dpc, timer->nmt_timerctx,
                   1367:            sysarg1, sysarg2);
                   1368:
                   1369:        if (NDIS_SERIALIZED(timer->nmt_block))
                   1370:                KeReleaseSpinLockFromDpcLevel(&timer->nmt_block->nmb_lock);
                   1371:
                   1372:        return;
                   1373: }
                   1374:
                   1375: /*
                   1376:  * For a long time I wondered why there were two NDIS timer initialization
                   1377:  * routines, and why this one needed an NDIS_MINIPORT_TIMER and the
                   1378:  * MiniportAdapterHandle. The NDIS_MINIPORT_TIMER has its own callout
                   1379:  * function and context pointers separate from those in the DPC, which
                   1380:  * allows for another level of indirection: when the timer fires, we
                   1381:  * can have our own timer function invoked, and from there we can call
                   1382:  * the driver's function. But why go to all that trouble? Then it hit
                   1383:  * me: for serialized miniports, the timer callouts are not re-entrant.
                   1384:  * By trapping the callouts and having access to the MiniportAdapterHandle,
                   1385:  * we can protect the driver callouts by acquiring the NDIS serialization
                   1386:  * lock. This is essential for allowing serialized miniports to work
                   1387:  * correctly on SMP systems. On UP hosts, setting IRQL to DISPATCH_LEVEL
                   1388:  * is enough to prevent other threads from pre-empting you, but with
                   1389:  * SMP, you must acquire a lock as well, otherwise the other CPU is
                   1390:  * free to clobber you.
                   1391:  */
1.3       rittera  1392:
                   1393:  /* Just to test out how much memory is wasted*/
                   1394:  int ndis_num_timers_allocated = 0;
                   1395:
1.1       rittera  1396: __stdcall static void
1.15    ! dsl      1397: NdisMInitializeTimer(ndis_miniport_timer *timer, ndis_handle handle, ndis_timer_function func, void *ctx)
1.1       rittera  1398: {
                   1399:        /* Save the driver's funcptr and context */
                   1400:
1.3       rittera  1401:        PN(NdisMInitializeTimer)
                   1402:
1.1       rittera  1403:        timer->nmt_timerfunc = func;
                   1404:        timer->nmt_timerctx = ctx;
                   1405:        timer->nmt_block = handle;
1.3       rittera  1406:
                   1407: #ifdef __NetBSD__
                   1408: /* TODO: free this memory somewhere! */
                   1409:        printf("Allocating callout struct\n");
                   1410:        if(timer->nmt_ktimer.k_handle == NULL) {
                   1411:                timer->nmt_ktimer.k_handle =
                   1412:                                malloc(sizeof(struct callout), M_DEVBUF, M_NOWAIT|M_ZERO);
                   1413:                ndis_num_timers_allocated++;
                   1414:        }
                   1415: #endif
1.1       rittera  1416:
                   1417:        /*
                   1418:         * Set up the timer so it will call our intermediate DPC.
                   1419:         * Be sure to use the wrapped entry point, since
                   1420:         * ntoskrnl_run_dpc() expects to invoke a function with
                   1421:         * Microsoft calling conventions.
                   1422:         */
                   1423:        KeInitializeTimer(&timer->nmt_ktimer);
                   1424:        KeInitializeDpc(&timer->nmt_kdpc,
                   1425:            ndis_findwrap((funcptr)ndis_timercall), timer);
                   1426:
                   1427:        return;
                   1428: }
                   1429:
                   1430: /*
                   1431:  * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
                   1432:  * but the former is just a macro wrapper around the latter.
                   1433:  */
                   1434: __stdcall static void
1.15    ! dsl      1435: NdisSetTimer(ndis_timer *timer, uint32_t msecs)
1.1       rittera  1436: {
1.3       rittera  1437:        PN(NdisSetTimer)
1.1       rittera  1438:        /*
                   1439:         * KeSetTimer() wants the period in
                   1440:         * hundred nanosecond intervals.
1.3       rittera  1441:         */
1.1       rittera  1442:        KeSetTimer(&timer->nt_ktimer,
1.3       rittera  1443:            ((int64_t)msecs * -10000), &timer->nt_kdpc);
1.1       rittera  1444:
                   1445:        return;
                   1446: }
                   1447:
                   1448: __stdcall static void
1.15    ! dsl      1449: NdisMSetPeriodicTimer(ndis_miniport_timer *timer, uint32_t msecs)
1.1       rittera  1450: {
1.3       rittera  1451:        PN(NdisMSetPeriodicTimer)
                   1452:
1.1       rittera  1453:        KeSetTimerEx(&timer->nmt_ktimer,
                   1454:            ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc);
                   1455:
                   1456:        return;
                   1457: }
                   1458:
                   1459: /*
                   1460:  * Technically, this is really NdisCancelTimer(), but we also
                   1461:  * (ab)use it for NdisMCancelTimer(), since in our implementation
                   1462:  * we don't need the extra info in the ndis_miniport_timer
                   1463:  * structure just to cancel a timer.
                   1464:  */
                   1465:
                   1466: __stdcall static void
1.15    ! dsl      1467: NdisMCancelTimer(ndis_timer *timer, uint8_t *cancelled)
1.1       rittera  1468: {
1.3       rittera  1469:        PN(NdisMCancelTimer)
1.1       rittera  1470:        *cancelled = KeCancelTimer(&timer->nt_ktimer);
                   1471:
                   1472:        return;
                   1473: }
                   1474:
                   1475: __stdcall static void
1.15    ! dsl      1476: NdisMQueryAdapterResources(ndis_status *status, ndis_handle adapter, ndis_resource_list *list, uint32_t *buflen)
1.1       rittera  1477: {
                   1478:        ndis_miniport_block     *block;
                   1479:        struct ndis_softc       *sc;
                   1480:        int                     rsclen;
                   1481:
1.3       rittera  1482:        PN(NdisMQueryAdapterResources)
                   1483:
1.1       rittera  1484:        block = (ndis_miniport_block *)adapter;
1.3       rittera  1485:
                   1486: #ifdef __FreeBSD__
1.1       rittera  1487:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1488: #else /* __NetBSD__ */
                   1489:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1490: #endif
1.1       rittera  1491:
                   1492:        rsclen = sizeof(ndis_resource_list) +
                   1493:            (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
                   1494:        if (*buflen < rsclen) {
                   1495:                *buflen = rsclen;
                   1496:                *status = NDIS_STATUS_INVALID_LENGTH;
                   1497:                return;
                   1498:        }
                   1499:
1.3       rittera  1500: #ifdef __FreeBSD__
1.1       rittera  1501:        bcopy((char *)block->nmb_rlist, (char *)list, rsclen);
1.3       rittera  1502: #else /* __NetBSD__ */
                   1503:        memcpy(list, block->nmb_rlist, rsclen);
                   1504: #endif
                   1505:
1.1       rittera  1506:        *status = NDIS_STATUS_SUCCESS;
                   1507:
                   1508:        return;
                   1509: }
                   1510:
                   1511: __stdcall static ndis_status
1.5       christos 1512: NdisMRegisterIoPortRange(
                   1513:        void                    **offset,
                   1514:        ndis_handle             adapter,
1.6       christos 1515:        uint32_t                port,
1.5       christos 1516:        uint32_t                numports)
1.1       rittera  1517: {
                   1518:        struct ndis_miniport_block      *block;
                   1519:        struct ndis_softc       *sc;
                   1520:
1.3       rittera  1521:        PN(NdisMRegisterIoPortRange)
                   1522:
1.1       rittera  1523:        if (adapter == NULL)
                   1524:                return(NDIS_STATUS_FAILURE);
                   1525:
                   1526:        block = (ndis_miniport_block *)adapter;
1.3       rittera  1527: #ifdef __FreeBSD__
1.1       rittera  1528:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1529: #else /* __NetBSD__ */
                   1530:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1531: #endif
1.1       rittera  1532:
1.3       rittera  1533: #ifdef __FreeBSD__
1.1       rittera  1534:        if (sc->ndis_res_io == NULL)
1.3       rittera  1535: #else
                   1536:     if (sc->ndis_res_io == NULL && sc->ndis_iftype != PCMCIABus)
                   1537: #endif
1.1       rittera  1538:                return(NDIS_STATUS_FAILURE);
                   1539:
                   1540:        /* Don't let the device map more ports than we have. */
1.3       rittera  1541: #ifdef __FreeBSD__
1.1       rittera  1542:        if (rman_get_size(sc->ndis_res_io) < numports)
1.3       rittera  1543: #else /* __NetBSD__ */
                   1544:     if ( (sc->ndis_iftype != PCMCIABus && sc->ndis_res_io->res_size < numports)
                   1545:             || (sc->ndis_iftype == PCMCIABus && sc->ndis_res_pcioh.size < numports) )
                   1546: #endif
1.1       rittera  1547:                return(NDIS_STATUS_INVALID_LENGTH);
1.3       rittera  1548:
                   1549: #ifdef __FreeBSD__
                   1550:         *offset = (void *)rman_get_start(sc->ndis_res_io);
                   1551: #else /* __NetBSD__ */
                   1552:     switch (sc->ndis_iftype){
                   1553:         case PCIBus:
                   1554:         case CBus:     /* CardBus */
                   1555:             *offset = (void*)sc->ndis_res_io->res_base;
                   1556:             break;
                   1557:         case PCMCIABus:
                   1558:             *offset = (void*)sc->ndis_res_pcioh.addr;
                   1559:             break;
                   1560:         default:
                   1561:             return(NDIS_STATUS_FAILURE);
                   1562:    }
                   1563: #endif /* __NetBSD__ */
1.1       rittera  1564:
                   1565:        return(NDIS_STATUS_SUCCESS);
                   1566: }
                   1567:
                   1568: __stdcall static void
1.5       christos 1569: NdisMDeregisterIoPortRange(
1.6       christos 1570:        ndis_handle             adapter,
                   1571:        uint32_t                port,
                   1572:        uint32_t                numports,
                   1573:        void                    *offset)
1.1       rittera  1574: {
                   1575:        return;
                   1576: }
                   1577:
                   1578: __stdcall static void
1.15    ! dsl      1579: NdisReadNetworkAddress(ndis_status *status, void **addr, uint32_t *addrlen, ndis_handle adapter)
1.1       rittera  1580: {
                   1581:        struct ndis_softc       *sc;
                   1582:        ndis_miniport_block     *block;
                   1583:        uint8_t                 empty[] = { 0, 0, 0, 0, 0, 0 };
1.3       rittera  1584:
                   1585:        PN(NdisReadNetworkAddress)
1.1       rittera  1586:
                   1587:        block = (ndis_miniport_block *)adapter;
1.3       rittera  1588: #ifdef __FreeBSD__
1.1       rittera  1589:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1590: #else /* __NetBSD__ */
                   1591:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1592: #endif
1.1       rittera  1593:
1.2       rittera  1594: #ifdef __FreeBSD__
1.1       rittera  1595:        if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1.2       rittera  1596: #else
1.9       dyoung   1597:        if (bcmp(CLLADDR(sc->arpcom.ec_if.if_sadl),
1.2       rittera  1598:                 empty, ETHER_ADDR_LEN) == 0)
                   1599: #endif
                   1600:
1.1       rittera  1601:                *status = NDIS_STATUS_FAILURE;
                   1602:        else {
1.2       rittera  1603: #ifdef __FreeBSD__
1.1       rittera  1604:                *addr = sc->arpcom.ac_enaddr;
1.2       rittera  1605: #else
1.12      dyoung   1606:                memcpy(sc->ndis_mac, CLLADDR(sc->arpcom.ec_if.if_sadl),
                   1607:                    ETHER_ADDR_LEN);
                   1608:                 *addr = sc->ndis_mac;
1.2       rittera  1609: #endif
1.1       rittera  1610:                *addrlen = ETHER_ADDR_LEN;
                   1611:                *status = NDIS_STATUS_SUCCESS;
                   1612:        }
                   1613:
                   1614:        return;
                   1615: }
                   1616:
                   1617: __stdcall static ndis_status
1.5       christos 1618: NdisQueryMapRegisterCount(
1.6       christos 1619:        uint32_t                bustype,
1.5       christos 1620:        uint32_t                *cnt)
1.1       rittera  1621: {
1.3       rittera  1622:        PN(NdisQueryMapRegisterCount)
                   1623:
1.1       rittera  1624:        *cnt = 8192;
                   1625:        return(NDIS_STATUS_SUCCESS);
                   1626: }
                   1627:
                   1628: __stdcall static ndis_status
1.5       christos 1629: NdisMAllocateMapRegisters(
                   1630:        ndis_handle             adapter,
1.6       christos 1631:        uint32_t                dmachannel,
                   1632:        uint8_t                 dmasize,
1.5       christos 1633:        uint32_t                physmapneeded,
                   1634:        uint32_t                maxmap)
1.1       rittera  1635: {
                   1636:        struct ndis_softc       *sc;
                   1637:        ndis_miniport_block     *block;
1.3       rittera  1638: #ifdef __FreeBSD__
                   1639:        int error;
                   1640: #endif
                   1641:        int                     i, nseg = NDIS_MAXSEG;
1.1       rittera  1642:
1.3       rittera  1643:        PN(NdisMAllocateMapRegisters)
                   1644:
1.1       rittera  1645:        block = (ndis_miniport_block *)adapter;
1.3       rittera  1646: #ifdef __FreeBSD__
1.1       rittera  1647:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1648: #else /* __NetBSD__ */
                   1649:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1650: #endif
1.1       rittera  1651:
                   1652:        sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
                   1653:            M_DEVBUF, M_NOWAIT|M_ZERO);
                   1654:
                   1655:        if (sc->ndis_mmaps == NULL)
                   1656:                return(NDIS_STATUS_RESOURCES);
                   1657:
1.2       rittera  1658: #ifdef __FreeBSD__
1.1       rittera  1659:        error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
                   1660:            BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
                   1661:            NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
                   1662:            NULL, NULL, &sc->ndis_mtag);
                   1663:
                   1664:        if (error) {
                   1665:                free(sc->ndis_mmaps, M_DEVBUF);
                   1666:                return(NDIS_STATUS_RESOURCES);
                   1667:        }
1.2       rittera  1668: #else
                   1669:        sc->ndis_mtag = sc->ndis_parent_tag;
                   1670: #endif
1.3       rittera  1671:
                   1672:        for (i = 0; i < physmapneeded; i++) {
1.2       rittera  1673: #ifdef __FreeBSD__
1.1       rittera  1674:                bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1.2       rittera  1675: #else
                   1676:                bus_dmamap_create(sc->ndis_mtag, maxmap * nseg,
                   1677:                                  nseg, maxmap, BUS_DMA_NOWAIT,
                   1678:                                  0, &sc->ndis_mmaps[i]);
                   1679: #endif
1.3       rittera  1680:        }
1.1       rittera  1681:
                   1682:        sc->ndis_mmapcnt = physmapneeded;
                   1683:
                   1684:        return(NDIS_STATUS_SUCCESS);
                   1685: }
                   1686:
                   1687: __stdcall static void
1.15    ! dsl      1688: NdisMFreeMapRegisters(ndis_handle adapter)
1.1       rittera  1689: {
                   1690:        struct ndis_softc       *sc;
                   1691:        ndis_miniport_block     *block;
                   1692:        int                     i;
                   1693:
1.3       rittera  1694:        PN(NdisMFreeMapRegisters)
                   1695:
1.1       rittera  1696:        block = (ndis_miniport_block *)adapter;
1.3       rittera  1697: #ifdef __FreeBSD__
1.1       rittera  1698:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1699: #else /* __NetBSD__ */
                   1700:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1701: #endif
1.1       rittera  1702:
                   1703:        for (i = 0; i < sc->ndis_mmapcnt; i++)
                   1704:                bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
                   1705:
                   1706:        free(sc->ndis_mmaps, M_DEVBUF);
                   1707:
1.3       rittera  1708: #ifdef __FreeBSD__
1.1       rittera  1709:        bus_dma_tag_destroy(sc->ndis_mtag);
1.3       rittera  1710: #endif
1.1       rittera  1711:
                   1712:        return;
                   1713: }
                   1714:
                   1715: static void
1.15    ! dsl      1716: ndis_mapshared_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1.1       rittera  1717: {
                   1718:        ndis_physaddr           *p;
                   1719:
1.3       rittera  1720:        /* PN(ndis_mapshared_cb) */
                   1721:
1.1       rittera  1722:        if (error || nseg > 1)
                   1723:                return;
                   1724:
                   1725:        p = arg;
                   1726:
                   1727:        p->np_quad = segs[0].ds_addr;
                   1728:
                   1729:        return;
                   1730: }
                   1731:
                   1732: /*
                   1733:  * This maps to bus_dmamem_alloc().
                   1734:  */
                   1735: __stdcall static void
1.5       christos 1736: NdisMAllocateSharedMemory(
                   1737:        ndis_handle             adapter,
                   1738:        uint32_t                len,
1.6       christos 1739:        uint8_t                 cached,
1.5       christos 1740:        void                    **vaddr,
                   1741:        ndis_physaddr           *paddr)
1.1       rittera  1742: {
                   1743:        ndis_miniport_block     *block;
                   1744:        struct ndis_softc       *sc;
                   1745:        struct ndis_shmem       *sh;
                   1746:        int                     error;
1.3       rittera  1747: #ifdef __NetBSD__
1.2       rittera  1748:        bus_dma_segment_t       segs;
1.3       rittera  1749:        int                                     nsegs;
1.2       rittera  1750: #endif
1.1       rittera  1751:
1.3       rittera  1752:        /* PN(NdisMAllocateSharedMemory) */
                   1753:
1.1       rittera  1754:        if (adapter == NULL)
                   1755:                return;
                   1756:
                   1757:        block = (ndis_miniport_block *)adapter;
1.3       rittera  1758: #ifdef __FreeBSD__
1.1       rittera  1759:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1760: #else /* __NetBSD__ */
                   1761:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1762: #endif
1.1       rittera  1763:
                   1764:        sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
                   1765:        if (sh == NULL)
                   1766:                return;
                   1767:
                   1768:        /*
                   1769:         * When performing shared memory allocations, create a tag
                   1770:         * with a lowaddr limit that restricts physical memory mappings
                   1771:         * so that they all fall within the first 1GB of memory.
                   1772:         * At least one device/driver combination (Linksys Instant
                   1773:         * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
                   1774:         * problems with performing DMA operations with physical
                   1775:         * addresses that lie above the 1GB mark. I don't know if this
                   1776:         * is a hardware limitation or if the addresses are being
                   1777:         * truncated within the driver, but this seems to be the only
                   1778:         * way to make these cards work reliably in systems with more
                   1779:         * than 1GB of physical memory.
                   1780:         */
                   1781:
1.2       rittera  1782: #ifdef __FreeBSD__
1.1       rittera  1783:        error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
                   1784:            0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL,
                   1785:            NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
                   1786:            &sh->ndis_stag);
                   1787:
                   1788:        if (error) {
                   1789:                free(sh, M_DEVBUF);
                   1790:                return;
                   1791:        }
                   1792:
                   1793:        error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
                   1794:            BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
                   1795:
                   1796:        if (error) {
                   1797:                bus_dma_tag_destroy(sh->ndis_stag);
                   1798:                free(sh, M_DEVBUF);
                   1799:                return;
                   1800:        }
                   1801:
                   1802:        error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
                   1803:            len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
                   1804:
                   1805:        if (error) {
                   1806:                bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
                   1807:                bus_dma_tag_destroy(sh->ndis_stag);
                   1808:                free(sh, M_DEVBUF);
                   1809:                return;
                   1810:        }
1.2       rittera  1811: #else
1.3       rittera  1812:        sh->ndis_stag = sc->ndis_parent_tag;
                   1813:
1.2       rittera  1814:        error = bus_dmamem_alloc(sh->ndis_stag, len, 64, 0,
                   1815:                                 &segs, 1, &nsegs, BUS_DMA_NOWAIT);
1.3       rittera  1816:
1.2       rittera  1817:        if (error) {
                   1818:                printf("bus_dmamem_alloc failed(1)\n");
                   1819:                return;
                   1820:        }
                   1821:
                   1822:        error = bus_dmamem_map(sh->ndis_stag, &segs, nsegs,
1.7       christos 1823:                                len, /*(void **)&vaddr*/ (void **)vaddr, BUS_DMA_NOWAIT);
1.2       rittera  1824:
1.3       rittera  1825:        /* printf("*vaddr = %x\n", (unsigned int)*vaddr); */
                   1826:
1.2       rittera  1827:        if (error) {
                   1828:                printf("bus_dmamem_alloc failed(2)\n");
                   1829:                /* XXX free */
                   1830:                return;
                   1831:        }
                   1832:
                   1833:        error = bus_dmamap_create(sh->ndis_stag, len, nsegs,
                   1834:                                  BUS_SPACE_MAXSIZE_32BIT, 0,
1.3       rittera  1835:                                  BUS_DMA_ALLOCNOW, &sh->ndis_smap);
1.2       rittera  1836:
                   1837:        if (error) {
                   1838:                printf("bus_dmamem_alloc failed(3)\n");
                   1839:                /* XXX free, unmap */
                   1840:                return;
                   1841:        }
1.3       rittera  1842:
                   1843:        error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, /*vaddr*/ *vaddr,
1.2       rittera  1844:                                len, NULL, BUS_DMA_NOWAIT);
                   1845:        ndis_mapshared_cb((void *)paddr,
                   1846:                          sh->ndis_smap->dm_segs,
                   1847:                          sh->ndis_smap->dm_nsegs, error);
                   1848:
                   1849:        if (error) {
                   1850:                printf("bus_dmamem_alloc failed(3)\n");
                   1851:                /* XXX free, unmap, destroy */
                   1852:                return;
                   1853:        }
                   1854: #endif
1.1       rittera  1855:
                   1856:        sh->ndis_saddr = *vaddr;
                   1857:        sh->ndis_next = sc->ndis_shlist;
                   1858:        sc->ndis_shlist = sh;
                   1859:
                   1860:        return;
                   1861: }
                   1862:
                   1863: struct ndis_allocwork {
                   1864:        ndis_handle             na_adapter;
                   1865:        uint32_t                na_len;
                   1866:        uint8_t                 na_cached;
                   1867:        void                    *na_ctx;
                   1868: };
                   1869:
                   1870: static void
1.15    ! dsl      1871: ndis_asyncmem_complete(void *arg)
1.1       rittera  1872: {
                   1873:        ndis_miniport_block     *block;
                   1874:        struct ndis_softc       *sc;
                   1875:        struct ndis_allocwork   *w;
                   1876:        void                    *vaddr;
                   1877:        ndis_physaddr           paddr;
                   1878:        __stdcall ndis_allocdone_handler        donefunc;
                   1879:
                   1880:        w = arg;
                   1881:        block = (ndis_miniport_block *)w->na_adapter;
1.3       rittera  1882: #ifdef __FreeBSD__
1.1       rittera  1883:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1884: #else /* __NetBSD__ */
                   1885:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1886: #endif
                   1887:
                   1888:        PN(ndis_asyncmem_complete)
1.1       rittera  1889:
                   1890:        vaddr = NULL;
                   1891:        paddr.np_quad = 0;
                   1892:
                   1893:        donefunc = sc->ndis_chars->nmc_allocate_complete_func;
                   1894:        NdisMAllocateSharedMemory(w->na_adapter, w->na_len,
                   1895:            w->na_cached, &vaddr, &paddr);
                   1896:        MSCALL5(donefunc, w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
                   1897:
                   1898:        free(arg, M_DEVBUF);
                   1899:
                   1900:        return;
                   1901: }
                   1902:
                   1903: __stdcall static ndis_status
1.15    ! dsl      1904: NdisMAllocateSharedMemoryAsync(ndis_handle adapter, uint32_t len, uint8_t cached, void *ctx)
1.1       rittera  1905: {
                   1906:        struct ndis_allocwork   *w;
                   1907:
1.3       rittera  1908:        PN(NdisMAllocateSharedMemoryAsync)
                   1909:
1.1       rittera  1910:        if (adapter == NULL)
                   1911:                return(NDIS_STATUS_FAILURE);
                   1912:
                   1913:        w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT);
                   1914:
                   1915:        if (w == NULL)
                   1916:                return(NDIS_STATUS_FAILURE);
                   1917:
                   1918:        w->na_adapter = adapter;
                   1919:        w->na_cached = cached;
                   1920:        w->na_len = len;
                   1921:        w->na_ctx = ctx;
                   1922:
                   1923:        /*
                   1924:         * Pawn this work off on the SWI thread instead of the
                   1925:         * taskqueue thread, because sometimes drivers will queue
                   1926:         * up work items on the taskqueue thread that will block,
                   1927:         * which would prevent the memory allocation from completing
                   1928:         * when we need it.
                   1929:         */
                   1930:        ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI);
                   1931:
                   1932:        return(NDIS_STATUS_PENDING);
                   1933: }
                   1934:
                   1935: __stdcall static void
1.5       christos 1936: NdisMFreeSharedMemory(
                   1937:        ndis_handle             adapter,
1.6       christos 1938:        uint32_t                len,
                   1939:        uint8_t                 cached,
1.5       christos 1940:        void                    *vaddr,
1.6       christos 1941:        ndis_physaddr           paddr)
1.1       rittera  1942: {
                   1943:        ndis_miniport_block     *block;
                   1944:        struct ndis_softc       *sc;
                   1945:        struct ndis_shmem       *sh, *prev;
                   1946:
1.3       rittera  1947:        PN(NdisMFreeSharedMemory)
                   1948:
1.1       rittera  1949:        if (vaddr == NULL || adapter == NULL)
                   1950:                return;
                   1951:
                   1952:        block = (ndis_miniport_block *)adapter;
1.3       rittera  1953: #ifdef __FreeBSD__
1.1       rittera  1954:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1955: #else /* __NetBSD__ */
                   1956:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1957: #endif
1.1       rittera  1958:        sh = prev = sc->ndis_shlist;
                   1959:
                   1960:        /* Sanity check: is list empty? */
                   1961:
                   1962:        if (sh == NULL)
                   1963:                return;
                   1964:
                   1965:        while (sh) {
                   1966:                if (sh->ndis_saddr == vaddr)
                   1967:                        break;
                   1968:                prev = sh;
                   1969:                sh = sh->ndis_next;
                   1970:        }
                   1971:
                   1972:        bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1.2       rittera  1973: #ifdef __FreeBSD__
1.1       rittera  1974:        bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1.3       rittera  1975:        bus_dma_tag_destroy(sh->ndis_stag);
1.2       rittera  1976: #else
                   1977:        bus_dmamem_unmap(sh->ndis_stag, vaddr, sh->ndis_smap->dm_mapsize);
                   1978:        bus_dmamem_free(sh->ndis_stag,
                   1979:                        sh->ndis_smap->dm_segs, sh->ndis_smap->dm_nsegs );
                   1980: #endif
1.1       rittera  1981:        if (sh == sc->ndis_shlist)
                   1982:                sc->ndis_shlist = sh->ndis_next;
                   1983:        else
                   1984:                prev->ndis_next = sh->ndis_next;
                   1985:
                   1986:        free(sh, M_DEVBUF);
                   1987:
                   1988:        return;
                   1989: }
                   1990:
                   1991: __stdcall static ndis_status
1.5       christos 1992: NdisMMapIoSpace(
                   1993:        void                    **vaddr,
                   1994:        ndis_handle             adapter,
                   1995:        ndis_physaddr           paddr,
1.6       christos 1996:        uint32_t                len)
1.1       rittera  1997: {
                   1998:        ndis_miniport_block     *block;
                   1999:        struct ndis_softc       *sc;
                   2000:
1.3       rittera  2001:        PN(NdisMMapIoSpace)
                   2002:
1.1       rittera  2003:        if (adapter == NULL)
                   2004:                return(NDIS_STATUS_FAILURE);
                   2005:
                   2006:        block = (ndis_miniport_block *)adapter;
1.3       rittera  2007: #ifdef __FreeBSD__
1.1       rittera  2008:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  2009: #else /* __NetBSD__ */
                   2010:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   2011: #endif
                   2012:
1.1       rittera  2013:
1.3       rittera  2014: #ifdef __FreeBSD__
1.1       rittera  2015:        if (sc->ndis_res_mem != NULL &&
                   2016:            paddr.np_quad == rman_get_start(sc->ndis_res_mem))
                   2017:                *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
                   2018:        else if (sc->ndis_res_altmem != NULL &&
                   2019:             paddr.np_quad == rman_get_start(sc->ndis_res_altmem))
                   2020:                *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem);
                   2021:        else if (sc->ndis_res_am != NULL &&
                   2022:             paddr.np_quad == rman_get_start(sc->ndis_res_am))
                   2023:                *vaddr = (void *)rman_get_virtual(sc->ndis_res_am);
                   2024:        else
                   2025:                return(NDIS_STATUS_FAILURE);
1.3       rittera  2026: #else
                   2027: /* TODO: add one for sc->ndis_res_am once PCMCIA is going */
                   2028:        if (sc->ndis_res_mem != NULL &&
                   2029:            paddr.np_quad == sc->ndis_res_mem->res_base)
                   2030:                *vaddr = bus_space_vaddr(sc->ndis_res_mem->res_tag,
                   2031:                                        sc->ndis_res_mem->res_handle);
                   2032:        else if (sc->ndis_res_altmem != NULL &&
                   2033:             paddr.np_quad == sc->ndis_res_altmem->res_base)
                   2034:                *vaddr = bus_space_vaddr(sc->ndis_res_altmem->res_tag,
                   2035:                                        sc->ndis_res_altmem->res_handle);
                   2036:        else
                   2037:                return(NDIS_STATUS_FAILURE);
                   2038: /*
                   2039:        *vaddr = bus_space_vaddr(sc->ndis_res_mem->res_tag,
                   2040:                                sc->ndis_res_mem->res_handle);
                   2041: */
                   2042: #endif
1.1       rittera  2043:
                   2044:        return(NDIS_STATUS_SUCCESS);
                   2045: }
                   2046:
                   2047: __stdcall static void
1.5       christos 2048: NdisMUnmapIoSpace(
1.6       christos 2049:        ndis_handle             adapter,
                   2050:        void                    *vaddr,
                   2051:        uint32_t                len)
1.1       rittera  2052: {
                   2053:        return;
                   2054: }
                   2055:
                   2056: __stdcall static uint32_t
                   2057: NdisGetCacheFillSize(void)
                   2058: {
                   2059:        return(128);
                   2060: }
                   2061:
                   2062: __stdcall static uint32_t
1.6       christos 2063: NdisMGetDmaAlignment(ndis_handle handle)
1.1       rittera  2064: {
                   2065:        return(128);
                   2066: }
                   2067:
                   2068: /*
                   2069:  * NDIS has two methods for dealing with NICs that support DMA.
                   2070:  * One is to just pass packets to the driver and let it call
                   2071:  * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
                   2072:  * all by itself, and the other is to let the NDIS library handle the
                   2073:  * buffer mapping internally, and hand the driver an already populated
                   2074:  * scatter/gather fragment list. If the driver calls
                   2075:  * NdisMInitializeScatterGatherDma(), it wants to use the latter
                   2076:  * method.
                   2077:  */
                   2078:
                   2079: __stdcall static ndis_status
1.5       christos 2080: NdisMInitializeScatterGatherDma(
                   2081:        ndis_handle             adapter,
1.6       christos 2082:        uint8_t                 is64,
                   2083:        uint32_t                maxphysmap)
1.1       rittera  2084: {
                   2085:        struct ndis_softc       *sc;
                   2086:        ndis_miniport_block     *block;
1.3       rittera  2087: #ifdef __FreeBSD__
1.1       rittera  2088:        int                     error;
1.3       rittera  2089: #endif
                   2090:
                   2091:        PN(NdisMInitializeScatterGatherDma)
1.1       rittera  2092:
                   2093:        if (adapter == NULL)
                   2094:                return(NDIS_STATUS_FAILURE);
                   2095:        block = (ndis_miniport_block *)adapter;
1.3       rittera  2096: #ifdef __FreeBSD__
1.1       rittera  2097:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  2098: #else /* __NetBSD__ */
                   2099:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   2100: #endif
1.1       rittera  2101:
                   2102:        /* Don't do this twice. */
                   2103:        if (sc->ndis_sc == 1)
                   2104:                return(NDIS_STATUS_SUCCESS);
                   2105:
1.3       rittera  2106: #ifdef __FreeBSD__
1.1       rittera  2107:        error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
                   2108:            BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
                   2109:            MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
                   2110:            NULL, NULL, &sc->ndis_ttag);
1.3       rittera  2111: #else /* __NetBSD__ */
                   2112: /* TODO: Is this correct to just use the parent tag? */
                   2113:        sc->ndis_ttag = sc->ndis_parent_tag;
                   2114: #endif
1.1       rittera  2115:
                   2116:        sc->ndis_sc = 1;
                   2117:
                   2118:        return(NDIS_STATUS_SUCCESS);
                   2119: }
                   2120:
                   2121: __stdcall void
1.15    ! dsl      2122: NdisAllocatePacketPool(ndis_status *status, ndis_handle *pool, uint32_t descnum, uint32_t protrsvdlen)
1.1       rittera  2123: {
                   2124:        ndis_packet             *cur;
                   2125:        int                     i;
1.3       rittera  2126:
                   2127:        PN(NdisAllocatePacketPool)
1.1       rittera  2128:
                   2129:        *pool = malloc((sizeof(ndis_packet) + protrsvdlen) *
                   2130:            ((descnum + NDIS_POOL_EXTRA) + 1),
                   2131:            M_DEVBUF, M_NOWAIT|M_ZERO);
                   2132:
                   2133:        if (*pool == NULL) {
                   2134:                *status = NDIS_STATUS_RESOURCES;
                   2135:                return;
                   2136:        }
                   2137:
                   2138:        cur = (ndis_packet *)*pool;
                   2139:        KeInitializeSpinLock(&cur->np_lock);
                   2140:        cur->np_private.npp_flags = 0x1; /* mark the head of the list */
                   2141:        cur->np_private.npp_totlen = 0; /* init deletetion flag */
                   2142:        for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
                   2143:                cur->np_private.npp_head = (ndis_handle)(cur + 1);
                   2144:                cur++;
                   2145:        }
                   2146:
                   2147:        *status = NDIS_STATUS_SUCCESS;
                   2148:        return;
                   2149: }
                   2150:
                   2151: __stdcall void
1.15    ! dsl      2152: NdisAllocatePacketPoolEx(ndis_status *status, ndis_handle *pool, uint32_t descnum, uint32_t oflowdescnum, uint32_t protrsvdlen)
1.1       rittera  2153: {
                   2154:        return(NdisAllocatePacketPool(status, pool,
                   2155:            descnum + oflowdescnum, protrsvdlen));
                   2156: }
                   2157:
                   2158: __stdcall uint32_t
1.15    ! dsl      2159: NdisPacketPoolUsage(ndis_handle pool)
1.1       rittera  2160: {
                   2161:        ndis_packet             *head;
                   2162:        uint8_t                 irql;
                   2163:        uint32_t                cnt;
                   2164:
                   2165:        head = (ndis_packet *)pool;
                   2166:        KeAcquireSpinLock(&head->np_lock, &irql);
                   2167:        cnt = head->np_private.npp_count;
                   2168:        KeReleaseSpinLock(&head->np_lock, irql);
                   2169:
                   2170:        return(cnt);
                   2171: }
                   2172:
                   2173: __stdcall void
1.15    ! dsl      2174: NdisFreePacketPool(ndis_handle pool)
1.1       rittera  2175: {
                   2176:        ndis_packet             *head;
                   2177:        uint8_t                 irql;
                   2178:
                   2179:        head = pool;
                   2180:
                   2181:        /* Mark this pool as 'going away.' */
                   2182:
                   2183:        KeAcquireSpinLock(&head->np_lock, &irql);
                   2184:        head->np_private.npp_totlen = 1;
                   2185:
                   2186:        /* If there are no buffers loaned out, destroy the pool. */
                   2187:
                   2188:        if (head->np_private.npp_count == 0) {
                   2189:                KeReleaseSpinLock(&head->np_lock, irql);
                   2190:                free(pool, M_DEVBUF);
                   2191:        } else {
                   2192:                printf("NDIS: buggy driver deleting active packet pool!\n");
                   2193:                KeReleaseSpinLock(&head->np_lock, irql);
                   2194:        }
                   2195:
                   2196:        return;
                   2197: }
                   2198:
                   2199: __stdcall void
1.15    ! dsl      2200: NdisAllocatePacket(ndis_status *status, ndis_packet **packet, ndis_handle pool)
1.1       rittera  2201: {
                   2202:        ndis_packet             *head, *pkt;
                   2203:        uint8_t                 irql;
                   2204:
1.3       rittera  2205: #ifdef __NetBSD__
                   2206: /*TODO: For some reason NdisAllocatePacket was getting called once with pool being NULL
                   2207:  *TODO: and this was causing a seg-fault.  This seems to solve the problem, but I'm not
                   2208:  *TODO: should happen at all in the first place.
                   2209:  */
                   2210:        if(pool == NULL) {
                   2211:                *status = NDIS_STATUS_FAILURE;
                   2212:                return;
                   2213:        }
                   2214: #endif
                   2215:
1.1       rittera  2216:        head = (ndis_packet *)pool;
                   2217:        KeAcquireSpinLock(&head->np_lock, &irql);
                   2218:
                   2219:        if (head->np_private.npp_flags != 0x1) {
                   2220:                *status = NDIS_STATUS_FAILURE;
                   2221:                KeReleaseSpinLock(&head->np_lock, irql);
                   2222:                return;
                   2223:        }
                   2224:
                   2225:        /*
                   2226:         * If this pool is marked as 'going away' don't allocate any
                   2227:         * more packets out of it.
                   2228:         */
                   2229:
                   2230:        if (head->np_private.npp_totlen) {
                   2231:                *status = NDIS_STATUS_FAILURE;
                   2232:                KeReleaseSpinLock(&head->np_lock, irql);
                   2233:                return;
                   2234:        }
                   2235:
                   2236:        pkt = (ndis_packet *)head->np_private.npp_head;
                   2237:
                   2238:        if (pkt == NULL) {
                   2239:                *status = NDIS_STATUS_RESOURCES;
                   2240:                KeReleaseSpinLock(&head->np_lock, irql);
                   2241:                return;
                   2242:        }
                   2243:
                   2244:        head->np_private.npp_head = pkt->np_private.npp_head;
                   2245:
                   2246:        pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
                   2247:        /* Save pointer to the pool. */
                   2248:        pkt->np_private.npp_pool = head;
                   2249:
                   2250:        /* Set the oob offset pointer. Lots of things expect this. */
                   2251:        pkt->np_private.npp_packetooboffset =
                   2252:            offsetof(ndis_packet, np_oob);
                   2253:
                   2254:        /*
                   2255:         * We must initialize the packet flags correctly in order
                   2256:         * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
                   2257:         * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work
                   2258:          * correctly.
                   2259:         */
                   2260:        pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
                   2261:        pkt->np_private.npp_validcounts = FALSE;
                   2262:
                   2263:        *packet = pkt;
                   2264:
                   2265:        head->np_private.npp_count++;
                   2266:        *status = NDIS_STATUS_SUCCESS;
                   2267:
                   2268:        KeReleaseSpinLock(&head->np_lock, irql);
                   2269:
                   2270:        return;
                   2271: }
                   2272:
                   2273: __stdcall void
1.15    ! dsl      2274: NdisFreePacket(ndis_packet *packet)
1.1       rittera  2275: {
                   2276:        ndis_packet             *head;
                   2277:        uint8_t                 irql;
                   2278:
                   2279:        if (packet == NULL || packet->np_private.npp_pool == NULL)
                   2280:                return;
                   2281:
                   2282:        head = packet->np_private.npp_pool;
                   2283:        KeAcquireSpinLock(&head->np_lock, &irql);
                   2284:
                   2285:        if (head->np_private.npp_flags != 0x1) {
                   2286:                KeReleaseSpinLock(&head->np_lock, irql);
                   2287:                return;
                   2288:        }
                   2289:
                   2290:        packet->np_private.npp_head = head->np_private.npp_head;
                   2291:        head->np_private.npp_head = (ndis_buffer *)packet;
                   2292:        head->np_private.npp_count--;
                   2293:
                   2294:        /*
                   2295:         * If the pool has been marked for deletion and there are
                   2296:         * no more packets outstanding, nuke the pool.
                   2297:         */
                   2298:
                   2299:        if (head->np_private.npp_totlen && head->np_private.npp_count == 0) {
                   2300:                KeReleaseSpinLock(&head->np_lock, irql);
                   2301:                free(head, M_DEVBUF);
                   2302:        } else
                   2303:                KeReleaseSpinLock(&head->np_lock, irql);
                   2304:
                   2305:        return;
                   2306: }
                   2307:
                   2308: __stdcall static void
1.15    ! dsl      2309: NdisUnchainBufferAtFront(ndis_packet *packet, ndis_buffer **buf)
1.1       rittera  2310: {
                   2311:        ndis_packet_private     *priv;
                   2312:
                   2313:        if (packet == NULL || buf == NULL)
                   2314:                return;
                   2315:
                   2316:        priv = &packet->np_private;
                   2317:
                   2318:        priv->npp_validcounts = FALSE;
                   2319:
                   2320:        if (priv->npp_head == priv->npp_tail) {
                   2321:                *buf = priv->npp_head;
                   2322:                priv->npp_head = priv->npp_tail = NULL;
                   2323:        } else {
                   2324:                *buf = priv->npp_head;
                   2325:                priv->npp_head = (*buf)->mdl_next;
                   2326:        }
                   2327:
                   2328:        return;
                   2329: }
                   2330:
                   2331: __stdcall static void
1.15    ! dsl      2332: NdisUnchainBufferAtBack(ndis_packet *packet, ndis_buffer **buf)
1.1       rittera  2333: {
                   2334:        ndis_packet_private     *priv;
                   2335:        ndis_buffer             *tmp;
                   2336:
                   2337:        if (packet == NULL || buf == NULL)
                   2338:                return;
                   2339:
                   2340:        priv = &packet->np_private;
                   2341:
                   2342:        priv->npp_validcounts = FALSE;
                   2343:
                   2344:        if (priv->npp_head == priv->npp_tail) {
                   2345:                *buf = priv->npp_head;
                   2346:                priv->npp_head = priv->npp_tail = NULL;
                   2347:        } else {
                   2348:                *buf = priv->npp_tail;
                   2349:                tmp = priv->npp_head;
                   2350:                while (tmp->mdl_next != priv->npp_tail)
                   2351:                        tmp = tmp->mdl_next;
                   2352:                priv->npp_tail = tmp;
                   2353:                tmp->mdl_next = NULL;
                   2354:        }
                   2355:
                   2356:        return;
                   2357: }
                   2358:
                   2359: /*
                   2360:  * The NDIS "buffer" is really an MDL (memory descriptor list)
                   2361:  * which is used to describe a buffer in a way that allows it
                   2362:  * to mapped into different contexts. We have to be careful how
                   2363:  * we handle them: in some versions of Windows, the NdisFreeBuffer()
                   2364:  * routine is an actual function in the NDIS API, but in others
                   2365:  * it's just a macro wrapper around IoFreeMdl(). There's really
                   2366:  * no way to use the 'descnum' parameter to count how many
                   2367:  * "buffers" are allocated since in order to use IoFreeMdl() to
                   2368:  * dispose of a buffer, we have to use IoAllocateMdl() to allocate
                   2369:  * them, and IoAllocateMdl() just grabs them out of the heap.
                   2370:  */
                   2371:
                   2372: __stdcall static void
1.5       christos 2373: NdisAllocateBufferPool(
                   2374:        ndis_status             *status,
                   2375:        ndis_handle             *pool,
1.6       christos 2376:        uint32_t                descnum)
1.1       rittera  2377: {
                   2378:        /*
                   2379:         * The only thing we can really do here is verify that descnum
                   2380:         * is a reasonable value, but I really don't know what to check
                   2381:         * it against.
                   2382:         */
                   2383:
                   2384:        *pool = NonPagedPool;
                   2385:        *status = NDIS_STATUS_SUCCESS;
                   2386:        return;
                   2387: }
                   2388:
                   2389: __stdcall static void
1.6       christos 2390: NdisFreeBufferPool(ndis_handle pool)
1.1       rittera  2391: {
                   2392:        return;
                   2393: }
                   2394:
                   2395: __stdcall static void
1.5       christos 2396: NdisAllocateBuffer(
                   2397:        ndis_status             *status,
                   2398:        ndis_buffer             **buffer,
1.6       christos 2399:        ndis_handle             pool,
1.5       christos 2400:        void                    *vaddr,
                   2401:        uint32_t                len)
1.1       rittera  2402: {
                   2403:        ndis_buffer             *buf;
                   2404:
                   2405:        buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL);
                   2406:        if (buf == NULL) {
                   2407:                *status = NDIS_STATUS_RESOURCES;
                   2408:                return;
                   2409:        }
                   2410:
                   2411:        *buffer = buf;
                   2412:        *status = NDIS_STATUS_SUCCESS;
                   2413:
                   2414:        return;
                   2415: }
                   2416:
                   2417: __stdcall static void
1.15    ! dsl      2418: NdisFreeBuffer(ndis_buffer *buf)
1.1       rittera  2419: {
                   2420:        IoFreeMdl(buf);
                   2421:        return;
                   2422: }
                   2423:
                   2424: /* Aw c'mon. */
                   2425:
                   2426: __stdcall static uint32_t
1.15    ! dsl      2427: NdisBufferLength(ndis_buffer *buf)
1.1       rittera  2428: {
                   2429:        return(MmGetMdlByteCount(buf));
                   2430: }
                   2431:
                   2432: /*
                   2433:  * Get the virtual address and length of a buffer.
                   2434:  * Note: the vaddr argument is optional.
                   2435:  */
                   2436:
                   2437: __stdcall static void
1.15    ! dsl      2438: NdisQueryBuffer(ndis_buffer *buf, void **vaddr, uint32_t *len)
1.1       rittera  2439: {
                   2440:        if (vaddr != NULL)
                   2441:                *vaddr = MmGetMdlVirtualAddress(buf);
                   2442:        *len = MmGetMdlByteCount(buf);
                   2443:
                   2444:        return;
                   2445: }
                   2446:
                   2447: /* Same as above -- we don't care about the priority. */
                   2448:
                   2449: __stdcall static void
1.5       christos 2450: NdisQueryBufferSafe(
                   2451:        ndis_buffer             *buf,
                   2452:        void                    **vaddr,
                   2453:        uint32_t                *len,
1.6       christos 2454:        uint32_t                prio)
1.1       rittera  2455: {
                   2456:        if (vaddr != NULL)
                   2457:                *vaddr = MmGetMdlVirtualAddress(buf);
                   2458:        *len = MmGetMdlByteCount(buf);
                   2459:
                   2460:        return;
                   2461: }
                   2462:
                   2463: /* Damnit Microsoft!! How many ways can you do the same thing?! */
                   2464:
                   2465: __stdcall static void *
1.15    ! dsl      2466: NdisBufferVirtualAddress(ndis_buffer *buf)
1.1       rittera  2467: {
                   2468:        return(MmGetMdlVirtualAddress(buf));
                   2469: }
                   2470:
                   2471: __stdcall static void *
1.5       christos 2472: NdisBufferVirtualAddressSafe(
                   2473:        ndis_buffer             *buf,
1.6       christos 2474:        uint32_t                prio)
1.1       rittera  2475: {
                   2476:        return(MmGetMdlVirtualAddress(buf));
                   2477: }
                   2478:
                   2479: __stdcall static void
1.15    ! dsl      2480: NdisAdjustBufferLength(ndis_buffer *buf, int len)
1.1       rittera  2481: {
                   2482:        MmGetMdlByteCount(buf) = len;
                   2483:
                   2484:        return;
                   2485: }
                   2486:
                   2487: __stdcall static uint32_t
1.15    ! dsl      2488: NdisInterlockedIncrement(uint32_t *addend)
1.1       rittera  2489: {
1.11      ad       2490:        atomic_inc_32(addend);
1.1       rittera  2491:        return(*addend);
                   2492: }
                   2493:
                   2494: __stdcall static uint32_t
1.15    ! dsl      2495: NdisInterlockedDecrement(uint32_t *addend)
1.1       rittera  2496: {
1.11      ad       2497:        atomic_dec_32(addend);
1.1       rittera  2498:        return(*addend);
                   2499: }
                   2500:
                   2501: __stdcall static void
1.15    ! dsl      2502: NdisInitializeEvent(ndis_event *event)
1.1       rittera  2503: {
                   2504:        /*
                   2505:         * NDIS events are always notification
                   2506:         * events, and should be initialized to the
                   2507:         * not signaled state.
                   2508:         */
                   2509:
                   2510:        KeInitializeEvent(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE);
                   2511:        return;
                   2512: }
                   2513:
                   2514: __stdcall static void
1.15    ! dsl      2515: NdisSetEvent(ndis_event *event)
1.1       rittera  2516: {
                   2517:        KeSetEvent(&event->ne_event, 0, 0);
                   2518:        return;
                   2519: }
                   2520:
                   2521: __stdcall static void
1.15    ! dsl      2522: NdisResetEvent(ndis_event *event)
1.1       rittera  2523: {
                   2524:        KeResetEvent(&event->ne_event);
                   2525:        return;
                   2526: }
                   2527:
                   2528: __stdcall static uint8_t
1.15    ! dsl      2529: NdisWaitEvent(ndis_event *event, uint32_t msecs)
1.1       rittera  2530: {
                   2531:        int64_t                 duetime;
                   2532:        uint32_t                rval;
                   2533:
                   2534:        duetime = ((int64_t)msecs * -10000);
                   2535:
                   2536:        rval = KeWaitForSingleObject((nt_dispatch_header *)event,
                   2537:            0, 0, TRUE, msecs ? &duetime : NULL);
                   2538:
                   2539:        if (rval == STATUS_TIMEOUT)
                   2540:                return(FALSE);
                   2541:
                   2542:        return(TRUE);
                   2543: }
                   2544:
                   2545: __stdcall static ndis_status
1.15    ! dsl      2546: NdisUnicodeStringToAnsiString(ndis_ansi_string *dstr, ndis_unicode_string *sstr)
1.1       rittera  2547: {
                   2548:        if (dstr == NULL || sstr == NULL)
                   2549:                return(NDIS_STATUS_FAILURE);
                   2550:        if (ndis_unicode_to_ascii(sstr->us_buf,
                   2551:            sstr->us_len, &dstr->nas_buf))
                   2552:                return(NDIS_STATUS_FAILURE);
                   2553:        dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
                   2554:        return (NDIS_STATUS_SUCCESS);
                   2555: }
                   2556:
                   2557: __stdcall static ndis_status
1.15    ! dsl      2558: NdisAnsiStringToUnicodeString(ndis_unicode_string *dstr, ndis_ansi_string *sstr)
1.1       rittera  2559: {
                   2560:        char                    *str;
                   2561:        if (dstr == NULL || sstr == NULL)
                   2562:                return(NDIS_STATUS_FAILURE);
                   2563:        str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
                   2564:        if (str == NULL)
                   2565:                return(NDIS_STATUS_FAILURE);
                   2566:        strncpy(str, sstr->nas_buf, sstr->nas_len);
                   2567:        *(str + sstr->nas_len) = '\0';
                   2568:        if (ndis_ascii_to_unicode(str, &dstr->us_buf)) {
                   2569:                free(str, M_DEVBUF);
                   2570:                return(NDIS_STATUS_FAILURE);
                   2571:        }
                   2572:        dstr->us_len = dstr->us_maxlen = sstr->nas_len * 2;
                   2573:        free(str, M_DEVBUF);
                   2574:        return (NDIS_STATUS_SUCCESS);
                   2575: }
                   2576:
                   2577: __stdcall static ndis_status
1.5       christos 2578: NdisMPciAssignResources(
                   2579:        ndis_handle             adapter,
1.6       christos 2580:        uint32_t                slot,
1.5       christos 2581:        ndis_resource_list      **list)
1.1       rittera  2582: {
                   2583:        ndis_miniport_block     *block;
                   2584:
                   2585:        if (adapter == NULL || list == NULL)
                   2586:                return (NDIS_STATUS_FAILURE);
                   2587:
                   2588:        block = (ndis_miniport_block *)adapter;
                   2589:        *list = block->nmb_rlist;
                   2590:
                   2591:        return (NDIS_STATUS_SUCCESS);
                   2592: }
                   2593:
                   2594: __stdcall static ndis_status
1.5       christos 2595: NdisMRegisterInterrupt(
                   2596:        ndis_miniport_interrupt *intr,
                   2597:        ndis_handle             adapter,
1.6       christos 2598:        uint32_t                ivec,
                   2599:        uint32_t                ilevel,
1.5       christos 2600:        uint8_t                 reqisr,
                   2601:        uint8_t                 shared,
1.6       christos 2602:        ndis_interrupt_mode     imode)
1.1       rittera  2603: {
                   2604:        ndis_miniport_block     *block;
                   2605:
                   2606:        block = adapter;
                   2607:
                   2608:        intr->ni_block = adapter;
                   2609:        intr->ni_isrreq = reqisr;
                   2610:        intr->ni_shared = shared;
                   2611:        block->nmb_interrupt = intr;
                   2612:
                   2613:        KeInitializeSpinLock(&intr->ni_dpccountlock);
                   2614:
                   2615:        return(NDIS_STATUS_SUCCESS);
                   2616: }
                   2617:
                   2618: __stdcall static void
1.6       christos 2619: NdisMDeregisterInterrupt(ndis_miniport_interrupt *intr)
1.1       rittera  2620: {
                   2621:        return;
                   2622: }
                   2623:
                   2624: __stdcall static void
1.15    ! dsl      2625: NdisMRegisterAdapterShutdownHandler(ndis_handle adapter, void *shutdownctx, ndis_shutdown_handler shutdownfunc)
1.1       rittera  2626: {
                   2627:        ndis_miniport_block     *block;
                   2628:        ndis_miniport_characteristics *chars;
                   2629:        struct ndis_softc       *sc;
                   2630:
                   2631:        if (adapter == NULL)
                   2632:                return;
                   2633:
                   2634:        block = (ndis_miniport_block *)adapter;
1.3       rittera  2635: #ifdef __FreeBSD__
1.1       rittera  2636:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  2637: #else /* __NetBSD__ */
                   2638:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   2639: #endif
1.1       rittera  2640:        chars = sc->ndis_chars;
                   2641:
                   2642:        chars->nmc_shutdown_handler = shutdownfunc;
                   2643:        chars->nmc_rsvd0 = shutdownctx;
                   2644:
                   2645:        return;
                   2646: }
                   2647:
                   2648: __stdcall static void
1.15    ! dsl      2649: NdisMDeregisterAdapterShutdownHandler(ndis_handle adapter)
1.1       rittera  2650: {
                   2651:        ndis_miniport_block     *block;
                   2652:        ndis_miniport_characteristics *chars;
                   2653:        struct ndis_softc       *sc;
                   2654:
                   2655:        if (adapter == NULL)
                   2656:                return;
                   2657:
                   2658:        block = (ndis_miniport_block *)adapter;
1.3       rittera  2659: #ifdef __FreeBSD__
1.1       rittera  2660:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  2661: #else /* __NetBSD__ */
                   2662:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   2663: #endif
1.1       rittera  2664:        chars = sc->ndis_chars;
                   2665:
                   2666:        chars->nmc_shutdown_handler = NULL;
                   2667:        chars->nmc_rsvd0 = NULL;
                   2668:
                   2669:        return;
                   2670: }
                   2671:
                   2672: __stdcall static uint32_t
1.15    ! dsl      2673: NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *buf)
1.1       rittera  2674: {
                   2675:        if (buf == NULL)
                   2676:                return(0);
                   2677:        if (MmGetMdlByteCount(buf) == 0)
                   2678:                return(1);
                   2679:        return(SPAN_PAGES(MmGetMdlVirtualAddress(buf),
                   2680:            MmGetMdlByteCount(buf)));
                   2681: }
                   2682:
                   2683: __stdcall static void
1.15    ! dsl      2684: NdisGetBufferPhysicalArraySize(ndis_buffer *buf, uint32_t *pages)
1.1       rittera  2685: {
                   2686:        if (buf == NULL)
                   2687:                return;
                   2688:
                   2689:        *pages = NDIS_BUFFER_TO_SPAN_PAGES(buf);
                   2690:        return;
                   2691: }
                   2692:
                   2693: __stdcall static void
1.15    ! dsl      2694: NdisQueryBufferOffset(ndis_buffer *buf, uint32_t *off, uint32_t *len)
1.1       rittera  2695: {
                   2696:        if (buf == NULL)
                   2697:                return;
                   2698:
                   2699:        *off = MmGetMdlByteOffset(buf);
                   2700:        *len = MmGetMdlByteCount(buf);
                   2701:
                   2702:        return;
                   2703: }
                   2704:
                   2705: __stdcall static void
1.15    ! dsl      2706: NdisMSleep(uint32_t usecs)
1.1       rittera  2707: {
                   2708:        struct timeval          tv;
                   2709:
                   2710:        tv.tv_sec = 0;
                   2711:        tv.tv_usec = usecs;
                   2712:
1.2       rittera  2713: #ifdef __FreeBSD__
1.1       rittera  2714:        ndis_thsuspend(curthread->td_proc, NULL, tvtohz(&tv));
1.2       rittera  2715: #else
                   2716:        ndis_thsuspend(curproc, NULL, tvtohz(&tv));
                   2717: #endif
1.1       rittera  2718:
                   2719:        return;
                   2720: }
                   2721:
                   2722: __stdcall static uint32_t
1.15    ! dsl      2723: NdisReadPcmciaAttributeMemory(ndis_handle handle, uint32_t offset, void *buf, uint32_t len)
1.1       rittera  2724: {
                   2725:        struct ndis_softc       *sc;
                   2726:        ndis_miniport_block     *block;
                   2727:        bus_space_handle_t      bh;
                   2728:        bus_space_tag_t         bt;
                   2729:        char                    *dest;
                   2730:        int                     i;
                   2731:
                   2732:        if (handle == NULL)
                   2733:                return(0);
                   2734:
                   2735:        block = (ndis_miniport_block *)handle;
1.3       rittera  2736: #ifdef __FreeBSD__
1.1       rittera  2737:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  2738: #else /* __NetBSD__ */
                   2739:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   2740: #endif
1.1       rittera  2741:        dest = buf;
                   2742:
1.3       rittera  2743: #ifdef __FreeBSD__
                   2744:     bh = rman_get_bushandle(sc->ndis_res_am);
                   2745:     bt = rman_get_bustag(sc->ndis_res_am);
                   2746:
                   2747: #else
                   2748:     if ( sc->ndis_iftype == PCMCIABus  ){
                   2749:         bt = sc->ndis_res_pcmem.memt;
                   2750:         bh = sc->ndis_res_pcmem.memh;
                   2751:    } else { /* cardbus case */
                   2752:             /* TODO  what does it really wait for ? */
                   2753:         bt = sc->ndis_res_mem->res_tag;
                   2754:         bh = sc->ndis_res_mem->res_handle;
                   2755:    }
                   2756: #endif
1.1       rittera  2757:
                   2758:        for (i = 0; i < len; i++)
                   2759:                dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2);
                   2760:
                   2761:        return(i);
                   2762: }
                   2763:
                   2764: __stdcall static uint32_t
1.15    ! dsl      2765: NdisWritePcmciaAttributeMemory(ndis_handle handle, uint32_t offset, void *buf, uint32_t len)
1.1       rittera  2766: {
                   2767:        struct ndis_softc       *sc;
                   2768:        ndis_miniport_block     *block;
                   2769:        bus_space_handle_t      bh;
                   2770:        bus_space_tag_t         bt;
                   2771:        char                    *src;
                   2772:        int                     i;
                   2773:
                   2774:        if (handle == NULL)
                   2775:                return(0);
                   2776:
                   2777:        block = (ndis_miniport_block *)handle;
1.3       rittera  2778: #ifdef __FreeBSD__
1.1       rittera  2779:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  2780: #else /* __NetBSD__ */
                   2781:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   2782: #endif
1.1       rittera  2783:        src = buf;
1.3       rittera  2784: #ifdef __FreeBSD__
                   2785:     bh = rman_get_bushandle(sc->ndis_res_am);
                   2786:     bt = rman_get_bustag(sc->ndis_res_am);
                   2787: #else
                   2788:     if ( sc->ndis_iftype == PCMCIABus  ){
                   2789:         bt = sc->ndis_res_pcmem.memt;
                   2790:         bh = sc->ndis_res_pcmem.memh;
                   2791:    } else { /* cardbus case */
                   2792:             /* TODO  what does it really wait for ? */
                   2793:         bt = sc->ndis_res_mem->res_tag;
                   2794:         bh = sc->ndis_res_mem->res_handle;
                   2795:    }
                   2796: #endif
1.1       rittera  2797:
                   2798:        for (i = 0; i < len; i++)
                   2799:                bus_space_write_1(bt, bh, (offset + i) * 2, src[i]);
                   2800:
                   2801:        return(i);
                   2802: }
                   2803:
                   2804: __stdcall static list_entry *
1.15    ! dsl      2805: NdisInterlockedInsertHeadList(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
1.1       rittera  2806: {
                   2807:        list_entry              *flink;
                   2808:
                   2809:        KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
                   2810:        flink = head->nle_flink;
                   2811:        entry->nle_flink = flink;
                   2812:        entry->nle_blink = head;
                   2813:        flink->nle_blink = entry;
                   2814:        head->nle_flink = entry;
                   2815:        KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
                   2816:
                   2817:        return(flink);
                   2818: }
                   2819:
                   2820: __stdcall static list_entry *
1.15    ! dsl      2821: NdisInterlockedRemoveHeadList(list_entry *head, ndis_spin_lock *lock)
1.1       rittera  2822: {
                   2823:        list_entry              *flink;
                   2824:        list_entry              *entry;
                   2825:
                   2826:        KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
                   2827:        entry = head->nle_flink;
                   2828:        flink = entry->nle_flink;
                   2829:        head->nle_flink = flink;
                   2830:        flink->nle_blink = head;
                   2831:        KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
                   2832:
                   2833:        return(entry);
                   2834: }
                   2835:
                   2836: __stdcall static list_entry *
1.15    ! dsl      2837: NdisInterlockedInsertTailList(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
1.1       rittera  2838: {
                   2839:        list_entry              *blink;
                   2840:
                   2841:        KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
                   2842:        blink = head->nle_blink;
                   2843:        entry->nle_flink = head;
                   2844:        entry->nle_blink = blink;
                   2845:        blink->nle_flink = entry;
                   2846:        head->nle_blink = entry;
                   2847:        KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
                   2848:
                   2849:        return(blink);
                   2850: }
                   2851:
                   2852: __stdcall static uint8_t
1.15    ! dsl      2853: NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *intr, void *syncfunc, void *syncctx)
1.1       rittera  2854: {
                   2855:        __stdcall uint8_t (*sync)(void *);
                   2856:        uint8_t                 rval;
                   2857:        uint8_t                 irql;
                   2858:
                   2859:        if (syncfunc == NULL || syncctx == NULL)
                   2860:                return(0);
                   2861:
                   2862:        sync = syncfunc;
                   2863:        KeAcquireSpinLock(&intr->ni_dpccountlock, &irql);
                   2864:        rval = MSCALL1(sync, syncctx);
                   2865:        KeReleaseSpinLock(&intr->ni_dpccountlock, irql);
                   2866:
                   2867:        return(rval);
                   2868: }
                   2869:
                   2870: /*
                   2871:  * Return the number of 100 nanosecond intervals since
                   2872:  * January 1, 1601. (?!?!)
                   2873:  */
                   2874: __stdcall static void
1.15    ! dsl      2875: NdisGetCurrentSystemTime(uint64_t *tval)
1.1       rittera  2876: {
                   2877:        struct timespec         ts;
1.3       rittera  2878: #ifdef __NetBSD__
                   2879:     struct timeval      tv;
                   2880:
                   2881:     microtime(&tv);
                   2882:     TIMEVAL_TO_TIMESPEC(&tv,&ts);
                   2883: #else
                   2884:     nanotime(&ts);
                   2885: #endif
1.1       rittera  2886:
                   2887:        *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
1.2       rittera  2888:            (uint64_t)11644473600ULL;
1.1       rittera  2889:
                   2890:        return;
                   2891: }
                   2892:
                   2893: /*
                   2894:  * Return the number of milliseconds since the system booted.
                   2895:  */
                   2896: __stdcall static void
1.15    ! dsl      2897: NdisGetSystemUpTime(uint32_t *tval)
1.1       rittera  2898: {
                   2899:        *tval = (ticks * hz) / 1000;
                   2900:
                   2901:        return;
                   2902: }
                   2903:
                   2904: __stdcall static void
1.15    ! dsl      2905: NdisInitializeString(ndis_unicode_string *dst, char *src)
1.1       rittera  2906: {
                   2907:        ndis_unicode_string     *u;
                   2908:
                   2909:        u = dst;
                   2910:        u->us_buf = NULL;
                   2911:        if (ndis_ascii_to_unicode(src, &u->us_buf))
                   2912:                return;
                   2913:        u->us_len = u->us_maxlen = strlen(src) * 2;
                   2914:        return;
                   2915: }
                   2916:
                   2917: __stdcall static void
1.15    ! dsl      2918: NdisFreeString(ndis_unicode_string *str)
1.1       rittera  2919: {
                   2920:        if (str == NULL)
                   2921:                return;
                   2922:        if (str->us_buf != NULL)
                   2923:                free(str->us_buf, M_DEVBUF);
                   2924:        free(str, M_DEVBUF);
                   2925:        return;
                   2926: }
                   2927:
                   2928: __stdcall static ndis_status
1.6       christos 2929: NdisMRemoveMiniport(ndis_handle        *adapter)
1.1       rittera  2930: {
                   2931:        return(NDIS_STATUS_SUCCESS);
                   2932: }
                   2933:
                   2934: __stdcall static void
1.15    ! dsl      2935: NdisInitAnsiString(ndis_ansi_string *dst, char *src)
1.1       rittera  2936: {
                   2937:        ndis_ansi_string        *a;
                   2938:
                   2939:        a = dst;
                   2940:        if (a == NULL)
                   2941:                return;
                   2942:        if (src == NULL) {
                   2943:                a->nas_len = a->nas_maxlen = 0;
                   2944:                a->nas_buf = NULL;
                   2945:        } else {
                   2946:                a->nas_buf = src;
                   2947:                a->nas_len = a->nas_maxlen = strlen(src);
                   2948:        }
                   2949:
                   2950:        return;
                   2951: }
                   2952:
                   2953: __stdcall static void
1.15    ! dsl      2954: NdisInitUnicodeString(ndis_unicode_string *dst, uint16_t *src)
1.1       rittera  2955: {
                   2956:        ndis_unicode_string     *u;
                   2957:        int                     i;
                   2958:
                   2959:        u = dst;
                   2960:        if (u == NULL)
                   2961:                return;
                   2962:        if (src == NULL) {
                   2963:                u->us_len = u->us_maxlen = 0;
                   2964:                u->us_buf = NULL;
                   2965:        } else {
                   2966:                i = 0;
                   2967:                while(src[i] != 0)
                   2968:                        i++;
                   2969:                u->us_buf = src;
                   2970:                u->us_len = u->us_maxlen = i * 2;
                   2971:        }
                   2972:
                   2973:        return;
                   2974: }
                   2975:
1.5       christos 2976: __stdcall static void NdisMGetDeviceProperty(
                   2977:        ndis_handle             adapter,
                   2978:        device_object           **phydevobj,
                   2979:        device_object           **funcdevobj,
                   2980:        device_object           **nextdevobj,
1.6       christos 2981:        cm_resource_list        *resources,
                   2982:        cm_resource_list        *transresources)
1.1       rittera  2983: {
                   2984:        ndis_miniport_block     *block;
                   2985:
                   2986:        block = (ndis_miniport_block *)adapter;
                   2987:
                   2988:        if (phydevobj != NULL)
                   2989:                *phydevobj = block->nmb_physdeviceobj;
                   2990:        if (funcdevobj != NULL)
                   2991:                *funcdevobj = block->nmb_deviceobj;
                   2992:        if (nextdevobj != NULL)
                   2993:                *nextdevobj = block->nmb_nextdeviceobj;
                   2994:
                   2995:        return;
                   2996: }
                   2997:
                   2998: __stdcall static void
1.15    ! dsl      2999: NdisGetFirstBufferFromPacket(ndis_packet *packet, ndis_buffer **buf, void **firstva, uint32_t *firstlen, uint32_t *totlen)
1.1       rittera  3000: {
                   3001:        ndis_buffer             *tmp;
                   3002:
                   3003:        tmp = packet->np_private.npp_head;
                   3004:        *buf = tmp;
                   3005:        if (tmp == NULL) {
                   3006:                *firstva = NULL;
                   3007:                *firstlen = *totlen = 0;
                   3008:        } else {
                   3009:                *firstva = MmGetMdlVirtualAddress(tmp);
                   3010:                *firstlen = *totlen = MmGetMdlByteCount(tmp);
                   3011:                for (tmp = tmp->mdl_next; tmp != NULL; tmp = tmp->mdl_next)
                   3012:                        *totlen += MmGetMdlByteCount(tmp);
                   3013:        }
                   3014:
                   3015:        return;
                   3016: }
                   3017:
                   3018: __stdcall static void
1.5       christos 3019: NdisGetFirstBufferFromPacketSafe(
                   3020:        ndis_packet             *packet,
                   3021:        ndis_buffer             **buf,
                   3022:        void                    **firstva,
                   3023:        uint32_t                *firstlen,
                   3024:        uint32_t                *totlen,
1.6       christos 3025:        uint32_t                prio)
1.1       rittera  3026: {
                   3027:        NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen);
                   3028: }
                   3029:
1.2       rittera  3030: #ifdef __FreeBSD__
1.1       rittera  3031: static int
1.15    ! dsl      3032: ndis_find_sym(linker_file_t lf, char *filename, char *suffix, void * *sym)
1.1       rittera  3033: {
                   3034:        char                    *fullsym;
                   3035:        char                    *suf;
                   3036:        int                     i;
                   3037:
                   3038:        fullsym = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
                   3039:        if (fullsym == NULL)
                   3040:                return(ENOMEM);
                   3041:
                   3042:        bzero(fullsym, MAXPATHLEN);
                   3043:        strncpy(fullsym, filename, MAXPATHLEN);
                   3044:        if (strlen(filename) < 4) {
                   3045:                ExFreePool(fullsym);
                   3046:                return(EINVAL);
                   3047:        }
                   3048:
                   3049:        /* If the filename has a .ko suffix, strip if off. */
                   3050:        suf = fullsym + (strlen(filename) - 3);
                   3051:        if (strcmp(suf, ".ko") == 0)
                   3052:                *suf = '\0';
                   3053:
                   3054:        for (i = 0; i < strlen(fullsym); i++) {
                   3055:                if (fullsym[i] == '.')
                   3056:                        fullsym[i] = '_';
                   3057:                else
                   3058:                        fullsym[i] = tolower(fullsym[i]);
                   3059:        }
                   3060:        strcat(fullsym, suffix);
                   3061:        *sym = linker_file_lookup_symbol(lf, fullsym, 0);
                   3062:        ExFreePool(fullsym);
                   3063:        if (*sym == 0)
                   3064:                return(ENOENT);
                   3065:
                   3066:        return(0);
                   3067: }
                   3068:
                   3069: /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
                   3070: __stdcall static void
1.15    ! dsl      3071: NdisOpenFile(ndis_status *status, ndis_handle *filehandle, uint32_t *filelength, ndis_unicode_string *filename, ndis_physaddr highestaddr)
1.1       rittera  3072: {
                   3073:        char                    *afilename = NULL;
                   3074:        struct thread           *td = curthread;
                   3075:        struct nameidata        nd;
                   3076:        int                     flags, error;
                   3077:        struct vattr            vat;
                   3078:        struct vattr            *vap = &vat;
                   3079:        ndis_fh                 *fh;
                   3080:        char                    *path;
                   3081:        linker_file_t           head, lf;
1.8       dogcow   3082:        void                    *kldstart, *kldend;
1.1       rittera  3083:
                   3084:        ndis_unicode_to_ascii(filename->us_buf,
                   3085:            filename->us_len, &afilename);
                   3086:
                   3087:        fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0);
                   3088:        if (fh == NULL) {
                   3089:                *status = NDIS_STATUS_RESOURCES;
                   3090:                return;
                   3091:        }
                   3092:
                   3093:        /*
                   3094:         * During system bootstrap, it's impossible to load files
                   3095:         * from the rootfs since it's not mounted yet. We therefore
                   3096:         * offer the possibility of opening files that have been
                   3097:         * preloaded as modules instead. Both choices will work
                   3098:         * when kldloading a module from multiuser, but only the
                   3099:         * module option will work during bootstrap. The module
                   3100:         * loading option works by using the ndiscvt(8) utility
                   3101:         * to convert the arbitrary file into a .ko using objcopy(1).
                   3102:         * This file will contain two special symbols: filename_start
                   3103:         * and filename_end. All we have to do is traverse the KLD
                   3104:         * list in search of those symbols and we've found the file
                   3105:         * data. As an added bonus, ndiscvt(8) will also generate
                   3106:         * a normal .o file which can be linked statically with
                   3107:         * the kernel. This means that the symbols will actual reside
                   3108:         * in the kernel's symbol table, but that doesn't matter to
                   3109:         * us since the kernel appears to us as just another module.
                   3110:         */
                   3111:
                   3112:        /*
                   3113:         * This is an evil trick for getting the head of the linked
                   3114:         * file list, which is not exported from kern_linker.o. It
                   3115:         * happens that linker file #1 is always the kernel, and is
                   3116:         * always the first element in the list.
                   3117:         */
                   3118:
                   3119:        head = linker_find_file_by_id(1);
                   3120:        for (lf = head; lf != NULL; lf = TAILQ_NEXT(lf, link)) {
                   3121:                if (ndis_find_sym(lf, afilename, "_start", &kldstart))
                   3122:                        continue;
                   3123:                if (ndis_find_sym(lf, afilename, "_end", &kldend))
                   3124:                        continue;
                   3125:                fh->nf_vp = lf;
                   3126:                fh->nf_map = NULL;
                   3127:                fh->nf_type = NDIS_FH_TYPE_MODULE;
                   3128:                *filelength = fh->nf_maplen = (kldend - kldstart) & 0xFFFFFFFF;
                   3129:                *filehandle = fh;
                   3130:                free(afilename, M_DEVBUF);
                   3131:                *status = NDIS_STATUS_SUCCESS;
                   3132:                return;
                   3133:        }
                   3134:
                   3135:        if (TAILQ_EMPTY(&mountlist)) {
                   3136:                ExFreePool(fh);
                   3137:                *status = NDIS_STATUS_FILE_NOT_FOUND;
                   3138:                printf("NDIS: could not find file %s in linker list\n",
                   3139:                    afilename);
                   3140:                printf("NDIS: and no filesystems mounted yet, "
                   3141:                    "aborting NdisOpenFile()\n");
                   3142:                free(afilename, M_DEVBUF);
                   3143:                return;
                   3144:        }
                   3145:
                   3146:        path = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
                   3147:        if (path == NULL) {
                   3148:                ExFreePool(fh);
                   3149:                *status = NDIS_STATUS_RESOURCES;
                   3150:                return;
                   3151:        }
                   3152:
                   3153:        snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename);
                   3154:        free(afilename, M_DEVBUF);
                   3155:
                   3156:        mtx_lock(&Giant);
                   3157:
                   3158:        /* Some threads don't have a current working directory. */
                   3159:
                   3160:        if (td->td_proc->p_fd->fd_rdir == NULL)
                   3161:                td->td_proc->p_fd->fd_rdir = rootvnode;
                   3162:        if (td->td_proc->p_fd->fd_cdir == NULL)
                   3163:                td->td_proc->p_fd->fd_cdir = rootvnode;
                   3164:
                   3165:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
                   3166:
                   3167:        flags = FREAD;
                   3168:        error = vn_open(&nd, &flags, 0, -1);
                   3169:        if (error) {
                   3170:                mtx_unlock(&Giant);
                   3171:                *status = NDIS_STATUS_FILE_NOT_FOUND;
                   3172:                ExFreePool(fh);
                   3173:                printf("NDIS: open file %s failed: %d\n", path, error);
                   3174:                ExFreePool(path);
                   3175:                return;
                   3176:        }
                   3177:
                   3178:        ExFreePool(path);
                   3179:
                   3180:        NDFREE(&nd, NDF_ONLY_PNBUF);
                   3181:
                   3182:        /* Get the file size. */
                   3183:        VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td);
                   3184:        VOP_UNLOCK(nd.ni_vp, 0, td);
                   3185:        mtx_unlock(&Giant);
                   3186:
                   3187:        fh->nf_vp = nd.ni_vp;
                   3188:        fh->nf_map = NULL;
                   3189:        fh->nf_type = NDIS_FH_TYPE_VFS;
                   3190:        *filehandle = fh;
                   3191:        *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
                   3192:        *status = NDIS_STATUS_SUCCESS;
                   3193:
                   3194:        return;
                   3195: }
                   3196:
                   3197: __stdcall static void
1.15    ! dsl      3198: NdisMapFile(ndis_status *status, void **mappedbuffer, ndis_handle filehandle)
1.1       rittera  3199: {
                   3200:        ndis_fh                 *fh;
                   3201:        struct thread           *td = curthread;
                   3202:        linker_file_t           lf;
1.7       christos 3203:        void *                  kldstart;
1.1       rittera  3204:        int                     error, resid;
                   3205:
                   3206:        if (filehandle == NULL) {
                   3207:                *status = NDIS_STATUS_FAILURE;
                   3208:                return;
                   3209:        }
                   3210:
                   3211:        fh = (ndis_fh *)filehandle;
                   3212:
                   3213:        if (fh->nf_vp == NULL) {
                   3214:                *status = NDIS_STATUS_FAILURE;
                   3215:                return;
                   3216:        }
                   3217:
                   3218:        if (fh->nf_map != NULL) {
                   3219:                *status = NDIS_STATUS_ALREADY_MAPPED;
                   3220:                return;
                   3221:        }
                   3222:
                   3223:        if (fh->nf_type == NDIS_FH_TYPE_MODULE) {
                   3224:                lf = fh->nf_vp;
                   3225:                if (ndis_find_sym(lf, lf->filename, "_start", &kldstart)) {
                   3226:                        *status = NDIS_STATUS_FAILURE;
                   3227:                        return;
                   3228:                }
                   3229:                fh->nf_map = kldstart;
                   3230:                *status = NDIS_STATUS_SUCCESS;
                   3231:                *mappedbuffer = fh->nf_map;
                   3232:                return;
                   3233:        }
                   3234:
                   3235:        fh->nf_map = ExAllocatePoolWithTag(NonPagedPool, fh->nf_maplen, 0);
                   3236:
                   3237:        if (fh->nf_map == NULL) {
                   3238:                *status = NDIS_STATUS_RESOURCES;
                   3239:                return;
                   3240:        }
                   3241:
                   3242:        mtx_lock(&Giant);
                   3243:        error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
                   3244:            UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td);
                   3245:        mtx_unlock(&Giant);
                   3246:
                   3247:        if (error)
                   3248:                *status = NDIS_STATUS_FAILURE;
                   3249:        else {
                   3250:                *status = NDIS_STATUS_SUCCESS;
                   3251:                *mappedbuffer = fh->nf_map;
                   3252:        }
                   3253:
                   3254:        return;
                   3255: }
                   3256:
                   3257: __stdcall static void
1.15    ! dsl      3258: NdisUnmapFile(ndis_handle filehandle)
1.1       rittera  3259: {
                   3260:        ndis_fh                 *fh;
                   3261:        fh = (ndis_fh *)filehandle;
                   3262:
                   3263:        if (fh->nf_map == NULL)
                   3264:                return;
                   3265:
                   3266:        if (fh->nf_type == NDIS_FH_TYPE_VFS)
                   3267:                ExFreePool(fh->nf_map);
                   3268:        fh->nf_map = NULL;
                   3269:
                   3270:        return;
                   3271: }
                   3272:
                   3273: __stdcall static void
1.15    ! dsl      3274: NdisCloseFile(ndis_handle filehandle)
1.1       rittera  3275: {
                   3276:        struct thread           *td = curthread;
                   3277:        ndis_fh                 *fh;
                   3278:
                   3279:        if (filehandle == NULL)
                   3280:                return;
                   3281:
                   3282:        fh = (ndis_fh *)filehandle;
                   3283:        if (fh->nf_map != NULL) {
                   3284:                if (fh->nf_type == NDIS_FH_TYPE_VFS)
                   3285:                        ExFreePool(fh->nf_map);
                   3286:                fh->nf_map = NULL;
                   3287:        }
                   3288:
                   3289:        if (fh->nf_vp == NULL)
                   3290:                return;
                   3291:
                   3292:        if (fh->nf_type == NDIS_FH_TYPE_VFS) {
                   3293:                mtx_lock(&Giant);
                   3294:                vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
                   3295:                mtx_unlock(&Giant);
                   3296:        }
                   3297:
                   3298:        fh->nf_vp = NULL;
                   3299:        ExFreePool(fh);
                   3300:
                   3301:        return;
                   3302: }
1.2       rittera  3303: #endif /* __FreeBSD__ */
1.1       rittera  3304: __stdcall static uint8_t
                   3305: NdisSystemProcessorCount()
                   3306: {
1.2       rittera  3307: #ifdef __FreeBSD__
1.1       rittera  3308:        return(mp_ncpus);
1.2       rittera  3309: #else
                   3310:        return(nprocs);
                   3311: #endif
1.1       rittera  3312: }
                   3313:
                   3314: typedef void (*ndis_statusdone_handler)(ndis_handle);
                   3315: typedef void (*ndis_status_handler)(ndis_handle, ndis_status,
                   3316:         void *, uint32_t);
                   3317:
                   3318: __stdcall static void
1.15    ! dsl      3319: NdisMIndicateStatusComplete(ndis_handle adapter)
1.1       rittera  3320: {
                   3321:        ndis_miniport_block     *block;
                   3322:        __stdcall ndis_statusdone_handler       statusdonefunc;
                   3323:
                   3324:        block = (ndis_miniport_block *)adapter;
                   3325:        statusdonefunc = block->nmb_statusdone_func;
                   3326:
                   3327:        MSCALL1(statusdonefunc, adapter);
                   3328:        return;
                   3329: }
                   3330:
                   3331: __stdcall static void
1.15    ! dsl      3332: NdisMIndicateStatus(ndis_handle adapter, ndis_status status, void *sbuf, uint32_t slen)
1.1       rittera  3333: {
                   3334:        ndis_miniport_block     *block;
                   3335:        __stdcall ndis_status_handler   statusfunc;
                   3336:
                   3337:        block = (ndis_miniport_block *)adapter;
                   3338:        statusfunc = block->nmb_status_func;
                   3339:
                   3340:        MSCALL4(statusfunc, adapter, status, sbuf, slen);
                   3341:        return;
                   3342: }
                   3343:
                   3344: static void
1.15    ! dsl      3345: ndis_workfunc(void *ctx)
1.1       rittera  3346: {
                   3347:        ndis_work_item          *work;
                   3348:        __stdcall ndis_proc     workfunc;
                   3349:
                   3350:        work = ctx;
                   3351:        workfunc = work->nwi_func;
                   3352:        MSCALL2(workfunc, work, work->nwi_ctx);
                   3353:        return;
                   3354: }
                   3355:
                   3356: __stdcall static ndis_status
1.15    ! dsl      3357: NdisScheduleWorkItem(ndis_work_item *work)
1.1       rittera  3358: {
                   3359:        ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
                   3360:        return(NDIS_STATUS_SUCCESS);
                   3361: }
                   3362:
                   3363: __stdcall static void
1.15    ! dsl      3364: NdisCopyFromPacketToPacket(ndis_packet *dpkt, uint32_t doff, uint32_t reqlen, ndis_packet *spkt, uint32_t soff, uint32_t *cpylen)
1.1       rittera  3365: {
                   3366:        ndis_buffer             *src, *dst;
                   3367:        char                    *sptr, *dptr;
                   3368:        int                     resid, copied, len, scnt, dcnt;
                   3369:
                   3370:        *cpylen = 0;
                   3371:
                   3372:        src = spkt->np_private.npp_head;
                   3373:        dst = dpkt->np_private.npp_head;
                   3374:
                   3375:        sptr = MmGetMdlVirtualAddress(src);
                   3376:        dptr = MmGetMdlVirtualAddress(dst);
                   3377:        scnt = MmGetMdlByteCount(src);
                   3378:        dcnt = MmGetMdlByteCount(dst);
                   3379:
                   3380:        while (soff) {
                   3381:                if (MmGetMdlByteCount(src) > soff) {
                   3382:                        sptr += soff;
                   3383:                        scnt = MmGetMdlByteCount(src)- soff;
                   3384:                        break;
                   3385:                }
                   3386:                soff -= MmGetMdlByteCount(src);
                   3387:                src = src->mdl_next;
                   3388:                if (src == NULL)
                   3389:                        return;
                   3390:                sptr = MmGetMdlVirtualAddress(src);
                   3391:        }
                   3392:
                   3393:        while (doff) {
                   3394:                if (MmGetMdlByteCount(dst) > doff) {
                   3395:                        dptr += doff;
                   3396:                        dcnt = MmGetMdlByteCount(dst) - doff;
                   3397:                        break;
                   3398:                }
                   3399:                doff -= MmGetMdlByteCount(dst);
                   3400:                dst = dst->mdl_next;
                   3401:                if (dst == NULL)
                   3402:                        return;
                   3403:                dptr = MmGetMdlVirtualAddress(dst);
                   3404:        }
                   3405:
                   3406:        resid = reqlen;
                   3407:        copied = 0;
                   3408:
                   3409:        while(1) {
                   3410:                if (resid < scnt)
                   3411:                        len = resid;
                   3412:                else
                   3413:                        len = scnt;
                   3414:                if (dcnt < len)
                   3415:                        len = dcnt;
                   3416:
                   3417:                bcopy(sptr, dptr, len);
                   3418:
                   3419:                copied += len;
                   3420:                resid -= len;
                   3421:                if (resid == 0)
                   3422:                        break;
                   3423:
                   3424:                dcnt -= len;
                   3425:                if (dcnt == 0) {
                   3426:                        dst = dst->mdl_next;
                   3427:                        if (dst == NULL)
                   3428:                                break;
                   3429:                        dptr = MmGetMdlVirtualAddress(dst);
                   3430:                        dcnt = MmGetMdlByteCount(dst);
                   3431:                }
                   3432:
                   3433:                scnt -= len;
                   3434:                if (scnt == 0) {
                   3435:                        src = src->mdl_next;
                   3436:                        if (src == NULL)
                   3437:                                break;
                   3438:                        sptr = MmGetMdlVirtualAddress(src);
                   3439:                        scnt = MmGetMdlByteCount(src);
                   3440:                }
                   3441:        }
                   3442:
                   3443:        *cpylen = copied;
                   3444:        return;
                   3445: }
                   3446:
                   3447: __stdcall static void
1.5       christos 3448: NdisCopyFromPacketToPacketSafe(
                   3449:        ndis_packet             *dpkt,
                   3450:        uint32_t                doff,
                   3451:        uint32_t                reqlen,
                   3452:        ndis_packet             *spkt,
                   3453:        uint32_t                soff,
                   3454:        uint32_t                *cpylen,
1.6       christos 3455:        uint32_t                prio)
1.1       rittera  3456: {
                   3457:        NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen);
                   3458:        return;
                   3459: }
                   3460:
                   3461: __stdcall static ndis_status
1.5       christos 3462: NdisMRegisterDevice(
                   3463:        ndis_handle             handle,
1.6       christos 3464:        ndis_unicode_string     *devname,
                   3465:        ndis_unicode_string     *symname,
                   3466:        driver_dispatch         *majorfuncs[],
1.5       christos 3467:        void                    **devobj,
                   3468:        ndis_handle             *devhandle)
1.1       rittera  3469: {
                   3470:        ndis_miniport_block     *block;
                   3471:
                   3472:        block = (ndis_miniport_block *)handle;
                   3473:        *devobj = block->nmb_deviceobj;
                   3474:        *devhandle = handle;
                   3475:
                   3476:        return(NDIS_STATUS_SUCCESS);
                   3477: }
                   3478:
                   3479: __stdcall static ndis_status
1.6       christos 3480: NdisMDeregisterDevice(ndis_handle handle)
1.1       rittera  3481: {
                   3482:        return(NDIS_STATUS_SUCCESS);
                   3483: }
                   3484:
                   3485: __stdcall static ndis_status
1.15    ! dsl      3486: NdisMQueryAdapterInstanceName(ndis_unicode_string *name, ndis_handle handle)
1.1       rittera  3487: {
                   3488:        ndis_miniport_block     *block;
                   3489:        device_t                dev;
                   3490:
                   3491:        block = (ndis_miniport_block *)handle;
                   3492:        dev = block->nmb_physdeviceobj->do_devext;
                   3493:
                   3494:        ndis_ascii_to_unicode(__DECONST(char *,
                   3495:            device_get_nameunit(dev)), &name->us_buf);
                   3496:        name->us_len = strlen(device_get_nameunit(dev)) * 2;
                   3497:
                   3498:        return(NDIS_STATUS_SUCCESS);
                   3499: }
                   3500:
                   3501: __stdcall static void
1.5       christos 3502: NdisMRegisterUnloadHandler(
1.6       christos 3503:        ndis_handle             handle,
                   3504:        void                    *func)
1.1       rittera  3505: {
                   3506:        return;
                   3507: }
                   3508:
                   3509: __stdcall static void
                   3510: dummy()
                   3511: {
                   3512:        printf ("NDIS dummy called...\n");
                   3513:        return;
                   3514: }
                   3515:
                   3516: image_patch_table ndis_functbl[] = {
                   3517:        IMPORT_FUNC(NdisCopyFromPacketToPacket),
                   3518:        IMPORT_FUNC(NdisCopyFromPacketToPacketSafe),
                   3519:        IMPORT_FUNC(NdisScheduleWorkItem),
                   3520:        IMPORT_FUNC(NdisMIndicateStatusComplete),
                   3521:        IMPORT_FUNC(NdisMIndicateStatus),
                   3522:        IMPORT_FUNC(NdisSystemProcessorCount),
                   3523:        IMPORT_FUNC(NdisUnchainBufferAtBack),
                   3524:        IMPORT_FUNC(NdisGetFirstBufferFromPacket),
                   3525:        IMPORT_FUNC(NdisGetFirstBufferFromPacketSafe),
                   3526:        IMPORT_FUNC(NdisGetBufferPhysicalArraySize),
                   3527:        IMPORT_FUNC(NdisMGetDeviceProperty),
                   3528:        IMPORT_FUNC(NdisInitAnsiString),
                   3529:        IMPORT_FUNC(NdisInitUnicodeString),
                   3530:        IMPORT_FUNC(NdisWriteConfiguration),
                   3531:        IMPORT_FUNC(NdisAnsiStringToUnicodeString),
                   3532:        IMPORT_FUNC(NdisTerminateWrapper),
                   3533:        IMPORT_FUNC(NdisOpenConfigurationKeyByName),
                   3534:        IMPORT_FUNC(NdisOpenConfigurationKeyByIndex),
                   3535:        IMPORT_FUNC(NdisMRemoveMiniport),
                   3536:        IMPORT_FUNC(NdisInitializeString),
                   3537:        IMPORT_FUNC(NdisFreeString),
                   3538:        IMPORT_FUNC(NdisGetCurrentSystemTime),
                   3539:        IMPORT_FUNC(NdisGetSystemUpTime),
                   3540:        IMPORT_FUNC(NdisMSynchronizeWithInterrupt),
                   3541:        IMPORT_FUNC(NdisMAllocateSharedMemoryAsync),
                   3542:        IMPORT_FUNC(NdisInterlockedInsertHeadList),
                   3543:        IMPORT_FUNC(NdisInterlockedInsertTailList),
                   3544:        IMPORT_FUNC(NdisInterlockedRemoveHeadList),
                   3545:        IMPORT_FUNC(NdisInitializeWrapper),
                   3546:        IMPORT_FUNC(NdisMRegisterMiniport),
                   3547:        IMPORT_FUNC(NdisAllocateMemoryWithTag),
                   3548:        IMPORT_FUNC(NdisAllocateMemory),
                   3549:        IMPORT_FUNC(NdisMSetAttributesEx),
                   3550:        IMPORT_FUNC(NdisCloseConfiguration),
                   3551:        IMPORT_FUNC(NdisReadConfiguration),
                   3552:        IMPORT_FUNC(NdisOpenConfiguration),
                   3553:        IMPORT_FUNC(NdisAcquireSpinLock),
                   3554:        IMPORT_FUNC(NdisReleaseSpinLock),
                   3555:        IMPORT_FUNC(NdisDprAcquireSpinLock),
                   3556:        IMPORT_FUNC(NdisDprReleaseSpinLock),
                   3557:        IMPORT_FUNC(NdisAllocateSpinLock),
                   3558:        IMPORT_FUNC(NdisFreeSpinLock),
                   3559:        IMPORT_FUNC(NdisFreeMemory),
                   3560:        IMPORT_FUNC(NdisReadPciSlotInformation),
                   3561:        IMPORT_FUNC(NdisWritePciSlotInformation),
                   3562:        IMPORT_FUNC_MAP(NdisImmediateReadPciSlotInformation,
                   3563:            NdisReadPciSlotInformation),
                   3564:        IMPORT_FUNC_MAP(NdisImmediateWritePciSlotInformation,
                   3565:            NdisWritePciSlotInformation),
                   3566:        IMPORT_FUNC(NdisWriteErrorLogEntry),
                   3567:        IMPORT_FUNC(NdisMStartBufferPhysicalMapping),
                   3568:        IMPORT_FUNC(NdisMCompleteBufferPhysicalMapping),
                   3569:        IMPORT_FUNC(NdisMInitializeTimer),
                   3570:        IMPORT_FUNC(NdisInitializeTimer),
                   3571:        IMPORT_FUNC(NdisSetTimer),
                   3572:        IMPORT_FUNC(NdisMCancelTimer),
                   3573:        IMPORT_FUNC_MAP(NdisCancelTimer, NdisMCancelTimer),
                   3574:        IMPORT_FUNC(NdisMSetPeriodicTimer),
                   3575:        IMPORT_FUNC(NdisMQueryAdapterResources),
                   3576:        IMPORT_FUNC(NdisMRegisterIoPortRange),
                   3577:        IMPORT_FUNC(NdisMDeregisterIoPortRange),
                   3578:        IMPORT_FUNC(NdisReadNetworkAddress),
                   3579:        IMPORT_FUNC(NdisQueryMapRegisterCount),
                   3580:        IMPORT_FUNC(NdisMAllocateMapRegisters),
                   3581:        IMPORT_FUNC(NdisMFreeMapRegisters),
                   3582:        IMPORT_FUNC(NdisMAllocateSharedMemory),
                   3583:        IMPORT_FUNC(NdisMMapIoSpace),
                   3584:        IMPORT_FUNC(NdisMUnmapIoSpace),
                   3585:        IMPORT_FUNC(NdisGetCacheFillSize),
                   3586:        IMPORT_FUNC(NdisMGetDmaAlignment),
                   3587:        IMPORT_FUNC(NdisMInitializeScatterGatherDma),
                   3588:        IMPORT_FUNC(NdisAllocatePacketPool),
                   3589:        IMPORT_FUNC(NdisAllocatePacketPoolEx),
                   3590:        IMPORT_FUNC(NdisAllocatePacket),
                   3591:        IMPORT_FUNC(NdisFreePacket),
                   3592:        IMPORT_FUNC(NdisFreePacketPool),
                   3593:        IMPORT_FUNC_MAP(NdisDprAllocatePacket, NdisAllocatePacket),
                   3594:        IMPORT_FUNC_MAP(NdisDprFreePacket, NdisFreePacket),
                   3595:        IMPORT_FUNC(NdisAllocateBufferPool),
                   3596:        IMPORT_FUNC(NdisAllocateBuffer),
                   3597:        IMPORT_FUNC(NdisQueryBuffer),
                   3598:        IMPORT_FUNC(NdisQueryBufferSafe),
                   3599:        IMPORT_FUNC(NdisBufferVirtualAddress),
                   3600:        IMPORT_FUNC(NdisBufferVirtualAddressSafe),
                   3601:        IMPORT_FUNC(NdisBufferLength),
                   3602:        IMPORT_FUNC(NdisFreeBuffer),
                   3603:        IMPORT_FUNC(NdisFreeBufferPool),
                   3604:        IMPORT_FUNC(NdisInterlockedIncrement),
                   3605:        IMPORT_FUNC(NdisInterlockedDecrement),
                   3606:        IMPORT_FUNC(NdisInitializeEvent),
                   3607:        IMPORT_FUNC(NdisSetEvent),
                   3608:        IMPORT_FUNC(NdisResetEvent),
                   3609:        IMPORT_FUNC(NdisWaitEvent),
                   3610:        IMPORT_FUNC(NdisUnicodeStringToAnsiString),
                   3611:        IMPORT_FUNC(NdisMPciAssignResources),
                   3612:        IMPORT_FUNC(NdisMFreeSharedMemory),
                   3613:        IMPORT_FUNC(NdisMRegisterInterrupt),
                   3614:        IMPORT_FUNC(NdisMDeregisterInterrupt),
                   3615:        IMPORT_FUNC(NdisMRegisterAdapterShutdownHandler),
                   3616:        IMPORT_FUNC(NdisMDeregisterAdapterShutdownHandler),
                   3617:        IMPORT_FUNC(NDIS_BUFFER_TO_SPAN_PAGES),
                   3618:        IMPORT_FUNC(NdisQueryBufferOffset),
                   3619:        IMPORT_FUNC(NdisAdjustBufferLength),
                   3620:        IMPORT_FUNC(NdisPacketPoolUsage),
                   3621:        IMPORT_FUNC(NdisMSleep),
                   3622:        IMPORT_FUNC(NdisUnchainBufferAtFront),
                   3623:        IMPORT_FUNC(NdisReadPcmciaAttributeMemory),
                   3624:        IMPORT_FUNC(NdisWritePcmciaAttributeMemory),
1.2       rittera  3625: #ifdef __FreeBSD__
1.1       rittera  3626:        IMPORT_FUNC(NdisOpenFile),
                   3627:        IMPORT_FUNC(NdisMapFile),
                   3628:        IMPORT_FUNC(NdisUnmapFile),
                   3629:        IMPORT_FUNC(NdisCloseFile),
1.2       rittera  3630: #endif
1.1       rittera  3631:        IMPORT_FUNC(NdisMRegisterDevice),
                   3632:        IMPORT_FUNC(NdisMDeregisterDevice),
                   3633:        IMPORT_FUNC(NdisMQueryAdapterInstanceName),
                   3634:        IMPORT_FUNC(NdisMRegisterUnloadHandler),
                   3635:        IMPORT_FUNC(ndis_timercall),
                   3636:
                   3637:        /*
                   3638:         * This last entry is a catch-all for any function we haven't
                   3639:         * implemented yet. The PE import list patching routine will
                   3640:         * use it for any function that doesn't have an explicit match
                   3641:         * in this table.
                   3642:         */
                   3643:
                   3644:        { NULL, (FUNC)dummy, NULL },
                   3645:
                   3646:        /* End of list. */
                   3647:
                   3648:        { NULL, NULL, NULL }
                   3649: };

CVSweb <webmaster@jp.NetBSD.org>