[BACK]Return to kern_ndis.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / compat / ndis

Annotation of src/sys/compat/ndis/kern_ndis.c, Revision 1.14.10.2

1.1       rittera     1: /*-
                      2:  * Copyright (c) 2003
                      3:  *     Bill Paul <wpaul@windriver.com>.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by Bill Paul.
                     16:  * 4. Neither the name of the author nor the names of any co-contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     30:  * THE POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: #include <sys/cdefs.h>
1.2       rittera    34: #ifdef __FreeBSD__
1.1       rittera    35: __FBSDID("$FreeBSD: src/sys/compat/ndis/kern_ndis.c,v 1.60.2.5 2005/04/01 17:14:20 wpaul Exp $");
1.2       rittera    36: #endif
                     37: #ifdef __NetBSD__
1.14.10.2! yamt       38: __KERNEL_RCSID(0, "$NetBSD: kern_ndis.c,v 1.14.10.1 2009/05/04 08:12:24 yamt Exp $");
1.2       rittera    39: #endif
1.1       rittera    40:
                     41: #include <sys/param.h>
                     42: #include <sys/systm.h>
                     43: #include <sys/unistd.h>
                     44: #include <sys/types.h>
                     45: #include <sys/errno.h>
                     46: #include <sys/callout.h>
                     47: #include <sys/socket.h>
                     48: #include <sys/queue.h>
                     49: #include <sys/sysctl.h>
                     50: #include <sys/proc.h>
                     51: #include <sys/malloc.h>
                     52: #include <sys/lock.h>
1.2       rittera    53: #ifdef __FreeBSD__
1.1       rittera    54: #include <sys/mutex.h>
1.2       rittera    55: #endif
1.1       rittera    56: #include <sys/conf.h>
                     57:
                     58: #include <sys/kernel.h>
                     59: #include <sys/module.h>
1.3       rittera    60: #include <sys/mbuf.h>
1.1       rittera    61: #include <sys/kthread.h>
1.12      ad         62: #include <sys/bus.h>
1.2       rittera    63: #ifdef __FreeBSD__
1.1       rittera    64: #include <machine/resource.h>
                     65: #include <sys/rman.h>
1.2       rittera    66: #endif
1.1       rittera    67:
1.3       rittera    68: #ifdef __NetBSD__
                     69: #include <dev/pci/pcivar.h>
                     70: #include <dev/pci/pcireg.h>
                     71: #endif
                     72:
1.1       rittera    73: #include <net/if.h>
                     74: #include <net/if_arp.h>
1.2       rittera    75: #ifdef __FreeBSD__
1.1       rittera    76: #include <net/ethernet.h>
1.2       rittera    77: #else
                     78: #include <net/if_ether.h>
                     79: #endif
1.1       rittera    80: #include <net/if_dl.h>
                     81: #include <net/if_media.h>
                     82:
                     83: #include <net80211/ieee80211_var.h>
                     84: #include <net80211/ieee80211_ioctl.h>
                     85:
                     86: #include <compat/ndis/pe_var.h>
                     87: #include <compat/ndis/resource_var.h>
                     88: #include <compat/ndis/ntoskrnl_var.h>
                     89: #include <compat/ndis/ndis_var.h>
                     90: #include <compat/ndis/hal_var.h>
                     91: #include <compat/ndis/cfg_var.h>
                     92: #include <compat/ndis/usbd_var.h>
                     93: #include <dev/if_ndis/if_ndisvar.h>
                     94:
1.14.10.1  yamt       95: MODULE(MODULE_CLASS_MISC, ndis, NULL);
                     96:
1.1       rittera    97: #define NDIS_DUMMY_PATH "\\\\some\\bogus\\path"
                     98:
                     99: __stdcall static void ndis_status_func(ndis_handle, ndis_status,
                    100:        void *, uint32_t);
                    101: __stdcall static void ndis_statusdone_func(ndis_handle);
                    102: __stdcall static void ndis_setdone_func(ndis_handle, ndis_status);
                    103: __stdcall static void ndis_getdone_func(ndis_handle, ndis_status);
                    104: __stdcall static void ndis_resetdone_func(ndis_handle, ndis_status, uint8_t);
                    105: __stdcall static void ndis_sendrsrcavail_func(ndis_handle);
                    106: __stdcall static void ndis_intrhand(kdpc *, device_object *,
                    107:        irp *, struct ndis_softc *);
                    108:
                    109: static image_patch_table kernndis_functbl[] = {
                    110:        IMPORT_FUNC(ndis_status_func),
                    111:        IMPORT_FUNC(ndis_statusdone_func),
                    112:        IMPORT_FUNC(ndis_setdone_func),
                    113:        IMPORT_FUNC(ndis_getdone_func),
                    114:        IMPORT_FUNC(ndis_resetdone_func),
                    115:        IMPORT_FUNC(ndis_sendrsrcavail_func),
                    116:        IMPORT_FUNC(ndis_intrhand),
                    117:
                    118:        { NULL, NULL, NULL }
                    119: };
                    120:
                    121: struct nd_head ndis_devhead;
                    122:
                    123: struct ndis_req {
                    124:        void                    (*nr_func)(void *);
                    125:        void                    *nr_arg;
                    126:        int                     nr_exit;
                    127:        STAILQ_ENTRY(ndis_req)  link;
1.3       rittera   128:        /* just for debugging */
                    129:        int                     area;
1.1       rittera   130: };
                    131:
                    132: struct ndisproc {
                    133:        struct ndisqhead        *np_q;
                    134:        struct proc             *np_p;
                    135:        int                     np_state;
1.3       rittera   136:        uint8_t                 np_stack[PAGE_SIZE*NDIS_KSTACK_PAGES];
                    137: #ifdef __NetBSD__
                    138:        int                     np_needs_wakeup;
                    139: #endif
1.1       rittera   140: };
                    141:
                    142: static void ndis_return(void *);
1.11      ad        143: static int ndis_create_kthreads(void);
1.1       rittera   144: static void ndis_destroy_kthreads(void);
                    145: static void ndis_stop_thread(int);
                    146: static int ndis_enlarge_thrqueue(int);
                    147: static int ndis_shrink_thrqueue(int);
1.3       rittera   148: //#ifdef NDIS_LKM
1.1       rittera   149: static void ndis_runq(void *);
1.3       rittera   150: //#endif
1.1       rittera   151:
1.3       rittera   152: #ifdef __FreeBSD__
1.1       rittera   153: static struct mtx ndis_thr_mtx;
1.3       rittera   154: #else /* __NetBSD__ */
                    155: static struct simplelock ndis_thr_mtx;
                    156: #define THR_LOCK()      do {old_ipl = splnet(); simple_lock(&ndis_thr_mtx);} while(0)
                    157: #define THR_UNLOCK()    do {simple_unlock(&ndis_thr_mtx); splx(old_ipl);} while(0)
                    158: #endif
                    159:
1.1       rittera   160: static struct mtx ndis_req_mtx;
                    161: static STAILQ_HEAD(ndisqhead, ndis_req) ndis_ttodo;
                    162: static struct ndisqhead ndis_itodo;
                    163: static struct ndisqhead ndis_free;
                    164: static int ndis_jobs = 32;
                    165:
                    166: static struct ndisproc ndis_tproc;
                    167: static struct ndisproc ndis_iproc;
                    168:
                    169: /*
                    170:  * This allows us to export our symbols to other modules.
                    171:  * Note that we call ourselves 'ndisapi' to avoid a namespace
                    172:  * collision with if_ndis.ko, which internally calls itself
                    173:  * 'ndis.'
                    174:  */
                    175:
1.2       rittera   176: #ifdef __FreeBSD__
1.1       rittera   177: static int
                    178: ndis_modevent(module_t mod, int cmd, void *arg)
                    179: {
                    180:        int                     error = 0;
                    181:        image_patch_table       *patch;
                    182:
                    183:        switch (cmd) {
                    184:        case MOD_LOAD:
                    185:                /* Initialize subsystems */
                    186:                windrv_libinit();
                    187:                hal_libinit();
                    188:                ndis_libinit();
                    189:                ntoskrnl_libinit();
1.3       rittera   190: #ifdef usbimplemented
1.1       rittera   191:                usbd_libinit();
1.3       rittera   192: #endif
1.1       rittera   193:
                    194:                patch = kernndis_functbl;
                    195:                while (patch->ipt_func != NULL) {
                    196:                        windrv_wrap((funcptr)patch->ipt_func,
                    197:                            (funcptr *)&patch->ipt_wrap);
                    198:                        patch++;
                    199:                }
                    200:
                    201:                ndis_create_kthreads();
                    202:
                    203:                TAILQ_INIT(&ndis_devhead);
                    204:
                    205:                break;
                    206:        case MOD_SHUTDOWN:
                    207:                /* stop kthreads */
                    208:                ndis_destroy_kthreads();
                    209:                if (TAILQ_FIRST(&ndis_devhead) == NULL) {
                    210:                        /* Shut down subsystems */
                    211:                        hal_libfini();
                    212:                        ndis_libfini();
                    213:                        ntoskrnl_libfini();
1.3       rittera   214: #ifdef usbimplemented
1.1       rittera   215:                        usbd_libfini();
1.3       rittera   216: #endif
1.1       rittera   217:                        windrv_libfini();
                    218:
                    219:                        patch = kernndis_functbl;
                    220:                        while (patch->ipt_func != NULL) {
                    221:                                windrv_unwrap(patch->ipt_wrap);
                    222:                                patch++;
                    223:                        }
                    224:                }
                    225:                break;
                    226:        case MOD_UNLOAD:
                    227:                /* stop kthreads */
                    228:                ndis_destroy_kthreads();
                    229:
                    230:                /* Shut down subsystems */
                    231:                hal_libfini();
                    232:                ndis_libfini();
                    233:                ntoskrnl_libfini();
                    234:                usbd_libfini();
                    235:                windrv_libfini();
                    236:
                    237:                patch = kernndis_functbl;
                    238:                while (patch->ipt_func != NULL) {
                    239:                        windrv_unwrap(patch->ipt_wrap);
                    240:                        patch++;
                    241:                }
                    242:
                    243:                break;
                    244:        default:
                    245:                error = EINVAL;
                    246:                break;
                    247:        }
                    248:
                    249:        return(error);
                    250: }
                    251: DEV_MODULE(ndisapi, ndis_modevent, NULL);
                    252: MODULE_VERSION(ndisapi, 1);
1.2       rittera   253: #endif
                    254:
1.14.10.1  yamt      255: static int
                    256: ndis_modcmd(modcmd_t cmd, void *arg)
1.2       rittera   257: {
                    258:        int                     error = 0;
                    259:        image_patch_table       *patch;
                    260:
                    261:        switch (cmd) {
1.14.10.1  yamt      262:        case MODULE_CMD_INIT:
1.2       rittera   263:                /* Initialize subsystems */
                    264:                windrv_libinit();
                    265:                hal_libinit();
                    266:                ndis_libinit();
                    267:                ntoskrnl_libinit();
1.3       rittera   268: #ifdef usbimplemented
1.2       rittera   269:                usbd_libinit();
1.3       rittera   270: #endif
1.2       rittera   271:
                    272:                patch = kernndis_functbl;
                    273:                while (patch->ipt_func != NULL) {
                    274:                        windrv_wrap((funcptr)patch->ipt_func,
                    275:                            (funcptr *)&patch->ipt_wrap);
                    276:                        patch++;
                    277:                }
                    278:
                    279:                TAILQ_INIT(&ndis_devhead);
                    280:
1.11      ad        281:                ndis_create_kthreads();
1.2       rittera   282:                break;
1.14.10.1  yamt      283:
                    284:        case MODULE_CMD_FINI:
1.2       rittera   285:                /* stop kthreads */
                    286:                ndis_destroy_kthreads();
                    287:
                    288:                /* Shut down subsystems */
                    289:                hal_libfini();
                    290:                ndis_libfini();
                    291:                ntoskrnl_libfini();
1.3       rittera   292: #ifdef usbimplemented
1.2       rittera   293:                usbd_libfini();
1.3       rittera   294: #endif
1.2       rittera   295:                windrv_libfini();
                    296:
                    297:                patch = kernndis_functbl;
                    298:                while (patch->ipt_func != NULL) {
                    299:                        windrv_unwrap(patch->ipt_wrap);
                    300:                        patch++;
                    301:                }
                    302:
                    303:                break;
1.14.10.1  yamt      304:
1.2       rittera   305:        default:
1.14.10.1  yamt      306:                error = ENOTTY;
1.2       rittera   307:                break;
                    308:        }
                    309:
                    310:        return(error);
                    311: }
                    312:
