subr_ndis.c revision 123573
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 123573 2003-12-16 18:56:33Z 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 66#include <net/if.h> 67#include <net/if_arp.h> 68#include <net/ethernet.h> 69#include <net/if_dl.h> 70#include <net/if_media.h> 71 72#include <machine/bus_memio.h> 73#include <machine/bus_pio.h> 74#include <machine/bus.h> 75#include <machine/resource.h> 76 77#include <sys/bus.h> 78#include <sys/rman.h> 79 80#include <machine/stdarg.h> 81 82#include <dev/pci/pcireg.h> 83#include <dev/pci/pcivar.h> 84 85#include <compat/ndis/pe_var.h> 86#include <compat/ndis/resource_var.h> 87#include <compat/ndis/ntoskrnl_var.h> 88#include <compat/ndis/ndis_var.h> 89#include <compat/ndis/cfg_var.h> 90#include <dev/if_ndis/if_ndisvar.h> 91 92#define __stdcall __attribute__((__stdcall__)) 93#define FUNC void(*)(void) 94 95static struct mtx ndis_interlock; 96static int ndis_inits = 0; 97 98__stdcall static void ndis_initwrap(ndis_handle, 99 ndis_driver_object *, void *, void *); 100__stdcall static ndis_status ndis_register_miniport(ndis_handle, 101 ndis_miniport_characteristics *, int); 102__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t); 103__stdcall static ndis_status ndis_malloc(void **, 104 uint32_t, uint32_t, ndis_physaddr); 105__stdcall static void ndis_free(void *, uint32_t, uint32_t); 106__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle, 107 uint32_t, uint32_t, ndis_interface_type); 108__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle); 109__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle, 110 uint32_t, ndis_unicode_string *, ndis_handle *); 111__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle, 112 ndis_unicode_string *, ndis_handle *); 113static ndis_status ndis_encode_parm(ndis_miniport_block *, 114 struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); 115static ndis_status ndis_decode_parm(ndis_miniport_block *, 116 ndis_config_parm *, char *); 117__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **, 118 ndis_handle, ndis_unicode_string *, ndis_parm_type); 119__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle, 120 ndis_unicode_string *, ndis_config_parm *); 121__stdcall static void ndis_close_cfg(ndis_handle); 122__stdcall static void ndis_create_lock(ndis_spin_lock *); 123__stdcall static void ndis_destroy_lock(ndis_spin_lock *); 124__stdcall static void ndis_lock(ndis_spin_lock *); 125__stdcall static void ndis_unlock(ndis_spin_lock *); 126__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t, 127 uint32_t, void *, uint32_t); 128__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t, 129 uint32_t, void *, uint32_t); 130static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...); 131static void ndis_map_cb(void *, bus_dma_segment_t *, int, int); 132__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *, 133 uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); 134__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t); 135__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *, 136 ndis_timer_function, void *); 137static void ndis_timercall(void *); 138__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t); 139static void ndis_tick(void *); 140__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t); 141__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *); 142__stdcall static void ndis_query_resources(ndis_status *, ndis_handle, 143 ndis_resource_list *, uint32_t *); 144__stdcall static ndis_status ndis_register_ioport(void **, 145 ndis_handle, uint32_t, uint32_t); 146__stdcall static void ndis_deregister_ioport(ndis_handle, 147 uint32_t, uint32_t, void *); 148__stdcall static void ndis_read_netaddr(ndis_status *, void **, 149 uint32_t *, ndis_handle); 150__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle, 151 uint32_t, uint8_t, uint32_t, uint32_t); 152__stdcall static void ndis_free_mapreg(ndis_handle); 153static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); 154__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t, 155 uint8_t, void **, ndis_physaddr *); 156__stdcall static void ndis_alloc_sharedmem_async(ndis_handle, 157 uint32_t, uint8_t, void *); 158__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t, 159 uint8_t, void *, ndis_physaddr); 160__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle, 161 ndis_physaddr, uint32_t); 162__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t); 163__stdcall static uint32_t ndis_cachefill(void); 164__stdcall static uint32_t ndis_dma_align(ndis_handle); 165__stdcall static ndis_status ndis_init_sc_dma(ndis_handle, 166 uint8_t, uint32_t); 167__stdcall static void ndis_alloc_packetpool(ndis_status *, 168 ndis_handle *, uint32_t, uint32_t); 169__stdcall static void ndis_ex_alloc_packetpool(ndis_status *, 170 ndis_handle *, uint32_t, uint32_t, uint32_t); 171__stdcall static uint32_t ndis_packetpool_use(ndis_handle); 172__stdcall static void ndis_free_packetpool(ndis_handle); 173__stdcall static void ndis_alloc_packet(ndis_status *, 174 ndis_packet **, ndis_handle); 175__stdcall static void ndis_release_packet(ndis_packet *); 176__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **); 177__stdcall static void ndis_alloc_bufpool(ndis_status *, 178 ndis_handle *, uint32_t); 179__stdcall static void ndis_free_bufpool(ndis_handle); 180__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **, 181 ndis_handle, void *, uint32_t); 182__stdcall static void ndis_release_buf(ndis_buffer *); 183__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *); 184__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **, 185 uint32_t *, uint32_t); 186__stdcall static void ndis_adjust_buflen(ndis_buffer *, int); 187__stdcall static uint32_t ndis_interlock_inc(uint32_t *); 188__stdcall static uint32_t ndis_interlock_dec(uint32_t *); 189__stdcall static void ndis_init_event(ndis_event *); 190__stdcall static void ndis_set_event(ndis_event *); 191__stdcall static void ndis_reset_event(ndis_event *); 192__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t); 193__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *, 194 ndis_unicode_string *); 195__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *, 196 ndis_ansi_string *); 197__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle, 198 uint32_t, ndis_resource_list **); 199__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *, 200 ndis_handle, uint32_t, uint32_t, uint8_t, 201 uint8_t, ndis_interrupt_mode); 202__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *); 203__stdcall static void ndis_register_shutdown(ndis_handle, void *, 204 ndis_shutdown_handler); 205__stdcall static void ndis_deregister_shutdown(ndis_handle); 206__stdcall static uint32_t ndis_numpages(ndis_buffer *); 207__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *); 208__stdcall static void ndis_query_bufoffset(ndis_buffer *, 209 uint32_t *, uint32_t *); 210__stdcall static void ndis_sleep(uint32_t); 211__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle, 212 uint32_t, void *, uint32_t); 213__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle, 214 uint32_t, void *, uint32_t); 215__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *, 216 ndis_list_entry *, ndis_spin_lock *); 217__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *, 218 ndis_spin_lock *); 219__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *, 220 ndis_list_entry *, ndis_spin_lock *); 221__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *, 222 void *, void *); 223__stdcall static void ndis_time(uint64_t *); 224__stdcall static void ndis_init_string(ndis_unicode_string **, char *); 225__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *); 226__stdcall static void ndis_free_string(ndis_unicode_string *); 227__stdcall static ndis_status ndis_remove_miniport(ndis_handle *); 228__stdcall static void ndis_termwrap(ndis_handle, void *); 229__stdcall static void ndis_get_devprop(ndis_handle, void *, void *, 230 void *, cm_resource_list *, cm_resource_list *); 231__stdcall static void dummy(void); 232 233 234int 235ndis_libinit() 236{ 237 if (ndis_inits) { 238 ndis_inits++; 239 return(0); 240 } 241 242 mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK, 243 MTX_DEF | MTX_RECURSE | MTX_DUPOK); 244 245 ndis_inits++; 246 return(0); 247} 248 249int 250ndis_libfini() 251{ 252 if (ndis_inits != 1) { 253 ndis_inits--; 254 return(0); 255 } 256 257 mtx_destroy(&ndis_interlock); 258 ndis_inits--; 259 260 return(0); 261} 262 263/* 264 * NDIS deals with strings in unicode format, so we have 265 * do deal with them that way too. For now, we only handle 266 * conversion between unicode and ASCII since that's all 267 * that device drivers care about. 268 */ 269 270int 271ndis_ascii_to_unicode(ascii, unicode) 272 char *ascii; 273 uint16_t **unicode; 274{ 275 uint16_t *ustr; 276 int i; 277 278 if (*unicode == NULL) 279 *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK); 280 281 if (*unicode == NULL) 282 return(ENOMEM); 283 ustr = *unicode; 284 for (i = 0; i < strlen(ascii); i++) { 285 *ustr = (uint16_t)ascii[i]; 286 ustr++; 287 } 288 289 return(0); 290} 291 292int 293ndis_unicode_to_ascii(unicode, ulen, ascii) 294 uint16_t *unicode; 295 int ulen; 296 char **ascii; 297{ 298 uint8_t *astr; 299 int i; 300 301 if (*ascii == NULL) 302 *ascii = malloc(ulen, M_DEVBUF, M_WAITOK); 303 304 if (*ascii == NULL) 305 return(ENOMEM); 306 astr = *ascii; 307 for (i = 0; i < ulen; i++) { 308 *astr = (uint8_t)unicode[i]; 309 astr++; 310 } 311 312 return(0); 313} 314 315__stdcall static void 316ndis_initwrap(wrapper, drv_obj, path, unused) 317 ndis_handle wrapper; 318 ndis_driver_object *drv_obj; 319 void *path; 320 void *unused; 321{ 322 ndis_driver_object **drv; 323 324 drv = wrapper; 325 *drv = drv_obj; 326 327 return; 328} 329 330__stdcall static void 331ndis_termwrap(handle, syspec) 332 ndis_handle handle; 333 void *syspec; 334{ 335 return; 336} 337 338__stdcall static ndis_status 339ndis_register_miniport(handle, characteristics, len) 340 ndis_handle handle; 341 ndis_miniport_characteristics *characteristics; 342 int len; 343{ 344 ndis_driver_object *drv; 345 346 drv = handle; 347 bcopy((char *)characteristics, (char *)&drv->ndo_chars, 348 sizeof(ndis_miniport_characteristics)); 349 return(NDIS_STATUS_SUCCESS); 350} 351 352__stdcall static ndis_status 353ndis_malloc_withtag(vaddr, len, tag) 354 void **vaddr; 355 uint32_t len; 356 uint32_t tag; 357{ 358 void *mem; 359 360 mem = malloc(len, M_DEVBUF, M_NOWAIT); 361 if (mem == NULL) 362 return(NDIS_STATUS_RESOURCES); 363 *vaddr = mem; 364 365 return(NDIS_STATUS_SUCCESS); 366} 367 368__stdcall static ndis_status 369ndis_malloc(vaddr, len, flags, highaddr) 370 void **vaddr; 371 uint32_t len; 372 uint32_t flags; 373 ndis_physaddr highaddr; 374{ 375 void *mem; 376 377 mem = malloc(len, M_DEVBUF, M_NOWAIT); 378 if (mem == NULL) 379 return(NDIS_STATUS_RESOURCES); 380 *vaddr = mem; 381 382 return(NDIS_STATUS_SUCCESS); 383} 384 385__stdcall static void 386ndis_free(vaddr, len, flags) 387 void *vaddr; 388 uint32_t len; 389 uint32_t flags; 390{ 391 if (len == 0) 392 return; 393 free(vaddr, M_DEVBUF); 394 return; 395} 396 397__stdcall static ndis_status 398ndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs, 399 flags, iftype) 400 ndis_handle adapter_handle; 401 ndis_handle adapter_ctx; 402 uint32_t hangsecs; 403 uint32_t flags; 404 ndis_interface_type iftype; 405{ 406 ndis_miniport_block *block; 407 408 /* 409 * Save the adapter context, we need it for calling 410 * the driver's internal functions. 411 */ 412 block = (ndis_miniport_block *)adapter_handle; 413 block->nmb_miniportadapterctx = adapter_ctx; 414 block->nmb_checkforhangsecs = hangsecs; 415 416 return(NDIS_STATUS_SUCCESS); 417} 418 419__stdcall static void 420ndis_open_cfg(status, cfg, wrapctx) 421 ndis_status *status; 422 ndis_handle *cfg; 423 ndis_handle wrapctx; 424{ 425 *cfg = wrapctx; 426 *status = NDIS_STATUS_SUCCESS; 427 return; 428} 429 430__stdcall static void 431ndis_open_cfgbyname(status, cfg, subkey, subhandle) 432 ndis_status *status; 433 ndis_handle cfg; 434 ndis_unicode_string *subkey; 435 ndis_handle *subhandle; 436{ 437 *subhandle = cfg; 438 *status = NDIS_STATUS_SUCCESS; 439 return; 440} 441 442__stdcall static void 443ndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle) 444 ndis_status *status; 445 ndis_handle cfg; 446 uint32_t idx; 447 ndis_unicode_string *subkey; 448 ndis_handle *subhandle; 449{ 450 *status = NDIS_STATUS_FAILURE; 451 return; 452} 453 454static ndis_status 455ndis_encode_parm(block, oid, type, parm) 456 ndis_miniport_block *block; 457 struct sysctl_oid *oid; 458 ndis_parm_type type; 459 ndis_config_parm **parm; 460{ 461 uint16_t *unicode; 462 ndis_unicode_string *ustr; 463 464 unicode = (uint16_t *)&block->nmb_dummybuf; 465 466 switch(type) { 467 case ndis_parm_string: 468 ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode); 469 (*parm)->ncp_type = ndis_parm_string; 470 ustr = &(*parm)->ncp_parmdata.ncp_stringdata; 471 ustr->nus_len = strlen((char *)oid->oid_arg1) * 2; 472 ustr->nus_buf = unicode; 473 break; 474 case ndis_parm_int: 475 (*parm)->ncp_type = ndis_parm_int; 476 (*parm)->ncp_parmdata.ncp_intdata = 477 strtol((char *)oid->oid_arg1, NULL, 10); 478 break; 479 case ndis_parm_hexint: 480 (*parm)->ncp_type = ndis_parm_hexint; 481 (*parm)->ncp_parmdata.ncp_intdata = 482 strtoul((char *)oid->oid_arg1, NULL, 16); 483 break; 484 default: 485 return(NDIS_STATUS_FAILURE); 486 break; 487 } 488 489 return(NDIS_STATUS_SUCCESS); 490} 491 492__stdcall static void 493ndis_read_cfg(status, parm, cfg, key, type) 494 ndis_status *status; 495 ndis_config_parm **parm; 496 ndis_handle cfg; 497 ndis_unicode_string *key; 498 ndis_parm_type type; 499{ 500 char *keystr = NULL; 501 uint16_t *unicode; 502 ndis_miniport_block *block; 503 struct ndis_softc *sc; 504 struct sysctl_oid *oidp; 505 struct sysctl_ctx_entry *e; 506 507 block = (ndis_miniport_block *)cfg; 508 sc = (struct ndis_softc *)block->nmb_ifp; 509 510 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); 511 512 *parm = &block->nmb_replyparm; 513 bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm)); 514 unicode = (uint16_t *)&block->nmb_dummybuf; 515 516 /* 517 * See if registry key is already in a list of known keys 518 * included with the driver. 519 */ 520 TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 521 oidp = e->entry; 522 if (strcmp(oidp->oid_name, keystr) == 0) { 523 if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { 524 free(keystr, M_DEVBUF); 525 *status = NDIS_STATUS_FAILURE; 526 return; 527 } 528 *status = ndis_encode_parm(block, oidp, type, parm); 529 free(keystr, M_DEVBUF); 530 return; 531 } 532 } 533 534 /* 535 * If the key didn't match, add it to the list of dynamically 536 * created ones. Sometimes, drivers refer to registry keys 537 * that aren't documented in their .INF files. These keys 538 * are supposed to be created by some sort of utility or 539 * control panel snap-in that comes with the driver software. 540 * Sometimes it's useful to be able to manipulate these. 541 * If the driver requests the key in the form of a string, 542 * make its default value an empty string, otherwise default 543 * it to "0". 544 */ 545 546 if (type == ndis_parm_int || type == ndis_parm_hexint) 547 ndis_add_sysctl(sc, keystr, "(dynamic integer key)", 548 "UNSET", CTLFLAG_RW); 549 else 550 ndis_add_sysctl(sc, keystr, "(dynamic string key)", 551 "UNSET", CTLFLAG_RW); 552 553 free(keystr, M_DEVBUF); 554 *status = NDIS_STATUS_FAILURE; 555 return; 556} 557 558static ndis_status 559ndis_decode_parm(block, parm, val) 560 ndis_miniport_block *block; 561 ndis_config_parm *parm; 562 char *val; 563{ 564 uint16_t *unicode; 565 ndis_unicode_string *ustr; 566 567 unicode = (uint16_t *)&block->nmb_dummybuf; 568 569 switch(parm->ncp_type) { 570 case ndis_parm_string: 571 ustr = &parm->ncp_parmdata.ncp_stringdata; 572 ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &val); 573 break; 574 case ndis_parm_int: 575 sprintf(val, "%ul", parm->ncp_parmdata.ncp_intdata); 576 break; 577 case ndis_parm_hexint: 578 sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata); 579 break; 580 default: 581 return(NDIS_STATUS_FAILURE); 582 break; 583 } 584 return(NDIS_STATUS_SUCCESS); 585} 586 587__stdcall static void 588ndis_write_cfg(status, cfg, key, parm) 589 ndis_status *status; 590 ndis_handle cfg; 591 ndis_unicode_string *key; 592 ndis_config_parm *parm; 593{ 594 char *keystr = NULL; 595 ndis_miniport_block *block; 596 struct ndis_softc *sc; 597 struct sysctl_oid *oidp; 598 struct sysctl_ctx_entry *e; 599 char val[256]; 600 601 block = (ndis_miniport_block *)cfg; 602 sc = (struct ndis_softc *)block->nmb_ifp; 603 604 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); 605 606 /* Decode the parameter into a string. */ 607 *status = ndis_decode_parm(block, parm, val); 608 if (*status != NDIS_STATUS_SUCCESS) { 609 free(keystr, M_DEVBUF); 610 return; 611 } 612 613 /* See if the key already exists. */ 614 615 TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 616 oidp = e->entry; 617 if (strcmp(oidp->oid_name, keystr) == 0) { 618 /* Found it, set the value. */ 619 strcpy((char *)oidp->oid_arg1, val); 620 free(keystr, M_DEVBUF); 621 return; 622 } 623 } 624 625 /* Not found, add a new key with the specified value. */ 626 ndis_add_sysctl(sc, keystr, "(dynamically set key)", 627 val, CTLFLAG_RW); 628 629 free(keystr, M_DEVBUF); 630 *status = NDIS_STATUS_SUCCESS; 631 return; 632} 633 634__stdcall static void 635ndis_close_cfg(cfg) 636 ndis_handle cfg; 637{ 638 return; 639} 640 641__stdcall static void 642ndis_create_lock(lock) 643 ndis_spin_lock *lock; 644{ 645 struct mtx *mtx; 646 647 mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO); 648 if (mtx == NULL) 649 return; 650 mtx_init(mtx, "ndislock", MTX_NETWORK_LOCK, 651 MTX_DEF | MTX_RECURSE | MTX_DUPOK); 652 lock->nsl_spinlock = (ndis_kspin_lock)mtx; 653 654 return; 655} 656 657__stdcall static void 658ndis_destroy_lock(lock) 659 ndis_spin_lock *lock; 660{ 661 struct mtx *ndis_mtx; 662 663 ndis_mtx = (struct mtx *)lock->nsl_spinlock; 664 mtx_destroy(ndis_mtx); 665 free(ndis_mtx, M_DEVBUF); 666 667 return; 668} 669 670__stdcall static void 671ndis_lock(lock) 672 ndis_spin_lock *lock; 673{ 674 if (lock == NULL) 675 return; 676 mtx_lock((struct mtx *)lock->nsl_spinlock); 677 678 return; 679} 680 681__stdcall static void 682ndis_unlock(lock) 683 ndis_spin_lock *lock; 684{ 685 if (lock == NULL) 686 return; 687 mtx_unlock((struct mtx *)lock->nsl_spinlock); 688 689 return; 690} 691 692__stdcall static uint32_t 693ndis_read_pci(adapter, slot, offset, buf, len) 694 ndis_handle adapter; 695 uint32_t slot; 696 uint32_t offset; 697 void *buf; 698 uint32_t len; 699{ 700 ndis_miniport_block *block; 701 int i; 702 char *dest; 703 704 block = (ndis_miniport_block *)adapter; 705 dest = buf; 706 if (block == NULL || block->nmb_dev == NULL) 707 return(0); 708 709 for (i = 0; i < len; i++) 710 dest[i] = pci_read_config(block->nmb_dev, i + offset, 1); 711 712 return(len); 713} 714 715__stdcall static uint32_t 716ndis_write_pci(adapter, slot, offset, buf, len) 717 ndis_handle adapter; 718 uint32_t slot; 719 uint32_t offset; 720 void *buf; 721 uint32_t len; 722{ 723 ndis_miniport_block *block; 724 int i; 725 char *dest; 726 727 block = (ndis_miniport_block *)adapter; 728 dest = buf; 729 730 if (block == NULL || block->nmb_dev == NULL) 731 return(0); 732 733 for (i = 0; i < len; i++) 734 pci_write_config(block->nmb_dev, i + offset, dest[i], 1); 735 736 return(len); 737} 738 739/* 740 * The errorlog routine uses a variable argument list, so we 741 * have to declare it this way. 742 */ 743static void 744ndis_syslog(ndis_handle adapter, ndis_error_code code, 745 uint32_t numerrors, ...) 746{ 747 ndis_miniport_block *block; 748 va_list ap; 749 int i; 750 751 block = (ndis_miniport_block *)adapter; 752 753 printf ("NDIS ERROR: %x\n", code); 754 printf ("NDIS NUMERRORS: %x\n", numerrors); 755 756 va_start(ap, numerrors); 757 for (i = 0; i < numerrors; i++) 758 printf ("argptr: %p\n", va_arg(ap, void *)); 759 va_end(ap); 760 761 return; 762} 763 764static void 765ndis_map_cb(arg, segs, nseg, error) 766 void *arg; 767 bus_dma_segment_t *segs; 768 int nseg; 769 int error; 770{ 771 struct ndis_map_arg *ctx; 772 int i; 773 774 if (error) 775 return; 776 777 ctx = arg; 778 779 for (i = 0; i < nseg; i++) { 780 ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr; 781 ctx->nma_fraglist[i].npu_len = segs[i].ds_len; 782 } 783 784 ctx->nma_cnt = nseg; 785 786 return; 787} 788 789__stdcall static void 790ndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize) 791 ndis_handle adapter; 792 ndis_buffer *buf; 793 uint32_t mapreg; 794 uint8_t writedev; 795 ndis_paddr_unit *addrarray; 796 uint32_t *arraysize; 797{ 798 ndis_miniport_block *block; 799 struct ndis_softc *sc; 800 struct ndis_map_arg nma; 801 bus_dmamap_t map; 802 int error; 803 804 if (adapter == NULL) 805 return; 806 807 block = (ndis_miniport_block *)adapter; 808 sc = (struct ndis_softc *)(block->nmb_ifp); 809 810 if (mapreg > sc->ndis_mmapcnt) 811 return; 812 813 map = sc->ndis_mmaps[mapreg]; 814 nma.nma_fraglist = addrarray; 815 816 error = bus_dmamap_load(sc->ndis_mtag, map, 817 buf->nb_mappedsystemva, buf->nb_bytecount, ndis_map_cb, 818 (void *)&nma, BUS_DMA_NOWAIT); 819 820 if (error) 821 return; 822 823 bus_dmamap_sync(sc->ndis_mtag, map, 824 writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); 825 826 *arraysize = nma.nma_cnt; 827 828 return; 829} 830 831__stdcall static void 832ndis_vtophys_unload(adapter, buf, mapreg) 833 ndis_handle adapter; 834 ndis_buffer *buf; 835 uint32_t mapreg; 836{ 837 ndis_miniport_block *block; 838 struct ndis_softc *sc; 839 bus_dmamap_t map; 840 841 if (adapter == NULL) 842 return; 843 844 block = (ndis_miniport_block *)adapter; 845 sc = (struct ndis_softc *)(block->nmb_ifp); 846 847 if (mapreg > sc->ndis_mmapcnt) 848 return; 849 850 map = sc->ndis_mmaps[mapreg]; 851 852 bus_dmamap_sync(sc->ndis_mtag, map, 853 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 854 855 bus_dmamap_unload(sc->ndis_mtag, map); 856 857 return; 858} 859 860__stdcall static void 861ndis_create_timer(timer, handle, func, ctx) 862 ndis_miniport_timer *timer; 863 ndis_handle *handle; 864 ndis_timer_function func; 865 void *ctx; 866{ 867 struct callout_handle *ch; 868 869 ch = (struct callout_handle *)&timer->nmt_dpc; 870 callout_handle_init(ch); 871 timer->nmt_timerfunc = func; 872 timer->nmt_timerctx = ctx; 873 874 return; 875} 876 877/* 878 * The driver's timer callout is __stdcall function, so we need this 879 * intermediate step. 880 */ 881 882static void 883ndis_timercall(arg) 884 void *arg; 885{ 886 ndis_miniport_timer *timer; 887 __stdcall ndis_timer_function timerfunc; 888 889 timer = arg; 890 891 timerfunc = timer->nmt_timerfunc; 892 timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 893 894 return; 895} 896 897/* 898 * Windows specifies timeouts in milliseconds. We specify timeouts 899 * in hz. Trying to compute a tenth of a second based on hz is tricky. 900 * so we approximate. Note that we abuse the dpc portion of the 901 * miniport timer structure to hold the UNIX callout handle. 902 */ 903__stdcall static void 904ndis_set_timer(timer, msecs) 905 ndis_miniport_timer *timer; 906 uint32_t msecs; 907{ 908 struct callout_handle *ch; 909 struct timeval tv; 910 911 tv.tv_sec = 0; 912 tv.tv_usec = msecs * 1000; 913 914 ch = (struct callout_handle *)&timer->nmt_dpc; 915 timer->nmt_dpc.nk_sysarg2 = ndis_timercall; 916 *ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, (void *)timer, 917 tvtohz(&tv)); 918 919 return; 920} 921 922static void 923ndis_tick(arg) 924 void *arg; 925{ 926 ndis_miniport_timer *timer; 927 struct callout_handle *ch; 928 __stdcall ndis_timer_function timerfunc; 929 struct timeval tv; 930 931 timer = arg; 932 933 timerfunc = timer->nmt_timerfunc; 934 timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 935 936 /* Automatically reload timer. */ 937 938 tv.tv_sec = 0; 939 tv.tv_usec = timer->nmt_ktimer.nk_period * 1000; 940 ch = (struct callout_handle *)&timer->nmt_dpc; 941 timer->nmt_dpc.nk_sysarg2 = ndis_tick; 942 *ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer, 943 tvtohz(&tv)); 944 945 return; 946} 947 948__stdcall static void 949ndis_set_periodic_timer(timer, msecs) 950 ndis_miniport_timer *timer; 951 uint32_t msecs; 952{ 953 struct callout_handle *ch; 954 struct timeval tv; 955 956 tv.tv_sec = 0; 957 tv.tv_usec = msecs * 1000; 958 959 timer->nmt_ktimer.nk_period = msecs; 960 ch = (struct callout_handle *)&timer->nmt_dpc; 961 timer->nmt_dpc.nk_sysarg2 = ndis_tick; 962 *ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer, 963 tvtohz(&tv)); 964 965 return; 966} 967 968__stdcall static void 969ndis_cancel_timer(timer, cancelled) 970 ndis_miniport_timer *timer; 971 uint8_t *cancelled; 972{ 973 struct callout_handle *ch; 974 975 ch = (struct callout_handle *)&timer->nmt_dpc; 976 untimeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer, *ch); 977 978 return; 979} 980 981__stdcall static void 982ndis_query_resources(status, adapter, list, buflen) 983 ndis_status *status; 984 ndis_handle adapter; 985 ndis_resource_list *list; 986 uint32_t *buflen; 987{ 988 ndis_miniport_block *block; 989 struct ndis_softc *sc; 990 991 block = (ndis_miniport_block *)adapter; 992 sc = (struct ndis_softc *)block->nmb_ifp; 993 994 *buflen = sizeof(ndis_resource_list) + 995 (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); 996 997 bcopy((char *)block->nmb_rlist, (char *)list, *buflen); 998 *status = NDIS_STATUS_SUCCESS; 999 return; 1000} 1001 1002__stdcall static ndis_status 1003ndis_register_ioport(offset, adapter, port, numports) 1004 void **offset; 1005 ndis_handle adapter; 1006 uint32_t port; 1007 uint32_t numports; 1008{ 1009 struct ndis_miniport_block *block; 1010 struct ndis_softc *sc; 1011 1012 if (adapter == NULL) 1013 return(NDIS_STATUS_FAILURE); 1014 1015 block = (ndis_miniport_block *)adapter; 1016 sc = (struct ndis_softc *)(block->nmb_ifp); 1017 1018 if (sc->ndis_res_io == NULL) 1019 return(NDIS_STATUS_FAILURE); 1020 1021 if (rman_get_size(sc->ndis_res_io) != numports) 1022 return(NDIS_STATUS_INVALID_LENGTH); 1023 1024 *offset = (void *)rman_get_start(sc->ndis_res_io); 1025 1026 return(NDIS_STATUS_SUCCESS); 1027} 1028 1029__stdcall static void 1030ndis_deregister_ioport(adapter, port, numports, offset) 1031 ndis_handle adapter; 1032 uint32_t port; 1033 uint32_t numports; 1034 void *offset; 1035{ 1036 return; 1037} 1038 1039__stdcall static void 1040ndis_read_netaddr(status, addr, addrlen, adapter) 1041 ndis_status *status; 1042 void **addr; 1043 uint32_t *addrlen; 1044 ndis_handle adapter; 1045{ 1046 struct ndis_softc *sc; 1047 ndis_miniport_block *block; 1048 uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; 1049 1050 block = (ndis_miniport_block *)adapter; 1051 sc = (struct ndis_softc *)block->nmb_ifp; 1052 1053 if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0) 1054 *status = NDIS_STATUS_FAILURE; 1055 else { 1056 *addr = sc->arpcom.ac_enaddr; 1057 *addrlen = ETHER_ADDR_LEN; 1058 *status = NDIS_STATUS_SUCCESS; 1059 } 1060 1061 return; 1062} 1063 1064__stdcall static ndis_status 1065ndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap) 1066 ndis_handle adapter; 1067 uint32_t dmachannel; 1068 uint8_t dmasize; 1069 uint32_t physmapneeded; 1070 uint32_t maxmap; 1071{ 1072 struct ndis_softc *sc; 1073 ndis_miniport_block *block; 1074 int error, i, nseg = NDIS_MAXSEG; 1075 1076 block = (ndis_miniport_block *)adapter; 1077 sc = (struct ndis_softc *)block->nmb_ifp; 1078 1079 sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, 1080 M_DEVBUF, M_NOWAIT|M_ZERO); 1081 1082 if (sc->ndis_mmaps == NULL) 1083 return(NDIS_STATUS_RESOURCES); 1084 1085 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1086 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1087 NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, 1088 NULL, NULL, &sc->ndis_mtag); 1089 1090 if (error) { 1091 free(sc->ndis_mmaps, M_DEVBUF); 1092 return(NDIS_STATUS_RESOURCES); 1093 } 1094 1095 for (i = 0; i < physmapneeded; i++) 1096 bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); 1097 1098 sc->ndis_mmapcnt = physmapneeded; 1099 1100 return(NDIS_STATUS_SUCCESS); 1101} 1102 1103__stdcall static void 1104ndis_free_mapreg(adapter) 1105 ndis_handle adapter; 1106{ 1107 struct ndis_softc *sc; 1108 ndis_miniport_block *block; 1109 int i; 1110 1111 block = (ndis_miniport_block *)adapter; 1112 sc = (struct ndis_softc *)block->nmb_ifp; 1113 1114 for (i = 0; i < sc->ndis_mmapcnt; i++) 1115 bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); 1116 1117 free(sc->ndis_mmaps, M_DEVBUF); 1118 1119 bus_dma_tag_destroy(sc->ndis_mtag); 1120 1121 return; 1122} 1123 1124static void 1125ndis_mapshared_cb(arg, segs, nseg, error) 1126 void *arg; 1127 bus_dma_segment_t *segs; 1128 int nseg; 1129 int error; 1130{ 1131 ndis_physaddr *p; 1132 1133 if (error || nseg > 1) 1134 return; 1135 1136 p = arg; 1137 1138 p->np_quad = segs[0].ds_addr; 1139 1140 return; 1141} 1142 1143/* 1144 * This maps to bus_dmamem_alloc(). 1145 */ 1146__stdcall static void 1147ndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr) 1148 ndis_handle adapter; 1149 uint32_t len; 1150 uint8_t cached; 1151 void **vaddr; 1152 ndis_physaddr *paddr; 1153{ 1154 ndis_miniport_block *block; 1155 struct ndis_softc *sc; 1156 struct ndis_shmem *sh; 1157 int error; 1158 1159 if (adapter == NULL) 1160 return; 1161 1162 block = (ndis_miniport_block *)adapter; 1163 sc = (struct ndis_softc *)(block->nmb_ifp); 1164 1165 sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); 1166 if (sh == NULL) 1167 return; 1168 1169 error = bus_dma_tag_create(sc->ndis_parent_tag, 64, 1170 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1171 NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, 1172 &sh->ndis_stag); 1173 1174 if (error) { 1175 free(sh, M_DEVBUF); 1176 return; 1177 } 1178 1179 error = bus_dmamem_alloc(sh->ndis_stag, vaddr, 1180 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); 1181 1182 if (error) { 1183 bus_dma_tag_destroy(sh->ndis_stag); 1184 free(sh, M_DEVBUF); 1185 return; 1186 } 1187 1188 error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, 1189 len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); 1190 1191 if (error) { 1192 bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); 1193 bus_dma_tag_destroy(sh->ndis_stag); 1194 free(sh, M_DEVBUF); 1195 return; 1196 } 1197 1198 sh->ndis_saddr = *vaddr; 1199 sh->ndis_next = sc->ndis_shlist; 1200 sc->ndis_shlist = sh; 1201 1202 return; 1203} 1204 1205__stdcall static void 1206ndis_alloc_sharedmem_async(adapter, len, cached, ctx) 1207 ndis_handle adapter; 1208 uint32_t len; 1209 uint8_t cached; 1210 void *ctx; 1211{ 1212 ndis_miniport_block *block; 1213 struct ndis_softc *sc; 1214 void *vaddr; 1215 ndis_physaddr paddr; 1216 __stdcall ndis_allocdone_handler donefunc; 1217 1218 if (adapter == NULL) 1219 return; 1220 1221 block = (ndis_miniport_block *)adapter; 1222 sc = (struct ndis_softc *)(block->nmb_ifp); 1223 donefunc = sc->ndis_chars.nmc_allocate_complete_func; 1224 1225 ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr); 1226 donefunc(adapter, vaddr, &paddr, len, ctx); 1227 1228 return; 1229} 1230 1231__stdcall static void 1232ndis_free_sharedmem(adapter, len, cached, vaddr, paddr) 1233 ndis_handle adapter; 1234 uint32_t len; 1235 uint8_t cached; 1236 void *vaddr; 1237 ndis_physaddr paddr; 1238{ 1239 ndis_miniport_block *block; 1240 struct ndis_softc *sc; 1241 struct ndis_shmem *sh, *prev; 1242 1243 if (vaddr == NULL || adapter == NULL) 1244 return; 1245 1246 block = (ndis_miniport_block *)adapter; 1247 sc = (struct ndis_softc *)(block->nmb_ifp); 1248 sh = prev = sc->ndis_shlist; 1249 1250 while (sh) { 1251 if (sh->ndis_saddr == vaddr) 1252 break; 1253 prev = sh; 1254 sh = sh->ndis_next; 1255 } 1256 1257 bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); 1258 bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap); 1259 bus_dma_tag_destroy(sh->ndis_stag); 1260 1261 if (sh == sc->ndis_shlist) 1262 sc->ndis_shlist = sh->ndis_next; 1263 else 1264 prev->ndis_next = sh->ndis_next; 1265 1266 free(sh, M_DEVBUF); 1267 1268 return; 1269} 1270 1271__stdcall static ndis_status 1272ndis_map_iospace(vaddr, adapter, paddr, len) 1273 void **vaddr; 1274 ndis_handle adapter; 1275 ndis_physaddr paddr; 1276 uint32_t len; 1277{ 1278 ndis_miniport_block *block; 1279 struct ndis_softc *sc; 1280 1281 if (adapter == NULL) 1282 return(NDIS_STATUS_FAILURE); 1283 1284 block = (ndis_miniport_block *)adapter; 1285 sc = (struct ndis_softc *)(block->nmb_ifp); 1286 1287 if (sc->ndis_res_mem == NULL) 1288 return(NDIS_STATUS_FAILURE); 1289 1290 *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem); 1291 1292 return(NDIS_STATUS_SUCCESS); 1293} 1294 1295__stdcall static void 1296ndis_unmap_iospace(adapter, vaddr, len) 1297 ndis_handle adapter; 1298 void *vaddr; 1299 uint32_t len; 1300{ 1301 return; 1302} 1303 1304__stdcall static uint32_t 1305ndis_cachefill(void) 1306{ 1307 return(128); 1308} 1309 1310__stdcall static uint32_t 1311ndis_dma_align(handle) 1312 ndis_handle handle; 1313{ 1314 return(128); 1315} 1316 1317/* 1318 * NDIS has two methods for dealing with NICs that support DMA. 1319 * One is to just pass packets to the driver and let it call 1320 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet 1321 * all by itself, and the other is to let the NDIS library handle the 1322 * buffer mapping internally, and hand the driver an already populated 1323 * scatter/gather fragment list. If the driver calls 1324 * NdisMInitializeScatterGatherDma(), it wants to use the latter 1325 * method. 1326 */ 1327 1328__stdcall static ndis_status 1329ndis_init_sc_dma(adapter, is64, maxphysmap) 1330 ndis_handle adapter; 1331 uint8_t is64; 1332 uint32_t maxphysmap; 1333{ 1334 struct ndis_softc *sc; 1335 ndis_miniport_block *block; 1336 int error; 1337 1338 if (adapter == NULL) 1339 return(NDIS_STATUS_FAILURE); 1340 block = (ndis_miniport_block *)adapter; 1341 sc = (struct ndis_softc *)block->nmb_ifp; 1342 1343 /* Don't do this twice. */ 1344 if (sc->ndis_sc == 1) 1345 return(NDIS_STATUS_SUCCESS); 1346 1347 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1348 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1349 MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, 1350 NULL, NULL, &sc->ndis_ttag); 1351 1352 sc->ndis_sc = 1; 1353 1354 return(NDIS_STATUS_SUCCESS); 1355} 1356 1357__stdcall static void 1358ndis_alloc_packetpool(status, pool, descnum, protrsvdlen) 1359 ndis_status *status; 1360 ndis_handle *pool; 1361 uint32_t descnum; 1362 uint32_t protrsvdlen; 1363{ 1364 ndis_packet *cur; 1365 int i; 1366 1367 *pool = malloc(sizeof(ndis_packet) * (descnum + 1), 1368 M_DEVBUF, M_NOWAIT|M_ZERO); 1369 1370 if (pool == NULL) { 1371 *status = NDIS_STATUS_RESOURCES; 1372 return; 1373 } 1374 1375 cur = (ndis_packet *)*pool; 1376 cur->np_private.npp_flags = 0x1; /* mark the head of the list */ 1377 for (i = 0; i < descnum; i++) { 1378 cur->np_private.npp_head = (ndis_handle)(cur + 1); 1379 cur++; 1380 } 1381 1382 *status = NDIS_STATUS_SUCCESS; 1383 return; 1384} 1385 1386__stdcall static void 1387ndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen) 1388 ndis_status *status; 1389 ndis_handle *pool; 1390 uint32_t descnum; 1391 uint32_t oflowdescnum; 1392 uint32_t protrsvdlen; 1393{ 1394 return(ndis_alloc_packetpool(status, pool, 1395 descnum + oflowdescnum, protrsvdlen)); 1396} 1397 1398__stdcall static uint32_t 1399ndis_packetpool_use(pool) 1400 ndis_handle pool; 1401{ 1402 ndis_packet *head; 1403 1404 head = (ndis_packet *)pool; 1405 1406 return(head->np_private.npp_count); 1407} 1408 1409__stdcall static void 1410ndis_free_packetpool(pool) 1411 ndis_handle pool; 1412{ 1413 free(pool, M_DEVBUF); 1414 return; 1415} 1416 1417__stdcall static void 1418ndis_alloc_packet(status, packet, pool) 1419 ndis_status *status; 1420 ndis_packet **packet; 1421 ndis_handle pool; 1422{ 1423 ndis_packet *head, *pkt; 1424 1425 head = (ndis_packet *)pool; 1426 1427 if (head->np_private.npp_flags != 0x1) { 1428 *status = NDIS_STATUS_FAILURE; 1429 return; 1430 } 1431 1432 pkt = (ndis_packet *)head->np_private.npp_head; 1433 1434 if (pkt == NULL) { 1435 *status = NDIS_STATUS_RESOURCES; 1436 return; 1437 } 1438 1439 head->np_private.npp_head = pkt->np_private.npp_head; 1440 1441 pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL; 1442 /* Save pointer to the pool. */ 1443 pkt->np_private.npp_pool = head; 1444 1445 /* Set the oob offset pointer. Lots of things expect this. */ 1446 pkt->np_private.npp_packetooboffset = 1447 offsetof(ndis_packet, np_oob); 1448 1449 *packet = pkt; 1450 1451 head->np_private.npp_count++; 1452 *status = NDIS_STATUS_SUCCESS; 1453 return; 1454} 1455 1456__stdcall static void 1457ndis_release_packet(packet) 1458 ndis_packet *packet; 1459{ 1460 ndis_packet *head; 1461 1462 if (packet == NULL || packet->np_private.npp_pool == NULL) 1463 return; 1464 1465 head = packet->np_private.npp_pool; 1466 if (head->np_private.npp_flags != 0x1) 1467 return; 1468 1469 packet->np_private.npp_head = head->np_private.npp_head; 1470 head->np_private.npp_head = (ndis_buffer *)packet; 1471 head->np_private.npp_count--; 1472 1473 return; 1474} 1475 1476__stdcall static void 1477ndis_unchain_headbuf(packet, buf) 1478 ndis_packet *packet; 1479 ndis_buffer **buf; 1480{ 1481 ndis_packet_private *priv; 1482 1483 if (packet == NULL || buf == NULL) 1484 return; 1485 1486 priv = &packet->np_private; 1487 1488 priv->npp_validcounts = FALSE; 1489 1490 if (priv->npp_head == priv->npp_tail) { 1491 *buf = priv->npp_head; 1492 priv->npp_head = priv->npp_tail = NULL; 1493 } else { 1494 *buf = priv->npp_head; 1495 priv->npp_head = (*buf)->nb_next; 1496 } 1497 1498 return; 1499} 1500 1501/* 1502 * The NDIS "buffer" manipulation functions are somewhat misnamed. 1503 * They don't really allocate buffers: they allocate buffer mappings. 1504 * The idea is you reserve a chunk of DMA-able memory using 1505 * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer() 1506 * to obtain the virtual address of the DMA-able region. 1507 * ndis_alloc_bufpool() is analagous to bus_dma_tag_create(). 1508 */ 1509 1510__stdcall static void 1511ndis_alloc_bufpool(status, pool, descnum) 1512 ndis_status *status; 1513 ndis_handle *pool; 1514 uint32_t descnum; 1515{ 1516 ndis_buffer *cur; 1517 int i; 1518 1519 *pool = malloc(sizeof(ndis_buffer) * (descnum + 1), 1520 M_DEVBUF, M_NOWAIT|M_ZERO); 1521 1522 if (pool == NULL) { 1523 *status = NDIS_STATUS_RESOURCES; 1524 return; 1525 } 1526 1527 cur = (ndis_buffer *)*pool; 1528 cur->nb_flags = 0x1; /* mark the head of the list */ 1529 for (i = 0; i < descnum; i++) { 1530 cur->nb_next = cur + 1; 1531 cur++; 1532 } 1533 1534 *status = NDIS_STATUS_SUCCESS; 1535 return; 1536} 1537 1538__stdcall static void 1539ndis_free_bufpool(pool) 1540 ndis_handle pool; 1541{ 1542 free(pool, M_DEVBUF); 1543 return; 1544} 1545 1546/* 1547 * This maps to a bus_dmamap_create() and bus_dmamap_load(). 1548 */ 1549__stdcall static void 1550ndis_alloc_buf(status, buffer, pool, vaddr, len) 1551 ndis_status *status; 1552 ndis_buffer **buffer; 1553 ndis_handle pool; 1554 void *vaddr; 1555 uint32_t len; 1556{ 1557 ndis_buffer *head, *buf; 1558 1559 head = (ndis_buffer *)pool; 1560 if (head->nb_flags != 0x1) { 1561 *status = NDIS_STATUS_FAILURE; 1562 return; 1563 } 1564 1565 buf = head->nb_next; 1566 1567 if (buf == NULL) { 1568 *status = NDIS_STATUS_RESOURCES; 1569 return; 1570 } 1571 1572 head->nb_next = buf->nb_next; 1573 1574 /* Save pointer to the pool. */ 1575 buf->nb_process = head; 1576 1577 buf->nb_mappedsystemva = vaddr; 1578 buf->nb_size = len; 1579 buf->nb_next = NULL; 1580 1581 *buffer = buf; 1582 1583 *status = NDIS_STATUS_SUCCESS; 1584 return; 1585} 1586 1587__stdcall static void 1588ndis_release_buf(buf) 1589 ndis_buffer *buf; 1590{ 1591 ndis_buffer *head; 1592 1593 if (buf == NULL || buf->nb_process == NULL) 1594 return; 1595 1596 head = buf->nb_process; 1597 1598 if (head->nb_flags != 0x1) 1599 return; 1600 1601 buf->nb_next = head->nb_next; 1602 head->nb_next = buf; 1603 1604 return; 1605} 1606 1607/* Get the virtual address and length of a buffer */ 1608 1609__stdcall static void 1610ndis_query_buf(buf, vaddr, len) 1611 ndis_buffer *buf; 1612 void **vaddr; 1613 uint32_t *len; 1614{ 1615 *vaddr = buf->nb_mappedsystemva; 1616 *len = buf->nb_bytecount; 1617 1618 return; 1619} 1620 1621/* Same as above -- we don't care about the priority. */ 1622 1623__stdcall static void 1624ndis_query_buf_safe(buf, vaddr, len, prio) 1625 ndis_buffer *buf; 1626 void **vaddr; 1627 uint32_t *len; 1628 uint32_t prio; 1629{ 1630 *vaddr = buf->nb_mappedsystemva; 1631 *len = buf->nb_bytecount; 1632 1633 return; 1634} 1635 1636__stdcall static void 1637ndis_adjust_buflen(buf, len) 1638 ndis_buffer *buf; 1639 int len; 1640{ 1641 if (len > buf->nb_size) 1642 return; 1643 buf->nb_bytecount = len; 1644 1645 return; 1646} 1647 1648__stdcall static uint32_t 1649ndis_interlock_inc(addend) 1650 uint32_t *addend; 1651{ 1652 mtx_lock(&ndis_interlock); 1653 *addend++; 1654 mtx_unlock(&ndis_interlock); 1655 return(*addend); 1656} 1657 1658__stdcall static uint32_t 1659ndis_interlock_dec(addend) 1660 uint32_t *addend; 1661{ 1662 mtx_lock(&ndis_interlock); 1663 *addend--; 1664 mtx_unlock(&ndis_interlock); 1665 return(*addend); 1666} 1667 1668__stdcall static void 1669ndis_init_event(event) 1670 ndis_event *event; 1671{ 1672 event->ne_event.nk_header.dh_sigstate = FALSE; 1673 return; 1674} 1675 1676__stdcall static void 1677ndis_set_event(event) 1678 ndis_event *event; 1679{ 1680 event->ne_event.nk_header.dh_sigstate = TRUE; 1681 wakeup(event); 1682 return; 1683} 1684 1685__stdcall static void 1686ndis_reset_event(event) 1687 ndis_event *event; 1688{ 1689 event->ne_event.nk_header.dh_sigstate = FALSE; 1690 wakeup(event); 1691 return; 1692} 1693 1694__stdcall static uint8_t 1695ndis_wait_event(event, msecs) 1696 ndis_event *event; 1697 uint32_t msecs; 1698{ 1699 int error; 1700 struct timeval tv; 1701 1702 if (event->ne_event.nk_header.dh_sigstate == TRUE) 1703 return(TRUE); 1704 1705 tv.tv_sec = 0; 1706 tv.tv_usec = msecs * 1000; 1707 1708 error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 1709 1710 return(event->ne_event.nk_header.dh_sigstate); 1711} 1712 1713__stdcall static ndis_status 1714ndis_unicode2ansi(dstr, sstr) 1715 ndis_ansi_string *dstr; 1716 ndis_unicode_string *sstr; 1717{ 1718 if (dstr == NULL || sstr == NULL) 1719 return(NDIS_STATUS_FAILURE); 1720 if (ndis_unicode_to_ascii(sstr->nus_buf, 1721 sstr->nus_len, &dstr->nas_buf)) 1722 return(NDIS_STATUS_FAILURE); 1723 dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf); 1724 return (NDIS_STATUS_SUCCESS); 1725} 1726 1727__stdcall static ndis_status 1728ndis_ansi2unicode(dstr, sstr) 1729 ndis_unicode_string *dstr; 1730 ndis_ansi_string *sstr; 1731{ 1732 char *str; 1733 if (dstr == NULL || sstr == NULL) 1734 return(NDIS_STATUS_FAILURE); 1735 str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT); 1736 if (str == NULL) 1737 return(NDIS_STATUS_FAILURE); 1738 strncpy(str, sstr->nas_buf, sstr->nas_len); 1739 *(str + sstr->nas_len) = '\0'; 1740 if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) { 1741 free(str, M_DEVBUF); 1742 return(NDIS_STATUS_FAILURE); 1743 } 1744 dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2; 1745 free(str, M_DEVBUF); 1746 return (NDIS_STATUS_SUCCESS); 1747} 1748 1749__stdcall static ndis_status 1750ndis_assign_pcirsrc(adapter, slot, list) 1751 ndis_handle adapter; 1752 uint32_t slot; 1753 ndis_resource_list **list; 1754{ 1755 ndis_miniport_block *block; 1756 1757 if (adapter == NULL || list == NULL) 1758 return (NDIS_STATUS_FAILURE); 1759 1760 block = (ndis_miniport_block *)adapter; 1761 *list = block->nmb_rlist; 1762 1763 printf ("assign PCI resources...\n"); 1764 return (NDIS_STATUS_SUCCESS); 1765} 1766 1767__stdcall static ndis_status 1768ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode) 1769 ndis_miniport_interrupt *intr; 1770 ndis_handle adapter; 1771 uint32_t ivec; 1772 uint32_t ilevel; 1773 uint8_t reqisr; 1774 uint8_t shared; 1775 ndis_interrupt_mode imode; 1776{ 1777 1778 return(NDIS_STATUS_SUCCESS); 1779} 1780 1781__stdcall static void 1782ndis_deregister_intr(intr) 1783 ndis_miniport_interrupt *intr; 1784{ 1785 return; 1786} 1787 1788__stdcall static void 1789ndis_register_shutdown(adapter, shutdownctx, shutdownfunc) 1790 ndis_handle adapter; 1791 void *shutdownctx; 1792 ndis_shutdown_handler shutdownfunc; 1793{ 1794 ndis_miniport_block *block; 1795 ndis_miniport_characteristics *chars; 1796 struct ndis_softc *sc; 1797 1798 if (adapter == NULL) 1799 return; 1800 1801 block = (ndis_miniport_block *)adapter; 1802 sc = (struct ndis_softc *)block->nmb_ifp; 1803 chars = &sc->ndis_chars; 1804 1805 chars->nmc_shutdown_handler = shutdownfunc; 1806 chars->nmc_rsvd0 = shutdownctx; 1807 1808 return; 1809} 1810 1811__stdcall static void 1812ndis_deregister_shutdown(adapter) 1813 ndis_handle adapter; 1814{ 1815 ndis_miniport_block *block; 1816 ndis_miniport_characteristics *chars; 1817 struct ndis_softc *sc; 1818 1819 if (adapter == NULL) 1820 return; 1821 1822 block = (ndis_miniport_block *)adapter; 1823 sc = (struct ndis_softc *)block->nmb_ifp; 1824 chars = &sc->ndis_chars; 1825 1826 chars->nmc_shutdown_handler = NULL; 1827 chars->nmc_rsvd0 = NULL; 1828 1829 return; 1830} 1831 1832__stdcall static uint32_t 1833ndis_numpages(buf) 1834 ndis_buffer *buf; 1835{ 1836 if (buf->nb_bytecount == 0) 1837 return(1); 1838 return(SPAN_PAGES(buf->nb_mappedsystemva, buf->nb_bytecount)); 1839} 1840 1841__stdcall static void 1842ndis_buf_physpages(buf, pages) 1843 ndis_buffer *buf; 1844 uint32_t *pages; 1845{ 1846 *pages = ndis_numpages(buf); 1847 return; 1848} 1849 1850__stdcall static void 1851ndis_query_bufoffset(buf, off, len) 1852 ndis_buffer *buf; 1853 uint32_t *off; 1854 uint32_t *len; 1855{ 1856 *off = (uint32_t)buf->nb_mappedsystemva & (PAGE_SIZE - 1); 1857 *len = buf->nb_bytecount; 1858 1859 return; 1860} 1861 1862__stdcall static void 1863ndis_sleep(usecs) 1864 uint32_t usecs; 1865{ 1866 struct timeval tv; 1867 uint32_t dummy; 1868 1869 tv.tv_sec = 0; 1870 tv.tv_usec = usecs; 1871 1872 tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 1873 return; 1874} 1875 1876__stdcall static uint32_t 1877ndis_read_pccard_amem(handle, offset, buf, len) 1878 ndis_handle handle; 1879 uint32_t offset; 1880 void *buf; 1881 uint32_t len; 1882{ 1883 struct ndis_softc *sc; 1884 ndis_miniport_block *block; 1885 bus_space_handle_t bh; 1886 bus_space_tag_t bt; 1887 char *dest; 1888 int i; 1889 1890 if (handle == NULL) 1891 return(0); 1892 1893 block = (ndis_miniport_block *)handle; 1894 sc = (struct ndis_softc *)block->nmb_ifp; 1895 dest = buf; 1896 1897 bh = rman_get_bushandle(sc->ndis_res_am); 1898 bt = rman_get_bustag(sc->ndis_res_am); 1899 1900 for (i = 0; i < len; i++) 1901 dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2)); 1902 1903 return(i); 1904} 1905 1906__stdcall static uint32_t 1907ndis_write_pccard_amem(handle, offset, buf, len) 1908 ndis_handle handle; 1909 uint32_t offset; 1910 void *buf; 1911 uint32_t len; 1912{ 1913 struct ndis_softc *sc; 1914 ndis_miniport_block *block; 1915 bus_space_handle_t bh; 1916 bus_space_tag_t bt; 1917 char *src; 1918 int i; 1919 1920 if (handle == NULL) 1921 return(0); 1922 1923 block = (ndis_miniport_block *)handle; 1924 sc = (struct ndis_softc *)block->nmb_ifp; 1925 src = buf; 1926 1927 bh = rman_get_bushandle(sc->ndis_res_am); 1928 bt = rman_get_bustag(sc->ndis_res_am); 1929 1930 for (i = 0; i < len; i++) 1931 bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]); 1932 1933 return(i); 1934} 1935 1936__stdcall static ndis_list_entry * 1937ndis_insert_head(head, entry, lock) 1938 ndis_list_entry *head; 1939 ndis_list_entry *entry; 1940 ndis_spin_lock *lock; 1941{ 1942 ndis_list_entry *flink; 1943 1944 mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 1945 flink = head->nle_flink; 1946 entry->nle_flink = flink; 1947 entry->nle_blink = head; 1948 flink->nle_blink = entry; 1949 head->nle_flink = entry; 1950 mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 1951 1952 return(flink); 1953} 1954 1955__stdcall static ndis_list_entry * 1956ndis_remove_head(head, lock) 1957 ndis_list_entry *head; 1958 ndis_spin_lock *lock; 1959{ 1960 ndis_list_entry *flink; 1961 ndis_list_entry *entry; 1962 1963 mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 1964 entry = head->nle_flink; 1965 flink = entry->nle_flink; 1966 head->nle_flink = flink; 1967 flink->nle_blink = head; 1968 mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 1969 1970 return(entry); 1971} 1972 1973__stdcall static ndis_list_entry * 1974ndis_insert_tail(head, entry, lock) 1975 ndis_list_entry *head; 1976 ndis_list_entry *entry; 1977 ndis_spin_lock *lock; 1978{ 1979 ndis_list_entry *blink; 1980 1981 mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 1982 blink = head->nle_blink; 1983 entry->nle_flink = head; 1984 entry->nle_blink = blink; 1985 blink->nle_flink = entry; 1986 head->nle_blink = entry; 1987 mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 1988 1989 return(blink); 1990} 1991 1992__stdcall static uint8_t 1993ndis_sync_with_intr(intr, syncfunc, syncctx) 1994 ndis_miniport_interrupt *intr; 1995 void *syncfunc; 1996 void *syncctx; 1997{ 1998 __stdcall uint8_t (*sync)(void *); 1999 2000 if (syncfunc == NULL || syncctx == NULL) 2001 return(0); 2002 2003 sync = syncfunc; 2004 return(sync(syncctx)); 2005} 2006 2007/* 2008 * Return the number of 100 nanosecond intervals since 2009 * January 1, 1601. (?!?!) 2010 */ 2011__stdcall static void 2012ndis_time(tval) 2013 uint64_t *tval; 2014{ 2015 struct timespec ts; 2016 nanotime(&ts); 2017 *tval = (ts.tv_nsec / 100) + (ts.tv_nsec * 10000000); 2018 *tval += 11644473600; 2019 return; 2020} 2021 2022__stdcall static void 2023ndis_init_string(dst, src) 2024 ndis_unicode_string **dst; 2025 char *src; 2026{ 2027 ndis_unicode_string *u; 2028 2029 u = malloc(sizeof(ndis_unicode_string), M_DEVBUF, M_NOWAIT); 2030 if (u == NULL) 2031 return; 2032 u->nus_buf = NULL; 2033 if (ndis_ascii_to_unicode(src, &u->nus_buf)) { 2034 free(u, M_DEVBUF); 2035 return; 2036 } 2037 u->nus_len = u->nus_maxlen = strlen(src) * 2; 2038 return; 2039} 2040 2041__stdcall static void 2042ndis_free_string(str) 2043 ndis_unicode_string *str; 2044{ 2045 if (str == NULL) 2046 return; 2047 if (str->nus_buf != NULL) 2048 free(str->nus_buf, M_DEVBUF); 2049 free(str, M_DEVBUF); 2050 return; 2051} 2052 2053__stdcall static ndis_status 2054ndis_remove_miniport(adapter) 2055 ndis_handle *adapter; 2056{ 2057 return(NDIS_STATUS_SUCCESS); 2058} 2059 2060__stdcall static void 2061ndis_init_ansi_string(dst, src) 2062 ndis_ansi_string *dst; 2063 char *src; 2064{ 2065 ndis_ansi_string *a; 2066 2067 a = dst; 2068 if (a == NULL) 2069 return; 2070 if (src == NULL) { 2071 a->nas_len = a->nas_maxlen = 0; 2072 a->nas_buf = NULL; 2073 } else { 2074 a->nas_buf = src; 2075 a->nas_len = a->nas_maxlen = strlen(src); 2076 } 2077 2078 return; 2079} 2080 2081__stdcall static void ndis_get_devprop(adapter, phydevobj, 2082 funcdevobj, nextdevobj, resources, transresources) 2083 ndis_handle adapter; 2084 void *phydevobj; 2085 void *funcdevobj; 2086 void *nextdevobj; 2087 cm_resource_list *resources; 2088 cm_resource_list *transresources; 2089{ 2090 return; 2091} 2092 2093__stdcall static void 2094dummy() 2095{ 2096 printf ("NDIS dummy called...\n"); 2097 return; 2098} 2099 2100image_patch_table ndis_functbl[] = { 2101 { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages }, 2102 { "NdisMGetDeviceProperty", (FUNC)ndis_get_devprop }, 2103 { "NdisInitAnsiString", (FUNC)ndis_init_ansi_string }, 2104 { "NdisWriteConfiguration", (FUNC)ndis_write_cfg }, 2105 { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode }, 2106 { "NdisTerminateWrapper", (FUNC)ndis_termwrap }, 2107 { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname }, 2108 { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx }, 2109 { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport }, 2110 { "NdisInitializeString", (FUNC)ndis_init_string }, 2111 { "NdisFreeString", (FUNC)ndis_free_string }, 2112 { "NdisGetCurrentSystemTime", (FUNC)ndis_time }, 2113 { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr }, 2114 { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async }, 2115 { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head }, 2116 { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail }, 2117 { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head }, 2118 { "NdisInitializeWrapper", (FUNC)ndis_initwrap }, 2119 { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport }, 2120 { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag }, 2121 { "NdisAllocateMemory", (FUNC)ndis_malloc }, 2122 { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex }, 2123 { "NdisCloseConfiguration", (FUNC)ndis_close_cfg }, 2124 { "NdisReadConfiguration", (FUNC)ndis_read_cfg }, 2125 { "NdisOpenConfiguration", (FUNC)ndis_open_cfg }, 2126 { "NdisReleaseSpinLock", (FUNC)ndis_unlock }, 2127 { "NdisDprAcquireSpinLock", (FUNC)ndis_lock }, 2128 { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock }, 2129 { "NdisAcquireSpinLock", (FUNC)ndis_lock }, 2130 { "NdisAllocateSpinLock", (FUNC)ndis_create_lock }, 2131 { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock }, 2132 { "NdisFreeMemory", (FUNC)ndis_free }, 2133 { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci }, 2134 { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci }, 2135 { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog }, 2136 { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load }, 2137 { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload }, 2138 { "NdisMInitializeTimer", (FUNC)ndis_create_timer }, 2139 { "NdisSetTimer", (FUNC)ndis_set_timer }, 2140 { "NdisMCancelTimer", (FUNC)ndis_cancel_timer }, 2141 { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer }, 2142 { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources }, 2143 { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport }, 2144 { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport }, 2145 { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr }, 2146 { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg }, 2147 { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg }, 2148 { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem }, 2149 { "NdisMMapIoSpace", (FUNC)ndis_map_iospace }, 2150 { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace }, 2151 { "NdisGetCacheFillSize", (FUNC)ndis_cachefill }, 2152 { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align }, 2153 { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma }, 2154 { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool }, 2155 { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool }, 2156 { "NdisAllocatePacket", (FUNC)ndis_alloc_packet }, 2157 { "NdisFreePacket", (FUNC)ndis_release_packet }, 2158 { "NdisFreePacketPool", (FUNC)ndis_free_packetpool }, 2159 { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool }, 2160 { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf }, 2161 { "NdisQueryBuffer", (FUNC)ndis_query_buf }, 2162 { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe }, 2163 { "NdisFreeBuffer", (FUNC)ndis_release_buf }, 2164 { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool }, 2165 { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc }, 2166 { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec }, 2167 { "NdisInitializeEvent", (FUNC)ndis_init_event }, 2168 { "NdisSetEvent", (FUNC)ndis_set_event }, 2169 { "NdisResetEvent", (FUNC)ndis_reset_event }, 2170 { "NdisWaitEvent", (FUNC)ndis_wait_event }, 2171 { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi }, 2172 { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc }, 2173 { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem }, 2174 { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr }, 2175 { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr }, 2176 { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown }, 2177 { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown }, 2178 { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages }, 2179 { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset }, 2180 { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen }, 2181 { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use }, 2182 { "NdisMSleep", (FUNC)ndis_sleep }, 2183 { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf }, 2184 { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem }, 2185 { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem }, 2186 2187 /* 2188 * This last entry is a catch-all for any function we haven't 2189 * implemented yet. The PE import list patching routine will 2190 * use it for any function that doesn't have an explicit match 2191 * in this table. 2192 */ 2193 2194 { NULL, (FUNC)dummy }, 2195 2196 /* End of list. */ 2197 2198 { NULL, NULL }, 2199}; 2200 2201