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