1.1       rittera   313: /*
                    314:  * We create two kthreads for the NDIS subsystem. One of them is a task
                    315:  * queue for performing various odd jobs. The other is an swi thread
                    316:  * reserved exclusively for running interrupt handlers. The reason we
                    317:  * have our own task queue is that there are some cases where we may
                    318:  * need to sleep for a significant amount of time, and if we were to
                    319:  * use one of the taskqueue threads, we might delay the processing
                    320:  * of other pending tasks which might need to run right away. We have
                    321:  * a separate swi thread because we don't want our interrupt handling
                    322:  * to be delayed either.
                    323:  *
                    324:  * By default there are 32 jobs available to start, and another 8
                    325:  * are added to the free list each time a new device is created.
                    326:  */
1.3       rittera   327:
                    328: /* Just for testing this can be removed later */
                    329: struct ndis_req *_ndis_taskqueue_req;
                    330: struct ndis_req *_ndis_swi_req;
                    331: int calling_in_swi = FALSE;
                    332: int calling_in_tq  = FALSE;
                    333: int num_swi             = 0;
                    334: int num_tq              = 0;
1.1       rittera   335:
                    336: static void
1.14.10.1  yamt      337: ndis_runq(void *arg)
1.1       rittera   338: {
                    339:        struct ndis_req         *r = NULL, *die = NULL;
                    340:        struct ndisproc         *p;
1.3       rittera   341: #ifdef __NetBSD__
                    342:        int old_ipl;
                    343: #endif
1.1       rittera   344:
                    345:        p = arg;
                    346:
                    347:        while (1) {
                    348:
1.3       rittera   349:                /* Protect against interrupts between checking if the queue is empty, and going to sleep
                    350:                 * to avoid a wakeup before sleep.
                    351:                 */
                    352:                old_ipl = splnet();
1.1       rittera   353:                /* Sleep, but preserve our original priority. */
1.3       rittera   354:                if(STAILQ_EMPTY(p->np_q)) {
                    355:                        /* TODO: If we get an interrupt between checking if the queue is empty,
                    356:                         * TODO: and sleeping, then in the interrupt, an item could be placed
                    357:                         * TODO: on the queue, and we could be woken up before we sleep.
                    358:                         *
                    359:                         */
                    360:                        ndis_thsuspend(p->np_p, NULL, 0);
                    361:                }
                    362:                splx(old_ipl);
                    363:
                    364: #ifdef __NetBSD__
                    365:                p->np_needs_wakeup = FALSE;
                    366: #endif
                    367:
1.1       rittera   368:                /* Look for any jobs on the work queue. */
1.3       rittera   369: #ifdef __FreeBSD__
1.1       rittera   370:                mtx_lock_spin(&ndis_thr_mtx);
1.3       rittera   371: #else /* __NetBSD__ */
                    372:                THR_LOCK();
                    373: #endif
                    374:
1.1       rittera   375:                p->np_state = NDIS_PSTATE_RUNNING;
1.3       rittera   376:                while(!STAILQ_EMPTY(p->np_q)/*STAILQ_FIRST(p->np_q) != NULL*/) {
1.1       rittera   377:                        r = STAILQ_FIRST(p->np_q);
1.3       rittera   378:                        STAILQ_REMOVE_HEAD(p->np_q, link);
                    379:
                    380:                        /* for debugging */
                    381:
                    382:                        if(p == &ndis_tproc) {
                    383:                                num_tq++;
                    384:                                _ndis_taskqueue_req = r;
                    385:                                r->area = 1;
                    386:                        } else if(p == &ndis_iproc) {
                    387:                                num_swi++;
                    388:                                _ndis_swi_req = r;
                    389:                                r->area = 2;
                    390:                        }
                    391: #ifdef __FreeBSD__
1.1       rittera   392:                        mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   393: #else /* __NetBSD__ */
                    394:                        THR_UNLOCK();
                    395: #endif
                    396:                        /* Just for debugging */
                    397:
                    398:                        if(p == &ndis_tproc) {
                    399:                                calling_in_tq = TRUE;
                    400:                        } else if(p == &ndis_iproc) {
                    401:                                calling_in_swi     = TRUE;
                    402:                        }
                    403:
1.1       rittera   404:                        /* Do the work. */
                    405:                        if (r->nr_func != NULL)
                    406:                                (*r->nr_func)(r->nr_arg);
1.3       rittera   407:
                    408:                        /* Just for debugging */
                    409:                        if(p == &ndis_tproc) {
                    410:                                calling_in_tq = FALSE;
                    411:                        } else if(p == &ndis_iproc) {
                    412:                                calling_in_swi     = FALSE;
                    413:                        }
1.1       rittera   414:
1.3       rittera   415: #ifdef __FreeBSD__
1.1       rittera   416:                        mtx_lock_spin(&ndis_thr_mtx);
1.3       rittera   417: #else /* __NetBSD__ */
                    418:                        THR_LOCK();
                    419: #endif
                    420:
                    421:                        /* Zeroing out the ndis_req is just for debugging */
                    422:                        //memset(r, 0, sizeof(struct ndis_req));
1.1       rittera   423:                        STAILQ_INSERT_HEAD(&ndis_free, r, link);
1.3       rittera   424:
1.1       rittera   425:                        /* Check for a shutdown request */
                    426:                        if (r->nr_exit == TRUE)
                    427:                                die = r;
                    428:                }
                    429:                p->np_state = NDIS_PSTATE_SLEEPING;
1.3       rittera   430:
                    431: #ifdef __FreeBSD__
1.1       rittera   432:                mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   433: #else /* __NetBSD__ */
                    434:                THR_UNLOCK();
                    435: #endif
1.1       rittera   436:
                    437:                /* Bail if we were told to shut down. */
                    438:
                    439:                if (die != NULL)
                    440:                        break;
                    441:        }
                    442:
                    443:        wakeup(die);
1.2       rittera   444: #ifdef __FreeBSD__
1.1       rittera   445: #if __FreeBSD_version < 502113
                    446:        mtx_lock(&Giant);
                    447: #endif
1.2       rittera   448: #endif
1.3       rittera   449:        if(p == &ndis_tproc) {
                    450:                printf("taskqueue thread exiting!\n");
                    451:        } else if(p == &ndis_iproc) {
                    452:                printf("swi thread exiting!\n");
                    453:        }
1.1       rittera   454:        kthread_exit(0);
                    455:        return; /* notreached */
                    456: }
                    457:
1.3       rittera   458: /*static*/ int
1.14.10.1  yamt      459: ndis_create_kthreads(void)
1.1       rittera   460: {
                    461:        struct ndis_req         *r;
                    462:        int                     i, error = 0;
                    463:
1.3       rittera   464:        printf("in ndis_create_kthreads\n");
                    465:
                    466: #ifdef __FreeBSD__
1.1       rittera   467:        mtx_init(&ndis_thr_mtx, "NDIS thread lock", NULL, MTX_SPIN);
1.3       rittera   468: #else /* __NetBSD__ */
                    469:        simple_lock_init(&ndis_thr_mtx);
1.14.10.2! yamt      470:        //lockinit(&ndis_thr_mtx, PWAIT, "NDIS thread lock", 0, 0);
1.3       rittera   471: #endif
1.1       rittera   472:        mtx_init(&ndis_req_mtx, "NDIS request lock", MTX_NDIS_LOCK, MTX_DEF);
                    473:
                    474:        STAILQ_INIT(&ndis_ttodo);
                    475:        STAILQ_INIT(&ndis_itodo);
                    476:        STAILQ_INIT(&ndis_free);
                    477:
                    478:        for (i = 0; i < ndis_jobs; i++) {
1.3       rittera   479:                r = malloc(sizeof(struct ndis_req), M_DEVBUF, M_WAITOK|M_ZERO);
1.1       rittera   480:                if (r == NULL) {
                    481:                        error = ENOMEM;
                    482:                        break;
                    483:                }
                    484:                STAILQ_INSERT_HEAD(&ndis_free, r, link);
                    485:        }
                    486:
                    487:        if (error == 0) {
                    488:                ndis_tproc.np_q = &ndis_ttodo;
                    489:                ndis_tproc.np_state = NDIS_PSTATE_SLEEPING;
1.2       rittera   490: #ifdef __FreeBSD__
1.1       rittera   491:                error = kthread_create(ndis_runq, &ndis_tproc,
                    492:                    &ndis_tproc.np_p, RFHIGHPID,
                    493:                    NDIS_KSTACK_PAGES, "ndis taskqueue");
1.3       rittera   494: #else /* __NetBSD__ */
                    495:                error = ndis_kthread_create(ndis_runq, &ndis_tproc,
                    496:                    &ndis_tproc.np_p, ndis_tproc.np_stack, PAGE_SIZE*NDIS_KSTACK_PAGES, "ndis taskqueue");
1.2       rittera   497: #endif
1.1       rittera   498:        }
                    499:
                    500:        if (error == 0) {
                    501:                ndis_iproc.np_q = &ndis_itodo;
                    502:                ndis_iproc.np_state = NDIS_PSTATE_SLEEPING;
1.2       rittera   503: #ifdef __FreeBSD__
1.1       rittera   504:                error = kthread_create(ndis_runq, &ndis_iproc,
                    505:                    &ndis_iproc.np_p, RFHIGHPID,
                    506:                    NDIS_KSTACK_PAGES, "ndis swi");
1.2       rittera   507: #else
1.3       rittera   508:                error = ndis_kthread_create(ndis_runq, &ndis_iproc,
                    509:                    &ndis_iproc.np_p, ndis_iproc.np_stack, PAGE_SIZE*NDIS_KSTACK_PAGES, "ndis swi");
1.2       rittera   510: #endif
1.1       rittera   511:        }
                    512:
                    513:        if (error) {
                    514:                while ((r = STAILQ_FIRST(&ndis_free)) != NULL) {
                    515:                        STAILQ_REMOVE_HEAD(&ndis_free, link);
                    516:                        free(r, M_DEVBUF);
                    517:                }
                    518:                return(error);
                    519:        }
                    520:
                    521:        return(0);
                    522: }
                    523:
                    524: static void
1.14.10.1  yamt      525: ndis_destroy_kthreads(void)
1.1       rittera   526: {
                    527:        struct ndis_req         *r;
                    528:
                    529:        /* Stop the threads. */
                    530:
                    531:        ndis_stop_thread(NDIS_TASKQUEUE);
                    532:        ndis_stop_thread(NDIS_SWI);
                    533:
                    534:        /* Destroy request structures. */
                    535:
                    536:        while ((r = STAILQ_FIRST(&ndis_free)) != NULL) {
                    537:                STAILQ_REMOVE_HEAD(&ndis_free, link);
                    538:                free(r, M_DEVBUF);
                    539:        }
                    540:
                    541:        mtx_destroy(&ndis_req_mtx);
1.13      ad        542: #ifndef __NetBSD__
1.1       rittera   543:        mtx_destroy(&ndis_thr_mtx);
1.13      ad        544: #endif
1.1       rittera   545:
                    546:        return;
                    547: }
                    548:
                    549: static void
1.14.10.1  yamt      550: ndis_stop_thread(int t)
1.1       rittera   551: {
                    552:        struct ndis_req         *r;
                    553:        struct ndisqhead        *q;
                    554:        struct proc             *p;
1.3       rittera   555: #ifdef __NetBSD__
                    556:        int old_ipl;
                    557: #endif
1.1       rittera   558:
                    559:        if (t == NDIS_TASKQUEUE) {
                    560:                q = &ndis_ttodo;
                    561:                p = ndis_tproc.np_p;
                    562:        } else {
                    563:                q = &ndis_itodo;
                    564:                p = ndis_iproc.np_p;
                    565:        }
                    566:
                    567:        /* Create and post a special 'exit' job. */
                    568:
1.3       rittera   569: #ifdef __FreeBSD__
1.1       rittera   570:        mtx_lock_spin(&ndis_thr_mtx);
1.3       rittera   571: #else /* __NetBSD__ */
                    572:        THR_LOCK();
                    573: #endif
1.1       rittera   574:        r = STAILQ_FIRST(&ndis_free);
                    575:        STAILQ_REMOVE_HEAD(&ndis_free, link);
                    576:        r->nr_func = NULL;
                    577:        r->nr_arg = NULL;
                    578:        r->nr_exit = TRUE;
1.3       rittera   579:        r->area    = 3;
1.1       rittera   580:        STAILQ_INSERT_TAIL(q, r, link);
1.3       rittera   581: #ifdef __FreeBSD__
1.1       rittera   582:        mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   583: #else /* __NetBSD__ */
                    584:        THR_UNLOCK();
                    585: #endif
1.1       rittera   586:
                    587:        ndis_thresume(p);
                    588:
                    589:        /* wait for thread exit */
                    590:
1.2       rittera   591: #ifdef __FreeBSD__
1.1       rittera   592:        tsleep(r, curthread->td_priority|PCATCH, "ndisthexit", hz * 60);
1.2       rittera   593: #else
                    594:        tsleep(r, curlwp->l_priority|PCATCH, "ndisthexit", hz * 60);
                    595: #endif
1.1       rittera   596:
                    597:        /* Now empty the job list. */
1.3       rittera   598: #ifdef __FreeBSD__
1.1       rittera   599:        mtx_lock_spin(&ndis_thr_mtx);
1.3       rittera   600: #else /* __NetBSD__ */
                    601:        THR_LOCK();
                    602: #endif
1.1       rittera   603:        while ((r = STAILQ_FIRST(q)) != NULL) {
                    604:                STAILQ_REMOVE_HEAD(q, link);
                    605:                STAILQ_INSERT_HEAD(&ndis_free, r, link);
                    606:        }
1.3       rittera   607:
                    608: #ifdef __FreeBSD__
1.1       rittera   609:        mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   610: #else /* __NetBSD__ */
                    611:        THR_UNLOCK();
                    612: #endif
1.1       rittera   613:
                    614:        return;
                    615: }
                    616:
                    617: static int
