Index: head/sys/compat/ndis/kern_ndis.c =================================================================== --- head/sys/compat/ndis/kern_ndis.c (revision 131952) +++ head/sys/compat/ndis/kern_ndis.c (revision 131953) @@ -1,1688 +1,1689 @@ /* * Copyright (c) 2003 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define NDIS_DUMMY_PATH "\\\\some\\bogus\\path" __stdcall static void ndis_status_func(ndis_handle, ndis_status, void *, uint32_t); __stdcall static void ndis_statusdone_func(ndis_handle); __stdcall static void ndis_setdone_func(ndis_handle, ndis_status); __stdcall static void ndis_getdone_func(ndis_handle, ndis_status); __stdcall static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t); __stdcall static void ndis_sendrsrcavail_func(ndis_handle); struct nd_head ndis_devhead; struct ndis_req { void (*nr_func)(void *); void *nr_arg; int nr_exit; STAILQ_ENTRY(ndis_req) link; }; struct ndisproc { struct ndisqhead *np_q; struct proc *np_p; int np_state; }; static void ndis_return(void *); static int ndis_create_kthreads(void); static void ndis_destroy_kthreads(void); static void ndis_stop_thread(int); static int ndis_enlarge_thrqueue(int); static int ndis_shrink_thrqueue(int); static void ndis_runq(void *); static uma_zone_t ndis_packet_zone, ndis_buffer_zone; struct mtx ndis_thr_mtx; static STAILQ_HEAD(ndisqhead, ndis_req) ndis_ttodo; struct ndisqhead ndis_itodo; struct ndisqhead ndis_free; static int ndis_jobs = 32; static struct ndisproc ndis_tproc; static struct ndisproc ndis_iproc; /* * This allows us to export our symbols to other modules. * Note that we call ourselves 'ndisapi' to avoid a namespace * collision with if_ndis.ko, which internally calls itself * 'ndis.' */ static int ndis_modevent(module_t mod, int cmd, void *arg) { int error = 0; switch (cmd) { case MOD_LOAD: /* Initialize subsystems */ ndis_libinit(); ntoskrnl_libinit(); /* Initialize TX buffer UMA zone. */ ndis_packet_zone = uma_zcreate("NDIS packet", sizeof(ndis_packet), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); ndis_buffer_zone = uma_zcreate("NDIS buffer", sizeof(ndis_buffer), NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); ndis_create_kthreads(); TAILQ_INIT(&ndis_devhead); break; case MOD_SHUTDOWN: /* stop kthreads */ ndis_destroy_kthreads(); if (TAILQ_FIRST(&ndis_devhead) == NULL) { /* Shut down subsystems */ ndis_libfini(); ntoskrnl_libfini(); /* Remove zones */ uma_zdestroy(ndis_packet_zone); uma_zdestroy(ndis_buffer_zone); } break; case MOD_UNLOAD: /* stop kthreads */ ndis_destroy_kthreads(); /* Shut down subsystems */ ndis_libfini(); ntoskrnl_libfini(); /* Remove zones */ uma_zdestroy(ndis_packet_zone); uma_zdestroy(ndis_buffer_zone); break; default: error = EINVAL; break; } return(error); } DEV_MODULE(ndisapi, ndis_modevent, NULL); MODULE_VERSION(ndisapi, 1); /* * We create two kthreads for the NDIS subsystem. One of them is a task * queue for performing various odd jobs. The other is an swi thread * reserved exclusively for running interrupt handlers. The reason we * have our own task queue is that there are some cases where we may * need to sleep for a significant amount of time, and if we were to * use one of the taskqueue threads, we might delay the processing * of other pending tasks which might need to run right away. We have * a separate swi thread because we don't want our interrupt handling * to be delayed either. * * By default there are 32 jobs available to start, and another 8 * are added to the free list each time a new device is created. */ static void ndis_runq(arg) void *arg; { struct ndis_req *r = NULL, *die = NULL; struct ndisproc *p; p = arg; while (1) { /* Sleep, but preserve our original priority. */ ndis_thsuspend(p->np_p, 0); /* Look for any jobs on the work queue. */ mtx_lock(&ndis_thr_mtx); p->np_state = NDIS_PSTATE_RUNNING; while(STAILQ_FIRST(p->np_q) != NULL) { r = STAILQ_FIRST(p->np_q); STAILQ_REMOVE_HEAD(p->np_q, link); mtx_unlock(&ndis_thr_mtx); /* Do the work. */ if (r->nr_func != NULL) (*r->nr_func)(r->nr_arg); mtx_lock(&ndis_thr_mtx); STAILQ_INSERT_HEAD(&ndis_free, r, link); /* Check for a shutdown request */ if (r->nr_exit == TRUE) die = r; } p->np_state = NDIS_PSTATE_SLEEPING; mtx_unlock(&ndis_thr_mtx); /* Bail if we were told to shut down. */ if (die != NULL) break; } wakeup(die); #if __FreeBSD_version < 502113 mtx_lock(&Giant); #endif kthread_exit(0); return; /* notreached */ } static int ndis_create_kthreads() { struct ndis_req *r; int i, error = 0; mtx_init(&ndis_thr_mtx, "NDIS thread lock", MTX_NDIS_LOCK, MTX_DEF); STAILQ_INIT(&ndis_ttodo); STAILQ_INIT(&ndis_itodo); STAILQ_INIT(&ndis_free); for (i = 0; i < ndis_jobs; i++) { r = malloc(sizeof(struct ndis_req), M_DEVBUF, M_WAITOK); if (r == NULL) { error = ENOMEM; break; } STAILQ_INSERT_HEAD(&ndis_free, r, link); } if (error == 0) { ndis_tproc.np_q = &ndis_ttodo; ndis_tproc.np_state = NDIS_PSTATE_SLEEPING; error = kthread_create(ndis_runq, &ndis_tproc, &ndis_tproc.np_p, RFHIGHPID, NDIS_KSTACK_PAGES, "ndis taskqueue"); } if (error == 0) { ndis_iproc.np_q = &ndis_itodo; ndis_iproc.np_state = NDIS_PSTATE_SLEEPING; error = kthread_create(ndis_runq, &ndis_iproc, &ndis_iproc.np_p, RFHIGHPID, NDIS_KSTACK_PAGES, "ndis swi"); } if (error) { while ((r = STAILQ_FIRST(&ndis_free)) != NULL) { STAILQ_REMOVE_HEAD(&ndis_free, link); free(r, M_DEVBUF); } return(error); } return(0); } static void ndis_destroy_kthreads() { struct ndis_req *r; /* Stop the threads. */ ndis_stop_thread(NDIS_TASKQUEUE); ndis_stop_thread(NDIS_SWI); /* Destroy request structures. */ while ((r = STAILQ_FIRST(&ndis_free)) != NULL) { STAILQ_REMOVE_HEAD(&ndis_free, link); free(r, M_DEVBUF); } mtx_destroy(&ndis_thr_mtx); return; } static void ndis_stop_thread(t) int t; { struct ndis_req *r; struct ndisqhead *q; struct proc *p; if (t == NDIS_TASKQUEUE) { q = &ndis_ttodo; p = ndis_tproc.np_p; } else { q = &ndis_itodo; p = ndis_iproc.np_p; } /* Create and post a special 'exit' job. */ mtx_lock(&ndis_thr_mtx); r = STAILQ_FIRST(&ndis_free); STAILQ_REMOVE_HEAD(&ndis_free, link); r->nr_func = NULL; r->nr_arg = NULL; r->nr_exit = TRUE; STAILQ_INSERT_TAIL(q, r, link); mtx_unlock(&ndis_thr_mtx); ndis_thresume(p); /* wait for thread exit */ tsleep(r, curthread->td_priority|PCATCH, "ndisthexit", hz * 60); /* Now empty the job list. */ mtx_lock(&ndis_thr_mtx); while ((r = STAILQ_FIRST(q)) != NULL) { STAILQ_REMOVE_HEAD(q, link); STAILQ_INSERT_HEAD(&ndis_free, r, link); } mtx_unlock(&ndis_thr_mtx); return; } static int ndis_enlarge_thrqueue(cnt) int cnt; { struct ndis_req *r; int i; for (i = 0; i < cnt; i++) { r = malloc(sizeof(struct ndis_req), M_DEVBUF, M_WAITOK); if (r == NULL) return(ENOMEM); mtx_lock(&ndis_thr_mtx); STAILQ_INSERT_HEAD(&ndis_free, r, link); ndis_jobs++; mtx_unlock(&ndis_thr_mtx); } return(0); } static int ndis_shrink_thrqueue(cnt) int cnt; { struct ndis_req *r; int i; for (i = 0; i < cnt; i++) { mtx_lock(&ndis_thr_mtx); r = STAILQ_FIRST(&ndis_free); if (r == NULL) { mtx_unlock(&ndis_thr_mtx); return(ENOMEM); } STAILQ_REMOVE_HEAD(&ndis_free, link); ndis_jobs--; mtx_unlock(&ndis_thr_mtx); free(r, M_DEVBUF); } return(0); } int ndis_unsched(func, arg, t) void (*func)(void *); void *arg; int t; { struct ndis_req *r; struct ndisqhead *q; struct proc *p; if (t == NDIS_TASKQUEUE) { q = &ndis_ttodo; p = ndis_tproc.np_p; } else { q = &ndis_itodo; p = ndis_iproc.np_p; } mtx_lock(&ndis_thr_mtx); STAILQ_FOREACH(r, q, link) { if (r->nr_func == func && r->nr_arg == arg) { STAILQ_REMOVE(q, r, ndis_req, link); STAILQ_INSERT_HEAD(&ndis_free, r, link); mtx_unlock(&ndis_thr_mtx); return(0); } } mtx_unlock(&ndis_thr_mtx); return(ENOENT); } int ndis_sched(func, arg, t) void (*func)(void *); void *arg; int t; { struct ndis_req *r; struct ndisqhead *q; struct proc *p; int s; if (t == NDIS_TASKQUEUE) { q = &ndis_ttodo; p = ndis_tproc.np_p; } else { q = &ndis_itodo; p = ndis_iproc.np_p; } mtx_lock(&ndis_thr_mtx); /* * Check to see if an instance of this job is already * pending. If so, don't bother queuing it again. */ STAILQ_FOREACH(r, q, link) { if (r->nr_func == func && r->nr_arg == arg) { mtx_unlock(&ndis_thr_mtx); return(0); } } r = STAILQ_FIRST(&ndis_free); if (r == NULL) { mtx_unlock(&ndis_thr_mtx); return(EAGAIN); } STAILQ_REMOVE_HEAD(&ndis_free, link); r->nr_func = func; r->nr_arg = arg; r->nr_exit = FALSE; STAILQ_INSERT_TAIL(q, r, link); if (t == NDIS_TASKQUEUE) s = ndis_tproc.np_state; else s = ndis_iproc.np_state; mtx_unlock(&ndis_thr_mtx); /* * Post the job, but only if the thread is actually blocked * on its own suspend call. If a driver queues up a job with * NdisScheduleWorkItem() which happens to do a KeWaitForObject(), * it may suspend there, and in that case we don't want to wake * it up until KeWaitForObject() gets woken up on its own. */ if (s == NDIS_PSTATE_SLEEPING) ndis_thresume(p); return(0); } int ndis_thsuspend(p, timo) struct proc *p; int timo; { int error; PROC_LOCK(p); error = msleep(&p->p_siglist, &p->p_mtx, curthread->td_priority|PDROP, "ndissp", timo); return(error); } void ndis_thresume(p) struct proc *p; { wakeup(&p->p_siglist); return; } __stdcall static void ndis_sendrsrcavail_func(adapter) ndis_handle adapter; { return; } __stdcall static void ndis_status_func(adapter, status, sbuf, slen) ndis_handle adapter; ndis_status status; void *sbuf; uint32_t slen; { ndis_miniport_block *block; block = adapter; if (block->nmb_ifp->if_flags & IFF_DEBUG) device_printf (block->nmb_dev, "status: %x\n", status); return; } __stdcall static void ndis_statusdone_func(adapter) ndis_handle adapter; { ndis_miniport_block *block; block = adapter; if (block->nmb_ifp->if_flags & IFF_DEBUG) device_printf (block->nmb_dev, "status complete\n"); return; } __stdcall static void ndis_setdone_func(adapter, status) ndis_handle adapter; ndis_status status; { ndis_miniport_block *block; block = adapter; block->nmb_setstat = status; wakeup(&block->nmb_wkupdpctimer); return; } __stdcall static void ndis_getdone_func(adapter, status) ndis_handle adapter; ndis_status status; { ndis_miniport_block *block; block = adapter; block->nmb_getstat = status; wakeup(&block->nmb_wkupdpctimer); return; } __stdcall static void ndis_resetdone_func(adapter, status, addressingreset) ndis_handle adapter; ndis_status status; uint8_t addressingreset; { ndis_miniport_block *block; block = adapter; if (block->nmb_ifp->if_flags & IFF_DEBUG) device_printf (block->nmb_dev, "reset done...\n"); wakeup(block->nmb_ifp); return; } int ndis_create_sysctls(arg) void *arg; { struct ndis_softc *sc; ndis_cfg *vals; char buf[256]; if (arg == NULL) return(EINVAL); sc = arg; vals = sc->ndis_regvals; TAILQ_INIT(&sc->ndis_cfglist_head); #if __FreeBSD_version < 502113 /* Create the sysctl tree. */ sc->ndis_tree = SYSCTL_ADD_NODE(&sc->ndis_ctx, SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, device_get_nameunit(sc->ndis_dev), CTLFLAG_RD, 0, device_get_desc(sc->ndis_dev)); #endif /* Add the driver-specific registry keys. */ vals = sc->ndis_regvals; while(1) { if (vals->nc_cfgkey == NULL) break; if (vals->nc_idx != sc->ndis_devidx) { vals++; continue; } #if __FreeBSD_version < 502113 SYSCTL_ADD_STRING(&sc->ndis_ctx, SYSCTL_CHILDREN(sc->ndis_tree), #else SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev), SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)), #endif OID_AUTO, vals->nc_cfgkey, CTLFLAG_RW, vals->nc_val, sizeof(vals->nc_val), vals->nc_cfgdesc); vals++; } /* Now add a couple of builtin keys. */ /* * Environment can be either Windows (0) or WindowsNT (1). * We qualify as the latter. */ ndis_add_sysctl(sc, "Environment", "Windows environment", "1", CTLFLAG_RD); /* NDIS version should be 5.1. */ ndis_add_sysctl(sc, "NdisVersion", "NDIS API Version", "0x00050001", CTLFLAG_RD); /* Bus type (PCI, PCMCIA, etc...) */ sprintf(buf, "%d", (int)sc->ndis_iftype); ndis_add_sysctl(sc, "BusType", "Bus Type", buf, CTLFLAG_RD); if (sc->ndis_res_io != NULL) { sprintf(buf, "0x%lx", rman_get_start(sc->ndis_res_io)); ndis_add_sysctl(sc, "IOBaseAddress", "Base I/O Address", buf, CTLFLAG_RD); } if (sc->ndis_irq != NULL) { sprintf(buf, "%lu", rman_get_start(sc->ndis_irq)); ndis_add_sysctl(sc, "InterruptNumber", "Interrupt Number", buf, CTLFLAG_RD); } return(0); } int ndis_add_sysctl(arg, key, desc, val, flag) void *arg; char *key; char *desc; char *val; int flag; { struct ndis_softc *sc; struct ndis_cfglist *cfg; char descstr[256]; sc = arg; cfg = malloc(sizeof(struct ndis_cfglist), M_DEVBUF, M_NOWAIT|M_ZERO); if (cfg == NULL) return(ENOMEM); cfg->ndis_cfg.nc_cfgkey = strdup(key, M_DEVBUF); if (desc == NULL) { snprintf(descstr, sizeof(descstr), "%s (dynamic)", key); cfg->ndis_cfg.nc_cfgdesc = strdup(descstr, M_DEVBUF); } else cfg->ndis_cfg.nc_cfgdesc = strdup(desc, M_DEVBUF); strcpy(cfg->ndis_cfg.nc_val, val); TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link); #if __FreeBSD_version < 502113 SYSCTL_ADD_STRING(&sc->ndis_ctx, SYSCTL_CHILDREN(sc->ndis_tree), #else SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev), SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)), #endif OID_AUTO, cfg->ndis_cfg.nc_cfgkey, flag, cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val), cfg->ndis_cfg.nc_cfgdesc); return(0); } int ndis_flush_sysctls(arg) void *arg; { struct ndis_softc *sc; struct ndis_cfglist *cfg; sc = arg; while (!TAILQ_EMPTY(&sc->ndis_cfglist_head)) { cfg = TAILQ_FIRST(&sc->ndis_cfglist_head); TAILQ_REMOVE(&sc->ndis_cfglist_head, cfg, link); free(cfg->ndis_cfg.nc_cfgkey, M_DEVBUF); free(cfg->ndis_cfg.nc_cfgdesc, M_DEVBUF); free(cfg, M_DEVBUF); } return(0); } static void ndis_return(arg) void *arg; { struct ndis_softc *sc; __stdcall ndis_return_handler returnfunc; ndis_handle adapter; ndis_packet *p; uint8_t irql; p = arg; sc = p->np_softc; adapter = sc->ndis_block.nmb_miniportadapterctx; if (adapter == NULL) return; returnfunc = sc->ndis_chars.nmc_return_packet_func; irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL); returnfunc(adapter, p); FASTCALL1(hal_lower_irql, irql); return; } void ndis_return_packet(buf, arg) void *buf; /* not used */ void *arg; { ndis_packet *p; if (arg == NULL) return; p = arg; /* Decrement refcount. */ p->np_refcnt--; /* Release packet when refcount hits zero, otherwise return. */ if (p->np_refcnt) return; ndis_sched(ndis_return, p, NDIS_SWI); return; } void ndis_free_bufs(b0) ndis_buffer *b0; { ndis_buffer *next; if (b0 == NULL) return; while(b0 != NULL) { next = b0->nb_next; uma_zfree (ndis_buffer_zone, b0); b0 = next; } return; } void ndis_free_packet(p) ndis_packet *p; { if (p == NULL) return; ndis_free_bufs(p->np_private.npp_head); uma_zfree(ndis_packet_zone, p); return; } int ndis_convert_res(arg) void *arg; { struct ndis_softc *sc; ndis_resource_list *rl = NULL; cm_partial_resource_desc *prd = NULL; ndis_miniport_block *block; device_t dev; struct resource_list *brl; struct resource_list brl_rev; struct resource_list_entry *brle, *n; int error = 0; sc = arg; block = &sc->ndis_block; dev = sc->ndis_dev; SLIST_INIT(&brl_rev); rl = malloc(sizeof(ndis_resource_list) + (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)), M_DEVBUF, M_NOWAIT|M_ZERO); if (rl == NULL) return(ENOMEM); rl->cprl_version = 5; rl->cprl_version = 1; rl->cprl_count = sc->ndis_rescnt; prd = rl->cprl_partial_descs; - brl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); + brl = BUS_GET_RESOURCE_LIST(dev, dev); + if (brl != NULL) { /* * We have a small problem. Some PCI devices have * multiple I/O ranges. Windows orders them starting * from lowest numbered BAR to highest. We discover * them in that order too, but insert them into a singly * linked list head first, which means when time comes * to traverse the list, we enumerate them in reverse * order. This screws up some drivers which expect the * BARs to be in ascending order so that they can choose * the "first" one as their register space. Unfortunately, * in order to fix this, we have to create our own * temporary list with the entries in reverse order. */ SLIST_FOREACH(brle, brl, link) { n = malloc(sizeof(struct resource_list_entry), M_TEMP, M_NOWAIT); if (n == NULL) { error = ENOMEM; goto bad; } bcopy((char *)brle, (char *)n, sizeof(struct resource_list_entry)); SLIST_INSERT_HEAD(&brl_rev, n, link); } SLIST_FOREACH(brle, &brl_rev, link) { switch (brle->type) { case SYS_RES_IOPORT: prd->cprd_type = CmResourceTypePort; prd->cprd_flags = CM_RESOURCE_PORT_IO; prd->cprd_sharedisp = CmResourceShareDeviceExclusive; prd->u.cprd_port.cprd_start.np_quad = brle->start; prd->u.cprd_port.cprd_len = brle->count; break; case SYS_RES_MEMORY: prd->cprd_type = CmResourceTypeMemory; prd->cprd_flags = CM_RESOURCE_MEMORY_READ_WRITE; prd->cprd_sharedisp = CmResourceShareDeviceExclusive; prd->u.cprd_port.cprd_start.np_quad = brle->start; prd->u.cprd_port.cprd_len = brle->count; break; case SYS_RES_IRQ: prd->cprd_type = CmResourceTypeInterrupt; prd->cprd_flags = 0; prd->cprd_sharedisp = CmResourceShareDeviceExclusive; prd->u.cprd_intr.cprd_level = brle->start; prd->u.cprd_intr.cprd_vector = brle->start; prd->u.cprd_intr.cprd_affinity = 0; break; default: break; } prd++; } } block->nmb_rlist = rl; bad: while (!SLIST_EMPTY(&brl_rev)) { n = SLIST_FIRST(&brl_rev); SLIST_REMOVE_HEAD(&brl_rev, link); free (n, M_TEMP); } return(error); } /* * Map an NDIS packet to an mbuf list. When an NDIS driver receives a * packet, it will hand it to us in the form of an ndis_packet, * which we need to convert to an mbuf that is then handed off * to the stack. Note: we configure the mbuf list so that it uses * the memory regions specified by the ndis_buffer structures in * the ndis_packet as external storage. In most cases, this will * point to a memory region allocated by the driver (either by * ndis_malloc_withtag() or ndis_alloc_sharedmem()). We expect * the driver to handle free()ing this region for is, so we set up * a dummy no-op free handler for it. */ int ndis_ptom(m0, p) struct mbuf **m0; ndis_packet *p; { struct mbuf *m, *prev = NULL; ndis_buffer *buf; ndis_packet_private *priv; uint32_t totlen = 0; if (p == NULL || m0 == NULL) return(EINVAL); priv = &p->np_private; buf = priv->npp_head; p->np_refcnt = 0; for (buf = priv->npp_head; buf != NULL; buf = buf->nb_next) { if (buf == priv->npp_head) MGETHDR(m, M_DONTWAIT, MT_HEADER); else MGET(m, M_DONTWAIT, MT_DATA); if (m == NULL) { m_freem(*m0); *m0 = NULL; return(ENOBUFS); } m->m_len = buf->nb_bytecount; m->m_data = MDL_VA(buf); MEXTADD(m, m->m_data, m->m_len, ndis_return_packet, p, 0, EXT_NDIS); p->np_refcnt++; totlen += m->m_len; if (m->m_flags & MT_HEADER) *m0 = m; else prev->m_next = m; prev = m; } (*m0)->m_pkthdr.len = totlen; return(0); } /* * Create an mbuf chain from an NDIS packet chain. * This is used mainly when transmitting packets, where we need * to turn an mbuf off an interface's send queue and transform it * into an NDIS packet which will be fed into the NDIS driver's * send routine. * * NDIS packets consist of two parts: an ndis_packet structure, * which is vaguely analagous to the pkthdr portion of an mbuf, * and one or more ndis_buffer structures, which define the * actual memory segments in which the packet data resides. * We need to allocate one ndis_buffer for each mbuf in a chain, * plus one ndis_packet as the header. */ int ndis_mtop(m0, p) struct mbuf *m0; ndis_packet **p; { struct mbuf *m; ndis_buffer *buf = NULL, *prev = NULL; ndis_packet_private *priv; if (p == NULL || m0 == NULL) return(EINVAL); /* If caller didn't supply a packet, make one. */ if (*p == NULL) { *p = uma_zalloc(ndis_packet_zone, M_NOWAIT|M_ZERO); if (*p == NULL) return(ENOMEM); } priv = &(*p)->np_private; priv->npp_totlen = m0->m_pkthdr.len; priv->npp_packetooboffset = offsetof(ndis_packet, np_oob); priv->npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS; for (m = m0; m != NULL; m = m->m_next) { if (m->m_len == 0) continue; buf = uma_zalloc(ndis_buffer_zone, M_NOWAIT | M_ZERO); if (buf == NULL) { ndis_free_packet(*p); *p = NULL; return(ENOMEM); } MDL_INIT(buf, m->m_data, m->m_len); if (priv->npp_head == NULL) priv->npp_head = buf; else prev->nb_next = buf; prev = buf; } priv->npp_tail = buf; priv->npp_totlen = m0->m_pkthdr.len; return(0); } int ndis_get_supported_oids(arg, oids, oidcnt) void *arg; ndis_oid **oids; int *oidcnt; { int len, rval; ndis_oid *o; if (arg == NULL || oids == NULL || oidcnt == NULL) return(EINVAL); len = 0; ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, NULL, &len); o = malloc(len, M_DEVBUF, M_NOWAIT); if (o == NULL) return(ENOMEM); rval = ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, o, &len); if (rval) { free(o, M_DEVBUF); return(rval); } *oids = o; *oidcnt = len / 4; return(0); } int ndis_set_info(arg, oid, buf, buflen) void *arg; ndis_oid oid; void *buf; int *buflen; { struct ndis_softc *sc; ndis_status rval; ndis_handle adapter; __stdcall ndis_setinfo_handler setfunc; uint32_t byteswritten = 0, bytesneeded = 0; int error; uint8_t irql; sc = arg; NDIS_LOCK(sc); setfunc = sc->ndis_chars.nmc_setinfo_func; adapter = sc->ndis_block.nmb_miniportadapterctx; NDIS_UNLOCK(sc); if (adapter == NULL || setfunc == NULL) return(ENXIO); irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL); rval = setfunc(adapter, oid, buf, *buflen, &byteswritten, &bytesneeded); FASTCALL1(hal_lower_irql, irql); if (rval == NDIS_STATUS_PENDING) { PROC_LOCK(curthread->td_proc); error = msleep(&sc->ndis_block.nmb_wkupdpctimer, &curthread->td_proc->p_mtx, curthread->td_priority|PDROP, "ndisset", 5 * hz); rval = sc->ndis_block.nmb_setstat; } if (byteswritten) *buflen = byteswritten; if (bytesneeded) *buflen = bytesneeded; if (rval == NDIS_STATUS_INVALID_LENGTH) return(ENOSPC); if (rval == NDIS_STATUS_INVALID_OID) return(EINVAL); if (rval == NDIS_STATUS_NOT_SUPPORTED || rval == NDIS_STATUS_NOT_ACCEPTED) return(ENOTSUP); if (rval != NDIS_STATUS_SUCCESS) return(ENODEV); return(0); } typedef void (*ndis_senddone_func)(ndis_handle, ndis_packet *, ndis_status); int ndis_send_packets(arg, packets, cnt) void *arg; ndis_packet **packets; int cnt; { struct ndis_softc *sc; ndis_handle adapter; __stdcall ndis_sendmulti_handler sendfunc; __stdcall ndis_senddone_func senddonefunc; int i; ndis_packet *p; uint8_t irql; sc = arg; adapter = sc->ndis_block.nmb_miniportadapterctx; if (adapter == NULL) return(ENXIO); sendfunc = sc->ndis_chars.nmc_sendmulti_func; senddonefunc = sc->ndis_block.nmb_senddone_func; irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL); sendfunc(adapter, packets, cnt); FASTCALL1(hal_lower_irql, irql); for (i = 0; i < cnt; i++) { p = packets[i]; /* * Either the driver already handed the packet to * ndis_txeof() due to a failure, or it wants to keep * it and release it asynchronously later. Skip to the * next one. */ if (p == NULL || p->np_oob.npo_status == NDIS_STATUS_PENDING) continue; senddonefunc(&sc->ndis_block, p, p->np_oob.npo_status); } return(0); } int ndis_send_packet(arg, packet) void *arg; ndis_packet *packet; { struct ndis_softc *sc; ndis_handle adapter; ndis_status status; __stdcall ndis_sendsingle_handler sendfunc; __stdcall ndis_senddone_func senddonefunc; uint8_t irql; sc = arg; adapter = sc->ndis_block.nmb_miniportadapterctx; if (adapter == NULL) return(ENXIO); sendfunc = sc->ndis_chars.nmc_sendsingle_func; senddonefunc = sc->ndis_block.nmb_senddone_func; irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL); status = sendfunc(adapter, packet, packet->np_private.npp_flags); FASTCALL1(hal_lower_irql, irql); if (status == NDIS_STATUS_PENDING) return(0); senddonefunc(&sc->ndis_block, packet, status); return(0); } int ndis_init_dma(arg) void *arg; { struct ndis_softc *sc; int i, error; sc = arg; sc->ndis_tmaps = malloc(sizeof(bus_dmamap_t) * sc->ndis_maxpkts, M_DEVBUF, M_NOWAIT|M_ZERO); if (sc->ndis_tmaps == NULL) return(ENOMEM); for (i = 0; i < sc->ndis_maxpkts; i++) { error = bus_dmamap_create(sc->ndis_ttag, 0, &sc->ndis_tmaps[i]); if (error) { free(sc->ndis_tmaps, M_DEVBUF); return(ENODEV); } } return(0); } int ndis_destroy_dma(arg) void *arg; { struct ndis_softc *sc; struct mbuf *m; ndis_packet *p = NULL; int i; sc = arg; for (i = 0; i < sc->ndis_maxpkts; i++) { if (sc->ndis_txarray[i] != NULL) { p = sc->ndis_txarray[i]; m = (struct mbuf *)p->np_rsvd[1]; if (m != NULL) m_freem(m); ndis_free_packet(sc->ndis_txarray[i]); } bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]); } free(sc->ndis_tmaps, M_DEVBUF); bus_dma_tag_destroy(sc->ndis_ttag); return(0); } int ndis_reset_nic(arg) void *arg; { struct ndis_softc *sc; ndis_handle adapter; __stdcall ndis_reset_handler resetfunc; uint8_t addressing_reset; struct ifnet *ifp; int rval; uint8_t irql; sc = arg; ifp = &sc->arpcom.ac_if; NDIS_LOCK(sc); adapter = sc->ndis_block.nmb_miniportadapterctx; resetfunc = sc->ndis_chars.nmc_reset_func; NDIS_UNLOCK(sc); if (adapter == NULL || resetfunc == NULL) return(EIO); irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL); rval = resetfunc(&addressing_reset, adapter); FASTCALL1(hal_lower_irql, irql); if (rval == NDIS_STATUS_PENDING) { PROC_LOCK(curthread->td_proc); msleep(sc, &curthread->td_proc->p_mtx, curthread->td_priority|PDROP, "ndisrst", 0); } return(0); } int ndis_halt_nic(arg) void *arg; { struct ndis_softc *sc; ndis_handle adapter; __stdcall ndis_halt_handler haltfunc; struct ifnet *ifp; sc = arg; ifp = &sc->arpcom.ac_if; NDIS_LOCK(sc); adapter = sc->ndis_block.nmb_miniportadapterctx; if (adapter == NULL) { NDIS_UNLOCK(sc); return(EIO); } /* * The adapter context is only valid after the init * handler has been called, and is invalid once the * halt handler has been called. */ haltfunc = sc->ndis_chars.nmc_halt_func; NDIS_UNLOCK(sc); haltfunc(adapter); NDIS_LOCK(sc); sc->ndis_block.nmb_miniportadapterctx = NULL; NDIS_UNLOCK(sc); return(0); } int ndis_shutdown_nic(arg) void *arg; { struct ndis_softc *sc; ndis_handle adapter; __stdcall ndis_shutdown_handler shutdownfunc; sc = arg; NDIS_LOCK(sc); adapter = sc->ndis_block.nmb_miniportadapterctx; shutdownfunc = sc->ndis_chars.nmc_shutdown_handler; NDIS_UNLOCK(sc); if (adapter == NULL || shutdownfunc == NULL) return(EIO); if (sc->ndis_chars.nmc_rsvd0 == NULL) shutdownfunc(adapter); else shutdownfunc(sc->ndis_chars.nmc_rsvd0); ndis_shrink_thrqueue(8); TAILQ_REMOVE(&ndis_devhead, &sc->ndis_block, link); return(0); } int ndis_init_nic(arg) void *arg; { struct ndis_softc *sc; ndis_miniport_block *block; __stdcall ndis_init_handler initfunc; ndis_status status, openstatus = 0; ndis_medium mediumarray[NdisMediumMax]; uint32_t chosenmedium, i; if (arg == NULL) return(EINVAL); sc = arg; NDIS_LOCK(sc); block = &sc->ndis_block; initfunc = sc->ndis_chars.nmc_init_func; NDIS_UNLOCK(sc); TAILQ_INIT(&block->nmb_timerlist); for (i = 0; i < NdisMediumMax; i++) mediumarray[i] = i; status = initfunc(&openstatus, &chosenmedium, mediumarray, NdisMediumMax, block, block); /* * If the init fails, blow away the other exported routines * we obtained from the driver so we can't call them later. * If the init failed, none of these will work. */ if (status != NDIS_STATUS_SUCCESS) { NDIS_LOCK(sc); sc->ndis_block.nmb_miniportadapterctx = NULL; NDIS_UNLOCK(sc); return(ENXIO); } return(0); } void ndis_enable_intr(arg) void *arg; { struct ndis_softc *sc; ndis_handle adapter; __stdcall ndis_enable_interrupts_handler intrenbfunc; sc = arg; adapter = sc->ndis_block.nmb_miniportadapterctx; intrenbfunc = sc->ndis_chars.nmc_enable_interrupts_func; if (adapter == NULL || intrenbfunc == NULL) return; intrenbfunc(adapter); return; } void ndis_disable_intr(arg) void *arg; { struct ndis_softc *sc; ndis_handle adapter; __stdcall ndis_disable_interrupts_handler intrdisfunc; sc = arg; NDIS_LOCK(sc); adapter = sc->ndis_block.nmb_miniportadapterctx; intrdisfunc = sc->ndis_chars.nmc_disable_interrupts_func; NDIS_UNLOCK(sc); if (adapter == NULL || intrdisfunc == NULL) return; intrdisfunc(adapter); return; } int ndis_isr(arg, ourintr, callhandler) void *arg; int *ourintr; int *callhandler; { struct ndis_softc *sc; ndis_handle adapter; __stdcall ndis_isr_handler isrfunc; uint8_t accepted, queue; if (arg == NULL || ourintr == NULL || callhandler == NULL) return(EINVAL); sc = arg; adapter = sc->ndis_block.nmb_miniportadapterctx; isrfunc = sc->ndis_chars.nmc_isr_func; if (adapter == NULL || isrfunc == NULL) return(ENXIO); isrfunc(&accepted, &queue, adapter); *ourintr = accepted; *callhandler = queue; return(0); } int ndis_intrhand(arg) void *arg; { struct ndis_softc *sc; ndis_handle adapter; __stdcall ndis_interrupt_handler intrfunc; if (arg == NULL) return(EINVAL); sc = arg; NDIS_LOCK(sc); adapter = sc->ndis_block.nmb_miniportadapterctx; intrfunc = sc->ndis_chars.nmc_interrupt_func; NDIS_UNLOCK(sc); if (adapter == NULL || intrfunc == NULL) return(EINVAL); intrfunc(adapter); return(0); } int ndis_get_info(arg, oid, buf, buflen) void *arg; ndis_oid oid; void *buf; int *buflen; { struct ndis_softc *sc; ndis_status rval; ndis_handle adapter; __stdcall ndis_queryinfo_handler queryfunc; uint32_t byteswritten = 0, bytesneeded = 0; int error; uint8_t irql; sc = arg; NDIS_LOCK(sc); queryfunc = sc->ndis_chars.nmc_queryinfo_func; adapter = sc->ndis_block.nmb_miniportadapterctx; NDIS_UNLOCK(sc); if (adapter == NULL || queryfunc == NULL) return(ENXIO); irql = FASTCALL1(hal_raise_irql, DISPATCH_LEVEL); rval = queryfunc(adapter, oid, buf, *buflen, &byteswritten, &bytesneeded); FASTCALL1(hal_lower_irql, irql); /* Wait for requests that block. */ if (rval == NDIS_STATUS_PENDING) { PROC_LOCK(curthread->td_proc); error = msleep(&sc->ndis_block.nmb_wkupdpctimer, &curthread->td_proc->p_mtx, curthread->td_priority|PDROP, "ndisget", 5 * hz); rval = sc->ndis_block.nmb_getstat; } if (byteswritten) *buflen = byteswritten; if (bytesneeded) *buflen = bytesneeded; if (rval == NDIS_STATUS_INVALID_LENGTH || rval == NDIS_STATUS_BUFFER_TOO_SHORT) return(ENOSPC); if (rval == NDIS_STATUS_INVALID_OID) return(EINVAL); if (rval == NDIS_STATUS_NOT_SUPPORTED || rval == NDIS_STATUS_NOT_ACCEPTED) return(ENOTSUP); if (rval != NDIS_STATUS_SUCCESS) return(ENODEV); return(0); } int ndis_unload_driver(arg) void *arg; { struct ndis_softc *sc; sc = arg; free(sc->ndis_block.nmb_rlist, M_DEVBUF); ndis_flush_sysctls(sc); ndis_shrink_thrqueue(8); TAILQ_REMOVE(&ndis_devhead, &sc->ndis_block, link); return(0); } #define NDIS_LOADED htonl(0x42534F44) int ndis_load_driver(img, arg) vm_offset_t img; void *arg; { __stdcall driver_entry entry; image_optional_header opt_hdr; image_import_descriptor imp_desc; ndis_unicode_string dummystr; ndis_miniport_block *block; ndis_status status; int idx; uint32_t *ptr; struct ndis_softc *sc; sc = arg; /* * Only perform the relocation/linking phase once * since the binary image may be shared among multiple * device instances. */ ptr = (uint32_t *)(img + 8); if (*ptr != NDIS_LOADED) { /* Perform text relocation */ if (pe_relocate(img)) return(ENOEXEC); /* Dynamically link the NDIS.SYS routines -- required. */ if (pe_patch_imports(img, "NDIS", ndis_functbl)) return(ENOEXEC); /* Dynamically link the HAL.dll routines -- also required. */ if (pe_patch_imports(img, "HAL", hal_functbl)) return(ENOEXEC); /* Dynamically link ntoskrnl.exe -- optional. */ if (pe_get_import_descriptor(img, &imp_desc, "ntoskrnl") == 0) { if (pe_patch_imports(img, "ntoskrnl", ntoskrnl_functbl)) return(ENOEXEC); } *ptr = NDIS_LOADED; } /* Locate the driver entry point */ pe_get_optional_header(img, &opt_hdr); entry = (driver_entry)pe_translate_addr(img, opt_hdr.ioh_entryaddr); dummystr.nus_len = strlen(NDIS_DUMMY_PATH) * 2; dummystr.nus_maxlen = strlen(NDIS_DUMMY_PATH) * 2; dummystr.nus_buf = NULL; ndis_ascii_to_unicode(NDIS_DUMMY_PATH, &dummystr.nus_buf); /* * Now that we have the miniport driver characteristics, * create an NDIS block and call the init handler. * This will cause the driver to try to probe for * a device. */ block = &sc->ndis_block; ptr = (uint32_t *)block; for (idx = 0; idx < sizeof(ndis_miniport_block) / 4; idx++) { *ptr = idx | 0xdead0000; ptr++; } block->nmb_signature = (void *)0xcafebabe; block->nmb_setdone_func = ndis_setdone_func; block->nmb_querydone_func = ndis_getdone_func; block->nmb_status_func = ndis_status_func; block->nmb_statusdone_func = ndis_statusdone_func; block->nmb_resetdone_func = ndis_resetdone_func; block->nmb_sendrsrc_func = ndis_sendrsrcavail_func; block->nmb_ifp = &sc->arpcom.ac_if; block->nmb_dev = sc->ndis_dev; block->nmb_img = img; block->nmb_devobj.do_rsvd = block; /* * Now call the DriverEntry() routine. This will cause * a callout to the NdisInitializeWrapper() and * NdisMRegisterMiniport() routines. */ status = entry(&block->nmb_devobj, &dummystr); free (dummystr.nus_buf, M_DEVBUF); if (status != NDIS_STATUS_SUCCESS) return(ENODEV); ndis_enlarge_thrqueue(8); TAILQ_INSERT_TAIL(&ndis_devhead, block, link); return(0); } Index: head/sys/compat/ndis/ndis_var.h =================================================================== --- head/sys/compat/ndis/ndis_var.h (revision 131952) +++ head/sys/compat/ndis/ndis_var.h (revision 131953) @@ -1,1525 +1,1527 @@ /* * Copyright (c) 2003 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _NDIS_VAR_H_ #define _NDIS_VAR_H_ /* Forward declarations */ struct ndis_miniport_block; struct ndis_mdriver_block; typedef struct ndis_miniport_block ndis_miniport_block; typedef struct ndis_mdriver_block ndis_mdriver_block; /* Base types */ typedef uint32_t ndis_status; typedef void *ndis_handle; typedef uint32_t ndis_oid; typedef uint32_t ndis_error_code; typedef register_t ndis_kspin_lock; typedef uint8_t ndis_kirql; /* * NDIS status codes (there are lots of them). The ones that * don't seem to fit the pattern are actually mapped to generic * NT status codes. */ #define NDIS_STATUS_SUCCESS 0 #define NDIS_STATUS_PENDING 0x00000103 #define NDIS_STATUS_NOT_RECOGNIZED 0x00010001 #define NDIS_STATUS_NOT_COPIED 0x00010002 #define NDIS_STATUS_NOT_ACCEPTED 0x00010003 #define NDIS_STATUS_CALL_ACTIVE 0x00010007 #define NDIS_STATUS_ONLINE 0x40010003 #define NDIS_STATUS_RESET_START 0x40010004 #define NDIS_STATUS_RESET_END 0x40010005 #define NDIS_STATUS_RING_STATUS 0x40010006 #define NDIS_STATUS_CLOSED 0x40010007 #define NDIS_STATUS_WAN_LINE_UP 0x40010008 #define NDIS_STATUS_WAN_LINE_DOWN 0x40010009 #define NDIS_STATUS_WAN_FRAGMENT 0x4001000A #define NDIS_STATUS_MEDIA_CONNECT 0x4001000B #define NDIS_STATUS_MEDIA_DISCONNECT 0x4001000C #define NDIS_STATUS_HARDWARE_LINE_UP 0x4001000D #define NDIS_STATUS_HARDWARE_LINE_DOWN 0x4001000E #define NDIS_STATUS_INTERFACE_UP 0x4001000F #define NDIS_STATUS_INTERFACE_DOWN 0x40010010 #define NDIS_STATUS_MEDIA_BUSY 0x40010011 #define NDIS_STATUS_MEDIA_SPECIFIC_INDICATION 0x40010012 #define NDIS_STATUS_WW_INDICATION NDIS_STATUS_MEDIA_SPECIFIC_INDICATION #define NDIS_STATUS_LINK_SPEED_CHANGE 0x40010013 #define NDIS_STATUS_WAN_GET_STATS 0x40010014 #define NDIS_STATUS_WAN_CO_FRAGMENT 0x40010015 #define NDIS_STATUS_WAN_CO_LINKPARAMS 0x40010016 #define NDIS_STATUS_NOT_RESETTABLE 0x80010001 #define NDIS_STATUS_SOFT_ERRORS 0x80010003 #define NDIS_STATUS_HARD_ERRORS 0x80010004 #define NDIS_STATUS_BUFFER_OVERFLOW 0x80000005 #define NDIS_STATUS_FAILURE 0xC0000001 #define NDIS_STATUS_RESOURCES 0xC000009A #define NDIS_STATUS_CLOSING 0xC0010002 #define NDIS_STATUS_BAD_VERSION 0xC0010004 #define NDIS_STATUS_BAD_CHARACTERISTICS 0xC0010005 #define NDIS_STATUS_ADAPTER_NOT_FOUND 0xC0010006 #define NDIS_STATUS_OPEN_FAILED 0xC0010007 #define NDIS_STATUS_DEVICE_FAILED 0xC0010008 #define NDIS_STATUS_MULTICAST_FULL 0xC0010009 #define NDIS_STATUS_MULTICAST_EXISTS 0xC001000A #define NDIS_STATUS_MULTICAST_NOT_FOUND 0xC001000B #define NDIS_STATUS_REQUEST_ABORTED 0xC001000C #define NDIS_STATUS_RESET_IN_PROGRESS 0xC001000D #define NDIS_STATUS_CLOSING_INDICATING 0xC001000E #define NDIS_STATUS_NOT_SUPPORTED 0xC00000BB #define NDIS_STATUS_INVALID_PACKET 0xC001000F #define NDIS_STATUS_OPEN_LIST_FULL 0xC0010010 #define NDIS_STATUS_ADAPTER_NOT_READY 0xC0010011 #define NDIS_STATUS_ADAPTER_NOT_OPEN 0xC0010012 #define NDIS_STATUS_NOT_INDICATING 0xC0010013 #define NDIS_STATUS_INVALID_LENGTH 0xC0010014 #define NDIS_STATUS_INVALID_DATA 0xC0010015 #define NDIS_STATUS_BUFFER_TOO_SHORT 0xC0010016 #define NDIS_STATUS_INVALID_OID 0xC0010017 #define NDIS_STATUS_ADAPTER_REMOVED 0xC0010018 #define NDIS_STATUS_UNSUPPORTED_MEDIA 0xC0010019 #define NDIS_STATUS_GROUP_ADDRESS_IN_USE 0xC001001A #define NDIS_STATUS_FILE_NOT_FOUND 0xC001001B #define NDIS_STATUS_ERROR_READING_FILE 0xC001001C #define NDIS_STATUS_ALREADY_MAPPED 0xC001001D #define NDIS_STATUS_RESOURCE_CONFLICT 0xC001001E #define NDIS_STATUS_NO_CABLE 0xC001001F #define NDIS_STATUS_INVALID_SAP 0xC0010020 #define NDIS_STATUS_SAP_IN_USE 0xC0010021 #define NDIS_STATUS_INVALID_ADDRESS 0xC0010022 #define NDIS_STATUS_VC_NOT_ACTIVATED 0xC0010023 #define NDIS_STATUS_DEST_OUT_OF_ORDER 0xC0010024 #define NDIS_STATUS_VC_NOT_AVAILABLE 0xC0010025 #define NDIS_STATUS_CELLRATE_NOT_AVAILABLE 0xC0010026 #define NDIS_STATUS_INCOMPATABLE_QOS 0xC0010027 #define NDIS_STATUS_AAL_PARAMS_UNSUPPORTED 0xC0010028 #define NDIS_STATUS_NO_ROUTE_TO_DESTINATION 0xC0010029 #define NDIS_STATUS_TOKEN_RING_OPEN_ERROR 0xC0011000 #define NDIS_STATUS_INVALID_DEVICE_REQUEST 0xC0000010 #define NDIS_STATUS_NETWORK_UNREACHABLE 0xC000023C /* * NDIS event codes. They are usually reported to NdisWriteErrorLogEntry(). */ #define EVENT_NDIS_RESOURCE_CONFLICT 0xC0001388 #define EVENT_NDIS_OUT_OF_RESOURCE 0xC0001389 #define EVENT_NDIS_HARDWARE_FAILURE 0xC000138A #define EVENT_NDIS_ADAPTER_NOT_FOUND 0xC000138B #define EVENT_NDIS_INTERRUPT_CONNECT 0xC000138C #define EVENT_NDIS_DRIVER_FAILURE 0xC000138D #define EVENT_NDIS_BAD_VERSION 0xC000138E #define EVENT_NDIS_TIMEOUT 0x8000138F #define EVENT_NDIS_NETWORK_ADDRESS 0xC0001390 #define EVENT_NDIS_UNSUPPORTED_CONFIGURATION 0xC0001391 #define EVENT_NDIS_INVALID_VALUE_FROM_ADAPTER 0xC0001392 #define EVENT_NDIS_MISSING_CONFIGURATION_PARAMETER 0xC0001393 #define EVENT_NDIS_BAD_IO_BASE_ADDRESS 0xC0001394 #define EVENT_NDIS_RECEIVE_SPACE_SMALL 0x40001395 #define EVENT_NDIS_ADAPTER_DISABLED 0x80001396 #define EVENT_NDIS_IO_PORT_CONFLICT 0x80001397 #define EVENT_NDIS_PORT_OR_DMA_CONFLICT 0x80001398 #define EVENT_NDIS_MEMORY_CONFLICT 0x80001399 #define EVENT_NDIS_INTERRUPT_CONFLICT 0x8000139A #define EVENT_NDIS_DMA_CONFLICT 0x8000139B #define EVENT_NDIS_INVALID_DOWNLOAD_FILE_ERROR 0xC000139C #define EVENT_NDIS_MAXRECEIVES_ERROR 0x8000139D #define EVENT_NDIS_MAXTRANSMITS_ERROR 0x8000139E #define EVENT_NDIS_MAXFRAMESIZE_ERROR 0x8000139F #define EVENT_NDIS_MAXINTERNALBUFS_ERROR 0x800013A0 #define EVENT_NDIS_MAXMULTICAST_ERROR 0x800013A1 #define EVENT_NDIS_PRODUCTID_ERROR 0x800013A2 #define EVENT_NDIS_LOBE_FAILUE_ERROR 0x800013A3 #define EVENT_NDIS_SIGNAL_LOSS_ERROR 0x800013A4 #define EVENT_NDIS_REMOVE_RECEIVED_ERROR 0x800013A5 #define EVENT_NDIS_TOKEN_RING_CORRECTION 0x400013A6 #define EVENT_NDIS_ADAPTER_CHECK_ERROR 0xC00013A7 #define EVENT_NDIS_RESET_FAILURE_ERROR 0x800013A8 #define EVENT_NDIS_CABLE_DISCONNECTED_ERROR 0x800013A9 #define EVENT_NDIS_RESET_FAILURE_CORRECTION 0x800013AA /* * NDIS OIDs used by the queryinfo/setinfo routines. * Some are required by all NDIS drivers, some are specific to * a particular type of device, and some are purely optional. * Unfortunately, one of the purely optional OIDs is the one * that lets us set the MAC address of the device. */ /* Required OIDs */ #define OID_GEN_SUPPORTED_LIST 0x00010101 #define OID_GEN_HARDWARE_STATUS 0x00010102 #define OID_GEN_MEDIA_SUPPORTED 0x00010103 #define OID_GEN_MEDIA_IN_USE 0x00010104 #define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 #define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 #define OID_GEN_LINK_SPEED 0x00010107 #define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 #define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 #define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A #define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B #define OID_GEN_VENDOR_ID 0x0001010C #define OID_GEN_VENDOR_DESCRIPTION 0x0001010D #define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E #define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F #define OID_GEN_DRIVER_VERSION 0x00010110 #define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 #define OID_GEN_PROTOCOL_OPTIONS 0x00010112 #define OID_GEN_MAC_OPTIONS 0x00010113 #define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 #define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 #define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 #define OID_GEN_SUPPORTED_GUIDS 0x00010117 #define OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 /* Set only */ #define OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 /* Set only */ #define OID_GEN_MACHINE_NAME 0x0001021A #define OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B /* Set only */ #define OID_GEN_VLAN_ID 0x0001021C /* Optional OIDs. */ #define OID_GEN_MEDIA_CAPABILITIES 0x00010201 #define OID_GEN_PHYSICAL_MEDIUM 0x00010202 /* Required statistics OIDs. */ #define OID_GEN_XMIT_OK 0x00020101 #define OID_GEN_RCV_OK 0x00020102 #define OID_GEN_XMIT_ERROR 0x00020103 #define OID_GEN_RCV_ERROR 0x00020104 #define OID_GEN_RCV_NO_BUFFER 0x00020105 /* Optional OID statistics */ #define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 #define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 #define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 #define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 #define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 #define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 #define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 #define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 #define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 #define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A #define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B #define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C #define OID_GEN_RCV_CRC_ERROR 0x0002020D #define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E #define OID_GEN_GET_TIME_CAPS 0x0002020F #define OID_GEN_GET_NETCARD_TIME 0x00020210 #define OID_GEN_NETCARD_LOAD 0x00020211 #define OID_GEN_DEVICE_PROFILE 0x00020212 /* 802.3 (ethernet) OIDs */ #define OID_802_3_PERMANENT_ADDRESS 0x01010101 #define OID_802_3_CURRENT_ADDRESS 0x01010102 #define OID_802_3_MULTICAST_LIST 0x01010103 #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 #define OID_802_3_MAC_OPTIONS 0x01010105 #define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001 #define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 #define OID_802_3_XMIT_ONE_COLLISION 0x01020102 #define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 #define OID_802_3_XMIT_DEFERRED 0x01020201 #define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 #define OID_802_3_RCV_OVERRUN 0x01020203 #define OID_802_3_XMIT_UNDERRUN 0x01020204 #define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 #define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 #define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 /* PnP and power management OIDs */ #define OID_PNP_CAPABILITIES 0xFD010100 #define OID_PNP_SET_POWER 0xFD010101 #define OID_PNP_QUERY_POWER 0xFD010102 #define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 #define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 #define OID_PNP_WAKE_UP_PATTERN_LIST 0xFD010105 #define OID_PNP_ENABLE_WAKE_UP 0xFD010106 /* PnP/PM Statistics (Optional). */ #define OID_PNP_WAKE_UP_OK 0xFD020200 #define OID_PNP_WAKE_UP_ERROR 0xFD020201 /* The following bits are defined for OID_PNP_ENABLE_WAKE_UP */ #define NDIS_PNP_WAKE_UP_MAGIC_PACKET 0x00000001 #define NDIS_PNP_WAKE_UP_PATTERN_MATCH 0x00000002 #define NDIS_PNP_WAKE_UP_LINK_CHANGE 0x00000004 /* 802.11 OIDs */ #define OID_802_11_BSSID 0x0D010101 #define OID_802_11_SSID 0x0D010102 #define OID_802_11_NETWORK_TYPES_SUPPORTED 0x0D010203 #define OID_802_11_NETWORK_TYPE_IN_USE 0x0D010204 #define OID_802_11_TX_POWER_LEVEL 0x0D010205 #define OID_802_11_RSSI 0x0D010206 #define OID_802_11_RSSI_TRIGGER 0x0D010207 #define OID_802_11_INFRASTRUCTURE_MODE 0x0D010108 #define OID_802_11_FRAGMENTATION_THRESHOLD 0x0D010209 #define OID_802_11_RTS_THRESHOLD 0x0D01020A #define OID_802_11_NUMBER_OF_ANTENNAS 0x0D01020B #define OID_802_11_RX_ANTENNA_SELECTED 0x0D01020C #define OID_802_11_TX_ANTENNA_SELECTED 0x0D01020D #define OID_802_11_SUPPORTED_RATES 0x0D01020E #define OID_802_11_DESIRED_RATES 0x0D010210 #define OID_802_11_CONFIGURATION 0x0D010211 #define OID_802_11_STATISTICS 0x0D020212 #define OID_802_11_ADD_WEP 0x0D010113 #define OID_802_11_REMOVE_WEP 0x0D010114 #define OID_802_11_DISASSOCIATE 0x0D010115 #define OID_802_11_POWER_MODE 0x0D010216 #define OID_802_11_BSSID_LIST 0x0D010217 #define OID_802_11_AUTHENTICATION_MODE 0x0D010118 #define OID_802_11_PRIVACY_FILTER 0x0D010119 #define OID_802_11_BSSID_LIST_SCAN 0x0D01011A #define OID_802_11_WEP_STATUS 0x0D01011B #define OID_802_11_ENCRYPTION_STATUS OID_802_11_WEP_STATUS #define OID_802_11_RELOAD_DEFAULTS 0x0D01011C #define OID_802_11_ADD_KEY 0x0D01011D #define OID_802_11_REMOVE_KEY 0x0D01011E #define OID_802_11_ASSOCIATION_INFORMATION 0x0D01011F #define OID_802_11_TEST 0x0D010120 /* structures/definitions for 802.11 */ #define NDIS_80211_NETTYPE_11FH 0x00000000 #define NDIS_80211_NETTYPE_11DS 0x00000001 #define NDIS_80211_NETTYPE_11OFDM5 0x00000002 #define NDIS_80211_NETTYPE_11OFDM24 0x00000003 struct ndis_80211_nettype_list { uint32_t ntl_items; uint32_t ntl_type[1]; }; #define NDIS_80211_POWERMODE_CAM 0x00000000 #define NDIS_80211_POWERMODE_MAX_PSP 0x00000001 #define NDIS_80211_POWERMODE_FAST_PSP 0x00000002 typedef uint32_t ndis_80211_power; /* Power in milliwatts */ typedef uint32_t ndis_80211_rssi; /* Signal strength in dBm */ struct ndis_80211_config_fh { uint32_t ncf_length; uint32_t ncf_hoppatterh; uint32_t ncf_hopset; uint32_t ncf_dwelltime; }; typedef struct ndis_80211_config_fh ndis_80211_config_fh; struct ndis_80211_config { uint32_t nc_length; uint32_t nc_beaconperiod; uint32_t nc_atimwin; uint32_t nc_dsconfig; ndis_80211_config_fh nc_fhconfig; }; typedef struct ndis_80211_config ndis_80211_config; struct ndis_80211_stats { uint32_t ns_length; uint64_t ns_txfragcnt; uint64_t ns_txmcastcnt; uint64_t ns_failedcnt; uint64_t ns_retrycnt; uint64_t ns_multiretrycnt; uint64_t ns_rtssuccesscnt; uint64_t ns_rtsfailcnt; uint64_t ns_ackfailcnt; uint64_t ns_dupeframecnt; uint64_t ns_rxfragcnt; uint64_t ns_rxmcastcnt; uint64_t ns_fcserrcnt; }; typedef struct ndis_80211_stats ndis_80211_stats; typedef uint32_t ndis_80211_key_idx; struct ndis_80211_wep { uint32_t nw_length; uint32_t nw_keyidx; uint32_t nw_keylen; uint8_t nw_keydata[256]; }; typedef struct ndis_80211_wep ndis_80211_wep; #define NDIS_80211_WEPKEY_TX 0x80000000 #define NDIS_80211_WEPKEY_PERCLIENT 0x40000000 #define NDIS_80211_NET_INFRA_IBSS 0x00000000 #define NDIS_80211_NET_INFRA_BSS 0x00000001 #define NDIS_80211_NET_INFRA_AUTO 0x00000002 #define NDIS_80211_AUTHMODE_OPEN 0x00000000 #define NDIS_80211_AUTHMODE_SHARED 0x00000001 #define NDIS_80211_AUTHMODE_AUTO 0x00000002 #define NDIS_80211_AUTHMODE_WPA 0x00000003 #define NDIS_80211_AUTHMODE_WPAPSK 0x00000004 #define NDIS_80211_AUTHMODE_WPANONE 0x00000005 typedef uint8_t ndis_80211_rates[8]; typedef uint8_t ndis_80211_rates_ex[16]; typedef uint8_t ndis_80211_macaddr[6]; struct ndis_80211_ssid { uint32_t ns_ssidlen; uint8_t ns_ssid[32]; }; typedef struct ndis_80211_ssid ndis_80211_ssid; struct ndis_wlan_bssid { uint32_t nwb_length; ndis_80211_macaddr nwb_macaddr; uint8_t nwb_rsvd[2]; ndis_80211_ssid nwb_ssid; uint32_t nwb_privacy; ndis_80211_rssi nwb_rssi; uint32_t nwb_nettype; ndis_80211_config nwb_config; uint32_t nwb_netinfra; ndis_80211_rates nwb_supportedrates; }; typedef struct ndis_wlan_bssid ndis_wlan_bssid; struct ndis_80211_bssid_list { uint32_t nbl_items; ndis_wlan_bssid nbl_bssid[1]; }; typedef struct ndis_80211_bssid_list ndis_80211_bssid_list; struct ndis_wlan_bssid_ex { uint32_t nwbx_len; ndis_80211_macaddr nwbx_macaddr; uint8_t nwbx_rsvd[2]; ndis_80211_ssid nwbx_ssid; uint32_t nwbx_privacy; ndis_80211_rssi nwbx_rssi; uint32_t nwbx_nettype; ndis_80211_config nwbx_config; uint32_t nwbx_netinfra; ndis_80211_rates_ex nwbx_supportedrates; uint32_t nwbx_ielen; uint32_t nwbx_ies[1]; }; typedef struct ndis_wlan_bssid_ex ndis_wlan_bssid_ex; struct ndis_80211_bssid_list_ex { uint32_t nblx_items; ndis_wlan_bssid_ex nblx_bssid[1]; }; typedef struct ndis_80211_bssid_list_ex ndis_80211_bssid_list_ex; struct ndis_80211_fixed_ies { uint8_t nfi_tstamp[8]; uint16_t nfi_beaconint; uint16_t nfi_caps; }; struct ndis_80211_variable_ies { uint8_t nvi_elemid; uint8_t nvi_len; uint8_t nvi_data[1]; }; typedef uint32_t ndis_80211_fragthresh; typedef uint32_t ndis_80211_rtsthresh; typedef uint32_t ndis_80211_antenna; #define NDIS_80211_PRIVFILT_ACCEPTALL 0x00000000 #define NDIS_80211_PRIVFILT_8021XWEP 0x00000001 #define NDIS_80211_WEPSTAT_ENABLED 0x00000000 #define NDIS_80211_WEPSTAT_ENC1ENABLED NDIS_80211_WEPSTAT_ENABLED #define NDIS_80211_WEPSTAT_DISABLED 0x00000001 #define NDIS_80211_WEPSTAT_ENCDISABLED NDIS_80211_WEPSTAT_DISABLED #define NDIS_80211_WEPSTAT_KEYABSENT 0x00000002 #define NDIS_80211_WEPSTAT_ENC1KEYABSENT NDIS_80211_WEPSTAT_KEYABSENT #define NDIS_80211_WEPSTAT_NOTSUPPORTED 0x00000003 #define NDIS_80211_WEPSTAT_ENCNOTSUPPORTED NDIS_80211_WEPSTAT_NOTSUPPORTED #define NDIS_80211_WEPSTAT_ENC2ENABLED 0x00000004 #define NDIS_80211_WEPSTAT_ENC2KEYABSENT 0x00000005 #define NDIS_80211_WEPSTAT_ENC3ENABLED 0x00000006 #define NDIS_80211_WEPSTAT_ENC3KEYABSENT 0x00000007 #define NDIS_80211_RELOADDEFAULT_WEP 0x00000000 #define NDIS_80211_STATUSTYPE_AUTH 0x00000000 struct ndis_80211_status_indication { uint32_t nsi_type; }; typedef struct ndis_80211_status_indication ndis_80211_status_indication; struct ndis_80211_auth_request { uint32_t nar_len; ndis_80211_macaddr nar_bssid; uint32_t nar_flags; }; typedef struct ndis_80211_auth_request ndis_80211_auth_request; struct ndis_80211_key { uint32_t nk_len; uint32_t nk_keyidx; uint32_t nk_keylen; ndis_80211_macaddr nk_bssid; uint64_t nk_keyrsc; uint8_t nk_keydata[256]; }; typedef struct ndis_80211_key ndis_80211_key; struct ndis_80211_remove_key { uint32_t nk_len; uint32_t nk_keyidx; ndis_80211_macaddr nk_bssid; }; typedef struct ndis_80211_remove_key ndis_80211_remove_key; #define NDIS_80211_AI_REQFI_CAPABILITIES 0x00000001 #define NDIS_80211_AI_REQFI_LISTENINTERVAL 0x00000002 #define NDIS_80211_AI_REQFI_CURRENTAPADDRESS 0x00000004 #define NDIS_80211_AI_RESFI_CAPABILITIES 0x00000001 #define NDIS_80211_AI_RESFI_STATUSCODE 0x00000002 #define NDIS_80211_AI_RESFI_ASSOCIATIONID 0x00000004 struct ndis_80211_ai_reqfi { uint16_t naq_caps; uint16_t naq_listentint; ndis_80211_macaddr naq_currentapaddr; }; typedef struct ndis_80211_ai_reqfi ndis_80211_ai_reqfi; struct ndis_80211_ai_resfi { uint16_t nas_caps; uint16_t nas_statuscode; uint16_t nas_associd; }; typedef struct ndis_80211_ai_resfi ndis_80211_ai_resfi; struct ndis_80211_assoc_info { uint32_t nai_len; uint16_t nai_avail_req_fixed_ies; ndis_80211_ai_reqfi nai_req_fixed_ies; uint32_t nai_req_ielen; uint32_t nai_offset_req_ies; uint16_t nai_avail_resp_fixed_ies; ndis_80211_ai_resfi nai_resp_fixed_iex; uint32_t nai_resp_ielen; uint32_t nai_offset_resp_ies; }; typedef struct ndis_80211_assoc_info ndis_80211_assoc_info; struct ndis_80211_auth_event { ndis_80211_status_indication nae_status; ndis_80211_auth_request nae_request[1]; }; typedef struct ndis_80211_auth_event ndis_80211_auth_event; struct ndis_80211_test { uint32_t nt_len; uint32_t nt_type; union { ndis_80211_auth_event nt_authevent; uint32_t nt_rssitrigger; } u; }; typedef struct ndis_80211_test ndis_80211_test; /* TCP OIDs. */ #define OID_TCP_TASK_OFFLOAD 0xFC010201 #define OID_TCP_TASK_IPSEC_ADD_SA 0xFC010202 #define OID_TCP_TASK_IPSEC_DELETE_SA 0xFC010203 #define OID_TCP_SAN_SUPPORT 0xFC010204 #define NDIS_TASK_OFFLOAD_VERSION 1 #define NDIS_TASK_TCPIP_CSUM 0x00000000 #define NDIS_TASK_IPSEC 0x00000001 #define NDIS_TASK_TCP_LARGESEND 0x00000002 #define NDIS_ENCAP_UNSPEC 0x00000000 #define NDIS_ENCAP_NULL 0x00000001 #define NDIS_ENCAP_IEEE802_3 0x00000002 #define NDIS_ENCAP_IEEE802_5 0x00000003 #define NDIS_ENCAP_SNAP_ROUTED 0x00000004 #define NDIS_ENCAP_SNAP_BRIDGED 0x00000005 #define NDIS_ENCAPFLAG_FIXEDHDRLEN 0x00000001 struct ndis_encap_fmt { uint32_t nef_encap; uint32_t nef_flags; uint32_t nef_encaphdrlen; }; typedef struct ndis_encap_fmt ndis_encap_fmt; struct ndis_task_offload_hdr { uint32_t ntoh_vers; uint32_t ntoh_len; uint32_t ntoh_rsvd; uint32_t ntoh_offset_firsttask; ndis_encap_fmt ntoh_encapfmt; }; typedef struct ndis_task_offload_hdr ndis_task_offload_hdr; struct ndis_task_offload { uint32_t nto_vers; uint32_t nto_len; uint32_t nto_task; uint32_t nto_offset_nexttask; uint32_t nto_taskbuflen; uint8_t nto_taskbuf[1]; }; typedef struct ndis_task_offload ndis_task_offload; #define NDIS_TCPSUM_FLAGS_IP_OPTS 0x00000001 #define NDIS_TCPSUM_FLAGS_TCP_OPTS 0x00000002 #define NDIS_TCPSUM_FLAGS_TCP_CSUM 0x00000004 #define NDIS_TCPSUM_FLAGS_UDP_CSUM 0x00000008 #define NDIS_TCPSUM_FLAGS_IP_CSUM 0x00000010 struct ndis_task_tcpip_csum { uint32_t nttc_v4tx; uint32_t nttc_v4rx; uint32_t nttc_v6tx; uint32_t nttc_v6rx; }; typedef struct ndis_task_tcpip_csum ndis_task_tcpip_csum; struct ndis_task_tcp_largesend { uint32_t nttl_vers; uint32_t nttl_maxofflen; uint32_t nttl_minsegcnt; uint8_t nttl_tcpopt; uint8_t nttl_ipopt; }; typedef struct ndis_task_tcp_largesend ndis_task_tcp_largesend; #define NDIS_IPSEC_AH_MD5 0x00000001 #define NDIS_IPSEC_AH_SHA1 0x00000002 #define NDIS_IPSEC_AH_TRANSPORT 0x00000004 #define NDIS_IPSEC_AH_TUNNEL 0x00000008 #define NDIS_IPSEC_AH_SEND 0x00000010 #define NDIS_IPSEC_AH_RECEIVE 0x00000020 #define NDIS_IPSEC_ESP_DES 0x00000001 #define NDIS_IPSEC_ESP_RSVD 0x00000002 #define NDIS_IPSEC_ESP_3DES 0x00000004 #define NDIS_IPSEC_ESP_NULL 0x00000008 #define NDIS_IPSEC_ESP_TRANSPORT 0x00000010 #define NDIS_IPSEC_ESP_TUNNEL 0x00000020 #define NDIS_IPSEC_ESP_SEND 0x00000040 #define NDIS_IPSEC_ESP_RECEIVE 0x00000080 struct ndis_task_ipsec { uint32_t nti_ah_esp_combined; uint32_t nti_ah_transport_tunnel_combined; uint32_t nti_v4_options; uint32_t nti_rsvd; uint32_t nti_v4ah; uint32_t nti_v4esp; }; typedef struct ndis_task_ipsec ndis_task_ipsec; /* * Attribures of NDIS drivers. Not all drivers support * all attributes. */ #define NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT 0x00000002 #define NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS 0x00000004 #define NDIS_ATTRIBUTE_BUS_MASTER 0x00000008 #define NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER 0x00000010 #define NDIS_ATTRIBUTE_DESERIALIZE 0x00000020 #define NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND 0x00000040 #define NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK 0x00000080 #define NDIS_ATTRIBUTE_NOT_CO_NDIS 0x00000100 #define NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS 0x00000200 enum ndis_media_state { nmc_connected, nmc_disconnected }; typedef enum ndis_media_state ndis_media_state; /* Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). */ #define NDIS_PACKET_TYPE_DIRECTED 0x00000001 #define NDIS_PACKET_TYPE_MULTICAST 0x00000002 #define NDIS_PACKET_TYPE_ALL_MULTICAST 0x00000004 #define NDIS_PACKET_TYPE_BROADCAST 0x00000008 #define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x00000010 #define NDIS_PACKET_TYPE_PROMISCUOUS 0x00000020 #define NDIS_PACKET_TYPE_SMT 0x00000040 #define NDIS_PACKET_TYPE_ALL_LOCAL 0x00000080 #define NDIS_PACKET_TYPE_GROUP 0x00001000 #define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x00002000 #define NDIS_PACKET_TYPE_FUNCTIONAL 0x00004000 #define NDIS_PACKET_TYPE_MAC_FRAME 0x00008000 /* Ndis MAC option bits (OID_GEN_MAC_OPTIONS). */ #define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001 #define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002 #define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004 #define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008 #define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010 #define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020 #define NDIS_MAC_OPTION_8021P_PRIORITY 0x00000040 #define NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE 0x00000080 #define NDIS_MAC_OPTION_RECEIVE_AT_DPC 0x00000100 #define NDIS_MAC_OPTION_8021Q_VLAN 0x00000200 #define NDIS_MAC_OPTION_RESERVED 0x80000000 #define NDIS_DMA_24BITS 0x00 #define NDIS_DMA_32BITS 0x01 #define NDIS_DMA_64BITS 0x02 struct ndis_physaddr { uint64_t np_quad; #ifdef notdef uint32_t np_low; uint32_t np_high; #endif }; typedef struct ndis_physaddr ndis_physaddr; struct ndis_ansi_string { uint16_t nas_len; uint16_t nas_maxlen; char *nas_buf; }; typedef struct ndis_ansi_string ndis_ansi_string; /* * nus_buf is really a wchar_t *, but it's inconvenient to include * all the necessary header goop needed to define it, and it's a * pointer anyway, so for now, just make it a uint16_t *. */ struct ndis_unicode_string { uint16_t nus_len; uint16_t nus_maxlen; uint16_t *nus_buf; }; typedef struct ndis_unicode_string ndis_unicode_string; enum ndis_parm_type { ndis_parm_int, ndis_parm_hexint, ndis_parm_string, ndis_parm_multistring, ndis_parm_binary }; typedef enum ndis_parm_type ndis_parm_type; struct ndis_binary_data { uint16_t nbd_len; void *nbd_buf; }; typedef struct ndis_binary_data ndis_binary_data; struct ndis_config_parm { ndis_parm_type ncp_type; union { uint32_t ncp_intdata; ndis_unicode_string ncp_stringdata; ndis_binary_data ncp_binarydata; } ncp_parmdata; }; typedef struct ndis_config_parm ndis_config_parm; #ifdef notdef struct ndis_list_entry { struct ndis_list_entry *nle_flink; struct ndis_list_entry *nle_blink; }; typedef struct ndis_list_entry ndis_list_entry; #endif struct ndis_bind_paths { uint32_t nbp_number; ndis_unicode_string nbp_paths[1]; }; typedef struct ndis_bind_paths ndis_bind_paths; #ifdef notdef struct dispatch_header { uint8_t dh_type; uint8_t dh_abs; uint8_t dh_size; uint8_t dh_inserted; uint32_t dh_sigstate; list_entry dh_waitlisthead; }; #endif #define dispatch_header nt_dispatch_header struct ndis_ktimer { struct dispatch_header nk_header; uint64_t nk_duetime; list_entry nk_timerlistentry; void *nk_dpc; uint32_t nk_period; }; struct ndis_kevent { struct dispatch_header nk_header; }; struct ndis_event { struct nt_kevent ne_event; }; typedef struct ndis_event ndis_event; /* Kernel defered procedure call (i.e. timer callback) */ struct ndis_kdpc; typedef void (*ndis_kdpc_func)(struct ndis_kdpc *, void *, void *, void *); struct ndis_kdpc { uint16_t nk_type; uint8_t nk_num; uint8_t nk_importance; list_entry nk_dpclistentry; ndis_kdpc_func nk_deferedfunc; void *nk_deferredctx; void *nk_sysarg1; void *nk_sysarg2; uint32_t *nk_lock; }; struct ndis_timer { struct ktimer nt_ktimer; struct kdpc nt_kdpc; }; typedef struct ndis_timer ndis_timer; typedef void (*ndis_timer_function)(void *, void *, void *, void *); struct ndis_miniport_timer { struct ktimer nmt_ktimer; struct kdpc nmt_kdpc; ndis_timer_function nmt_timerfunc; void *nmt_timerctx; ndis_miniport_block *nmt_block; struct ndis_miniport_timer *nmt_nexttimer; }; typedef struct ndis_miniport_timer ndis_miniport_timer; struct ndis_spin_lock { ndis_kspin_lock nsl_spinlock; ndis_kirql nsl_kirql; }; typedef struct ndis_spin_lock ndis_spin_lock; struct ndis_request { uint8_t nr_macreserved[4*sizeof(void *)]; uint32_t nr_requesttype; union _ndis_data { struct _ndis_query_information { ndis_oid nr_oid; void *nr_infobuf; uint32_t nr_infobuflen; uint32_t nr_byteswritten; uint32_t nr_bytesneeded; } ndis_query_information; struct _ndis_set_information { ndis_oid nr_oid; void *nr_infobuf; uint32_t nr_infobuflen; uint32_t nr_byteswritten; uint32_t nr_bytesneeded; } ndis_set_information; } ndis_data; /* NDIS 5.0 extentions */ uint8_t nr_ndis_rsvd[9 * sizeof(void *)]; union { uint8_t nr_callmgr_rsvd[2 * sizeof(void *)]; uint8_t nr_protocol_rsvd[2 * sizeof(void *)]; } u; uint8_t nr_miniport_rsvd[2 * sizeof(void *)]; }; typedef struct ndis_request ndis_request; /* * Filler, not used. */ struct ndis_miniport_interrupt { void *ni_introbj; ndis_kspin_lock ni_dpccountlock; void *ni_rsvd; void *ni_isrfunc; void *ni_dpcfunc; struct ndis_kdpc ni_dpc; ndis_miniport_block *ni_block; uint8_t ni_dpccnt; uint8_t ni_filler1; struct ndis_kevent ni_dpcsdoneevent; uint8_t ni_shared; uint8_t ni_isrreq; }; typedef struct ndis_miniport_interrupt ndis_miniport_interrupt; enum ndis_interrupt_mode { nim_level, nim_latched }; typedef enum ndis_interrupt_mode ndis_interrupt_mode; struct ndis_work_item; typedef void (*ndis_proc)(struct ndis_work_item *, void *); struct ndis_work_item { void *nwi_ctx; ndis_proc nwi_func; uint8_t nwi_wraprsvd[sizeof(void *) * 8]; }; typedef struct ndis_work_item ndis_work_item; struct ndis_buffer { struct ndis_buffer *nb_next; uint16_t nb_size; uint16_t nb_flags; void *nb_process; void *nb_mappedsystemva; void *nb_startva; uint32_t nb_bytecount; uint32_t nb_byteoffset; }; typedef struct ndis_buffer ndis_buffer; struct ndis_sc_element { ndis_physaddr nse_addr; uint32_t nse_len; uint32_t *nse_rsvd; }; typedef struct ndis_sc_element ndis_sc_element; #define NDIS_MAXSEG 32 #define NDIS_BUS_SPACE_SHARED_MAXADDR 0x3E7FFFFF struct ndis_sc_list { uint32_t nsl_frags; uint32_t *nsl_rsvd; ndis_sc_element nsl_elements[NDIS_MAXSEG]; }; typedef struct ndis_sc_list ndis_sc_list; struct ndis_tcpip_csum { union { uint32_t ntc_txflags; uint32_t ntc_rxflags; uint32_t ntc_val; } u; }; typedef struct ndis_tcpip_csum ndis_tcpip_csum; #define NDIS_TXCSUM_DO_IPV4 0x00000001 #define NDIS_TXCSUM_DO_IPV6 0x00000002 #define NDIS_TXCSUM_DO_TCP 0x00000004 #define NDIS_TXCSUM_DO_UDP 0x00000008 #define NDIS_TXCSUM_DO_IP 0x00000010 #define NDIS_RXCSUM_TCP_FAILED 0x00000001 #define NDIS_RXCSUM_UDP_FAILED 0x00000002 #define NDIS_RXCSUM_IP_FAILED 0x00000004 #define NDIS_RXCSUM_TCP_PASSED 0x00000008 #define NDIS_RXCSUM_UDP_PASSED 0x00000010 #define NDIS_RXCSUM_IP_PASSED 0x00000020 #define NDIS_RXCSUM_LOOPBACK 0x00000040 struct ndis_vlan { union { struct { uint32_t nvt_userprio:3; uint32_t nvt_canformatid:1; uint32_t nvt_vlanid:12; uint32_t nvt_rsvd:16; } nv_taghdr; } u; }; typedef struct ndis_vlan ndis_vlan; enum ndis_perpkt_info { ndis_tcpipcsum_info, ndis_ipsec_info, ndis_largesend_info, ndis_classhandle_info, ndis_rsvd, ndis_sclist_info, ndis_ieee8021q_info, ndis_originalpkt_info, ndis_packetcancelid, ndis_maxpkt_info }; typedef enum ndis_perpkt_info ndis_perpkt_info; struct ndis_packet_extension { void *npe_info[ndis_maxpkt_info]; }; typedef struct ndis_packet_extension ndis_packet_extension; struct ndis_packet_private { uint32_t npp_physcnt; uint32_t npp_totlen; ndis_buffer *npp_head; ndis_buffer *npp_tail; void *npp_pool; uint32_t npp_count; uint32_t npp_flags; uint8_t npp_validcounts; uint8_t npp_ndispktflags; uint16_t npp_packetooboffset; }; #define NDIS_FLAGS_PROTOCOL_ID_MASK 0x0000000F #define NDIS_FLAGS_MULTICAST_PACKET 0x00000010 #define NDIS_FLAGS_RESERVED2 0x00000020 #define NDIS_FLAGS_RESERVED3 0x00000040 #define NDIS_FLAGS_DONT_LOOPBACK 0x00000080 #define NDIS_FLAGS_IS_LOOPBACK_PACKET 0x00000100 #define NDIS_FLAGS_LOOPBACK_ONLY 0x00000200 #define NDIS_FLAGS_RESERVED4 0x00000400 #define NDIS_FLAGS_DOUBLE_BUFFERED 0x00000800 #define NDIS_FLAGS_SENT_AT_DPC 0x00001000 #define NDIS_FLAGS_USES_SG_BUFFER_LIST 0x00002000 #define NDIS_PACKET_WRAPPER_RESERVED 0x3F #define NDIS_PACKET_CONTAINS_MEDIA_SPECIFIC_INFO 0x40 #define NDIS_PACKET_ALLOCATED_BY_NDIS 0x80 #define NDIS_PROTOCOL_ID_DEFAULT 0x00 #define NDIS_PROTOCOL_ID_TCP_IP 0x02 #define NDIS_PROTOCOL_ID_IPX 0x06 #define NDIS_PROTOCOL_ID_NBF 0x07 #define NDIS_PROTOCOL_ID_MAX 0x0F #define NDIS_PROTOCOL_ID_MASK 0x0F typedef struct ndis_packet_private ndis_packet_private; enum ndis_classid { ndis_class_802_3prio, ndis_class_wirelesswan_mbx, ndis_class_irda_packetinfo, ndis_class_atm_aainfo }; typedef enum ndis_classid ndis_classid; struct ndis_mediaspecific_info { uint32_t nmi_nextentoffset; ndis_classid nmi_classid; uint32_t nmi_size; uint8_t nmi_classinfo[1]; }; typedef struct ndis_mediaspecific_info ndis_mediaspecific_info; struct ndis_packet_oob { union { uint64_t npo_timetotx; uint64_t npo_timetxed; } u; uint64_t npo_timerxed; uint32_t npo_hdrlen; uint32_t npo_mediaspecific_len; void *npo_mediaspecific; ndis_status npo_status; }; typedef struct ndis_packet_oob ndis_packet_oob; struct ndis_packet { ndis_packet_private np_private; union { /* For connectionless miniports. */ struct { uint8_t np_miniport_rsvd[2 * sizeof(void *)]; uint8_t np_wrapper_rsvd[2 * sizeof(void *)]; } np_clrsvd; /* For de-serialized miniports */ struct { uint8_t np_miniport_rsvdex[3 * sizeof(void *)]; uint8_t np_wrapper_rsvdex[sizeof(void *)]; } np_dsrsvd; struct { uint8_t np_mac_rsvd[4 * sizeof(void *)]; } np_macrsvd; } u; uint32_t *np_rsvd[2]; /* * This next part is probably wrong, but we need some place * to put the out of band data structure... */ ndis_packet_oob np_oob; ndis_packet_extension np_ext; ndis_sc_list np_sclist; /* BSD-specific stuff which should be invisible to drivers. */ uint32_t np_refcnt; void *np_softc; void *np_m0; int np_txidx; }; typedef struct ndis_packet ndis_packet; /* mbuf ext type for NDIS */ #define EXT_NDIS 0x999 /* mtx type for NDIS */ #define MTX_NDIS_LOCK "NDIS lock" struct ndis_filterdbs { union { void *nf_ethdb; void *nf_nulldb; } u; void *nf_trdb; void *nf_fddidb; void *nf_arcdb; }; typedef struct ndis_filterdbs ndis_filterdbs; enum ndis_medium { NdisMedium802_3, NdisMedium802_5, NdisMediumFddi, NdisMediumWan, NdisMediumLocalTalk, NdisMediumDix, /* defined for convenience, not a real medium */ NdisMediumArcnetRaw, NdisMediumArcnet878_2, NdisMediumAtm, NdisMediumWirelessWan, NdisMediumIrda, NdisMediumBpc, NdisMediumCoWan, NdisMedium1394, NdisMediumMax }; typedef enum ndis_medium ndis_medium; /* enum interface_type { InterfaceTypeUndefined = -1, Internal, Isa, Eisa, MicroChannel, TurboChannel, PCIBus, VMEBus, NuBus, PCMCIABus, CBus, MPIBus, MPSABus, ProcessorInternal, InternalPowerBus, PNPISABus, PNPBus, MaximumInterfaceType }; */ enum ndis_interface_type { NdisInterfaceInternal = Internal, NdisInterfaceIsa = Isa, NdisInterfaceEisa = Eisa, NdisInterfaceMca = MicroChannel, NdisInterfaceTurboChannel = TurboChannel, NdisInterfacePci = PCIBus, NdisInterfacePcMcia = PCMCIABus }; typedef enum ndis_interface_type ndis_interface_type; struct ndis_paddr_unit { ndis_physaddr npu_physaddr; uint32_t npu_len; }; typedef struct ndis_paddr_unit ndis_paddr_unit; struct ndis_map_arg { ndis_paddr_unit *nma_fraglist; int nma_cnt; int nma_max; }; /* * Miniport characteristics were originally defined in the NDIS 3.0 * spec and then extended twice, in NDIS 4.0 and 5.0. */ struct ndis_miniport_characteristics { /* NDIS 3.0 */ uint8_t nmc_version_major; uint8_t nmc_version_minor; uint16_t nmc_pad; uint32_t nmc_rsvd; void * nmc_checkhang_func; void * nmc_disable_interrupts_func; void * nmc_enable_interrupts_func; void * nmc_halt_func; void * nmc_interrupt_func; void * nmc_init_func; void * nmc_isr_func; void * nmc_queryinfo_func; void * nmc_reconfig_func; void * nmc_reset_func; void * nmc_sendsingle_func; void * nmc_setinfo_func; void * nmc_transferdata_func; /* NDIS 4.0 extentions */ void * nmc_return_packet_func; void * nmc_sendmulti_func; void * nmc_allocate_complete_func; /* NDIS 5.0 extensions */ void * nmc_cocreatevc_func; void * nmc_codeletevc_func; void * nmc_coactivatevc_func; void * nmc_codeactivatevc_func; void * nmc_comultisend_func; void * nmc_corequest_func; /* NDIS 5.1 extentions */ void * nmc_canceltxpkts_handler; void * nmc_pnpevent_handler; void * nmc_shutdown_handler; void * nmc_rsvd0; void * nmc_rsvd1; void * nmc_rsvd2; void * nmc_rsvd3; }; typedef struct ndis_miniport_characteristics ndis_miniport_characteristics; struct ndis_driver_object { char *ndo_ifname; void *ndo_softc; ndis_miniport_characteristics ndo_chars; }; typedef struct ndis_driver_object ndis_driver_object; struct ndis_reference { ndis_kspin_lock nr_spinlock; uint16_t nr_refcnt; uint8_t nr_closing; }; typedef struct ndis_reference ndis_reference; struct ndis_timer_entry { struct callout nte_ch; ndis_miniport_timer *nte_timer; TAILQ_ENTRY(ndis_timer_entry) link; }; TAILQ_HEAD(nte_head, ndis_timer_entry); struct ndis_fh { void *nf_vp; void *nf_map; uint32_t nf_maplen; }; typedef struct ndis_fh ndis_fh; /* * The miniport block is basically the internal NDIS handle. We need * to define this because, unfortunately, it is not entirely opaque * to NDIS drivers. For one thing, it contains the function pointer * to the NDIS packet receive handler, which is invoked out of the * NDIS block via a macro rather than a function pointer. (The * NdisMIndicateReceivePacket() routine is a macro rather than * a function.) For another, the driver maintains a pointer to the * miniport block and passes it as a handle to various NDIS functions. * (The driver never really knows this because it's hidden behind * an ndis_handle though.) * * The miniport block has two parts: the first part contains fields * that must never change, since they are referenced by driver * binaries through macros. The second part is ignored by the driver, * but contains various things used internaly by NDIS.SYS. In our * case, we define the first 'immutable' part exactly as it appears * in Windows, but don't bother duplicating the Windows definitions * for the second part. Instead, we replace them with a few BSD-specific * things. */ struct ndis_miniport_block { /* * Windows-specific portion -- DO NOT MODIFY OR NDIS * DRIVERS WILL NOT WORK. */ void *nmb_signature; /* magic number */ ndis_miniport_block *nmb_nextminiport; ndis_mdriver_block *nmb_driverhandle; ndis_handle nmb_miniportadapterctx; ndis_unicode_string nmb_name; ndis_bind_paths *nmb_bindpaths; ndis_handle nmb_openqueue; ndis_reference nmb_ref; ndis_handle nmb_devicectx; uint8_t nmb_padding; uint8_t nmb_lockacquired; uint8_t nmb_pmodeopens; uint8_t nmb_assignedcpu; ndis_kspin_lock nmb_lock; ndis_request *nmb_mediarequest; ndis_miniport_interrupt *nmb_interrupt; uint32_t nmb_flags; uint32_t nmb_pnpflags; list_entry nmb_packetlist; ndis_packet *nmb_firstpendingtxpacket; ndis_packet *nmb_returnpacketqueue; uint32_t nmb_requestbuffer; void *nmb_setmcastbuf; ndis_miniport_block *nmb_primaryminiport; void *nmb_wrapperctx; void *nmb_busdatactx; uint32_t nmb_pnpcaps; cm_resource_list *nmb_resources; ndis_timer nmb_wkupdpctimer; ndis_unicode_string nmb_basename; ndis_unicode_string nmb_symlinkname; uint32_t nmb_checkforhangsecs; uint16_t nmb_cfhticks; uint16_t nmb_cfhcurrticks; ndis_status nmb_resetstatus; ndis_handle nmb_resetopen; ndis_filterdbs nmb_filterdbs; void *nmb_pktind_func; void *nmb_senddone_func; void *nmb_sendrsrc_func; void *nmb_resetdone_func; ndis_medium nmb_medium; uint32_t nmb_busnum; uint32_t nmb_bustye; uint32_t nmb_adaptertype; void *nmb_deviceobj; void *nmb_physdeviceobj; void *nmb_nextdeviceobj; void *nmb_mapreg; void *nmb_callmgraflist; void *nmb_miniportthread; void *nmb_setinfobuf; uint16_t nmb_setinfobuflen; uint16_t nmb_maxsendpkts; ndis_status nmb_fakestatus; void *nmb_lockhandler; ndis_unicode_string *nmb_adapterinstancename; void *nmb_timerqueue; uint32_t nmb_mactoptions; ndis_request *nmb_pendingreq; uint32_t nmb_maxlongaddrs; uint32_t nmb_maxshortaddrs; uint32_t nmb_currlookahead; uint32_t nmb_maxlookahead; void *nmb_interrupt_func; void *nmb_disableintr_func; void *nmb_enableintr_func; void *nmb_sendpkts_func; void *nmb_deferredsend_func; void *nmb_ethrxindicate_func; void *nmb_txrxindicate_func; void *nmb_fddirxindicate_func; void *nmb_ethrxdone_func; void *nmb_txrxdone_func; void *nmb_fddirxcond_func; void *nmb_status_func; void *nmb_statusdone_func; void *nmb_tdcond_func; void *nmb_querydone_func; void *nmb_setdone_func; void *nmb_wantxdone_func; void *nmb_wanrx_func; void *nmb_wanrxdone_func; /* * End of windows-specific portion of miniport block. Everything * below is BSD-specific. */ struct ifnet *nmb_ifp; uint8_t nmb_dummybuf[128]; device_object nmb_devobj; ndis_config_parm nmb_replyparm; int nmb_pciidx; device_t nmb_dev; ndis_resource_list *nmb_rlist; ndis_status nmb_getstat; ndis_status nmb_setstat; struct nte_head nmb_timerlist; vm_offset_t nmb_img; TAILQ_ENTRY(ndis_miniport_block) link; }; TAILQ_HEAD(nd_head, ndis_miniport_block); typedef ndis_status (*ndis_init_handler)(ndis_status *, uint32_t *, ndis_medium *, uint32_t, ndis_handle, ndis_handle); typedef ndis_status (*ndis_queryinfo_handler)(ndis_handle, ndis_oid, void *, uint32_t, uint32_t *, uint32_t *); typedef ndis_status (*ndis_setinfo_handler)(ndis_handle, ndis_oid, void *, uint32_t, uint32_t *, uint32_t *); typedef ndis_status (*ndis_sendsingle_handler)(ndis_handle, ndis_packet *, uint32_t); typedef ndis_status (*ndis_sendmulti_handler)(ndis_handle, ndis_packet **, uint32_t); typedef void (*ndis_isr_handler)(uint8_t *, uint8_t *, ndis_handle); typedef void (*ndis_interrupt_handler)(ndis_handle); typedef int (*ndis_reset_handler)(uint8_t *, ndis_handle); typedef void (*ndis_halt_handler)(ndis_handle); typedef void (*ndis_return_handler)(ndis_handle, ndis_packet *); typedef void (*ndis_enable_interrupts_handler)(ndis_handle); typedef void (*ndis_disable_interrupts_handler)(ndis_handle); typedef void (*ndis_shutdown_handler)(void *); typedef void (*ndis_allocdone_handler)(ndis_handle, void *, ndis_physaddr *, uint32_t, void *); typedef uint8_t (*ndis_checkforhang_handler)(ndis_handle); typedef ndis_status (*driver_entry)(void *, ndis_unicode_string *); extern image_patch_table ndis_functbl[]; #define NDIS_TASKQUEUE 1 #define NDIS_SWI 2 #define NDIS_PSTATE_RUNNING 1 #define NDIS_PSTATE_SLEEPING 2 __BEGIN_DECLS extern int ndis_libinit(void); extern int ndis_libfini(void); extern int ndis_ascii_to_unicode(char *, uint16_t **); extern int ndis_unicode_to_ascii(uint16_t *, int, char **); extern int ndis_load_driver(vm_offset_t, void *); extern int ndis_unload_driver(void *); extern int ndis_mtop(struct mbuf *, ndis_packet **); extern int ndis_ptom(struct mbuf **, ndis_packet *); extern int ndis_get_info(void *, ndis_oid, void *, int *); extern int ndis_set_info(void *, ndis_oid, void *, int *); extern int ndis_get_supported_oids(void *, ndis_oid **, int *); extern int ndis_send_packets(void *, ndis_packet **, int); extern int ndis_send_packet(void *, ndis_packet *); extern int ndis_convert_res(void *); extern int ndis_alloc_amem(void *); +extern void ndis_free_amem(void *); extern void ndis_free_packet(ndis_packet *); extern void ndis_free_bufs(ndis_buffer *); extern int ndis_reset_nic(void *); extern int ndis_halt_nic(void *); extern int ndis_shutdown_nic(void *); extern int ndis_init_nic(void *); extern int ndis_isr(void *, int *, int *); extern int ndis_intrhand(void *); extern void ndis_return_packet(void *, void *); extern void ndis_enable_intr(void *); extern void ndis_disable_intr(void *); extern int ndis_init_dma(void *); extern int ndis_destroy_dma(void *); extern int ndis_create_sysctls(void *); extern int ndis_add_sysctl(void *, char *, char *, char *, int); extern int ndis_flush_sysctls(void *); extern int ndis_sched(void (*)(void *), void *, int); extern int ndis_unsched(void (*)(void *), void *, int); extern int ndis_thsuspend(struct proc *, int); extern void ndis_thresume(struct proc *); +extern int ndis_strcasecmp(const char *, const char *); __END_DECLS #endif /* _NDIS_VAR_H_ */ Index: head/sys/compat/ndis/subr_ndis.c =================================================================== --- head/sys/compat/ndis/subr_ndis.c (revision 131952) +++ head/sys/compat/ndis/subr_ndis.c (revision 131953) @@ -1,3041 +1,3045 @@ /* * Copyright (c) 2003 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * This file implements a translation layer between the BSD networking * infrasturcture and Windows(R) NDIS network driver modules. A Windows * NDIS driver calls into several functions in the NDIS.SYS Windows * kernel module and exports a table of functions designed to be called * by the NDIS subsystem. Using the PE loader, we can patch our own * versions of the NDIS routines into a given Windows driver module and * convince the driver that it is in fact running on Windows. * * We provide a table of all our implemented NDIS routines which is patched * into the driver object code. All our exported routines must use the * _stdcall calling convention, since that's what the Windows object code * expects. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define FUNC void(*)(void) static char ndis_filepath[MAXPATHLEN]; extern struct nd_head ndis_devhead; SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath, MAXPATHLEN, "Path used by NdisOpenFile() to search for files"); __stdcall static void ndis_initwrap(ndis_handle *, device_object *, void *, void *); __stdcall static ndis_status ndis_register_miniport(ndis_handle, ndis_miniport_characteristics *, int); __stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t); __stdcall static ndis_status ndis_malloc(void **, uint32_t, uint32_t, ndis_physaddr); __stdcall static void ndis_free(void *, uint32_t, uint32_t); __stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle, uint32_t, uint32_t, ndis_interface_type); __stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle); __stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle, uint32_t, ndis_unicode_string *, ndis_handle *); __stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle, ndis_unicode_string *, ndis_handle *); static ndis_status ndis_encode_parm(ndis_miniport_block *, struct sysctl_oid *, ndis_parm_type, ndis_config_parm **); static ndis_status ndis_decode_parm(ndis_miniport_block *, ndis_config_parm *, char *); -static int my_strcasecmp(const char *, const char *); __stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **, ndis_handle, ndis_unicode_string *, ndis_parm_type); __stdcall static void ndis_write_cfg(ndis_status *, ndis_handle, ndis_unicode_string *, ndis_config_parm *); __stdcall static void ndis_close_cfg(ndis_handle); __stdcall static void ndis_create_lock(ndis_spin_lock *); __stdcall static void ndis_destroy_lock(ndis_spin_lock *); __stdcall static void ndis_lock(ndis_spin_lock *); __stdcall static void ndis_unlock(ndis_spin_lock *); __stdcall static void ndis_lock_dpr(ndis_spin_lock *); __stdcall static void ndis_unlock_dpr(ndis_spin_lock *); __stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t, uint32_t, void *, uint32_t); __stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t, uint32_t, void *, uint32_t); static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...); static void ndis_map_cb(void *, bus_dma_segment_t *, int, int); __stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *); __stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t); __stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle, ndis_timer_function, void *); __stdcall static void ndis_init_timer(ndis_timer *, ndis_timer_function, void *); __stdcall static void ndis_set_timer(ndis_timer *, uint32_t); __stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t); __stdcall static void ndis_cancel_timer(ndis_timer *, uint8_t *); __stdcall static void ndis_query_resources(ndis_status *, ndis_handle, ndis_resource_list *, uint32_t *); __stdcall static ndis_status ndis_register_ioport(void **, ndis_handle, uint32_t, uint32_t); __stdcall static void ndis_deregister_ioport(ndis_handle, uint32_t, uint32_t, void *); __stdcall static void ndis_read_netaddr(ndis_status *, void **, uint32_t *, ndis_handle); __stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *); __stdcall static ndis_status ndis_alloc_mapreg(ndis_handle, uint32_t, uint8_t, uint32_t, uint32_t); __stdcall static void ndis_free_mapreg(ndis_handle); static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int); __stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t, uint8_t, void **, ndis_physaddr *); static void ndis_asyncmem_complete(void *); __stdcall static ndis_status ndis_alloc_sharedmem_async(ndis_handle, uint32_t, uint8_t, void *); __stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t, uint8_t, void *, ndis_physaddr); __stdcall static ndis_status ndis_map_iospace(void **, ndis_handle, ndis_physaddr, uint32_t); __stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t); __stdcall static uint32_t ndis_cachefill(void); __stdcall static uint32_t ndis_dma_align(ndis_handle); __stdcall static ndis_status ndis_init_sc_dma(ndis_handle, uint8_t, uint32_t); __stdcall static void ndis_alloc_packetpool(ndis_status *, ndis_handle *, uint32_t, uint32_t); __stdcall static void ndis_ex_alloc_packetpool(ndis_status *, ndis_handle *, uint32_t, uint32_t, uint32_t); __stdcall static uint32_t ndis_packetpool_use(ndis_handle); __stdcall static void ndis_free_packetpool(ndis_handle); __stdcall static void ndis_alloc_packet(ndis_status *, ndis_packet **, ndis_handle); __stdcall static void ndis_release_packet(ndis_packet *); __stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **); __stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **); __stdcall static void ndis_alloc_bufpool(ndis_status *, ndis_handle *, uint32_t); __stdcall static void ndis_free_bufpool(ndis_handle); __stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **, ndis_handle, void *, uint32_t); __stdcall static void ndis_release_buf(ndis_buffer *); __stdcall static uint32_t ndis_buflen(ndis_buffer *); __stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *); __stdcall static void ndis_query_buf_safe(ndis_buffer *, void **, uint32_t *, uint32_t); __stdcall static void *ndis_buf_vaddr(ndis_buffer *); __stdcall static void *ndis_buf_vaddr_safe(ndis_buffer *, uint32_t); __stdcall static void ndis_adjust_buflen(ndis_buffer *, int); __stdcall static uint32_t ndis_interlock_inc(uint32_t *); __stdcall static uint32_t ndis_interlock_dec(uint32_t *); __stdcall static void ndis_init_event(ndis_event *); __stdcall static void ndis_set_event(ndis_event *); __stdcall static void ndis_reset_event(ndis_event *); __stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t); __stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *, ndis_unicode_string *); __stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *, ndis_ansi_string *); __stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle, uint32_t, ndis_resource_list **); __stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *, ndis_handle, uint32_t, uint32_t, uint8_t, uint8_t, ndis_interrupt_mode); __stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *); __stdcall static void ndis_register_shutdown(ndis_handle, void *, ndis_shutdown_handler); __stdcall static void ndis_deregister_shutdown(ndis_handle); __stdcall static uint32_t ndis_numpages(ndis_buffer *); __stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *); __stdcall static void ndis_query_bufoffset(ndis_buffer *, uint32_t *, uint32_t *); __stdcall static void ndis_sleep(uint32_t); __stdcall static uint32_t ndis_read_pccard_amem(ndis_handle, uint32_t, void *, uint32_t); __stdcall static uint32_t ndis_write_pccard_amem(ndis_handle, uint32_t, void *, uint32_t); __stdcall static list_entry *ndis_insert_head(list_entry *, list_entry *, ndis_spin_lock *); __stdcall static list_entry *ndis_remove_head(list_entry *, ndis_spin_lock *); __stdcall static list_entry *ndis_insert_tail(list_entry *, list_entry *, ndis_spin_lock *); __stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *, void *, void *); __stdcall static void ndis_time(uint64_t *); __stdcall static void ndis_uptime(uint32_t *); __stdcall static void ndis_init_string(ndis_unicode_string *, char *); __stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *); __stdcall static void ndis_init_unicode_string(ndis_unicode_string *, uint16_t *); __stdcall static void ndis_free_string(ndis_unicode_string *); __stdcall static ndis_status ndis_remove_miniport(ndis_handle *); __stdcall static void ndis_termwrap(ndis_handle, void *); __stdcall static void ndis_get_devprop(ndis_handle, device_object **, device_object **, device_object **, cm_resource_list *, cm_resource_list *); __stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **, void **, uint32_t *, uint32_t *); __stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t); __stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *, ndis_unicode_string *, ndis_physaddr); __stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle); __stdcall static void ndis_unmap_file(ndis_handle); __stdcall static void ndis_close_file(ndis_handle); __stdcall static u_int8_t ndis_cpu_cnt(void); __stdcall static void ndis_ind_statusdone(ndis_handle); __stdcall static void ndis_ind_status(ndis_handle, ndis_status, void *, uint32_t); static void ndis_workfunc(void *); __stdcall static ndis_status ndis_sched_workitem(ndis_work_item *); __stdcall static void ndis_pkt_to_pkt(ndis_packet *, uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *); __stdcall static void ndis_pkt_to_pkt_safe(ndis_packet *, uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t); __stdcall static ndis_status ndis_register_dev(ndis_handle, ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **, void **, ndis_handle *); __stdcall static ndis_status ndis_deregister_dev(ndis_handle); __stdcall static ndis_status ndis_query_name(ndis_unicode_string *, ndis_handle); __stdcall static void ndis_register_unload(ndis_handle, void *); __stdcall static void dummy(void); /* * Some really old drivers do not properly check the return value * from NdisAllocatePacket() and NdisAllocateBuffer() and will * sometimes allocate few more buffers/packets that they originally * requested when they created the pool. To prevent this from being * a problem, we allocate a few extra buffers/packets beyond what * the driver asks for. This #define controls how many. */ #define NDIS_POOL_EXTRA 16 int ndis_libinit() { strcpy(ndis_filepath, "/compat/ndis"); return(0); } int ndis_libfini() { return(0); } /* * NDIS deals with strings in unicode format, so we have * do deal with them that way too. For now, we only handle * conversion between unicode and ASCII since that's all * that device drivers care about. */ int ndis_ascii_to_unicode(ascii, unicode) char *ascii; uint16_t **unicode; { uint16_t *ustr; int i; if (*unicode == NULL) *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK); if (*unicode == NULL) return(ENOMEM); ustr = *unicode; for (i = 0; i < strlen(ascii); i++) { *ustr = (uint16_t)ascii[i]; ustr++; } return(0); } int ndis_unicode_to_ascii(unicode, ulen, ascii) uint16_t *unicode; int ulen; char **ascii; { uint8_t *astr; int i; if (*ascii == NULL) *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO); if (*ascii == NULL) return(ENOMEM); astr = *ascii; for (i = 0; i < ulen / 2; i++) { *astr = (uint8_t)unicode[i]; astr++; } return(0); } __stdcall static void ndis_initwrap(wrapper, drv_obj, path, unused) ndis_handle *wrapper; device_object *drv_obj; void *path; void *unused; { ndis_miniport_block *block; block = drv_obj->do_rsvd; *wrapper = block; return; } __stdcall static void ndis_termwrap(handle, syspec) ndis_handle handle; void *syspec; { return; } __stdcall static ndis_status ndis_register_miniport(handle, characteristics, len) ndis_handle handle; ndis_miniport_characteristics *characteristics; int len; { ndis_miniport_block *block; struct ndis_softc *sc; block = (ndis_miniport_block *)handle; sc = (struct ndis_softc *)block->nmb_ifp; bcopy((char *)characteristics, (char *)&sc->ndis_chars, sizeof(ndis_miniport_characteristics)); if (sc->ndis_chars.nmc_version_major < 5 || sc->ndis_chars.nmc_version_minor < 1) { sc->ndis_chars.nmc_shutdown_handler = NULL; sc->ndis_chars.nmc_canceltxpkts_handler = NULL; sc->ndis_chars.nmc_pnpevent_handler = NULL; } return(NDIS_STATUS_SUCCESS); } __stdcall static ndis_status ndis_malloc_withtag(vaddr, len, tag) void **vaddr; uint32_t len; uint32_t tag; { void *mem; mem = malloc(len, M_DEVBUF, M_NOWAIT); if (mem == NULL) return(NDIS_STATUS_RESOURCES); *vaddr = mem; return(NDIS_STATUS_SUCCESS); } __stdcall static ndis_status ndis_malloc(vaddr, len, flags, highaddr) void **vaddr; uint32_t len; uint32_t flags; ndis_physaddr highaddr; { void *mem; mem = malloc(len, M_DEVBUF, M_NOWAIT); if (mem == NULL) return(NDIS_STATUS_RESOURCES); *vaddr = mem; return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_free(vaddr, len, flags) void *vaddr; uint32_t len; uint32_t flags; { if (len == 0) return; free(vaddr, M_DEVBUF); return; } __stdcall static ndis_status ndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs, flags, iftype) ndis_handle adapter_handle; ndis_handle adapter_ctx; uint32_t hangsecs; uint32_t flags; ndis_interface_type iftype; { ndis_miniport_block *block; /* * Save the adapter context, we need it for calling * the driver's internal functions. */ block = (ndis_miniport_block *)adapter_handle; block->nmb_miniportadapterctx = adapter_ctx; block->nmb_checkforhangsecs = hangsecs; block->nmb_flags = flags; return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_open_cfg(status, cfg, wrapctx) ndis_status *status; ndis_handle *cfg; ndis_handle wrapctx; { *cfg = wrapctx; *status = NDIS_STATUS_SUCCESS; return; } __stdcall static void ndis_open_cfgbyname(status, cfg, subkey, subhandle) ndis_status *status; ndis_handle cfg; ndis_unicode_string *subkey; ndis_handle *subhandle; { *subhandle = cfg; *status = NDIS_STATUS_SUCCESS; return; } __stdcall static void ndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle) ndis_status *status; ndis_handle cfg; uint32_t idx; ndis_unicode_string *subkey; ndis_handle *subhandle; { *status = NDIS_STATUS_FAILURE; return; } static ndis_status ndis_encode_parm(block, oid, type, parm) ndis_miniport_block *block; struct sysctl_oid *oid; ndis_parm_type type; ndis_config_parm **parm; { uint16_t *unicode; ndis_unicode_string *ustr; int base = 0; unicode = (uint16_t *)&block->nmb_dummybuf; switch(type) { case ndis_parm_string: ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode); (*parm)->ncp_type = ndis_parm_string; ustr = &(*parm)->ncp_parmdata.ncp_stringdata; ustr->nus_len = strlen((char *)oid->oid_arg1) * 2; ustr->nus_buf = unicode; break; case ndis_parm_int: if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) base = 16; else base = 10; (*parm)->ncp_type = ndis_parm_int; (*parm)->ncp_parmdata.ncp_intdata = strtol((char *)oid->oid_arg1, NULL, base); break; case ndis_parm_hexint: if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) base = 16; else base = 10; (*parm)->ncp_type = ndis_parm_hexint; (*parm)->ncp_parmdata.ncp_intdata = strtoul((char *)oid->oid_arg1, NULL, base); break; default: return(NDIS_STATUS_FAILURE); break; } return(NDIS_STATUS_SUCCESS); } -static int -my_strcasecmp(s1, s2) +int +ndis_strcasecmp(s1, s2) const char *s1; const char *s2; { char a, b; /* * In the kernel, toupper() is a macro. Have to be careful * not to use pointer arithmetic when passing it arguments. */ while(1) { a = *s1; b = *s2++; if (toupper(a) != toupper(b)) break; if (*s1++ == 0) return(0); } return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1)); } __stdcall static void ndis_read_cfg(status, parm, cfg, key, type) ndis_status *status; ndis_config_parm **parm; ndis_handle cfg; ndis_unicode_string *key; ndis_parm_type type; { char *keystr = NULL; uint16_t *unicode; ndis_miniport_block *block; struct ndis_softc *sc; struct sysctl_oid *oidp; struct sysctl_ctx_entry *e; block = (ndis_miniport_block *)cfg; sc = (struct ndis_softc *)block->nmb_ifp; if (key->nus_len == 0 || key->nus_buf == NULL) { *status = NDIS_STATUS_FAILURE; return; } ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); *parm = &block->nmb_replyparm; bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm)); unicode = (uint16_t *)&block->nmb_dummybuf; /* * See if registry key is already in a list of known keys * included with the driver. */ #if __FreeBSD_version < 502113 TAILQ_FOREACH(e, &sc->ndis_ctx, link) { #else TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { #endif oidp = e->entry; - if (my_strcasecmp(oidp->oid_name, keystr) == 0) { + if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) { if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) { free(keystr, M_DEVBUF); *status = NDIS_STATUS_FAILURE; return; } *status = ndis_encode_parm(block, oidp, type, parm); free(keystr, M_DEVBUF); return; } } /* * If the key didn't match, add it to the list of dynamically * created ones. Sometimes, drivers refer to registry keys * that aren't documented in their .INF files. These keys * are supposed to be created by some sort of utility or * control panel snap-in that comes with the driver software. * Sometimes it's useful to be able to manipulate these. * If the driver requests the key in the form of a string, * make its default value an empty string, otherwise default * it to "0". */ if (type == ndis_parm_int || type == ndis_parm_hexint) ndis_add_sysctl(sc, keystr, "(dynamic integer key)", "UNSET", CTLFLAG_RW); else ndis_add_sysctl(sc, keystr, "(dynamic string key)", "UNSET", CTLFLAG_RW); free(keystr, M_DEVBUF); *status = NDIS_STATUS_FAILURE; return; } static ndis_status ndis_decode_parm(block, parm, val) ndis_miniport_block *block; ndis_config_parm *parm; char *val; { ndis_unicode_string *ustr; char *astr = NULL; switch(parm->ncp_type) { case ndis_parm_string: ustr = &parm->ncp_parmdata.ncp_stringdata; ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &astr); bcopy(astr, val, 254); free(astr, M_DEVBUF); break; case ndis_parm_int: sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata); break; case ndis_parm_hexint: sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata); break; default: return(NDIS_STATUS_FAILURE); break; } return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_write_cfg(status, cfg, key, parm) ndis_status *status; ndis_handle cfg; ndis_unicode_string *key; ndis_config_parm *parm; { char *keystr = NULL; ndis_miniport_block *block; struct ndis_softc *sc; struct sysctl_oid *oidp; struct sysctl_ctx_entry *e; char val[256]; block = (ndis_miniport_block *)cfg; sc = (struct ndis_softc *)block->nmb_ifp; ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr); /* Decode the parameter into a string. */ bzero(val, sizeof(val)); *status = ndis_decode_parm(block, parm, val); if (*status != NDIS_STATUS_SUCCESS) { free(keystr, M_DEVBUF); return; } /* See if the key already exists. */ #if __FreeBSD_version < 502113 TAILQ_FOREACH(e, &sc->ndis_ctx, link) { #else TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) { #endif oidp = e->entry; - if (my_strcasecmp(oidp->oid_name, keystr) == 0) { + if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) { /* Found it, set the value. */ strcpy((char *)oidp->oid_arg1, val); free(keystr, M_DEVBUF); return; } } /* Not found, add a new key with the specified value. */ ndis_add_sysctl(sc, keystr, "(dynamically set key)", val, CTLFLAG_RW); free(keystr, M_DEVBUF); *status = NDIS_STATUS_SUCCESS; return; } __stdcall static void ndis_close_cfg(cfg) ndis_handle cfg; { return; } /* * Initialize a Windows spinlock. */ __stdcall static void ndis_create_lock(lock) ndis_spin_lock *lock; { lock->nsl_spinlock = 0; lock->nsl_kirql = 0; return; } /* * Destroy a Windows spinlock. This is a no-op for now. There are two reasons * for this. One is that it's sort of superfluous: we don't have to do anything * special to deallocate the spinlock. The other is that there are some buggy * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm * talking to you.) */ __stdcall static void ndis_destroy_lock(lock) ndis_spin_lock *lock; { #ifdef notdef lock->nsl_spinlock = 0; lock->nsl_kirql = 0; #endif return; } /* * Acquire a spinlock from IRQL <= DISPATCH_LEVEL. */ __stdcall static void ndis_lock(lock) ndis_spin_lock *lock; { lock->nsl_kirql = FASTCALL2(hal_lock, &lock->nsl_spinlock, DISPATCH_LEVEL); return; } /* * Release a spinlock from IRQL == DISPATCH_LEVEL. */ __stdcall static void ndis_unlock(lock) ndis_spin_lock *lock; { FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql); return; } /* * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL. */ __stdcall static void ndis_lock_dpr(lock) ndis_spin_lock *lock; { FASTCALL1(ntoskrnl_lock_dpc, &lock->nsl_spinlock); return; } /* * Release a spinlock without leaving IRQL == DISPATCH_LEVEL. */ __stdcall static void ndis_unlock_dpr(lock) ndis_spin_lock *lock; { FASTCALL1(ntoskrnl_unlock_dpc, &lock->nsl_spinlock); return; } __stdcall static uint32_t ndis_read_pci(adapter, slot, offset, buf, len) ndis_handle adapter; uint32_t slot; uint32_t offset; void *buf; uint32_t len; { ndis_miniport_block *block; int i; char *dest; block = (ndis_miniport_block *)adapter; dest = buf; if (block == NULL || block->nmb_dev == NULL) return(0); for (i = 0; i < len; i++) dest[i] = pci_read_config(block->nmb_dev, i + offset, 1); return(len); } __stdcall static uint32_t ndis_write_pci(adapter, slot, offset, buf, len) ndis_handle adapter; uint32_t slot; uint32_t offset; void *buf; uint32_t len; { ndis_miniport_block *block; int i; char *dest; block = (ndis_miniport_block *)adapter; dest = buf; if (block == NULL || block->nmb_dev == NULL) return(0); for (i = 0; i < len; i++) pci_write_config(block->nmb_dev, i + offset, dest[i], 1); return(len); } /* * The errorlog routine uses a variable argument list, so we * have to declare it this way. */ #define ERRMSGLEN 512 static void ndis_syslog(ndis_handle adapter, ndis_error_code code, uint32_t numerrors, ...) { ndis_miniport_block *block; va_list ap; int i, error; char *str = NULL, *ustr = NULL; uint16_t flags; char msgbuf[ERRMSGLEN]; + block = (ndis_miniport_block *)adapter; error = pe_get_message(block->nmb_img, code, &str, &i, &flags); if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) { ustr = msgbuf; ndis_unicode_to_ascii((uint16_t *)str, ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr); str = ustr; } device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code, str == NULL ? "unknown error" : str); device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors); va_start(ap, numerrors); for (i = 0; i < numerrors; i++) device_printf (block->nmb_dev, "argptr: %p\n", va_arg(ap, void *)); va_end(ap); return; } static void ndis_map_cb(arg, segs, nseg, error) void *arg; bus_dma_segment_t *segs; int nseg; int error; { struct ndis_map_arg *ctx; int i; if (error) return; ctx = arg; for (i = 0; i < nseg; i++) { ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr; ctx->nma_fraglist[i].npu_len = segs[i].ds_len; } ctx->nma_cnt = nseg; return; } __stdcall static void ndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize) ndis_handle adapter; ndis_buffer *buf; uint32_t mapreg; uint8_t writedev; ndis_paddr_unit *addrarray; uint32_t *arraysize; { ndis_miniport_block *block; struct ndis_softc *sc; struct ndis_map_arg nma; bus_dmamap_t map; int error; if (adapter == NULL) return; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)(block->nmb_ifp); if (mapreg > sc->ndis_mmapcnt) return; map = sc->ndis_mmaps[mapreg]; nma.nma_fraglist = addrarray; error = bus_dmamap_load(sc->ndis_mtag, map, MDL_VA(buf), buf->nb_bytecount, ndis_map_cb, (void *)&nma, BUS_DMA_NOWAIT); if (error) return; bus_dmamap_sync(sc->ndis_mtag, map, writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD); *arraysize = nma.nma_cnt; return; } __stdcall static void ndis_vtophys_unload(adapter, buf, mapreg) ndis_handle adapter; ndis_buffer *buf; uint32_t mapreg; { ndis_miniport_block *block; struct ndis_softc *sc; bus_dmamap_t map; if (adapter == NULL) return; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)(block->nmb_ifp); if (mapreg > sc->ndis_mmapcnt) return; map = sc->ndis_mmaps[mapreg]; bus_dmamap_sync(sc->ndis_mtag, map, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); bus_dmamap_unload(sc->ndis_mtag, map); return; } /* * This is an older pre-miniport timer init routine which doesn't * accept a miniport context handle. The function context (ctx) * is supposed to be a pointer to the adapter handle, which should * have been handed to us via NdisSetAttributesEx(). We use this * function context to track down the corresponding ndis_miniport_block * structure. It's vital that we track down the miniport block structure, * so if we can't do it, we panic. Note that we also play some games * here by treating ndis_timer and ndis_miniport_timer as the same * thing. */ __stdcall static void ndis_init_timer(timer, func, ctx) ndis_timer *timer; ndis_timer_function func; void *ctx; { ntoskrnl_init_timer(&timer->nt_ktimer); ntoskrnl_init_dpc(&timer->nt_kdpc, func, ctx); return; } __stdcall static void ndis_create_timer(timer, handle, func, ctx) ndis_miniport_timer *timer; ndis_handle handle; ndis_timer_function func; void *ctx; { /* Save the funcptr and context */ timer->nmt_timerfunc = func; timer->nmt_timerctx = ctx; timer->nmt_block = handle; ntoskrnl_init_timer(&timer->nmt_ktimer); ntoskrnl_init_dpc(&timer->nmt_kdpc, func, ctx); return; } /* * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(), * but the former is just a macro wrapper around the latter. */ __stdcall static void ndis_set_timer(timer, msecs) ndis_timer *timer; uint32_t msecs; { /* * KeSetTimer() wants the period in * hundred nanosecond intervals. */ ntoskrnl_set_timer(&timer->nt_ktimer, ((int64_t)msecs * -10000), &timer->nt_kdpc); return; } __stdcall static void ndis_set_periodic_timer(timer, msecs) ndis_miniport_timer *timer; uint32_t msecs; { ntoskrnl_set_timer_ex(&timer->nmt_ktimer, ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc); return; } /* * Technically, this is really NdisCancelTimer(), but we also * (ab)use it for NdisMCancelTimer(), since in our implementation * we don't need the extra info in the ndis_miniport_timer * structure. */ __stdcall static void ndis_cancel_timer(timer, cancelled) ndis_timer *timer; uint8_t *cancelled; { *cancelled = ntoskrnl_cancel_timer(&timer->nt_ktimer); return; } __stdcall static void ndis_query_resources(status, adapter, list, buflen) ndis_status *status; ndis_handle adapter; ndis_resource_list *list; uint32_t *buflen; { ndis_miniport_block *block; struct ndis_softc *sc; int rsclen; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)block->nmb_ifp; rsclen = sizeof(ndis_resource_list) + (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)); if (*buflen < rsclen) { *buflen = rsclen; *status = NDIS_STATUS_INVALID_LENGTH; return; } bcopy((char *)block->nmb_rlist, (char *)list, rsclen); *status = NDIS_STATUS_SUCCESS; return; } __stdcall static ndis_status ndis_register_ioport(offset, adapter, port, numports) void **offset; ndis_handle adapter; uint32_t port; uint32_t numports; { struct ndis_miniport_block *block; struct ndis_softc *sc; if (adapter == NULL) return(NDIS_STATUS_FAILURE); block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)(block->nmb_ifp); if (sc->ndis_res_io == NULL) return(NDIS_STATUS_FAILURE); /* Don't let the device map more ports than we have. */ if (rman_get_size(sc->ndis_res_io) < numports) return(NDIS_STATUS_INVALID_LENGTH); *offset = (void *)rman_get_start(sc->ndis_res_io); return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_deregister_ioport(adapter, port, numports, offset) ndis_handle adapter; uint32_t port; uint32_t numports; void *offset; { return; } __stdcall static void ndis_read_netaddr(status, addr, addrlen, adapter) ndis_status *status; void **addr; uint32_t *addrlen; ndis_handle adapter; { struct ndis_softc *sc; ndis_miniport_block *block; uint8_t empty[] = { 0, 0, 0, 0, 0, 0 }; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)block->nmb_ifp; if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0) *status = NDIS_STATUS_FAILURE; else { *addr = sc->arpcom.ac_enaddr; *addrlen = ETHER_ADDR_LEN; *status = NDIS_STATUS_SUCCESS; } return; } __stdcall static ndis_status ndis_mapreg_cnt(bustype, cnt) uint32_t bustype; uint32_t *cnt; { *cnt = 8192; return(NDIS_STATUS_SUCCESS); } __stdcall static ndis_status ndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap) ndis_handle adapter; uint32_t dmachannel; uint8_t dmasize; uint32_t physmapneeded; uint32_t maxmap; { struct ndis_softc *sc; ndis_miniport_block *block; int error, i, nseg = NDIS_MAXSEG; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)block->nmb_ifp; sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded, M_DEVBUF, M_NOWAIT|M_ZERO); if (sc->ndis_mmaps == NULL) return(NDIS_STATUS_RESOURCES); error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->ndis_mtag); if (error) { free(sc->ndis_mmaps, M_DEVBUF); return(NDIS_STATUS_RESOURCES); } for (i = 0; i < physmapneeded; i++) bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]); sc->ndis_mmapcnt = physmapneeded; return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_free_mapreg(adapter) ndis_handle adapter; { struct ndis_softc *sc; ndis_miniport_block *block; int i; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)block->nmb_ifp; for (i = 0; i < sc->ndis_mmapcnt; i++) bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]); free(sc->ndis_mmaps, M_DEVBUF); bus_dma_tag_destroy(sc->ndis_mtag); return; } static void ndis_mapshared_cb(arg, segs, nseg, error) void *arg; bus_dma_segment_t *segs; int nseg; int error; { ndis_physaddr *p; if (error || nseg > 1) return; p = arg; p->np_quad = segs[0].ds_addr; return; } /* * This maps to bus_dmamem_alloc(). */ __stdcall static void ndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr) ndis_handle adapter; uint32_t len; uint8_t cached; void **vaddr; ndis_physaddr *paddr; { ndis_miniport_block *block; struct ndis_softc *sc; struct ndis_shmem *sh; int error; if (adapter == NULL) return; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)(block->nmb_ifp); sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO); if (sh == NULL) return; /* * When performing shared memory allocations, create a tag * with a lowaddr limit that restricts physical memory mappings * so that they all fall within the first 1GB of memory. * At least one device/driver combination (Linksys Instant * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have * problems with performing DMA operations with physical * that lie above the 1GB mark. I don't know if this is a * hardware limitation or if the addresses are being truncated * within the driver, but this seems to be the only way to * make these cards work reliably in systems with more than * 1GB of physical memory. */ error = bus_dma_tag_create(sc->ndis_parent_tag, 64, 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL, &sh->ndis_stag); if (error) { free(sh, M_DEVBUF); return; } error = bus_dmamem_alloc(sh->ndis_stag, vaddr, BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap); if (error) { bus_dma_tag_destroy(sh->ndis_stag); free(sh, M_DEVBUF); return; } error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr, len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT); if (error) { bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap); bus_dma_tag_destroy(sh->ndis_stag); free(sh, M_DEVBUF); return; } sh->ndis_saddr = *vaddr; sh->ndis_next = sc->ndis_shlist; sc->ndis_shlist = sh; return; } struct ndis_allocwork { ndis_handle na_adapter; uint32_t na_len; uint8_t na_cached; void *na_ctx; }; static void ndis_asyncmem_complete(arg) void *arg; { ndis_miniport_block *block; struct ndis_softc *sc; struct ndis_allocwork *w; void *vaddr; ndis_physaddr paddr; __stdcall ndis_allocdone_handler donefunc; w = arg; block = (ndis_miniport_block *)w->na_adapter; sc = (struct ndis_softc *)(block->nmb_ifp); vaddr = NULL; paddr.np_quad = 0; donefunc = sc->ndis_chars.nmc_allocate_complete_func; ndis_alloc_sharedmem(w->na_adapter, w->na_len, w->na_cached, &vaddr, &paddr); donefunc(w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx); free(arg, M_DEVBUF); return; } __stdcall static ndis_status ndis_alloc_sharedmem_async(adapter, len, cached, ctx) ndis_handle adapter; uint32_t len; uint8_t cached; void *ctx; { struct ndis_allocwork *w; if (adapter == NULL) return(NDIS_STATUS_FAILURE); w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT); if (w == NULL) return(NDIS_STATUS_FAILURE); w->na_adapter = adapter; w->na_cached = cached; w->na_len = len; w->na_ctx = ctx; /* * Pawn this work off on the SWI thread instead of the * taskqueue thread, because sometimes drivers will queue * up work items on the taskqueue thread that will block, * which would prevent the memory allocation from completing * when we need it. */ ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI); return(NDIS_STATUS_PENDING); } __stdcall static void ndis_free_sharedmem(adapter, len, cached, vaddr, paddr) ndis_handle adapter; uint32_t len; uint8_t cached; void *vaddr; ndis_physaddr paddr; { ndis_miniport_block *block; struct ndis_softc *sc; struct ndis_shmem *sh, *prev; if (vaddr == NULL || adapter == NULL) return; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)(block->nmb_ifp); sh = prev = sc->ndis_shlist; while (sh) { if (sh->ndis_saddr == vaddr) break; prev = sh; sh = sh->ndis_next; } bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap); bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap); bus_dma_tag_destroy(sh->ndis_stag); if (sh == sc->ndis_shlist) sc->ndis_shlist = sh->ndis_next; else prev->ndis_next = sh->ndis_next; free(sh, M_DEVBUF); return; } __stdcall static ndis_status ndis_map_iospace(vaddr, adapter, paddr, len) void **vaddr; ndis_handle adapter; ndis_physaddr paddr; uint32_t len; { ndis_miniport_block *block; struct ndis_softc *sc; if (adapter == NULL) return(NDIS_STATUS_FAILURE); block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)(block->nmb_ifp); if (sc->ndis_res_mem != NULL && paddr.np_quad == rman_get_start(sc->ndis_res_mem)) *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem); else if (sc->ndis_res_altmem != NULL && paddr.np_quad == rman_get_start(sc->ndis_res_altmem)) *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem); + else if (sc->ndis_res_am != NULL && + paddr.np_quad == rman_get_start(sc->ndis_res_am)) + *vaddr = (void *)rman_get_virtual(sc->ndis_res_am); else return(NDIS_STATUS_FAILURE); return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_unmap_iospace(adapter, vaddr, len) ndis_handle adapter; void *vaddr; uint32_t len; { return; } __stdcall static uint32_t ndis_cachefill(void) { return(128); } __stdcall static uint32_t ndis_dma_align(handle) ndis_handle handle; { return(128); } /* * NDIS has two methods for dealing with NICs that support DMA. * One is to just pass packets to the driver and let it call * NdisMStartBufferPhysicalMapping() to map each buffer in the packet * all by itself, and the other is to let the NDIS library handle the * buffer mapping internally, and hand the driver an already populated * scatter/gather fragment list. If the driver calls * NdisMInitializeScatterGatherDma(), it wants to use the latter * method. */ __stdcall static ndis_status ndis_init_sc_dma(adapter, is64, maxphysmap) ndis_handle adapter; uint8_t is64; uint32_t maxphysmap; { struct ndis_softc *sc; ndis_miniport_block *block; int error; if (adapter == NULL) return(NDIS_STATUS_FAILURE); block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)block->nmb_ifp; /* Don't do this twice. */ if (sc->ndis_sc == 1) return(NDIS_STATUS_SUCCESS); error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW, NULL, NULL, &sc->ndis_ttag); sc->ndis_sc = 1; return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_alloc_packetpool(status, pool, descnum, protrsvdlen) ndis_status *status; ndis_handle *pool; uint32_t descnum; uint32_t protrsvdlen; { ndis_packet *cur; int i; *pool = malloc(sizeof(ndis_packet) * ((descnum + NDIS_POOL_EXTRA) + 1), M_DEVBUF, M_NOWAIT|M_ZERO); if (pool == NULL) { *status = NDIS_STATUS_RESOURCES; return; } cur = (ndis_packet *)*pool; cur->np_private.npp_flags = 0x1; /* mark the head of the list */ cur->np_private.npp_totlen = 0; /* init deletetion flag */ for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) { cur->np_private.npp_head = (ndis_handle)(cur + 1); cur++; } *status = NDIS_STATUS_SUCCESS; return; } __stdcall static void ndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen) ndis_status *status; ndis_handle *pool; uint32_t descnum; uint32_t oflowdescnum; uint32_t protrsvdlen; { return(ndis_alloc_packetpool(status, pool, descnum + oflowdescnum, protrsvdlen)); } __stdcall static uint32_t ndis_packetpool_use(pool) ndis_handle pool; { ndis_packet *head; head = (ndis_packet *)pool; return(head->np_private.npp_count); } __stdcall static void ndis_free_packetpool(pool) ndis_handle pool; { ndis_packet *head; head = pool; /* Mark this pool as 'going away.' */ head->np_private.npp_totlen = 1; /* If there are no buffers loaned out, destroy the pool. */ if (head->np_private.npp_count == 0) free(pool, M_DEVBUF); else printf("NDIS: buggy driver deleting active packet pool!\n"); return; } __stdcall static void ndis_alloc_packet(status, packet, pool) ndis_status *status; ndis_packet **packet; ndis_handle pool; { ndis_packet *head, *pkt; head = (ndis_packet *)pool; if (head->np_private.npp_flags != 0x1) { *status = NDIS_STATUS_FAILURE; return; } /* * If this pool is marked as 'going away' don't allocate any * more packets out of it. */ if (head->np_private.npp_totlen) { *status = NDIS_STATUS_FAILURE; return; } pkt = (ndis_packet *)head->np_private.npp_head; if (pkt == NULL) { *status = NDIS_STATUS_RESOURCES; return; } head->np_private.npp_head = pkt->np_private.npp_head; pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL; /* Save pointer to the pool. */ pkt->np_private.npp_pool = head; /* Set the oob offset pointer. Lots of things expect this. */ pkt->np_private.npp_packetooboffset = offsetof(ndis_packet, np_oob); /* * We must initialize the packet flags correctly in order * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly. */ pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS; *packet = pkt; head->np_private.npp_count++; *status = NDIS_STATUS_SUCCESS; return; } __stdcall static void ndis_release_packet(packet) ndis_packet *packet; { ndis_packet *head; if (packet == NULL || packet->np_private.npp_pool == NULL) return; head = packet->np_private.npp_pool; if (head->np_private.npp_flags != 0x1) return; packet->np_private.npp_head = head->np_private.npp_head; head->np_private.npp_head = (ndis_buffer *)packet; head->np_private.npp_count--; /* * If the pool has been marked for deletion and there are * no more packets outstanding, nuke the pool. */ if (head->np_private.npp_totlen && head->np_private.npp_count == 0) free(head, M_DEVBUF); return; } __stdcall static void ndis_unchain_headbuf(packet, buf) ndis_packet *packet; ndis_buffer **buf; { ndis_packet_private *priv; if (packet == NULL || buf == NULL) return; priv = &packet->np_private; priv->npp_validcounts = FALSE; if (priv->npp_head == priv->npp_tail) { *buf = priv->npp_head; priv->npp_head = priv->npp_tail = NULL; } else { *buf = priv->npp_head; priv->npp_head = (*buf)->nb_next; } return; } __stdcall static void ndis_unchain_tailbuf(packet, buf) ndis_packet *packet; ndis_buffer **buf; { ndis_packet_private *priv; ndis_buffer *tmp; if (packet == NULL || buf == NULL) return; priv = &packet->np_private; priv->npp_validcounts = FALSE; if (priv->npp_head == priv->npp_tail) { *buf = priv->npp_head; priv->npp_head = priv->npp_tail = NULL; } else { *buf = priv->npp_tail; tmp = priv->npp_head; while (tmp->nb_next != priv->npp_tail) tmp = tmp->nb_next; priv->npp_tail = tmp; tmp->nb_next = NULL; } return; } /* * The NDIS "buffer" manipulation functions are somewhat misnamed. * They don't really allocate buffers: they allocate buffer mappings. * The idea is you reserve a chunk of DMA-able memory using * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer() * to obtain the virtual address of the DMA-able region. * ndis_alloc_bufpool() is analagous to bus_dma_tag_create(). */ __stdcall static void ndis_alloc_bufpool(status, pool, descnum) ndis_status *status; ndis_handle *pool; uint32_t descnum; { ndis_buffer *cur; int i; *pool = malloc(sizeof(ndis_buffer) * ((descnum + NDIS_POOL_EXTRA) + 1), M_DEVBUF, M_NOWAIT|M_ZERO); if (pool == NULL) { *status = NDIS_STATUS_RESOURCES; return; } cur = (ndis_buffer *)*pool; cur->nb_flags = 0x1; /* mark the head of the list */ cur->nb_bytecount = 0; /* init usage count */ cur->nb_byteoffset = 0; /* init deletetion flag */ for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) { cur->nb_next = cur + 1; cur++; } *status = NDIS_STATUS_SUCCESS; return; } __stdcall static void ndis_free_bufpool(pool) ndis_handle pool; { ndis_buffer *head; head = pool; /* Mark this pool as 'going away.' */ head->nb_byteoffset = 1; /* If there are no buffers loaned out, destroy the pool. */ if (head->nb_bytecount == 0) free(pool, M_DEVBUF); else printf("NDIS: buggy driver deleting active buffer pool!\n"); return; } /* * This maps to a bus_dmamap_create() and bus_dmamap_load(). */ __stdcall static void ndis_alloc_buf(status, buffer, pool, vaddr, len) ndis_status *status; ndis_buffer **buffer; ndis_handle pool; void *vaddr; uint32_t len; { ndis_buffer *head, *buf; head = (ndis_buffer *)pool; if (head->nb_flags != 0x1) { *status = NDIS_STATUS_FAILURE; return; } /* * If this pool is marked as 'going away' don't allocate any * more buffers out of it. */ if (head->nb_byteoffset) { *status = NDIS_STATUS_FAILURE; return; } buf = head->nb_next; if (buf == NULL) { *status = NDIS_STATUS_RESOURCES; return; } head->nb_next = buf->nb_next; /* Save pointer to the pool. */ buf->nb_process = head; MDL_INIT(buf, vaddr, len); *buffer = buf; /* Increment count of busy buffers. */ head->nb_bytecount++; *status = NDIS_STATUS_SUCCESS; return; } __stdcall static void ndis_release_buf(buf) ndis_buffer *buf; { ndis_buffer *head; if (buf == NULL || buf->nb_process == NULL) return; head = buf->nb_process; if (head->nb_flags != 0x1) return; buf->nb_next = head->nb_next; head->nb_next = buf; /* Decrement count of busy buffers. */ head->nb_bytecount--; /* * If the pool has been marked for deletion and there are * no more buffers outstanding, nuke the pool. */ if (head->nb_byteoffset && head->nb_bytecount == 0) free(head, M_DEVBUF); return; } /* Aw c'mon. */ __stdcall static uint32_t ndis_buflen(buf) ndis_buffer *buf; { return(buf->nb_bytecount); } /* * Get the virtual address and length of a buffer. * Note: the vaddr argument is optional. */ __stdcall static void ndis_query_buf(buf, vaddr, len) ndis_buffer *buf; void **vaddr; uint32_t *len; { if (vaddr != NULL) *vaddr = MDL_VA(buf); *len = buf->nb_bytecount; return; } /* Same as above -- we don't care about the priority. */ __stdcall static void ndis_query_buf_safe(buf, vaddr, len, prio) ndis_buffer *buf; void **vaddr; uint32_t *len; uint32_t prio; { if (vaddr != NULL) *vaddr = MDL_VA(buf); *len = buf->nb_bytecount; return; } /* Damnit Microsoft!! How many ways can you do the same thing?! */ __stdcall static void * ndis_buf_vaddr(buf) ndis_buffer *buf; { return(MDL_VA(buf)); } __stdcall static void * ndis_buf_vaddr_safe(buf, prio) ndis_buffer *buf; uint32_t prio; { return(MDL_VA(buf)); } __stdcall static void ndis_adjust_buflen(buf, len) ndis_buffer *buf; int len; { buf->nb_bytecount = len; return; } __stdcall static uint32_t ndis_interlock_inc(addend) uint32_t *addend; { atomic_add_long((u_long *)addend, 1); return(*addend); } __stdcall static uint32_t ndis_interlock_dec(addend) uint32_t *addend; { atomic_subtract_long((u_long *)addend, 1); return(*addend); } __stdcall static void ndis_init_event(event) ndis_event *event; { /* * NDIS events are always notification * events, and should be initialized to the * not signaled state. */ ntoskrnl_init_event(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE); return; } __stdcall static void ndis_set_event(event) ndis_event *event; { ntoskrnl_set_event(&event->ne_event, 0, 0); return; } __stdcall static void ndis_reset_event(event) ndis_event *event; { ntoskrnl_reset_event(&event->ne_event); return; } __stdcall static uint8_t ndis_wait_event(event, msecs) ndis_event *event; uint32_t msecs; { int64_t duetime; uint32_t rval; duetime = ((int64_t)msecs * -10000); rval = ntoskrnl_waitforobj((nt_dispatch_header *)event, 0, 0, TRUE, msecs ? &duetime : NULL); if (rval == STATUS_TIMEOUT) return(FALSE); return(TRUE); } __stdcall static ndis_status ndis_unicode2ansi(dstr, sstr) ndis_ansi_string *dstr; ndis_unicode_string *sstr; { if (dstr == NULL || sstr == NULL) return(NDIS_STATUS_FAILURE); if (ndis_unicode_to_ascii(sstr->nus_buf, sstr->nus_len, &dstr->nas_buf)) return(NDIS_STATUS_FAILURE); dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf); return (NDIS_STATUS_SUCCESS); } __stdcall static ndis_status ndis_ansi2unicode(dstr, sstr) ndis_unicode_string *dstr; ndis_ansi_string *sstr; { char *str; if (dstr == NULL || sstr == NULL) return(NDIS_STATUS_FAILURE); str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT); if (str == NULL) return(NDIS_STATUS_FAILURE); strncpy(str, sstr->nas_buf, sstr->nas_len); *(str + sstr->nas_len) = '\0'; if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) { free(str, M_DEVBUF); return(NDIS_STATUS_FAILURE); } dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2; free(str, M_DEVBUF); return (NDIS_STATUS_SUCCESS); } __stdcall static ndis_status ndis_assign_pcirsrc(adapter, slot, list) ndis_handle adapter; uint32_t slot; ndis_resource_list **list; { ndis_miniport_block *block; if (adapter == NULL || list == NULL) return (NDIS_STATUS_FAILURE); block = (ndis_miniport_block *)adapter; *list = block->nmb_rlist; return (NDIS_STATUS_SUCCESS); } __stdcall static ndis_status ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode) ndis_miniport_interrupt *intr; ndis_handle adapter; uint32_t ivec; uint32_t ilevel; uint8_t reqisr; uint8_t shared; ndis_interrupt_mode imode; { ndis_miniport_block *block; block = adapter; intr->ni_block = adapter; intr->ni_isrreq = reqisr; intr->ni_shared = shared; block->nmb_interrupt = intr; return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_deregister_intr(intr) ndis_miniport_interrupt *intr; { return; } __stdcall static void ndis_register_shutdown(adapter, shutdownctx, shutdownfunc) ndis_handle adapter; void *shutdownctx; ndis_shutdown_handler shutdownfunc; { ndis_miniport_block *block; ndis_miniport_characteristics *chars; struct ndis_softc *sc; if (adapter == NULL) return; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)block->nmb_ifp; chars = &sc->ndis_chars; chars->nmc_shutdown_handler = shutdownfunc; chars->nmc_rsvd0 = shutdownctx; return; } __stdcall static void ndis_deregister_shutdown(adapter) ndis_handle adapter; { ndis_miniport_block *block; ndis_miniport_characteristics *chars; struct ndis_softc *sc; if (adapter == NULL) return; block = (ndis_miniport_block *)adapter; sc = (struct ndis_softc *)block->nmb_ifp; chars = &sc->ndis_chars; chars->nmc_shutdown_handler = NULL; chars->nmc_rsvd0 = NULL; return; } __stdcall static uint32_t ndis_numpages(buf) ndis_buffer *buf; { if (buf == NULL) return(0); if (buf->nb_bytecount == 0) return(1); return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount)); } __stdcall static void ndis_buf_physpages(buf, pages) ndis_buffer *buf; uint32_t *pages; { if (buf == NULL) return; *pages = ndis_numpages(buf); return; } __stdcall static void ndis_query_bufoffset(buf, off, len) ndis_buffer *buf; uint32_t *off; uint32_t *len; { if (buf == NULL) return; *off = buf->nb_byteoffset; *len = buf->nb_bytecount; return; } __stdcall static void ndis_sleep(usecs) uint32_t usecs; { struct timeval tv; tv.tv_sec = 0; tv.tv_usec = usecs; ndis_thsuspend(curthread->td_proc, tvtohz(&tv)); return; } __stdcall static uint32_t ndis_read_pccard_amem(handle, offset, buf, len) ndis_handle handle; uint32_t offset; void *buf; uint32_t len; { struct ndis_softc *sc; ndis_miniport_block *block; bus_space_handle_t bh; bus_space_tag_t bt; char *dest; int i; if (handle == NULL) return(0); block = (ndis_miniport_block *)handle; sc = (struct ndis_softc *)block->nmb_ifp; dest = buf; bh = rman_get_bushandle(sc->ndis_res_am); bt = rman_get_bustag(sc->ndis_res_am); for (i = 0; i < len; i++) - dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2)); + dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2); return(i); } __stdcall static uint32_t ndis_write_pccard_amem(handle, offset, buf, len) ndis_handle handle; uint32_t offset; void *buf; uint32_t len; { struct ndis_softc *sc; ndis_miniport_block *block; bus_space_handle_t bh; bus_space_tag_t bt; char *src; int i; if (handle == NULL) return(0); block = (ndis_miniport_block *)handle; sc = (struct ndis_softc *)block->nmb_ifp; src = buf; bh = rman_get_bushandle(sc->ndis_res_am); bt = rman_get_bustag(sc->ndis_res_am); for (i = 0; i < len; i++) - bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]); + bus_space_write_1(bt, bh, (offset + i) * 2, src[i]); return(i); } __stdcall static list_entry * ndis_insert_head(head, entry, lock) list_entry *head; list_entry *entry; ndis_spin_lock *lock; { list_entry *flink; lock->nsl_kirql = FASTCALL2(hal_lock, &lock->nsl_spinlock, DISPATCH_LEVEL); flink = head->nle_flink; entry->nle_flink = flink; entry->nle_blink = head; flink->nle_blink = entry; head->nle_flink = entry; FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql); return(flink); } __stdcall static list_entry * ndis_remove_head(head, lock) list_entry *head; ndis_spin_lock *lock; { list_entry *flink; list_entry *entry; lock->nsl_kirql = FASTCALL2(hal_lock, &lock->nsl_spinlock, DISPATCH_LEVEL); entry = head->nle_flink; flink = entry->nle_flink; head->nle_flink = flink; flink->nle_blink = head; FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql); return(entry); } __stdcall static list_entry * ndis_insert_tail(head, entry, lock) list_entry *head; list_entry *entry; ndis_spin_lock *lock; { list_entry *blink; lock->nsl_kirql = FASTCALL2(hal_lock, &lock->nsl_spinlock, DISPATCH_LEVEL); blink = head->nle_blink; entry->nle_flink = head; entry->nle_blink = blink; blink->nle_flink = entry; head->nle_blink = entry; FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql); return(blink); } __stdcall static uint8_t ndis_sync_with_intr(intr, syncfunc, syncctx) ndis_miniport_interrupt *intr; void *syncfunc; void *syncctx; { struct ndis_softc *sc; __stdcall uint8_t (*sync)(void *); uint8_t rval; if (syncfunc == NULL || syncctx == NULL) return(0); sc = (struct ndis_softc *)intr->ni_block->nmb_ifp; sync = syncfunc; mtx_lock(&sc->ndis_intrmtx); rval = sync(syncctx); mtx_unlock(&sc->ndis_intrmtx); return(rval); } /* * Return the number of 100 nanosecond intervals since * January 1, 1601. (?!?!) */ __stdcall static void ndis_time(tval) uint64_t *tval; { struct timespec ts; nanotime(&ts); *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 + 11644473600; return; } /* * Return the number of milliseconds since the system booted. */ __stdcall static void ndis_uptime(tval) uint32_t *tval; { struct timespec ts; nanouptime(&ts); *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000; return; } __stdcall static void ndis_init_string(dst, src) ndis_unicode_string *dst; char *src; { ndis_unicode_string *u; u = dst; u->nus_buf = NULL; if (ndis_ascii_to_unicode(src, &u->nus_buf)) return; u->nus_len = u->nus_maxlen = strlen(src) * 2; return; } __stdcall static void ndis_free_string(str) ndis_unicode_string *str; { if (str == NULL) return; if (str->nus_buf != NULL) free(str->nus_buf, M_DEVBUF); free(str, M_DEVBUF); return; } __stdcall static ndis_status ndis_remove_miniport(adapter) ndis_handle *adapter; { return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_init_ansi_string(dst, src) ndis_ansi_string *dst; char *src; { ndis_ansi_string *a; a = dst; if (a == NULL) return; if (src == NULL) { a->nas_len = a->nas_maxlen = 0; a->nas_buf = NULL; } else { a->nas_buf = src; a->nas_len = a->nas_maxlen = strlen(src); } return; } __stdcall static void ndis_init_unicode_string(dst, src) ndis_unicode_string *dst; uint16_t *src; { ndis_unicode_string *u; int i; u = dst; if (u == NULL) return; if (src == NULL) { u->nus_len = u->nus_maxlen = 0; u->nus_buf = NULL; } else { i = 0; while(src[i] != 0) i++; u->nus_buf = src; u->nus_len = u->nus_maxlen = i * 2; } return; } __stdcall static void ndis_get_devprop(adapter, phydevobj, funcdevobj, nextdevobj, resources, transresources) ndis_handle adapter; device_object **phydevobj; device_object **funcdevobj; device_object **nextdevobj; cm_resource_list *resources; cm_resource_list *transresources; { ndis_miniport_block *block; block = (ndis_miniport_block *)adapter; if (phydevobj != NULL) *phydevobj = &block->nmb_devobj; if (funcdevobj != NULL) *funcdevobj = &block->nmb_devobj; return; } __stdcall static void ndis_firstbuf(packet, buf, firstva, firstlen, totlen) ndis_packet *packet; ndis_buffer **buf; void **firstva; uint32_t *firstlen; uint32_t *totlen; { ndis_buffer *tmp; tmp = packet->np_private.npp_head; *buf = tmp; if (tmp == NULL) { *firstva = NULL; *firstlen = *totlen = 0; } else { *firstva = MDL_VA(tmp); *firstlen = *totlen = tmp->nb_bytecount; for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next) *totlen += tmp->nb_bytecount; } return; } __stdcall static void ndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio) ndis_packet *packet; ndis_buffer **buf; void **firstva; uint32_t *firstlen; uint32_t *totlen; uint32_t prio; { ndis_firstbuf(packet, buf, firstva, firstlen, totlen); } /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */ __stdcall static void ndis_open_file(status, filehandle, filelength, filename, highestaddr) ndis_status *status; ndis_handle *filehandle; uint32_t *filelength; ndis_unicode_string *filename; ndis_physaddr highestaddr; { char *afilename = NULL; struct thread *td = curthread; struct nameidata nd; int flags, error; struct vattr vat; struct vattr *vap = &vat; ndis_fh *fh; char path[MAXPATHLEN]; ndis_unicode_to_ascii(filename->nus_buf, filename->nus_len, &afilename); sprintf(path, "%s/%s", ndis_filepath, afilename); free(afilename, M_DEVBUF); fh = malloc(sizeof(ndis_fh), M_TEMP, M_NOWAIT); if (fh == NULL) { *status = NDIS_STATUS_RESOURCES; return; } mtx_lock(&Giant); /* Some threads don't have a current working directory. */ if (td->td_proc->p_fd->fd_rdir == NULL) td->td_proc->p_fd->fd_rdir = rootvnode; if (td->td_proc->p_fd->fd_cdir == NULL) td->td_proc->p_fd->fd_cdir = rootvnode; NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); flags = FREAD; error = vn_open(&nd, &flags, 0, -1); if (error) { mtx_unlock(&Giant); *status = NDIS_STATUS_FILE_NOT_FOUND; free(fh, M_TEMP); printf("NDIS: open file %s failed: %d\n", path, error); return; } NDFREE(&nd, NDF_ONLY_PNBUF); /* Get the file size. */ - VOP_GETATTR(nd.ni_vp, vap, NOCRED, td); + VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td); VOP_UNLOCK(nd.ni_vp, 0, td); mtx_unlock(&Giant); fh->nf_vp = nd.ni_vp; fh->nf_map = NULL; *filehandle = fh; *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF; *status = NDIS_STATUS_SUCCESS; + return; } __stdcall static void ndis_map_file(status, mappedbuffer, filehandle) ndis_status *status; void **mappedbuffer; ndis_handle filehandle; { ndis_fh *fh; struct thread *td = curthread; int error, resid; if (filehandle == NULL) { *status = NDIS_STATUS_FAILURE; return; } fh = (ndis_fh *)filehandle; if (fh->nf_vp == NULL) { *status = NDIS_STATUS_FAILURE; return; } if (fh->nf_map != NULL) { *status = NDIS_STATUS_ALREADY_MAPPED; return; } fh->nf_map = malloc(fh->nf_maplen, M_DEVBUF, M_NOWAIT); if (fh->nf_map == NULL) { *status = NDIS_STATUS_RESOURCES; return; } mtx_lock(&Giant); error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0, UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td); mtx_unlock(&Giant); if (error) *status = NDIS_STATUS_FAILURE; else { *status = NDIS_STATUS_SUCCESS; *mappedbuffer = fh->nf_map; } return; } __stdcall static void ndis_unmap_file(filehandle) ndis_handle filehandle; { ndis_fh *fh; fh = (ndis_fh *)filehandle; if (fh->nf_map == NULL) return; free(fh->nf_map, M_DEVBUF); fh->nf_map = NULL; return; } __stdcall static void ndis_close_file(filehandle) ndis_handle filehandle; { struct thread *td = curthread; ndis_fh *fh; if (filehandle == NULL) return; fh = (ndis_fh *)filehandle; if (fh->nf_map != NULL) { free(fh->nf_map, M_DEVBUF); fh->nf_map = NULL; } if (fh->nf_vp == NULL) return; mtx_lock(&Giant); vn_close(fh->nf_vp, FREAD, td->td_ucred, td); mtx_unlock(&Giant); fh->nf_vp = NULL; free(fh, M_DEVBUF); return; } __stdcall static uint8_t ndis_cpu_cnt() { return(mp_ncpus); } typedef void (*ndis_statusdone_handler)(ndis_handle); typedef void (*ndis_status_handler)(ndis_handle, ndis_status, void *, uint32_t); __stdcall static void ndis_ind_statusdone(adapter) ndis_handle adapter; { ndis_miniport_block *block; __stdcall ndis_statusdone_handler statusdonefunc; block = (ndis_miniport_block *)adapter; statusdonefunc = block->nmb_statusdone_func; statusdonefunc(adapter); return; } __stdcall static void ndis_ind_status(adapter, status, sbuf, slen) ndis_handle adapter; ndis_status status; void *sbuf; uint32_t slen; { ndis_miniport_block *block; __stdcall ndis_status_handler statusfunc; block = (ndis_miniport_block *)adapter; statusfunc = block->nmb_status_func; statusfunc(adapter, status, sbuf, slen); return; } static void ndis_workfunc(ctx) void *ctx; { ndis_work_item *work; __stdcall ndis_proc workfunc; work = ctx; workfunc = work->nwi_func; workfunc(work, work->nwi_ctx); return; } __stdcall static ndis_status ndis_sched_workitem(work) ndis_work_item *work; { ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE); return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen) ndis_packet *dpkt; uint32_t doff; uint32_t reqlen; ndis_packet *spkt; uint32_t soff; uint32_t *cpylen; { ndis_buffer *src, *dst; char *sptr, *dptr; int resid, copied, len, scnt, dcnt; *cpylen = 0; src = spkt->np_private.npp_head; dst = dpkt->np_private.npp_head; sptr = MDL_VA(src); dptr = MDL_VA(dst); scnt = src->nb_bytecount; dcnt = dst->nb_bytecount; while (soff) { if (src->nb_bytecount > soff) { sptr += soff; scnt = src->nb_bytecount - soff; break; } soff -= src->nb_bytecount; src = src->nb_next; if (src == NULL) return; sptr = MDL_VA(src); } while (doff) { if (dst->nb_bytecount > doff) { dptr += doff; dcnt = dst->nb_bytecount - doff; break; } doff -= dst->nb_bytecount; dst = dst->nb_next; if (dst == NULL) return; dptr = MDL_VA(dst); } resid = reqlen; copied = 0; while(1) { if (resid < scnt) len = resid; else len = scnt; if (dcnt < len) len = dcnt; bcopy(sptr, dptr, len); copied += len; resid -= len; if (resid == 0) break; dcnt -= len; if (dcnt == 0) { dst = dst->nb_next; if (dst == NULL) break; dptr = MDL_VA(dst); dcnt = dst->nb_bytecount; } scnt -= len; if (scnt == 0) { src = src->nb_next; if (src == NULL) break; sptr = MDL_VA(src); scnt = src->nb_bytecount; } } *cpylen = copied; return; } __stdcall static void ndis_pkt_to_pkt_safe(dpkt, doff, reqlen, spkt, soff, cpylen, prio) ndis_packet *dpkt; uint32_t doff; uint32_t reqlen; ndis_packet *spkt; uint32_t soff; uint32_t *cpylen; uint32_t prio; { ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen); return; } __stdcall static ndis_status ndis_register_dev(handle, devname, symname, majorfuncs, devobj, devhandle) ndis_handle handle; ndis_unicode_string *devname; ndis_unicode_string *symname; driver_dispatch *majorfuncs[]; void **devobj; ndis_handle *devhandle; { ndis_miniport_block *block; block = (ndis_miniport_block *)handle; *devobj = &block->nmb_devobj; *devhandle = handle; return(NDIS_STATUS_SUCCESS); } __stdcall static ndis_status ndis_deregister_dev(handle) ndis_handle handle; { return(NDIS_STATUS_SUCCESS); } __stdcall static ndis_status ndis_query_name(name, handle) ndis_unicode_string *name; ndis_handle handle; { ndis_miniport_block *block; block = (ndis_miniport_block *)handle; ndis_ascii_to_unicode(__DECONST(char *, device_get_nameunit(block->nmb_dev)), &name->nus_buf); name->nus_len = strlen(device_get_nameunit(block->nmb_dev)) * 2; return(NDIS_STATUS_SUCCESS); } __stdcall static void ndis_register_unload(handle, func) ndis_handle handle; void *func; { return; } __stdcall static void dummy() { printf ("NDIS dummy called...\n"); return; } image_patch_table ndis_functbl[] = { { "NdisCopyFromPacketToPacket", (FUNC)ndis_pkt_to_pkt }, { "NdisCopyFromPacketToPacketSafe", (FUNC)ndis_pkt_to_pkt_safe }, { "NdisScheduleWorkItem", (FUNC)ndis_sched_workitem }, { "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone }, { "NdisMIndicateStatus", (FUNC)ndis_ind_status }, { "NdisSystemProcessorCount", (FUNC)ndis_cpu_cnt }, { "NdisUnchainBufferAtBack", (FUNC)ndis_unchain_tailbuf, }, { "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf }, { "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe }, { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages }, { "NdisMGetDeviceProperty", (FUNC)ndis_get_devprop }, { "NdisInitAnsiString", (FUNC)ndis_init_ansi_string }, { "NdisInitUnicodeString", (FUNC)ndis_init_unicode_string }, { "NdisWriteConfiguration", (FUNC)ndis_write_cfg }, { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode }, { "NdisTerminateWrapper", (FUNC)ndis_termwrap }, { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname }, { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx }, { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport }, { "NdisInitializeString", (FUNC)ndis_init_string }, { "NdisFreeString", (FUNC)ndis_free_string }, { "NdisGetCurrentSystemTime", (FUNC)ndis_time }, { "NdisGetSystemUpTime", (FUNC)ndis_uptime }, { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr }, { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async }, { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head }, { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail }, { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head }, { "NdisInitializeWrapper", (FUNC)ndis_initwrap }, { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport }, { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag }, { "NdisAllocateMemory", (FUNC)ndis_malloc }, { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex }, { "NdisCloseConfiguration", (FUNC)ndis_close_cfg }, { "NdisReadConfiguration", (FUNC)ndis_read_cfg }, { "NdisOpenConfiguration", (FUNC)ndis_open_cfg }, { "NdisAcquireSpinLock", (FUNC)ndis_lock }, { "NdisReleaseSpinLock", (FUNC)ndis_unlock }, { "NdisDprAcquireSpinLock", (FUNC)ndis_lock_dpr }, { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock_dpr }, { "NdisAllocateSpinLock", (FUNC)ndis_create_lock }, { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock }, { "NdisFreeMemory", (FUNC)ndis_free }, { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci }, { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci }, { "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci }, { "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci }, { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog }, { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load }, { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload }, { "NdisMInitializeTimer", (FUNC)ndis_create_timer }, { "NdisInitializeTimer", (FUNC)ndis_init_timer }, { "NdisSetTimer", (FUNC)ndis_set_timer }, { "NdisMCancelTimer", (FUNC)ndis_cancel_timer }, { "NdisCancelTimer", (FUNC)ndis_cancel_timer }, { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer }, { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources }, { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport }, { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport }, { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr }, { "NdisQueryMapRegisterCount", (FUNC)ndis_mapreg_cnt }, { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg }, { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg }, { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem }, { "NdisMMapIoSpace", (FUNC)ndis_map_iospace }, { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace }, { "NdisGetCacheFillSize", (FUNC)ndis_cachefill }, { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align }, { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma }, { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool }, { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool }, { "NdisAllocatePacket", (FUNC)ndis_alloc_packet }, { "NdisFreePacket", (FUNC)ndis_release_packet }, { "NdisFreePacketPool", (FUNC)ndis_free_packetpool }, { "NdisDprAllocatePacket", (FUNC)ndis_alloc_packet }, { "NdisDprFreePacket", (FUNC)ndis_release_packet }, { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool }, { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf }, { "NdisQueryBuffer", (FUNC)ndis_query_buf }, { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe }, { "NdisBufferVirtualAddress", (FUNC)ndis_buf_vaddr }, { "NdisBufferVirtualAddressSafe", (FUNC)ndis_buf_vaddr_safe }, { "NdisBufferLength", (FUNC)ndis_buflen }, { "NdisFreeBuffer", (FUNC)ndis_release_buf }, { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool }, { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc }, { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec }, { "NdisInitializeEvent", (FUNC)ndis_init_event }, { "NdisSetEvent", (FUNC)ndis_set_event }, { "NdisResetEvent", (FUNC)ndis_reset_event }, { "NdisWaitEvent", (FUNC)ndis_wait_event }, { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi }, { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc }, { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem }, { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr }, { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr }, { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown }, { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown }, { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages }, { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset }, { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen }, { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use }, { "NdisMSleep", (FUNC)ndis_sleep }, { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf }, { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem }, { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem }, { "NdisOpenFile", (FUNC)ndis_open_file }, { "NdisMapFile", (FUNC)ndis_map_file }, { "NdisUnmapFile", (FUNC)ndis_unmap_file }, { "NdisCloseFile", (FUNC)ndis_close_file }, { "NdisMRegisterDevice", (FUNC)ndis_register_dev }, { "NdisMDeregisterDevice", (FUNC)ndis_deregister_dev }, { "NdisMQueryAdapterInstanceName", (FUNC)ndis_query_name }, { "NdisMRegisterUnloadHandler", (FUNC)ndis_register_unload }, /* * This last entry is a catch-all for any function we haven't * implemented yet. The PE import list patching routine will * use it for any function that doesn't have an explicit match * in this table. */ { NULL, (FUNC)dummy }, /* End of list. */ { NULL, NULL }, }; Index: head/sys/dev/if_ndis/if_ndis_pccard.c =================================================================== --- head/sys/dev/if_ndis/if_ndis_pccard.c (revision 131952) +++ head/sys/dev/if_ndis/if_ndis_pccard.c (revision 131953) @@ -1,294 +1,329 @@ /* * Copyright (c) 2003 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "card_if.h" #include "ndis_driver_data.h" #ifdef NDIS_PCMCIA_DEV_TABLE MODULE_DEPEND(ndis, pccard, 1, 1, 1); MODULE_DEPEND(ndis, ether, 1, 1, 1); MODULE_DEPEND(ndis, wlan, 1, 1, 1); MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); /* * Various supported device vendors/types and their names. * These are defined in the ndis_driver_data.h file. */ static struct ndis_pccard_type ndis_devs[] = { #ifdef NDIS_PCMCIA_DEV_TABLE NDIS_PCMCIA_DEV_TABLE #endif { NULL, NULL, NULL } }; static int ndis_probe_pccard (device_t); static int ndis_attach_pccard (device_t); +static struct resource_list *ndis_get_resource_list + (device_t, device_t); extern int ndis_attach (device_t); extern int ndis_shutdown (device_t); extern int ndis_detach (device_t); extern int ndis_suspend (device_t); extern int ndis_resume (device_t); -static int my_strcasecmp (const char *, const char *, int); - extern struct mtx_pool *ndis_mtxpool; static device_method_t ndis_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ndis_probe_pccard), DEVMETHOD(device_attach, ndis_attach_pccard), DEVMETHOD(device_detach, ndis_detach), DEVMETHOD(device_shutdown, ndis_shutdown), DEVMETHOD(device_suspend, ndis_suspend), DEVMETHOD(device_resume, ndis_resume), + /* Bus interface. */ + + /* + * This is an awful kludge, but we need it becase pccard + * does not implement a bus_get_resource_list() method. + */ + + DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), + { 0, 0 } }; static driver_t ndis_driver = { #ifdef NDIS_DEVNAME NDIS_DEVNAME, #else "ndis", #endif ndis_methods, sizeof(struct ndis_softc) }; static devclass_t ndis_devclass; #ifdef NDIS_MODNAME #define NDIS_MODNAME_OVERRIDE_PCMCIA(x) \ DRIVER_MODULE(x, pccard, ndis_driver, ndis_devclass, 0, 0) NDIS_MODNAME_OVERRIDE_PCMCIA(NDIS_MODNAME); #else DRIVER_MODULE(ndis, pccard, ndis_driver, ndis_devclass, 0, 0); #endif -static int my_strcasecmp(s1, s2, len) - const char *s1; - const char *s2; - int len; -{ - int i; - - for (i = 0; i < len; i++) { - if (toupper(s1[i]) != toupper(s2[i])) - return(0); - } - - return(1); -} - - /* * Probe for an NDIS device. Check the PCI vendor and device * IDs against our list and return a device name if we find a match. */ static int ndis_probe_pccard(dev) device_t dev; { struct ndis_pccard_type *t; const char *prodstr, *vendstr; int error; t = ndis_devs; error = pccard_get_product_str(dev, &prodstr); if (error) return(error); error = pccard_get_vendor_str(dev, &vendstr); if (error) return(error); while(t->ndis_name != NULL) { - if (my_strcasecmp(vendstr, t->ndis_vid, strlen(vendstr)) && - my_strcasecmp(prodstr, t->ndis_did, strlen(prodstr))) { + if (ndis_strcasecmp(vendstr, t->ndis_vid) == 0 && + ndis_strcasecmp(prodstr, t->ndis_did) == 0) { device_set_desc(dev, t->ndis_name); return(0); } t++; } return(ENXIO); } /* * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. */ static int ndis_attach_pccard(dev) device_t dev; { struct ndis_softc *sc; int unit, error = 0, rid; struct ndis_pccard_type *t; int devidx = 0; const char *prodstr, *vendstr; sc = device_get_softc(dev); unit = device_get_unit(dev); sc->ndis_dev = dev; + resource_list_init(&sc->ndis_rl); sc->ndis_io_rid = 0; sc->ndis_res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->ndis_io_rid, 0, ~0, 1, RF_ACTIVE); if (sc->ndis_res_io == NULL) { device_printf(dev, "couldn't map iospace\n"); error = ENXIO; goto fail; } sc->ndis_rescnt++; + resource_list_add(&sc->ndis_rl, SYS_RES_IOPORT, rid, + rman_get_start(sc->ndis_res_io), rman_get_end(sc->ndis_res_io), + rman_get_size(sc->ndis_res_io)); rid = 0; sc->ndis_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->ndis_irq == NULL) { device_printf(dev, "couldn't map interrupt\n"); error = ENXIO; goto fail; } sc->ndis_rescnt++; + resource_list_add(&sc->ndis_rl, SYS_RES_IRQ, rid, + rman_get_start(sc->ndis_irq), rman_get_start(sc->ndis_irq), 1); sc->ndis_iftype = PCMCIABus; /* Figure out exactly which device we matched. */ t = ndis_devs; error = pccard_get_product_str(dev, &prodstr); if (error) return(error); error = pccard_get_vendor_str(dev, &vendstr); if (error) return(error); while(t->ndis_name != NULL) { - if (my_strcasecmp(vendstr, t->ndis_vid, strlen(vendstr)) && - my_strcasecmp(prodstr, t->ndis_did, strlen(prodstr))) + if (ndis_strcasecmp(vendstr, t->ndis_vid) == 0 && + ndis_strcasecmp(prodstr, t->ndis_did) == 0) break; t++; devidx++; } sc->ndis_devidx = devidx; error = ndis_attach(dev); fail: return(error); } +static struct resource_list * +ndis_get_resource_list(dev, child) + device_t dev; + device_t child; +{ + struct ndis_softc *sc; + + sc = device_get_softc(dev); + return (&sc->ndis_rl); +} + #endif /* NDIS_PCI_DEV_TABLE */ #define NDIS_AM_RID 3 int ndis_alloc_amem(arg) void *arg; { struct ndis_softc *sc; int error, rid; if (arg == NULL) return(EINVAL); sc = arg; rid = NDIS_AM_RID; sc->ndis_res_am = bus_alloc_resource(sc->ndis_dev, SYS_RES_MEMORY, &rid, 0UL, ~0UL, 0x1000, RF_ACTIVE); if (sc->ndis_res_am == NULL) { device_printf(sc->ndis_dev, "failed to allocate attribute memory\n"); return(ENXIO); } + sc->ndis_rescnt++; + resource_list_add(&sc->ndis_rl, SYS_RES_MEMORY, rid, + rman_get_start(sc->ndis_res_am), rman_get_end(sc->ndis_res_am), + rman_get_size(sc->ndis_res_am)); error = CARD_SET_MEMORY_OFFSET(device_get_parent(sc->ndis_dev), sc->ndis_dev, rid, 0, NULL); if (error) { device_printf(sc->ndis_dev, "CARD_SET_MEMORY_OFFSET() returned 0x%x\n", error); return(error); } error = CARD_SET_RES_FLAGS(device_get_parent(sc->ndis_dev), sc->ndis_dev, SYS_RES_MEMORY, rid, PCCARD_A_MEM_ATTR); if (error) { device_printf(sc->ndis_dev, "CARD_SET_RES_FLAGS() returned 0x%x\n", error); return(error); } + sc->ndis_am_rid = rid; + return(0); +} + +void +ndis_free_amem(arg) + void *arg; +{ + struct ndis_softc *sc; + + if (arg == NULL) + return; + + sc = arg; + + if (sc->ndis_res_am != NULL) + bus_release_resource(sc->ndis_dev, SYS_RES_MEMORY, + sc->ndis_am_rid, sc->ndis_res_am); + resource_list_free(&sc->ndis_rl); + + return; } Index: head/sys/dev/if_ndis/if_ndis_pci.c =================================================================== --- head/sys/dev/if_ndis/if_ndis_pci.c (revision 131952) +++ head/sys/dev/if_ndis/if_ndis_pci.c (revision 131953) @@ -1,324 +1,340 @@ /* * Copyright (c) 2003 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ndis_driver_data.h" #ifdef NDIS_PCI_DEV_TABLE MODULE_DEPEND(ndis, pci, 1, 1, 1); MODULE_DEPEND(ndis, ether, 1, 1, 1); MODULE_DEPEND(ndis, wlan, 1, 1, 1); MODULE_DEPEND(ndis, ndisapi, 1, 1, 1); /* * Various supported device vendors/types and their names. * These are defined in the ndis_driver_data.h file. */ static struct ndis_pci_type ndis_devs[] = { #ifdef NDIS_PCI_DEV_TABLE NDIS_PCI_DEV_TABLE #endif { 0, 0, 0, NULL } }; static int ndis_probe_pci (device_t); static int ndis_attach_pci (device_t); +static struct resource_list *ndis_get_resource_list + (device_t, device_t); extern int ndis_attach (device_t); extern int ndis_shutdown (device_t); extern int ndis_detach (device_t); extern int ndis_suspend (device_t); extern int ndis_resume (device_t); extern struct mtx_pool *ndis_mtxpool; static device_method_t ndis_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ndis_probe_pci), DEVMETHOD(device_attach, ndis_attach_pci), DEVMETHOD(device_detach, ndis_detach), DEVMETHOD(device_shutdown, ndis_shutdown), DEVMETHOD(device_suspend, ndis_suspend), DEVMETHOD(device_resume, ndis_resume), + /* Bus interface */ + DEVMETHOD(bus_get_resource_list, ndis_get_resource_list), + { 0, 0 } }; static driver_t ndis_driver = { #ifdef NDIS_DEVNAME NDIS_DEVNAME, #else "ndis", #endif ndis_methods, sizeof(struct ndis_softc) }; static devclass_t ndis_devclass; #ifdef NDIS_MODNAME #define NDIS_MODNAME_OVERRIDE_PCI(x) \ DRIVER_MODULE(x, pci, ndis_driver, ndis_devclass, 0, 0) #define NDIS_MODNAME_OVERRIDE_CARDBUS(x) \ DRIVER_MODULE(x, cardbus, ndis_driver, ndis_devclass, 0, 0) NDIS_MODNAME_OVERRIDE_PCI(NDIS_MODNAME); NDIS_MODNAME_OVERRIDE_CARDBUS(NDIS_MODNAME); #else DRIVER_MODULE(ndis, pci, ndis_driver, ndis_devclass, 0, 0); DRIVER_MODULE(ndis, cardbus, ndis_driver, ndis_devclass, 0, 0); #endif /* * Probe for an NDIS device. Check the PCI vendor and device * IDs against our list and return a device name if we find a match. */ static int ndis_probe_pci(dev) device_t dev; { struct ndis_pci_type *t; t = ndis_devs; while(t->ndis_name != NULL) { if ((pci_get_vendor(dev) == t->ndis_vid) && (pci_get_device(dev) == t->ndis_did) && ((pci_read_config(dev, PCIR_SUBVEND_0, 4) == t->ndis_subsys) || t->ndis_subsys == 0)) { device_set_desc(dev, t->ndis_name); return(0); } t++; } return(ENXIO); } /* * Attach the interface. Allocate softc structures, do ifmedia * setup and ethernet/BPF attach. */ static int ndis_attach_pci(dev) device_t dev; { struct ndis_softc *sc; int unit, error = 0, rid; struct ndis_pci_type *t; int devidx = 0, defidx = 0; struct resource_list *rl; struct resource_list_entry *rle; sc = device_get_softc(dev); unit = device_get_unit(dev); sc->ndis_dev = dev; /* * Map control/status registers. */ pci_enable_busmaster(dev); rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); if (rl != NULL) { SLIST_FOREACH(rle, rl, link) { switch (rle->type) { case SYS_RES_IOPORT: sc->ndis_io_rid = rle->rid; sc->ndis_res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->ndis_io_rid, 0, ~0, 1, RF_ACTIVE); if (sc->ndis_res_io == NULL) { device_printf(dev, "couldn't map iospace\n"); error = ENXIO; goto fail; } break; case SYS_RES_MEMORY: if (sc->ndis_res_altmem != NULL && sc->ndis_res_mem != NULL) { device_printf(dev, "too many memory resources\n"); error = ENXIO; goto fail; } if (rle->rid == PCIR_BAR(2)) { sc->ndis_altmem_rid = rle->rid; sc->ndis_res_altmem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->ndis_altmem_rid, 0, ~0, 1, RF_ACTIVE); if (sc->ndis_res_altmem == NULL) { device_printf(dev, "couldn't map alt " "memory\n"); error = ENXIO; goto fail; } } else { sc->ndis_mem_rid = rle->rid; sc->ndis_res_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->ndis_mem_rid, 0, ~0, 1, RF_ACTIVE); if (sc->ndis_res_mem == NULL) { device_printf(dev, "couldn't map memory\n"); error = ENXIO; goto fail; } } break; case SYS_RES_IRQ: rid = rle->rid; sc->ndis_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->ndis_irq == NULL) { device_printf(dev, "couldn't map interrupt\n"); error = ENXIO; goto fail; } break; default: break; } sc->ndis_rescnt++; } } /* * If the BIOS did not set up an interrupt for this device, * the resource traversal code above will fail to set up * an IRQ resource. This is usually a bad thing, so try to * force the allocation of an interrupt here. If one was * not assigned to us by the BIOS, bus_alloc_resource() * should route one for us. */ if (sc->ndis_irq == NULL) { rid = 0; sc->ndis_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); if (sc->ndis_irq == NULL) { device_printf(dev, "couldn't route interrupt\n"); error = ENXIO; goto fail; } sc->ndis_rescnt++; } /* * Allocate the parent bus DMA tag appropriate for PCI. */ #define NDIS_NSEG_NEW 32 error = bus_dma_tag_create(NULL, /* parent */ 1, 0, /* alignment, boundary */ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ BUS_SPACE_MAXADDR, /* highaddr */ NULL, NULL, /* filter, filterarg */ MAXBSIZE, NDIS_NSEG_NEW,/* maxsize, nsegments */ BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */ BUS_DMA_ALLOCNOW, /* flags */ NULL, NULL, /* lockfunc, lockarg */ &sc->ndis_parent_tag); if (error) goto fail; sc->ndis_iftype = PCIBus; /* Figure out exactly which device we matched. */ t = ndis_devs; while(t->ndis_name != NULL) { if ((pci_get_vendor(dev) == t->ndis_vid) && (pci_get_device(dev) == t->ndis_did)) { if (t->ndis_subsys == 0) defidx = devidx; else { if (t->ndis_subsys == pci_read_config(dev, PCIR_SUBVEND_0, 4)) break; } } t++; devidx++; } if (ndis_devs[devidx].ndis_name == NULL) sc->ndis_devidx = defidx; else sc->ndis_devidx = devidx; error = ndis_attach(dev); fail: return(error); +} + +static struct resource_list * +ndis_get_resource_list(dev, child) + device_t dev; + device_t child; +{ + struct ndis_softc *sc; + + sc = device_get_softc(dev); + return (BUS_GET_RESOURCE_LIST(device_get_parent(sc->ndis_dev), dev)); } #endif /* NDIS_PCI_DEV_TABLE */ Index: head/sys/dev/if_ndis/if_ndisvar.h =================================================================== --- head/sys/dev/if_ndis/if_ndisvar.h (revision 131952) +++ head/sys/dev/if_ndis/if_ndisvar.h (revision 131953) @@ -1,135 +1,137 @@ /* * Copyright (c) 2003 * Bill Paul . All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bill Paul. * 4. Neither the name of the author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #define NDIS_DEFAULT_NODENAME "FreeBSD NDIS node" #define NDIS_NODENAME_LEN 32 struct ndis_pci_type { uint16_t ndis_vid; uint16_t ndis_did; uint32_t ndis_subsys; char *ndis_name; }; struct ndis_pccard_type { const char *ndis_vid; const char *ndis_did; char *ndis_name; }; struct ndis_shmem { bus_dma_tag_t ndis_stag; bus_dmamap_t ndis_smap; void *ndis_saddr; struct ndis_shmem *ndis_next; }; struct ndis_cfglist { ndis_cfg ndis_cfg; TAILQ_ENTRY(ndis_cfglist) link; }; TAILQ_HEAD(nch, ndis_cfglist); #define NDIS_INITIALIZED(sc) (sc->ndis_block.nmb_miniportadapterctx != NULL) #define NDIS_INC(x) \ (x)->ndis_txidx = ((x)->ndis_txidx + 1) % (x)->ndis_maxpkts #define arpcom ic.ic_ac struct ndis_softc { struct ieee80211com ic; /* interface info */ #ifdef notdef struct ieee80211com arpcom; /* interface info */ #endif struct ifmedia ifmedia; /* media info */ u_long ndis_hwassist; uint32_t ndis_v4tx; uint32_t ndis_v4rx; bus_space_handle_t ndis_bhandle; bus_space_tag_t ndis_btag; void *ndis_intrhand; struct resource *ndis_irq; struct resource *ndis_res; struct resource *ndis_res_io; int ndis_io_rid; struct resource *ndis_res_mem; int ndis_mem_rid; struct resource *ndis_res_altmem; int ndis_altmem_rid; struct resource *ndis_res_am; /* attribute mem (pccard) */ + int ndis_am_rid; struct resource *ndis_res_cm; /* common mem (pccard) */ + struct resource_list ndis_rl; int ndis_rescnt; struct mtx ndis_mtx; struct mtx ndis_intrmtx; device_t ndis_dev; int ndis_unit; ndis_miniport_block ndis_block; ndis_miniport_characteristics ndis_chars; interface_type ndis_type; struct callout_handle ndis_stat_ch; int ndis_maxpkts; ndis_oid *ndis_oids; int ndis_oidcnt; int ndis_txidx; int ndis_txpending; ndis_packet **ndis_txarray; int ndis_sc; ndis_cfg *ndis_regvals; struct nch ndis_cfglist_head; int ndis_80211; int ndis_link; uint32_t ndis_filter; int ndis_if_flags; int ndis_skip; #if __FreeBSD_version < 502113 struct sysctl_ctx_list ndis_ctx; struct sysctl_oid *ndis_tree; #endif int ndis_devidx; interface_type ndis_iftype; bus_dma_tag_t ndis_parent_tag; struct ndis_shmem *ndis_shlist; bus_dma_tag_t ndis_mtag; bus_dma_tag_t ndis_ttag; bus_dmamap_t *ndis_mmaps; bus_dmamap_t *ndis_tmaps; int ndis_mmapcnt; }; #define NDIS_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx) #define NDIS_UNLOCK(_sc) mtx_unlock(&(_sc)->ndis_mtx)