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