1.14.10.1  yamt      618: ndis_enlarge_thrqueue(int cnt)
1.1       rittera   619: {
                    620:        struct ndis_req         *r;
                    621:        int                     i;
1.3       rittera   622: #ifdef __NetBSD__
                    623:        int                     old_ipl;
                    624: #endif
1.1       rittera   625:
                    626:        for (i = 0; i < cnt; i++) {
                    627:                r = malloc(sizeof(struct ndis_req), M_DEVBUF, M_WAITOK);
                    628:                if (r == NULL)
                    629:                        return(ENOMEM);
1.3       rittera   630: #ifdef __FreeBSD__
1.1       rittera   631:                mtx_lock_spin(&ndis_thr_mtx);
1.3       rittera   632: #else /* __NetBSD__ */
                    633:                THR_LOCK();
                    634: #endif
1.1       rittera   635:                STAILQ_INSERT_HEAD(&ndis_free, r, link);
                    636:                ndis_jobs++;
1.3       rittera   637: #ifdef __FreeBSD__
1.1       rittera   638:                mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   639: #else /* __NetBSD__ */
                    640:                THR_UNLOCK();
                    641: #endif
1.1       rittera   642:        }
                    643:
                    644:        return(0);
                    645: }
                    646:
                    647: static int
1.14.10.1  yamt      648: ndis_shrink_thrqueue(int cnt)
1.1       rittera   649: {
                    650:        struct ndis_req         *r;
                    651:        int                     i;
1.3       rittera   652: #ifdef __NetBSD__
                    653:        int                     old_ipl;
                    654: #endif
1.1       rittera   655:
                    656:        for (i = 0; i < cnt; i++) {
1.3       rittera   657: #ifdef __FreeBSD__
1.1       rittera   658:                mtx_lock_spin(&ndis_thr_mtx);
1.3       rittera   659: #else /* __NetBSD__ */
                    660:                THR_LOCK();
                    661: #endif
1.1       rittera   662:                r = STAILQ_FIRST(&ndis_free);
                    663:                if (r == NULL) {
1.3       rittera   664: #ifdef __FreeBSD__
1.1       rittera   665:                        mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   666: #else /* __NetBSD__ */
                    667:                        THR_UNLOCK();
                    668: #endif
1.1       rittera   669:                        return(ENOMEM);
                    670:                }
                    671:                STAILQ_REMOVE_HEAD(&ndis_free, link);
                    672:                ndis_jobs--;
1.3       rittera   673: #ifdef __FreeBSD__
1.1       rittera   674:                mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   675: #else /* __NetBSD__ */
                    676:                THR_UNLOCK();
                    677: #endif
                    678:
1.1       rittera   679:                free(r, M_DEVBUF);
                    680:        }
                    681:
                    682:        return(0);
                    683: }
                    684:
                    685: int
1.14.10.1  yamt      686: ndis_unsched(void (*func)(void *), void *arg, int t)
1.1       rittera   687: {
                    688:        struct ndis_req         *r;
                    689:        struct ndisqhead        *q;
                    690:        struct proc             *p;
1.3       rittera   691: #ifdef __NetBSD__
                    692:        int                     old_ipl;
                    693: #endif
1.1       rittera   694:
                    695:        if (t == NDIS_TASKQUEUE) {
                    696:                q = &ndis_ttodo;
                    697:                p = ndis_tproc.np_p;
                    698:        } else {
                    699:                q = &ndis_itodo;
                    700:                p = ndis_iproc.np_p;
                    701:        }
                    702:
1.3       rittera   703: #ifdef __FreeBSD__
1.1       rittera   704:        mtx_lock_spin(&ndis_thr_mtx);
1.3       rittera   705: #else /* __NetBSD__ */
                    706:        THR_LOCK();
                    707: #endif
1.1       rittera   708:        STAILQ_FOREACH(r, q, link) {
                    709:                if (r->nr_func == func && r->nr_arg == arg) {
1.3       rittera   710:                        r->area = 4;
1.1       rittera   711:                        STAILQ_REMOVE(q, r, ndis_req, link);
                    712:                        STAILQ_INSERT_HEAD(&ndis_free, r, link);
1.3       rittera   713: #ifdef __FreeBSD__
1.1       rittera   714:                        mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   715: #else /* __NetBSD__ */
                    716:                        THR_UNLOCK();
                    717: #endif
1.1       rittera   718:                        return(0);
                    719:                }
                    720:        }
1.3       rittera   721: #ifdef __FreeBSD__
1.1       rittera   722:        mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   723: #else /* __NetBSD__ */
                    724:        THR_UNLOCK();
                    725: #endif
1.1       rittera   726:        return(ENOENT);
                    727: }
                    728:
1.3       rittera   729: /* just for testing */
                    730: struct ndis_req *ls_tq_req = NULL;
                    731: struct ndis_req *ls_swi_req = NULL;
                    732:
1.1       rittera   733: int
1.14.10.1  yamt      734: ndis_sched(void (*func)(void *), void *arg, int t)
1.1       rittera   735: {
                    736:        struct ndis_req         *r;
                    737:        struct ndisqhead        *q;
                    738:        struct proc             *p;
                    739:        int                     s;
1.3       rittera   740: #ifdef __NetBSD__
                    741:        int                     old_ipl;
                    742:        /* just for debugging */
                    743:        struct ndis_req         **ls;
                    744:        //struct lwp            *l = curlwp;
                    745: #endif
1.1       rittera   746:
                    747:        if (t == NDIS_TASKQUEUE) {
1.3       rittera   748:                ls = &ls_tq_req;
1.1       rittera   749:                q = &ndis_ttodo;
                    750:                p = ndis_tproc.np_p;
                    751:        } else {
1.3       rittera   752:                ls = &ls_swi_req;
1.1       rittera   753:                q = &ndis_itodo;
                    754:                p = ndis_iproc.np_p;
                    755:        }
                    756:
1.3       rittera   757: #ifdef __FreeBSD__
1.1       rittera   758:        mtx_lock_spin(&ndis_thr_mtx);
1.3       rittera   759: #else /* __NetBSD__ */
                    760:        THR_LOCK();
                    761: #endif
                    762:
1.1       rittera   763:        /*
                    764:         * Check to see if an instance of this job is already
                    765:         * pending. If so, don't bother queuing it again.
                    766:         */
                    767:        STAILQ_FOREACH(r, q, link) {
                    768:                if (r->nr_func == func && r->nr_arg == arg) {
1.3       rittera   769: #ifdef __NetBSD__
                    770:                        if (t == NDIS_TASKQUEUE)
                    771:                                s = ndis_tproc.np_state;
                    772:                        else
                    773:                                s = ndis_iproc.np_state;
                    774: #endif
                    775: #ifdef __FreeBSD__
1.1       rittera   776:                        mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   777: #else /* __NetBSD__ */
                    778:                        THR_UNLOCK();
                    779: #endif
                    780: #ifdef __NetBSD__
                    781:                        /* The swi thread seemed to be going to sleep, and not waking up
                    782:                         * again, so I thought I'd try this out...
                    783:                         */
                    784:                        if (s == NDIS_PSTATE_SLEEPING)
                    785:                                ndis_thresume(p);
                    786: #endif
1.1       rittera   787:                        return(0);
                    788:                }
                    789:        }
                    790:        r = STAILQ_FIRST(&ndis_free);
                    791:        if (r == NULL) {
1.3       rittera   792: #ifdef __FreeBSD__
1.1       rittera   793:                mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   794: #else /* __NetBSD__ */
                    795:                THR_UNLOCK();
                    796: #endif
1.1       rittera   797:                return(EAGAIN);
                    798:        }
                    799:        STAILQ_REMOVE_HEAD(&ndis_free, link);
1.3       rittera   800: #ifdef __NetBSD__
                    801:        //memset(r, 0, sizeof(struct ndis_req));
                    802: #endif
                    803:        *ls = r;
1.1       rittera   804:        r->nr_func = func;
                    805:        r->nr_arg = arg;
                    806:        r->nr_exit = FALSE;
1.3       rittera   807:        r->area    = 5;
1.1       rittera   808:        STAILQ_INSERT_TAIL(q, r, link);
1.3       rittera   809:        if (t == NDIS_TASKQUEUE) {
1.1       rittera   810:                s = ndis_tproc.np_state;
1.3       rittera   811: #ifdef __NetBSD__
                    812:                ndis_tproc.np_needs_wakeup = TRUE;
                    813: #endif
                    814:        } else {
1.1       rittera   815:                s = ndis_iproc.np_state;
1.3       rittera   816: #ifdef __NetBSD__
                    817:                ndis_iproc.np_needs_wakeup = TRUE;
                    818: #endif
                    819:        }
                    820:
                    821: #ifdef __FreeBSD__
1.1       rittera   822:        mtx_unlock_spin(&ndis_thr_mtx);
1.3       rittera   823: #else /* __NetBSD__ */
                    824:        THR_UNLOCK();
                    825: #endif
1.1       rittera   826:
                    827:        /*
                    828:         * Post the job, but only if the thread is actually blocked
                    829:         * on its own suspend call. If a driver queues up a job with
                    830:         * NdisScheduleWorkItem() which happens to do a KeWaitForObject(),
                    831:         * it may suspend there, and in that case we don't want to wake
                    832:         * it up until KeWaitForObject() gets woken up on its own.
                    833:         */
1.3       rittera   834:        if (s == NDIS_PSTATE_SLEEPING) {
1.1       rittera   835:                ndis_thresume(p);
1.3       rittera   836:        }
1.1       rittera   837:
                    838:        return(0);
                    839: }
                    840:
1.3       rittera   841: /* Try out writing my own version of ndis_sched() for NetBSD in which I just
                    842:  * call the function instead of scheduling it.  I know this isn't
                    843:  * what's supposed to be done, but I've been having a lot of problems
                    844:  * with the SWI and taskqueue threads, and just thought I'd give this
                    845:  * a try.
                    846:  */
                    847:
                    848:  /* I don't think this will work, because it means that DPC's will be
                    849:   * called from the bottom half of the kernel, so they won't be able
                    850:   * to sleep using KeWaitForSingleObject.
                    851:   */
                    852:  /*
                    853:  int
1.14.10.1  yamt      854: ndis_sched(void (*func)(void *), void *arg, int t)
1.3       rittera   855: {
                    856:        if(func != NULL) {
                    857:                (*func)(arg);
                    858:        }
                    859:
                    860:        return 0;
                    861: }
                    862: */
                    863:
1.1       rittera   864: int
                    865: ndis_thsuspend(p, m, timo)
                    866:        struct proc             *p;
1.3       rittera   867: #ifdef __FreeBSD__
1.1       rittera   868:        struct mtx              *m;
1.3       rittera   869: #else /* __NetBSD__*/
                    870:        struct simplelock       *m;
                    871: #endif
1.1       rittera   872:        int                     timo;
                    873: {
                    874:        int                     error;
                    875:
1.2       rittera   876: #ifdef __FreeBSD__
1.1       rittera   877:        if (m != NULL) {
                    878:                error = msleep(&p->p_siglist, m,
                    879:                    curthread->td_priority, "ndissp", timo);
                    880:        } else {
                    881:                PROC_LOCK(p);
                    882:                error = msleep(&p->p_siglist, &p->p_mtx,
                    883:                    curthread->td_priority|PDROP, "ndissp", timo);
                    884:        }
1.2       rittera   885: #else
1.3       rittera   886: /* TODO: Why do they wait on &p->p_siglist?  I noticed that in FreeBSD's
                    887:  * src/sys/sys/proc.h there is some mention of p_siglist having to do with
                    888:  * M:N threading.
                    889:  */
                    890:        if (m != NULL) {
                    891:                //mtx_unlock(m);
1.9       ad        892:                error = ltsleep(&p->p_sigpend.sp_set, curlwp->l_priority,
1.3       rittera   893:                                "ndissp", timo, m);
                    894:                //mtx_lock(m);
                    895:        } else {
1.9       ad        896:                error = ltsleep(&p->p_sigpend.sp_set, curlwp->l_priority/*|PNORELOCK*/,
1.3       rittera   897:                                "ndissp", timo, 0 /*&p->p_lock*/);
                    898:        }
                    899:
1.2       rittera   900: #endif
1.1       rittera   901:
                    902:        return(error);
                    903: }
                    904:
                    905: void
