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