subr_ndis.c revision 151451
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: head/sys/compat/ndis/subr_ndis.c 151451 2005-10-18 19:52:15Z wpaul $"); 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> 98123474Swpaul 99123474Swpaul#include <compat/ndis/pe_var.h> 100145485Swpaul#include <compat/ndis/cfg_var.h> 101123474Swpaul#include <compat/ndis/resource_var.h> 102123512Swpaul#include <compat/ndis/ntoskrnl_var.h> 103128229Swpaul#include <compat/ndis/hal_var.h> 104123474Swpaul#include <compat/ndis/ndis_var.h> 105123474Swpaul#include <dev/if_ndis/if_ndisvar.h> 106123474Swpaul 107151207Swpaul#include <vm/vm.h> 108151207Swpaul#include <vm/vm_param.h> 109151207Swpaul#include <vm/pmap.h> 110151207Swpaul#include <vm/uma.h> 111151207Swpaul#include <vm/vm_kern.h> 112151207Swpaul#include <vm/vm_map.h> 113151207Swpaul 114124272Swpaulstatic char ndis_filepath[MAXPATHLEN]; 115123474Swpaul 116124272SwpaulSYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath, 117124272Swpaul MAXPATHLEN, "Path used by NdisOpenFile() to search for files"); 118124272Swpaul 119144888Swpaulstatic void NdisInitializeWrapper(ndis_handle *, 120141524Swpaul driver_object *, void *, void *); 121144888Swpaulstatic ndis_status NdisMRegisterMiniport(ndis_handle, 122123474Swpaul ndis_miniport_characteristics *, int); 123144888Swpaulstatic ndis_status NdisAllocateMemoryWithTag(void **, 124140751Swpaul uint32_t, uint32_t); 125144888Swpaulstatic ndis_status NdisAllocateMemory(void **, 126123474Swpaul uint32_t, uint32_t, ndis_physaddr); 127144888Swpaulstatic void NdisFreeMemory(void *, uint32_t, uint32_t); 128144888Swpaulstatic ndis_status NdisMSetAttributesEx(ndis_handle, ndis_handle, 129123474Swpaul uint32_t, uint32_t, ndis_interface_type); 130144888Swpaulstatic void NdisOpenConfiguration(ndis_status *, 131140751Swpaul ndis_handle *, ndis_handle); 132144888Swpaulstatic void NdisOpenConfigurationKeyByIndex(ndis_status *, 133151207Swpaul ndis_handle, uint32_t, unicode_string *, ndis_handle *); 134144888Swpaulstatic void NdisOpenConfigurationKeyByName(ndis_status *, 135151207Swpaul ndis_handle, unicode_string *, ndis_handle *); 136123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *, 137123474Swpaul struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); 138123526Swpaulstatic ndis_status ndis_decode_parm(ndis_miniport_block *, 139123526Swpaul ndis_config_parm *, char *); 140144888Swpaulstatic void NdisReadConfiguration(ndis_status *, ndis_config_parm **, 141151207Swpaul ndis_handle, unicode_string *, ndis_parm_type); 142144888Swpaulstatic void NdisWriteConfiguration(ndis_status *, ndis_handle, 143151207Swpaul unicode_string *, ndis_config_parm *); 144144888Swpaulstatic void NdisCloseConfiguration(ndis_handle); 145144888Swpaulstatic void NdisAllocateSpinLock(ndis_spin_lock *); 146144888Swpaulstatic void NdisFreeSpinLock(ndis_spin_lock *); 147144888Swpaulstatic void NdisAcquireSpinLock(ndis_spin_lock *); 148144888Swpaulstatic void NdisReleaseSpinLock(ndis_spin_lock *); 149144888Swpaulstatic void NdisDprAcquireSpinLock(ndis_spin_lock *); 150144888Swpaulstatic void NdisDprReleaseSpinLock(ndis_spin_lock *); 151145895Swpaulstatic void NdisInitializeReadWriteLock(ndis_rw_lock *); 152145895Swpaulstatic void NdisAcquireReadWriteLock(ndis_rw_lock *, 153145895Swpaul uint8_t, ndis_lock_state *); 154145895Swpaulstatic void NdisReleaseReadWriteLock(ndis_rw_lock *, ndis_lock_state *); 155144888Swpaulstatic uint32_t NdisReadPciSlotInformation(ndis_handle, uint32_t, 156123474Swpaul uint32_t, void *, uint32_t); 157144888Swpaulstatic uint32_t NdisWritePciSlotInformation(ndis_handle, uint32_t, 158123474Swpaul uint32_t, void *, uint32_t); 159140751Swpaulstatic void NdisWriteErrorLogEntry(ndis_handle, ndis_error_code, uint32_t, ...); 160123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int); 161144888Swpaulstatic void NdisMStartBufferPhysicalMapping(ndis_handle, 162140751Swpaul ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); 163144888Swpaulstatic void NdisMCompleteBufferPhysicalMapping(ndis_handle, 164140751Swpaul ndis_buffer *, uint32_t); 165144888Swpaulstatic void NdisMInitializeTimer(ndis_miniport_timer *, ndis_handle, 166123474Swpaul ndis_timer_function, void *); 167144888Swpaulstatic void NdisInitializeTimer(ndis_timer *, 168125057Swpaul ndis_timer_function, void *); 169144888Swpaulstatic void NdisSetTimer(ndis_timer *, uint32_t); 170144888Swpaulstatic void NdisMSetPeriodicTimer(ndis_miniport_timer *, uint32_t); 171144888Swpaulstatic void NdisMCancelTimer(ndis_timer *, uint8_t *); 172144888Swpaulstatic void ndis_timercall(kdpc *, ndis_miniport_timer *, 173144174Swpaul void *, void *); 174144888Swpaulstatic void NdisMQueryAdapterResources(ndis_status *, ndis_handle, 175123474Swpaul ndis_resource_list *, uint32_t *); 176144888Swpaulstatic ndis_status NdisMRegisterIoPortRange(void **, 177123474Swpaul ndis_handle, uint32_t, uint32_t); 178144888Swpaulstatic void NdisMDeregisterIoPortRange(ndis_handle, 179123474Swpaul uint32_t, uint32_t, void *); 180144888Swpaulstatic void NdisReadNetworkAddress(ndis_status *, void **, 181123474Swpaul uint32_t *, ndis_handle); 182144888Swpaulstatic ndis_status NdisQueryMapRegisterCount(uint32_t, uint32_t *); 183144888Swpaulstatic ndis_status NdisMAllocateMapRegisters(ndis_handle, 184123474Swpaul uint32_t, uint8_t, uint32_t, uint32_t); 185144888Swpaulstatic void NdisMFreeMapRegisters(ndis_handle); 186123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); 187144888Swpaulstatic void NdisMAllocateSharedMemory(ndis_handle, uint32_t, 188123474Swpaul uint8_t, void **, ndis_physaddr *); 189145895Swpaulstatic void ndis_asyncmem_complete(device_object *, void *); 190144888Swpaulstatic ndis_status NdisMAllocateSharedMemoryAsync(ndis_handle, 191123474Swpaul uint32_t, uint8_t, void *); 192144888Swpaulstatic void NdisMFreeSharedMemory(ndis_handle, uint32_t, 193123474Swpaul uint8_t, void *, ndis_physaddr); 194144888Swpaulstatic ndis_status NdisMMapIoSpace(void **, ndis_handle, 195123474Swpaul ndis_physaddr, uint32_t); 196144888Swpaulstatic void NdisMUnmapIoSpace(ndis_handle, void *, uint32_t); 197144888Swpaulstatic uint32_t NdisGetCacheFillSize(void); 198144888Swpaulstatic uint32_t NdisMGetDmaAlignment(ndis_handle); 199144888Swpaulstatic ndis_status NdisMInitializeScatterGatherDma(ndis_handle, 200123474Swpaul uint8_t, uint32_t); 201144888Swpaulstatic void NdisUnchainBufferAtFront(ndis_packet *, ndis_buffer **); 202144888Swpaulstatic void NdisUnchainBufferAtBack(ndis_packet *, ndis_buffer **); 203144888Swpaulstatic void NdisAllocateBufferPool(ndis_status *, 204123474Swpaul ndis_handle *, uint32_t); 205144888Swpaulstatic void NdisFreeBufferPool(ndis_handle); 206144888Swpaulstatic void NdisAllocateBuffer(ndis_status *, ndis_buffer **, 207123474Swpaul ndis_handle, void *, uint32_t); 208144888Swpaulstatic void NdisFreeBuffer(ndis_buffer *); 209144888Swpaulstatic uint32_t NdisBufferLength(ndis_buffer *); 210144888Swpaulstatic void NdisQueryBuffer(ndis_buffer *, void **, uint32_t *); 211144888Swpaulstatic void NdisQueryBufferSafe(ndis_buffer *, void **, 212123474Swpaul uint32_t *, uint32_t); 213144888Swpaulstatic void *NdisBufferVirtualAddress(ndis_buffer *); 214144888Swpaulstatic void *NdisBufferVirtualAddressSafe(ndis_buffer *, uint32_t); 215144888Swpaulstatic void NdisAdjustBufferLength(ndis_buffer *, int); 216144888Swpaulstatic uint32_t NdisInterlockedIncrement(uint32_t *); 217144888Swpaulstatic uint32_t NdisInterlockedDecrement(uint32_t *); 218144888Swpaulstatic void NdisInitializeEvent(ndis_event *); 219144888Swpaulstatic void NdisSetEvent(ndis_event *); 220144888Swpaulstatic void NdisResetEvent(ndis_event *); 221144888Swpaulstatic uint8_t NdisWaitEvent(ndis_event *, uint32_t); 222151207Swpaulstatic ndis_status NdisUnicodeStringToAnsiString(ansi_string *, 223151207Swpaul unicode_string *); 224144888Swpaulstatic ndis_status 225151207Swpaul NdisAnsiStringToUnicodeString(unicode_string *, ansi_string *); 226144888Swpaulstatic ndis_status NdisMPciAssignResources(ndis_handle, 227123474Swpaul uint32_t, ndis_resource_list **); 228144888Swpaulstatic ndis_status NdisMRegisterInterrupt(ndis_miniport_interrupt *, 229123474Swpaul ndis_handle, uint32_t, uint32_t, uint8_t, 230123474Swpaul uint8_t, ndis_interrupt_mode); 231144888Swpaulstatic void NdisMDeregisterInterrupt(ndis_miniport_interrupt *); 232144888Swpaulstatic void NdisMRegisterAdapterShutdownHandler(ndis_handle, void *, 233123474Swpaul ndis_shutdown_handler); 234144888Swpaulstatic void NdisMDeregisterAdapterShutdownHandler(ndis_handle); 235144888Swpaulstatic uint32_t NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *); 236144888Swpaulstatic void NdisGetBufferPhysicalArraySize(ndis_buffer *, 237140751Swpaul uint32_t *); 238144888Swpaulstatic void NdisQueryBufferOffset(ndis_buffer *, 239123474Swpaul uint32_t *, uint32_t *); 240144888Swpaulstatic uint32_t NdisReadPcmciaAttributeMemory(ndis_handle, 241123474Swpaul uint32_t, void *, uint32_t); 242144888Swpaulstatic uint32_t NdisWritePcmciaAttributeMemory(ndis_handle, 243123474Swpaul uint32_t, void *, uint32_t); 244144888Swpaulstatic list_entry *NdisInterlockedInsertHeadList(list_entry *, 245125551Swpaul list_entry *, ndis_spin_lock *); 246144888Swpaulstatic list_entry *NdisInterlockedRemoveHeadList(list_entry *, 247123474Swpaul ndis_spin_lock *); 248144888Swpaulstatic list_entry *NdisInterlockedInsertTailList(list_entry *, 249125551Swpaul list_entry *, ndis_spin_lock *); 250144888Swpaulstatic uint8_t 251140751Swpaul NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *, 252123474Swpaul void *, void *); 253144888Swpaulstatic void NdisGetCurrentSystemTime(uint64_t *); 254144888Swpaulstatic void NdisGetSystemUpTime(uint32_t *); 255151207Swpaulstatic void NdisInitializeString(unicode_string *, char *); 256151207Swpaulstatic void NdisInitAnsiString(ansi_string *, char *); 257151207Swpaulstatic void NdisInitUnicodeString(unicode_string *, uint16_t *); 258151207Swpaulstatic void NdisFreeString(unicode_string *); 259144888Swpaulstatic ndis_status NdisMRemoveMiniport(ndis_handle *); 260144888Swpaulstatic void NdisTerminateWrapper(ndis_handle, void *); 261144888Swpaulstatic void NdisMGetDeviceProperty(ndis_handle, device_object **, 262125551Swpaul device_object **, device_object **, cm_resource_list *, 263125551Swpaul cm_resource_list *); 264144888Swpaulstatic void NdisGetFirstBufferFromPacket(ndis_packet *, 265140751Swpaul ndis_buffer **, void **, uint32_t *, uint32_t *); 266144888Swpaulstatic void NdisGetFirstBufferFromPacketSafe(ndis_packet *, 267140751Swpaul ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t); 268132973Swpaulstatic int ndis_find_sym(linker_file_t, char *, char *, caddr_t *); 269144888Swpaulstatic void NdisOpenFile(ndis_status *, ndis_handle *, uint32_t *, 270151207Swpaul unicode_string *, ndis_physaddr); 271144888Swpaulstatic void NdisMapFile(ndis_status *, void **, ndis_handle); 272144888Swpaulstatic void NdisUnmapFile(ndis_handle); 273144888Swpaulstatic void NdisCloseFile(ndis_handle); 274144888Swpaulstatic uint8_t NdisSystemProcessorCount(void); 275144888Swpaulstatic void NdisMIndicateStatusComplete(ndis_handle); 276144888Swpaulstatic void NdisMIndicateStatus(ndis_handle, ndis_status, 277124116Swpaul void *, uint32_t); 278151207Swpaulstatic void ndis_intr(void *); 279151207Swpaulstatic void ndis_intrhand(kdpc *, ndis_miniport_interrupt *, void *, void *); 280144402Swpaulstatic funcptr ndis_findwrap(funcptr); 281144888Swpaulstatic void NdisCopyFromPacketToPacket(ndis_packet *, 282140751Swpaul uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *); 283144888Swpaulstatic void NdisCopyFromPacketToPacketSafe(ndis_packet *, 284140751Swpaul uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t); 285144888Swpaulstatic ndis_status NdisMRegisterDevice(ndis_handle, 286151207Swpaul unicode_string *, unicode_string *, driver_dispatch **, 287125551Swpaul void **, ndis_handle *); 288144888Swpaulstatic ndis_status NdisMDeregisterDevice(ndis_handle); 289144888Swpaulstatic ndis_status 290151207Swpaul NdisMQueryAdapterInstanceName(unicode_string *, ndis_handle); 291144888Swpaulstatic void NdisMRegisterUnloadHandler(ndis_handle, void *); 292144888Swpaulstatic void dummy(void); 293123474Swpaul 294124116Swpaul/* 295124116Swpaul * Some really old drivers do not properly check the return value 296124116Swpaul * from NdisAllocatePacket() and NdisAllocateBuffer() and will 297124116Swpaul * sometimes allocate few more buffers/packets that they originally 298124116Swpaul * requested when they created the pool. To prevent this from being 299124116Swpaul * a problem, we allocate a few extra buffers/packets beyond what 300124116Swpaul * the driver asks for. This #define controls how many. 301124116Swpaul */ 302124116Swpaul#define NDIS_POOL_EXTRA 16 303123474Swpaul 304123474Swpaulint 305123474Swpaulndis_libinit() 306123474Swpaul{ 307141963Swpaul image_patch_table *patch; 308141963Swpaul 309124272Swpaul strcpy(ndis_filepath, "/compat/ndis"); 310141963Swpaul 311141963Swpaul patch = ndis_functbl; 312141963Swpaul while (patch->ipt_func != NULL) { 313141963Swpaul windrv_wrap((funcptr)patch->ipt_func, 314144888Swpaul (funcptr *)&patch->ipt_wrap, 315144888Swpaul patch->ipt_argcnt, patch->ipt_ftype); 316141963Swpaul patch++; 317141963Swpaul } 318141963Swpaul 319123474Swpaul return(0); 320123474Swpaul} 321123474Swpaul 322123474Swpaulint 323123474Swpaulndis_libfini() 324123474Swpaul{ 325141963Swpaul image_patch_table *patch; 326141963Swpaul 327141963Swpaul patch = ndis_functbl; 328141963Swpaul while (patch->ipt_func != NULL) { 329141963Swpaul windrv_unwrap(patch->ipt_wrap); 330141963Swpaul patch++; 331141963Swpaul } 332141963Swpaul 333123474Swpaul return(0); 334123474Swpaul} 335123474Swpaul 336144402Swpaulstatic funcptr 337144402Swpaulndis_findwrap(func) 338144402Swpaul funcptr func; 339144402Swpaul{ 340144402Swpaul image_patch_table *patch; 341144402Swpaul 342144428Swpaul patch = ndis_functbl; 343144402Swpaul while (patch->ipt_func != NULL) { 344144402Swpaul if ((funcptr)patch->ipt_func == func) 345144402Swpaul return((funcptr)patch->ipt_wrap); 346144402Swpaul patch++; 347144402Swpaul } 348144402Swpaul 349144402Swpaul return(NULL); 350144402Swpaul} 351144402Swpaul 352123474Swpaul/* 353141524Swpaul * This routine does the messy Windows Driver Model device attachment 354141524Swpaul * stuff on behalf of NDIS drivers. We register our own AddDevice 355141524Swpaul * routine here 356141524Swpaul */ 357144888Swpaulstatic void 358141524SwpaulNdisInitializeWrapper(wrapper, drv, path, unused) 359125551Swpaul ndis_handle *wrapper; 360141524Swpaul driver_object *drv; 361123474Swpaul void *path; 362123474Swpaul void *unused; 363123474Swpaul{ 364141524Swpaul /* 365141524Swpaul * As of yet, I haven't come up with a compelling 366141524Swpaul * reason to define a private NDIS wrapper structure, 367141524Swpaul * so we use a pointer to the driver object as the 368141524Swpaul * wrapper handle. The driver object has the miniport 369141524Swpaul * characteristics struct for this driver hung off it 370141524Swpaul * via IoAllocateDriverObjectExtension(), and that's 371141524Swpaul * really all the private data we need. 372141524Swpaul */ 373123474Swpaul 374141524Swpaul *wrapper = drv; 375123474Swpaul 376141524Swpaul /* 377141524Swpaul * If this was really Windows, we'd be registering dispatch 378141524Swpaul * routines for the NDIS miniport module here, but we're 379141524Swpaul * not Windows so all we really need to do is set up an 380141524Swpaul * AddDevice function that'll be invoked when a new device 381141524Swpaul * instance appears. 382141524Swpaul */ 383141524Swpaul 384141524Swpaul drv->dro_driverext->dre_adddevicefunc = NdisAddDevice; 385141524Swpaul 386123474Swpaul return; 387123474Swpaul} 388123474Swpaul 389144888Swpaulstatic void 390140751SwpaulNdisTerminateWrapper(handle, syspec) 391123526Swpaul ndis_handle handle; 392123526Swpaul void *syspec; 393123526Swpaul{ 394141524Swpaul /* Nothing to see here, move along. */ 395123526Swpaul return; 396123526Swpaul} 397123526Swpaul 398144888Swpaulstatic ndis_status 399140751SwpaulNdisMRegisterMiniport(handle, characteristics, len) 400123474Swpaul ndis_handle handle; 401123474Swpaul ndis_miniport_characteristics *characteristics; 402123474Swpaul int len; 403123474Swpaul{ 404141524Swpaul ndis_miniport_characteristics *ch = NULL; 405141524Swpaul driver_object *drv; 406123474Swpaul 407141524Swpaul drv = (driver_object *)handle; 408141524Swpaul 409141524Swpaul /* 410141524Swpaul * We need to save the NDIS miniport characteristics 411141524Swpaul * somewhere. This data is per-driver, not per-device 412141524Swpaul * (all devices handled by the same driver have the 413141524Swpaul * same characteristics) so we hook it onto the driver 414141524Swpaul * object using IoAllocateDriverObjectExtension(). 415141524Swpaul * The extra extension info is automagically deleted when 416141524Swpaul * the driver is unloaded (see windrv_unload()). 417141524Swpaul */ 418141524Swpaul 419141524Swpaul if (IoAllocateDriverObjectExtension(drv, (void *)1, 420141524Swpaul sizeof(ndis_miniport_characteristics), (void **)&ch) != 421151207Swpaul STATUS_SUCCESS) { 422141524Swpaul return(NDIS_STATUS_RESOURCES); 423151207Swpaul } 424141524Swpaul 425141524Swpaul bzero((char *)ch, sizeof(ndis_miniport_characteristics)); 426141524Swpaul 427141524Swpaul bcopy((char *)characteristics, (char *)ch, len); 428141524Swpaul 429141524Swpaul if (ch->nmc_version_major < 5 || ch->nmc_version_minor < 1) { 430141524Swpaul ch->nmc_shutdown_handler = NULL; 431141524Swpaul ch->nmc_canceltxpkts_handler = NULL; 432141524Swpaul ch->nmc_pnpevent_handler = NULL; 433125551Swpaul } 434125551Swpaul 435123474Swpaul return(NDIS_STATUS_SUCCESS); 436123474Swpaul} 437123474Swpaul 438144888Swpaulstatic ndis_status 439140751SwpaulNdisAllocateMemoryWithTag(vaddr, len, tag) 440123474Swpaul void **vaddr; 441123474Swpaul uint32_t len; 442123474Swpaul uint32_t tag; 443123474Swpaul{ 444123474Swpaul void *mem; 445123474Swpaul 446141524Swpaul mem = ExAllocatePoolWithTag(NonPagedPool, len, tag); 447151207Swpaul if (mem == NULL) { 448123474Swpaul return(NDIS_STATUS_RESOURCES); 449151207Swpaul } 450123474Swpaul *vaddr = mem; 451123474Swpaul 452123474Swpaul return(NDIS_STATUS_SUCCESS); 453123474Swpaul} 454123474Swpaul 455144888Swpaulstatic ndis_status 456140751SwpaulNdisAllocateMemory(vaddr, len, flags, highaddr) 457123474Swpaul void **vaddr; 458123474Swpaul uint32_t len; 459123474Swpaul uint32_t flags; 460123474Swpaul ndis_physaddr highaddr; 461123474Swpaul{ 462123474Swpaul void *mem; 463123474Swpaul 464141524Swpaul mem = ExAllocatePoolWithTag(NonPagedPool, len, 0); 465123474Swpaul if (mem == NULL) 466123474Swpaul return(NDIS_STATUS_RESOURCES); 467123474Swpaul *vaddr = mem; 468123474Swpaul 469123474Swpaul return(NDIS_STATUS_SUCCESS); 470123474Swpaul} 471123474Swpaul 472144888Swpaulstatic void 473140751SwpaulNdisFreeMemory(vaddr, len, flags) 474123474Swpaul void *vaddr; 475123474Swpaul uint32_t len; 476123474Swpaul uint32_t flags; 477123474Swpaul{ 478123474Swpaul if (len == 0) 479123474Swpaul return; 480125551Swpaul 481141524Swpaul ExFreePool(vaddr); 482141524Swpaul 483123474Swpaul return; 484123474Swpaul} 485123474Swpaul 486144888Swpaulstatic ndis_status 487140751SwpaulNdisMSetAttributesEx(adapter_handle, adapter_ctx, hangsecs, 488123474Swpaul flags, iftype) 489123474Swpaul ndis_handle adapter_handle; 490123474Swpaul ndis_handle adapter_ctx; 491123474Swpaul uint32_t hangsecs; 492123474Swpaul uint32_t flags; 493123474Swpaul ndis_interface_type iftype; 494123474Swpaul{ 495123474Swpaul ndis_miniport_block *block; 496123474Swpaul 497123474Swpaul /* 498123474Swpaul * Save the adapter context, we need it for calling 499123474Swpaul * the driver's internal functions. 500123474Swpaul */ 501123474Swpaul block = (ndis_miniport_block *)adapter_handle; 502123474Swpaul block->nmb_miniportadapterctx = adapter_ctx; 503123474Swpaul block->nmb_checkforhangsecs = hangsecs; 504126833Swpaul block->nmb_flags = flags; 505123474Swpaul 506123474Swpaul return(NDIS_STATUS_SUCCESS); 507123474Swpaul} 508123474Swpaul 509144888Swpaulstatic void 510140751SwpaulNdisOpenConfiguration(status, cfg, wrapctx) 511123474Swpaul ndis_status *status; 512123474Swpaul ndis_handle *cfg; 513123474Swpaul ndis_handle wrapctx; 514123474Swpaul{ 515123474Swpaul *cfg = wrapctx; 516123474Swpaul *status = NDIS_STATUS_SUCCESS; 517141524Swpaul 518123474Swpaul return; 519123474Swpaul} 520123474Swpaul 521144888Swpaulstatic void 522140751SwpaulNdisOpenConfigurationKeyByName(status, cfg, subkey, subhandle) 523123526Swpaul ndis_status *status; 524123526Swpaul ndis_handle cfg; 525151207Swpaul unicode_string *subkey; 526123526Swpaul ndis_handle *subhandle; 527123526Swpaul{ 528123526Swpaul *subhandle = cfg; 529123526Swpaul *status = NDIS_STATUS_SUCCESS; 530145895Swpaul 531123526Swpaul return; 532123526Swpaul} 533123526Swpaul 534144888Swpaulstatic void 535140751SwpaulNdisOpenConfigurationKeyByIndex(status, cfg, idx, subkey, subhandle) 536123526Swpaul ndis_status *status; 537123526Swpaul ndis_handle cfg; 538123526Swpaul uint32_t idx; 539151207Swpaul unicode_string *subkey; 540123526Swpaul ndis_handle *subhandle; 541123526Swpaul{ 542123526Swpaul *status = NDIS_STATUS_FAILURE; 543145895Swpaul 544123526Swpaul return; 545123526Swpaul} 546123526Swpaul 547123474Swpaulstatic ndis_status 548123474Swpaulndis_encode_parm(block, oid, type, parm) 549123474Swpaul ndis_miniport_block *block; 550123474Swpaul struct sysctl_oid *oid; 551123474Swpaul ndis_parm_type type; 552123474Swpaul ndis_config_parm **parm; 553123474Swpaul{ 554151207Swpaul ndis_config_parm *p; 555151207Swpaul ndis_parmlist_entry *np; 556151207Swpaul unicode_string *us; 557151207Swpaul ansi_string as; 558127248Swpaul int base = 0; 559151207Swpaul uint32_t val; 560151207Swpaul char tmp[32]; 561123474Swpaul 562151207Swpaul np = ExAllocatePoolWithTag(NonPagedPool, 563151207Swpaul sizeof(ndis_parmlist_entry), 0); 564151207Swpaul if (np == NULL) 565151207Swpaul return(NDIS_STATUS_RESOURCES); 566151207Swpaul InsertHeadList((&block->nmb_parmlist), (&np->np_list)); 567151207Swpaul *parm = p = &np->np_parm; 568123474Swpaul 569123474Swpaul switch(type) { 570123474Swpaul case ndis_parm_string: 571151207Swpaul /* See if this might be a number. */ 572151207Swpaul val = strtoul((char *)oid->oid_arg1, NULL, 10); 573151207Swpaul us = &p->ncp_parmdata.ncp_stringdata; 574151207Swpaul p->ncp_type = ndis_parm_string; 575151207Swpaul if (val) { 576151207Swpaul snprintf(tmp, 32, "%x", val); 577151207Swpaul RtlInitAnsiString(&as, tmp); 578151207Swpaul } else { 579151207Swpaul RtlInitAnsiString(&as, (char *)oid->oid_arg1); 580151207Swpaul } 581151207Swpaul 582151207Swpaul if (RtlAnsiStringToUnicodeString(us, &as, TRUE)) { 583151207Swpaul ExFreePool(np); 584151207Swpaul return(NDIS_STATUS_RESOURCES); 585151207Swpaul } 586123474Swpaul break; 587123474Swpaul case ndis_parm_int: 588127248Swpaul if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) 589127248Swpaul base = 16; 590127248Swpaul else 591127248Swpaul base = 10; 592151207Swpaul p->ncp_type = ndis_parm_int; 593151207Swpaul p->ncp_parmdata.ncp_intdata = 594127248Swpaul strtol((char *)oid->oid_arg1, NULL, base); 595123474Swpaul break; 596123474Swpaul case ndis_parm_hexint: 597151207Swpaul#ifdef notdef 598127248Swpaul if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) 599127248Swpaul base = 16; 600127248Swpaul else 601127248Swpaul base = 10; 602151207Swpaul#endif 603151207Swpaul base = 16; 604151207Swpaul p->ncp_type = ndis_parm_hexint; 605151207Swpaul p->ncp_parmdata.ncp_intdata = 606127248Swpaul strtoul((char *)oid->oid_arg1, NULL, base); 607123474Swpaul break; 608123474Swpaul default: 609123474Swpaul return(NDIS_STATUS_FAILURE); 610123474Swpaul break; 611123474Swpaul } 612123474Swpaul 613123474Swpaul return(NDIS_STATUS_SUCCESS); 614123474Swpaul} 615123474Swpaul 616131953Swpaulint 617131953Swpaulndis_strcasecmp(s1, s2) 618129834Swpaul const char *s1; 619129834Swpaul const char *s2; 620129834Swpaul{ 621130052Swpaul char a, b; 622129834Swpaul 623130052Swpaul /* 624130052Swpaul * In the kernel, toupper() is a macro. Have to be careful 625130052Swpaul * not to use pointer arithmetic when passing it arguments. 626130052Swpaul */ 627129834Swpaul 628130052Swpaul while(1) { 629130052Swpaul a = *s1; 630130052Swpaul b = *s2++; 631130052Swpaul if (toupper(a) != toupper(b)) 632130052Swpaul break; 633132973Swpaul if (*s1++ == '\0') 634130052Swpaul return(0); 635130052Swpaul } 636130052Swpaul 637130052Swpaul return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1)); 638129834Swpaul} 639129834Swpaul 640132973Swpaulint 641132973Swpaulndis_strncasecmp(s1, s2, n) 642132973Swpaul const char *s1; 643132973Swpaul const char *s2; 644132973Swpaul size_t n; 645132973Swpaul{ 646132973Swpaul char a, b; 647132973Swpaul 648132973Swpaul if (n != 0) { 649132973Swpaul do { 650132973Swpaul a = *s1; 651132973Swpaul b = *s2++; 652132973Swpaul if (toupper(a) != toupper(b)) 653132973Swpaul return (*(const unsigned char *)s1 - 654132973Swpaul *(const unsigned char *)(s2 - 1)); 655132973Swpaul if (*s1++ == '\0') 656132973Swpaul break; 657132973Swpaul } while (--n != 0); 658132973Swpaul } 659132973Swpaul 660132973Swpaul return(0); 661132973Swpaul} 662132973Swpaul 663144888Swpaulstatic void 664140751SwpaulNdisReadConfiguration(status, parm, cfg, key, type) 665123474Swpaul ndis_status *status; 666123474Swpaul ndis_config_parm **parm; 667123474Swpaul ndis_handle cfg; 668151207Swpaul unicode_string *key; 669123474Swpaul ndis_parm_type type; 670123474Swpaul{ 671123474Swpaul char *keystr = NULL; 672123474Swpaul ndis_miniport_block *block; 673123474Swpaul struct ndis_softc *sc; 674123474Swpaul struct sysctl_oid *oidp; 675123474Swpaul struct sysctl_ctx_entry *e; 676151207Swpaul ansi_string as; 677123474Swpaul 678123474Swpaul block = (ndis_miniport_block *)cfg; 679141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 680123474Swpaul 681141524Swpaul if (key->us_len == 0 || key->us_buf == NULL) { 682124100Swpaul *status = NDIS_STATUS_FAILURE; 683124100Swpaul return; 684124100Swpaul } 685124100Swpaul 686151207Swpaul if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { 687151207Swpaul *status = NDIS_STATUS_RESOURCES; 688151207Swpaul return; 689151207Swpaul } 690123474Swpaul 691151207Swpaul keystr = as.as_buf; 692151207Swpaul 693123474Swpaul /* 694123474Swpaul * See if registry key is already in a list of known keys 695123474Swpaul * included with the driver. 696123474Swpaul */ 697130097Sdes#if __FreeBSD_version < 502113 698123474Swpaul TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 699130097Sdes#else 700130097Sdes TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { 701130097Sdes#endif 702123474Swpaul oidp = e->entry; 703131953Swpaul if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) { 704123488Swpaul if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { 705151207Swpaul RtlFreeAnsiString(&as); 706123488Swpaul *status = NDIS_STATUS_FAILURE; 707123488Swpaul return; 708123488Swpaul } 709151207Swpaul 710123474Swpaul *status = ndis_encode_parm(block, oidp, type, parm); 711151207Swpaul RtlFreeAnsiString(&as); 712123474Swpaul return; 713123474Swpaul } 714123474Swpaul } 715123474Swpaul 716123474Swpaul /* 717123474Swpaul * If the key didn't match, add it to the list of dynamically 718123474Swpaul * created ones. Sometimes, drivers refer to registry keys 719123474Swpaul * that aren't documented in their .INF files. These keys 720123474Swpaul * are supposed to be created by some sort of utility or 721123474Swpaul * control panel snap-in that comes with the driver software. 722123474Swpaul * Sometimes it's useful to be able to manipulate these. 723123474Swpaul * If the driver requests the key in the form of a string, 724123474Swpaul * make its default value an empty string, otherwise default 725123474Swpaul * it to "0". 726123474Swpaul */ 727123474Swpaul 728123474Swpaul if (type == ndis_parm_int || type == ndis_parm_hexint) 729123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic integer key)", 730123488Swpaul "UNSET", CTLFLAG_RW); 731123474Swpaul else 732123488Swpaul ndis_add_sysctl(sc, keystr, "(dynamic string key)", 733123488Swpaul "UNSET", CTLFLAG_RW); 734123474Swpaul 735151207Swpaul RtlFreeAnsiString(&as); 736123474Swpaul *status = NDIS_STATUS_FAILURE; 737145895Swpaul 738123474Swpaul return; 739123474Swpaul} 740123474Swpaul 741123526Swpaulstatic ndis_status 742123526Swpaulndis_decode_parm(block, parm, val) 743123526Swpaul ndis_miniport_block *block; 744123526Swpaul ndis_config_parm *parm; 745123526Swpaul char *val; 746123526Swpaul{ 747151207Swpaul unicode_string *ustr; 748151207Swpaul ansi_string as; 749123526Swpaul 750123526Swpaul switch(parm->ncp_type) { 751123526Swpaul case ndis_parm_string: 752123526Swpaul ustr = &parm->ncp_parmdata.ncp_stringdata; 753151207Swpaul if (RtlUnicodeStringToAnsiString(&as, ustr, TRUE)) 754151207Swpaul return(NDIS_STATUS_RESOURCES); 755151207Swpaul bcopy(as.as_buf, val, as.as_len); 756151207Swpaul RtlFreeAnsiString(&as); 757123526Swpaul break; 758123526Swpaul case ndis_parm_int: 759124697Swpaul sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata); 760123526Swpaul break; 761123526Swpaul case ndis_parm_hexint: 762123526Swpaul sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata); 763123526Swpaul break; 764123526Swpaul default: 765123526Swpaul return(NDIS_STATUS_FAILURE); 766123526Swpaul break; 767123526Swpaul } 768123526Swpaul return(NDIS_STATUS_SUCCESS); 769123526Swpaul} 770123526Swpaul 771144888Swpaulstatic void 772140751SwpaulNdisWriteConfiguration(status, cfg, key, parm) 773123526Swpaul ndis_status *status; 774123526Swpaul ndis_handle cfg; 775151207Swpaul unicode_string *key; 776123526Swpaul ndis_config_parm *parm; 777123526Swpaul{ 778151207Swpaul ansi_string as; 779123526Swpaul char *keystr = NULL; 780123526Swpaul ndis_miniport_block *block; 781123526Swpaul struct ndis_softc *sc; 782123526Swpaul struct sysctl_oid *oidp; 783123526Swpaul struct sysctl_ctx_entry *e; 784123526Swpaul char val[256]; 785123526Swpaul 786123526Swpaul block = (ndis_miniport_block *)cfg; 787141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 788123526Swpaul 789151207Swpaul if (RtlUnicodeStringToAnsiString(&as, key, TRUE)) { 790151207Swpaul *status = NDIS_STATUS_RESOURCES; 791151207Swpaul return; 792151207Swpaul } 793123526Swpaul 794151207Swpaul keystr = as.as_buf; 795151207Swpaul 796123526Swpaul /* Decode the parameter into a string. */ 797124697Swpaul bzero(val, sizeof(val)); 798123526Swpaul *status = ndis_decode_parm(block, parm, val); 799123526Swpaul if (*status != NDIS_STATUS_SUCCESS) { 800151207Swpaul RtlFreeAnsiString(&as); 801123526Swpaul return; 802123526Swpaul } 803123526Swpaul 804123526Swpaul /* See if the key already exists. */ 805123526Swpaul 806130097Sdes#if __FreeBSD_version < 502113 807123526Swpaul TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 808130097Sdes#else 809130097Sdes TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { 810130097Sdes#endif 811123526Swpaul oidp = e->entry; 812131953Swpaul if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) { 813123526Swpaul /* Found it, set the value. */ 814123526Swpaul strcpy((char *)oidp->oid_arg1, val); 815151207Swpaul RtlFreeAnsiString(&as); 816123526Swpaul return; 817123526Swpaul } 818123526Swpaul } 819123526Swpaul 820123526Swpaul /* Not found, add a new key with the specified value. */ 821123526Swpaul ndis_add_sysctl(sc, keystr, "(dynamically set key)", 822123526Swpaul val, CTLFLAG_RW); 823123526Swpaul 824151207Swpaul RtlFreeAnsiString(&as); 825123526Swpaul *status = NDIS_STATUS_SUCCESS; 826123526Swpaul return; 827123526Swpaul} 828123526Swpaul 829144888Swpaulstatic void 830140751SwpaulNdisCloseConfiguration(cfg) 831123474Swpaul ndis_handle cfg; 832123474Swpaul{ 833151207Swpaul list_entry *e; 834151207Swpaul ndis_parmlist_entry *pe; 835151207Swpaul ndis_miniport_block *block; 836151207Swpaul ndis_config_parm *p; 837151207Swpaul 838151207Swpaul block = (ndis_miniport_block *)cfg; 839151207Swpaul 840151207Swpaul while (!IsListEmpty(&block->nmb_parmlist)) { 841151207Swpaul e = RemoveHeadList(&block->nmb_parmlist); 842151207Swpaul pe = CONTAINING_RECORD(e, ndis_parmlist_entry, np_list); 843151207Swpaul p = &pe->np_parm; 844151207Swpaul if (p->ncp_type == ndis_parm_string) 845151207Swpaul RtlFreeUnicodeString(&p->ncp_parmdata.ncp_stringdata); 846151207Swpaul ExFreePool(e); 847151207Swpaul } 848151207Swpaul 849123474Swpaul return; 850123474Swpaul} 851123474Swpaul 852128229Swpaul/* 853128229Swpaul * Initialize a Windows spinlock. 854128229Swpaul */ 855144888Swpaulstatic void 856140751SwpaulNdisAllocateSpinLock(lock) 857123474Swpaul ndis_spin_lock *lock; 858123474Swpaul{ 859140751Swpaul KeInitializeSpinLock(&lock->nsl_spinlock); 860128229Swpaul lock->nsl_kirql = 0; 861128229Swpaul 862123474Swpaul return; 863123474Swpaul} 864123474Swpaul 865128229Swpaul/* 866128229Swpaul * Destroy a Windows spinlock. This is a no-op for now. There are two reasons 867128229Swpaul * for this. One is that it's sort of superfluous: we don't have to do anything 868128229Swpaul * special to deallocate the spinlock. The other is that there are some buggy 869128229Swpaul * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on 870128229Swpaul * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm 871128229Swpaul * talking to you.) 872128229Swpaul */ 873144888Swpaulstatic void 874140751SwpaulNdisFreeSpinLock(lock) 875123474Swpaul ndis_spin_lock *lock; 876123474Swpaul{ 877128229Swpaul#ifdef notdef 878140751Swpaul KeInitializeSpinLock(&lock->nsl_spinlock); 879128229Swpaul lock->nsl_kirql = 0; 880128229Swpaul#endif 881123474Swpaul return; 882123474Swpaul} 883123474Swpaul 884128229Swpaul/* 885128229Swpaul * Acquire a spinlock from IRQL <= DISPATCH_LEVEL. 886128229Swpaul */ 887128229Swpaul 888144888Swpaulstatic void 889140751SwpaulNdisAcquireSpinLock(lock) 890123474Swpaul ndis_spin_lock *lock; 891123474Swpaul{ 892140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 893123474Swpaul return; 894123474Swpaul} 895123474Swpaul 896128229Swpaul/* 897128229Swpaul * Release a spinlock from IRQL == DISPATCH_LEVEL. 898128229Swpaul */ 899128229Swpaul 900144888Swpaulstatic void 901140751SwpaulNdisReleaseSpinLock(lock) 902123474Swpaul ndis_spin_lock *lock; 903123474Swpaul{ 904140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 905123474Swpaul return; 906123474Swpaul} 907123474Swpaul 908128229Swpaul/* 909128229Swpaul * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL. 910128229Swpaul */ 911144888Swpaulstatic void 912140751SwpaulNdisDprAcquireSpinLock(lock) 913128229Swpaul ndis_spin_lock *lock; 914128229Swpaul{ 915144174Swpaul KeAcquireSpinLockAtDpcLevel(&lock->nsl_spinlock); 916128229Swpaul return; 917128229Swpaul} 918128229Swpaul 919128229Swpaul/* 920128229Swpaul * Release a spinlock without leaving IRQL == DISPATCH_LEVEL. 921128229Swpaul */ 922144888Swpaulstatic void 923140751SwpaulNdisDprReleaseSpinLock(lock) 924128229Swpaul ndis_spin_lock *lock; 925128229Swpaul{ 926144174Swpaul KeReleaseSpinLockFromDpcLevel(&lock->nsl_spinlock); 927128229Swpaul return; 928128229Swpaul} 929128229Swpaul 930145895Swpaulstatic void 931145895SwpaulNdisInitializeReadWriteLock(lock) 932145895Swpaul ndis_rw_lock *lock; 933145895Swpaul{ 934145895Swpaul KeInitializeSpinLock(&lock->nrl_spinlock); 935145895Swpaul bzero((char *)&lock->nrl_rsvd, sizeof(lock->nrl_rsvd)); 936145895Swpaul return; 937145895Swpaul} 938145895Swpaul 939145895Swpaulstatic void 940145895SwpaulNdisAcquireReadWriteLock(lock, writeacc, state) 941145895Swpaul ndis_rw_lock *lock; 942145895Swpaul uint8_t writeacc; 943145895Swpaul ndis_lock_state *state; 944145895Swpaul{ 945145895Swpaul if (writeacc == TRUE) { 946145895Swpaul KeAcquireSpinLock(&lock->nrl_spinlock, &state->nls_oldirql); 947145895Swpaul lock->nrl_rsvd[0]++; 948145895Swpaul } else 949145895Swpaul lock->nrl_rsvd[1]++; 950145895Swpaul 951145895Swpaul return; 952145895Swpaul} 953145895Swpaul 954145895Swpaulstatic void 955145895SwpaulNdisReleaseReadWriteLock(lock, state) 956145895Swpaul ndis_rw_lock *lock; 957145895Swpaul ndis_lock_state *state; 958145895Swpaul{ 959145895Swpaul if (lock->nrl_rsvd[0]) { 960145895Swpaul lock->nrl_rsvd[0]--; 961145895Swpaul KeReleaseSpinLock(&lock->nrl_spinlock, state->nls_oldirql); 962145895Swpaul } else 963145895Swpaul lock->nrl_rsvd[1]--; 964145895Swpaul 965145895Swpaul return; 966145895Swpaul} 967145895Swpaul 968144888Swpaulstatic uint32_t 969140751SwpaulNdisReadPciSlotInformation(adapter, slot, offset, buf, len) 970123474Swpaul ndis_handle adapter; 971123474Swpaul uint32_t slot; 972123474Swpaul uint32_t offset; 973123474Swpaul void *buf; 974123474Swpaul uint32_t len; 975123474Swpaul{ 976123474Swpaul ndis_miniport_block *block; 977123474Swpaul int i; 978123474Swpaul char *dest; 979141524Swpaul device_t dev; 980123474Swpaul 981123474Swpaul block = (ndis_miniport_block *)adapter; 982123474Swpaul dest = buf; 983141524Swpaul if (block == NULL) 984123474Swpaul return(0); 985123474Swpaul 986141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 987144174Swpaul 988144174Swpaul /* 989144174Swpaul * I have a test system consisting of a Sun w2100z 990144174Swpaul * dual 2.4Ghz Opteron machine and an Atheros 802.11a/b/g 991144174Swpaul * "Aries" miniPCI NIC. (The NIC is installed in the 992144174Swpaul * machine using a miniPCI to PCI bus adapter card.) 993144174Swpaul * When running in SMP mode, I found that 994144174Swpaul * performing a large number of consecutive calls to 995144174Swpaul * NdisReadPciSlotInformation() would result in a 996144174Swpaul * sudden system reset (or in some cases a freeze). 997144174Swpaul * My suspicion is that the multiple reads are somehow 998144174Swpaul * triggering a fatal PCI bus error that leads to a 999144174Swpaul * machine check. The 1us delay in the loop below 1000144174Swpaul * seems to prevent this problem. 1001144174Swpaul */ 1002144174Swpaul 1003144174Swpaul for (i = 0; i < len; i++) { 1004144174Swpaul DELAY(1); 1005141524Swpaul dest[i] = pci_read_config(dev, i + offset, 1); 1006144174Swpaul } 1007123474Swpaul 1008123474Swpaul return(len); 1009123474Swpaul} 1010123474Swpaul 1011144888Swpaulstatic uint32_t 1012140751SwpaulNdisWritePciSlotInformation(adapter, slot, offset, buf, len) 1013123474Swpaul ndis_handle adapter; 1014123474Swpaul uint32_t slot; 1015123474Swpaul uint32_t offset; 1016123474Swpaul void *buf; 1017123474Swpaul uint32_t len; 1018123474Swpaul{ 1019123474Swpaul ndis_miniport_block *block; 1020123474Swpaul int i; 1021123474Swpaul char *dest; 1022141524Swpaul device_t dev; 1023123474Swpaul 1024123474Swpaul block = (ndis_miniport_block *)adapter; 1025123474Swpaul dest = buf; 1026123474Swpaul 1027141524Swpaul if (block == NULL) 1028123474Swpaul return(0); 1029123474Swpaul 1030141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 1031144174Swpaul for (i = 0; i < len; i++) { 1032144174Swpaul DELAY(1); 1033141524Swpaul pci_write_config(dev, i + offset, dest[i], 1); 1034144174Swpaul } 1035123474Swpaul 1036123474Swpaul return(len); 1037123474Swpaul} 1038123474Swpaul 1039123474Swpaul/* 1040123474Swpaul * The errorlog routine uses a variable argument list, so we 1041123474Swpaul * have to declare it this way. 1042123474Swpaul */ 1043151207Swpaul 1044124228Swpaul#define ERRMSGLEN 512 1045123474Swpaulstatic void 1046140751SwpaulNdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code, 1047123474Swpaul uint32_t numerrors, ...) 1048123474Swpaul{ 1049123474Swpaul ndis_miniport_block *block; 1050123474Swpaul va_list ap; 1051124173Swpaul int i, error; 1052151207Swpaul char *str = NULL; 1053124173Swpaul uint16_t flags; 1054124228Swpaul char msgbuf[ERRMSGLEN]; 1055141524Swpaul device_t dev; 1056141963Swpaul driver_object *drv; 1057145895Swpaul struct ndis_softc *sc; 1058145895Swpaul struct ifnet *ifp; 1059151207Swpaul unicode_string us; 1060151207Swpaul ansi_string as; 1061123474Swpaul 1062123474Swpaul block = (ndis_miniport_block *)adapter; 1063141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 1064145485Swpaul drv = block->nmb_deviceobj->do_drvobj; 1065145895Swpaul sc = device_get_softc(dev); 1066147256Sbrooks ifp = sc->ifp; 1067123474Swpaul 1068141963Swpaul error = pe_get_message((vm_offset_t)drv->dro_driverstart, 1069141963Swpaul code, &str, &i, &flags); 1070145895Swpaul if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE && 1071145895Swpaul ifp->if_flags & IFF_DEBUG) { 1072151207Swpaul RtlInitUnicodeString(&us, (uint16_t *)msgbuf); 1073151207Swpaul if (RtlUnicodeStringToAnsiString(&as, &us, TRUE)) 1074151207Swpaul return; 1075151207Swpaul str = as.as_buf; 1076124173Swpaul } 1077145895Swpaul 1078141524Swpaul device_printf (dev, "NDIS ERROR: %x (%s)\n", code, 1079124165Swpaul str == NULL ? "unknown error" : str); 1080123474Swpaul 1081145895Swpaul if (ifp->if_flags & IFF_DEBUG) { 1082145895Swpaul device_printf (dev, "NDIS NUMERRORS: %x\n", numerrors); 1083145895Swpaul va_start(ap, numerrors); 1084145895Swpaul for (i = 0; i < numerrors; i++) 1085145895Swpaul device_printf (dev, "argptr: %p\n", 1086145895Swpaul va_arg(ap, void *)); 1087145895Swpaul va_end(ap); 1088145895Swpaul } 1089123474Swpaul 1090151207Swpaul if (str != NULL) 1091151207Swpaul RtlFreeAnsiString(&as); 1092151207Swpaul 1093123474Swpaul return; 1094123474Swpaul} 1095123474Swpaul 1096123474Swpaulstatic void 1097123474Swpaulndis_map_cb(arg, segs, nseg, error) 1098123474Swpaul void *arg; 1099123474Swpaul bus_dma_segment_t *segs; 1100123474Swpaul int nseg; 1101123474Swpaul int error; 1102123474Swpaul{ 1103123474Swpaul struct ndis_map_arg *ctx; 1104123474Swpaul int i; 1105123474Swpaul 1106123474Swpaul if (error) 1107123474Swpaul return; 1108123474Swpaul 1109123474Swpaul ctx = arg; 1110123474Swpaul 1111123474Swpaul for (i = 0; i < nseg; i++) { 1112123474Swpaul ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr; 1113123474Swpaul ctx->nma_fraglist[i].npu_len = segs[i].ds_len; 1114123474Swpaul } 1115123474Swpaul 1116123474Swpaul ctx->nma_cnt = nseg; 1117123474Swpaul 1118123474Swpaul return; 1119123474Swpaul} 1120123474Swpaul 1121144888Swpaulstatic void 1122140751SwpaulNdisMStartBufferPhysicalMapping(adapter, buf, mapreg, writedev, addrarray, arraysize) 1123123474Swpaul ndis_handle adapter; 1124123474Swpaul ndis_buffer *buf; 1125123474Swpaul uint32_t mapreg; 1126123474Swpaul uint8_t writedev; 1127123474Swpaul ndis_paddr_unit *addrarray; 1128123474Swpaul uint32_t *arraysize; 1129123474Swpaul{ 1130123474Swpaul ndis_miniport_block *block; 1131123474Swpaul struct ndis_softc *sc; 1132123474Swpaul struct ndis_map_arg nma; 1133123474Swpaul bus_dmamap_t map; 1134123474Swpaul int error; 1135123474Swpaul 1136123474Swpaul if (adapter == NULL) 1137123474Swpaul return; 1138123474Swpaul 1139123474Swpaul block = (ndis_miniport_block *)adapter; 1140141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1141123474Swpaul 1142123474Swpaul if (mapreg > sc->ndis_mmapcnt) 1143123474Swpaul return; 1144123474Swpaul 1145123474Swpaul map = sc->ndis_mmaps[mapreg]; 1146123474Swpaul nma.nma_fraglist = addrarray; 1147123474Swpaul 1148123474Swpaul error = bus_dmamap_load(sc->ndis_mtag, map, 1149140751Swpaul MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf), ndis_map_cb, 1150123474Swpaul (void *)&nma, BUS_DMA_NOWAIT); 1151123474Swpaul 1152123474Swpaul if (error) 1153123474Swpaul return; 1154123474Swpaul 1155123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 1156123474Swpaul writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); 1157123474Swpaul 1158123474Swpaul *arraysize = nma.nma_cnt; 1159123474Swpaul 1160123474Swpaul return; 1161123474Swpaul} 1162123474Swpaul 1163144888Swpaulstatic void 1164140751SwpaulNdisMCompleteBufferPhysicalMapping(adapter, buf, mapreg) 1165123474Swpaul ndis_handle adapter; 1166123474Swpaul ndis_buffer *buf; 1167123474Swpaul uint32_t mapreg; 1168123474Swpaul{ 1169123474Swpaul ndis_miniport_block *block; 1170123474Swpaul struct ndis_softc *sc; 1171123474Swpaul bus_dmamap_t map; 1172123474Swpaul 1173123474Swpaul if (adapter == NULL) 1174123474Swpaul return; 1175123474Swpaul 1176123474Swpaul block = (ndis_miniport_block *)adapter; 1177141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1178123474Swpaul 1179123474Swpaul if (mapreg > sc->ndis_mmapcnt) 1180123474Swpaul return; 1181123474Swpaul 1182123474Swpaul map = sc->ndis_mmaps[mapreg]; 1183123474Swpaul 1184123474Swpaul bus_dmamap_sync(sc->ndis_mtag, map, 1185123474Swpaul BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 1186123474Swpaul 1187123474Swpaul bus_dmamap_unload(sc->ndis_mtag, map); 1188123474Swpaul 1189123474Swpaul return; 1190123474Swpaul} 1191123474Swpaul 1192125057Swpaul/* 1193144174Swpaul * This is an older (?) timer init routine which doesn't 1194144174Swpaul * accept a miniport context handle. Serialized miniports should 1195144174Swpaul * never call this function. 1196125057Swpaul */ 1197125057Swpaul 1198144888Swpaulstatic void 1199140751SwpaulNdisInitializeTimer(timer, func, ctx) 1200125057Swpaul ndis_timer *timer; 1201125057Swpaul ndis_timer_function func; 1202125057Swpaul void *ctx; 1203125057Swpaul{ 1204140751Swpaul KeInitializeTimer(&timer->nt_ktimer); 1205140751Swpaul KeInitializeDpc(&timer->nt_kdpc, func, ctx); 1206145895Swpaul KeSetImportanceDpc(&timer->nt_kdpc, KDPC_IMPORTANCE_LOW); 1207125057Swpaul 1208125057Swpaul return; 1209125057Swpaul} 1210125057Swpaul 1211144888Swpaulstatic void 1212144174Swpaulndis_timercall(dpc, timer, sysarg1, sysarg2) 1213144174Swpaul kdpc *dpc; 1214144174Swpaul ndis_miniport_timer *timer; 1215144174Swpaul void *sysarg1; 1216144174Swpaul void *sysarg2; 1217144174Swpaul{ 1218144174Swpaul /* 1219144174Swpaul * Since we're called as a DPC, we should be running 1220144174Swpaul * at DISPATCH_LEVEL here. This means to acquire the 1221144174Swpaul * spinlock, we can use KeAcquireSpinLockAtDpcLevel() 1222144174Swpaul * rather than KeAcquireSpinLock(). 1223144174Swpaul */ 1224144174Swpaul if (NDIS_SERIALIZED(timer->nmt_block)) 1225144174Swpaul KeAcquireSpinLockAtDpcLevel(&timer->nmt_block->nmb_lock); 1226144174Swpaul 1227144174Swpaul MSCALL4(timer->nmt_timerfunc, dpc, timer->nmt_timerctx, 1228144174Swpaul sysarg1, sysarg2); 1229144174Swpaul 1230144174Swpaul if (NDIS_SERIALIZED(timer->nmt_block)) 1231144174Swpaul KeReleaseSpinLockFromDpcLevel(&timer->nmt_block->nmb_lock); 1232144174Swpaul 1233144174Swpaul return; 1234144174Swpaul} 1235144174Swpaul 1236144174Swpaul/* 1237144174Swpaul * For a long time I wondered why there were two NDIS timer initialization 1238144174Swpaul * routines, and why this one needed an NDIS_MINIPORT_TIMER and the 1239144174Swpaul * MiniportAdapterHandle. The NDIS_MINIPORT_TIMER has its own callout 1240144174Swpaul * function and context pointers separate from those in the DPC, which 1241144174Swpaul * allows for another level of indirection: when the timer fires, we 1242144174Swpaul * can have our own timer function invoked, and from there we can call 1243144174Swpaul * the driver's function. But why go to all that trouble? Then it hit 1244144174Swpaul * me: for serialized miniports, the timer callouts are not re-entrant. 1245144174Swpaul * By trapping the callouts and having access to the MiniportAdapterHandle, 1246144174Swpaul * we can protect the driver callouts by acquiring the NDIS serialization 1247144174Swpaul * lock. This is essential for allowing serialized miniports to work 1248144174Swpaul * correctly on SMP systems. On UP hosts, setting IRQL to DISPATCH_LEVEL 1249144174Swpaul * is enough to prevent other threads from pre-empting you, but with 1250144174Swpaul * SMP, you must acquire a lock as well, otherwise the other CPU is 1251144174Swpaul * free to clobber you. 1252144174Swpaul */ 1253144888Swpaulstatic void 1254140751SwpaulNdisMInitializeTimer(timer, handle, func, ctx) 1255123474Swpaul ndis_miniport_timer *timer; 1256127248Swpaul ndis_handle handle; 1257123474Swpaul ndis_timer_function func; 1258123474Swpaul void *ctx; 1259123474Swpaul{ 1260145895Swpaul uint8_t irql; 1261145895Swpaul 1262144174Swpaul /* Save the driver's funcptr and context */ 1263123474Swpaul 1264127248Swpaul timer->nmt_timerfunc = func; 1265127248Swpaul timer->nmt_timerctx = ctx; 1266127248Swpaul timer->nmt_block = handle; 1267123821Swpaul 1268144402Swpaul /* 1269144402Swpaul * Set up the timer so it will call our intermediate DPC. 1270144402Swpaul * Be sure to use the wrapped entry point, since 1271144402Swpaul * ntoskrnl_run_dpc() expects to invoke a function with 1272144402Swpaul * Microsoft calling conventions. 1273144402Swpaul */ 1274140751Swpaul KeInitializeTimer(&timer->nmt_ktimer); 1275144402Swpaul KeInitializeDpc(&timer->nmt_kdpc, 1276144402Swpaul ndis_findwrap((funcptr)ndis_timercall), timer); 1277145895Swpaul timer->nmt_ktimer.k_dpc = &timer->nmt_kdpc; 1278123474Swpaul 1279145895Swpaul KeAcquireSpinLock(&timer->nmt_block->nmb_lock, &irql); 1280145895Swpaul 1281145895Swpaul timer->nmt_nexttimer = timer->nmt_block->nmb_timerlist; 1282145895Swpaul timer->nmt_block->nmb_timerlist = timer; 1283145895Swpaul 1284145895Swpaul KeReleaseSpinLock(&timer->nmt_block->nmb_lock, irql); 1285145895Swpaul 1286123474Swpaul return; 1287123474Swpaul} 1288123474Swpaul 1289123474Swpaul/* 1290127248Swpaul * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(), 1291127248Swpaul * but the former is just a macro wrapper around the latter. 1292123474Swpaul */ 1293144888Swpaulstatic void 1294140751SwpaulNdisSetTimer(timer, msecs) 1295127248Swpaul ndis_timer *timer; 1296123474Swpaul uint32_t msecs; 1297123474Swpaul{ 1298127248Swpaul /* 1299127248Swpaul * KeSetTimer() wants the period in 1300127248Swpaul * hundred nanosecond intervals. 1301127248Swpaul */ 1302140751Swpaul KeSetTimer(&timer->nt_ktimer, 1303127248Swpaul ((int64_t)msecs * -10000), &timer->nt_kdpc); 1304123474Swpaul 1305123474Swpaul return; 1306123474Swpaul} 1307123474Swpaul 1308144888Swpaulstatic void 1309140751SwpaulNdisMSetPeriodicTimer(timer, msecs) 1310123474Swpaul ndis_miniport_timer *timer; 1311123474Swpaul uint32_t msecs; 1312123474Swpaul{ 1313140751Swpaul KeSetTimerEx(&timer->nmt_ktimer, 1314127248Swpaul ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc); 1315123474Swpaul 1316123474Swpaul return; 1317123474Swpaul} 1318123474Swpaul 1319127248Swpaul/* 1320127248Swpaul * Technically, this is really NdisCancelTimer(), but we also 1321127248Swpaul * (ab)use it for NdisMCancelTimer(), since in our implementation 1322127248Swpaul * we don't need the extra info in the ndis_miniport_timer 1323144174Swpaul * structure just to cancel a timer. 1324127248Swpaul */ 1325127248Swpaul 1326144888Swpaulstatic void 1327140751SwpaulNdisMCancelTimer(timer, cancelled) 1328127248Swpaul ndis_timer *timer; 1329123474Swpaul uint8_t *cancelled; 1330123474Swpaul{ 1331140751Swpaul *cancelled = KeCancelTimer(&timer->nt_ktimer); 1332123474Swpaul return; 1333123474Swpaul} 1334123474Swpaul 1335144888Swpaulstatic void 1336140751SwpaulNdisMQueryAdapterResources(status, adapter, list, buflen) 1337123474Swpaul ndis_status *status; 1338123474Swpaul ndis_handle adapter; 1339123474Swpaul ndis_resource_list *list; 1340123474Swpaul uint32_t *buflen; 1341123474Swpaul{ 1342123474Swpaul ndis_miniport_block *block; 1343123474Swpaul struct ndis_softc *sc; 1344124094Swpaul int rsclen; 1345123474Swpaul 1346123474Swpaul block = (ndis_miniport_block *)adapter; 1347141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1348124094Swpaul 1349124094Swpaul rsclen = sizeof(ndis_resource_list) + 1350123474Swpaul (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); 1351124094Swpaul if (*buflen < rsclen) { 1352124094Swpaul *buflen = rsclen; 1353124094Swpaul *status = NDIS_STATUS_INVALID_LENGTH; 1354124094Swpaul return; 1355124094Swpaul } 1356123474Swpaul 1357127887Swpaul bcopy((char *)block->nmb_rlist, (char *)list, rsclen); 1358123474Swpaul *status = NDIS_STATUS_SUCCESS; 1359141963Swpaul 1360123474Swpaul return; 1361123474Swpaul} 1362123474Swpaul 1363144888Swpaulstatic ndis_status 1364140751SwpaulNdisMRegisterIoPortRange(offset, adapter, port, numports) 1365123474Swpaul void **offset; 1366123474Swpaul ndis_handle adapter; 1367123474Swpaul uint32_t port; 1368123474Swpaul uint32_t numports; 1369123474Swpaul{ 1370123474Swpaul struct ndis_miniport_block *block; 1371123474Swpaul struct ndis_softc *sc; 1372123474Swpaul 1373123474Swpaul if (adapter == NULL) 1374123474Swpaul return(NDIS_STATUS_FAILURE); 1375123474Swpaul 1376123474Swpaul block = (ndis_miniport_block *)adapter; 1377141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1378123474Swpaul 1379123474Swpaul if (sc->ndis_res_io == NULL) 1380123474Swpaul return(NDIS_STATUS_FAILURE); 1381123474Swpaul 1382124454Swpaul /* Don't let the device map more ports than we have. */ 1383124454Swpaul if (rman_get_size(sc->ndis_res_io) < numports) 1384123474Swpaul return(NDIS_STATUS_INVALID_LENGTH); 1385123474Swpaul 1386123474Swpaul *offset = (void *)rman_get_start(sc->ndis_res_io); 1387123474Swpaul 1388123474Swpaul return(NDIS_STATUS_SUCCESS); 1389123474Swpaul} 1390123474Swpaul 1391144888Swpaulstatic void 1392140751SwpaulNdisMDeregisterIoPortRange(adapter, port, numports, offset) 1393123474Swpaul ndis_handle adapter; 1394123474Swpaul uint32_t port; 1395123474Swpaul uint32_t numports; 1396123474Swpaul void *offset; 1397123474Swpaul{ 1398123474Swpaul return; 1399123474Swpaul} 1400123474Swpaul 1401144888Swpaulstatic void 1402140751SwpaulNdisReadNetworkAddress(status, addr, addrlen, adapter) 1403123474Swpaul ndis_status *status; 1404123474Swpaul void **addr; 1405123474Swpaul uint32_t *addrlen; 1406123474Swpaul ndis_handle adapter; 1407123474Swpaul{ 1408123474Swpaul struct ndis_softc *sc; 1409123474Swpaul ndis_miniport_block *block; 1410123474Swpaul uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; 1411123474Swpaul 1412123474Swpaul block = (ndis_miniport_block *)adapter; 1413141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1414123474Swpaul 1415151207Swpaul#ifdef IFP2ENADDR 1416147256Sbrooks if (bcmp(IFP2ENADDR(sc->ifp), empty, ETHER_ADDR_LEN) == 0) 1417151207Swpaul#else 1418151207Swpaul if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0) 1419151207Swpaul#endif 1420123474Swpaul *status = NDIS_STATUS_FAILURE; 1421123474Swpaul else { 1422151207Swpaul#ifdef IFP2ENADDR 1423147256Sbrooks *addr = IFP2ENADDR(sc->ifp); 1424151207Swpaul#else 1425151207Swpaul *addr = sc->arpcom.ac_enaddr; 1426151207Swpaul#endif 1427123474Swpaul *addrlen = ETHER_ADDR_LEN; 1428123474Swpaul *status = NDIS_STATUS_SUCCESS; 1429123474Swpaul } 1430123474Swpaul 1431123474Swpaul return; 1432123474Swpaul} 1433123474Swpaul 1434144888Swpaulstatic ndis_status 1435140751SwpaulNdisQueryMapRegisterCount(bustype, cnt) 1436123848Swpaul uint32_t bustype; 1437123848Swpaul uint32_t *cnt; 1438123848Swpaul{ 1439124097Swpaul *cnt = 8192; 1440123848Swpaul return(NDIS_STATUS_SUCCESS); 1441123848Swpaul} 1442123848Swpaul 1443144888Swpaulstatic ndis_status 1444140751SwpaulNdisMAllocateMapRegisters(adapter, dmachannel, dmasize, physmapneeded, maxmap) 1445123474Swpaul ndis_handle adapter; 1446123474Swpaul uint32_t dmachannel; 1447123474Swpaul uint8_t dmasize; 1448123474Swpaul uint32_t physmapneeded; 1449123474Swpaul uint32_t maxmap; 1450123474Swpaul{ 1451123474Swpaul struct ndis_softc *sc; 1452123474Swpaul ndis_miniport_block *block; 1453123474Swpaul int error, i, nseg = NDIS_MAXSEG; 1454123474Swpaul 1455123474Swpaul block = (ndis_miniport_block *)adapter; 1456141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1457123474Swpaul 1458123474Swpaul sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, 1459123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 1460123474Swpaul 1461123474Swpaul if (sc->ndis_mmaps == NULL) 1462123474Swpaul return(NDIS_STATUS_RESOURCES); 1463123474Swpaul 1464123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1465123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1466123474Swpaul NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, 1467123474Swpaul NULL, NULL, &sc->ndis_mtag); 1468123474Swpaul 1469123474Swpaul if (error) { 1470123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1471123474Swpaul return(NDIS_STATUS_RESOURCES); 1472123474Swpaul } 1473123474Swpaul 1474123474Swpaul for (i = 0; i < physmapneeded; i++) 1475123474Swpaul bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); 1476123474Swpaul 1477123474Swpaul sc->ndis_mmapcnt = physmapneeded; 1478123474Swpaul 1479123474Swpaul return(NDIS_STATUS_SUCCESS); 1480123474Swpaul} 1481123474Swpaul 1482144888Swpaulstatic void 1483140751SwpaulNdisMFreeMapRegisters(adapter) 1484123474Swpaul ndis_handle adapter; 1485123474Swpaul{ 1486123474Swpaul struct ndis_softc *sc; 1487123474Swpaul ndis_miniport_block *block; 1488123474Swpaul int i; 1489123474Swpaul 1490123474Swpaul block = (ndis_miniport_block *)adapter; 1491141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1492123474Swpaul 1493123474Swpaul for (i = 0; i < sc->ndis_mmapcnt; i++) 1494123474Swpaul bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); 1495123474Swpaul 1496123474Swpaul free(sc->ndis_mmaps, M_DEVBUF); 1497123474Swpaul 1498123474Swpaul bus_dma_tag_destroy(sc->ndis_mtag); 1499123474Swpaul 1500123474Swpaul return; 1501123474Swpaul} 1502123474Swpaul 1503123474Swpaulstatic void 1504123474Swpaulndis_mapshared_cb(arg, segs, nseg, error) 1505123474Swpaul void *arg; 1506123474Swpaul bus_dma_segment_t *segs; 1507123474Swpaul int nseg; 1508123474Swpaul int error; 1509123474Swpaul{ 1510123474Swpaul ndis_physaddr *p; 1511123474Swpaul 1512123474Swpaul if (error || nseg > 1) 1513123474Swpaul return; 1514123474Swpaul 1515123474Swpaul p = arg; 1516123474Swpaul 1517123474Swpaul p->np_quad = segs[0].ds_addr; 1518123474Swpaul 1519123474Swpaul return; 1520123474Swpaul} 1521123474Swpaul 1522123474Swpaul/* 1523123474Swpaul * This maps to bus_dmamem_alloc(). 1524123474Swpaul */ 1525145895Swpaul 1526144888Swpaulstatic void 1527140751SwpaulNdisMAllocateSharedMemory(adapter, len, cached, vaddr, paddr) 1528123474Swpaul ndis_handle adapter; 1529123474Swpaul uint32_t len; 1530123474Swpaul uint8_t cached; 1531123474Swpaul void **vaddr; 1532123474Swpaul ndis_physaddr *paddr; 1533123474Swpaul{ 1534123474Swpaul ndis_miniport_block *block; 1535123474Swpaul struct ndis_softc *sc; 1536123474Swpaul struct ndis_shmem *sh; 1537123474Swpaul int error; 1538123474Swpaul 1539123474Swpaul if (adapter == NULL) 1540123474Swpaul return; 1541123474Swpaul 1542123474Swpaul block = (ndis_miniport_block *)adapter; 1543141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1544123474Swpaul 1545123474Swpaul sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); 1546123474Swpaul if (sh == NULL) 1547123474Swpaul return; 1548123474Swpaul 1549151207Swpaul InitializeListHead(&sh->ndis_list); 1550151207Swpaul 1551131750Swpaul /* 1552131750Swpaul * When performing shared memory allocations, create a tag 1553131750Swpaul * with a lowaddr limit that restricts physical memory mappings 1554131750Swpaul * so that they all fall within the first 1GB of memory. 1555131750Swpaul * At least one device/driver combination (Linksys Instant 1556131750Swpaul * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have 1557131750Swpaul * problems with performing DMA operations with physical 1558141963Swpaul * addresses that lie above the 1GB mark. I don't know if this 1559141963Swpaul * is a hardware limitation or if the addresses are being 1560141963Swpaul * truncated within the driver, but this seems to be the only 1561141963Swpaul * way to make these cards work reliably in systems with more 1562141963Swpaul * than 1GB of physical memory. 1563131750Swpaul */ 1564131750Swpaul 1565123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, 64, 1566131750Swpaul 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL, 1567123474Swpaul NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, 1568123474Swpaul &sh->ndis_stag); 1569123474Swpaul 1570123474Swpaul if (error) { 1571123474Swpaul free(sh, M_DEVBUF); 1572123474Swpaul return; 1573123474Swpaul } 1574123474Swpaul 1575123474Swpaul error = bus_dmamem_alloc(sh->ndis_stag, vaddr, 1576123474Swpaul BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); 1577123474Swpaul 1578123474Swpaul if (error) { 1579123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1580123474Swpaul free(sh, M_DEVBUF); 1581123474Swpaul return; 1582123474Swpaul } 1583123474Swpaul 1584123474Swpaul error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, 1585123474Swpaul len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); 1586123474Swpaul 1587123474Swpaul if (error) { 1588123474Swpaul bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); 1589123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1590123474Swpaul free(sh, M_DEVBUF); 1591123474Swpaul return; 1592123474Swpaul } 1593123474Swpaul 1594145895Swpaul /* 1595145895Swpaul * Save the physical address along with the source address. 1596145895Swpaul * The AirGo MIMO driver will call NdisMFreeSharedMemory() 1597145895Swpaul * with a bogus virtual address sometimes, but with a valid 1598145895Swpaul * physical address. To keep this from causing trouble, we 1599145895Swpaul * use the physical address to as a sanity check in case 1600145895Swpaul * searching based on the virtual address fails. 1601145895Swpaul */ 1602145895Swpaul 1603151207Swpaul NDIS_LOCK(sc); 1604145895Swpaul sh->ndis_paddr.np_quad = paddr->np_quad; 1605123474Swpaul sh->ndis_saddr = *vaddr; 1606151207Swpaul InsertHeadList((&sc->ndis_shlist), (&sh->ndis_list)); 1607151207Swpaul NDIS_UNLOCK(sc); 1608123474Swpaul 1609123474Swpaul return; 1610123474Swpaul} 1611123474Swpaul 1612125413Swpaulstruct ndis_allocwork { 1613125413Swpaul uint32_t na_len; 1614125413Swpaul uint8_t na_cached; 1615125413Swpaul void *na_ctx; 1616145895Swpaul io_workitem *na_iw; 1617125413Swpaul}; 1618125413Swpaul 1619125413Swpaulstatic void 1620145895Swpaulndis_asyncmem_complete(dobj, arg) 1621145895Swpaul device_object *dobj; 1622125413Swpaul void *arg; 1623123474Swpaul{ 1624123474Swpaul ndis_miniport_block *block; 1625123474Swpaul struct ndis_softc *sc; 1626125413Swpaul struct ndis_allocwork *w; 1627123474Swpaul void *vaddr; 1628123474Swpaul ndis_physaddr paddr; 1629144888Swpaul ndis_allocdone_handler donefunc; 1630123474Swpaul 1631125413Swpaul w = arg; 1632145895Swpaul block = (ndis_miniport_block *)dobj->do_devext; 1633141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1634123474Swpaul 1635125413Swpaul vaddr = NULL; 1636125413Swpaul paddr.np_quad = 0; 1637125413Swpaul 1638141524Swpaul donefunc = sc->ndis_chars->nmc_allocate_complete_func; 1639145895Swpaul NdisMAllocateSharedMemory(block, w->na_len, 1640125413Swpaul w->na_cached, &vaddr, &paddr); 1641145895Swpaul MSCALL5(donefunc, block, vaddr, &paddr, w->na_len, w->na_ctx); 1642123474Swpaul 1643145895Swpaul IoFreeWorkItem(w->na_iw); 1644145895Swpaul free(w, M_DEVBUF); 1645123474Swpaul 1646123474Swpaul return; 1647123474Swpaul} 1648123474Swpaul 1649144888Swpaulstatic ndis_status 1650140751SwpaulNdisMAllocateSharedMemoryAsync(adapter, len, cached, ctx) 1651125413Swpaul ndis_handle adapter; 1652125413Swpaul uint32_t len; 1653125413Swpaul uint8_t cached; 1654125413Swpaul void *ctx; 1655125413Swpaul{ 1656145895Swpaul ndis_miniport_block *block; 1657125413Swpaul struct ndis_allocwork *w; 1658145895Swpaul io_workitem *iw; 1659145895Swpaul io_workitem_func ifw; 1660125413Swpaul 1661125413Swpaul if (adapter == NULL) 1662125413Swpaul return(NDIS_STATUS_FAILURE); 1663125413Swpaul 1664145895Swpaul block = adapter; 1665145895Swpaul 1666145895Swpaul iw = IoAllocateWorkItem(block->nmb_deviceobj); 1667145895Swpaul if (iw == NULL) 1668145895Swpaul return(NDIS_STATUS_FAILURE); 1669145895Swpaul 1670125413Swpaul w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT); 1671125413Swpaul 1672125413Swpaul if (w == NULL) 1673125413Swpaul return(NDIS_STATUS_FAILURE); 1674125413Swpaul 1675125413Swpaul w->na_cached = cached; 1676125413Swpaul w->na_len = len; 1677125413Swpaul w->na_ctx = ctx; 1678146273Swpaul w->na_iw = iw; 1679125413Swpaul 1680145895Swpaul ifw = (io_workitem_func)ndis_findwrap((funcptr)ndis_asyncmem_complete); 1681145895Swpaul IoQueueWorkItem(iw, ifw, WORKQUEUE_DELAYED, w); 1682125413Swpaul 1683125413Swpaul return(NDIS_STATUS_PENDING); 1684125413Swpaul} 1685125413Swpaul 1686144888Swpaulstatic void 1687140751SwpaulNdisMFreeSharedMemory(adapter, len, cached, vaddr, paddr) 1688123474Swpaul ndis_handle adapter; 1689123474Swpaul uint32_t len; 1690123474Swpaul uint8_t cached; 1691123474Swpaul void *vaddr; 1692123474Swpaul ndis_physaddr paddr; 1693123474Swpaul{ 1694123474Swpaul ndis_miniport_block *block; 1695123474Swpaul struct ndis_softc *sc; 1696151207Swpaul struct ndis_shmem *sh = NULL; 1697151207Swpaul list_entry *l; 1698123474Swpaul 1699123474Swpaul if (vaddr == NULL || adapter == NULL) 1700123474Swpaul return; 1701123474Swpaul 1702123474Swpaul block = (ndis_miniport_block *)adapter; 1703141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1704123474Swpaul 1705144254Swpaul /* Sanity check: is list empty? */ 1706144254Swpaul 1707151207Swpaul if (IsListEmpty(&sc->ndis_shlist)) 1708144254Swpaul return; 1709144254Swpaul 1710151207Swpaul NDIS_LOCK(sc); 1711151207Swpaul l = sc->ndis_shlist.nle_flink; 1712151207Swpaul while (l != &sc->ndis_shlist) { 1713151207Swpaul sh = CONTAINING_RECORD(l, struct ndis_shmem, ndis_list); 1714123474Swpaul if (sh->ndis_saddr == vaddr) 1715123474Swpaul break; 1716145895Swpaul /* 1717145895Swpaul * Check the physaddr too, just in case the driver lied 1718145895Swpaul * about the virtual address. 1719145895Swpaul */ 1720145895Swpaul if (sh->ndis_paddr.np_quad == paddr.np_quad) 1721145895Swpaul break; 1722151207Swpaul l = l->nle_flink; 1723123474Swpaul } 1724123474Swpaul 1725145895Swpaul if (sh == NULL) { 1726151207Swpaul NDIS_UNLOCK(sc); 1727145895Swpaul printf("NDIS: buggy driver tried to free " 1728145906Swpaul "invalid shared memory: vaddr: %p paddr: 0x%jx\n", 1729145935Swpaul vaddr, (uintmax_t)paddr.np_quad); 1730145895Swpaul return; 1731145895Swpaul } 1732145895Swpaul 1733151207Swpaul RemoveEntryList(&sh->ndis_list); 1734151207Swpaul 1735151207Swpaul NDIS_UNLOCK(sc); 1736151207Swpaul 1737123474Swpaul bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); 1738145895Swpaul bus_dmamem_free(sh->ndis_stag, sh->ndis_saddr, sh->ndis_smap); 1739123474Swpaul bus_dma_tag_destroy(sh->ndis_stag); 1740123474Swpaul 1741123474Swpaul free(sh, M_DEVBUF); 1742123474Swpaul 1743123474Swpaul return; 1744123474Swpaul} 1745123474Swpaul 1746144888Swpaulstatic ndis_status 1747140751SwpaulNdisMMapIoSpace(vaddr, adapter, paddr, len) 1748123474Swpaul void **vaddr; 1749123474Swpaul ndis_handle adapter; 1750123474Swpaul ndis_physaddr paddr; 1751123474Swpaul uint32_t len; 1752123474Swpaul{ 1753123474Swpaul ndis_miniport_block *block; 1754123474Swpaul struct ndis_softc *sc; 1755123474Swpaul 1756123474Swpaul if (adapter == NULL) 1757123474Swpaul return(NDIS_STATUS_FAILURE); 1758123474Swpaul 1759123474Swpaul block = (ndis_miniport_block *)adapter; 1760141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1761123474Swpaul 1762125599Swpaul if (sc->ndis_res_mem != NULL && 1763125599Swpaul paddr.np_quad == rman_get_start(sc->ndis_res_mem)) 1764125598Swpaul *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem); 1765125599Swpaul else if (sc->ndis_res_altmem != NULL && 1766125599Swpaul paddr.np_quad == rman_get_start(sc->ndis_res_altmem)) 1767125598Swpaul *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem); 1768131953Swpaul else if (sc->ndis_res_am != NULL && 1769131953Swpaul paddr.np_quad == rman_get_start(sc->ndis_res_am)) 1770131953Swpaul *vaddr = (void *)rman_get_virtual(sc->ndis_res_am); 1771125598Swpaul else 1772123474Swpaul return(NDIS_STATUS_FAILURE); 1773123474Swpaul 1774123474Swpaul return(NDIS_STATUS_SUCCESS); 1775123474Swpaul} 1776123474Swpaul 1777144888Swpaulstatic void 1778140751SwpaulNdisMUnmapIoSpace(adapter, vaddr, len) 1779123474Swpaul ndis_handle adapter; 1780123474Swpaul void *vaddr; 1781123474Swpaul uint32_t len; 1782123474Swpaul{ 1783123474Swpaul return; 1784123474Swpaul} 1785123474Swpaul 1786144888Swpaulstatic uint32_t 1787140751SwpaulNdisGetCacheFillSize(void) 1788123474Swpaul{ 1789123474Swpaul return(128); 1790123474Swpaul} 1791123474Swpaul 1792144888Swpaulstatic uint32_t 1793140751SwpaulNdisMGetDmaAlignment(handle) 1794123474Swpaul ndis_handle handle; 1795123474Swpaul{ 1796145895Swpaul return(16); 1797123474Swpaul} 1798123474Swpaul 1799123474Swpaul/* 1800123474Swpaul * NDIS has two methods for dealing with NICs that support DMA. 1801123474Swpaul * One is to just pass packets to the driver and let it call 1802123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet 1803123474Swpaul * all by itself, and the other is to let the NDIS library handle the 1804123474Swpaul * buffer mapping internally, and hand the driver an already populated 1805123474Swpaul * scatter/gather fragment list. If the driver calls 1806123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter 1807123474Swpaul * method. 1808123474Swpaul */ 1809123474Swpaul 1810144888Swpaulstatic ndis_status 1811140751SwpaulNdisMInitializeScatterGatherDma(adapter, is64, maxphysmap) 1812123474Swpaul ndis_handle adapter; 1813123474Swpaul uint8_t is64; 1814123474Swpaul uint32_t maxphysmap; 1815123474Swpaul{ 1816123474Swpaul struct ndis_softc *sc; 1817123474Swpaul ndis_miniport_block *block; 1818123474Swpaul int error; 1819123474Swpaul 1820123474Swpaul if (adapter == NULL) 1821123474Swpaul return(NDIS_STATUS_FAILURE); 1822123474Swpaul block = (ndis_miniport_block *)adapter; 1823141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 1824123474Swpaul 1825123474Swpaul /* Don't do this twice. */ 1826123474Swpaul if (sc->ndis_sc == 1) 1827123474Swpaul return(NDIS_STATUS_SUCCESS); 1828123474Swpaul 1829123474Swpaul error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1830123474Swpaul BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1831123474Swpaul MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, 1832123474Swpaul NULL, NULL, &sc->ndis_ttag); 1833123474Swpaul 1834123474Swpaul sc->ndis_sc = 1; 1835123474Swpaul 1836123474Swpaul return(NDIS_STATUS_SUCCESS); 1837123474Swpaul} 1838123474Swpaul 1839144888Swpaulvoid 1840140751SwpaulNdisAllocatePacketPool(status, pool, descnum, protrsvdlen) 1841123474Swpaul ndis_status *status; 1842123474Swpaul ndis_handle *pool; 1843123474Swpaul uint32_t descnum; 1844123474Swpaul uint32_t protrsvdlen; 1845123474Swpaul{ 1846151451Swpaul ndis_packet_pool *p; 1847151451Swpaul ndis_packet *packets; 1848123474Swpaul int i; 1849123474Swpaul 1850151451Swpaul p = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_packet_pool), 0); 1851151451Swpaul if (p == NULL) { 1852123474Swpaul *status = NDIS_STATUS_RESOURCES; 1853123474Swpaul return; 1854123474Swpaul } 1855123474Swpaul 1856151451Swpaul p->np_cnt = descnum + NDIS_POOL_EXTRA; 1857151451Swpaul p->np_protrsvd = protrsvdlen; 1858151451Swpaul p->np_len = sizeof(ndis_packet) + protrsvdlen; 1859151451Swpaul 1860151451Swpaul packets = ExAllocatePoolWithTag(NonPagedPool, p->np_cnt * 1861151451Swpaul p->np_len, 0); 1862151451Swpaul 1863151451Swpaul 1864151451Swpaul if (packets == NULL) { 1865151451Swpaul ExFreePool(p); 1866151451Swpaul *status = NDIS_STATUS_RESOURCES; 1867151451Swpaul return; 1868123474Swpaul } 1869123474Swpaul 1870151451Swpaul p->np_pktmem = packets; 1871151451Swpaul 1872151451Swpaul for (i = 0; i < p->np_cnt; i++) 1873151451Swpaul InterlockedPushEntrySList(&p->np_head, 1874151451Swpaul (struct slist_entry *)&packets[i]); 1875151451Swpaul 1876151451Swpaul#ifdef NDIS_DEBUG_PACKETS 1877151451Swpaul p->np_dead = 0; 1878151451Swpaul KeInitializeSpinLock(&p->np_lock); 1879151451Swpaul KeInitializeEvent(&p->np_event, EVENT_TYPE_NOTIFY, TRUE); 1880151451Swpaul#endif 1881151451Swpaul 1882151451Swpaul *pool = p; 1883123474Swpaul *status = NDIS_STATUS_SUCCESS; 1884123474Swpaul return; 1885123474Swpaul} 1886123474Swpaul 1887144888Swpaulvoid 1888140751SwpaulNdisAllocatePacketPoolEx(status, pool, descnum, oflowdescnum, protrsvdlen) 1889123474Swpaul ndis_status *status; 1890123474Swpaul ndis_handle *pool; 1891123474Swpaul uint32_t descnum; 1892123474Swpaul uint32_t oflowdescnum; 1893123474Swpaul uint32_t protrsvdlen; 1894123474Swpaul{ 1895140751Swpaul return(NdisAllocatePacketPool(status, pool, 1896123474Swpaul descnum + oflowdescnum, protrsvdlen)); 1897123474Swpaul} 1898123474Swpaul 1899144888Swpauluint32_t 1900140751SwpaulNdisPacketPoolUsage(pool) 1901123474Swpaul ndis_handle pool; 1902123474Swpaul{ 1903151451Swpaul ndis_packet_pool *p; 1904123474Swpaul 1905151451Swpaul p = (ndis_packet_pool *)pool; 1906151451Swpaul return(p->np_cnt - ExQueryDepthSList(&p->np_head)); 1907123474Swpaul} 1908123474Swpaul 1909144888Swpaulvoid 1910140751SwpaulNdisFreePacketPool(pool) 1911123474Swpaul ndis_handle pool; 1912123474Swpaul{ 1913151451Swpaul ndis_packet_pool *p; 1914151451Swpaul int usage; 1915151451Swpaul#ifdef NDIS_DEBUG_PACKETS 1916143086Swpaul uint8_t irql; 1917151451Swpaul#endif 1918126568Swpaul 1919151451Swpaul p = (ndis_packet_pool *)pool; 1920126568Swpaul 1921151451Swpaul#ifdef NDIS_DEBUG_PACKETS 1922151451Swpaul KeAcquireSpinLock(&p->np_lock, &irql); 1923151451Swpaul#endif 1924126568Swpaul 1925151451Swpaul usage = NdisPacketPoolUsage(pool); 1926126568Swpaul 1927151451Swpaul#ifdef NDIS_DEBUG_PACKETS 1928151451Swpaul if (usage) { 1929151451Swpaul p->np_dead = 1; 1930151451Swpaul KeResetEvent(&p->np_event); 1931151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1932151451Swpaul KeWaitForSingleObject(&p->np_event, 0, 0, FALSE, NULL); 1933151451Swpaul } else 1934151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1935151451Swpaul#endif 1936126568Swpaul 1937151451Swpaul ExFreePool(p->np_pktmem); 1938151451Swpaul ExFreePool(p); 1939126568Swpaul 1940123474Swpaul return; 1941123474Swpaul} 1942123474Swpaul 1943144888Swpaulvoid 1944140751SwpaulNdisAllocatePacket(status, packet, pool) 1945123474Swpaul ndis_status *status; 1946123474Swpaul ndis_packet **packet; 1947123474Swpaul ndis_handle pool; 1948123474Swpaul{ 1949151451Swpaul ndis_packet_pool *p; 1950151451Swpaul ndis_packet *pkt; 1951151451Swpaul#ifdef NDIS_DEBUG_PACKETS 1952143086Swpaul uint8_t irql; 1953151451Swpaul#endif 1954123474Swpaul 1955151451Swpaul p = (ndis_packet_pool *)pool; 1956123474Swpaul 1957151451Swpaul#ifdef NDIS_DEBUG_PACKETS 1958151451Swpaul KeAcquireSpinLock(&p->np_lock, &irql); 1959151451Swpaul if (p->np_dead) { 1960151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1961151451Swpaul printf("NDIS: tried to allocate packet from dead pool %p\n", 1962151451Swpaul pool); 1963151451Swpaul *status = NDIS_STATUS_RESOURCES; 1964123474Swpaul return; 1965123474Swpaul } 1966151451Swpaul#endif 1967123474Swpaul 1968151451Swpaul pkt = (ndis_packet *)InterlockedPopEntrySList(&p->np_head); 1969126568Swpaul 1970151451Swpaul#ifdef NDIS_DEBUG_PACKETS 1971151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 1972151451Swpaul#endif 1973126568Swpaul 1974123474Swpaul if (pkt == NULL) { 1975123474Swpaul *status = NDIS_STATUS_RESOURCES; 1976123474Swpaul return; 1977123474Swpaul } 1978123474Swpaul 1979123474Swpaul 1980151451Swpaul bzero((char *)pkt, sizeof(ndis_packet)); 1981151451Swpaul 1982123474Swpaul /* Save pointer to the pool. */ 1983151451Swpaul pkt->np_private.npp_pool = pool; 1984123474Swpaul 1985123474Swpaul /* Set the oob offset pointer. Lots of things expect this. */ 1986144888Swpaul pkt->np_private.npp_packetooboffset = offsetof(ndis_packet, np_oob); 1987123474Swpaul 1988124278Swpaul /* 1989124278Swpaul * We must initialize the packet flags correctly in order 1990124278Swpaul * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and 1991141963Swpaul * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work 1992141963Swpaul * correctly. 1993124278Swpaul */ 1994124278Swpaul pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS; 1995144239Swpaul pkt->np_private.npp_validcounts = FALSE; 1996124278Swpaul 1997123474Swpaul *packet = pkt; 1998123474Swpaul 1999123474Swpaul *status = NDIS_STATUS_SUCCESS; 2000141963Swpaul 2001123474Swpaul return; 2002123474Swpaul} 2003123474Swpaul 2004144888Swpaulvoid 2005140751SwpaulNdisFreePacket(packet) 2006123474Swpaul ndis_packet *packet; 2007123474Swpaul{ 2008151451Swpaul ndis_packet_pool *p; 2009151451Swpaul#ifdef NDIS_DEBUG_PACKETS 2010143086Swpaul uint8_t irql; 2011151451Swpaul#endif 2012123474Swpaul 2013151451Swpaul p = (ndis_packet_pool *)packet->np_private.npp_pool; 2014123474Swpaul 2015151451Swpaul#ifdef NDIS_DEBUG_PACKETS 2016151451Swpaul KeAcquireSpinLock(&p->np_lock, &irql); 2017151451Swpaul#endif 2018143086Swpaul 2019151451Swpaul InterlockedPushEntrySList(&p->np_head, (slist_entry *)packet); 2020151451Swpaul 2021151451Swpaul#ifdef NDIS_DEBUG_PACKETS 2022151451Swpaul if (p->np_dead) { 2023151451Swpaul if (ExQueryDepthSList(&p->np_head) == p->np_cnt) 2024151451Swpaul KeSetEvent(&p->np_event, IO_NO_INCREMENT, FALSE); 2025143086Swpaul } 2026151451Swpaul KeReleaseSpinLock(&p->np_lock, irql); 2027151451Swpaul#endif 2028123474Swpaul 2029123474Swpaul return; 2030123474Swpaul} 2031123474Swpaul 2032144888Swpaulstatic void 2033140751SwpaulNdisUnchainBufferAtFront(packet, buf) 2034123474Swpaul ndis_packet *packet; 2035123474Swpaul ndis_buffer **buf; 2036123474Swpaul{ 2037123474Swpaul ndis_packet_private *priv; 2038123474Swpaul 2039123474Swpaul if (packet == NULL || buf == NULL) 2040123474Swpaul return; 2041123474Swpaul 2042123474Swpaul priv = &packet->np_private; 2043123474Swpaul 2044123474Swpaul priv->npp_validcounts = FALSE; 2045123474Swpaul 2046123474Swpaul if (priv->npp_head == priv->npp_tail) { 2047123474Swpaul *buf = priv->npp_head; 2048123474Swpaul priv->npp_head = priv->npp_tail = NULL; 2049123474Swpaul } else { 2050123474Swpaul *buf = priv->npp_head; 2051140751Swpaul priv->npp_head = (*buf)->mdl_next; 2052123474Swpaul } 2053123474Swpaul 2054123474Swpaul return; 2055123474Swpaul} 2056123474Swpaul 2057144888Swpaulstatic void 2058140751SwpaulNdisUnchainBufferAtBack(packet, buf) 2059123721Swpaul ndis_packet *packet; 2060123721Swpaul ndis_buffer **buf; 2061123721Swpaul{ 2062123721Swpaul ndis_packet_private *priv; 2063123721Swpaul ndis_buffer *tmp; 2064123721Swpaul 2065123721Swpaul if (packet == NULL || buf == NULL) 2066123721Swpaul return; 2067123721Swpaul 2068123721Swpaul priv = &packet->np_private; 2069123721Swpaul 2070123721Swpaul priv->npp_validcounts = FALSE; 2071123721Swpaul 2072123721Swpaul if (priv->npp_head == priv->npp_tail) { 2073123721Swpaul *buf = priv->npp_head; 2074123721Swpaul priv->npp_head = priv->npp_tail = NULL; 2075123721Swpaul } else { 2076123721Swpaul *buf = priv->npp_tail; 2077123721Swpaul tmp = priv->npp_head; 2078140751Swpaul while (tmp->mdl_next != priv->npp_tail) 2079140751Swpaul tmp = tmp->mdl_next; 2080123721Swpaul priv->npp_tail = tmp; 2081140751Swpaul tmp->mdl_next = NULL; 2082123721Swpaul } 2083123721Swpaul 2084123721Swpaul return; 2085123721Swpaul} 2086123721Swpaul 2087123474Swpaul/* 2088141963Swpaul * The NDIS "buffer" is really an MDL (memory descriptor list) 2089141963Swpaul * which is used to describe a buffer in a way that allows it 2090141963Swpaul * to mapped into different contexts. We have to be careful how 2091141963Swpaul * we handle them: in some versions of Windows, the NdisFreeBuffer() 2092141963Swpaul * routine is an actual function in the NDIS API, but in others 2093141963Swpaul * it's just a macro wrapper around IoFreeMdl(). There's really 2094141963Swpaul * no way to use the 'descnum' parameter to count how many 2095141963Swpaul * "buffers" are allocated since in order to use IoFreeMdl() to 2096141963Swpaul * dispose of a buffer, we have to use IoAllocateMdl() to allocate 2097141963Swpaul * them, and IoAllocateMdl() just grabs them out of the heap. 2098123474Swpaul */ 2099123474Swpaul 2100144888Swpaulstatic void 2101140751SwpaulNdisAllocateBufferPool(status, pool, descnum) 2102123474Swpaul ndis_status *status; 2103123474Swpaul ndis_handle *pool; 2104123474Swpaul uint32_t descnum; 2105123474Swpaul{ 2106151207Swpaul 2107141963Swpaul /* 2108141963Swpaul * The only thing we can really do here is verify that descnum 2109141963Swpaul * is a reasonable value, but I really don't know what to check 2110141963Swpaul * it against. 2111141963Swpaul */ 2112123474Swpaul 2113141963Swpaul *pool = NonPagedPool; 2114123474Swpaul *status = NDIS_STATUS_SUCCESS; 2115123474Swpaul return; 2116123474Swpaul} 2117123474Swpaul 2118144888Swpaulstatic void 2119140751SwpaulNdisFreeBufferPool(pool) 2120123474Swpaul ndis_handle pool; 2121123474Swpaul{ 2122123474Swpaul return; 2123123474Swpaul} 2124123474Swpaul 2125144888Swpaulstatic void 2126140751SwpaulNdisAllocateBuffer(status, buffer, pool, vaddr, len) 2127123474Swpaul ndis_status *status; 2128123474Swpaul ndis_buffer **buffer; 2129123474Swpaul ndis_handle pool; 2130123474Swpaul void *vaddr; 2131123474Swpaul uint32_t len; 2132123474Swpaul{ 2133141963Swpaul ndis_buffer *buf; 2134123474Swpaul 2135141963Swpaul buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL); 2136123474Swpaul if (buf == NULL) { 2137123474Swpaul *status = NDIS_STATUS_RESOURCES; 2138123474Swpaul return; 2139123474Swpaul } 2140123474Swpaul 2141151207Swpaul MmBuildMdlForNonPagedPool(buf); 2142151207Swpaul 2143123474Swpaul *buffer = buf; 2144141963Swpaul *status = NDIS_STATUS_SUCCESS; 2145123474Swpaul 2146123474Swpaul return; 2147123474Swpaul} 2148123474Swpaul 2149144888Swpaulstatic void 2150140751SwpaulNdisFreeBuffer(buf) 2151123474Swpaul ndis_buffer *buf; 2152123474Swpaul{ 2153141963Swpaul IoFreeMdl(buf); 2154123474Swpaul return; 2155123474Swpaul} 2156123474Swpaul 2157124100Swpaul/* Aw c'mon. */ 2158124100Swpaul 2159144888Swpaulstatic uint32_t 2160140751SwpaulNdisBufferLength(buf) 2161124100Swpaul ndis_buffer *buf; 2162124100Swpaul{ 2163140751Swpaul return(MmGetMdlByteCount(buf)); 2164124100Swpaul} 2165124100Swpaul 2166123723Swpaul/* 2167123723Swpaul * Get the virtual address and length of a buffer. 2168123723Swpaul * Note: the vaddr argument is optional. 2169123723Swpaul */ 2170123474Swpaul 2171144888Swpaulstatic void 2172140751SwpaulNdisQueryBuffer(buf, vaddr, len) 2173123474Swpaul ndis_buffer *buf; 2174123474Swpaul void **vaddr; 2175123474Swpaul uint32_t *len; 2176123474Swpaul{ 2177123723Swpaul if (vaddr != NULL) 2178140751Swpaul *vaddr = MmGetMdlVirtualAddress(buf); 2179140751Swpaul *len = MmGetMdlByteCount(buf); 2180123474Swpaul 2181123474Swpaul return; 2182123474Swpaul} 2183123474Swpaul 2184123474Swpaul/* Same as above -- we don't care about the priority. */ 2185123474Swpaul 2186144888Swpaulstatic void 2187140751SwpaulNdisQueryBufferSafe(buf, vaddr, len, prio) 2188123474Swpaul ndis_buffer *buf; 2189123474Swpaul void **vaddr; 2190123474Swpaul uint32_t *len; 2191123474Swpaul uint32_t prio; 2192123474Swpaul{ 2193123723Swpaul if (vaddr != NULL) 2194140751Swpaul *vaddr = MmGetMdlVirtualAddress(buf); 2195140751Swpaul *len = MmGetMdlByteCount(buf); 2196123474Swpaul 2197123474Swpaul return; 2198123474Swpaul} 2199123474Swpaul 2200125069Swpaul/* Damnit Microsoft!! How many ways can you do the same thing?! */ 2201125069Swpaul 2202144888Swpaulstatic void * 2203140751SwpaulNdisBufferVirtualAddress(buf) 2204125069Swpaul ndis_buffer *buf; 2205125069Swpaul{ 2206140751Swpaul return(MmGetMdlVirtualAddress(buf)); 2207125069Swpaul} 2208125069Swpaul 2209144888Swpaulstatic void * 2210140751SwpaulNdisBufferVirtualAddressSafe(buf, prio) 2211125069Swpaul ndis_buffer *buf; 2212125069Swpaul uint32_t prio; 2213125069Swpaul{ 2214140751Swpaul return(MmGetMdlVirtualAddress(buf)); 2215125069Swpaul} 2216125069Swpaul 2217144888Swpaulstatic void 2218140751SwpaulNdisAdjustBufferLength(buf, len) 2219123474Swpaul ndis_buffer *buf; 2220123474Swpaul int len; 2221123474Swpaul{ 2222140751Swpaul MmGetMdlByteCount(buf) = len; 2223123474Swpaul 2224123474Swpaul return; 2225123474Swpaul} 2226123474Swpaul 2227144888Swpaulstatic uint32_t 2228140751SwpaulNdisInterlockedIncrement(addend) 2229123474Swpaul uint32_t *addend; 2230123474Swpaul{ 2231124203Swpaul atomic_add_long((u_long *)addend, 1); 2232123474Swpaul return(*addend); 2233123474Swpaul} 2234123474Swpaul 2235144888Swpaulstatic uint32_t 2236140751SwpaulNdisInterlockedDecrement(addend) 2237123474Swpaul uint32_t *addend; 2238123474Swpaul{ 2239124203Swpaul atomic_subtract_long((u_long *)addend, 1); 2240123474Swpaul return(*addend); 2241123474Swpaul} 2242123474Swpaul 2243144888Swpaulstatic void 2244140751SwpaulNdisInitializeEvent(event) 2245123474Swpaul ndis_event *event; 2246123474Swpaul{ 2247127248Swpaul /* 2248127411Swpaul * NDIS events are always notification 2249127248Swpaul * events, and should be initialized to the 2250127248Swpaul * not signaled state. 2251127248Swpaul */ 2252140751Swpaul KeInitializeEvent(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE); 2253123474Swpaul return; 2254123474Swpaul} 2255123474Swpaul 2256144888Swpaulstatic void 2257140751SwpaulNdisSetEvent(event) 2258123474Swpaul ndis_event *event; 2259123474Swpaul{ 2260151451Swpaul KeSetEvent(&event->ne_event, IO_NO_INCREMENT, FALSE); 2261123474Swpaul return; 2262123474Swpaul} 2263123474Swpaul 2264144888Swpaulstatic void 2265140751SwpaulNdisResetEvent(event) 2266123474Swpaul ndis_event *event; 2267123474Swpaul{ 2268140751Swpaul KeResetEvent(&event->ne_event); 2269123474Swpaul return; 2270123474Swpaul} 2271123474Swpaul 2272144888Swpaulstatic uint8_t 2273140751SwpaulNdisWaitEvent(event, msecs) 2274123474Swpaul ndis_event *event; 2275123474Swpaul uint32_t msecs; 2276123474Swpaul{ 2277127248Swpaul int64_t duetime; 2278127248Swpaul uint32_t rval; 2279123474Swpaul 2280127248Swpaul duetime = ((int64_t)msecs * -10000); 2281151451Swpaul rval = KeWaitForSingleObject(event, 2282145895Swpaul 0, 0, TRUE, msecs ? & duetime : NULL); 2283123474Swpaul 2284127248Swpaul if (rval == STATUS_TIMEOUT) 2285127248Swpaul return(FALSE); 2286125551Swpaul 2287127248Swpaul return(TRUE); 2288123474Swpaul} 2289123474Swpaul 2290144888Swpaulstatic ndis_status 2291140751SwpaulNdisUnicodeStringToAnsiString(dstr, sstr) 2292151207Swpaul ansi_string *dstr; 2293151207Swpaul unicode_string *sstr; 2294123474Swpaul{ 2295151207Swpaul uint32_t rval; 2296151207Swpaul 2297151207Swpaul rval = RtlUnicodeStringToAnsiString(dstr, sstr, FALSE); 2298151207Swpaul 2299151207Swpaul if (rval == STATUS_INSUFFICIENT_RESOURCES) 2300151207Swpaul return(NDIS_STATUS_RESOURCES); 2301151207Swpaul if (rval) 2302123526Swpaul return(NDIS_STATUS_FAILURE); 2303151207Swpaul 2304123474Swpaul return (NDIS_STATUS_SUCCESS); 2305123474Swpaul} 2306123474Swpaul 2307144888Swpaulstatic ndis_status 2308140751SwpaulNdisAnsiStringToUnicodeString(dstr, sstr) 2309151207Swpaul unicode_string *dstr; 2310151207Swpaul ansi_string *sstr; 2311123526Swpaul{ 2312151207Swpaul uint32_t rval; 2313151207Swpaul 2314151207Swpaul rval = RtlAnsiStringToUnicodeString(dstr, sstr, FALSE); 2315151207Swpaul 2316151207Swpaul if (rval == STATUS_INSUFFICIENT_RESOURCES) 2317151207Swpaul return(NDIS_STATUS_RESOURCES); 2318151207Swpaul if (rval) 2319123526Swpaul return(NDIS_STATUS_FAILURE); 2320151207Swpaul 2321123526Swpaul return (NDIS_STATUS_SUCCESS); 2322123526Swpaul} 2323123526Swpaul 2324144888Swpaulstatic ndis_status 2325140751SwpaulNdisMPciAssignResources(adapter, slot, list) 2326123474Swpaul ndis_handle adapter; 2327123474Swpaul uint32_t slot; 2328123474Swpaul ndis_resource_list **list; 2329123474Swpaul{ 2330123474Swpaul ndis_miniport_block *block; 2331123474Swpaul 2332123474Swpaul if (adapter == NULL || list == NULL) 2333123474Swpaul return (NDIS_STATUS_FAILURE); 2334123474Swpaul 2335123474Swpaul block = (ndis_miniport_block *)adapter; 2336123474Swpaul *list = block->nmb_rlist; 2337123474Swpaul 2338123474Swpaul return (NDIS_STATUS_SUCCESS); 2339123474Swpaul} 2340123474Swpaul 2341151207Swpaulstatic void 2342151207Swpaulndis_intr(arg) 2343151207Swpaul void *arg; 2344151207Swpaul{ 2345151207Swpaul struct ndis_softc *sc; 2346151207Swpaul struct ifnet *ifp; 2347151207Swpaul int is_our_intr = 0; 2348151207Swpaul int call_isr = 0; 2349151207Swpaul ndis_miniport_interrupt *intr; 2350151207Swpaul 2351151207Swpaul sc = arg; 2352151207Swpaul ifp = sc->ifp; 2353151207Swpaul intr = sc->ndis_block->nmb_interrupt; 2354151207Swpaul 2355151207Swpaul if (intr == NULL || sc->ndis_block->nmb_miniportadapterctx == NULL) 2356151207Swpaul return; 2357151207Swpaul 2358151207Swpaul if (sc->ndis_block->nmb_interrupt->ni_isrreq == TRUE) 2359151207Swpaul ndis_isr(sc, &is_our_intr, &call_isr); 2360151207Swpaul else { 2361151207Swpaul ndis_disable_intr(sc); 2362151207Swpaul call_isr = 1; 2363151207Swpaul } 2364151207Swpaul 2365151207Swpaul if ((is_our_intr || call_isr)) 2366151207Swpaul IoRequestDpc(sc->ndis_block->nmb_deviceobj, NULL, sc); 2367151207Swpaul 2368151207Swpaul return; 2369151207Swpaul} 2370151207Swpaul 2371151207Swpaulstatic void 2372151207Swpaulndis_intrhand(dpc, intr, sysarg1, sysarg2) 2373151207Swpaul kdpc *dpc; 2374151207Swpaul ndis_miniport_interrupt *intr; 2375151207Swpaul void *sysarg1; 2376151207Swpaul void *sysarg2; 2377151207Swpaul{ 2378151207Swpaul struct ndis_softc *sc; 2379151207Swpaul ndis_miniport_block *block; 2380151207Swpaul ndis_handle adapter; 2381151207Swpaul 2382151207Swpaul block = intr->ni_block; 2383151207Swpaul adapter = block->nmb_miniportadapterctx; 2384151207Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2385151207Swpaul 2386151207Swpaul if (NDIS_SERIALIZED(sc->ndis_block)) 2387151207Swpaul KeAcquireSpinLockAtDpcLevel(&block->nmb_lock); 2388151207Swpaul 2389151207Swpaul MSCALL1(intr->ni_isrfunc, adapter); 2390151207Swpaul 2391151207Swpaul /* If there's a MiniportEnableInterrupt() routine, call it. */ 2392151207Swpaul 2393151207Swpaul ndis_enable_intr(sc); 2394151207Swpaul 2395151207Swpaul if (NDIS_SERIALIZED(sc->ndis_block)) 2396151207Swpaul KeReleaseSpinLockFromDpcLevel(&block->nmb_lock); 2397151207Swpaul 2398151207Swpaul /* 2399151207Swpaul * Set the completion event if we've drained all 2400151207Swpaul * pending interrupts. 2401151207Swpaul */ 2402151207Swpaul 2403151207Swpaul KeAcquireSpinLockAtDpcLevel(&intr->ni_dpccountlock); 2404151207Swpaul intr->ni_dpccnt--; 2405151207Swpaul if (intr->ni_dpccnt == 0) 2406151207Swpaul KeSetEvent(&intr->ni_dpcevt, IO_NO_INCREMENT, FALSE); 2407151207Swpaul KeReleaseSpinLockFromDpcLevel(&intr->ni_dpccountlock); 2408151207Swpaul 2409151207Swpaul return; 2410151207Swpaul} 2411151207Swpaul 2412144888Swpaulstatic ndis_status 2413140751SwpaulNdisMRegisterInterrupt(intr, adapter, ivec, ilevel, reqisr, shared, imode) 2414123474Swpaul ndis_miniport_interrupt *intr; 2415123474Swpaul ndis_handle adapter; 2416123474Swpaul uint32_t ivec; 2417123474Swpaul uint32_t ilevel; 2418123474Swpaul uint8_t reqisr; 2419123474Swpaul uint8_t shared; 2420123474Swpaul ndis_interrupt_mode imode; 2421123474Swpaul{ 2422124165Swpaul ndis_miniport_block *block; 2423151207Swpaul ndis_miniport_characteristics *ch; 2424151207Swpaul struct ndis_softc *sc; 2425151207Swpaul int error; 2426124165Swpaul 2427124165Swpaul block = adapter; 2428151207Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2429151207Swpaul ch = IoGetDriverObjectExtension(block->nmb_deviceobj->do_drvobj, 2430151207Swpaul (void *)1); 2431124165Swpaul 2432151207Swpaul intr->ni_rsvd = ExAllocatePoolWithTag(NonPagedPool, 2433151207Swpaul sizeof(struct mtx), 0); 2434151207Swpaul if (intr->ni_rsvd == NULL) 2435151207Swpaul return(NDIS_STATUS_RESOURCES); 2436151207Swpaul 2437124135Swpaul intr->ni_block = adapter; 2438124165Swpaul intr->ni_isrreq = reqisr; 2439124165Swpaul intr->ni_shared = shared; 2440151207Swpaul intr->ni_dpccnt = 0; 2441151207Swpaul intr->ni_isrfunc = ch->nmc_interrupt_func; 2442151207Swpaul intr->ni_dpcfunc = ch->nmc_isr_func; 2443151207Swpaul 2444151207Swpaul KeInitializeEvent(&intr->ni_dpcevt, EVENT_TYPE_NOTIFY, TRUE); 2445151207Swpaul KeInitializeDpc(&intr->ni_dpc, 2446151207Swpaul ndis_findwrap((funcptr)ndis_intrhand), intr); 2447151207Swpaul KeSetImportanceDpc(&intr->ni_dpc, KDPC_IMPORTANCE_LOW); 2448151207Swpaul 2449151207Swpaul error = IoConnectInterrupt(&intr->ni_introbj, 2450151207Swpaul ndis_findwrap((funcptr)ndis_intr), sc, NULL, 2451151207Swpaul ivec, ilevel, 0, imode, shared, 0, FALSE); 2452151207Swpaul 2453151207Swpaul if (error != STATUS_SUCCESS) 2454151207Swpaul return(NDIS_STATUS_FAILURE); 2455151207Swpaul 2456124165Swpaul block->nmb_interrupt = intr; 2457141524Swpaul 2458123474Swpaul return(NDIS_STATUS_SUCCESS); 2459123474Swpaul} 2460123474Swpaul 2461144888Swpaulstatic void 2462140751SwpaulNdisMDeregisterInterrupt(intr) 2463123474Swpaul ndis_miniport_interrupt *intr; 2464123474Swpaul{ 2465151207Swpaul ndis_miniport_block *block; 2466151207Swpaul struct ndis_softc *sc; 2467151207Swpaul uint8_t irql; 2468151207Swpaul 2469151207Swpaul block = intr->ni_block; 2470151207Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2471151207Swpaul 2472151207Swpaul /* Should really be KeSynchronizeExecution() */ 2473151207Swpaul 2474151207Swpaul KeAcquireSpinLock(intr->ni_introbj->ki_lock, &irql); 2475151207Swpaul block->nmb_interrupt = NULL; 2476151207Swpaul KeReleaseSpinLock(intr->ni_introbj->ki_lock, irql); 2477151207Swpaul/* 2478151207Swpaul KeFlushQueuedDpcs(); 2479151207Swpaul*/ 2480151207Swpaul /* Disconnect our ISR */ 2481151207Swpaul 2482151207Swpaul IoDisconnectInterrupt(intr->ni_introbj); 2483151207Swpaul 2484151451Swpaul KeWaitForSingleObject(&intr->ni_dpcevt, 0, 0, FALSE, NULL); 2485151207Swpaul KeResetEvent(&intr->ni_dpcevt); 2486151207Swpaul 2487123474Swpaul return; 2488123474Swpaul} 2489123474Swpaul 2490144888Swpaulstatic void 2491140751SwpaulNdisMRegisterAdapterShutdownHandler(adapter, shutdownctx, shutdownfunc) 2492123474Swpaul ndis_handle adapter; 2493123474Swpaul void *shutdownctx; 2494123474Swpaul ndis_shutdown_handler shutdownfunc; 2495123474Swpaul{ 2496123474Swpaul ndis_miniport_block *block; 2497123474Swpaul ndis_miniport_characteristics *chars; 2498123474Swpaul struct ndis_softc *sc; 2499123474Swpaul 2500123474Swpaul if (adapter == NULL) 2501123474Swpaul return; 2502123474Swpaul 2503123474Swpaul block = (ndis_miniport_block *)adapter; 2504141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2505141524Swpaul chars = sc->ndis_chars; 2506123474Swpaul 2507123474Swpaul chars->nmc_shutdown_handler = shutdownfunc; 2508123474Swpaul chars->nmc_rsvd0 = shutdownctx; 2509123474Swpaul 2510123474Swpaul return; 2511123474Swpaul} 2512123474Swpaul 2513144888Swpaulstatic void 2514140751SwpaulNdisMDeregisterAdapterShutdownHandler(adapter) 2515123474Swpaul ndis_handle adapter; 2516123474Swpaul{ 2517123474Swpaul ndis_miniport_block *block; 2518123474Swpaul ndis_miniport_characteristics *chars; 2519123474Swpaul struct ndis_softc *sc; 2520123474Swpaul 2521123474Swpaul if (adapter == NULL) 2522123474Swpaul return; 2523123474Swpaul 2524123474Swpaul block = (ndis_miniport_block *)adapter; 2525141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2526141524Swpaul chars = sc->ndis_chars; 2527123474Swpaul 2528123474Swpaul chars->nmc_shutdown_handler = NULL; 2529123474Swpaul chars->nmc_rsvd0 = NULL; 2530123474Swpaul 2531123474Swpaul return; 2532123474Swpaul} 2533123474Swpaul 2534144888Swpaulstatic uint32_t 2535140751SwpaulNDIS_BUFFER_TO_SPAN_PAGES(buf) 2536123474Swpaul ndis_buffer *buf; 2537123474Swpaul{ 2538123757Swpaul if (buf == NULL) 2539123757Swpaul return(0); 2540140751Swpaul if (MmGetMdlByteCount(buf) == 0) 2541123512Swpaul return(1); 2542140751Swpaul return(SPAN_PAGES(MmGetMdlVirtualAddress(buf), 2543140751Swpaul MmGetMdlByteCount(buf))); 2544123474Swpaul} 2545123474Swpaul 2546144888Swpaulstatic void 2547140751SwpaulNdisGetBufferPhysicalArraySize(buf, pages) 2548123573Swpaul ndis_buffer *buf; 2549123573Swpaul uint32_t *pages; 2550123573Swpaul{ 2551123757Swpaul if (buf == NULL) 2552123757Swpaul return; 2553123757Swpaul 2554140751Swpaul *pages = NDIS_BUFFER_TO_SPAN_PAGES(buf); 2555123573Swpaul return; 2556123573Swpaul} 2557123573Swpaul 2558144888Swpaulstatic void 2559140751SwpaulNdisQueryBufferOffset(buf, off, len) 2560123474Swpaul ndis_buffer *buf; 2561123474Swpaul uint32_t *off; 2562123474Swpaul uint32_t *len; 2563123474Swpaul{ 2564123757Swpaul if (buf == NULL) 2565123757Swpaul return; 2566123757Swpaul 2567140751Swpaul *off = MmGetMdlByteOffset(buf); 2568140751Swpaul *len = MmGetMdlByteCount(buf); 2569123474Swpaul 2570123474Swpaul return; 2571123474Swpaul} 2572123474Swpaul 2573151451Swpaulvoid 2574140751SwpaulNdisMSleep(usecs) 2575123474Swpaul uint32_t usecs; 2576123474Swpaul{ 2577151207Swpaul ktimer timer; 2578123474Swpaul 2579145485Swpaul /* 2580145485Swpaul * During system bootstrap, (i.e. cold == 1), we aren't 2581151207Swpaul * allowed to sleep, so we have to do a hard DELAY() 2582151207Swpaul * instead. 2583145485Swpaul */ 2584123474Swpaul 2585151207Swpaul if (cold) 2586145485Swpaul DELAY(usecs); 2587151207Swpaul else { 2588151207Swpaul KeInitializeTimer(&timer); 2589151207Swpaul KeSetTimer(&timer, ((int64_t)usecs * -10), NULL); 2590151451Swpaul KeWaitForSingleObject(&timer, 0, 0, FALSE, NULL); 2591151207Swpaul } 2592151451Swpaul 2593123474Swpaul return; 2594123474Swpaul} 2595123474Swpaul 2596144888Swpaulstatic uint32_t 2597140751SwpaulNdisReadPcmciaAttributeMemory(handle, offset, buf, len) 2598123474Swpaul ndis_handle handle; 2599123474Swpaul uint32_t offset; 2600123474Swpaul void *buf; 2601123474Swpaul uint32_t len; 2602123474Swpaul{ 2603123474Swpaul struct ndis_softc *sc; 2604123474Swpaul ndis_miniport_block *block; 2605123474Swpaul bus_space_handle_t bh; 2606123474Swpaul bus_space_tag_t bt; 2607123474Swpaul char *dest; 2608123474Swpaul int i; 2609123474Swpaul 2610123474Swpaul if (handle == NULL) 2611123474Swpaul return(0); 2612123474Swpaul 2613123474Swpaul block = (ndis_miniport_block *)handle; 2614141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2615123474Swpaul dest = buf; 2616123474Swpaul 2617123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 2618123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 2619123474Swpaul 2620123474Swpaul for (i = 0; i < len; i++) 2621131953Swpaul dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2); 2622123474Swpaul 2623123474Swpaul return(i); 2624123474Swpaul} 2625123474Swpaul 2626144888Swpaulstatic uint32_t 2627140751SwpaulNdisWritePcmciaAttributeMemory(handle, offset, buf, len) 2628123474Swpaul ndis_handle handle; 2629123474Swpaul uint32_t offset; 2630123474Swpaul void *buf; 2631123474Swpaul uint32_t len; 2632123474Swpaul{ 2633123474Swpaul struct ndis_softc *sc; 2634123474Swpaul ndis_miniport_block *block; 2635123474Swpaul bus_space_handle_t bh; 2636123474Swpaul bus_space_tag_t bt; 2637123474Swpaul char *src; 2638123474Swpaul int i; 2639123474Swpaul 2640123474Swpaul if (handle == NULL) 2641123474Swpaul return(0); 2642123474Swpaul 2643123474Swpaul block = (ndis_miniport_block *)handle; 2644141524Swpaul sc = device_get_softc(block->nmb_physdeviceobj->do_devext); 2645123474Swpaul src = buf; 2646123474Swpaul 2647123474Swpaul bh = rman_get_bushandle(sc->ndis_res_am); 2648123474Swpaul bt = rman_get_bustag(sc->ndis_res_am); 2649123474Swpaul 2650123474Swpaul for (i = 0; i < len; i++) 2651131953Swpaul bus_space_write_1(bt, bh, (offset + i) * 2, src[i]); 2652123474Swpaul 2653123474Swpaul return(i); 2654123474Swpaul} 2655123474Swpaul 2656144888Swpaulstatic list_entry * 2657140751SwpaulNdisInterlockedInsertHeadList(head, entry, lock) 2658125551Swpaul list_entry *head; 2659125551Swpaul list_entry *entry; 2660123474Swpaul ndis_spin_lock *lock; 2661123474Swpaul{ 2662125551Swpaul list_entry *flink; 2663123474Swpaul 2664140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 2665123474Swpaul flink = head->nle_flink; 2666123474Swpaul entry->nle_flink = flink; 2667123474Swpaul entry->nle_blink = head; 2668123474Swpaul flink->nle_blink = entry; 2669123474Swpaul head->nle_flink = entry; 2670140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 2671123474Swpaul 2672123474Swpaul return(flink); 2673123474Swpaul} 2674123474Swpaul 2675144888Swpaulstatic list_entry * 2676140751SwpaulNdisInterlockedRemoveHeadList(head, lock) 2677125551Swpaul list_entry *head; 2678123474Swpaul ndis_spin_lock *lock; 2679123474Swpaul{ 2680125551Swpaul list_entry *flink; 2681125551Swpaul list_entry *entry; 2682123474Swpaul 2683140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 2684123474Swpaul entry = head->nle_flink; 2685123474Swpaul flink = entry->nle_flink; 2686123474Swpaul head->nle_flink = flink; 2687123474Swpaul flink->nle_blink = head; 2688140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 2689123474Swpaul 2690123474Swpaul return(entry); 2691123474Swpaul} 2692123474Swpaul 2693144888Swpaulstatic list_entry * 2694140751SwpaulNdisInterlockedInsertTailList(head, entry, lock) 2695125551Swpaul list_entry *head; 2696125551Swpaul list_entry *entry; 2697123474Swpaul ndis_spin_lock *lock; 2698123474Swpaul{ 2699125551Swpaul list_entry *blink; 2700123474Swpaul 2701140751Swpaul KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql); 2702123474Swpaul blink = head->nle_blink; 2703123474Swpaul entry->nle_flink = head; 2704123474Swpaul entry->nle_blink = blink; 2705123474Swpaul blink->nle_flink = entry; 2706123474Swpaul head->nle_blink = entry; 2707140751Swpaul KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql); 2708123474Swpaul 2709123474Swpaul return(blink); 2710123474Swpaul} 2711123474Swpaul 2712144888Swpaulstatic uint8_t 2713140751SwpaulNdisMSynchronizeWithInterrupt(intr, syncfunc, syncctx) 2714123474Swpaul ndis_miniport_interrupt *intr; 2715123474Swpaul void *syncfunc; 2716123474Swpaul void *syncctx; 2717123474Swpaul{ 2718151207Swpaul return(KeSynchronizeExecution(intr->ni_introbj, syncfunc, syncctx)); 2719123474Swpaul} 2720123474Swpaul 2721123504Swpaul/* 2722123504Swpaul * Return the number of 100 nanosecond intervals since 2723123504Swpaul * January 1, 1601. (?!?!) 2724123504Swpaul */ 2725144888Swpaulstatic void 2726140751SwpaulNdisGetCurrentSystemTime(tval) 2727123504Swpaul uint64_t *tval; 2728123504Swpaul{ 2729123504Swpaul struct timespec ts; 2730123822Swpaul 2731123504Swpaul nanotime(&ts); 2732123822Swpaul *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 + 2733123822Swpaul 11644473600; 2734125551Swpaul 2735125551Swpaul return; 2736123504Swpaul} 2737123504Swpaul 2738123822Swpaul/* 2739123822Swpaul * Return the number of milliseconds since the system booted. 2740123822Swpaul */ 2741144888Swpaulstatic void 2742140751SwpaulNdisGetSystemUpTime(tval) 2743123822Swpaul uint32_t *tval; 2744123822Swpaul{ 2745144888Swpaul struct timespec ts; 2746144888Swpaul 2747144888Swpaul nanouptime(&ts); 2748144888Swpaul *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000; 2749123822Swpaul 2750125551Swpaul return; 2751123822Swpaul} 2752123822Swpaul 2753144888Swpaulstatic void 2754140751SwpaulNdisInitializeString(dst, src) 2755151207Swpaul unicode_string *dst; 2756123507Swpaul char *src; 2757123507Swpaul{ 2758151207Swpaul ansi_string as; 2759151207Swpaul RtlInitAnsiString(&as, src); 2760151207Swpaul RtlAnsiStringToUnicodeString(dst, &as, TRUE); 2761123507Swpaul return; 2762123507Swpaul} 2763123507Swpaul 2764144888Swpaulstatic void 2765140751SwpaulNdisFreeString(str) 2766151207Swpaul unicode_string *str; 2767123507Swpaul{ 2768151207Swpaul RtlFreeUnicodeString(str); 2769123507Swpaul return; 2770123507Swpaul} 2771123507Swpaul 2772144888Swpaulstatic ndis_status 2773140751SwpaulNdisMRemoveMiniport(adapter) 2774123507Swpaul ndis_handle *adapter; 2775123507Swpaul{ 2776123507Swpaul return(NDIS_STATUS_SUCCESS); 2777123507Swpaul} 2778123507Swpaul 2779144888Swpaulstatic void 2780140751SwpaulNdisInitAnsiString(dst, src) 2781151207Swpaul ansi_string *dst; 2782123526Swpaul char *src; 2783123526Swpaul{ 2784151207Swpaul RtlInitAnsiString(dst, src); 2785123526Swpaul return; 2786123526Swpaul} 2787123526Swpaul 2788144888Swpaulstatic void 2789140751SwpaulNdisInitUnicodeString(dst, src) 2790151207Swpaul unicode_string *dst; 2791123941Swpaul uint16_t *src; 2792123941Swpaul{ 2793151207Swpaul RtlInitUnicodeString(dst, src); 2794123941Swpaul return; 2795123941Swpaul} 2796123941Swpaul 2797144888Swpaulstatic void NdisMGetDeviceProperty(adapter, phydevobj, 2798123526Swpaul funcdevobj, nextdevobj, resources, transresources) 2799123526Swpaul ndis_handle adapter; 2800125551Swpaul device_object **phydevobj; 2801125551Swpaul device_object **funcdevobj; 2802125551Swpaul device_object **nextdevobj; 2803123526Swpaul cm_resource_list *resources; 2804123526Swpaul cm_resource_list *transresources; 2805123526Swpaul{ 2806125551Swpaul ndis_miniport_block *block; 2807125551Swpaul 2808125551Swpaul block = (ndis_miniport_block *)adapter; 2809125551Swpaul 2810125551Swpaul if (phydevobj != NULL) 2811141524Swpaul *phydevobj = block->nmb_physdeviceobj; 2812125551Swpaul if (funcdevobj != NULL) 2813141524Swpaul *funcdevobj = block->nmb_deviceobj; 2814141524Swpaul if (nextdevobj != NULL) 2815141524Swpaul *nextdevobj = block->nmb_nextdeviceobj; 2816125551Swpaul 2817123526Swpaul return; 2818123526Swpaul} 2819123526Swpaul 2820144888Swpaulstatic void 2821140751SwpaulNdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen) 2822123721Swpaul ndis_packet *packet; 2823123721Swpaul ndis_buffer **buf; 2824123721Swpaul void **firstva; 2825123721Swpaul uint32_t *firstlen; 2826123721Swpaul uint32_t *totlen; 2827123721Swpaul{ 2828123721Swpaul ndis_buffer *tmp; 2829123721Swpaul 2830123721Swpaul tmp = packet->np_private.npp_head; 2831123721Swpaul *buf = tmp; 2832123721Swpaul if (tmp == NULL) { 2833123721Swpaul *firstva = NULL; 2834123721Swpaul *firstlen = *totlen = 0; 2835123721Swpaul } else { 2836140751Swpaul *firstva = MmGetMdlVirtualAddress(tmp); 2837140751Swpaul *firstlen = *totlen = MmGetMdlByteCount(tmp); 2838140751Swpaul for (tmp = tmp->mdl_next; tmp != NULL; tmp = tmp->mdl_next) 2839140751Swpaul *totlen += MmGetMdlByteCount(tmp); 2840123721Swpaul } 2841123721Swpaul 2842123721Swpaul return; 2843123721Swpaul} 2844123721Swpaul 2845144888Swpaulstatic void 2846140751SwpaulNdisGetFirstBufferFromPacketSafe(packet, buf, firstva, firstlen, totlen, prio) 2847123721Swpaul ndis_packet *packet; 2848123721Swpaul ndis_buffer **buf; 2849123721Swpaul void **firstva; 2850123721Swpaul uint32_t *firstlen; 2851123721Swpaul uint32_t *totlen; 2852123721Swpaul uint32_t prio; 2853123721Swpaul{ 2854140751Swpaul NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen); 2855123721Swpaul} 2856123721Swpaul 2857132973Swpaulstatic int 2858132973Swpaulndis_find_sym(lf, filename, suffix, sym) 2859132973Swpaul linker_file_t lf; 2860132973Swpaul char *filename; 2861132973Swpaul char *suffix; 2862132973Swpaul caddr_t *sym; 2863132973Swpaul{ 2864143086Swpaul char *fullsym; 2865133876Swpaul char *suf; 2866132973Swpaul int i; 2867132973Swpaul 2868143086Swpaul fullsym = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0); 2869143086Swpaul if (fullsym == NULL) 2870143086Swpaul return(ENOMEM); 2871143086Swpaul 2872143086Swpaul bzero(fullsym, MAXPATHLEN); 2873143086Swpaul strncpy(fullsym, filename, MAXPATHLEN); 2874143086Swpaul if (strlen(filename) < 4) { 2875143086Swpaul ExFreePool(fullsym); 2876133876Swpaul return(EINVAL); 2877143086Swpaul } 2878133876Swpaul 2879133876Swpaul /* If the filename has a .ko suffix, strip if off. */ 2880133876Swpaul suf = fullsym + (strlen(filename) - 3); 2881133876Swpaul if (strcmp(suf, ".ko") == 0) 2882133876Swpaul *suf = '\0'; 2883133876Swpaul 2884132973Swpaul for (i = 0; i < strlen(fullsym); i++) { 2885132973Swpaul if (fullsym[i] == '.') 2886132973Swpaul fullsym[i] = '_'; 2887132973Swpaul else 2888132973Swpaul fullsym[i] = tolower(fullsym[i]); 2889132973Swpaul } 2890132973Swpaul strcat(fullsym, suffix); 2891132973Swpaul *sym = linker_file_lookup_symbol(lf, fullsym, 0); 2892143086Swpaul ExFreePool(fullsym); 2893132973Swpaul if (*sym == 0) 2894132973Swpaul return(ENOENT); 2895132973Swpaul 2896132973Swpaul return(0); 2897132973Swpaul} 2898132973Swpaul 2899123822Swpaul/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */ 2900144888Swpaulstatic void 2901140751SwpaulNdisOpenFile(status, filehandle, filelength, filename, highestaddr) 2902123822Swpaul ndis_status *status; 2903123822Swpaul ndis_handle *filehandle; 2904123822Swpaul uint32_t *filelength; 2905151207Swpaul unicode_string *filename; 2906123822Swpaul ndis_physaddr highestaddr; 2907123822Swpaul{ 2908151207Swpaul ansi_string as; 2909123822Swpaul char *afilename = NULL; 2910124272Swpaul struct thread *td = curthread; 2911124272Swpaul struct nameidata nd; 2912124272Swpaul int flags, error; 2913124272Swpaul struct vattr vat; 2914124272Swpaul struct vattr *vap = &vat; 2915124272Swpaul ndis_fh *fh; 2916143086Swpaul char *path; 2917132973Swpaul linker_file_t head, lf; 2918132973Swpaul caddr_t kldstart, kldend; 2919123822Swpaul 2920151207Swpaul if (RtlUnicodeStringToAnsiString(&as, filename, TRUE)) { 2921151207Swpaul *status = NDIS_STATUS_RESOURCES; 2922151207Swpaul return; 2923151207Swpaul } 2924124272Swpaul 2925151207Swpaul afilename = strdup(as.as_buf, M_DEVBUF); 2926151207Swpaul RtlFreeAnsiString(&as); 2927151207Swpaul 2928143086Swpaul fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0); 2929124272Swpaul if (fh == NULL) { 2930145895Swpaul free(afilename, M_DEVBUF); 2931124272Swpaul *status = NDIS_STATUS_RESOURCES; 2932124272Swpaul return; 2933124272Swpaul } 2934124272Swpaul 2935145895Swpaul fh->nf_name = afilename; 2936145895Swpaul 2937132973Swpaul /* 2938132973Swpaul * During system bootstrap, it's impossible to load files 2939132973Swpaul * from the rootfs since it's not mounted yet. We therefore 2940132973Swpaul * offer the possibility of opening files that have been 2941132973Swpaul * preloaded as modules instead. Both choices will work 2942132973Swpaul * when kldloading a module from multiuser, but only the 2943132973Swpaul * module option will work during bootstrap. The module 2944132973Swpaul * loading option works by using the ndiscvt(8) utility 2945132973Swpaul * to convert the arbitrary file into a .ko using objcopy(1). 2946132973Swpaul * This file will contain two special symbols: filename_start 2947132973Swpaul * and filename_end. All we have to do is traverse the KLD 2948132973Swpaul * list in search of those symbols and we've found the file 2949132973Swpaul * data. As an added bonus, ndiscvt(8) will also generate 2950132973Swpaul * a normal .o file which can be linked statically with 2951132973Swpaul * the kernel. This means that the symbols will actual reside 2952132973Swpaul * in the kernel's symbol table, but that doesn't matter to 2953132973Swpaul * us since the kernel appears to us as just another module. 2954132973Swpaul */ 2955132973Swpaul 2956132973Swpaul /* 2957132973Swpaul * This is an evil trick for getting the head of the linked 2958132973Swpaul * file list, which is not exported from kern_linker.o. It 2959132973Swpaul * happens that linker file #1 is always the kernel, and is 2960132973Swpaul * always the first element in the list. 2961132973Swpaul */ 2962132973Swpaul 2963132973Swpaul head = linker_find_file_by_id(1); 2964132973Swpaul for (lf = head; lf != NULL; lf = TAILQ_NEXT(lf, link)) { 2965132973Swpaul if (ndis_find_sym(lf, afilename, "_start", &kldstart)) 2966132973Swpaul continue; 2967132973Swpaul if (ndis_find_sym(lf, afilename, "_end", &kldend)) 2968132973Swpaul continue; 2969132973Swpaul fh->nf_vp = lf; 2970133880Swpaul fh->nf_map = NULL; 2971132973Swpaul fh->nf_type = NDIS_FH_TYPE_MODULE; 2972132973Swpaul *filelength = fh->nf_maplen = (kldend - kldstart) & 0xFFFFFFFF; 2973132973Swpaul *filehandle = fh; 2974132973Swpaul *status = NDIS_STATUS_SUCCESS; 2975132973Swpaul return; 2976132973Swpaul } 2977132973Swpaul 2978132973Swpaul if (TAILQ_EMPTY(&mountlist)) { 2979144256Swpaul ExFreePool(fh); 2980132973Swpaul *status = NDIS_STATUS_FILE_NOT_FOUND; 2981132973Swpaul printf("NDIS: could not find file %s in linker list\n", 2982132973Swpaul afilename); 2983132973Swpaul printf("NDIS: and no filesystems mounted yet, " 2984132973Swpaul "aborting NdisOpenFile()\n"); 2985132973Swpaul free(afilename, M_DEVBUF); 2986132973Swpaul return; 2987132973Swpaul } 2988132973Swpaul 2989143086Swpaul path = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0); 2990143086Swpaul if (path == NULL) { 2991144256Swpaul ExFreePool(fh); 2992145895Swpaul free(afilename, M_DEVBUF); 2993143086Swpaul *status = NDIS_STATUS_RESOURCES; 2994143086Swpaul return; 2995143086Swpaul } 2996143086Swpaul 2997143086Swpaul snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename); 2998132973Swpaul 2999124272Swpaul mtx_lock(&Giant); 3000125377Swpaul 3001125377Swpaul /* Some threads don't have a current working directory. */ 3002125377Swpaul 3003125377Swpaul if (td->td_proc->p_fd->fd_rdir == NULL) 3004125377Swpaul td->td_proc->p_fd->fd_rdir = rootvnode; 3005125377Swpaul if (td->td_proc->p_fd->fd_cdir == NULL) 3006125377Swpaul td->td_proc->p_fd->fd_cdir = rootvnode; 3007125377Swpaul 3008124272Swpaul NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); 3009124272Swpaul 3010124272Swpaul flags = FREAD; 3011124272Swpaul error = vn_open(&nd, &flags, 0, -1); 3012124272Swpaul if (error) { 3013124272Swpaul mtx_unlock(&Giant); 3014124272Swpaul *status = NDIS_STATUS_FILE_NOT_FOUND; 3015143086Swpaul ExFreePool(fh); 3016127887Swpaul printf("NDIS: open file %s failed: %d\n", path, error); 3017143086Swpaul ExFreePool(path); 3018145895Swpaul free(afilename, M_DEVBUF); 3019124272Swpaul return; 3020124272Swpaul } 3021124272Swpaul 3022143086Swpaul ExFreePool(path); 3023143086Swpaul 3024124272Swpaul NDFREE(&nd, NDF_ONLY_PNBUF); 3025124272Swpaul 3026124272Swpaul /* Get the file size. */ 3027131953Swpaul VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td); 3028124272Swpaul VOP_UNLOCK(nd.ni_vp, 0, td); 3029124272Swpaul mtx_unlock(&Giant); 3030124272Swpaul 3031124272Swpaul fh->nf_vp = nd.ni_vp; 3032124272Swpaul fh->nf_map = NULL; 3033132973Swpaul fh->nf_type = NDIS_FH_TYPE_VFS; 3034124272Swpaul *filehandle = fh; 3035124272Swpaul *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF; 3036124272Swpaul *status = NDIS_STATUS_SUCCESS; 3037131953Swpaul 3038123822Swpaul return; 3039123822Swpaul} 3040123822Swpaul 3041144888Swpaulstatic void 3042140751SwpaulNdisMapFile(status, mappedbuffer, filehandle) 3043123822Swpaul ndis_status *status; 3044123822Swpaul void **mappedbuffer; 3045123822Swpaul ndis_handle filehandle; 3046123822Swpaul{ 3047124272Swpaul ndis_fh *fh; 3048124272Swpaul struct thread *td = curthread; 3049133876Swpaul linker_file_t lf; 3050133876Swpaul caddr_t kldstart; 3051124272Swpaul int error, resid; 3052123822Swpaul 3053124272Swpaul if (filehandle == NULL) { 3054124272Swpaul *status = NDIS_STATUS_FAILURE; 3055124272Swpaul return; 3056124272Swpaul } 3057124272Swpaul 3058124272Swpaul fh = (ndis_fh *)filehandle; 3059124272Swpaul 3060124272Swpaul if (fh->nf_vp == NULL) { 3061124272Swpaul *status = NDIS_STATUS_FAILURE; 3062124272Swpaul return; 3063124272Swpaul } 3064124272Swpaul 3065124272Swpaul if (fh->nf_map != NULL) { 3066124272Swpaul *status = NDIS_STATUS_ALREADY_MAPPED; 3067124272Swpaul return; 3068124272Swpaul } 3069124272Swpaul 3070132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_MODULE) { 3071133876Swpaul lf = fh->nf_vp; 3072145895Swpaul if (ndis_find_sym(lf, fh->nf_name, "_start", &kldstart)) { 3073133876Swpaul *status = NDIS_STATUS_FAILURE; 3074133876Swpaul return; 3075133876Swpaul } 3076133876Swpaul fh->nf_map = kldstart; 3077132973Swpaul *status = NDIS_STATUS_SUCCESS; 3078132973Swpaul *mappedbuffer = fh->nf_map; 3079132973Swpaul return; 3080132973Swpaul } 3081132973Swpaul 3082143086Swpaul fh->nf_map = ExAllocatePoolWithTag(NonPagedPool, fh->nf_maplen, 0); 3083124272Swpaul 3084124272Swpaul if (fh->nf_map == NULL) { 3085124272Swpaul *status = NDIS_STATUS_RESOURCES; 3086124272Swpaul return; 3087124272Swpaul } 3088124272Swpaul 3089124272Swpaul mtx_lock(&Giant); 3090124272Swpaul error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0, 3091124272Swpaul UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td); 3092124272Swpaul mtx_unlock(&Giant); 3093124272Swpaul 3094124272Swpaul if (error) 3095124272Swpaul *status = NDIS_STATUS_FAILURE; 3096124272Swpaul else { 3097124272Swpaul *status = NDIS_STATUS_SUCCESS; 3098124272Swpaul *mappedbuffer = fh->nf_map; 3099124272Swpaul } 3100124272Swpaul 3101123822Swpaul return; 3102123822Swpaul} 3103123822Swpaul 3104144888Swpaulstatic void 3105140751SwpaulNdisUnmapFile(filehandle) 3106123822Swpaul ndis_handle filehandle; 3107123822Swpaul{ 3108124272Swpaul ndis_fh *fh; 3109124272Swpaul fh = (ndis_fh *)filehandle; 3110124272Swpaul 3111124272Swpaul if (fh->nf_map == NULL) 3112124272Swpaul return; 3113132973Swpaul 3114132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_VFS) 3115143086Swpaul ExFreePool(fh->nf_map); 3116124272Swpaul fh->nf_map = NULL; 3117124272Swpaul 3118123822Swpaul return; 3119123822Swpaul} 3120123822Swpaul 3121144888Swpaulstatic void 3122140751SwpaulNdisCloseFile(filehandle) 3123123822Swpaul ndis_handle filehandle; 3124123822Swpaul{ 3125124272Swpaul struct thread *td = curthread; 3126124272Swpaul ndis_fh *fh; 3127124272Swpaul 3128124272Swpaul if (filehandle == NULL) 3129124272Swpaul return; 3130124272Swpaul 3131124272Swpaul fh = (ndis_fh *)filehandle; 3132124272Swpaul if (fh->nf_map != NULL) { 3133132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_VFS) 3134143086Swpaul ExFreePool(fh->nf_map); 3135124272Swpaul fh->nf_map = NULL; 3136124272Swpaul } 3137124272Swpaul 3138124272Swpaul if (fh->nf_vp == NULL) 3139124272Swpaul return; 3140124272Swpaul 3141132973Swpaul if (fh->nf_type == NDIS_FH_TYPE_VFS) { 3142132973Swpaul mtx_lock(&Giant); 3143132973Swpaul vn_close(fh->nf_vp, FREAD, td->td_ucred, td); 3144132973Swpaul mtx_unlock(&Giant); 3145132973Swpaul } 3146124272Swpaul 3147124272Swpaul fh->nf_vp = NULL; 3148145895Swpaul free(fh->nf_name, M_DEVBUF); 3149143086Swpaul ExFreePool(fh); 3150124272Swpaul 3151123822Swpaul return; 3152123822Swpaul} 3153123822Swpaul 3154144888Swpaulstatic uint8_t 3155140751SwpaulNdisSystemProcessorCount() 3156123848Swpaul{ 3157123848Swpaul return(mp_ncpus); 3158124509Swpaul} 3159123848Swpaul 3160124116Swpaultypedef void (*ndis_statusdone_handler)(ndis_handle); 3161124116Swpaultypedef void (*ndis_status_handler)(ndis_handle, ndis_status, 3162124116Swpaul void *, uint32_t); 3163124116Swpaul 3164144888Swpaulstatic void 3165140751SwpaulNdisMIndicateStatusComplete(adapter) 3166124116Swpaul ndis_handle adapter; 3167124116Swpaul{ 3168124116Swpaul ndis_miniport_block *block; 3169144888Swpaul ndis_statusdone_handler statusdonefunc; 3170124116Swpaul 3171124116Swpaul block = (ndis_miniport_block *)adapter; 3172124116Swpaul statusdonefunc = block->nmb_statusdone_func; 3173124116Swpaul 3174141963Swpaul MSCALL1(statusdonefunc, adapter); 3175124116Swpaul return; 3176124116Swpaul} 3177124116Swpaul 3178144888Swpaulstatic void 3179140751SwpaulNdisMIndicateStatus(adapter, status, sbuf, slen) 3180124116Swpaul ndis_handle adapter; 3181124116Swpaul ndis_status status; 3182124116Swpaul void *sbuf; 3183124116Swpaul uint32_t slen; 3184124116Swpaul{ 3185124116Swpaul ndis_miniport_block *block; 3186144888Swpaul ndis_status_handler statusfunc; 3187124116Swpaul 3188124116Swpaul block = (ndis_miniport_block *)adapter; 3189124116Swpaul statusfunc = block->nmb_status_func; 3190124116Swpaul 3191141963Swpaul MSCALL4(statusfunc, adapter, status, sbuf, slen); 3192124116Swpaul return; 3193124116Swpaul} 3194124116Swpaul 3195145895Swpaul/* 3196145895Swpaul * The DDK documentation says that you should use IoQueueWorkItem() 3197145895Swpaul * instead of ExQueueWorkItem(). The problem is, IoQueueWorkItem() 3198145895Swpaul * is fundamentally incompatible with NdisScheduleWorkItem(), which 3199145895Swpaul * depends on the API semantics of ExQueueWorkItem(). In our world, 3200145895Swpaul * ExQueueWorkItem() is implemented on top of IoAllocateQueueItem() 3201145895Swpaul * anyway. 3202146273Swpaul * 3203146273Swpaul * There are actually three distinct APIs here. NdisScheduleWorkItem() 3204146273Swpaul * takes a pointer to an NDIS_WORK_ITEM. ExQueueWorkItem() takes a pointer 3205146273Swpaul * to a WORK_QUEUE_ITEM. And finally, IoQueueWorkItem() takes a pointer 3206146273Swpaul * to an opaque work item thingie which you get from IoAllocateWorkItem(). 3207146273Swpaul * An NDIS_WORK_ITEM is not the same as a WORK_QUEUE_ITEM. However, 3208146273Swpaul * the NDIS_WORK_ITEM has some opaque storage at the end of it, and we 3209146273Swpaul * (ab)use this storage as a WORK_QUEUE_ITEM, which is what we submit 3210146273Swpaul * to ExQueueWorkItem(). 3211146273Swpaul * 3212146273Swpaul * Got all that? (Sheesh.) 3213145895Swpaul */ 3214124122Swpaul 3215145895Swpaulndis_status 3216140751SwpaulNdisScheduleWorkItem(work) 3217124122Swpaul ndis_work_item *work; 3218124122Swpaul{ 3219146273Swpaul work_queue_item *wqi; 3220146273Swpaul 3221146273Swpaul wqi = (work_queue_item *)work->nwi_wraprsvd; 3222146273Swpaul ExInitializeWorkItem(wqi, 3223146273Swpaul (work_item_func)work->nwi_func, work->nwi_ctx); 3224146273Swpaul ExQueueWorkItem(wqi, WORKQUEUE_DELAYED); 3225151207Swpaul 3226124122Swpaul return(NDIS_STATUS_SUCCESS); 3227124122Swpaul} 3228124122Swpaul 3229144888Swpaulstatic void 3230140751SwpaulNdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen) 3231124541Swpaul ndis_packet *dpkt; 3232124541Swpaul uint32_t doff; 3233124541Swpaul uint32_t reqlen; 3234124541Swpaul ndis_packet *spkt; 3235124541Swpaul uint32_t soff; 3236124541Swpaul uint32_t *cpylen; 3237124541Swpaul{ 3238124541Swpaul ndis_buffer *src, *dst; 3239124541Swpaul char *sptr, *dptr; 3240124541Swpaul int resid, copied, len, scnt, dcnt; 3241124541Swpaul 3242124541Swpaul *cpylen = 0; 3243124541Swpaul 3244124541Swpaul src = spkt->np_private.npp_head; 3245124541Swpaul dst = dpkt->np_private.npp_head; 3246124541Swpaul 3247140751Swpaul sptr = MmGetMdlVirtualAddress(src); 3248140751Swpaul dptr = MmGetMdlVirtualAddress(dst); 3249140751Swpaul scnt = MmGetMdlByteCount(src); 3250140751Swpaul dcnt = MmGetMdlByteCount(dst); 3251124541Swpaul 3252124541Swpaul while (soff) { 3253140751Swpaul if (MmGetMdlByteCount(src) > soff) { 3254124541Swpaul sptr += soff; 3255140751Swpaul scnt = MmGetMdlByteCount(src)- soff; 3256124541Swpaul break; 3257124541Swpaul } 3258140751Swpaul soff -= MmGetMdlByteCount(src); 3259140751Swpaul src = src->mdl_next; 3260124541Swpaul if (src == NULL) 3261124541Swpaul return; 3262140751Swpaul sptr = MmGetMdlVirtualAddress(src); 3263124541Swpaul } 3264124541Swpaul 3265124541Swpaul while (doff) { 3266140751Swpaul if (MmGetMdlByteCount(dst) > doff) { 3267124541Swpaul dptr += doff; 3268140751Swpaul dcnt = MmGetMdlByteCount(dst) - doff; 3269124541Swpaul break; 3270124541Swpaul } 3271140751Swpaul doff -= MmGetMdlByteCount(dst); 3272140751Swpaul dst = dst->mdl_next; 3273124541Swpaul if (dst == NULL) 3274124541Swpaul return; 3275140751Swpaul dptr = MmGetMdlVirtualAddress(dst); 3276124541Swpaul } 3277124541Swpaul 3278124541Swpaul resid = reqlen; 3279124541Swpaul copied = 0; 3280124541Swpaul 3281124541Swpaul while(1) { 3282124541Swpaul if (resid < scnt) 3283124541Swpaul len = resid; 3284124541Swpaul else 3285124541Swpaul len = scnt; 3286124541Swpaul if (dcnt < len) 3287124541Swpaul len = dcnt; 3288124541Swpaul 3289124541Swpaul bcopy(sptr, dptr, len); 3290124541Swpaul 3291124541Swpaul copied += len; 3292124541Swpaul resid -= len; 3293124541Swpaul if (resid == 0) 3294124541Swpaul break; 3295124541Swpaul 3296124541Swpaul dcnt -= len; 3297124541Swpaul if (dcnt == 0) { 3298140751Swpaul dst = dst->mdl_next; 3299124541Swpaul if (dst == NULL) 3300124541Swpaul break; 3301140751Swpaul dptr = MmGetMdlVirtualAddress(dst); 3302140751Swpaul dcnt = MmGetMdlByteCount(dst); 3303124541Swpaul } 3304124541Swpaul 3305124541Swpaul scnt -= len; 3306124541Swpaul if (scnt == 0) { 3307140751Swpaul src = src->mdl_next; 3308124541Swpaul if (src == NULL) 3309124541Swpaul break; 3310140751Swpaul sptr = MmGetMdlVirtualAddress(src); 3311140751Swpaul scnt = MmGetMdlByteCount(src); 3312124541Swpaul } 3313124541Swpaul } 3314124541Swpaul 3315124541Swpaul *cpylen = copied; 3316124541Swpaul return; 3317124541Swpaul} 3318124541Swpaul 3319144888Swpaulstatic void 3320140751SwpaulNdisCopyFromPacketToPacketSafe(dpkt, doff, reqlen, spkt, soff, cpylen, prio) 3321124541Swpaul ndis_packet *dpkt; 3322124541Swpaul uint32_t doff; 3323124541Swpaul uint32_t reqlen; 3324124541Swpaul ndis_packet *spkt; 3325124541Swpaul uint32_t soff; 3326124541Swpaul uint32_t *cpylen; 3327124541Swpaul uint32_t prio; 3328124541Swpaul{ 3329140751Swpaul NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen); 3330124541Swpaul return; 3331124541Swpaul} 3332124541Swpaul 3333144888Swpaulstatic ndis_status 3334140751SwpaulNdisMRegisterDevice(handle, devname, symname, majorfuncs, devobj, devhandle) 3335125551Swpaul ndis_handle handle; 3336151207Swpaul unicode_string *devname; 3337151207Swpaul unicode_string *symname; 3338125551Swpaul driver_dispatch *majorfuncs[]; 3339125551Swpaul void **devobj; 3340125551Swpaul ndis_handle *devhandle; 3341125057Swpaul{ 3342146364Swpaul uint32_t status; 3343146364Swpaul device_object *dobj; 3344125551Swpaul 3345146364Swpaul status = IoCreateDevice(handle, 0, devname, 3346146364Swpaul FILE_DEVICE_UNKNOWN, 0, FALSE, &dobj); 3347125551Swpaul 3348146364Swpaul if (status == STATUS_SUCCESS) { 3349146364Swpaul *devobj = dobj; 3350146364Swpaul *devhandle = dobj; 3351146364Swpaul } 3352146364Swpaul 3353146364Swpaul return(status); 3354125057Swpaul} 3355125057Swpaul 3356144888Swpaulstatic ndis_status 3357140751SwpaulNdisMDeregisterDevice(handle) 3358125551Swpaul ndis_handle handle; 3359125057Swpaul{ 3360146364Swpaul IoDeleteDevice(handle); 3361125057Swpaul return(NDIS_STATUS_SUCCESS); 3362125057Swpaul} 3363125057Swpaul 3364144888Swpaulstatic ndis_status 3365140751SwpaulNdisMQueryAdapterInstanceName(name, handle) 3366151207Swpaul unicode_string *name; 3367125551Swpaul ndis_handle handle; 3368125551Swpaul{ 3369125551Swpaul ndis_miniport_block *block; 3370141524Swpaul device_t dev; 3371151207Swpaul ansi_string as; 3372125057Swpaul 3373125551Swpaul block = (ndis_miniport_block *)handle; 3374141524Swpaul dev = block->nmb_physdeviceobj->do_devext; 3375141524Swpaul 3376151207Swpaul RtlInitAnsiString(&as, __DECONST(char *, device_get_nameunit(dev))); 3377151207Swpaul if (RtlAnsiStringToUnicodeString(name, &as, TRUE)) 3378151207Swpaul return(NDIS_STATUS_RESOURCES); 3379125551Swpaul 3380125551Swpaul return(NDIS_STATUS_SUCCESS); 3381125551Swpaul} 3382125551Swpaul 3383144888Swpaulstatic void 3384140751SwpaulNdisMRegisterUnloadHandler(handle, func) 3385125551Swpaul ndis_handle handle; 3386125551Swpaul void *func; 3387125551Swpaul{ 3388125551Swpaul return; 3389125551Swpaul} 3390125551Swpaul 3391144888Swpaulstatic void 3392123474Swpauldummy() 3393123474Swpaul{ 3394123474Swpaul printf ("NDIS dummy called...\n"); 3395123474Swpaul return; 3396123474Swpaul} 3397123474Swpaul 3398144888Swpaul/* 3399144888Swpaul * Note: a couple of entries in this table specify the 3400144888Swpaul * number of arguments as "foo + 1". These are routines 3401144888Swpaul * that accept a 64-bit argument, passed by value. On 3402144888Swpaul * x86, these arguments consume two longwords on the stack, 3403144888Swpaul * so we lie and say there's one additional argument so 3404144888Swpaul * that the wrapping routines will do the right thing. 3405144888Swpaul */ 3406144888Swpaul 3407123474Swpaulimage_patch_table ndis_functbl[] = { 3408144888Swpaul IMPORT_SFUNC(NdisCopyFromPacketToPacket, 6), 3409144888Swpaul IMPORT_SFUNC(NdisCopyFromPacketToPacketSafe, 7), 3410144888Swpaul IMPORT_SFUNC(NdisScheduleWorkItem, 1), 3411144888Swpaul IMPORT_SFUNC(NdisMIndicateStatusComplete, 1), 3412144888Swpaul IMPORT_SFUNC(NdisMIndicateStatus, 4), 3413144888Swpaul IMPORT_SFUNC(NdisSystemProcessorCount, 0), 3414144888Swpaul IMPORT_SFUNC(NdisUnchainBufferAtBack, 2), 3415144888Swpaul IMPORT_SFUNC(NdisGetFirstBufferFromPacket, 5), 3416144888Swpaul IMPORT_SFUNC(NdisGetFirstBufferFromPacketSafe, 6), 3417144888Swpaul IMPORT_SFUNC(NdisGetBufferPhysicalArraySize, 2), 3418144888Swpaul IMPORT_SFUNC(NdisMGetDeviceProperty, 6), 3419144888Swpaul IMPORT_SFUNC(NdisInitAnsiString, 2), 3420144888Swpaul IMPORT_SFUNC(NdisInitUnicodeString, 2), 3421144888Swpaul IMPORT_SFUNC(NdisWriteConfiguration, 4), 3422144888Swpaul IMPORT_SFUNC(NdisAnsiStringToUnicodeString, 2), 3423144888Swpaul IMPORT_SFUNC(NdisTerminateWrapper, 2), 3424144888Swpaul IMPORT_SFUNC(NdisOpenConfigurationKeyByName, 4), 3425144888Swpaul IMPORT_SFUNC(NdisOpenConfigurationKeyByIndex, 5), 3426144888Swpaul IMPORT_SFUNC(NdisMRemoveMiniport, 1), 3427144888Swpaul IMPORT_SFUNC(NdisInitializeString, 2), 3428144888Swpaul IMPORT_SFUNC(NdisFreeString, 1), 3429144888Swpaul IMPORT_SFUNC(NdisGetCurrentSystemTime, 1), 3430144888Swpaul IMPORT_SFUNC(NdisGetSystemUpTime, 1), 3431144888Swpaul IMPORT_SFUNC(NdisMSynchronizeWithInterrupt, 3), 3432144888Swpaul IMPORT_SFUNC(NdisMAllocateSharedMemoryAsync, 4), 3433144888Swpaul IMPORT_SFUNC(NdisInterlockedInsertHeadList, 3), 3434144888Swpaul IMPORT_SFUNC(NdisInterlockedInsertTailList, 3), 3435144888Swpaul IMPORT_SFUNC(NdisInterlockedRemoveHeadList, 2), 3436144888Swpaul IMPORT_SFUNC(NdisInitializeWrapper, 4), 3437144888Swpaul IMPORT_SFUNC(NdisMRegisterMiniport, 3), 3438144888Swpaul IMPORT_SFUNC(NdisAllocateMemoryWithTag, 3), 3439144888Swpaul IMPORT_SFUNC(NdisAllocateMemory, 4 + 1), 3440144888Swpaul IMPORT_SFUNC(NdisMSetAttributesEx, 5), 3441144888Swpaul IMPORT_SFUNC(NdisCloseConfiguration, 1), 3442144888Swpaul IMPORT_SFUNC(NdisReadConfiguration, 5), 3443144888Swpaul IMPORT_SFUNC(NdisOpenConfiguration, 3), 3444144888Swpaul IMPORT_SFUNC(NdisAcquireSpinLock, 1), 3445144888Swpaul IMPORT_SFUNC(NdisReleaseSpinLock, 1), 3446144888Swpaul IMPORT_SFUNC(NdisDprAcquireSpinLock, 1), 3447144888Swpaul IMPORT_SFUNC(NdisDprReleaseSpinLock, 1), 3448144888Swpaul IMPORT_SFUNC(NdisAllocateSpinLock, 1), 3449145895Swpaul IMPORT_SFUNC(NdisInitializeReadWriteLock, 1), 3450145895Swpaul IMPORT_SFUNC(NdisAcquireReadWriteLock, 3), 3451145895Swpaul IMPORT_SFUNC(NdisReleaseReadWriteLock, 2), 3452144888Swpaul IMPORT_SFUNC(NdisFreeSpinLock, 1), 3453144888Swpaul IMPORT_SFUNC(NdisFreeMemory, 3), 3454144888Swpaul IMPORT_SFUNC(NdisReadPciSlotInformation, 5), 3455144888Swpaul IMPORT_SFUNC(NdisWritePciSlotInformation, 5), 3456144888Swpaul IMPORT_SFUNC_MAP(NdisImmediateReadPciSlotInformation, 3457144888Swpaul NdisReadPciSlotInformation, 5), 3458144888Swpaul IMPORT_SFUNC_MAP(NdisImmediateWritePciSlotInformation, 3459144888Swpaul NdisWritePciSlotInformation, 5), 3460144888Swpaul IMPORT_CFUNC(NdisWriteErrorLogEntry, 0), 3461144888Swpaul IMPORT_SFUNC(NdisMStartBufferPhysicalMapping, 6), 3462144888Swpaul IMPORT_SFUNC(NdisMCompleteBufferPhysicalMapping, 3), 3463144888Swpaul IMPORT_SFUNC(NdisMInitializeTimer, 4), 3464144888Swpaul IMPORT_SFUNC(NdisInitializeTimer, 3), 3465144888Swpaul IMPORT_SFUNC(NdisSetTimer, 2), 3466144888Swpaul IMPORT_SFUNC(NdisMCancelTimer, 2), 3467144888Swpaul IMPORT_SFUNC_MAP(NdisCancelTimer, NdisMCancelTimer, 2), 3468144888Swpaul IMPORT_SFUNC(NdisMSetPeriodicTimer, 2), 3469144888Swpaul IMPORT_SFUNC(NdisMQueryAdapterResources, 4), 3470144888Swpaul IMPORT_SFUNC(NdisMRegisterIoPortRange, 4), 3471144888Swpaul IMPORT_SFUNC(NdisMDeregisterIoPortRange, 4), 3472144888Swpaul IMPORT_SFUNC(NdisReadNetworkAddress, 4), 3473144888Swpaul IMPORT_SFUNC(NdisQueryMapRegisterCount, 2), 3474144888Swpaul IMPORT_SFUNC(NdisMAllocateMapRegisters, 5), 3475144888Swpaul IMPORT_SFUNC(NdisMFreeMapRegisters, 1), 3476144888Swpaul IMPORT_SFUNC(NdisMAllocateSharedMemory, 5), 3477144888Swpaul IMPORT_SFUNC(NdisMMapIoSpace, 4 + 1), 3478144888Swpaul IMPORT_SFUNC(NdisMUnmapIoSpace, 3), 3479144888Swpaul IMPORT_SFUNC(NdisGetCacheFillSize, 0), 3480144888Swpaul IMPORT_SFUNC(NdisMGetDmaAlignment, 1), 3481144888Swpaul IMPORT_SFUNC(NdisMInitializeScatterGatherDma, 3), 3482144888Swpaul IMPORT_SFUNC(NdisAllocatePacketPool, 4), 3483144888Swpaul IMPORT_SFUNC(NdisAllocatePacketPoolEx, 5), 3484144888Swpaul IMPORT_SFUNC(NdisAllocatePacket, 3), 3485144888Swpaul IMPORT_SFUNC(NdisFreePacket, 1), 3486144888Swpaul IMPORT_SFUNC(NdisFreePacketPool, 1), 3487144888Swpaul IMPORT_SFUNC_MAP(NdisDprAllocatePacket, NdisAllocatePacket, 3), 3488144888Swpaul IMPORT_SFUNC_MAP(NdisDprFreePacket, NdisFreePacket, 1), 3489144888Swpaul IMPORT_SFUNC(NdisAllocateBufferPool, 3), 3490144888Swpaul IMPORT_SFUNC(NdisAllocateBuffer, 5), 3491144888Swpaul IMPORT_SFUNC(NdisQueryBuffer, 3), 3492144888Swpaul IMPORT_SFUNC(NdisQueryBufferSafe, 4), 3493144888Swpaul IMPORT_SFUNC(NdisBufferVirtualAddress, 1), 3494144888Swpaul IMPORT_SFUNC(NdisBufferVirtualAddressSafe, 2), 3495144888Swpaul IMPORT_SFUNC(NdisBufferLength, 1), 3496144888Swpaul IMPORT_SFUNC(NdisFreeBuffer, 1), 3497144888Swpaul IMPORT_SFUNC(NdisFreeBufferPool, 1), 3498144888Swpaul IMPORT_SFUNC(NdisInterlockedIncrement, 1), 3499144888Swpaul IMPORT_SFUNC(NdisInterlockedDecrement, 1), 3500144888Swpaul IMPORT_SFUNC(NdisInitializeEvent, 1), 3501144888Swpaul IMPORT_SFUNC(NdisSetEvent, 1), 3502144888Swpaul IMPORT_SFUNC(NdisResetEvent, 1), 3503144888Swpaul IMPORT_SFUNC(NdisWaitEvent, 2), 3504144888Swpaul IMPORT_SFUNC(NdisUnicodeStringToAnsiString, 2), 3505144888Swpaul IMPORT_SFUNC(NdisMPciAssignResources, 3), 3506144888Swpaul IMPORT_SFUNC(NdisMFreeSharedMemory, 5 + 1), 3507144888Swpaul IMPORT_SFUNC(NdisMRegisterInterrupt, 7), 3508144888Swpaul IMPORT_SFUNC(NdisMDeregisterInterrupt, 1), 3509144888Swpaul IMPORT_SFUNC(NdisMRegisterAdapterShutdownHandler, 3), 3510144888Swpaul IMPORT_SFUNC(NdisMDeregisterAdapterShutdownHandler, 1), 3511144888Swpaul IMPORT_SFUNC(NDIS_BUFFER_TO_SPAN_PAGES, 1), 3512144888Swpaul IMPORT_SFUNC(NdisQueryBufferOffset, 3), 3513144888Swpaul IMPORT_SFUNC(NdisAdjustBufferLength, 2), 3514144888Swpaul IMPORT_SFUNC(NdisPacketPoolUsage, 1), 3515144888Swpaul IMPORT_SFUNC(NdisMSleep, 1), 3516144888Swpaul IMPORT_SFUNC(NdisUnchainBufferAtFront, 2), 3517144888Swpaul IMPORT_SFUNC(NdisReadPcmciaAttributeMemory, 4), 3518144888Swpaul IMPORT_SFUNC(NdisWritePcmciaAttributeMemory, 4), 3519144888Swpaul IMPORT_SFUNC(NdisOpenFile, 5 + 1), 3520144888Swpaul IMPORT_SFUNC(NdisMapFile, 3), 3521144888Swpaul IMPORT_SFUNC(NdisUnmapFile, 1), 3522144888Swpaul IMPORT_SFUNC(NdisCloseFile, 1), 3523144888Swpaul IMPORT_SFUNC(NdisMRegisterDevice, 6), 3524144888Swpaul IMPORT_SFUNC(NdisMDeregisterDevice, 1), 3525144888Swpaul IMPORT_SFUNC(NdisMQueryAdapterInstanceName, 2), 3526144888Swpaul IMPORT_SFUNC(NdisMRegisterUnloadHandler, 2), 3527144888Swpaul IMPORT_SFUNC(ndis_timercall, 4), 3528145895Swpaul IMPORT_SFUNC(ndis_asyncmem_complete, 2), 3529151207Swpaul IMPORT_SFUNC(ndis_intr, 1), 3530151207Swpaul IMPORT_SFUNC(ndis_intrhand, 4), 3531123474Swpaul 3532123474Swpaul /* 3533123474Swpaul * This last entry is a catch-all for any function we haven't 3534123474Swpaul * implemented yet. The PE import list patching routine will 3535123474Swpaul * use it for any function that doesn't have an explicit match 3536123474Swpaul * in this table. 3537123474Swpaul */ 3538123474Swpaul 3539145895Swpaul { NULL, (FUNC)dummy, NULL, 0, WINDRV_WRAP_STDCALL }, 3540123474Swpaul 3541123474Swpaul /* End of list. */ 3542123474Swpaul 3543141963Swpaul { NULL, NULL, NULL } 3544123474Swpaul}; 3545