1.14.10.1  yamt      906: ndis_thresume(struct proc *p)
1.1       rittera   907: {
1.9       ad        908:        wakeup(&p->p_sigpend.sp_set);
1.3       rittera   909:
1.1       rittera   910:        return;
                    911: }
                    912:
                    913: __stdcall static void
1.7       christos  914: ndis_sendrsrcavail_func(ndis_handle adapter)
1.1       rittera   915: {
                    916:        return;
                    917: }
                    918:
                    919: __stdcall static void
1.7       christos  920: ndis_status_func(ndis_handle adapter, ndis_status status, void *sbuf,
                    921:     uint32_t slen)
1.1       rittera   922: {
                    923:        ndis_miniport_block     *block;
                    924:        struct ndis_softc       *sc;
                    925:        struct ifnet            *ifp;
                    926:
                    927:        block = adapter;
1.3       rittera   928: #ifdef __FreeBSD__
1.1       rittera   929:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera   930: #else /* __NetBSD__ */
                    931:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                    932: #endif
                    933:
1.2       rittera   934: #ifdef __FreeBSD__
1.1       rittera   935:        ifp = &sc->arpcom.ac_if;
1.2       rittera   936: #else
                    937:        ifp = &sc->arpcom.ec_if;
                    938: #endif
1.1       rittera   939:        if (ifp->if_flags & IFF_DEBUG)
1.4       rittera   940:                printf("%s: status: %x\n",
1.14.10.2! yamt      941:                       device_xname(sc->ndis_dev), status);
1.1       rittera   942:        return;
                    943: }
                    944:
                    945: __stdcall static void
1.14.10.1  yamt      946: ndis_statusdone_func(ndis_handle adapter)
1.1       rittera   947: {
                    948:        ndis_miniport_block     *block;
                    949:        struct ndis_softc       *sc;
                    950:        struct ifnet            *ifp;
                    951:
                    952:        block = adapter;
1.3       rittera   953: #ifdef __FreeBSD__
1.1       rittera   954:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera   955: #else /* __NetBSD__ */
                    956:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                    957: #endif
                    958:
1.2       rittera   959: #ifdef __FreeBSD__
1.1       rittera   960:        ifp = &sc->arpcom.ac_if;
1.2       rittera   961: #else
                    962:        ifp = &sc->arpcom.ec_if;
                    963: #endif
1.1       rittera   964:        if (ifp->if_flags & IFF_DEBUG)
1.4       rittera   965:                printf("%s: status complete\n",
1.14.10.2! yamt      966:                       device_xname(sc->ndis_dev));
1.1       rittera   967:        return;
                    968: }
                    969:
                    970: __stdcall static void
1.14.10.1  yamt      971: ndis_setdone_func(ndis_handle adapter, ndis_status status)
1.1       rittera   972: {
                    973:        ndis_miniport_block     *block;
                    974:        block = adapter;
                    975:
                    976:        block->nmb_setstat = status;
                    977:        wakeup(&block->nmb_setstat);
                    978:        return;
                    979: }
                    980:
                    981: __stdcall static void
1.14.10.1  yamt      982: ndis_getdone_func(ndis_handle adapter, ndis_status status)
1.1       rittera   983: {
                    984:        ndis_miniport_block     *block;
                    985:        block = adapter;
                    986:
                    987:        block->nmb_getstat = status;
                    988:        wakeup(&block->nmb_getstat);
                    989:        return;
                    990: }
                    991:
                    992: __stdcall static void
1.7       christos  993: ndis_resetdone_func(ndis_handle adapter, ndis_status status,
                    994:     uint8_t addressingreset)
1.1       rittera   995: {
                    996:        ndis_miniport_block     *block;
                    997:        struct ndis_softc       *sc;
                    998:        struct ifnet            *ifp;
                    999:
                   1000:        block = adapter;
1.3       rittera  1001: #ifdef __FreeBSD__
1.1       rittera  1002:        sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3       rittera  1003: #else /* __NetBSD__ */
                   1004:        sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
                   1005: #endif
                   1006:
1.2       rittera  1007: #ifdef __FreeBSD__
1.1       rittera  1008:        ifp = &sc->arpcom.ac_if;
1.2       rittera  1009: #else
                   1010:        ifp = &sc->arpcom.ec_if;
                   1011: #endif
1.1       rittera  1012:
                   1013:        if (ifp->if_flags & IFF_DEBUG)
1.4       rittera  1014:                printf("%s: reset done...\n",
1.14.10.2! yamt     1015:                       device_xname(sc->ndis_dev));
1.1       rittera  1016:        wakeup(sc);
                   1017:        return;
                   1018: }
                   1019:
1.3       rittera  1020: #ifdef __FreeBSD__
                   1021: /* FreeBSD version of ndis_create_sysctls() */
1.1       rittera  1022: int
1.14.10.1  yamt     1023: ndis_create_sysctls(void *arg)
1.1       rittera  1024: {
                   1025:        struct ndis_softc       *sc;
                   1026:        ndis_cfg                *vals;
                   1027:        char                    buf[256];
                   1028:        struct sysctl_oid       *oidp;
                   1029:        struct sysctl_ctx_entry *e;
                   1030:
                   1031:        if (arg == NULL)
                   1032:                return(EINVAL);
                   1033:
                   1034:        sc = arg;
                   1035:        vals = sc->ndis_regvals;
                   1036:
                   1037:        TAILQ_INIT(&sc->ndis_cfglist_head);
                   1038:
                   1039: #if __FreeBSD_version < 502113
                   1040:        /* Create the sysctl tree. */
                   1041:
                   1042:        sc->ndis_tree = SYSCTL_ADD_NODE(&sc->ndis_ctx,
                   1043:            SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
                   1044:            device_get_nameunit(sc->ndis_dev), CTLFLAG_RD, 0,
                   1045:            device_get_desc(sc->ndis_dev));
                   1046:
                   1047: #endif
                   1048:        /* Add the driver-specific registry keys. */
                   1049:
                   1050:        vals = sc->ndis_regvals;
                   1051:        while(1) {
                   1052:                if (vals->nc_cfgkey == NULL)
                   1053:                        break;
                   1054:                if (vals->nc_idx != sc->ndis_devidx) {
                   1055:                        vals++;
                   1056:                        continue;
                   1057:                }
                   1058:
                   1059:                /* See if we already have a sysctl with this name */
                   1060:
                   1061:                oidp = NULL;
                   1062: #if __FreeBSD_version < 502113
                   1063:                TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
                   1064: #else
                   1065:                TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
                   1066: #endif
                   1067:                        oidp = e->entry;
                   1068:                        if (ndis_strcasecmp(oidp->oid_name,
                   1069:                            vals->nc_cfgkey) == 0)
                   1070:                                break;
                   1071:                        oidp = NULL;
                   1072:                }
                   1073:
                   1074:                if (oidp != NULL) {
                   1075:                        vals++;
                   1076:                        continue;
                   1077:                }
                   1078:
                   1079: #if __FreeBSD_version < 502113
                   1080:                SYSCTL_ADD_STRING(&sc->ndis_ctx,
                   1081:                    SYSCTL_CHILDREN(sc->ndis_tree),
                   1082: #else
                   1083:                SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev),
                   1084:                    SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)),
                   1085: #endif
                   1086:                    OID_AUTO, vals->nc_cfgkey,
                   1087:                    CTLFLAG_RW, vals->nc_val,
                   1088:                    sizeof(vals->nc_val),
                   1089:                    vals->nc_cfgdesc);
                   1090:                vals++;
                   1091:        }
                   1092:
                   1093:        /* Now add a couple of builtin keys. */
                   1094:
                   1095:        /*
                   1096:         * Environment can be either Windows (0) or WindowsNT (1).
                   1097:         * We qualify as the latter.
                   1098:         */
                   1099:        ndis_add_sysctl(sc, "Environment",
                   1100:            "Windows environment", "1", CTLFLAG_RD);
                   1101:
                   1102:        /* NDIS version should be 5.1. */
                   1103:        ndis_add_sysctl(sc, "NdisVersion",
                   1104:            "NDIS API Version", "0x00050001", CTLFLAG_RD);
                   1105:
                   1106:        /* Bus type (PCI, PCMCIA, etc...) */
                   1107:        sprintf(buf, "%d", (int)sc->ndis_iftype);
                   1108:        ndis_add_sysctl(sc, "BusType", "Bus Type", buf, CTLFLAG_RD);
                   1109:
                   1110:        if (sc->ndis_res_io != NULL) {
                   1111:                sprintf(buf, "0x%lx", rman_get_start(sc->ndis_res_io));
                   1112:                ndis_add_sysctl(sc, "IOBaseAddress",
                   1113:                    "Base I/O Address", buf, CTLFLAG_RD);
                   1114:        }
                   1115:
                   1116:        if (sc->ndis_irq != NULL) {
                   1117:                sprintf(buf, "%lu", rman_get_start(sc->ndis_irq));
                   1118:                ndis_add_sysctl(sc, "InterruptNumber",
                   1119:                    "Interrupt Number", buf, CTLFLAG_RD);
                   1120:        }
                   1121:
1.3       rittera  1122:        return(0);
                   1123: }
1.2       rittera  1124: #endif /* __FreeBSD__ */
1.3       rittera  1125:
                   1126: #ifdef __NetBSD__
                   1127: /* NetBSD version of ndis_create_sysctls() */
                   1128: int
1.14.10.1  yamt     1129: ndis_create_sysctls(void *arg)
1.3       rittera  1130: {
                   1131:        struct ndis_softc       *sc;
                   1132:        ndis_cfg                *vals;
                   1133:        const struct sysctlnode *ndis_node;
                   1134:        char buf[256];
                   1135:
                   1136:        printf("in ndis_create_sysctls()\n");
                   1137:
                   1138:        if (arg == NULL)
                   1139:                return(EINVAL);
                   1140:
                   1141:        sc = arg;
                   1142:        vals = sc->ndis_regvals;
                   1143:
                   1144:        TAILQ_INIT(&sc->ndis_cfglist_head);
                   1145:
                   1146:        /* Create the sysctl tree. */
                   1147:        sysctl_createv(&sc->sysctllog, 0, NULL, &ndis_node, CTLFLAG_READWRITE, CTLTYPE_NODE,
1.14.10.2! yamt     1148:                                        device_xname(sc->ndis_dev), NULL, NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL);
1.3       rittera  1149:
                   1150:        /* Store the number of the ndis mib */
                   1151:        sc->ndis_sysctl_mib = ndis_node->sysctl_num;
                   1152:
                   1153:        /* Add the driver-specific registry keys. */
                   1154:        vals = sc->ndis_regvals;
                   1155:        while(1) {
                   1156:                if (vals->nc_cfgkey == NULL)
                   1157:                        break;
                   1158:                if (vals->nc_idx != sc->ndis_devidx) {
                   1159:                        vals++;
                   1160:                        continue;
                   1161:                }
                   1162:
                   1163:                /* See if we already have a sysctl with this name */
1.14      skrll    1164: /* TODO: Is something like this necessary in NetBSD?  I'm guessing this
1.3       rittera  1165:    TODO: is just checking if any of the information in the .inf file was
                   1166:    TODO: already determined by FreeBSD's autoconfiguration which seems to
                   1167:    TODO: add dev.XXX sysctl's beginning with %.  (NetBSD dosen't seem to do this).
                   1168: */
                   1169:
                   1170: /* TODO: use CTLFLAG_OWNDATA or not? */
                   1171:                   /*
                   1172:                sysctl_createv(&sc->sysctllog, 0, NULL, NULL,
                   1173:                                                CTLFLAG_READWRITE|CTLFLAG_OWNDESC|CTLFLAG_OWNDATA, CTLTYPE_STRING,
                   1174:                                                vals->nc_cfgkey, vals->nc_cfgdesc, NULL, 0, vals->nc_val, strlen(vals->nc_val),
                   1175:                                            ndis_node->sysctl_num, CTL_CREATE, CTL_EOL);
                   1176:                   */
                   1177:                   ndis_add_sysctl(sc, vals->nc_cfgkey,
                   1178:                                                   vals->nc_cfgdesc, vals->nc_val, CTLFLAG_READWRITE);
                   1179:
                   1180:                vals++;
                   1181:        } /* end while */
                   1182:
                   1183:                /* Now add a couple of builtin keys. */
                   1184:
                   1185:        /*
                   1186:         * Environment can be either Windows (0) or WindowsNT (1).
                   1187:         * We qualify as the latter.
                   1188:         */
                   1189: #ifdef __NetBSD__
                   1190: #define CTLFLAG_RD CTLFLAG_READONLY
                   1191: /* TODO: do we need something like rman_get_start? */
                   1192: #define rman_get_start(x) x
                   1193: #endif
                   1194:                ndis_add_sysctl(sc, "Environment",
                   1195:                                                "Windows environment", "1", CTLFLAG_RD);
                   1196:
                   1197:                /* NDIS version should be 5.1. */
                   1198:                ndis_add_sysctl(sc, "NdisVersion",
                   1199:                                                /*"NDIS API Version"*/ "Version", "0x00050001", CTLFLAG_RD);
                   1200:
                   1201:                /* Bus type (PCI, PCMCIA, etc...) */
                   1202:                sprintf(buf, "%d", (int)sc->ndis_iftype);
                   1203:                ndis_add_sysctl(sc, "BusType", "Bus Type", buf, CTLFLAG_RD);
                   1204:
                   1205:                if (sc->ndis_res_io != NULL) {
                   1206:                        sprintf(buf, "0x%lx", (long unsigned int)rman_get_start(sc->ndis_res_io));
                   1207:                        ndis_add_sysctl(sc, "IOBaseAddress",
                   1208:                                                        /*"Base I/O Address"*/ "Base I/O", buf, CTLFLAG_RD);
                   1209:                }
                   1210:
                   1211:                if (sc->ndis_irq != NULL) {
                   1212:                        sprintf(buf, "%lu", (long unsigned int)rman_get_start(sc->ndis_irq));
                   1213:                        ndis_add_sysctl(sc, "InterruptNumber",
                   1214:                                                        "Interrupt Number", buf, CTLFLAG_RD);
                   1215:                }
                   1216:
                   1217:                return(0);
                   1218: }
                   1219: #endif /* __NetBSD__ */
                   1220:
                   1221: char *ndis_strdup(const char *src);
                   1222:
                   1223: char *ndis_strdup(const char *src)
                   1224: {
                   1225:        char *ret;
                   1226:
                   1227:        ret = malloc(strlen(src), M_DEVBUF, M_NOWAIT|M_ZERO);
                   1228:        if (ret == NULL) {
                   1229:                printf("ndis_strdup failed\n");
                   1230:                return(NULL);
                   1231:        }
                   1232:        strcpy(ret, src);
                   1233:
                   1234:        return ret;
1.1       rittera  1235: }
                   1236:
                   1237: int
