kern_ndis.c revision 123695
1123474Swpaul/* 2123474Swpaul * Copyright (c) 2003 3123474Swpaul * Bill Paul <wpaul@windriver.com>. All rights reserved. 4123474Swpaul * 5123474Swpaul * Redistribution and use in source and binary forms, with or without 6123474Swpaul * modification, are permitted provided that the following conditions 7123474Swpaul * are met: 8123474Swpaul * 1. Redistributions of source code must retain the above copyright 9123474Swpaul * notice, this list of conditions and the following disclaimer. 10123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright 11123474Swpaul * notice, this list of conditions and the following disclaimer in the 12123474Swpaul * documentation and/or other materials provided with the distribution. 13123474Swpaul * 3. All advertising materials mentioning features or use of this software 14123474Swpaul * must display the following acknowledgement: 15123474Swpaul * This product includes software developed by Bill Paul. 16123474Swpaul * 4. Neither the name of the author nor the names of any co-contributors 17123474Swpaul * may be used to endorse or promote products derived from this software 18123474Swpaul * without specific prior written permission. 19123474Swpaul * 20123474Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21123474Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22123474Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23123474Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 24123474Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25123474Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26123474Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27123474Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28123474Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29123474Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 30123474Swpaul * THE POSSIBILITY OF SUCH DAMAGE. 31123474Swpaul */ 32123474Swpaul 33123474Swpaul#include <sys/cdefs.h> 34123474Swpaul__FBSDID("$FreeBSD: head/sys/compat/ndis/kern_ndis.c 123695 2003-12-21 00:00:08Z wpaul $"); 35123474Swpaul 36123474Swpaul#include <sys/param.h> 37123474Swpaul#include <sys/types.h> 38123474Swpaul#include <sys/errno.h> 39123474Swpaul#include <sys/callout.h> 40123474Swpaul#include <sys/socket.h> 41123474Swpaul#include <sys/queue.h> 42123474Swpaul#include <sys/sysctl.h> 43123474Swpaul#include <sys/systm.h> 44123474Swpaul#include <sys/malloc.h> 45123474Swpaul#include <sys/lock.h> 46123474Swpaul#include <sys/mutex.h> 47123474Swpaul#include <sys/conf.h> 48123474Swpaul 49123474Swpaul#include <sys/kernel.h> 50123474Swpaul#include <machine/bus.h> 51123474Swpaul#include <machine/resource.h> 52123474Swpaul#include <sys/bus.h> 53123474Swpaul#include <sys/rman.h> 54123474Swpaul 55123474Swpaul#include <net/if.h> 56123474Swpaul#include <net/if_arp.h> 57123474Swpaul#include <net/ethernet.h> 58123474Swpaul#include <net/if_dl.h> 59123474Swpaul#include <net/if_media.h> 60123474Swpaul 61123695Swpaul#include <net80211/ieee80211_var.h> 62123695Swpaul#include <net80211/ieee80211_ioctl.h> 63123695Swpaul 64123474Swpaul#include <dev/pccard/pccardvar.h> 65123474Swpaul#include "card_if.h" 66123474Swpaul 67123474Swpaul#include <compat/ndis/pe_var.h> 68123474Swpaul#include <compat/ndis/resource_var.h> 69123474Swpaul#include <compat/ndis/ndis_var.h> 70123474Swpaul#include <compat/ndis/hal_var.h> 71123474Swpaul#include <compat/ndis/ntoskrnl_var.h> 72123474Swpaul#include <compat/ndis/cfg_var.h> 73123474Swpaul#include <dev/if_ndis/if_ndisvar.h> 74123474Swpaul 75123474Swpaul#define __stdcall __attribute__((__stdcall__)) 76123474Swpaul#define NDIS_DUMMY_PATH "\\\\some\\bogus\\path" 77123474Swpaul 78123474Swpaul__stdcall static void ndis_status_func(ndis_handle, ndis_status, 79123474Swpaul void *, uint32_t); 80123474Swpaul__stdcall static void ndis_statusdone_func(ndis_handle); 81123474Swpaul__stdcall static void ndis_setdone_func(ndis_handle, ndis_status); 82123535Swpaul__stdcall static void ndis_getdone_func(ndis_handle, ndis_status); 83123474Swpaul__stdcall static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t); 84123474Swpaul 85123474Swpaul/* 86123474Swpaul * This allows us to export our symbols to other modules. 87123474Swpaul * Note that we call ourselves 'ndisapi' to avoid a namespace 88123474Swpaul * collision with if_ndis.ko, which internally calls itself 89123474Swpaul * 'ndis.' 90123474Swpaul */ 91123474Swpaulstatic int 92123474Swpaulndis_modevent(module_t mod, int cmd, void *arg) 93123474Swpaul{ 94123474Swpaul return(0); 95123474Swpaul} 96123474SwpaulDEV_MODULE(ndisapi, ndis_modevent, NULL); 97123474SwpaulMODULE_VERSION(ndisapi, 1); 98123474Swpaul 99123474Swpaul 100123474Swpaul__stdcall static void 101123474Swpaulndis_status_func(adapter, status, sbuf, slen) 102123474Swpaul ndis_handle adapter; 103123474Swpaul ndis_status status; 104123474Swpaul void *sbuf; 105123474Swpaul uint32_t slen; 106123474Swpaul{ 107123474Swpaul printf ("status: %x\n", status); 108123474Swpaul return; 109123474Swpaul} 110123474Swpaul 111123474Swpaul__stdcall static void 112123474Swpaulndis_statusdone_func(adapter) 113123474Swpaul ndis_handle adapter; 114123474Swpaul{ 115123474Swpaul printf ("status complete\n"); 116123474Swpaul return; 117123474Swpaul} 118123474Swpaul 119123474Swpaul__stdcall static void 120123474Swpaulndis_setdone_func(adapter, status) 121123474Swpaul ndis_handle adapter; 122123474Swpaul ndis_status status; 123123474Swpaul{ 124123695Swpaul ndis_miniport_block *block; 125123695Swpaul block = adapter; 126123695Swpaul 127123695Swpaul block->nmb_setstat = status; 128123695Swpaul wakeup(&block->nmb_wkupdpctimer); 129123474Swpaul return; 130123474Swpaul} 131123474Swpaul 132123474Swpaul__stdcall static void 133123535Swpaulndis_getdone_func(adapter, status) 134123535Swpaul ndis_handle adapter; 135123535Swpaul ndis_status status; 136123535Swpaul{ 137123695Swpaul ndis_miniport_block *block; 138123695Swpaul block = adapter; 139123695Swpaul 140123695Swpaul block->nmb_getstat = status; 141123695Swpaul wakeup(&block->nmb_wkupdpctimer); 142123535Swpaul return; 143123535Swpaul} 144123535Swpaul 145123535Swpaul__stdcall static void 146123474Swpaulndis_resetdone_func(adapter, status, addressingreset) 147123474Swpaul ndis_handle adapter; 148123474Swpaul ndis_status status; 149123474Swpaul uint8_t addressingreset; 150123474Swpaul{ 151123474Swpaul printf ("reset done...\n"); 152123474Swpaul return; 153123474Swpaul} 154123474Swpaul 155123474Swpaul#define NDIS_AM_RID 3 156123474Swpaul 157123474Swpaulint 158123474Swpaulndis_alloc_amem(arg) 159123474Swpaul void *arg; 160123474Swpaul{ 161123474Swpaul struct ndis_softc *sc; 162123474Swpaul int error, rid; 163123474Swpaul 164123474Swpaul if (arg == NULL) 165123474Swpaul return(EINVAL); 166123474Swpaul 167123474Swpaul sc = arg; 168123474Swpaul rid = NDIS_AM_RID; 169123474Swpaul sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY, 170123474Swpaul &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE); 171123474Swpaul 172123474Swpaul if (sc->ndis_res_am == NULL) { 173123474Swpaul printf("ndis%d: failed to allocate attribute memory\n", 174123474Swpaul sc->ndis_unit); 175123474Swpaul return(ENXIO); 176123474Swpaul } 177123474Swpaul 178123474Swpaul error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev), 179123474Swpaul sc->ndis_dev, rid, 0, NULL); 180123474Swpaul 181123474Swpaul if (error) { 182123474Swpaul printf("ndis%d: CARD_SET_MEMORY_OFFSET() returned 0x%x\n", 183123474Swpaul sc->ndis_unit, error); 184123474Swpaul return(error); 185123474Swpaul } 186123474Swpaul 187123474Swpaul error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev), 188123474Swpaul sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); 189123474Swpaul 190123474Swpaul if (error) { 191123474Swpaul printf("ndis%d: CARD_SET_RES_FLAGS() returned 0x%x\n", 192123474Swpaul sc->ndis_unit, error); 193123474Swpaul return(error); 194123474Swpaul } 195123474Swpaul 196123474Swpaul return(0); 197123474Swpaul} 198123474Swpaul 199123474Swpaulint 200123474Swpaulndis_create_sysctls(arg) 201123474Swpaul void *arg; 202123474Swpaul{ 203123474Swpaul struct ndis_softc *sc; 204123474Swpaul ndis_cfg *vals; 205123474Swpaul char buf[256]; 206123474Swpaul 207123474Swpaul if (arg == NULL) 208123474Swpaul return(EINVAL); 209123474Swpaul 210123474Swpaul sc = arg; 211123474Swpaul vals = sc->ndis_regvals; 212123474Swpaul 213123474Swpaul TAILQ_INIT(&sc->ndis_cfglist_head); 214123474Swpaul 215123474Swpaul /* Create the sysctl tree. */ 216123474Swpaul 217123474Swpaul sc->ndis_tree = SYSCTL_ADD_NODE(&sc->ndis_ctx, 218123474Swpaul SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, 219123474Swpaul device_get_nameunit(sc->ndis_dev), CTLFLAG_RD, 0, 220123474Swpaul device_get_desc(sc->ndis_dev)); 221123474Swpaul 222123474Swpaul /* Add the driver-specific registry keys. */ 223123474Swpaul 224123474Swpaul vals = sc->ndis_regvals; 225123474Swpaul while(1) { 226123474Swpaul if (vals->nc_cfgkey == NULL) 227123474Swpaul break; 228123620Swpaul if (vals->nc_idx != sc->ndis_devidx) { 229123620Swpaul vals++; 230123620Swpaul continue; 231123620Swpaul } 232123474Swpaul SYSCTL_ADD_STRING(&sc->ndis_ctx, 233123474Swpaul SYSCTL_CHILDREN(sc->ndis_tree), 234123474Swpaul OID_AUTO, vals->nc_cfgkey, 235123474Swpaul CTLFLAG_RW, vals->nc_val, 236123474Swpaul sizeof(vals->nc_val), 237123474Swpaul vals->nc_cfgdesc); 238123474Swpaul vals++; 239123474Swpaul } 240123474Swpaul 241123474Swpaul /* Now add a couple of builtin keys. */ 242123474Swpaul 243123474Swpaul /* 244123474Swpaul * Environment can be either Windows (0) or WindowsNT (1). 245123474Swpaul * We qualify as the latter. 246123474Swpaul */ 247123474Swpaul ndis_add_sysctl(sc, "Environment", 248123474Swpaul "Windows environment", "1", CTLFLAG_RD); 249123474Swpaul 250123474Swpaul /* NDIS version should be 5.1. */ 251123474Swpaul ndis_add_sysctl(sc, "NdisVersion", 252123474Swpaul "NDIS API Version", "0x00050001", CTLFLAG_RD); 253123474Swpaul 254123474Swpaul /* Bus type (PCI, PCMCIA, etc...) */ 255123474Swpaul sprintf(buf, "%d\n", (int)sc->ndis_iftype); 256123474Swpaul ndis_add_sysctl(sc, "BusType", "Bus Type", buf, CTLFLAG_RD); 257123474Swpaul 258123474Swpaul if (sc->ndis_res_io != NULL) { 259123474Swpaul sprintf(buf, "0x%lx\n", rman_get_start(sc->ndis_res_io)); 260123474Swpaul ndis_add_sysctl(sc, "IOBaseAddress", 261123474Swpaul "Base I/O Address", buf, CTLFLAG_RD); 262123474Swpaul } 263123474Swpaul 264123474Swpaul if (sc->ndis_irq != NULL) { 265123474Swpaul sprintf(buf, "%lu\n", rman_get_start(sc->ndis_irq)); 266123474Swpaul ndis_add_sysctl(sc, "InterruptNumber", 267123474Swpaul "Interrupt Number", buf, CTLFLAG_RD); 268123474Swpaul } 269123474Swpaul 270123474Swpaul return(0); 271123474Swpaul} 272123474Swpaul 273123474Swpaulint 274123474Swpaulndis_add_sysctl(arg, key, desc, val, flag) 275123474Swpaul void *arg; 276123474Swpaul char *key; 277123474Swpaul char *desc; 278123474Swpaul char *val; 279123474Swpaul int flag; 280123474Swpaul{ 281123474Swpaul struct ndis_softc *sc; 282123474Swpaul struct ndis_cfglist *cfg; 283123474Swpaul char descstr[256]; 284123474Swpaul 285123474Swpaul sc = arg; 286123474Swpaul 287123474Swpaul cfg = malloc(sizeof(struct ndis_cfglist), M_DEVBUF, M_NOWAIT|M_ZERO); 288123474Swpaul 289123474Swpaul if (cfg == NULL) 290123474Swpaul return(ENOMEM); 291123474Swpaul 292123474Swpaul cfg->ndis_cfg.nc_cfgkey = strdup(key, M_DEVBUF); 293123474Swpaul if (desc == NULL) { 294123474Swpaul snprintf(descstr, sizeof(descstr), "%s (dynamic)", key); 295123474Swpaul cfg->ndis_cfg.nc_cfgdesc = strdup(descstr, M_DEVBUF); 296123474Swpaul } else 297123474Swpaul cfg->ndis_cfg.nc_cfgdesc = strdup(desc, M_DEVBUF); 298123474Swpaul strcpy(cfg->ndis_cfg.nc_val, val); 299123474Swpaul 300123474Swpaul TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link); 301123474Swpaul 302123474Swpaul SYSCTL_ADD_STRING(&sc->ndis_ctx, SYSCTL_CHILDREN(sc->ndis_tree), 303123474Swpaul OID_AUTO, cfg->ndis_cfg.nc_cfgkey, flag, 304123474Swpaul cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val), 305123474Swpaul cfg->ndis_cfg.nc_cfgdesc); 306123474Swpaul 307123474Swpaul return(0); 308123474Swpaul} 309123474Swpaul 310123474Swpaulint 311123474Swpaulndis_flush_sysctls(arg) 312123474Swpaul void *arg; 313123474Swpaul{ 314123474Swpaul struct ndis_softc *sc; 315123474Swpaul struct ndis_cfglist *cfg; 316123474Swpaul 317123474Swpaul sc = arg; 318123474Swpaul 319123474Swpaul while (!TAILQ_EMPTY(&sc->ndis_cfglist_head)) { 320123474Swpaul cfg = TAILQ_FIRST(&sc->ndis_cfglist_head); 321123474Swpaul TAILQ_REMOVE(&sc->ndis_cfglist_head, cfg, link); 322123474Swpaul free(cfg->ndis_cfg.nc_cfgkey, M_DEVBUF); 323123474Swpaul free(cfg->ndis_cfg.nc_cfgdesc, M_DEVBUF); 324123474Swpaul free(cfg, M_DEVBUF); 325123474Swpaul } 326123474Swpaul 327123474Swpaul return(0); 328123474Swpaul} 329123474Swpaul 330123474Swpaulvoid 331123474Swpaulndis_return_packet(packet, arg) 332123474Swpaul void *packet; 333123474Swpaul void *arg; 334123474Swpaul{ 335123474Swpaul struct ndis_softc *sc; 336123474Swpaul ndis_handle adapter; 337123535Swpaul ndis_packet *p; 338123474Swpaul __stdcall ndis_return_handler returnfunc; 339123474Swpaul 340123474Swpaul if (arg == NULL || packet == NULL) 341123474Swpaul return; 342123474Swpaul 343123535Swpaul p = packet; 344123535Swpaul 345123535Swpaul /* Decrement refcount. */ 346123535Swpaul p->np_private.npp_count--; 347123535Swpaul 348123535Swpaul /* Release packet when refcount hits zero, otherwise return. */ 349123535Swpaul if (p->np_private.npp_count) 350123535Swpaul return; 351123536Swpaul 352123474Swpaul sc = arg; 353123474Swpaul returnfunc = sc->ndis_chars.nmc_return_packet_func; 354123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 355123474Swpaul if (returnfunc == NULL) 356123474Swpaul ndis_free_packet((ndis_packet *)packet); 357123474Swpaul else 358123474Swpaul returnfunc(adapter, (ndis_packet *)packet); 359123474Swpaul return; 360123474Swpaul} 361123474Swpaul 362123474Swpaulvoid 363123474Swpaulndis_free_bufs(b0) 364123474Swpaul ndis_buffer *b0; 365123474Swpaul{ 366123474Swpaul ndis_buffer *next; 367123474Swpaul 368123474Swpaul if (b0 == NULL) 369123474Swpaul return; 370123474Swpaul 371123474Swpaul while(b0 != NULL) { 372123474Swpaul next = b0->nb_next; 373123474Swpaul free (b0, M_DEVBUF); 374123474Swpaul b0 = next; 375123474Swpaul } 376123474Swpaul 377123474Swpaul return; 378123474Swpaul} 379123474Swpaul 380123474Swpaulvoid 381123474Swpaulndis_free_packet(p) 382123474Swpaul ndis_packet *p; 383123474Swpaul{ 384123474Swpaul if (p == NULL) 385123474Swpaul return; 386123474Swpaul 387123474Swpaul ndis_free_bufs(p->np_private.npp_head); 388123474Swpaul free(p, M_DEVBUF); 389123474Swpaul 390123474Swpaul return; 391123474Swpaul} 392123474Swpaul 393123474Swpaulint 394123474Swpaulndis_convert_res(arg) 395123474Swpaul void *arg; 396123474Swpaul{ 397123474Swpaul struct ndis_softc *sc; 398123474Swpaul ndis_resource_list *rl = NULL; 399123474Swpaul cm_partial_resource_desc *prd = NULL; 400123474Swpaul ndis_miniport_block *block; 401123474Swpaul 402123474Swpaul sc = arg; 403123474Swpaul block = &sc->ndis_block; 404123474Swpaul 405123474Swpaul rl = malloc(sizeof(ndis_resource_list) + 406123474Swpaul (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)), 407123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 408123474Swpaul 409123474Swpaul if (rl == NULL) 410123474Swpaul return(ENOMEM); 411123474Swpaul 412123474Swpaul rl->cprl_version = 5; 413123474Swpaul rl->cprl_version = 1; 414123474Swpaul rl->cprl_count = sc->ndis_rescnt; 415123474Swpaul 416123474Swpaul prd = rl->cprl_partial_descs; 417123474Swpaul if (sc->ndis_res_io) { 418123474Swpaul prd->cprd_type = CmResourceTypePort; 419123474Swpaul prd->u.cprd_port.cprd_start.np_quad = 420123474Swpaul rman_get_start(sc->ndis_res_io); 421123474Swpaul prd->u.cprd_port.cprd_len = 422123474Swpaul rman_get_size(sc->ndis_res_io); 423123474Swpaul prd++; 424123474Swpaul } 425123474Swpaul 426123474Swpaul if (sc->ndis_res_mem) { 427123474Swpaul prd->cprd_type = CmResourceTypeMemory; 428123474Swpaul prd->u.cprd_mem.cprd_start.np_quad = 429123474Swpaul rman_get_start(sc->ndis_res_mem); 430123474Swpaul prd->u.cprd_mem.cprd_len = 431123474Swpaul rman_get_size(sc->ndis_res_mem); 432123474Swpaul prd++; 433123474Swpaul } 434123474Swpaul 435123474Swpaul if (sc->ndis_irq) { 436123474Swpaul prd->cprd_type = CmResourceTypeInterrupt; 437123474Swpaul prd->u.cprd_intr.cprd_level = 438123474Swpaul rman_get_start(sc->ndis_irq); 439123474Swpaul prd->u.cprd_intr.cprd_vector = 440123474Swpaul rman_get_start(sc->ndis_irq); 441123474Swpaul prd->u.cprd_intr.cprd_affinity = 0; 442123474Swpaul } 443123474Swpaul 444123474Swpaul block->nmb_rlist = rl; 445123474Swpaul 446123474Swpaul return(0); 447123474Swpaul} 448123474Swpaul 449123474Swpaul/* 450123474Swpaul * Map an NDIS packet to an mbuf list. When an NDIS driver receives a 451123474Swpaul * packet, it will hand it to us in the form of an ndis_packet, 452123474Swpaul * which we need to convert to an mbuf that is then handed off 453123474Swpaul * to the stack. Note: we configure the mbuf list so that it uses 454123474Swpaul * the memory regions specified by the ndis_buffer structures in 455123474Swpaul * the ndis_packet as external storage. In most cases, this will 456123474Swpaul * point to a memory region allocated by the driver (either by 457123474Swpaul * ndis_malloc_withtag() or ndis_alloc_sharedmem()). We expect 458123474Swpaul * the driver to handle free()ing this region for is, so we set up 459123474Swpaul * a dummy no-op free handler for it. 460123474Swpaul */ 461123474Swpaul 462123474Swpaulint 463123474Swpaulndis_ptom(m0, p) 464123474Swpaul struct mbuf **m0; 465123474Swpaul ndis_packet *p; 466123474Swpaul{ 467123474Swpaul struct mbuf *m, *prev = NULL; 468123474Swpaul ndis_buffer *buf; 469123474Swpaul ndis_packet_private *priv; 470123474Swpaul uint32_t totlen = 0; 471123474Swpaul 472123474Swpaul if (p == NULL || m0 == NULL) 473123474Swpaul return(EINVAL); 474123474Swpaul 475123474Swpaul priv = &p->np_private; 476123474Swpaul buf = priv->npp_head; 477123535Swpaul priv->npp_count = 0; 478123474Swpaul 479123474Swpaul for (buf = priv->npp_head; buf != NULL; buf = buf->nb_next) { 480123474Swpaul if (buf == priv->npp_head) 481123474Swpaul MGETHDR(m, M_DONTWAIT, MT_HEADER); 482123474Swpaul else 483123474Swpaul MGET(m, M_DONTWAIT, MT_DATA); 484123474Swpaul if (m == NULL) { 485123474Swpaul m_freem(*m0); 486123474Swpaul *m0 = NULL; 487123474Swpaul return(ENOBUFS); 488123474Swpaul } 489123488Swpaul if (buf->nb_bytecount > buf->nb_size) 490123474Swpaul m->m_len = buf->nb_size; 491123474Swpaul else 492123474Swpaul m->m_len = buf->nb_bytecount; 493123474Swpaul m->m_data = buf->nb_mappedsystemva; 494123535Swpaul MEXTADD(m, m->m_data, m->m_len, ndis_return_packet, 495123535Swpaul p->np_rsvd[0], 0, EXT_NDIS); 496123535Swpaul m->m_ext.ext_buf = (void *)p; /* XXX */ 497123535Swpaul priv->npp_count++; 498123474Swpaul totlen += m->m_len; 499123474Swpaul if (m->m_flags & MT_HEADER) 500123474Swpaul *m0 = m; 501123474Swpaul else 502123474Swpaul prev->m_next = m; 503123474Swpaul prev = m; 504123474Swpaul } 505123474Swpaul 506123474Swpaul (*m0)->m_pkthdr.len = totlen; 507123474Swpaul 508123474Swpaul return(0); 509123474Swpaul} 510123474Swpaul 511123474Swpaul/* 512123474Swpaul * Create an mbuf chain from an NDIS packet chain. 513123474Swpaul * This is used mainly when transmitting packets, where we need 514123474Swpaul * to turn an mbuf off an interface's send queue and transform it 515123474Swpaul * into an NDIS packet which will be fed into the NDIS driver's 516123474Swpaul * send routine. 517123474Swpaul * 518123474Swpaul * NDIS packets consist of two parts: an ndis_packet structure, 519123474Swpaul * which is vaguely analagous to the pkthdr portion of an mbuf, 520123474Swpaul * and one or more ndis_buffer structures, which define the 521123474Swpaul * actual memory segments in which the packet data resides. 522123474Swpaul * We need to allocate one ndis_buffer for each mbuf in a chain, 523123474Swpaul * plus one ndis_packet as the header. 524123474Swpaul */ 525123474Swpaul 526123474Swpaulint 527123474Swpaulndis_mtop(m0, p) 528123474Swpaul struct mbuf *m0; 529123474Swpaul ndis_packet **p; 530123474Swpaul{ 531123474Swpaul struct mbuf *m; 532123474Swpaul ndis_buffer *buf = NULL, *prev = NULL; 533123474Swpaul ndis_packet_private *priv; 534123474Swpaul 535123474Swpaul if (p == NULL || m0 == NULL) 536123474Swpaul return(EINVAL); 537123474Swpaul 538123474Swpaul /* If caller didn't supply a packet, make one. */ 539123474Swpaul if (*p == NULL) { 540123474Swpaul *p = malloc(sizeof(ndis_packet), M_DEVBUF, M_NOWAIT|M_ZERO); 541123474Swpaul 542123474Swpaul if (*p == NULL) 543123474Swpaul return(ENOMEM); 544123474Swpaul } 545123474Swpaul 546123474Swpaul priv = &(*p)->np_private; 547123474Swpaul priv->npp_totlen = m0->m_pkthdr.len; 548123474Swpaul priv->npp_packetooboffset = offsetof(ndis_packet, np_oob); 549123474Swpaul 550123474Swpaul for (m = m0; m != NULL; m = m->m_next) { 551123474Swpaul if (m->m_len == NULL) 552123474Swpaul continue; 553123474Swpaul buf = malloc(sizeof(ndis_buffer), M_DEVBUF, M_NOWAIT|M_ZERO); 554123474Swpaul if (buf == NULL) { 555123474Swpaul ndis_free_packet(*p); 556123474Swpaul *p = NULL; 557123474Swpaul return(ENOMEM); 558123474Swpaul } 559123474Swpaul 560123474Swpaul buf->nb_bytecount = m->m_len; 561123474Swpaul buf->nb_mappedsystemva = m->m_data; 562123474Swpaul if (priv->npp_head == NULL) 563123474Swpaul priv->npp_head = buf; 564123474Swpaul else 565123474Swpaul prev->nb_next = buf; 566123474Swpaul prev = buf; 567123474Swpaul } 568123474Swpaul 569123474Swpaul priv->npp_tail = buf; 570123474Swpaul 571123474Swpaul return(0); 572123474Swpaul} 573123474Swpaul 574123474Swpaulint 575123474Swpaulndis_get_supported_oids(arg, oids, oidcnt) 576123474Swpaul void *arg; 577123474Swpaul ndis_oid **oids; 578123474Swpaul int *oidcnt; 579123474Swpaul{ 580123474Swpaul int len, rval; 581123474Swpaul ndis_oid *o; 582123474Swpaul 583123474Swpaul if (arg == NULL || oids == NULL || oidcnt == NULL) 584123474Swpaul return(EINVAL); 585123474Swpaul len = 0; 586123474Swpaul ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, NULL, &len); 587123474Swpaul 588123474Swpaul o = malloc(len, M_DEVBUF, M_NOWAIT); 589123474Swpaul if (o == NULL) 590123474Swpaul return(ENOMEM); 591123474Swpaul 592123474Swpaul rval = ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, o, &len); 593123474Swpaul 594123474Swpaul if (rval) { 595123474Swpaul free(o, M_DEVBUF); 596123474Swpaul return(rval); 597123474Swpaul } 598123474Swpaul 599123474Swpaul *oids = o; 600123474Swpaul *oidcnt = len / 4; 601123474Swpaul 602123474Swpaul return(0); 603123474Swpaul} 604123474Swpaul 605123474Swpaulint 606123474Swpaulndis_set_info(arg, oid, buf, buflen) 607123474Swpaul void *arg; 608123474Swpaul ndis_oid oid; 609123474Swpaul void *buf; 610123474Swpaul int *buflen; 611123474Swpaul{ 612123474Swpaul struct ndis_softc *sc; 613123474Swpaul ndis_status rval; 614123474Swpaul ndis_handle adapter; 615123474Swpaul __stdcall ndis_setinfo_handler setfunc; 616123474Swpaul uint32_t byteswritten = 0, bytesneeded = 0; 617123695Swpaul struct timeval tv; 618123695Swpaul int error; 619123474Swpaul 620123474Swpaul sc = arg; 621123474Swpaul setfunc = sc->ndis_chars.nmc_setinfo_func; 622123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 623123474Swpaul 624123474Swpaul rval = setfunc(adapter, oid, buf, *buflen, 625123474Swpaul &byteswritten, &bytesneeded); 626123474Swpaul 627123695Swpaul if (rval == NDIS_STATUS_PENDING) { 628123695Swpaul tv.tv_sec = 60; 629123695Swpaul tv.tv_usec = 0; 630123695Swpaul error = tsleep(&sc->ndis_block.nmb_wkupdpctimer, 631123695Swpaul PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 632123695Swpaul rval = sc->ndis_block.nmb_setstat; 633123695Swpaul } 634123695Swpaul 635123474Swpaul if (byteswritten) 636123474Swpaul *buflen = byteswritten; 637123474Swpaul if (bytesneeded) 638123474Swpaul *buflen = bytesneeded; 639123474Swpaul 640123474Swpaul if (rval == NDIS_STATUS_INVALID_LENGTH) 641123474Swpaul return(ENOSPC); 642123474Swpaul 643123474Swpaul if (rval == NDIS_STATUS_INVALID_OID) 644123474Swpaul return(EINVAL); 645123474Swpaul 646123474Swpaul if (rval == NDIS_STATUS_NOT_SUPPORTED || 647123474Swpaul rval == NDIS_STATUS_NOT_ACCEPTED) 648123474Swpaul return(ENOTSUP); 649123474Swpaul 650123474Swpaul return(0); 651123474Swpaul} 652123474Swpaul 653123474Swpaulint 654123474Swpaulndis_send_packets(arg, packets, cnt) 655123474Swpaul void *arg; 656123474Swpaul ndis_packet **packets; 657123474Swpaul int cnt; 658123474Swpaul{ 659123474Swpaul struct ndis_softc *sc; 660123474Swpaul ndis_handle adapter; 661123474Swpaul __stdcall ndis_sendmulti_handler sendfunc; 662123474Swpaul 663123474Swpaul sc = arg; 664123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 665123474Swpaul sendfunc = sc->ndis_chars.nmc_sendmulti_func; 666123474Swpaul sendfunc(adapter, packets, cnt); 667123474Swpaul 668123474Swpaul return(0); 669123474Swpaul} 670123474Swpaul 671123474Swpaulint 672123474Swpaulndis_init_dma(arg) 673123474Swpaul void *arg; 674123474Swpaul{ 675123474Swpaul struct ndis_softc *sc; 676123474Swpaul int i, error; 677123474Swpaul 678123474Swpaul sc = arg; 679123474Swpaul 680123474Swpaul sc->ndis_tmaps = malloc(sizeof(bus_dmamap_t) * sc->ndis_maxpkts, 681123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 682123474Swpaul 683123474Swpaul if (sc->ndis_tmaps == NULL) 684123474Swpaul return(ENOMEM); 685123474Swpaul 686123474Swpaul for (i = 0; i < sc->ndis_maxpkts; i++) { 687123474Swpaul error = bus_dmamap_create(sc->ndis_ttag, 0, 688123474Swpaul &sc->ndis_tmaps[i]); 689123474Swpaul if (error) { 690123474Swpaul free(sc->ndis_tmaps, M_DEVBUF); 691123474Swpaul return(ENODEV); 692123474Swpaul } 693123474Swpaul } 694123474Swpaul 695123474Swpaul return(0); 696123474Swpaul} 697123474Swpaul 698123474Swpaulint 699123474Swpaulndis_destroy_dma(arg) 700123474Swpaul void *arg; 701123474Swpaul{ 702123474Swpaul struct ndis_softc *sc; 703123535Swpaul struct mbuf *m; 704123535Swpaul ndis_packet *p = NULL; 705123474Swpaul int i; 706123474Swpaul 707123474Swpaul sc = arg; 708123474Swpaul 709123474Swpaul for (i = 0; i < sc->ndis_maxpkts; i++) { 710123535Swpaul if (sc->ndis_txarray[i] != NULL) { 711123535Swpaul p = sc->ndis_txarray[i]; 712123535Swpaul m = (struct mbuf *)p->np_rsvd[1]; 713123535Swpaul if (m != NULL) 714123535Swpaul m_freem(m); 715123535Swpaul ndis_free_packet(sc->ndis_txarray[i]); 716123535Swpaul } 717123474Swpaul bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]); 718123474Swpaul } 719123474Swpaul 720123474Swpaul free(sc->ndis_tmaps, M_DEVBUF); 721123474Swpaul 722123474Swpaul bus_dma_tag_destroy(sc->ndis_ttag); 723123474Swpaul 724123474Swpaul return(0); 725123474Swpaul} 726123474Swpaul 727123474Swpaulint 728123474Swpaulndis_reset_nic(arg) 729123474Swpaul void *arg; 730123474Swpaul{ 731123474Swpaul struct ndis_softc *sc; 732123474Swpaul ndis_handle adapter; 733123474Swpaul __stdcall ndis_reset_handler resetfunc; 734123474Swpaul uint8_t addressing_reset; 735123474Swpaul struct ifnet *ifp; 736123474Swpaul 737123474Swpaul sc = arg; 738123474Swpaul ifp = &sc->arpcom.ac_if; 739123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 740123474Swpaul if (adapter == NULL) 741123474Swpaul return(EIO); 742123474Swpaul resetfunc = sc->ndis_chars.nmc_reset_func; 743123474Swpaul 744123474Swpaul if (resetfunc == NULL) 745123474Swpaul return(EINVAL); 746123474Swpaul 747123474Swpaul resetfunc(&addressing_reset, adapter); 748123474Swpaul 749123474Swpaul return(0); 750123474Swpaul} 751123474Swpaul 752123474Swpaulint 753123474Swpaulndis_halt_nic(arg) 754123474Swpaul void *arg; 755123474Swpaul{ 756123474Swpaul struct ndis_softc *sc; 757123474Swpaul ndis_handle adapter; 758123474Swpaul __stdcall ndis_halt_handler haltfunc; 759123474Swpaul struct ifnet *ifp; 760123474Swpaul 761123474Swpaul sc = arg; 762123474Swpaul ifp = &sc->arpcom.ac_if; 763123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 764123474Swpaul if (adapter == NULL) 765123474Swpaul return(EIO); 766123474Swpaul haltfunc = sc->ndis_chars.nmc_halt_func; 767123474Swpaul 768123474Swpaul if (haltfunc == NULL) 769123474Swpaul return(EINVAL); 770123474Swpaul 771123474Swpaul haltfunc(adapter); 772123474Swpaul 773123474Swpaul /* 774123474Swpaul * The adapter context is only valid after the init 775123474Swpaul * handler has been called, and is invalid once the 776123474Swpaul * halt handler has been called. 777123474Swpaul */ 778123474Swpaul 779123474Swpaul sc->ndis_block.nmb_miniportadapterctx = NULL; 780123474Swpaul 781123474Swpaul return(0); 782123474Swpaul} 783123474Swpaul 784123474Swpaulint 785123474Swpaulndis_shutdown_nic(arg) 786123474Swpaul void *arg; 787123474Swpaul{ 788123474Swpaul struct ndis_softc *sc; 789123474Swpaul ndis_handle adapter; 790123474Swpaul __stdcall ndis_shutdown_handler shutdownfunc; 791123474Swpaul 792123474Swpaul 793123474Swpaul sc = arg; 794123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 795123474Swpaul if (adapter == NULL) 796123474Swpaul return(EIO); 797123474Swpaul shutdownfunc = sc->ndis_chars.nmc_shutdown_handler; 798123474Swpaul 799123474Swpaul if (shutdownfunc == NULL) 800123474Swpaul return(EINVAL); 801123474Swpaul 802123485Swpaul if (sc->ndis_chars.nmc_rsvd0 == NULL) 803123485Swpaul shutdownfunc(adapter); 804123485Swpaul else 805123485Swpaul shutdownfunc(sc->ndis_chars.nmc_rsvd0); 806123474Swpaul 807123474Swpaul return(0); 808123474Swpaul} 809123474Swpaul 810123474Swpaulint 811123474Swpaulndis_init_nic(arg) 812123474Swpaul void *arg; 813123474Swpaul{ 814123474Swpaul struct ndis_softc *sc; 815123474Swpaul ndis_miniport_block *block; 816123474Swpaul __stdcall ndis_init_handler initfunc; 817123474Swpaul ndis_status status, openstatus = 0; 818123474Swpaul ndis_medium mediumarray[NdisMediumMax]; 819123474Swpaul uint32_t chosenmedium, i; 820123474Swpaul 821123474Swpaul if (arg == NULL) 822123474Swpaul return(EINVAL); 823123474Swpaul 824123474Swpaul sc = arg; 825123474Swpaul block = &sc->ndis_block; 826123474Swpaul initfunc = sc->ndis_chars.nmc_init_func; 827123474Swpaul 828123474Swpaul for (i = 0; i < NdisMediumMax; i++) 829123474Swpaul mediumarray[i] = i; 830123474Swpaul 831123474Swpaul status = initfunc(&openstatus, &chosenmedium, 832123474Swpaul mediumarray, NdisMediumMax, block, block); 833123474Swpaul 834123474Swpaul /* 835123474Swpaul * If the init fails, blow away the other exported routines 836123474Swpaul * we obtained from the driver so we can't call them later. 837123474Swpaul * If the init failed, none of these will work. 838123474Swpaul */ 839123474Swpaul if (status != NDIS_STATUS_SUCCESS) { 840123474Swpaul bzero((char *)&sc->ndis_chars, 841123474Swpaul sizeof(ndis_miniport_characteristics)); 842123474Swpaul return(ENXIO); 843123474Swpaul } 844123474Swpaul 845123474Swpaul return(0); 846123474Swpaul} 847123474Swpaul 848123474Swpaulvoid 849123474Swpaulndis_enable_intr(arg) 850123474Swpaul void *arg; 851123474Swpaul{ 852123474Swpaul struct ndis_softc *sc; 853123474Swpaul ndis_handle adapter; 854123474Swpaul __stdcall ndis_enable_interrupts_handler intrenbfunc; 855123474Swpaul 856123474Swpaul sc = arg; 857123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 858123474Swpaul if (adapter == NULL) 859123474Swpaul return; 860123474Swpaul intrenbfunc = sc->ndis_chars.nmc_enable_interrupts_func; 861123474Swpaul if (intrenbfunc == NULL) 862123474Swpaul return; 863123474Swpaul intrenbfunc(adapter); 864123474Swpaul 865123474Swpaul return; 866123474Swpaul} 867123474Swpaul 868123474Swpaulvoid 869123474Swpaulndis_disable_intr(arg) 870123474Swpaul void *arg; 871123474Swpaul{ 872123474Swpaul struct ndis_softc *sc; 873123474Swpaul ndis_handle adapter; 874123474Swpaul __stdcall ndis_disable_interrupts_handler intrdisfunc; 875123474Swpaul 876123474Swpaul sc = arg; 877123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 878123474Swpaul if (adapter == NULL) 879123474Swpaul return; 880123474Swpaul intrdisfunc = sc->ndis_chars.nmc_disable_interrupts_func; 881123474Swpaul if (intrdisfunc == NULL) 882123474Swpaul return; 883123474Swpaul intrdisfunc(adapter); 884123474Swpaul 885123474Swpaul return; 886123474Swpaul} 887123474Swpaul 888123474Swpaulint 889123474Swpaulndis_isr(arg, ourintr, callhandler) 890123474Swpaul void *arg; 891123474Swpaul int *ourintr; 892123474Swpaul int *callhandler; 893123474Swpaul{ 894123474Swpaul struct ndis_softc *sc; 895123474Swpaul ndis_handle adapter; 896123474Swpaul __stdcall ndis_isr_handler isrfunc; 897123474Swpaul uint8_t accepted, queue; 898123474Swpaul 899123474Swpaul if (arg == NULL || ourintr == NULL || callhandler == NULL) 900123474Swpaul return(EINVAL); 901123474Swpaul 902123474Swpaul sc = arg; 903123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 904123474Swpaul isrfunc = sc->ndis_chars.nmc_isr_func; 905123474Swpaul isrfunc(&accepted, &queue, adapter); 906123474Swpaul *ourintr = accepted; 907123474Swpaul *callhandler = queue; 908123474Swpaul 909123474Swpaul return(0); 910123474Swpaul} 911123474Swpaul 912123474Swpaulint 913123474Swpaulndis_intrhand(arg) 914123474Swpaul void *arg; 915123474Swpaul{ 916123474Swpaul struct ndis_softc *sc; 917123474Swpaul ndis_handle adapter; 918123474Swpaul __stdcall ndis_interrupt_handler intrfunc; 919123474Swpaul 920123474Swpaul if (arg == NULL) 921123474Swpaul return(EINVAL); 922123474Swpaul 923123474Swpaul sc = arg; 924123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 925123474Swpaul intrfunc = sc->ndis_chars.nmc_interrupt_func; 926123474Swpaul intrfunc(adapter); 927123474Swpaul 928123474Swpaul return(0); 929123474Swpaul} 930123474Swpaul 931123474Swpaulint 932123474Swpaulndis_get_info(arg, oid, buf, buflen) 933123474Swpaul void *arg; 934123474Swpaul ndis_oid oid; 935123474Swpaul void *buf; 936123474Swpaul int *buflen; 937123474Swpaul{ 938123474Swpaul struct ndis_softc *sc; 939123474Swpaul ndis_status rval; 940123474Swpaul ndis_handle adapter; 941123474Swpaul __stdcall ndis_queryinfo_handler queryfunc; 942123474Swpaul uint32_t byteswritten = 0, bytesneeded = 0; 943123695Swpaul struct timeval tv; 944123695Swpaul int error; 945123474Swpaul 946123474Swpaul sc = arg; 947123474Swpaul queryfunc = sc->ndis_chars.nmc_queryinfo_func; 948123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 949123474Swpaul 950123474Swpaul rval = queryfunc(adapter, oid, buf, *buflen, 951123474Swpaul &byteswritten, &bytesneeded); 952123474Swpaul 953123695Swpaul /* Wait for requests that block. */ 954123695Swpaul 955123695Swpaul if (rval == NDIS_STATUS_PENDING) { 956123695Swpaul tv.tv_sec = 60; 957123695Swpaul tv.tv_usec = 0; 958123695Swpaul error = tsleep(&sc->ndis_block.nmb_wkupdpctimer, 959123695Swpaul PPAUSE|PCATCH, "ndis", tvtohz(&tv)); 960123695Swpaul rval = sc->ndis_block.nmb_getstat; 961123695Swpaul } 962123695Swpaul 963123474Swpaul if (byteswritten) 964123474Swpaul *buflen = byteswritten; 965123474Swpaul if (bytesneeded) 966123474Swpaul *buflen = bytesneeded; 967123474Swpaul 968123474Swpaul if (rval == NDIS_STATUS_INVALID_LENGTH || 969123474Swpaul rval == NDIS_STATUS_BUFFER_TOO_SHORT) 970123474Swpaul return(ENOSPC); 971123474Swpaul 972123474Swpaul if (rval == NDIS_STATUS_INVALID_OID) 973123474Swpaul return(EINVAL); 974123474Swpaul 975123474Swpaul if (rval == NDIS_STATUS_NOT_SUPPORTED || 976123474Swpaul rval == NDIS_STATUS_NOT_ACCEPTED) 977123474Swpaul return(ENOTSUP); 978123474Swpaul 979123474Swpaul return(0); 980123474Swpaul} 981123474Swpaul 982123474Swpaulint 983123474Swpaulndis_unload_driver(arg) 984123474Swpaul void *arg; 985123474Swpaul{ 986123474Swpaul struct ndis_softc *sc; 987123474Swpaul 988123474Swpaul sc = arg; 989123474Swpaul 990123474Swpaul free(sc->ndis_block.nmb_rlist, M_DEVBUF); 991123474Swpaul 992123474Swpaul ndis_flush_sysctls(sc); 993123474Swpaul ndis_libfini(); 994123474Swpaul ntoskrnl_libfini(); 995123474Swpaul 996123474Swpaul return(0); 997123474Swpaul} 998123474Swpaul 999123474Swpaulint 1000123474Swpaulndis_load_driver(img, arg) 1001123474Swpaul vm_offset_t img; 1002123474Swpaul void *arg; 1003123474Swpaul{ 1004123474Swpaul __stdcall driver_entry entry; 1005123474Swpaul image_optional_header opt_hdr; 1006123474Swpaul image_import_descriptor imp_desc; 1007123474Swpaul ndis_unicode_string dummystr; 1008123474Swpaul ndis_driver_object drv; 1009123474Swpaul ndis_miniport_block *block; 1010123474Swpaul ndis_status status; 1011123474Swpaul int idx; 1012123474Swpaul uint32_t *ptr; 1013123474Swpaul struct ndis_softc *sc; 1014123474Swpaul 1015123474Swpaul sc = arg; 1016123474Swpaul 1017123474Swpaul /* Perform text relocation */ 1018123474Swpaul if (pe_relocate(img)) 1019123474Swpaul return(ENOEXEC); 1020123474Swpaul 1021123474Swpaul /* Dynamically link the NDIS.SYS routines -- required. */ 1022123474Swpaul if (pe_patch_imports(img, "NDIS", ndis_functbl)) 1023123474Swpaul return(ENOEXEC); 1024123474Swpaul 1025123474Swpaul /* Dynamically link the HAL.dll routines -- also required. */ 1026123474Swpaul if (pe_patch_imports(img, "HAL", hal_functbl)) 1027123474Swpaul return(ENOEXEC); 1028123474Swpaul 1029123474Swpaul /* Dynamically link ntoskrnl.exe -- optional. */ 1030123474Swpaul if (pe_get_import_descriptor(img, &imp_desc, "ntoskrnl") == 0) { 1031123474Swpaul if (pe_patch_imports(img, "ntoskrnl", ntoskrnl_functbl)) 1032123474Swpaul return(ENOEXEC); 1033123474Swpaul } 1034123474Swpaul 1035123474Swpaul /* Initialize subsystems */ 1036123474Swpaul ndis_libinit(); 1037123474Swpaul ntoskrnl_libinit(); 1038123474Swpaul 1039123474Swpaul /* Locate the driver entry point */ 1040123474Swpaul pe_get_optional_header(img, &opt_hdr); 1041123474Swpaul entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr); 1042123474Swpaul 1043123474Swpaul /* 1044123474Swpaul * Now call the DriverEntry() routine. This will cause 1045123474Swpaul * a callout to the NdisInitializeWrapper() and 1046123474Swpaul * NdisMRegisterMiniport() routines. 1047123474Swpaul */ 1048123474Swpaul dummystr.nus_len = strlen(NDIS_DUMMY_PATH); 1049123474Swpaul dummystr.nus_maxlen = strlen(NDIS_DUMMY_PATH); 1050123474Swpaul dummystr.nus_buf = NULL; 1051123474Swpaul ndis_ascii_to_unicode(NDIS_DUMMY_PATH, &dummystr.nus_buf); 1052123474Swpaul drv.ndo_ifname = "ndis0"; 1053123474Swpaul 1054123474Swpaul status = entry(&drv, &dummystr); 1055123474Swpaul 1056123474Swpaul free (dummystr.nus_buf, M_DEVBUF); 1057123474Swpaul 1058123474Swpaul if (status != NDIS_STATUS_SUCCESS) 1059123474Swpaul return(ENODEV); 1060123474Swpaul 1061123474Swpaul /* 1062123474Swpaul * Now that we have the miniport driver characteristics, 1063123474Swpaul * create an NDIS block and call the init handler. 1064123474Swpaul * This will cause the driver to try to probe for 1065123474Swpaul * a device. 1066123474Swpaul */ 1067123474Swpaul 1068123474Swpaul block = &sc->ndis_block; 1069123474Swpaul bcopy((char *)&drv.ndo_chars, (char *)&sc->ndis_chars, 1070123474Swpaul sizeof(ndis_miniport_characteristics)); 1071123474Swpaul 1072123474Swpaul /*block->nmb_signature = 0xcafebabe;*/ 1073123474Swpaul 1074123474Swpaul ptr = (uint32_t *)block; 1075123474Swpaul for (idx = 0; idx < sizeof(ndis_miniport_block) / 4; idx++) { 1076123474Swpaul *ptr = idx | 0xdead0000; 1077123474Swpaul ptr++; 1078123474Swpaul } 1079123474Swpaul 1080123474Swpaul block->nmb_signature = (void *)0xcafebabe; 1081123474Swpaul block->nmb_setdone_func = ndis_setdone_func; 1082123535Swpaul block->nmb_querydone_func = ndis_getdone_func; 1083123474Swpaul block->nmb_status_func = ndis_status_func; 1084123474Swpaul block->nmb_statusdone_func = ndis_statusdone_func; 1085123474Swpaul block->nmb_resetdone_func = ndis_resetdone_func; 1086123474Swpaul 1087123474Swpaul block->nmb_ifp = &sc->arpcom.ac_if; 1088123474Swpaul block->nmb_dev = sc->ndis_dev; 1089123474Swpaul 1090123474Swpaul return(0); 1091123474Swpaul} 1092