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