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>