kern_ndis.c revision 123485
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 123485 2003-12-12 05:27:58Z 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 61123474Swpaul#include <dev/pccard/pccardvar.h> 62123474Swpaul#include "card_if.h" 63123474Swpaul 64123474Swpaul#include <compat/ndis/pe_var.h> 65123474Swpaul#include <compat/ndis/resource_var.h> 66123474Swpaul#include <compat/ndis/ndis_var.h> 67123474Swpaul#include <compat/ndis/hal_var.h> 68123474Swpaul#include <compat/ndis/ntoskrnl_var.h> 69123474Swpaul#include <compat/ndis/cfg_var.h> 70123474Swpaul#include <dev/if_ndis/if_ndisvar.h> 71123474Swpaul 72123474Swpaul#define __stdcall __attribute__((__stdcall__)) 73123474Swpaul#define NDIS_DUMMY_PATH "\\\\some\\bogus\\path" 74123474Swpaul 75123474Swpaul__stdcall static void ndis_status_func(ndis_handle, ndis_status, 76123474Swpaul void *, uint32_t); 77123474Swpaul__stdcall static void ndis_statusdone_func(ndis_handle); 78123474Swpaul__stdcall static void ndis_setdone_func(ndis_handle, ndis_status); 79123474Swpaul__stdcall static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t); 80123474Swpaul 81123474Swpaul/* 82123474Swpaul * This allows us to export our symbols to other modules. 83123474Swpaul * Note that we call ourselves 'ndisapi' to avoid a namespace 84123474Swpaul * collision with if_ndis.ko, which internally calls itself 85123474Swpaul * 'ndis.' 86123474Swpaul */ 87123474Swpaulstatic int 88123474Swpaulndis_modevent(module_t mod, int cmd, void *arg) 89123474Swpaul{ 90123474Swpaul return(0); 91123474Swpaul} 92123474SwpaulDEV_MODULE(ndisapi, ndis_modevent, NULL); 93123474SwpaulMODULE_VERSION(ndisapi, 1); 94123474Swpaul 95123474Swpaul 96123474Swpaul__stdcall static void 97123474Swpaulndis_status_func(adapter, status, sbuf, slen) 98123474Swpaul ndis_handle adapter; 99123474Swpaul ndis_status status; 100123474Swpaul void *sbuf; 101123474Swpaul uint32_t slen; 102123474Swpaul{ 103123474Swpaul printf ("status: %x\n", status); 104123474Swpaul return; 105123474Swpaul} 106123474Swpaul 107123474Swpaul__stdcall static void 108123474Swpaulndis_statusdone_func(adapter) 109123474Swpaul ndis_handle adapter; 110123474Swpaul{ 111123474Swpaul printf ("status complete\n"); 112123474Swpaul return; 113123474Swpaul} 114123474Swpaul 115123474Swpaul__stdcall static void 116123474Swpaulndis_setdone_func(adapter, status) 117123474Swpaul ndis_handle adapter; 118123474Swpaul ndis_status status; 119123474Swpaul{ 120123474Swpaul printf ("Setup done... %x\n", status); 121123474Swpaul return; 122123474Swpaul} 123123474Swpaul 124123474Swpaul__stdcall static void 125123474Swpaulndis_resetdone_func(adapter, status, addressingreset) 126123474Swpaul ndis_handle adapter; 127123474Swpaul ndis_status status; 128123474Swpaul uint8_t addressingreset; 129123474Swpaul{ 130123474Swpaul printf ("reset done...\n"); 131123474Swpaul return; 132123474Swpaul} 133123474Swpaul 134123474Swpaul#define NDIS_AM_RID 3 135123474Swpaul 136123474Swpaulint 137123474Swpaulndis_alloc_amem(arg) 138123474Swpaul void *arg; 139123474Swpaul{ 140123474Swpaul struct ndis_softc *sc; 141123474Swpaul int error, rid; 142123474Swpaul 143123474Swpaul if (arg == NULL) 144123474Swpaul return(EINVAL); 145123474Swpaul 146123474Swpaul sc = arg; 147123474Swpaul rid = NDIS_AM_RID; 148123474Swpaul sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY, 149123474Swpaul &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE); 150123474Swpaul 151123474Swpaul if (sc->ndis_res_am == NULL) { 152123474Swpaul printf("ndis%d: failed to allocate attribute memory\n", 153123474Swpaul sc->ndis_unit); 154123474Swpaul return(ENXIO); 155123474Swpaul } 156123474Swpaul 157123474Swpaul error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev), 158123474Swpaul sc->ndis_dev, rid, 0, NULL); 159123474Swpaul 160123474Swpaul if (error) { 161123474Swpaul printf("ndis%d: CARD_SET_MEMORY_OFFSET() returned 0x%x\n", 162123474Swpaul sc->ndis_unit, error); 163123474Swpaul return(error); 164123474Swpaul } 165123474Swpaul 166123474Swpaul error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev), 167123474Swpaul sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); 168123474Swpaul 169123474Swpaul if (error) { 170123474Swpaul printf("ndis%d: CARD_SET_RES_FLAGS() returned 0x%x\n", 171123474Swpaul sc->ndis_unit, error); 172123474Swpaul return(error); 173123474Swpaul } 174123474Swpaul 175123474Swpaul return(0); 176123474Swpaul} 177123474Swpaul 178123474Swpaulint 179123474Swpaulndis_create_sysctls(arg) 180123474Swpaul void *arg; 181123474Swpaul{ 182123474Swpaul struct ndis_softc *sc; 183123474Swpaul ndis_cfg *vals; 184123474Swpaul char buf[256]; 185123474Swpaul 186123474Swpaul if (arg == NULL) 187123474Swpaul return(EINVAL); 188123474Swpaul 189123474Swpaul sc = arg; 190123474Swpaul vals = sc->ndis_regvals; 191123474Swpaul 192123474Swpaul TAILQ_INIT(&sc->ndis_cfglist_head); 193123474Swpaul 194123474Swpaul /* Create the sysctl tree. */ 195123474Swpaul 196123474Swpaul sc->ndis_tree = SYSCTL_ADD_NODE(&sc->ndis_ctx, 197123474Swpaul SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, 198123474Swpaul device_get_nameunit(sc->ndis_dev), CTLFLAG_RD, 0, 199123474Swpaul device_get_desc(sc->ndis_dev)); 200123474Swpaul 201123474Swpaul /* Add the driver-specific registry keys. */ 202123474Swpaul 203123474Swpaul vals = sc->ndis_regvals; 204123474Swpaul while(1) { 205123474Swpaul if (vals->nc_cfgkey == NULL) 206123474Swpaul break; 207123474Swpaul SYSCTL_ADD_STRING(&sc->ndis_ctx, 208123474Swpaul SYSCTL_CHILDREN(sc->ndis_tree), 209123474Swpaul OID_AUTO, vals->nc_cfgkey, 210123474Swpaul CTLFLAG_RW, vals->nc_val, 211123474Swpaul sizeof(vals->nc_val), 212123474Swpaul vals->nc_cfgdesc); 213123474Swpaul vals++; 214123474Swpaul } 215123474Swpaul 216123474Swpaul /* Now add a couple of builtin keys. */ 217123474Swpaul 218123474Swpaul /* 219123474Swpaul * Environment can be either Windows (0) or WindowsNT (1). 220123474Swpaul * We qualify as the latter. 221123474Swpaul */ 222123474Swpaul ndis_add_sysctl(sc, "Environment", 223123474Swpaul "Windows environment", "1", CTLFLAG_RD); 224123474Swpaul 225123474Swpaul /* NDIS version should be 5.1. */ 226123474Swpaul ndis_add_sysctl(sc, "NdisVersion", 227123474Swpaul "NDIS API Version", "0x00050001", CTLFLAG_RD); 228123474Swpaul 229123474Swpaul /* Bus type (PCI, PCMCIA, etc...) */ 230123474Swpaul sprintf(buf, "%d\n", (int)sc->ndis_iftype); 231123474Swpaul ndis_add_sysctl(sc, "BusType", "Bus Type", buf, CTLFLAG_RD); 232123474Swpaul 233123474Swpaul if (sc->ndis_res_io != NULL) { 234123474Swpaul sprintf(buf, "0x%lx\n", rman_get_start(sc->ndis_res_io)); 235123474Swpaul ndis_add_sysctl(sc, "IOBaseAddress", 236123474Swpaul "Base I/O Address", buf, CTLFLAG_RD); 237123474Swpaul } 238123474Swpaul 239123474Swpaul if (sc->ndis_irq != NULL) { 240123474Swpaul sprintf(buf, "%lu\n", rman_get_start(sc->ndis_irq)); 241123474Swpaul ndis_add_sysctl(sc, "InterruptNumber", 242123474Swpaul "Interrupt Number", buf, CTLFLAG_RD); 243123474Swpaul } 244123474Swpaul 245123474Swpaul return(0); 246123474Swpaul} 247123474Swpaul 248123474Swpaulint 249123474Swpaulndis_add_sysctl(arg, key, desc, val, flag) 250123474Swpaul void *arg; 251123474Swpaul char *key; 252123474Swpaul char *desc; 253123474Swpaul char *val; 254123474Swpaul int flag; 255123474Swpaul{ 256123474Swpaul struct ndis_softc *sc; 257123474Swpaul struct ndis_cfglist *cfg; 258123474Swpaul char descstr[256]; 259123474Swpaul 260123474Swpaul sc = arg; 261123474Swpaul 262123474Swpaul cfg = malloc(sizeof(struct ndis_cfglist), M_DEVBUF, M_NOWAIT|M_ZERO); 263123474Swpaul 264123474Swpaul if (cfg == NULL) 265123474Swpaul return(ENOMEM); 266123474Swpaul 267123474Swpaul cfg->ndis_cfg.nc_cfgkey = strdup(key, M_DEVBUF); 268123474Swpaul if (desc == NULL) { 269123474Swpaul snprintf(descstr, sizeof(descstr), "%s (dynamic)", key); 270123474Swpaul cfg->ndis_cfg.nc_cfgdesc = strdup(descstr, M_DEVBUF); 271123474Swpaul } else 272123474Swpaul cfg->ndis_cfg.nc_cfgdesc = strdup(desc, M_DEVBUF); 273123474Swpaul strcpy(cfg->ndis_cfg.nc_val, val); 274123474Swpaul 275123474Swpaul TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link); 276123474Swpaul 277123474Swpaul SYSCTL_ADD_STRING(&sc->ndis_ctx, SYSCTL_CHILDREN(sc->ndis_tree), 278123474Swpaul OID_AUTO, cfg->ndis_cfg.nc_cfgkey, flag, 279123474Swpaul cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val), 280123474Swpaul cfg->ndis_cfg.nc_cfgdesc); 281123474Swpaul 282123474Swpaul return(0); 283123474Swpaul} 284123474Swpaul 285123474Swpaulint 286123474Swpaulndis_flush_sysctls(arg) 287123474Swpaul void *arg; 288123474Swpaul{ 289123474Swpaul struct ndis_softc *sc; 290123474Swpaul struct ndis_cfglist *cfg; 291123474Swpaul 292123474Swpaul sc = arg; 293123474Swpaul 294123474Swpaul while (!TAILQ_EMPTY(&sc->ndis_cfglist_head)) { 295123474Swpaul cfg = TAILQ_FIRST(&sc->ndis_cfglist_head); 296123474Swpaul TAILQ_REMOVE(&sc->ndis_cfglist_head, cfg, link); 297123474Swpaul free(cfg->ndis_cfg.nc_cfgkey, M_DEVBUF); 298123474Swpaul free(cfg->ndis_cfg.nc_cfgdesc, M_DEVBUF); 299123474Swpaul free(cfg, M_DEVBUF); 300123474Swpaul } 301123474Swpaul 302123474Swpaul return(0); 303123474Swpaul} 304123474Swpaul 305123474Swpaulvoid 306123474Swpaulndis_return_packet(packet, arg) 307123474Swpaul void *packet; 308123474Swpaul void *arg; 309123474Swpaul{ 310123474Swpaul struct ndis_softc *sc; 311123474Swpaul ndis_handle adapter; 312123474Swpaul __stdcall ndis_return_handler returnfunc; 313123474Swpaul 314123474Swpaul if (arg == NULL || packet == NULL) 315123474Swpaul return; 316123474Swpaul 317123474Swpaul sc = arg; 318123474Swpaul returnfunc = sc->ndis_chars.nmc_return_packet_func; 319123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 320123474Swpaul if (returnfunc == NULL) 321123474Swpaul ndis_free_packet((ndis_packet *)packet); 322123474Swpaul else 323123474Swpaul returnfunc(adapter, (ndis_packet *)packet); 324123474Swpaul return; 325123474Swpaul} 326123474Swpaul 327123474Swpaulvoid 328123474Swpaulndis_free_bufs(b0) 329123474Swpaul ndis_buffer *b0; 330123474Swpaul{ 331123474Swpaul ndis_buffer *next; 332123474Swpaul 333123474Swpaul if (b0 == NULL) 334123474Swpaul return; 335123474Swpaul 336123474Swpaul while(b0 != NULL) { 337123474Swpaul next = b0->nb_next; 338123474Swpaul free (b0, M_DEVBUF); 339123474Swpaul b0 = next; 340123474Swpaul } 341123474Swpaul 342123474Swpaul return; 343123474Swpaul} 344123474Swpaul 345123474Swpaulvoid 346123474Swpaulndis_free_packet(p) 347123474Swpaul ndis_packet *p; 348123474Swpaul{ 349123474Swpaul if (p == NULL) 350123474Swpaul return; 351123474Swpaul 352123474Swpaul ndis_free_bufs(p->np_private.npp_head); 353123474Swpaul free(p, M_DEVBUF); 354123474Swpaul 355123474Swpaul return; 356123474Swpaul} 357123474Swpaul 358123474Swpaulint 359123474Swpaulndis_convert_res(arg) 360123474Swpaul void *arg; 361123474Swpaul{ 362123474Swpaul struct ndis_softc *sc; 363123474Swpaul ndis_resource_list *rl = NULL; 364123474Swpaul cm_partial_resource_desc *prd = NULL; 365123474Swpaul ndis_miniport_block *block; 366123474Swpaul 367123474Swpaul sc = arg; 368123474Swpaul block = &sc->ndis_block; 369123474Swpaul 370123474Swpaul rl = malloc(sizeof(ndis_resource_list) + 371123474Swpaul (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)), 372123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 373123474Swpaul 374123474Swpaul if (rl == NULL) 375123474Swpaul return(ENOMEM); 376123474Swpaul 377123474Swpaul rl->cprl_version = 5; 378123474Swpaul rl->cprl_version = 1; 379123474Swpaul rl->cprl_count = sc->ndis_rescnt; 380123474Swpaul 381123474Swpaul prd = rl->cprl_partial_descs; 382123474Swpaul if (sc->ndis_res_io) { 383123474Swpaul prd->cprd_type = CmResourceTypePort; 384123474Swpaul prd->u.cprd_port.cprd_start.np_quad = 385123474Swpaul rman_get_start(sc->ndis_res_io); 386123474Swpaul prd->u.cprd_port.cprd_len = 387123474Swpaul rman_get_size(sc->ndis_res_io); 388123474Swpaul prd++; 389123474Swpaul } 390123474Swpaul 391123474Swpaul if (sc->ndis_res_mem) { 392123474Swpaul prd->cprd_type = CmResourceTypeMemory; 393123474Swpaul prd->u.cprd_mem.cprd_start.np_quad = 394123474Swpaul rman_get_start(sc->ndis_res_mem); 395123474Swpaul prd->u.cprd_mem.cprd_len = 396123474Swpaul rman_get_size(sc->ndis_res_mem); 397123474Swpaul prd++; 398123474Swpaul } 399123474Swpaul 400123474Swpaul if (sc->ndis_irq) { 401123474Swpaul prd->cprd_type = CmResourceTypeInterrupt; 402123474Swpaul prd->u.cprd_intr.cprd_level = 403123474Swpaul rman_get_start(sc->ndis_irq); 404123474Swpaul prd->u.cprd_intr.cprd_vector = 405123474Swpaul rman_get_start(sc->ndis_irq); 406123474Swpaul prd->u.cprd_intr.cprd_affinity = 0; 407123474Swpaul } 408123474Swpaul 409123474Swpaul block->nmb_rlist = rl; 410123474Swpaul 411123474Swpaul return(0); 412123474Swpaul} 413123474Swpaul 414123474Swpaul/* 415123474Swpaul * Map an NDIS packet to an mbuf list. When an NDIS driver receives a 416123474Swpaul * packet, it will hand it to us in the form of an ndis_packet, 417123474Swpaul * which we need to convert to an mbuf that is then handed off 418123474Swpaul * to the stack. Note: we configure the mbuf list so that it uses 419123474Swpaul * the memory regions specified by the ndis_buffer structures in 420123474Swpaul * the ndis_packet as external storage. In most cases, this will 421123474Swpaul * point to a memory region allocated by the driver (either by 422123474Swpaul * ndis_malloc_withtag() or ndis_alloc_sharedmem()). We expect 423123474Swpaul * the driver to handle free()ing this region for is, so we set up 424123474Swpaul * a dummy no-op free handler for it. 425123474Swpaul */ 426123474Swpaul 427123474Swpaulint 428123474Swpaulndis_ptom(m0, p) 429123474Swpaul struct mbuf **m0; 430123474Swpaul ndis_packet *p; 431123474Swpaul{ 432123474Swpaul struct mbuf *m, *prev = NULL; 433123474Swpaul ndis_buffer *buf; 434123474Swpaul ndis_packet_private *priv; 435123474Swpaul uint32_t totlen = 0; 436123474Swpaul 437123474Swpaul if (p == NULL || m0 == NULL) 438123474Swpaul return(EINVAL); 439123474Swpaul 440123474Swpaul priv = &p->np_private; 441123474Swpaul buf = priv->npp_head; 442123474Swpaul 443123474Swpaul for (buf = priv->npp_head; buf != NULL; buf = buf->nb_next) { 444123474Swpaul if (buf == priv->npp_head) 445123474Swpaul MGETHDR(m, M_DONTWAIT, MT_HEADER); 446123474Swpaul else 447123474Swpaul MGET(m, M_DONTWAIT, MT_DATA); 448123474Swpaul if (m == NULL) { 449123474Swpaul m_freem(*m0); 450123474Swpaul *m0 = NULL; 451123474Swpaul return(ENOBUFS); 452123474Swpaul } 453123474Swpaul 454123474Swpaul /* 455123474Swpaul * Note: there's some hackery going on here. We want 456123474Swpaul * to mate the mbufs to the buffers in the NDIS packet, 457123474Swpaul * but we don't mark the mbufs with the M_EXT flag to 458123474Swpaul * indicate external storage. This is because we don't 459123474Swpaul * want anything special done to free the buffers. 460123474Swpaul * Depending on the circumstances, the caller may want 461123474Swpaul * the entire packet to be released, buffers and all, 462123474Swpaul * by calling ndis_return_packet(), or ndis_free_packet(). 463123474Swpaul * We leave it up to the caller to do the MEXTADD() to 464123474Swpaul * set up the free mechanism in the first mbuf of the 465123474Swpaul * chain. 466123474Swpaul */ 467123474Swpaul if (buf->nb_size) 468123474Swpaul m->m_len = buf->nb_size; 469123474Swpaul else 470123474Swpaul m->m_len = buf->nb_bytecount; 471123474Swpaul m->m_data = buf->nb_mappedsystemva; 472123474Swpaul totlen += m->m_len; 473123474Swpaul if (m->m_flags & MT_HEADER) 474123474Swpaul *m0 = m; 475123474Swpaul else 476123474Swpaul prev->m_next = m; 477123474Swpaul prev = m; 478123474Swpaul } 479123474Swpaul 480123474Swpaul (*m0)->m_pkthdr.len = totlen; 481123474Swpaul 482123474Swpaul return(0); 483123474Swpaul} 484123474Swpaul 485123474Swpaul/* 486123474Swpaul * Create an mbuf chain from an NDIS packet chain. 487123474Swpaul * This is used mainly when transmitting packets, where we need 488123474Swpaul * to turn an mbuf off an interface's send queue and transform it 489123474Swpaul * into an NDIS packet which will be fed into the NDIS driver's 490123474Swpaul * send routine. 491123474Swpaul * 492123474Swpaul * NDIS packets consist of two parts: an ndis_packet structure, 493123474Swpaul * which is vaguely analagous to the pkthdr portion of an mbuf, 494123474Swpaul * and one or more ndis_buffer structures, which define the 495123474Swpaul * actual memory segments in which the packet data resides. 496123474Swpaul * We need to allocate one ndis_buffer for each mbuf in a chain, 497123474Swpaul * plus one ndis_packet as the header. 498123474Swpaul */ 499123474Swpaul 500123474Swpaulint 501123474Swpaulndis_mtop(m0, p) 502123474Swpaul struct mbuf *m0; 503123474Swpaul ndis_packet **p; 504123474Swpaul{ 505123474Swpaul struct mbuf *m; 506123474Swpaul ndis_buffer *buf = NULL, *prev = NULL; 507123474Swpaul ndis_packet_private *priv; 508123474Swpaul 509123474Swpaul if (p == NULL || m0 == NULL) 510123474Swpaul return(EINVAL); 511123474Swpaul 512123474Swpaul /* If caller didn't supply a packet, make one. */ 513123474Swpaul if (*p == NULL) { 514123474Swpaul *p = malloc(sizeof(ndis_packet), M_DEVBUF, M_NOWAIT|M_ZERO); 515123474Swpaul 516123474Swpaul if (*p == NULL) 517123474Swpaul return(ENOMEM); 518123474Swpaul } 519123474Swpaul 520123474Swpaul priv = &(*p)->np_private; 521123474Swpaul priv->npp_totlen = m0->m_pkthdr.len; 522123474Swpaul priv->npp_packetooboffset = offsetof(ndis_packet, np_oob); 523123474Swpaul 524123474Swpaul for (m = m0; m != NULL; m = m->m_next) { 525123474Swpaul if (m->m_len == NULL) 526123474Swpaul continue; 527123474Swpaul 528123474Swpaul buf = malloc(sizeof(ndis_buffer), M_DEVBUF, M_NOWAIT|M_ZERO); 529123474Swpaul if (buf == NULL) { 530123474Swpaul ndis_free_packet(*p); 531123474Swpaul *p = NULL; 532123474Swpaul return(ENOMEM); 533123474Swpaul } 534123474Swpaul 535123474Swpaul buf->nb_bytecount = m->m_len; 536123474Swpaul buf->nb_mappedsystemva = m->m_data; 537123474Swpaul if (priv->npp_head == NULL) 538123474Swpaul priv->npp_head = buf; 539123474Swpaul else 540123474Swpaul prev->nb_next = buf; 541123474Swpaul prev = buf; 542123474Swpaul } 543123474Swpaul 544123474Swpaul priv->npp_tail = buf; 545123474Swpaul 546123474Swpaul return(0); 547123474Swpaul} 548123474Swpaul 549123474Swpaulint 550123474Swpaulndis_get_supported_oids(arg, oids, oidcnt) 551123474Swpaul void *arg; 552123474Swpaul ndis_oid **oids; 553123474Swpaul int *oidcnt; 554123474Swpaul{ 555123474Swpaul int len, rval; 556123474Swpaul ndis_oid *o; 557123474Swpaul 558123474Swpaul if (arg == NULL || oids == NULL || oidcnt == NULL) 559123474Swpaul return(EINVAL); 560123474Swpaul len = 0; 561123474Swpaul ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, NULL, &len); 562123474Swpaul 563123474Swpaul o = malloc(len, M_DEVBUF, M_NOWAIT); 564123474Swpaul if (o == NULL) 565123474Swpaul return(ENOMEM); 566123474Swpaul 567123474Swpaul rval = ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, o, &len); 568123474Swpaul 569123474Swpaul if (rval) { 570123474Swpaul free(o, M_DEVBUF); 571123474Swpaul return(rval); 572123474Swpaul } 573123474Swpaul 574123474Swpaul *oids = o; 575123474Swpaul *oidcnt = len / 4; 576123474Swpaul 577123474Swpaul return(0); 578123474Swpaul} 579123474Swpaul 580123474Swpaulint 581123474Swpaulndis_set_info(arg, oid, buf, buflen) 582123474Swpaul void *arg; 583123474Swpaul ndis_oid oid; 584123474Swpaul void *buf; 585123474Swpaul int *buflen; 586123474Swpaul{ 587123474Swpaul struct ndis_softc *sc; 588123474Swpaul ndis_status rval; 589123474Swpaul ndis_handle adapter; 590123474Swpaul __stdcall ndis_setinfo_handler setfunc; 591123474Swpaul uint32_t byteswritten = 0, bytesneeded = 0; 592123474Swpaul 593123474Swpaul sc = arg; 594123474Swpaul setfunc = sc->ndis_chars.nmc_setinfo_func; 595123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 596123474Swpaul 597123474Swpaul rval = setfunc(adapter, oid, buf, *buflen, 598123474Swpaul &byteswritten, &bytesneeded); 599123474Swpaul 600123474Swpaul if (byteswritten) 601123474Swpaul *buflen = byteswritten; 602123474Swpaul if (bytesneeded) 603123474Swpaul *buflen = bytesneeded; 604123474Swpaul 605123474Swpaul if (rval == NDIS_STATUS_INVALID_LENGTH) 606123474Swpaul return(ENOSPC); 607123474Swpaul 608123474Swpaul if (rval == NDIS_STATUS_INVALID_OID) 609123474Swpaul return(EINVAL); 610123474Swpaul 611123474Swpaul if (rval == NDIS_STATUS_NOT_SUPPORTED || 612123474Swpaul rval == NDIS_STATUS_NOT_ACCEPTED) 613123474Swpaul return(ENOTSUP); 614123474Swpaul 615123474Swpaul if (rval == NDIS_STATUS_PENDING) 616123474Swpaul return(EAGAIN); 617123474Swpaul 618123474Swpaul return(0); 619123474Swpaul} 620123474Swpaul 621123474Swpaulint 622123474Swpaulndis_send_packets(arg, packets, cnt) 623123474Swpaul void *arg; 624123474Swpaul ndis_packet **packets; 625123474Swpaul int cnt; 626123474Swpaul{ 627123474Swpaul struct ndis_softc *sc; 628123474Swpaul ndis_handle adapter; 629123474Swpaul __stdcall ndis_sendmulti_handler sendfunc; 630123474Swpaul 631123474Swpaul sc = arg; 632123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 633123474Swpaul sendfunc = sc->ndis_chars.nmc_sendmulti_func; 634123474Swpaul sendfunc(adapter, packets, cnt); 635123474Swpaul 636123474Swpaul return(0); 637123474Swpaul} 638123474Swpaul 639123474Swpaulint 640123474Swpaulndis_init_dma(arg) 641123474Swpaul void *arg; 642123474Swpaul{ 643123474Swpaul struct ndis_softc *sc; 644123474Swpaul int i, error; 645123474Swpaul 646123474Swpaul sc = arg; 647123474Swpaul 648123474Swpaul sc->ndis_tmaps = malloc(sizeof(bus_dmamap_t) * sc->ndis_maxpkts, 649123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 650123474Swpaul 651123474Swpaul if (sc->ndis_tmaps == NULL) 652123474Swpaul return(ENOMEM); 653123474Swpaul 654123474Swpaul sc->ndis_mbufs = malloc(sizeof(struct mbuf) * sc->ndis_maxpkts, 655123474Swpaul M_DEVBUF, M_NOWAIT|M_ZERO); 656123474Swpaul 657123474Swpaul if (sc->ndis_mbufs == NULL) { 658123474Swpaul free(sc->ndis_tmaps, M_DEVBUF); 659123474Swpaul return(ENOMEM); 660123474Swpaul } 661123474Swpaul 662123474Swpaul for (i = 0; i < sc->ndis_maxpkts; i++) { 663123474Swpaul error = bus_dmamap_create(sc->ndis_ttag, 0, 664123474Swpaul &sc->ndis_tmaps[i]); 665123474Swpaul if (error) { 666123474Swpaul free(sc->ndis_tmaps, M_DEVBUF); 667123474Swpaul free(sc->ndis_mbufs, M_DEVBUF); 668123474Swpaul return(ENODEV); 669123474Swpaul } 670123474Swpaul } 671123474Swpaul 672123474Swpaul return(0); 673123474Swpaul} 674123474Swpaul 675123474Swpaulint 676123474Swpaulndis_destroy_dma(arg) 677123474Swpaul void *arg; 678123474Swpaul{ 679123474Swpaul struct ndis_softc *sc; 680123474Swpaul int i; 681123474Swpaul 682123474Swpaul sc = arg; 683123474Swpaul 684123474Swpaul for (i = 0; i < sc->ndis_maxpkts; i++) { 685123474Swpaul if (sc->ndis_mbufs[i] != NULL) 686123474Swpaul m_freem(sc->ndis_mbufs[i]); 687123474Swpaul bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]); 688123474Swpaul } 689123474Swpaul 690123474Swpaul free(sc->ndis_tmaps, M_DEVBUF); 691123474Swpaul free(sc->ndis_mbufs, M_DEVBUF); 692123474Swpaul 693123474Swpaul bus_dma_tag_destroy(sc->ndis_ttag); 694123474Swpaul 695123474Swpaul return(0); 696123474Swpaul} 697123474Swpaul 698123474Swpaulint 699123474Swpaulndis_reset_nic(arg) 700123474Swpaul void *arg; 701123474Swpaul{ 702123474Swpaul struct ndis_softc *sc; 703123474Swpaul ndis_handle adapter; 704123474Swpaul __stdcall ndis_reset_handler resetfunc; 705123474Swpaul uint8_t addressing_reset; 706123474Swpaul struct ifnet *ifp; 707123474Swpaul 708123474Swpaul sc = arg; 709123474Swpaul ifp = &sc->arpcom.ac_if; 710123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 711123474Swpaul if (adapter == NULL) 712123474Swpaul return(EIO); 713123474Swpaul resetfunc = sc->ndis_chars.nmc_reset_func; 714123474Swpaul 715123474Swpaul if (resetfunc == NULL) 716123474Swpaul return(EINVAL); 717123474Swpaul 718123474Swpaul resetfunc(&addressing_reset, adapter); 719123474Swpaul 720123474Swpaul return(0); 721123474Swpaul} 722123474Swpaul 723123474Swpaulint 724123474Swpaulndis_halt_nic(arg) 725123474Swpaul void *arg; 726123474Swpaul{ 727123474Swpaul struct ndis_softc *sc; 728123474Swpaul ndis_handle adapter; 729123474Swpaul __stdcall ndis_halt_handler haltfunc; 730123474Swpaul struct ifnet *ifp; 731123474Swpaul 732123474Swpaul sc = arg; 733123474Swpaul ifp = &sc->arpcom.ac_if; 734123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 735123474Swpaul if (adapter == NULL) 736123474Swpaul return(EIO); 737123474Swpaul haltfunc = sc->ndis_chars.nmc_halt_func; 738123474Swpaul 739123474Swpaul if (haltfunc == NULL) 740123474Swpaul return(EINVAL); 741123474Swpaul 742123474Swpaul haltfunc(adapter); 743123474Swpaul 744123474Swpaul /* 745123474Swpaul * The adapter context is only valid after the init 746123474Swpaul * handler has been called, and is invalid once the 747123474Swpaul * halt handler has been called. 748123474Swpaul */ 749123474Swpaul 750123474Swpaul sc->ndis_block.nmb_miniportadapterctx = NULL; 751123474Swpaul 752123474Swpaul return(0); 753123474Swpaul} 754123474Swpaul 755123474Swpaulint 756123474Swpaulndis_shutdown_nic(arg) 757123474Swpaul void *arg; 758123474Swpaul{ 759123474Swpaul struct ndis_softc *sc; 760123474Swpaul ndis_handle adapter; 761123474Swpaul __stdcall ndis_shutdown_handler shutdownfunc; 762123474Swpaul 763123474Swpaul 764123474Swpaul sc = arg; 765123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 766123474Swpaul if (adapter == NULL) 767123474Swpaul return(EIO); 768123474Swpaul shutdownfunc = sc->ndis_chars.nmc_shutdown_handler; 769123474Swpaul 770123474Swpaul if (shutdownfunc == NULL) 771123474Swpaul return(EINVAL); 772123474Swpaul 773123485Swpaul if (sc->ndis_chars.nmc_rsvd0 == NULL) 774123485Swpaul shutdownfunc(adapter); 775123485Swpaul else 776123485Swpaul shutdownfunc(sc->ndis_chars.nmc_rsvd0); 777123474Swpaul 778123474Swpaul return(0); 779123474Swpaul} 780123474Swpaul 781123474Swpaulint 782123474Swpaulndis_init_nic(arg) 783123474Swpaul void *arg; 784123474Swpaul{ 785123474Swpaul struct ndis_softc *sc; 786123474Swpaul ndis_miniport_block *block; 787123474Swpaul __stdcall ndis_init_handler initfunc; 788123474Swpaul ndis_status status, openstatus = 0; 789123474Swpaul ndis_medium mediumarray[NdisMediumMax]; 790123474Swpaul uint32_t chosenmedium, i; 791123474Swpaul 792123474Swpaul if (arg == NULL) 793123474Swpaul return(EINVAL); 794123474Swpaul 795123474Swpaul sc = arg; 796123474Swpaul block = &sc->ndis_block; 797123474Swpaul initfunc = sc->ndis_chars.nmc_init_func; 798123474Swpaul 799123474Swpaul for (i = 0; i < NdisMediumMax; i++) 800123474Swpaul mediumarray[i] = i; 801123474Swpaul 802123474Swpaul status = initfunc(&openstatus, &chosenmedium, 803123474Swpaul mediumarray, NdisMediumMax, block, block); 804123474Swpaul 805123474Swpaul /* 806123474Swpaul * If the init fails, blow away the other exported routines 807123474Swpaul * we obtained from the driver so we can't call them later. 808123474Swpaul * If the init failed, none of these will work. 809123474Swpaul */ 810123474Swpaul if (status != NDIS_STATUS_SUCCESS) { 811123474Swpaul bzero((char *)&sc->ndis_chars, 812123474Swpaul sizeof(ndis_miniport_characteristics)); 813123474Swpaul return(ENXIO); 814123474Swpaul } 815123474Swpaul 816123474Swpaul return(0); 817123474Swpaul} 818123474Swpaul 819123474Swpaulvoid 820123474Swpaulndis_enable_intr(arg) 821123474Swpaul void *arg; 822123474Swpaul{ 823123474Swpaul struct ndis_softc *sc; 824123474Swpaul ndis_handle adapter; 825123474Swpaul __stdcall ndis_enable_interrupts_handler intrenbfunc; 826123474Swpaul 827123474Swpaul sc = arg; 828123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 829123474Swpaul if (adapter == NULL) 830123474Swpaul return; 831123474Swpaul intrenbfunc = sc->ndis_chars.nmc_enable_interrupts_func; 832123474Swpaul if (intrenbfunc == NULL) 833123474Swpaul return; 834123474Swpaul intrenbfunc(adapter); 835123474Swpaul 836123474Swpaul return; 837123474Swpaul} 838123474Swpaul 839123474Swpaulvoid 840123474Swpaulndis_disable_intr(arg) 841123474Swpaul void *arg; 842123474Swpaul{ 843123474Swpaul struct ndis_softc *sc; 844123474Swpaul ndis_handle adapter; 845123474Swpaul __stdcall ndis_disable_interrupts_handler intrdisfunc; 846123474Swpaul 847123474Swpaul sc = arg; 848123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 849123474Swpaul if (adapter == NULL) 850123474Swpaul return; 851123474Swpaul intrdisfunc = sc->ndis_chars.nmc_disable_interrupts_func; 852123474Swpaul if (intrdisfunc == NULL) 853123474Swpaul return; 854123474Swpaul intrdisfunc(adapter); 855123474Swpaul 856123474Swpaul return; 857123474Swpaul} 858123474Swpaul 859123474Swpaulint 860123474Swpaulndis_isr(arg, ourintr, callhandler) 861123474Swpaul void *arg; 862123474Swpaul int *ourintr; 863123474Swpaul int *callhandler; 864123474Swpaul{ 865123474Swpaul struct ndis_softc *sc; 866123474Swpaul ndis_handle adapter; 867123474Swpaul __stdcall ndis_isr_handler isrfunc; 868123474Swpaul uint8_t accepted, queue; 869123474Swpaul 870123474Swpaul if (arg == NULL || ourintr == NULL || callhandler == NULL) 871123474Swpaul return(EINVAL); 872123474Swpaul 873123474Swpaul sc = arg; 874123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 875123474Swpaul isrfunc = sc->ndis_chars.nmc_isr_func; 876123474Swpaul isrfunc(&accepted, &queue, adapter); 877123474Swpaul *ourintr = accepted; 878123474Swpaul *callhandler = queue; 879123474Swpaul 880123474Swpaul return(0); 881123474Swpaul} 882123474Swpaul 883123474Swpaulint 884123474Swpaulndis_intrhand(arg) 885123474Swpaul void *arg; 886123474Swpaul{ 887123474Swpaul struct ndis_softc *sc; 888123474Swpaul ndis_handle adapter; 889123474Swpaul __stdcall ndis_interrupt_handler intrfunc; 890123474Swpaul 891123474Swpaul if (arg == NULL) 892123474Swpaul return(EINVAL); 893123474Swpaul 894123474Swpaul sc = arg; 895123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 896123474Swpaul intrfunc = sc->ndis_chars.nmc_interrupt_func; 897123474Swpaul intrfunc(adapter); 898123474Swpaul 899123474Swpaul return(0); 900123474Swpaul} 901123474Swpaul 902123474Swpaulint 903123474Swpaulndis_get_info(arg, oid, buf, buflen) 904123474Swpaul void *arg; 905123474Swpaul ndis_oid oid; 906123474Swpaul void *buf; 907123474Swpaul int *buflen; 908123474Swpaul{ 909123474Swpaul struct ndis_softc *sc; 910123474Swpaul ndis_status rval; 911123474Swpaul ndis_handle adapter; 912123474Swpaul __stdcall ndis_queryinfo_handler queryfunc; 913123474Swpaul uint32_t byteswritten = 0, bytesneeded = 0; 914123474Swpaul 915123474Swpaul sc = arg; 916123474Swpaul queryfunc = sc->ndis_chars.nmc_queryinfo_func; 917123474Swpaul adapter = sc->ndis_block.nmb_miniportadapterctx; 918123474Swpaul 919123474Swpaul rval = queryfunc(adapter, oid, buf, *buflen, 920123474Swpaul &byteswritten, &bytesneeded); 921123474Swpaul 922123474Swpaul if (byteswritten) 923123474Swpaul *buflen = byteswritten; 924123474Swpaul if (bytesneeded) 925123474Swpaul *buflen = bytesneeded; 926123474Swpaul 927123474Swpaul if (rval == NDIS_STATUS_INVALID_LENGTH || 928123474Swpaul rval == NDIS_STATUS_BUFFER_TOO_SHORT) 929123474Swpaul return(ENOSPC); 930123474Swpaul 931123474Swpaul if (rval == NDIS_STATUS_INVALID_OID) 932123474Swpaul return(EINVAL); 933123474Swpaul 934123474Swpaul if (rval == NDIS_STATUS_NOT_SUPPORTED || 935123474Swpaul rval == NDIS_STATUS_NOT_ACCEPTED) 936123474Swpaul return(ENOTSUP); 937123474Swpaul 938123474Swpaul if (rval == NDIS_STATUS_PENDING) 939123474Swpaul return(EAGAIN); 940123474Swpaul 941123474Swpaul return(0); 942123474Swpaul} 943123474Swpaul 944123474Swpaulint 945123474Swpaulndis_unload_driver(arg) 946123474Swpaul void *arg; 947123474Swpaul{ 948123474Swpaul struct ndis_softc *sc; 949123474Swpaul 950123474Swpaul sc = arg; 951123474Swpaul 952123474Swpaul free(sc->ndis_block.nmb_rlist, M_DEVBUF); 953123474Swpaul 954123474Swpaul ndis_flush_sysctls(sc); 955123474Swpaul ndis_libfini(); 956123474Swpaul ntoskrnl_libfini(); 957123474Swpaul 958123474Swpaul return(0); 959123474Swpaul} 960123474Swpaul 961123474Swpaulint 962123474Swpaulndis_load_driver(img, arg) 963123474Swpaul vm_offset_t img; 964123474Swpaul void *arg; 965123474Swpaul{ 966123474Swpaul __stdcall driver_entry entry; 967123474Swpaul image_optional_header opt_hdr; 968123474Swpaul image_import_descriptor imp_desc; 969123474Swpaul ndis_unicode_string dummystr; 970123474Swpaul ndis_driver_object drv; 971123474Swpaul ndis_miniport_block *block; 972123474Swpaul ndis_status status; 973123474Swpaul int idx; 974123474Swpaul uint32_t *ptr; 975123474Swpaul struct ndis_softc *sc; 976123474Swpaul 977123474Swpaul sc = arg; 978123474Swpaul 979123474Swpaul /* Perform text relocation */ 980123474Swpaul if (pe_relocate(img)) 981123474Swpaul return(ENOEXEC); 982123474Swpaul 983123474Swpaul /* Dynamically link the NDIS.SYS routines -- required. */ 984123474Swpaul if (pe_patch_imports(img, "NDIS", ndis_functbl)) 985123474Swpaul return(ENOEXEC); 986123474Swpaul 987123474Swpaul /* Dynamically link the HAL.dll routines -- also required. */ 988123474Swpaul if (pe_patch_imports(img, "HAL", hal_functbl)) 989123474Swpaul return(ENOEXEC); 990123474Swpaul 991123474Swpaul /* Dynamically link ntoskrnl.exe -- optional. */ 992123474Swpaul if (pe_get_import_descriptor(img, &imp_desc, "ntoskrnl") == 0) { 993123474Swpaul if (pe_patch_imports(img, "ntoskrnl", ntoskrnl_functbl)) 994123474Swpaul return(ENOEXEC); 995123474Swpaul } 996123474Swpaul 997123474Swpaul /* Initialize subsystems */ 998123474Swpaul ndis_libinit(); 999123474Swpaul ntoskrnl_libinit(); 1000123474Swpaul 1001123474Swpaul /* Locate the driver entry point */ 1002123474Swpaul pe_get_optional_header(img, &opt_hdr); 1003123474Swpaul entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr); 1004123474Swpaul 1005123474Swpaul /* 1006123474Swpaul * Now call the DriverEntry() routine. This will cause 1007123474Swpaul * a callout to the NdisInitializeWrapper() and 1008123474Swpaul * NdisMRegisterMiniport() routines. 1009123474Swpaul */ 1010123474Swpaul dummystr.nus_len = strlen(NDIS_DUMMY_PATH); 1011123474Swpaul dummystr.nus_maxlen = strlen(NDIS_DUMMY_PATH); 1012123474Swpaul dummystr.nus_buf = NULL; 1013123474Swpaul ndis_ascii_to_unicode(NDIS_DUMMY_PATH, &dummystr.nus_buf); 1014123474Swpaul drv.ndo_ifname = "ndis0"; 1015123474Swpaul 1016123474Swpaul status = entry(&drv, &dummystr); 1017123474Swpaul 1018123474Swpaul free (dummystr.nus_buf, M_DEVBUF); 1019123474Swpaul 1020123474Swpaul if (status != NDIS_STATUS_SUCCESS) 1021123474Swpaul return(ENODEV); 1022123474Swpaul 1023123474Swpaul /* 1024123474Swpaul * Now that we have the miniport driver characteristics, 1025123474Swpaul * create an NDIS block and call the init handler. 1026123474Swpaul * This will cause the driver to try to probe for 1027123474Swpaul * a device. 1028123474Swpaul */ 1029123474Swpaul 1030123474Swpaul block = &sc->ndis_block; 1031123474Swpaul bcopy((char *)&drv.ndo_chars, (char *)&sc->ndis_chars, 1032123474Swpaul sizeof(ndis_miniport_characteristics)); 1033123474Swpaul 1034123474Swpaul /*block->nmb_signature = 0xcafebabe;*/ 1035123474Swpaul 1036123474Swpaul ptr = (uint32_t *)block; 1037123474Swpaul for (idx = 0; idx < sizeof(ndis_miniport_block) / 4; idx++) { 1038123474Swpaul *ptr = idx | 0xdead0000; 1039123474Swpaul ptr++; 1040123474Swpaul } 1041123474Swpaul 1042123474Swpaul block->nmb_signature = (void *)0xcafebabe; 1043123474Swpaul block->nmb_setdone_func = ndis_setdone_func; 1044123474Swpaul block->nmb_status_func = ndis_status_func; 1045123474Swpaul block->nmb_statusdone_func = ndis_statusdone_func; 1046123474Swpaul block->nmb_resetdone_func = ndis_resetdone_func; 1047123474Swpaul 1048123474Swpaul block->nmb_ifp = &sc->arpcom.ac_if; 1049123474Swpaul block->nmb_dev = sc->ndis_dev; 1050123474Swpaul 1051123474Swpaul return(0); 1052123474Swpaul} 1053