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