subr_ndis.c revision 125069
1123474Swpaul/*
2123474Swpaul * Copyright (c) 2003
3123474Swpaul *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
4123474Swpaul *
5123474Swpaul * Redistribution and use in source and binary forms, with or without
6123474Swpaul * modification, are permitted provided that the following conditions
7123474Swpaul * are met:
8123474Swpaul * 1. Redistributions of source code must retain the above copyright
9123474Swpaul *    notice, this list of conditions and the following disclaimer.
10123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright
11123474Swpaul *    notice, this list of conditions and the following disclaimer in the
12123474Swpaul *    documentation and/or other materials provided with the distribution.
13123474Swpaul * 3. All advertising materials mentioning features or use of this software
14123474Swpaul *    must display the following acknowledgement:
15123474Swpaul *	This product includes software developed by Bill Paul.
16123474Swpaul * 4. Neither the name of the author nor the names of any co-contributors
17123474Swpaul *    may be used to endorse or promote products derived from this software
18123474Swpaul *    without specific prior written permission.
19123474Swpaul *
20123474Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21123474Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22123474Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23123474Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24123474Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25123474Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26123474Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27123474Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28123474Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29123474Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30123474Swpaul * THE POSSIBILITY OF SUCH DAMAGE.
31123474Swpaul */
32123474Swpaul
33123474Swpaul#include <sys/cdefs.h>
34123474Swpaul__FBSDID("$FreeBSD: head/sys/compat/ndis/subr_ndis.c 125069 2004-01-27 08:10:34Z wpaul $");
35123474Swpaul
36123474Swpaul/*
37123474Swpaul * This file implements a translation layer between the BSD networking
38123474Swpaul * infrasturcture and Windows(R) NDIS network driver modules. A Windows
39123474Swpaul * NDIS driver calls into several functions in the NDIS.SYS Windows
40123474Swpaul * kernel module and exports a table of functions designed to be called
41123474Swpaul * by the NDIS subsystem. Using the PE loader, we can patch our own
42123474Swpaul * versions of the NDIS routines into a given Windows driver module and
43123474Swpaul * convince the driver that it is in fact running on Windows.
44123474Swpaul *
45123474Swpaul * We provide a table of all our implemented NDIS routines which is patched
46123474Swpaul * into the driver object code. All our exported routines must use the
47123474Swpaul * _stdcall calling convention, since that's what the Windows object code
48123474Swpaul * expects.
49123474Swpaul */
50123474Swpaul
51123474Swpaul
52123474Swpaul#include <sys/param.h>
53123474Swpaul#include <sys/types.h>
54123474Swpaul#include <sys/errno.h>
55123474Swpaul
56123474Swpaul#include <sys/callout.h>
57123474Swpaul#include <sys/kernel.h>
58123474Swpaul#include <sys/systm.h>
59123474Swpaul#include <sys/malloc.h>
60123474Swpaul#include <sys/lock.h>
61123474Swpaul#include <sys/mutex.h>
62123474Swpaul#include <sys/socket.h>
63123474Swpaul#include <sys/sysctl.h>
64123504Swpaul#include <sys/timespec.h>
65123848Swpaul#include <sys/smp.h>
66124122Swpaul#include <sys/queue.h>
67124272Swpaul#include <sys/proc.h>
68124272Swpaul#include <sys/namei.h>
69124272Swpaul#include <sys/fcntl.h>
70124272Swpaul#include <sys/vnode.h>
71123474Swpaul
72123474Swpaul#include <net/if.h>
73123474Swpaul#include <net/if_arp.h>
74123474Swpaul#include <net/ethernet.h>
75123474Swpaul#include <net/if_dl.h>
76123474Swpaul#include <net/if_media.h>
77123474Swpaul
78124203Swpaul#include <machine/atomic.h>
79123474Swpaul#include <machine/bus_memio.h>
80123474Swpaul#include <machine/bus_pio.h>
81123474Swpaul#include <machine/bus.h>
82123474Swpaul#include <machine/resource.h>
83123474Swpaul
84123474Swpaul#include <sys/bus.h>
85123474Swpaul#include <sys/rman.h>
86123474Swpaul
87123474Swpaul#include <machine/stdarg.h>
88123474Swpaul
89123695Swpaul#include <net80211/ieee80211_var.h>
90123695Swpaul#include <net80211/ieee80211_ioctl.h>
91123695Swpaul
92123474Swpaul#include <dev/pci/pcireg.h>
93123474Swpaul#include <dev/pci/pcivar.h>
94123474Swpaul
95123474Swpaul#include <compat/ndis/pe_var.h>
96123474Swpaul#include <compat/ndis/resource_var.h>
97123512Swpaul#include <compat/ndis/ntoskrnl_var.h>
98123474Swpaul#include <compat/ndis/ndis_var.h>
99123474Swpaul#include <compat/ndis/cfg_var.h>
100123474Swpaul#include <dev/if_ndis/if_ndisvar.h>
101123474Swpaul
102123474Swpaul#define FUNC void(*)(void)
103123474Swpaul
104124409Swpaulstatic struct mtx *ndis_interlock;
105124272Swpaulstatic char ndis_filepath[MAXPATHLEN];
106124409Swpaulstruct mtx_pool *ndis_mtxpool;
107125057Swpaulextern struct nd_head ndis_devhead;
108123474Swpaul
109124272SwpaulSYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
110124272Swpaul        MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
111124272Swpaul
112123474Swpaul__stdcall static void ndis_initwrap(ndis_handle,
113123474Swpaul	ndis_driver_object *, void *, void *);
114123474Swpaul__stdcall static ndis_status ndis_register_miniport(ndis_handle,
115123474Swpaul	ndis_miniport_characteristics *, int);
116123474Swpaul__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
117123474Swpaul__stdcall static ndis_status ndis_malloc(void **,
118123474Swpaul	uint32_t, uint32_t, ndis_physaddr);
119123474Swpaul__stdcall static void ndis_free(void *, uint32_t, uint32_t);
120123474Swpaul__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
121123474Swpaul	uint32_t, uint32_t, ndis_interface_type);
122123474Swpaul__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
123123526Swpaul__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle,
124123526Swpaul	uint32_t, ndis_unicode_string *, ndis_handle *);
125123526Swpaul__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle,
126123526Swpaul	ndis_unicode_string *, ndis_handle *);
127123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *,
128123474Swpaul	struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
129123526Swpaulstatic ndis_status ndis_decode_parm(ndis_miniport_block *,
130123526Swpaul	ndis_config_parm *, char *);
131123474Swpaul__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
132123474Swpaul	ndis_handle, ndis_unicode_string *, ndis_parm_type);
133123526Swpaul__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle,
134123526Swpaul	ndis_unicode_string *, ndis_config_parm *);
135123474Swpaul__stdcall static void ndis_close_cfg(ndis_handle);
136123474Swpaul__stdcall static void ndis_create_lock(ndis_spin_lock *);
137123474Swpaul__stdcall static void ndis_destroy_lock(ndis_spin_lock *);
138123474Swpaul__stdcall static void ndis_lock(ndis_spin_lock *);
139123474Swpaul__stdcall static void ndis_unlock(ndis_spin_lock *);
140123474Swpaul__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
141123474Swpaul	uint32_t, void *, uint32_t);
142123474Swpaul__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
143123474Swpaul	uint32_t, void *, uint32_t);
144123474Swpaulstatic void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
145123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
146123474Swpaul__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
147123474Swpaul	uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
148123474Swpaul__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
149123474Swpaul__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *,
150123474Swpaul	ndis_timer_function, void *);
151125057Swpaul__stdcall static void ndis_init_timer(ndis_timer *,
152125057Swpaul	ndis_timer_function, void *);
153123474Swpaulstatic void ndis_timercall(void *);
154123474Swpaul__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t);
155123474Swpaulstatic void ndis_tick(void *);
156123474Swpaul__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
157123474Swpaul__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *);
158123474Swpaul__stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
159123474Swpaul	ndis_resource_list *, uint32_t *);
160123474Swpaul__stdcall static ndis_status ndis_register_ioport(void **,
161123474Swpaul	ndis_handle, uint32_t, uint32_t);
162123474Swpaul__stdcall static void ndis_deregister_ioport(ndis_handle,
163123474Swpaul	uint32_t, uint32_t, void *);
164123474Swpaul__stdcall static void ndis_read_netaddr(ndis_status *, void **,
165123474Swpaul	uint32_t *, ndis_handle);
166123848Swpaul__stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *);
167123474Swpaul__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
168123474Swpaul	uint32_t, uint8_t, uint32_t, uint32_t);
169123474Swpaul__stdcall static void ndis_free_mapreg(ndis_handle);
170123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
171123474Swpaul__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
172123474Swpaul	uint8_t, void **, ndis_physaddr *);
173123474Swpaul__stdcall static void ndis_alloc_sharedmem_async(ndis_handle,
174123474Swpaul	uint32_t, uint8_t, void *);
175123474Swpaul__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
176123474Swpaul	uint8_t, void *, ndis_physaddr);
177123474Swpaul__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
178123474Swpaul	ndis_physaddr, uint32_t);
179123474Swpaul__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
180123474Swpaul__stdcall static uint32_t ndis_cachefill(void);
181123474Swpaul__stdcall static uint32_t ndis_dma_align(ndis_handle);
182123474Swpaul__stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
183123474Swpaul	uint8_t, uint32_t);
184123474Swpaul__stdcall static void ndis_alloc_packetpool(ndis_status *,
185123474Swpaul	ndis_handle *, uint32_t, uint32_t);
186123474Swpaul__stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
187123474Swpaul	ndis_handle *, uint32_t, uint32_t, uint32_t);
188123474Swpaul__stdcall static uint32_t ndis_packetpool_use(ndis_handle);
189123474Swpaul__stdcall static void ndis_free_packetpool(ndis_handle);
190123474Swpaul__stdcall static void ndis_alloc_packet(ndis_status *,
191123474Swpaul	ndis_packet **, ndis_handle);
192123474Swpaul__stdcall static void ndis_release_packet(ndis_packet *);
193123474Swpaul__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
194123721Swpaul__stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **);
195123474Swpaul__stdcall static void ndis_alloc_bufpool(ndis_status *,
196123474Swpaul	ndis_handle *, uint32_t);
197123474Swpaul__stdcall static void ndis_free_bufpool(ndis_handle);
198123474Swpaul__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
199123474Swpaul	ndis_handle, void *, uint32_t);
200123474Swpaul__stdcall static void ndis_release_buf(ndis_buffer *);
201124100Swpaul__stdcall static uint32_t ndis_buflen(ndis_buffer *);
202123474Swpaul__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
203123474Swpaul__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
204123474Swpaul	uint32_t *, uint32_t);
205125069Swpaul__stdcall static void *ndis_buf_vaddr(ndis_buffer *);
206125069Swpaul__stdcall static void *ndis_buf_vaddr_safe(ndis_buffer *, uint32_t);
207123474Swpaul__stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
208123474Swpaul__stdcall static uint32_t ndis_interlock_inc(uint32_t *);
209123474Swpaul__stdcall static uint32_t ndis_interlock_dec(uint32_t *);
210123474Swpaul__stdcall static void ndis_init_event(ndis_event *);
211123474Swpaul__stdcall static void ndis_set_event(ndis_event *);
212123474Swpaul__stdcall static void ndis_reset_event(ndis_event *);
213123474Swpaul__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
214123474Swpaul__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
215123474Swpaul	ndis_unicode_string *);
216123526Swpaul__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
217123526Swpaul	ndis_ansi_string *);
218123474Swpaul__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
219123474Swpaul	uint32_t, ndis_resource_list **);
220123474Swpaul__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
221123474Swpaul	ndis_handle, uint32_t, uint32_t, uint8_t,
222123474Swpaul	uint8_t, ndis_interrupt_mode);
223123474Swpaul__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
224123474Swpaul__stdcall static void ndis_register_shutdown(ndis_handle, void *,
225123474Swpaul	ndis_shutdown_handler);
226123474Swpaul__stdcall static void ndis_deregister_shutdown(ndis_handle);
227123474Swpaul__stdcall static uint32_t ndis_numpages(ndis_buffer *);
228123573Swpaul__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
229123474Swpaul__stdcall static void ndis_query_bufoffset(ndis_buffer *,
230123474Swpaul	uint32_t *, uint32_t *);
231123474Swpaul__stdcall static void ndis_sleep(uint32_t);
232123474Swpaul__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
233123474Swpaul	uint32_t, void *, uint32_t);
234123474Swpaul__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
235123474Swpaul	uint32_t, void *, uint32_t);
236123474Swpaul__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *,
237123474Swpaul	ndis_list_entry *, ndis_spin_lock *);
238123474Swpaul__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *,
239123474Swpaul	ndis_spin_lock *);
240123474Swpaul__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *,
241123474Swpaul	ndis_list_entry *, ndis_spin_lock *);
242123474Swpaul__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
243123474Swpaul	void *, void *);
244123504Swpaul__stdcall static void ndis_time(uint64_t *);
245123822Swpaul__stdcall static void ndis_uptime(uint32_t *);
246124100Swpaul__stdcall static void ndis_init_string(ndis_unicode_string *, char *);
247123526Swpaul__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
248123941Swpaul__stdcall static void ndis_init_unicode_string(ndis_unicode_string *,
249123941Swpaul	uint16_t *);
250123507Swpaul__stdcall static void ndis_free_string(ndis_unicode_string *);
251123507Swpaul__stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
252123526Swpaul__stdcall static void ndis_termwrap(ndis_handle, void *);
253123526Swpaul__stdcall static void ndis_get_devprop(ndis_handle, void *, void *,
254123526Swpaul	void *, cm_resource_list *, cm_resource_list *);
255123721Swpaul__stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
256123721Swpaul	void **, uint32_t *, uint32_t *);
257123721Swpaul__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
258123721Swpaul	void **, uint32_t *, uint32_t *, uint32_t);
259123822Swpaul__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
260123822Swpaul	ndis_unicode_string *, ndis_physaddr);
261123822Swpaul__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
262123822Swpaul__stdcall static void ndis_unmap_file(ndis_handle);
263123822Swpaul__stdcall static void ndis_close_file(ndis_handle);
264123848Swpaul__stdcall static u_int8_t ndis_cpu_cnt(void);
265124116Swpaul__stdcall static void ndis_ind_statusdone(ndis_handle);
266124116Swpaul__stdcall static void ndis_ind_status(ndis_handle, ndis_status,
267124116Swpaul        void *, uint32_t);
268124697Swpaulstatic void ndis_workfunc(void *);
269124122Swpaul__stdcall static ndis_status ndis_sched_workitem(ndis_work_item *);
270124541Swpaul__stdcall static void ndis_pkt_to_pkt(ndis_packet *, uint32_t, uint32_t,
271124541Swpaul	ndis_packet *, uint32_t, uint32_t *);
272124541Swpaul__stdcall static void ndis_pkt_to_pkt_safe(ndis_packet *, uint32_t, uint32_t,
273124541Swpaul	ndis_packet *, uint32_t, uint32_t *, uint32_t);
274125057Swpaul__stdcall static ndis_status ndis_register_dev(ndis_handle *,
275125057Swpaul	ndis_unicode_string *, ndis_unicode_string *, void *,
276125057Swpaul	void *, ndis_handle **);
277125057Swpaul__stdcall static ndis_status ndis_deregister_dev(ndis_handle *);
278123474Swpaul__stdcall static void dummy(void);
279123474Swpaul
280124116Swpaul/*
281124116Swpaul * Some really old drivers do not properly check the return value
282124116Swpaul * from NdisAllocatePacket() and NdisAllocateBuffer() and will
283124116Swpaul * sometimes allocate few more buffers/packets that they originally
284124116Swpaul * requested when they created the pool. To prevent this from being
285124116Swpaul * a problem, we allocate a few extra buffers/packets beyond what
286124116Swpaul * the driver asks for. This #define controls how many.
287124116Swpaul */
288124116Swpaul#define NDIS_POOL_EXTRA		16
289123474Swpaul
290123474Swpaulint
291123474Swpaulndis_libinit()
292123474Swpaul{
293124272Swpaul	strcpy(ndis_filepath, "/compat/ndis");
294124409Swpaul	ndis_mtxpool = mtx_pool_create("ndis mutex pool",
295124409Swpaul	    1024, MTX_DEF | MTX_RECURSE | MTX_DUPOK);;
296124409Swpaul	ndis_interlock = mtx_pool_alloc(ndis_mtxpool);
297123474Swpaul	return(0);
298123474Swpaul}
299123474Swpaul
300123474Swpaulint
301123474Swpaulndis_libfini()
302123474Swpaul{
303124409Swpaul	mtx_pool_destroy(&ndis_mtxpool);
304123474Swpaul	return(0);
305123474Swpaul}
306123474Swpaul
307123474Swpaul/*
308123474Swpaul * NDIS deals with strings in unicode format, so we have
309123474Swpaul * do deal with them that way too. For now, we only handle
310123474Swpaul * conversion between unicode and ASCII since that's all
311123474Swpaul * that device drivers care about.
312123474Swpaul */
313123474Swpaul
314123474Swpaulint
315123474Swpaulndis_ascii_to_unicode(ascii, unicode)
316123474Swpaul	char			*ascii;
317123474Swpaul	uint16_t		**unicode;
318123474Swpaul{
319123474Swpaul	uint16_t		*ustr;
320123474Swpaul	int			i;
321123474Swpaul
322123474Swpaul	if (*unicode == NULL)
323123474Swpaul		*unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
324123474Swpaul
325123474Swpaul	if (*unicode == NULL)
326123474Swpaul		return(ENOMEM);
327123474Swpaul	ustr = *unicode;
328123474Swpaul	for (i = 0; i < strlen(ascii); i++) {
329123474Swpaul		*ustr = (uint16_t)ascii[i];
330123474Swpaul		ustr++;
331123474Swpaul	}
332123474Swpaul
333123474Swpaul	return(0);
334123474Swpaul}
335123474Swpaul
336123474Swpaulint
337123474Swpaulndis_unicode_to_ascii(unicode, ulen, ascii)
338123474Swpaul	uint16_t		*unicode;
339123474Swpaul	int			ulen;
340123474Swpaul	char			**ascii;
341123474Swpaul{
342123474Swpaul	uint8_t			*astr;
343123474Swpaul	int			i;
344123474Swpaul
345123474Swpaul	if (*ascii == NULL)
346124100Swpaul		*ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO);
347123474Swpaul	if (*ascii == NULL)
348123474Swpaul		return(ENOMEM);
349123474Swpaul	astr = *ascii;
350124100Swpaul	for (i = 0; i < ulen / 2; i++) {
351123474Swpaul		*astr = (uint8_t)unicode[i];
352123474Swpaul		astr++;
353123474Swpaul	}
354123474Swpaul
355123474Swpaul	return(0);
356123474Swpaul}
357123474Swpaul
358123474Swpaul__stdcall static void
359123474Swpaulndis_initwrap(wrapper, drv_obj, path, unused)
360123474Swpaul	ndis_handle		wrapper;
361123474Swpaul	ndis_driver_object	*drv_obj;
362123474Swpaul	void			*path;
363123474Swpaul	void			*unused;
364123474Swpaul{
365123474Swpaul	ndis_driver_object	**drv;
366123474Swpaul
367123474Swpaul	drv = wrapper;
368123474Swpaul	*drv = drv_obj;
369123474Swpaul
370123474Swpaul	return;
371123474Swpaul}
372123474Swpaul
373123526Swpaul__stdcall static void
374123526Swpaulndis_termwrap(handle, syspec)
375123526Swpaul	ndis_handle		handle;
376123526Swpaul	void			*syspec;
377123526Swpaul{
378123526Swpaul	return;
379123526Swpaul}
380123526Swpaul
381123474Swpaul__stdcall static ndis_status
382123474Swpaulndis_register_miniport(handle, characteristics, len)
383123474Swpaul	ndis_handle		handle;
384123474Swpaul	ndis_miniport_characteristics *characteristics;
385123474Swpaul	int			len;
386123474Swpaul{
387123474Swpaul	ndis_driver_object	*drv;
388123474Swpaul
389123474Swpaul	drv = handle;
390123474Swpaul	bcopy((char *)characteristics, (char *)&drv->ndo_chars,
391123474Swpaul	    sizeof(ndis_miniport_characteristics));
392123474Swpaul	return(NDIS_STATUS_SUCCESS);
393123474Swpaul}
394123474Swpaul
395123474Swpaul__stdcall static ndis_status
396123474Swpaulndis_malloc_withtag(vaddr, len, tag)
397123474Swpaul	void			**vaddr;
398123474Swpaul	uint32_t		len;
399123474Swpaul	uint32_t		tag;
400123474Swpaul{
401123474Swpaul	void			*mem;
402123474Swpaul
403123474Swpaul	mem = malloc(len, M_DEVBUF, M_NOWAIT);
404123474Swpaul	if (mem == NULL)
405123474Swpaul		return(NDIS_STATUS_RESOURCES);
406123474Swpaul	*vaddr = mem;
407123474Swpaul
408123474Swpaul	return(NDIS_STATUS_SUCCESS);
409123474Swpaul}
410123474Swpaul
411123474Swpaul__stdcall static ndis_status
412123474Swpaulndis_malloc(vaddr, len, flags, highaddr)
413123474Swpaul	void			**vaddr;
414123474Swpaul	uint32_t		len;
415123474Swpaul	uint32_t		flags;
416123474Swpaul	ndis_physaddr		highaddr;
417123474Swpaul{
418123474Swpaul	void			*mem;
419123474Swpaul
420123474Swpaul	mem = malloc(len, M_DEVBUF, M_NOWAIT);
421123474Swpaul	if (mem == NULL)
422123474Swpaul		return(NDIS_STATUS_RESOURCES);
423123474Swpaul	*vaddr = mem;
424123474Swpaul
425123474Swpaul	return(NDIS_STATUS_SUCCESS);
426123474Swpaul}
427123474Swpaul
428123474Swpaul__stdcall static void
429123474Swpaulndis_free(vaddr, len, flags)
430123474Swpaul	void			*vaddr;
431123474Swpaul	uint32_t		len;
432123474Swpaul	uint32_t		flags;
433123474Swpaul{
434123474Swpaul	if (len == 0)
435123474Swpaul		return;
436123474Swpaul	free(vaddr, M_DEVBUF);
437123474Swpaul	return;
438123474Swpaul}
439123474Swpaul
440123474Swpaul__stdcall static ndis_status
441123474Swpaulndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
442123474Swpaul			flags, iftype)
443123474Swpaul	ndis_handle			adapter_handle;
444123474Swpaul	ndis_handle			adapter_ctx;
445123474Swpaul	uint32_t			hangsecs;
446123474Swpaul	uint32_t			flags;
447123474Swpaul	ndis_interface_type		iftype;
448123474Swpaul{
449123474Swpaul	ndis_miniport_block		*block;
450123474Swpaul
451123474Swpaul	/*
452123474Swpaul	 * Save the adapter context, we need it for calling
453123474Swpaul	 * the driver's internal functions.
454123474Swpaul	 */
455123474Swpaul	block = (ndis_miniport_block *)adapter_handle;
456123474Swpaul	block->nmb_miniportadapterctx = adapter_ctx;
457123474Swpaul	block->nmb_checkforhangsecs = hangsecs;
458123474Swpaul
459123474Swpaul	return(NDIS_STATUS_SUCCESS);
460123474Swpaul}
461123474Swpaul
462123474Swpaul__stdcall static void
463123474Swpaulndis_open_cfg(status, cfg, wrapctx)
464123474Swpaul	ndis_status		*status;
465123474Swpaul	ndis_handle		*cfg;
466123474Swpaul	ndis_handle		wrapctx;
467123474Swpaul{
468123474Swpaul	*cfg = wrapctx;
469123474Swpaul	*status = NDIS_STATUS_SUCCESS;
470123474Swpaul	return;
471123474Swpaul}
472123474Swpaul
473123526Swpaul__stdcall static void
474123526Swpaulndis_open_cfgbyname(status, cfg, subkey, subhandle)
475123526Swpaul	ndis_status		*status;
476123526Swpaul	ndis_handle		cfg;
477123526Swpaul	ndis_unicode_string	*subkey;
478123526Swpaul	ndis_handle		*subhandle;
479123526Swpaul{
480123526Swpaul	*subhandle = cfg;
481123526Swpaul	*status = NDIS_STATUS_SUCCESS;
482123526Swpaul	return;
483123526Swpaul}
484123526Swpaul
485123526Swpaul__stdcall static void
486123526Swpaulndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle)
487123526Swpaul	ndis_status		*status;
488123526Swpaul	ndis_handle		cfg;
489123526Swpaul	uint32_t		idx;
490123526Swpaul	ndis_unicode_string	*subkey;
491123526Swpaul	ndis_handle		*subhandle;
492123526Swpaul{
493123526Swpaul	*status = NDIS_STATUS_FAILURE;
494123526Swpaul	return;
495123526Swpaul}
496123526Swpaul
497123474Swpaulstatic ndis_status
498123474Swpaulndis_encode_parm(block, oid, type, parm)
499123474Swpaul	ndis_miniport_block	*block;
500123474Swpaul        struct sysctl_oid	*oid;
501123474Swpaul	ndis_parm_type		type;
502123474Swpaul	ndis_config_parm	**parm;
503123474Swpaul{
504123474Swpaul	uint16_t		*unicode;
505123474Swpaul	ndis_unicode_string	*ustr;
506123474Swpaul
507123474Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
508123474Swpaul
509123474Swpaul	switch(type) {
510123474Swpaul	case ndis_parm_string:
511123474Swpaul		ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
512123474Swpaul		(*parm)->ncp_type = ndis_parm_string;
513123474Swpaul		ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
514123474Swpaul		ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
515123474Swpaul		ustr->nus_buf = unicode;
516123474Swpaul		break;
517123474Swpaul	case ndis_parm_int:
518123474Swpaul		(*parm)->ncp_type = ndis_parm_int;
519123474Swpaul		(*parm)->ncp_parmdata.ncp_intdata =
520123474Swpaul		    strtol((char *)oid->oid_arg1, NULL, 10);
521123474Swpaul		break;
522123474Swpaul	case ndis_parm_hexint:
523123474Swpaul		(*parm)->ncp_type = ndis_parm_hexint;
524123474Swpaul		(*parm)->ncp_parmdata.ncp_intdata =
525123474Swpaul		    strtoul((char *)oid->oid_arg1, NULL, 16);
526123474Swpaul		break;
527123474Swpaul	default:
528123474Swpaul		return(NDIS_STATUS_FAILURE);
529123474Swpaul		break;
530123474Swpaul	}
531123474Swpaul
532123474Swpaul	return(NDIS_STATUS_SUCCESS);
533123474Swpaul}
534123474Swpaul
535123474Swpaul__stdcall static void
536123474Swpaulndis_read_cfg(status, parm, cfg, key, type)
537123474Swpaul	ndis_status		*status;
538123474Swpaul	ndis_config_parm	**parm;
539123474Swpaul	ndis_handle		cfg;
540123474Swpaul	ndis_unicode_string	*key;
541123474Swpaul	ndis_parm_type		type;
542123474Swpaul{
543123474Swpaul	char			*keystr = NULL;
544123474Swpaul	uint16_t		*unicode;
545123474Swpaul	ndis_miniport_block	*block;
546123474Swpaul	struct ndis_softc	*sc;
547123474Swpaul        struct sysctl_oid	*oidp;
548123474Swpaul	struct sysctl_ctx_entry	*e;
549123474Swpaul
550123474Swpaul	block = (ndis_miniport_block *)cfg;
551123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
552123474Swpaul
553124100Swpaul	if (key->nus_len == 0 || key->nus_buf == NULL) {
554124100Swpaul		*status = NDIS_STATUS_FAILURE;
555124100Swpaul		return;
556124100Swpaul	}
557124100Swpaul
558123474Swpaul	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
559123474Swpaul
560123474Swpaul	*parm = &block->nmb_replyparm;
561123474Swpaul	bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
562123474Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
563123474Swpaul
564123474Swpaul	/*
565123474Swpaul	 * See if registry key is already in a list of known keys
566123474Swpaul	 * included with the driver.
567123474Swpaul	 */
568123474Swpaul	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
569123474Swpaul		oidp = e->entry;
570123474Swpaul		if (strcmp(oidp->oid_name, keystr) == 0) {
571123488Swpaul			if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
572123488Swpaul				free(keystr, M_DEVBUF);
573123488Swpaul				*status = NDIS_STATUS_FAILURE;
574123488Swpaul				return;
575123488Swpaul			}
576123474Swpaul			*status = ndis_encode_parm(block, oidp, type, parm);
577123474Swpaul			free(keystr, M_DEVBUF);
578123474Swpaul			return;
579123474Swpaul		}
580123474Swpaul	}
581123474Swpaul
582123474Swpaul	/*
583123474Swpaul	 * If the key didn't match, add it to the list of dynamically
584123474Swpaul	 * created ones. Sometimes, drivers refer to registry keys
585123474Swpaul	 * that aren't documented in their .INF files. These keys
586123474Swpaul	 * are supposed to be created by some sort of utility or
587123474Swpaul	 * control panel snap-in that comes with the driver software.
588123474Swpaul	 * Sometimes it's useful to be able to manipulate these.
589123474Swpaul	 * If the driver requests the key in the form of a string,
590123474Swpaul	 * make its default value an empty string, otherwise default
591123474Swpaul	 * it to "0".
592123474Swpaul	 */
593123474Swpaul
594123474Swpaul	if (type == ndis_parm_int || type == ndis_parm_hexint)
595123488Swpaul		ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
596123488Swpaul		    "UNSET", CTLFLAG_RW);
597123474Swpaul	else
598123488Swpaul		ndis_add_sysctl(sc, keystr, "(dynamic string key)",
599123488Swpaul		    "UNSET", CTLFLAG_RW);
600123474Swpaul
601123474Swpaul	free(keystr, M_DEVBUF);
602123474Swpaul	*status = NDIS_STATUS_FAILURE;
603123474Swpaul	return;
604123474Swpaul}
605123474Swpaul
606123526Swpaulstatic ndis_status
607123526Swpaulndis_decode_parm(block, parm, val)
608123526Swpaul	ndis_miniport_block	*block;
609123526Swpaul	ndis_config_parm	*parm;
610123526Swpaul	char			*val;
611123526Swpaul{
612123526Swpaul	ndis_unicode_string	*ustr;
613124697Swpaul	char			*astr = NULL;
614123526Swpaul
615123526Swpaul	switch(parm->ncp_type) {
616123526Swpaul	case ndis_parm_string:
617123526Swpaul		ustr = &parm->ncp_parmdata.ncp_stringdata;
618124697Swpaul		ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &astr);
619124697Swpaul		bcopy(astr, val, 254);
620124697Swpaul		free(astr, M_DEVBUF);
621123526Swpaul		break;
622123526Swpaul	case ndis_parm_int:
623124697Swpaul		sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
624123526Swpaul		break;
625123526Swpaul	case ndis_parm_hexint:
626123526Swpaul		sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
627123526Swpaul		break;
628123526Swpaul	default:
629123526Swpaul		return(NDIS_STATUS_FAILURE);
630123526Swpaul		break;
631123526Swpaul	}
632123526Swpaul	return(NDIS_STATUS_SUCCESS);
633123526Swpaul}
634123526Swpaul
635123474Swpaul__stdcall static void
636123526Swpaulndis_write_cfg(status, cfg, key, parm)
637123526Swpaul	ndis_status		*status;
638123526Swpaul	ndis_handle		cfg;
639123526Swpaul	ndis_unicode_string	*key;
640123526Swpaul	ndis_config_parm	*parm;
641123526Swpaul{
642123526Swpaul	char			*keystr = NULL;
643123526Swpaul	ndis_miniport_block	*block;
644123526Swpaul	struct ndis_softc	*sc;
645123526Swpaul        struct sysctl_oid	*oidp;
646123526Swpaul	struct sysctl_ctx_entry	*e;
647123526Swpaul	char			val[256];
648123526Swpaul
649123526Swpaul	block = (ndis_miniport_block *)cfg;
650123526Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
651123526Swpaul
652123526Swpaul	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
653123526Swpaul
654123526Swpaul	/* Decode the parameter into a string. */
655124697Swpaul	bzero(val, sizeof(val));
656123526Swpaul	*status = ndis_decode_parm(block, parm, val);
657123526Swpaul	if (*status != NDIS_STATUS_SUCCESS) {
658123526Swpaul		free(keystr, M_DEVBUF);
659123526Swpaul		return;
660123526Swpaul	}
661123526Swpaul
662123526Swpaul	/* See if the key already exists. */
663123526Swpaul
664123526Swpaul	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
665123526Swpaul		oidp = e->entry;
666123526Swpaul		if (strcmp(oidp->oid_name, keystr) == 0) {
667123526Swpaul			/* Found it, set the value. */
668123526Swpaul			strcpy((char *)oidp->oid_arg1, val);
669123526Swpaul			free(keystr, M_DEVBUF);
670123526Swpaul			return;
671123526Swpaul		}
672123526Swpaul	}
673123526Swpaul
674123526Swpaul	/* Not found, add a new key with the specified value. */
675123526Swpaul	ndis_add_sysctl(sc, keystr, "(dynamically set key)",
676123526Swpaul		    val, CTLFLAG_RW);
677123526Swpaul
678123526Swpaul	free(keystr, M_DEVBUF);
679123526Swpaul	*status = NDIS_STATUS_SUCCESS;
680123526Swpaul	return;
681123526Swpaul}
682123526Swpaul
683123526Swpaul__stdcall static void
684123474Swpaulndis_close_cfg(cfg)
685123474Swpaul	ndis_handle		cfg;
686123474Swpaul{
687123474Swpaul	return;
688123474Swpaul}
689123474Swpaul
690123474Swpaul__stdcall static void
691123474Swpaulndis_create_lock(lock)
692123474Swpaul	ndis_spin_lock		*lock;
693123474Swpaul{
694124409Swpaul	lock->nsl_spinlock = (ndis_kspin_lock)mtx_pool_alloc(ndis_mtxpool);
695123474Swpaul	return;
696123474Swpaul}
697123474Swpaul
698123474Swpaul__stdcall static void
699123474Swpaulndis_destroy_lock(lock)
700123474Swpaul	ndis_spin_lock		*lock;
701123474Swpaul{
702124409Swpaul	/* We use a mutex pool, so this is a no-op. */
703123474Swpaul	return;
704123474Swpaul}
705123474Swpaul
706123474Swpaul__stdcall static void
707123474Swpaulndis_lock(lock)
708123474Swpaul	ndis_spin_lock		*lock;
709123474Swpaul{
710124409Swpaul	mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
711123474Swpaul	return;
712123474Swpaul}
713123474Swpaul
714123474Swpaul__stdcall static void
715123474Swpaulndis_unlock(lock)
716123474Swpaul	ndis_spin_lock		*lock;
717123474Swpaul{
718124409Swpaul	mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
719123474Swpaul	return;
720123474Swpaul}
721123474Swpaul
722123474Swpaul__stdcall static uint32_t
723123474Swpaulndis_read_pci(adapter, slot, offset, buf, len)
724123474Swpaul	ndis_handle		adapter;
725123474Swpaul	uint32_t		slot;
726123474Swpaul	uint32_t		offset;
727123474Swpaul	void			*buf;
728123474Swpaul	uint32_t		len;
729123474Swpaul{
730123474Swpaul	ndis_miniport_block	*block;
731123474Swpaul	int			i;
732123474Swpaul	char			*dest;
733123474Swpaul
734123474Swpaul	block = (ndis_miniport_block *)adapter;
735123474Swpaul	dest = buf;
736123474Swpaul	if (block == NULL || block->nmb_dev == NULL)
737123474Swpaul		return(0);
738123474Swpaul
739123474Swpaul	for (i = 0; i < len; i++)
740123474Swpaul		dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
741123474Swpaul
742123474Swpaul	return(len);
743123474Swpaul}
744123474Swpaul
745123474Swpaul__stdcall static uint32_t
746123474Swpaulndis_write_pci(adapter, slot, offset, buf, len)
747123474Swpaul	ndis_handle		adapter;
748123474Swpaul	uint32_t		slot;
749123474Swpaul	uint32_t		offset;
750123474Swpaul	void			*buf;
751123474Swpaul	uint32_t		len;
752123474Swpaul{
753123474Swpaul	ndis_miniport_block	*block;
754123474Swpaul	int			i;
755123474Swpaul	char			*dest;
756123474Swpaul
757123474Swpaul	block = (ndis_miniport_block *)adapter;
758123474Swpaul	dest = buf;
759123474Swpaul
760123474Swpaul	if (block == NULL || block->nmb_dev == NULL)
761123474Swpaul		return(0);
762123474Swpaul
763123474Swpaul	for (i = 0; i < len; i++)
764123474Swpaul		pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
765123474Swpaul
766123474Swpaul	return(len);
767123474Swpaul}
768123474Swpaul
769123474Swpaul/*
770123474Swpaul * The errorlog routine uses a variable argument list, so we
771123474Swpaul * have to declare it this way.
772123474Swpaul */
773124228Swpaul#define ERRMSGLEN 512
774123474Swpaulstatic void
775123474Swpaulndis_syslog(ndis_handle adapter, ndis_error_code code,
776123474Swpaul	uint32_t numerrors, ...)
777123474Swpaul{
778123474Swpaul	ndis_miniport_block	*block;
779123474Swpaul	va_list			ap;
780124173Swpaul	int			i, error;
781124173Swpaul	char			*str = NULL, *ustr = NULL;
782124173Swpaul	uint16_t		flags;
783124228Swpaul	char			msgbuf[ERRMSGLEN];
784123474Swpaul
785123474Swpaul	block = (ndis_miniport_block *)adapter;
786123474Swpaul
787124173Swpaul	error = pe_get_message(block->nmb_img, code, &str, &i, &flags);
788124173Swpaul	if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
789124228Swpaul		ustr = msgbuf;
790124228Swpaul		ndis_unicode_to_ascii((uint16_t *)str,
791124228Swpaul		    ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
792124173Swpaul		str = ustr;
793124173Swpaul	}
794124165Swpaul	device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code,
795124165Swpaul	    str == NULL ? "unknown error" : str);
796124060Swpaul	device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
797123474Swpaul
798123474Swpaul	va_start(ap, numerrors);
799123474Swpaul	for (i = 0; i < numerrors; i++)
800124060Swpaul		device_printf (block->nmb_dev, "argptr: %p\n",
801124060Swpaul		    va_arg(ap, void *));
802123474Swpaul	va_end(ap);
803123474Swpaul
804123474Swpaul	return;
805123474Swpaul}
806123474Swpaul
807123474Swpaulstatic void
808123474Swpaulndis_map_cb(arg, segs, nseg, error)
809123474Swpaul	void			*arg;
810123474Swpaul	bus_dma_segment_t	*segs;
811123474Swpaul	int			nseg;
812123474Swpaul	int			error;
813123474Swpaul{
814123474Swpaul	struct ndis_map_arg	*ctx;
815123474Swpaul	int			i;
816123474Swpaul
817123474Swpaul	if (error)
818123474Swpaul		return;
819123474Swpaul
820123474Swpaul	ctx = arg;
821123474Swpaul
822123474Swpaul	for (i = 0; i < nseg; i++) {
823123474Swpaul		ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
824123474Swpaul		ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
825123474Swpaul	}
826123474Swpaul
827123474Swpaul	ctx->nma_cnt = nseg;
828123474Swpaul
829123474Swpaul	return;
830123474Swpaul}
831123474Swpaul
832123474Swpaul__stdcall static void
833123474Swpaulndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
834123474Swpaul	ndis_handle		adapter;
835123474Swpaul	ndis_buffer		*buf;
836123474Swpaul	uint32_t		mapreg;
837123474Swpaul	uint8_t			writedev;
838123474Swpaul	ndis_paddr_unit		*addrarray;
839123474Swpaul	uint32_t		*arraysize;
840123474Swpaul{
841123474Swpaul	ndis_miniport_block	*block;
842123474Swpaul	struct ndis_softc	*sc;
843123474Swpaul	struct ndis_map_arg	nma;
844123474Swpaul	bus_dmamap_t		map;
845123474Swpaul	int			error;
846123474Swpaul
847123474Swpaul	if (adapter == NULL)
848123474Swpaul		return;
849123474Swpaul
850123474Swpaul	block = (ndis_miniport_block *)adapter;
851123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
852123474Swpaul
853123474Swpaul	if (mapreg > sc->ndis_mmapcnt)
854123474Swpaul		return;
855123474Swpaul
856123474Swpaul	map = sc->ndis_mmaps[mapreg];
857123474Swpaul	nma.nma_fraglist = addrarray;
858123474Swpaul
859123474Swpaul	error = bus_dmamap_load(sc->ndis_mtag, map,
860123757Swpaul	    MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
861123474Swpaul	    (void *)&nma, BUS_DMA_NOWAIT);
862123474Swpaul
863123474Swpaul	if (error)
864123474Swpaul		return;
865123474Swpaul
866123474Swpaul	bus_dmamap_sync(sc->ndis_mtag, map,
867123474Swpaul	    writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
868123474Swpaul
869123474Swpaul	*arraysize = nma.nma_cnt;
870123474Swpaul
871123474Swpaul	return;
872123474Swpaul}
873123474Swpaul
874123474Swpaul__stdcall static void
875123474Swpaulndis_vtophys_unload(adapter, buf, mapreg)
876123474Swpaul	ndis_handle		adapter;
877123474Swpaul	ndis_buffer		*buf;
878123474Swpaul	uint32_t		mapreg;
879123474Swpaul{
880123474Swpaul	ndis_miniport_block	*block;
881123474Swpaul	struct ndis_softc	*sc;
882123474Swpaul	bus_dmamap_t		map;
883123474Swpaul
884123474Swpaul	if (adapter == NULL)
885123474Swpaul		return;
886123474Swpaul
887123474Swpaul	block = (ndis_miniport_block *)adapter;
888123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
889123474Swpaul
890123474Swpaul	if (mapreg > sc->ndis_mmapcnt)
891123474Swpaul		return;
892123474Swpaul
893123474Swpaul	map = sc->ndis_mmaps[mapreg];
894123474Swpaul
895123474Swpaul	bus_dmamap_sync(sc->ndis_mtag, map,
896123474Swpaul	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
897123474Swpaul
898123474Swpaul	bus_dmamap_unload(sc->ndis_mtag, map);
899123474Swpaul
900123474Swpaul	return;
901123474Swpaul}
902123474Swpaul
903125057Swpaul/*
904125057Swpaul * This is an older pre-miniport timer init routine which doesn't
905125057Swpaul * accept a miniport context handle. The function context (ctx)
906125057Swpaul * is supposed to be a pointer to the adapter handle, which should
907125057Swpaul * have been handed to us via NdisSetAttributesEx(). We use this
908125057Swpaul * function context to track down the corresponding ndis_miniport_block
909125057Swpaul * structure. It's vital that we track down the miniport block structure,
910125057Swpaul * so if we can't do it, we panic. Note that we also play some games
911125057Swpaul * here by treating ndis_timer and ndis_miniport_timer as the same
912125057Swpaul * thing.
913125057Swpaul */
914125057Swpaul
915123474Swpaul__stdcall static void
916125057Swpaulndis_init_timer(timer, func, ctx)
917125057Swpaul	ndis_timer		*timer;
918125057Swpaul	ndis_timer_function	func;
919125057Swpaul	void			*ctx;
920125057Swpaul{
921125057Swpaul	struct ndis_timer_entry	*ne = NULL;
922125057Swpaul	ndis_miniport_block	*block = NULL;
923125057Swpaul
924125057Swpaul	TAILQ_FOREACH(block, &ndis_devhead, link) {
925125057Swpaul		if (block->nmb_miniportadapterctx == ctx)
926125057Swpaul			break;
927125057Swpaul	}
928125057Swpaul
929125057Swpaul	if (block->nmb_miniportadapterctx != ctx)
930125057Swpaul		panic("NDIS driver timer context didn't "
931125057Swpaul		    "match any adapter contexts");
932125057Swpaul
933125057Swpaul	ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT);
934125057Swpaul	callout_init(&ne->nte_ch, CALLOUT_MPSAFE);
935125057Swpaul	TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link);
936125057Swpaul	ne->nte_timer = (ndis_miniport_timer *)timer;
937125057Swpaul
938125057Swpaul	timer->nt_timer.nk_header.dh_sigstate = TRUE;
939125057Swpaul	timer->nt_dpc.nk_sysarg1 = &ne->nte_ch;
940125057Swpaul	timer->nt_dpc.nk_deferedfunc = (ndis_kdpc_func)func;
941125057Swpaul	timer->nt_dpc.nk_deferredctx = ctx;
942125057Swpaul
943125057Swpaul	return;
944125057Swpaul}
945125057Swpaul
946125057Swpaul__stdcall static void
947123474Swpaulndis_create_timer(timer, handle, func, ctx)
948123474Swpaul	ndis_miniport_timer	*timer;
949123474Swpaul	ndis_handle		*handle;
950123474Swpaul	ndis_timer_function	func;
951123474Swpaul	void			*ctx;
952123474Swpaul{
953123821Swpaul	struct ndis_timer_entry	*ne = NULL;
954123821Swpaul	ndis_miniport_block	*block;
955123821Swpaul	block = (ndis_miniport_block *)handle;
956123474Swpaul
957123821Swpaul	ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT);
958123832Swpaul	callout_init(&ne->nte_ch, CALLOUT_MPSAFE);
959123821Swpaul	TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link);
960123821Swpaul	ne->nte_timer = timer;
961123821Swpaul
962123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
963125057Swpaul	timer->nmt_dpc.nk_sysarg1 = &ne->nte_ch;
964125057Swpaul	timer->nmt_dpc.nk_deferedfunc = (ndis_kdpc_func)func;
965125057Swpaul	timer->nmt_dpc.nk_deferredctx = ctx;
966123474Swpaul
967123474Swpaul	return;
968123474Swpaul}
969123474Swpaul
970123474Swpaul/*
971123474Swpaul * The driver's timer callout is __stdcall function, so we need this
972123474Swpaul * intermediate step.
973123474Swpaul */
974123474Swpaul
975123474Swpaulstatic void
976123474Swpaulndis_timercall(arg)
977123474Swpaul	void		*arg;
978123474Swpaul{
979123474Swpaul	ndis_miniport_timer	*timer;
980123474Swpaul	__stdcall ndis_timer_function	timerfunc;
981123474Swpaul
982123474Swpaul	timer = arg;
983123474Swpaul
984123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
985125057Swpaul	timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc;
986125057Swpaul	timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL);
987123474Swpaul
988123474Swpaul	return;
989123474Swpaul}
990123474Swpaul
991123474Swpaul/*
992123474Swpaul * Windows specifies timeouts in milliseconds. We specify timeouts
993123474Swpaul * in hz. Trying to compute a tenth of a second based on hz is tricky.
994123474Swpaul * so we approximate. Note that we abuse the dpc portion of the
995123474Swpaul * miniport timer structure to hold the UNIX callout handle.
996123474Swpaul */
997123474Swpaul__stdcall static void
998123474Swpaulndis_set_timer(timer, msecs)
999123474Swpaul	ndis_miniport_timer	*timer;
1000123474Swpaul	uint32_t		msecs;
1001123474Swpaul{
1002123832Swpaul	struct callout		*ch;
1003123474Swpaul	struct timeval		tv;
1004123474Swpaul
1005123474Swpaul	tv.tv_sec = 0;
1006123474Swpaul	tv.tv_usec = msecs * 1000;
1007123474Swpaul
1008125057Swpaul	ch = timer->nmt_dpc.nk_sysarg1;
1009123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_timercall;
1010123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
1011123832Swpaul	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1012123474Swpaul
1013123474Swpaul	return;
1014123474Swpaul}
1015123474Swpaul
1016123474Swpaulstatic void
1017123474Swpaulndis_tick(arg)
1018123474Swpaul	void			*arg;
1019123474Swpaul{
1020123474Swpaul	ndis_miniport_timer	*timer;
1021123832Swpaul	struct callout		*ch;
1022123474Swpaul	__stdcall ndis_timer_function	timerfunc;
1023123474Swpaul	struct timeval		tv;
1024123474Swpaul
1025123474Swpaul	timer = arg;
1026123474Swpaul
1027123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
1028125057Swpaul	timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc;
1029125057Swpaul	timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL);
1030123474Swpaul
1031123474Swpaul	/* Automatically reload timer. */
1032123474Swpaul
1033123474Swpaul	tv.tv_sec = 0;
1034123474Swpaul	tv.tv_usec = timer->nmt_ktimer.nk_period * 1000;
1035125057Swpaul	ch = timer->nmt_dpc.nk_sysarg1;
1036123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
1037123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
1038123832Swpaul	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1039123474Swpaul
1040123474Swpaul	return;
1041123474Swpaul}
1042123474Swpaul
1043123474Swpaul__stdcall static void
1044123474Swpaulndis_set_periodic_timer(timer, msecs)
1045123474Swpaul	ndis_miniport_timer	*timer;
1046123474Swpaul	uint32_t		msecs;
1047123474Swpaul{
1048123832Swpaul	struct callout		*ch;
1049123474Swpaul	struct timeval		tv;
1050123474Swpaul
1051123474Swpaul	tv.tv_sec = 0;
1052123474Swpaul	tv.tv_usec = msecs * 1000;
1053123474Swpaul
1054123474Swpaul	timer->nmt_ktimer.nk_period = msecs;
1055125057Swpaul	ch = timer->nmt_dpc.nk_sysarg1;
1056123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
1057123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
1058123832Swpaul	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1059123474Swpaul
1060123474Swpaul	return;
1061123474Swpaul}
1062123474Swpaul
1063123474Swpaul__stdcall static void
1064123474Swpaulndis_cancel_timer(timer, cancelled)
1065123474Swpaul	ndis_miniport_timer	*timer;
1066123474Swpaul	uint8_t			*cancelled;
1067123474Swpaul{
1068123832Swpaul	struct callout		*ch;
1069123474Swpaul
1070124097Swpaul	if (timer == NULL)
1071124097Swpaul		return;
1072125057Swpaul	ch = timer->nmt_dpc.nk_sysarg1;
1073124097Swpaul	if (ch == NULL)
1074124097Swpaul		return;
1075123832Swpaul	callout_stop(ch);
1076123821Swpaul	*cancelled = timer->nmt_ktimer.nk_header.dh_sigstate;
1077123474Swpaul
1078123474Swpaul	return;
1079123474Swpaul}
1080123474Swpaul
1081123474Swpaul__stdcall static void
1082123474Swpaulndis_query_resources(status, adapter, list, buflen)
1083123474Swpaul	ndis_status		*status;
1084123474Swpaul	ndis_handle		adapter;
1085123474Swpaul	ndis_resource_list	*list;
1086123474Swpaul	uint32_t		*buflen;
1087123474Swpaul{
1088123474Swpaul	ndis_miniport_block	*block;
1089123474Swpaul	struct ndis_softc	*sc;
1090124094Swpaul	int			rsclen;
1091123474Swpaul
1092123474Swpaul	block = (ndis_miniport_block *)adapter;
1093123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1094124094Swpaul
1095124094Swpaul	rsclen = sizeof(ndis_resource_list) +
1096123474Swpaul	    (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1097124094Swpaul	if (*buflen < rsclen) {
1098124094Swpaul		*buflen = rsclen;
1099124094Swpaul		*status = NDIS_STATUS_INVALID_LENGTH;
1100124094Swpaul		return;
1101124094Swpaul	}
1102123474Swpaul
1103123474Swpaul	bcopy((char *)block->nmb_rlist, (char *)list, *buflen);
1104123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1105123474Swpaul	return;
1106123474Swpaul}
1107123474Swpaul
1108123474Swpaul__stdcall static ndis_status
1109123474Swpaulndis_register_ioport(offset, adapter, port, numports)
1110123474Swpaul	void			**offset;
1111123474Swpaul	ndis_handle		adapter;
1112123474Swpaul	uint32_t		port;
1113123474Swpaul	uint32_t		numports;
1114123474Swpaul{
1115123474Swpaul	struct ndis_miniport_block	*block;
1116123474Swpaul	struct ndis_softc	*sc;
1117123474Swpaul
1118123474Swpaul	if (adapter == NULL)
1119123474Swpaul		return(NDIS_STATUS_FAILURE);
1120123474Swpaul
1121123474Swpaul	block = (ndis_miniport_block *)adapter;
1122123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1123123474Swpaul
1124123474Swpaul	if (sc->ndis_res_io == NULL)
1125123474Swpaul		return(NDIS_STATUS_FAILURE);
1126123474Swpaul
1127124454Swpaul	/* Don't let the device map more ports than we have. */
1128124454Swpaul	if (rman_get_size(sc->ndis_res_io) < numports)
1129123474Swpaul		return(NDIS_STATUS_INVALID_LENGTH);
1130123474Swpaul
1131123474Swpaul	*offset = (void *)rman_get_start(sc->ndis_res_io);
1132123474Swpaul
1133123474Swpaul	return(NDIS_STATUS_SUCCESS);
1134123474Swpaul}
1135123474Swpaul
1136123474Swpaul__stdcall static void
1137123474Swpaulndis_deregister_ioport(adapter, port, numports, offset)
1138123474Swpaul	ndis_handle		adapter;
1139123474Swpaul	uint32_t		port;
1140123474Swpaul	uint32_t		numports;
1141123474Swpaul	void			*offset;
1142123474Swpaul{
1143123474Swpaul	return;
1144123474Swpaul}
1145123474Swpaul
1146123474Swpaul__stdcall static void
1147123474Swpaulndis_read_netaddr(status, addr, addrlen, adapter)
1148123474Swpaul	ndis_status		*status;
1149123474Swpaul	void			**addr;
1150123474Swpaul	uint32_t		*addrlen;
1151123474Swpaul	ndis_handle		adapter;
1152123474Swpaul{
1153123474Swpaul	struct ndis_softc	*sc;
1154123474Swpaul	ndis_miniport_block	*block;
1155123474Swpaul	uint8_t			empty[] = { 0, 0, 0, 0, 0, 0 };
1156123474Swpaul
1157123474Swpaul	block = (ndis_miniport_block *)adapter;
1158123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1159123474Swpaul
1160123474Swpaul	if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1161123474Swpaul		*status = NDIS_STATUS_FAILURE;
1162123474Swpaul	else {
1163123474Swpaul		*addr = sc->arpcom.ac_enaddr;
1164123474Swpaul		*addrlen = ETHER_ADDR_LEN;
1165123474Swpaul		*status = NDIS_STATUS_SUCCESS;
1166123474Swpaul	}
1167123474Swpaul
1168123474Swpaul	return;
1169123474Swpaul}
1170123474Swpaul
1171123474Swpaul__stdcall static ndis_status
1172123848Swpaulndis_mapreg_cnt(bustype, cnt)
1173123848Swpaul	uint32_t		bustype;
1174123848Swpaul	uint32_t		*cnt;
1175123848Swpaul{
1176124097Swpaul	*cnt = 8192;
1177123848Swpaul	return(NDIS_STATUS_SUCCESS);
1178123848Swpaul}
1179123848Swpaul
1180123848Swpaul__stdcall static ndis_status
1181123474Swpaulndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
1182123474Swpaul	ndis_handle		adapter;
1183123474Swpaul	uint32_t		dmachannel;
1184123474Swpaul	uint8_t			dmasize;
1185123474Swpaul	uint32_t		physmapneeded;
1186123474Swpaul	uint32_t		maxmap;
1187123474Swpaul{
1188123474Swpaul	struct ndis_softc	*sc;
1189123474Swpaul	ndis_miniport_block	*block;
1190123474Swpaul	int			error, i, nseg = NDIS_MAXSEG;
1191123474Swpaul
1192123474Swpaul	block = (ndis_miniport_block *)adapter;
1193123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1194123474Swpaul
1195123474Swpaul	sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1196123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1197123474Swpaul
1198123474Swpaul	if (sc->ndis_mmaps == NULL)
1199123474Swpaul		return(NDIS_STATUS_RESOURCES);
1200123474Swpaul
1201123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1202123474Swpaul	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1203123474Swpaul	    NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1204123474Swpaul	    NULL, NULL, &sc->ndis_mtag);
1205123474Swpaul
1206123474Swpaul	if (error) {
1207123474Swpaul		free(sc->ndis_mmaps, M_DEVBUF);
1208123474Swpaul		return(NDIS_STATUS_RESOURCES);
1209123474Swpaul	}
1210123474Swpaul
1211123474Swpaul	for (i = 0; i < physmapneeded; i++)
1212123474Swpaul		bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1213123474Swpaul
1214123474Swpaul	sc->ndis_mmapcnt = physmapneeded;
1215123474Swpaul
1216123474Swpaul	return(NDIS_STATUS_SUCCESS);
1217123474Swpaul}
1218123474Swpaul
1219123474Swpaul__stdcall static void
1220123474Swpaulndis_free_mapreg(adapter)
1221123474Swpaul	ndis_handle		adapter;
1222123474Swpaul{
1223123474Swpaul	struct ndis_softc	*sc;
1224123474Swpaul	ndis_miniport_block	*block;
1225123474Swpaul	int			i;
1226123474Swpaul
1227123474Swpaul	block = (ndis_miniport_block *)adapter;
1228123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1229123474Swpaul
1230123474Swpaul	for (i = 0; i < sc->ndis_mmapcnt; i++)
1231123474Swpaul		bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1232123474Swpaul
1233123474Swpaul	free(sc->ndis_mmaps, M_DEVBUF);
1234123474Swpaul
1235123474Swpaul	bus_dma_tag_destroy(sc->ndis_mtag);
1236123474Swpaul
1237123474Swpaul	return;
1238123474Swpaul}
1239123474Swpaul
1240123474Swpaulstatic void
1241123474Swpaulndis_mapshared_cb(arg, segs, nseg, error)
1242123474Swpaul	void			*arg;
1243123474Swpaul	bus_dma_segment_t	*segs;
1244123474Swpaul	int			nseg;
1245123474Swpaul	int			error;
1246123474Swpaul{
1247123474Swpaul	ndis_physaddr		*p;
1248123474Swpaul
1249123474Swpaul	if (error || nseg > 1)
1250123474Swpaul		return;
1251123474Swpaul
1252123474Swpaul	p = arg;
1253123474Swpaul
1254123474Swpaul	p->np_quad = segs[0].ds_addr;
1255123474Swpaul
1256123474Swpaul	return;
1257123474Swpaul}
1258123474Swpaul
1259123474Swpaul/*
1260123474Swpaul * This maps to bus_dmamem_alloc().
1261123474Swpaul */
1262123474Swpaul__stdcall static void
1263123474Swpaulndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
1264123474Swpaul	ndis_handle		adapter;
1265123474Swpaul	uint32_t		len;
1266123474Swpaul	uint8_t			cached;
1267123474Swpaul	void			**vaddr;
1268123474Swpaul	ndis_physaddr		*paddr;
1269123474Swpaul{
1270123474Swpaul	ndis_miniport_block	*block;
1271123474Swpaul	struct ndis_softc	*sc;
1272123474Swpaul	struct ndis_shmem	*sh;
1273123474Swpaul	int			error;
1274123474Swpaul
1275123474Swpaul	if (adapter == NULL)
1276123474Swpaul		return;
1277123474Swpaul
1278123474Swpaul	block = (ndis_miniport_block *)adapter;
1279123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1280123474Swpaul
1281123474Swpaul	sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1282123474Swpaul	if (sh == NULL)
1283123474Swpaul		return;
1284123474Swpaul
1285123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1286123474Swpaul	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1287123474Swpaul	    NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
1288123474Swpaul	    &sh->ndis_stag);
1289123474Swpaul
1290123474Swpaul	if (error) {
1291123474Swpaul		free(sh, M_DEVBUF);
1292123474Swpaul		return;
1293123474Swpaul	}
1294123474Swpaul
1295123474Swpaul	error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1296123474Swpaul	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1297123474Swpaul
1298123474Swpaul	if (error) {
1299123474Swpaul		bus_dma_tag_destroy(sh->ndis_stag);
1300123474Swpaul		free(sh, M_DEVBUF);
1301123474Swpaul		return;
1302123474Swpaul	}
1303123474Swpaul
1304123474Swpaul	error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1305123474Swpaul	    len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1306123474Swpaul
1307123474Swpaul	if (error) {
1308123474Swpaul		bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1309123474Swpaul		bus_dma_tag_destroy(sh->ndis_stag);
1310123474Swpaul		free(sh, M_DEVBUF);
1311123474Swpaul		return;
1312123474Swpaul	}
1313123474Swpaul
1314123474Swpaul	sh->ndis_saddr = *vaddr;
1315123474Swpaul	sh->ndis_next = sc->ndis_shlist;
1316123474Swpaul	sc->ndis_shlist = sh;
1317123474Swpaul
1318123474Swpaul	return;
1319123474Swpaul}
1320123474Swpaul
1321123474Swpaul__stdcall static void
1322123474Swpaulndis_alloc_sharedmem_async(adapter, len, cached, ctx)
1323123474Swpaul	ndis_handle		adapter;
1324123474Swpaul	uint32_t		len;
1325123474Swpaul	uint8_t			cached;
1326123474Swpaul	void			*ctx;
1327123474Swpaul{
1328123474Swpaul	ndis_miniport_block	*block;
1329123474Swpaul	struct ndis_softc	*sc;
1330123474Swpaul	void			*vaddr;
1331123474Swpaul	ndis_physaddr		paddr;
1332123474Swpaul	__stdcall ndis_allocdone_handler	donefunc;
1333123474Swpaul
1334123474Swpaul	if (adapter == NULL)
1335123474Swpaul		return;
1336123474Swpaul
1337123474Swpaul	block = (ndis_miniport_block *)adapter;
1338123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1339123474Swpaul	donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1340123474Swpaul
1341123474Swpaul	ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr);
1342123474Swpaul	donefunc(adapter, vaddr, &paddr, len, ctx);
1343123474Swpaul
1344123474Swpaul	return;
1345123474Swpaul}
1346123474Swpaul
1347123474Swpaul__stdcall static void
1348123474Swpaulndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
1349123474Swpaul	ndis_handle		adapter;
1350123474Swpaul	uint32_t		len;
1351123474Swpaul	uint8_t			cached;
1352123474Swpaul	void			*vaddr;
1353123474Swpaul	ndis_physaddr		paddr;
1354123474Swpaul{
1355123474Swpaul	ndis_miniport_block	*block;
1356123474Swpaul	struct ndis_softc	*sc;
1357123474Swpaul	struct ndis_shmem	*sh, *prev;
1358123474Swpaul
1359123474Swpaul	if (vaddr == NULL || adapter == NULL)
1360123474Swpaul		return;
1361123474Swpaul
1362123474Swpaul	block = (ndis_miniport_block *)adapter;
1363123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1364123474Swpaul	sh = prev = sc->ndis_shlist;
1365123474Swpaul
1366123474Swpaul	while (sh) {
1367123474Swpaul		if (sh->ndis_saddr == vaddr)
1368123474Swpaul			break;
1369123474Swpaul		prev = sh;
1370123474Swpaul		sh = sh->ndis_next;
1371123474Swpaul	}
1372123474Swpaul
1373123474Swpaul	bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1374123474Swpaul	bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1375123474Swpaul	bus_dma_tag_destroy(sh->ndis_stag);
1376123474Swpaul
1377123474Swpaul	if (sh == sc->ndis_shlist)
1378123474Swpaul		sc->ndis_shlist = sh->ndis_next;
1379123474Swpaul	else
1380123474Swpaul		prev->ndis_next = sh->ndis_next;
1381123474Swpaul
1382123474Swpaul	free(sh, M_DEVBUF);
1383123474Swpaul
1384123474Swpaul	return;
1385123474Swpaul}
1386123474Swpaul
1387123474Swpaul__stdcall static ndis_status
1388123474Swpaulndis_map_iospace(vaddr, adapter, paddr, len)
1389123474Swpaul	void			**vaddr;
1390123474Swpaul	ndis_handle		adapter;
1391123474Swpaul	ndis_physaddr		paddr;
1392123474Swpaul	uint32_t		len;
1393123474Swpaul{
1394123474Swpaul	ndis_miniport_block	*block;
1395123474Swpaul	struct ndis_softc	*sc;
1396123474Swpaul
1397123474Swpaul	if (adapter == NULL)
1398123474Swpaul		return(NDIS_STATUS_FAILURE);
1399123474Swpaul
1400123474Swpaul	block = (ndis_miniport_block *)adapter;
1401123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1402123474Swpaul
1403123474Swpaul	if (sc->ndis_res_mem == NULL)
1404123474Swpaul		return(NDIS_STATUS_FAILURE);
1405123474Swpaul
1406123474Swpaul	*vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1407123474Swpaul
1408123474Swpaul	return(NDIS_STATUS_SUCCESS);
1409123474Swpaul}
1410123474Swpaul
1411123474Swpaul__stdcall static void
1412123474Swpaulndis_unmap_iospace(adapter, vaddr, len)
1413123474Swpaul	ndis_handle		adapter;
1414123474Swpaul	void			*vaddr;
1415123474Swpaul	uint32_t		len;
1416123474Swpaul{
1417123474Swpaul	return;
1418123474Swpaul}
1419123474Swpaul
1420123474Swpaul__stdcall static uint32_t
1421123474Swpaulndis_cachefill(void)
1422123474Swpaul{
1423123474Swpaul	return(128);
1424123474Swpaul}
1425123474Swpaul
1426123474Swpaul__stdcall static uint32_t
1427123474Swpaulndis_dma_align(handle)
1428123474Swpaul	ndis_handle		handle;
1429123474Swpaul{
1430123474Swpaul	return(128);
1431123474Swpaul}
1432123474Swpaul
1433123474Swpaul/*
1434123474Swpaul * NDIS has two methods for dealing with NICs that support DMA.
1435123474Swpaul * One is to just pass packets to the driver and let it call
1436123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1437123474Swpaul * all by itself, and the other is to let the NDIS library handle the
1438123474Swpaul * buffer mapping internally, and hand the driver an already populated
1439123474Swpaul * scatter/gather fragment list. If the driver calls
1440123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter
1441123474Swpaul * method.
1442123474Swpaul */
1443123474Swpaul
1444123474Swpaul__stdcall static ndis_status
1445123474Swpaulndis_init_sc_dma(adapter, is64, maxphysmap)
1446123474Swpaul	ndis_handle		adapter;
1447123474Swpaul	uint8_t			is64;
1448123474Swpaul	uint32_t		maxphysmap;
1449123474Swpaul{
1450123474Swpaul	struct ndis_softc	*sc;
1451123474Swpaul	ndis_miniport_block	*block;
1452123474Swpaul	int			error;
1453123474Swpaul
1454123474Swpaul	if (adapter == NULL)
1455123474Swpaul		return(NDIS_STATUS_FAILURE);
1456123474Swpaul	block = (ndis_miniport_block *)adapter;
1457123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1458123474Swpaul
1459123474Swpaul	/* Don't do this twice. */
1460123474Swpaul	if (sc->ndis_sc == 1)
1461123474Swpaul		return(NDIS_STATUS_SUCCESS);
1462123474Swpaul
1463123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1464123474Swpaul	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1465123474Swpaul	    MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1466123474Swpaul	    NULL, NULL, &sc->ndis_ttag);
1467123474Swpaul
1468123474Swpaul	sc->ndis_sc = 1;
1469123474Swpaul
1470123474Swpaul	return(NDIS_STATUS_SUCCESS);
1471123474Swpaul}
1472123474Swpaul
1473123474Swpaul__stdcall static void
1474123474Swpaulndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
1475123474Swpaul	ndis_status		*status;
1476123474Swpaul	ndis_handle		*pool;
1477123474Swpaul	uint32_t		descnum;
1478123474Swpaul	uint32_t		protrsvdlen;
1479123474Swpaul{
1480123474Swpaul	ndis_packet		*cur;
1481123474Swpaul	int			i;
1482123474Swpaul
1483124116Swpaul	*pool = malloc(sizeof(ndis_packet) *
1484124116Swpaul	    ((descnum + NDIS_POOL_EXTRA) + 1),
1485123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1486123474Swpaul
1487123474Swpaul	if (pool == NULL) {
1488123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1489123474Swpaul		return;
1490123474Swpaul	}
1491123474Swpaul
1492123474Swpaul	cur = (ndis_packet *)*pool;
1493123474Swpaul	cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1494124116Swpaul	for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1495123474Swpaul		cur->np_private.npp_head = (ndis_handle)(cur + 1);
1496123474Swpaul		cur++;
1497123474Swpaul	}
1498123474Swpaul
1499123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1500123474Swpaul	return;
1501123474Swpaul}
1502123474Swpaul
1503123474Swpaul__stdcall static void
1504123474Swpaulndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
1505123474Swpaul	ndis_status		*status;
1506123474Swpaul	ndis_handle		*pool;
1507123474Swpaul	uint32_t		descnum;
1508123474Swpaul	uint32_t		oflowdescnum;
1509123474Swpaul	uint32_t		protrsvdlen;
1510123474Swpaul{
1511123474Swpaul	return(ndis_alloc_packetpool(status, pool,
1512123474Swpaul	    descnum + oflowdescnum, protrsvdlen));
1513123474Swpaul}
1514123474Swpaul
1515123474Swpaul__stdcall static uint32_t
1516123474Swpaulndis_packetpool_use(pool)
1517123474Swpaul	ndis_handle		pool;
1518123474Swpaul{
1519123474Swpaul	ndis_packet		*head;
1520123474Swpaul
1521123474Swpaul	head = (ndis_packet *)pool;
1522123474Swpaul
1523123474Swpaul	return(head->np_private.npp_count);
1524123474Swpaul}
1525123474Swpaul
1526123474Swpaul__stdcall static void
1527123474Swpaulndis_free_packetpool(pool)
1528123474Swpaul	ndis_handle		pool;
1529123474Swpaul{
1530123474Swpaul	free(pool, M_DEVBUF);
1531123474Swpaul	return;
1532123474Swpaul}
1533123474Swpaul
1534123474Swpaul__stdcall static void
1535123474Swpaulndis_alloc_packet(status, packet, pool)
1536123474Swpaul	ndis_status		*status;
1537123474Swpaul	ndis_packet		**packet;
1538123474Swpaul	ndis_handle		pool;
1539123474Swpaul{
1540123474Swpaul	ndis_packet		*head, *pkt;
1541123474Swpaul
1542123474Swpaul	head = (ndis_packet *)pool;
1543123474Swpaul
1544123474Swpaul	if (head->np_private.npp_flags != 0x1) {
1545123474Swpaul		*status = NDIS_STATUS_FAILURE;
1546123474Swpaul		return;
1547123474Swpaul	}
1548123474Swpaul
1549123474Swpaul	pkt = (ndis_packet *)head->np_private.npp_head;
1550123474Swpaul
1551123474Swpaul	if (pkt == NULL) {
1552123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1553123474Swpaul		return;
1554123474Swpaul	}
1555123474Swpaul
1556123474Swpaul	head->np_private.npp_head = pkt->np_private.npp_head;
1557123474Swpaul
1558123474Swpaul	pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1559123474Swpaul	/* Save pointer to the pool. */
1560123474Swpaul	pkt->np_private.npp_pool = head;
1561123474Swpaul
1562123474Swpaul	/* Set the oob offset pointer. Lots of things expect this. */
1563123474Swpaul	pkt->np_private.npp_packetooboffset =
1564123474Swpaul	    offsetof(ndis_packet, np_oob);
1565123474Swpaul
1566124278Swpaul	/*
1567124278Swpaul	 * We must initialize the packet flags correctly in order
1568124278Swpaul	 * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
1569124278Swpaul	 * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly.
1570124278Swpaul	 */
1571124278Swpaul	pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
1572124278Swpaul
1573123474Swpaul	*packet = pkt;
1574123474Swpaul
1575123474Swpaul	head->np_private.npp_count++;
1576123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1577123474Swpaul	return;
1578123474Swpaul}
1579123474Swpaul
1580123848Swpaul__stdcall static void
1581123848Swpaulndis_release_packet(packet)
1582123474Swpaul	ndis_packet		*packet;
1583123474Swpaul{
1584123474Swpaul	ndis_packet		*head;
1585123474Swpaul
1586123474Swpaul	if (packet == NULL || packet->np_private.npp_pool == NULL)
1587123474Swpaul		return;
1588123474Swpaul
1589123474Swpaul	head = packet->np_private.npp_pool;
1590123474Swpaul	if (head->np_private.npp_flags != 0x1)
1591123474Swpaul		return;
1592123474Swpaul
1593123474Swpaul	packet->np_private.npp_head = head->np_private.npp_head;
1594123474Swpaul	head->np_private.npp_head = (ndis_buffer *)packet;
1595123474Swpaul	head->np_private.npp_count--;
1596123474Swpaul
1597123474Swpaul	return;
1598123474Swpaul}
1599123474Swpaul
1600123474Swpaul__stdcall static void
1601123474Swpaulndis_unchain_headbuf(packet, buf)
1602123474Swpaul	ndis_packet		*packet;
1603123474Swpaul	ndis_buffer		**buf;
1604123474Swpaul{
1605123474Swpaul	ndis_packet_private	*priv;
1606123474Swpaul
1607123474Swpaul	if (packet == NULL || buf == NULL)
1608123474Swpaul		return;
1609123474Swpaul
1610123474Swpaul	priv = &packet->np_private;
1611123474Swpaul
1612123474Swpaul	priv->npp_validcounts = FALSE;
1613123474Swpaul
1614123474Swpaul	if (priv->npp_head == priv->npp_tail) {
1615123474Swpaul		*buf = priv->npp_head;
1616123474Swpaul		priv->npp_head = priv->npp_tail = NULL;
1617123474Swpaul	} else {
1618123474Swpaul		*buf = priv->npp_head;
1619123474Swpaul		priv->npp_head = (*buf)->nb_next;
1620123474Swpaul	}
1621123474Swpaul
1622123474Swpaul	return;
1623123474Swpaul}
1624123474Swpaul
1625123721Swpaul__stdcall static void
1626123721Swpaulndis_unchain_tailbuf(packet, buf)
1627123721Swpaul	ndis_packet		*packet;
1628123721Swpaul	ndis_buffer		**buf;
1629123721Swpaul{
1630123721Swpaul	ndis_packet_private	*priv;
1631123721Swpaul	ndis_buffer		*tmp;
1632123721Swpaul
1633123721Swpaul	if (packet == NULL || buf == NULL)
1634123721Swpaul		return;
1635123721Swpaul
1636123721Swpaul	priv = &packet->np_private;
1637123721Swpaul
1638123721Swpaul	priv->npp_validcounts = FALSE;
1639123721Swpaul
1640123721Swpaul	if (priv->npp_head == priv->npp_tail) {
1641123721Swpaul		*buf = priv->npp_head;
1642123721Swpaul		priv->npp_head = priv->npp_tail = NULL;
1643123721Swpaul	} else {
1644123721Swpaul		*buf = priv->npp_tail;
1645123721Swpaul		tmp = priv->npp_head;
1646123721Swpaul		while (tmp->nb_next != priv->npp_tail)
1647123721Swpaul			tmp = tmp->nb_next;
1648123721Swpaul		priv->npp_tail = tmp;
1649123721Swpaul		tmp->nb_next = NULL;
1650123721Swpaul	}
1651123721Swpaul
1652123721Swpaul	return;
1653123721Swpaul}
1654123721Swpaul
1655123474Swpaul/*
1656123474Swpaul * The NDIS "buffer" manipulation functions are somewhat misnamed.
1657123474Swpaul * They don't really allocate buffers: they allocate buffer mappings.
1658123474Swpaul * The idea is you reserve a chunk of DMA-able memory using
1659123474Swpaul * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1660123474Swpaul * to obtain the virtual address of the DMA-able region.
1661123474Swpaul * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1662123474Swpaul */
1663123474Swpaul
1664123474Swpaul__stdcall static void
1665123474Swpaulndis_alloc_bufpool(status, pool, descnum)
1666123474Swpaul	ndis_status		*status;
1667123474Swpaul	ndis_handle		*pool;
1668123474Swpaul	uint32_t		descnum;
1669123474Swpaul{
1670123474Swpaul	ndis_buffer		*cur;
1671123474Swpaul	int			i;
1672123474Swpaul
1673124116Swpaul	*pool = malloc(sizeof(ndis_buffer) *
1674124116Swpaul	    ((descnum + NDIS_POOL_EXTRA) + 1),
1675123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1676123474Swpaul
1677123474Swpaul	if (pool == NULL) {
1678123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1679123474Swpaul		return;
1680123474Swpaul	}
1681123474Swpaul
1682123474Swpaul	cur = (ndis_buffer *)*pool;
1683123474Swpaul	cur->nb_flags = 0x1; /* mark the head of the list */
1684124116Swpaul	for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1685123474Swpaul		cur->nb_next = cur + 1;
1686123474Swpaul		cur++;
1687123474Swpaul	}
1688123474Swpaul
1689123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1690123474Swpaul	return;
1691123474Swpaul}
1692123474Swpaul
1693123474Swpaul__stdcall static void
1694123474Swpaulndis_free_bufpool(pool)
1695123474Swpaul	ndis_handle		pool;
1696123474Swpaul{
1697123474Swpaul	free(pool, M_DEVBUF);
1698123474Swpaul	return;
1699123474Swpaul}
1700123474Swpaul
1701123474Swpaul/*
1702123474Swpaul * This maps to a bus_dmamap_create() and bus_dmamap_load().
1703123474Swpaul */
1704123474Swpaul__stdcall static void
1705123474Swpaulndis_alloc_buf(status, buffer, pool, vaddr, len)
1706123474Swpaul	ndis_status		*status;
1707123474Swpaul	ndis_buffer		**buffer;
1708123474Swpaul	ndis_handle		pool;
1709123474Swpaul	void			*vaddr;
1710123474Swpaul	uint32_t		len;
1711123474Swpaul{
1712123474Swpaul	ndis_buffer		*head, *buf;
1713123474Swpaul
1714123474Swpaul	head = (ndis_buffer *)pool;
1715123474Swpaul	if (head->nb_flags != 0x1) {
1716123474Swpaul		*status = NDIS_STATUS_FAILURE;
1717123474Swpaul		return;
1718123474Swpaul	}
1719123474Swpaul
1720123474Swpaul	buf = head->nb_next;
1721123474Swpaul
1722123474Swpaul	if (buf == NULL) {
1723123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1724123474Swpaul		return;
1725123474Swpaul	}
1726123474Swpaul
1727123474Swpaul	head->nb_next = buf->nb_next;
1728123474Swpaul
1729123474Swpaul	/* Save pointer to the pool. */
1730123474Swpaul	buf->nb_process = head;
1731123474Swpaul
1732123757Swpaul	MDL_INIT(buf, vaddr, len);
1733123474Swpaul
1734123474Swpaul	*buffer = buf;
1735123474Swpaul
1736123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1737123474Swpaul	return;
1738123474Swpaul}
1739123474Swpaul
1740123848Swpaul__stdcall static void
1741123848Swpaulndis_release_buf(buf)
1742123474Swpaul	ndis_buffer		*buf;
1743123474Swpaul{
1744123474Swpaul	ndis_buffer		*head;
1745123474Swpaul
1746123474Swpaul	if (buf == NULL || buf->nb_process == NULL)
1747123474Swpaul		return;
1748123474Swpaul
1749123474Swpaul	head = buf->nb_process;
1750123474Swpaul
1751123474Swpaul	if (head->nb_flags != 0x1)
1752123474Swpaul		return;
1753123474Swpaul
1754123474Swpaul	buf->nb_next = head->nb_next;
1755123474Swpaul	head->nb_next = buf;
1756123474Swpaul
1757123474Swpaul	return;
1758123474Swpaul}
1759123474Swpaul
1760124100Swpaul/* Aw c'mon. */
1761124100Swpaul
1762124100Swpaul__stdcall static uint32_t
1763124100Swpaulndis_buflen(buf)
1764124100Swpaul	ndis_buffer		*buf;
1765124100Swpaul{
1766124100Swpaul	return(buf->nb_bytecount);
1767124100Swpaul}
1768124100Swpaul
1769123723Swpaul/*
1770123723Swpaul * Get the virtual address and length of a buffer.
1771123723Swpaul * Note: the vaddr argument is optional.
1772123723Swpaul */
1773123474Swpaul
1774123474Swpaul__stdcall static void
1775123474Swpaulndis_query_buf(buf, vaddr, len)
1776123474Swpaul	ndis_buffer		*buf;
1777123474Swpaul	void			**vaddr;
1778123474Swpaul	uint32_t		*len;
1779123474Swpaul{
1780123723Swpaul	if (vaddr != NULL)
1781123757Swpaul		*vaddr = MDL_VA(buf);
1782123474Swpaul	*len = buf->nb_bytecount;
1783123474Swpaul
1784123474Swpaul	return;
1785123474Swpaul}
1786123474Swpaul
1787123474Swpaul/* Same as above -- we don't care about the priority. */
1788123474Swpaul
1789123474Swpaul__stdcall static void
1790123474Swpaulndis_query_buf_safe(buf, vaddr, len, prio)
1791123474Swpaul	ndis_buffer		*buf;
1792123474Swpaul	void			**vaddr;
1793123474Swpaul	uint32_t		*len;
1794123474Swpaul	uint32_t		prio;
1795123474Swpaul{
1796123723Swpaul	if (vaddr != NULL)
1797123757Swpaul		*vaddr = MDL_VA(buf);
1798123474Swpaul	*len = buf->nb_bytecount;
1799123474Swpaul
1800123474Swpaul	return;
1801123474Swpaul}
1802123474Swpaul
1803125069Swpaul/* Damnit Microsoft!! How many ways can you do the same thing?! */
1804125069Swpaul
1805125069Swpaul__stdcall static void *
1806125069Swpaulndis_buf_vaddr(buf)
1807125069Swpaul	ndis_buffer		*buf;
1808125069Swpaul{
1809125069Swpaul	return(MDL_VA(buf));
1810125069Swpaul}
1811125069Swpaul
1812125069Swpaul__stdcall static void *
1813125069Swpaulndis_buf_vaddr_safe(buf, prio)
1814125069Swpaul	ndis_buffer		*buf;
1815125069Swpaul	uint32_t		prio;
1816125069Swpaul{
1817125069Swpaul	return(MDL_VA(buf));
1818125069Swpaul}
1819125069Swpaul
1820123474Swpaul__stdcall static void
1821123474Swpaulndis_adjust_buflen(buf, len)
1822123474Swpaul	ndis_buffer		*buf;
1823123474Swpaul	int			len;
1824123474Swpaul{
1825123474Swpaul	buf->nb_bytecount = len;
1826123474Swpaul
1827123474Swpaul	return;
1828123474Swpaul}
1829123474Swpaul
1830123474Swpaul__stdcall static uint32_t
1831123474Swpaulndis_interlock_inc(addend)
1832123474Swpaul	uint32_t		*addend;
1833123474Swpaul{
1834124203Swpaul	atomic_add_long((u_long *)addend, 1);
1835123474Swpaul	return(*addend);
1836123474Swpaul}
1837123474Swpaul
1838123474Swpaul__stdcall static uint32_t
1839123474Swpaulndis_interlock_dec(addend)
1840123474Swpaul	uint32_t		*addend;
1841123474Swpaul{
1842124203Swpaul	atomic_subtract_long((u_long *)addend, 1);
1843123474Swpaul	return(*addend);
1844123474Swpaul}
1845123474Swpaul
1846123474Swpaul__stdcall static void
1847123474Swpaulndis_init_event(event)
1848123474Swpaul	ndis_event		*event;
1849123474Swpaul{
1850123474Swpaul	event->ne_event.nk_header.dh_sigstate = FALSE;
1851123474Swpaul	return;
1852123474Swpaul}
1853123474Swpaul
1854123474Swpaul__stdcall static void
1855123474Swpaulndis_set_event(event)
1856123474Swpaul	ndis_event		*event;
1857123474Swpaul{
1858123474Swpaul	event->ne_event.nk_header.dh_sigstate = TRUE;
1859123474Swpaul	wakeup(event);
1860123474Swpaul	return;
1861123474Swpaul}
1862123474Swpaul
1863123474Swpaul__stdcall static void
1864123474Swpaulndis_reset_event(event)
1865123474Swpaul	ndis_event		*event;
1866123474Swpaul{
1867123474Swpaul	event->ne_event.nk_header.dh_sigstate = FALSE;
1868123474Swpaul	wakeup(event);
1869123474Swpaul	return;
1870123474Swpaul}
1871123474Swpaul
1872123474Swpaul__stdcall static uint8_t
1873123474Swpaulndis_wait_event(event, msecs)
1874123474Swpaul	ndis_event		*event;
1875123474Swpaul	uint32_t		msecs;
1876123474Swpaul{
1877123474Swpaul	int			error;
1878123474Swpaul	struct timeval		tv;
1879123474Swpaul
1880123474Swpaul	if (event->ne_event.nk_header.dh_sigstate == TRUE)
1881123474Swpaul		return(TRUE);
1882123474Swpaul
1883123474Swpaul	tv.tv_sec = 0;
1884123474Swpaul	tv.tv_usec = msecs * 1000;
1885123474Swpaul
1886123474Swpaul	error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
1887123474Swpaul
1888123474Swpaul	return(event->ne_event.nk_header.dh_sigstate);
1889123474Swpaul}
1890123474Swpaul
1891123474Swpaul__stdcall static ndis_status
1892123474Swpaulndis_unicode2ansi(dstr, sstr)
1893123526Swpaul	ndis_ansi_string	*dstr;
1894123526Swpaul	ndis_unicode_string	*sstr;
1895123474Swpaul{
1896123526Swpaul	if (dstr == NULL || sstr == NULL)
1897123526Swpaul		return(NDIS_STATUS_FAILURE);
1898123526Swpaul	if (ndis_unicode_to_ascii(sstr->nus_buf,
1899123526Swpaul	    sstr->nus_len, &dstr->nas_buf))
1900123526Swpaul		return(NDIS_STATUS_FAILURE);
1901123526Swpaul	dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
1902123474Swpaul	return (NDIS_STATUS_SUCCESS);
1903123474Swpaul}
1904123474Swpaul
1905123474Swpaul__stdcall static ndis_status
1906123526Swpaulndis_ansi2unicode(dstr, sstr)
1907123526Swpaul	ndis_unicode_string	*dstr;
1908123526Swpaul	ndis_ansi_string	*sstr;
1909123526Swpaul{
1910123526Swpaul	char			*str;
1911123526Swpaul	if (dstr == NULL || sstr == NULL)
1912123526Swpaul		return(NDIS_STATUS_FAILURE);
1913123526Swpaul	str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
1914123526Swpaul	if (str == NULL)
1915123526Swpaul		return(NDIS_STATUS_FAILURE);
1916123526Swpaul	strncpy(str, sstr->nas_buf, sstr->nas_len);
1917123526Swpaul	*(str + sstr->nas_len) = '\0';
1918123526Swpaul	if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
1919123526Swpaul		free(str, M_DEVBUF);
1920123526Swpaul		return(NDIS_STATUS_FAILURE);
1921123526Swpaul	}
1922123526Swpaul	dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
1923123526Swpaul	free(str, M_DEVBUF);
1924123526Swpaul	return (NDIS_STATUS_SUCCESS);
1925123526Swpaul}
1926123526Swpaul
1927123526Swpaul__stdcall static ndis_status
1928123474Swpaulndis_assign_pcirsrc(adapter, slot, list)
1929123474Swpaul	ndis_handle		adapter;
1930123474Swpaul	uint32_t		slot;
1931123474Swpaul	ndis_resource_list	**list;
1932123474Swpaul{
1933123474Swpaul	ndis_miniport_block	*block;
1934123474Swpaul
1935123474Swpaul	if (adapter == NULL || list == NULL)
1936123474Swpaul		return (NDIS_STATUS_FAILURE);
1937123474Swpaul
1938123474Swpaul	block = (ndis_miniport_block *)adapter;
1939123474Swpaul	*list = block->nmb_rlist;
1940123474Swpaul
1941123474Swpaul	return (NDIS_STATUS_SUCCESS);
1942123474Swpaul}
1943123474Swpaul
1944123474Swpaul__stdcall static ndis_status
1945123474Swpaulndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
1946123474Swpaul	ndis_miniport_interrupt	*intr;
1947123474Swpaul	ndis_handle		adapter;
1948123474Swpaul	uint32_t		ivec;
1949123474Swpaul	uint32_t		ilevel;
1950123474Swpaul	uint8_t			reqisr;
1951123474Swpaul	uint8_t			shared;
1952123474Swpaul	ndis_interrupt_mode	imode;
1953123474Swpaul{
1954124165Swpaul	ndis_miniport_block	*block;
1955124165Swpaul
1956124165Swpaul	block = adapter;
1957124165Swpaul
1958124135Swpaul	intr->ni_block = adapter;
1959124165Swpaul	intr->ni_isrreq = reqisr;
1960124165Swpaul	intr->ni_shared = shared;
1961124165Swpaul	block->nmb_interrupt = intr;
1962123474Swpaul	return(NDIS_STATUS_SUCCESS);
1963123474Swpaul}
1964123474Swpaul
1965123474Swpaul__stdcall static void
1966123474Swpaulndis_deregister_intr(intr)
1967123474Swpaul	ndis_miniport_interrupt	*intr;
1968123474Swpaul{
1969123474Swpaul	return;
1970123474Swpaul}
1971123474Swpaul
1972123474Swpaul__stdcall static void
1973123474Swpaulndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
1974123474Swpaul	ndis_handle		adapter;
1975123474Swpaul	void			*shutdownctx;
1976123474Swpaul	ndis_shutdown_handler	shutdownfunc;
1977123474Swpaul{
1978123474Swpaul	ndis_miniport_block	*block;
1979123474Swpaul	ndis_miniport_characteristics *chars;
1980123474Swpaul	struct ndis_softc	*sc;
1981123474Swpaul
1982123474Swpaul	if (adapter == NULL)
1983123474Swpaul		return;
1984123474Swpaul
1985123474Swpaul	block = (ndis_miniport_block *)adapter;
1986123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1987123474Swpaul	chars = &sc->ndis_chars;
1988123474Swpaul
1989123474Swpaul	chars->nmc_shutdown_handler = shutdownfunc;
1990123474Swpaul	chars->nmc_rsvd0 = shutdownctx;
1991123474Swpaul
1992123474Swpaul	return;
1993123474Swpaul}
1994123474Swpaul
1995123474Swpaul__stdcall static void
1996123474Swpaulndis_deregister_shutdown(adapter)
1997123474Swpaul	ndis_handle		adapter;
1998123474Swpaul{
1999123474Swpaul	ndis_miniport_block	*block;
2000123474Swpaul	ndis_miniport_characteristics *chars;
2001123474Swpaul	struct ndis_softc	*sc;
2002123474Swpaul
2003123474Swpaul	if (adapter == NULL)
2004123474Swpaul		return;
2005123474Swpaul
2006123474Swpaul	block = (ndis_miniport_block *)adapter;
2007123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
2008123474Swpaul	chars = &sc->ndis_chars;
2009123474Swpaul
2010123474Swpaul	chars->nmc_shutdown_handler = NULL;
2011123474Swpaul	chars->nmc_rsvd0 = NULL;
2012123474Swpaul
2013123474Swpaul	return;
2014123474Swpaul}
2015123474Swpaul
2016123474Swpaul__stdcall static uint32_t
2017123474Swpaulndis_numpages(buf)
2018123474Swpaul	ndis_buffer		*buf;
2019123474Swpaul{
2020123757Swpaul	if (buf == NULL)
2021123757Swpaul		return(0);
2022123512Swpaul	if (buf->nb_bytecount == 0)
2023123512Swpaul		return(1);
2024123757Swpaul	return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
2025123474Swpaul}
2026123474Swpaul
2027123474Swpaul__stdcall static void
2028123573Swpaulndis_buf_physpages(buf, pages)
2029123573Swpaul	ndis_buffer		*buf;
2030123573Swpaul	uint32_t		*pages;
2031123573Swpaul{
2032123757Swpaul	if (buf == NULL)
2033123757Swpaul		return;
2034123757Swpaul
2035123573Swpaul	*pages = ndis_numpages(buf);
2036123573Swpaul	return;
2037123573Swpaul}
2038123573Swpaul
2039123573Swpaul__stdcall static void
2040123474Swpaulndis_query_bufoffset(buf, off, len)
2041123474Swpaul	ndis_buffer		*buf;
2042123474Swpaul	uint32_t		*off;
2043123474Swpaul	uint32_t		*len;
2044123474Swpaul{
2045123757Swpaul	if (buf == NULL)
2046123757Swpaul		return;
2047123757Swpaul
2048123757Swpaul	*off = buf->nb_byteoffset;
2049123474Swpaul	*len = buf->nb_bytecount;
2050123474Swpaul
2051123474Swpaul	return;
2052123474Swpaul}
2053123474Swpaul
2054123474Swpaul__stdcall static void
2055123474Swpaulndis_sleep(usecs)
2056123474Swpaul	uint32_t		usecs;
2057123474Swpaul{
2058123474Swpaul	struct timeval		tv;
2059123474Swpaul	uint32_t		dummy;
2060123474Swpaul
2061123474Swpaul	tv.tv_sec = 0;
2062123474Swpaul	tv.tv_usec = usecs;
2063123474Swpaul
2064123474Swpaul	tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
2065124100Swpaul
2066123474Swpaul	return;
2067123474Swpaul}
2068123474Swpaul
2069123474Swpaul__stdcall static uint32_t
2070123474Swpaulndis_read_pccard_amem(handle, offset, buf, len)
2071123474Swpaul	ndis_handle		handle;
2072123474Swpaul	uint32_t		offset;
2073123474Swpaul	void			*buf;
2074123474Swpaul	uint32_t		len;
2075123474Swpaul{
2076123474Swpaul	struct ndis_softc	*sc;
2077123474Swpaul	ndis_miniport_block	*block;
2078123474Swpaul	bus_space_handle_t	bh;
2079123474Swpaul	bus_space_tag_t		bt;
2080123474Swpaul	char			*dest;
2081123474Swpaul	int			i;
2082123474Swpaul
2083123474Swpaul	if (handle == NULL)
2084123474Swpaul		return(0);
2085123474Swpaul
2086123474Swpaul	block = (ndis_miniport_block *)handle;
2087123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
2088123474Swpaul	dest = buf;
2089123474Swpaul
2090123474Swpaul	bh = rman_get_bushandle(sc->ndis_res_am);
2091123474Swpaul	bt = rman_get_bustag(sc->ndis_res_am);
2092123474Swpaul
2093123474Swpaul	for (i = 0; i < len; i++)
2094123474Swpaul		dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2));
2095123474Swpaul
2096123474Swpaul	return(i);
2097123474Swpaul}
2098123474Swpaul
2099123474Swpaul__stdcall static uint32_t
2100123474Swpaulndis_write_pccard_amem(handle, offset, buf, len)
2101123474Swpaul	ndis_handle		handle;
2102123474Swpaul	uint32_t		offset;
2103123474Swpaul	void			*buf;
2104123474Swpaul	uint32_t		len;
2105123474Swpaul{
2106123474Swpaul	struct ndis_softc	*sc;
2107123474Swpaul	ndis_miniport_block	*block;
2108123474Swpaul	bus_space_handle_t	bh;
2109123474Swpaul	bus_space_tag_t		bt;
2110123474Swpaul	char			*src;
2111123474Swpaul	int			i;
2112123474Swpaul
2113123474Swpaul	if (handle == NULL)
2114123474Swpaul		return(0);
2115123474Swpaul
2116123474Swpaul	block = (ndis_miniport_block *)handle;
2117123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
2118123474Swpaul	src = buf;
2119123474Swpaul
2120123474Swpaul	bh = rman_get_bushandle(sc->ndis_res_am);
2121123474Swpaul	bt = rman_get_bustag(sc->ndis_res_am);
2122123474Swpaul
2123123474Swpaul	for (i = 0; i < len; i++)
2124123474Swpaul		bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]);
2125123474Swpaul
2126123474Swpaul	return(i);
2127123474Swpaul}
2128123474Swpaul
2129123474Swpaul__stdcall static ndis_list_entry *
2130123474Swpaulndis_insert_head(head, entry, lock)
2131123474Swpaul	ndis_list_entry		*head;
2132123474Swpaul	ndis_list_entry		*entry;
2133123474Swpaul	ndis_spin_lock		*lock;
2134123474Swpaul{
2135123474Swpaul	ndis_list_entry		*flink;
2136123474Swpaul
2137124409Swpaul	mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2138123474Swpaul	flink = head->nle_flink;
2139123474Swpaul	entry->nle_flink = flink;
2140123474Swpaul	entry->nle_blink = head;
2141123474Swpaul	flink->nle_blink = entry;
2142123474Swpaul	head->nle_flink = entry;
2143124409Swpaul	mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2144123474Swpaul
2145123474Swpaul	return(flink);
2146123474Swpaul}
2147123474Swpaul
2148123474Swpaul__stdcall static ndis_list_entry *
2149123474Swpaulndis_remove_head(head, lock)
2150123474Swpaul	ndis_list_entry		*head;
2151123474Swpaul	ndis_spin_lock		*lock;
2152123474Swpaul{
2153123474Swpaul	ndis_list_entry		*flink;
2154123474Swpaul	ndis_list_entry		*entry;
2155123474Swpaul
2156124409Swpaul	mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2157123474Swpaul	entry = head->nle_flink;
2158123474Swpaul	flink = entry->nle_flink;
2159123474Swpaul	head->nle_flink = flink;
2160123474Swpaul	flink->nle_blink = head;
2161124409Swpaul	mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2162123474Swpaul
2163123474Swpaul	return(entry);
2164123474Swpaul}
2165123474Swpaul
2166123474Swpaul__stdcall static ndis_list_entry *
2167123474Swpaulndis_insert_tail(head, entry, lock)
2168123474Swpaul	ndis_list_entry		*head;
2169123474Swpaul	ndis_list_entry		*entry;
2170123474Swpaul	ndis_spin_lock		*lock;
2171123474Swpaul{
2172123474Swpaul	ndis_list_entry		*blink;
2173123474Swpaul
2174124409Swpaul	mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2175123474Swpaul	blink = head->nle_blink;
2176123474Swpaul	entry->nle_flink = head;
2177123474Swpaul	entry->nle_blink = blink;
2178123474Swpaul	blink->nle_flink = entry;
2179123474Swpaul	head->nle_blink = entry;
2180124409Swpaul	mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2181123474Swpaul
2182123474Swpaul	return(blink);
2183123474Swpaul}
2184123474Swpaul
2185123474Swpaul__stdcall static uint8_t
2186123474Swpaulndis_sync_with_intr(intr, syncfunc, syncctx)
2187123474Swpaul	ndis_miniport_interrupt	*intr;
2188123474Swpaul	void			*syncfunc;
2189123474Swpaul	void			*syncctx;
2190123474Swpaul{
2191124135Swpaul	struct ndis_softc	*sc;
2192123474Swpaul	__stdcall uint8_t (*sync)(void *);
2193124135Swpaul	uint8_t			rval;
2194123474Swpaul
2195123474Swpaul	if (syncfunc == NULL || syncctx == NULL)
2196123474Swpaul		return(0);
2197123474Swpaul
2198124135Swpaul	sc = (struct ndis_softc *)intr->ni_block->nmb_ifp;
2199123474Swpaul	sync = syncfunc;
2200124409Swpaul	mtx_pool_lock(ndis_mtxpool, sc->ndis_intrmtx);
2201124135Swpaul	rval = sync(syncctx);
2202124409Swpaul	mtx_pool_unlock(ndis_mtxpool, sc->ndis_intrmtx);
2203124135Swpaul
2204124135Swpaul	return(rval);
2205123474Swpaul}
2206123474Swpaul
2207123504Swpaul/*
2208123504Swpaul * Return the number of 100 nanosecond intervals since
2209123504Swpaul * January 1, 1601. (?!?!)
2210123504Swpaul */
2211123474Swpaul__stdcall static void
2212123504Swpaulndis_time(tval)
2213123504Swpaul	uint64_t		*tval;
2214123504Swpaul{
2215123504Swpaul	struct timespec		ts;
2216123822Swpaul
2217123504Swpaul	nanotime(&ts);
2218123822Swpaul	*tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2219123822Swpaul	    11644473600;
2220123504Swpaul}
2221123504Swpaul
2222123822Swpaul/*
2223123822Swpaul * Return the number of milliseconds since the system booted.
2224123822Swpaul */
2225123504Swpaul__stdcall static void
2226123822Swpaulndis_uptime(tval)
2227123822Swpaul	uint32_t		*tval;
2228123822Swpaul{
2229123822Swpaul	struct timespec		ts;
2230123822Swpaul
2231123822Swpaul	nanouptime(&ts);
2232123822Swpaul	*tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
2233123822Swpaul}
2234123822Swpaul
2235123822Swpaul__stdcall static void
2236123507Swpaulndis_init_string(dst, src)
2237124100Swpaul	ndis_unicode_string	*dst;
2238123507Swpaul	char			*src;
2239123507Swpaul{
2240123507Swpaul	ndis_unicode_string	*u;
2241123507Swpaul
2242124100Swpaul	u = dst;
2243124116Swpaul	u->nus_buf = NULL;
2244124100Swpaul	if (ndis_ascii_to_unicode(src, &u->nus_buf))
2245123507Swpaul		return;
2246123507Swpaul	u->nus_len = u->nus_maxlen = strlen(src) * 2;
2247123507Swpaul	return;
2248123507Swpaul}
2249123507Swpaul
2250123507Swpaul__stdcall static void
2251123507Swpaulndis_free_string(str)
2252123507Swpaul	ndis_unicode_string	*str;
2253123507Swpaul{
2254123507Swpaul	if (str == NULL)
2255123507Swpaul		return;
2256123507Swpaul	if (str->nus_buf != NULL)
2257123507Swpaul		free(str->nus_buf, M_DEVBUF);
2258123507Swpaul	free(str, M_DEVBUF);
2259123507Swpaul	return;
2260123507Swpaul}
2261123507Swpaul
2262123507Swpaul__stdcall static ndis_status
2263123507Swpaulndis_remove_miniport(adapter)
2264123507Swpaul	ndis_handle		*adapter;
2265123507Swpaul{
2266123507Swpaul	return(NDIS_STATUS_SUCCESS);
2267123507Swpaul}
2268123507Swpaul
2269123507Swpaul__stdcall static void
2270123526Swpaulndis_init_ansi_string(dst, src)
2271123526Swpaul	ndis_ansi_string	*dst;
2272123526Swpaul	char			*src;
2273123526Swpaul{
2274123526Swpaul	ndis_ansi_string	*a;
2275123526Swpaul
2276123526Swpaul	a = dst;
2277123526Swpaul	if (a == NULL)
2278123526Swpaul		return;
2279123526Swpaul	if (src == NULL) {
2280123526Swpaul		a->nas_len = a->nas_maxlen = 0;
2281123526Swpaul		a->nas_buf = NULL;
2282123526Swpaul	} else {
2283123526Swpaul		a->nas_buf = src;
2284123526Swpaul		a->nas_len = a->nas_maxlen = strlen(src);
2285123526Swpaul	}
2286123526Swpaul
2287123526Swpaul	return;
2288123526Swpaul}
2289123526Swpaul
2290123941Swpaul__stdcall static void
2291123941Swpaulndis_init_unicode_string(dst, src)
2292123941Swpaul	ndis_unicode_string	*dst;
2293123941Swpaul	uint16_t		*src;
2294123941Swpaul{
2295123941Swpaul	ndis_unicode_string	*u;
2296123941Swpaul	int			i;
2297123941Swpaul
2298123941Swpaul	u = dst;
2299123941Swpaul	if (u == NULL)
2300123941Swpaul		return;
2301123941Swpaul	if (src == NULL) {
2302123941Swpaul		u->nus_len = u->nus_maxlen = 0;
2303123941Swpaul		u->nus_buf = NULL;
2304123941Swpaul	} else {
2305123941Swpaul		i = 0;
2306123941Swpaul		while(src[i] != 0)
2307123941Swpaul			i++;
2308123941Swpaul		u->nus_buf = src;
2309123941Swpaul		u->nus_len = u->nus_maxlen = i * 2;
2310123941Swpaul	}
2311123941Swpaul
2312123941Swpaul	return;
2313123941Swpaul}
2314123941Swpaul
2315123526Swpaul__stdcall static void ndis_get_devprop(adapter, phydevobj,
2316123526Swpaul	funcdevobj, nextdevobj, resources, transresources)
2317123526Swpaul	ndis_handle		adapter;
2318123526Swpaul	void			*phydevobj;
2319123526Swpaul	void			*funcdevobj;
2320123526Swpaul	void			*nextdevobj;
2321123526Swpaul	cm_resource_list	*resources;
2322123526Swpaul	cm_resource_list	*transresources;
2323123526Swpaul{
2324123526Swpaul	return;
2325123526Swpaul}
2326123526Swpaul
2327123526Swpaul__stdcall static void
2328123721Swpaulndis_firstbuf(packet, buf, firstva, firstlen, totlen)
2329123721Swpaul	ndis_packet		*packet;
2330123721Swpaul	ndis_buffer		**buf;
2331123721Swpaul	void			**firstva;
2332123721Swpaul	uint32_t		*firstlen;
2333123721Swpaul	uint32_t		*totlen;
2334123721Swpaul{
2335123721Swpaul	ndis_buffer		*tmp;
2336123721Swpaul
2337123721Swpaul	tmp = packet->np_private.npp_head;
2338123721Swpaul	*buf = tmp;
2339123721Swpaul	if (tmp == NULL) {
2340123721Swpaul		*firstva = NULL;
2341123721Swpaul		*firstlen = *totlen = 0;
2342123721Swpaul	} else {
2343123757Swpaul		*firstva = MDL_VA(tmp);
2344123721Swpaul		*firstlen = *totlen = tmp->nb_bytecount;
2345123721Swpaul		for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
2346123721Swpaul			*totlen += tmp->nb_bytecount;
2347123721Swpaul	}
2348123721Swpaul
2349123721Swpaul	return;
2350123721Swpaul}
2351123721Swpaul
2352123721Swpaul__stdcall static void
2353123721Swpaulndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio)
2354123721Swpaul	ndis_packet		*packet;
2355123721Swpaul	ndis_buffer		**buf;
2356123721Swpaul	void			**firstva;
2357123721Swpaul	uint32_t		*firstlen;
2358123721Swpaul	uint32_t		*totlen;
2359123721Swpaul	uint32_t		prio;
2360123721Swpaul{
2361123721Swpaul	ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
2362123721Swpaul}
2363123721Swpaul
2364123822Swpaul/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2365123721Swpaul__stdcall static void
2366123822Swpaulndis_open_file(status, filehandle, filelength, filename, highestaddr)
2367123822Swpaul	ndis_status		*status;
2368123822Swpaul	ndis_handle		*filehandle;
2369123822Swpaul	uint32_t		*filelength;
2370123822Swpaul	ndis_unicode_string	*filename;
2371123822Swpaul	ndis_physaddr		highestaddr;
2372123822Swpaul{
2373123822Swpaul	char			*afilename = NULL;
2374124272Swpaul	struct thread		*td = curthread;
2375124272Swpaul	struct nameidata	nd;
2376124272Swpaul	int			flags, error;
2377124272Swpaul	struct vattr		vat;
2378124272Swpaul	struct vattr		*vap = &vat;
2379124272Swpaul	ndis_fh			*fh;
2380124272Swpaul	char			path[MAXPATHLEN];
2381123822Swpaul
2382124272Swpaul	ndis_unicode_to_ascii(filename->nus_buf,
2383124272Swpaul	    filename->nus_len, &afilename);
2384124272Swpaul
2385124272Swpaul	sprintf(path, "%s/%s", ndis_filepath, afilename);
2386123822Swpaul	free(afilename, M_DEVBUF);
2387124272Swpaul
2388124272Swpaul	fh = malloc(sizeof(ndis_fh), M_TEMP, M_NOWAIT);
2389124272Swpaul	if (fh == NULL) {
2390124272Swpaul		*status = NDIS_STATUS_RESOURCES;
2391124272Swpaul		return;
2392124272Swpaul	}
2393124272Swpaul
2394124272Swpaul	mtx_lock(&Giant);
2395124272Swpaul	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
2396124272Swpaul
2397124272Swpaul	flags = FREAD;
2398124272Swpaul	error = vn_open(&nd, &flags, 0, -1);
2399124272Swpaul	if (error) {
2400124272Swpaul		mtx_unlock(&Giant);
2401124272Swpaul		*status = NDIS_STATUS_FILE_NOT_FOUND;
2402124272Swpaul		free(fh, M_TEMP);
2403124272Swpaul		return;
2404124272Swpaul	}
2405124272Swpaul
2406124272Swpaul	NDFREE(&nd, NDF_ONLY_PNBUF);
2407124272Swpaul
2408124272Swpaul	/* Get the file size. */
2409124272Swpaul	VOP_GETATTR(nd.ni_vp, vap, NOCRED, td);
2410124272Swpaul	VOP_UNLOCK(nd.ni_vp, 0, td);
2411124272Swpaul	mtx_unlock(&Giant);
2412124272Swpaul
2413124272Swpaul	fh->nf_vp = nd.ni_vp;
2414124272Swpaul	fh->nf_map = NULL;
2415124272Swpaul	*filehandle = fh;
2416124272Swpaul	*filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
2417124272Swpaul	*status = NDIS_STATUS_SUCCESS;
2418123822Swpaul	return;
2419123822Swpaul}
2420123822Swpaul
2421123822Swpaul__stdcall static void
2422123822Swpaulndis_map_file(status, mappedbuffer, filehandle)
2423123822Swpaul	ndis_status		*status;
2424123822Swpaul	void			**mappedbuffer;
2425123822Swpaul	ndis_handle		filehandle;
2426123822Swpaul{
2427124272Swpaul	ndis_fh			*fh;
2428124272Swpaul	struct thread		*td = curthread;
2429124272Swpaul	int			error, resid;
2430123822Swpaul
2431124272Swpaul	if (filehandle == NULL) {
2432124272Swpaul		*status = NDIS_STATUS_FAILURE;
2433124272Swpaul		return;
2434124272Swpaul	}
2435124272Swpaul
2436124272Swpaul	fh = (ndis_fh *)filehandle;
2437124272Swpaul
2438124272Swpaul	if (fh->nf_vp == NULL) {
2439124272Swpaul		*status = NDIS_STATUS_FAILURE;
2440124272Swpaul		return;
2441124272Swpaul	}
2442124272Swpaul
2443124272Swpaul	if (fh->nf_map != NULL) {
2444124272Swpaul		*status = NDIS_STATUS_ALREADY_MAPPED;
2445124272Swpaul		return;
2446124272Swpaul	}
2447124272Swpaul
2448124272Swpaul	fh->nf_map = malloc(fh->nf_maplen, M_DEVBUF, M_NOWAIT);
2449124272Swpaul
2450124272Swpaul	if (fh->nf_map == NULL) {
2451124272Swpaul		*status = NDIS_STATUS_RESOURCES;
2452124272Swpaul		return;
2453124272Swpaul	}
2454124272Swpaul
2455124272Swpaul	mtx_lock(&Giant);
2456124272Swpaul	error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
2457124272Swpaul	    UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td);
2458124272Swpaul	mtx_unlock(&Giant);
2459124272Swpaul
2460124272Swpaul	if (error)
2461124272Swpaul		*status = NDIS_STATUS_FAILURE;
2462124272Swpaul	else {
2463124272Swpaul		*status = NDIS_STATUS_SUCCESS;
2464124272Swpaul		*mappedbuffer = fh->nf_map;
2465124272Swpaul	}
2466124272Swpaul
2467123822Swpaul	return;
2468123822Swpaul}
2469123822Swpaul
2470123822Swpaul__stdcall static void
2471123822Swpaulndis_unmap_file(filehandle)
2472123822Swpaul	ndis_handle		filehandle;
2473123822Swpaul{
2474124272Swpaul	ndis_fh			*fh;
2475124272Swpaul	fh = (ndis_fh *)filehandle;
2476124272Swpaul
2477124272Swpaul	if (fh->nf_map == NULL)
2478124272Swpaul		return;
2479124272Swpaul	free(fh->nf_map, M_DEVBUF);
2480124272Swpaul	fh->nf_map = NULL;
2481124272Swpaul
2482123822Swpaul	return;
2483123822Swpaul}
2484123822Swpaul
2485123822Swpaul__stdcall static void
2486123822Swpaulndis_close_file(filehandle)
2487123822Swpaul	ndis_handle		filehandle;
2488123822Swpaul{
2489124272Swpaul	struct thread		*td = curthread;
2490124272Swpaul	ndis_fh			*fh;
2491124272Swpaul
2492124272Swpaul	if (filehandle == NULL)
2493124272Swpaul		return;
2494124272Swpaul
2495124272Swpaul	fh = (ndis_fh *)filehandle;
2496124272Swpaul	if (fh->nf_map != NULL) {
2497124272Swpaul		free(fh->nf_map, M_DEVBUF);
2498124272Swpaul		fh->nf_map = NULL;
2499124272Swpaul	}
2500124272Swpaul
2501124272Swpaul	if (fh->nf_vp == NULL)
2502124272Swpaul		return;
2503124272Swpaul
2504124272Swpaul	mtx_lock(&Giant);
2505124272Swpaul	vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
2506124272Swpaul	mtx_unlock(&Giant);
2507124272Swpaul
2508124272Swpaul	fh->nf_vp = NULL;
2509124272Swpaul	free(fh, M_DEVBUF);
2510124272Swpaul
2511123822Swpaul	return;
2512123822Swpaul}
2513123822Swpaul
2514123848Swpaul__stdcall static uint8_t
2515123848Swpaulndis_cpu_cnt()
2516123848Swpaul{
2517123848Swpaul	return(mp_ncpus);
2518124509Swpaul}
2519123848Swpaul
2520124116Swpaultypedef void (*ndis_statusdone_handler)(ndis_handle);
2521124116Swpaultypedef void (*ndis_status_handler)(ndis_handle, ndis_status,
2522124116Swpaul        void *, uint32_t);
2523124116Swpaul
2524123822Swpaul__stdcall static void
2525124116Swpaulndis_ind_statusdone(adapter)
2526124116Swpaul	ndis_handle		adapter;
2527124116Swpaul{
2528124116Swpaul	ndis_miniport_block	*block;
2529124116Swpaul	__stdcall ndis_statusdone_handler	statusdonefunc;
2530124116Swpaul
2531124116Swpaul	block = (ndis_miniport_block *)adapter;
2532124116Swpaul	statusdonefunc = block->nmb_statusdone_func;
2533124116Swpaul
2534124116Swpaul	statusdonefunc(adapter);
2535124116Swpaul	return;
2536124116Swpaul}
2537124116Swpaul
2538124116Swpaul__stdcall static void
2539124116Swpaulndis_ind_status(adapter, status, sbuf, slen)
2540124116Swpaul	ndis_handle		adapter;
2541124116Swpaul	ndis_status		status;
2542124116Swpaul	void			*sbuf;
2543124116Swpaul	uint32_t		slen;
2544124116Swpaul{
2545124116Swpaul	ndis_miniport_block	*block;
2546124116Swpaul	__stdcall ndis_status_handler	statusfunc;
2547124116Swpaul
2548124116Swpaul	block = (ndis_miniport_block *)adapter;
2549124116Swpaul	statusfunc = block->nmb_status_func;
2550124116Swpaul
2551124116Swpaul	statusfunc(adapter, status, sbuf, slen);
2552124116Swpaul	return;
2553124116Swpaul}
2554124116Swpaul
2555124122Swpaulstatic void
2556124697Swpaulndis_workfunc(ctx)
2557124122Swpaul	void			*ctx;
2558124122Swpaul{
2559124122Swpaul	ndis_work_item		*work;
2560124122Swpaul	__stdcall ndis_proc	workfunc;
2561124122Swpaul
2562124122Swpaul	work = ctx;
2563124122Swpaul	workfunc = work->nwi_func;
2564124122Swpaul	workfunc(work, work->nwi_ctx);
2565124122Swpaul	return;
2566124122Swpaul}
2567124122Swpaul
2568124122Swpaul__stdcall static ndis_status
2569124122Swpaulndis_sched_workitem(work)
2570124122Swpaul	ndis_work_item		*work;
2571124122Swpaul{
2572124697Swpaul	ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
2573124122Swpaul	return(NDIS_STATUS_SUCCESS);
2574124122Swpaul}
2575124122Swpaul
2576124116Swpaul__stdcall static void
2577124541Swpaulndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen)
2578124541Swpaul	ndis_packet		*dpkt;
2579124541Swpaul	uint32_t		doff;
2580124541Swpaul	uint32_t		reqlen;
2581124541Swpaul	ndis_packet		*spkt;
2582124541Swpaul	uint32_t		soff;
2583124541Swpaul	uint32_t		*cpylen;
2584124541Swpaul{
2585124541Swpaul	ndis_buffer		*src, *dst;
2586124541Swpaul	char			*sptr, *dptr;
2587124541Swpaul	int			resid, copied, len, scnt, dcnt;
2588124541Swpaul
2589124541Swpaul	*cpylen = 0;
2590124541Swpaul
2591124541Swpaul	src = spkt->np_private.npp_head;
2592124541Swpaul	dst = dpkt->np_private.npp_head;
2593124541Swpaul
2594124541Swpaul	sptr = MDL_VA(src);
2595124541Swpaul	dptr = MDL_VA(dst);
2596124541Swpaul	scnt = src->nb_bytecount;
2597124541Swpaul	dcnt = dst->nb_bytecount;
2598124541Swpaul
2599124541Swpaul	while (soff) {
2600124541Swpaul		if (src->nb_bytecount > soff) {
2601124541Swpaul			sptr += soff;
2602124541Swpaul			scnt = src->nb_bytecount - soff;
2603124541Swpaul			break;
2604124541Swpaul		}
2605124541Swpaul		soff -= src->nb_bytecount;
2606124541Swpaul		src = src->nb_next;
2607124541Swpaul		if (src == NULL)
2608124541Swpaul			return;
2609124541Swpaul		sptr = MDL_VA(src);
2610124541Swpaul	}
2611124541Swpaul
2612124541Swpaul	while (doff) {
2613124541Swpaul		if (dst->nb_bytecount > doff) {
2614124541Swpaul			dptr += doff;
2615124541Swpaul			dcnt = dst->nb_bytecount - doff;
2616124541Swpaul			break;
2617124541Swpaul		}
2618124541Swpaul		doff -= dst->nb_bytecount;
2619124541Swpaul		dst = dst->nb_next;
2620124541Swpaul		if (dst == NULL)
2621124541Swpaul			return;
2622124541Swpaul		dptr = MDL_VA(dst);
2623124541Swpaul	}
2624124541Swpaul
2625124541Swpaul	resid = reqlen;
2626124541Swpaul	copied = 0;
2627124541Swpaul
2628124541Swpaul	while(1) {
2629124541Swpaul		if (resid < scnt)
2630124541Swpaul			len = resid;
2631124541Swpaul		else
2632124541Swpaul			len = scnt;
2633124541Swpaul		if (dcnt < len)
2634124541Swpaul			len = dcnt;
2635124541Swpaul
2636124541Swpaul		bcopy(sptr, dptr, len);
2637124541Swpaul
2638124541Swpaul		copied += len;
2639124541Swpaul		resid -= len;
2640124541Swpaul		if (resid == 0)
2641124541Swpaul			break;
2642124541Swpaul
2643124541Swpaul		dcnt -= len;
2644124541Swpaul		if (dcnt == 0) {
2645124541Swpaul			dst = dst->nb_next;
2646124541Swpaul			if (dst == NULL)
2647124541Swpaul				break;
2648124541Swpaul			dptr = MDL_VA(dst);
2649124541Swpaul			dcnt = dst->nb_bytecount;
2650124541Swpaul		}
2651124541Swpaul
2652124541Swpaul		scnt -= len;
2653124541Swpaul		if (scnt == 0) {
2654124541Swpaul			src = src->nb_next;
2655124541Swpaul			if (src == NULL)
2656124541Swpaul				break;
2657124541Swpaul			sptr = MDL_VA(src);
2658124541Swpaul			scnt = src->nb_bytecount;
2659124541Swpaul		}
2660124541Swpaul	}
2661124541Swpaul
2662124541Swpaul	*cpylen = copied;
2663124541Swpaul	return;
2664124541Swpaul}
2665124541Swpaul
2666124541Swpaul__stdcall static void
2667124541Swpaulndis_pkt_to_pkt_safe(dpkt, doff, reqlen, spkt, soff, cpylen, prio)
2668124541Swpaul	ndis_packet		*dpkt;
2669124541Swpaul	uint32_t		doff;
2670124541Swpaul	uint32_t		reqlen;
2671124541Swpaul	ndis_packet		*spkt;
2672124541Swpaul	uint32_t		soff;
2673124541Swpaul	uint32_t		*cpylen;
2674124541Swpaul	uint32_t		prio;
2675124541Swpaul{
2676124541Swpaul	ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen);
2677124541Swpaul	return;
2678124541Swpaul}
2679124541Swpaul
2680125057Swpaul__stdcall static ndis_status
2681125057Swpaulndis_register_dev(handle, devname, symname, majorfuncs, devobj, devhandle)
2682125057Swpaul	ndis_handle		*handle;
2683125057Swpaul	ndis_unicode_string	*devname;
2684125057Swpaul	ndis_unicode_string	*symname;
2685125057Swpaul	void			*majorfuncs;
2686125057Swpaul	void			*devobj;
2687125057Swpaul	ndis_handle		**devhandle;
2688125057Swpaul{
2689125057Swpaul	return(NDIS_STATUS_SUCCESS);
2690125057Swpaul}
2691125057Swpaul
2692125057Swpaul__stdcall static ndis_status
2693125057Swpaulndis_deregister_dev(devhandle)
2694125057Swpaul	ndis_handle		*devhandle;
2695125057Swpaul{
2696125057Swpaul	return(NDIS_STATUS_SUCCESS);
2697125057Swpaul}
2698125057Swpaul
2699125057Swpaul
2700124541Swpaul__stdcall static void
2701123474Swpauldummy()
2702123474Swpaul{
2703123474Swpaul	printf ("NDIS dummy called...\n");
2704123474Swpaul	return;
2705123474Swpaul}
2706123474Swpaul
2707123474Swpaulimage_patch_table ndis_functbl[] = {
2708124541Swpaul	{ "NdisCopyFromPacketToPacket",	(FUNC)ndis_pkt_to_pkt },
2709124541Swpaul	{ "NdisCopyFromPacketToPacketSafe", (FUNC)ndis_pkt_to_pkt_safe },
2710124122Swpaul	{ "NdisScheduleWorkItem",	(FUNC)ndis_sched_workitem },
2711124116Swpaul	{ "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone },
2712124116Swpaul	{ "NdisMIndicateStatus",	(FUNC)ndis_ind_status },
2713123848Swpaul	{ "NdisSystemProcessorCount",	(FUNC)ndis_cpu_cnt },
2714123721Swpaul	{ "NdisUnchainBufferAtBack",	(FUNC)ndis_unchain_tailbuf, },
2715123721Swpaul	{ "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf },
2716123721Swpaul	{ "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe },
2717123573Swpaul	{ "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2718123526Swpaul	{ "NdisMGetDeviceProperty",	(FUNC)ndis_get_devprop },
2719123526Swpaul	{ "NdisInitAnsiString",		(FUNC)ndis_init_ansi_string },
2720123941Swpaul	{ "NdisInitUnicodeString",	(FUNC)ndis_init_unicode_string },
2721123526Swpaul	{ "NdisWriteConfiguration",	(FUNC)ndis_write_cfg },
2722123526Swpaul	{ "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2723123526Swpaul	{ "NdisTerminateWrapper",	(FUNC)ndis_termwrap },
2724123526Swpaul	{ "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2725123526Swpaul	{ "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2726123507Swpaul	{ "NdisMRemoveMiniport",	(FUNC)ndis_remove_miniport },
2727123507Swpaul	{ "NdisInitializeString",	(FUNC)ndis_init_string },
2728123507Swpaul	{ "NdisFreeString",		(FUNC)ndis_free_string },
2729123504Swpaul	{ "NdisGetCurrentSystemTime",	(FUNC)ndis_time },
2730123822Swpaul	{ "NdisGetSystemUpTime",	(FUNC)ndis_uptime },
2731123474Swpaul	{ "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2732123474Swpaul	{ "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2733123474Swpaul	{ "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2734123474Swpaul	{ "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2735123474Swpaul	{ "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2736123474Swpaul	{ "NdisInitializeWrapper",	(FUNC)ndis_initwrap },
2737123474Swpaul	{ "NdisMRegisterMiniport",	(FUNC)ndis_register_miniport },
2738123474Swpaul	{ "NdisAllocateMemoryWithTag",	(FUNC)ndis_malloc_withtag },
2739123474Swpaul	{ "NdisAllocateMemory",		(FUNC)ndis_malloc },
2740123474Swpaul	{ "NdisMSetAttributesEx",	(FUNC)ndis_setattr_ex },
2741123474Swpaul	{ "NdisCloseConfiguration",	(FUNC)ndis_close_cfg },
2742123474Swpaul	{ "NdisReadConfiguration",	(FUNC)ndis_read_cfg },
2743123474Swpaul	{ "NdisOpenConfiguration",	(FUNC)ndis_open_cfg },
2744123474Swpaul	{ "NdisReleaseSpinLock",	(FUNC)ndis_unlock },
2745123474Swpaul	{ "NdisDprAcquireSpinLock",	(FUNC)ndis_lock },
2746123474Swpaul	{ "NdisDprReleaseSpinLock",	(FUNC)ndis_unlock },
2747123474Swpaul	{ "NdisAcquireSpinLock",	(FUNC)ndis_lock },
2748123474Swpaul	{ "NdisAllocateSpinLock",	(FUNC)ndis_create_lock },
2749123474Swpaul	{ "NdisFreeSpinLock",		(FUNC)ndis_destroy_lock },
2750123474Swpaul	{ "NdisFreeMemory",		(FUNC)ndis_free },
2751123474Swpaul	{ "NdisReadPciSlotInformation",	(FUNC)ndis_read_pci },
2752123474Swpaul	{ "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2753124100Swpaul	{ "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci },
2754124100Swpaul	{ "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci },
2755123474Swpaul	{ "NdisWriteErrorLogEntry",	(FUNC)ndis_syslog },
2756123474Swpaul	{ "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2757123474Swpaul	{ "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2758123474Swpaul	{ "NdisMInitializeTimer",	(FUNC)ndis_create_timer },
2759125057Swpaul	{ "NdisInitializeTimer",	(FUNC)ndis_init_timer },
2760123474Swpaul	{ "NdisSetTimer",		(FUNC)ndis_set_timer },
2761123474Swpaul	{ "NdisMCancelTimer",		(FUNC)ndis_cancel_timer },
2762125057Swpaul	{ "NdisCancelTimer",		(FUNC)ndis_cancel_timer },
2763123474Swpaul	{ "NdisMSetPeriodicTimer",	(FUNC)ndis_set_periodic_timer },
2764123474Swpaul	{ "NdisMQueryAdapterResources",	(FUNC)ndis_query_resources },
2765123474Swpaul	{ "NdisMRegisterIoPortRange",	(FUNC)ndis_register_ioport },
2766123474Swpaul	{ "NdisMDeregisterIoPortRange",	(FUNC)ndis_deregister_ioport },
2767123474Swpaul	{ "NdisReadNetworkAddress",	(FUNC)ndis_read_netaddr },
2768123848Swpaul	{ "NdisQueryMapRegisterCount",	(FUNC)ndis_mapreg_cnt },
2769123474Swpaul	{ "NdisMAllocateMapRegisters",	(FUNC)ndis_alloc_mapreg },
2770123848Swpaul	{ "NdisMFreeMapRegisters",	(FUNC)ndis_free_mapreg },
2771123474Swpaul	{ "NdisMAllocateSharedMemory",	(FUNC)ndis_alloc_sharedmem },
2772123474Swpaul	{ "NdisMMapIoSpace",		(FUNC)ndis_map_iospace },
2773123474Swpaul	{ "NdisMUnmapIoSpace",		(FUNC)ndis_unmap_iospace },
2774123474Swpaul	{ "NdisGetCacheFillSize",	(FUNC)ndis_cachefill },
2775123474Swpaul	{ "NdisMGetDmaAlignment",	(FUNC)ndis_dma_align },
2776123474Swpaul	{ "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2777123474Swpaul	{ "NdisAllocatePacketPool",	(FUNC)ndis_alloc_packetpool },
2778123474Swpaul	{ "NdisAllocatePacketPoolEx",	(FUNC)ndis_ex_alloc_packetpool },
2779123474Swpaul	{ "NdisAllocatePacket",		(FUNC)ndis_alloc_packet },
2780123474Swpaul	{ "NdisFreePacket",		(FUNC)ndis_release_packet },
2781123474Swpaul	{ "NdisFreePacketPool",		(FUNC)ndis_free_packetpool },
2782124097Swpaul	{ "NdisDprAllocatePacket",	(FUNC)ndis_alloc_packet },
2783124097Swpaul	{ "NdisDprFreePacket",		(FUNC)ndis_release_packet },
2784123474Swpaul	{ "NdisAllocateBufferPool",	(FUNC)ndis_alloc_bufpool },
2785123474Swpaul	{ "NdisAllocateBuffer",		(FUNC)ndis_alloc_buf },
2786123474Swpaul	{ "NdisQueryBuffer",		(FUNC)ndis_query_buf },
2787123474Swpaul	{ "NdisQueryBufferSafe",	(FUNC)ndis_query_buf_safe },
2788125069Swpaul	{ "NdisBufferVirtualAddress",	(FUNC)ndis_buf_vaddr },
2789125069Swpaul	{ "NdisBufferVirtualAddressSafe", (FUNC)ndis_buf_vaddr_safe },
2790124100Swpaul	{ "NdisBufferLength",		(FUNC)ndis_buflen },
2791123474Swpaul	{ "NdisFreeBuffer",		(FUNC)ndis_release_buf },
2792123474Swpaul	{ "NdisFreeBufferPool",		(FUNC)ndis_free_bufpool },
2793123474Swpaul	{ "NdisInterlockedIncrement",	(FUNC)ndis_interlock_inc },
2794123474Swpaul	{ "NdisInterlockedDecrement",	(FUNC)ndis_interlock_dec },
2795123474Swpaul	{ "NdisInitializeEvent",	(FUNC)ndis_init_event },
2796123474Swpaul	{ "NdisSetEvent",		(FUNC)ndis_set_event },
2797123474Swpaul	{ "NdisResetEvent",		(FUNC)ndis_reset_event },
2798123474Swpaul	{ "NdisWaitEvent",		(FUNC)ndis_wait_event },
2799123474Swpaul	{ "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2800123474Swpaul	{ "NdisMPciAssignResources",	(FUNC)ndis_assign_pcirsrc },
2801123474Swpaul	{ "NdisMFreeSharedMemory",	(FUNC)ndis_free_sharedmem },
2802123474Swpaul	{ "NdisMRegisterInterrupt",	(FUNC)ndis_register_intr },
2803123474Swpaul	{ "NdisMDeregisterInterrupt",	(FUNC)ndis_deregister_intr },
2804123474Swpaul	{ "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2805123474Swpaul	{ "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
2806123474Swpaul	{ "NDIS_BUFFER_TO_SPAN_PAGES",	(FUNC)ndis_numpages },
2807123474Swpaul	{ "NdisQueryBufferOffset",	(FUNC)ndis_query_bufoffset },
2808123474Swpaul	{ "NdisAdjustBufferLength",	(FUNC)ndis_adjust_buflen },
2809123474Swpaul	{ "NdisPacketPoolUsage",	(FUNC)ndis_packetpool_use },
2810123474Swpaul	{ "NdisMSleep",			(FUNC)ndis_sleep },
2811123474Swpaul	{ "NdisUnchainBufferAtFront",	(FUNC)ndis_unchain_headbuf },
2812123474Swpaul	{ "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
2813123474Swpaul	{ "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
2814123822Swpaul	{ "NdisOpenFile",		(FUNC)ndis_open_file },
2815123822Swpaul	{ "NdisMapFile",		(FUNC)ndis_map_file },
2816123822Swpaul	{ "NdisUnmapFile",		(FUNC)ndis_unmap_file },
2817123822Swpaul	{ "NdisCloseFile",		(FUNC)ndis_close_file },
2818125057Swpaul	{ "NdisMRegisterDevice",	(FUNC)ndis_register_dev },
2819125057Swpaul	{ "NdisMDeregisterDevice",	(FUNC)ndis_deregister_dev },
2820123474Swpaul
2821123474Swpaul	/*
2822123474Swpaul	 * This last entry is a catch-all for any function we haven't
2823123474Swpaul	 * implemented yet. The PE import list patching routine will
2824123474Swpaul	 * use it for any function that doesn't have an explicit match
2825123474Swpaul	 * in this table.
2826123474Swpaul	 */
2827123474Swpaul
2828123474Swpaul	{ NULL, (FUNC)dummy },
2829123474Swpaul
2830123474Swpaul	/* End of list. */
2831123474Swpaul
2832123474Swpaul	{ NULL, NULL },
2833123474Swpaul};
2834