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