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