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