1.14.10.1  yamt     1238: ndis_add_sysctl(void *arg, const char *key, const char *desc, const char *val, int flag)
1.1       rittera  1239: {
                   1240:        struct ndis_softc       *sc;
                   1241:        struct ndis_cfglist     *cfg;
                   1242:        char                    descstr[256];
1.3       rittera  1243: #ifdef __NetBSD__
                   1244:        char newkey[MAX_SYSCTL_LEN+1];
                   1245: #endif
1.1       rittera  1246:
                   1247:        sc = arg;
                   1248:
                   1249:        cfg = malloc(sizeof(struct ndis_cfglist), M_DEVBUF, M_NOWAIT|M_ZERO);
                   1250:
                   1251:        if (cfg == NULL)
                   1252:                return(ENOMEM);
                   1253:
1.3       rittera  1254:        /* I added this because NetBSD sysctl node names can't begin with
                   1255:         * a digit.
                   1256:         */
                   1257: #ifdef __NetBSD__
                   1258:        if(strlen(key) + strlen("ndis_") > MAX_SYSCTL_LEN) {
                   1259:                panic("sysctl name too long: %s\n", key);
                   1260:        }
                   1261:        strcpy(newkey, "ndis_");
                   1262:        strcpy(newkey + strlen("ndis_"), key);
                   1263:        key = newkey;
                   1264: #endif
                   1265:
                   1266:        cfg->ndis_cfg.nc_cfgkey = ndis_strdup(key);
                   1267:
1.1       rittera  1268:        if (desc == NULL) {
                   1269:                snprintf(descstr, sizeof(descstr), "%s (dynamic)", key);
1.3       rittera  1270:                cfg->ndis_cfg.nc_cfgdesc = ndis_strdup(descstr);
1.1       rittera  1271:        } else
1.3       rittera  1272:                cfg->ndis_cfg.nc_cfgdesc = ndis_strdup(desc);
1.1       rittera  1273:        strcpy(cfg->ndis_cfg.nc_val, val);
                   1274:
                   1275:        TAILQ_INSERT_TAIL(&sc->ndis_cfglist_head, cfg, link);
                   1276:
1.3       rittera  1277: #ifdef __FreeBSD__
1.1       rittera  1278: #if __FreeBSD_version < 502113
                   1279:        SYSCTL_ADD_STRING(&sc->ndis_ctx, SYSCTL_CHILDREN(sc->ndis_tree),
                   1280: #else
                   1281:        SYSCTL_ADD_STRING(device_get_sysctl_ctx(sc->ndis_dev),
                   1282:            SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ndis_dev)),
                   1283: #endif
                   1284:            OID_AUTO, cfg->ndis_cfg.nc_cfgkey, flag,
                   1285:            cfg->ndis_cfg.nc_val, sizeof(cfg->ndis_cfg.nc_val),
                   1286:            cfg->ndis_cfg.nc_cfgdesc);
1.3       rittera  1287: #else /* __NetBSD__ */
                   1288: /* TODO: use CTLFLAG_OWNDATA or not? */
                   1289:        sysctl_createv(&sc->sysctllog, 0, NULL, NULL, flag/*|CTLFLAG_OWNDESC|CTLFLAG_OWNDATA*/, CTLTYPE_STRING,
                   1290:                                        cfg->ndis_cfg.nc_cfgkey, cfg->ndis_cfg.nc_cfgdesc, NULL, 0, cfg->ndis_cfg.nc_val,
                   1291:                                        strlen(cfg->ndis_cfg.nc_val), sc->ndis_sysctl_mib, CTL_CREATE, CTL_EOL);
                   1292: #endif
1.1       rittera  1293:        return(0);
                   1294: }
                   1295:
                   1296: int
1.14.10.1  yamt     1297: ndis_flush_sysctls(void *arg)
1.1       rittera  1298: {
                   1299:        struct ndis_softc       *sc;
                   1300:        struct ndis_cfglist     *cfg;
                   1301:
                   1302:        sc = arg;
                   1303:
                   1304:        while (!TAILQ_EMPTY(&sc->ndis_cfglist_head)) {
                   1305:                cfg = TAILQ_FIRST(&sc->ndis_cfglist_head);
                   1306:                TAILQ_REMOVE(&sc->ndis_cfglist_head, cfg, link);
1.3       rittera  1307: #ifdef __FreeBSD__
1.1       rittera  1308:                free(cfg->ndis_cfg.nc_cfgkey, M_DEVBUF);
                   1309:                free(cfg->ndis_cfg.nc_cfgdesc, M_DEVBUF);
1.3       rittera  1310: #endif
1.1       rittera  1311:                free(cfg, M_DEVBUF);
                   1312:        }
                   1313:
                   1314:        return(0);
                   1315: }
                   1316:
                   1317: static void
1.14.10.1  yamt     1318: ndis_return(void *arg)
1.1       rittera  1319: {
                   1320:        struct ndis_softc       *sc;
                   1321:        __stdcall ndis_return_handler   returnfunc;
                   1322:        ndis_handle             adapter;
                   1323:        ndis_packet             *p;
1.5       christos 1324:        uint8_t                 irql = 0;       /* XXX: gcc */
1.1       rittera  1325:
                   1326:        p = arg;
                   1327:        sc = p->np_softc;
                   1328:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   1329:
                   1330:        if (adapter == NULL)
                   1331:                return;
                   1332:
                   1333:        returnfunc = sc->ndis_chars->nmc_return_packet_func;
                   1334:
                   1335:        KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
                   1336:        MSCALL2(returnfunc, adapter, p);
                   1337:        KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
                   1338:
                   1339:        return;
                   1340: }
                   1341:
                   1342: void
1.3       rittera  1343: #ifdef __FreeBSD__
1.1       rittera  1344: ndis_return_packet(buf, arg)
                   1345:        void                    *buf;   /* not used */
                   1346:        void                    *arg;
1.3       rittera  1347: #else
1.10      christos 1348: ndis_return_packet(struct mbuf *m, void *buf,
1.7       christos 1349:     size_t size, void *arg)
1.3       rittera  1350: #endif
                   1351:
1.1       rittera  1352: {
                   1353:        ndis_packet             *p;
                   1354:
                   1355:        if (arg == NULL)
                   1356:                return;
                   1357:
                   1358:        p = arg;
                   1359:
                   1360:        /* Decrement refcount. */
                   1361:        p->np_refcnt--;
                   1362:
                   1363:        /* Release packet when refcount hits zero, otherwise return. */
                   1364:        if (p->np_refcnt)
                   1365:                return;
                   1366:
                   1367:        ndis_sched(ndis_return, p, NDIS_TASKQUEUE);
                   1368:
                   1369:        return;
                   1370: }
                   1371:
                   1372: void
1.14.10.1  yamt     1373: ndis_free_bufs(ndis_buffer *b0)
1.1       rittera  1374: {
                   1375:        ndis_buffer             *next;
                   1376:
                   1377:        if (b0 == NULL)
                   1378:                return;
                   1379:
                   1380:        while(b0 != NULL) {
                   1381:                next = b0->mdl_next;
                   1382:                IoFreeMdl(b0);
                   1383:                b0 = next;
                   1384:        }
                   1385:
                   1386:        return;
                   1387: }
                   1388: int in_reset = 0;
                   1389: void
1.14.10.1  yamt     1390: ndis_free_packet(ndis_packet *p)
1.1       rittera  1391: {
                   1392:        if (p == NULL)
                   1393:                return;
                   1394:
                   1395:        ndis_free_bufs(p->np_private.npp_head);
                   1396:        NdisFreePacket(p);
                   1397:        return;
                   1398: }
                   1399:
1.3       rittera  1400: #ifdef __FreeBSD__
1.1       rittera  1401: int
1.14.10.1  yamt     1402: ndis_convert_res(void *arg)
1.1       rittera  1403: {
                   1404:        struct ndis_softc       *sc;
                   1405:        ndis_resource_list      *rl = NULL;
                   1406:        cm_partial_resource_desc        *prd = NULL;
                   1407:        ndis_miniport_block     *block;
                   1408:        device_t                dev;
                   1409:        struct resource_list    *brl;
                   1410:        struct resource_list_entry      *brle;
                   1411: #if __FreeBSD_version < 600022
                   1412:        struct resource_list    brl_rev;
                   1413:        struct resource_list_entry      *n;
                   1414: #endif
                   1415:        int                     error = 0;
                   1416:
                   1417:        sc = arg;
                   1418:        block = sc->ndis_block;
                   1419:        dev = sc->ndis_dev;
                   1420:
                   1421: #if __FreeBSD_version < 600022
                   1422:        SLIST_INIT(&brl_rev);
                   1423: #endif
                   1424:        rl = malloc(sizeof(ndis_resource_list) +
                   1425:            (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1)),
                   1426:            M_DEVBUF, M_NOWAIT|M_ZERO);
                   1427:
                   1428:        if (rl == NULL)
                   1429:                return(ENOMEM);
                   1430:
                   1431:        rl->cprl_version = 5;
                   1432:        rl->cprl_version = 1;
                   1433:        rl->cprl_count = sc->ndis_rescnt;
                   1434:        prd = rl->cprl_partial_descs;
                   1435:
                   1436:        brl = BUS_GET_RESOURCE_LIST(dev, dev);
                   1437:
                   1438:        if (brl != NULL) {
                   1439:
                   1440: #if __FreeBSD_version < 600022
                   1441:                /*
                   1442:                 * We have a small problem. Some PCI devices have
                   1443:                 * multiple I/O ranges. Windows orders them starting
                   1444:                 * from lowest numbered BAR to highest. We discover
                   1445:                 * them in that order too, but insert them into a singly
                   1446:                 * linked list head first, which means when time comes
                   1447:                 * to traverse the list, we enumerate them in reverse
                   1448:                 * order. This screws up some drivers which expect the
                   1449:                 * BARs to be in ascending order so that they can choose
                   1450:                 * the "first" one as their register space. Unfortunately,
                   1451:                 * in order to fix this, we have to create our own
                   1452:                 * temporary list with the entries in reverse order.
                   1453:                 */
                   1454:                SLIST_FOREACH(brle, brl, link) {
                   1455:                        n = malloc(sizeof(struct resource_list_entry),
                   1456:                            M_TEMP, M_NOWAIT);
                   1457:                        if (n == NULL) {
                   1458:                                error = ENOMEM;
                   1459:                                goto bad;
                   1460:                        }
1.14.10.1  yamt     1461:                        memcpy( (char *)n, (char *)brle,
1.1       rittera  1462:                            sizeof(struct resource_list_entry));
                   1463:                        SLIST_INSERT_HEAD(&brl_rev, n, link);
                   1464:                }
                   1465:
                   1466:                SLIST_FOREACH(brle, &brl_rev, link) {
                   1467: #else
                   1468:                STAILQ_FOREACH(brle, brl, link) {
                   1469: #endif
                   1470:                        switch (brle->type) {
                   1471:                        case SYS_RES_IOPORT:
                   1472:                                prd->cprd_type = CmResourceTypePort;
                   1473:                                prd->cprd_flags = CM_RESOURCE_PORT_IO;
                   1474:                                prd->cprd_sharedisp =
                   1475:                                    CmResourceShareDeviceExclusive;
                   1476:                                prd->u.cprd_port.cprd_start.np_quad =
                   1477:                                    brle->start;
                   1478:                                prd->u.cprd_port.cprd_len = brle->count;
                   1479:                                break;
                   1480:                        case SYS_RES_MEMORY:
                   1481:                                prd->cprd_type = CmResourceTypeMemory;
                   1482:                                prd->cprd_flags =
                   1483:                                    CM_RESOURCE_MEMORY_READ_WRITE;
                   1484:                                prd->cprd_sharedisp =
                   1485:                                    CmResourceShareDeviceExclusive;
                   1486:                                prd->u.cprd_port.cprd_start.np_quad =
                   1487:                                    brle->start;
                   1488:                                prd->u.cprd_port.cprd_len = brle->count;
                   1489:                                break;
                   1490:                        case SYS_RES_IRQ:
                   1491:                                prd->cprd_type = CmResourceTypeInterrupt;
                   1492:                                prd->cprd_flags = 0;
                   1493:                                prd->cprd_sharedisp =
                   1494:                                    CmResourceShareDeviceExclusive;
                   1495:                                prd->u.cprd_intr.cprd_level = brle->start;
                   1496:                                prd->u.cprd_intr.cprd_vector = brle->start;
                   1497:                                prd->u.cprd_intr.cprd_affinity = 0;
                   1498:                                break;
                   1499:                        default:
                   1500:                                break;
                   1501:                        }
                   1502:                        prd++;
                   1503:                }
                   1504:        }
                   1505:
                   1506:        block->nmb_rlist = rl;
                   1507:
                   1508: #if __FreeBSD_version < 600022
                   1509: bad:
                   1510:
                   1511:        while (!SLIST_EMPTY(&brl_rev)) {
                   1512:                n = SLIST_FIRST(&brl_rev);
                   1513:                SLIST_REMOVE_HEAD(&brl_rev, link);
                   1514:                free (n, M_TEMP);
                   1515:        }
                   1516: #endif
                   1517:
                   1518:        return(error);
                   1519: }
