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