[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.9

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

CVSweb <webmaster@jp.NetBSD.org>