1.3       rittera  1520: #endif /* __FreeBSD__ */
1.1       rittera  1521: /*
                   1522:  * Map an NDIS packet to an mbuf list. When an NDIS driver receives a
                   1523:  * packet, it will hand it to us in the form of an ndis_packet,
                   1524:  * which we need to convert to an mbuf that is then handed off
                   1525:  * to the stack. Note: we configure the mbuf list so that it uses
                   1526:  * the memory regions specified by the ndis_buffer structures in
                   1527:  * the ndis_packet as external storage. In most cases, this will
                   1528:  * point to a memory region allocated by the driver (either by
                   1529:  * ndis_malloc_withtag() or ndis_alloc_sharedmem()). We expect
                   1530:  * the driver to handle free()ing this region for is, so we set up
                   1531:  * a dummy no-op free handler for it.
                   1532:  */
                   1533:
                   1534: int
1.14.10.1  yamt     1535: ndis_ptom(struct mbuf **m0, ndis_packet *p)
1.1       rittera  1536: {
                   1537:        struct mbuf             *m, *prev = NULL;
                   1538:        ndis_buffer             *buf;
                   1539:        ndis_packet_private     *priv;
                   1540:        uint32_t                totlen = 0;
                   1541:
                   1542:        if (p == NULL || m0 == NULL)
                   1543:                return(EINVAL);
                   1544:
                   1545:        priv = &p->np_private;
                   1546:        buf = priv->npp_head;
                   1547:        p->np_refcnt = 0;
                   1548:
                   1549:        for (buf = priv->npp_head; buf != NULL; buf = buf->mdl_next) {
                   1550:                if (buf == priv->npp_head)
                   1551:                        MGETHDR(m, M_DONTWAIT, MT_HEADER);
                   1552:                else
                   1553:                        MGET(m, M_DONTWAIT, MT_DATA);
                   1554:                if (m == NULL) {
                   1555:                        m_freem(*m0);
                   1556:                        *m0 = NULL;
                   1557:                        return(ENOBUFS);
                   1558:                }
                   1559:                m->m_len = MmGetMdlByteCount(buf);
                   1560:                m->m_data = MmGetMdlVirtualAddress(buf);
1.3       rittera  1561: #ifdef __FreeBSD__
1.1       rittera  1562:                MEXTADD(m, m->m_data, m->m_len, ndis_return_packet,
1.3       rittera  1563:                        p, 0, EXT_NDIS);
                   1564: #else
                   1565:                MEXTADD(m, m->m_data, m->m_len, M_DEVBUF,
                   1566:                        ndis_return_packet, p);
                   1567: #endif
1.1       rittera  1568:                p->np_refcnt++;
                   1569:                totlen += m->m_len;
                   1570:                if (m->m_flags & MT_HEADER)
                   1571:                        *m0 = m;
                   1572:                else
                   1573:                        prev->m_next = m;
                   1574:                prev = m;
                   1575:        }
                   1576:
                   1577:        (*m0)->m_pkthdr.len = totlen;
                   1578:
                   1579:        return(0);
                   1580: }
                   1581:
                   1582: /*
                   1583:  * Create an NDIS packet from an mbuf chain.
                   1584:  * This is used mainly when transmitting packets, where we need
                   1585:  * to turn an mbuf off an interface's send queue and transform it
                   1586:  * into an NDIS packet which will be fed into the NDIS driver's
                   1587:  * send routine.
                   1588:  *
                   1589:  * NDIS packets consist of two parts: an ndis_packet structure,
                   1590:  * which is vaguely analagous to the pkthdr portion of an mbuf,
                   1591:  * and one or more ndis_buffer structures, which define the
                   1592:  * actual memory segments in which the packet data resides.
                   1593:  * We need to allocate one ndis_buffer for each mbuf in a chain,
                   1594:  * plus one ndis_packet as the header.
                   1595:  */
                   1596:
                   1597: int
1.14.10.1  yamt     1598: ndis_mtop(struct mbuf *m0, ndis_packet **p)
1.1       rittera  1599: {
                   1600:        struct mbuf             *m;
                   1601:        ndis_buffer             *buf = NULL, *prev = NULL;
                   1602:        ndis_packet_private     *priv;
                   1603:
                   1604:        if (p == NULL || *p == NULL || m0 == NULL)
                   1605:                return(EINVAL);
                   1606:
                   1607:        priv = &(*p)->np_private;
                   1608:        priv->npp_totlen = m0->m_pkthdr.len;
                   1609:
                   1610:        for (m = m0; m != NULL; m = m->m_next) {
                   1611:                if (m->m_len == 0)
                   1612:                        continue;
                   1613:                buf = IoAllocateMdl(m->m_data, m->m_len, FALSE, FALSE, NULL);
                   1614:                if (buf == NULL) {
                   1615:                        ndis_free_packet(*p);
                   1616:                        *p = NULL;
                   1617:                        return(ENOMEM);
                   1618:                }
                   1619:
                   1620:                if (priv->npp_head == NULL)
                   1621:                        priv->npp_head = buf;
                   1622:                else
                   1623:                        prev->mdl_next = buf;
                   1624:                prev = buf;
                   1625:        }
                   1626:
                   1627:        priv->npp_tail = buf;
                   1628:
                   1629:        return(0);
                   1630: }
                   1631:
                   1632: int
1.14.10.1  yamt     1633: ndis_get_supported_oids(void *arg, ndis_oid **oids, int *oidcnt)
1.1       rittera  1634: {
                   1635:        int                     len, rval;
                   1636:        ndis_oid                *o;
                   1637:
                   1638:        if (arg == NULL || oids == NULL || oidcnt == NULL)
                   1639:                return(EINVAL);
                   1640:        len = 0;
                   1641:        ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, NULL, &len);
                   1642:
                   1643:        o = malloc(len, M_DEVBUF, M_NOWAIT);
                   1644:        if (o == NULL)
                   1645:                return(ENOMEM);
                   1646:
                   1647:        rval = ndis_get_info(arg, OID_GEN_SUPPORTED_LIST, o, &len);
                   1648:
                   1649:        if (rval) {
                   1650:                free(o, M_DEVBUF);
                   1651:                return(rval);
                   1652:        }
                   1653:
                   1654:        *oids = o;
                   1655:        *oidcnt = len / 4;
                   1656:
                   1657:        return(0);
                   1658: }
                   1659:
                   1660: int
1.14.10.1  yamt     1661: ndis_set_info(void *arg, ndis_oid oid, void *buf, int *buflen)
1.1       rittera  1662: {
                   1663:        struct ndis_softc       *sc;
                   1664:        ndis_status             rval;
                   1665:        ndis_handle             adapter;
                   1666:        __stdcall ndis_setinfo_handler  setfunc;
                   1667:        uint32_t                byteswritten = 0, bytesneeded = 0;
                   1668:        int                     error;
1.5       christos 1669:        uint8_t                 irql = 0;       /* XXX: gcc */
1.3       rittera  1670: #ifdef __NetBSD__
                   1671:        int                     s;
                   1672: #endif
1.1       rittera  1673:
                   1674:        /*
                   1675:         * According to the NDIS spec, MiniportQueryInformation()
                   1676:         * and MiniportSetInformation() requests are handled serially:
                   1677:         * once one request has been issued, we must wait for it to
                   1678:         * finish before allowing another request to proceed.
                   1679:         */
                   1680:
                   1681:        sc = arg;
                   1682:
                   1683:        KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
                   1684:
                   1685:        if (sc->ndis_block->nmb_pendingreq != NULL)
                   1686:                panic("ndis_set_info() called while other request pending");
                   1687:        else
                   1688:                sc->ndis_block->nmb_pendingreq = (ndis_request *)sc;
                   1689:
1.3       rittera  1690:        /* I added this lock because it was present in the FreeBSD-current sources */
                   1691:        NDIS_LOCK(sc);
                   1692:
1.1       rittera  1693:        setfunc = sc->ndis_chars->nmc_setinfo_func;
                   1694:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   1695:
                   1696:        if (adapter == NULL || setfunc == NULL) {
                   1697:                sc->ndis_block->nmb_pendingreq = NULL;
                   1698:                KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
1.3       rittera  1699:                NDIS_UNLOCK(sc);
1.1       rittera  1700:                return(ENXIO);
                   1701:        }
1.3       rittera  1702:
                   1703:        NDIS_UNLOCK(sc);
                   1704:
1.1       rittera  1705:        rval = MSCALL6(setfunc, adapter, oid, buf, *buflen,
                   1706:            &byteswritten, &bytesneeded);
                   1707:
                   1708:        sc->ndis_block->nmb_pendingreq = NULL;
                   1709:
                   1710:        KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
                   1711:
                   1712:        if (rval == NDIS_STATUS_PENDING) {
                   1713:                mtx_lock(&ndis_req_mtx);
1.3       rittera  1714: #ifdef __FreeBSD__
1.1       rittera  1715:                error = msleep(&sc->ndis_block->nmb_setstat,
                   1716:                    &ndis_req_mtx,
                   1717:                    curthread->td_priority|PDROP,
                   1718:                    "ndisset", 5 * hz);
1.3       rittera  1719: #else
                   1720:                error = ltsleep(&sc->ndis_block->nmb_setstat,
                   1721:                                curlwp->l_priority|PNORELOCK,
                   1722:                                "ndisset", 5 * hz, 0);
                   1723: #endif
1.1       rittera  1724:                rval = sc->ndis_block->nmb_setstat;
1.3       rittera  1725: #ifdef __NetBSD__
                   1726:                mtx_unlock(&ndis_req_mtx);
                   1727: #endif
1.1       rittera  1728:        }
                   1729:
                   1730:
                   1731:        if (byteswritten)
                   1732:                *buflen = byteswritten;
                   1733:        if (bytesneeded)
                   1734:                *buflen = bytesneeded;
                   1735:
                   1736:        if (rval == NDIS_STATUS_INVALID_LENGTH)
                   1737:                return(ENOSPC);
                   1738:
                   1739:        if (rval == NDIS_STATUS_INVALID_OID)
                   1740:                return(EINVAL);
                   1741:
                   1742:        if (rval == NDIS_STATUS_NOT_SUPPORTED ||
                   1743:            rval == NDIS_STATUS_NOT_ACCEPTED)
                   1744:                return(ENOTSUP);
                   1745:
                   1746:        if (rval != NDIS_STATUS_SUCCESS)
                   1747:                return(ENODEV);
                   1748:
                   1749:        return(0);
                   1750: }
                   1751:
                   1752: typedef void (*ndis_senddone_func)(ndis_handle, ndis_packet *, ndis_status);
                   1753:
                   1754: int
