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