Rename printf -> kprintf in sys/ and add some defines where necessary
[dragonfly.git] / sys / emulation / ndis / subr_ndis.c
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  * $FreeBSD: src/sys/compat/ndis/subr_ndis.c,v 1.62 2004/07/11 00:19:30 wpaul Exp $
33  * $DragonFly: src/sys/emulation/ndis/subr_ndis.c,v 1.19 2006/12/23 00:27:02 swildner Exp $
34  */
35
36 /*
37  * This file implements a translation layer between the BSD networking
38  * infrasturcture and Windows(R) NDIS network driver modules. A Windows
39  * NDIS driver calls into several functions in the NDIS.SYS Windows
40  * kernel module and exports a table of functions designed to be called
41  * by the NDIS subsystem. Using the PE loader, we can patch our own
42  * versions of the NDIS routines into a given Windows driver module and
43  * convince the driver that it is in fact running on Windows.
44  *
45  * We provide a table of all our implemented NDIS routines which is patched
46  * into the driver object code. All our exported routines must use the
47  * _stdcall calling convention, since that's what the Windows object code
48  * expects.
49  */
50
51 #include <sys/ctype.h>
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/kernel.h>
55 #include <sys/types.h>
56 #include <sys/errno.h>
57
58 #include <sys/callout.h>
59 #include <sys/malloc.h>
60 #include <sys/lock.h>
61 #include <sys/socket.h>
62 #include <sys/sysctl.h>
63 #include <sys/queue.h>
64 #include <sys/proc.h>
65 #include <sys/filedesc.h>
66 #include <sys/nlookup.h>
67 #include <sys/fcntl.h>
68 #include <sys/vnode.h>
69 #include <sys/kthread.h>
70 #include <sys/bus.h>
71 #include <sys/rman.h>
72
73 #include <net/if.h>
74 #include <net/if_arp.h>
75 #include <net/ethernet.h>
76 #include <net/if_dl.h>
77 #include <net/if_media.h>
78
79 #include <machine/atomic.h>
80 #include <machine/stdarg.h>
81
82 #include <netproto/802_11/ieee80211_var.h>
83 #include <netproto/802_11/ieee80211_ioctl.h>
84
85 #include <bus/pci/pcireg.h>
86 #include <bus/pci/pcivar.h>
87
88 #include "regcall.h"
89 #include "pe_var.h"
90 #include "resource_var.h"
91 #include "ntoskrnl_var.h"
92 #include "hal_var.h"
93 #include "ndis_var.h"
94 #include "cfg_var.h"
95 #include <dev/netif/ndis/if_ndisvar.h>
96
97 #define FUNC void(*)(void)
98
99 static char ndis_filepath[MAXPATHLEN];
100 extern struct nd_head ndis_devhead;
101
102 SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
103         MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
104
105 __stdcall static void ndis_initwrap(ndis_handle *,
106         device_object *, void *, void *);
107 __stdcall static ndis_status ndis_register_miniport(ndis_handle,
108         ndis_miniport_characteristics *, int);
109 __stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
110 __stdcall static ndis_status ndis_malloc(void **,
111         uint32_t, uint32_t, ndis_physaddr);
112 __stdcall static void ndis_free(void *, uint32_t, uint32_t);
113 __stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
114         uint32_t, uint32_t, ndis_interface_type);
115 __stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
116 __stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle,
117         uint32_t, ndis_unicode_string *, ndis_handle *);
118 __stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle,
119         ndis_unicode_string *, ndis_handle *);
120 static ndis_status ndis_encode_parm(ndis_miniport_block *,
121         struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
122 static ndis_status ndis_decode_parm(ndis_miniport_block *,
123         ndis_config_parm *, char *);
124 __stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
125         ndis_handle, ndis_unicode_string *, ndis_parm_type);
126 __stdcall static void ndis_write_cfg(ndis_status *, ndis_handle,
127         ndis_unicode_string *, ndis_config_parm *);
128 __stdcall static void ndis_close_cfg(ndis_handle);
129 __stdcall static void ndis_create_lock(ndis_spin_lock *);
130 __stdcall static void ndis_destroy_lock(ndis_spin_lock *);
131 __stdcall static void ndis_lock(ndis_spin_lock *);
132 __stdcall static void ndis_unlock(ndis_spin_lock *);
133 __stdcall static void ndis_lock_dpr(ndis_spin_lock *);
134 __stdcall static void ndis_unlock_dpr(ndis_spin_lock *);
135 __stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
136         uint32_t, void *, uint32_t);
137 __stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
138         uint32_t, void *, uint32_t);
139 static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
140 static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
141 __stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
142         uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
143 __stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
144 __stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle,
145         ndis_timer_function, void *);
146 __stdcall static void ndis_init_timer(ndis_timer *,
147         ndis_timer_function, void *);
148 __stdcall static void ndis_set_timer(ndis_timer *, uint32_t);
149 __stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
150 __stdcall static void ndis_cancel_timer(ndis_timer *, uint8_t *);
151 __stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
152         ndis_resource_list *, uint32_t *);
153 __stdcall static ndis_status ndis_register_ioport(void **,
154         ndis_handle, uint32_t, uint32_t);
155 __stdcall static void ndis_deregister_ioport(ndis_handle,
156         uint32_t, uint32_t, void *);
157 __stdcall static void ndis_read_netaddr(ndis_status *, void **,
158         uint32_t *, ndis_handle);
159 __stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *);
160 __stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
161         uint32_t, uint8_t, uint32_t, uint32_t);
162 __stdcall static void ndis_free_mapreg(ndis_handle);
163 static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
164 __stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
165         uint8_t, void **, ndis_physaddr *);
166 static void ndis_asyncmem_complete(void *);
167 __stdcall static ndis_status ndis_alloc_sharedmem_async(ndis_handle,
168         uint32_t, uint8_t, void *);
169 __stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
170         uint8_t, void *, ndis_physaddr);
171 __stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
172         ndis_physaddr, uint32_t);
173 __stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
174 __stdcall static uint32_t ndis_cachefill(void);
175 __stdcall static uint32_t ndis_dma_align(ndis_handle);
176 __stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
177         uint8_t, uint32_t);
178 __stdcall static void ndis_alloc_packetpool(ndis_status *,
179         ndis_handle *, uint32_t, uint32_t);
180 __stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
181         ndis_handle *, uint32_t, uint32_t, uint32_t);
182 __stdcall static uint32_t ndis_packetpool_use(ndis_handle);
183 __stdcall static void ndis_free_packetpool(ndis_handle);
184 __stdcall static void ndis_alloc_packet(ndis_status *,
185         ndis_packet **, ndis_handle);
186 __stdcall static void ndis_release_packet(ndis_packet *);
187 __stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
188 __stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **);
189 __stdcall static void ndis_alloc_bufpool(ndis_status *,
190         ndis_handle *, uint32_t);
191 __stdcall static void ndis_free_bufpool(ndis_handle);
192 __stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
193         ndis_handle, void *, uint32_t);
194 __stdcall static void ndis_release_buf(ndis_buffer *);
195 __stdcall static uint32_t ndis_buflen(ndis_buffer *);
196 __stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
197 __stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
198         uint32_t *, uint32_t);
199 __stdcall static void *ndis_buf_vaddr(ndis_buffer *);
200 __stdcall static void *ndis_buf_vaddr_safe(ndis_buffer *, uint32_t);
201 __stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
202 __stdcall static uint32_t ndis_interlock_inc(uint32_t *);
203 __stdcall static uint32_t ndis_interlock_dec(uint32_t *);
204 __stdcall static void ndis_init_event(ndis_event *);
205 __stdcall static void ndis_set_event(ndis_event *);
206 __stdcall static void ndis_reset_event(ndis_event *);
207 __stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
208 __stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
209         ndis_unicode_string *);
210 __stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
211         ndis_ansi_string *);
212 __stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
213         uint32_t, ndis_resource_list **);
214 __stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
215         ndis_handle, uint32_t, uint32_t, uint8_t,
216         uint8_t, ndis_interrupt_mode);
217 __stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
218 __stdcall static void ndis_register_shutdown(ndis_handle, void *,
219         ndis_shutdown_handler);
220 __stdcall static void ndis_deregister_shutdown(ndis_handle);
221 __stdcall static uint32_t ndis_numpages(ndis_buffer *);
222 __stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
223 __stdcall static void ndis_query_bufoffset(ndis_buffer *,
224         uint32_t *, uint32_t *);
225 __stdcall static void ndis_sleep(uint32_t);
226 __stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
227         uint32_t, void *, uint32_t);
228 __stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
229         uint32_t, void *, uint32_t);
230 __stdcall static list_entry *ndis_insert_head(list_entry *,
231         list_entry *, ndis_spin_lock *);
232 __stdcall static list_entry *ndis_remove_head(list_entry *,
233         ndis_spin_lock *);
234 __stdcall static list_entry *ndis_insert_tail(list_entry *,
235         list_entry *, ndis_spin_lock *);
236 __stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
237         void *, void *);
238 __stdcall static void ndis_time(uint64_t *);
239 __stdcall static void ndis_uptime(uint32_t *);
240 __stdcall static void ndis_init_string(ndis_unicode_string *, char *);
241 __stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
242 __stdcall static void ndis_init_unicode_string(ndis_unicode_string *,
243         uint16_t *);
244 __stdcall static void ndis_free_string(ndis_unicode_string *);
245 __stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
246 __stdcall static void ndis_termwrap(ndis_handle, void *);
247 __stdcall static void ndis_get_devprop(ndis_handle, device_object **,
248         device_object **, device_object **, cm_resource_list *,
249         cm_resource_list *);
250 __stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
251         void **, uint32_t *, uint32_t *);
252 __stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
253         void **, uint32_t *, uint32_t *, uint32_t);
254 __stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
255         ndis_unicode_string *, ndis_physaddr);
256 __stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
257 __stdcall static void ndis_unmap_file(ndis_handle);
258 __stdcall static void ndis_close_file(ndis_handle);
259 __stdcall static u_int8_t ndis_cpu_cnt(void);
260 __stdcall static void ndis_ind_statusdone(ndis_handle);
261 __stdcall static void ndis_ind_status(ndis_handle, ndis_status,
262         void *, uint32_t);
263 static void ndis_workfunc(void *);
264 __stdcall static ndis_status ndis_sched_workitem(ndis_work_item *);
265 __stdcall static void ndis_pkt_to_pkt(ndis_packet *, uint32_t, uint32_t,
266         ndis_packet *, uint32_t, uint32_t *);
267 __stdcall static void ndis_pkt_to_pkt_safe(ndis_packet *, uint32_t, uint32_t,
268         ndis_packet *, uint32_t, uint32_t *, uint32_t);
269 __stdcall static ndis_status ndis_register_dev(ndis_handle,
270         ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **,
271         void **, ndis_handle *);
272 __stdcall static ndis_status ndis_deregister_dev(ndis_handle);
273 __stdcall static ndis_status ndis_query_name(ndis_unicode_string *,
274         ndis_handle);
275 __stdcall static void ndis_register_unload(ndis_handle, void *);
276 __stdcall static void dummy(void);
277
278 /*
279  * Some really old drivers do not properly check the return value
280  * from NdisAllocatePacket() and NdisAllocateBuffer() and will
281  * sometimes allocate few more buffers/packets that they originally
282  * requested when they created the pool. To prevent this from being
283  * a problem, we allocate a few extra buffers/packets beyond what
284  * the driver asks for. This #define controls how many.
285  */
286 #define NDIS_POOL_EXTRA         16
287
288 int
289 ndis_libinit(void)
290 {
291         strcpy(ndis_filepath, "/compat/ndis");
292         return(0);
293 }
294
295 int
296 ndis_libfini(void)
297 {
298         return(0);
299 }
300
301 /*
302  * NDIS deals with strings in unicode format, so we have
303  * do deal with them that way too. For now, we only handle
304  * conversion between unicode and ASCII since that's all
305  * that device drivers care about.
306  */
307
308 int
309 ndis_ascii_to_unicode(char *ascii, uint16_t **unicode)
310 {
311         uint16_t                *ustr;
312         int                     i;
313
314         if (*unicode == NULL)
315                 *unicode = kmalloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
316         ustr = *unicode;
317         for (i = 0; i < strlen(ascii); i++) {
318                 *ustr = (uint16_t)ascii[i];
319                 ustr++;
320         }
321
322         return(0);
323 }
324
325 int
326 ndis_unicode_to_ascii(uint16_t *unicode, int ulen, char **ascii)
327 {
328         uint8_t                 *astr;
329         int                     i;
330
331         if (*ascii == NULL)
332                 *ascii = kmalloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO);
333         astr = *ascii;
334         for (i = 0; i < ulen / 2; i++) {
335                 *astr = (uint8_t)unicode[i];
336                 astr++;
337         }
338
339         return(0);
340 }
341
342 __stdcall static void
343 ndis_initwrap(ndis_handle *wrapper, device_object *drv_obj, void *path,
344               void *unused)
345 {
346         ndis_miniport_block     *block;
347
348         block = drv_obj->do_rsvd;
349         *wrapper = block;
350
351         return;
352 }
353
354 __stdcall static void
355 ndis_termwrap(ndis_handle handle, void *syspec)
356 {
357         return;
358 }
359
360 __stdcall static ndis_status
361 ndis_register_miniport(ndis_handle handle,
362                        ndis_miniport_characteristics *characteristics,
363                        int len)
364 {
365         ndis_miniport_block     *block;
366         struct ndis_softc       *sc;
367
368         block = (ndis_miniport_block *)handle;
369         sc = (struct ndis_softc *)block->nmb_ifp;
370         bcopy((char *)characteristics, (char *)&sc->ndis_chars,
371             sizeof(ndis_miniport_characteristics));
372         if (sc->ndis_chars.nmc_version_major < 5 ||
373             sc->ndis_chars.nmc_version_minor < 1) {
374                 sc->ndis_chars.nmc_shutdown_handler = NULL;
375                 sc->ndis_chars.nmc_canceltxpkts_handler = NULL;
376                 sc->ndis_chars.nmc_pnpevent_handler = NULL;
377         }
378
379         return(NDIS_STATUS_SUCCESS);
380 }
381
382 __stdcall static ndis_status
383 ndis_malloc_withtag(void **vaddr, uint32_t len, uint32_t tag)
384 {
385         void                    *mem;
386
387         mem = kmalloc(len, M_DEVBUF, M_INTWAIT|M_NULLOK);
388         if (mem == NULL)
389                 return(NDIS_STATUS_RESOURCES);
390         *vaddr = mem;
391
392         return(NDIS_STATUS_SUCCESS);
393 }
394
395 __stdcall static ndis_status
396 ndis_malloc(void **vaddr, uint32_t len, uint32_t flags,
397             ndis_physaddr highaddr)
398 {
399         void                    *mem;
400
401         mem = kmalloc(len, M_DEVBUF, M_INTWAIT|M_NULLOK);
402         if (mem == NULL)
403                 return(NDIS_STATUS_RESOURCES);
404         *vaddr = mem;
405
406         return(NDIS_STATUS_SUCCESS);
407 }
408
409 __stdcall static void
410 ndis_free(void *vaddr, uint32_t len, uint32_t flags)
411 {
412         if (len == 0)
413                 return;
414         kfree(vaddr, M_DEVBUF);
415
416         return;
417 }
418
419 __stdcall static ndis_status
420 ndis_setattr_ex(ndis_handle adapter_handle, ndis_handle adapter_ctx,
421                 uint32_t hangsecs, uint32_t flags,
422                 ndis_interface_type iftype)
423 {
424         ndis_miniport_block             *block;
425
426         /*
427          * Save the adapter context, we need it for calling
428          * the driver's internal functions.
429          */
430         block = (ndis_miniport_block *)adapter_handle;
431         block->nmb_miniportadapterctx = adapter_ctx;
432         block->nmb_checkforhangsecs = hangsecs;
433         block->nmb_flags = flags;
434
435         return(NDIS_STATUS_SUCCESS);
436 }
437
438 __stdcall static void
439 ndis_open_cfg(ndis_status *status, ndis_handle *cfg, ndis_handle wrapctx)
440 {
441         *cfg = wrapctx;
442         *status = NDIS_STATUS_SUCCESS;
443         return;
444 }
445
446 __stdcall static void
447 ndis_open_cfgbyname(ndis_status *status, ndis_handle cfg,
448                     ndis_unicode_string *subkey, ndis_handle *subhandle)
449 {
450         *subhandle = cfg;
451         *status = NDIS_STATUS_SUCCESS;
452         return;
453 }
454
455 __stdcall static void
456 ndis_open_cfgbyidx(ndis_status *status, ndis_handle cfg, uint32_t idx,
457                    ndis_unicode_string *subkey, ndis_handle *subhandle)
458 {
459         *status = NDIS_STATUS_FAILURE;
460         return;
461 }
462
463 static ndis_status
464 ndis_encode_parm(ndis_miniport_block *block, struct sysctl_oid *oid,
465                  ndis_parm_type type, ndis_config_parm **parm)
466 {
467         uint16_t                *unicode;
468         ndis_unicode_string     *ustr;
469         int                     base = 0;
470
471         unicode = (uint16_t *)&block->nmb_dummybuf;
472
473         switch(type) {
474         case ndis_parm_string:
475                 ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
476                 (*parm)->ncp_type = ndis_parm_string;
477                 ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
478                 ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
479                 ustr->nus_buf = unicode;
480                 break;
481         case ndis_parm_int:
482                 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
483                         base = 16;
484                 else
485                         base = 10;
486                 (*parm)->ncp_type = ndis_parm_int;
487                 (*parm)->ncp_parmdata.ncp_intdata =
488                     strtol((char *)oid->oid_arg1, NULL, base);
489                 break;
490         case ndis_parm_hexint:
491                 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
492                         base = 16;
493                 else
494                         base = 10;
495                 (*parm)->ncp_type = ndis_parm_hexint;
496                 (*parm)->ncp_parmdata.ncp_intdata =
497                     strtoul((char *)oid->oid_arg1, NULL, base);
498                 break;
499         default:
500                 return(NDIS_STATUS_FAILURE);
501                 break;
502         }
503
504         return(NDIS_STATUS_SUCCESS);
505 }
506
507 int
508 ndis_strcasecmp(const char *s1, const char *s2)
509 {
510         char                    a, b;
511
512         /*
513          * In the kernel, toupper() is a macro. Have to be careful
514          * not to use pointer arithmetic when passing it arguments.
515          */
516
517         while(1) {
518                 a = *s1;
519                 b = *s2++;
520                 if (toupper(a) != toupper(b))
521                         break;
522                 if (*s1++ == 0)
523                         return(0);
524         }
525
526         return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
527 }
528
529 __stdcall static void
530 ndis_read_cfg(ndis_status *status, ndis_config_parm **parm, ndis_handle cfg,
531               ndis_unicode_string *key, ndis_parm_type type)
532 {
533         char                    *keystr = NULL;
534         uint16_t                *unicode;
535         ndis_miniport_block     *block;
536         struct ndis_softc       *sc;
537         struct sysctl_oid       *oidp;
538         struct sysctl_ctx_entry *e;
539
540         block = (ndis_miniport_block *)cfg;
541         sc = (struct ndis_softc *)block->nmb_ifp;
542
543         if (key->nus_len == 0 || key->nus_buf == NULL) {
544                 *status = NDIS_STATUS_FAILURE;
545                 return;
546         }
547
548         ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
549
550         *parm = &block->nmb_replyparm;
551         bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
552         unicode = (uint16_t *)&block->nmb_dummybuf;
553
554         /*
555          * See if registry key is already in a list of known keys
556          * included with the driver.
557          */
558 #if __FreeBSD_version < 502113
559         TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
560 #else
561         TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
562 #endif
563                 oidp = e->entry;
564                 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
565                         if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
566                                 kfree(keystr, M_DEVBUF);
567                                 *status = NDIS_STATUS_FAILURE;
568                                 return;
569                         }
570                         *status = ndis_encode_parm(block, oidp, type, parm);
571                         kfree(keystr, M_DEVBUF);
572                         return;
573                 }
574         }
575
576         /*
577          * If the key didn't match, add it to the list of dynamically
578          * created ones. Sometimes, drivers refer to registry keys
579          * that aren't documented in their .INF files. These keys
580          * are supposed to be created by some sort of utility or
581          * control panel snap-in that comes with the driver software.
582          * Sometimes it's useful to be able to manipulate these.
583          * If the driver requests the key in the form of a string,
584          * make its default value an empty string, otherwise default
585          * it to "0".
586          */
587
588         if (type == ndis_parm_int || type == ndis_parm_hexint)
589                 ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
590                     "UNSET", CTLFLAG_RW);
591         else
592                 ndis_add_sysctl(sc, keystr, "(dynamic string key)",
593                     "UNSET", CTLFLAG_RW);
594
595         kfree(keystr, M_DEVBUF);
596         *status = NDIS_STATUS_FAILURE;
597         return;
598 }
599
600 static ndis_status
601 ndis_decode_parm(ndis_miniport_block *block, ndis_config_parm *parm,
602                  char *val)
603 {
604         ndis_unicode_string     *ustr;
605         char                    *astr = NULL;
606
607         switch(parm->ncp_type) {
608         case ndis_parm_string:
609                 ustr = &parm->ncp_parmdata.ncp_stringdata;
610                 ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &astr);
611                 bcopy(astr, val, 254);
612                 kfree(astr, M_DEVBUF);
613                 break;
614         case ndis_parm_int:
615                 ksprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
616                 break;
617         case ndis_parm_hexint:
618                 ksprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
619                 break;
620         default:
621                 return(NDIS_STATUS_FAILURE);
622                 break;
623         }
624         return(NDIS_STATUS_SUCCESS);
625 }
626
627 __stdcall static void
628 ndis_write_cfg(ndis_status *status, ndis_handle cfg, ndis_unicode_string *key,
629                ndis_config_parm *parm)
630 {
631         char                    *keystr = NULL;
632         ndis_miniport_block     *block;
633         struct ndis_softc       *sc;
634         struct sysctl_oid       *oidp;
635         struct sysctl_ctx_entry *e;
636         char                    val[256];
637
638         block = (ndis_miniport_block *)cfg;
639         sc = (struct ndis_softc *)block->nmb_ifp;
640
641         ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
642
643         /* Decode the parameter into a string. */
644         bzero(val, sizeof(val));
645         *status = ndis_decode_parm(block, parm, val);
646         if (*status != NDIS_STATUS_SUCCESS) {
647                 kfree(keystr, M_DEVBUF);
648                 return;
649         }
650
651         /* See if the key already exists. */
652
653 #if __FreeBSD_version < 502113
654         TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
655 #else
656         TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
657 #endif
658                 oidp = e->entry;
659                 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
660                         /* Found it, set the value. */
661                         strcpy((char *)oidp->oid_arg1, val);
662                         kfree(keystr, M_DEVBUF);
663                         return;
664                 }
665         }
666
667         /* Not found, add a new key with the specified value. */
668         ndis_add_sysctl(sc, keystr, "(dynamically set key)",
669                     val, CTLFLAG_RW);
670
671         kfree(keystr, M_DEVBUF);
672         *status = NDIS_STATUS_SUCCESS;
673         return;
674 }
675
676 __stdcall static void
677 ndis_close_cfg(ndis_handle cfg)
678 {
679         return;
680 }
681
682 /*
683  * Initialize a Windows spinlock.
684  */
685 __stdcall static void
686 ndis_create_lock(ndis_spin_lock *lock)
687 {
688         lock->nsl_spinlock = 0;
689         lock->nsl_kirql = 0;
690
691         return;
692 }
693
694 /*
695  * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
696  * for this. One is that it's sort of superfluous: we don't have to do anything
697  * special to deallocate the spinlock. The other is that there are some buggy
698  * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
699  * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
700  * talking to you.)
701  */
702 __stdcall static void
703 ndis_destroy_lock(ndis_spin_lock *lock)
704 {
705 #ifdef notdef
706         lock->nsl_spinlock = 0;
707         lock->nsl_kirql = 0;
708 #endif
709         return;
710 }
711
712 /*
713  * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
714  */
715
716 __stdcall static void
717 ndis_lock(ndis_spin_lock *lock)
718 {
719         lock->nsl_kirql = FASTCALL2(hal_lock,
720             &lock->nsl_spinlock, DISPATCH_LEVEL);
721         return;
722 }
723
724 /*
725  * Release a spinlock from IRQL == DISPATCH_LEVEL.
726  */
727
728 __stdcall static void
729 ndis_unlock(ndis_spin_lock *lock)
730 {
731         FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
732         return;
733 }
734
735 /*
736  * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
737  */
738 __stdcall static void
739 ndis_lock_dpr(ndis_spin_lock *lock)
740 {
741         FASTCALL1(ntoskrnl_lock_dpc, &lock->nsl_spinlock);
742         return;
743 }
744
745 /*
746  * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
747  */
748 __stdcall static void
749 ndis_unlock_dpr(ndis_spin_lock *lock)
750 {
751         FASTCALL1(ntoskrnl_unlock_dpc, &lock->nsl_spinlock);
752         return;
753 }
754
755 __stdcall static uint32_t
756 ndis_read_pci(ndis_handle adapter, uint32_t slot, uint32_t offset,
757               void *buf, uint32_t len)
758 {
759         ndis_miniport_block     *block;
760         int                     i;
761         char                    *dest;
762
763         block = (ndis_miniport_block *)adapter;
764         dest = buf;
765         if (block == NULL || block->nmb_dev == NULL)
766                 return(0);
767
768         for (i = 0; i < len; i++)
769                 dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
770
771         return(len);
772 }
773
774 __stdcall static uint32_t
775 ndis_write_pci(ndis_handle adapter, uint32_t slot, uint32_t offset,
776                void *buf, uint32_t len)
777 {
778         ndis_miniport_block     *block;
779         int                     i;
780         char                    *dest;
781
782         block = (ndis_miniport_block *)adapter;
783         dest = buf;
784
785         if (block == NULL || block->nmb_dev == NULL)
786                 return(0);
787
788         for (i = 0; i < len; i++)
789                 pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
790
791         return(len);
792 }
793
794 /*
795  * The errorlog routine uses a variable argument list, so we
796  * have to declare it this way.
797  */
798 #define ERRMSGLEN 512
799 static void
800 ndis_syslog(ndis_handle adapter, ndis_error_code code,
801         uint32_t numerrors, ...)
802 {
803         ndis_miniport_block     *block;
804         __va_list               ap;
805         int                     i, error;
806         char                    *str = NULL, *ustr = NULL;
807         uint16_t                flags;
808         char                    msgbuf[ERRMSGLEN];
809
810
811         block = (ndis_miniport_block *)adapter;
812
813         error = pe_get_message(block->nmb_img, code, &str, &i, &flags);
814         if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
815                 ustr = msgbuf;
816                 ndis_unicode_to_ascii((uint16_t *)str,
817                     ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
818                 str = ustr;
819         }
820         device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code,
821             str == NULL ? "unknown error" : str);
822         device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
823
824         __va_start(ap, numerrors);
825         for (i = 0; i < numerrors; i++)
826                 device_printf (block->nmb_dev, "argptr: %p\n",
827                     __va_arg(ap, void *));
828         __va_end(ap);
829
830         return;
831 }
832
833 static void
834 ndis_map_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
835 {
836         struct ndis_map_arg     *ctx;
837         int                     i;
838
839         if (error)
840                 return;
841
842         ctx = arg;
843
844         for (i = 0; i < nseg; i++) {
845                 ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
846                 ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
847         }
848
849         ctx->nma_cnt = nseg;
850
851         return;
852 }
853
854 __stdcall static void
855 ndis_vtophys_load(ndis_handle adapter, ndis_buffer *buf, uint32_t mapreg,
856                   uint8_t writedev, ndis_paddr_unit *addrarray,
857                   uint32_t *arraysize)
858 {
859         ndis_miniport_block     *block;
860         struct ndis_softc       *sc;
861         struct ndis_map_arg     nma;
862         bus_dmamap_t            map;
863         int                     error;
864
865         if (adapter == NULL)
866                 return;
867
868         block = (ndis_miniport_block *)adapter;
869         sc = (struct ndis_softc *)(block->nmb_ifp);
870
871         if (mapreg > sc->ndis_mmapcnt)
872                 return;
873
874         map = sc->ndis_mmaps[mapreg];
875         nma.nma_fraglist = addrarray;
876
877         error = bus_dmamap_load(sc->ndis_mtag, map,
878             MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
879             (void *)&nma, BUS_DMA_NOWAIT);
880
881         if (error)
882                 return;
883
884         bus_dmamap_sync(sc->ndis_mtag, map,
885             writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
886
887         *arraysize = nma.nma_cnt;
888
889         return;
890 }
891
892 __stdcall static void
893 ndis_vtophys_unload(ndis_handle adapter, ndis_buffer *buf,
894                     uint32_t mapreg)
895 {
896         ndis_miniport_block     *block;
897         struct ndis_softc       *sc;
898         bus_dmamap_t            map;
899
900         if (adapter == NULL)
901                 return;
902
903         block = (ndis_miniport_block *)adapter;
904         sc = (struct ndis_softc *)(block->nmb_ifp);
905
906         if (mapreg > sc->ndis_mmapcnt)
907                 return;
908
909         map = sc->ndis_mmaps[mapreg];
910
911         bus_dmamap_sync(sc->ndis_mtag, map,
912             BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
913
914         bus_dmamap_unload(sc->ndis_mtag, map);
915
916         return;
917 }
918
919 /*
920  * This is an older pre-miniport timer init routine which doesn't
921  * accept a miniport context handle. The function context (ctx)
922  * is supposed to be a pointer to the adapter handle, which should
923  * have been handed to us via NdisSetAttributesEx(). We use this
924  * function context to track down the corresponding ndis_miniport_block
925  * structure. It's vital that we track down the miniport block structure,
926  * so if we can't do it, we panic. Note that we also play some games
927  * here by treating ndis_timer and ndis_miniport_timer as the same
928  * thing.
929  */
930
931 __stdcall static void
932 ndis_init_timer(ndis_timer *timer, ndis_timer_function func, void *ctx)
933 {
934         ntoskrnl_init_timer(&timer->nt_ktimer);
935         ntoskrnl_init_dpc(&timer->nt_kdpc, func, ctx);
936
937         return;
938 }
939
940 __stdcall static void
941 ndis_create_timer(ndis_miniport_timer *timer, ndis_handle handle,
942                   ndis_timer_function func, void *ctx)
943 {
944         /* Save the funcptr and context */
945
946         timer->nmt_timerfunc = func;
947         timer->nmt_timerctx = ctx;
948         timer->nmt_block = handle;
949
950         ntoskrnl_init_timer(&timer->nmt_ktimer);
951         ntoskrnl_init_dpc(&timer->nmt_kdpc, func, ctx);
952
953         return;
954 }
955
956 /*
957  * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
958  * but the former is just a macro wrapper around the latter.
959  */
960 __stdcall static void
961 ndis_set_timer(ndis_timer *timer, uint32_t msecs)
962 {
963         /*
964          * KeSetTimer() wants the period in
965          * hundred nanosecond intervals.
966          */
967         ntoskrnl_set_timer(&timer->nt_ktimer,
968             ((int64_t)msecs * -10000), &timer->nt_kdpc);
969
970         return;
971 }
972
973 __stdcall static void
974 ndis_set_periodic_timer(ndis_miniport_timer *timer, uint32_t msecs)
975 {
976         ntoskrnl_set_timer_ex(&timer->nmt_ktimer,
977             ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc);
978
979         return;
980 }
981
982 /*
983  * Technically, this is really NdisCancelTimer(), but we also
984  * (ab)use it for NdisMCancelTimer(), since in our implementation
985  * we don't need the extra info in the ndis_miniport_timer
986  * structure.
987  */
988
989 __stdcall static void
990 ndis_cancel_timer(ndis_timer *timer, uint8_t *cancelled)
991 {
992         *cancelled = ntoskrnl_cancel_timer(&timer->nt_ktimer);
993
994         return;
995 }
996
997 __stdcall static void
998 ndis_query_resources(ndis_status *status, ndis_handle adapter,
999                      ndis_resource_list *list, uint32_t *buflen)
1000 {
1001         ndis_miniport_block     *block;
1002         struct ndis_softc       *sc;
1003         int                     rsclen;
1004
1005         block = (ndis_miniport_block *)adapter;
1006         sc = (struct ndis_softc *)block->nmb_ifp;
1007
1008         rsclen = sizeof(ndis_resource_list) +
1009             (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1010         if (*buflen < rsclen) {
1011                 *buflen = rsclen;
1012                 *status = NDIS_STATUS_INVALID_LENGTH;
1013                 return;
1014         }
1015
1016         bcopy((char *)block->nmb_rlist, (char *)list, rsclen);
1017         *status = NDIS_STATUS_SUCCESS;
1018         return;
1019 }
1020
1021 __stdcall static ndis_status
1022 ndis_register_ioport(void **offset, ndis_handle adapter,
1023                      uint32_t port, uint32_t numports)
1024 {
1025         struct ndis_miniport_block      *block;
1026         struct ndis_softc       *sc;
1027
1028         if (adapter == NULL)
1029                 return(NDIS_STATUS_FAILURE);
1030
1031         block = (ndis_miniport_block *)adapter;
1032         sc = (struct ndis_softc *)(block->nmb_ifp);
1033
1034         if (sc->ndis_res_io == NULL)
1035                 return(NDIS_STATUS_FAILURE);
1036
1037         /* Don't let the device map more ports than we have. */
1038         if (rman_get_size(sc->ndis_res_io) < numports)
1039                 return(NDIS_STATUS_INVALID_LENGTH);
1040
1041         *offset = (void *)rman_get_start(sc->ndis_res_io);
1042
1043         return(NDIS_STATUS_SUCCESS);
1044 }
1045
1046 __stdcall static void
1047 ndis_deregister_ioport(ndis_handle adapter, uint32_t port,
1048                        uint32_t numports, void *offset)
1049 {
1050         return;
1051 }
1052
1053 __stdcall static void
1054 ndis_read_netaddr(ndis_status *status, void **addr,
1055                   uint32_t *addrlen, ndis_handle adapter)
1056 {
1057         struct ndis_softc       *sc;
1058         ndis_miniport_block     *block;
1059         uint8_t                 empty[] = { 0, 0, 0, 0, 0, 0 };
1060
1061         block = (ndis_miniport_block *)adapter;
1062         sc = (struct ndis_softc *)block->nmb_ifp;
1063
1064         if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1065                 *status = NDIS_STATUS_FAILURE;
1066         else {
1067                 *addr = sc->arpcom.ac_enaddr;
1068                 *addrlen = ETHER_ADDR_LEN;
1069                 *status = NDIS_STATUS_SUCCESS;
1070         }
1071
1072         return;
1073 }
1074
1075 __stdcall static ndis_status
1076 ndis_mapreg_cnt(uint32_t bustype, uint32_t *cnt)
1077 {
1078         *cnt = 8192;
1079         return(NDIS_STATUS_SUCCESS);
1080 }
1081
1082 __stdcall static ndis_status
1083 ndis_alloc_mapreg(ndis_handle adapter, uint32_t dmachannel, uint8_t dmasize,
1084                   uint32_t physmapneeded, uint32_t maxmap)
1085 {
1086         struct ndis_softc       *sc;
1087         ndis_miniport_block     *block;
1088         int                     error, i, nseg = NDIS_MAXSEG;
1089
1090         block = (ndis_miniport_block *)adapter;
1091         sc = (struct ndis_softc *)block->nmb_ifp;
1092
1093         sc->ndis_mmaps = kmalloc(sizeof(bus_dmamap_t) * physmapneeded,
1094             M_DEVBUF, M_INTWAIT|M_ZERO);
1095
1096         if (sc->ndis_mmaps == NULL)
1097                 return(NDIS_STATUS_RESOURCES);
1098
1099         error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1100             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1101             NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1102             &sc->ndis_mtag);
1103
1104         if (error) {
1105                 kfree(sc->ndis_mmaps, M_DEVBUF);
1106                 return(NDIS_STATUS_RESOURCES);
1107         }
1108
1109         for (i = 0; i < physmapneeded; i++)
1110                 bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1111
1112         sc->ndis_mmapcnt = physmapneeded;
1113
1114         return(NDIS_STATUS_SUCCESS);
1115 }
1116
1117 __stdcall static void
1118 ndis_free_mapreg(ndis_handle adapter)
1119 {
1120         struct ndis_softc       *sc;
1121         ndis_miniport_block     *block;
1122         int                     i;
1123
1124         block = (ndis_miniport_block *)adapter;
1125         sc = (struct ndis_softc *)block->nmb_ifp;
1126
1127         for (i = 0; i < sc->ndis_mmapcnt; i++)
1128                 bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1129
1130         kfree(sc->ndis_mmaps, M_DEVBUF);
1131
1132         bus_dma_tag_destroy(sc->ndis_mtag);
1133
1134         return;
1135 }
1136
1137 static void
1138 ndis_mapshared_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1139 {
1140         ndis_physaddr           *p;
1141
1142         if (error || nseg > 1)
1143                 return;
1144
1145         p = arg;
1146
1147         p->np_quad = segs[0].ds_addr;
1148
1149         return;
1150 }
1151
1152 /*
1153  * This maps to bus_dmamem_alloc().
1154  */
1155 __stdcall static void
1156 ndis_alloc_sharedmem(ndis_handle adapter, uint32_t len, uint8_t cached,
1157                      void **vaddr, ndis_physaddr *paddr)
1158 {
1159         ndis_miniport_block     *block;
1160         struct ndis_softc       *sc;
1161         struct ndis_shmem       *sh;
1162         int                     error;
1163
1164         if (adapter == NULL)
1165                 return;
1166
1167         block = (ndis_miniport_block *)adapter;
1168         sc = (struct ndis_softc *)(block->nmb_ifp);
1169
1170         sh = kmalloc(sizeof(struct ndis_shmem), M_DEVBUF, M_INTWAIT|M_ZERO);
1171         if (sh == NULL)
1172                 return;
1173
1174         /*
1175          * When performing shared memory allocations, create a tag
1176          * with a lowaddr limit that restricts physical memory mappings
1177          * so that they all fall within the first 1GB of memory.
1178          * At least one device/driver combination (Linksys Instant
1179          * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
1180          * problems with performing DMA operations with physical
1181          * that lie above the 1GB mark. I don't know if this is a
1182          * hardware limitation or if the addresses are being truncated
1183          * within the driver, but this seems to be the only way to
1184          * make these cards work reliably in systems with more than
1185          * 1GB of physical memory.
1186          */
1187
1188         error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1189             0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL,
1190             NULL, len, 1, len, BUS_DMA_ALLOCNOW, 
1191             &sh->ndis_stag);
1192
1193         if (error) {
1194                 kfree(sh, M_DEVBUF);
1195                 return;
1196         }
1197
1198         error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1199             BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1200
1201         if (error) {
1202                 bus_dma_tag_destroy(sh->ndis_stag);
1203                 kfree(sh, M_DEVBUF);
1204                 return;
1205         }
1206
1207         error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1208             len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1209
1210         if (error) {
1211                 bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1212                 bus_dma_tag_destroy(sh->ndis_stag);
1213                 kfree(sh, M_DEVBUF);
1214                 return;
1215         }
1216
1217         sh->ndis_saddr = *vaddr;
1218         sh->ndis_next = sc->ndis_shlist;
1219         sc->ndis_shlist = sh;
1220
1221         return;
1222 }
1223
1224 struct ndis_allocwork {
1225         ndis_handle             na_adapter;
1226         uint32_t                na_len;
1227         uint8_t                 na_cached;
1228         void                    *na_ctx;
1229 };
1230
1231 static void
1232 ndis_asyncmem_complete(void *arg)
1233 {
1234         ndis_miniport_block     *block;
1235         struct ndis_softc       *sc;
1236         struct ndis_allocwork   *w;
1237         void                    *vaddr;
1238         ndis_physaddr           paddr;
1239         ndis_allocdone_handler  donefunc;
1240
1241         w = arg;
1242         block = (ndis_miniport_block *)w->na_adapter;
1243         sc = (struct ndis_softc *)(block->nmb_ifp);
1244
1245         vaddr = NULL;
1246         paddr.np_quad = 0;
1247
1248         donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1249         ndis_alloc_sharedmem(w->na_adapter, w->na_len,
1250             w->na_cached, &vaddr, &paddr);
1251         donefunc(w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
1252
1253         kfree(arg, M_DEVBUF);
1254
1255         return;
1256 }
1257
1258 __stdcall static ndis_status
1259 ndis_alloc_sharedmem_async(ndis_handle adapter, uint32_t len,
1260                            uint8_t cached, void *ctx)
1261 {
1262         struct ndis_allocwork   *w;
1263
1264         if (adapter == NULL)
1265                 return(NDIS_STATUS_FAILURE);
1266
1267         w = kmalloc(sizeof(struct ndis_allocwork), M_TEMP, M_INTWAIT);
1268
1269         if (w == NULL)
1270                 return(NDIS_STATUS_FAILURE);
1271
1272         w->na_adapter = adapter;
1273         w->na_cached = cached;
1274         w->na_len = len;
1275         w->na_ctx = ctx;
1276
1277         /*
1278          * Pawn this work off on the SWI thread instead of the
1279          * taskqueue thread, because sometimes drivers will queue
1280          * up work items on the taskqueue thread that will block,
1281          * which would prevent the memory allocation from completing
1282          * when we need it.
1283          */
1284         ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI);
1285
1286         return(NDIS_STATUS_PENDING);
1287 }
1288
1289 __stdcall static void
1290 ndis_free_sharedmem(ndis_handle adapter, uint32_t len, uint8_t cached,
1291                     void *vaddr, ndis_physaddr paddr)
1292 {
1293         ndis_miniport_block     *block;
1294         struct ndis_softc       *sc;
1295         struct ndis_shmem       *sh, *prev;
1296
1297         if (vaddr == NULL || adapter == NULL)
1298                 return;
1299
1300         block = (ndis_miniport_block *)adapter;
1301         sc = (struct ndis_softc *)(block->nmb_ifp);
1302         sh = prev = sc->ndis_shlist;
1303
1304         while (sh) {
1305                 if (sh->ndis_saddr == vaddr)
1306                         break;
1307                 prev = sh;
1308                 sh = sh->ndis_next;
1309         }
1310
1311         bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1312         bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1313         bus_dma_tag_destroy(sh->ndis_stag);
1314
1315         if (sh == sc->ndis_shlist)
1316                 sc->ndis_shlist = sh->ndis_next;
1317         else
1318                 prev->ndis_next = sh->ndis_next;
1319
1320         kfree(sh, M_DEVBUF);
1321
1322         return;
1323 }
1324
1325 __stdcall static ndis_status
1326 ndis_map_iospace(void **vaddr, ndis_handle adapter, ndis_physaddr paddr,
1327                  uint32_t len)
1328 {
1329         ndis_miniport_block     *block;
1330         struct ndis_softc       *sc;
1331
1332         if (adapter == NULL)
1333                 return(NDIS_STATUS_FAILURE);
1334
1335         block = (ndis_miniport_block *)adapter;
1336         sc = (struct ndis_softc *)(block->nmb_ifp);
1337
1338         if (sc->ndis_res_mem != NULL &&
1339             paddr.np_quad == rman_get_start(sc->ndis_res_mem))
1340                 *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1341         else if (sc->ndis_res_altmem != NULL &&
1342              paddr.np_quad == rman_get_start(sc->ndis_res_altmem))
1343                 *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem);
1344         else if (sc->ndis_res_am != NULL &&
1345              paddr.np_quad == rman_get_start(sc->ndis_res_am))
1346                 *vaddr = (void *)rman_get_virtual(sc->ndis_res_am);
1347         else
1348                 return(NDIS_STATUS_FAILURE);
1349
1350         return(NDIS_STATUS_SUCCESS);
1351 }
1352
1353 __stdcall static void
1354 ndis_unmap_iospace(ndis_handle adapter, void *vaddr, uint32_t len)
1355 {
1356         return;
1357 }
1358
1359 __stdcall static uint32_t
1360 ndis_cachefill(void)
1361 {
1362         return(128);
1363 }
1364
1365 __stdcall static uint32_t
1366 ndis_dma_align(ndis_handle handle)
1367 {
1368         return(128);
1369 }
1370
1371 /*
1372  * NDIS has two methods for dealing with NICs that support DMA.
1373  * One is to just pass packets to the driver and let it call
1374  * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1375  * all by itself, and the other is to let the NDIS library handle the
1376  * buffer mapping internally, and hand the driver an already populated
1377  * scatter/gather fragment list. If the driver calls
1378  * NdisMInitializeScatterGatherDma(), it wants to use the latter
1379  * method.
1380  */
1381
1382 __stdcall static ndis_status
1383 ndis_init_sc_dma(ndis_handle adapter, uint8_t is64, uint32_t maxphysmap)
1384 {
1385         struct ndis_softc       *sc;
1386         ndis_miniport_block     *block;
1387         int                     error;
1388
1389         if (adapter == NULL)
1390                 return(NDIS_STATUS_FAILURE);
1391         block = (ndis_miniport_block *)adapter;
1392         sc = (struct ndis_softc *)block->nmb_ifp;
1393
1394         /* Don't do this twice. */
1395         if (sc->ndis_sc == 1)
1396                 return(NDIS_STATUS_SUCCESS);
1397
1398         error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1399             BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1400             MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1401             &sc->ndis_ttag);
1402
1403         sc->ndis_sc = 1;
1404
1405         return(NDIS_STATUS_SUCCESS);
1406 }
1407
1408 __stdcall static void
1409 ndis_alloc_packetpool(ndis_status *status, ndis_handle *pool,
1410                       uint32_t descnum, uint32_t protrsvdlen)
1411 {
1412         ndis_packet             *cur;
1413         int                     i;
1414
1415         *pool = kmalloc(sizeof(ndis_packet) *
1416             ((descnum + NDIS_POOL_EXTRA) + 1),
1417             M_DEVBUF, M_WAITOK|M_ZERO);
1418         cur = (ndis_packet *)*pool;
1419         cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1420         cur->np_private.npp_totlen = 0; /* init deletetion flag */
1421         for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1422                 cur->np_private.npp_head = (ndis_handle)(cur + 1);
1423                 cur++;
1424         }
1425
1426         *status = NDIS_STATUS_SUCCESS;
1427         return;
1428 }
1429
1430 __stdcall static void
1431 ndis_ex_alloc_packetpool(ndis_status *status, ndis_handle *pool,
1432                          uint32_t descnum, uint32_t oflowdescnum,
1433                          uint32_t protrsvdlen)
1434 {
1435         return(ndis_alloc_packetpool(status, pool,
1436             descnum + oflowdescnum, protrsvdlen));
1437 }
1438
1439 __stdcall static uint32_t
1440 ndis_packetpool_use(ndis_handle pool)
1441 {
1442         ndis_packet             *head;
1443
1444         head = (ndis_packet *)pool;
1445
1446         return(head->np_private.npp_count);
1447 }
1448
1449 __stdcall static void
1450 ndis_free_packetpool(ndis_handle pool)
1451 {
1452         ndis_packet             *head;
1453
1454         head = pool;
1455
1456         /* Mark this pool as 'going away.' */
1457
1458         head->np_private.npp_totlen = 1;
1459
1460         /* If there are no buffers loaned out, destroy the pool. */
1461
1462         if (head->np_private.npp_count == 0)
1463                 kfree(pool, M_DEVBUF);
1464         else
1465                 kprintf("NDIS: buggy driver deleting active packet pool!\n");
1466
1467         return;
1468 }
1469
1470 __stdcall static void
1471 ndis_alloc_packet(ndis_status *status, ndis_packet **packet, ndis_handle pool)
1472 {
1473         ndis_packet             *head, *pkt;
1474
1475         head = (ndis_packet *)pool;
1476
1477         if (head->np_private.npp_flags != 0x1) {
1478                 *status = NDIS_STATUS_FAILURE;
1479                 return;
1480         }
1481
1482         /*
1483          * If this pool is marked as 'going away' don't allocate any
1484          * more packets out of it.
1485          */
1486
1487         if (head->np_private.npp_totlen) {
1488                 *status = NDIS_STATUS_FAILURE;
1489                 return;
1490         }
1491
1492         pkt = (ndis_packet *)head->np_private.npp_head;
1493
1494         if (pkt == NULL) {
1495                 *status = NDIS_STATUS_RESOURCES;
1496                 return;
1497         }
1498
1499         head->np_private.npp_head = pkt->np_private.npp_head;
1500
1501         pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1502         /* Save pointer to the pool. */
1503         pkt->np_private.npp_pool = head;
1504
1505         /* Set the oob offset pointer. Lots of things expect this. */
1506         pkt->np_private.npp_packetooboffset =
1507             offsetof(ndis_packet, np_oob);
1508
1509         /*
1510          * We must initialize the packet flags correctly in order
1511          * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
1512          * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly.
1513          */
1514         pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
1515
1516         *packet = pkt;
1517
1518         head->np_private.npp_count++;
1519         *status = NDIS_STATUS_SUCCESS;
1520         return;
1521 }
1522
1523 __stdcall static void
1524 ndis_release_packet(ndis_packet *packet)
1525 {
1526         ndis_packet             *head;
1527
1528         if (packet == NULL || packet->np_private.npp_pool == NULL)
1529                 return;
1530
1531         head = packet->np_private.npp_pool;
1532         if (head->np_private.npp_flags != 0x1)
1533                 return;
1534
1535         packet->np_private.npp_head = head->np_private.npp_head;
1536         head->np_private.npp_head = (ndis_buffer *)packet;
1537         head->np_private.npp_count--;
1538
1539         /*
1540          * If the pool has been marked for deletion and there are
1541          * no more packets outstanding, nuke the pool.
1542          */
1543
1544         if (head->np_private.npp_totlen && head->np_private.npp_count == 0)
1545                 kfree(head, M_DEVBUF);
1546
1547         return;
1548 }
1549
1550 __stdcall static void
1551 ndis_unchain_headbuf(ndis_packet *packet, ndis_buffer **buf)
1552 {
1553         ndis_packet_private     *priv;
1554
1555         if (packet == NULL || buf == NULL)
1556                 return;
1557
1558         priv = &packet->np_private;
1559
1560         priv->npp_validcounts = FALSE;
1561
1562         if (priv->npp_head == priv->npp_tail) {
1563                 *buf = priv->npp_head;
1564                 priv->npp_head = priv->npp_tail = NULL;
1565         } else {
1566                 *buf = priv->npp_head;
1567                 priv->npp_head = (*buf)->nb_next;
1568         }
1569
1570         return;
1571 }
1572
1573 __stdcall static void
1574 ndis_unchain_tailbuf(ndis_packet *packet, ndis_buffer **buf)
1575 {
1576         ndis_packet_private     *priv;
1577         ndis_buffer             *tmp;
1578
1579         if (packet == NULL || buf == NULL)
1580                 return;
1581
1582         priv = &packet->np_private;
1583
1584         priv->npp_validcounts = FALSE;
1585
1586         if (priv->npp_head == priv->npp_tail) {
1587                 *buf = priv->npp_head;
1588                 priv->npp_head = priv->npp_tail = NULL;
1589         } else {
1590                 *buf = priv->npp_tail;
1591                 tmp = priv->npp_head;
1592                 while (tmp->nb_next != priv->npp_tail)
1593                         tmp = tmp->nb_next;
1594                 priv->npp_tail = tmp;
1595                 tmp->nb_next = NULL;
1596         }
1597
1598         return;
1599 }
1600
1601 /*
1602  * The NDIS "buffer" manipulation functions are somewhat misnamed.
1603  * They don't really allocate buffers: they allocate buffer mappings.
1604  * The idea is you reserve a chunk of DMA-able memory using
1605  * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1606  * to obtain the virtual address of the DMA-able region.
1607  * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1608  */
1609
1610 __stdcall static void
1611 ndis_alloc_bufpool(ndis_status *status, ndis_handle *pool,
1612                    uint32_t descnum)
1613 {
1614         ndis_buffer             *cur;
1615         int                     i;
1616
1617         *pool = kmalloc(sizeof(ndis_buffer) *
1618             ((descnum + NDIS_POOL_EXTRA) + 1),
1619             M_DEVBUF, M_WAITOK|M_ZERO);
1620         cur = (ndis_buffer *)*pool;
1621         cur->nb_flags = 0x1; /* mark the head of the list */
1622         cur->nb_bytecount = 0; /* init usage count */
1623         cur->nb_byteoffset = 0; /* init deletetion flag */
1624         for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1625                 cur->nb_next = cur + 1;
1626                 cur++;
1627         }
1628
1629         *status = NDIS_STATUS_SUCCESS;
1630         return;
1631 }
1632
1633 __stdcall static void
1634 ndis_free_bufpool(ndis_handle pool)
1635 {
1636         ndis_buffer             *head;
1637
1638         head = pool;
1639
1640         /* Mark this pool as 'going away.' */
1641
1642         head->nb_byteoffset = 1;
1643
1644         /* If there are no buffers loaned out, destroy the pool. */
1645         if (head->nb_bytecount == 0)
1646                 kfree(pool, M_DEVBUF);
1647         else
1648                 kprintf("NDIS: buggy driver deleting active buffer pool!\n");
1649
1650         return;
1651 }
1652
1653 /*
1654  * This maps to a bus_dmamap_create() and bus_dmamap_load().
1655  */
1656 __stdcall static void
1657 ndis_alloc_buf(ndis_status *status, ndis_buffer **buffer, ndis_handle pool,
1658                void *vaddr, uint32_t len)
1659 {
1660         ndis_buffer             *head, *buf;
1661
1662         head = (ndis_buffer *)pool;
1663         if (head->nb_flags != 0x1) {
1664                 *status = NDIS_STATUS_FAILURE;
1665                 return;
1666         }
1667
1668         /*
1669          * If this pool is marked as 'going away' don't allocate any
1670          * more buffers out of it.
1671          */
1672
1673         if (head->nb_byteoffset) {
1674                 *status = NDIS_STATUS_FAILURE;
1675                 return;
1676         }
1677
1678         buf = head->nb_next;
1679
1680         if (buf == NULL) {
1681                 *status = NDIS_STATUS_RESOURCES;
1682                 return;
1683         }
1684
1685         head->nb_next = buf->nb_next;
1686
1687         /* Save pointer to the pool. */
1688         buf->nb_process = head;
1689
1690         MDL_INIT(buf, vaddr, len);
1691
1692         *buffer = buf;
1693
1694         /* Increment count of busy buffers. */
1695
1696         head->nb_bytecount++;
1697
1698         *status = NDIS_STATUS_SUCCESS;
1699         return;
1700 }
1701
1702 __stdcall static void
1703 ndis_release_buf(ndis_buffer *buf)
1704 {
1705         ndis_buffer             *head;
1706
1707         if (buf == NULL || buf->nb_process == NULL)
1708                 return;
1709
1710         head = buf->nb_process;
1711
1712         if (head->nb_flags != 0x1)
1713                 return;
1714
1715         buf->nb_next = head->nb_next;
1716         head->nb_next = buf;
1717
1718         /* Decrement count of busy buffers. */
1719
1720         head->nb_bytecount--;
1721
1722         /*
1723          * If the pool has been marked for deletion and there are
1724          * no more buffers outstanding, nuke the pool.
1725          */
1726
1727         if (head->nb_byteoffset && head->nb_bytecount == 0)
1728                 kfree(head, M_DEVBUF);
1729
1730         return;
1731 }
1732
1733 /* Aw c'mon. */
1734
1735 __stdcall static uint32_t
1736 ndis_buflen(ndis_buffer *buf)
1737 {
1738         return(buf->nb_bytecount);
1739 }
1740
1741 /*
1742  * Get the virtual address and length of a buffer.
1743  * Note: the vaddr argument is optional.
1744  */
1745
1746 __stdcall static void
1747 ndis_query_buf(ndis_buffer *buf, void **vaddr, uint32_t *len)
1748 {
1749         if (vaddr != NULL)
1750                 *vaddr = MDL_VA(buf);
1751         *len = buf->nb_bytecount;
1752
1753         return;
1754 }
1755
1756 /* Same as above -- we don't care about the priority. */
1757
1758 __stdcall static void
1759 ndis_query_buf_safe(ndis_buffer *buf, void **vaddr,
1760                     uint32_t *len, uint32_t prio)
1761 {
1762         if (vaddr != NULL)
1763                 *vaddr = MDL_VA(buf);
1764         *len = buf->nb_bytecount;
1765
1766         return;
1767 }
1768
1769 /* Damnit Microsoft!! How many ways can you do the same thing?! */
1770
1771 __stdcall static void *
1772 ndis_buf_vaddr(ndis_buffer *buf)
1773 {
1774         return(MDL_VA(buf));
1775 }
1776
1777 __stdcall static void *
1778 ndis_buf_vaddr_safe(ndis_buffer *buf, uint32_t prio)
1779 {
1780         return(MDL_VA(buf));
1781 }
1782
1783 __stdcall static void
1784 ndis_adjust_buflen(ndis_buffer *buf, int len)
1785 {
1786         buf->nb_bytecount = len;
1787
1788         return;
1789 }
1790
1791 __stdcall static uint32_t
1792 ndis_interlock_inc(uint32_t *addend)
1793 {
1794         atomic_add_long((u_long *)addend, 1);
1795         return(*addend);
1796 }
1797
1798 __stdcall static uint32_t
1799 ndis_interlock_dec(uint32_t *addend)
1800 {
1801         atomic_subtract_long((u_long *)addend, 1);
1802         return(*addend);
1803 }
1804
1805 __stdcall static void
1806 ndis_init_event(ndis_event *event)
1807 {
1808         /*
1809          * NDIS events are always notification
1810          * events, and should be initialized to the
1811          * not signaled state.
1812          */
1813  
1814         ntoskrnl_init_event(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE);
1815         return;
1816 }
1817
1818 __stdcall static void
1819 ndis_set_event(ndis_event *event)
1820 {
1821         ntoskrnl_set_event(&event->ne_event, 0, 0);
1822         return;
1823 }
1824
1825 __stdcall static void
1826 ndis_reset_event(ndis_event *event)
1827 {
1828         ntoskrnl_reset_event(&event->ne_event);
1829         return;
1830 }
1831
1832 __stdcall static uint8_t
1833 ndis_wait_event(ndis_event *event, uint32_t msecs)
1834 {
1835         int64_t                 duetime;
1836         uint32_t                rval;
1837
1838         duetime = ((int64_t)msecs * -10000);
1839
1840         rval = ntoskrnl_waitforobj((nt_dispatch_header *)event,
1841             0, 0, TRUE, msecs ? &duetime : NULL);
1842
1843         if (rval == STATUS_TIMEOUT)
1844                 return(FALSE);
1845
1846         return(TRUE);
1847 }
1848
1849 __stdcall static ndis_status
1850 ndis_unicode2ansi(ndis_ansi_string *dstr, ndis_unicode_string *sstr)
1851 {
1852         if (dstr == NULL || sstr == NULL)
1853                 return(NDIS_STATUS_FAILURE);
1854         if (ndis_unicode_to_ascii(sstr->nus_buf,
1855             sstr->nus_len, &dstr->nas_buf))
1856                 return(NDIS_STATUS_FAILURE);
1857         dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
1858         return (NDIS_STATUS_SUCCESS);
1859 }
1860
1861 __stdcall static ndis_status
1862 ndis_ansi2unicode(ndis_unicode_string *dstr, ndis_ansi_string *sstr)
1863 {
1864         char                    *str;
1865         if (dstr == NULL || sstr == NULL)
1866                 return(NDIS_STATUS_FAILURE);
1867         str = kmalloc(sstr->nas_len + 1, M_DEVBUF, M_WAITOK);
1868         strncpy(str, sstr->nas_buf, sstr->nas_len);
1869         *(str + sstr->nas_len) = '\0';
1870         if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
1871                 kfree(str, M_DEVBUF);
1872                 return(NDIS_STATUS_FAILURE);
1873         }
1874         dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
1875         kfree(str, M_DEVBUF);
1876         return (NDIS_STATUS_SUCCESS);
1877 }
1878
1879 __stdcall static ndis_status
1880 ndis_assign_pcirsrc(ndis_handle adapter, uint32_t slot,
1881                     ndis_resource_list **list)
1882 {
1883         ndis_miniport_block     *block;
1884
1885         if (adapter == NULL || list == NULL)
1886                 return (NDIS_STATUS_FAILURE);
1887
1888         block = (ndis_miniport_block *)adapter;
1889         *list = block->nmb_rlist;
1890
1891         return (NDIS_STATUS_SUCCESS);
1892 }
1893
1894 __stdcall static ndis_status
1895 ndis_register_intr(ndis_miniport_interrupt *intr, ndis_handle adapter,
1896                    uint32_t ivec, uint32_t ilevel, uint8_t reqisr,
1897                    uint8_t shared, ndis_interrupt_mode imode)
1898 {
1899         ndis_miniport_block     *block;
1900
1901         block = adapter;
1902
1903         intr->ni_block = adapter;
1904         intr->ni_isrreq = reqisr;
1905         intr->ni_shared = shared;
1906         block->nmb_interrupt = intr;
1907         return(NDIS_STATUS_SUCCESS);
1908 }       
1909
1910 __stdcall static void
1911 ndis_deregister_intr(ndis_miniport_interrupt *intr)
1912 {
1913         return;
1914 }
1915
1916 __stdcall static void
1917 ndis_register_shutdown(ndis_handle adapter, void *shutdownctx,
1918                        ndis_shutdown_handler shutdownfunc)
1919 {
1920         ndis_miniport_block     *block;
1921         ndis_miniport_characteristics *chars;
1922         struct ndis_softc       *sc;
1923
1924         if (adapter == NULL)
1925                 return;
1926
1927         block = (ndis_miniport_block *)adapter;
1928         sc = (struct ndis_softc *)block->nmb_ifp;
1929         chars = &sc->ndis_chars;
1930
1931         chars->nmc_shutdown_handler = shutdownfunc;
1932         chars->nmc_rsvd0 = shutdownctx;
1933
1934         return;
1935 }
1936
1937 __stdcall static void
1938 ndis_deregister_shutdown(ndis_handle adapter)
1939 {
1940         ndis_miniport_block     *block;
1941         ndis_miniport_characteristics *chars;
1942         struct ndis_softc       *sc;
1943
1944         if (adapter == NULL)
1945                 return;
1946
1947         block = (ndis_miniport_block *)adapter;
1948         sc = (struct ndis_softc *)block->nmb_ifp;
1949         chars = &sc->ndis_chars;
1950
1951         chars->nmc_shutdown_handler = NULL;
1952         chars->nmc_rsvd0 = NULL;
1953
1954         return;
1955 }
1956
1957 __stdcall static uint32_t
1958 ndis_numpages(ndis_buffer *buf)
1959 {
1960         if (buf == NULL)
1961                 return(0);
1962         if (buf->nb_bytecount == 0)
1963                 return(1);
1964         return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
1965 }
1966
1967 __stdcall static void
1968 ndis_buf_physpages(ndis_buffer *buf, uint32_t *pages)
1969 {
1970         if (buf == NULL)
1971                 return;
1972
1973         *pages = ndis_numpages(buf);
1974         return;
1975 }
1976
1977 __stdcall static void
1978 ndis_query_bufoffset(ndis_buffer *buf, uint32_t *off, uint32_t *len)
1979 {
1980         if (buf == NULL)
1981                 return;
1982
1983         *off = buf->nb_byteoffset;
1984         *len = buf->nb_bytecount;
1985
1986         return;
1987 }
1988
1989 __stdcall static void
1990 ndis_sleep(uint32_t usecs)
1991 {
1992         struct timeval          tv;
1993
1994         tv.tv_sec = 0;
1995         tv.tv_usec = usecs;
1996
1997         ndis_thsuspend(curthread, 1 + usecs * hz / 1000000);
1998
1999         return;
2000 }
2001
2002 __stdcall static uint32_t
2003 ndis_read_pccard_amem(ndis_handle handle, uint32_t offset, void *buf,
2004                       uint32_t len)
2005 {
2006         struct ndis_softc       *sc;
2007         ndis_miniport_block     *block;
2008         bus_space_handle_t      bh;
2009         bus_space_tag_t         bt;
2010         char                    *dest;
2011         int                     i;
2012
2013         if (handle == NULL)
2014                 return(0);
2015
2016         block = (ndis_miniport_block *)handle;
2017         sc = (struct ndis_softc *)block->nmb_ifp;
2018         dest = buf;
2019
2020         bh = rman_get_bushandle(sc->ndis_res_am);
2021         bt = rman_get_bustag(sc->ndis_res_am);
2022
2023         for (i = 0; i < len; i++)
2024                 dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2);
2025
2026         return(i);
2027 }
2028
2029 __stdcall static uint32_t
2030 ndis_write_pccard_amem(ndis_handle handle, uint32_t offset, void *buf,
2031                        uint32_t len)
2032 {
2033         struct ndis_softc       *sc;
2034         ndis_miniport_block     *block;
2035         bus_space_handle_t      bh;
2036         bus_space_tag_t         bt;
2037         char                    *src;
2038         int                     i;
2039
2040         if (handle == NULL)
2041                 return(0);
2042
2043         block = (ndis_miniport_block *)handle;
2044         sc = (struct ndis_softc *)block->nmb_ifp;
2045         src = buf;
2046
2047         bh = rman_get_bushandle(sc->ndis_res_am);
2048         bt = rman_get_bustag(sc->ndis_res_am);
2049
2050         for (i = 0; i < len; i++)
2051                 bus_space_write_1(bt, bh, (offset + i) * 2, src[i]);
2052
2053         return(i);
2054 }
2055
2056 __stdcall static list_entry *
2057 ndis_insert_head(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
2058 {
2059         list_entry              *flink;
2060
2061         lock->nsl_kirql = FASTCALL2(hal_lock,
2062             &lock->nsl_spinlock, DISPATCH_LEVEL);
2063         flink = head->nle_flink;
2064         entry->nle_flink = flink;
2065         entry->nle_blink = head;
2066         flink->nle_blink = entry;
2067         head->nle_flink = entry;
2068         FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2069
2070         return(flink);
2071 }
2072
2073 __stdcall static list_entry *
2074 ndis_remove_head(list_entry *head, ndis_spin_lock *lock)
2075 {
2076         list_entry              *flink;
2077         list_entry              *entry;
2078
2079         lock->nsl_kirql = FASTCALL2(hal_lock,
2080             &lock->nsl_spinlock, DISPATCH_LEVEL);
2081         entry = head->nle_flink;
2082         flink = entry->nle_flink;
2083         head->nle_flink = flink;
2084         flink->nle_blink = head;
2085         FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2086
2087         return(entry);
2088 }
2089
2090 __stdcall static list_entry *
2091 ndis_insert_tail(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
2092 {
2093         list_entry              *blink;
2094
2095         lock->nsl_kirql = FASTCALL2(hal_lock,
2096             &lock->nsl_spinlock, DISPATCH_LEVEL);
2097         blink = head->nle_blink;
2098         entry->nle_flink = head;
2099         entry->nle_blink = blink;
2100         blink->nle_flink = entry;
2101         head->nle_blink = entry;
2102         FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2103
2104         return(blink);
2105 }
2106
2107 __stdcall static uint8_t
2108 ndis_sync_with_intr(ndis_miniport_interrupt *intr, void *syncfunc,
2109                     void *syncctx)
2110 {
2111         struct ndis_softc       *sc;
2112         struct ifnet            *ifp;
2113         __stdcall uint8_t (*sync)(void *);
2114         uint8_t                 rval;
2115
2116         if (syncfunc == NULL || syncctx == NULL)
2117                 return(0);
2118
2119         sc = (struct ndis_softc *)intr->ni_block->nmb_ifp;
2120         ifp = &sc->arpcom.ac_if;
2121         sync = syncfunc;
2122         rval = sync(syncctx);
2123
2124         return(rval);
2125 }
2126
2127 /*
2128  * Return the number of 100 nanosecond intervals since
2129  * January 1, 1601. (?!?!)
2130  */
2131 __stdcall static void
2132 ndis_time(uint64_t *tval)
2133 {
2134         struct timespec         ts;
2135
2136         nanotime(&ts);
2137         *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2138             11644473600LL;
2139
2140         return;
2141 }
2142
2143 /*
2144  * Return the number of milliseconds since the system booted.
2145  */
2146 __stdcall static void
2147 ndis_uptime(uint32_t *tval)
2148 {
2149         struct timespec         ts;
2150
2151         nanouptime(&ts);
2152         *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
2153
2154         return;
2155 }
2156
2157 __stdcall static void
2158 ndis_init_string(ndis_unicode_string *dst, char *src)
2159 {
2160         ndis_unicode_string     *u;
2161
2162         u = dst;
2163         u->nus_buf = NULL;
2164         if (ndis_ascii_to_unicode(src, &u->nus_buf))
2165                 return;
2166         u->nus_len = u->nus_maxlen = strlen(src) * 2;
2167         return;
2168 }
2169
2170 __stdcall static void
2171 ndis_free_string(ndis_unicode_string *str)
2172 {
2173         if (str == NULL)
2174                 return;
2175         if (str->nus_buf != NULL)
2176                 kfree(str->nus_buf, M_DEVBUF);
2177         kfree(str, M_DEVBUF);
2178         return;
2179 }
2180
2181 __stdcall static ndis_status
2182 ndis_remove_miniport(ndis_handle *adapter)
2183 {
2184         return(NDIS_STATUS_SUCCESS);
2185 }
2186
2187 __stdcall static void
2188 ndis_init_ansi_string(ndis_ansi_string *dst, char *src)
2189 {
2190         ndis_ansi_string        *a;
2191
2192         a = dst;
2193         if (a == NULL)
2194                 return;
2195         if (src == NULL) {
2196                 a->nas_len = a->nas_maxlen = 0;
2197                 a->nas_buf = NULL;
2198         } else {
2199                 a->nas_buf = src;
2200                 a->nas_len = a->nas_maxlen = strlen(src);
2201         }
2202
2203         return;
2204 }
2205
2206 __stdcall static void
2207 ndis_init_unicode_string(ndis_unicode_string *dst, uint16_t *src)
2208 {
2209         ndis_unicode_string     *u;
2210         int                     i;
2211
2212         u = dst;
2213         if (u == NULL)
2214                 return;
2215         if (src == NULL) {
2216                 u->nus_len = u->nus_maxlen = 0;
2217                 u->nus_buf = NULL;
2218         } else {
2219                 i = 0;
2220                 while(src[i] != 0)
2221                         i++;
2222                 u->nus_buf = src;
2223                 u->nus_len = u->nus_maxlen = i * 2;
2224         }
2225
2226         return;
2227 }
2228
2229 __stdcall static void
2230 ndis_get_devprop(ndis_handle adapter, device_object **phydevobj,
2231                  device_object **funcdevobj, device_object **nextdevobj,
2232                  cm_resource_list *resources, cm_resource_list *transresources)
2233 {
2234         ndis_miniport_block     *block;
2235
2236         block = (ndis_miniport_block *)adapter;
2237
2238         if (phydevobj != NULL)
2239                 *phydevobj = &block->nmb_devobj;
2240         if (funcdevobj != NULL)
2241                 *funcdevobj = &block->nmb_devobj;
2242
2243         return;
2244 }
2245
2246 __stdcall static void
2247 ndis_firstbuf(ndis_packet *packet, ndis_buffer **buf, void **firstva,
2248               uint32_t *firstlen, uint32_t *totlen)
2249 {
2250         ndis_buffer             *tmp;
2251
2252         tmp = packet->np_private.npp_head;
2253         *buf = tmp;
2254         if (tmp == NULL) {
2255                 *firstva = NULL;
2256                 *firstlen = *totlen = 0;
2257         } else {
2258                 *firstva = MDL_VA(tmp);
2259                 *firstlen = *totlen = tmp->nb_bytecount;
2260                 for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
2261                         *totlen += tmp->nb_bytecount;
2262         }
2263
2264         return;
2265 }
2266
2267 __stdcall static void
2268 ndis_firstbuf_safe(ndis_packet *packet, ndis_buffer **buf, void **firstva,
2269                    uint32_t *firstlen, uint32_t *totlen, uint32_t prio)
2270 {
2271         ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
2272 }
2273
2274 /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2275 __stdcall static void
2276 ndis_open_file(ndis_status *status, ndis_handle *filehandle, uint32_t *filelength,
2277                ndis_unicode_string *filename, ndis_physaddr highestaddr)
2278 {
2279         char                    *afilename = NULL;
2280         struct nlookupdata      nd;
2281         int                     error;
2282         struct vattr            vat;
2283         struct vattr            *vap = &vat;
2284         ndis_fh                 *fh;
2285         struct vnode            *vp;
2286         char                    path[MAXPATHLEN];
2287
2288         ndis_unicode_to_ascii(filename->nus_buf,
2289             filename->nus_len, &afilename);
2290
2291         ksprintf(path, "%s/%s", ndis_filepath, afilename);
2292         kfree(afilename, M_DEVBUF);
2293
2294         fh = kmalloc(sizeof(ndis_fh), M_TEMP, M_WAITOK);
2295
2296         error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW|NLC_LOCKVP);
2297         if (error == 0)
2298                 error = vn_open(&nd, NULL, FREAD, 0);
2299         if (error) {
2300                 *status = NDIS_STATUS_FILE_NOT_FOUND;
2301                 kfree(fh, M_TEMP);
2302                 kprintf("NDIS: open file %s failed: %d\n", path, error);
2303                 goto done;
2304         }
2305
2306         vp = nd.nl_open_vp;
2307         nd.nl_open_vp = NULL;
2308
2309         /* Get the file size. */
2310         VOP_GETATTR(vp, vap);
2311         vn_unlock(vp);
2312
2313         fh->nf_vp = vp;
2314         fh->nf_map = NULL;
2315         *filehandle = fh;
2316         *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
2317         *status = NDIS_STATUS_SUCCESS;
2318
2319 done:
2320         nlookup_done(&nd);
2321         return;
2322 }
2323
2324 __stdcall static void
2325 ndis_map_file(ndis_status *status, void **mappedbuffer, ndis_handle filehandle)
2326 {
2327         ndis_fh                 *fh;
2328         int                     error, resid;
2329
2330         if (filehandle == NULL) {
2331                 *status = NDIS_STATUS_FAILURE;
2332                 return;
2333         }
2334
2335         fh = (ndis_fh *)filehandle;
2336
2337         if (fh->nf_vp == NULL) {
2338                 *status = NDIS_STATUS_FAILURE;
2339                 return;
2340         }
2341
2342         if (fh->nf_map != NULL) {
2343                 *status = NDIS_STATUS_ALREADY_MAPPED;
2344                 return;
2345         }
2346
2347         fh->nf_map = kmalloc(fh->nf_maplen, M_DEVBUF, M_WAITOK);
2348
2349         error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
2350                         UIO_SYSSPACE, 0, proc0.p_ucred, &resid);
2351
2352         if (error)
2353                 *status = NDIS_STATUS_FAILURE;
2354         else {
2355                 *status = NDIS_STATUS_SUCCESS;
2356                 *mappedbuffer = fh->nf_map;
2357         }
2358
2359         return;
2360 }
2361
2362 __stdcall static void
2363 ndis_unmap_file(ndis_handle filehandle)
2364 {
2365         ndis_fh                 *fh;
2366         fh = (ndis_fh *)filehandle;
2367
2368         if (fh->nf_map == NULL)
2369                 return;
2370         kfree(fh->nf_map, M_DEVBUF);
2371         fh->nf_map = NULL;
2372
2373         return;
2374 }
2375
2376 __stdcall static void
2377 ndis_close_file(ndis_handle filehandle)
2378 {
2379         ndis_fh                 *fh;
2380
2381         if (filehandle == NULL)
2382                 return;
2383
2384         fh = (ndis_fh *)filehandle;
2385         if (fh->nf_map != NULL) {
2386                 kfree(fh->nf_map, M_DEVBUF);
2387                 fh->nf_map = NULL;
2388         }
2389
2390         if (fh->nf_vp == NULL)
2391                 return;
2392
2393         vn_close(fh->nf_vp, FREAD);
2394
2395         fh->nf_vp = NULL;
2396         kfree(fh, M_DEVBUF);
2397
2398         return;
2399 }
2400
2401 __stdcall static uint8_t
2402 ndis_cpu_cnt(void)
2403 {
2404         return(ncpus);
2405 }
2406
2407 typedef __stdcall void (*ndis_statusdone_handler)(ndis_handle);
2408 typedef __stdcall void (*ndis_status_handler)(ndis_handle, ndis_status,
2409         void *, uint32_t);
2410
2411 __stdcall static void
2412 ndis_ind_statusdone(ndis_handle adapter)
2413 {
2414         ndis_miniport_block     *block;
2415         ndis_statusdone_handler statusdonefunc;
2416
2417         block = (ndis_miniport_block *)adapter;
2418         statusdonefunc = block->nmb_statusdone_func;
2419
2420         statusdonefunc(adapter);
2421         return;
2422 }
2423
2424 __stdcall static void
2425 ndis_ind_status(ndis_handle adapter, ndis_status status, void *sbuf,
2426                 uint32_t slen)
2427 {
2428         ndis_miniport_block     *block;
2429         ndis_status_handler     statusfunc;
2430
2431         block = (ndis_miniport_block *)adapter;
2432         statusfunc = block->nmb_status_func;
2433
2434         statusfunc(adapter, status, sbuf, slen);
2435         return;
2436 }
2437
2438 static void
2439 ndis_workfunc(void *ctx)
2440 {
2441         ndis_work_item          *work;
2442         ndis_proc               workfunc;
2443
2444         work = ctx;
2445         workfunc = work->nwi_func;
2446         workfunc(work, work->nwi_ctx);
2447         return;
2448 }
2449
2450 __stdcall static ndis_status
2451 ndis_sched_workitem(ndis_work_item *work)
2452 {
2453         ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
2454         return(NDIS_STATUS_SUCCESS);
2455 }
2456
2457 __stdcall static void
2458 ndis_pkt_to_pkt(ndis_packet *dpkt, uint32_t doff, uint32_t reqlen,
2459                 ndis_packet *spkt, uint32_t soff, uint32_t *cpylen)
2460 {
2461         ndis_buffer             *src, *dst;
2462         char                    *sptr, *dptr;
2463         int                     resid, copied, len, scnt, dcnt;
2464
2465         *cpylen = 0;
2466
2467         src = spkt->np_private.npp_head;
2468         dst = dpkt->np_private.npp_head;
2469
2470         sptr = MDL_VA(src);
2471         dptr = MDL_VA(dst);
2472         scnt = src->nb_bytecount;
2473         dcnt = dst->nb_bytecount;
2474
2475         while (soff) {
2476                 if (src->nb_bytecount > soff) {
2477                         sptr += soff;
2478                         scnt = src->nb_bytecount - soff;
2479                         break;
2480                 }
2481                 soff -= src->nb_bytecount;
2482                 src = src->nb_next;
2483                 if (src == NULL)
2484                         return;
2485                 sptr = MDL_VA(src);
2486         }
2487
2488         while (doff) {
2489                 if (dst->nb_bytecount > doff) {
2490                         dptr += doff;
2491                         dcnt = dst->nb_bytecount - doff;
2492                         break;
2493                 }
2494                 doff -= dst->nb_bytecount;
2495                 dst = dst->nb_next;
2496                 if (dst == NULL)
2497                         return;
2498                 dptr = MDL_VA(dst);
2499         }
2500
2501         resid = reqlen;
2502         copied = 0;
2503
2504         while(1) {
2505                 if (resid < scnt)
2506                         len = resid;
2507                 else
2508                         len = scnt;
2509                 if (dcnt < len)
2510                         len = dcnt;
2511
2512                 bcopy(sptr, dptr, len);
2513
2514                 copied += len;
2515                 resid -= len;
2516                 if (resid == 0)
2517                         break;
2518
2519                 dcnt -= len;
2520                 if (dcnt == 0) {
2521                         dst = dst->nb_next;
2522                         if (dst == NULL)
2523                                 break;
2524                         dptr = MDL_VA(dst);
2525                         dcnt = dst->nb_bytecount;
2526                 }
2527
2528                 scnt -= len;
2529                 if (scnt == 0) {
2530                         src = src->nb_next;
2531                         if (src == NULL)
2532                                 break;
2533                         sptr = MDL_VA(src);
2534                         scnt = src->nb_bytecount;
2535                 }
2536         }
2537
2538         *cpylen = copied;
2539         return;
2540 }
2541
2542 __stdcall static void
2543 ndis_pkt_to_pkt_safe(ndis_packet *dpkt, uint32_t doff, uint32_t reqlen,
2544                      ndis_packet *spkt, uint32_t soff, uint32_t *cpylen,
2545                      uint32_t prio)
2546 {
2547         ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen);
2548         return;
2549 }
2550
2551 __stdcall static ndis_status
2552 ndis_register_dev(ndis_handle handle, ndis_unicode_string *devname,
2553                   ndis_unicode_string *symname, driver_dispatch **majorfuncs,
2554                   void **devobj, ndis_handle *devhandle)
2555 {
2556         ndis_miniport_block     *block;
2557
2558         block = (ndis_miniport_block *)handle;
2559         *devobj = &block->nmb_devobj;
2560         *devhandle = handle;
2561
2562         return(NDIS_STATUS_SUCCESS);
2563 }
2564
2565 __stdcall static ndis_status
2566 ndis_deregister_dev(ndis_handle handle)
2567 {
2568         return(NDIS_STATUS_SUCCESS);
2569 }
2570
2571 __stdcall static ndis_status
2572 ndis_query_name(ndis_unicode_string *name, ndis_handle handle)
2573 {
2574         ndis_miniport_block     *block;
2575
2576         block = (ndis_miniport_block *)handle;
2577         ndis_ascii_to_unicode(__DECONST(char *,
2578             device_get_nameunit(block->nmb_dev)), &name->nus_buf);
2579         name->nus_len = strlen(device_get_nameunit(block->nmb_dev)) * 2;
2580
2581         return(NDIS_STATUS_SUCCESS);
2582 }
2583
2584 __stdcall static void
2585 ndis_register_unload(ndis_handle handle, void *func)
2586 {
2587         return;
2588 }
2589
2590 __stdcall static void
2591 dummy(void)
2592 {
2593         kprintf ("NDIS dummy called...\n");
2594         return;
2595 }
2596
2597 image_patch_table ndis_functbl[] = {
2598         { "NdisCopyFromPacketToPacket", (FUNC)ndis_pkt_to_pkt },
2599         { "NdisCopyFromPacketToPacketSafe", (FUNC)ndis_pkt_to_pkt_safe },
2600         { "NdisScheduleWorkItem",       (FUNC)ndis_sched_workitem },
2601         { "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone },
2602         { "NdisMIndicateStatus",        (FUNC)ndis_ind_status },
2603         { "NdisSystemProcessorCount",   (FUNC)ndis_cpu_cnt },
2604         { "NdisUnchainBufferAtBack",    (FUNC)ndis_unchain_tailbuf, },
2605         { "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf },
2606         { "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe },
2607         { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2608         { "NdisMGetDeviceProperty",     (FUNC)ndis_get_devprop },
2609         { "NdisInitAnsiString",         (FUNC)ndis_init_ansi_string },
2610         { "NdisInitUnicodeString",      (FUNC)ndis_init_unicode_string },
2611         { "NdisWriteConfiguration",     (FUNC)ndis_write_cfg },
2612         { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2613         { "NdisTerminateWrapper",       (FUNC)ndis_termwrap },
2614         { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2615         { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2616         { "NdisMRemoveMiniport",        (FUNC)ndis_remove_miniport },
2617         { "NdisInitializeString",       (FUNC)ndis_init_string },       
2618         { "NdisFreeString",             (FUNC)ndis_free_string },       
2619         { "NdisGetCurrentSystemTime",   (FUNC)ndis_time },
2620         { "NdisGetSystemUpTime",        (FUNC)ndis_uptime },
2621         { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2622         { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2623         { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2624         { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2625         { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2626         { "NdisInitializeWrapper",      (FUNC)ndis_initwrap },
2627         { "NdisMRegisterMiniport",      (FUNC)ndis_register_miniport },
2628         { "NdisAllocateMemoryWithTag",  (FUNC)ndis_malloc_withtag },
2629         { "NdisAllocateMemory",         (FUNC)ndis_malloc },
2630         { "NdisMSetAttributesEx",       (FUNC)ndis_setattr_ex },
2631         { "NdisCloseConfiguration",     (FUNC)ndis_close_cfg },
2632         { "NdisReadConfiguration",      (FUNC)ndis_read_cfg },
2633         { "NdisOpenConfiguration",      (FUNC)ndis_open_cfg },
2634         { "NdisAcquireSpinLock",        (FUNC)ndis_lock },
2635         { "NdisReleaseSpinLock",        (FUNC)ndis_unlock },
2636         { "NdisDprAcquireSpinLock",     (FUNC)ndis_lock_dpr },
2637         { "NdisDprReleaseSpinLock",     (FUNC)ndis_unlock_dpr },
2638         { "NdisAllocateSpinLock",       (FUNC)ndis_create_lock },
2639         { "NdisFreeSpinLock",           (FUNC)ndis_destroy_lock },
2640         { "NdisFreeMemory",             (FUNC)ndis_free },
2641         { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci },
2642         { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2643         { "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci },
2644         { "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci },
2645         { "NdisWriteErrorLogEntry",     (FUNC)ndis_syslog },
2646         { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2647         { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2648         { "NdisMInitializeTimer",       (FUNC)ndis_create_timer },
2649         { "NdisInitializeTimer",        (FUNC)ndis_init_timer },
2650         { "NdisSetTimer",               (FUNC)ndis_set_timer },
2651         { "NdisMCancelTimer",           (FUNC)ndis_cancel_timer },
2652         { "NdisCancelTimer",            (FUNC)ndis_cancel_timer },
2653         { "NdisMSetPeriodicTimer",      (FUNC)ndis_set_periodic_timer },
2654         { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources },
2655         { "NdisMRegisterIoPortRange",   (FUNC)ndis_register_ioport },
2656         { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport },
2657         { "NdisReadNetworkAddress",     (FUNC)ndis_read_netaddr },
2658         { "NdisQueryMapRegisterCount",  (FUNC)ndis_mapreg_cnt },
2659         { "NdisMAllocateMapRegisters",  (FUNC)ndis_alloc_mapreg },
2660         { "NdisMFreeMapRegisters",      (FUNC)ndis_free_mapreg },
2661         { "NdisMAllocateSharedMemory",  (FUNC)ndis_alloc_sharedmem },
2662         { "NdisMMapIoSpace",            (FUNC)ndis_map_iospace },
2663         { "NdisMUnmapIoSpace",          (FUNC)ndis_unmap_iospace },
2664         { "NdisGetCacheFillSize",       (FUNC)ndis_cachefill },
2665         { "NdisMGetDmaAlignment",       (FUNC)ndis_dma_align },
2666         { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2667         { "NdisAllocatePacketPool",     (FUNC)ndis_alloc_packetpool },
2668         { "NdisAllocatePacketPoolEx",   (FUNC)ndis_ex_alloc_packetpool },
2669         { "NdisAllocatePacket",         (FUNC)ndis_alloc_packet },
2670         { "NdisFreePacket",             (FUNC)ndis_release_packet },
2671         { "NdisFreePacketPool",         (FUNC)ndis_free_packetpool },
2672         { "NdisDprAllocatePacket",      (FUNC)ndis_alloc_packet },
2673         { "NdisDprFreePacket",          (FUNC)ndis_release_packet },
2674         { "NdisAllocateBufferPool",     (FUNC)ndis_alloc_bufpool },
2675         { "NdisAllocateBuffer",         (FUNC)ndis_alloc_buf },
2676         { "NdisQueryBuffer",            (FUNC)ndis_query_buf },
2677         { "NdisQueryBufferSafe",        (FUNC)ndis_query_buf_safe },
2678         { "NdisBufferVirtualAddress",   (FUNC)ndis_buf_vaddr },
2679         { "NdisBufferVirtualAddressSafe", (FUNC)ndis_buf_vaddr_safe },
2680         { "NdisBufferLength",           (FUNC)ndis_buflen },
2681         { "NdisFreeBuffer",             (FUNC)ndis_release_buf },
2682         { "NdisFreeBufferPool",         (FUNC)ndis_free_bufpool },
2683         { "NdisInterlockedIncrement",   (FUNC)ndis_interlock_inc },
2684         { "NdisInterlockedDecrement",   (FUNC)ndis_interlock_dec },
2685         { "NdisInitializeEvent",        (FUNC)ndis_init_event },
2686         { "NdisSetEvent",               (FUNC)ndis_set_event },
2687         { "NdisResetEvent",             (FUNC)ndis_reset_event },
2688         { "NdisWaitEvent",              (FUNC)ndis_wait_event },
2689         { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2690         { "NdisMPciAssignResources",    (FUNC)ndis_assign_pcirsrc },
2691         { "NdisMFreeSharedMemory",      (FUNC)ndis_free_sharedmem },
2692         { "NdisMRegisterInterrupt",     (FUNC)ndis_register_intr },
2693         { "NdisMDeregisterInterrupt",   (FUNC)ndis_deregister_intr },
2694         { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2695         { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
2696         { "NDIS_BUFFER_TO_SPAN_PAGES",  (FUNC)ndis_numpages },
2697         { "NdisQueryBufferOffset",      (FUNC)ndis_query_bufoffset },
2698         { "NdisAdjustBufferLength",     (FUNC)ndis_adjust_buflen },
2699         { "NdisPacketPoolUsage",        (FUNC)ndis_packetpool_use },
2700         { "NdisMSleep",                 (FUNC)ndis_sleep },
2701         { "NdisUnchainBufferAtFront",   (FUNC)ndis_unchain_headbuf },
2702         { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
2703         { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
2704         { "NdisOpenFile",               (FUNC)ndis_open_file },
2705         { "NdisMapFile",                (FUNC)ndis_map_file },
2706         { "NdisUnmapFile",              (FUNC)ndis_unmap_file },
2707         { "NdisCloseFile",              (FUNC)ndis_close_file },
2708         { "NdisMRegisterDevice",        (FUNC)ndis_register_dev },
2709         { "NdisMDeregisterDevice",      (FUNC)ndis_deregister_dev },
2710         { "NdisMQueryAdapterInstanceName", (FUNC)ndis_query_name },
2711         { "NdisMRegisterUnloadHandler", (FUNC)ndis_register_unload },
2712
2713         /*
2714          * This last entry is a catch-all for any function we haven't
2715          * implemented yet. The PE import list patching routine will
2716          * use it for any function that doesn't have an explicit match
2717          * in this table.
2718          */
2719
2720         { NULL, (FUNC)dummy },
2721
2722         /* End of list. */
2723
2724         { NULL, NULL },
2725 };