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