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