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$"); 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> 79123474Swpaul#include <net/if_arp.h> 80123474Swpaul#include <net/ethernet.h> 81123474Swpaul#include <net/if_dl.h> 82123474Swpaul#include <net/if_media.h> 83123474Swpaul 84124203Swpaul#include <machine/atomic.h> 85123474Swpaul#include <machine/bus.h> 86123474Swpaul#include <machine/resource.h> 87123474Swpaul 88123474Swpaul#include <sys/bus.h> 89123474Swpaul#include <sys/rman.h> 90123474Swpaul 91123474Swpaul#include <machine/stdarg.h> 92123474Swpaul 93123695Swpaul#include <net80211/ieee80211_var.h> 94123695Swpaul#include <net80211/ieee80211_ioctl.h> 95123695Swpaul 96123474Swpaul#include <dev/pci/pcireg.h> 97123474Swpaul#include <dev/pci/pcivar.h> 98189488Sweongyo#include <dev/usb/usb.h> 99194677Sthompsa#include <dev/usb/usbdi.h> 100123474Swpaul 101123474Swpaul#include <compat/ndis/pe_var.h> 102145485Swpaul#include <compat/ndis/cfg_var.h> 103123474Swpaul#include <compat/ndis/resource_var.h> 104123512Swpaul#include <compat/ndis/ntoskrnl_var.h> 105128229Swpaul#include <compat/ndis/hal_var.h> 106123474Swpaul#include <compat/ndis/ndis_var.h> 107123474Swpaul#include <dev/if_ndis/if_ndisvar.h> 108123474Swpaul 109151207Swpaul#include <vm/vm.h> 110151207Swpaul#include <vm/vm_param.h> 111151207Swpaul#include <vm/pmap.h> 112151207Swpaul#include <vm/uma.h> 113151207Swpaul#include <vm/vm_kern.h> 114151207Swpaul#include <vm/vm_map.h> 115151207Swpaul 116124272Swpaulstatic char ndis_filepath[MAXPATHLEN]; 117123474Swpaul 118124272SwpaulSYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath, 119189488Sweongyo MAXPATHLEN, "Path used by NdisOpenFile() to search for files"); 120124272Swpaul 121144888Swpaulstatic void NdisInitializeWrapper(ndis_handle *, 122141524Swpaul driver_object *, void *, void *); 123144888Swpaulstatic ndis_status NdisMRegisterMiniport(ndis_handle, 124123474Swpaul ndis_miniport_characteristics *, int); 125144888Swpaulstatic ndis_status NdisAllocateMemoryWithTag(void **, 126140751Swpaul uint32_t, uint32_t); 127144888Swpaulstatic ndis_status NdisAllocateMemory(void **, 128123474Swpaul uint32_t, uint32_t, ndis_physaddr); 129144888Swpaulstatic void NdisFreeMemory(void *, uint32_t, uint32_t); 130144888Swpaulstatic ndis_status NdisMSetAttributesEx(ndis_handle, ndis_handle, 131123474Swpaul uint32_t, uint32_t, ndis_interface_type); 132144888Swpaulstatic void NdisOpenConfiguration(ndis_status *, 133140751Swpaul ndis_handle *, ndis_handle); 134144888Swpaulstatic void NdisOpenConfigurationKeyByIndex(ndis_status *, 135151207Swpaul ndis_handle, uint32_t, unicode_string *, ndis_handle *); 136144888Swpaulstatic void NdisOpenConfigurationKeyByName(ndis_status *, 137151207Swpaul ndis_handle, unicode_string *, ndis_handle *); 138123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *, 139123474Swpaul struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); 140123526Swpaulstatic ndis_status ndis_decode_parm(ndis_miniport_block *, 141123526Swpaul ndis_config_parm *, char *); 142144888Swpaulstatic void NdisReadConfiguration(ndis_status *, ndis_config_parm **, 143151207Swpaul ndis_handle, unicode_string *, ndis_parm_type); 144144888Swpaulstatic void NdisWriteConfiguration(ndis_status *, ndis_handle, 145151207Swpaul unicode_string *, ndis_config_parm *); 146144888Swpaulstatic void NdisCloseConfiguration(ndis_handle); 147144888Swpaulstatic void NdisAllocateSpinLock(ndis_spin_lock *); 148144888Swpaulstatic void NdisFreeSpinLock(ndis_spin_lock *); 149144888Swpaulstatic void NdisAcquireSpinLock(ndis_spin_lock *); 150144888Swpaulstatic void NdisReleaseSpinLock(ndis_spin_lock *); 151144888Swpaulstatic void NdisDprAcquireSpinLock(ndis_spin_lock *); 152144888Swpaulstatic void NdisDprReleaseSpinLock(ndis_spin_lock *); 153145895Swpaulstatic void NdisInitializeReadWriteLock(ndis_rw_lock *); 154145895Swpaulstatic void NdisAcquireReadWriteLock(ndis_rw_lock *, 155145895Swpaul uint8_t, ndis_lock_state *); 156145895Swpaulstatic void NdisReleaseReadWriteLock(ndis_rw_lock *, ndis_lock_state *); 157144888Swpaulstatic uint32_t NdisReadPciSlotInformation(ndis_handle, uint32_t, 158123474Swpaul uint32_t, void *, uint32_t); 159144888Swpaulstatic uint32_t NdisWritePciSlotInformation(ndis_handle, uint32_t, 160123474Swpaul uint32_t, void *, uint32_t); 161140751Swpaulstatic void NdisWriteErrorLogEntry(ndis_handle, ndis_error_code, uint32_t, ...); 162123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int); 163144888Swpaulstatic void NdisMStartBufferPhysicalMapping(ndis_handle, 164140751Swpaul ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); 165144888Swpaulstatic void NdisMCompleteBufferPhysicalMapping(ndis_handle, 166140751Swpaul ndis_buffer *, uint32_t); 167144888Swpaulstatic void NdisMInitializeTimer(ndis_miniport_timer *, ndis_handle, 168123474Swpaul ndis_timer_function, void *); 169144888Swpaulstatic void NdisInitializeTimer(ndis_timer *, 170125057Swpaul ndis_timer_function, void *); 171144888Swpaulstatic void NdisSetTimer(ndis_timer *, uint32_t); 172144888Swpaulstatic void NdisMSetPeriodicTimer(ndis_miniport_timer *, uint32_t); 173144888Swpaulstatic void NdisMCancelTimer(ndis_timer *, uint8_t *); 174144888Swpaulstatic void ndis_timercall(kdpc *, ndis_miniport_timer *, 175144174Swpaul void *, void *); 176144888Swpaulstatic void NdisMQueryAdapterResources(ndis_status *, ndis_handle, 177123474Swpaul ndis_resource_list *, uint32_t *); 178144888Swpaulstatic ndis_status NdisMRegisterIoPortRange(void **, 179123474Swpaul ndis_handle, uint32_t, uint32_t); 180144888Swpaulstatic void NdisMDeregisterIoPortRange(ndis_handle, 181123474Swpaul uint32_t, uint32_t, void *); 182144888Swpaulstatic void NdisReadNetworkAddress(ndis_status *, void **, 183123474Swpaul uint32_t *, ndis_handle); 184144888Swpaulstatic ndis_status NdisQueryMapRegisterCount(uint32_t, uint32_t *); 185144888Swpaulstatic ndis_status NdisMAllocateMapRegisters(ndis_handle, 186123474Swpaul uint32_t, uint8_t, uint32_t, uint32_t); 187144888Swpaulstatic void NdisMFreeMapRegisters(ndis_handle); 188123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); 189144888Swpaulstatic void NdisMAllocateSharedMemory(ndis_handle, uint32_t, 190123474Swpaul uint8_t, void **, ndis_physaddr *); 191145895Swpaulstatic void ndis_asyncmem_complete(device_object *, void *); 192144888Swpaulstatic ndis_status NdisMAllocateSharedMemoryAsync(ndis_handle, 193123474Swpaul uint32_t, uint8_t, void *); 194144888Swpaulstatic void NdisMFreeSharedMemory(ndis_handle, uint32_t, 195123474Swpaul uint8_t, void *, ndis_physaddr); 196144888Swpaulstatic ndis_status NdisMMapIoSpace(void **, ndis_handle, 197123474Swpaul ndis_physaddr, uint32_t); 198144888Swpaulstatic void NdisMUnmapIoSpace(ndis_handle, void *, uint32_t); 199144888Swpaulstatic uint32_t NdisGetCacheFillSize(void); 200216242Sbschmidtstatic void *NdisGetRoutineAddress(unicode_string *); 201144888Swpaulstatic uint32_t NdisMGetDmaAlignment(ndis_handle); 202144888Swpaulstatic ndis_status NdisMInitializeScatterGatherDma(ndis_handle, 203123474Swpaul uint8_t, uint32_t); 204144888Swpaulstatic void NdisUnchainBufferAtFront(ndis_packet *, ndis_buffer **); 205144888Swpaulstatic void NdisUnchainBufferAtBack(ndis_packet *, ndis_buffer **); 206144888Swpaulstatic void NdisAllocateBufferPool(ndis_status *, 207123474Swpaul ndis_handle *, uint32_t); 208144888Swpaulstatic void NdisFreeBufferPool(ndis_handle); 209144888Swpaulstatic void NdisAllocateBuffer(ndis_status *, ndis_buffer **, 210123474Swpaul ndis_handle, void *, uint32_t); 211144888Swpaulstatic void NdisFreeBuffer(ndis_buffer *); 212144888Swpaulstatic uint32_t NdisBufferLength(ndis_buffer *); 213144888Swpaulstatic void NdisQueryBuffer(ndis_buffer *, void **, uint32_t *); 214144888Swpaulstatic void NdisQueryBufferSafe(ndis_buffer *, void **, 215123474Swpaul uint32_t *, uint32_t); 216144888Swpaulstatic void *NdisBufferVirtualAddress(ndis_buffer *); 217144888Swpaulstatic void *NdisBufferVirtualAddressSafe(ndis_buffer *, uint32_t); 218144888Swpaulstatic void NdisAdjustBufferLength(ndis_buffer *, int); 219144888Swpaulstatic uint32_t NdisInterlockedIncrement(uint32_t *); 220144888Swpaulstatic uint32_t NdisInterlockedDecrement(uint32_t *); 221144888Swpaulstatic void NdisInitializeEvent(ndis_event *); 222144888Swpaulstatic void NdisSetEvent(ndis_event *); 223144888Swpaulstatic void NdisResetEvent(ndis_event *); 224144888Swpaulstatic uint8_t NdisWaitEvent(ndis_event *, uint32_t); 225151207Swpaulstatic ndis_status NdisUnicodeStringToAnsiString(ansi_string *, 226151207Swpaul unicode_string *); 227144888Swpaulstatic ndis_status 228151207Swpaul NdisAnsiStringToUnicodeString(unicode_string *, ansi_string *); 229144888Swpaulstatic ndis_status NdisMPciAssignResources(ndis_handle, 230123474Swpaul uint32_t, ndis_resource_list **); 231144888Swpaulstatic ndis_status NdisMRegisterInterrupt(ndis_miniport_interrupt *, 232123474Swpaul ndis_handle, uint32_t, uint32_t, uint8_t, 233123474Swpaul uint8_t, ndis_interrupt_mode); 234144888Swpaulstatic void NdisMDeregisterInterrupt(ndis_miniport_interrupt *); 235144888Swpaulstatic void NdisMRegisterAdapterShutdownHandler(ndis_handle, void *, 236123474Swpaul ndis_shutdown_handler); 237144888Swpaulstatic void NdisMDeregisterAdapterShutdownHandler(ndis_handle); 238144888Swpaulstatic uint32_t NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *); 239144888Swpaulstatic void NdisGetBufferPhysicalArraySize(ndis_buffer *, 240140751Swpaul uint32_t *); 241144888Swpaulstatic void NdisQueryBufferOffset(ndis_buffer *, 242123474Swpaul uint32_t *, uint32_t *); 243144888Swpaulstatic uint32_t NdisReadPcmciaAttributeMemory(ndis_handle, 244123474Swpaul uint32_t, void *, uint32_t); 245144888Swpaulstatic uint32_t NdisWritePcmciaAttributeMemory(ndis_handle, 246123474Swpaul uint32_t, void *, uint32_t); 247144888Swpaulstatic list_entry *NdisInterlockedInsertHeadList(list_entry *, 248125551Swpaul list_entry *, ndis_spin_lock *); 249144888Swpaulstatic list_entry *NdisInterlockedRemoveHeadList(list_entry *, 250123474Swpaul ndis_spin_lock *); 251144888Swpaulstatic list_entry *NdisInterlockedInsertTailList(list_entry *, 252125551Swpaul list_entry *, ndis_spin_lock *); 253144888Swpaulstatic uint8_t 254140751Swpaul NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *, 255123474Swpaul void *, void *); 256144888Swpaulstatic void NdisGetCurrentSystemTime(uint64_t *); 257144888Swpaulstatic void NdisGetSystemUpTime(uint32_t *); 258215779Sbschmidtstatic uint32_t NdisGetVersion(void); 259151207Swpaulstatic void NdisInitializeString(unicode_string *, char *); 260151207Swpaulstatic void NdisInitAnsiString(ansi_string *, char *); 261151207Swpaulstatic void NdisInitUnicodeString(unicode_string *, uint16_t *); 262151207Swpaulstatic void NdisFreeString(unicode_string *); 263144888Swpaulstatic ndis_status NdisMRemoveMiniport(ndis_handle *); 264144888Swpaulstatic void NdisTerminateWrapper(ndis_handle, void *); 265144888Swpaulstatic void NdisMGetDeviceProperty(ndis_handle, device_object **, 266125551Swpaul device_object **, device_object **, cm_resource_list *, 267125551Swpaul cm_resource_list *); 268144888Swpaulstatic void NdisGetFirstBufferFromPacket(ndis_packet *, 269140751Swpaul ndis_buffer **, void **, uint32_t *, uint32_t *); 270144888Swpaulstatic void NdisGetFirstBufferFromPacketSafe(ndis_packet *, 271140751Swpaul ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t); 272132973Swpaulstatic int ndis_find_sym(linker_file_t, char *, char *, caddr_t *); 273144888Swpaulstatic void NdisOpenFile(ndis_status *, ndis_handle *, uint32_t *, 274151207Swpaul unicode_string *, ndis_physaddr); 275144888Swpaulstatic void NdisMapFile(ndis_status *, void **, ndis_handle); 276144888Swpaulstatic void NdisUnmapFile(ndis_handle); 277144888Swpaulstatic void NdisCloseFile(ndis_handle); 278144888Swpaulstatic uint8_t NdisSystemProcessorCount(void); 279215779Sbschmidtstatic void NdisGetCurrentProcessorCounts(uint32_t *, uint32_t *, uint32_t *); 280144888Swpaulstatic void NdisMIndicateStatusComplete(ndis_handle); 281144888Swpaulstatic void NdisMIndicateStatus(ndis_handle, ndis_status, 282189488Sweongyo void *, uint32_t); 283152626Swpaulstatic uint8_t ndis_intr(kinterrupt *, void *); 284151207Swpaulstatic void ndis_intrhand(kdpc *, ndis_miniport_interrupt *, void *, void *); 285144402Swpaulstatic funcptr ndis_findwrap(funcptr); 286144888Swpaulstatic void NdisCopyFromPacketToPacket(ndis_packet *, 287140751Swpaul uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *); 288144888Swpaulstatic void NdisCopyFromPacketToPacketSafe(ndis_packet *, 289140751Swpaul uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t); 290174240Sthompsastatic void NdisIMCopySendPerPacketInfo(ndis_packet *, ndis_packet *); 291144888Swpaulstatic ndis_status NdisMRegisterDevice(ndis_handle, 292151207Swpaul unicode_string *, unicode_string *, driver_dispatch **, 293125551Swpaul void **, ndis_handle *); 294144888Swpaulstatic ndis_status NdisMDeregisterDevice(ndis_handle); 295144888Swpaulstatic ndis_status 296151207Swpaul NdisMQueryAdapterInstanceName(unicode_string *, ndis_handle); 297144888Swpaulstatic void NdisMRegisterUnloadHandler(ndis_handle, void *); 298144888Swpaulstatic void dummy(void); 299123474Swpaul 300124116Swpaul/* 301124116Swpaul * Some really old drivers do not properly check the return value 302124116Swpaul * from NdisAllocatePacket() and NdisAllocateBuffer() and will 303124116Swpaul * sometimes allocate few more buffers/packets that they originally 304124116Swpaul * requested when they created the pool. To prevent this from being 305124116Swpaul * a problem, we allocate a few extra buffers/packets beyond what 306124116Swpaul * the driver asks for. This #define controls how many. 307124116Swpaul */ 308124116Swpaul#define NDIS_POOL_EXTRA 16 309123474Swpaul 310123474Swpaulint 311123474Swpaulndis_libinit() 312123474Swpaul{ 313141963Swpaul image_patch_table *patch; 314141963Swpaul 315124272Swpaul strcpy(ndis_filepath, "/compat/ndis"); 316141963Swpaul 317141963Swpaul patch = ndis_functbl; 318141963Swpaul while (patch->ipt_func != NULL) { 319141963Swpaul windrv_wrap((funcptr)patch->ipt_func, 320144888Swpaul (funcptr *)&patch->ipt_wrap, 321144888Swpaul patch->ipt_argcnt, patch->ipt_ftype); 322141963Swpaul patch++; 323141963Swpaul } 324141963Swpaul 325198786Srpaulo return (0); 326123474Swpaul} 327123474Swpaul 328123474Swpaulint 329123474Swpaulndis_libfini() 330123474Swpaul{ 331141963Swpaul image_patch_table *patch; 332141963Swpaul 333141963Swpaul patch = ndis_functbl; 334141963Swpaul while (patch->ipt_func != NULL) { 335141963Swpaul windrv_unwrap(patch->ipt_wrap); 336141963Swpaul patch++; 337141963Swpaul } 338141963Swpaul 339198786Srpaulo return (0); 340123474Swpaul} 341123474Swpaul 342144402Swpaulstatic funcptr 343144402Swpaulndis_findwrap(func) 344144402Swpaul funcptr func; 345144402Swpaul{ 346144402Swpaul image_patch_table *patch; 347144402Swpaul 348144428Swpaul patch = ndis_functbl; 349144402Swpaul while (patch->ipt_func != NULL) { 350144402Swpaul if ((funcptr)patch->ipt_func == func) 351198786Srpaulo return ((funcptr)patch->ipt_wrap); 352144402Swpaul patch++; 353144402Swpaul } 354144402Swpaul 355198786Srpaulo return (NULL); 356144402Swpaul} 357144402Swpaul 358123474Swpaul/* 359141524Swpaul * This routine does the messy Windows Driver Model device attachment 360141524Swpaul * stuff on behalf of NDIS drivers. We register our own AddDevice 361141524Swpaul * routine here 362141524Swpaul */ 363144888Swpaulstatic void 364141524SwpaulNdisInitializeWrapper(wrapper, drv, path, unused) 365125551Swpaul ndis_handle *wrapper; 366141524Swpaul driver_object *drv; 367123474Swpaul void *path; 368123474Swpaul void *unused; 369123474Swpaul{ 370141524Swpaul /* 371141524Swpaul * As of yet, I haven't come up with a compelling 372141524Swpaul * reason to define a private NDIS wrapper structure, 373141524Swpaul * so we use a pointer to the driver object as the 374141524Swpaul * wrapper handle. The driver object has the miniport 375141524Swpaul * characteristics struct for this driver hung off it 376141524Swpaul * via IoAllocateDriverObjectExtension(), and that's 377141524Swpaul * really all the private data we need. 378141524Swpaul */ 379123474Swpaul 380141524Swpaul *wrapper = drv; 381123474Swpaul 382141524Swpaul /* 383141524Swpaul * If this was really Windows, we'd be registering dispatch 384141524Swpaul * routines for the NDIS miniport module here, but we're 385141524Swpaul * not Windows so all we really need to do is set up an 386141524Swpaul * AddDevice function that'll be invoked when a new device 387141524Swpaul * instance appears. 388141524Swpaul */ 389141524Swpaul 390141524Swpaul drv->dro_driverext->dre_adddevicefunc = NdisAddDevice; 391123474Swpaul} 392123474Swpaul 393144888Swpaulstatic void 394140751SwpaulNdisTerminateWrapper(handle, syspec) 395123526Swpaul ndis_handle handle; 396123526Swpaul void *syspec; 397123526Swpaul{ 398141524Swpaul /* Nothing to see here, move along. */ 399123526Swpaul} 400123526Swpaul 401144888Swpaulstatic ndis_status 402140751SwpaulNdisMRegisterMiniport(handle, characteristics, len) 403123474Swpaul ndis_handle handle; 404123474Swpaul ndis_miniport_characteristics *characteristics; 405123474Swpaul int len; 406123474Swpaul{ 407141524Swpaul ndis_miniport_characteristics *ch = NULL; 408141524Swpaul driver_object *drv; 409123474Swpaul 410141524Swpaul drv = (driver_object *)handle; 411141524Swpaul 412141524Swpaul /* 413141524Swpaul * We need to save the NDIS miniport characteristics 414141524Swpaul * somewhere. This data is per-driver, not per-device 415141524Swpaul * (all devices handled by the same driver have the 416141524Swpaul * same characteristics) so we hook it onto the driver 417141524Swpaul * object using IoAllocateDriverObjectExtension(). 418141524Swpaul * The extra extension info is automagically deleted when 419141524Swpaul * the driver is unloaded (see windrv_unload()). 420141524Swpaul */ 421141524Swpaul 422141524Swpaul if (IoAllocateDriverObjectExtension(drv, (void *)1, 423141524Swpaul sizeof(ndis_miniport_characteristics), (void **)&ch) != 424151207Swpaul STATUS_SUCCESS) { 425198786Srpaulo return (NDIS_STATUS_RESOURCES); 426151207Swpaul } 427141524Swpaul 428141524Swpaul bzero((char *)ch, sizeof(ndis_miniport_characteristics)); 429141524Swpaul 430141524Swpaul bcopy((char *)characteristics, (char *)ch, len); 431141524Swpaul 432141524Swpaul if (ch->nmc_version_major < 5 || ch->nmc_version_minor < 1) { 433141524Swpaul ch->nmc_shutdown_handler = NULL; 434141524Swpaul ch->nmc_canceltxpkts_handler = NULL; 435141524Swpaul ch->nmc_pnpevent_handler = NULL; 436125551Swpaul } 437125551Swpaul 438198786Srpaulo return (NDIS_STATUS_SUCCESS); 439123474Swpaul} 440123474Swpaul 441144888Swpaulstatic ndis_status 442140751SwpaulNdisAllocateMemoryWithTag(vaddr, len, tag) 443123474Swpaul void **vaddr; 444123474Swpaul uint32_t len; 445123474Swpaul uint32_t tag; 446123474Swpaul{ 447123474Swpaul void *mem; 448123474Swpaul 449141524Swpaul mem = ExAllocatePoolWithTag(NonPagedPool, len, tag); 450151207Swpaul if (mem == NULL) { 451198786Srpaulo return (NDIS_STATUS_RESOURCES); 452151207Swpaul } 453123474Swpaul *vaddr = mem; 454123474Swpaul 455198786Srpaulo return (NDIS_STATUS_SUCCESS); 456123474Swpaul} 457123474Swpaul 458144888Swpaulstatic ndis_status 459140751SwpaulNdisAllocateMemory(vaddr, len, flags, highaddr) 460123474Swpaul void **vaddr; 461123474Swpaul uint32_t len; 462123474Swpaul uint32_t flags; 463123474Swpaul ndis_physaddr highaddr; 464123474Swpaul{ 465123474Swpaul void *mem; 466123474Swpaul 467141524Swpaul mem = ExAllocatePoolWithTag(NonPagedPool, len, 0); 468123474Swpaul if (mem == NULL) 469198786Srpaulo return (NDIS_STATUS_RESOURCES); 470123474Swpaul *vaddr = mem; 471123474Swpaul 472198786Srpaulo return (NDIS_STATUS_SUCCESS); 473123474Swpaul} 474123474Swpaul 475144888Swpaulstatic void 476140751SwpaulNdisFreeMemory(vaddr, len, flags) 477123474Swpaul void *vaddr; 478123474Swpaul uint32_t len; 479123474Swpaul uint32_t flags; 480123474Swpaul{ 481123474Swpaul if (len == 0) 482123474Swpaul return; 483125551Swpaul 484141524Swpaul ExFreePool(vaddr); 485123474Swpaul} 486123474Swpaul 487144888Swpaulstatic ndis_status 488140751SwpaulNdisMSetAttributesEx(adapter_handle, adapter_ctx, hangsecs, 489123474Swpaul flags, iftype) 490123474Swpaul ndis_handle adapter_handle; 491123474Swpaul ndis_handle adapter_ctx; 492123474Swpaul uint32_t hangsecs; 493123474Swpaul uint32_t flags; 494123474Swpaul ndis_interface_type iftype; 495123474Swpaul{ 496123474Swpaul ndis_miniport_block *block; 497123474Swpaul 498123474Swpaul /* 499123474Swpaul * Save the adapter context, we need it for calling 500123474Swpaul * the driver's internal functions. 501123474Swpaul */ 502123474Swpaul block = (ndis_miniport_block *)adapter_handle; 503123474Swpaul block->nmb_miniportadapterctx = adapter_ctx; 504123474Swpaul block->nmb_checkforhangsecs = hangsecs; 505126833Swpaul block->nmb_flags = flags; 506123474Swpaul 507198786Srpaulo return (NDIS_STATUS_SUCCESS); 508123474Swpaul} 509123474Swpaul 510144888Swpaulstatic void 511140751SwpaulNdisOpenConfiguration(status, cfg, wrapctx) 512123474Swpaul ndis_status *status; 513123474Swpaul ndis_handle *cfg; 514123474Swpaul ndis_handle wrapctx; 515123474Swpaul{ 516123474Swpaul *cfg = wrapctx; 517123474Swpaul *status = NDIS_STATUS_SUCCESS; 518123474Swpaul} 519123474Swpaul 520144888Swpaulstatic void 521140751SwpaulNdisOpenConfigurationKeyByName(status, cfg, subkey, subhandle) 522123526Swpaul ndis_status *status; 523123526Swpaul ndis_handle cfg; 524151207Swpaul unicode_string *subkey; 525123526Swpaul ndis_handle *subhandle; 526123526Swpaul{ 527123526Swpaul *subhandle = cfg; 528123526Swpaul *status = NDIS_STATUS_SUCCESS; 529123526Swpaul} 530123526Swpaul 531144888Swpaulstatic void 532140751SwpaulNdisOpenConfigurationKeyByIndex(status, cfg, idx, subkey, subhandle) 533123526Swpaul ndis_status *status; 534123526Swpaul ndis_handle cfg; 535123526Swpaul uint32_t idx; 536151207Swpaul unicode_string *subkey; 537123526Swpaul ndis_handle *subhandle; 538123526Swpaul{ 539123526Swpaul *status = NDIS_STATUS_FAILURE; 540123526Swpaul} 541123526Swpaul 542123474Swpaulstatic ndis_status 543123474Swpaulndis_encode_parm(block, oid, type, parm) 544123474Swpaul ndis_miniport_block *block; 545189488Sweongyo struct sysctl_oid *oid; 546123474Swpaul ndis_parm_type type; 547123474Swpaul ndis_config_parm **parm; 548123474Swpaul{ 549151207Swpaul ndis_config_parm *p; 550151207Swpaul ndis_parmlist_entry *np; 551151207Swpaul unicode_string *us; 552151207Swpaul ansi_string as; 553127248Swpaul int base = 0; 554151207Swpaul uint32_t val; 555151207Swpaul char tmp[32]; 556123474Swpaul 557151207Swpaul np = ExAllocatePoolWithTag(NonPagedPool, 558151207Swpaul sizeof(ndis_parmlist_entry), 0); 559151207Swpaul if (np == NULL) 560198786Srpaulo return (NDIS_STATUS_RESOURCES); 561151207Swpaul InsertHeadList((&block->nmb_parmlist), (&np->np_list)); 562151207Swpaul *parm = p = &np->np_parm; 563123474Swpaul 564123474Swpaul switch(type) { 565123474Swpaul case ndis_parm_string: 566151207Swpaul /* See if this might be a number. */ 567151207Swpaul val = strtoul((char *)oid->oid_arg1, NULL, 10); 568151207Swpaul us = &p->ncp_parmdata.ncp_stringdata; 569151207Swpaul p->ncp_type = ndis_parm_string; 570151207Swpaul if (val) { 571151207Swpaul snprintf(tmp, 32, "%x", val); 572151207Swpaul RtlInitAnsiString(&as, tmp); 573151207Swpaul } else { 574151207Swpaul RtlInitAnsiString(&as, (char *)oid->oid_arg1); 575151207Swpaul } 576151207Swpaul 577151207Swpaul if (RtlAnsiStringToUnicodeString(us, &as, TRUE)) { 578151207Swpaul ExFreePool(np); 579198786Srpaulo return (NDIS_STATUS_RESOURCES); 580151207Swpaul } 581123474Swpaul break; 582123474Swpaul case ndis_parm_int: 583127248Swpaul if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) 584127248Swpaul base = 16; 585127248Swpaul else 586127248Swpaul base = 10; 587151207Swpaul p->ncp_type = ndis_parm_int; 588151207Swpaul p->ncp_parmdata.ncp_intdata = 589127248Swpaul strtol((char *)oid->oid_arg1, NULL, base); 590123474Swpaul break; 591123474Swpaul case ndis_parm_hexint: 592151207Swpaul#ifdef notdef 593127248Swpaul if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) 594127248Swpaul base = 16; 595127248Swpaul else 596127248Swpaul base = 10; 597151207Swpaul#endif 598151207Swpaul base = 16; 599151207Swpaul p->ncp_type = ndis_parm_hexint; 600151207Swpaul p->ncp_parmdata.ncp_intdata = 601127248Swpaul strtoul((char *)oid->oid_arg1, NULL, base); 602123474Swpaul break; 603123474Swpaul default: 604198786Srpaulo return (NDIS_STATUS_FAILURE); 605123474Swpaul break; 606123474Swpaul } 607123474Swpaul 608198786Srpaulo return (NDIS_STATUS_SUCCESS); 609123474Swpaul} 610123474Swpaul 611144888Swpaulstatic void 612140751SwpaulNdisReadConfiguration(status, parm, cfg, key, type) 613123474Swpaul ndis_status *status; 614123474Swpaul ndis_config_parm **parm; 615123474Swpaul ndis_handle cfg; 616151207Swpaul unicode_string *key; 617123474Swpaul ndis_parm_type type; 618123474Swpaul{ 619123474Swpaul char *keystr = NULL; 620123474Swpaul ndis_miniport_block *block; 621123474Swpaul struct ndis_softc *sc; 622189488Sweongyo struct sysctl_oid *oidp; 623123474Swpaul struct sysctl_ctx_entry *e; 624151207Swpaul ansi_string as; 625123474Swpaul 626123474Swpaul block = (ndis_miniport_block *)cfg; 627141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 628123474Swpaul 629141524Swpaul if (key->us_len == 0 || key->us_buf == NULL) { 630124100Swpaul *status = NDIS_STATUS_FAILURE; 631124100Swpaul return; 632124100Swpaul } 633124100Swpaul 634151207Swpaul if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { 635151207Swpaul *status = NDIS_STATUS_RESOURCES; 636151207Swpaul return; 637151207Swpaul } 638123474Swpaul 639151207Swpaul keystr = as.as_buf; 640151207Swpaul 641123474Swpaul /* 642123474Swpaul * See if registry key is already in a list of known keys 643123474Swpaul * included with the driver. 644123474Swpaul */ 645130097Sdes TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { 646123474Swpaul oidp = e->entry; 647168421Spjd if (strcasecmp(oidp->oid_name, keystr) == 0) { 648123488Swpaul if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { 649151207Swpaul RtlFreeAnsiString(&as); 650123488Swpaul *status = NDIS_STATUS_FAILURE; 651123488Swpaul return; 652123488Swpaul } 653151207Swpaul 654123474Swpaul *status = ndis_encode_parm(block, oidp, type, parm); 655151207Swpaul RtlFreeAnsiString(&as); 656123474Swpaul return; 657123474Swpaul } 658123474Swpaul } 659123474Swpaul 660123474Swpaul /* 661123474Swpaul * If the key didn't match, add it to the list of dynamically 662123474Swpaul * created ones. Sometimes, drivers refer to registry keys 663123474Swpaul * that aren't documented in their .INF files. These keys 664123474Swpaul * are supposed to be created by some sort of utility or 665123474Swpaul * control panel snap-in that comes with the driver software. 666123474Swpaul * Sometimes it's useful to be able to manipulate these. 667123474Swpaul * If the driver requests the key in the form of a string, 668123474Swpaul * make its default value an empty string, otherwise default 669123474Swpaul * it to "0". 670123474Swpaul */ 671123474Swpaul 672123474Swpaul if (type == ndis_parm_int || type == ndis_parm_hexint) 673123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic integer key)", 674123488Swpaul "UNSET", CTLFLAG_RW); 675123474Swpaul else 676123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic string key)", 677123488Swpaul "UNSET", CTLFLAG_RW); 678123474Swpaul 679151207Swpaul RtlFreeAnsiString(&as); 680123474Swpaul *status = NDIS_STATUS_FAILURE; 681123474Swpaul} 682123474Swpaul 683123526Swpaulstatic ndis_status 684123526Swpaulndis_decode_parm(block, parm, val) 685123526Swpaul ndis_miniport_block *block; 686123526Swpaul ndis_config_parm *parm; 687123526Swpaul char *val; 688123526Swpaul{ 689151207Swpaul unicode_string *ustr; 690151207Swpaul ansi_string as; 691123526Swpaul 692123526Swpaul switch(parm->ncp_type) { 693123526Swpaul case ndis_parm_string: 694123526Swpaul ustr = &parm->ncp_parmdata.ncp_stringdata; 695151207Swpaul if (RtlUnicodeStringToAnsiString(&as, ustr, TRUE)) 696198786Srpaulo return (NDIS_STATUS_RESOURCES); 697151207Swpaul bcopy(as.as_buf, val, as.as_len); 698151207Swpaul RtlFreeAnsiString(&as); 699123526Swpaul break; 700123526Swpaul case ndis_parm_int: 701124697Swpaul sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata); 702123526Swpaul break; 703123526Swpaul case ndis_parm_hexint: 704123526Swpaul sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata); 705123526Swpaul break; 706123526Swpaul default: 707198786Srpaulo return (NDIS_STATUS_FAILURE); 708123526Swpaul break; 709123526Swpaul } 710198786Srpaulo return (NDIS_STATUS_SUCCESS); 711123526Swpaul} 712123526Swpaul 713144888Swpaulstatic void 714140751SwpaulNdisWriteConfiguration(status, cfg, key, parm) 715123526Swpaul ndis_status *status; 716123526Swpaul ndis_handle cfg; 717151207Swpaul unicode_string *key; 718123526Swpaul ndis_config_parm *parm; 719123526Swpaul{ 720151207Swpaul ansi_string as; 721123526Swpaul char *keystr = NULL; 722123526Swpaul ndis_miniport_block *block; 723123526Swpaul struct ndis_softc *sc; 724189488Sweongyo struct sysctl_oid *oidp; 725123526Swpaul struct sysctl_ctx_entry *e; 726123526Swpaul char val[256]; 727123526Swpaul 728123526Swpaul block = (ndis_miniport_block *)cfg; 729141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 730123526Swpaul 731151207Swpaul if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { 732151207Swpaul *status = NDIS_STATUS_RESOURCES; 733151207Swpaul return; 734151207Swpaul } 735123526Swpaul 736151207Swpaul keystr = as.as_buf; 737151207Swpaul 738123526Swpaul /* Decode the parameter into a string. */ 739124697Swpaul bzero(val, sizeof(val)); 740123526Swpaul *status = ndis_decode_parm(block, parm, val); 741123526Swpaul if (*status != NDIS_STATUS_SUCCESS) { 742151207Swpaul RtlFreeAnsiString(&as); 743123526Swpaul return; 744123526Swpaul } 745123526Swpaul 746123526Swpaul /* See if the key already exists. */ 747123526Swpaul 748130097Sdes TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { 749123526Swpaul oidp = e->entry; 750168421Spjd if (strcasecmp(oidp->oid_name, keystr) == 0) { 751123526Swpaul /* Found it, set the value. */ 752123526Swpaul strcpy((char *)oidp->oid_arg1, val); 753151207Swpaul RtlFreeAnsiString(&as); 754123526Swpaul return; 755123526Swpaul } 756123526Swpaul } 757123526Swpaul 758123526Swpaul /* Not found, add a new key with the specified value. */ 759123526Swpaul ndis_add_sysctl(sc, keystr, "(dynamically set key)", 760123526Swpaul val, CTLFLAG_RW); 761123526Swpaul 762151207Swpaul RtlFreeAnsiString(&as); 763123526Swpaul *status = NDIS_STATUS_SUCCESS; 764123526Swpaul} 765123526Swpaul 766144888Swpaulstatic void 767140751SwpaulNdisCloseConfiguration(cfg) 768123474Swpaul ndis_handle cfg; 769123474Swpaul{ 770151207Swpaul list_entry *e; 771151207Swpaul ndis_parmlist_entry *pe; 772151207Swpaul ndis_miniport_block *block; 773151207Swpaul ndis_config_parm *p; 774151207Swpaul 775151207Swpaul block = (ndis_miniport_block *)cfg; 776151207Swpaul 777151207Swpaul while (!IsListEmpty(&block->nmb_parmlist)) { 778189488Sweongyo e = RemoveHeadList(&block->nmb_parmlist); 779189488Sweongyo pe = CONTAINING_RECORD(e, ndis_parmlist_entry, np_list); 780151207Swpaul p = &pe->np_parm; 781151207Swpaul if (p->ncp_type == ndis_parm_string) 782151207Swpaul RtlFreeUnicodeString(&p->ncp_parmdata.ncp_stringdata); 783151207Swpaul ExFreePool(e); 784151207Swpaul } 785123474Swpaul} 786123474Swpaul 787128229Swpaul/* 788128229Swpaul * Initialize a Windows spinlock. 789128229Swpaul */ 790144888Swpaulstatic void 791140751SwpaulNdisAllocateSpinLock(lock) 792123474Swpaul ndis_spin_lock *lock; 793123474Swpaul{ 794140751Swpaul KeInitializeSpinLock(&lock->nsl_spinlock); 795128229Swpaul lock->nsl_kirql = 0; 796123474Swpaul} 797123474Swpaul 798128229Swpaul/* 799128229Swpaul * Destroy a Windows spinlock. This is a no-op for now. There are two reasons 800128229Swpaul * for this. One is that it's sort of superfluous: we don't have to do anything 801128229Swpaul * special to deallocate the spinlock. The other is that there are some buggy 802128229Swpaul * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on 803128229Swpaul * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm 804128229Swpaul * talking to you.) 805128229Swpaul */ 806144888Swpaulstatic void 807140751SwpaulNdisFreeSpinLock(lock) 808123474Swpaul ndis_spin_lock *lock; 809123474Swpaul{ 810128229Swpaul#ifdef notdef 811140751Swpaul KeInitializeSpinLock(&lock->nsl_spinlock); 812128229Swpaul lock->nsl_kirql = 0; 813128229Swpaul#endif 814123474Swpaul} 815123474Swpaul 816128229Swpaul/* 817128229Swpaul * Acquire a spinlock from IRQL <= DISPATCH_LEVEL. 818128229Swpaul */ 819128229Swpaul 820144888Swpaulstatic void 821140751SwpaulNdisAcquireSpinLock(lock) 822123474Swpaul ndis_spin_lock *lock; 823123474Swpaul{ 824140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 825123474Swpaul} 826123474Swpaul 827128229Swpaul/* 828128229Swpaul * Release a spinlock from IRQL == DISPATCH_LEVEL. 829128229Swpaul */ 830128229Swpaul 831144888Swpaulstatic void 832140751SwpaulNdisReleaseSpinLock(lock) 833123474Swpaul ndis_spin_lock *lock; 834123474Swpaul{ 835140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 836123474Swpaul} 837123474Swpaul 838128229Swpaul/* 839128229Swpaul * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL. 840128229Swpaul */ 841144888Swpaulstatic void 842140751SwpaulNdisDprAcquireSpinLock(lock) 843128229Swpaul ndis_spin_lock *lock; 844128229Swpaul{ 845144174Swpaul KeAcquireSpinLockAtDpcLevel(&lock->nsl_spinlock); 846128229Swpaul} 847128229Swpaul 848128229Swpaul/* 849128229Swpaul * Release a spinlock without leaving IRQL == DISPATCH_LEVEL. 850128229Swpaul */ 851144888Swpaulstatic void 852140751SwpaulNdisDprReleaseSpinLock(lock) 853128229Swpaul ndis_spin_lock *lock; 854128229Swpaul{ 855144174Swpaul KeReleaseSpinLockFromDpcLevel(&lock->nsl_spinlock); 856128229Swpaul} 857128229Swpaul 858145895Swpaulstatic void 859145895SwpaulNdisInitializeReadWriteLock(lock) 860145895Swpaul ndis_rw_lock *lock; 861145895Swpaul{ 862145895Swpaul KeInitializeSpinLock(&lock->nrl_spinlock); 863145895Swpaul bzero((char *)&lock->nrl_rsvd, sizeof(lock->nrl_rsvd)); 864145895Swpaul} 865145895Swpaul 866145895Swpaulstatic void 867189004SrdivackyNdisAcquireReadWriteLock(ndis_rw_lock *lock, uint8_t writeacc, 868189004Srdivacky ndis_lock_state *state) 869145895Swpaul{ 870145895Swpaul if (writeacc == TRUE) { 871145895Swpaul KeAcquireSpinLock(&lock->nrl_spinlock, &state->nls_oldirql); 872145895Swpaul lock->nrl_rsvd[0]++; 873145895Swpaul } else 874145895Swpaul lock->nrl_rsvd[1]++; 875145895Swpaul} 876145895Swpaul 877145895Swpaulstatic void 878145895SwpaulNdisReleaseReadWriteLock(lock, state) 879145895Swpaul ndis_rw_lock *lock; 880145895Swpaul ndis_lock_state *state; 881145895Swpaul{ 882145895Swpaul if (lock->nrl_rsvd[0]) { 883145895Swpaul lock->nrl_rsvd[0]--; 884145895Swpaul KeReleaseSpinLock(&lock->nrl_spinlock, state->nls_oldirql); 885145895Swpaul } else 886145895Swpaul lock->nrl_rsvd[1]--; 887145895Swpaul} 888145895Swpaul 889144888Swpaulstatic uint32_t 890140751SwpaulNdisReadPciSlotInformation(adapter, slot, offset, buf, len) 891123474Swpaul ndis_handle adapter; 892123474Swpaul uint32_t slot; 893123474Swpaul uint32_t offset; 894123474Swpaul void *buf; 895123474Swpaul uint32_t len; 896123474Swpaul{ 897123474Swpaul ndis_miniport_block *block; 898123474Swpaul int i; 899123474Swpaul char *dest; 900141524Swpaul device_t dev; 901123474Swpaul 902123474Swpaul block = (ndis_miniport_block *)adapter; 903123474Swpaul dest = buf; 904141524Swpaul if (block == NULL) 905198786Srpaulo return (0); 906123474Swpaul 907141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 908144174Swpaul 909144174Swpaul /* 910144174Swpaul * I have a test system consisting of a Sun w2100z 911144174Swpaul * dual 2.4Ghz Opteron machine and an Atheros 802.11a/b/g 912144174Swpaul * "Aries" miniPCI NIC. (The NIC is installed in the 913144174Swpaul * machine using a miniPCI to PCI bus adapter card.) 914144174Swpaul * When running in SMP mode, I found that 915144174Swpaul * performing a large number of consecutive calls to 916144174Swpaul * NdisReadPciSlotInformation() would result in a 917144174Swpaul * sudden system reset (or in some cases a freeze). 918144174Swpaul * My suspicion is that the multiple reads are somehow 919144174Swpaul * triggering a fatal PCI bus error that leads to a 920144174Swpaul * machine check. The 1us delay in the loop below 921144174Swpaul * seems to prevent this problem. 922144174Swpaul */ 923144174Swpaul 924144174Swpaul for (i = 0; i < len; i++) { 925144174Swpaul DELAY(1); 926141524Swpaul dest[i] = pci_read_config(dev, i + offset, 1); 927144174Swpaul } 928123474Swpaul 929198786Srpaulo return (len); 930123474Swpaul} 931123474Swpaul 932144888Swpaulstatic uint32_t 933140751SwpaulNdisWritePciSlotInformation(adapter, slot, offset, buf, len) 934123474Swpaul ndis_handle adapter; 935123474Swpaul uint32_t slot; 936123474Swpaul uint32_t offset; 937123474Swpaul void *buf; 938123474Swpaul uint32_t len; 939123474Swpaul{ 940123474Swpaul ndis_miniport_block *block; 941123474Swpaul int i; 942123474Swpaul char *dest; 943141524Swpaul device_t dev; 944123474Swpaul 945123474Swpaul block = (ndis_miniport_block *)adapter; 946123474Swpaul dest = buf; 947123474Swpaul 948141524Swpaul if (block == NULL) 949198786Srpaulo return (0); 950123474Swpaul 951141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 952144174Swpaul for (i = 0; i < len; i++) { 953144174Swpaul DELAY(1); 954141524Swpaul pci_write_config(dev, i + offset, dest[i], 1); 955144174Swpaul } 956123474Swpaul 957198786Srpaulo return (len); 958123474Swpaul} 959123474Swpaul 960123474Swpaul/* 961123474Swpaul * The errorlog routine uses a variable argument list, so we 962123474Swpaul * have to declare it this way. 963123474Swpaul */ 964151207Swpaul 965124228Swpaul#define ERRMSGLEN 512 966123474Swpaulstatic void 967140751SwpaulNdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, 968123474Swpaul uint32_t numerrors, ...) 969123474Swpaul{ 970123474Swpaul ndis_miniport_block *block; 971123474Swpaul va_list ap; 972124173Swpaul int i, error; 973151207Swpaul char *str = NULL; 974124173Swpaul uint16_t flags; 975141524Swpaul device_t dev; 976141963Swpaul driver_object *drv; 977145895Swpaul struct ndis_softc *sc; 978145895Swpaul struct ifnet *ifp; 979151207Swpaul unicode_string us; 980151606Swpaul ansi_string as = { 0, 0, NULL }; 981123474Swpaul 982123474Swpaul block = (ndis_miniport_block *)adapter; 983141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 984145485Swpaul drv = block->nmb_deviceobj->do_drvobj; 985145895Swpaul sc = device_get_softc(dev); 986147256Sbrooks ifp = sc->ifp; 987123474Swpaul 988179720Sweongyo if (ifp != NULL && ifp->if_flags & IFF_DEBUG) { 989151977Swpaul error = pe_get_message((vm_offset_t)drv->dro_driverstart, 990151977Swpaul code, &str, &i, &flags); 991151977Swpaul if (error == 0) { 992151977Swpaul if (flags & MESSAGE_RESOURCE_UNICODE) { 993151977Swpaul RtlInitUnicodeString(&us, (uint16_t *)str); 994151977Swpaul if (RtlUnicodeStringToAnsiString(&as, 995151977Swpaul &us, TRUE) == STATUS_SUCCESS) 996151977Swpaul str = as.as_buf; 997151977Swpaul else 998151977Swpaul str = NULL; 999151977Swpaul } 1000151977Swpaul } 1001151977Swpaul } 1002145895Swpaul 1003198786Srpaulo device_printf(dev, "NDIS ERROR: %x (%s)\n", code, 1004124165Swpaul str == NULL ? "unknown error" : str); 1005123474Swpaul 1006179720Sweongyo if (ifp != NULL && ifp->if_flags & IFF_DEBUG) { 1007198786Srpaulo device_printf(dev, "NDIS NUMERRORS: %x\n", numerrors); 1008145895Swpaul va_start(ap, numerrors); 1009145895Swpaul for (i = 0; i < numerrors; i++) 1010198786Srpaulo device_printf(dev, "argptr: %p\n", 1011145895Swpaul va_arg(ap, void *)); 1012145895Swpaul va_end(ap); 1013145895Swpaul } 1014123474Swpaul 1015151606Swpaul if (as.as_len) 1016151207Swpaul RtlFreeAnsiString(&as); 1017123474Swpaul} 1018123474Swpaul 1019123474Swpaulstatic void 1020123474Swpaulndis_map_cb(arg, segs, nseg, error) 1021123474Swpaul void *arg; 1022123474Swpaul bus_dma_segment_t *segs; 1023123474Swpaul int nseg; 1024123474Swpaul int error; 1025123474Swpaul{ 1026123474Swpaul struct ndis_map_arg *ctx; 1027123474Swpaul int i; 1028123474Swpaul 1029123474Swpaul if (error) 1030123474Swpaul return; 1031123474Swpaul 1032123474Swpaul ctx = arg; 1033123474Swpaul 1034123474Swpaul for (i = 0; i < nseg; i++) { 1035123474Swpaul ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr; 1036123474Swpaul ctx->nma_fraglist[i].npu_len = segs[i].ds_len; 1037123474Swpaul } 1038123474Swpaul 1039123474Swpaul ctx->nma_cnt = nseg; 1040123474Swpaul} 1041123474Swpaul 1042144888Swpaulstatic void 1043189004SrdivackyNdisMStartBufferPhysicalMapping(ndis_handle adapter, ndis_buffer *buf, 1044189004Srdivacky uint32_t mapreg, uint8_t writedev, ndis_paddr_unit *addrarray, 1045189004Srdivacky uint32_t *arraysize) 1046123474Swpaul{ 1047123474Swpaul ndis_miniport_block *block; 1048123474Swpaul struct ndis_softc *sc; 1049123474Swpaul struct ndis_map_arg nma; 1050123474Swpaul bus_dmamap_t map; 1051123474Swpaul int error; 1052123474Swpaul 1053123474Swpaul if (adapter == NULL) 1054123474Swpaul return; 1055123474Swpaul 1056123474Swpaul block = (ndis_miniport_block *)adapter; 1057141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1058123474Swpaul 1059123474Swpaul if (mapreg > sc->ndis_mmapcnt) 1060123474Swpaul return; 1061123474Swpaul 1062123474Swpaul map = sc->ndis_mmaps[mapreg]; 1063123474Swpaul nma.nma_fraglist = addrarray; 1064123474Swpaul 1065123474Swpaul error = bus_dmamap_load(sc->ndis_mtag, map, 1066140751Swpaul MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf), ndis_map_cb, 1067123474Swpaul (void *)&nma, BUS_DMA_NOWAIT); 1068123474Swpaul 1069123474Swpaul if (error) 1070123474Swpaul return; 1071123474Swpaul 1072123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 1073123474Swpaul writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); 1074123474Swpaul 1075123474Swpaul *arraysize = nma.nma_cnt; 1076123474Swpaul} 1077123474Swpaul 1078144888Swpaulstatic void 1079140751SwpaulNdisMCompleteBufferPhysicalMapping(adapter, buf, mapreg) 1080123474Swpaul ndis_handle adapter; 1081123474Swpaul ndis_buffer *buf; 1082123474Swpaul uint32_t mapreg; 1083123474Swpaul{ 1084123474Swpaul ndis_miniport_block *block; 1085123474Swpaul struct ndis_softc *sc; 1086123474Swpaul bus_dmamap_t map; 1087123474Swpaul 1088123474Swpaul if (adapter == NULL) 1089123474Swpaul return; 1090123474Swpaul 1091123474Swpaul block = (ndis_miniport_block *)adapter; 1092141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1093123474Swpaul 1094123474Swpaul if (mapreg > sc->ndis_mmapcnt) 1095123474Swpaul return; 1096123474Swpaul 1097123474Swpaul map = sc->ndis_mmaps[mapreg]; 1098123474Swpaul 1099123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 1100123474Swpaul BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1101123474Swpaul 1102123474Swpaul bus_dmamap_unload(sc->ndis_mtag, map); 1103123474Swpaul} 1104123474Swpaul 1105125057Swpaul/* 1106144174Swpaul * This is an older (?) timer init routine which doesn't 1107144174Swpaul * accept a miniport context handle. Serialized miniports should 1108144174Swpaul * never call this function. 1109125057Swpaul */ 1110125057Swpaul 1111144888Swpaulstatic void 1112140751SwpaulNdisInitializeTimer(timer, func, ctx) 1113125057Swpaul ndis_timer *timer; 1114125057Swpaul ndis_timer_function func; 1115125057Swpaul void *ctx; 1116125057Swpaul{ 1117140751Swpaul KeInitializeTimer(&timer->nt_ktimer); 1118140751Swpaul KeInitializeDpc(&timer->nt_kdpc, func, ctx); 1119145895Swpaul KeSetImportanceDpc(&timer->nt_kdpc, KDPC_IMPORTANCE_LOW); 1120125057Swpaul} 1121125057Swpaul 1122144888Swpaulstatic void 1123144174Swpaulndis_timercall(dpc, timer, sysarg1, sysarg2) 1124144174Swpaul kdpc *dpc; 1125144174Swpaul ndis_miniport_timer *timer; 1126144174Swpaul void *sysarg1; 1127144174Swpaul void *sysarg2; 1128144174Swpaul{ 1129144174Swpaul /* 1130144174Swpaul * Since we're called as a DPC, we should be running 1131144174Swpaul * at DISPATCH_LEVEL here. This means to acquire the 1132144174Swpaul * spinlock, we can use KeAcquireSpinLockAtDpcLevel() 1133144174Swpaul * rather than KeAcquireSpinLock(). 1134144174Swpaul */ 1135144174Swpaul if (NDIS_SERIALIZED(timer->nmt_block)) 1136144174Swpaul KeAcquireSpinLockAtDpcLevel(&timer->nmt_block->nmb_lock); 1137144174Swpaul 1138144174Swpaul MSCALL4(timer->nmt_timerfunc, dpc, timer->nmt_timerctx, 1139144174Swpaul sysarg1, sysarg2); 1140144174Swpaul 1141144174Swpaul if (NDIS_SERIALIZED(timer->nmt_block)) 1142144174Swpaul KeReleaseSpinLockFromDpcLevel(&timer->nmt_block->nmb_lock); 1143144174Swpaul} 1144144174Swpaul 1145144174Swpaul/* 1146144174Swpaul * For a long time I wondered why there were two NDIS timer initialization 1147144174Swpaul * routines, and why this one needed an NDIS_MINIPORT_TIMER and the 1148144174Swpaul * MiniportAdapterHandle. The NDIS_MINIPORT_TIMER has its own callout 1149144174Swpaul * function and context pointers separate from those in the DPC, which 1150144174Swpaul * allows for another level of indirection: when the timer fires, we 1151144174Swpaul * can have our own timer function invoked, and from there we can call 1152144174Swpaul * the driver's function. But why go to all that trouble? Then it hit 1153144174Swpaul * me: for serialized miniports, the timer callouts are not re-entrant. 1154144174Swpaul * By trapping the callouts and having access to the MiniportAdapterHandle, 1155144174Swpaul * we can protect the driver callouts by acquiring the NDIS serialization 1156144174Swpaul * lock. This is essential for allowing serialized miniports to work 1157144174Swpaul * correctly on SMP systems. On UP hosts, setting IRQL to DISPATCH_LEVEL 1158144174Swpaul * is enough to prevent other threads from pre-empting you, but with 1159144174Swpaul * SMP, you must acquire a lock as well, otherwise the other CPU is 1160144174Swpaul * free to clobber you. 1161144174Swpaul */ 1162144888Swpaulstatic void 1163140751SwpaulNdisMInitializeTimer(timer, handle, func, ctx) 1164123474Swpaul ndis_miniport_timer *timer; 1165127248Swpaul ndis_handle handle; 1166123474Swpaul ndis_timer_function func; 1167123474Swpaul void *ctx; 1168123474Swpaul{ 1169186507Sweongyo ndis_miniport_block *block; 1170186507Sweongyo struct ndis_softc *sc; 1171186507Sweongyo 1172186507Sweongyo block = (ndis_miniport_block *)handle; 1173186507Sweongyo sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1174186507Sweongyo 1175144174Swpaul /* Save the driver's funcptr and context */ 1176123474Swpaul 1177127248Swpaul timer->nmt_timerfunc = func; 1178127248Swpaul timer->nmt_timerctx = ctx; 1179127248Swpaul timer->nmt_block = handle; 1180123821Swpaul 1181144402Swpaul /* 1182144402Swpaul * Set up the timer so it will call our intermediate DPC. 1183144402Swpaul * Be sure to use the wrapped entry point, since 1184144402Swpaul * ntoskrnl_run_dpc() expects to invoke a function with 1185144402Swpaul * Microsoft calling conventions. 1186144402Swpaul */ 1187140751Swpaul KeInitializeTimer(&timer->nmt_ktimer); 1188144402Swpaul KeInitializeDpc(&timer->nmt_kdpc, 1189144402Swpaul ndis_findwrap((funcptr)ndis_timercall), timer); 1190145895Swpaul timer->nmt_ktimer.k_dpc = &timer->nmt_kdpc; 1191123474Swpaul} 1192123474Swpaul 1193123474Swpaul/* 1194127248Swpaul * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(), 1195127248Swpaul * but the former is just a macro wrapper around the latter. 1196123474Swpaul */ 1197144888Swpaulstatic void 1198140751SwpaulNdisSetTimer(timer, msecs) 1199127248Swpaul ndis_timer *timer; 1200123474Swpaul uint32_t msecs; 1201123474Swpaul{ 1202127248Swpaul /* 1203127248Swpaul * KeSetTimer() wants the period in 1204127248Swpaul * hundred nanosecond intervals. 1205127248Swpaul */ 1206140751Swpaul KeSetTimer(&timer->nt_ktimer, 1207127248Swpaul ((int64_t)msecs * -10000), &timer->nt_kdpc); 1208123474Swpaul} 1209123474Swpaul 1210144888Swpaulstatic void 1211140751SwpaulNdisMSetPeriodicTimer(timer, msecs) 1212123474Swpaul ndis_miniport_timer *timer; 1213123474Swpaul uint32_t msecs; 1214123474Swpaul{ 1215140751Swpaul KeSetTimerEx(&timer->nmt_ktimer, 1216127248Swpaul ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc); 1217123474Swpaul} 1218123474Swpaul 1219127248Swpaul/* 1220127248Swpaul * Technically, this is really NdisCancelTimer(), but we also 1221127248Swpaul * (ab)use it for NdisMCancelTimer(), since in our implementation 1222127248Swpaul * we don't need the extra info in the ndis_miniport_timer 1223144174Swpaul * structure just to cancel a timer. 1224127248Swpaul */ 1225127248Swpaul 1226144888Swpaulstatic void 1227140751SwpaulNdisMCancelTimer(timer, cancelled) 1228127248Swpaul ndis_timer *timer; 1229123474Swpaul uint8_t *cancelled; 1230123474Swpaul{ 1231186507Sweongyo 1232140751Swpaul *cancelled = KeCancelTimer(&timer->nt_ktimer); 1233123474Swpaul} 1234123474Swpaul 1235144888Swpaulstatic void 1236140751SwpaulNdisMQueryAdapterResources(status, adapter, list, buflen) 1237123474Swpaul ndis_status *status; 1238123474Swpaul ndis_handle adapter; 1239123474Swpaul ndis_resource_list *list; 1240123474Swpaul uint32_t *buflen; 1241123474Swpaul{ 1242123474Swpaul ndis_miniport_block *block; 1243123474Swpaul struct ndis_softc *sc; 1244198819Srpaulo int rsclen; 1245123474Swpaul 1246123474Swpaul block = (ndis_miniport_block *)adapter; 1247141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1248124094Swpaul 1249124094Swpaul rsclen = sizeof(ndis_resource_list) + 1250123474Swpaul (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); 1251124094Swpaul if (*buflen < rsclen) { 1252124094Swpaul *buflen = rsclen; 1253124094Swpaul *status = NDIS_STATUS_INVALID_LENGTH; 1254124094Swpaul return; 1255124094Swpaul } 1256123474Swpaul 1257127887Swpaul bcopy((char *)block->nmb_rlist, (char *)list, rsclen); 1258123474Swpaul *status = NDIS_STATUS_SUCCESS; 1259123474Swpaul} 1260123474Swpaul 1261144888Swpaulstatic ndis_status 1262140751SwpaulNdisMRegisterIoPortRange(offset, adapter, port, numports) 1263123474Swpaul void **offset; 1264123474Swpaul ndis_handle adapter; 1265123474Swpaul uint32_t port; 1266123474Swpaul uint32_t numports; 1267123474Swpaul{ 1268123474Swpaul struct ndis_miniport_block *block; 1269123474Swpaul struct ndis_softc *sc; 1270123474Swpaul 1271123474Swpaul if (adapter == NULL) 1272198786Srpaulo return (NDIS_STATUS_FAILURE); 1273123474Swpaul 1274123474Swpaul block = (ndis_miniport_block *)adapter; 1275141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1276123474Swpaul 1277123474Swpaul if (sc->ndis_res_io == NULL) 1278198786Srpaulo return (NDIS_STATUS_FAILURE); 1279123474Swpaul 1280124454Swpaul /* Don't let the device map more ports than we have. */ 1281124454Swpaul if (rman_get_size(sc->ndis_res_io) < numports) 1282198786Srpaulo return (NDIS_STATUS_INVALID_LENGTH); 1283123474Swpaul 1284123474Swpaul *offset = (void *)rman_get_start(sc->ndis_res_io); 1285123474Swpaul 1286198786Srpaulo return (NDIS_STATUS_SUCCESS); 1287123474Swpaul} 1288123474Swpaul 1289144888Swpaulstatic void 1290140751SwpaulNdisMDeregisterIoPortRange(adapter, port, numports, offset) 1291123474Swpaul ndis_handle adapter; 1292123474Swpaul uint32_t port; 1293123474Swpaul uint32_t numports; 1294123474Swpaul void *offset; 1295123474Swpaul{ 1296123474Swpaul} 1297123474Swpaul 1298144888Swpaulstatic void 1299140751SwpaulNdisReadNetworkAddress(status, addr, addrlen, adapter) 1300123474Swpaul ndis_status *status; 1301123474Swpaul void **addr; 1302123474Swpaul uint32_t *addrlen; 1303123474Swpaul ndis_handle adapter; 1304123474Swpaul{ 1305123474Swpaul struct ndis_softc *sc; 1306123474Swpaul ndis_miniport_block *block; 1307123474Swpaul uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; 1308123474Swpaul 1309123474Swpaul block = (ndis_miniport_block *)adapter; 1310141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1311179009Sweongyo if (sc->ifp == NULL) { 1312179009Sweongyo *status = NDIS_STATUS_FAILURE; 1313179009Sweongyo return; 1314179009Sweongyo } 1315123474Swpaul 1316152423Sru if (sc->ifp->if_addr == NULL || 1317152423Sru bcmp(IF_LLADDR(sc->ifp), empty, ETHER_ADDR_LEN) == 0) 1318123474Swpaul *status = NDIS_STATUS_FAILURE; 1319123474Swpaul else { 1320152315Sru *addr = IF_LLADDR(sc->ifp); 1321123474Swpaul *addrlen = ETHER_ADDR_LEN; 1322123474Swpaul *status = NDIS_STATUS_SUCCESS; 1323123474Swpaul } 1324123474Swpaul} 1325123474Swpaul 1326144888Swpaulstatic ndis_status 1327140751SwpaulNdisQueryMapRegisterCount(bustype, cnt) 1328123848Swpaul uint32_t bustype; 1329123848Swpaul uint32_t *cnt; 1330123848Swpaul{ 1331124097Swpaul *cnt = 8192; 1332198786Srpaulo return (NDIS_STATUS_SUCCESS); 1333123848Swpaul} 1334123848Swpaul 1335144888Swpaulstatic ndis_status 1336189004SrdivackyNdisMAllocateMapRegisters(ndis_handle adapter, uint32_t dmachannel, 1337189004Srdivacky uint8_t dmasize, uint32_t physmapneeded, uint32_t maxmap) 1338123474Swpaul{ 1339123474Swpaul struct ndis_softc *sc; 1340123474Swpaul ndis_miniport_block *block; 1341123474Swpaul int error, i, nseg = NDIS_MAXSEG; 1342123474Swpaul 1343123474Swpaul block = (ndis_miniport_block *)adapter; 1344141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1345123474Swpaul 1346123474Swpaul sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, 1347123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1348123474Swpaul 1349123474Swpaul if (sc->ndis_mmaps == NULL) 1350198786Srpaulo return (NDIS_STATUS_RESOURCES); 1351123474Swpaul 1352123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1353123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1354123474Swpaul NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, 1355123474Swpaul NULL, NULL, &sc->ndis_mtag); 1356123474Swpaul 1357123474Swpaul if (error) { 1358123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1359198786Srpaulo return (NDIS_STATUS_RESOURCES); 1360123474Swpaul } 1361123474Swpaul 1362123474Swpaul for (i = 0; i < physmapneeded; i++) 1363123474Swpaul bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); 1364123474Swpaul 1365123474Swpaul sc->ndis_mmapcnt = physmapneeded; 1366123474Swpaul 1367198786Srpaulo return (NDIS_STATUS_SUCCESS); 1368123474Swpaul} 1369123474Swpaul 1370144888Swpaulstatic void 1371140751SwpaulNdisMFreeMapRegisters(adapter) 1372123474Swpaul ndis_handle adapter; 1373123474Swpaul{ 1374123474Swpaul struct ndis_softc *sc; 1375123474Swpaul ndis_miniport_block *block; 1376123474Swpaul int i; 1377123474Swpaul 1378123474Swpaul block = (ndis_miniport_block *)adapter; 1379141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1380123474Swpaul 1381123474Swpaul for (i = 0; i < sc->ndis_mmapcnt; i++) 1382123474Swpaul bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); 1383123474Swpaul 1384123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1385123474Swpaul 1386123474Swpaul bus_dma_tag_destroy(sc->ndis_mtag); 1387123474Swpaul} 1388123474Swpaul 1389123474Swpaulstatic void 1390123474Swpaulndis_mapshared_cb(arg, segs, nseg, error) 1391123474Swpaul void *arg; 1392123474Swpaul bus_dma_segment_t *segs; 1393123474Swpaul int nseg; 1394123474Swpaul int error; 1395123474Swpaul{ 1396123474Swpaul ndis_physaddr *p; 1397123474Swpaul 1398123474Swpaul if (error || nseg > 1) 1399123474Swpaul return; 1400123474Swpaul 1401123474Swpaul p = arg; 1402123474Swpaul 1403123474Swpaul p->np_quad = segs[0].ds_addr; 1404123474Swpaul} 1405123474Swpaul 1406123474Swpaul/* 1407123474Swpaul * This maps to bus_dmamem_alloc(). 1408123474Swpaul */ 1409145895Swpaul 1410144888Swpaulstatic void 1411189004SrdivackyNdisMAllocateSharedMemory(ndis_handle adapter, uint32_t len, uint8_t cached, 1412189004Srdivacky void **vaddr, ndis_physaddr *paddr) 1413123474Swpaul{ 1414123474Swpaul ndis_miniport_block *block; 1415123474Swpaul struct ndis_softc *sc; 1416123474Swpaul struct ndis_shmem *sh; 1417123474Swpaul int error; 1418123474Swpaul 1419123474Swpaul if (adapter == NULL) 1420123474Swpaul return; 1421123474Swpaul 1422123474Swpaul block = (ndis_miniport_block *)adapter; 1423141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1424123474Swpaul 1425123474Swpaul sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); 1426123474Swpaul if (sh == NULL) 1427123474Swpaul return; 1428123474Swpaul 1429151207Swpaul InitializeListHead(&sh->ndis_list); 1430151207Swpaul 1431131750Swpaul /* 1432131750Swpaul * When performing shared memory allocations, create a tag 1433131750Swpaul * with a lowaddr limit that restricts physical memory mappings 1434131750Swpaul * so that they all fall within the first 1GB of memory. 1435131750Swpaul * At least one device/driver combination (Linksys Instant 1436131750Swpaul * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have 1437131750Swpaul * problems with performing DMA operations with physical 1438141963Swpaul * addresses that lie above the 1GB mark. I don't know if this 1439141963Swpaul * is a hardware limitation or if the addresses are being 1440141963Swpaul * truncated within the driver, but this seems to be the only 1441141963Swpaul * way to make these cards work reliably in systems with more 1442141963Swpaul * than 1GB of physical memory. 1443131750Swpaul */ 1444131750Swpaul 1445123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, 64, 1446131750Swpaul 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL, 1447123474Swpaul NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, 1448123474Swpaul &sh->ndis_stag); 1449123474Swpaul 1450123474Swpaul if (error) { 1451123474Swpaul free(sh, M_DEVBUF); 1452123474Swpaul return; 1453123474Swpaul } 1454123474Swpaul 1455123474Swpaul error = bus_dmamem_alloc(sh->ndis_stag, vaddr, 1456123474Swpaul BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); 1457123474Swpaul 1458123474Swpaul if (error) { 1459123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1460123474Swpaul free(sh, M_DEVBUF); 1461123474Swpaul return; 1462123474Swpaul } 1463123474Swpaul 1464123474Swpaul error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, 1465123474Swpaul len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); 1466123474Swpaul 1467123474Swpaul if (error) { 1468123474Swpaul bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); 1469123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1470123474Swpaul free(sh, M_DEVBUF); 1471123474Swpaul return; 1472123474Swpaul } 1473123474Swpaul 1474145895Swpaul /* 1475145895Swpaul * Save the physical address along with the source address. 1476145895Swpaul * The AirGo MIMO driver will call NdisMFreeSharedMemory() 1477145895Swpaul * with a bogus virtual address sometimes, but with a valid 1478145895Swpaul * physical address. To keep this from causing trouble, we 1479145895Swpaul * use the physical address to as a sanity check in case 1480145895Swpaul * searching based on the virtual address fails. 1481145895Swpaul */ 1482145895Swpaul 1483151207Swpaul NDIS_LOCK(sc); 1484145895Swpaul sh->ndis_paddr.np_quad = paddr->np_quad; 1485123474Swpaul sh->ndis_saddr = *vaddr; 1486151207Swpaul InsertHeadList((&sc->ndis_shlist), (&sh->ndis_list)); 1487151207Swpaul NDIS_UNLOCK(sc); 1488123474Swpaul} 1489123474Swpaul 1490125413Swpaulstruct ndis_allocwork { 1491125413Swpaul uint32_t na_len; 1492125413Swpaul uint8_t na_cached; 1493125413Swpaul void *na_ctx; 1494145895Swpaul io_workitem *na_iw; 1495125413Swpaul}; 1496125413Swpaul 1497125413Swpaulstatic void 1498145895Swpaulndis_asyncmem_complete(dobj, arg) 1499145895Swpaul device_object *dobj; 1500125413Swpaul void *arg; 1501123474Swpaul{ 1502123474Swpaul ndis_miniport_block *block; 1503123474Swpaul struct ndis_softc *sc; 1504125413Swpaul struct ndis_allocwork *w; 1505123474Swpaul void *vaddr; 1506123474Swpaul ndis_physaddr paddr; 1507144888Swpaul ndis_allocdone_handler donefunc; 1508123474Swpaul 1509125413Swpaul w = arg; 1510145895Swpaul block = (ndis_miniport_block *)dobj->do_devext; 1511141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1512123474Swpaul 1513125413Swpaul vaddr = NULL; 1514125413Swpaul paddr.np_quad = 0; 1515125413Swpaul 1516141524Swpaul donefunc = sc->ndis_chars->nmc_allocate_complete_func; 1517145895Swpaul NdisMAllocateSharedMemory(block, w->na_len, 1518125413Swpaul w->na_cached, &vaddr, &paddr); 1519145895Swpaul MSCALL5(donefunc, block, vaddr, &paddr, w->na_len, w->na_ctx); 1520123474Swpaul 1521145895Swpaul IoFreeWorkItem(w->na_iw); 1522145895Swpaul free(w, M_DEVBUF); 1523123474Swpaul} 1524123474Swpaul 1525144888Swpaulstatic ndis_status 1526189004SrdivackyNdisMAllocateSharedMemoryAsync(ndis_handle adapter, uint32_t len, 1527189004Srdivacky uint8_t cached, void *ctx) 1528125413Swpaul{ 1529145895Swpaul ndis_miniport_block *block; 1530125413Swpaul struct ndis_allocwork *w; 1531145895Swpaul io_workitem *iw; 1532145895Swpaul io_workitem_func ifw; 1533125413Swpaul 1534125413Swpaul if (adapter == NULL) 1535198786Srpaulo return (NDIS_STATUS_FAILURE); 1536125413Swpaul 1537145895Swpaul block = adapter; 1538145895Swpaul 1539145895Swpaul iw = IoAllocateWorkItem(block->nmb_deviceobj); 1540145895Swpaul if (iw == NULL) 1541198786Srpaulo return (NDIS_STATUS_FAILURE); 1542145895Swpaul 1543125413Swpaul w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT); 1544125413Swpaul 1545125413Swpaul if (w == NULL) 1546198786Srpaulo return (NDIS_STATUS_FAILURE); 1547125413Swpaul 1548125413Swpaul w->na_cached = cached; 1549125413Swpaul w->na_len = len; 1550125413Swpaul w->na_ctx = ctx; 1551146273Swpaul w->na_iw = iw; 1552125413Swpaul 1553145895Swpaul ifw = (io_workitem_func)ndis_findwrap((funcptr)ndis_asyncmem_complete); 1554145895Swpaul IoQueueWorkItem(iw, ifw, WORKQUEUE_DELAYED, w); 1555125413Swpaul 1556198786Srpaulo return (NDIS_STATUS_PENDING); 1557125413Swpaul} 1558125413Swpaul 1559144888Swpaulstatic void 1560189004SrdivackyNdisMFreeSharedMemory(ndis_handle adapter, uint32_t len, uint8_t cached, 1561189004Srdivacky void *vaddr, ndis_physaddr paddr) 1562123474Swpaul{ 1563123474Swpaul ndis_miniport_block *block; 1564123474Swpaul struct ndis_softc *sc; 1565151207Swpaul struct ndis_shmem *sh = NULL; 1566151207Swpaul list_entry *l; 1567123474Swpaul 1568123474Swpaul if (vaddr == NULL || adapter == NULL) 1569123474Swpaul return; 1570123474Swpaul 1571123474Swpaul block = (ndis_miniport_block *)adapter; 1572141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1573123474Swpaul 1574144254Swpaul /* Sanity check: is list empty? */ 1575144254Swpaul 1576151207Swpaul if (IsListEmpty(&sc->ndis_shlist)) 1577144254Swpaul return; 1578144254Swpaul 1579151207Swpaul NDIS_LOCK(sc); 1580151207Swpaul l = sc->ndis_shlist.nle_flink; 1581151207Swpaul while (l != &sc->ndis_shlist) { 1582151207Swpaul sh = CONTAINING_RECORD(l, struct ndis_shmem, ndis_list); 1583123474Swpaul if (sh->ndis_saddr == vaddr) 1584123474Swpaul break; 1585145895Swpaul /* 1586189488Sweongyo * Check the physaddr too, just in case the driver lied 1587145895Swpaul * about the virtual address. 1588145895Swpaul */ 1589145895Swpaul if (sh->ndis_paddr.np_quad == paddr.np_quad) 1590145895Swpaul break; 1591151207Swpaul l = l->nle_flink; 1592123474Swpaul } 1593123474Swpaul 1594145895Swpaul if (sh == NULL) { 1595151207Swpaul NDIS_UNLOCK(sc); 1596145895Swpaul printf("NDIS: buggy driver tried to free " 1597145906Swpaul "invalid shared memory: vaddr: %p paddr: 0x%jx\n", 1598145935Swpaul vaddr, (uintmax_t)paddr.np_quad); 1599145895Swpaul return; 1600145895Swpaul } 1601145895Swpaul 1602151207Swpaul RemoveEntryList(&sh->ndis_list); 1603151207Swpaul 1604151207Swpaul NDIS_UNLOCK(sc); 1605151207Swpaul 1606123474Swpaul bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); 1607145895Swpaul bus_dmamem_free(sh->ndis_stag, sh->ndis_saddr, sh->ndis_smap); 1608123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1609123474Swpaul 1610123474Swpaul free(sh, M_DEVBUF); 1611123474Swpaul} 1612123474Swpaul 1613144888Swpaulstatic ndis_status 1614140751SwpaulNdisMMapIoSpace(vaddr, adapter, paddr, len) 1615123474Swpaul void **vaddr; 1616123474Swpaul ndis_handle adapter; 1617123474Swpaul ndis_physaddr paddr; 1618123474Swpaul uint32_t len; 1619123474Swpaul{ 1620123474Swpaul if (adapter == NULL) 1621198786Srpaulo return (NDIS_STATUS_FAILURE); 1622123474Swpaul 1623151691Swpaul *vaddr = MmMapIoSpace(paddr.np_quad, len, 0); 1624123474Swpaul 1625151691Swpaul if (*vaddr == NULL) 1626198786Srpaulo return (NDIS_STATUS_FAILURE); 1627123474Swpaul 1628198786Srpaulo return (NDIS_STATUS_SUCCESS); 1629123474Swpaul} 1630123474Swpaul 1631144888Swpaulstatic void 1632140751SwpaulNdisMUnmapIoSpace(adapter, vaddr, len) 1633123474Swpaul ndis_handle adapter; 1634123474Swpaul void *vaddr; 1635123474Swpaul uint32_t len; 1636123474Swpaul{ 1637151691Swpaul MmUnmapIoSpace(vaddr, len); 1638123474Swpaul} 1639123474Swpaul 1640144888Swpaulstatic uint32_t 1641140751SwpaulNdisGetCacheFillSize(void) 1642123474Swpaul{ 1643198786Srpaulo return (128); 1644123474Swpaul} 1645123474Swpaul 1646216242Sbschmidtstatic void * 1647216242SbschmidtNdisGetRoutineAddress(ustr) 1648216242Sbschmidt unicode_string *ustr; 1649216242Sbschmidt{ 1650216242Sbschmidt ansi_string astr; 1651216242Sbschmidt 1652216242Sbschmidt if (RtlUnicodeStringToAnsiString(&astr, ustr, TRUE)) 1653216242Sbschmidt return (NULL); 1654216242Sbschmidt return (ndis_get_routine_address(ndis_functbl, astr.as_buf)); 1655216242Sbschmidt} 1656216242Sbschmidt 1657144888Swpaulstatic uint32_t 1658140751SwpaulNdisMGetDmaAlignment(handle) 1659123474Swpaul ndis_handle handle; 1660123474Swpaul{ 1661198786Srpaulo return (16); 1662123474Swpaul} 1663123474Swpaul 1664123474Swpaul/* 1665123474Swpaul * NDIS has two methods for dealing with NICs that support DMA. 1666123474Swpaul * One is to just pass packets to the driver and let it call 1667123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet 1668123474Swpaul * all by itself, and the other is to let the NDIS library handle the 1669123474Swpaul * buffer mapping internally, and hand the driver an already populated 1670123474Swpaul * scatter/gather fragment list. If the driver calls 1671123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter 1672123474Swpaul * method. 1673123474Swpaul */ 1674123474Swpaul 1675144888Swpaulstatic ndis_status 1676189004SrdivackyNdisMInitializeScatterGatherDma(ndis_handle adapter, uint8_t is64, 1677189004Srdivacky uint32_t maxphysmap) 1678123474Swpaul{ 1679123474Swpaul struct ndis_softc *sc; 1680123474Swpaul ndis_miniport_block *block; 1681123474Swpaul int error; 1682123474Swpaul 1683123474Swpaul if (adapter == NULL) 1684198786Srpaulo return (NDIS_STATUS_FAILURE); 1685123474Swpaul block = (ndis_miniport_block *)adapter; 1686141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1687123474Swpaul 1688123474Swpaul /* Don't do this twice. */ 1689123474Swpaul if (sc->ndis_sc == 1) 1690198786Srpaulo return (NDIS_STATUS_SUCCESS); 1691123474Swpaul 1692123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1693123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1694123474Swpaul MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, 1695123474Swpaul NULL, NULL, &sc->ndis_ttag); 1696123474Swpaul 1697123474Swpaul sc->ndis_sc = 1; 1698123474Swpaul 1699198786Srpaulo return (NDIS_STATUS_SUCCESS); 1700123474Swpaul} 1701123474Swpaul 1702144888Swpaulvoid 1703140751SwpaulNdisAllocatePacketPool(status, pool, descnum, protrsvdlen) 1704123474Swpaul ndis_status *status; 1705123474Swpaul ndis_handle *pool; 1706123474Swpaul uint32_t descnum; 1707123474Swpaul uint32_t protrsvdlen; 1708123474Swpaul{ 1709151451Swpaul ndis_packet_pool *p; 1710151451Swpaul ndis_packet *packets; 1711123474Swpaul int i; 1712123474Swpaul 1713151451Swpaul p = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_packet_pool), 0); 1714151451Swpaul if (p == NULL) { 1715123474Swpaul *status = NDIS_STATUS_RESOURCES; 1716123474Swpaul return; 1717123474Swpaul } 1718123474Swpaul 1719151451Swpaul p->np_cnt = descnum + NDIS_POOL_EXTRA; 1720151451Swpaul p->np_protrsvd = protrsvdlen; 1721151451Swpaul p->np_len = sizeof(ndis_packet) + protrsvdlen; 1722151451Swpaul 1723151451Swpaul packets = ExAllocatePoolWithTag(NonPagedPool, p->np_cnt * 1724151451Swpaul p->np_len, 0); 1725151451Swpaul 1726151451Swpaul 1727151451Swpaul if (packets == NULL) { 1728151451Swpaul ExFreePool(p); 1729151451Swpaul *status = NDIS_STATUS_RESOURCES; 1730151451Swpaul return; 1731123474Swpaul } 1732123474Swpaul 1733151451Swpaul p->np_pktmem = packets; 1734151451Swpaul 1735151451Swpaul for (i = 0; i < p->np_cnt; i++) 1736151451Swpaul InterlockedPushEntrySList(&p->np_head, 1737151451Swpaul (struct slist_entry *)&packets[i]); 1738151451Swpaul 1739151451Swpaul#ifdef NDIS_DEBUG_PACKETS 1740151451Swpaul p->np_dead = 0; 1741151451Swpaul KeInitializeSpinLock(&p->np_lock); 1742189488Sweongyo KeInitializeEvent(&p->np_event, EVENT_TYPE_NOTIFY, TRUE); 1743151451Swpaul#endif 1744151451Swpaul 1745151451Swpaul *pool = p; 1746123474Swpaul *status = NDIS_STATUS_SUCCESS; 1747123474Swpaul} 1748123474Swpaul 1749144888Swpaulvoid 1750140751SwpaulNdisAllocatePacketPoolEx(status, pool, descnum, oflowdescnum, protrsvdlen) 1751123474Swpaul ndis_status *status; 1752123474Swpaul ndis_handle *pool; 1753123474Swpaul uint32_t descnum; 1754123474Swpaul uint32_t oflowdescnum; 1755123474Swpaul uint32_t protrsvdlen; 1756123474Swpaul{ 1757198786Srpaulo return (NdisAllocatePacketPool(status, pool, 1758123474Swpaul descnum + oflowdescnum, protrsvdlen)); 1759123474Swpaul} 1760123474Swpaul 1761144888Swpauluint32_t 1762140751SwpaulNdisPacketPoolUsage(pool) 1763123474Swpaul ndis_handle pool; 1764123474Swpaul{ 1765151451Swpaul ndis_packet_pool *p; 1766123474Swpaul 1767151451Swpaul p = (ndis_packet_pool *)pool; 1768198786Srpaulo return (p->np_cnt - ExQueryDepthSList(&p->np_head)); 1769123474Swpaul} 1770123474Swpaul 1771144888Swpaulvoid 1772140751SwpaulNdisFreePacketPool(pool) 1773123474Swpaul ndis_handle pool; 1774123474Swpaul{ 1775151451Swpaul ndis_packet_pool *p; 1776151451Swpaul int usage; 1777189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1778143086Swpaul uint8_t irql; 1779151451Swpaul#endif 1780126568Swpaul 1781151451Swpaul p = (ndis_packet_pool *)pool; 1782126568Swpaul 1783189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1784151451Swpaul KeAcquireSpinLock(&p->np_lock, &irql); 1785151451Swpaul#endif 1786126568Swpaul 1787151451Swpaul usage = NdisPacketPoolUsage(pool); 1788126568Swpaul 1789189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1790151451Swpaul if (usage) { 1791151451Swpaul p->np_dead = 1; 1792151451Swpaul KeResetEvent(&p->np_event); 1793151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1794151451Swpaul KeWaitForSingleObject(&p->np_event, 0, 0, FALSE, NULL); 1795151451Swpaul } else 1796151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1797151451Swpaul#endif 1798126568Swpaul 1799151451Swpaul ExFreePool(p->np_pktmem); 1800151451Swpaul ExFreePool(p); 1801123474Swpaul} 1802123474Swpaul 1803144888Swpaulvoid 1804140751SwpaulNdisAllocatePacket(status, packet, pool) 1805123474Swpaul ndis_status *status; 1806123474Swpaul ndis_packet **packet; 1807123474Swpaul ndis_handle pool; 1808123474Swpaul{ 1809151451Swpaul ndis_packet_pool *p; 1810151451Swpaul ndis_packet *pkt; 1811189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1812143086Swpaul uint8_t irql; 1813151451Swpaul#endif 1814123474Swpaul 1815151451Swpaul p = (ndis_packet_pool *)pool; 1816123474Swpaul 1817189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1818151451Swpaul KeAcquireSpinLock(&p->np_lock, &irql); 1819151451Swpaul if (p->np_dead) { 1820151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1821151451Swpaul printf("NDIS: tried to allocate packet from dead pool %p\n", 1822151451Swpaul pool); 1823151451Swpaul *status = NDIS_STATUS_RESOURCES; 1824123474Swpaul return; 1825123474Swpaul } 1826151451Swpaul#endif 1827123474Swpaul 1828151451Swpaul pkt = (ndis_packet *)InterlockedPopEntrySList(&p->np_head); 1829126568Swpaul 1830189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1831151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1832151451Swpaul#endif 1833126568Swpaul 1834123474Swpaul if (pkt == NULL) { 1835123474Swpaul *status = NDIS_STATUS_RESOURCES; 1836123474Swpaul return; 1837123474Swpaul } 1838123474Swpaul 1839123474Swpaul 1840151451Swpaul bzero((char *)pkt, sizeof(ndis_packet)); 1841151451Swpaul 1842123474Swpaul /* Save pointer to the pool. */ 1843151451Swpaul pkt->np_private.npp_pool = pool; 1844123474Swpaul 1845123474Swpaul /* Set the oob offset pointer. Lots of things expect this. */ 1846144888Swpaul pkt->np_private.npp_packetooboffset = offsetof(ndis_packet, np_oob); 1847123474Swpaul 1848124278Swpaul /* 1849124278Swpaul * We must initialize the packet flags correctly in order 1850124278Swpaul * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and 1851141963Swpaul * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work 1852189488Sweongyo * correctly. 1853124278Swpaul */ 1854124278Swpaul pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS; 1855144239Swpaul pkt->np_private.npp_validcounts = FALSE; 1856124278Swpaul 1857123474Swpaul *packet = pkt; 1858123474Swpaul 1859123474Swpaul *status = NDIS_STATUS_SUCCESS; 1860123474Swpaul} 1861123474Swpaul 1862144888Swpaulvoid 1863140751SwpaulNdisFreePacket(packet) 1864123474Swpaul ndis_packet *packet; 1865123474Swpaul{ 1866151451Swpaul ndis_packet_pool *p; 1867189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1868143086Swpaul uint8_t irql; 1869151451Swpaul#endif 1870123474Swpaul 1871151451Swpaul p = (ndis_packet_pool *)packet->np_private.npp_pool; 1872123474Swpaul 1873189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1874151451Swpaul KeAcquireSpinLock(&p->np_lock, &irql); 1875151451Swpaul#endif 1876143086Swpaul 1877151451Swpaul InterlockedPushEntrySList(&p->np_head, (slist_entry *)packet); 1878151451Swpaul 1879189488Sweongyo#ifdef NDIS_DEBUG_PACKETS 1880151451Swpaul if (p->np_dead) { 1881151451Swpaul if (ExQueryDepthSList(&p->np_head) == p->np_cnt) 1882151451Swpaul KeSetEvent(&p->np_event, IO_NO_INCREMENT, FALSE); 1883143086Swpaul } 1884151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1885151451Swpaul#endif 1886123474Swpaul} 1887123474Swpaul 1888144888Swpaulstatic void 1889140751SwpaulNdisUnchainBufferAtFront(packet, buf) 1890123474Swpaul ndis_packet *packet; 1891123474Swpaul ndis_buffer **buf; 1892123474Swpaul{ 1893123474Swpaul ndis_packet_private *priv; 1894123474Swpaul 1895123474Swpaul if (packet == NULL || buf == NULL) 1896123474Swpaul return; 1897123474Swpaul 1898123474Swpaul priv = &packet->np_private; 1899123474Swpaul 1900123474Swpaul priv->npp_validcounts = FALSE; 1901123474Swpaul 1902123474Swpaul if (priv->npp_head == priv->npp_tail) { 1903123474Swpaul *buf = priv->npp_head; 1904123474Swpaul priv->npp_head = priv->npp_tail = NULL; 1905123474Swpaul } else { 1906123474Swpaul *buf = priv->npp_head; 1907140751Swpaul priv->npp_head = (*buf)->mdl_next; 1908123474Swpaul } 1909123474Swpaul} 1910123474Swpaul 1911144888Swpaulstatic void 1912140751SwpaulNdisUnchainBufferAtBack(packet, buf) 1913123721Swpaul ndis_packet *packet; 1914123721Swpaul ndis_buffer **buf; 1915123721Swpaul{ 1916123721Swpaul ndis_packet_private *priv; 1917123721Swpaul ndis_buffer *tmp; 1918123721Swpaul 1919123721Swpaul if (packet == NULL || buf == NULL) 1920123721Swpaul return; 1921123721Swpaul 1922123721Swpaul priv = &packet->np_private; 1923123721Swpaul 1924123721Swpaul priv->npp_validcounts = FALSE; 1925123721Swpaul 1926123721Swpaul if (priv->npp_head == priv->npp_tail) { 1927123721Swpaul *buf = priv->npp_head; 1928123721Swpaul priv->npp_head = priv->npp_tail = NULL; 1929123721Swpaul } else { 1930123721Swpaul *buf = priv->npp_tail; 1931123721Swpaul tmp = priv->npp_head; 1932140751Swpaul while (tmp->mdl_next != priv->npp_tail) 1933140751Swpaul tmp = tmp->mdl_next; 1934123721Swpaul priv->npp_tail = tmp; 1935140751Swpaul tmp->mdl_next = NULL; 1936123721Swpaul } 1937123721Swpaul} 1938123721Swpaul 1939123474Swpaul/* 1940141963Swpaul * The NDIS "buffer" is really an MDL (memory descriptor list) 1941141963Swpaul * which is used to describe a buffer in a way that allows it 1942141963Swpaul * to mapped into different contexts. We have to be careful how 1943141963Swpaul * we handle them: in some versions of Windows, the NdisFreeBuffer() 1944141963Swpaul * routine is an actual function in the NDIS API, but in others 1945141963Swpaul * it's just a macro wrapper around IoFreeMdl(). There's really 1946141963Swpaul * no way to use the 'descnum' parameter to count how many 1947141963Swpaul * "buffers" are allocated since in order to use IoFreeMdl() to 1948141963Swpaul * dispose of a buffer, we have to use IoAllocateMdl() to allocate 1949141963Swpaul * them, and IoAllocateMdl() just grabs them out of the heap. 1950123474Swpaul */ 1951123474Swpaul 1952144888Swpaulstatic void 1953140751SwpaulNdisAllocateBufferPool(status, pool, descnum) 1954123474Swpaul ndis_status *status; 1955123474Swpaul ndis_handle *pool; 1956123474Swpaul uint32_t descnum; 1957123474Swpaul{ 1958151207Swpaul 1959141963Swpaul /* 1960141963Swpaul * The only thing we can really do here is verify that descnum 1961141963Swpaul * is a reasonable value, but I really don't know what to check 1962141963Swpaul * it against. 1963141963Swpaul */ 1964123474Swpaul 1965141963Swpaul *pool = NonPagedPool; 1966123474Swpaul *status = NDIS_STATUS_SUCCESS; 1967123474Swpaul} 1968123474Swpaul 1969144888Swpaulstatic void 1970140751SwpaulNdisFreeBufferPool(pool) 1971123474Swpaul ndis_handle pool; 1972123474Swpaul{ 1973123474Swpaul} 1974123474Swpaul 1975144888Swpaulstatic void 1976140751SwpaulNdisAllocateBuffer(status, buffer, pool, vaddr, len) 1977123474Swpaul ndis_status *status; 1978123474Swpaul ndis_buffer **buffer; 1979123474Swpaul ndis_handle pool; 1980123474Swpaul void *vaddr; 1981123474Swpaul uint32_t len; 1982123474Swpaul{ 1983141963Swpaul ndis_buffer *buf; 1984123474Swpaul 1985141963Swpaul buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL); 1986123474Swpaul if (buf == NULL) { 1987123474Swpaul *status = NDIS_STATUS_RESOURCES; 1988123474Swpaul return; 1989123474Swpaul } 1990123474Swpaul 1991151207Swpaul MmBuildMdlForNonPagedPool(buf); 1992151207Swpaul 1993123474Swpaul *buffer = buf; 1994141963Swpaul *status = NDIS_STATUS_SUCCESS; 1995123474Swpaul} 1996123474Swpaul 1997144888Swpaulstatic void 1998140751SwpaulNdisFreeBuffer(buf) 1999123474Swpaul ndis_buffer *buf; 2000123474Swpaul{ 2001141963Swpaul IoFreeMdl(buf); 2002123474Swpaul} 2003123474Swpaul 2004124100Swpaul/* Aw c'mon. */ 2005124100Swpaul 2006144888Swpaulstatic uint32_t 2007140751SwpaulNdisBufferLength(buf) 2008124100Swpaul ndis_buffer *buf; 2009124100Swpaul{ 2010198786Srpaulo return (MmGetMdlByteCount(buf)); 2011124100Swpaul} 2012124100Swpaul 2013123723Swpaul/* 2014123723Swpaul * Get the virtual address and length of a buffer. 2015123723Swpaul * Note: the vaddr argument is optional. 2016123723Swpaul */ 2017123474Swpaul 2018144888Swpaulstatic void 2019140751SwpaulNdisQueryBuffer(buf, vaddr, len) 2020123474Swpaul ndis_buffer *buf; 2021123474Swpaul void **vaddr; 2022123474Swpaul uint32_t *len; 2023123474Swpaul{ 2024123723Swpaul if (vaddr != NULL) 2025140751Swpaul *vaddr = MmGetMdlVirtualAddress(buf); 2026140751Swpaul *len = MmGetMdlByteCount(buf); 2027123474Swpaul} 2028123474Swpaul 2029123474Swpaul/* Same as above -- we don't care about the priority. */ 2030123474Swpaul 2031144888Swpaulstatic void 2032140751SwpaulNdisQueryBufferSafe(buf, vaddr, len, prio) 2033123474Swpaul ndis_buffer *buf; 2034123474Swpaul void **vaddr; 2035123474Swpaul uint32_t *len; 2036123474Swpaul uint32_t prio; 2037123474Swpaul{ 2038123723Swpaul if (vaddr != NULL) 2039140751Swpaul *vaddr = MmGetMdlVirtualAddress(buf); 2040140751Swpaul *len = MmGetMdlByteCount(buf); 2041123474Swpaul} 2042123474Swpaul 2043125069Swpaul/* Damnit Microsoft!! How many ways can you do the same thing?! */ 2044125069Swpaul 2045144888Swpaulstatic void * 2046140751SwpaulNdisBufferVirtualAddress(buf) 2047125069Swpaul ndis_buffer *buf; 2048125069Swpaul{ 2049198786Srpaulo return (MmGetMdlVirtualAddress(buf)); 2050125069Swpaul} 2051125069Swpaul 2052144888Swpaulstatic void * 2053140751SwpaulNdisBufferVirtualAddressSafe(buf, prio) 2054125069Swpaul ndis_buffer *buf; 2055125069Swpaul uint32_t prio; 2056125069Swpaul{ 2057198786Srpaulo return (MmGetMdlVirtualAddress(buf)); 2058125069Swpaul} 2059125069Swpaul 2060144888Swpaulstatic void 2061140751SwpaulNdisAdjustBufferLength(buf, len) 2062123474Swpaul ndis_buffer *buf; 2063123474Swpaul int len; 2064123474Swpaul{ 2065140751Swpaul MmGetMdlByteCount(buf) = len; 2066123474Swpaul} 2067123474Swpaul 2068144888Swpaulstatic uint32_t 2069140751SwpaulNdisInterlockedIncrement(addend) 2070123474Swpaul uint32_t *addend; 2071123474Swpaul{ 2072124203Swpaul atomic_add_long((u_long *)addend, 1); 2073198786Srpaulo return (*addend); 2074123474Swpaul} 2075123474Swpaul 2076144888Swpaulstatic uint32_t 2077140751SwpaulNdisInterlockedDecrement(addend) 2078123474Swpaul uint32_t *addend; 2079123474Swpaul{ 2080124203Swpaul atomic_subtract_long((u_long *)addend, 1); 2081198786Srpaulo return (*addend); 2082123474Swpaul} 2083123474Swpaul 2084215779Sbschmidtstatic uint32_t 2085215779SbschmidtNdisGetVersion(void) 2086215779Sbschmidt{ 2087215779Sbschmidt return (0x00050001); 2088215779Sbschmidt} 2089215779Sbschmidt 2090144888Swpaulstatic void 2091140751SwpaulNdisInitializeEvent(event) 2092123474Swpaul ndis_event *event; 2093123474Swpaul{ 2094127248Swpaul /* 2095127411Swpaul * NDIS events are always notification 2096127248Swpaul * events, and should be initialized to the 2097127248Swpaul * not signaled state. 2098127248Swpaul */ 2099140751Swpaul KeInitializeEvent(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE); 2100123474Swpaul} 2101123474Swpaul 2102144888Swpaulstatic void 2103140751SwpaulNdisSetEvent(event) 2104123474Swpaul ndis_event *event; 2105123474Swpaul{ 2106151451Swpaul KeSetEvent(&event->ne_event, IO_NO_INCREMENT, FALSE); 2107123474Swpaul} 2108123474Swpaul 2109144888Swpaulstatic void 2110140751SwpaulNdisResetEvent(event) 2111123474Swpaul ndis_event *event; 2112123474Swpaul{ 2113140751Swpaul KeResetEvent(&event->ne_event); 2114123474Swpaul} 2115123474Swpaul 2116144888Swpaulstatic uint8_t 2117140751SwpaulNdisWaitEvent(event, msecs) 2118123474Swpaul ndis_event *event; 2119123474Swpaul uint32_t msecs; 2120123474Swpaul{ 2121127248Swpaul int64_t duetime; 2122127248Swpaul uint32_t rval; 2123123474Swpaul 2124127248Swpaul duetime = ((int64_t)msecs * -10000); 2125151451Swpaul rval = KeWaitForSingleObject(event, 2126145895Swpaul 0, 0, TRUE, msecs ? & duetime : NULL); 2127123474Swpaul 2128127248Swpaul if (rval == STATUS_TIMEOUT) 2129198786Srpaulo return (FALSE); 2130125551Swpaul 2131198786Srpaulo return (TRUE); 2132123474Swpaul} 2133123474Swpaul 2134144888Swpaulstatic ndis_status 2135140751SwpaulNdisUnicodeStringToAnsiString(dstr, sstr) 2136151207Swpaul ansi_string *dstr; 2137151207Swpaul unicode_string *sstr; 2138123474Swpaul{ 2139151207Swpaul uint32_t rval; 2140151207Swpaul 2141151207Swpaul rval = RtlUnicodeStringToAnsiString(dstr, sstr, FALSE); 2142151207Swpaul 2143151207Swpaul if (rval == STATUS_INSUFFICIENT_RESOURCES) 2144198786Srpaulo return (NDIS_STATUS_RESOURCES); 2145151207Swpaul if (rval) 2146198786Srpaulo return (NDIS_STATUS_FAILURE); 2147151207Swpaul 2148123474Swpaul return (NDIS_STATUS_SUCCESS); 2149123474Swpaul} 2150123474Swpaul 2151144888Swpaulstatic ndis_status 2152140751SwpaulNdisAnsiStringToUnicodeString(dstr, sstr) 2153151207Swpaul unicode_string *dstr; 2154151207Swpaul ansi_string *sstr; 2155123526Swpaul{ 2156151207Swpaul uint32_t rval; 2157151207Swpaul 2158151207Swpaul rval = RtlAnsiStringToUnicodeString(dstr, sstr, FALSE); 2159151207Swpaul 2160151207Swpaul if (rval == STATUS_INSUFFICIENT_RESOURCES) 2161198786Srpaulo return (NDIS_STATUS_RESOURCES); 2162151207Swpaul if (rval) 2163198786Srpaulo return (NDIS_STATUS_FAILURE); 2164151207Swpaul 2165123526Swpaul return (NDIS_STATUS_SUCCESS); 2166123526Swpaul} 2167123526Swpaul 2168144888Swpaulstatic ndis_status 2169140751SwpaulNdisMPciAssignResources(adapter, slot, list) 2170123474Swpaul ndis_handle adapter; 2171123474Swpaul uint32_t slot; 2172123474Swpaul ndis_resource_list **list; 2173123474Swpaul{ 2174123474Swpaul ndis_miniport_block *block; 2175123474Swpaul 2176123474Swpaul if (adapter == NULL || list == NULL) 2177123474Swpaul return (NDIS_STATUS_FAILURE); 2178123474Swpaul 2179123474Swpaul block = (ndis_miniport_block *)adapter; 2180123474Swpaul *list = block->nmb_rlist; 2181123474Swpaul 2182123474Swpaul return (NDIS_STATUS_SUCCESS); 2183123474Swpaul} 2184123474Swpaul 2185152626Swpaulstatic uint8_t 2186152626Swpaulndis_intr(iobj, arg) 2187152626Swpaul kinterrupt *iobj; 2188189488Sweongyo void *arg; 2189151207Swpaul{ 2190151207Swpaul struct ndis_softc *sc; 2191152626Swpaul uint8_t is_our_intr = FALSE; 2192151207Swpaul int call_isr = 0; 2193151207Swpaul ndis_miniport_interrupt *intr; 2194151207Swpaul 2195151207Swpaul sc = arg; 2196151207Swpaul intr = sc->ndis_block->nmb_interrupt; 2197151207Swpaul 2198151207Swpaul if (intr == NULL || sc->ndis_block->nmb_miniportadapterctx == NULL) 2199198786Srpaulo return (FALSE); 2200151207Swpaul 2201151207Swpaul if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE) 2202151977Swpaul MSCALL3(intr->ni_isrfunc, &is_our_intr, &call_isr, 2203151977Swpaul sc->ndis_block->nmb_miniportadapterctx); 2204151207Swpaul else { 2205151977Swpaul MSCALL1(sc->ndis_chars->nmc_disable_interrupts_func, 2206151977Swpaul sc->ndis_block->nmb_miniportadapterctx); 2207151207Swpaul call_isr = 1; 2208151207Swpaul } 2209151207Swpaul 2210152626Swpaul if (call_isr) 2211151207Swpaul IoRequestDpc(sc->ndis_block->nmb_deviceobj, NULL, sc); 2212151207Swpaul 2213198786Srpaulo return (is_our_intr); 2214151207Swpaul} 2215151207Swpaul 2216151207Swpaulstatic void 2217151207Swpaulndis_intrhand(dpc, intr, sysarg1, sysarg2) 2218151207Swpaul kdpc *dpc; 2219151207Swpaul ndis_miniport_interrupt *intr; 2220151207Swpaul void *sysarg1; 2221151207Swpaul void *sysarg2; 2222151207Swpaul{ 2223151207Swpaul struct ndis_softc *sc; 2224151207Swpaul ndis_miniport_block *block; 2225189488Sweongyo ndis_handle adapter; 2226151207Swpaul 2227151207Swpaul block = intr->ni_block; 2228189488Sweongyo adapter = block->nmb_miniportadapterctx; 2229151207Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2230151207Swpaul 2231189488Sweongyo if (NDIS_SERIALIZED(sc->ndis_block)) 2232189488Sweongyo KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); 2233151207Swpaul 2234189488Sweongyo MSCALL1(intr->ni_dpcfunc, adapter); 2235151207Swpaul 2236189488Sweongyo /* If there's a MiniportEnableInterrupt() routine, call it. */ 2237151207Swpaul 2238151977Swpaul if (sc->ndis_chars->nmc_enable_interrupts_func != NULL) 2239151977Swpaul MSCALL1(sc->ndis_chars->nmc_enable_interrupts_func, adapter); 2240151207Swpaul 2241189488Sweongyo if (NDIS_SERIALIZED(sc->ndis_block)) 2242189488Sweongyo KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); 2243151207Swpaul 2244151207Swpaul /* 2245151207Swpaul * Set the completion event if we've drained all 2246151207Swpaul * pending interrupts. 2247151207Swpaul */ 2248151207Swpaul 2249151207Swpaul KeAcquireSpinLockAtDpcLevel(&intr->ni_dpccountlock); 2250151207Swpaul intr->ni_dpccnt--; 2251151207Swpaul if (intr->ni_dpccnt == 0) 2252151207Swpaul KeSetEvent(&intr->ni_dpcevt, IO_NO_INCREMENT, FALSE); 2253151207Swpaul KeReleaseSpinLockFromDpcLevel(&intr->ni_dpccountlock); 2254151207Swpaul} 2255151207Swpaul 2256144888Swpaulstatic ndis_status 2257189004SrdivackyNdisMRegisterInterrupt(ndis_miniport_interrupt *intr, ndis_handle adapter, 2258189004Srdivacky uint32_t ivec, uint32_t ilevel, uint8_t reqisr, uint8_t shared, 2259189004Srdivacky ndis_interrupt_mode imode) 2260123474Swpaul{ 2261124165Swpaul ndis_miniport_block *block; 2262151207Swpaul ndis_miniport_characteristics *ch; 2263151207Swpaul struct ndis_softc *sc; 2264151207Swpaul int error; 2265124165Swpaul 2266124165Swpaul block = adapter; 2267151207Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2268151207Swpaul ch = IoGetDriverObjectExtension(block->nmb_deviceobj->do_drvobj, 2269151207Swpaul (void *)1); 2270124165Swpaul 2271151207Swpaul intr->ni_rsvd = ExAllocatePoolWithTag(NonPagedPool, 2272151207Swpaul sizeof(struct mtx), 0); 2273151207Swpaul if (intr->ni_rsvd == NULL) 2274198786Srpaulo return (NDIS_STATUS_RESOURCES); 2275151207Swpaul 2276124135Swpaul intr->ni_block = adapter; 2277124165Swpaul intr->ni_isrreq = reqisr; 2278124165Swpaul intr->ni_shared = shared; 2279151207Swpaul intr->ni_dpccnt = 0; 2280151977Swpaul intr->ni_isrfunc = ch->nmc_isr_func; 2281151977Swpaul intr->ni_dpcfunc = ch->nmc_interrupt_func; 2282151207Swpaul 2283189488Sweongyo KeInitializeEvent(&intr->ni_dpcevt, EVENT_TYPE_NOTIFY, TRUE); 2284189488Sweongyo KeInitializeDpc(&intr->ni_dpc, 2285151207Swpaul ndis_findwrap((funcptr)ndis_intrhand), intr); 2286189488Sweongyo KeSetImportanceDpc(&intr->ni_dpc, KDPC_IMPORTANCE_LOW); 2287151207Swpaul 2288151207Swpaul error = IoConnectInterrupt(&intr->ni_introbj, 2289151207Swpaul ndis_findwrap((funcptr)ndis_intr), sc, NULL, 2290151207Swpaul ivec, ilevel, 0, imode, shared, 0, FALSE); 2291151207Swpaul 2292151207Swpaul if (error != STATUS_SUCCESS) 2293198786Srpaulo return (NDIS_STATUS_FAILURE); 2294151207Swpaul 2295124165Swpaul block->nmb_interrupt = intr; 2296141524Swpaul 2297198786Srpaulo return (NDIS_STATUS_SUCCESS); 2298189488Sweongyo} 2299123474Swpaul 2300144888Swpaulstatic void 2301140751SwpaulNdisMDeregisterInterrupt(intr) 2302123474Swpaul ndis_miniport_interrupt *intr; 2303123474Swpaul{ 2304151207Swpaul ndis_miniport_block *block; 2305151207Swpaul uint8_t irql; 2306151207Swpaul 2307151207Swpaul block = intr->ni_block; 2308151207Swpaul 2309151207Swpaul /* Should really be KeSynchronizeExecution() */ 2310151207Swpaul 2311151207Swpaul KeAcquireSpinLock(intr->ni_introbj->ki_lock, &irql); 2312151207Swpaul block->nmb_interrupt = NULL; 2313151207Swpaul KeReleaseSpinLock(intr->ni_introbj->ki_lock, irql); 2314151207Swpaul/* 2315151207Swpaul KeFlushQueuedDpcs(); 2316151207Swpaul*/ 2317151207Swpaul /* Disconnect our ISR */ 2318151207Swpaul 2319151207Swpaul IoDisconnectInterrupt(intr->ni_introbj); 2320151207Swpaul 2321151451Swpaul KeWaitForSingleObject(&intr->ni_dpcevt, 0, 0, FALSE, NULL); 2322151207Swpaul KeResetEvent(&intr->ni_dpcevt); 2323123474Swpaul} 2324123474Swpaul 2325144888Swpaulstatic void 2326140751SwpaulNdisMRegisterAdapterShutdownHandler(adapter, shutdownctx, shutdownfunc) 2327123474Swpaul ndis_handle adapter; 2328123474Swpaul void *shutdownctx; 2329123474Swpaul ndis_shutdown_handler shutdownfunc; 2330123474Swpaul{ 2331123474Swpaul ndis_miniport_block *block; 2332123474Swpaul ndis_miniport_characteristics *chars; 2333123474Swpaul struct ndis_softc *sc; 2334123474Swpaul 2335123474Swpaul if (adapter == NULL) 2336123474Swpaul return; 2337123474Swpaul 2338123474Swpaul block = (ndis_miniport_block *)adapter; 2339141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2340141524Swpaul chars = sc->ndis_chars; 2341123474Swpaul 2342123474Swpaul chars->nmc_shutdown_handler = shutdownfunc; 2343123474Swpaul chars->nmc_rsvd0 = shutdownctx; 2344123474Swpaul} 2345123474Swpaul 2346144888Swpaulstatic void 2347140751SwpaulNdisMDeregisterAdapterShutdownHandler(adapter) 2348123474Swpaul ndis_handle adapter; 2349123474Swpaul{ 2350123474Swpaul ndis_miniport_block *block; 2351123474Swpaul ndis_miniport_characteristics *chars; 2352123474Swpaul struct ndis_softc *sc; 2353123474Swpaul 2354123474Swpaul if (adapter == NULL) 2355123474Swpaul return; 2356123474Swpaul 2357123474Swpaul block = (ndis_miniport_block *)adapter; 2358141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2359141524Swpaul chars = sc->ndis_chars; 2360123474Swpaul 2361123474Swpaul chars->nmc_shutdown_handler = NULL; 2362123474Swpaul chars->nmc_rsvd0 = NULL; 2363123474Swpaul} 2364123474Swpaul 2365144888Swpaulstatic uint32_t 2366140751SwpaulNDIS_BUFFER_TO_SPAN_PAGES(buf) 2367123474Swpaul ndis_buffer *buf; 2368123474Swpaul{ 2369123757Swpaul if (buf == NULL) 2370198786Srpaulo return (0); 2371140751Swpaul if (MmGetMdlByteCount(buf) == 0) 2372198786Srpaulo return (1); 2373198786Srpaulo return (SPAN_PAGES(MmGetMdlVirtualAddress(buf), 2374140751Swpaul MmGetMdlByteCount(buf))); 2375123474Swpaul} 2376123474Swpaul 2377144888Swpaulstatic void 2378140751SwpaulNdisGetBufferPhysicalArraySize(buf, pages) 2379123573Swpaul ndis_buffer *buf; 2380123573Swpaul uint32_t *pages; 2381123573Swpaul{ 2382123757Swpaul if (buf == NULL) 2383123757Swpaul return; 2384123757Swpaul 2385140751Swpaul *pages = NDIS_BUFFER_TO_SPAN_PAGES(buf); 2386123573Swpaul} 2387123573Swpaul 2388144888Swpaulstatic void 2389140751SwpaulNdisQueryBufferOffset(buf, off, len) 2390123474Swpaul ndis_buffer *buf; 2391123474Swpaul uint32_t *off; 2392123474Swpaul uint32_t *len; 2393123474Swpaul{ 2394123757Swpaul if (buf == NULL) 2395123757Swpaul return; 2396123757Swpaul 2397140751Swpaul *off = MmGetMdlByteOffset(buf); 2398140751Swpaul *len = MmGetMdlByteCount(buf); 2399123474Swpaul} 2400123474Swpaul 2401151451Swpaulvoid 2402140751SwpaulNdisMSleep(usecs) 2403123474Swpaul uint32_t usecs; 2404123474Swpaul{ 2405151207Swpaul ktimer timer; 2406123474Swpaul 2407145485Swpaul /* 2408145485Swpaul * During system bootstrap, (i.e. cold == 1), we aren't 2409151207Swpaul * allowed to sleep, so we have to do a hard DELAY() 2410151207Swpaul * instead. 2411145485Swpaul */ 2412123474Swpaul 2413151207Swpaul if (cold) 2414145485Swpaul DELAY(usecs); 2415151207Swpaul else { 2416151207Swpaul KeInitializeTimer(&timer); 2417151207Swpaul KeSetTimer(&timer, ((int64_t)usecs * -10), NULL); 2418151451Swpaul KeWaitForSingleObject(&timer, 0, 0, FALSE, NULL); 2419151207Swpaul } 2420123474Swpaul} 2421123474Swpaul 2422144888Swpaulstatic uint32_t 2423140751SwpaulNdisReadPcmciaAttributeMemory(handle, offset, buf, len) 2424123474Swpaul ndis_handle handle; 2425123474Swpaul uint32_t offset; 2426123474Swpaul void *buf; 2427123474Swpaul uint32_t len; 2428123474Swpaul{ 2429123474Swpaul struct ndis_softc *sc; 2430123474Swpaul ndis_miniport_block *block; 2431123474Swpaul bus_space_handle_t bh; 2432123474Swpaul bus_space_tag_t bt; 2433123474Swpaul char *dest; 2434123474Swpaul int i; 2435123474Swpaul 2436123474Swpaul if (handle == NULL) 2437198786Srpaulo return (0); 2438123474Swpaul 2439123474Swpaul block = (ndis_miniport_block *)handle; 2440141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2441123474Swpaul dest = buf; 2442123474Swpaul 2443123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 2444123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 2445123474Swpaul 2446123474Swpaul for (i = 0; i < len; i++) 2447131953Swpaul dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2); 2448123474Swpaul 2449198786Srpaulo return (i); 2450123474Swpaul} 2451123474Swpaul 2452144888Swpaulstatic uint32_t 2453140751SwpaulNdisWritePcmciaAttributeMemory(handle, offset, buf, len) 2454123474Swpaul ndis_handle handle; 2455123474Swpaul uint32_t offset; 2456123474Swpaul void *buf; 2457123474Swpaul uint32_t len; 2458123474Swpaul{ 2459123474Swpaul struct ndis_softc *sc; 2460123474Swpaul ndis_miniport_block *block; 2461123474Swpaul bus_space_handle_t bh; 2462123474Swpaul bus_space_tag_t bt; 2463123474Swpaul char *src; 2464123474Swpaul int i; 2465123474Swpaul 2466123474Swpaul if (handle == NULL) 2467198786Srpaulo return (0); 2468123474Swpaul 2469123474Swpaul block = (ndis_miniport_block *)handle; 2470141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2471123474Swpaul src = buf; 2472123474Swpaul 2473123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 2474123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 2475123474Swpaul 2476123474Swpaul for (i = 0; i < len; i++) 2477131953Swpaul bus_space_write_1(bt, bh, (offset + i) * 2, src[i]); 2478123474Swpaul 2479198786Srpaulo return (i); 2480123474Swpaul} 2481123474Swpaul 2482144888Swpaulstatic list_entry * 2483140751SwpaulNdisInterlockedInsertHeadList(head, entry, lock) 2484125551Swpaul list_entry *head; 2485125551Swpaul list_entry *entry; 2486123474Swpaul ndis_spin_lock *lock; 2487123474Swpaul{ 2488125551Swpaul list_entry *flink; 2489123474Swpaul 2490140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 2491123474Swpaul flink = head->nle_flink; 2492123474Swpaul entry->nle_flink = flink; 2493123474Swpaul entry->nle_blink = head; 2494123474Swpaul flink->nle_blink = entry; 2495123474Swpaul head->nle_flink = entry; 2496140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 2497123474Swpaul 2498198786Srpaulo return (flink); 2499123474Swpaul} 2500123474Swpaul 2501144888Swpaulstatic list_entry * 2502140751SwpaulNdisInterlockedRemoveHeadList(head, lock) 2503125551Swpaul list_entry *head; 2504123474Swpaul ndis_spin_lock *lock; 2505123474Swpaul{ 2506125551Swpaul list_entry *flink; 2507125551Swpaul list_entry *entry; 2508123474Swpaul 2509140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 2510123474Swpaul entry = head->nle_flink; 2511123474Swpaul flink = entry->nle_flink; 2512123474Swpaul head->nle_flink = flink; 2513123474Swpaul flink->nle_blink = head; 2514140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 2515123474Swpaul 2516198786Srpaulo return (entry); 2517123474Swpaul} 2518123474Swpaul 2519144888Swpaulstatic list_entry * 2520140751SwpaulNdisInterlockedInsertTailList(head, entry, lock) 2521125551Swpaul list_entry *head; 2522125551Swpaul list_entry *entry; 2523123474Swpaul ndis_spin_lock *lock; 2524123474Swpaul{ 2525125551Swpaul list_entry *blink; 2526123474Swpaul 2527140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 2528123474Swpaul blink = head->nle_blink; 2529123474Swpaul entry->nle_flink = head; 2530123474Swpaul entry->nle_blink = blink; 2531123474Swpaul blink->nle_flink = entry; 2532123474Swpaul head->nle_blink = entry; 2533140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 2534123474Swpaul 2535198786Srpaulo return (blink); 2536123474Swpaul} 2537123474Swpaul 2538144888Swpaulstatic uint8_t 2539140751SwpaulNdisMSynchronizeWithInterrupt(intr, syncfunc, syncctx) 2540123474Swpaul ndis_miniport_interrupt *intr; 2541123474Swpaul void *syncfunc; 2542123474Swpaul void *syncctx; 2543123474Swpaul{ 2544198786Srpaulo return (KeSynchronizeExecution(intr->ni_introbj, syncfunc, syncctx)); 2545123474Swpaul} 2546123474Swpaul 2547144888Swpaulstatic void 2548140751SwpaulNdisGetCurrentSystemTime(tval) 2549123504Swpaul uint64_t *tval; 2550123504Swpaul{ 2551174150Sthompsa ntoskrnl_time(tval); 2552123504Swpaul} 2553123504Swpaul 2554123822Swpaul/* 2555123822Swpaul * Return the number of milliseconds since the system booted. 2556123822Swpaul */ 2557144888Swpaulstatic void 2558140751SwpaulNdisGetSystemUpTime(tval) 2559123822Swpaul uint32_t *tval; 2560123822Swpaul{ 2561144888Swpaul struct timespec ts; 2562189488Sweongyo 2563144888Swpaul nanouptime(&ts); 2564144888Swpaul *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000; 2565123822Swpaul} 2566123822Swpaul 2567144888Swpaulstatic void 2568140751SwpaulNdisInitializeString(dst, src) 2569151207Swpaul unicode_string *dst; 2570123507Swpaul char *src; 2571123507Swpaul{ 2572151207Swpaul ansi_string as; 2573151207Swpaul RtlInitAnsiString(&as, src); 2574151207Swpaul RtlAnsiStringToUnicodeString(dst, &as, TRUE); 2575123507Swpaul} 2576123507Swpaul 2577144888Swpaulstatic void 2578140751SwpaulNdisFreeString(str) 2579151207Swpaul unicode_string *str; 2580123507Swpaul{ 2581151207Swpaul RtlFreeUnicodeString(str); 2582123507Swpaul} 2583123507Swpaul 2584144888Swpaulstatic ndis_status 2585140751SwpaulNdisMRemoveMiniport(adapter) 2586123507Swpaul ndis_handle *adapter; 2587123507Swpaul{ 2588198786Srpaulo return (NDIS_STATUS_SUCCESS); 2589123507Swpaul} 2590123507Swpaul 2591144888Swpaulstatic void 2592140751SwpaulNdisInitAnsiString(dst, src) 2593151207Swpaul ansi_string *dst; 2594123526Swpaul char *src; 2595123526Swpaul{ 2596151207Swpaul RtlInitAnsiString(dst, src); 2597123526Swpaul} 2598123526Swpaul 2599144888Swpaulstatic void 2600140751SwpaulNdisInitUnicodeString(dst, src) 2601151207Swpaul unicode_string *dst; 2602123941Swpaul uint16_t *src; 2603123941Swpaul{ 2604151207Swpaul RtlInitUnicodeString(dst, src); 2605123941Swpaul} 2606123941Swpaul 2607144888Swpaulstatic void NdisMGetDeviceProperty(adapter, phydevobj, 2608123526Swpaul funcdevobj, nextdevobj, resources, transresources) 2609123526Swpaul ndis_handle adapter; 2610125551Swpaul device_object **phydevobj; 2611125551Swpaul device_object **funcdevobj; 2612125551Swpaul device_object **nextdevobj; 2613123526Swpaul cm_resource_list *resources; 2614123526Swpaul cm_resource_list *transresources; 2615123526Swpaul{ 2616125551Swpaul ndis_miniport_block *block; 2617125551Swpaul 2618125551Swpaul block = (ndis_miniport_block *)adapter; 2619125551Swpaul 2620125551Swpaul if (phydevobj != NULL) 2621141524Swpaul *phydevobj = block->nmb_physdeviceobj; 2622125551Swpaul if (funcdevobj != NULL) 2623141524Swpaul *funcdevobj = block->nmb_deviceobj; 2624141524Swpaul if (nextdevobj != NULL) 2625141524Swpaul *nextdevobj = block->nmb_nextdeviceobj; 2626123526Swpaul} 2627123526Swpaul 2628144888Swpaulstatic void 2629140751SwpaulNdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen) 2630123721Swpaul ndis_packet *packet; 2631123721Swpaul ndis_buffer **buf; 2632123721Swpaul void **firstva; 2633123721Swpaul uint32_t *firstlen; 2634123721Swpaul uint32_t *totlen; 2635123721Swpaul{ 2636123721Swpaul ndis_buffer *tmp; 2637123721Swpaul 2638123721Swpaul tmp = packet->np_private.npp_head; 2639123721Swpaul *buf = tmp; 2640123721Swpaul if (tmp == NULL) { 2641123721Swpaul *firstva = NULL; 2642123721Swpaul *firstlen = *totlen = 0; 2643123721Swpaul } else { 2644140751Swpaul *firstva = MmGetMdlVirtualAddress(tmp); 2645140751Swpaul *firstlen = *totlen = MmGetMdlByteCount(tmp); 2646140751Swpaul for (tmp = tmp->mdl_next; tmp != NULL; tmp = tmp->mdl_next) 2647140751Swpaul *totlen += MmGetMdlByteCount(tmp); 2648123721Swpaul } 2649123721Swpaul} 2650123721Swpaul 2651144888Swpaulstatic void 2652140751SwpaulNdisGetFirstBufferFromPacketSafe(packet, buf, firstva, firstlen, totlen, prio) 2653123721Swpaul ndis_packet *packet; 2654123721Swpaul ndis_buffer **buf; 2655123721Swpaul void **firstva; 2656123721Swpaul uint32_t *firstlen; 2657123721Swpaul uint32_t *totlen; 2658123721Swpaul uint32_t prio; 2659123721Swpaul{ 2660140751Swpaul NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen); 2661123721Swpaul} 2662123721Swpaul 2663132973Swpaulstatic int 2664132973Swpaulndis_find_sym(lf, filename, suffix, sym) 2665132973Swpaul linker_file_t lf; 2666132973Swpaul char *filename; 2667132973Swpaul char *suffix; 2668132973Swpaul caddr_t *sym; 2669132973Swpaul{ 2670143086Swpaul char *fullsym; 2671133876Swpaul char *suf; 2672132973Swpaul int i; 2673132973Swpaul 2674143086Swpaul fullsym = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0); 2675143086Swpaul if (fullsym == NULL) 2676198786Srpaulo return (ENOMEM); 2677143086Swpaul 2678143086Swpaul bzero(fullsym, MAXPATHLEN); 2679143086Swpaul strncpy(fullsym, filename, MAXPATHLEN); 2680143086Swpaul if (strlen(filename) < 4) { 2681143086Swpaul ExFreePool(fullsym); 2682198786Srpaulo return (EINVAL); 2683143086Swpaul } 2684133876Swpaul 2685133876Swpaul /* If the filename has a .ko suffix, strip if off. */ 2686133876Swpaul suf = fullsym + (strlen(filename) - 3); 2687133876Swpaul if (strcmp(suf, ".ko") == 0) 2688133876Swpaul *suf = '\0'; 2689133876Swpaul 2690132973Swpaul for (i = 0; i < strlen(fullsym); i++) { 2691132973Swpaul if (fullsym[i] == '.') 2692132973Swpaul fullsym[i] = '_'; 2693132973Swpaul else 2694132973Swpaul fullsym[i] = tolower(fullsym[i]); 2695132973Swpaul } 2696132973Swpaul strcat(fullsym, suffix); 2697132973Swpaul *sym = linker_file_lookup_symbol(lf, fullsym, 0); 2698143086Swpaul ExFreePool(fullsym); 2699132973Swpaul if (*sym == 0) 2700198786Srpaulo return (ENOENT); 2701132973Swpaul 2702198786Srpaulo return (0); 2703132973Swpaul} 2704132973Swpaul 2705159797Sjhbstruct ndis_checkmodule { 2706159797Sjhb char *afilename; 2707159797Sjhb ndis_fh *fh; 2708159797Sjhb}; 2709159797Sjhb 2710159797Sjhb/* 2711159797Sjhb * See if a single module contains the symbols for a specified file. 2712159797Sjhb */ 2713159797Sjhbstatic int 2714159797SjhbNdisCheckModule(linker_file_t lf, void *context) 2715159797Sjhb{ 2716159797Sjhb struct ndis_checkmodule *nc; 2717159797Sjhb caddr_t kldstart, kldend; 2718159797Sjhb 2719159797Sjhb nc = (struct ndis_checkmodule *)context; 2720159797Sjhb if (ndis_find_sym(lf, nc->afilename, "_start", &kldstart)) 2721159797Sjhb return (0); 2722159797Sjhb if (ndis_find_sym(lf, nc->afilename, "_end", &kldend)) 2723159797Sjhb return (0); 2724159797Sjhb nc->fh->nf_vp = lf; 2725159797Sjhb nc->fh->nf_map = NULL; 2726159797Sjhb nc->fh->nf_type = NDIS_FH_TYPE_MODULE; 2727159797Sjhb nc->fh->nf_maplen = (kldend - kldstart) & 0xFFFFFFFF; 2728159797Sjhb return (1); 2729159797Sjhb} 2730159797Sjhb 2731123822Swpaul/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */ 2732144888Swpaulstatic void 2733140751SwpaulNdisOpenFile(status, filehandle, filelength, filename, highestaddr) 2734123822Swpaul ndis_status *status; 2735123822Swpaul ndis_handle *filehandle; 2736123822Swpaul uint32_t *filelength; 2737151207Swpaul unicode_string *filename; 2738123822Swpaul ndis_physaddr highestaddr; 2739123822Swpaul{ 2740151207Swpaul ansi_string as; 2741123822Swpaul char *afilename = NULL; 2742124272Swpaul struct thread *td = curthread; 2743124272Swpaul struct nameidata nd; 2744159808Sjhb int flags, error, vfslocked; 2745124272Swpaul struct vattr vat; 2746124272Swpaul struct vattr *vap = &vat; 2747124272Swpaul ndis_fh *fh; 2748143086Swpaul char *path; 2749159797Sjhb struct ndis_checkmodule nc; 2750123822Swpaul 2751151207Swpaul if (RtlUnicodeStringToAnsiString(&as, filename, TRUE)) { 2752151207Swpaul *status = NDIS_STATUS_RESOURCES; 2753151207Swpaul return; 2754151207Swpaul } 2755124272Swpaul 2756151207Swpaul afilename = strdup(as.as_buf, M_DEVBUF); 2757151207Swpaul RtlFreeAnsiString(&as); 2758151207Swpaul 2759143086Swpaul fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0); 2760124272Swpaul if (fh == NULL) { 2761145895Swpaul free(afilename, M_DEVBUF); 2762124272Swpaul *status = NDIS_STATUS_RESOURCES; 2763124272Swpaul return; 2764124272Swpaul } 2765124272Swpaul 2766145895Swpaul fh->nf_name = afilename; 2767145895Swpaul 2768132973Swpaul /* 2769132973Swpaul * During system bootstrap, it's impossible to load files 2770132973Swpaul * from the rootfs since it's not mounted yet. We therefore 2771132973Swpaul * offer the possibility of opening files that have been 2772132973Swpaul * preloaded as modules instead. Both choices will work 2773132973Swpaul * when kldloading a module from multiuser, but only the 2774132973Swpaul * module option will work during bootstrap. The module 2775132973Swpaul * loading option works by using the ndiscvt(8) utility 2776132973Swpaul * to convert the arbitrary file into a .ko using objcopy(1). 2777132973Swpaul * This file will contain two special symbols: filename_start 2778132973Swpaul * and filename_end. All we have to do is traverse the KLD 2779132973Swpaul * list in search of those symbols and we've found the file 2780132973Swpaul * data. As an added bonus, ndiscvt(8) will also generate 2781132973Swpaul * a normal .o file which can be linked statically with 2782132973Swpaul * the kernel. This means that the symbols will actual reside 2783132973Swpaul * in the kernel's symbol table, but that doesn't matter to 2784132973Swpaul * us since the kernel appears to us as just another module. 2785132973Swpaul */ 2786132973Swpaul 2787159797Sjhb nc.afilename = afilename; 2788159797Sjhb nc.fh = fh; 2789159797Sjhb if (linker_file_foreach(NdisCheckModule, &nc)) { 2790159797Sjhb *filelength = fh->nf_maplen; 2791132973Swpaul *filehandle = fh; 2792132973Swpaul *status = NDIS_STATUS_SUCCESS; 2793132973Swpaul return; 2794132973Swpaul } 2795132973Swpaul 2796132973Swpaul if (TAILQ_EMPTY(&mountlist)) { 2797144256Swpaul ExFreePool(fh); 2798132973Swpaul *status = NDIS_STATUS_FILE_NOT_FOUND; 2799132973Swpaul printf("NDIS: could not find file %s in linker list\n", 2800132973Swpaul afilename); 2801132973Swpaul printf("NDIS: and no filesystems mounted yet, " 2802132973Swpaul "aborting NdisOpenFile()\n"); 2803132973Swpaul free(afilename, M_DEVBUF); 2804132973Swpaul return; 2805132973Swpaul } 2806132973Swpaul 2807143086Swpaul path = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0); 2808143086Swpaul if (path == NULL) { 2809144256Swpaul ExFreePool(fh); 2810145895Swpaul free(afilename, M_DEVBUF); 2811143086Swpaul *status = NDIS_STATUS_RESOURCES; 2812143086Swpaul return; 2813143086Swpaul } 2814143086Swpaul 2815143086Swpaul snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename); 2816132973Swpaul 2817125377Swpaul /* Some threads don't have a current working directory. */ 2818125377Swpaul 2819125377Swpaul if (td->td_proc->p_fd->fd_rdir == NULL) 2820125377Swpaul td->td_proc->p_fd->fd_rdir = rootvnode; 2821125377Swpaul if (td->td_proc->p_fd->fd_cdir == NULL) 2822125377Swpaul td->td_proc->p_fd->fd_cdir = rootvnode; 2823125377Swpaul 2824159808Sjhb NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, path, td); 2825124272Swpaul 2826124272Swpaul flags = FREAD; 2827170152Skib error = vn_open(&nd, &flags, 0, NULL); 2828124272Swpaul if (error) { 2829124272Swpaul *status = NDIS_STATUS_FILE_NOT_FOUND; 2830143086Swpaul ExFreePool(fh); 2831127887Swpaul printf("NDIS: open file %s failed: %d\n", path, error); 2832143086Swpaul ExFreePool(path); 2833145895Swpaul free(afilename, M_DEVBUF); 2834124272Swpaul return; 2835124272Swpaul } 2836159808Sjhb vfslocked = NDHASGIANT(&nd); 2837124272Swpaul 2838143086Swpaul ExFreePool(path); 2839143086Swpaul 2840124272Swpaul NDFREE(&nd, NDF_ONLY_PNBUF); 2841124272Swpaul 2842124272Swpaul /* Get the file size. */ 2843182371Sattilio VOP_GETATTR(nd.ni_vp, vap, td->td_ucred); 2844175294Sattilio VOP_UNLOCK(nd.ni_vp, 0); 2845159808Sjhb VFS_UNLOCK_GIANT(vfslocked); 2846124272Swpaul 2847124272Swpaul fh->nf_vp = nd.ni_vp; 2848124272Swpaul fh->nf_map = NULL; 2849132973Swpaul fh->nf_type = NDIS_FH_TYPE_VFS; 2850124272Swpaul *filehandle = fh; 2851124272Swpaul *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF; 2852124272Swpaul *status = NDIS_STATUS_SUCCESS; 2853123822Swpaul} 2854123822Swpaul 2855144888Swpaulstatic void 2856140751SwpaulNdisMapFile(status, mappedbuffer, filehandle) 2857123822Swpaul ndis_status *status; 2858123822Swpaul void **mappedbuffer; 2859123822Swpaul ndis_handle filehandle; 2860123822Swpaul{ 2861124272Swpaul ndis_fh *fh; 2862124272Swpaul struct thread *td = curthread; 2863133876Swpaul linker_file_t lf; 2864133876Swpaul caddr_t kldstart; 2865233353Skib int error, vfslocked; 2866233353Skib ssize_t resid; 2867159808Sjhb struct vnode *vp; 2868123822Swpaul 2869124272Swpaul if (filehandle == NULL) { 2870124272Swpaul *status = NDIS_STATUS_FAILURE; 2871124272Swpaul return; 2872124272Swpaul } 2873124272Swpaul 2874124272Swpaul fh = (ndis_fh *)filehandle; 2875124272Swpaul 2876124272Swpaul if (fh->nf_vp == NULL) { 2877124272Swpaul *status = NDIS_STATUS_FAILURE; 2878124272Swpaul return; 2879124272Swpaul } 2880124272Swpaul 2881124272Swpaul if (fh->nf_map != NULL) { 2882124272Swpaul *status = NDIS_STATUS_ALREADY_MAPPED; 2883124272Swpaul return; 2884124272Swpaul } 2885124272Swpaul 2886132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_MODULE) { 2887133876Swpaul lf = fh->nf_vp; 2888145895Swpaul if (ndis_find_sym(lf, fh->nf_name, "_start", &kldstart)) { 2889133876Swpaul *status = NDIS_STATUS_FAILURE; 2890133876Swpaul return; 2891133876Swpaul } 2892133876Swpaul fh->nf_map = kldstart; 2893132973Swpaul *status = NDIS_STATUS_SUCCESS; 2894132973Swpaul *mappedbuffer = fh->nf_map; 2895132973Swpaul return; 2896132973Swpaul } 2897132973Swpaul 2898143086Swpaul fh->nf_map = ExAllocatePoolWithTag(NonPagedPool, fh->nf_maplen, 0); 2899124272Swpaul 2900124272Swpaul if (fh->nf_map == NULL) { 2901124272Swpaul *status = NDIS_STATUS_RESOURCES; 2902124272Swpaul return; 2903124272Swpaul } 2904124272Swpaul 2905159808Sjhb vp = fh->nf_vp; 2906159808Sjhb vfslocked = VFS_LOCK_GIANT(vp->v_mount); 2907159808Sjhb error = vn_rdwr(UIO_READ, vp, fh->nf_map, fh->nf_maplen, 0, 2908124272Swpaul UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td); 2909159808Sjhb VFS_UNLOCK_GIANT(vfslocked); 2910124272Swpaul 2911124272Swpaul if (error) 2912124272Swpaul *status = NDIS_STATUS_FAILURE; 2913124272Swpaul else { 2914124272Swpaul *status = NDIS_STATUS_SUCCESS; 2915124272Swpaul *mappedbuffer = fh->nf_map; 2916124272Swpaul } 2917123822Swpaul} 2918123822Swpaul 2919144888Swpaulstatic void 2920140751SwpaulNdisUnmapFile(filehandle) 2921123822Swpaul ndis_handle filehandle; 2922123822Swpaul{ 2923124272Swpaul ndis_fh *fh; 2924124272Swpaul fh = (ndis_fh *)filehandle; 2925124272Swpaul 2926124272Swpaul if (fh->nf_map == NULL) 2927124272Swpaul return; 2928132973Swpaul 2929132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_VFS) 2930143086Swpaul ExFreePool(fh->nf_map); 2931124272Swpaul fh->nf_map = NULL; 2932123822Swpaul} 2933123822Swpaul 2934144888Swpaulstatic void 2935140751SwpaulNdisCloseFile(filehandle) 2936123822Swpaul ndis_handle filehandle; 2937123822Swpaul{ 2938124272Swpaul struct thread *td = curthread; 2939124272Swpaul ndis_fh *fh; 2940159808Sjhb int vfslocked; 2941159808Sjhb struct vnode *vp; 2942124272Swpaul 2943124272Swpaul if (filehandle == NULL) 2944124272Swpaul return; 2945124272Swpaul 2946124272Swpaul fh = (ndis_fh *)filehandle; 2947124272Swpaul if (fh->nf_map != NULL) { 2948132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_VFS) 2949143086Swpaul ExFreePool(fh->nf_map); 2950124272Swpaul fh->nf_map = NULL; 2951124272Swpaul } 2952124272Swpaul 2953124272Swpaul if (fh->nf_vp == NULL) 2954124272Swpaul return; 2955124272Swpaul 2956132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_VFS) { 2957159808Sjhb vp = fh->nf_vp; 2958159808Sjhb vfslocked = VFS_LOCK_GIANT(vp->v_mount); 2959159808Sjhb vn_close(vp, FREAD, td->td_ucred, td); 2960159808Sjhb VFS_UNLOCK_GIANT(vfslocked); 2961132973Swpaul } 2962124272Swpaul 2963124272Swpaul fh->nf_vp = NULL; 2964145895Swpaul free(fh->nf_name, M_DEVBUF); 2965143086Swpaul ExFreePool(fh); 2966123822Swpaul} 2967123822Swpaul 2968144888Swpaulstatic uint8_t 2969140751SwpaulNdisSystemProcessorCount() 2970123848Swpaul{ 2971198786Srpaulo return (mp_ncpus); 2972124509Swpaul} 2973123848Swpaul 2974215779Sbschmidtstatic void 2975215779SbschmidtNdisGetCurrentProcessorCounts(idle_count, kernel_and_user, index) 2976215779Sbschmidt uint32_t *idle_count; 2977215779Sbschmidt uint32_t *kernel_and_user; 2978215779Sbschmidt uint32_t *index; 2979215779Sbschmidt{ 2980215779Sbschmidt struct pcpu *pcpu; 2981215779Sbschmidt 2982215779Sbschmidt pcpu = pcpu_find(curthread->td_oncpu); 2983215779Sbschmidt *index = pcpu->pc_cpuid; 2984215779Sbschmidt *idle_count = pcpu->pc_cp_time[CP_IDLE]; 2985215779Sbschmidt *kernel_and_user = pcpu->pc_cp_time[CP_INTR]; 2986215779Sbschmidt} 2987215779Sbschmidt 2988124116Swpaultypedef void (*ndis_statusdone_handler)(ndis_handle); 2989124116Swpaultypedef void (*ndis_status_handler)(ndis_handle, ndis_status, 2990189488Sweongyo void *, uint32_t); 2991124116Swpaul 2992144888Swpaulstatic void 2993140751SwpaulNdisMIndicateStatusComplete(adapter) 2994124116Swpaul ndis_handle adapter; 2995124116Swpaul{ 2996124116Swpaul ndis_miniport_block *block; 2997144888Swpaul ndis_statusdone_handler statusdonefunc; 2998124116Swpaul 2999124116Swpaul block = (ndis_miniport_block *)adapter; 3000124116Swpaul statusdonefunc = block->nmb_statusdone_func; 3001124116Swpaul 3002141963Swpaul MSCALL1(statusdonefunc, adapter); 3003124116Swpaul} 3004124116Swpaul 3005144888Swpaulstatic void 3006140751SwpaulNdisMIndicateStatus(adapter, status, sbuf, slen) 3007124116Swpaul ndis_handle adapter; 3008124116Swpaul ndis_status status; 3009124116Swpaul void *sbuf; 3010124116Swpaul uint32_t slen; 3011124116Swpaul{ 3012124116Swpaul ndis_miniport_block *block; 3013144888Swpaul ndis_status_handler statusfunc; 3014124116Swpaul 3015124116Swpaul block = (ndis_miniport_block *)adapter; 3016124116Swpaul statusfunc = block->nmb_status_func; 3017124116Swpaul 3018141963Swpaul MSCALL4(statusfunc, adapter, status, sbuf, slen); 3019124116Swpaul} 3020124116Swpaul 3021145895Swpaul/* 3022145895Swpaul * The DDK documentation says that you should use IoQueueWorkItem() 3023145895Swpaul * instead of ExQueueWorkItem(). The problem is, IoQueueWorkItem() 3024145895Swpaul * is fundamentally incompatible with NdisScheduleWorkItem(), which 3025145895Swpaul * depends on the API semantics of ExQueueWorkItem(). In our world, 3026145895Swpaul * ExQueueWorkItem() is implemented on top of IoAllocateQueueItem() 3027145895Swpaul * anyway. 3028146273Swpaul * 3029146273Swpaul * There are actually three distinct APIs here. NdisScheduleWorkItem() 3030146273Swpaul * takes a pointer to an NDIS_WORK_ITEM. ExQueueWorkItem() takes a pointer 3031146273Swpaul * to a WORK_QUEUE_ITEM. And finally, IoQueueWorkItem() takes a pointer 3032146273Swpaul * to an opaque work item thingie which you get from IoAllocateWorkItem(). 3033146273Swpaul * An NDIS_WORK_ITEM is not the same as a WORK_QUEUE_ITEM. However, 3034146273Swpaul * the NDIS_WORK_ITEM has some opaque storage at the end of it, and we 3035146273Swpaul * (ab)use this storage as a WORK_QUEUE_ITEM, which is what we submit 3036146273Swpaul * to ExQueueWorkItem(). 3037146273Swpaul * 3038146273Swpaul * Got all that? (Sheesh.) 3039145895Swpaul */ 3040124122Swpaul 3041145895Swpaulndis_status 3042140751SwpaulNdisScheduleWorkItem(work) 3043124122Swpaul ndis_work_item *work; 3044124122Swpaul{ 3045146273Swpaul work_queue_item *wqi; 3046146273Swpaul 3047146273Swpaul wqi = (work_queue_item *)work->nwi_wraprsvd; 3048146273Swpaul ExInitializeWorkItem(wqi, 3049146273Swpaul (work_item_func)work->nwi_func, work->nwi_ctx); 3050146273Swpaul ExQueueWorkItem(wqi, WORKQUEUE_DELAYED); 3051151207Swpaul 3052198786Srpaulo return (NDIS_STATUS_SUCCESS); 3053124122Swpaul} 3054124122Swpaul 3055144888Swpaulstatic void 3056140751SwpaulNdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen) 3057124541Swpaul ndis_packet *dpkt; 3058124541Swpaul uint32_t doff; 3059124541Swpaul uint32_t reqlen; 3060124541Swpaul ndis_packet *spkt; 3061124541Swpaul uint32_t soff; 3062124541Swpaul uint32_t *cpylen; 3063124541Swpaul{ 3064124541Swpaul ndis_buffer *src, *dst; 3065124541Swpaul char *sptr, *dptr; 3066124541Swpaul int resid, copied, len, scnt, dcnt; 3067124541Swpaul 3068124541Swpaul *cpylen = 0; 3069124541Swpaul 3070124541Swpaul src = spkt->np_private.npp_head; 3071124541Swpaul dst = dpkt->np_private.npp_head; 3072124541Swpaul 3073140751Swpaul sptr = MmGetMdlVirtualAddress(src); 3074140751Swpaul dptr = MmGetMdlVirtualAddress(dst); 3075140751Swpaul scnt = MmGetMdlByteCount(src); 3076140751Swpaul dcnt = MmGetMdlByteCount(dst); 3077124541Swpaul 3078124541Swpaul while (soff) { 3079140751Swpaul if (MmGetMdlByteCount(src) > soff) { 3080124541Swpaul sptr += soff; 3081140751Swpaul scnt = MmGetMdlByteCount(src)- soff; 3082124541Swpaul break; 3083124541Swpaul } 3084140751Swpaul soff -= MmGetMdlByteCount(src); 3085140751Swpaul src = src->mdl_next; 3086124541Swpaul if (src == NULL) 3087124541Swpaul return; 3088140751Swpaul sptr = MmGetMdlVirtualAddress(src); 3089124541Swpaul } 3090124541Swpaul 3091124541Swpaul while (doff) { 3092140751Swpaul if (MmGetMdlByteCount(dst) > doff) { 3093124541Swpaul dptr += doff; 3094140751Swpaul dcnt = MmGetMdlByteCount(dst) - doff; 3095124541Swpaul break; 3096124541Swpaul } 3097140751Swpaul doff -= MmGetMdlByteCount(dst); 3098140751Swpaul dst = dst->mdl_next; 3099124541Swpaul if (dst == NULL) 3100124541Swpaul return; 3101140751Swpaul dptr = MmGetMdlVirtualAddress(dst); 3102124541Swpaul } 3103124541Swpaul 3104124541Swpaul resid = reqlen; 3105124541Swpaul copied = 0; 3106124541Swpaul 3107124541Swpaul while(1) { 3108124541Swpaul if (resid < scnt) 3109124541Swpaul len = resid; 3110124541Swpaul else 3111124541Swpaul len = scnt; 3112124541Swpaul if (dcnt < len) 3113124541Swpaul len = dcnt; 3114124541Swpaul 3115124541Swpaul bcopy(sptr, dptr, len); 3116124541Swpaul 3117124541Swpaul copied += len; 3118124541Swpaul resid -= len; 3119124541Swpaul if (resid == 0) 3120124541Swpaul break; 3121124541Swpaul 3122124541Swpaul dcnt -= len; 3123124541Swpaul if (dcnt == 0) { 3124140751Swpaul dst = dst->mdl_next; 3125124541Swpaul if (dst == NULL) 3126124541Swpaul break; 3127140751Swpaul dptr = MmGetMdlVirtualAddress(dst); 3128140751Swpaul dcnt = MmGetMdlByteCount(dst); 3129124541Swpaul } 3130124541Swpaul 3131124541Swpaul scnt -= len; 3132124541Swpaul if (scnt == 0) { 3133140751Swpaul src = src->mdl_next; 3134124541Swpaul if (src == NULL) 3135124541Swpaul break; 3136140751Swpaul sptr = MmGetMdlVirtualAddress(src); 3137140751Swpaul scnt = MmGetMdlByteCount(src); 3138124541Swpaul } 3139124541Swpaul } 3140124541Swpaul 3141124541Swpaul *cpylen = copied; 3142124541Swpaul} 3143124541Swpaul 3144144888Swpaulstatic void 3145140751SwpaulNdisCopyFromPacketToPacketSafe(dpkt, doff, reqlen, spkt, soff, cpylen, prio) 3146124541Swpaul ndis_packet *dpkt; 3147124541Swpaul uint32_t doff; 3148124541Swpaul uint32_t reqlen; 3149124541Swpaul ndis_packet *spkt; 3150124541Swpaul uint32_t soff; 3151124541Swpaul uint32_t *cpylen; 3152124541Swpaul uint32_t prio; 3153124541Swpaul{ 3154140751Swpaul NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen); 3155124541Swpaul} 3156124541Swpaul 3157174240Sthompsastatic void 3158174240SthompsaNdisIMCopySendPerPacketInfo(dpkt, spkt) 3159174240Sthompsa ndis_packet *dpkt; 3160174240Sthompsa ndis_packet *spkt; 3161174240Sthompsa{ 3162174240Sthompsa memcpy(&dpkt->np_ext, &spkt->np_ext, sizeof(ndis_packet_extension)); 3163174240Sthompsa} 3164174240Sthompsa 3165144888Swpaulstatic ndis_status 3166140751SwpaulNdisMRegisterDevice(handle, devname, symname, majorfuncs, devobj, devhandle) 3167125551Swpaul ndis_handle handle; 3168151207Swpaul unicode_string *devname; 3169151207Swpaul unicode_string *symname; 3170125551Swpaul driver_dispatch *majorfuncs[]; 3171125551Swpaul void **devobj; 3172125551Swpaul ndis_handle *devhandle; 3173125057Swpaul{ 3174146364Swpaul uint32_t status; 3175146364Swpaul device_object *dobj; 3176125551Swpaul 3177146364Swpaul status = IoCreateDevice(handle, 0, devname, 3178146364Swpaul FILE_DEVICE_UNKNOWN, 0, FALSE, &dobj); 3179125551Swpaul 3180146364Swpaul if (status == STATUS_SUCCESS) { 3181146364Swpaul *devobj = dobj; 3182146364Swpaul *devhandle = dobj; 3183146364Swpaul } 3184146364Swpaul 3185198786Srpaulo return (status); 3186125057Swpaul} 3187125057Swpaul 3188144888Swpaulstatic ndis_status 3189140751SwpaulNdisMDeregisterDevice(handle) 3190125551Swpaul ndis_handle handle; 3191125057Swpaul{ 3192146364Swpaul IoDeleteDevice(handle); 3193198786Srpaulo return (NDIS_STATUS_SUCCESS); 3194125057Swpaul} 3195125057Swpaul 3196144888Swpaulstatic ndis_status 3197140751SwpaulNdisMQueryAdapterInstanceName(name, handle) 3198151207Swpaul unicode_string *name; 3199125551Swpaul ndis_handle handle; 3200125551Swpaul{ 3201125551Swpaul ndis_miniport_block *block; 3202141524Swpaul device_t dev; 3203151207Swpaul ansi_string as; 3204125057Swpaul 3205125551Swpaul block = (ndis_miniport_block *)handle; 3206141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 3207141524Swpaul 3208151207Swpaul RtlInitAnsiString(&as, __DECONST(char *, device_get_nameunit(dev))); 3209151207Swpaul if (RtlAnsiStringToUnicodeString(name, &as, TRUE)) 3210198786Srpaulo return (NDIS_STATUS_RESOURCES); 3211125551Swpaul 3212198786Srpaulo return (NDIS_STATUS_SUCCESS); 3213125551Swpaul} 3214125551Swpaul 3215144888Swpaulstatic void 3216140751SwpaulNdisMRegisterUnloadHandler(handle, func) 3217125551Swpaul ndis_handle handle; 3218125551Swpaul void *func; 3219125551Swpaul{ 3220125551Swpaul} 3221125551Swpaul 3222144888Swpaulstatic void 3223123474Swpauldummy() 3224123474Swpaul{ 3225198786Srpaulo printf("NDIS dummy called...\n"); 3226123474Swpaul} 3227123474Swpaul 3228144888Swpaul/* 3229144888Swpaul * Note: a couple of entries in this table specify the 3230144888Swpaul * number of arguments as "foo + 1". These are routines 3231144888Swpaul * that accept a 64-bit argument, passed by value. On 3232144888Swpaul * x86, these arguments consume two longwords on the stack, 3233144888Swpaul * so we lie and say there's one additional argument so 3234144888Swpaul * that the wrapping routines will do the right thing. 3235144888Swpaul */ 3236144888Swpaul 3237123474Swpaulimage_patch_table ndis_functbl[] = { 3238144888Swpaul IMPORT_SFUNC(NdisCopyFromPacketToPacket, 6), 3239144888Swpaul IMPORT_SFUNC(NdisCopyFromPacketToPacketSafe, 7), 3240174240Sthompsa IMPORT_SFUNC(NdisIMCopySendPerPacketInfo, 2), 3241144888Swpaul IMPORT_SFUNC(NdisScheduleWorkItem, 1), 3242144888Swpaul IMPORT_SFUNC(NdisMIndicateStatusComplete, 1), 3243144888Swpaul IMPORT_SFUNC(NdisMIndicateStatus, 4), 3244144888Swpaul IMPORT_SFUNC(NdisSystemProcessorCount, 0), 3245215779Sbschmidt IMPORT_SFUNC(NdisGetCurrentProcessorCounts, 3), 3246144888Swpaul IMPORT_SFUNC(NdisUnchainBufferAtBack, 2), 3247144888Swpaul IMPORT_SFUNC(NdisGetFirstBufferFromPacket, 5), 3248144888Swpaul IMPORT_SFUNC(NdisGetFirstBufferFromPacketSafe, 6), 3249144888Swpaul IMPORT_SFUNC(NdisGetBufferPhysicalArraySize, 2), 3250144888Swpaul IMPORT_SFUNC(NdisMGetDeviceProperty, 6), 3251144888Swpaul IMPORT_SFUNC(NdisInitAnsiString, 2), 3252144888Swpaul IMPORT_SFUNC(NdisInitUnicodeString, 2), 3253144888Swpaul IMPORT_SFUNC(NdisWriteConfiguration, 4), 3254144888Swpaul IMPORT_SFUNC(NdisAnsiStringToUnicodeString, 2), 3255144888Swpaul IMPORT_SFUNC(NdisTerminateWrapper, 2), 3256144888Swpaul IMPORT_SFUNC(NdisOpenConfigurationKeyByName, 4), 3257144888Swpaul IMPORT_SFUNC(NdisOpenConfigurationKeyByIndex, 5), 3258144888Swpaul IMPORT_SFUNC(NdisMRemoveMiniport, 1), 3259189488Sweongyo IMPORT_SFUNC(NdisInitializeString, 2), 3260189488Sweongyo IMPORT_SFUNC(NdisFreeString, 1), 3261144888Swpaul IMPORT_SFUNC(NdisGetCurrentSystemTime, 1), 3262216242Sbschmidt IMPORT_SFUNC(NdisGetRoutineAddress, 1), 3263144888Swpaul IMPORT_SFUNC(NdisGetSystemUpTime, 1), 3264215779Sbschmidt IMPORT_SFUNC(NdisGetVersion, 0), 3265144888Swpaul IMPORT_SFUNC(NdisMSynchronizeWithInterrupt, 3), 3266144888Swpaul IMPORT_SFUNC(NdisMAllocateSharedMemoryAsync, 4), 3267144888Swpaul IMPORT_SFUNC(NdisInterlockedInsertHeadList, 3), 3268144888Swpaul IMPORT_SFUNC(NdisInterlockedInsertTailList, 3), 3269144888Swpaul IMPORT_SFUNC(NdisInterlockedRemoveHeadList, 2), 3270144888Swpaul IMPORT_SFUNC(NdisInitializeWrapper, 4), 3271144888Swpaul IMPORT_SFUNC(NdisMRegisterMiniport, 3), 3272144888Swpaul IMPORT_SFUNC(NdisAllocateMemoryWithTag, 3), 3273144888Swpaul IMPORT_SFUNC(NdisAllocateMemory, 4 + 1), 3274144888Swpaul IMPORT_SFUNC(NdisMSetAttributesEx, 5), 3275144888Swpaul IMPORT_SFUNC(NdisCloseConfiguration, 1), 3276144888Swpaul IMPORT_SFUNC(NdisReadConfiguration, 5), 3277144888Swpaul IMPORT_SFUNC(NdisOpenConfiguration, 3), 3278144888Swpaul IMPORT_SFUNC(NdisAcquireSpinLock, 1), 3279144888Swpaul IMPORT_SFUNC(NdisReleaseSpinLock, 1), 3280144888Swpaul IMPORT_SFUNC(NdisDprAcquireSpinLock, 1), 3281144888Swpaul IMPORT_SFUNC(NdisDprReleaseSpinLock, 1), 3282144888Swpaul IMPORT_SFUNC(NdisAllocateSpinLock, 1), 3283145895Swpaul IMPORT_SFUNC(NdisInitializeReadWriteLock, 1), 3284145895Swpaul IMPORT_SFUNC(NdisAcquireReadWriteLock, 3), 3285145895Swpaul IMPORT_SFUNC(NdisReleaseReadWriteLock, 2), 3286144888Swpaul IMPORT_SFUNC(NdisFreeSpinLock, 1), 3287144888Swpaul IMPORT_SFUNC(NdisFreeMemory, 3), 3288144888Swpaul IMPORT_SFUNC(NdisReadPciSlotInformation, 5), 3289144888Swpaul IMPORT_SFUNC(NdisWritePciSlotInformation, 5), 3290144888Swpaul IMPORT_SFUNC_MAP(NdisImmediateReadPciSlotInformation, 3291144888Swpaul NdisReadPciSlotInformation, 5), 3292144888Swpaul IMPORT_SFUNC_MAP(NdisImmediateWritePciSlotInformation, 3293144888Swpaul NdisWritePciSlotInformation, 5), 3294144888Swpaul IMPORT_CFUNC(NdisWriteErrorLogEntry, 0), 3295144888Swpaul IMPORT_SFUNC(NdisMStartBufferPhysicalMapping, 6), 3296144888Swpaul IMPORT_SFUNC(NdisMCompleteBufferPhysicalMapping, 3), 3297144888Swpaul IMPORT_SFUNC(NdisMInitializeTimer, 4), 3298144888Swpaul IMPORT_SFUNC(NdisInitializeTimer, 3), 3299144888Swpaul IMPORT_SFUNC(NdisSetTimer, 2), 3300144888Swpaul IMPORT_SFUNC(NdisMCancelTimer, 2), 3301144888Swpaul IMPORT_SFUNC_MAP(NdisCancelTimer, NdisMCancelTimer, 2), 3302144888Swpaul IMPORT_SFUNC(NdisMSetPeriodicTimer, 2), 3303144888Swpaul IMPORT_SFUNC(NdisMQueryAdapterResources, 4), 3304144888Swpaul IMPORT_SFUNC(NdisMRegisterIoPortRange, 4), 3305144888Swpaul IMPORT_SFUNC(NdisMDeregisterIoPortRange, 4), 3306144888Swpaul IMPORT_SFUNC(NdisReadNetworkAddress, 4), 3307144888Swpaul IMPORT_SFUNC(NdisQueryMapRegisterCount, 2), 3308144888Swpaul IMPORT_SFUNC(NdisMAllocateMapRegisters, 5), 3309144888Swpaul IMPORT_SFUNC(NdisMFreeMapRegisters, 1), 3310144888Swpaul IMPORT_SFUNC(NdisMAllocateSharedMemory, 5), 3311144888Swpaul IMPORT_SFUNC(NdisMMapIoSpace, 4 + 1), 3312144888Swpaul IMPORT_SFUNC(NdisMUnmapIoSpace, 3), 3313144888Swpaul IMPORT_SFUNC(NdisGetCacheFillSize, 0), 3314144888Swpaul IMPORT_SFUNC(NdisMGetDmaAlignment, 1), 3315144888Swpaul IMPORT_SFUNC(NdisMInitializeScatterGatherDma, 3), 3316144888Swpaul IMPORT_SFUNC(NdisAllocatePacketPool, 4), 3317144888Swpaul IMPORT_SFUNC(NdisAllocatePacketPoolEx, 5), 3318144888Swpaul IMPORT_SFUNC(NdisAllocatePacket, 3), 3319144888Swpaul IMPORT_SFUNC(NdisFreePacket, 1), 3320144888Swpaul IMPORT_SFUNC(NdisFreePacketPool, 1), 3321144888Swpaul IMPORT_SFUNC_MAP(NdisDprAllocatePacket, NdisAllocatePacket, 3), 3322144888Swpaul IMPORT_SFUNC_MAP(NdisDprFreePacket, NdisFreePacket, 1), 3323144888Swpaul IMPORT_SFUNC(NdisAllocateBufferPool, 3), 3324144888Swpaul IMPORT_SFUNC(NdisAllocateBuffer, 5), 3325144888Swpaul IMPORT_SFUNC(NdisQueryBuffer, 3), 3326144888Swpaul IMPORT_SFUNC(NdisQueryBufferSafe, 4), 3327144888Swpaul IMPORT_SFUNC(NdisBufferVirtualAddress, 1), 3328144888Swpaul IMPORT_SFUNC(NdisBufferVirtualAddressSafe, 2), 3329144888Swpaul IMPORT_SFUNC(NdisBufferLength, 1), 3330144888Swpaul IMPORT_SFUNC(NdisFreeBuffer, 1), 3331144888Swpaul IMPORT_SFUNC(NdisFreeBufferPool, 1), 3332144888Swpaul IMPORT_SFUNC(NdisInterlockedIncrement, 1), 3333144888Swpaul IMPORT_SFUNC(NdisInterlockedDecrement, 1), 3334144888Swpaul IMPORT_SFUNC(NdisInitializeEvent, 1), 3335144888Swpaul IMPORT_SFUNC(NdisSetEvent, 1), 3336144888Swpaul IMPORT_SFUNC(NdisResetEvent, 1), 3337144888Swpaul IMPORT_SFUNC(NdisWaitEvent, 2), 3338144888Swpaul IMPORT_SFUNC(NdisUnicodeStringToAnsiString, 2), 3339144888Swpaul IMPORT_SFUNC(NdisMPciAssignResources, 3), 3340144888Swpaul IMPORT_SFUNC(NdisMFreeSharedMemory, 5 + 1), 3341144888Swpaul IMPORT_SFUNC(NdisMRegisterInterrupt, 7), 3342144888Swpaul IMPORT_SFUNC(NdisMDeregisterInterrupt, 1), 3343144888Swpaul IMPORT_SFUNC(NdisMRegisterAdapterShutdownHandler, 3), 3344144888Swpaul IMPORT_SFUNC(NdisMDeregisterAdapterShutdownHandler, 1), 3345144888Swpaul IMPORT_SFUNC(NDIS_BUFFER_TO_SPAN_PAGES, 1), 3346144888Swpaul IMPORT_SFUNC(NdisQueryBufferOffset, 3), 3347144888Swpaul IMPORT_SFUNC(NdisAdjustBufferLength, 2), 3348144888Swpaul IMPORT_SFUNC(NdisPacketPoolUsage, 1), 3349144888Swpaul IMPORT_SFUNC(NdisMSleep, 1), 3350144888Swpaul IMPORT_SFUNC(NdisUnchainBufferAtFront, 2), 3351144888Swpaul IMPORT_SFUNC(NdisReadPcmciaAttributeMemory, 4), 3352144888Swpaul IMPORT_SFUNC(NdisWritePcmciaAttributeMemory, 4), 3353144888Swpaul IMPORT_SFUNC(NdisOpenFile, 5 + 1), 3354144888Swpaul IMPORT_SFUNC(NdisMapFile, 3), 3355144888Swpaul IMPORT_SFUNC(NdisUnmapFile, 1), 3356144888Swpaul IMPORT_SFUNC(NdisCloseFile, 1), 3357144888Swpaul IMPORT_SFUNC(NdisMRegisterDevice, 6), 3358144888Swpaul IMPORT_SFUNC(NdisMDeregisterDevice, 1), 3359144888Swpaul IMPORT_SFUNC(NdisMQueryAdapterInstanceName, 2), 3360144888Swpaul IMPORT_SFUNC(NdisMRegisterUnloadHandler, 2), 3361144888Swpaul IMPORT_SFUNC(ndis_timercall, 4), 3362145895Swpaul IMPORT_SFUNC(ndis_asyncmem_complete, 2), 3363152626Swpaul IMPORT_SFUNC(ndis_intr, 2), 3364151207Swpaul IMPORT_SFUNC(ndis_intrhand, 4), 3365123474Swpaul 3366123474Swpaul /* 3367123474Swpaul * This last entry is a catch-all for any function we haven't 3368123474Swpaul * implemented yet. The PE import list patching routine will 3369123474Swpaul * use it for any function that doesn't have an explicit match 3370123474Swpaul * in this table. 3371123474Swpaul */ 3372123474Swpaul 3373145895Swpaul { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, 3374123474Swpaul 3375123474Swpaul /* End of list. */ 3376123474Swpaul 3377141963Swpaul { NULL, NULL, NULL } 3378123474Swpaul}; 3379