1.14.10.1  yamt     1755: ndis_send_packets(void *arg, ndis_packet **packets, int cnt)
1.1       rittera  1756: {
                   1757:        struct ndis_softc       *sc;
                   1758:        ndis_handle             adapter;
                   1759:        __stdcall ndis_sendmulti_handler        sendfunc;
                   1760:        __stdcall ndis_senddone_func            senddonefunc;
                   1761:        int                     i;
                   1762:        ndis_packet             *p;
1.5       christos 1763:        uint8_t                 irql = 0;       /* XXX: gcc */
1.1       rittera  1764:
                   1765:        sc = arg;
                   1766:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   1767:        if (adapter == NULL)
                   1768:                return(ENXIO);
                   1769:        sendfunc = sc->ndis_chars->nmc_sendmulti_func;
                   1770:        senddonefunc = sc->ndis_block->nmb_senddone_func;
                   1771:
                   1772:        if (NDIS_SERIALIZED(sc->ndis_block))
                   1773:                KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
                   1774:
                   1775:        MSCALL3(sendfunc, adapter, packets, cnt);
                   1776:
                   1777:        for (i = 0; i < cnt; i++) {
                   1778:                p = packets[i];
                   1779:                /*
                   1780:                 * Either the driver already handed the packet to
                   1781:                 * ndis_txeof() due to a failure, or it wants to keep
                   1782:                 * it and release it asynchronously later. Skip to the
                   1783:                 * next one.
                   1784:                 */
                   1785:                if (p == NULL || p->np_oob.npo_status == NDIS_STATUS_PENDING)
                   1786:                        continue;
                   1787:                MSCALL3(senddonefunc, sc->ndis_block, p, p->np_oob.npo_status);
                   1788:        }
                   1789:
                   1790:        if (NDIS_SERIALIZED(sc->ndis_block))
                   1791:                KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
                   1792:
                   1793:        return(0);
                   1794: }
                   1795:
                   1796: int
1.14.10.1  yamt     1797: ndis_send_packet(void *arg, ndis_packet *packet)
1.1       rittera  1798: {
                   1799:        struct ndis_softc       *sc;
                   1800:        ndis_handle             adapter;
                   1801:        ndis_status             status;
                   1802:        __stdcall ndis_sendsingle_handler       sendfunc;
                   1803:        __stdcall ndis_senddone_func            senddonefunc;
1.5       christos 1804:        uint8_t                 irql = 0;       /* XXX: gcc */
1.1       rittera  1805:
                   1806:        sc = arg;
                   1807:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   1808:        if (adapter == NULL)
                   1809:                return(ENXIO);
                   1810:        sendfunc = sc->ndis_chars->nmc_sendsingle_func;
                   1811:        senddonefunc = sc->ndis_block->nmb_senddone_func;
                   1812:
                   1813:        if (NDIS_SERIALIZED(sc->ndis_block))
                   1814:                KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
                   1815:        status = MSCALL3(sendfunc, adapter, packet,
                   1816:            packet->np_private.npp_flags);
                   1817:
                   1818:        if (status == NDIS_STATUS_PENDING) {
                   1819:                if (NDIS_SERIALIZED(sc->ndis_block))
                   1820:                        KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
                   1821:                return(0);
                   1822:        }
                   1823:
                   1824:        MSCALL3(senddonefunc, sc->ndis_block, packet, status);
                   1825:
                   1826:        if (NDIS_SERIALIZED(sc->ndis_block))
                   1827:                KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
                   1828:
                   1829:        return(0);
                   1830: }
                   1831:
                   1832: int
1.14.10.1  yamt     1833: ndis_init_dma(void *arg)
1.1       rittera  1834: {
                   1835:        struct ndis_softc       *sc;
1.3       rittera  1836:        int                     i, error = 0;
1.1       rittera  1837:
                   1838:        sc = arg;
                   1839:
                   1840:        sc->ndis_tmaps = malloc(sizeof(bus_dmamap_t) * sc->ndis_maxpkts,
                   1841:            M_DEVBUF, M_NOWAIT|M_ZERO);
                   1842:
                   1843:        if (sc->ndis_tmaps == NULL)
                   1844:                return(ENOMEM);
                   1845:
                   1846:        for (i = 0; i < sc->ndis_maxpkts; i++) {
1.3       rittera  1847: #ifdef __FreeBSD__
1.1       rittera  1848:                error = bus_dmamap_create(sc->ndis_ttag, 0,
                   1849:                    &sc->ndis_tmaps[i]);
1.3       rittera  1850: #else
                   1851:                /*
                   1852:                bus_dmamap_create(sc->ndis_mtag, sizeof(bus_dmamap_t),
                   1853:                                  1, sizeof(bus_dmamap_t), BUS_DMA_NOWAIT,
                   1854:                                  0, &sc->ndis_mmaps[i]);
                   1855:                */
                   1856:                bus_dmamap_create(sc->ndis_ttag, NDIS_MAXSEG * MCLBYTES,
                   1857:                                  NDIS_MAXSEG, MCLBYTES, 0,
                   1858:                                  BUS_DMA_NOWAIT, &sc->ndis_tmaps[i]);
                   1859: #endif
1.1       rittera  1860:                if (error) {
                   1861:                        free(sc->ndis_tmaps, M_DEVBUF);
                   1862:                        return(ENODEV);
                   1863:                }
                   1864:        }
                   1865:
                   1866:        return(0);
                   1867: }
                   1868:
                   1869: int
1.14.10.1  yamt     1870: ndis_destroy_dma(void *arg)
1.1       rittera  1871: {
                   1872:        struct ndis_softc       *sc;
                   1873:        struct mbuf             *m;
                   1874:        ndis_packet             *p = NULL;
                   1875:        int                     i;
                   1876:
                   1877:        sc = arg;
                   1878:
                   1879:        for (i = 0; i < sc->ndis_maxpkts; i++) {
                   1880:                if (sc->ndis_txarray[i] != NULL) {
                   1881:                        p = sc->ndis_txarray[i];
                   1882:                        m = (struct mbuf *)p->np_rsvd[1];
                   1883:                        if (m != NULL)
                   1884:                                m_freem(m);
                   1885:                        ndis_free_packet(sc->ndis_txarray[i]);
                   1886:                }
                   1887:                bus_dmamap_destroy(sc->ndis_ttag, sc->ndis_tmaps[i]);
                   1888:        }
                   1889:
                   1890:        free(sc->ndis_tmaps, M_DEVBUF);
                   1891:
1.3       rittera  1892: #ifdef __FreeBSD__
1.1       rittera  1893:        bus_dma_tag_destroy(sc->ndis_ttag);
1.3       rittera  1894: #endif
1.1       rittera  1895:
                   1896:        return(0);
                   1897: }
                   1898:
                   1899: int
1.14.10.1  yamt     1900: ndis_reset_nic(void *arg)
1.1       rittera  1901: {
                   1902:        struct ndis_softc       *sc;
                   1903:        ndis_handle             adapter;
                   1904:        __stdcall ndis_reset_handler    resetfunc;
                   1905:        uint8_t                 addressing_reset;
                   1906:        struct ifnet            *ifp;
                   1907:        int                     rval;
1.5       christos 1908:        uint8_t                 irql = 0;       /* XXX: gcc */
1.1       rittera  1909:
                   1910:        sc = arg;
1.3       rittera  1911: #ifdef __FreeBSD__
1.1       rittera  1912:        ifp = &sc->arpcom.ac_if;
1.3       rittera  1913: #else
                   1914:        ifp = &sc->arpcom.ec_if;
                   1915: #endif
1.1       rittera  1916:
                   1917:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   1918:        resetfunc = sc->ndis_chars->nmc_reset_func;
                   1919:
                   1920:        if (adapter == NULL || resetfunc == NULL)
                   1921:                return(EIO);
                   1922:
                   1923:        if (NDIS_SERIALIZED(sc->ndis_block))
                   1924:                KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
                   1925:
                   1926:        rval = MSCALL2(resetfunc, &addressing_reset, adapter);
                   1927:
                   1928:        if (NDIS_SERIALIZED(sc->ndis_block))
                   1929:                KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
                   1930:
                   1931:        if (rval == NDIS_STATUS_PENDING) {
                   1932:                mtx_lock(&ndis_req_mtx);
1.3       rittera  1933: #ifdef __FreeBSD__
1.1       rittera  1934:                msleep(sc, &ndis_req_mtx,
1.3       rittera  1935:                       curthread->td_priority|PDROP, "ndisrst", 0);
                   1936: #else
                   1937:                ltsleep(sc, curlwp->l_priority|PNORELOCK, "ndisrst", 0, 0);
                   1938: #endif
1.1       rittera  1939:        }
                   1940:
                   1941:        return(0);
                   1942: }
                   1943:
                   1944: int
1.14.10.1  yamt     1945: ndis_halt_nic(void *arg)
1.1       rittera  1946: {
                   1947:        struct ndis_softc       *sc;
                   1948:        ndis_handle             adapter;
                   1949:        __stdcall ndis_halt_handler     haltfunc;
                   1950:        struct ifnet            *ifp;
1.3       rittera  1951: #ifdef __NetBSD__
                   1952:        int                     s;
                   1953: #endif
1.1       rittera  1954:
                   1955:        sc = arg;
1.3       rittera  1956: #ifdef __FreeBSD__
1.1       rittera  1957:        ifp = &sc->arpcom.ac_if;
1.3       rittera  1958: #else
                   1959:        ifp = &sc->arpcom.ec_if;
                   1960: #endif
1.1       rittera  1961:
                   1962:        NDIS_LOCK(sc);
1.3       rittera  1963:
1.1       rittera  1964:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   1965:        if (adapter == NULL) {
1.3       rittera  1966:                NDIS_UNLOCK(sc);
1.1       rittera  1967:                return(EIO);
                   1968:        }
                   1969:
                   1970:        /*
                   1971:         * The adapter context is only valid after the init
                   1972:         * handler has been called, and is invalid once the
                   1973:         * halt handler has been called.
                   1974:         */
                   1975:
                   1976:        haltfunc = sc->ndis_chars->nmc_halt_func;
1.3       rittera  1977:
1.1       rittera  1978:        NDIS_UNLOCK(sc);
                   1979:
                   1980:        MSCALL1(haltfunc, adapter);
                   1981:
                   1982:        NDIS_LOCK(sc);
1.3       rittera  1983:
1.1       rittera  1984:        sc->ndis_block->nmb_miniportadapterctx = NULL;
1.3       rittera  1985:
                   1986:        NDIS_UNLOCK(sc);
1.1       rittera  1987:
                   1988:        return(0);
                   1989: }
                   1990:
                   1991: int
1.14.10.1  yamt     1992: ndis_shutdown_nic(void *arg)
1.1       rittera  1993: {
                   1994:        struct ndis_softc       *sc;
                   1995:        ndis_handle             adapter;
                   1996:        __stdcall ndis_shutdown_handler shutdownfunc;
1.3       rittera  1997: #ifdef __NetBSD__
                   1998:        int                     s;
                   1999: #endif
1.1       rittera  2000:
                   2001:        sc = arg;
1.3       rittera  2002:
1.1       rittera  2003:        NDIS_LOCK(sc);
1.3       rittera  2004:
1.1       rittera  2005:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   2006:        shutdownfunc = sc->ndis_chars->nmc_shutdown_handler;
1.3       rittera  2007:
1.1       rittera  2008:        NDIS_UNLOCK(sc);
1.3       rittera  2009:
1.1       rittera  2010:        if (adapter == NULL || shutdownfunc == NULL)
                   2011:                return(EIO);
                   2012:
                   2013:        if (sc->ndis_chars->nmc_rsvd0 == NULL)
                   2014:                MSCALL1(shutdownfunc, adapter);
                   2015:        else
                   2016:                MSCALL1(shutdownfunc, sc->ndis_chars->nmc_rsvd0);
                   2017:
                   2018:        ndis_shrink_thrqueue(8);
                   2019:        TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link);
                   2020:
                   2021:        return(0);
                   2022: }
                   2023:
                   2024: int
