subr_ndis.c revision 124173
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 124173 2004-01-06 18:06:54Z 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/taskqueue.h> 68 69#include <net/if.h> 70#include <net/if_arp.h> 71#include <net/ethernet.h> 72#include <net/if_dl.h> 73#include <net/if_media.h> 74 75#include <machine/bus_memio.h> 76#include <machine/bus_pio.h> 77#include <machine/bus.h> 78#include <machine/resource.h> 79 80#include <sys/bus.h> 81#include <sys/rman.h> 82 83#include <machine/stdarg.h> 84 85#include <net80211/ieee80211_var.h> 86#include <net80211/ieee80211_ioctl.h> 87 88#include <dev/pci/pcireg.h> 89#include <dev/pci/pcivar.h> 90 91#include <compat/ndis/pe_var.h> 92#include <compat/ndis/resource_var.h> 93#include <compat/ndis/ntoskrnl_var.h> 94#include <compat/ndis/ndis_var.h> 95#include <compat/ndis/cfg_var.h> 96#include <dev/if_ndis/if_ndisvar.h> 97 98#define __stdcall __attribute__((__stdcall__)) 99#define FUNC void(*)(void) 100 101static struct mtx ndis_interlock; 102 103__stdcall static void ndis_initwrap(ndis_handle, 104 ndis_driver_object *, void *, void *); 105__stdcall static ndis_status ndis_register_miniport(ndis_handle, 106 ndis_miniport_characteristics *, int); 107__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t); 108__stdcall static ndis_status ndis_malloc(void **, 109 uint32_t, uint32_t, ndis_physaddr); 110__stdcall static void ndis_free(void *, uint32_t, uint32_t); 111__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle, 112 uint32_t, uint32_t, ndis_interface_type); 113__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle); 114__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle, 115 uint32_t, ndis_unicode_string *, ndis_handle *); 116__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle, 117 ndis_unicode_string *, ndis_handle *); 118static ndis_status ndis_encode_parm(ndis_miniport_block *, 119 struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); 120static ndis_status ndis_decode_parm(ndis_miniport_block *, 121 ndis_config_parm *, char *); 122__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **, 123 ndis_handle, ndis_unicode_string *, ndis_parm_type); 124__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle, 125 ndis_unicode_string *, ndis_config_parm *); 126__stdcall static void ndis_close_cfg(ndis_handle); 127__stdcall static void ndis_create_lock(ndis_spin_lock *); 128__stdcall static void ndis_destroy_lock(ndis_spin_lock *); 129__stdcall static void ndis_lock(ndis_spin_lock *); 130__stdcall static void ndis_unlock(ndis_spin_lock *); 131__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t, 132 uint32_t, void *, uint32_t); 133__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t, 134 uint32_t, void *, uint32_t); 135static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...); 136static void ndis_map_cb(void *, bus_dma_segment_t *, int, int); 137__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *, 138 uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); 139__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t); 140__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *, 141 ndis_timer_function, void *); 142static void ndis_timercall(void *); 143__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t); 144static void ndis_tick(void *); 145__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t); 146__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *); 147__stdcall static void ndis_query_resources(ndis_status *, ndis_handle, 148 ndis_resource_list *, uint32_t *); 149__stdcall static ndis_status ndis_register_ioport(void **, 150 ndis_handle, uint32_t, uint32_t); 151__stdcall static void ndis_deregister_ioport(ndis_handle, 152 uint32_t, uint32_t, void *); 153__stdcall static void ndis_read_netaddr(ndis_status *, void **, 154 uint32_t *, ndis_handle); 155__stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *); 156__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle, 157 uint32_t, uint8_t, uint32_t, uint32_t); 158__stdcall static void ndis_free_mapreg(ndis_handle); 159static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); 160__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t, 161 uint8_t, void **, ndis_physaddr *); 162__stdcall static void ndis_alloc_sharedmem_async(ndis_handle, 163 uint32_t, uint8_t, void *); 164__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t, 165 uint8_t, void *, ndis_physaddr); 166__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle, 167 ndis_physaddr, uint32_t); 168__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t); 169__stdcall static uint32_t ndis_cachefill(void); 170__stdcall static uint32_t ndis_dma_align(ndis_handle); 171__stdcall static ndis_status ndis_init_sc_dma(ndis_handle, 172 uint8_t, uint32_t); 173__stdcall static void ndis_alloc_packetpool(ndis_status *, 174 ndis_handle *, uint32_t, uint32_t); 175__stdcall static void ndis_ex_alloc_packetpool(ndis_status *, 176 ndis_handle *, uint32_t, uint32_t, uint32_t); 177__stdcall static uint32_t ndis_packetpool_use(ndis_handle); 178__stdcall static void ndis_free_packetpool(ndis_handle); 179__stdcall static void ndis_alloc_packet(ndis_status *, 180 ndis_packet **, ndis_handle); 181__stdcall static void ndis_release_packet(ndis_packet *); 182__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **); 183__stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **); 184__stdcall static void ndis_alloc_bufpool(ndis_status *, 185 ndis_handle *, uint32_t); 186__stdcall static void ndis_free_bufpool(ndis_handle); 187__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **, 188 ndis_handle, void *, uint32_t); 189__stdcall static void ndis_release_buf(ndis_buffer *); 190__stdcall static uint32_t ndis_buflen(ndis_buffer *); 191__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *); 192__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **, 193 uint32_t *, uint32_t); 194__stdcall static void ndis_adjust_buflen(ndis_buffer *, int); 195__stdcall static uint32_t ndis_interlock_inc(uint32_t *); 196__stdcall static uint32_t ndis_interlock_dec(uint32_t *); 197__stdcall static void ndis_init_event(ndis_event *); 198__stdcall static void ndis_set_event(ndis_event *); 199__stdcall static void ndis_reset_event(ndis_event *); 200__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t); 201__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *, 202 ndis_unicode_string *); 203__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *, 204 ndis_ansi_string *); 205__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle, 206 uint32_t, ndis_resource_list **); 207__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *, 208 ndis_handle, uint32_t, uint32_t, uint8_t, 209 uint8_t, ndis_interrupt_mode); 210__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *); 211__stdcall static void ndis_register_shutdown(ndis_handle, void *, 212 ndis_shutdown_handler); 213__stdcall static void ndis_deregister_shutdown(ndis_handle); 214__stdcall static uint32_t ndis_numpages(ndis_buffer *); 215__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *); 216__stdcall static void ndis_query_bufoffset(ndis_buffer *, 217 uint32_t *, uint32_t *); 218__stdcall static void ndis_sleep(uint32_t); 219__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle, 220 uint32_t, void *, uint32_t); 221__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle, 222 uint32_t, void *, uint32_t); 223__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *, 224 ndis_list_entry *, ndis_spin_lock *); 225__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *, 226 ndis_spin_lock *); 227__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *, 228 ndis_list_entry *, ndis_spin_lock *); 229__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *, 230 void *, void *); 231__stdcall static void ndis_time(uint64_t *); 232__stdcall static void ndis_uptime(uint32_t *); 233__stdcall static void ndis_init_string(ndis_unicode_string *, char *); 234__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *); 235__stdcall static void ndis_init_unicode_string(ndis_unicode_string *, 236 uint16_t *); 237__stdcall static void ndis_free_string(ndis_unicode_string *); 238__stdcall static ndis_status ndis_remove_miniport(ndis_handle *); 239__stdcall static void ndis_termwrap(ndis_handle, void *); 240__stdcall static void ndis_get_devprop(ndis_handle, void *, void *, 241 void *, cm_resource_list *, cm_resource_list *); 242__stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **, 243 void **, uint32_t *, uint32_t *); 244__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **, 245 void **, uint32_t *, uint32_t *, uint32_t); 246__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *, 247 ndis_unicode_string *, ndis_physaddr); 248__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle); 249__stdcall static void ndis_unmap_file(ndis_handle); 250__stdcall static void ndis_close_file(ndis_handle); 251__stdcall static u_int8_t ndis_cpu_cnt(void); 252__stdcall static void ndis_ind_statusdone(ndis_handle); 253__stdcall static void ndis_ind_status(ndis_handle, ndis_status, 254 void *, uint32_t); 255static void ndis_workfunc(void *, int); 256__stdcall static ndis_status ndis_sched_workitem(ndis_work_item *); 257__stdcall static void dummy(void); 258 259/* 260 * Some really old drivers do not properly check the return value 261 * from NdisAllocatePacket() and NdisAllocateBuffer() and will 262 * sometimes allocate few more buffers/packets that they originally 263 * requested when they created the pool. To prevent this from being 264 * a problem, we allocate a few extra buffers/packets beyond what 265 * the driver asks for. This #define controls how many. 266 */ 267#define NDIS_POOL_EXTRA 16 268 269int 270ndis_libinit() 271{ 272 mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK, 273 MTX_DEF | MTX_RECURSE | MTX_DUPOK); 274 275 return(0); 276} 277 278int 279ndis_libfini() 280{ 281 mtx_destroy(&ndis_interlock); 282 return(0); 283} 284 285/* 286 * NDIS deals with strings in unicode format, so we have 287 * do deal with them that way too. For now, we only handle 288 * conversion between unicode and ASCII since that's all 289 * that device drivers care about. 290 */ 291 292int 293ndis_ascii_to_unicode(ascii, unicode) 294 char *ascii; 295 uint16_t **unicode; 296{ 297 uint16_t *ustr; 298 int i; 299 300 if (*unicode == NULL) 301 *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK); 302 303 if (*unicode == NULL) 304 return(ENOMEM); 305 ustr = *unicode; 306 for (i = 0; i < strlen(ascii); i++) { 307 *ustr = (uint16_t)ascii[i]; 308 ustr++; 309 } 310 311 return(0); 312} 313 314int 315ndis_unicode_to_ascii(unicode, ulen, ascii) 316 uint16_t *unicode; 317 int ulen; 318 char **ascii; 319{ 320 uint8_t *astr; 321 int i; 322 323 if (*ascii == NULL) 324 *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO); 325 if (*ascii == NULL) 326 return(ENOMEM); 327 astr = *ascii; 328 for (i = 0; i < ulen / 2; i++) { 329 *astr = (uint8_t)unicode[i]; 330 astr++; 331 } 332 333 return(0); 334} 335 336__stdcall static void 337ndis_initwrap(wrapper, drv_obj, path, unused) 338 ndis_handle wrapper; 339 ndis_driver_object *drv_obj; 340 void *path; 341 void *unused; 342{ 343 ndis_driver_object **drv; 344 345 drv = wrapper; 346 *drv = drv_obj; 347 348 return; 349} 350 351__stdcall static void 352ndis_termwrap(handle, syspec) 353 ndis_handle handle; 354 void *syspec; 355{ 356 return; 357} 358 359__stdcall static ndis_status 360ndis_register_miniport(handle, characteristics, len) 361 ndis_handle handle; 362 ndis_miniport_characteristics *characteristics; 363 int len; 364{ 365 ndis_driver_object *drv; 366 367 drv = handle; 368 bcopy((char *)characteristics, (char *)&drv->ndo_chars, 369 sizeof(ndis_miniport_characteristics)); 370 return(NDIS_STATUS_SUCCESS); 371} 372 373__stdcall static ndis_status 374ndis_malloc_withtag(vaddr, len, tag) 375 void **vaddr; 376 uint32_t len; 377 uint32_t tag; 378{ 379 void *mem; 380 381 mem = malloc(len, M_DEVBUF, M_NOWAIT); 382 if (mem == NULL) 383 return(NDIS_STATUS_RESOURCES); 384 *vaddr = mem; 385 386 return(NDIS_STATUS_SUCCESS); 387} 388 389__stdcall static ndis_status 390ndis_malloc(vaddr, len, flags, highaddr) 391 void **vaddr; 392 uint32_t len; 393 uint32_t flags; 394 ndis_physaddr highaddr; 395{ 396 void *mem; 397 398 mem = malloc(len, M_DEVBUF, M_NOWAIT); 399 if (mem == NULL) 400 return(NDIS_STATUS_RESOURCES); 401 *vaddr = mem; 402 403 return(NDIS_STATUS_SUCCESS); 404} 405 406__stdcall static void 407ndis_free(vaddr, len, flags) 408 void *vaddr; 409 uint32_t len; 410 uint32_t flags; 411{ 412 if (len == 0) 413 return; 414 free(vaddr, M_DEVBUF); 415 return; 416} 417 418__stdcall static ndis_status 419ndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs, 420 flags, iftype) 421 ndis_handle adapter_handle; 422 ndis_handle adapter_ctx; 423 uint32_t hangsecs; 424 uint32_t flags; 425 ndis_interface_type iftype; 426{ 427 ndis_miniport_block *block; 428 429 /* 430 * Save the adapter context, we need it for calling 431 * the driver's internal functions. 432 */ 433 block = (ndis_miniport_block *)adapter_handle; 434 block->nmb_miniportadapterctx = adapter_ctx; 435 block->nmb_checkforhangsecs = hangsecs; 436 437 return(NDIS_STATUS_SUCCESS); 438} 439 440__stdcall static void 441ndis_open_cfg(status, cfg, wrapctx) 442 ndis_status *status; 443 ndis_handle *cfg; 444 ndis_handle wrapctx; 445{ 446 *cfg = wrapctx; 447 *status = NDIS_STATUS_SUCCESS; 448 return; 449} 450 451__stdcall static void 452ndis_open_cfgbyname(status, cfg, subkey, subhandle) 453 ndis_status *status; 454 ndis_handle cfg; 455 ndis_unicode_string *subkey; 456 ndis_handle *subhandle; 457{ 458 *subhandle = cfg; 459 *status = NDIS_STATUS_SUCCESS; 460 return; 461} 462 463__stdcall static void 464ndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle) 465 ndis_status *status; 466 ndis_handle cfg; 467 uint32_t idx; 468 ndis_unicode_string *subkey; 469 ndis_handle *subhandle; 470{ 471 *status = NDIS_STATUS_FAILURE; 472 return; 473} 474 475static ndis_status 476ndis_encode_parm(block, oid, type, parm) 477 ndis_miniport_block *block; 478 struct sysctl_oid *oid; 479 ndis_parm_type type; 480 ndis_config_parm **parm; 481{ 482 uint16_t *unicode; 483 ndis_unicode_string *ustr; 484 485 unicode = (uint16_t *)&block->nmb_dummybuf; 486 487 switch(type) { 488 case ndis_parm_string: 489 ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode); 490 (*parm)->ncp_type = ndis_parm_string; 491 ustr = &(*parm)->ncp_parmdata.ncp_stringdata; 492 ustr->nus_len = strlen((char *)oid->oid_arg1) * 2; 493 ustr->nus_buf = unicode; 494 break; 495 case ndis_parm_int: 496 (*parm)->ncp_type = ndis_parm_int; 497 (*parm)->ncp_parmdata.ncp_intdata = 498 strtol((char *)oid->oid_arg1, NULL, 10); 499 break; 500 case ndis_parm_hexint: 501 (*parm)->ncp_type = ndis_parm_hexint; 502 (*parm)->ncp_parmdata.ncp_intdata = 503 strtoul((char *)oid->oid_arg1, NULL, 16); 504 break; 505 default: 506 return(NDIS_STATUS_FAILURE); 507 break; 508 } 509 510 return(NDIS_STATUS_SUCCESS); 511} 512 513__stdcall static void 514ndis_read_cfg(status, parm, cfg, key, type) 515 ndis_status *status; 516 ndis_config_parm **parm; 517 ndis_handle cfg; 518 ndis_unicode_string *key; 519 ndis_parm_type type; 520{ 521 char *keystr = NULL; 522 uint16_t *unicode; 523 ndis_miniport_block *block; 524 struct ndis_softc *sc; 525 struct sysctl_oid *oidp; 526 struct sysctl_ctx_entry *e; 527 528 block = (ndis_miniport_block *)cfg; 529 sc = (struct ndis_softc *)block->nmb_ifp; 530 531 if (key->nus_len == 0 || key->nus_buf == NULL) { 532 *status = NDIS_STATUS_FAILURE; 533 return; 534 } 535 536 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); 537 538 *parm = &block->nmb_replyparm; 539 bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm)); 540 unicode = (uint16_t *)&block->nmb_dummybuf; 541 542 /* 543 * See if registry key is already in a list of known keys 544 * included with the driver. 545 */ 546 TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 547 oidp = e->entry; 548 if (strcmp(oidp->oid_name, keystr) == 0) { 549 if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { 550 free(keystr, M_DEVBUF); 551 *status = NDIS_STATUS_FAILURE; 552 return; 553 } 554 *status = ndis_encode_parm(block, oidp, type, parm); 555 free(keystr, M_DEVBUF); 556 return; 557 } 558 } 559 560 /* 561 * If the key didn't match, add it to the list of dynamically 562 * created ones. Sometimes, drivers refer to registry keys 563 * that aren't documented in their .INF files. These keys 564 * are supposed to be created by some sort of utility or 565 * control panel snap-in that comes with the driver software. 566 * Sometimes it's useful to be able to manipulate these. 567 * If the driver requests the key in the form of a string, 568 * make its default value an empty string, otherwise default 569 * it to "0". 570 */ 571 572 if (type == ndis_parm_int || type == ndis_parm_hexint) 573 ndis_add_sysctl(sc, keystr, "(dynamic integer key)", 574 "UNSET", CTLFLAG_RW); 575 else 576 ndis_add_sysctl(sc, keystr, "(dynamic string key)", 577 "UNSET", CTLFLAG_RW); 578 579 free(keystr, M_DEVBUF); 580 *status = NDIS_STATUS_FAILURE; 581 return; 582} 583 584static ndis_status 585ndis_decode_parm(block, parm, val) 586 ndis_miniport_block *block; 587 ndis_config_parm *parm; 588 char *val; 589{ 590 uint16_t *unicode; 591 ndis_unicode_string *ustr; 592 593 unicode = (uint16_t *)&block->nmb_dummybuf; 594 595 switch(parm->ncp_type) { 596 case ndis_parm_string: 597 ustr = &parm->ncp_parmdata.ncp_stringdata; 598 ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &val); 599 break; 600 case ndis_parm_int: 601 sprintf(val, "%ul", parm->ncp_parmdata.ncp_intdata); 602 break; 603 case ndis_parm_hexint: 604 sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata); 605 break; 606 default: 607 return(NDIS_STATUS_FAILURE); 608 break; 609 } 610 return(NDIS_STATUS_SUCCESS); 611} 612 613__stdcall static void 614ndis_write_cfg(status, cfg, key, parm) 615 ndis_status *status; 616 ndis_handle cfg; 617 ndis_unicode_string *key; 618 ndis_config_parm *parm; 619{ 620 char *keystr = NULL; 621 ndis_miniport_block *block; 622 struct ndis_softc *sc; 623 struct sysctl_oid *oidp; 624 struct sysctl_ctx_entry *e; 625 char val[256]; 626 627 block = (ndis_miniport_block *)cfg; 628 sc = (struct ndis_softc *)block->nmb_ifp; 629 630 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); 631 632 /* Decode the parameter into a string. */ 633 *status = ndis_decode_parm(block, parm, val); 634 if (*status != NDIS_STATUS_SUCCESS) { 635 free(keystr, M_DEVBUF); 636 return; 637 } 638 639 /* See if the key already exists. */ 640 641 TAILQ_FOREACH(e, &sc->ndis_ctx, link) { 642 oidp = e->entry; 643 if (strcmp(oidp->oid_name, keystr) == 0) { 644 /* Found it, set the value. */ 645 strcpy((char *)oidp->oid_arg1, val); 646 free(keystr, M_DEVBUF); 647 return; 648 } 649 } 650 651 /* Not found, add a new key with the specified value. */ 652 ndis_add_sysctl(sc, keystr, "(dynamically set key)", 653 val, CTLFLAG_RW); 654 655 free(keystr, M_DEVBUF); 656 *status = NDIS_STATUS_SUCCESS; 657 return; 658} 659 660__stdcall static void 661ndis_close_cfg(cfg) 662 ndis_handle cfg; 663{ 664 return; 665} 666 667__stdcall static void 668ndis_create_lock(lock) 669 ndis_spin_lock *lock; 670{ 671 struct mtx *mtx; 672 673 mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO); 674 if (mtx == NULL) 675 return; 676 mtx_init(mtx, "ndislock", "ndis spin lock", 677 MTX_DEF | MTX_RECURSE | MTX_DUPOK); 678 lock->nsl_spinlock = (ndis_kspin_lock)mtx; 679 680 return; 681} 682 683__stdcall static void 684ndis_destroy_lock(lock) 685 ndis_spin_lock *lock; 686{ 687 struct mtx *ndis_mtx; 688 689 ndis_mtx = (struct mtx *)lock->nsl_spinlock; 690 mtx_destroy(ndis_mtx); 691 free(ndis_mtx, M_DEVBUF); 692 lock->nsl_spinlock = 0xdeadf00d; /* XXX */ 693 694 return; 695} 696 697__stdcall static void 698ndis_lock(lock) 699 ndis_spin_lock *lock; 700{ 701 if (lock == NULL) 702 return; 703 /* 704 * Workaround for certain broken NDIS drivers. I have 705 * encountered one case where a driver creates a spinlock 706 * within its DriverEntry() routine, which is then destroyed 707 * in its MiniportHalt() routine. This is a bug, because 708 * MiniportHalt() is meant to only destroy what MiniportInit() 709 * creates. This leads to the following problem: 710 * DriverEntry() <- spinlock created 711 * MiniportInit() <- NIC initialized 712 * MiniportHalt() <- NIC halted, spinlock destroyed 713 * MiniportInit() <- NIC initialized, spinlock not recreated 714 * NdisAcquireSpinLock(boguslock) <- panic 715 * To work around this, we poison the spinlock on destroy, and 716 * if we try to re-acquire the poison pill^Wspinlock, we init 717 * it again so subsequent calls will work. 718 * 719 * Drivers that behave in this way are likely not officially 720 * certified by Microsoft, since their I would expect the 721 * Microsoft NDIS test tool to catch mistakes like this. 722 */ 723 if (lock->nsl_spinlock == 0xdeadf00d) 724 ndis_create_lock(lock); 725 mtx_lock((struct mtx *)lock->nsl_spinlock); 726 727 return; 728} 729 730__stdcall static void 731ndis_unlock(lock) 732 ndis_spin_lock *lock; 733{ 734 if (lock == NULL) 735 return; 736 mtx_unlock((struct mtx *)lock->nsl_spinlock); 737 738 return; 739} 740 741__stdcall static uint32_t 742ndis_read_pci(adapter, slot, offset, buf, len) 743 ndis_handle adapter; 744 uint32_t slot; 745 uint32_t offset; 746 void *buf; 747 uint32_t len; 748{ 749 ndis_miniport_block *block; 750 int i; 751 char *dest; 752 753 block = (ndis_miniport_block *)adapter; 754 dest = buf; 755 if (block == NULL || block->nmb_dev == NULL) 756 return(0); 757 758 for (i = 0; i < len; i++) 759 dest[i] = pci_read_config(block->nmb_dev, i + offset, 1); 760 761 return(len); 762} 763 764__stdcall static uint32_t 765ndis_write_pci(adapter, slot, offset, buf, len) 766 ndis_handle adapter; 767 uint32_t slot; 768 uint32_t offset; 769 void *buf; 770 uint32_t len; 771{ 772 ndis_miniport_block *block; 773 int i; 774 char *dest; 775 776 block = (ndis_miniport_block *)adapter; 777 dest = buf; 778 779 if (block == NULL || block->nmb_dev == NULL) 780 return(0); 781 782 for (i = 0; i < len; i++) 783 pci_write_config(block->nmb_dev, i + offset, dest[i], 1); 784 785 return(len); 786} 787 788/* 789 * The errorlog routine uses a variable argument list, so we 790 * have to declare it this way. 791 */ 792static void 793ndis_syslog(ndis_handle adapter, ndis_error_code code, 794 uint32_t numerrors, ...) 795{ 796 ndis_miniport_block *block; 797 va_list ap; 798 int i, error; 799 char *str = NULL, *ustr = NULL; 800 uint16_t flags; 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 ndis_unicode_to_ascii((uint16_t *)str, i, &ustr); 807 str = ustr; 808 } 809 device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code, 810 str == NULL ? "unknown error" : str); 811 device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors); 812 813 va_start(ap, numerrors); 814 for (i = 0; i < numerrors; i++) 815 device_printf (block->nmb_dev, "argptr: %p\n", 816 va_arg(ap, void *)); 817 va_end(ap); 818 819 if (ustr != NULL) 820 free(ustr, M_DEVBUF); 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__stdcall static void 921ndis_create_timer(timer, handle, func, ctx) 922 ndis_miniport_timer *timer; 923 ndis_handle *handle; 924 ndis_timer_function func; 925 void *ctx; 926{ 927 struct ndis_timer_entry *ne = NULL; 928 ndis_miniport_block *block; 929 block = (ndis_miniport_block *)handle; 930 931 ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT); 932 callout_init(&ne->nte_ch, CALLOUT_MPSAFE); 933 TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link); 934 ne->nte_timer = timer; 935 936 timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 937 timer->nmt_dpc.nk_deferredctx = &ne->nte_ch; 938 timer->nmt_timerfunc = func; 939 timer->nmt_timerctx = ctx; 940 941 return; 942} 943 944/* 945 * The driver's timer callout is __stdcall function, so we need this 946 * intermediate step. 947 */ 948 949static void 950ndis_timercall(arg) 951 void *arg; 952{ 953 ndis_miniport_timer *timer; 954 __stdcall ndis_timer_function timerfunc; 955 956 timer = arg; 957 958 timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; 959 timerfunc = timer->nmt_timerfunc; 960 timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 961 962 return; 963} 964 965/* 966 * Windows specifies timeouts in milliseconds. We specify timeouts 967 * in hz. Trying to compute a tenth of a second based on hz is tricky. 968 * so we approximate. Note that we abuse the dpc portion of the 969 * miniport timer structure to hold the UNIX callout handle. 970 */ 971__stdcall static void 972ndis_set_timer(timer, msecs) 973 ndis_miniport_timer *timer; 974 uint32_t msecs; 975{ 976 struct callout *ch; 977 struct timeval tv; 978 979 tv.tv_sec = 0; 980 tv.tv_usec = msecs * 1000; 981 982 ch = timer->nmt_dpc.nk_deferredctx; 983 timer->nmt_dpc.nk_sysarg2 = ndis_timercall; 984 timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 985 callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); 986 987 return; 988} 989 990static void 991ndis_tick(arg) 992 void *arg; 993{ 994 ndis_miniport_timer *timer; 995 struct callout *ch; 996 __stdcall ndis_timer_function timerfunc; 997 struct timeval tv; 998 999 timer = arg; 1000 1001 timer->nmt_ktimer.nk_header.dh_sigstate = FALSE; 1002 timerfunc = timer->nmt_timerfunc; 1003 timerfunc(NULL, timer->nmt_timerctx, NULL, NULL); 1004 1005 /* Automatically reload timer. */ 1006 1007 tv.tv_sec = 0; 1008 tv.tv_usec = timer->nmt_ktimer.nk_period * 1000; 1009 ch = timer->nmt_dpc.nk_deferredctx; 1010 timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 1011 timer->nmt_dpc.nk_sysarg2 = ndis_tick; 1012 callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); 1013 1014 return; 1015} 1016 1017__stdcall static void 1018ndis_set_periodic_timer(timer, msecs) 1019 ndis_miniport_timer *timer; 1020 uint32_t msecs; 1021{ 1022 struct callout *ch; 1023 struct timeval tv; 1024 1025 tv.tv_sec = 0; 1026 tv.tv_usec = msecs * 1000; 1027 1028 timer->nmt_ktimer.nk_period = msecs; 1029 ch = timer->nmt_dpc.nk_deferredctx; 1030 timer->nmt_dpc.nk_sysarg2 = ndis_tick; 1031 timer->nmt_ktimer.nk_header.dh_sigstate = TRUE; 1032 callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer); 1033 1034 return; 1035} 1036 1037__stdcall static void 1038ndis_cancel_timer(timer, cancelled) 1039 ndis_miniport_timer *timer; 1040 uint8_t *cancelled; 1041{ 1042 struct callout *ch; 1043 1044 if (timer == NULL) 1045 return; 1046 ch = timer->nmt_dpc.nk_deferredctx; 1047 if (ch == NULL) 1048 return; 1049 callout_stop(ch); 1050 *cancelled = timer->nmt_ktimer.nk_header.dh_sigstate; 1051 1052 return; 1053} 1054 1055__stdcall static void 1056ndis_query_resources(status, adapter, list, buflen) 1057 ndis_status *status; 1058 ndis_handle adapter; 1059 ndis_resource_list *list; 1060 uint32_t *buflen; 1061{ 1062 ndis_miniport_block *block; 1063 struct ndis_softc *sc; 1064 int rsclen; 1065 1066 block = (ndis_miniport_block *)adapter; 1067 sc = (struct ndis_softc *)block->nmb_ifp; 1068 1069 rsclen = sizeof(ndis_resource_list) + 1070 (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); 1071 if (*buflen < rsclen) { 1072 *buflen = rsclen; 1073 *status = NDIS_STATUS_INVALID_LENGTH; 1074 return; 1075 } 1076 1077 bcopy((char *)block->nmb_rlist, (char *)list, *buflen); 1078 *status = NDIS_STATUS_SUCCESS; 1079 return; 1080} 1081 1082__stdcall static ndis_status 1083ndis_register_ioport(offset, adapter, port, numports) 1084 void **offset; 1085 ndis_handle adapter; 1086 uint32_t port; 1087 uint32_t numports; 1088{ 1089 struct ndis_miniport_block *block; 1090 struct ndis_softc *sc; 1091 1092 if (adapter == NULL) 1093 return(NDIS_STATUS_FAILURE); 1094 1095 block = (ndis_miniport_block *)adapter; 1096 sc = (struct ndis_softc *)(block->nmb_ifp); 1097 1098 if (sc->ndis_res_io == NULL) 1099 return(NDIS_STATUS_FAILURE); 1100 1101 if (rman_get_size(sc->ndis_res_io) != numports) 1102 return(NDIS_STATUS_INVALID_LENGTH); 1103 1104 *offset = (void *)rman_get_start(sc->ndis_res_io); 1105 1106 return(NDIS_STATUS_SUCCESS); 1107} 1108 1109__stdcall static void 1110ndis_deregister_ioport(adapter, port, numports, offset) 1111 ndis_handle adapter; 1112 uint32_t port; 1113 uint32_t numports; 1114 void *offset; 1115{ 1116 return; 1117} 1118 1119__stdcall static void 1120ndis_read_netaddr(status, addr, addrlen, adapter) 1121 ndis_status *status; 1122 void **addr; 1123 uint32_t *addrlen; 1124 ndis_handle adapter; 1125{ 1126 struct ndis_softc *sc; 1127 ndis_miniport_block *block; 1128 uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; 1129 1130 block = (ndis_miniport_block *)adapter; 1131 sc = (struct ndis_softc *)block->nmb_ifp; 1132 1133 if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0) 1134 *status = NDIS_STATUS_FAILURE; 1135 else { 1136 *addr = sc->arpcom.ac_enaddr; 1137 *addrlen = ETHER_ADDR_LEN; 1138 *status = NDIS_STATUS_SUCCESS; 1139 } 1140 1141 return; 1142} 1143 1144__stdcall static ndis_status 1145ndis_mapreg_cnt(bustype, cnt) 1146 uint32_t bustype; 1147 uint32_t *cnt; 1148{ 1149 *cnt = 8192; 1150 return(NDIS_STATUS_SUCCESS); 1151} 1152 1153__stdcall static ndis_status 1154ndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap) 1155 ndis_handle adapter; 1156 uint32_t dmachannel; 1157 uint8_t dmasize; 1158 uint32_t physmapneeded; 1159 uint32_t maxmap; 1160{ 1161 struct ndis_softc *sc; 1162 ndis_miniport_block *block; 1163 int error, i, nseg = NDIS_MAXSEG; 1164 1165 block = (ndis_miniport_block *)adapter; 1166 sc = (struct ndis_softc *)block->nmb_ifp; 1167 1168 sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, 1169 M_DEVBUF, M_NOWAIT|M_ZERO); 1170 1171 if (sc->ndis_mmaps == NULL) 1172 return(NDIS_STATUS_RESOURCES); 1173 1174 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1175 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1176 NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, 1177 NULL, NULL, &sc->ndis_mtag); 1178 1179 if (error) { 1180 free(sc->ndis_mmaps, M_DEVBUF); 1181 return(NDIS_STATUS_RESOURCES); 1182 } 1183 1184 for (i = 0; i < physmapneeded; i++) 1185 bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); 1186 1187 sc->ndis_mmapcnt = physmapneeded; 1188 1189 return(NDIS_STATUS_SUCCESS); 1190} 1191 1192__stdcall static void 1193ndis_free_mapreg(adapter) 1194 ndis_handle adapter; 1195{ 1196 struct ndis_softc *sc; 1197 ndis_miniport_block *block; 1198 int i; 1199 1200 block = (ndis_miniport_block *)adapter; 1201 sc = (struct ndis_softc *)block->nmb_ifp; 1202 1203 for (i = 0; i < sc->ndis_mmapcnt; i++) 1204 bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); 1205 1206 free(sc->ndis_mmaps, M_DEVBUF); 1207 1208 bus_dma_tag_destroy(sc->ndis_mtag); 1209 1210 return; 1211} 1212 1213static void 1214ndis_mapshared_cb(arg, segs, nseg, error) 1215 void *arg; 1216 bus_dma_segment_t *segs; 1217 int nseg; 1218 int error; 1219{ 1220 ndis_physaddr *p; 1221 1222 if (error || nseg > 1) 1223 return; 1224 1225 p = arg; 1226 1227 p->np_quad = segs[0].ds_addr; 1228 1229 return; 1230} 1231 1232/* 1233 * This maps to bus_dmamem_alloc(). 1234 */ 1235__stdcall static void 1236ndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr) 1237 ndis_handle adapter; 1238 uint32_t len; 1239 uint8_t cached; 1240 void **vaddr; 1241 ndis_physaddr *paddr; 1242{ 1243 ndis_miniport_block *block; 1244 struct ndis_softc *sc; 1245 struct ndis_shmem *sh; 1246 int error; 1247 1248 if (adapter == NULL) 1249 return; 1250 1251 block = (ndis_miniport_block *)adapter; 1252 sc = (struct ndis_softc *)(block->nmb_ifp); 1253 1254 sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); 1255 if (sh == NULL) 1256 return; 1257 1258 error = bus_dma_tag_create(sc->ndis_parent_tag, 64, 1259 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, 1260 NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, 1261 &sh->ndis_stag); 1262 1263 if (error) { 1264 free(sh, M_DEVBUF); 1265 return; 1266 } 1267 1268 error = bus_dmamem_alloc(sh->ndis_stag, vaddr, 1269 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); 1270 1271 if (error) { 1272 bus_dma_tag_destroy(sh->ndis_stag); 1273 free(sh, M_DEVBUF); 1274 return; 1275 } 1276 1277 error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, 1278 len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); 1279 1280 if (error) { 1281 bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); 1282 bus_dma_tag_destroy(sh->ndis_stag); 1283 free(sh, M_DEVBUF); 1284 return; 1285 } 1286 1287 sh->ndis_saddr = *vaddr; 1288 sh->ndis_next = sc->ndis_shlist; 1289 sc->ndis_shlist = sh; 1290 1291 return; 1292} 1293 1294__stdcall static void 1295ndis_alloc_sharedmem_async(adapter, len, cached, ctx) 1296 ndis_handle adapter; 1297 uint32_t len; 1298 uint8_t cached; 1299 void *ctx; 1300{ 1301 ndis_miniport_block *block; 1302 struct ndis_softc *sc; 1303 void *vaddr; 1304 ndis_physaddr paddr; 1305 __stdcall ndis_allocdone_handler donefunc; 1306 1307 if (adapter == NULL) 1308 return; 1309 1310 block = (ndis_miniport_block *)adapter; 1311 sc = (struct ndis_softc *)(block->nmb_ifp); 1312 donefunc = sc->ndis_chars.nmc_allocate_complete_func; 1313 1314 ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr); 1315 donefunc(adapter, vaddr, &paddr, len, ctx); 1316 1317 return; 1318} 1319 1320__stdcall static void 1321ndis_free_sharedmem(adapter, len, cached, vaddr, paddr) 1322 ndis_handle adapter; 1323 uint32_t len; 1324 uint8_t cached; 1325 void *vaddr; 1326 ndis_physaddr paddr; 1327{ 1328 ndis_miniport_block *block; 1329 struct ndis_softc *sc; 1330 struct ndis_shmem *sh, *prev; 1331 1332 if (vaddr == NULL || adapter == NULL) 1333 return; 1334 1335 block = (ndis_miniport_block *)adapter; 1336 sc = (struct ndis_softc *)(block->nmb_ifp); 1337 sh = prev = sc->ndis_shlist; 1338 1339 while (sh) { 1340 if (sh->ndis_saddr == vaddr) 1341 break; 1342 prev = sh; 1343 sh = sh->ndis_next; 1344 } 1345 1346 bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); 1347 bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap); 1348 bus_dma_tag_destroy(sh->ndis_stag); 1349 1350 if (sh == sc->ndis_shlist) 1351 sc->ndis_shlist = sh->ndis_next; 1352 else 1353 prev->ndis_next = sh->ndis_next; 1354 1355 free(sh, M_DEVBUF); 1356 1357 return; 1358} 1359 1360__stdcall static ndis_status 1361ndis_map_iospace(vaddr, adapter, paddr, len) 1362 void **vaddr; 1363 ndis_handle adapter; 1364 ndis_physaddr paddr; 1365 uint32_t len; 1366{ 1367 ndis_miniport_block *block; 1368 struct ndis_softc *sc; 1369 1370 if (adapter == NULL) 1371 return(NDIS_STATUS_FAILURE); 1372 1373 block = (ndis_miniport_block *)adapter; 1374 sc = (struct ndis_softc *)(block->nmb_ifp); 1375 1376 if (sc->ndis_res_mem == NULL) 1377 return(NDIS_STATUS_FAILURE); 1378 1379 *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem); 1380 1381 return(NDIS_STATUS_SUCCESS); 1382} 1383 1384__stdcall static void 1385ndis_unmap_iospace(adapter, vaddr, len) 1386 ndis_handle adapter; 1387 void *vaddr; 1388 uint32_t len; 1389{ 1390 return; 1391} 1392 1393__stdcall static uint32_t 1394ndis_cachefill(void) 1395{ 1396 return(128); 1397} 1398 1399__stdcall static uint32_t 1400ndis_dma_align(handle) 1401 ndis_handle handle; 1402{ 1403 return(128); 1404} 1405 1406/* 1407 * NDIS has two methods for dealing with NICs that support DMA. 1408 * One is to just pass packets to the driver and let it call 1409 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet 1410 * all by itself, and the other is to let the NDIS library handle the 1411 * buffer mapping internally, and hand the driver an already populated 1412 * scatter/gather fragment list. If the driver calls 1413 * NdisMInitializeScatterGatherDma(), it wants to use the latter 1414 * method. 1415 */ 1416 1417__stdcall static ndis_status 1418ndis_init_sc_dma(adapter, is64, maxphysmap) 1419 ndis_handle adapter; 1420 uint8_t is64; 1421 uint32_t maxphysmap; 1422{ 1423 struct ndis_softc *sc; 1424 ndis_miniport_block *block; 1425 int error; 1426 1427 if (adapter == NULL) 1428 return(NDIS_STATUS_FAILURE); 1429 block = (ndis_miniport_block *)adapter; 1430 sc = (struct ndis_softc *)block->nmb_ifp; 1431 1432 /* Don't do this twice. */ 1433 if (sc->ndis_sc == 1) 1434 return(NDIS_STATUS_SUCCESS); 1435 1436 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, 1437 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, 1438 MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, 1439 NULL, NULL, &sc->ndis_ttag); 1440 1441 sc->ndis_sc = 1; 1442 1443 return(NDIS_STATUS_SUCCESS); 1444} 1445 1446__stdcall static void 1447ndis_alloc_packetpool(status, pool, descnum, protrsvdlen) 1448 ndis_status *status; 1449 ndis_handle *pool; 1450 uint32_t descnum; 1451 uint32_t protrsvdlen; 1452{ 1453 ndis_packet *cur; 1454 int i; 1455 1456 *pool = malloc(sizeof(ndis_packet) * 1457 ((descnum + NDIS_POOL_EXTRA) + 1), 1458 M_DEVBUF, M_NOWAIT|M_ZERO); 1459 1460 if (pool == NULL) { 1461 *status = NDIS_STATUS_RESOURCES; 1462 return; 1463 } 1464 1465 cur = (ndis_packet *)*pool; 1466 cur->np_private.npp_flags = 0x1; /* mark the head of the list */ 1467 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) { 1468 cur->np_private.npp_head = (ndis_handle)(cur + 1); 1469 cur++; 1470 } 1471 1472 *status = NDIS_STATUS_SUCCESS; 1473 return; 1474} 1475 1476__stdcall static void 1477ndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen) 1478 ndis_status *status; 1479 ndis_handle *pool; 1480 uint32_t descnum; 1481 uint32_t oflowdescnum; 1482 uint32_t protrsvdlen; 1483{ 1484 return(ndis_alloc_packetpool(status, pool, 1485 descnum + oflowdescnum, protrsvdlen)); 1486} 1487 1488__stdcall static uint32_t 1489ndis_packetpool_use(pool) 1490 ndis_handle pool; 1491{ 1492 ndis_packet *head; 1493 1494 head = (ndis_packet *)pool; 1495 1496 return(head->np_private.npp_count); 1497} 1498 1499__stdcall static void 1500ndis_free_packetpool(pool) 1501 ndis_handle pool; 1502{ 1503 free(pool, M_DEVBUF); 1504 return; 1505} 1506 1507__stdcall static void 1508ndis_alloc_packet(status, packet, pool) 1509 ndis_status *status; 1510 ndis_packet **packet; 1511 ndis_handle pool; 1512{ 1513 ndis_packet *head, *pkt; 1514 1515 head = (ndis_packet *)pool; 1516 1517 if (head->np_private.npp_flags != 0x1) { 1518 *status = NDIS_STATUS_FAILURE; 1519 return; 1520 } 1521 1522 pkt = (ndis_packet *)head->np_private.npp_head; 1523 1524 if (pkt == NULL) { 1525 *status = NDIS_STATUS_RESOURCES; 1526 return; 1527 } 1528 1529 head->np_private.npp_head = pkt->np_private.npp_head; 1530 1531 pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL; 1532 /* Save pointer to the pool. */ 1533 pkt->np_private.npp_pool = head; 1534 1535 /* Set the oob offset pointer. Lots of things expect this. */ 1536 pkt->np_private.npp_packetooboffset = 1537 offsetof(ndis_packet, np_oob); 1538 1539 *packet = pkt; 1540 1541 head->np_private.npp_count++; 1542 *status = NDIS_STATUS_SUCCESS; 1543 return; 1544} 1545 1546__stdcall static void 1547ndis_release_packet(packet) 1548 ndis_packet *packet; 1549{ 1550 ndis_packet *head; 1551 1552 if (packet == NULL || packet->np_private.npp_pool == NULL) 1553 return; 1554 1555 head = packet->np_private.npp_pool; 1556 if (head->np_private.npp_flags != 0x1) 1557 return; 1558 1559 packet->np_private.npp_head = head->np_private.npp_head; 1560 head->np_private.npp_head = (ndis_buffer *)packet; 1561 head->np_private.npp_count--; 1562 1563 return; 1564} 1565 1566__stdcall static void 1567ndis_unchain_headbuf(packet, buf) 1568 ndis_packet *packet; 1569 ndis_buffer **buf; 1570{ 1571 ndis_packet_private *priv; 1572 1573 if (packet == NULL || buf == NULL) 1574 return; 1575 1576 priv = &packet->np_private; 1577 1578 priv->npp_validcounts = FALSE; 1579 1580 if (priv->npp_head == priv->npp_tail) { 1581 *buf = priv->npp_head; 1582 priv->npp_head = priv->npp_tail = NULL; 1583 } else { 1584 *buf = priv->npp_head; 1585 priv->npp_head = (*buf)->nb_next; 1586 } 1587 1588 return; 1589} 1590 1591__stdcall static void 1592ndis_unchain_tailbuf(packet, buf) 1593 ndis_packet *packet; 1594 ndis_buffer **buf; 1595{ 1596 ndis_packet_private *priv; 1597 ndis_buffer *tmp; 1598 1599 if (packet == NULL || buf == NULL) 1600 return; 1601 1602 priv = &packet->np_private; 1603 1604 priv->npp_validcounts = FALSE; 1605 1606 if (priv->npp_head == priv->npp_tail) { 1607 *buf = priv->npp_head; 1608 priv->npp_head = priv->npp_tail = NULL; 1609 } else { 1610 *buf = priv->npp_tail; 1611 tmp = priv->npp_head; 1612 while (tmp->nb_next != priv->npp_tail) 1613 tmp = tmp->nb_next; 1614 priv->npp_tail = tmp; 1615 tmp->nb_next = NULL; 1616 } 1617 1618 return; 1619} 1620 1621/* 1622 * The NDIS "buffer" manipulation functions are somewhat misnamed. 1623 * They don't really allocate buffers: they allocate buffer mappings. 1624 * The idea is you reserve a chunk of DMA-able memory using 1625 * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer() 1626 * to obtain the virtual address of the DMA-able region. 1627 * ndis_alloc_bufpool() is analagous to bus_dma_tag_create(). 1628 */ 1629 1630__stdcall static void 1631ndis_alloc_bufpool(status, pool, descnum) 1632 ndis_status *status; 1633 ndis_handle *pool; 1634 uint32_t descnum; 1635{ 1636 ndis_buffer *cur; 1637 int i; 1638 1639 *pool = malloc(sizeof(ndis_buffer) * 1640 ((descnum + NDIS_POOL_EXTRA) + 1), 1641 M_DEVBUF, M_NOWAIT|M_ZERO); 1642 1643 if (pool == NULL) { 1644 *status = NDIS_STATUS_RESOURCES; 1645 return; 1646 } 1647 1648 cur = (ndis_buffer *)*pool; 1649 cur->nb_flags = 0x1; /* mark the head of the list */ 1650 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) { 1651 cur->nb_next = cur + 1; 1652 cur++; 1653 } 1654 1655 *status = NDIS_STATUS_SUCCESS; 1656 return; 1657} 1658 1659__stdcall static void 1660ndis_free_bufpool(pool) 1661 ndis_handle pool; 1662{ 1663 free(pool, M_DEVBUF); 1664 return; 1665} 1666 1667/* 1668 * This maps to a bus_dmamap_create() and bus_dmamap_load(). 1669 */ 1670__stdcall static void 1671ndis_alloc_buf(status, buffer, pool, vaddr, len) 1672 ndis_status *status; 1673 ndis_buffer **buffer; 1674 ndis_handle pool; 1675 void *vaddr; 1676 uint32_t len; 1677{ 1678 ndis_buffer *head, *buf; 1679 1680 head = (ndis_buffer *)pool; 1681 if (head->nb_flags != 0x1) { 1682 *status = NDIS_STATUS_FAILURE; 1683 return; 1684 } 1685 1686 buf = head->nb_next; 1687 1688 if (buf == NULL) { 1689 *status = NDIS_STATUS_RESOURCES; 1690 return; 1691 } 1692 1693 head->nb_next = buf->nb_next; 1694 1695 /* Save pointer to the pool. */ 1696 buf->nb_process = head; 1697 1698 MDL_INIT(buf, vaddr, len); 1699 1700 *buffer = buf; 1701 1702 *status = NDIS_STATUS_SUCCESS; 1703 return; 1704} 1705 1706__stdcall static void 1707ndis_release_buf(buf) 1708 ndis_buffer *buf; 1709{ 1710 ndis_buffer *head; 1711 1712 if (buf == NULL || buf->nb_process == NULL) 1713 return; 1714 1715 head = buf->nb_process; 1716 1717 if (head->nb_flags != 0x1) 1718 return; 1719 1720 buf->nb_next = head->nb_next; 1721 head->nb_next = buf; 1722 1723 return; 1724} 1725 1726/* Aw c'mon. */ 1727 1728__stdcall static uint32_t 1729ndis_buflen(buf) 1730 ndis_buffer *buf; 1731{ 1732 return(buf->nb_bytecount); 1733} 1734 1735/* 1736 * Get the virtual address and length of a buffer. 1737 * Note: the vaddr argument is optional. 1738 */ 1739 1740__stdcall static void 1741ndis_query_buf(buf, vaddr, len) 1742 ndis_buffer *buf; 1743 void **vaddr; 1744 uint32_t *len; 1745{ 1746 if (vaddr != NULL) 1747 *vaddr = MDL_VA(buf); 1748 *len = buf->nb_bytecount; 1749 1750 return; 1751} 1752 1753/* Same as above -- we don't care about the priority. */ 1754 1755__stdcall static void 1756ndis_query_buf_safe(buf, vaddr, len, prio) 1757 ndis_buffer *buf; 1758 void **vaddr; 1759 uint32_t *len; 1760 uint32_t prio; 1761{ 1762 if (vaddr != NULL) 1763 *vaddr = MDL_VA(buf); 1764 *len = buf->nb_bytecount; 1765 1766 return; 1767} 1768 1769__stdcall static void 1770ndis_adjust_buflen(buf, len) 1771 ndis_buffer *buf; 1772 int len; 1773{ 1774 buf->nb_bytecount = len; 1775 1776 return; 1777} 1778 1779__stdcall static uint32_t 1780ndis_interlock_inc(addend) 1781 uint32_t *addend; 1782{ 1783 mtx_lock(&ndis_interlock); 1784 *addend++; 1785 mtx_unlock(&ndis_interlock); 1786 return(*addend); 1787} 1788 1789__stdcall static uint32_t 1790ndis_interlock_dec(addend) 1791 uint32_t *addend; 1792{ 1793 mtx_lock(&ndis_interlock); 1794 *addend--; 1795 mtx_unlock(&ndis_interlock); 1796 return(*addend); 1797} 1798 1799__stdcall static void 1800ndis_init_event(event) 1801 ndis_event *event; 1802{ 1803 event->ne_event.nk_header.dh_sigstate = FALSE; 1804 return; 1805} 1806 1807__stdcall static void 1808ndis_set_event(event) 1809 ndis_event *event; 1810{ 1811 event->ne_event.nk_header.dh_sigstate = TRUE; 1812 wakeup(event); 1813 return; 1814} 1815 1816__stdcall static void 1817ndis_reset_event(event) 1818 ndis_event *event; 1819{ 1820 event->ne_event.nk_header.dh_sigstate = FALSE; 1821 wakeup(event); 1822 return; 1823} 1824 1825__stdcall static uint8_t 1826ndis_wait_event(event, msecs) 1827 ndis_event *event; 1828 uint32_t msecs; 1829{ 1830 int error; 1831 struct timeval tv; 1832 1833 if (event->ne_event.nk_header.dh_sigstate == TRUE) 1834 return(TRUE); 1835 1836 tv.tv_sec = 0; 1837 tv.tv_usec = msecs * 1000; 1838 1839 error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 1840 1841 return(event->ne_event.nk_header.dh_sigstate); 1842} 1843 1844__stdcall static ndis_status 1845ndis_unicode2ansi(dstr, sstr) 1846 ndis_ansi_string *dstr; 1847 ndis_unicode_string *sstr; 1848{ 1849 if (dstr == NULL || sstr == NULL) 1850 return(NDIS_STATUS_FAILURE); 1851 if (ndis_unicode_to_ascii(sstr->nus_buf, 1852 sstr->nus_len, &dstr->nas_buf)) 1853 return(NDIS_STATUS_FAILURE); 1854 dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf); 1855 return (NDIS_STATUS_SUCCESS); 1856} 1857 1858__stdcall static ndis_status 1859ndis_ansi2unicode(dstr, sstr) 1860 ndis_unicode_string *dstr; 1861 ndis_ansi_string *sstr; 1862{ 1863 char *str; 1864 if (dstr == NULL || sstr == NULL) 1865 return(NDIS_STATUS_FAILURE); 1866 str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT); 1867 if (str == NULL) 1868 return(NDIS_STATUS_FAILURE); 1869 strncpy(str, sstr->nas_buf, sstr->nas_len); 1870 *(str + sstr->nas_len) = '\0'; 1871 if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) { 1872 free(str, M_DEVBUF); 1873 return(NDIS_STATUS_FAILURE); 1874 } 1875 dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2; 1876 free(str, M_DEVBUF); 1877 return (NDIS_STATUS_SUCCESS); 1878} 1879 1880__stdcall static ndis_status 1881ndis_assign_pcirsrc(adapter, slot, list) 1882 ndis_handle adapter; 1883 uint32_t slot; 1884 ndis_resource_list **list; 1885{ 1886 ndis_miniport_block *block; 1887 1888 if (adapter == NULL || list == NULL) 1889 return (NDIS_STATUS_FAILURE); 1890 1891 block = (ndis_miniport_block *)adapter; 1892 *list = block->nmb_rlist; 1893 1894 return (NDIS_STATUS_SUCCESS); 1895} 1896 1897__stdcall static ndis_status 1898ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode) 1899 ndis_miniport_interrupt *intr; 1900 ndis_handle adapter; 1901 uint32_t ivec; 1902 uint32_t ilevel; 1903 uint8_t reqisr; 1904 uint8_t shared; 1905 ndis_interrupt_mode imode; 1906{ 1907 ndis_miniport_block *block; 1908 1909 block = adapter; 1910 1911 intr->ni_block = adapter; 1912 intr->ni_isrreq = reqisr; 1913 intr->ni_shared = shared; 1914 block->nmb_interrupt = intr; 1915 return(NDIS_STATUS_SUCCESS); 1916} 1917 1918__stdcall static void 1919ndis_deregister_intr(intr) 1920 ndis_miniport_interrupt *intr; 1921{ 1922 return; 1923} 1924 1925__stdcall static void 1926ndis_register_shutdown(adapter, shutdownctx, shutdownfunc) 1927 ndis_handle adapter; 1928 void *shutdownctx; 1929 ndis_shutdown_handler shutdownfunc; 1930{ 1931 ndis_miniport_block *block; 1932 ndis_miniport_characteristics *chars; 1933 struct ndis_softc *sc; 1934 1935 if (adapter == NULL) 1936 return; 1937 1938 block = (ndis_miniport_block *)adapter; 1939 sc = (struct ndis_softc *)block->nmb_ifp; 1940 chars = &sc->ndis_chars; 1941 1942 chars->nmc_shutdown_handler = shutdownfunc; 1943 chars->nmc_rsvd0 = shutdownctx; 1944 1945 return; 1946} 1947 1948__stdcall static void 1949ndis_deregister_shutdown(adapter) 1950 ndis_handle adapter; 1951{ 1952 ndis_miniport_block *block; 1953 ndis_miniport_characteristics *chars; 1954 struct ndis_softc *sc; 1955 1956 if (adapter == NULL) 1957 return; 1958 1959 block = (ndis_miniport_block *)adapter; 1960 sc = (struct ndis_softc *)block->nmb_ifp; 1961 chars = &sc->ndis_chars; 1962 1963 chars->nmc_shutdown_handler = NULL; 1964 chars->nmc_rsvd0 = NULL; 1965 1966 return; 1967} 1968 1969__stdcall static uint32_t 1970ndis_numpages(buf) 1971 ndis_buffer *buf; 1972{ 1973 if (buf == NULL) 1974 return(0); 1975 if (buf->nb_bytecount == 0) 1976 return(1); 1977 return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount)); 1978} 1979 1980__stdcall static void 1981ndis_buf_physpages(buf, pages) 1982 ndis_buffer *buf; 1983 uint32_t *pages; 1984{ 1985 if (buf == NULL) 1986 return; 1987 1988 *pages = ndis_numpages(buf); 1989 return; 1990} 1991 1992__stdcall static void 1993ndis_query_bufoffset(buf, off, len) 1994 ndis_buffer *buf; 1995 uint32_t *off; 1996 uint32_t *len; 1997{ 1998 if (buf == NULL) 1999 return; 2000 2001 *off = buf->nb_byteoffset; 2002 *len = buf->nb_bytecount; 2003 2004 return; 2005} 2006 2007__stdcall static void 2008ndis_sleep(usecs) 2009 uint32_t usecs; 2010{ 2011 struct timeval tv; 2012 uint32_t dummy; 2013 2014 tv.tv_sec = 0; 2015 tv.tv_usec = usecs; 2016 2017 tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 2018 2019 return; 2020} 2021 2022__stdcall static uint32_t 2023ndis_read_pccard_amem(handle, offset, buf, len) 2024 ndis_handle handle; 2025 uint32_t offset; 2026 void *buf; 2027 uint32_t len; 2028{ 2029 struct ndis_softc *sc; 2030 ndis_miniport_block *block; 2031 bus_space_handle_t bh; 2032 bus_space_tag_t bt; 2033 char *dest; 2034 int i; 2035 2036 if (handle == NULL) 2037 return(0); 2038 2039 block = (ndis_miniport_block *)handle; 2040 sc = (struct ndis_softc *)block->nmb_ifp; 2041 dest = buf; 2042 2043 bh = rman_get_bushandle(sc->ndis_res_am); 2044 bt = rman_get_bustag(sc->ndis_res_am); 2045 2046 for (i = 0; i < len; i++) 2047 dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2)); 2048 2049 return(i); 2050} 2051 2052__stdcall static uint32_t 2053ndis_write_pccard_amem(handle, offset, buf, len) 2054 ndis_handle handle; 2055 uint32_t offset; 2056 void *buf; 2057 uint32_t len; 2058{ 2059 struct ndis_softc *sc; 2060 ndis_miniport_block *block; 2061 bus_space_handle_t bh; 2062 bus_space_tag_t bt; 2063 char *src; 2064 int i; 2065 2066 if (handle == NULL) 2067 return(0); 2068 2069 block = (ndis_miniport_block *)handle; 2070 sc = (struct ndis_softc *)block->nmb_ifp; 2071 src = buf; 2072 2073 bh = rman_get_bushandle(sc->ndis_res_am); 2074 bt = rman_get_bustag(sc->ndis_res_am); 2075 2076 for (i = 0; i < len; i++) 2077 bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]); 2078 2079 return(i); 2080} 2081 2082__stdcall static ndis_list_entry * 2083ndis_insert_head(head, entry, lock) 2084 ndis_list_entry *head; 2085 ndis_list_entry *entry; 2086 ndis_spin_lock *lock; 2087{ 2088 ndis_list_entry *flink; 2089 2090 mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 2091 flink = head->nle_flink; 2092 entry->nle_flink = flink; 2093 entry->nle_blink = head; 2094 flink->nle_blink = entry; 2095 head->nle_flink = entry; 2096 mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 2097 2098 return(flink); 2099} 2100 2101__stdcall static ndis_list_entry * 2102ndis_remove_head(head, lock) 2103 ndis_list_entry *head; 2104 ndis_spin_lock *lock; 2105{ 2106 ndis_list_entry *flink; 2107 ndis_list_entry *entry; 2108 2109 mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 2110 entry = head->nle_flink; 2111 flink = entry->nle_flink; 2112 head->nle_flink = flink; 2113 flink->nle_blink = head; 2114 mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 2115 2116 return(entry); 2117} 2118 2119__stdcall static ndis_list_entry * 2120ndis_insert_tail(head, entry, lock) 2121 ndis_list_entry *head; 2122 ndis_list_entry *entry; 2123 ndis_spin_lock *lock; 2124{ 2125 ndis_list_entry *blink; 2126 2127 mtx_lock_spin((struct mtx *)lock->nsl_spinlock); 2128 blink = head->nle_blink; 2129 entry->nle_flink = head; 2130 entry->nle_blink = blink; 2131 blink->nle_flink = entry; 2132 head->nle_blink = entry; 2133 mtx_unlock_spin((struct mtx *)lock->nsl_spinlock); 2134 2135 return(blink); 2136} 2137 2138__stdcall static uint8_t 2139ndis_sync_with_intr(intr, syncfunc, syncctx) 2140 ndis_miniport_interrupt *intr; 2141 void *syncfunc; 2142 void *syncctx; 2143{ 2144 struct ndis_softc *sc; 2145 __stdcall uint8_t (*sync)(void *); 2146 uint8_t rval; 2147 2148 if (syncfunc == NULL || syncctx == NULL) 2149 return(0); 2150 2151 sc = (struct ndis_softc *)intr->ni_block->nmb_ifp; 2152 sync = syncfunc; 2153 mtx_lock(&sc->ndis_intrmtx); 2154 rval = sync(syncctx); 2155 mtx_unlock(&sc->ndis_intrmtx); 2156 2157 return(rval); 2158} 2159 2160/* 2161 * Return the number of 100 nanosecond intervals since 2162 * January 1, 1601. (?!?!) 2163 */ 2164__stdcall static void 2165ndis_time(tval) 2166 uint64_t *tval; 2167{ 2168 struct timespec ts; 2169 2170 nanotime(&ts); 2171 *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 + 2172 11644473600; 2173} 2174 2175/* 2176 * Return the number of milliseconds since the system booted. 2177 */ 2178__stdcall static void 2179ndis_uptime(tval) 2180 uint32_t *tval; 2181{ 2182 struct timespec ts; 2183 2184 nanouptime(&ts); 2185 *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000; 2186} 2187 2188__stdcall static void 2189ndis_init_string(dst, src) 2190 ndis_unicode_string *dst; 2191 char *src; 2192{ 2193 ndis_unicode_string *u; 2194 2195 u = dst; 2196 u->nus_buf = NULL; 2197 if (ndis_ascii_to_unicode(src, &u->nus_buf)) 2198 return; 2199 u->nus_len = u->nus_maxlen = strlen(src) * 2; 2200 return; 2201} 2202 2203__stdcall static void 2204ndis_free_string(str) 2205 ndis_unicode_string *str; 2206{ 2207 if (str == NULL) 2208 return; 2209 if (str->nus_buf != NULL) 2210 free(str->nus_buf, M_DEVBUF); 2211 free(str, M_DEVBUF); 2212 return; 2213} 2214 2215__stdcall static ndis_status 2216ndis_remove_miniport(adapter) 2217 ndis_handle *adapter; 2218{ 2219 return(NDIS_STATUS_SUCCESS); 2220} 2221 2222__stdcall static void 2223ndis_init_ansi_string(dst, src) 2224 ndis_ansi_string *dst; 2225 char *src; 2226{ 2227 ndis_ansi_string *a; 2228 2229 a = dst; 2230 if (a == NULL) 2231 return; 2232 if (src == NULL) { 2233 a->nas_len = a->nas_maxlen = 0; 2234 a->nas_buf = NULL; 2235 } else { 2236 a->nas_buf = src; 2237 a->nas_len = a->nas_maxlen = strlen(src); 2238 } 2239 2240 return; 2241} 2242 2243__stdcall static void 2244ndis_init_unicode_string(dst, src) 2245 ndis_unicode_string *dst; 2246 uint16_t *src; 2247{ 2248 ndis_unicode_string *u; 2249 int i; 2250 2251 u = dst; 2252 if (u == NULL) 2253 return; 2254 if (src == NULL) { 2255 u->nus_len = u->nus_maxlen = 0; 2256 u->nus_buf = NULL; 2257 } else { 2258 i = 0; 2259 while(src[i] != 0) 2260 i++; 2261 u->nus_buf = src; 2262 u->nus_len = u->nus_maxlen = i * 2; 2263 } 2264 2265 return; 2266} 2267 2268__stdcall static void ndis_get_devprop(adapter, phydevobj, 2269 funcdevobj, nextdevobj, resources, transresources) 2270 ndis_handle adapter; 2271 void *phydevobj; 2272 void *funcdevobj; 2273 void *nextdevobj; 2274 cm_resource_list *resources; 2275 cm_resource_list *transresources; 2276{ 2277 return; 2278} 2279 2280__stdcall static void 2281ndis_firstbuf(packet, buf, firstva, firstlen, totlen) 2282 ndis_packet *packet; 2283 ndis_buffer **buf; 2284 void **firstva; 2285 uint32_t *firstlen; 2286 uint32_t *totlen; 2287{ 2288 ndis_buffer *tmp; 2289 2290 tmp = packet->np_private.npp_head; 2291 *buf = tmp; 2292 if (tmp == NULL) { 2293 *firstva = NULL; 2294 *firstlen = *totlen = 0; 2295 } else { 2296 *firstva = MDL_VA(tmp); 2297 *firstlen = *totlen = tmp->nb_bytecount; 2298 for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next) 2299 *totlen += tmp->nb_bytecount; 2300 } 2301 2302 return; 2303} 2304 2305__stdcall static void 2306ndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio) 2307 ndis_packet *packet; 2308 ndis_buffer **buf; 2309 void **firstva; 2310 uint32_t *firstlen; 2311 uint32_t *totlen; 2312 uint32_t prio; 2313{ 2314 ndis_firstbuf(packet, buf, firstva, firstlen, totlen); 2315} 2316 2317/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */ 2318__stdcall static void 2319ndis_open_file(status, filehandle, filelength, filename, highestaddr) 2320 ndis_status *status; 2321 ndis_handle *filehandle; 2322 uint32_t *filelength; 2323 ndis_unicode_string *filename; 2324 ndis_physaddr highestaddr; 2325{ 2326 char *afilename = NULL; 2327 2328 ndis_unicode_to_ascii(filename->nus_buf, filename->nus_len, &afilename); 2329 printf("ndis_open_file(\"%s\", %ju)\n", afilename, 2330 highestaddr.np_quad); 2331 free(afilename, M_DEVBUF); 2332 *status = NDIS_STATUS_FILE_NOT_FOUND; 2333 return; 2334} 2335 2336__stdcall static void 2337ndis_map_file(status, mappedbuffer, filehandle) 2338 ndis_status *status; 2339 void **mappedbuffer; 2340 ndis_handle filehandle; 2341{ 2342 2343 *status = NDIS_STATUS_ALREADY_MAPPED; 2344 return; 2345} 2346 2347__stdcall static void 2348ndis_unmap_file(filehandle) 2349 ndis_handle filehandle; 2350{ 2351 return; 2352} 2353 2354__stdcall static void 2355ndis_close_file(filehandle) 2356 ndis_handle filehandle; 2357{ 2358 return; 2359} 2360 2361__stdcall static uint8_t 2362ndis_cpu_cnt() 2363{ 2364#ifdef SMP 2365 return(mp_ncpus); 2366#else 2367 return(1); 2368#endif 2369}; 2370 2371typedef void (*ndis_statusdone_handler)(ndis_handle); 2372typedef void (*ndis_status_handler)(ndis_handle, ndis_status, 2373 void *, uint32_t); 2374 2375__stdcall static void 2376ndis_ind_statusdone(adapter) 2377 ndis_handle adapter; 2378{ 2379 ndis_miniport_block *block; 2380 __stdcall ndis_statusdone_handler statusdonefunc; 2381 2382 block = (ndis_miniport_block *)adapter; 2383 statusdonefunc = block->nmb_statusdone_func; 2384 2385 statusdonefunc(adapter); 2386 return; 2387} 2388 2389__stdcall static void 2390ndis_ind_status(adapter, status, sbuf, slen) 2391 ndis_handle adapter; 2392 ndis_status status; 2393 void *sbuf; 2394 uint32_t slen; 2395{ 2396 ndis_miniport_block *block; 2397 __stdcall ndis_status_handler statusfunc; 2398 2399 block = (ndis_miniport_block *)adapter; 2400 statusfunc = block->nmb_status_func; 2401 2402 statusfunc(adapter, status, sbuf, slen); 2403 return; 2404} 2405 2406static void 2407ndis_workfunc(ctx, pending) 2408 void *ctx; 2409 int pending; 2410{ 2411 ndis_work_item *work; 2412 __stdcall ndis_proc workfunc; 2413 2414 work = ctx; 2415 workfunc = work->nwi_func; 2416 workfunc(work, work->nwi_ctx); 2417 return; 2418} 2419 2420__stdcall static ndis_status 2421ndis_sched_workitem(work) 2422 ndis_work_item *work; 2423{ 2424 struct task *t; 2425 2426 t = (struct task *)&work->nwi_wraprsvd; 2427 TASK_INIT(t, 0, ndis_workfunc, work); 2428 taskqueue_enqueue(taskqueue_swi, t); 2429 return(NDIS_STATUS_SUCCESS); 2430} 2431 2432__stdcall static void 2433dummy() 2434{ 2435 printf ("NDIS dummy called...\n"); 2436 return; 2437} 2438 2439image_patch_table ndis_functbl[] = { 2440 { "NdisScheduleWorkItem", (FUNC)ndis_sched_workitem }, 2441 { "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone }, 2442 { "NdisMIndicateStatus", (FUNC)ndis_ind_status }, 2443 { "NdisSystemProcessorCount", (FUNC)ndis_cpu_cnt }, 2444 { "NdisUnchainBufferAtBack", (FUNC)ndis_unchain_tailbuf, }, 2445 { "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf }, 2446 { "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe }, 2447 { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages }, 2448 { "NdisMGetDeviceProperty", (FUNC)ndis_get_devprop }, 2449 { "NdisInitAnsiString", (FUNC)ndis_init_ansi_string }, 2450 { "NdisInitUnicodeString", (FUNC)ndis_init_unicode_string }, 2451 { "NdisWriteConfiguration", (FUNC)ndis_write_cfg }, 2452 { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode }, 2453 { "NdisTerminateWrapper", (FUNC)ndis_termwrap }, 2454 { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname }, 2455 { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx }, 2456 { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport }, 2457 { "NdisInitializeString", (FUNC)ndis_init_string }, 2458 { "NdisFreeString", (FUNC)ndis_free_string }, 2459 { "NdisGetCurrentSystemTime", (FUNC)ndis_time }, 2460 { "NdisGetSystemUpTime", (FUNC)ndis_uptime }, 2461 { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr }, 2462 { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async }, 2463 { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head }, 2464 { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail }, 2465 { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head }, 2466 { "NdisInitializeWrapper", (FUNC)ndis_initwrap }, 2467 { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport }, 2468 { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag }, 2469 { "NdisAllocateMemory", (FUNC)ndis_malloc }, 2470 { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex }, 2471 { "NdisCloseConfiguration", (FUNC)ndis_close_cfg }, 2472 { "NdisReadConfiguration", (FUNC)ndis_read_cfg }, 2473 { "NdisOpenConfiguration", (FUNC)ndis_open_cfg }, 2474 { "NdisReleaseSpinLock", (FUNC)ndis_unlock }, 2475 { "NdisDprAcquireSpinLock", (FUNC)ndis_lock }, 2476 { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock }, 2477 { "NdisAcquireSpinLock", (FUNC)ndis_lock }, 2478 { "NdisAllocateSpinLock", (FUNC)ndis_create_lock }, 2479 { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock }, 2480 { "NdisFreeMemory", (FUNC)ndis_free }, 2481 { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci }, 2482 { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci }, 2483 { "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci }, 2484 { "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci }, 2485 { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog }, 2486 { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load }, 2487 { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload }, 2488 { "NdisMInitializeTimer", (FUNC)ndis_create_timer }, 2489 { "NdisSetTimer", (FUNC)ndis_set_timer }, 2490 { "NdisMCancelTimer", (FUNC)ndis_cancel_timer }, 2491 { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer }, 2492 { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources }, 2493 { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport }, 2494 { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport }, 2495 { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr }, 2496 { "NdisQueryMapRegisterCount", (FUNC)ndis_mapreg_cnt }, 2497 { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg }, 2498 { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg }, 2499 { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem }, 2500 { "NdisMMapIoSpace", (FUNC)ndis_map_iospace }, 2501 { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace }, 2502 { "NdisGetCacheFillSize", (FUNC)ndis_cachefill }, 2503 { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align }, 2504 { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma }, 2505 { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool }, 2506 { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool }, 2507 { "NdisAllocatePacket", (FUNC)ndis_alloc_packet }, 2508 { "NdisFreePacket", (FUNC)ndis_release_packet }, 2509 { "NdisFreePacketPool", (FUNC)ndis_free_packetpool }, 2510 { "NdisDprAllocatePacket", (FUNC)ndis_alloc_packet }, 2511 { "NdisDprFreePacket", (FUNC)ndis_release_packet }, 2512 { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool }, 2513 { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf }, 2514 { "NdisQueryBuffer", (FUNC)ndis_query_buf }, 2515 { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe }, 2516 { "NdisBufferLength", (FUNC)ndis_buflen }, 2517 { "NdisFreeBuffer", (FUNC)ndis_release_buf }, 2518 { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool }, 2519 { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc }, 2520 { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec }, 2521 { "NdisInitializeEvent", (FUNC)ndis_init_event }, 2522 { "NdisSetEvent", (FUNC)ndis_set_event }, 2523 { "NdisResetEvent", (FUNC)ndis_reset_event }, 2524 { "NdisWaitEvent", (FUNC)ndis_wait_event }, 2525 { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi }, 2526 { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc }, 2527 { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem }, 2528 { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr }, 2529 { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr }, 2530 { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown }, 2531 { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown }, 2532 { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages }, 2533 { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset }, 2534 { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen }, 2535 { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use }, 2536 { "NdisMSleep", (FUNC)ndis_sleep }, 2537 { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf }, 2538 { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem }, 2539 { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem }, 2540 { "NdisOpenFile", (FUNC)ndis_open_file }, 2541 { "NdisMapFile", (FUNC)ndis_map_file }, 2542 { "NdisUnmapFile", (FUNC)ndis_unmap_file }, 2543 { "NdisCloseFile", (FUNC)ndis_close_file }, 2544 2545 /* 2546 * This last entry is a catch-all for any function we haven't 2547 * implemented yet. The PE import list patching routine will 2548 * use it for any function that doesn't have an explicit match 2549 * in this table. 2550 */ 2551 2552 { NULL, (FUNC)dummy }, 2553 2554 /* End of list. */ 2555 2556 { NULL, NULL }, 2557}; 2558