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