1.14.10.1  yamt     2025: ndis_init_nic(void *arg)
1.1       rittera  2026: {
                   2027:        struct ndis_softc       *sc;
                   2028:        ndis_miniport_block     *block;
                   2029:         __stdcall ndis_init_handler    initfunc;
                   2030:        ndis_status             status, openstatus = 0;
                   2031:        ndis_medium             mediumarray[NdisMediumMax];
                   2032:        uint32_t                chosenmedium, i;
1.3       rittera  2033: #ifdef __NetBSD__
                   2034:        int                     s;
                   2035: #endif
1.1       rittera  2036:
                   2037:        if (arg == NULL)
                   2038:                return(EINVAL);
                   2039:
                   2040:        sc = arg;
1.3       rittera  2041:
1.1       rittera  2042:        NDIS_LOCK(sc);
1.3       rittera  2043:
1.1       rittera  2044:        block = sc->ndis_block;
                   2045:        initfunc = sc->ndis_chars->nmc_init_func;
1.3       rittera  2046:
                   2047:        NDIS_UNLOCK(sc);
                   2048:
                   2049:        printf("sc->ndis_chars->nmc_version_major = %d\n\
                   2050:                        sc->ndis_chars->nmc_version_minor = %d\n",
                   2051:                        sc->ndis_chars->nmc_version_major,
                   2052:                        sc->ndis_chars->nmc_version_minor);
1.1       rittera  2053:
                   2054:        for (i = 0; i < NdisMediumMax; i++)
                   2055:                mediumarray[i] = i;
                   2056:
                   2057:         status = MSCALL6(initfunc, &openstatus, &chosenmedium,
                   2058:             mediumarray, NdisMediumMax, block, block);
1.3       rittera  2059:
                   2060:        printf("status = %x", status);
1.1       rittera  2061:
                   2062:        /*
                   2063:         * If the init fails, blow away the other exported routines
                   2064:         * we obtained from the driver so we can't call them later.
                   2065:         * If the init failed, none of these will work.
                   2066:         */
                   2067:        if (status != NDIS_STATUS_SUCCESS) {
                   2068:                NDIS_LOCK(sc);
1.3       rittera  2069:
1.1       rittera  2070:                sc->ndis_block->nmb_miniportadapterctx = NULL;
1.3       rittera  2071:
                   2072:                NDIS_UNLOCK(sc);
1.1       rittera  2073:                return(ENXIO);
                   2074:        }
                   2075:
                   2076:        return(0);
                   2077: }
                   2078:
                   2079: void
1.14.10.1  yamt     2080: ndis_enable_intr(void *arg)
1.1       rittera  2081: {
                   2082:        struct ndis_softc       *sc;
                   2083:        ndis_handle             adapter;
                   2084:        __stdcall ndis_enable_interrupts_handler        intrenbfunc;
                   2085:
                   2086:        sc = arg;
                   2087:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   2088:        intrenbfunc = sc->ndis_chars->nmc_enable_interrupts_func;
                   2089:        if (adapter == NULL || intrenbfunc == NULL)
                   2090:                return;
                   2091:        MSCALL1(intrenbfunc, adapter);
                   2092:
                   2093:        return;
                   2094: }
                   2095:
                   2096: void
1.14.10.1  yamt     2097: ndis_disable_intr(void *arg)
1.1       rittera  2098: {
                   2099:        struct ndis_softc       *sc;
                   2100:        ndis_handle             adapter;
                   2101:        __stdcall ndis_disable_interrupts_handler       intrdisfunc;
                   2102:
                   2103:        sc = arg;
                   2104:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   2105:        intrdisfunc = sc->ndis_chars->nmc_disable_interrupts_func;
                   2106:        if (adapter == NULL || intrdisfunc == NULL)
                   2107:            return;
                   2108:
                   2109:        MSCALL1(intrdisfunc, adapter);
                   2110:
                   2111:        return;
                   2112: }
                   2113:
                   2114: int
1.14.10.1  yamt     2115: ndis_isr(void *arg, int *ourintr, int *callhandler)
1.1       rittera  2116: {
                   2117:        struct ndis_softc       *sc;
                   2118:        ndis_handle             adapter;
                   2119:        __stdcall ndis_isr_handler      isrfunc;
                   2120:        uint8_t                 accepted, queue;
                   2121:
                   2122:        if (arg == NULL || ourintr == NULL || callhandler == NULL)
                   2123:                return(EINVAL);
                   2124:
                   2125:        sc = arg;
                   2126:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   2127:        isrfunc = sc->ndis_chars->nmc_isr_func;
                   2128:
                   2129:        if (adapter == NULL || isrfunc == NULL)
                   2130:                return(ENXIO);
                   2131:
                   2132:        MSCALL3(isrfunc, &accepted, &queue, adapter);
                   2133:
                   2134:        *ourintr = accepted;
                   2135:        *callhandler = queue;
                   2136:
                   2137:        return(0);
                   2138: }
                   2139:
                   2140: __stdcall static void
1.7       christos 2141: ndis_intrhand(kdpc *dpc, device_object *dobj,
                   2142:     irp *ip, struct ndis_softc *sc)
1.1       rittera  2143: {
                   2144:        ndis_handle             adapter;
                   2145:        __stdcall ndis_interrupt_handler        intrfunc;
1.5       christos 2146:        uint8_t                 irql = 0;       /* XXX: gcc */
1.1       rittera  2147:
                   2148:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   2149:        intrfunc = sc->ndis_chars->nmc_interrupt_func;
                   2150:
                   2151:        if (adapter == NULL || intrfunc == NULL)
                   2152:                return;
                   2153:
                   2154:        if (NDIS_SERIALIZED(sc->ndis_block))
                   2155:                KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
                   2156:
                   2157:        MSCALL1(intrfunc, adapter);
                   2158:
                   2159:        /* If there's a MiniportEnableInterrupt() routine, call it. */
                   2160:
                   2161:        ndis_enable_intr(sc);
                   2162:
                   2163:        if (NDIS_SERIALIZED(sc->ndis_block))
                   2164:                KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
                   2165:
                   2166:        return;
                   2167: }
                   2168:
                   2169: int
1.14.10.1  yamt     2170: ndis_get_info(void *arg, ndis_oid oid, void *buf, int *buflen)
1.1       rittera  2171: {
                   2172:        struct ndis_softc       *sc;
                   2173:        ndis_status             rval;
                   2174:        ndis_handle             adapter;
                   2175:        __stdcall ndis_queryinfo_handler        queryfunc;
                   2176:        uint32_t                byteswritten = 0, bytesneeded = 0;
1.3       rittera  2177: #ifdef __FreeBSD__
1.1       rittera  2178:        int                     error;
1.3       rittera  2179: #endif
1.5       christos 2180:        uint8_t                 irql = 0;       /* XXX: gcc */
1.1       rittera  2181:
1.3       rittera  2182:        //printf("in ndis_get_info\n");
                   2183:
1.1       rittera  2184:        sc = arg;
                   2185:        KeAcquireSpinLock(&sc->ndis_block->nmb_lock, &irql);
                   2186:
                   2187:        if (sc->ndis_block->nmb_pendingreq != NULL)
                   2188:                panic("ndis_get_info() called while other request pending");
                   2189:        else
                   2190:                sc->ndis_block->nmb_pendingreq = (ndis_request *)sc;
                   2191:
                   2192:        queryfunc = sc->ndis_chars->nmc_queryinfo_func;
                   2193:        adapter = sc->ndis_block->nmb_miniportadapterctx;
                   2194:
                   2195:        if (adapter == NULL || queryfunc == NULL) {
                   2196:                sc->ndis_block->nmb_pendingreq = NULL;
                   2197:                KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
                   2198:                return(ENXIO);
                   2199:        }
                   2200:
                   2201:        rval = MSCALL6(queryfunc, adapter, oid, buf, *buflen,
                   2202:            &byteswritten, &bytesneeded);
                   2203:
                   2204:        sc->ndis_block->nmb_pendingreq = NULL;
                   2205:
                   2206:        KeReleaseSpinLock(&sc->ndis_block->nmb_lock, irql);
                   2207:
                   2208:        /* Wait for requests that block. */
                   2209:
                   2210:        if (rval == NDIS_STATUS_PENDING) {
                   2211:                mtx_lock(&ndis_req_mtx);
1.3       rittera  2212: #ifdef __FreeBSD__
1.1       rittera  2213:                error = msleep(&sc->ndis_block->nmb_getstat,
                   2214:                    &ndis_req_mtx,
                   2215:                    curthread->td_priority|PDROP,
                   2216:                    "ndisget", 5 * hz);
1.3       rittera  2217: #else
                   2218:                ltsleep(&sc->ndis_block->nmb_getstat,
                   2219:                        curlwp->l_priority|PNORELOCK, "ndisget", 5 * hz, 0);
                   2220: #endif
1.1       rittera  2221:                rval = sc->ndis_block->nmb_getstat;
                   2222:        }
                   2223:
                   2224:        if (byteswritten)
                   2225:                *buflen = byteswritten;
                   2226:        if (bytesneeded)
                   2227:                *buflen = bytesneeded;
                   2228:
                   2229:        if (rval == NDIS_STATUS_INVALID_LENGTH ||
                   2230:            rval == NDIS_STATUS_BUFFER_TOO_SHORT)
                   2231:                return(ENOSPC);
                   2232:
                   2233:        if (rval == NDIS_STATUS_INVALID_OID)
                   2234:                return(EINVAL);
                   2235:
                   2236:        if (rval == NDIS_STATUS_NOT_SUPPORTED ||
                   2237:            rval == NDIS_STATUS_NOT_ACCEPTED)
                   2238:                return(ENOTSUP);
                   2239:
                   2240:        if (rval != NDIS_STATUS_SUCCESS)
                   2241:                return(ENODEV);
                   2242:
                   2243:        return(0);
                   2244: }
                   2245:
                   2246: __stdcall uint32_t
1.14.10.1  yamt     2247: NdisAddDevice(driver_object *drv, device_object *pdo)
1.1       rittera  2248: {
                   2249:        device_object           *fdo;
                   2250:        ndis_miniport_block     *block;
                   2251:        struct ndis_softc       *sc;
                   2252:        uint32_t                status;
                   2253:
                   2254:        status = IoCreateDevice(drv, sizeof(ndis_miniport_block), NULL,
                   2255:            FILE_DEVICE_UNKNOWN, 0, FALSE, &fdo);
                   2256:
                   2257:        if (status != STATUS_SUCCESS)
                   2258:                return(status);
                   2259:
                   2260:        block = fdo->do_devext;
                   2261:        block->nmb_deviceobj = fdo;
                   2262:        block->nmb_physdeviceobj = pdo;
                   2263:        block->nmb_nextdeviceobj = IoAttachDeviceToDeviceStack(fdo, pdo);
                   2264:        KeInitializeSpinLock(&block->nmb_lock);
1.3       rittera  2265:
                   2266: #ifdef __NetBSD__
                   2267:        /* NetBSD has a pointer to the callout object */
                   2268:        block->nmb_wkupdpctimer.nt_ktimer.k_handle =
                   2269:                malloc(sizeof(struct callout), M_DEVBUF, M_NOWAIT|M_ZERO);
                   2270: #endif
1.1       rittera  2271:
                   2272:        /*
                   2273:         * Stash pointers to the miniport block and miniport
                   2274:         * characteristics info in the if_ndis softc so the
                   2275:         * UNIX wrapper driver can get to them later.
1.3       rittera  2276:      */
                   2277: #ifdef __FreeBSD__
1.1       rittera  2278:        sc = device_get_softc(pdo->do_devext);
1.3       rittera  2279: #else /* __NetBSD__ */
                   2280:        sc = pdo->pdo_sc;
                   2281:        fdo->fdo_sc = sc;
                   2282: #endif
1.1       rittera  2283:        sc->ndis_block = block;
                   2284:        sc->ndis_chars = IoGetDriverObjectExtension(drv, (void *)1);
                   2285:
                   2286:        IoInitializeDpcRequest(fdo, kernndis_functbl[6].ipt_wrap);
                   2287:
                   2288:        /* Finish up BSD-specific setup. */
                   2289:
                   2290:        block->nmb_signature = (void *)0xcafebabe;
                   2291:        block->nmb_status_func = kernndis_functbl[0].ipt_wrap;
                   2292:        block->nmb_statusdone_func = kernndis_functbl[1].ipt_wrap;
                   2293:        block->nmb_setdone_func = kernndis_functbl[2].ipt_wrap;
                   2294:        block->nmb_querydone_func = kernndis_functbl[3].ipt_wrap;
                   2295:        block->nmb_resetdone_func = kernndis_functbl[4].ipt_wrap;
                   2296:        block->nmb_sendrsrc_func = kernndis_functbl[5].ipt_wrap;
                   2297:        block->nmb_pendingreq = NULL;
                   2298:
                   2299:        ndis_enlarge_thrqueue(8);
                   2300:
                   2301:        TAILQ_INSERT_TAIL(&ndis_devhead, block, link);
                   2302:
                   2303:        return (STATUS_SUCCESS);
                   2304: }
                   2305:
                   2306: int
1.14.10.1  yamt     2307: ndis_unload_driver(void *arg)
1.1       rittera  2308: {
                   2309:        struct ndis_softc       *sc;
                   2310:        device_object           *fdo;
                   2311:
                   2312:        sc = arg;
                   2313:
                   2314:        if (sc->ndis_block->nmb_rlist != NULL)
                   2315:                free(sc->ndis_block->nmb_rlist, M_DEVBUF);
                   2316:
                   2317:        ndis_flush_sysctls(sc);
                   2318:
                   2319:        ndis_shrink_thrqueue(8);
                   2320:        TAILQ_REMOVE(&ndis_devhead, sc->ndis_block, link);
                   2321:
                   2322:        fdo = sc->ndis_block->nmb_deviceobj;
                   2323:        IoDetachDevice(sc->ndis_block->nmb_nextdeviceobj);
                   2324:        IoDeleteDevice(fdo);
                   2325:
                   2326:        return(0);
                   2327: }

CVSweb <webmaster@jp.NetBSD.org>