35 36#include <sys/param.h> 37#include <sys/types.h> 38#include <sys/errno.h> 39#include <sys/callout.h> 40#include <sys/socket.h> 41#include <sys/queue.h> 42#include <sys/sysctl.h> 43#include <sys/systm.h> 44#include <sys/malloc.h> 45#include <sys/lock.h> 46#include <sys/mutex.h> 47#include <sys/conf.h> 48 49#include <sys/kernel.h> 50#include <machine/bus.h> 51#include <machine/resource.h> 52#include <sys/bus.h> 53#include <sys/rman.h> 54 55#include <net/if.h> 56#include <net/if_arp.h> 57#include <net/ethernet.h> 58#include <net/if_dl.h> 59#include <net/if_media.h> 60 61#include <dev/pccard/pccardvar.h> 62#include "card_if.h" 63 64#include <compat/ndis/pe_var.h> 65#include <compat/ndis/resource_var.h> 66#include <compat/ndis/ndis_var.h> 67#include <compat/ndis/hal_var.h> 68#include <compat/ndis/ntoskrnl_var.h> 69#include <compat/ndis/cfg_var.h> 70#include <dev/if_ndis/if_ndisvar.h> 71 72#define __stdcall __attribute__((__stdcall__)) 73#define NDIS_DUMMY_PATH "\\\\some\\bogus\\path" 74 75__stdcall static void ndis_status_func(ndis_handle, ndis_status, 76 void *, uint32_t); 77__stdcall static void ndis_statusdone_func(ndis_handle); 78__stdcall static void ndis_setdone_func(ndis_handle, ndis_status); 79__stdcall static void ndis_getdone_func(ndis_handle, ndis_status); 80__stdcall static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t); 81 82/* 83 * This allows us to export our symbols to other modules. 84 * Note that we call ourselves 'ndisapi' to avoid a namespace 85 * collision with if_ndis.ko, which internally calls itself 86 * 'ndis.' 87 */ 88static int 89ndis_modevent(module_t mod, int cmd, void *arg) 90{ 91 return(0); 92} 93DEV_MODULE(ndisapi, ndis_modevent, NULL); 94MODULE_VERSION(ndisapi, 1); 95 96 97__stdcall static void 98ndis_status_func(adapter, status, sbuf, slen) 99 ndis_handle adapter; 100 ndis_status status; 101 void *sbuf; 102 uint32_t slen; 103{ 104 printf ("status: %x\n", status); 105 return; 106} 107 108__stdcall static void 109ndis_statusdone_func(adapter) 110 ndis_handle adapter; 111{ 112 printf ("status complete\n"); 113 return; 114} 115 116__stdcall static void 117ndis_setdone_func(adapter, status) 118 ndis_handle adapter; 119 ndis_status status; 120{ 121 printf ("Setup done... %x\n", status); 122 return; 123} 124 125__stdcall static void 126ndis_getdone_func(adapter, status) 127 ndis_handle adapter; 128 ndis_status status; 129{ 130 printf ("Query done... %x\n", status); 131 return; 132} 133 134__stdcall static void 135ndis_resetdone_func(adapter, status, addressingreset) 136 ndis_handle adapter; 137 ndis_status status; 138 uint8_t addressingreset; 139{ 140 printf ("reset done...\n"); 141 return; 142} 143 144#define NDIS_AM_RID 3 145 146int 147ndis_alloc_amem(arg) 148 void *arg; 149{ 150 struct ndis_softc *sc; 151 int error, rid; 152 153 if (arg == NULL) 154 return(EINVAL); 155 156 sc = arg; 157 rid = NDIS_AM_RID; 158 sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY, 159 &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE); 160 161 if (sc->ndis_res_am == NULL) { 162 printf("ndis%d: failed to allocate attribute memory\n", 163 sc->ndis_unit); 164 return(ENXIO); 165 } 166 167 error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev), 168 sc->ndis_dev, rid, 0, NULL); 169 170 if (error) { 171 printf("ndis%d: CARD_SET_MEMORY_OFFSET() returned 0x%x\n", 172 sc->ndis_unit, error); 173 return(error); 174 } 175 176 error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev), 177 sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); 178 179 if (error) { 180 printf("ndis%d: CARD_SET_RES_FLAGS() returned 0x%x\n", 181 sc->ndis_unit, error); 182 return(error); 183 } 184 185 return(0); 186} 187 188int 189ndis_create_sysctls(arg) 190 void *arg; 191{ 192 struct ndis_softc *sc; 193 ndis_cfg *vals; 194 char buf[256]; 195 196 if (arg == NULL) 197 return(EINVAL); 198 199 sc = arg; 200 vals = sc->ndis_regvals; 201 202 TAILQ_INIT(&sc->ndis_cfglist_head); 203 204 /* Create the sysctl tree. */ 205 206 sc->ndis_tree = SYSCTL_ADD_NODE(&sc->ndis_ctx, 207 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, 208 device_get_nameunit(sc->ndis_dev), CTLFLAG_RD, 0, 209 device_get_desc(sc->ndis_dev)); 210 211 /* Add the driver-specific registry keys. */ 212 213 vals = sc->ndis_regvals; 214 while(1) { 215 if (vals->nc_cfgkey == NULL) 216 break;
|
221 SYSCTL_ADD_STRING(&sc->ndis_ctx, 222 SYSCTL_CHILDREN(sc->ndis_tree), 223 OID_AUTO, vals->nc_cfgkey, 224 CTLFLAG_RW, vals->nc_val, 225 sizeof(vals->nc_val), 226 vals->nc_cfgdesc); 227 vals++; 228 } 229 230 /* Now add a couple of builtin keys. */ 231 232 /* 233 * Environment can be either Windows (0) or WindowsNT (1). 234 * We qualify as the latter. 235 */ 236 ndis_add_sysctl(sc, "Environment", 237 "Windows environment", "1", CTLFLAG_RD); 238 239 /* NDIS version should be 5.1. */ 240 ndis_add_sysctl(sc, "NdisVersion", 241 "NDIS API Version", "0x00050001", CTLFLAG_RD); 242 243 /* Bus type (PCI, PCMCIA, etc...) */ 244 sprintf(buf, "%d\n", (int)sc->ndis_iftype); 245 ndis_add_sysctl(sc, "BusType", "Bus Type", buf, CTLFLAG_RD); 246 247 if (sc->ndis_res_io != NULL) { 248 sprintf(buf, "0x%lx\n", rman_get_start(sc->ndis_res_io)); 249 ndis_add_sysctl(sc, "IOBaseAddress", 250 "Base I/O Address", buf, CTLFLAG_RD); 251 } 252 253 if (sc->ndis_irq != NULL) { 254 sprintf(buf, "%lu\n", rman_get_start(sc->ndis_irq)); 255 ndis_add_sysctl(sc, "InterruptNumber", 256 "Interrupt Number", buf, CTLFLAG_RD); 257 } 258 259 return(0); 260} 261 262int 263ndis_add_sysctl(arg, key, desc, val, flag) 264 void *arg; 265 char *key; 266 char *desc; 267 char *val; 268 int flag; 269{ 270 struct ndis_softc *sc; 271 struct ndis_cfglist *cfg; 272 char descstr[256]; 273 274 sc = arg; 275 276 cfg = malloc(sizeof(struct ndis_cfglist), M_DEVBUF, M_NOWAIT|M_ZERO); 277 278 if (cfg == NULL) 279 return(ENOMEM); 280 281 cfg->ndis_cfg.nc_cfgkey = strdup(key, M_DEVBUF); 282 if (desc == NULL) { 283 snprintf(descstr, sizeof(descstr), "%s (dynamic)", key); 284 cfg->ndis_cfg.nc_cfgdesc = strdup(descstr, M_DEVBUF); 285 } else 286 cfg->ndis_cfg.nc_cfgdesc = strdup(desc, M_DEVBUF); 287 strcpy(cfg->ndis_cfg.nc_val, val); 288 289 TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link); 290 291 SYSCTL_ADD_STRING(&sc->ndis_ctx, SYSCTL_CHILDREN(sc->ndis_tree), 292 OID_AUTO, cfg->ndis_cfg.nc_cfgkey, flag, 293 cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val), 294 cfg->ndis_cfg.nc_cfgdesc); 295 296 return(0); 297} 298 299int 300ndis_flush_sysctls(arg) 301 void *arg; 302{ 303 struct ndis_softc *sc; 304 struct ndis_cfglist *cfg; 305 306 sc = arg; 307 308 while (!TAILQ_EMPTY(&sc->ndis_cfglist_head)) { 309 cfg = TAILQ_FIRST(&sc->ndis_cfglist_head); 310 TAILQ_REMOVE(&sc->ndis_cfglist_head, cfg, link); 311 free(cfg->ndis_cfg.nc_cfgkey, M_DEVBUF); 312 free(cfg->ndis_cfg.nc_cfgdesc, M_DEVBUF); 313 free(cfg, M_DEVBUF); 314 } 315 316 return(0); 317} 318 319void 320ndis_return_packet(packet, arg) 321 void *packet; 322 void *arg; 323{ 324 struct ndis_softc *sc; 325 ndis_handle adapter; 326 ndis_packet *p; 327 __stdcall ndis_return_handler returnfunc; 328 329 if (arg == NULL || packet == NULL) 330 return; 331 332 p = packet; 333 334 /* Decrement refcount. */ 335 p->np_private.npp_count--; 336 337 /* Release packet when refcount hits zero, otherwise return. */ 338 if (p->np_private.npp_count) 339 return; 340 341 sc = arg; 342 returnfunc = sc->ndis_chars.nmc_return_packet_func; 343 adapter = sc->ndis_block.nmb_miniportadapterctx; 344 if (returnfunc == NULL) 345 ndis_free_packet((ndis_packet *)packet); 346 else 347 returnfunc(adapter, (ndis_packet *)packet); 348 return; 349} 350 351void 352ndis_free_bufs(b0) 353 ndis_buffer *b0; 354{ 355 ndis_buffer *next; 356 357 if (b0 == NULL) 358 return; 359 360 while(b0 != NULL) { 361 next = b0->nb_next; 362 free (b0, M_DEVBUF); 363 b0 = next; 364 } 365 366 return; 367} 368 369void 370ndis_free_packet(p) 371 ndis_packet *p; 372{ 373 if (p == NULL) 374 return; 375 376 ndis_free_bufs(p->np_private.npp_head); 377 free(p, M_DEVBUF); 378 379 return; 380} 381 382int 383ndis_convert_res(arg) 384 void *arg; 385{ 386 struct ndis_softc *sc; 387 ndis_resource_list *rl = NULL; 388 cm_partial_resource_desc *prd = NULL; 389 ndis_miniport_block *block; 390 391 sc = arg; 392 block = &sc->ndis_block; 393 394 rl = malloc(sizeof(ndis_resource_list) + 395 (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)), 396 M_DEVBUF, M_NOWAIT|M_ZERO); 397 398 if (rl == NULL) 399 return(ENOMEM); 400 401 rl->cprl_version = 5; 402 rl->cprl_version = 1; 403 rl->cprl_count = sc->ndis_rescnt; 404 405 prd = rl->cprl_partial_descs; 406 if (sc->ndis_res_io) { 407 prd->cprd_type = CmResourceTypePort; 408 prd->u.cprd_port.cprd_start.np_quad = 409 rman_get_start(sc->ndis_res_io); 410 prd->u.cprd_port.cprd_len = 411 rman_get_size(sc->ndis_res_io); 412 prd++; 413 } 414 415 if (sc->ndis_res_mem) { 416 prd->cprd_type = CmResourceTypeMemory; 417 prd->u.cprd_mem.cprd_start.np_quad = 418 rman_get_start(sc->ndis_res_mem); 419 prd->u.cprd_mem.cprd_len = 420 rman_get_size(sc->ndis_res_mem); 421 prd++; 422 } 423 424 if (sc->ndis_irq) { 425 prd->cprd_type = CmResourceTypeInterrupt; 426 prd->u.cprd_intr.cprd_level = 427 rman_get_start(sc->ndis_irq); 428 prd->u.cprd_intr.cprd_vector = 429 rman_get_start(sc->ndis_irq); 430 prd->u.cprd_intr.cprd_affinity = 0; 431 } 432 433 block->nmb_rlist = rl; 434 435 return(0); 436} 437 438/* 439 * Map an NDIS packet to an mbuf list. When an NDIS driver receives a 440 * packet, it will hand it to us in the form of an ndis_packet, 441 * which we need to convert to an mbuf that is then handed off 442 * to the stack. Note: we configure the mbuf list so that it uses 443 * the memory regions specified by the ndis_buffer structures in 444 * the ndis_packet as external storage. In most cases, this will 445 * point to a memory region allocated by the driver (either by 446 * ndis_malloc_withtag() or ndis_alloc_sharedmem()). We expect 447 * the driver to handle free()ing this region for is, so we set up 448 * a dummy no-op free handler for it. 449 */ 450 451int 452ndis_ptom(m0, p) 453 struct mbuf **m0; 454 ndis_packet *p; 455{ 456 struct mbuf *m, *prev = NULL; 457 ndis_buffer *buf; 458 ndis_packet_private *priv; 459 uint32_t totlen = 0; 460 461 if (p == NULL || m0 == NULL) 462 return(EINVAL); 463 464 priv = &p->np_private; 465 buf = priv->npp_head; 466 priv->npp_count = 0; 467 468 for (buf = priv->npp_head; buf != NULL; buf = buf->nb_next) { 469 if (buf == priv->npp_head) 470 MGETHDR(m, M_DONTWAIT, MT_HEADER); 471 else 472 MGET(m, M_DONTWAIT, MT_DATA); 473 if (m == NULL) { 474 m_freem(*m0); 475 *m0 = NULL; 476 return(ENOBUFS); 477 } 478 if (buf->nb_bytecount > buf->nb_size) 479 m->m_len = buf->nb_size; 480 else 481 m->m_len = buf->nb_bytecount; 482 m->m_data = buf->nb_mappedsystemva; 483 MEXTADD(m, m->m_data, m->m_len, ndis_return_packet, 484 p->np_rsvd[0], 0, EXT_NDIS); 485 m->m_ext.ext_buf = (void *)p; /* XXX */ 486 priv->npp_count++; 487 totlen += m->m_len; 488 if (m->m_flags & MT_HEADER) 489 *m0 = m; 490 else 491 prev->m_next = m; 492 prev = m; 493 } 494 495 (*m0)->m_pkthdr.len = totlen; 496 497 return(0); 498} 499 500/* 501 * Create an mbuf chain from an NDIS packet chain. 502 * This is used mainly when transmitting packets, where we need 503 * to turn an mbuf off an interface's send queue and transform it 504 * into an NDIS packet which will be fed into the NDIS driver's 505 * send routine. 506 * 507 * NDIS packets consist of two parts: an ndis_packet structure, 508 * which is vaguely analagous to the pkthdr portion of an mbuf, 509 * and one or more ndis_buffer structures, which define the 510 * actual memory segments in which the packet data resides. 511 * We need to allocate one ndis_buffer for each mbuf in a chain, 512 * plus one ndis_packet as the header. 513 */ 514 515int 516ndis_mtop(m0, p) 517 struct mbuf *m0; 518 ndis_packet **p; 519{ 520 struct mbuf *m; 521 ndis_buffer *buf = NULL, *prev = NULL; 522 ndis_packet_private *priv; 523 524 if (p == NULL || m0 == NULL) 525 return(EINVAL); 526 527 /* If caller didn't supply a packet, make one. */ 528 if (*p == NULL) { 529 *p = malloc(sizeof(ndis_packet), M_DEVBUF, M_NOWAIT|M_ZERO); 530 531 if (*p == NULL) 532 return(ENOMEM); 533 } 534 535 priv = &(*p)->np_private; 536 priv->npp_totlen = m0->m_pkthdr.len; 537 priv->npp_packetooboffset = offsetof(ndis_packet, np_oob); 538 539 for (m = m0; m != NULL; m = m->m_next) { 540 if (m->m_len == NULL) 541 continue; 542 buf = malloc(sizeof(ndis_buffer), M_DEVBUF, M_NOWAIT|M_ZERO); 543 if (buf == NULL) { 544 ndis_free_packet(*p); 545 *p = NULL; 546 return(ENOMEM); 547 } 548 549 buf->nb_bytecount = m->m_len; 550 buf->nb_mappedsystemva = m->m_data; 551 if (priv->npp_head == NULL) 552 priv->npp_head = buf; 553 else 554 prev->nb_next = buf; 555 prev = buf; 556 } 557 558 priv->npp_tail = buf; 559 560 return(0); 561} 562 563int 564ndis_get_supported_oids(arg, oids, oidcnt) 565 void *arg; 566 ndis_oid **oids; 567 int *oidcnt; 568{ 569 int len, rval; 570 ndis_oid *o; 571 572 if (arg == NULL || oids == NULL || oidcnt == NULL) 573 return(EINVAL); 574 len = 0; 575 ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, NULL, &len); 576 577 o = malloc(len, M_DEVBUF, M_NOWAIT); 578 if (o == NULL) 579 return(ENOMEM); 580 581 rval = ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, o, &len); 582 583 if (rval) { 584 free(o, M_DEVBUF); 585 return(rval); 586 } 587 588 *oids = o; 589 *oidcnt = len / 4; 590 591 return(0); 592} 593 594int 595ndis_set_info(arg, oid, buf, buflen) 596 void *arg; 597 ndis_oid oid; 598 void *buf; 599 int *buflen; 600{ 601 struct ndis_softc *sc; 602 ndis_status rval; 603 ndis_handle adapter; 604 __stdcall ndis_setinfo_handler setfunc; 605 uint32_t byteswritten = 0, bytesneeded = 0; 606 607 sc = arg; 608 setfunc = sc->ndis_chars.nmc_setinfo_func; 609 adapter = sc->ndis_block.nmb_miniportadapterctx; 610 611 rval = setfunc(adapter, oid, buf, *buflen, 612 &byteswritten, &bytesneeded); 613 614 if (byteswritten) 615 *buflen = byteswritten; 616 if (bytesneeded) 617 *buflen = bytesneeded; 618 619 if (rval == NDIS_STATUS_INVALID_LENGTH) 620 return(ENOSPC); 621 622 if (rval == NDIS_STATUS_INVALID_OID) 623 return(EINVAL); 624 625 if (rval == NDIS_STATUS_NOT_SUPPORTED || 626 rval == NDIS_STATUS_NOT_ACCEPTED) 627 return(ENOTSUP); 628 629 if (rval == NDIS_STATUS_PENDING) 630 return(EAGAIN); 631 632 return(0); 633} 634 635int 636ndis_send_packets(arg, packets, cnt) 637 void *arg; 638 ndis_packet **packets; 639 int cnt; 640{ 641 struct ndis_softc *sc; 642 ndis_handle adapter; 643 __stdcall ndis_sendmulti_handler sendfunc; 644 645 sc = arg; 646 adapter = sc->ndis_block.nmb_miniportadapterctx; 647 sendfunc = sc->ndis_chars.nmc_sendmulti_func; 648 sendfunc(adapter, packets, cnt); 649 650 return(0); 651} 652 653int 654ndis_init_dma(arg) 655 void *arg; 656{ 657 struct ndis_softc *sc; 658 int i, error; 659 660 sc = arg; 661 662 sc->ndis_tmaps = malloc(sizeof(bus_dmamap_t) * sc->ndis_maxpkts, 663 M_DEVBUF, M_NOWAIT|M_ZERO); 664 665 if (sc->ndis_tmaps == NULL) 666 return(ENOMEM); 667 668 for (i = 0; i < sc->ndis_maxpkts; i++) { 669 error = bus_dmamap_create(sc->ndis_ttag, 0, 670 &sc->ndis_tmaps[i]); 671 if (error) { 672 free(sc->ndis_tmaps, M_DEVBUF); 673 return(ENODEV); 674 } 675 } 676 677 return(0); 678} 679 680int 681ndis_destroy_dma(arg) 682 void *arg; 683{ 684 struct ndis_softc *sc; 685 struct mbuf *m; 686 ndis_packet *p = NULL; 687 int i; 688 689 sc = arg; 690 691 for (i = 0; i < sc->ndis_maxpkts; i++) { 692 if (sc->ndis_txarray[i] != NULL) { 693 p = sc->ndis_txarray[i]; 694 m = (struct mbuf *)p->np_rsvd[1]; 695 if (m != NULL) 696 m_freem(m); 697 ndis_free_packet(sc->ndis_txarray[i]); 698 } 699 bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]); 700 } 701 702 free(sc->ndis_tmaps, M_DEVBUF); 703 704 bus_dma_tag_destroy(sc->ndis_ttag); 705 706 return(0); 707} 708 709int 710ndis_reset_nic(arg) 711 void *arg; 712{ 713 struct ndis_softc *sc; 714 ndis_handle adapter; 715 __stdcall ndis_reset_handler resetfunc; 716 uint8_t addressing_reset; 717 struct ifnet *ifp; 718 719 sc = arg; 720 ifp = &sc->arpcom.ac_if; 721 adapter = sc->ndis_block.nmb_miniportadapterctx; 722 if (adapter == NULL) 723 return(EIO); 724 resetfunc = sc->ndis_chars.nmc_reset_func; 725 726 if (resetfunc == NULL) 727 return(EINVAL); 728 729 resetfunc(&addressing_reset, adapter); 730 731 return(0); 732} 733 734int 735ndis_halt_nic(arg) 736 void *arg; 737{ 738 struct ndis_softc *sc; 739 ndis_handle adapter; 740 __stdcall ndis_halt_handler haltfunc; 741 struct ifnet *ifp; 742 743 sc = arg; 744 ifp = &sc->arpcom.ac_if; 745 adapter = sc->ndis_block.nmb_miniportadapterctx; 746 if (adapter == NULL) 747 return(EIO); 748 haltfunc = sc->ndis_chars.nmc_halt_func; 749 750 if (haltfunc == NULL) 751 return(EINVAL); 752 753 haltfunc(adapter); 754 755 /* 756 * The adapter context is only valid after the init 757 * handler has been called, and is invalid once the 758 * halt handler has been called. 759 */ 760 761 sc->ndis_block.nmb_miniportadapterctx = NULL; 762 763 return(0); 764} 765 766int 767ndis_shutdown_nic(arg) 768 void *arg; 769{ 770 struct ndis_softc *sc; 771 ndis_handle adapter; 772 __stdcall ndis_shutdown_handler shutdownfunc; 773 774 775 sc = arg; 776 adapter = sc->ndis_block.nmb_miniportadapterctx; 777 if (adapter == NULL) 778 return(EIO); 779 shutdownfunc = sc->ndis_chars.nmc_shutdown_handler; 780 781 if (shutdownfunc == NULL) 782 return(EINVAL); 783 784 if (sc->ndis_chars.nmc_rsvd0 == NULL) 785 shutdownfunc(adapter); 786 else 787 shutdownfunc(sc->ndis_chars.nmc_rsvd0); 788 789 return(0); 790} 791 792int 793ndis_init_nic(arg) 794 void *arg; 795{ 796 struct ndis_softc *sc; 797 ndis_miniport_block *block; 798 __stdcall ndis_init_handler initfunc; 799 ndis_status status, openstatus = 0; 800 ndis_medium mediumarray[NdisMediumMax]; 801 uint32_t chosenmedium, i; 802 803 if (arg == NULL) 804 return(EINVAL); 805 806 sc = arg; 807 block = &sc->ndis_block; 808 initfunc = sc->ndis_chars.nmc_init_func; 809 810 for (i = 0; i < NdisMediumMax; i++) 811 mediumarray[i] = i; 812 813 status = initfunc(&openstatus, &chosenmedium, 814 mediumarray, NdisMediumMax, block, block); 815 816 /* 817 * If the init fails, blow away the other exported routines 818 * we obtained from the driver so we can't call them later. 819 * If the init failed, none of these will work. 820 */ 821 if (status != NDIS_STATUS_SUCCESS) { 822 bzero((char *)&sc->ndis_chars, 823 sizeof(ndis_miniport_characteristics)); 824 return(ENXIO); 825 } 826 827 return(0); 828} 829 830void 831ndis_enable_intr(arg) 832 void *arg; 833{ 834 struct ndis_softc *sc; 835 ndis_handle adapter; 836 __stdcall ndis_enable_interrupts_handler intrenbfunc; 837 838 sc = arg; 839 adapter = sc->ndis_block.nmb_miniportadapterctx; 840 if (adapter == NULL) 841 return; 842 intrenbfunc = sc->ndis_chars.nmc_enable_interrupts_func; 843 if (intrenbfunc == NULL) 844 return; 845 intrenbfunc(adapter); 846 847 return; 848} 849 850void 851ndis_disable_intr(arg) 852 void *arg; 853{ 854 struct ndis_softc *sc; 855 ndis_handle adapter; 856 __stdcall ndis_disable_interrupts_handler intrdisfunc; 857 858 sc = arg; 859 adapter = sc->ndis_block.nmb_miniportadapterctx; 860 if (adapter == NULL) 861 return; 862 intrdisfunc = sc->ndis_chars.nmc_disable_interrupts_func; 863 if (intrdisfunc == NULL) 864 return; 865 intrdisfunc(adapter); 866 867 return; 868} 869 870int 871ndis_isr(arg, ourintr, callhandler) 872 void *arg; 873 int *ourintr; 874 int *callhandler; 875{ 876 struct ndis_softc *sc; 877 ndis_handle adapter; 878 __stdcall ndis_isr_handler isrfunc; 879 uint8_t accepted, queue; 880 881 if (arg == NULL || ourintr == NULL || callhandler == NULL) 882 return(EINVAL); 883 884 sc = arg; 885 adapter = sc->ndis_block.nmb_miniportadapterctx; 886 isrfunc = sc->ndis_chars.nmc_isr_func; 887 isrfunc(&accepted, &queue, adapter); 888 *ourintr = accepted; 889 *callhandler = queue; 890 891 return(0); 892} 893 894int 895ndis_intrhand(arg) 896 void *arg; 897{ 898 struct ndis_softc *sc; 899 ndis_handle adapter; 900 __stdcall ndis_interrupt_handler intrfunc; 901 902 if (arg == NULL) 903 return(EINVAL); 904 905 sc = arg; 906 adapter = sc->ndis_block.nmb_miniportadapterctx; 907 intrfunc = sc->ndis_chars.nmc_interrupt_func; 908 intrfunc(adapter); 909 910 return(0); 911} 912 913int 914ndis_get_info(arg, oid, buf, buflen) 915 void *arg; 916 ndis_oid oid; 917 void *buf; 918 int *buflen; 919{ 920 struct ndis_softc *sc; 921 ndis_status rval; 922 ndis_handle adapter; 923 __stdcall ndis_queryinfo_handler queryfunc; 924 uint32_t byteswritten = 0, bytesneeded = 0; 925 926 sc = arg; 927 queryfunc = sc->ndis_chars.nmc_queryinfo_func; 928 adapter = sc->ndis_block.nmb_miniportadapterctx; 929 930 rval = queryfunc(adapter, oid, buf, *buflen, 931 &byteswritten, &bytesneeded); 932 933 if (byteswritten) 934 *buflen = byteswritten; 935 if (bytesneeded) 936 *buflen = bytesneeded; 937 938 if (rval == NDIS_STATUS_INVALID_LENGTH || 939 rval == NDIS_STATUS_BUFFER_TOO_SHORT) 940 return(ENOSPC); 941 942 if (rval == NDIS_STATUS_INVALID_OID) 943 return(EINVAL); 944 945 if (rval == NDIS_STATUS_NOT_SUPPORTED || 946 rval == NDIS_STATUS_NOT_ACCEPTED) 947 return(ENOTSUP); 948 949 if (rval == NDIS_STATUS_PENDING) 950 return(EAGAIN); 951 952 return(0); 953} 954 955int 956ndis_unload_driver(arg) 957 void *arg; 958{ 959 struct ndis_softc *sc; 960 961 sc = arg; 962 963 free(sc->ndis_block.nmb_rlist, M_DEVBUF); 964 965 ndis_flush_sysctls(sc); 966 ndis_libfini(); 967 ntoskrnl_libfini(); 968 969 return(0); 970} 971 972int 973ndis_load_driver(img, arg) 974 vm_offset_t img; 975 void *arg; 976{ 977 __stdcall driver_entry entry; 978 image_optional_header opt_hdr; 979 image_import_descriptor imp_desc; 980 ndis_unicode_string dummystr; 981 ndis_driver_object drv; 982 ndis_miniport_block *block; 983 ndis_status status; 984 int idx; 985 uint32_t *ptr; 986 struct ndis_softc *sc; 987 988 sc = arg; 989 990 /* Perform text relocation */ 991 if (pe_relocate(img)) 992 return(ENOEXEC); 993 994 /* Dynamically link the NDIS.SYS routines -- required. */ 995 if (pe_patch_imports(img, "NDIS", ndis_functbl)) 996 return(ENOEXEC); 997 998 /* Dynamically link the HAL.dll routines -- also required. */ 999 if (pe_patch_imports(img, "HAL", hal_functbl)) 1000 return(ENOEXEC); 1001 1002 /* Dynamically link ntoskrnl.exe -- optional. */ 1003 if (pe_get_import_descriptor(img, &imp_desc, "ntoskrnl") == 0) { 1004 if (pe_patch_imports(img, "ntoskrnl", ntoskrnl_functbl)) 1005 return(ENOEXEC); 1006 } 1007 1008 /* Initialize subsystems */ 1009 ndis_libinit(); 1010 ntoskrnl_libinit(); 1011 1012 /* Locate the driver entry point */ 1013 pe_get_optional_header(img, &opt_hdr); 1014 entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr); 1015 1016 /* 1017 * Now call the DriverEntry() routine. This will cause 1018 * a callout to the NdisInitializeWrapper() and 1019 * NdisMRegisterMiniport() routines. 1020 */ 1021 dummystr.nus_len = strlen(NDIS_DUMMY_PATH); 1022 dummystr.nus_maxlen = strlen(NDIS_DUMMY_PATH); 1023 dummystr.nus_buf = NULL; 1024 ndis_ascii_to_unicode(NDIS_DUMMY_PATH, &dummystr.nus_buf); 1025 drv.ndo_ifname = "ndis0"; 1026 1027 status = entry(&drv, &dummystr); 1028 1029 free (dummystr.nus_buf, M_DEVBUF); 1030 1031 if (status != NDIS_STATUS_SUCCESS) 1032 return(ENODEV); 1033 1034 /* 1035 * Now that we have the miniport driver characteristics, 1036 * create an NDIS block and call the init handler. 1037 * This will cause the driver to try to probe for 1038 * a device. 1039 */ 1040 1041 block = &sc->ndis_block; 1042 bcopy((char *)&drv.ndo_chars, (char *)&sc->ndis_chars, 1043 sizeof(ndis_miniport_characteristics)); 1044 1045 /*block->nmb_signature = 0xcafebabe;*/ 1046 1047 ptr = (uint32_t *)block; 1048 for (idx = 0; idx < sizeof(ndis_miniport_block) / 4; idx++) { 1049 *ptr = idx | 0xdead0000; 1050 ptr++; 1051 } 1052 1053 block->nmb_signature = (void *)0xcafebabe; 1054 block->nmb_setdone_func = ndis_setdone_func; 1055 block->nmb_querydone_func = ndis_getdone_func; 1056 block->nmb_status_func = ndis_status_func; 1057 block->nmb_statusdone_func = ndis_statusdone_func; 1058 block->nmb_resetdone_func = ndis_resetdone_func; 1059 1060 block->nmb_ifp = &sc->arpcom.ac_if; 1061 block->nmb_dev = sc->ndis_dev; 1062 1063 return(0); 1064}
|