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