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