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