1139743Simp/*- 2123474Swpaul * Copyright (c) 2003 3123474Swpaul * Bill Paul <wpaul@windriver.com>. All rights reserved. 4123474Swpaul * 5123474Swpaul * Redistribution and use in source and binary forms, with or without 6123474Swpaul * modification, are permitted provided that the following conditions 7123474Swpaul * are met: 8123474Swpaul * 1. Redistributions of source code must retain the above copyright 9123474Swpaul * notice, this list of conditions and the following disclaimer. 10123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright 11123474Swpaul * notice, this list of conditions and the following disclaimer in the 12123474Swpaul * documentation and/or other materials provided with the distribution. 13123474Swpaul * 3. All advertising materials mentioning features or use of this software 14123474Swpaul * must display the following acknowledgement: 15123474Swpaul * This product includes software developed by Bill Paul. 16123474Swpaul * 4. Neither the name of the author nor the names of any co-contributors 17123474Swpaul * may be used to endorse or promote products derived from this software 18123474Swpaul * without specific prior written permission. 19123474Swpaul * 20123474Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21123474Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22123474Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23123474Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24123474Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25123474Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26123474Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27123474Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28123474Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29123474Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30123474Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 31123474Swpaul */ 32123474Swpaul 33123474Swpaul#include <sys/cdefs.h> 34123474Swpaul__FBSDID("$FreeBSD: stable/11/sys/compat/ndis/subr_ndis.c 335472 2018-06-21 09:45:03Z dim $"); 35123474Swpaul 36123474Swpaul/* 37123474Swpaul * This file implements a translation layer between the BSD networking 38123474Swpaul * infrasturcture and Windows(R) NDIS network driver modules. A Windows 39123474Swpaul * NDIS driver calls into several functions in the NDIS.SYS Windows 40123474Swpaul * kernel module and exports a table of functions designed to be called 41123474Swpaul * by the NDIS subsystem. Using the PE loader, we can patch our own 42123474Swpaul * versions of the NDIS routines into a given Windows driver module and 43123474Swpaul * convince the driver that it is in fact running on Windows. 44123474Swpaul * 45123474Swpaul * We provide a table of all our implemented NDIS routines which is patched 46123474Swpaul * into the driver object code. All our exported routines must use the 47123474Swpaul * _stdcall calling convention, since that's what the Windows object code 48123474Swpaul * expects. 49123474Swpaul */ 50123474Swpaul 51123474Swpaul 52129834Swpaul#include <sys/ctype.h> 53123474Swpaul#include <sys/param.h> 54123474Swpaul#include <sys/types.h> 55123474Swpaul#include <sys/errno.h> 56123474Swpaul 57123474Swpaul#include <sys/callout.h> 58123474Swpaul#include <sys/kernel.h> 59123474Swpaul#include <sys/systm.h> 60123474Swpaul#include <sys/malloc.h> 61123474Swpaul#include <sys/lock.h> 62123474Swpaul#include <sys/mutex.h> 63123474Swpaul#include <sys/socket.h> 64123474Swpaul#include <sys/sysctl.h> 65123504Swpaul#include <sys/timespec.h> 66123848Swpaul#include <sys/smp.h> 67124122Swpaul#include <sys/queue.h> 68124272Swpaul#include <sys/proc.h> 69125377Swpaul#include <sys/filedesc.h> 70124272Swpaul#include <sys/namei.h> 71124272Swpaul#include <sys/fcntl.h> 72124272Swpaul#include <sys/vnode.h> 73125551Swpaul#include <sys/kthread.h> 74132973Swpaul#include <sys/linker.h> 75132973Swpaul#include <sys/mount.h> 76132973Swpaul#include <sys/sysproto.h> 77123474Swpaul 78123474Swpaul#include <net/if.h> 79257176Sglebius#include <net/if_var.h> 80123474Swpaul#include <net/if_arp.h> 81123474Swpaul#include <net/ethernet.h> 82123474Swpaul#include <net/if_dl.h> 83123474Swpaul#include <net/if_media.h> 84123474Swpaul 85124203Swpaul#include <machine/atomic.h> 86123474Swpaul#include <machine/bus.h> 87123474Swpaul#include <machine/resource.h> 88123474Swpaul 89123474Swpaul#include <sys/bus.h> 90123474Swpaul#include <sys/rman.h> 91123474Swpaul 92123474Swpaul#include <machine/stdarg.h> 93123474Swpaul 94123695Swpaul#include <net80211/ieee80211_var.h> 95123695Swpaul#include <net80211/ieee80211_ioctl.h> 96123695Swpaul 97123474Swpaul#include <dev/pci/pcireg.h> 98123474Swpaul#include <dev/pci/pcivar.h> 99189488Sweongyo#include <dev/usb/usb.h> 100194677Sthompsa#include <dev/usb/usbdi.h> 101123474Swpaul 102123474Swpaul#include <compat/ndis/pe_var.h> 103145485Swpaul#include <compat/ndis/cfg_var.h> 104123474Swpaul#include <compat/ndis/resource_var.h> 105123512Swpaul#include <compat/ndis/ntoskrnl_var.h> 106128229Swpaul#include <compat/ndis/hal_var.h> 107123474Swpaul#include <compat/ndis/ndis_var.h> 108123474Swpaul#include <dev/if_ndis/if_ndisvar.h> 109123474Swpaul 110151207Swpaul#include <vm/vm.h> 111151207Swpaul#include <vm/vm_param.h> 112151207Swpaul#include <vm/pmap.h> 113151207Swpaul#include <vm/uma.h> 114151207Swpaul#include <vm/vm_kern.h> 115151207Swpaul#include <vm/vm_map.h> 116151207Swpaul 117124272Swpaulstatic char ndis_filepath[MAXPATHLEN]; 118123474Swpaul 119124272SwpaulSYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath, 120189488Sweongyo MAXPATHLEN, "Path used by NdisOpenFile() to search for files"); 121124272Swpaul 122144888Swpaulstatic void NdisInitializeWrapper(ndis_handle *, 123141524Swpaul driver_object *, void *, void *); 124144888Swpaulstatic ndis_status NdisMRegisterMiniport(ndis_handle, 125123474Swpaul ndis_miniport_characteristics *, int); 126144888Swpaulstatic ndis_status NdisAllocateMemoryWithTag(void **, 127140751Swpaul uint32_t, uint32_t); 128144888Swpaulstatic ndis_status NdisAllocateMemory(void **, 129123474Swpaul uint32_t, uint32_t, ndis_physaddr); 130144888Swpaulstatic void NdisFreeMemory(void *, uint32_t, uint32_t); 131144888Swpaulstatic ndis_status NdisMSetAttributesEx(ndis_handle, ndis_handle, 132123474Swpaul uint32_t, uint32_t, ndis_interface_type); 133144888Swpaulstatic void NdisOpenConfiguration(ndis_status *, 134140751Swpaul ndis_handle *, ndis_handle); 135144888Swpaulstatic void NdisOpenConfigurationKeyByIndex(ndis_status *, 136151207Swpaul ndis_handle, uint32_t, unicode_string *, ndis_handle *); 137144888Swpaulstatic void NdisOpenConfigurationKeyByName(ndis_status *, 138151207Swpaul ndis_handle, unicode_string *, ndis_handle *); 139123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *, 140123474Swpaul struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); 141123526Swpaulstatic ndis_status ndis_decode_parm(ndis_miniport_block *, 142123526Swpaul ndis_config_parm *, char *); 143144888Swpaulstatic void NdisReadConfiguration(ndis_status *, ndis_config_parm **, 144151207Swpaul ndis_handle, unicode_string *, ndis_parm_type); 145144888Swpaulstatic void NdisWriteConfiguration(ndis_status *, ndis_handle, 146151207Swpaul unicode_string *, ndis_config_parm *); 147144888Swpaulstatic void NdisCloseConfiguration(ndis_handle); 148144888Swpaulstatic void NdisAllocateSpinLock(ndis_spin_lock *); 149144888Swpaulstatic void NdisFreeSpinLock(ndis_spin_lock *); 150144888Swpaulstatic void NdisAcquireSpinLock(ndis_spin_lock *); 151144888Swpaulstatic void NdisReleaseSpinLock(ndis_spin_lock *); 152144888Swpaulstatic void NdisDprAcquireSpinLock(ndis_spin_lock *); 153144888Swpaulstatic void NdisDprReleaseSpinLock(ndis_spin_lock *); 154145895Swpaulstatic void NdisInitializeReadWriteLock(ndis_rw_lock *); 155145895Swpaulstatic void NdisAcquireReadWriteLock(ndis_rw_lock *, 156145895Swpaul uint8_t, ndis_lock_state *); 157145895Swpaulstatic void NdisReleaseReadWriteLock(ndis_rw_lock *, ndis_lock_state *); 158144888Swpaulstatic uint32_t NdisReadPciSlotInformation(ndis_handle, uint32_t, 159123474Swpaul uint32_t, void *, uint32_t); 160144888Swpaulstatic uint32_t NdisWritePciSlotInformation(ndis_handle, uint32_t, 161123474Swpaul uint32_t, void *, uint32_t); 162140751Swpaulstatic void NdisWriteErrorLogEntry(ndis_handle, ndis_error_code, uint32_t, ...); 163123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int); 164144888Swpaulstatic void NdisMStartBufferPhysicalMapping(ndis_handle, 165140751Swpaul ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); 166144888Swpaulstatic void NdisMCompleteBufferPhysicalMapping(ndis_handle, 167140751Swpaul ndis_buffer *, uint32_t); 168144888Swpaulstatic void NdisMInitializeTimer(ndis_miniport_timer *, ndis_handle, 169123474Swpaul ndis_timer_function, void *); 170144888Swpaulstatic void NdisInitializeTimer(ndis_timer *, 171125057Swpaul ndis_timer_function, void *); 172144888Swpaulstatic void NdisSetTimer(ndis_timer *, uint32_t); 173144888Swpaulstatic void NdisMSetPeriodicTimer(ndis_miniport_timer *, uint32_t); 174144888Swpaulstatic void NdisMCancelTimer(ndis_timer *, uint8_t *); 175144888Swpaulstatic void ndis_timercall(kdpc *, ndis_miniport_timer *, 176144174Swpaul void *, void *); 177144888Swpaulstatic void NdisMQueryAdapterResources(ndis_status *, ndis_handle, 178123474Swpaul ndis_resource_list *, uint32_t *); 179144888Swpaulstatic ndis_status NdisMRegisterIoPortRange(void **, 180123474Swpaul ndis_handle, uint32_t, uint32_t); 181144888Swpaulstatic void NdisMDeregisterIoPortRange(ndis_handle, 182123474Swpaul uint32_t, uint32_t, void *); 183144888Swpaulstatic void NdisReadNetworkAddress(ndis_status *, void **, 184123474Swpaul uint32_t *, ndis_handle); 185144888Swpaulstatic ndis_status NdisQueryMapRegisterCount(uint32_t, uint32_t *); 186144888Swpaulstatic ndis_status NdisMAllocateMapRegisters(ndis_handle, 187123474Swpaul uint32_t, uint8_t, uint32_t, uint32_t); 188144888Swpaulstatic void NdisMFreeMapRegisters(ndis_handle); 189123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); 190144888Swpaulstatic void NdisMAllocateSharedMemory(ndis_handle, uint32_t, 191123474Swpaul uint8_t, void **, ndis_physaddr *); 192145895Swpaulstatic void ndis_asyncmem_complete(device_object *, void *); 193144888Swpaulstatic ndis_status NdisMAllocateSharedMemoryAsync(ndis_handle, 194123474Swpaul uint32_t, uint8_t, void *); 195144888Swpaulstatic void NdisMFreeSharedMemory(ndis_handle, uint32_t, 196123474Swpaul uint8_t, void *, ndis_physaddr); 197144888Swpaulstatic ndis_status NdisMMapIoSpace(void **, ndis_handle, 198123474Swpaul ndis_physaddr, uint32_t); 199144888Swpaulstatic void NdisMUnmapIoSpace(ndis_handle, void *, uint32_t); 200144888Swpaulstatic uint32_t NdisGetCacheFillSize(void); 201216242Sbschmidtstatic void *NdisGetRoutineAddress(unicode_string *); 202144888Swpaulstatic uint32_t NdisMGetDmaAlignment(ndis_handle); 203144888Swpaulstatic ndis_status NdisMInitializeScatterGatherDma(ndis_handle, 204123474Swpaul uint8_t, uint32_t); 205144888Swpaulstatic void NdisUnchainBufferAtFront(ndis_packet *, ndis_buffer **); 206144888Swpaulstatic void NdisUnchainBufferAtBack(ndis_packet *, ndis_buffer **); 207144888Swpaulstatic void NdisAllocateBufferPool(ndis_status *, 208123474Swpaul ndis_handle *, uint32_t); 209144888Swpaulstatic void NdisFreeBufferPool(ndis_handle); 210144888Swpaulstatic void NdisAllocateBuffer(ndis_status *, ndis_buffer **, 211123474Swpaul ndis_handle, void *, uint32_t); 212144888Swpaulstatic void NdisFreeBuffer(ndis_buffer *); 213144888Swpaulstatic uint32_t NdisBufferLength(ndis_buffer *); 214144888Swpaulstatic void NdisQueryBuffer(ndis_buffer *, void **, uint32_t *); 215144888Swpaulstatic void NdisQueryBufferSafe(ndis_buffer *, void **, 216123474Swpaul uint32_t *, uint32_t); 217144888Swpaulstatic void *NdisBufferVirtualAddress(ndis_buffer *); 218144888Swpaulstatic void *NdisBufferVirtualAddressSafe(ndis_buffer *, uint32_t); 219144888Swpaulstatic void NdisAdjustBufferLength(ndis_buffer *, int); 220144888Swpaulstatic uint32_t NdisInterlockedIncrement(uint32_t *); 221144888Swpaulstatic uint32_t NdisInterlockedDecrement(uint32_t *); 222144888Swpaulstatic void NdisInitializeEvent(ndis_event *); 223144888Swpaulstatic void NdisSetEvent(ndis_event *); 224144888Swpaulstatic void NdisResetEvent(ndis_event *); 225144888Swpaulstatic uint8_t NdisWaitEvent(ndis_event *, uint32_t); 226151207Swpaulstatic ndis_status NdisUnicodeStringToAnsiString(ansi_string *, 227151207Swpaul unicode_string *); 228144888Swpaulstatic ndis_status 229151207Swpaul NdisAnsiStringToUnicodeString(unicode_string *, ansi_string *); 230144888Swpaulstatic ndis_status NdisMPciAssignResources(ndis_handle, 231123474Swpaul uint32_t, ndis_resource_list **); 232144888Swpaulstatic ndis_status NdisMRegisterInterrupt(ndis_miniport_interrupt *, 233123474Swpaul ndis_handle, uint32_t, uint32_t, uint8_t, 234123474Swpaul uint8_t, ndis_interrupt_mode); 235144888Swpaulstatic void NdisMDeregisterInterrupt(ndis_miniport_interrupt *); 236144888Swpaulstatic void NdisMRegisterAdapterShutdownHandler(ndis_handle, void *, 237123474Swpaul ndis_shutdown_handler); 238144888Swpaulstatic void NdisMDeregisterAdapterShutdownHandler(ndis_handle); 239144888Swpaulstatic uint32_t NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *); 240144888Swpaulstatic void NdisGetBufferPhysicalArraySize(ndis_buffer *, 241140751Swpaul uint32_t *); 242144888Swpaulstatic void NdisQueryBufferOffset(ndis_buffer *, 243123474Swpaul uint32_t *, uint32_t *); 244144888Swpaulstatic uint32_t NdisReadPcmciaAttributeMemory(ndis_handle, 245123474Swpaul uint32_t, void *, uint32_t); 246144888Swpaulstatic uint32_t NdisWritePcmciaAttributeMemory(ndis_handle, 247123474Swpaul uint32_t, void *, uint32_t); 248144888Swpaulstatic list_entry *NdisInterlockedInsertHeadList(list_entry *, 249125551Swpaul list_entry *, ndis_spin_lock *); 250144888Swpaulstatic list_entry *NdisInterlockedRemoveHeadList(list_entry *, 251123474Swpaul ndis_spin_lock *); 252144888Swpaulstatic list_entry *NdisInterlockedInsertTailList(list_entry *, 253125551Swpaul list_entry *, ndis_spin_lock *); 254144888Swpaulstatic uint8_t 255140751Swpaul NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *, 256123474Swpaul void *, void *); 257144888Swpaulstatic void NdisGetCurrentSystemTime(uint64_t *); 258144888Swpaulstatic void NdisGetSystemUpTime(uint32_t *); 259215779Sbschmidtstatic uint32_t NdisGetVersion(void); 260151207Swpaulstatic void NdisInitializeString(unicode_string *, char *); 261151207Swpaulstatic void NdisInitAnsiString(ansi_string *, char *); 262151207Swpaulstatic void NdisInitUnicodeString(unicode_string *, uint16_t *); 263151207Swpaulstatic void NdisFreeString(unicode_string *); 264144888Swpaulstatic ndis_status NdisMRemoveMiniport(ndis_handle *); 265144888Swpaulstatic void NdisTerminateWrapper(ndis_handle, void *); 266144888Swpaulstatic void NdisMGetDeviceProperty(ndis_handle, device_object **, 267125551Swpaul device_object **, device_object **, cm_resource_list *, 268125551Swpaul cm_resource_list *); 269144888Swpaulstatic void NdisGetFirstBufferFromPacket(ndis_packet *, 270140751Swpaul ndis_buffer **, void **, uint32_t *, uint32_t *); 271144888Swpaulstatic void NdisGetFirstBufferFromPacketSafe(ndis_packet *, 272140751Swpaul ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t); 273132973Swpaulstatic int ndis_find_sym(linker_file_t, char *, char *, caddr_t *); 274144888Swpaulstatic void NdisOpenFile(ndis_status *, ndis_handle *, uint32_t *, 275151207Swpaul unicode_string *, ndis_physaddr); 276144888Swpaulstatic void NdisMapFile(ndis_status *, void **, ndis_handle); 277144888Swpaulstatic void NdisUnmapFile(ndis_handle); 278144888Swpaulstatic void NdisCloseFile(ndis_handle); 279144888Swpaulstatic uint8_t NdisSystemProcessorCount(void); 280215779Sbschmidtstatic void NdisGetCurrentProcessorCounts(uint32_t *, uint32_t *, uint32_t *); 281144888Swpaulstatic void NdisMIndicateStatusComplete(ndis_handle); 282144888Swpaulstatic void NdisMIndicateStatus(ndis_handle, ndis_status, 283189488Sweongyo void *, uint32_t); 284152626Swpaulstatic uint8_t ndis_intr(kinterrupt *, void *); 285151207Swpaulstatic void ndis_intrhand(kdpc *, ndis_miniport_interrupt *, void *, void *); 286144402Swpaulstatic funcptr ndis_findwrap(funcptr); 287144888Swpaulstatic void NdisCopyFromPacketToPacket(ndis_packet *, 288140751Swpaul uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *); 289144888Swpaulstatic void NdisCopyFromPacketToPacketSafe(ndis_packet *, 290140751Swpaul uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t); 291174240Sthompsastatic void NdisIMCopySendPerPacketInfo(ndis_packet *, ndis_packet *); 292144888Swpaulstatic ndis_status NdisMRegisterDevice(ndis_handle, 293151207Swpaul unicode_string *, unicode_string *, driver_dispatch **, 294125551Swpaul void **, ndis_handle *); 295144888Swpaulstatic ndis_status NdisMDeregisterDevice(ndis_handle); 296144888Swpaulstatic ndis_status 297151207Swpaul NdisMQueryAdapterInstanceName(unicode_string *, ndis_handle); 298144888Swpaulstatic void NdisMRegisterUnloadHandler(ndis_handle, void *); 299144888Swpaulstatic void dummy(void); 300123474Swpaul 301124116Swpaul/* 302124116Swpaul * Some really old drivers do not properly check the return value 303124116Swpaul * from NdisAllocatePacket() and NdisAllocateBuffer() and will 304124116Swpaul * sometimes allocate few more buffers/packets that they originally 305124116Swpaul * requested when they created the pool. To prevent this from being 306124116Swpaul * a problem, we allocate a few extra buffers/packets beyond what 307124116Swpaul * the driver asks for. This #define controls how many. 308124116Swpaul */ 309124116Swpaul#define NDIS_POOL_EXTRA 16 310123474Swpaul 311123474Swpaulint 312123474Swpaulndis_libinit() 313123474Swpaul{ 314141963Swpaul image_patch_table *patch; 315141963Swpaul 316124272Swpaul strcpy(ndis_filepath, "/compat/ndis"); 317141963Swpaul 318141963Swpaul patch = ndis_functbl; 319141963Swpaul while (patch->ipt_func != NULL) { 320141963Swpaul windrv_wrap((funcptr)patch->ipt_func, 321144888Swpaul (funcptr *)&patch->ipt_wrap, 322144888Swpaul patch->ipt_argcnt, patch->ipt_ftype); 323141963Swpaul patch++; 324141963Swpaul } 325141963Swpaul 326198786Srpaulo return (0); 327123474Swpaul} 328123474Swpaul 329123474Swpaulint 330123474Swpaulndis_libfini() 331123474Swpaul{ 332141963Swpaul image_patch_table *patch; 333141963Swpaul 334141963Swpaul patch = ndis_functbl; 335141963Swpaul while (patch->ipt_func != NULL) { 336141963Swpaul windrv_unwrap(patch->ipt_wrap); 337141963Swpaul patch++; 338141963Swpaul } 339141963Swpaul 340198786Srpaulo return (0); 341123474Swpaul} 342123474Swpaul 343144402Swpaulstatic funcptr 344144402Swpaulndis_findwrap(func) 345144402Swpaul funcptr func; 346144402Swpaul{ 347144402Swpaul image_patch_table *patch; 348144402Swpaul 349144428Swpaul patch = ndis_functbl; 350144402Swpaul while (patch->ipt_func != NULL) { 351144402Swpaul if ((funcptr)patch->ipt_func == func) 352198786Srpaulo return ((funcptr)patch->ipt_wrap); 353144402Swpaul patch++; 354144402Swpaul } 355144402Swpaul 356198786Srpaulo return (NULL); 357144402Swpaul} 358144402Swpaul 359123474Swpaul/* 360141524Swpaul * This routine does the messy Windows Driver Model device attachment 361141524Swpaul * stuff on behalf of NDIS drivers. We register our own AddDevice 362141524Swpaul * routine here 363141524Swpaul */ 364144888Swpaulstatic void 365141524SwpaulNdisInitializeWrapper(wrapper, drv, path, unused) 366125551Swpaul ndis_handle *wrapper; 367141524Swpaul driver_object *drv; 368123474Swpaul void *path; 369123474Swpaul void *unused; 370123474Swpaul{ 371141524Swpaul /* 372141524Swpaul * As of yet, I haven't come up with a compelling 373141524Swpaul * reason to define a private NDIS wrapper structure, 374141524Swpaul * so we use a pointer to the driver object as the 375141524Swpaul * wrapper handle. The driver object has the miniport 376141524Swpaul * characteristics struct for this driver hung off it 377141524Swpaul * via IoAllocateDriverObjectExtension(), and that's 378141524Swpaul * really all the private data we need. 379141524Swpaul */ 380123474Swpaul 381141524Swpaul *wrapper = drv; 382123474Swpaul 383141524Swpaul /* 384141524Swpaul * If this was really Windows, we'd be registering dispatch 385141524Swpaul * routines for the NDIS miniport module here, but we're 386141524Swpaul * not Windows so all we really need to do is set up an 387141524Swpaul * AddDevice function that'll be invoked when a new device 388141524Swpaul * instance appears. 389141524Swpaul */ 390141524Swpaul 391141524Swpaul drv->dro_driverext->dre_adddevicefunc = NdisAddDevice; 392123474Swpaul} 393123474Swpaul 394144888Swpaulstatic void 395140751SwpaulNdisTerminateWrapper(handle, syspec) 396123526Swpaul ndis_handle handle; 397123526Swpaul void *syspec; 398123526Swpaul{ 399141524Swpaul /* Nothing to see here, move along. */ 400123526Swpaul} 401123526Swpaul 402144888Swpaulstatic ndis_status 403140751SwpaulNdisMRegisterMiniport(handle, characteristics, len) 404123474Swpaul ndis_handle handle; 405123474Swpaul ndis_miniport_characteristics *characteristics; 406123474Swpaul int len; 407123474Swpaul{ 408141524Swpaul ndis_miniport_characteristics *ch = NULL; 409141524Swpaul driver_object *drv; 410123474Swpaul 411141524Swpaul drv = (driver_object *)handle; 412141524Swpaul 413141524Swpaul /* 414141524Swpaul * We need to save the NDIS miniport characteristics 415141524Swpaul * somewhere. This data is per-driver, not per-device 416141524Swpaul * (all devices handled by the same driver have the 417141524Swpaul * same characteristics) so we hook it onto the driver 418141524Swpaul * object using IoAllocateDriverObjectExtension(). 419141524Swpaul * The extra extension info is automagically deleted when 420141524Swpaul * the driver is unloaded (see windrv_unload()). 421141524Swpaul */ 422141524Swpaul 423141524Swpaul if (IoAllocateDriverObjectExtension(drv, (void *)1, 424141524Swpaul sizeof(ndis_miniport_characteristics), (void **)&ch) != 425151207Swpaul STATUS_SUCCESS) { 426198786Srpaulo return (NDIS_STATUS_RESOURCES); 427151207Swpaul } 428141524Swpaul 429141524Swpaul bzero((char *)ch, sizeof(ndis_miniport_characteristics)); 430141524Swpaul 431141524Swpaul bcopy((char *)characteristics, (char *)ch, len); 432141524Swpaul 433141524Swpaul if (ch->nmc_version_major < 5 || ch->nmc_version_minor < 1) { 434141524Swpaul ch->nmc_shutdown_handler = NULL; 435141524Swpaul ch->nmc_canceltxpkts_handler = NULL; 436141524Swpaul ch->nmc_pnpevent_handler = NULL; 437125551Swpaul } 438125551Swpaul 439198786Srpaulo return (NDIS_STATUS_SUCCESS); 440123474Swpaul} 441123474Swpaul 442144888Swpaulstatic ndis_status 443140751SwpaulNdisAllocateMemoryWithTag(vaddr, len, tag) 444123474Swpaul void **vaddr; 445123474Swpaul uint32_t len; 446123474Swpaul uint32_t tag; 447123474Swpaul{ 448123474Swpaul void *mem; 449123474Swpaul 450141524Swpaul mem = ExAllocatePoolWithTag(NonPagedPool, len, tag); 451151207Swpaul if (mem == NULL) { 452198786Srpaulo return (NDIS_STATUS_RESOURCES); 453151207Swpaul } 454123474Swpaul *vaddr = mem; 455123474Swpaul 456198786Srpaulo return (NDIS_STATUS_SUCCESS); 457123474Swpaul} 458123474Swpaul 459144888Swpaulstatic ndis_status 460140751SwpaulNdisAllocateMemory(vaddr, len, flags, highaddr) 461123474Swpaul void **vaddr; 462123474Swpaul uint32_t len; 463123474Swpaul uint32_t flags; 464123474Swpaul ndis_physaddr highaddr; 465123474Swpaul{ 466123474Swpaul void *mem; 467123474Swpaul 468141524Swpaul mem = ExAllocatePoolWithTag(NonPagedPool, len, 0); 469123474Swpaul if (mem == NULL) 470198786Srpaulo return (NDIS_STATUS_RESOURCES); 471123474Swpaul *vaddr = mem; 472123474Swpaul 473198786Srpaulo return (NDIS_STATUS_SUCCESS); 474123474Swpaul} 475123474Swpaul 476144888Swpaulstatic void 477140751SwpaulNdisFreeMemory(vaddr, len, flags) 478123474Swpaul void *vaddr; 479123474Swpaul uint32_t len; 480123474Swpaul uint32_t flags; 481123474Swpaul{ 482123474Swpaul if (len == 0) 483123474Swpaul return; 484125551Swpaul 485141524Swpaul ExFreePool(vaddr); 486123474Swpaul} 487123474Swpaul 488144888Swpaulstatic ndis_status 489140751SwpaulNdisMSetAttributesEx(adapter_handle, adapter_ctx, hangsecs, 490123474Swpaul flags, iftype) 491123474Swpaul ndis_handle adapter_handle; 492123474Swpaul ndis_handle adapter_ctx; 493123474Swpaul uint32_t hangsecs; 494123474Swpaul uint32_t flags; 495123474Swpaul ndis_interface_type iftype; 496123474Swpaul{ 497123474Swpaul ndis_miniport_block *block; 498123474Swpaul 499123474Swpaul /* 500123474Swpaul * Save the adapter context, we need it for calling 501123474Swpaul * the driver's internal functions. 502123474Swpaul */ 503123474Swpaul block = (ndis_miniport_block *)adapter_handle; 504123474Swpaul block->nmb_miniportadapterctx = adapter_ctx; 505123474Swpaul block->nmb_checkforhangsecs = hangsecs; 506126833Swpaul block->nmb_flags = flags; 507123474Swpaul 508198786Srpaulo return (NDIS_STATUS_SUCCESS); 509123474Swpaul} 510123474Swpaul 511144888Swpaulstatic void 512140751SwpaulNdisOpenConfiguration(status, cfg, wrapctx) 513123474Swpaul ndis_status *status; 514123474Swpaul ndis_handle *cfg; 515123474Swpaul ndis_handle wrapctx; 516123474Swpaul{ 517123474Swpaul *cfg = wrapctx; 518123474Swpaul *status = NDIS_STATUS_SUCCESS; 519123474Swpaul} 520123474Swpaul 521144888Swpaulstatic void 522140751SwpaulNdisOpenConfigurationKeyByName(status, cfg, subkey, subhandle) 523123526Swpaul ndis_status *status; 524123526Swpaul ndis_handle cfg; 525151207Swpaul unicode_string *subkey; 526123526Swpaul ndis_handle *subhandle; 527123526Swpaul{ 528123526Swpaul *subhandle = cfg; 529123526Swpaul *status = NDIS_STATUS_SUCCESS; 530123526Swpaul} 531123526Swpaul 532144888Swpaulstatic void 533140751SwpaulNdisOpenConfigurationKeyByIndex(status, cfg, idx, subkey, subhandle) 534123526Swpaul ndis_status *status; 535123526Swpaul ndis_handle cfg; 536123526Swpaul uint32_t idx; 537151207Swpaul unicode_string *subkey; 538123526Swpaul ndis_handle *subhandle; 539123526Swpaul{ 540123526Swpaul *status = NDIS_STATUS_FAILURE; 541123526Swpaul} 542123526Swpaul 543123474Swpaulstatic ndis_status 544123474Swpaulndis_encode_parm(block, oid, type, parm) 545123474Swpaul ndis_miniport_block *block; 546189488Sweongyo struct sysctl_oid *oid; 547123474Swpaul ndis_parm_type type; 548123474Swpaul ndis_config_parm **parm; 549123474Swpaul{ 550151207Swpaul ndis_config_parm *p; 551151207Swpaul ndis_parmlist_entry *np; 552151207Swpaul unicode_string *us; 553151207Swpaul ansi_string as; 554127248Swpaul int base = 0; 555151207Swpaul uint32_t val; 556151207Swpaul char tmp[32]; 557123474Swpaul 558151207Swpaul np = ExAllocatePoolWithTag(NonPagedPool, 559151207Swpaul sizeof(ndis_parmlist_entry), 0); 560151207Swpaul if (np == NULL) 561198786Srpaulo return (NDIS_STATUS_RESOURCES); 562151207Swpaul InsertHeadList((&block->nmb_parmlist), (&np->np_list)); 563151207Swpaul *parm = p = &np->np_parm; 564123474Swpaul 565123474Swpaul switch(type) { 566123474Swpaul case ndis_parm_string: 567151207Swpaul /* See if this might be a number. */ 568151207Swpaul val = strtoul((char *)oid->oid_arg1, NULL, 10); 569151207Swpaul us = &p->ncp_parmdata.ncp_stringdata; 570151207Swpaul p->ncp_type = ndis_parm_string; 571151207Swpaul if (val) { 572151207Swpaul snprintf(tmp, 32, "%x", val); 573151207Swpaul RtlInitAnsiString(&as, tmp); 574151207Swpaul } else { 575151207Swpaul RtlInitAnsiString(&as, (char *)oid->oid_arg1); 576151207Swpaul } 577151207Swpaul 578151207Swpaul if (RtlAnsiStringToUnicodeString(us, &as, TRUE)) { 579151207Swpaul ExFreePool(np); 580198786Srpaulo return (NDIS_STATUS_RESOURCES); 581151207Swpaul } 582123474Swpaul break; 583123474Swpaul case ndis_parm_int: 584127248Swpaul if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) 585127248Swpaul base = 16; 586127248Swpaul else 587127248Swpaul base = 10; 588151207Swpaul p->ncp_type = ndis_parm_int; 589151207Swpaul p->ncp_parmdata.ncp_intdata = 590127248Swpaul strtol((char *)oid->oid_arg1, NULL, base); 591123474Swpaul break; 592123474Swpaul case ndis_parm_hexint: 593151207Swpaul#ifdef notdef 594127248Swpaul if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) 595127248Swpaul base = 16; 596127248Swpaul else 597127248Swpaul base = 10; 598151207Swpaul#endif 599151207Swpaul base = 16; 600151207Swpaul p->ncp_type = ndis_parm_hexint; 601151207Swpaul p->ncp_parmdata.ncp_intdata = 602127248Swpaul strtoul((char *)oid->oid_arg1, NULL, base); 603123474Swpaul break; 604123474Swpaul default: 605198786Srpaulo return (NDIS_STATUS_FAILURE); 606123474Swpaul break; 607123474Swpaul } 608123474Swpaul 609198786Srpaulo return (NDIS_STATUS_SUCCESS); 610123474Swpaul} 611123474Swpaul 612144888Swpaulstatic void 613140751SwpaulNdisReadConfiguration(status, parm, cfg, key, type) 614123474Swpaul ndis_status *status; 615123474Swpaul ndis_config_parm **parm; 616123474Swpaul ndis_handle cfg; 617151207Swpaul unicode_string *key; 618123474Swpaul ndis_parm_type type; 619123474Swpaul{ 620123474Swpaul char *keystr = NULL; 621123474Swpaul ndis_miniport_block *block; 622123474Swpaul struct ndis_softc *sc; 623189488Sweongyo struct sysctl_oid *oidp; 624123474Swpaul struct sysctl_ctx_entry *e; 625151207Swpaul ansi_string as; 626123474Swpaul 627123474Swpaul block = (ndis_miniport_block *)cfg; 628141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 629319726Sglebius /* 630319726Sglebius device_printf(sc->ndis_dev, "NdisReadConfiguration sc=%p\n", sc); 631319726Sglebius */ 632123474Swpaul 633141524Swpaul if (key->us_len == 0 || key->us_buf == NULL) { 634124100Swpaul *status = NDIS_STATUS_FAILURE; 635124100Swpaul return; 636124100Swpaul } 637124100Swpaul 638151207Swpaul if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { 639151207Swpaul *status = NDIS_STATUS_RESOURCES; 640151207Swpaul return; 641151207Swpaul } 642123474Swpaul 643151207Swpaul keystr = as.as_buf; 644151207Swpaul 645123474Swpaul /* 646123474Swpaul * See if registry key is already in a list of known keys 647123474Swpaul * included with the driver. 648123474Swpaul */ 649130097Sdes TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { 650123474Swpaul oidp = e->entry; 651168421Spjd if (strcasecmp(oidp->oid_name, keystr) == 0) { 652123488Swpaul if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { 653151207Swpaul RtlFreeAnsiString(&as); 654123488Swpaul *status = NDIS_STATUS_FAILURE; 655123488Swpaul return; 656123488Swpaul } 657151207Swpaul 658123474Swpaul *status = ndis_encode_parm(block, oidp, type, parm); 659151207Swpaul RtlFreeAnsiString(&as); 660123474Swpaul return; 661123474Swpaul } 662123474Swpaul } 663123474Swpaul 664123474Swpaul /* 665123474Swpaul * If the key didn't match, add it to the list of dynamically 666123474Swpaul * created ones. Sometimes, drivers refer to registry keys 667123474Swpaul * that aren't documented in their .INF files. These keys 668123474Swpaul * are supposed to be created by some sort of utility or 669123474Swpaul * control panel snap-in that comes with the driver software. 670123474Swpaul * Sometimes it's useful to be able to manipulate these. 671123474Swpaul * If the driver requests the key in the form of a string, 672123474Swpaul * make its default value an empty string, otherwise default 673123474Swpaul * it to "0". 674123474Swpaul */ 675123474Swpaul 676123474Swpaul if (type == ndis_parm_int || type == ndis_parm_hexint) 677123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic integer key)", 678123488Swpaul "UNSET", CTLFLAG_RW); 679123474Swpaul else 680123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic string key)", 681123488Swpaul "UNSET", CTLFLAG_RW); 682123474Swpaul 683151207Swpaul RtlFreeAnsiString(&as); 684123474Swpaul *status = NDIS_STATUS_FAILURE; 685123474Swpaul} 686123474Swpaul 687123526Swpaulstatic ndis_status 688123526Swpaulndis_decode_parm(block, parm, val) 689123526Swpaul ndis_miniport_block *block; 690123526Swpaul ndis_config_parm *parm; 691123526Swpaul char *val; 692123526Swpaul{ 693151207Swpaul unicode_string *ustr; 694151207Swpaul ansi_string as; 695123526Swpaul 696123526Swpaul switch(parm->ncp_type) { 697123526Swpaul case ndis_parm_string: 698123526Swpaul ustr = &parm->ncp_parmdata.ncp_stringdata; 699151207Swpaul if (RtlUnicodeStringToAnsiString(&as, ustr, TRUE)) 700198786Srpaulo return (NDIS_STATUS_RESOURCES); 701151207Swpaul bcopy(as.as_buf, val, as.as_len); 702151207Swpaul RtlFreeAnsiString(&as); 703123526Swpaul break; 704123526Swpaul case ndis_parm_int: 705124697Swpaul sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata); 706123526Swpaul break; 707123526Swpaul case ndis_parm_hexint: 708123526Swpaul sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata); 709123526Swpaul break; 710123526Swpaul default: 711198786Srpaulo return (NDIS_STATUS_FAILURE); 712123526Swpaul break; 713123526Swpaul } 714198786Srpaulo return (NDIS_STATUS_SUCCESS); 715123526Swpaul} 716123526Swpaul 717144888Swpaulstatic void 718140751SwpaulNdisWriteConfiguration(status, cfg, key, parm) 719123526Swpaul ndis_status *status; 720123526Swpaul ndis_handle cfg; 721151207Swpaul unicode_string *key; 722123526Swpaul ndis_config_parm *parm; 723123526Swpaul{ 724151207Swpaul ansi_string as; 725123526Swpaul char *keystr = NULL; 726123526Swpaul ndis_miniport_block *block; 727123526Swpaul struct ndis_softc *sc; 728189488Sweongyo struct sysctl_oid *oidp; 729123526Swpaul struct sysctl_ctx_entry *e; 730123526Swpaul char val[256]; 731123526Swpaul 732123526Swpaul block = (ndis_miniport_block *)cfg; 733141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 734123526Swpaul 735151207Swpaul if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { 736151207Swpaul *status = NDIS_STATUS_RESOURCES; 737151207Swpaul return; 738151207Swpaul } 739123526Swpaul 740151207Swpaul keystr = as.as_buf; 741151207Swpaul 742123526Swpaul /* Decode the parameter into a string. */ 743124697Swpaul bzero(val, sizeof(val)); 744123526Swpaul *status = ndis_decode_parm(block, parm, val); 745123526Swpaul if (*status != NDIS_STATUS_SUCCESS) { 746151207Swpaul RtlFreeAnsiString(&as); 747123526Swpaul return; 748123526Swpaul } 749123526Swpaul 750123526Swpaul /* See if the key already exists. */ 751123526Swpaul 752130097Sdes TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { 753123526Swpaul oidp = e->entry; 754168421Spjd if (strcasecmp(oidp->oid_name, keystr) == 0) { 755123526Swpaul /* Found it, set the value. */ 756123526Swpaul strcpy((char *)oidp->oid_arg1, val); 757151207Swpaul RtlFreeAnsiString(&as); 758123526Swpaul return; 759123526Swpaul } 760123526Swpaul } 761123526Swpaul 762123526Swpaul /* Not found, add a new key with the specified value. */ 763123526Swpaul ndis_add_sysctl(sc, keystr, "(dynamically set key)", 764123526Swpaul val, CTLFLAG_RW); 765123526Swpaul 766151207Swpaul RtlFreeAnsiString(&as); 767123526Swpaul *status = NDIS_STATUS_SUCCESS; 768123526Swpaul} 769123526Swpaul 770144888Swpaulstatic void 771140751SwpaulNdisCloseConfiguration(cfg) 772123474Swpaul ndis_handle cfg; 773123474Swpaul{ 774151207Swpaul list_entry *e; 775151207Swpaul ndis_parmlist_entry *pe; 776151207Swpaul ndis_miniport_block *block; 777151207Swpaul ndis_config_parm *p; 778151207Swpaul 779151207Swpaul block = (ndis_miniport_block *)cfg; 780151207Swpaul 781151207Swpaul while (!IsListEmpty(&block->nmb_parmlist)) { 782189488Sweongyo e = RemoveHeadList(&block->nmb_parmlist); 783189488Sweongyo pe = CONTAINING_RECORD(e, ndis_parmlist_entry, np_list); 784151207Swpaul p = &pe->np_parm; 785151207Swpaul if (p->ncp_type == ndis_parm_string) 786151207Swpaul RtlFreeUnicodeString(&p->ncp_parmdata.ncp_stringdata); 787151207Swpaul ExFreePool(e); 788151207Swpaul } 789123474Swpaul} 790123474Swpaul 791128229Swpaul/* 792128229Swpaul * Initialize a Windows spinlock. 793128229Swpaul */ 794144888Swpaulstatic void 795140751SwpaulNdisAllocateSpinLock(lock) 796123474Swpaul ndis_spin_lock *lock; 797123474Swpaul{ 798140751Swpaul KeInitializeSpinLock(&lock->nsl_spinlock); 799128229Swpaul lock->nsl_kirql = 0; 800123474Swpaul} 801123474Swpaul 802128229Swpaul/* 803128229Swpaul * Destroy a Windows spinlock. This is a no-op for now. There are two reasons 804128229Swpaul * for this. One is that it's sort of superfluous: we don't have to do anything 805128229Swpaul * special to deallocate the spinlock. The other is that there are some buggy 806128229Swpaul * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on 807128229Swpaul * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm 808128229Swpaul * talking to you.) 809128229Swpaul */ 810144888Swpaulstatic void 811140751SwpaulNdisFreeSpinLock(lock) 812123474Swpaul ndis_spin_lock *lock; 813123474Swpaul{ 814128229Swpaul#ifdef notdef 815140751Swpaul KeInitializeSpinLock(&lock->nsl_spinlock); 816128229Swpaul lock->nsl_kirql = 0; 817128229Swpaul#endif 818123474Swpaul} 819123474Swpaul 820128229Swpaul/* 821128229Swpaul * Acquire a spinlock from IRQL <= DISPATCH_LEVEL. 822128229Swpaul */ 823128229Swpaul 824144888Swpaulstatic void 825140751SwpaulNdisAcquireSpinLock(lock) 826123474Swpaul ndis_spin_lock *lock; 827123474Swpaul{ 828140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 829123474Swpaul} 830123474Swpaul 831128229Swpaul/* 832128229Swpaul * Release a spinlock from IRQL == DISPATCH_LEVEL. 833128229Swpaul */ 834128229Swpaul 835144888Swpaulstatic void 836140751SwpaulNdisReleaseSpinLock(lock) 837123474Swpaul ndis_spin_lock *lock; 838123474Swpaul{ 839140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 840123474Swpaul} 841123474Swpaul 842128229Swpaul/* 843128229Swpaul * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL. 844128229Swpaul */ 845144888Swpaulstatic void 846140751SwpaulNdisDprAcquireSpinLock(lock) 847128229Swpaul ndis_spin_lock *lock; 848128229Swpaul{ 849144174Swpaul KeAcquireSpinLockAtDpcLevel(&lock->nsl_spinlock); 850128229Swpaul} 851128229Swpaul 852128229Swpaul/* 853128229Swpaul * Release a spinlock without leaving IRQL == DISPATCH_LEVEL. 854128229Swpaul */ 855144888Swpaulstatic void 856140751SwpaulNdisDprReleaseSpinLock(lock) 857128229Swpaul ndis_spin_lock *lock; 858128229Swpaul{ 859144174Swpaul KeReleaseSpinLockFromDpcLevel(&lock->nsl_spinlock); 860128229Swpaul} 861128229Swpaul 862145895Swpaulstatic void 863145895SwpaulNdisInitializeReadWriteLock(lock) 864145895Swpaul ndis_rw_lock *lock; 865145895Swpaul{ 866145895Swpaul KeInitializeSpinLock(&lock->nrl_spinlock); 867145895Swpaul bzero((char *)&lock->nrl_rsvd, sizeof(lock->nrl_rsvd)); 868145895Swpaul} 869145895Swpaul 870145895Swpaulstatic void 871189004SrdivackyNdisAcquireReadWriteLock(ndis_rw_lock *lock, uint8_t writeacc, 872189004Srdivacky ndis_lock_state *state) 873145895Swpaul{ 874145895Swpaul if (writeacc == TRUE) { 875145895Swpaul KeAcquireSpinLock(&lock->nrl_spinlock, &state->nls_oldirql); 876145895Swpaul lock->nrl_rsvd[0]++; 877145895Swpaul } else 878145895Swpaul lock->nrl_rsvd[1]++; 879145895Swpaul} 880145895Swpaul 881145895Swpaulstatic void 882145895SwpaulNdisReleaseReadWriteLock(lock, state) 883145895Swpaul ndis_rw_lock *lock; 884145895Swpaul ndis_lock_state *state; 885145895Swpaul{ 886145895Swpaul if (lock->nrl_rsvd[0]) { 887145895Swpaul lock->nrl_rsvd[0]--; 888145895Swpaul KeReleaseSpinLock(&lock->nrl_spinlock, state->nls_oldirql); 889145895Swpaul } else 890145895Swpaul lock->nrl_rsvd[1]--; 891145895Swpaul} 892145895Swpaul 893144888Swpaulstatic uint32_t 894140751SwpaulNdisReadPciSlotInformation(adapter, slot, offset, buf, len) 895123474Swpaul ndis_handle adapter; 896123474Swpaul uint32_t slot; 897123474Swpaul uint32_t offset; 898123474Swpaul void *buf; 899123474Swpaul uint32_t len; 900123474Swpaul{ 901123474Swpaul ndis_miniport_block *block; 902298731Spfg uint32_t i; 903123474Swpaul char *dest; 904141524Swpaul device_t dev; 905123474Swpaul 906123474Swpaul block = (ndis_miniport_block *)adapter; 907123474Swpaul dest = buf; 908141524Swpaul if (block == NULL) 909198786Srpaulo return (0); 910123474Swpaul 911141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 912144174Swpaul 913144174Swpaul /* 914144174Swpaul * I have a test system consisting of a Sun w2100z 915144174Swpaul * dual 2.4Ghz Opteron machine and an Atheros 802.11a/b/g 916144174Swpaul * "Aries" miniPCI NIC. (The NIC is installed in the 917144174Swpaul * machine using a miniPCI to PCI bus adapter card.) 918144174Swpaul * When running in SMP mode, I found that 919144174Swpaul * performing a large number of consecutive calls to 920144174Swpaul * NdisReadPciSlotInformation() would result in a 921144174Swpaul * sudden system reset (or in some cases a freeze). 922144174Swpaul * My suspicion is that the multiple reads are somehow 923144174Swpaul * triggering a fatal PCI bus error that leads to a 924144174Swpaul * machine check. The 1us delay in the loop below 925144174Swpaul * seems to prevent this problem. 926144174Swpaul */ 927144174Swpaul 928144174Swpaul for (i = 0; i < len; i++) { 929144174Swpaul DELAY(1); 930141524Swpaul dest[i] = pci_read_config(dev, i + offset, 1); 931144174Swpaul } 932123474Swpaul 933198786Srpaulo return (len); 934123474Swpaul} 935123474Swpaul 936144888Swpaulstatic uint32_t 937140751SwpaulNdisWritePciSlotInformation(adapter, slot, offset, buf, len) 938123474Swpaul ndis_handle adapter; 939123474Swpaul uint32_t slot; 940123474Swpaul uint32_t offset; 941123474Swpaul void *buf; 942123474Swpaul uint32_t len; 943123474Swpaul{ 944123474Swpaul ndis_miniport_block *block; 945298731Spfg uint32_t i; 946123474Swpaul char *dest; 947141524Swpaul device_t dev; 948123474Swpaul 949123474Swpaul block = (ndis_miniport_block *)adapter; 950123474Swpaul dest = buf; 951123474Swpaul 952141524Swpaul if (block == NULL) 953198786Srpaulo return (0); 954123474Swpaul 955141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 956144174Swpaul for (i = 0; i < len; i++) { 957144174Swpaul DELAY(1); 958141524Swpaul pci_write_config(dev, i + offset, dest[i], 1); 959144174Swpaul } 960123474Swpaul 961198786Srpaulo return (len); 962123474Swpaul} 963123474Swpaul 964123474Swpaul/* 965123474Swpaul * The errorlog routine uses a variable argument list, so we 966123474Swpaul * have to declare it this way. 967123474Swpaul */ 968151207Swpaul 969124228Swpaul#define ERRMSGLEN 512 970123474Swpaulstatic void 971140751SwpaulNdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, 972123474Swpaul uint32_t numerrors, ...) 973123474Swpaul{ 974123474Swpaul ndis_miniport_block *block; 975123474Swpaul va_list ap; 976124173Swpaul int i, error; 977151207Swpaul char *str = NULL; 978124173Swpaul uint16_t flags; 979141524Swpaul device_t dev; 980141963Swpaul driver_object *drv; 981145895Swpaul struct ndis_softc *sc; 982145895Swpaul struct ifnet *ifp; 983151207Swpaul unicode_string us; 984151606Swpaul ansi_string as = { 0, 0, NULL }; 985123474Swpaul 986123474Swpaul block = (ndis_miniport_block *)adapter; 987141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 988145485Swpaul drv = block->nmb_deviceobj->do_drvobj; 989145895Swpaul sc = device_get_softc(dev); 990319726Sglebius ifp = NDISUSB_GET_IFNET(sc); 991123474Swpaul 992179720Sweongyo if (ifp != NULL && ifp->if_flags & IFF_DEBUG) { 993151977Swpaul error = pe_get_message((vm_offset_t)drv->dro_driverstart, 994151977Swpaul code, &str, &i, &flags); 995151977Swpaul if (error == 0) { 996151977Swpaul if (flags & MESSAGE_RESOURCE_UNICODE) { 997151977Swpaul RtlInitUnicodeString(&us, (uint16_t *)str); 998151977Swpaul if (RtlUnicodeStringToAnsiString(&as, 999151977Swpaul &us, TRUE) == STATUS_SUCCESS) 1000151977Swpaul str = as.as_buf; 1001151977Swpaul else 1002151977Swpaul str = NULL; 1003151977Swpaul } 1004151977Swpaul } 1005151977Swpaul } 1006145895Swpaul 1007198786Srpaulo device_printf(dev, "NDIS ERROR: %x (%s)\n", code, 1008124165Swpaul str == NULL ? "unknown error" : str); 1009123474Swpaul 1010179720Sweongyo if (ifp != NULL && ifp->if_flags & IFF_DEBUG) { 1011198786Srpaulo device_printf(dev, "NDIS NUMERRORS: %x\n", numerrors); 1012145895Swpaul va_start(ap, numerrors); 1013145895Swpaul for (i = 0; i < numerrors; i++) 1014198786Srpaulo device_printf(dev, "argptr: %p\n", 1015145895Swpaul va_arg(ap, void *)); 1016145895Swpaul va_end(ap); 1017145895Swpaul } 1018123474Swpaul 1019151606Swpaul if (as.as_len) 1020151207Swpaul RtlFreeAnsiString(&as); 1021123474Swpaul} 1022123474Swpaul 1023123474Swpaulstatic void 1024123474Swpaulndis_map_cb(arg, segs, nseg, error) 1025123474Swpaul void *arg; 1026123474Swpaul bus_dma_segment_t *segs; 1027123474Swpaul int nseg; 1028123474Swpaul int error; 1029123474Swpaul{ 1030123474Swpaul struct ndis_map_arg *ctx; 1031123474Swpaul int i; 1032123474Swpaul 1033123474Swpaul if (error) 1034123474Swpaul return; 1035123474Swpaul 1036123474Swpaul ctx = arg; 1037123474Swpaul 1038123474Swpaul for (i = 0; i < nseg; i++) { 1039123474Swpaul ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr; 1040123474Swpaul ctx->nma_fraglist[i].npu_len = segs[i].ds_len; 1041123474Swpaul } 1042123474Swpaul 1043123474Swpaul ctx->nma_cnt = nseg; 1044123474Swpaul} 1045123474Swpaul 1046144888Swpaulstatic void 1047189004SrdivackyNdisMStartBufferPhysicalMapping(ndis_handle adapter, ndis_buffer *buf, 1048189004Srdivacky uint32_t mapreg, uint8_t writedev, ndis_paddr_unit *addrarray, 1049189004Srdivacky uint32_t *arraysize) 1050123474Swpaul{ 1051123474Swpaul ndis_miniport_block *block; 1052123474Swpaul struct ndis_softc *sc; 1053123474Swpaul struct ndis_map_arg nma; 1054123474Swpaul bus_dmamap_t map; 1055123474Swpaul int error; 1056123474Swpaul 1057123474Swpaul if (adapter == NULL) 1058123474Swpaul return; 1059123474Swpaul 1060123474Swpaul block = (ndis_miniport_block *)adapter; 1061141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1062123474Swpaul 1063123474Swpaul if (mapreg > sc->ndis_mmapcnt) 1064123474Swpaul return; 1065123474Swpaul 1066123474Swpaul map = sc->ndis_mmaps[mapreg]; 1067123474Swpaul nma.nma_fraglist = addrarray; 1068123474Swpaul 1069123474Swpaul error = bus_dmamap_load(sc->ndis_mtag, map, 1070140751Swpaul MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf), ndis_map_cb, 1071123474Swpaul (void *)&nma, BUS_DMA_NOWAIT); 1072123474Swpaul 1073123474Swpaul if (error) 1074123474Swpaul return; 1075123474Swpaul 1076123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 1077123474Swpaul writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); 1078123474Swpaul 1079123474Swpaul *arraysize = nma.nma_cnt; 1080123474Swpaul} 1081123474Swpaul 1082144888Swpaulstatic void 1083140751SwpaulNdisMCompleteBufferPhysicalMapping(adapter, buf, mapreg) 1084123474Swpaul ndis_handle adapter; 1085123474Swpaul ndis_buffer *buf; 1086123474Swpaul uint32_t mapreg; 1087123474Swpaul{ 1088123474Swpaul ndis_miniport_block *block; 1089123474Swpaul struct ndis_softc *sc; 1090123474Swpaul bus_dmamap_t map; 1091123474Swpaul 1092123474Swpaul if (adapter == NULL) 1093123474Swpaul return; 1094123474Swpaul 1095123474Swpaul block = (ndis_miniport_block *)adapter; 1096141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1097123474Swpaul 1098123474Swpaul if (mapreg > sc->ndis_mmapcnt) 1099123474Swpaul return; 1100123474Swpaul 1101123474Swpaul map = sc->ndis_mmaps[mapreg]; 1102123474Swpaul 1103123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 1104123474Swpaul BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1105123474Swpaul 1106123474Swpaul bus_dmamap_unload(sc->ndis_mtag, map); 1107123474Swpaul} 1108123474Swpaul 1109125057Swpaul/* 1110144174Swpaul * This is an older (?) timer init routine which doesn't 1111144174Swpaul * accept a miniport context handle. Serialized miniports should 1112144174Swpaul * never call this function. 1113125057Swpaul */ 1114125057Swpaul 1115144888Swpaulstatic void 1116140751SwpaulNdisInitializeTimer(timer, func, ctx) 1117125057Swpaul ndis_timer *timer; 1118125057Swpaul ndis_timer_function func; 1119125057Swpaul void *ctx; 1120125057Swpaul{ 1121140751Swpaul KeInitializeTimer(&timer->nt_ktimer); 1122140751Swpaul KeInitializeDpc(&timer->nt_kdpc, func, ctx); 1123145895Swpaul KeSetImportanceDpc(&timer->nt_kdpc, KDPC_IMPORTANCE_LOW); 1124125057Swpaul} 1125125057Swpaul 1126144888Swpaulstatic void 1127144174Swpaulndis_timercall(dpc, timer, sysarg1, sysarg2) 1128144174Swpaul kdpc *dpc; 1129144174Swpaul ndis_miniport_timer *timer; 1130144174Swpaul void *sysarg1; 1131144174Swpaul void *sysarg2; 1132144174Swpaul{ 1133144174Swpaul /* 1134144174Swpaul * Since we're called as a DPC, we should be running 1135144174Swpaul * at DISPATCH_LEVEL here. This means to acquire the 1136144174Swpaul * spinlock, we can use KeAcquireSpinLockAtDpcLevel() 1137144174Swpaul * rather than KeAcquireSpinLock(). 1138144174Swpaul */ 1139144174Swpaul if (NDIS_SERIALIZED(timer->nmt_block)) 1140144174Swpaul KeAcquireSpinLockAtDpcLevel(&timer->nmt_block->nmb_lock); 1141144174Swpaul 1142144174Swpaul MSCALL4(timer->nmt_timerfunc, dpc, timer->nmt_timerctx, 1143144174Swpaul sysarg1, sysarg2); 1144144174Swpaul 1145144174Swpaul if (NDIS_SERIALIZED(timer->nmt_block)) 1146144174Swpaul KeReleaseSpinLockFromDpcLevel(&timer->nmt_block->nmb_lock); 1147144174Swpaul} 1148144174Swpaul 1149144174Swpaul/* 1150144174Swpaul * For a long time I wondered why there were two NDIS timer initialization 1151144174Swpaul * routines, and why this one needed an NDIS_MINIPORT_TIMER and the 1152144174Swpaul * MiniportAdapterHandle. The NDIS_MINIPORT_TIMER has its own callout 1153144174Swpaul * function and context pointers separate from those in the DPC, which 1154144174Swpaul * allows for another level of indirection: when the timer fires, we 1155144174Swpaul * can have our own timer function invoked, and from there we can call 1156144174Swpaul * the driver's function. But why go to all that trouble? Then it hit 1157144174Swpaul * me: for serialized miniports, the timer callouts are not re-entrant. 1158144174Swpaul * By trapping the callouts and having access to the MiniportAdapterHandle, 1159144174Swpaul * we can protect the driver callouts by acquiring the NDIS serialization 1160144174Swpaul * lock. This is essential for allowing serialized miniports to work 1161144174Swpaul * correctly on SMP systems. On UP hosts, setting IRQL to DISPATCH_LEVEL 1162144174Swpaul * is enough to prevent other threads from pre-empting you, but with 1163144174Swpaul * SMP, you must acquire a lock as well, otherwise the other CPU is 1164144174Swpaul * free to clobber you. 1165144174Swpaul */ 1166144888Swpaulstatic void 1167140751SwpaulNdisMInitializeTimer(timer, handle, func, ctx) 1168123474Swpaul ndis_miniport_timer *timer; 1169127248Swpaul ndis_handle handle; 1170123474Swpaul ndis_timer_function func; 1171123474Swpaul void *ctx; 1172123474Swpaul{ 1173186507Sweongyo ndis_miniport_block *block; 1174186507Sweongyo struct ndis_softc *sc; 1175186507Sweongyo 1176186507Sweongyo block = (ndis_miniport_block *)handle; 1177186507Sweongyo sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1178186507Sweongyo 1179144174Swpaul /* Save the driver's funcptr and context */ 1180123474Swpaul 1181127248Swpaul timer->nmt_timerfunc = func; 1182127248Swpaul timer->nmt_timerctx = ctx; 1183127248Swpaul timer->nmt_block = handle; 1184123821Swpaul 1185144402Swpaul /* 1186144402Swpaul * Set up the timer so it will call our intermediate DPC. 1187144402Swpaul * Be sure to use the wrapped entry point, since 1188144402Swpaul * ntoskrnl_run_dpc() expects to invoke a function with 1189144402Swpaul * Microsoft calling conventions. 1190144402Swpaul */ 1191140751Swpaul KeInitializeTimer(&timer->nmt_ktimer); 1192144402Swpaul KeInitializeDpc(&timer->nmt_kdpc, 1193144402Swpaul ndis_findwrap((funcptr)ndis_timercall), timer); 1194145895Swpaul timer->nmt_ktimer.k_dpc = &timer->nmt_kdpc; 1195123474Swpaul} 1196123474Swpaul 1197123474Swpaul/* 1198127248Swpaul * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(), 1199127248Swpaul * but the former is just a macro wrapper around the latter. 1200123474Swpaul */ 1201144888Swpaulstatic void 1202140751SwpaulNdisSetTimer(timer, msecs) 1203127248Swpaul ndis_timer *timer; 1204123474Swpaul uint32_t msecs; 1205123474Swpaul{ 1206127248Swpaul /* 1207127248Swpaul * KeSetTimer() wants the period in 1208127248Swpaul * hundred nanosecond intervals. 1209127248Swpaul */ 1210140751Swpaul KeSetTimer(&timer->nt_ktimer, 1211127248Swpaul ((int64_t)msecs * -10000), &timer->nt_kdpc); 1212123474Swpaul} 1213123474Swpaul 1214144888Swpaulstatic void 1215140751SwpaulNdisMSetPeriodicTimer(timer, msecs) 1216123474Swpaul ndis_miniport_timer *timer; 1217123474Swpaul uint32_t msecs; 1218123474Swpaul{ 1219140751Swpaul KeSetTimerEx(&timer->nmt_ktimer, 1220127248Swpaul ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc); 1221123474Swpaul} 1222123474Swpaul 1223127248Swpaul/* 1224127248Swpaul * Technically, this is really NdisCancelTimer(), but we also 1225127248Swpaul * (ab)use it for NdisMCancelTimer(), since in our implementation 1226127248Swpaul * we don't need the extra info in the ndis_miniport_timer 1227144174Swpaul * structure just to cancel a timer. 1228127248Swpaul */ 1229127248Swpaul 1230144888Swpaulstatic void 1231140751SwpaulNdisMCancelTimer(timer, cancelled) 1232127248Swpaul ndis_timer *timer; 1233123474Swpaul uint8_t *cancelled; 1234123474Swpaul{ 1235186507Sweongyo 1236140751Swpaul *cancelled = KeCancelTimer(&timer->nt_ktimer); 1237123474Swpaul} 1238123474Swpaul 1239144888Swpaulstatic void 1240140751SwpaulNdisMQueryAdapterResources(status, adapter, list, buflen) 1241123474Swpaul ndis_status *status; 1242123474Swpaul ndis_handle adapter; 1243123474Swpaul ndis_resource_list *list; 1244123474Swpaul uint32_t *buflen; 1245123474Swpaul{ 1246123474Swpaul ndis_miniport_block *block; 1247123474Swpaul struct ndis_softc *sc; 1248198819Srpaulo int rsclen; 1249123474Swpaul 1250123474Swpaul block = (ndis_miniport_block *)adapter; 1251141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1252124094Swpaul 1253124094Swpaul rsclen = sizeof(ndis_resource_list) + 1254123474Swpaul (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); 1255124094Swpaul if (*buflen < rsclen) { 1256124094Swpaul *buflen = rsclen; 1257124094Swpaul *status = NDIS_STATUS_INVALID_LENGTH; 1258124094Swpaul return; 1259124094Swpaul } 1260123474Swpaul 1261127887Swpaul bcopy((char *)block->nmb_rlist, (char *)list, rsclen); 1262123474Swpaul *status = NDIS_STATUS_SUCCESS; 1263123474Swpaul} 1264123474Swpaul 1265144888Swpaulstatic ndis_status 1266140751SwpaulNdisMRegisterIoPortRange(offset, adapter, port, numports) 1267123474Swpaul void **offset; 1268123474Swpaul ndis_handle adapter; 1269123474Swpaul uint32_t port; 1270123474Swpaul uint32_t numports; 1271123474Swpaul{ 1272123474Swpaul struct ndis_miniport_block *block; 1273123474Swpaul struct ndis_softc *sc; 1274123474Swpaul 1275123474Swpaul if (adapter == NULL) 1276198786Srpaulo return (NDIS_STATUS_FAILURE); 1277123474Swpaul 1278123474Swpaul block = (ndis_miniport_block *)adapter; 1279141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1280123474Swpaul 1281123474Swpaul if (sc->ndis_res_io == NULL) 1282198786Srpaulo return (NDIS_STATUS_FAILURE); 1283123474Swpaul 1284124454Swpaul /* Don't let the device map more ports than we have. */ 1285124454Swpaul if (rman_get_size(sc->ndis_res_io) < numports) 1286198786Srpaulo return (NDIS_STATUS_INVALID_LENGTH); 1287123474Swpaul 1288335472Sdim *offset = (void *)(uintptr_t)rman_get_start(sc->ndis_res_io); 1289123474Swpaul 1290198786Srpaulo return (NDIS_STATUS_SUCCESS); 1291123474Swpaul} 1292123474Swpaul 1293144888Swpaulstatic void 1294140751SwpaulNdisMDeregisterIoPortRange(adapter, port, numports, offset) 1295123474Swpaul ndis_handle adapter; 1296123474Swpaul uint32_t port; 1297123474Swpaul uint32_t numports; 1298123474Swpaul void *offset; 1299123474Swpaul{ 1300123474Swpaul} 1301123474Swpaul 1302144888Swpaulstatic void 1303140751SwpaulNdisReadNetworkAddress(status, addr, addrlen, adapter) 1304123474Swpaul ndis_status *status; 1305123474Swpaul void **addr; 1306123474Swpaul uint32_t *addrlen; 1307123474Swpaul ndis_handle adapter; 1308123474Swpaul{ 1309123474Swpaul struct ndis_softc *sc; 1310319726Sglebius struct ifnet *ifp; 1311123474Swpaul ndis_miniport_block *block; 1312123474Swpaul uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; 1313123474Swpaul 1314123474Swpaul block = (ndis_miniport_block *)adapter; 1315141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1316319726Sglebius ifp = NDISUSB_GET_IFNET(sc); 1317319726Sglebius if (ifp == NULL) { 1318179009Sweongyo *status = NDIS_STATUS_FAILURE; 1319179009Sweongyo return; 1320179009Sweongyo } 1321123474Swpaul 1322319726Sglebius if (ifp->if_addr == NULL || 1323152423Sru bcmp(IF_LLADDR(sc->ifp), empty, ETHER_ADDR_LEN) == 0) 1324123474Swpaul *status = NDIS_STATUS_FAILURE; 1325123474Swpaul else { 1326152315Sru *addr = IF_LLADDR(sc->ifp); 1327123474Swpaul *addrlen = ETHER_ADDR_LEN; 1328123474Swpaul *status = NDIS_STATUS_SUCCESS; 1329123474Swpaul } 1330123474Swpaul} 1331123474Swpaul 1332144888Swpaulstatic ndis_status 1333140751SwpaulNdisQueryMapRegisterCount(bustype, cnt) 1334123848Swpaul uint32_t bustype; 1335123848Swpaul uint32_t *cnt; 1336123848Swpaul{ 1337124097Swpaul *cnt = 8192; 1338198786Srpaulo return (NDIS_STATUS_SUCCESS); 1339123848Swpaul} 1340123848Swpaul 1341144888Swpaulstatic ndis_status 1342189004SrdivackyNdisMAllocateMapRegisters(ndis_handle adapter, uint32_t dmachannel, 1343189004Srdivacky uint8_t dmasize, uint32_t physmapneeded, uint32_t maxmap) 1344123474Swpaul{ 1345123474Swpaul struct ndis_softc *sc; 1346123474Swpaul ndis_miniport_block *block; 1347123474Swpaul int error, i, nseg = NDIS_MAXSEG; 1348123474Swpaul 1349123474Swpaul block = (ndis_miniport_block *)adapter; 1350141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1351123474Swpaul 1352123474Swpaul sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, 1353123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1354123474Swpaul 1355123474Swpaul if (sc->ndis_mmaps == NULL) 1356198786Srpaulo return (NDIS_STATUS_RESOURCES); 1357123474Swpaul 1358123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1359123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1360123474Swpaul NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, 1361123474Swpaul NULL, NULL, &sc->ndis_mtag); 1362123474Swpaul 1363123474Swpaul if (error) { 1364123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1365198786Srpaulo return (NDIS_STATUS_RESOURCES); 1366123474Swpaul } 1367123474Swpaul 1368123474Swpaul for (i = 0; i < physmapneeded; i++) 1369123474Swpaul bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); 1370123474Swpaul 1371123474Swpaul sc->ndis_mmapcnt = physmapneeded; 1372123474Swpaul 1373198786Srpaulo return (NDIS_STATUS_SUCCESS); 1374123474Swpaul} 1375123474Swpaul 1376144888Swpaulstatic void 1377140751SwpaulNdisMFreeMapRegisters(adapter) 1378123474Swpaul ndis_handle adapter; 1379123474Swpaul{ 1380123474Swpaul struct ndis_softc *sc; 1381123474Swpaul ndis_miniport_block *block; 1382123474Swpaul int i; 1383123474Swpaul 1384123474Swpaul block = (ndis_miniport_block *)adapter; 1385141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1386123474Swpaul 1387123474Swpaul for (i = 0; i < sc->ndis_mmapcnt; i++) 1388123474Swpaul bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); 1389123474Swpaul 1390123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1391123474Swpaul 1392123474Swpaul bus_dma_tag_destroy(sc->ndis_mtag); 1393123474Swpaul} 1394123474Swpaul 1395123474Swpaulstatic void 1396123474Swpaulndis_mapshared_cb(arg, segs, nseg, error) 1397123474Swpaul void *arg; 1398123474Swpaul bus_dma_segment_t *segs; 1399123474Swpaul int nseg; 1400123474Swpaul int error; 1401123474Swpaul{ 1402123474Swpaul ndis_physaddr *p; 1403123474Swpaul 1404123474Swpaul if (error || nseg > 1) 1405123474Swpaul return; 1406123474Swpaul 1407123474Swpaul p = arg; 1408123474Swpaul 1409123474Swpaul p->np_quad = segs[0].ds_addr; 1410123474Swpaul} 1411123474Swpaul 1412123474Swpaul/* 1413123474Swpaul * This maps to bus_dmamem_alloc(). 1414123474Swpaul */ 1415145895Swpaul 1416144888Swpaulstatic void 1417189004SrdivackyNdisMAllocateSharedMemory(ndis_handle adapter, uint32_t len, uint8_t cached, 1418189004Srdivacky void **vaddr, ndis_physaddr *paddr) 1419123474Swpaul{ 1420123474Swpaul ndis_miniport_block *block; 1421123474Swpaul struct ndis_softc *sc; 1422123474Swpaul struct ndis_shmem *sh; 1423123474Swpaul int error; 1424123474Swpaul 1425123474Swpaul if (adapter == NULL) 1426123474Swpaul return; 1427123474Swpaul 1428123474Swpaul block = (ndis_miniport_block *)adapter; 1429141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1430123474Swpaul 1431123474Swpaul sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); 1432123474Swpaul if (sh == NULL) 1433123474Swpaul return; 1434123474Swpaul 1435151207Swpaul InitializeListHead(&sh->ndis_list); 1436151207Swpaul 1437131750Swpaul /* 1438131750Swpaul * When performing shared memory allocations, create a tag 1439131750Swpaul * with a lowaddr limit that restricts physical memory mappings 1440131750Swpaul * so that they all fall within the first 1GB of memory. 1441131750Swpaul * At least one device/driver combination (Linksys Instant 1442131750Swpaul * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have 1443131750Swpaul * problems with performing DMA operations with physical 1444141963Swpaul * addresses that lie above the 1GB mark. I don't know if this 1445141963Swpaul * is a hardware limitation or if the addresses are being 1446141963Swpaul * truncated within the driver, but this seems to be the only 1447141963Swpaul * way to make these cards work reliably in systems with more 1448141963Swpaul * than 1GB of physical memory. 1449131750Swpaul */ 1450131750Swpaul 1451123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, 64, 1452131750Swpaul 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL, 1453123474Swpaul NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, 1454123474Swpaul &sh->ndis_stag); 1455123474Swpaul 1456123474Swpaul if (error) { 1457123474Swpaul free(sh, M_DEVBUF); 1458123474Swpaul return; 1459123474Swpaul } 1460123474Swpaul 1461123474Swpaul error = bus_dmamem_alloc(sh->ndis_stag, vaddr, 1462123474Swpaul BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); 1463123474Swpaul 1464123474Swpaul if (error) { 1465123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1466123474Swpaul free(sh, M_DEVBUF); 1467123474Swpaul return; 1468123474Swpaul } 1469123474Swpaul 1470123474Swpaul error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, 1471123474Swpaul len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); 1472123474Swpaul 1473123474Swpaul if (error) { 1474123474Swpaul bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); 1475123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1476123474Swpaul free(sh, M_DEVBUF); 1477123474Swpaul return; 1478123474Swpaul } 1479123474Swpaul 1480145895Swpaul /* 1481145895Swpaul * Save the physical address along with the source address. 1482145895Swpaul * The AirGo MIMO driver will call NdisMFreeSharedMemory() 1483145895Swpaul * with a bogus virtual address sometimes, but with a valid 1484145895Swpaul * physical address. To keep this from causing trouble, we 1485145895Swpaul * use the physical address to as a sanity check in case 1486145895Swpaul * searching based on the virtual address fails. 1487145895Swpaul */ 1488145895Swpaul 1489151207Swpaul NDIS_LOCK(sc); 1490145895Swpaul sh->ndis_paddr.np_quad = paddr->np_quad; 1491123474Swpaul sh->ndis_saddr = *vaddr; 1492151207Swpaul InsertHeadList((&sc->ndis_shlist), (&sh->ndis_list)); 1493151207Swpaul NDIS_UNLOCK(sc); 1494123474Swpaul} 1495123474Swpaul 1496125413Swpaulstruct ndis_allocwork { 1497125413Swpaul uint32_t na_len; 1498125413Swpaul uint8_t na_cached; 1499125413Swpaul void *na_ctx; 1500145895Swpaul io_workitem *na_iw; 1501125413Swpaul}; 1502125413Swpaul 1503125413Swpaulstatic void 1504145895Swpaulndis_asyncmem_complete(dobj, arg) 1505145895Swpaul device_object *dobj; 1506125413Swpaul void *arg; 1507123474Swpaul{ 1508123474Swpaul ndis_miniport_block *block; 1509123474Swpaul struct ndis_softc *sc; 1510125413Swpaul struct ndis_allocwork *w; 1511123474Swpaul void *vaddr; 1512123474Swpaul ndis_physaddr paddr; 1513144888Swpaul ndis_allocdone_handler donefunc; 1514123474Swpaul 1515125413Swpaul w = arg; 1516145895Swpaul block = (ndis_miniport_block *)dobj->do_devext; 1517141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1518123474Swpaul 1519125413Swpaul vaddr = NULL; 1520125413Swpaul paddr.np_quad = 0; 1521125413Swpaul 1522141524Swpaul donefunc = sc->ndis_chars->nmc_allocate_complete_func; 1523145895Swpaul NdisMAllocateSharedMemory(block, w->na_len, 1524125413Swpaul w->na_cached, &vaddr, &paddr); 1525145895Swpaul MSCALL5(donefunc, block, vaddr, &paddr, w->na_len, w->na_ctx); 1526123474Swpaul 1527145895Swpaul IoFreeWorkItem(w->na_iw); 1528145895Swpaul free(w, M_DEVBUF); 1529123474Swpaul} 1530123474Swpaul 1531144888Swpaulstatic ndis_status 1532189004SrdivackyNdisMAllocateSharedMemoryAsync(ndis_handle adapter, uint32_t len, 1533189004Srdivacky uint8_t cached, void *ctx) 1534125413Swpaul{ 1535145895Swpaul ndis_miniport_block *block; 1536125413Swpaul struct ndis_allocwork *w; 1537145895Swpaul io_workitem *iw; 1538145895Swpaul io_workitem_func ifw; 1539125413Swpaul 1540125413Swpaul if (adapter == NULL) 1541198786Srpaulo return (NDIS_STATUS_FAILURE); 1542125413Swpaul 1543145895Swpaul block = adapter; 1544145895Swpaul 1545145895Swpaul iw = IoAllocateWorkItem(block->nmb_deviceobj); 1546145895Swpaul if (iw == NULL) 1547198786Srpaulo return (NDIS_STATUS_FAILURE); 1548145895Swpaul 1549125413Swpaul w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT); 1550125413Swpaul 1551125413Swpaul if (w == NULL) 1552198786Srpaulo return (NDIS_STATUS_FAILURE); 1553125413Swpaul 1554125413Swpaul w->na_cached = cached; 1555125413Swpaul w->na_len = len; 1556125413Swpaul w->na_ctx = ctx; 1557146273Swpaul w->na_iw = iw; 1558125413Swpaul 1559145895Swpaul ifw = (io_workitem_func)ndis_findwrap((funcptr)ndis_asyncmem_complete); 1560145895Swpaul IoQueueWorkItem(iw, ifw, WORKQUEUE_DELAYED, w); 1561125413Swpaul 1562198786Srpaulo return (NDIS_STATUS_PENDING); 1563125413Swpaul} 1564125413Swpaul 1565144888Swpaulstatic void 1566189004SrdivackyNdisMFreeSharedMemory(ndis_handle adapter, uint32_t len, uint8_t cached, 1567189004Srdivacky void *vaddr, ndis_physaddr paddr) 1568123474Swpaul{ 1569123474Swpaul ndis_miniport_block *block; 1570123474Swpaul struct ndis_softc *sc; 1571151207Swpaul struct ndis_shmem *sh = NULL; 1572151207Swpaul list_entry *l; 1573123474Swpaul 1574123474Swpaul if (vaddr == NULL || adapter == NULL) 1575123474Swpaul return; 1576123474Swpaul 1577123474Swpaul block = (ndis_miniport_block *)adapter; 1578141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1579123474Swpaul 1580144254Swpaul /* Sanity check: is list empty? */ 1581144254Swpaul 1582151207Swpaul if (IsListEmpty(&sc->ndis_shlist)) 1583144254Swpaul return; 1584144254Swpaul 1585151207Swpaul NDIS_LOCK(sc); 1586151207Swpaul l = sc->ndis_shlist.nle_flink; 1587151207Swpaul while (l != &sc->ndis_shlist) { 1588151207Swpaul sh = CONTAINING_RECORD(l, struct ndis_shmem, ndis_list); 1589123474Swpaul if (sh->ndis_saddr == vaddr) 1590123474Swpaul break; 1591145895Swpaul /* 1592189488Sweongyo * Check the physaddr too, just in case the driver lied 1593145895Swpaul * about the virtual address. 1594145895Swpaul */ 1595145895Swpaul if (sh->ndis_paddr.np_quad == paddr.np_quad) 1596145895Swpaul break; 1597151207Swpaul l = l->nle_flink; 1598123474Swpaul } 1599123474Swpaul 1600145895Swpaul if (sh == NULL) { 1601151207Swpaul NDIS_UNLOCK(sc); 1602145895Swpaul printf("NDIS: buggy driver tried to free " 1603145906Swpaul "invalid shared memory: vaddr: %p paddr: 0x%jx\n", 1604145935Swpaul vaddr, (uintmax_t)paddr.np_quad); 1605145895Swpaul return; 1606145895Swpaul } 1607145895Swpaul 1608151207Swpaul RemoveEntryList(&sh->ndis_list); 1609151207Swpaul 1610151207Swpaul NDIS_UNLOCK(sc); 1611151207Swpaul 1612123474Swpaul bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); 1613145895Swpaul bus_dmamem_free(sh->ndis_stag, sh->ndis_saddr, sh->ndis_smap); 1614123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1615123474Swpaul 1616123474Swpaul free(sh, M_DEVBUF); 1617123474Swpaul} 1618123474Swpaul 1619144888Swpaulstatic ndis_status 1620140751SwpaulNdisMMapIoSpace(vaddr, adapter, paddr, len) 1621123474Swpaul void **vaddr; 1622123474Swpaul ndis_handle adapter; 1623123474Swpaul ndis_physaddr paddr; 1624123474Swpaul uint32_t len; 1625123474Swpaul{ 1626123474Swpaul if (adapter == NULL) 1627198786Srpaulo return (NDIS_STATUS_FAILURE); 1628123474Swpaul 1629151691Swpaul *vaddr = MmMapIoSpace(paddr.np_quad, len, 0); 1630123474Swpaul 1631151691Swpaul if (*vaddr == NULL) 1632198786Srpaulo return (NDIS_STATUS_FAILURE); 1633123474Swpaul 1634198786Srpaulo return (NDIS_STATUS_SUCCESS); 1635123474Swpaul} 1636123474Swpaul 1637144888Swpaulstatic void 1638140751SwpaulNdisMUnmapIoSpace(adapter, vaddr, len) 1639123474Swpaul ndis_handle adapter; 1640123474Swpaul void *vaddr; 1641123474Swpaul uint32_t len; 1642123474Swpaul{ 1643151691Swpaul MmUnmapIoSpace(vaddr, len); 1644123474Swpaul} 1645123474Swpaul 1646144888Swpaulstatic uint32_t 1647140751SwpaulNdisGetCacheFillSize(void) 1648123474Swpaul{ 1649198786Srpaulo return (128); 1650123474Swpaul} 1651123474Swpaul 1652216242Sbschmidtstatic void * 1653216242SbschmidtNdisGetRoutineAddress(ustr) 1654216242Sbschmidt unicode_string *ustr; 1655216242Sbschmidt{ 1656216242Sbschmidt ansi_string astr; 1657216242Sbschmidt 1658216242Sbschmidt if (RtlUnicodeStringToAnsiString(&astr, ustr, TRUE)) 1659216242Sbschmidt return (NULL); 1660216242Sbschmidt return (ndis_get_routine_address(ndis_functbl, astr.as_buf)); 1661216242Sbschmidt} 1662216242Sbschmidt 1663144888Swpaulstatic uint32_t 1664140751SwpaulNdisMGetDmaAlignment(handle) 1665123474Swpaul ndis_handle handle; 1666123474Swpaul{ 1667198786Srpaulo return (16); 1668123474Swpaul} 1669123474Swpaul 1670123474Swpaul/* 1671123474Swpaul * NDIS has two methods for dealing with NICs that support DMA. 1672123474Swpaul * One is to just pass packets to the driver and let it call 1673123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet 1674123474Swpaul * all by itself, and the other is to let the NDIS library handle the 1675123474Swpaul * buffer mapping internally, and hand the driver an already populated 1676123474Swpaul * scatter/gather fragment list. If the driver calls 1677123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter 1678123474Swpaul * method. 1679123474Swpaul */ 1680123474Swpaul 1681144888Swpaulstatic ndis_status 1682189004SrdivackyNdisMInitializeScatterGatherDma(ndis_handle adapter, uint8_t is64, 1683189004Srdivacky uint32_t maxphysmap) 1684123474Swpaul{ 1685123474Swpaul struct ndis_softc *sc; 1686123474Swpaul ndis_miniport_block *block; 1687123474Swpaul int error; 1688123474Swpaul 1689123474Swpaul if (adapter == NULL) 1690198786Srpaulo return (NDIS_STATUS_FAILURE); 1691123474Swpaul block = (ndis_miniport_block *)adapter; 1692141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1693123474Swpaul 1694123474Swpaul /* Don't do this twice. */ 1695123474Swpaul if (sc->ndis_sc == 1) 1696198786Srpaulo return (NDIS_STATUS_SUCCESS); 1697123474Swpaul 1698123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1699123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1700123474Swpaul MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, 1701123474Swpaul NULL, NULL, &sc->ndis_ttag); 1702123474Swpaul 1703123474Swpaul sc->ndis_sc = 1; 1704123474Swpaul 1705198786Srpaulo return (NDIS_STATUS_SUCCESS); 1706123474Swpaul} 1707123474Swpaul 1708144888Swpaulvoid 1709140751SwpaulNdisAllocatePacketPool(status, pool, descnum, protrsvdlen) 1710123474Swpaul ndis_status *status; 1711123474Swpaul ndis_handle *pool; 1712123474Swpaul uint32_t descnum; 1713123474Swpaul uint32_t protrsvdlen; 1714123474Swpaul{ 1715151451Swpaul ndis_packet_pool *p; 1716151451Swpaul ndis_packet *packets; 1717123474Swpaul int i; 1718123474Swpaul 1719151451Swpaul p = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_packet_pool), 0); 1720151451Swpaul if (p == NULL) { 1721123474Swpaul *status = NDIS_STATUS_RESOURCES; 1722123474Swpaul return; 1723123474Swpaul } 1724123474Swpaul 1725151451Swpaul p->np_cnt = descnum + NDIS_POOL_EXTRA; 1726151451Swpaul p->np_protrsvd = protrsvdlen; 1727151451Swpaul p->np_len = sizeof(ndis_packet) + protrsvdlen; 1728151451Swpaul 1729151451Swpaul packets = ExAllocatePoolWithTag(NonPagedPool, p->np_cnt * 1730151451Swpaul p->np_len, 0); 1731151451Swpaul 1732151451Swpaul 1733151451Swpaul if (packets == NULL) { 1734151451Swpaul ExFreePool(p); 1735151451Swpaul *status = NDIS_STATUS_RESOURCES; 1736151451Swpaul return; 1737123474Swpaul } 1738123474Swpaul 1739151451Swpaul p->np_pktmem = packets; 1740151451Swpaul 1741151451Swpaul for (i = 0; i < p->np_cnt; i++) 1742151451Swpaul InterlockedPushEntrySList(&p->np_head, 1743151451Swpaul (struct slist_entry *)&packets[i]); 1744151451Swpaul 1745151451Swpaul#ifdef NDIS_DEBUG_PACKETS 1746151451Swpaul p->np_dead = 0; 1747151451Swpaul KeInitializeSpinLock(&p->np_lock); 1748189488Sweongyo KeInitializeEvent(&p->np_event, EVENT_TYPE_NOTIFY, TRUE); 1749151451Swpaul#endif 1750151451Swpaul 1751151451Swpaul *pool = p; 1752123474Swpaul *status = NDIS_STATUS_SUCCESS; 1753123474Swpaul} 1754123474Swpaul 1755144888Swpaulvoid 1756140751SwpaulNdisAllocatePacketPoolEx(status, pool, descnum, oflowdescnum, protrsvdlen) 1757123474Swpaul ndis_status *status; 1758123474Swpaul ndis_handle *pool; 1759123474Swpaul uint32_t descnum; 1760123474Swpaul uint32_t oflowdescnum; 1761123474Swpaul uint32_t protrsvdlen; 1762123474Swpaul{ 1763198786Srpaulo return (NdisAllocatePacketPool(status, pool, 1764123474Swpaul descnum + oflowdescnum, protrsvdlen)); 1765123474Swpaul} 1766123474Swpaul 1767144888Swpauluint32_t 1768140751SwpaulNdisPacketPoolUsage(pool) 1769123474Swpaul ndis_handle pool; 1770123474Swpaul{ 1771151451Swpaul ndis_packet_pool *p; 1772123474Swpaul 1773151451Swpaul p = (ndis_packet_pool *)pool; 1774198786Srpaulo return (p->np_cnt - ExQueryDepthSList(&p->np_head)); 1775123474Swpaul} 1776123474Swpaul 1777144888Swpaulvoid 1778140751SwpaulNdisFreePacketPool(pool) 1779123474Swpaul ndis_handle pool; 1780123474Swpaul{ 1781151451Swpaul ndis_packet_pool *p; 1782151451Swpaul int usage; 1783189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1784143086Swpaul uint8_t irql; 1785151451Swpaul#endif 1786126568Swpaul 1787151451Swpaul p = (ndis_packet_pool *)pool; 1788126568Swpaul 1789189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1790151451Swpaul KeAcquireSpinLock(&p->np_lock, &irql); 1791151451Swpaul#endif 1792126568Swpaul 1793151451Swpaul usage = NdisPacketPoolUsage(pool); 1794126568Swpaul 1795189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1796151451Swpaul if (usage) { 1797151451Swpaul p->np_dead = 1; 1798151451Swpaul KeResetEvent(&p->np_event); 1799151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1800151451Swpaul KeWaitForSingleObject(&p->np_event, 0, 0, FALSE, NULL); 1801151451Swpaul } else 1802151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1803151451Swpaul#endif 1804126568Swpaul 1805151451Swpaul ExFreePool(p->np_pktmem); 1806151451Swpaul ExFreePool(p); 1807123474Swpaul} 1808123474Swpaul 1809144888Swpaulvoid 1810140751SwpaulNdisAllocatePacket(status, packet, pool) 1811123474Swpaul ndis_status *status; 1812123474Swpaul ndis_packet **packet; 1813123474Swpaul ndis_handle pool; 1814123474Swpaul{ 1815151451Swpaul ndis_packet_pool *p; 1816151451Swpaul ndis_packet *pkt; 1817189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1818143086Swpaul uint8_t irql; 1819151451Swpaul#endif 1820123474Swpaul 1821151451Swpaul p = (ndis_packet_pool *)pool; 1822123474Swpaul 1823189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1824151451Swpaul KeAcquireSpinLock(&p->np_lock, &irql); 1825151451Swpaul if (p->np_dead) { 1826151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1827151451Swpaul printf("NDIS: tried to allocate packet from dead pool %p\n", 1828151451Swpaul pool); 1829151451Swpaul *status = NDIS_STATUS_RESOURCES; 1830123474Swpaul return; 1831123474Swpaul } 1832151451Swpaul#endif 1833123474Swpaul 1834151451Swpaul pkt = (ndis_packet *)InterlockedPopEntrySList(&p->np_head); 1835126568Swpaul 1836189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1837151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1838151451Swpaul#endif 1839126568Swpaul 1840123474Swpaul if (pkt == NULL) { 1841123474Swpaul *status = NDIS_STATUS_RESOURCES; 1842123474Swpaul return; 1843123474Swpaul } 1844123474Swpaul 1845123474Swpaul 1846151451Swpaul bzero((char *)pkt, sizeof(ndis_packet)); 1847151451Swpaul 1848123474Swpaul /* Save pointer to the pool. */ 1849151451Swpaul pkt->np_private.npp_pool = pool; 1850123474Swpaul 1851123474Swpaul /* Set the oob offset pointer. Lots of things expect this. */ 1852144888Swpaul pkt->np_private.npp_packetooboffset = offsetof(ndis_packet, np_oob); 1853123474Swpaul 1854124278Swpaul /* 1855124278Swpaul * We must initialize the packet flags correctly in order 1856124278Swpaul * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and 1857141963Swpaul * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work 1858189488Sweongyo * correctly. 1859124278Swpaul */ 1860124278Swpaul pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS; 1861144239Swpaul pkt->np_private.npp_validcounts = FALSE; 1862124278Swpaul 1863123474Swpaul *packet = pkt; 1864123474Swpaul 1865123474Swpaul *status = NDIS_STATUS_SUCCESS; 1866123474Swpaul} 1867123474Swpaul 1868144888Swpaulvoid 1869140751SwpaulNdisFreePacket(packet) 1870123474Swpaul ndis_packet *packet; 1871123474Swpaul{ 1872151451Swpaul ndis_packet_pool *p; 1873189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1874143086Swpaul uint8_t irql; 1875151451Swpaul#endif 1876123474Swpaul 1877151451Swpaul p = (ndis_packet_pool *)packet->np_private.npp_pool; 1878123474Swpaul 1879189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1880151451Swpaul KeAcquireSpinLock(&p->np_lock, &irql); 1881151451Swpaul#endif 1882143086Swpaul 1883151451Swpaul InterlockedPushEntrySList(&p->np_head, (slist_entry *)packet); 1884151451Swpaul 1885189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1886151451Swpaul if (p->np_dead) { 1887151451Swpaul if (ExQueryDepthSList(&p->np_head) == p->np_cnt) 1888151451Swpaul KeSetEvent(&p->np_event, IO_NO_INCREMENT, FALSE); 1889143086Swpaul } 1890151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1891151451Swpaul#endif 1892123474Swpaul} 1893123474Swpaul 1894144888Swpaulstatic void 1895140751SwpaulNdisUnchainBufferAtFront(packet, buf) 1896123474Swpaul ndis_packet *packet; 1897123474Swpaul ndis_buffer **buf; 1898123474Swpaul{ 1899123474Swpaul ndis_packet_private *priv; 1900123474Swpaul 1901123474Swpaul if (packet == NULL || buf == NULL) 1902123474Swpaul return; 1903123474Swpaul 1904123474Swpaul priv = &packet->np_private; 1905123474Swpaul 1906123474Swpaul priv->npp_validcounts = FALSE; 1907123474Swpaul 1908123474Swpaul if (priv->npp_head == priv->npp_tail) { 1909123474Swpaul *buf = priv->npp_head; 1910123474Swpaul priv->npp_head = priv->npp_tail = NULL; 1911123474Swpaul } else { 1912123474Swpaul *buf = priv->npp_head; 1913140751Swpaul priv->npp_head = (*buf)->mdl_next; 1914123474Swpaul } 1915123474Swpaul} 1916123474Swpaul 1917144888Swpaulstatic void 1918140751SwpaulNdisUnchainBufferAtBack(packet, buf) 1919123721Swpaul ndis_packet *packet; 1920123721Swpaul ndis_buffer **buf; 1921123721Swpaul{ 1922123721Swpaul ndis_packet_private *priv; 1923123721Swpaul ndis_buffer *tmp; 1924123721Swpaul 1925123721Swpaul if (packet == NULL || buf == NULL) 1926123721Swpaul return; 1927123721Swpaul 1928123721Swpaul priv = &packet->np_private; 1929123721Swpaul 1930123721Swpaul priv->npp_validcounts = FALSE; 1931123721Swpaul 1932123721Swpaul if (priv->npp_head == priv->npp_tail) { 1933123721Swpaul *buf = priv->npp_head; 1934123721Swpaul priv->npp_head = priv->npp_tail = NULL; 1935123721Swpaul } else { 1936123721Swpaul *buf = priv->npp_tail; 1937123721Swpaul tmp = priv->npp_head; 1938140751Swpaul while (tmp->mdl_next != priv->npp_tail) 1939140751Swpaul tmp = tmp->mdl_next; 1940123721Swpaul priv->npp_tail = tmp; 1941140751Swpaul tmp->mdl_next = NULL; 1942123721Swpaul } 1943123721Swpaul} 1944123721Swpaul 1945123474Swpaul/* 1946141963Swpaul * The NDIS "buffer" is really an MDL (memory descriptor list) 1947141963Swpaul * which is used to describe a buffer in a way that allows it 1948141963Swpaul * to mapped into different contexts. We have to be careful how 1949141963Swpaul * we handle them: in some versions of Windows, the NdisFreeBuffer() 1950141963Swpaul * routine is an actual function in the NDIS API, but in others 1951141963Swpaul * it's just a macro wrapper around IoFreeMdl(). There's really 1952141963Swpaul * no way to use the 'descnum' parameter to count how many 1953141963Swpaul * "buffers" are allocated since in order to use IoFreeMdl() to 1954141963Swpaul * dispose of a buffer, we have to use IoAllocateMdl() to allocate 1955141963Swpaul * them, and IoAllocateMdl() just grabs them out of the heap. 1956123474Swpaul */ 1957123474Swpaul 1958144888Swpaulstatic void 1959140751SwpaulNdisAllocateBufferPool(status, pool, descnum) 1960123474Swpaul ndis_status *status; 1961123474Swpaul ndis_handle *pool; 1962123474Swpaul uint32_t descnum; 1963123474Swpaul{ 1964151207Swpaul 1965141963Swpaul /* 1966141963Swpaul * The only thing we can really do here is verify that descnum 1967141963Swpaul * is a reasonable value, but I really don't know what to check 1968141963Swpaul * it against. 1969141963Swpaul */ 1970123474Swpaul 1971141963Swpaul *pool = NonPagedPool; 1972123474Swpaul *status = NDIS_STATUS_SUCCESS; 1973123474Swpaul} 1974123474Swpaul 1975144888Swpaulstatic void 1976140751SwpaulNdisFreeBufferPool(pool) 1977123474Swpaul ndis_handle pool; 1978123474Swpaul{ 1979123474Swpaul} 1980123474Swpaul 1981144888Swpaulstatic void 1982140751SwpaulNdisAllocateBuffer(status, buffer, pool, vaddr, len) 1983123474Swpaul ndis_status *status; 1984123474Swpaul ndis_buffer **buffer; 1985123474Swpaul ndis_handle pool; 1986123474Swpaul void *vaddr; 1987123474Swpaul uint32_t len; 1988123474Swpaul{ 1989141963Swpaul ndis_buffer *buf; 1990123474Swpaul 1991141963Swpaul buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL); 1992123474Swpaul if (buf == NULL) { 1993123474Swpaul *status = NDIS_STATUS_RESOURCES; 1994123474Swpaul return; 1995123474Swpaul } 1996123474Swpaul 1997151207Swpaul MmBuildMdlForNonPagedPool(buf); 1998151207Swpaul 1999123474Swpaul *buffer = buf; 2000141963Swpaul *status = NDIS_STATUS_SUCCESS; 2001123474Swpaul} 2002123474Swpaul 2003144888Swpaulstatic void 2004140751SwpaulNdisFreeBuffer(buf) 2005123474Swpaul ndis_buffer *buf; 2006123474Swpaul{ 2007141963Swpaul IoFreeMdl(buf); 2008123474Swpaul} 2009123474Swpaul 2010124100Swpaul/* Aw c'mon. */ 2011124100Swpaul 2012144888Swpaulstatic uint32_t 2013140751SwpaulNdisBufferLength(buf) 2014124100Swpaul ndis_buffer *buf; 2015124100Swpaul{ 2016198786Srpaulo return (MmGetMdlByteCount(buf)); 2017124100Swpaul} 2018124100Swpaul 2019123723Swpaul/* 2020123723Swpaul * Get the virtual address and length of a buffer. 2021123723Swpaul * Note: the vaddr argument is optional. 2022123723Swpaul */ 2023123474Swpaul 2024144888Swpaulstatic void 2025140751SwpaulNdisQueryBuffer(buf, vaddr, len) 2026123474Swpaul ndis_buffer *buf; 2027123474Swpaul void **vaddr; 2028123474Swpaul uint32_t *len; 2029123474Swpaul{ 2030123723Swpaul if (vaddr != NULL) 2031140751Swpaul *vaddr = MmGetMdlVirtualAddress(buf); 2032140751Swpaul *len = MmGetMdlByteCount(buf); 2033123474Swpaul} 2034123474Swpaul 2035123474Swpaul/* Same as above -- we don't care about the priority. */ 2036123474Swpaul 2037144888Swpaulstatic void 2038140751SwpaulNdisQueryBufferSafe(buf, vaddr, len, prio) 2039123474Swpaul ndis_buffer *buf; 2040123474Swpaul void **vaddr; 2041123474Swpaul uint32_t *len; 2042123474Swpaul uint32_t prio; 2043123474Swpaul{ 2044123723Swpaul if (vaddr != NULL) 2045140751Swpaul *vaddr = MmGetMdlVirtualAddress(buf); 2046140751Swpaul *len = MmGetMdlByteCount(buf); 2047123474Swpaul} 2048123474Swpaul 2049125069Swpaul/* Damnit Microsoft!! How many ways can you do the same thing?! */ 2050125069Swpaul 2051144888Swpaulstatic void * 2052140751SwpaulNdisBufferVirtualAddress(buf) 2053125069Swpaul ndis_buffer *buf; 2054125069Swpaul{ 2055198786Srpaulo return (MmGetMdlVirtualAddress(buf)); 2056125069Swpaul} 2057125069Swpaul 2058144888Swpaulstatic void * 2059140751SwpaulNdisBufferVirtualAddressSafe(buf, prio) 2060125069Swpaul ndis_buffer *buf; 2061125069Swpaul uint32_t prio; 2062125069Swpaul{ 2063198786Srpaulo return (MmGetMdlVirtualAddress(buf)); 2064125069Swpaul} 2065125069Swpaul 2066144888Swpaulstatic void 2067140751SwpaulNdisAdjustBufferLength(buf, len) 2068123474Swpaul ndis_buffer *buf; 2069123474Swpaul int len; 2070123474Swpaul{ 2071140751Swpaul MmGetMdlByteCount(buf) = len; 2072123474Swpaul} 2073123474Swpaul 2074144888Swpaulstatic uint32_t 2075140751SwpaulNdisInterlockedIncrement(addend) 2076123474Swpaul uint32_t *addend; 2077123474Swpaul{ 2078124203Swpaul atomic_add_long((u_long *)addend, 1); 2079198786Srpaulo return (*addend); 2080123474Swpaul} 2081123474Swpaul 2082144888Swpaulstatic uint32_t 2083140751SwpaulNdisInterlockedDecrement(addend) 2084123474Swpaul uint32_t *addend; 2085123474Swpaul{ 2086124203Swpaul atomic_subtract_long((u_long *)addend, 1); 2087198786Srpaulo return (*addend); 2088123474Swpaul} 2089123474Swpaul 2090215779Sbschmidtstatic uint32_t 2091215779SbschmidtNdisGetVersion(void) 2092215779Sbschmidt{ 2093215779Sbschmidt return (0x00050001); 2094215779Sbschmidt} 2095215779Sbschmidt 2096144888Swpaulstatic void 2097140751SwpaulNdisInitializeEvent(event) 2098123474Swpaul ndis_event *event; 2099123474Swpaul{ 2100127248Swpaul /* 2101127411Swpaul * NDIS events are always notification 2102127248Swpaul * events, and should be initialized to the 2103127248Swpaul * not signaled state. 2104127248Swpaul */ 2105140751Swpaul KeInitializeEvent(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE); 2106123474Swpaul} 2107123474Swpaul 2108144888Swpaulstatic void 2109140751SwpaulNdisSetEvent(event) 2110123474Swpaul ndis_event *event; 2111123474Swpaul{ 2112151451Swpaul KeSetEvent(&event->ne_event, IO_NO_INCREMENT, FALSE); 2113123474Swpaul} 2114123474Swpaul 2115144888Swpaulstatic void 2116140751SwpaulNdisResetEvent(event) 2117123474Swpaul ndis_event *event; 2118123474Swpaul{ 2119140751Swpaul KeResetEvent(&event->ne_event); 2120123474Swpaul} 2121123474Swpaul 2122144888Swpaulstatic uint8_t 2123140751SwpaulNdisWaitEvent(event, msecs) 2124123474Swpaul ndis_event *event; 2125123474Swpaul uint32_t msecs; 2126123474Swpaul{ 2127127248Swpaul int64_t duetime; 2128127248Swpaul uint32_t rval; 2129123474Swpaul 2130127248Swpaul duetime = ((int64_t)msecs * -10000); 2131151451Swpaul rval = KeWaitForSingleObject(event, 2132145895Swpaul 0, 0, TRUE, msecs ? & duetime : NULL); 2133123474Swpaul 2134127248Swpaul if (rval == STATUS_TIMEOUT) 2135198786Srpaulo return (FALSE); 2136125551Swpaul 2137198786Srpaulo return (TRUE); 2138123474Swpaul} 2139123474Swpaul 2140144888Swpaulstatic ndis_status 2141140751SwpaulNdisUnicodeStringToAnsiString(dstr, sstr) 2142151207Swpaul ansi_string *dstr; 2143151207Swpaul unicode_string *sstr; 2144123474Swpaul{ 2145151207Swpaul uint32_t rval; 2146151207Swpaul 2147151207Swpaul rval = RtlUnicodeStringToAnsiString(dstr, sstr, FALSE); 2148151207Swpaul 2149151207Swpaul if (rval == STATUS_INSUFFICIENT_RESOURCES) 2150198786Srpaulo return (NDIS_STATUS_RESOURCES); 2151151207Swpaul if (rval) 2152198786Srpaulo return (NDIS_STATUS_FAILURE); 2153151207Swpaul 2154123474Swpaul return (NDIS_STATUS_SUCCESS); 2155123474Swpaul} 2156123474Swpaul 2157144888Swpaulstatic ndis_status 2158140751SwpaulNdisAnsiStringToUnicodeString(dstr, sstr) 2159151207Swpaul unicode_string *dstr; 2160151207Swpaul ansi_string *sstr; 2161123526Swpaul{ 2162151207Swpaul uint32_t rval; 2163151207Swpaul 2164151207Swpaul rval = RtlAnsiStringToUnicodeString(dstr, sstr, FALSE); 2165151207Swpaul 2166151207Swpaul if (rval == STATUS_INSUFFICIENT_RESOURCES) 2167198786Srpaulo return (NDIS_STATUS_RESOURCES); 2168151207Swpaul if (rval) 2169198786Srpaulo return (NDIS_STATUS_FAILURE); 2170151207Swpaul 2171123526Swpaul return (NDIS_STATUS_SUCCESS); 2172123526Swpaul} 2173123526Swpaul 2174144888Swpaulstatic ndis_status 2175140751SwpaulNdisMPciAssignResources(adapter, slot, list) 2176123474Swpaul ndis_handle adapter; 2177123474Swpaul uint32_t slot; 2178123474Swpaul ndis_resource_list **list; 2179123474Swpaul{ 2180123474Swpaul ndis_miniport_block *block; 2181123474Swpaul 2182123474Swpaul if (adapter == NULL || list == NULL) 2183123474Swpaul return (NDIS_STATUS_FAILURE); 2184123474Swpaul 2185123474Swpaul block = (ndis_miniport_block *)adapter; 2186123474Swpaul *list = block->nmb_rlist; 2187123474Swpaul 2188123474Swpaul return (NDIS_STATUS_SUCCESS); 2189123474Swpaul} 2190123474Swpaul 2191152626Swpaulstatic uint8_t 2192152626Swpaulndis_intr(iobj, arg) 2193152626Swpaul kinterrupt *iobj; 2194189488Sweongyo void *arg; 2195151207Swpaul{ 2196151207Swpaul struct ndis_softc *sc; 2197152626Swpaul uint8_t is_our_intr = FALSE; 2198151207Swpaul int call_isr = 0; 2199151207Swpaul ndis_miniport_interrupt *intr; 2200151207Swpaul 2201151207Swpaul sc = arg; 2202151207Swpaul intr = sc->ndis_block->nmb_interrupt; 2203151207Swpaul 2204151207Swpaul if (intr == NULL || sc->ndis_block->nmb_miniportadapterctx == NULL) 2205198786Srpaulo return (FALSE); 2206151207Swpaul 2207151207Swpaul if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE) 2208151977Swpaul MSCALL3(intr->ni_isrfunc, &is_our_intr, &call_isr, 2209151977Swpaul sc->ndis_block->nmb_miniportadapterctx); 2210151207Swpaul else { 2211151977Swpaul MSCALL1(sc->ndis_chars->nmc_disable_interrupts_func, 2212151977Swpaul sc->ndis_block->nmb_miniportadapterctx); 2213151207Swpaul call_isr = 1; 2214151207Swpaul } 2215151207Swpaul 2216152626Swpaul if (call_isr) 2217151207Swpaul IoRequestDpc(sc->ndis_block->nmb_deviceobj, NULL, sc); 2218151207Swpaul 2219198786Srpaulo return (is_our_intr); 2220151207Swpaul} 2221151207Swpaul 2222151207Swpaulstatic void 2223151207Swpaulndis_intrhand(dpc, intr, sysarg1, sysarg2) 2224151207Swpaul kdpc *dpc; 2225151207Swpaul ndis_miniport_interrupt *intr; 2226151207Swpaul void *sysarg1; 2227151207Swpaul void *sysarg2; 2228151207Swpaul{ 2229151207Swpaul struct ndis_softc *sc; 2230151207Swpaul ndis_miniport_block *block; 2231189488Sweongyo ndis_handle adapter; 2232151207Swpaul 2233151207Swpaul block = intr->ni_block; 2234189488Sweongyo adapter = block->nmb_miniportadapterctx; 2235151207Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2236151207Swpaul 2237189488Sweongyo if (NDIS_SERIALIZED(sc->ndis_block)) 2238189488Sweongyo KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); 2239151207Swpaul 2240189488Sweongyo MSCALL1(intr->ni_dpcfunc, adapter); 2241151207Swpaul 2242189488Sweongyo /* If there's a MiniportEnableInterrupt() routine, call it. */ 2243151207Swpaul 2244151977Swpaul if (sc->ndis_chars->nmc_enable_interrupts_func != NULL) 2245151977Swpaul MSCALL1(sc->ndis_chars->nmc_enable_interrupts_func, adapter); 2246151207Swpaul 2247189488Sweongyo if (NDIS_SERIALIZED(sc->ndis_block)) 2248189488Sweongyo KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); 2249151207Swpaul 2250151207Swpaul /* 2251151207Swpaul * Set the completion event if we've drained all 2252151207Swpaul * pending interrupts. 2253151207Swpaul */ 2254151207Swpaul 2255151207Swpaul KeAcquireSpinLockAtDpcLevel(&intr->ni_dpccountlock); 2256151207Swpaul intr->ni_dpccnt--; 2257151207Swpaul if (intr->ni_dpccnt == 0) 2258151207Swpaul KeSetEvent(&intr->ni_dpcevt, IO_NO_INCREMENT, FALSE); 2259151207Swpaul KeReleaseSpinLockFromDpcLevel(&intr->ni_dpccountlock); 2260151207Swpaul} 2261151207Swpaul 2262144888Swpaulstatic ndis_status 2263189004SrdivackyNdisMRegisterInterrupt(ndis_miniport_interrupt *intr, ndis_handle adapter, 2264189004Srdivacky uint32_t ivec, uint32_t ilevel, uint8_t reqisr, uint8_t shared, 2265189004Srdivacky ndis_interrupt_mode imode) 2266123474Swpaul{ 2267124165Swpaul ndis_miniport_block *block; 2268151207Swpaul ndis_miniport_characteristics *ch; 2269151207Swpaul struct ndis_softc *sc; 2270151207Swpaul int error; 2271124165Swpaul 2272124165Swpaul block = adapter; 2273151207Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2274151207Swpaul ch = IoGetDriverObjectExtension(block->nmb_deviceobj->do_drvobj, 2275151207Swpaul (void *)1); 2276124165Swpaul 2277151207Swpaul intr->ni_rsvd = ExAllocatePoolWithTag(NonPagedPool, 2278151207Swpaul sizeof(struct mtx), 0); 2279151207Swpaul if (intr->ni_rsvd == NULL) 2280198786Srpaulo return (NDIS_STATUS_RESOURCES); 2281151207Swpaul 2282124135Swpaul intr->ni_block = adapter; 2283124165Swpaul intr->ni_isrreq = reqisr; 2284124165Swpaul intr->ni_shared = shared; 2285151207Swpaul intr->ni_dpccnt = 0; 2286151977Swpaul intr->ni_isrfunc = ch->nmc_isr_func; 2287151977Swpaul intr->ni_dpcfunc = ch->nmc_interrupt_func; 2288151207Swpaul 2289189488Sweongyo KeInitializeEvent(&intr->ni_dpcevt, EVENT_TYPE_NOTIFY, TRUE); 2290189488Sweongyo KeInitializeDpc(&intr->ni_dpc, 2291151207Swpaul ndis_findwrap((funcptr)ndis_intrhand), intr); 2292189488Sweongyo KeSetImportanceDpc(&intr->ni_dpc, KDPC_IMPORTANCE_LOW); 2293151207Swpaul 2294151207Swpaul error = IoConnectInterrupt(&intr->ni_introbj, 2295151207Swpaul ndis_findwrap((funcptr)ndis_intr), sc, NULL, 2296151207Swpaul ivec, ilevel, 0, imode, shared, 0, FALSE); 2297151207Swpaul 2298151207Swpaul if (error != STATUS_SUCCESS) 2299198786Srpaulo return (NDIS_STATUS_FAILURE); 2300151207Swpaul 2301124165Swpaul block->nmb_interrupt = intr; 2302141524Swpaul 2303198786Srpaulo return (NDIS_STATUS_SUCCESS); 2304189488Sweongyo} 2305123474Swpaul 2306144888Swpaulstatic void 2307140751SwpaulNdisMDeregisterInterrupt(intr) 2308123474Swpaul ndis_miniport_interrupt *intr; 2309123474Swpaul{ 2310151207Swpaul ndis_miniport_block *block; 2311151207Swpaul uint8_t irql; 2312151207Swpaul 2313151207Swpaul block = intr->ni_block; 2314151207Swpaul 2315151207Swpaul /* Should really be KeSynchronizeExecution() */ 2316151207Swpaul 2317151207Swpaul KeAcquireSpinLock(intr->ni_introbj->ki_lock, &irql); 2318151207Swpaul block->nmb_interrupt = NULL; 2319151207Swpaul KeReleaseSpinLock(intr->ni_introbj->ki_lock, irql); 2320151207Swpaul/* 2321151207Swpaul KeFlushQueuedDpcs(); 2322151207Swpaul*/ 2323151207Swpaul /* Disconnect our ISR */ 2324151207Swpaul 2325151207Swpaul IoDisconnectInterrupt(intr->ni_introbj); 2326151207Swpaul 2327151451Swpaul KeWaitForSingleObject(&intr->ni_dpcevt, 0, 0, FALSE, NULL); 2328151207Swpaul KeResetEvent(&intr->ni_dpcevt); 2329123474Swpaul} 2330123474Swpaul 2331144888Swpaulstatic void 2332140751SwpaulNdisMRegisterAdapterShutdownHandler(adapter, shutdownctx, shutdownfunc) 2333123474Swpaul ndis_handle adapter; 2334123474Swpaul void *shutdownctx; 2335123474Swpaul ndis_shutdown_handler shutdownfunc; 2336123474Swpaul{ 2337123474Swpaul ndis_miniport_block *block; 2338123474Swpaul ndis_miniport_characteristics *chars; 2339123474Swpaul struct ndis_softc *sc; 2340123474Swpaul 2341123474Swpaul if (adapter == NULL) 2342123474Swpaul return; 2343123474Swpaul 2344123474Swpaul block = (ndis_miniport_block *)adapter; 2345141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2346141524Swpaul chars = sc->ndis_chars; 2347123474Swpaul 2348123474Swpaul chars->nmc_shutdown_handler = shutdownfunc; 2349123474Swpaul chars->nmc_rsvd0 = shutdownctx; 2350123474Swpaul} 2351123474Swpaul 2352144888Swpaulstatic void 2353140751SwpaulNdisMDeregisterAdapterShutdownHandler(adapter) 2354123474Swpaul ndis_handle adapter; 2355123474Swpaul{ 2356123474Swpaul ndis_miniport_block *block; 2357123474Swpaul ndis_miniport_characteristics *chars; 2358123474Swpaul struct ndis_softc *sc; 2359123474Swpaul 2360123474Swpaul if (adapter == NULL) 2361123474Swpaul return; 2362123474Swpaul 2363123474Swpaul block = (ndis_miniport_block *)adapter; 2364141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2365141524Swpaul chars = sc->ndis_chars; 2366123474Swpaul 2367123474Swpaul chars->nmc_shutdown_handler = NULL; 2368123474Swpaul chars->nmc_rsvd0 = NULL; 2369123474Swpaul} 2370123474Swpaul 2371144888Swpaulstatic uint32_t 2372140751SwpaulNDIS_BUFFER_TO_SPAN_PAGES(buf) 2373123474Swpaul ndis_buffer *buf; 2374123474Swpaul{ 2375123757Swpaul if (buf == NULL) 2376198786Srpaulo return (0); 2377140751Swpaul if (MmGetMdlByteCount(buf) == 0) 2378198786Srpaulo return (1); 2379198786Srpaulo return (SPAN_PAGES(MmGetMdlVirtualAddress(buf), 2380140751Swpaul MmGetMdlByteCount(buf))); 2381123474Swpaul} 2382123474Swpaul 2383144888Swpaulstatic void 2384140751SwpaulNdisGetBufferPhysicalArraySize(buf, pages) 2385123573Swpaul ndis_buffer *buf; 2386123573Swpaul uint32_t *pages; 2387123573Swpaul{ 2388123757Swpaul if (buf == NULL) 2389123757Swpaul return; 2390123757Swpaul 2391140751Swpaul *pages = NDIS_BUFFER_TO_SPAN_PAGES(buf); 2392123573Swpaul} 2393123573Swpaul 2394144888Swpaulstatic void 2395140751SwpaulNdisQueryBufferOffset(buf, off, len) 2396123474Swpaul ndis_buffer *buf; 2397123474Swpaul uint32_t *off; 2398123474Swpaul uint32_t *len; 2399123474Swpaul{ 2400123757Swpaul if (buf == NULL) 2401123757Swpaul return; 2402123757Swpaul 2403140751Swpaul *off = MmGetMdlByteOffset(buf); 2404140751Swpaul *len = MmGetMdlByteCount(buf); 2405123474Swpaul} 2406123474Swpaul 2407151451Swpaulvoid 2408140751SwpaulNdisMSleep(usecs) 2409123474Swpaul uint32_t usecs; 2410123474Swpaul{ 2411151207Swpaul ktimer timer; 2412123474Swpaul 2413145485Swpaul /* 2414145485Swpaul * During system bootstrap, (i.e. cold == 1), we aren't 2415151207Swpaul * allowed to sleep, so we have to do a hard DELAY() 2416151207Swpaul * instead. 2417145485Swpaul */ 2418123474Swpaul 2419151207Swpaul if (cold) 2420145485Swpaul DELAY(usecs); 2421151207Swpaul else { 2422151207Swpaul KeInitializeTimer(&timer); 2423151207Swpaul KeSetTimer(&timer, ((int64_t)usecs * -10), NULL); 2424151451Swpaul KeWaitForSingleObject(&timer, 0, 0, FALSE, NULL); 2425151207Swpaul } 2426123474Swpaul} 2427123474Swpaul 2428144888Swpaulstatic uint32_t 2429140751SwpaulNdisReadPcmciaAttributeMemory(handle, offset, buf, len) 2430123474Swpaul ndis_handle handle; 2431123474Swpaul uint32_t offset; 2432123474Swpaul void *buf; 2433123474Swpaul uint32_t len; 2434123474Swpaul{ 2435123474Swpaul struct ndis_softc *sc; 2436123474Swpaul ndis_miniport_block *block; 2437123474Swpaul bus_space_handle_t bh; 2438123474Swpaul bus_space_tag_t bt; 2439123474Swpaul char *dest; 2440298731Spfg uint32_t i; 2441123474Swpaul 2442123474Swpaul if (handle == NULL) 2443198786Srpaulo return (0); 2444123474Swpaul 2445123474Swpaul block = (ndis_miniport_block *)handle; 2446141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2447123474Swpaul dest = buf; 2448123474Swpaul 2449123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 2450123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 2451123474Swpaul 2452123474Swpaul for (i = 0; i < len; i++) 2453131953Swpaul dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2); 2454123474Swpaul 2455198786Srpaulo return (i); 2456123474Swpaul} 2457123474Swpaul 2458144888Swpaulstatic uint32_t 2459140751SwpaulNdisWritePcmciaAttributeMemory(handle, offset, buf, len) 2460123474Swpaul ndis_handle handle; 2461123474Swpaul uint32_t offset; 2462123474Swpaul void *buf; 2463123474Swpaul uint32_t len; 2464123474Swpaul{ 2465123474Swpaul struct ndis_softc *sc; 2466123474Swpaul ndis_miniport_block *block; 2467123474Swpaul bus_space_handle_t bh; 2468123474Swpaul bus_space_tag_t bt; 2469123474Swpaul char *src; 2470298731Spfg uint32_t i; 2471123474Swpaul 2472123474Swpaul if (handle == NULL) 2473198786Srpaulo return (0); 2474123474Swpaul 2475123474Swpaul block = (ndis_miniport_block *)handle; 2476141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2477123474Swpaul src = buf; 2478123474Swpaul 2479123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 2480123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 2481123474Swpaul 2482123474Swpaul for (i = 0; i < len; i++) 2483131953Swpaul bus_space_write_1(bt, bh, (offset + i) * 2, src[i]); 2484123474Swpaul 2485198786Srpaulo return (i); 2486123474Swpaul} 2487123474Swpaul 2488144888Swpaulstatic list_entry * 2489140751SwpaulNdisInterlockedInsertHeadList(head, entry, lock) 2490125551Swpaul list_entry *head; 2491125551Swpaul list_entry *entry; 2492123474Swpaul ndis_spin_lock *lock; 2493123474Swpaul{ 2494125551Swpaul list_entry *flink; 2495123474Swpaul 2496140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 2497123474Swpaul flink = head->nle_flink; 2498123474Swpaul entry->nle_flink = flink; 2499123474Swpaul entry->nle_blink = head; 2500123474Swpaul flink->nle_blink = entry; 2501123474Swpaul head->nle_flink = entry; 2502140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 2503123474Swpaul 2504198786Srpaulo return (flink); 2505123474Swpaul} 2506123474Swpaul 2507144888Swpaulstatic list_entry * 2508140751SwpaulNdisInterlockedRemoveHeadList(head, lock) 2509125551Swpaul list_entry *head; 2510123474Swpaul ndis_spin_lock *lock; 2511123474Swpaul{ 2512125551Swpaul list_entry *flink; 2513125551Swpaul list_entry *entry; 2514123474Swpaul 2515140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 2516123474Swpaul entry = head->nle_flink; 2517123474Swpaul flink = entry->nle_flink; 2518123474Swpaul head->nle_flink = flink; 2519123474Swpaul flink->nle_blink = head; 2520140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 2521123474Swpaul 2522198786Srpaulo return (entry); 2523123474Swpaul} 2524123474Swpaul 2525144888Swpaulstatic list_entry * 2526140751SwpaulNdisInterlockedInsertTailList(head, entry, lock) 2527125551Swpaul list_entry *head; 2528125551Swpaul list_entry *entry; 2529123474Swpaul ndis_spin_lock *lock; 2530123474Swpaul{ 2531125551Swpaul list_entry *blink; 2532123474Swpaul 2533140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 2534123474Swpaul blink = head->nle_blink; 2535123474Swpaul entry->nle_flink = head; 2536123474Swpaul entry->nle_blink = blink; 2537123474Swpaul blink->nle_flink = entry; 2538123474Swpaul head->nle_blink = entry; 2539140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 2540123474Swpaul 2541198786Srpaulo return (blink); 2542123474Swpaul} 2543123474Swpaul 2544144888Swpaulstatic uint8_t 2545140751SwpaulNdisMSynchronizeWithInterrupt(intr, syncfunc, syncctx) 2546123474Swpaul ndis_miniport_interrupt *intr; 2547123474Swpaul void *syncfunc; 2548123474Swpaul void *syncctx; 2549123474Swpaul{ 2550198786Srpaulo return (KeSynchronizeExecution(intr->ni_introbj, syncfunc, syncctx)); 2551123474Swpaul} 2552123474Swpaul 2553144888Swpaulstatic void 2554140751SwpaulNdisGetCurrentSystemTime(tval) 2555123504Swpaul uint64_t *tval; 2556123504Swpaul{ 2557174150Sthompsa ntoskrnl_time(tval); 2558123504Swpaul} 2559123504Swpaul 2560123822Swpaul/* 2561123822Swpaul * Return the number of milliseconds since the system booted. 2562123822Swpaul */ 2563144888Swpaulstatic void 2564140751SwpaulNdisGetSystemUpTime(tval) 2565123822Swpaul uint32_t *tval; 2566123822Swpaul{ 2567144888Swpaul struct timespec ts; 2568189488Sweongyo 2569144888Swpaul nanouptime(&ts); 2570144888Swpaul *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000; 2571123822Swpaul} 2572123822Swpaul 2573144888Swpaulstatic void 2574140751SwpaulNdisInitializeString(dst, src) 2575151207Swpaul unicode_string *dst; 2576123507Swpaul char *src; 2577123507Swpaul{ 2578151207Swpaul ansi_string as; 2579151207Swpaul RtlInitAnsiString(&as, src); 2580151207Swpaul RtlAnsiStringToUnicodeString(dst, &as, TRUE); 2581123507Swpaul} 2582123507Swpaul 2583144888Swpaulstatic void 2584140751SwpaulNdisFreeString(str) 2585151207Swpaul unicode_string *str; 2586123507Swpaul{ 2587151207Swpaul RtlFreeUnicodeString(str); 2588123507Swpaul} 2589123507Swpaul 2590144888Swpaulstatic ndis_status 2591140751SwpaulNdisMRemoveMiniport(adapter) 2592123507Swpaul ndis_handle *adapter; 2593123507Swpaul{ 2594198786Srpaulo return (NDIS_STATUS_SUCCESS); 2595123507Swpaul} 2596123507Swpaul 2597144888Swpaulstatic void 2598140751SwpaulNdisInitAnsiString(dst, src) 2599151207Swpaul ansi_string *dst; 2600123526Swpaul char *src; 2601123526Swpaul{ 2602151207Swpaul RtlInitAnsiString(dst, src); 2603123526Swpaul} 2604123526Swpaul 2605144888Swpaulstatic void 2606140751SwpaulNdisInitUnicodeString(dst, src) 2607151207Swpaul unicode_string *dst; 2608123941Swpaul uint16_t *src; 2609123941Swpaul{ 2610151207Swpaul RtlInitUnicodeString(dst, src); 2611123941Swpaul} 2612123941Swpaul 2613144888Swpaulstatic void NdisMGetDeviceProperty(adapter, phydevobj, 2614123526Swpaul funcdevobj, nextdevobj, resources, transresources) 2615123526Swpaul ndis_handle adapter; 2616125551Swpaul device_object **phydevobj; 2617125551Swpaul device_object **funcdevobj; 2618125551Swpaul device_object **nextdevobj; 2619123526Swpaul cm_resource_list *resources; 2620123526Swpaul cm_resource_list *transresources; 2621123526Swpaul{ 2622125551Swpaul ndis_miniport_block *block; 2623125551Swpaul 2624125551Swpaul block = (ndis_miniport_block *)adapter; 2625125551Swpaul 2626125551Swpaul if (phydevobj != NULL) 2627141524Swpaul *phydevobj = block->nmb_physdeviceobj; 2628125551Swpaul if (funcdevobj != NULL) 2629141524Swpaul *funcdevobj = block->nmb_deviceobj; 2630141524Swpaul if (nextdevobj != NULL) 2631141524Swpaul *nextdevobj = block->nmb_nextdeviceobj; 2632123526Swpaul} 2633123526Swpaul 2634144888Swpaulstatic void 2635140751SwpaulNdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen) 2636123721Swpaul ndis_packet *packet; 2637123721Swpaul ndis_buffer **buf; 2638123721Swpaul void **firstva; 2639123721Swpaul uint32_t *firstlen; 2640123721Swpaul uint32_t *totlen; 2641123721Swpaul{ 2642123721Swpaul ndis_buffer *tmp; 2643123721Swpaul 2644123721Swpaul tmp = packet->np_private.npp_head; 2645123721Swpaul *buf = tmp; 2646123721Swpaul if (tmp == NULL) { 2647123721Swpaul *firstva = NULL; 2648123721Swpaul *firstlen = *totlen = 0; 2649123721Swpaul } else { 2650140751Swpaul *firstva = MmGetMdlVirtualAddress(tmp); 2651140751Swpaul *firstlen = *totlen = MmGetMdlByteCount(tmp); 2652140751Swpaul for (tmp = tmp->mdl_next; tmp != NULL; tmp = tmp->mdl_next) 2653140751Swpaul *totlen += MmGetMdlByteCount(tmp); 2654123721Swpaul } 2655123721Swpaul} 2656123721Swpaul 2657144888Swpaulstatic void 2658140751SwpaulNdisGetFirstBufferFromPacketSafe(packet, buf, firstva, firstlen, totlen, prio) 2659123721Swpaul ndis_packet *packet; 2660123721Swpaul ndis_buffer **buf; 2661123721Swpaul void **firstva; 2662123721Swpaul uint32_t *firstlen; 2663123721Swpaul uint32_t *totlen; 2664123721Swpaul uint32_t prio; 2665123721Swpaul{ 2666140751Swpaul NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen); 2667123721Swpaul} 2668123721Swpaul 2669132973Swpaulstatic int 2670132973Swpaulndis_find_sym(lf, filename, suffix, sym) 2671132973Swpaul linker_file_t lf; 2672132973Swpaul char *filename; 2673132973Swpaul char *suffix; 2674132973Swpaul caddr_t *sym; 2675132973Swpaul{ 2676143086Swpaul char *fullsym; 2677133876Swpaul char *suf; 2678298734Spfg u_int i; 2679132973Swpaul 2680143086Swpaul fullsym = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0); 2681143086Swpaul if (fullsym == NULL) 2682198786Srpaulo return (ENOMEM); 2683143086Swpaul 2684143086Swpaul bzero(fullsym, MAXPATHLEN); 2685143086Swpaul strncpy(fullsym, filename, MAXPATHLEN); 2686143086Swpaul if (strlen(filename) < 4) { 2687143086Swpaul ExFreePool(fullsym); 2688198786Srpaulo return (EINVAL); 2689143086Swpaul } 2690133876Swpaul 2691133876Swpaul /* If the filename has a .ko suffix, strip if off. */ 2692133876Swpaul suf = fullsym + (strlen(filename) - 3); 2693133876Swpaul if (strcmp(suf, ".ko") == 0) 2694133876Swpaul *suf = '\0'; 2695133876Swpaul 2696132973Swpaul for (i = 0; i < strlen(fullsym); i++) { 2697132973Swpaul if (fullsym[i] == '.') 2698132973Swpaul fullsym[i] = '_'; 2699132973Swpaul else 2700132973Swpaul fullsym[i] = tolower(fullsym[i]); 2701132973Swpaul } 2702132973Swpaul strcat(fullsym, suffix); 2703132973Swpaul *sym = linker_file_lookup_symbol(lf, fullsym, 0); 2704143086Swpaul ExFreePool(fullsym); 2705132973Swpaul if (*sym == 0) 2706198786Srpaulo return (ENOENT); 2707132973Swpaul 2708198786Srpaulo return (0); 2709132973Swpaul} 2710132973Swpaul 2711159797Sjhbstruct ndis_checkmodule { 2712159797Sjhb char *afilename; 2713159797Sjhb ndis_fh *fh; 2714159797Sjhb}; 2715159797Sjhb 2716159797Sjhb/* 2717159797Sjhb * See if a single module contains the symbols for a specified file. 2718159797Sjhb */ 2719159797Sjhbstatic int 2720159797SjhbNdisCheckModule(linker_file_t lf, void *context) 2721159797Sjhb{ 2722159797Sjhb struct ndis_checkmodule *nc; 2723159797Sjhb caddr_t kldstart, kldend; 2724159797Sjhb 2725159797Sjhb nc = (struct ndis_checkmodule *)context; 2726159797Sjhb if (ndis_find_sym(lf, nc->afilename, "_start", &kldstart)) 2727159797Sjhb return (0); 2728159797Sjhb if (ndis_find_sym(lf, nc->afilename, "_end", &kldend)) 2729159797Sjhb return (0); 2730159797Sjhb nc->fh->nf_vp = lf; 2731159797Sjhb nc->fh->nf_map = NULL; 2732159797Sjhb nc->fh->nf_type = NDIS_FH_TYPE_MODULE; 2733159797Sjhb nc->fh->nf_maplen = (kldend - kldstart) & 0xFFFFFFFF; 2734159797Sjhb return (1); 2735159797Sjhb} 2736159797Sjhb 2737123822Swpaul/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */ 2738144888Swpaulstatic void 2739140751SwpaulNdisOpenFile(status, filehandle, filelength, filename, highestaddr) 2740123822Swpaul ndis_status *status; 2741123822Swpaul ndis_handle *filehandle; 2742123822Swpaul uint32_t *filelength; 2743151207Swpaul unicode_string *filename; 2744123822Swpaul ndis_physaddr highestaddr; 2745123822Swpaul{ 2746151207Swpaul ansi_string as; 2747123822Swpaul char *afilename = NULL; 2748124272Swpaul struct thread *td = curthread; 2749124272Swpaul struct nameidata nd; 2750241896Skib int flags, error; 2751124272Swpaul struct vattr vat; 2752124272Swpaul struct vattr *vap = &vat; 2753124272Swpaul ndis_fh *fh; 2754143086Swpaul char *path; 2755159797Sjhb struct ndis_checkmodule nc; 2756123822Swpaul 2757151207Swpaul if (RtlUnicodeStringToAnsiString(&as, filename, TRUE)) { 2758151207Swpaul *status = NDIS_STATUS_RESOURCES; 2759151207Swpaul return; 2760151207Swpaul } 2761124272Swpaul 2762151207Swpaul afilename = strdup(as.as_buf, M_DEVBUF); 2763151207Swpaul RtlFreeAnsiString(&as); 2764151207Swpaul 2765143086Swpaul fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0); 2766124272Swpaul if (fh == NULL) { 2767145895Swpaul free(afilename, M_DEVBUF); 2768124272Swpaul *status = NDIS_STATUS_RESOURCES; 2769124272Swpaul return; 2770124272Swpaul } 2771124272Swpaul 2772145895Swpaul fh->nf_name = afilename; 2773145895Swpaul 2774132973Swpaul /* 2775132973Swpaul * During system bootstrap, it's impossible to load files 2776132973Swpaul * from the rootfs since it's not mounted yet. We therefore 2777132973Swpaul * offer the possibility of opening files that have been 2778132973Swpaul * preloaded as modules instead. Both choices will work 2779132973Swpaul * when kldloading a module from multiuser, but only the 2780132973Swpaul * module option will work during bootstrap. The module 2781132973Swpaul * loading option works by using the ndiscvt(8) utility 2782132973Swpaul * to convert the arbitrary file into a .ko using objcopy(1). 2783132973Swpaul * This file will contain two special symbols: filename_start 2784132973Swpaul * and filename_end. All we have to do is traverse the KLD 2785132973Swpaul * list in search of those symbols and we've found the file 2786132973Swpaul * data. As an added bonus, ndiscvt(8) will also generate 2787132973Swpaul * a normal .o file which can be linked statically with 2788132973Swpaul * the kernel. This means that the symbols will actual reside 2789132973Swpaul * in the kernel's symbol table, but that doesn't matter to 2790132973Swpaul * us since the kernel appears to us as just another module. 2791132973Swpaul */ 2792132973Swpaul 2793159797Sjhb nc.afilename = afilename; 2794159797Sjhb nc.fh = fh; 2795159797Sjhb if (linker_file_foreach(NdisCheckModule, &nc)) { 2796159797Sjhb *filelength = fh->nf_maplen; 2797132973Swpaul *filehandle = fh; 2798132973Swpaul *status = NDIS_STATUS_SUCCESS; 2799132973Swpaul return; 2800132973Swpaul } 2801132973Swpaul 2802132973Swpaul if (TAILQ_EMPTY(&mountlist)) { 2803144256Swpaul ExFreePool(fh); 2804132973Swpaul *status = NDIS_STATUS_FILE_NOT_FOUND; 2805132973Swpaul printf("NDIS: could not find file %s in linker list\n", 2806132973Swpaul afilename); 2807132973Swpaul printf("NDIS: and no filesystems mounted yet, " 2808132973Swpaul "aborting NdisOpenFile()\n"); 2809132973Swpaul free(afilename, M_DEVBUF); 2810132973Swpaul return; 2811132973Swpaul } 2812132973Swpaul 2813143086Swpaul path = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0); 2814143086Swpaul if (path == NULL) { 2815144256Swpaul ExFreePool(fh); 2816145895Swpaul free(afilename, M_DEVBUF); 2817143086Swpaul *status = NDIS_STATUS_RESOURCES; 2818143086Swpaul return; 2819143086Swpaul } 2820143086Swpaul 2821143086Swpaul snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename); 2822132973Swpaul 2823125377Swpaul /* Some threads don't have a current working directory. */ 2824125377Swpaul 2825285391Smjg pwd_ensure_dirs(); 2826125377Swpaul 2827241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); 2828124272Swpaul 2829124272Swpaul flags = FREAD; 2830170152Skib error = vn_open(&nd, &flags, 0, NULL); 2831124272Swpaul if (error) { 2832124272Swpaul *status = NDIS_STATUS_FILE_NOT_FOUND; 2833143086Swpaul ExFreePool(fh); 2834127887Swpaul printf("NDIS: open file %s failed: %d\n", path, error); 2835143086Swpaul ExFreePool(path); 2836145895Swpaul free(afilename, M_DEVBUF); 2837124272Swpaul return; 2838124272Swpaul } 2839124272Swpaul 2840143086Swpaul ExFreePool(path); 2841143086Swpaul 2842124272Swpaul NDFREE(&nd, NDF_ONLY_PNBUF); 2843124272Swpaul 2844124272Swpaul /* Get the file size. */ 2845182371Sattilio VOP_GETATTR(nd.ni_vp, vap, td->td_ucred); 2846175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 2847124272Swpaul 2848124272Swpaul fh->nf_vp = nd.ni_vp; 2849124272Swpaul fh->nf_map = NULL; 2850132973Swpaul fh->nf_type = NDIS_FH_TYPE_VFS; 2851124272Swpaul *filehandle = fh; 2852124272Swpaul *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF; 2853124272Swpaul *status = NDIS_STATUS_SUCCESS; 2854123822Swpaul} 2855123822Swpaul 2856144888Swpaulstatic void 2857140751SwpaulNdisMapFile(status, mappedbuffer, filehandle) 2858123822Swpaul ndis_status *status; 2859123822Swpaul void **mappedbuffer; 2860123822Swpaul ndis_handle filehandle; 2861123822Swpaul{ 2862124272Swpaul ndis_fh *fh; 2863124272Swpaul struct thread *td = curthread; 2864133876Swpaul linker_file_t lf; 2865133876Swpaul caddr_t kldstart; 2866241896Skib int error; 2867231949Skib ssize_t resid; 2868159808Sjhb struct vnode *vp; 2869123822Swpaul 2870124272Swpaul if (filehandle == NULL) { 2871124272Swpaul *status = NDIS_STATUS_FAILURE; 2872124272Swpaul return; 2873124272Swpaul } 2874124272Swpaul 2875124272Swpaul fh = (ndis_fh *)filehandle; 2876124272Swpaul 2877124272Swpaul if (fh->nf_vp == NULL) { 2878124272Swpaul *status = NDIS_STATUS_FAILURE; 2879124272Swpaul return; 2880124272Swpaul } 2881124272Swpaul 2882124272Swpaul if (fh->nf_map != NULL) { 2883124272Swpaul *status = NDIS_STATUS_ALREADY_MAPPED; 2884124272Swpaul return; 2885124272Swpaul } 2886124272Swpaul 2887132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_MODULE) { 2888133876Swpaul lf = fh->nf_vp; 2889145895Swpaul if (ndis_find_sym(lf, fh->nf_name, "_start", &kldstart)) { 2890133876Swpaul *status = NDIS_STATUS_FAILURE; 2891133876Swpaul return; 2892133876Swpaul } 2893133876Swpaul fh->nf_map = kldstart; 2894132973Swpaul *status = NDIS_STATUS_SUCCESS; 2895132973Swpaul *mappedbuffer = fh->nf_map; 2896132973Swpaul return; 2897132973Swpaul } 2898132973Swpaul 2899143086Swpaul fh->nf_map = ExAllocatePoolWithTag(NonPagedPool, fh->nf_maplen, 0); 2900124272Swpaul 2901124272Swpaul if (fh->nf_map == NULL) { 2902124272Swpaul *status = NDIS_STATUS_RESOURCES; 2903124272Swpaul return; 2904124272Swpaul } 2905124272Swpaul 2906159808Sjhb vp = fh->nf_vp; 2907159808Sjhb error = vn_rdwr(UIO_READ, vp, fh->nf_map, fh->nf_maplen, 0, 2908124272Swpaul UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td); 2909124272Swpaul 2910124272Swpaul if (error) 2911124272Swpaul *status = NDIS_STATUS_FAILURE; 2912124272Swpaul else { 2913124272Swpaul *status = NDIS_STATUS_SUCCESS; 2914124272Swpaul *mappedbuffer = fh->nf_map; 2915124272Swpaul } 2916123822Swpaul} 2917123822Swpaul 2918144888Swpaulstatic void 2919140751SwpaulNdisUnmapFile(filehandle) 2920123822Swpaul ndis_handle filehandle; 2921123822Swpaul{ 2922124272Swpaul ndis_fh *fh; 2923124272Swpaul fh = (ndis_fh *)filehandle; 2924124272Swpaul 2925124272Swpaul if (fh->nf_map == NULL) 2926124272Swpaul return; 2927132973Swpaul 2928132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_VFS) 2929143086Swpaul ExFreePool(fh->nf_map); 2930124272Swpaul fh->nf_map = NULL; 2931123822Swpaul} 2932123822Swpaul 2933144888Swpaulstatic void 2934140751SwpaulNdisCloseFile(filehandle) 2935123822Swpaul ndis_handle filehandle; 2936123822Swpaul{ 2937124272Swpaul struct thread *td = curthread; 2938124272Swpaul ndis_fh *fh; 2939159808Sjhb struct vnode *vp; 2940124272Swpaul 2941124272Swpaul if (filehandle == NULL) 2942124272Swpaul return; 2943124272Swpaul 2944124272Swpaul fh = (ndis_fh *)filehandle; 2945124272Swpaul if (fh->nf_map != NULL) { 2946132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_VFS) 2947143086Swpaul ExFreePool(fh->nf_map); 2948124272Swpaul fh->nf_map = NULL; 2949124272Swpaul } 2950124272Swpaul 2951124272Swpaul if (fh->nf_vp == NULL) 2952124272Swpaul return; 2953124272Swpaul 2954132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_VFS) { 2955159808Sjhb vp = fh->nf_vp; 2956159808Sjhb vn_close(vp, FREAD, td->td_ucred, td); 2957132973Swpaul } 2958124272Swpaul 2959124272Swpaul fh->nf_vp = NULL; 2960145895Swpaul free(fh->nf_name, M_DEVBUF); 2961143086Swpaul ExFreePool(fh); 2962123822Swpaul} 2963123822Swpaul 2964144888Swpaulstatic uint8_t 2965140751SwpaulNdisSystemProcessorCount() 2966123848Swpaul{ 2967198786Srpaulo return (mp_ncpus); 2968124509Swpaul} 2969123848Swpaul 2970215779Sbschmidtstatic void 2971215779SbschmidtNdisGetCurrentProcessorCounts(idle_count, kernel_and_user, index) 2972215779Sbschmidt uint32_t *idle_count; 2973215779Sbschmidt uint32_t *kernel_and_user; 2974215779Sbschmidt uint32_t *index; 2975215779Sbschmidt{ 2976215779Sbschmidt struct pcpu *pcpu; 2977215779Sbschmidt 2978215779Sbschmidt pcpu = pcpu_find(curthread->td_oncpu); 2979215779Sbschmidt *index = pcpu->pc_cpuid; 2980215779Sbschmidt *idle_count = pcpu->pc_cp_time[CP_IDLE]; 2981215779Sbschmidt *kernel_and_user = pcpu->pc_cp_time[CP_INTR]; 2982215779Sbschmidt} 2983215779Sbschmidt 2984124116Swpaultypedef void (*ndis_statusdone_handler)(ndis_handle); 2985124116Swpaultypedef void (*ndis_status_handler)(ndis_handle, ndis_status, 2986189488Sweongyo void *, uint32_t); 2987124116Swpaul 2988144888Swpaulstatic void 2989140751SwpaulNdisMIndicateStatusComplete(adapter) 2990124116Swpaul ndis_handle adapter; 2991124116Swpaul{ 2992124116Swpaul ndis_miniport_block *block; 2993144888Swpaul ndis_statusdone_handler statusdonefunc; 2994124116Swpaul 2995124116Swpaul block = (ndis_miniport_block *)adapter; 2996124116Swpaul statusdonefunc = block->nmb_statusdone_func; 2997124116Swpaul 2998141963Swpaul MSCALL1(statusdonefunc, adapter); 2999124116Swpaul} 3000124116Swpaul 3001144888Swpaulstatic void 3002140751SwpaulNdisMIndicateStatus(adapter, status, sbuf, slen) 3003124116Swpaul ndis_handle adapter; 3004124116Swpaul ndis_status status; 3005124116Swpaul void *sbuf; 3006124116Swpaul uint32_t slen; 3007124116Swpaul{ 3008124116Swpaul ndis_miniport_block *block; 3009144888Swpaul ndis_status_handler statusfunc; 3010124116Swpaul 3011124116Swpaul block = (ndis_miniport_block *)adapter; 3012124116Swpaul statusfunc = block->nmb_status_func; 3013124116Swpaul 3014141963Swpaul MSCALL4(statusfunc, adapter, status, sbuf, slen); 3015124116Swpaul} 3016124116Swpaul 3017145895Swpaul/* 3018145895Swpaul * The DDK documentation says that you should use IoQueueWorkItem() 3019145895Swpaul * instead of ExQueueWorkItem(). The problem is, IoQueueWorkItem() 3020145895Swpaul * is fundamentally incompatible with NdisScheduleWorkItem(), which 3021145895Swpaul * depends on the API semantics of ExQueueWorkItem(). In our world, 3022145895Swpaul * ExQueueWorkItem() is implemented on top of IoAllocateQueueItem() 3023145895Swpaul * anyway. 3024146273Swpaul * 3025146273Swpaul * There are actually three distinct APIs here. NdisScheduleWorkItem() 3026146273Swpaul * takes a pointer to an NDIS_WORK_ITEM. ExQueueWorkItem() takes a pointer 3027146273Swpaul * to a WORK_QUEUE_ITEM. And finally, IoQueueWorkItem() takes a pointer 3028146273Swpaul * to an opaque work item thingie which you get from IoAllocateWorkItem(). 3029146273Swpaul * An NDIS_WORK_ITEM is not the same as a WORK_QUEUE_ITEM. However, 3030146273Swpaul * the NDIS_WORK_ITEM has some opaque storage at the end of it, and we 3031146273Swpaul * (ab)use this storage as a WORK_QUEUE_ITEM, which is what we submit 3032146273Swpaul * to ExQueueWorkItem(). 3033146273Swpaul * 3034146273Swpaul * Got all that? (Sheesh.) 3035145895Swpaul */ 3036124122Swpaul 3037145895Swpaulndis_status 3038140751SwpaulNdisScheduleWorkItem(work) 3039124122Swpaul ndis_work_item *work; 3040124122Swpaul{ 3041146273Swpaul work_queue_item *wqi; 3042146273Swpaul 3043146273Swpaul wqi = (work_queue_item *)work->nwi_wraprsvd; 3044146273Swpaul ExInitializeWorkItem(wqi, 3045146273Swpaul (work_item_func)work->nwi_func, work->nwi_ctx); 3046146273Swpaul ExQueueWorkItem(wqi, WORKQUEUE_DELAYED); 3047151207Swpaul 3048198786Srpaulo return (NDIS_STATUS_SUCCESS); 3049124122Swpaul} 3050124122Swpaul 3051144888Swpaulstatic void 3052140751SwpaulNdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen) 3053124541Swpaul ndis_packet *dpkt; 3054124541Swpaul uint32_t doff; 3055124541Swpaul uint32_t reqlen; 3056124541Swpaul ndis_packet *spkt; 3057124541Swpaul uint32_t soff; 3058124541Swpaul uint32_t *cpylen; 3059124541Swpaul{ 3060124541Swpaul ndis_buffer *src, *dst; 3061124541Swpaul char *sptr, *dptr; 3062124541Swpaul int resid, copied, len, scnt, dcnt; 3063124541Swpaul 3064124541Swpaul *cpylen = 0; 3065124541Swpaul 3066124541Swpaul src = spkt->np_private.npp_head; 3067124541Swpaul dst = dpkt->np_private.npp_head; 3068124541Swpaul 3069140751Swpaul sptr = MmGetMdlVirtualAddress(src); 3070140751Swpaul dptr = MmGetMdlVirtualAddress(dst); 3071140751Swpaul scnt = MmGetMdlByteCount(src); 3072140751Swpaul dcnt = MmGetMdlByteCount(dst); 3073124541Swpaul 3074124541Swpaul while (soff) { 3075140751Swpaul if (MmGetMdlByteCount(src) > soff) { 3076124541Swpaul sptr += soff; 3077140751Swpaul scnt = MmGetMdlByteCount(src)- soff; 3078124541Swpaul break; 3079124541Swpaul } 3080140751Swpaul soff -= MmGetMdlByteCount(src); 3081140751Swpaul src = src->mdl_next; 3082124541Swpaul if (src == NULL) 3083124541Swpaul return; 3084140751Swpaul sptr = MmGetMdlVirtualAddress(src); 3085124541Swpaul } 3086124541Swpaul 3087124541Swpaul while (doff) { 3088140751Swpaul if (MmGetMdlByteCount(dst) > doff) { 3089124541Swpaul dptr += doff; 3090140751Swpaul dcnt = MmGetMdlByteCount(dst) - doff; 3091124541Swpaul break; 3092124541Swpaul } 3093140751Swpaul doff -= MmGetMdlByteCount(dst); 3094140751Swpaul dst = dst->mdl_next; 3095124541Swpaul if (dst == NULL) 3096124541Swpaul return; 3097140751Swpaul dptr = MmGetMdlVirtualAddress(dst); 3098124541Swpaul } 3099124541Swpaul 3100124541Swpaul resid = reqlen; 3101124541Swpaul copied = 0; 3102124541Swpaul 3103124541Swpaul while(1) { 3104124541Swpaul if (resid < scnt) 3105124541Swpaul len = resid; 3106124541Swpaul else 3107124541Swpaul len = scnt; 3108124541Swpaul if (dcnt < len) 3109124541Swpaul len = dcnt; 3110124541Swpaul 3111124541Swpaul bcopy(sptr, dptr, len); 3112124541Swpaul 3113124541Swpaul copied += len; 3114124541Swpaul resid -= len; 3115124541Swpaul if (resid == 0) 3116124541Swpaul break; 3117124541Swpaul 3118124541Swpaul dcnt -= len; 3119124541Swpaul if (dcnt == 0) { 3120140751Swpaul dst = dst->mdl_next; 3121124541Swpaul if (dst == NULL) 3122124541Swpaul break; 3123140751Swpaul dptr = MmGetMdlVirtualAddress(dst); 3124140751Swpaul dcnt = MmGetMdlByteCount(dst); 3125124541Swpaul } 3126124541Swpaul 3127124541Swpaul scnt -= len; 3128124541Swpaul if (scnt == 0) { 3129140751Swpaul src = src->mdl_next; 3130124541Swpaul if (src == NULL) 3131124541Swpaul break; 3132140751Swpaul sptr = MmGetMdlVirtualAddress(src); 3133140751Swpaul scnt = MmGetMdlByteCount(src); 3134124541Swpaul } 3135124541Swpaul } 3136124541Swpaul 3137124541Swpaul *cpylen = copied; 3138124541Swpaul} 3139124541Swpaul 3140144888Swpaulstatic void 3141140751SwpaulNdisCopyFromPacketToPacketSafe(dpkt, doff, reqlen, spkt, soff, cpylen, prio) 3142124541Swpaul ndis_packet *dpkt; 3143124541Swpaul uint32_t doff; 3144124541Swpaul uint32_t reqlen; 3145124541Swpaul ndis_packet *spkt; 3146124541Swpaul uint32_t soff; 3147124541Swpaul uint32_t *cpylen; 3148124541Swpaul uint32_t prio; 3149124541Swpaul{ 3150140751Swpaul NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen); 3151124541Swpaul} 3152124541Swpaul 3153174240Sthompsastatic void 3154174240SthompsaNdisIMCopySendPerPacketInfo(dpkt, spkt) 3155174240Sthompsa ndis_packet *dpkt; 3156174240Sthompsa ndis_packet *spkt; 3157174240Sthompsa{ 3158174240Sthompsa memcpy(&dpkt->np_ext, &spkt->np_ext, sizeof(ndis_packet_extension)); 3159174240Sthompsa} 3160174240Sthompsa 3161144888Swpaulstatic ndis_status 3162140751SwpaulNdisMRegisterDevice(handle, devname, symname, majorfuncs, devobj, devhandle) 3163125551Swpaul ndis_handle handle; 3164151207Swpaul unicode_string *devname; 3165151207Swpaul unicode_string *symname; 3166125551Swpaul driver_dispatch *majorfuncs[]; 3167125551Swpaul void **devobj; 3168125551Swpaul ndis_handle *devhandle; 3169125057Swpaul{ 3170146364Swpaul uint32_t status; 3171146364Swpaul device_object *dobj; 3172125551Swpaul 3173146364Swpaul status = IoCreateDevice(handle, 0, devname, 3174146364Swpaul FILE_DEVICE_UNKNOWN, 0, FALSE, &dobj); 3175125551Swpaul 3176146364Swpaul if (status == STATUS_SUCCESS) { 3177146364Swpaul *devobj = dobj; 3178146364Swpaul *devhandle = dobj; 3179146364Swpaul } 3180146364Swpaul 3181198786Srpaulo return (status); 3182125057Swpaul} 3183125057Swpaul 3184144888Swpaulstatic ndis_status 3185140751SwpaulNdisMDeregisterDevice(handle) 3186125551Swpaul ndis_handle handle; 3187125057Swpaul{ 3188146364Swpaul IoDeleteDevice(handle); 3189198786Srpaulo return (NDIS_STATUS_SUCCESS); 3190125057Swpaul} 3191125057Swpaul 3192144888Swpaulstatic ndis_status 3193140751SwpaulNdisMQueryAdapterInstanceName(name, handle) 3194151207Swpaul unicode_string *name; 3195125551Swpaul ndis_handle handle; 3196125551Swpaul{ 3197125551Swpaul ndis_miniport_block *block; 3198141524Swpaul device_t dev; 3199151207Swpaul ansi_string as; 3200125057Swpaul 3201125551Swpaul block = (ndis_miniport_block *)handle; 3202141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 3203141524Swpaul 3204151207Swpaul RtlInitAnsiString(&as, __DECONST(char *, device_get_nameunit(dev))); 3205151207Swpaul if (RtlAnsiStringToUnicodeString(name, &as, TRUE)) 3206198786Srpaulo return (NDIS_STATUS_RESOURCES); 3207125551Swpaul 3208198786Srpaulo return (NDIS_STATUS_SUCCESS); 3209125551Swpaul} 3210125551Swpaul 3211144888Swpaulstatic void 3212140751SwpaulNdisMRegisterUnloadHandler(handle, func) 3213125551Swpaul ndis_handle handle; 3214125551Swpaul void *func; 3215125551Swpaul{ 3216125551Swpaul} 3217125551Swpaul 3218144888Swpaulstatic void 3219123474Swpauldummy() 3220123474Swpaul{ 3221198786Srpaulo printf("NDIS dummy called...\n"); 3222123474Swpaul} 3223123474Swpaul 3224144888Swpaul/* 3225144888Swpaul * Note: a couple of entries in this table specify the 3226144888Swpaul * number of arguments as "foo + 1". These are routines 3227144888Swpaul * that accept a 64-bit argument, passed by value. On 3228144888Swpaul * x86, these arguments consume two longwords on the stack, 3229144888Swpaul * so we lie and say there's one additional argument so 3230144888Swpaul * that the wrapping routines will do the right thing. 3231144888Swpaul */ 3232144888Swpaul 3233123474Swpaulimage_patch_table ndis_functbl[] = { 3234144888Swpaul IMPORT_SFUNC(NdisCopyFromPacketToPacket, 6), 3235144888Swpaul IMPORT_SFUNC(NdisCopyFromPacketToPacketSafe, 7), 3236174240Sthompsa IMPORT_SFUNC(NdisIMCopySendPerPacketInfo, 2), 3237144888Swpaul IMPORT_SFUNC(NdisScheduleWorkItem, 1), 3238144888Swpaul IMPORT_SFUNC(NdisMIndicateStatusComplete, 1), 3239144888Swpaul IMPORT_SFUNC(NdisMIndicateStatus, 4), 3240144888Swpaul IMPORT_SFUNC(NdisSystemProcessorCount, 0), 3241215779Sbschmidt IMPORT_SFUNC(NdisGetCurrentProcessorCounts, 3), 3242144888Swpaul IMPORT_SFUNC(NdisUnchainBufferAtBack, 2), 3243144888Swpaul IMPORT_SFUNC(NdisGetFirstBufferFromPacket, 5), 3244144888Swpaul IMPORT_SFUNC(NdisGetFirstBufferFromPacketSafe, 6), 3245144888Swpaul IMPORT_SFUNC(NdisGetBufferPhysicalArraySize, 2), 3246144888Swpaul IMPORT_SFUNC(NdisMGetDeviceProperty, 6), 3247144888Swpaul IMPORT_SFUNC(NdisInitAnsiString, 2), 3248144888Swpaul IMPORT_SFUNC(NdisInitUnicodeString, 2), 3249144888Swpaul IMPORT_SFUNC(NdisWriteConfiguration, 4), 3250144888Swpaul IMPORT_SFUNC(NdisAnsiStringToUnicodeString, 2), 3251144888Swpaul IMPORT_SFUNC(NdisTerminateWrapper, 2), 3252144888Swpaul IMPORT_SFUNC(NdisOpenConfigurationKeyByName, 4), 3253144888Swpaul IMPORT_SFUNC(NdisOpenConfigurationKeyByIndex, 5), 3254144888Swpaul IMPORT_SFUNC(NdisMRemoveMiniport, 1), 3255189488Sweongyo IMPORT_SFUNC(NdisInitializeString, 2), 3256189488Sweongyo IMPORT_SFUNC(NdisFreeString, 1), 3257144888Swpaul IMPORT_SFUNC(NdisGetCurrentSystemTime, 1), 3258216242Sbschmidt IMPORT_SFUNC(NdisGetRoutineAddress, 1), 3259144888Swpaul IMPORT_SFUNC(NdisGetSystemUpTime, 1), 3260215779Sbschmidt IMPORT_SFUNC(NdisGetVersion, 0), 3261144888Swpaul IMPORT_SFUNC(NdisMSynchronizeWithInterrupt, 3), 3262144888Swpaul IMPORT_SFUNC(NdisMAllocateSharedMemoryAsync, 4), 3263144888Swpaul IMPORT_SFUNC(NdisInterlockedInsertHeadList, 3), 3264144888Swpaul IMPORT_SFUNC(NdisInterlockedInsertTailList, 3), 3265144888Swpaul IMPORT_SFUNC(NdisInterlockedRemoveHeadList, 2), 3266144888Swpaul IMPORT_SFUNC(NdisInitializeWrapper, 4), 3267144888Swpaul IMPORT_SFUNC(NdisMRegisterMiniport, 3), 3268144888Swpaul IMPORT_SFUNC(NdisAllocateMemoryWithTag, 3), 3269144888Swpaul IMPORT_SFUNC(NdisAllocateMemory, 4 + 1), 3270144888Swpaul IMPORT_SFUNC(NdisMSetAttributesEx, 5), 3271144888Swpaul IMPORT_SFUNC(NdisCloseConfiguration, 1), 3272144888Swpaul IMPORT_SFUNC(NdisReadConfiguration, 5), 3273144888Swpaul IMPORT_SFUNC(NdisOpenConfiguration, 3), 3274144888Swpaul IMPORT_SFUNC(NdisAcquireSpinLock, 1), 3275144888Swpaul IMPORT_SFUNC(NdisReleaseSpinLock, 1), 3276144888Swpaul IMPORT_SFUNC(NdisDprAcquireSpinLock, 1), 3277144888Swpaul IMPORT_SFUNC(NdisDprReleaseSpinLock, 1), 3278144888Swpaul IMPORT_SFUNC(NdisAllocateSpinLock, 1), 3279145895Swpaul IMPORT_SFUNC(NdisInitializeReadWriteLock, 1), 3280145895Swpaul IMPORT_SFUNC(NdisAcquireReadWriteLock, 3), 3281145895Swpaul IMPORT_SFUNC(NdisReleaseReadWriteLock, 2), 3282144888Swpaul IMPORT_SFUNC(NdisFreeSpinLock, 1), 3283144888Swpaul IMPORT_SFUNC(NdisFreeMemory, 3), 3284144888Swpaul IMPORT_SFUNC(NdisReadPciSlotInformation, 5), 3285144888Swpaul IMPORT_SFUNC(NdisWritePciSlotInformation, 5), 3286144888Swpaul IMPORT_SFUNC_MAP(NdisImmediateReadPciSlotInformation, 3287144888Swpaul NdisReadPciSlotInformation, 5), 3288144888Swpaul IMPORT_SFUNC_MAP(NdisImmediateWritePciSlotInformation, 3289144888Swpaul NdisWritePciSlotInformation, 5), 3290144888Swpaul IMPORT_CFUNC(NdisWriteErrorLogEntry, 0), 3291144888Swpaul IMPORT_SFUNC(NdisMStartBufferPhysicalMapping, 6), 3292144888Swpaul IMPORT_SFUNC(NdisMCompleteBufferPhysicalMapping, 3), 3293144888Swpaul IMPORT_SFUNC(NdisMInitializeTimer, 4), 3294144888Swpaul IMPORT_SFUNC(NdisInitializeTimer, 3), 3295144888Swpaul IMPORT_SFUNC(NdisSetTimer, 2), 3296144888Swpaul IMPORT_SFUNC(NdisMCancelTimer, 2), 3297144888Swpaul IMPORT_SFUNC_MAP(NdisCancelTimer, NdisMCancelTimer, 2), 3298144888Swpaul IMPORT_SFUNC(NdisMSetPeriodicTimer, 2), 3299144888Swpaul IMPORT_SFUNC(NdisMQueryAdapterResources, 4), 3300144888Swpaul IMPORT_SFUNC(NdisMRegisterIoPortRange, 4), 3301144888Swpaul IMPORT_SFUNC(NdisMDeregisterIoPortRange, 4), 3302144888Swpaul IMPORT_SFUNC(NdisReadNetworkAddress, 4), 3303144888Swpaul IMPORT_SFUNC(NdisQueryMapRegisterCount, 2), 3304144888Swpaul IMPORT_SFUNC(NdisMAllocateMapRegisters, 5), 3305144888Swpaul IMPORT_SFUNC(NdisMFreeMapRegisters, 1), 3306144888Swpaul IMPORT_SFUNC(NdisMAllocateSharedMemory, 5), 3307144888Swpaul IMPORT_SFUNC(NdisMMapIoSpace, 4 + 1), 3308144888Swpaul IMPORT_SFUNC(NdisMUnmapIoSpace, 3), 3309144888Swpaul IMPORT_SFUNC(NdisGetCacheFillSize, 0), 3310144888Swpaul IMPORT_SFUNC(NdisMGetDmaAlignment, 1), 3311144888Swpaul IMPORT_SFUNC(NdisMInitializeScatterGatherDma, 3), 3312144888Swpaul IMPORT_SFUNC(NdisAllocatePacketPool, 4), 3313144888Swpaul IMPORT_SFUNC(NdisAllocatePacketPoolEx, 5), 3314144888Swpaul IMPORT_SFUNC(NdisAllocatePacket, 3), 3315144888Swpaul IMPORT_SFUNC(NdisFreePacket, 1), 3316144888Swpaul IMPORT_SFUNC(NdisFreePacketPool, 1), 3317144888Swpaul IMPORT_SFUNC_MAP(NdisDprAllocatePacket, NdisAllocatePacket, 3), 3318144888Swpaul IMPORT_SFUNC_MAP(NdisDprFreePacket, NdisFreePacket, 1), 3319144888Swpaul IMPORT_SFUNC(NdisAllocateBufferPool, 3), 3320144888Swpaul IMPORT_SFUNC(NdisAllocateBuffer, 5), 3321144888Swpaul IMPORT_SFUNC(NdisQueryBuffer, 3), 3322144888Swpaul IMPORT_SFUNC(NdisQueryBufferSafe, 4), 3323144888Swpaul IMPORT_SFUNC(NdisBufferVirtualAddress, 1), 3324144888Swpaul IMPORT_SFUNC(NdisBufferVirtualAddressSafe, 2), 3325144888Swpaul IMPORT_SFUNC(NdisBufferLength, 1), 3326144888Swpaul IMPORT_SFUNC(NdisFreeBuffer, 1), 3327144888Swpaul IMPORT_SFUNC(NdisFreeBufferPool, 1), 3328144888Swpaul IMPORT_SFUNC(NdisInterlockedIncrement, 1), 3329144888Swpaul IMPORT_SFUNC(NdisInterlockedDecrement, 1), 3330144888Swpaul IMPORT_SFUNC(NdisInitializeEvent, 1), 3331144888Swpaul IMPORT_SFUNC(NdisSetEvent, 1), 3332144888Swpaul IMPORT_SFUNC(NdisResetEvent, 1), 3333144888Swpaul IMPORT_SFUNC(NdisWaitEvent, 2), 3334144888Swpaul IMPORT_SFUNC(NdisUnicodeStringToAnsiString, 2), 3335144888Swpaul IMPORT_SFUNC(NdisMPciAssignResources, 3), 3336144888Swpaul IMPORT_SFUNC(NdisMFreeSharedMemory, 5 + 1), 3337144888Swpaul IMPORT_SFUNC(NdisMRegisterInterrupt, 7), 3338144888Swpaul IMPORT_SFUNC(NdisMDeregisterInterrupt, 1), 3339144888Swpaul IMPORT_SFUNC(NdisMRegisterAdapterShutdownHandler, 3), 3340144888Swpaul IMPORT_SFUNC(NdisMDeregisterAdapterShutdownHandler, 1), 3341144888Swpaul IMPORT_SFUNC(NDIS_BUFFER_TO_SPAN_PAGES, 1), 3342144888Swpaul IMPORT_SFUNC(NdisQueryBufferOffset, 3), 3343144888Swpaul IMPORT_SFUNC(NdisAdjustBufferLength, 2), 3344144888Swpaul IMPORT_SFUNC(NdisPacketPoolUsage, 1), 3345144888Swpaul IMPORT_SFUNC(NdisMSleep, 1), 3346144888Swpaul IMPORT_SFUNC(NdisUnchainBufferAtFront, 2), 3347144888Swpaul IMPORT_SFUNC(NdisReadPcmciaAttributeMemory, 4), 3348144888Swpaul IMPORT_SFUNC(NdisWritePcmciaAttributeMemory, 4), 3349144888Swpaul IMPORT_SFUNC(NdisOpenFile, 5 + 1), 3350144888Swpaul IMPORT_SFUNC(NdisMapFile, 3), 3351144888Swpaul IMPORT_SFUNC(NdisUnmapFile, 1), 3352144888Swpaul IMPORT_SFUNC(NdisCloseFile, 1), 3353144888Swpaul IMPORT_SFUNC(NdisMRegisterDevice, 6), 3354144888Swpaul IMPORT_SFUNC(NdisMDeregisterDevice, 1), 3355144888Swpaul IMPORT_SFUNC(NdisMQueryAdapterInstanceName, 2), 3356144888Swpaul IMPORT_SFUNC(NdisMRegisterUnloadHandler, 2), 3357144888Swpaul IMPORT_SFUNC(ndis_timercall, 4), 3358145895Swpaul IMPORT_SFUNC(ndis_asyncmem_complete, 2), 3359152626Swpaul IMPORT_SFUNC(ndis_intr, 2), 3360151207Swpaul IMPORT_SFUNC(ndis_intrhand, 4), 3361123474Swpaul 3362123474Swpaul /* 3363123474Swpaul * This last entry is a catch-all for any function we haven't 3364123474Swpaul * implemented yet. The PE import list patching routine will 3365123474Swpaul * use it for any function that doesn't have an explicit match 3366123474Swpaul * in this table. 3367123474Swpaul */ 3368123474Swpaul 3369145895Swpaul { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, 3370123474Swpaul 3371123474Swpaul /* End of list. */ 3372123474Swpaul 3373141963Swpaul { NULL, NULL, NULL } 3374123474Swpaul}; 3375