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