subr_ndis.c revision 124122
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 124122 2004-01-04 07:47:33Z 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>
67124122Swpaul#include <sys/taskqueue.h>
68123474Swpaul
69123474Swpaul#include <net/if.h>
70123474Swpaul#include <net/if_arp.h>
71123474Swpaul#include <net/ethernet.h>
72123474Swpaul#include <net/if_dl.h>
73123474Swpaul#include <net/if_media.h>
74123474Swpaul
75123474Swpaul#include <machine/bus_memio.h>
76123474Swpaul#include <machine/bus_pio.h>
77123474Swpaul#include <machine/bus.h>
78123474Swpaul#include <machine/resource.h>
79123474Swpaul
80123474Swpaul#include <sys/bus.h>
81123474Swpaul#include <sys/rman.h>
82123474Swpaul
83123474Swpaul#include <machine/stdarg.h>
84123474Swpaul
85123695Swpaul#include <net80211/ieee80211_var.h>
86123695Swpaul#include <net80211/ieee80211_ioctl.h>
87123695Swpaul
88123474Swpaul#include <dev/pci/pcireg.h>
89123474Swpaul#include <dev/pci/pcivar.h>
90123474Swpaul
91123474Swpaul#include <compat/ndis/pe_var.h>
92123474Swpaul#include <compat/ndis/resource_var.h>
93123512Swpaul#include <compat/ndis/ntoskrnl_var.h>
94123474Swpaul#include <compat/ndis/ndis_var.h>
95123474Swpaul#include <compat/ndis/cfg_var.h>
96123474Swpaul#include <dev/if_ndis/if_ndisvar.h>
97123474Swpaul
98123474Swpaul#define __stdcall __attribute__((__stdcall__))
99123474Swpaul#define FUNC void(*)(void)
100123474Swpaul
101123474Swpaulstatic struct mtx ndis_interlock;
102123474Swpaul
103123474Swpaul__stdcall static void ndis_initwrap(ndis_handle,
104123474Swpaul	ndis_driver_object *, void *, void *);
105123474Swpaul__stdcall static ndis_status ndis_register_miniport(ndis_handle,
106123474Swpaul	ndis_miniport_characteristics *, int);
107123474Swpaul__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
108123474Swpaul__stdcall static ndis_status ndis_malloc(void **,
109123474Swpaul	uint32_t, uint32_t, ndis_physaddr);
110123474Swpaul__stdcall static void ndis_free(void *, uint32_t, uint32_t);
111123474Swpaul__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
112123474Swpaul	uint32_t, uint32_t, ndis_interface_type);
113123474Swpaul__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
114123526Swpaul__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle,
115123526Swpaul	uint32_t, ndis_unicode_string *, ndis_handle *);
116123526Swpaul__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle,
117123526Swpaul	ndis_unicode_string *, ndis_handle *);
118123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *,
119123474Swpaul	struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
120123526Swpaulstatic ndis_status ndis_decode_parm(ndis_miniport_block *,
121123526Swpaul	ndis_config_parm *, char *);
122123474Swpaul__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
123123474Swpaul	ndis_handle, ndis_unicode_string *, ndis_parm_type);
124123526Swpaul__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle,
125123526Swpaul	ndis_unicode_string *, ndis_config_parm *);
126123474Swpaul__stdcall static void ndis_close_cfg(ndis_handle);
127123474Swpaul__stdcall static void ndis_create_lock(ndis_spin_lock *);
128123474Swpaul__stdcall static void ndis_destroy_lock(ndis_spin_lock *);
129123474Swpaul__stdcall static void ndis_lock(ndis_spin_lock *);
130123474Swpaul__stdcall static void ndis_unlock(ndis_spin_lock *);
131123474Swpaul__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
132123474Swpaul	uint32_t, void *, uint32_t);
133123474Swpaul__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
134123474Swpaul	uint32_t, void *, uint32_t);
135123474Swpaulstatic void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
136123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
137123474Swpaul__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
138123474Swpaul	uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
139123474Swpaul__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
140123474Swpaul__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *,
141123474Swpaul	ndis_timer_function, void *);
142123474Swpaulstatic void ndis_timercall(void *);
143123474Swpaul__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t);
144123474Swpaulstatic void ndis_tick(void *);
145123474Swpaul__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
146123474Swpaul__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *);
147123474Swpaul__stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
148123474Swpaul	ndis_resource_list *, uint32_t *);
149123474Swpaul__stdcall static ndis_status ndis_register_ioport(void **,
150123474Swpaul	ndis_handle, uint32_t, uint32_t);
151123474Swpaul__stdcall static void ndis_deregister_ioport(ndis_handle,
152123474Swpaul	uint32_t, uint32_t, void *);
153123474Swpaul__stdcall static void ndis_read_netaddr(ndis_status *, void **,
154123474Swpaul	uint32_t *, ndis_handle);
155123848Swpaul__stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *);
156123474Swpaul__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
157123474Swpaul	uint32_t, uint8_t, uint32_t, uint32_t);
158123474Swpaul__stdcall static void ndis_free_mapreg(ndis_handle);
159123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
160123474Swpaul__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
161123474Swpaul	uint8_t, void **, ndis_physaddr *);
162123474Swpaul__stdcall static void ndis_alloc_sharedmem_async(ndis_handle,
163123474Swpaul	uint32_t, uint8_t, void *);
164123474Swpaul__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
165123474Swpaul	uint8_t, void *, ndis_physaddr);
166123474Swpaul__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
167123474Swpaul	ndis_physaddr, uint32_t);
168123474Swpaul__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
169123474Swpaul__stdcall static uint32_t ndis_cachefill(void);
170123474Swpaul__stdcall static uint32_t ndis_dma_align(ndis_handle);
171123474Swpaul__stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
172123474Swpaul	uint8_t, uint32_t);
173123474Swpaul__stdcall static void ndis_alloc_packetpool(ndis_status *,
174123474Swpaul	ndis_handle *, uint32_t, uint32_t);
175123474Swpaul__stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
176123474Swpaul	ndis_handle *, uint32_t, uint32_t, uint32_t);
177123474Swpaul__stdcall static uint32_t ndis_packetpool_use(ndis_handle);
178123474Swpaul__stdcall static void ndis_free_packetpool(ndis_handle);
179123474Swpaul__stdcall static void ndis_alloc_packet(ndis_status *,
180123474Swpaul	ndis_packet **, ndis_handle);
181123474Swpaul__stdcall static void ndis_release_packet(ndis_packet *);
182123474Swpaul__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
183123721Swpaul__stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **);
184123474Swpaul__stdcall static void ndis_alloc_bufpool(ndis_status *,
185123474Swpaul	ndis_handle *, uint32_t);
186123474Swpaul__stdcall static void ndis_free_bufpool(ndis_handle);
187123474Swpaul__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
188123474Swpaul	ndis_handle, void *, uint32_t);
189123474Swpaul__stdcall static void ndis_release_buf(ndis_buffer *);
190124100Swpaul__stdcall static uint32_t ndis_buflen(ndis_buffer *);
191123474Swpaul__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
192123474Swpaul__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
193123474Swpaul	uint32_t *, uint32_t);
194123474Swpaul__stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
195123474Swpaul__stdcall static uint32_t ndis_interlock_inc(uint32_t *);
196123474Swpaul__stdcall static uint32_t ndis_interlock_dec(uint32_t *);
197123474Swpaul__stdcall static void ndis_init_event(ndis_event *);
198123474Swpaul__stdcall static void ndis_set_event(ndis_event *);
199123474Swpaul__stdcall static void ndis_reset_event(ndis_event *);
200123474Swpaul__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
201123474Swpaul__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
202123474Swpaul	ndis_unicode_string *);
203123526Swpaul__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
204123526Swpaul	ndis_ansi_string *);
205123474Swpaul__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
206123474Swpaul	uint32_t, ndis_resource_list **);
207123474Swpaul__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
208123474Swpaul	ndis_handle, uint32_t, uint32_t, uint8_t,
209123474Swpaul	uint8_t, ndis_interrupt_mode);
210123474Swpaul__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
211123474Swpaul__stdcall static void ndis_register_shutdown(ndis_handle, void *,
212123474Swpaul	ndis_shutdown_handler);
213123474Swpaul__stdcall static void ndis_deregister_shutdown(ndis_handle);
214123474Swpaul__stdcall static uint32_t ndis_numpages(ndis_buffer *);
215123573Swpaul__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
216123474Swpaul__stdcall static void ndis_query_bufoffset(ndis_buffer *,
217123474Swpaul	uint32_t *, uint32_t *);
218123474Swpaul__stdcall static void ndis_sleep(uint32_t);
219123474Swpaul__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
220123474Swpaul	uint32_t, void *, uint32_t);
221123474Swpaul__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
222123474Swpaul	uint32_t, void *, uint32_t);
223123474Swpaul__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *,
224123474Swpaul	ndis_list_entry *, ndis_spin_lock *);
225123474Swpaul__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *,
226123474Swpaul	ndis_spin_lock *);
227123474Swpaul__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *,
228123474Swpaul	ndis_list_entry *, ndis_spin_lock *);
229123474Swpaul__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
230123474Swpaul	void *, void *);
231123504Swpaul__stdcall static void ndis_time(uint64_t *);
232123822Swpaul__stdcall static void ndis_uptime(uint32_t *);
233124100Swpaul__stdcall static void ndis_init_string(ndis_unicode_string *, char *);
234123526Swpaul__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
235123941Swpaul__stdcall static void ndis_init_unicode_string(ndis_unicode_string *,
236123941Swpaul	uint16_t *);
237123507Swpaul__stdcall static void ndis_free_string(ndis_unicode_string *);
238123507Swpaul__stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
239123526Swpaul__stdcall static void ndis_termwrap(ndis_handle, void *);
240123526Swpaul__stdcall static void ndis_get_devprop(ndis_handle, void *, void *,
241123526Swpaul	void *, cm_resource_list *, cm_resource_list *);
242123721Swpaul__stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
243123721Swpaul	void **, uint32_t *, uint32_t *);
244123721Swpaul__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
245123721Swpaul	void **, uint32_t *, uint32_t *, uint32_t);
246123822Swpaul__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
247123822Swpaul	ndis_unicode_string *, ndis_physaddr);
248123822Swpaul__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
249123822Swpaul__stdcall static void ndis_unmap_file(ndis_handle);
250123822Swpaul__stdcall static void ndis_close_file(ndis_handle);
251123848Swpaul__stdcall static u_int8_t ndis_cpu_cnt(void);
252124116Swpaul__stdcall static void ndis_ind_statusdone(ndis_handle);
253124116Swpaul__stdcall static void ndis_ind_status(ndis_handle, ndis_status,
254124116Swpaul        void *, uint32_t);
255124122Swpaulstatic void ndis_workfunc(void *, int);
256124122Swpaul__stdcall static ndis_status ndis_sched_workitem(ndis_work_item *);
257123474Swpaul__stdcall static void dummy(void);
258123474Swpaul
259124116Swpaul/*
260124116Swpaul * Some really old drivers do not properly check the return value
261124116Swpaul * from NdisAllocatePacket() and NdisAllocateBuffer() and will
262124116Swpaul * sometimes allocate few more buffers/packets that they originally
263124116Swpaul * requested when they created the pool. To prevent this from being
264124116Swpaul * a problem, we allocate a few extra buffers/packets beyond what
265124116Swpaul * the driver asks for. This #define controls how many.
266124116Swpaul */
267124116Swpaul#define NDIS_POOL_EXTRA		16
268123474Swpaul
269123474Swpaulint
270123474Swpaulndis_libinit()
271123474Swpaul{
272123474Swpaul	mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK,
273123474Swpaul	    MTX_DEF | MTX_RECURSE | MTX_DUPOK);
274123474Swpaul
275123474Swpaul	return(0);
276123474Swpaul}
277123474Swpaul
278123474Swpaulint
279123474Swpaulndis_libfini()
280123474Swpaul{
281123474Swpaul	mtx_destroy(&ndis_interlock);
282123474Swpaul	return(0);
283123474Swpaul}
284123474Swpaul
285123474Swpaul/*
286123474Swpaul * NDIS deals with strings in unicode format, so we have
287123474Swpaul * do deal with them that way too. For now, we only handle
288123474Swpaul * conversion between unicode and ASCII since that's all
289123474Swpaul * that device drivers care about.
290123474Swpaul */
291123474Swpaul
292123474Swpaulint
293123474Swpaulndis_ascii_to_unicode(ascii, unicode)
294123474Swpaul	char			*ascii;
295123474Swpaul	uint16_t		**unicode;
296123474Swpaul{
297123474Swpaul	uint16_t		*ustr;
298123474Swpaul	int			i;
299123474Swpaul
300123474Swpaul	if (*unicode == NULL)
301123474Swpaul		*unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
302123474Swpaul
303123474Swpaul	if (*unicode == NULL)
304123474Swpaul		return(ENOMEM);
305123474Swpaul	ustr = *unicode;
306123474Swpaul	for (i = 0; i < strlen(ascii); i++) {
307123474Swpaul		*ustr = (uint16_t)ascii[i];
308123474Swpaul		ustr++;
309123474Swpaul	}
310123474Swpaul
311123474Swpaul	return(0);
312123474Swpaul}
313123474Swpaul
314123474Swpaulint
315123474Swpaulndis_unicode_to_ascii(unicode, ulen, ascii)
316123474Swpaul	uint16_t		*unicode;
317123474Swpaul	int			ulen;
318123474Swpaul	char			**ascii;
319123474Swpaul{
320123474Swpaul	uint8_t			*astr;
321123474Swpaul	int			i;
322123474Swpaul
323123474Swpaul	if (*ascii == NULL)
324124100Swpaul		*ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO);
325123474Swpaul	if (*ascii == NULL)
326123474Swpaul		return(ENOMEM);
327123474Swpaul	astr = *ascii;
328124100Swpaul	for (i = 0; i < ulen / 2; i++) {
329123474Swpaul		*astr = (uint8_t)unicode[i];
330123474Swpaul		astr++;
331123474Swpaul	}
332123474Swpaul
333123474Swpaul	return(0);
334123474Swpaul}
335123474Swpaul
336123474Swpaul__stdcall static void
337123474Swpaulndis_initwrap(wrapper, drv_obj, path, unused)
338123474Swpaul	ndis_handle		wrapper;
339123474Swpaul	ndis_driver_object	*drv_obj;
340123474Swpaul	void			*path;
341123474Swpaul	void			*unused;
342123474Swpaul{
343123474Swpaul	ndis_driver_object	**drv;
344123474Swpaul
345123474Swpaul	drv = wrapper;
346123474Swpaul	*drv = drv_obj;
347123474Swpaul
348123474Swpaul	return;
349123474Swpaul}
350123474Swpaul
351123526Swpaul__stdcall static void
352123526Swpaulndis_termwrap(handle, syspec)
353123526Swpaul	ndis_handle		handle;
354123526Swpaul	void			*syspec;
355123526Swpaul{
356123526Swpaul	return;
357123526Swpaul}
358123526Swpaul
359123474Swpaul__stdcall static ndis_status
360123474Swpaulndis_register_miniport(handle, characteristics, len)
361123474Swpaul	ndis_handle		handle;
362123474Swpaul	ndis_miniport_characteristics *characteristics;
363123474Swpaul	int			len;
364123474Swpaul{
365123474Swpaul	ndis_driver_object	*drv;
366123474Swpaul
367123474Swpaul	drv = handle;
368123474Swpaul	bcopy((char *)characteristics, (char *)&drv->ndo_chars,
369123474Swpaul	    sizeof(ndis_miniport_characteristics));
370123474Swpaul	return(NDIS_STATUS_SUCCESS);
371123474Swpaul}
372123474Swpaul
373123474Swpaul__stdcall static ndis_status
374123474Swpaulndis_malloc_withtag(vaddr, len, tag)
375123474Swpaul	void			**vaddr;
376123474Swpaul	uint32_t		len;
377123474Swpaul	uint32_t		tag;
378123474Swpaul{
379123474Swpaul	void			*mem;
380123474Swpaul
381123474Swpaul	mem = malloc(len, M_DEVBUF, M_NOWAIT);
382123474Swpaul	if (mem == NULL)
383123474Swpaul		return(NDIS_STATUS_RESOURCES);
384123474Swpaul	*vaddr = mem;
385123474Swpaul
386123474Swpaul	return(NDIS_STATUS_SUCCESS);
387123474Swpaul}
388123474Swpaul
389123474Swpaul__stdcall static ndis_status
390123474Swpaulndis_malloc(vaddr, len, flags, highaddr)
391123474Swpaul	void			**vaddr;
392123474Swpaul	uint32_t		len;
393123474Swpaul	uint32_t		flags;
394123474Swpaul	ndis_physaddr		highaddr;
395123474Swpaul{
396123474Swpaul	void			*mem;
397123474Swpaul
398123474Swpaul	mem = malloc(len, M_DEVBUF, M_NOWAIT);
399123474Swpaul	if (mem == NULL)
400123474Swpaul		return(NDIS_STATUS_RESOURCES);
401123474Swpaul	*vaddr = mem;
402123474Swpaul
403123474Swpaul	return(NDIS_STATUS_SUCCESS);
404123474Swpaul}
405123474Swpaul
406123474Swpaul__stdcall static void
407123474Swpaulndis_free(vaddr, len, flags)
408123474Swpaul	void			*vaddr;
409123474Swpaul	uint32_t		len;
410123474Swpaul	uint32_t		flags;
411123474Swpaul{
412123474Swpaul	if (len == 0)
413123474Swpaul		return;
414123474Swpaul	free(vaddr, M_DEVBUF);
415123474Swpaul	return;
416123474Swpaul}
417123474Swpaul
418123474Swpaul__stdcall static ndis_status
419123474Swpaulndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
420123474Swpaul			flags, iftype)
421123474Swpaul	ndis_handle			adapter_handle;
422123474Swpaul	ndis_handle			adapter_ctx;
423123474Swpaul	uint32_t			hangsecs;
424123474Swpaul	uint32_t			flags;
425123474Swpaul	ndis_interface_type		iftype;
426123474Swpaul{
427123474Swpaul	ndis_miniport_block		*block;
428123474Swpaul
429123474Swpaul	/*
430123474Swpaul	 * Save the adapter context, we need it for calling
431123474Swpaul	 * the driver's internal functions.
432123474Swpaul	 */
433123474Swpaul	block = (ndis_miniport_block *)adapter_handle;
434123474Swpaul	block->nmb_miniportadapterctx = adapter_ctx;
435123474Swpaul	block->nmb_checkforhangsecs = hangsecs;
436123474Swpaul
437123474Swpaul	return(NDIS_STATUS_SUCCESS);
438123474Swpaul}
439123474Swpaul
440123474Swpaul__stdcall static void
441123474Swpaulndis_open_cfg(status, cfg, wrapctx)
442123474Swpaul	ndis_status		*status;
443123474Swpaul	ndis_handle		*cfg;
444123474Swpaul	ndis_handle		wrapctx;
445123474Swpaul{
446123474Swpaul	*cfg = wrapctx;
447123474Swpaul	*status = NDIS_STATUS_SUCCESS;
448123474Swpaul	return;
449123474Swpaul}
450123474Swpaul
451123526Swpaul__stdcall static void
452123526Swpaulndis_open_cfgbyname(status, cfg, subkey, subhandle)
453123526Swpaul	ndis_status		*status;
454123526Swpaul	ndis_handle		cfg;
455123526Swpaul	ndis_unicode_string	*subkey;
456123526Swpaul	ndis_handle		*subhandle;
457123526Swpaul{
458123526Swpaul	*subhandle = cfg;
459123526Swpaul	*status = NDIS_STATUS_SUCCESS;
460123526Swpaul	return;
461123526Swpaul}
462123526Swpaul
463123526Swpaul__stdcall static void
464123526Swpaulndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle)
465123526Swpaul	ndis_status		*status;
466123526Swpaul	ndis_handle		cfg;
467123526Swpaul	uint32_t		idx;
468123526Swpaul	ndis_unicode_string	*subkey;
469123526Swpaul	ndis_handle		*subhandle;
470123526Swpaul{
471123526Swpaul	*status = NDIS_STATUS_FAILURE;
472123526Swpaul	return;
473123526Swpaul}
474123526Swpaul
475123474Swpaulstatic ndis_status
476123474Swpaulndis_encode_parm(block, oid, type, parm)
477123474Swpaul	ndis_miniport_block	*block;
478123474Swpaul        struct sysctl_oid	*oid;
479123474Swpaul	ndis_parm_type		type;
480123474Swpaul	ndis_config_parm	**parm;
481123474Swpaul{
482123474Swpaul	uint16_t		*unicode;
483123474Swpaul	ndis_unicode_string	*ustr;
484123474Swpaul
485123474Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
486123474Swpaul
487123474Swpaul	switch(type) {
488123474Swpaul	case ndis_parm_string:
489123474Swpaul		ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
490123474Swpaul		(*parm)->ncp_type = ndis_parm_string;
491123474Swpaul		ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
492123474Swpaul		ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
493123474Swpaul		ustr->nus_buf = unicode;
494123474Swpaul		break;
495123474Swpaul	case ndis_parm_int:
496123474Swpaul		(*parm)->ncp_type = ndis_parm_int;
497123474Swpaul		(*parm)->ncp_parmdata.ncp_intdata =
498123474Swpaul		    strtol((char *)oid->oid_arg1, NULL, 10);
499123474Swpaul		break;
500123474Swpaul	case ndis_parm_hexint:
501123474Swpaul		(*parm)->ncp_type = ndis_parm_hexint;
502123474Swpaul		(*parm)->ncp_parmdata.ncp_intdata =
503123474Swpaul		    strtoul((char *)oid->oid_arg1, NULL, 16);
504123474Swpaul		break;
505123474Swpaul	default:
506123474Swpaul		return(NDIS_STATUS_FAILURE);
507123474Swpaul		break;
508123474Swpaul	}
509123474Swpaul
510123474Swpaul	return(NDIS_STATUS_SUCCESS);
511123474Swpaul}
512123474Swpaul
513123474Swpaul__stdcall static void
514123474Swpaulndis_read_cfg(status, parm, cfg, key, type)
515123474Swpaul	ndis_status		*status;
516123474Swpaul	ndis_config_parm	**parm;
517123474Swpaul	ndis_handle		cfg;
518123474Swpaul	ndis_unicode_string	*key;
519123474Swpaul	ndis_parm_type		type;
520123474Swpaul{
521123474Swpaul	char			*keystr = NULL;
522123474Swpaul	uint16_t		*unicode;
523123474Swpaul	ndis_miniport_block	*block;
524123474Swpaul	struct ndis_softc	*sc;
525123474Swpaul        struct sysctl_oid	*oidp;
526123474Swpaul	struct sysctl_ctx_entry	*e;
527123474Swpaul
528123474Swpaul	block = (ndis_miniport_block *)cfg;
529123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
530123474Swpaul
531124100Swpaul	if (key->nus_len == 0 || key->nus_buf == NULL) {
532124100Swpaul		*status = NDIS_STATUS_FAILURE;
533124100Swpaul		return;
534124100Swpaul	}
535124100Swpaul
536123474Swpaul	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
537123474Swpaul
538123474Swpaul	*parm = &block->nmb_replyparm;
539123474Swpaul	bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
540123474Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
541123474Swpaul
542123474Swpaul	/*
543123474Swpaul	 * See if registry key is already in a list of known keys
544123474Swpaul	 * included with the driver.
545123474Swpaul	 */
546123474Swpaul	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
547123474Swpaul		oidp = e->entry;
548123474Swpaul		if (strcmp(oidp->oid_name, keystr) == 0) {
549123488Swpaul			if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
550123488Swpaul				free(keystr, M_DEVBUF);
551123488Swpaul				*status = NDIS_STATUS_FAILURE;
552123488Swpaul				return;
553123488Swpaul			}
554123474Swpaul			*status = ndis_encode_parm(block, oidp, type, parm);
555123474Swpaul			free(keystr, M_DEVBUF);
556123474Swpaul			return;
557123474Swpaul		}
558123474Swpaul	}
559123474Swpaul
560123474Swpaul	/*
561123474Swpaul	 * If the key didn't match, add it to the list of dynamically
562123474Swpaul	 * created ones. Sometimes, drivers refer to registry keys
563123474Swpaul	 * that aren't documented in their .INF files. These keys
564123474Swpaul	 * are supposed to be created by some sort of utility or
565123474Swpaul	 * control panel snap-in that comes with the driver software.
566123474Swpaul	 * Sometimes it's useful to be able to manipulate these.
567123474Swpaul	 * If the driver requests the key in the form of a string,
568123474Swpaul	 * make its default value an empty string, otherwise default
569123474Swpaul	 * it to "0".
570123474Swpaul	 */
571123474Swpaul
572123474Swpaul	if (type == ndis_parm_int || type == ndis_parm_hexint)
573123488Swpaul		ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
574123488Swpaul		    "UNSET", CTLFLAG_RW);
575123474Swpaul	else
576123488Swpaul		ndis_add_sysctl(sc, keystr, "(dynamic string key)",
577123488Swpaul		    "UNSET", CTLFLAG_RW);
578123474Swpaul
579123474Swpaul	free(keystr, M_DEVBUF);
580123474Swpaul	*status = NDIS_STATUS_FAILURE;
581123474Swpaul	return;
582123474Swpaul}
583123474Swpaul
584123526Swpaulstatic ndis_status
585123526Swpaulndis_decode_parm(block, parm, val)
586123526Swpaul	ndis_miniport_block	*block;
587123526Swpaul	ndis_config_parm	*parm;
588123526Swpaul	char			*val;
589123526Swpaul{
590123526Swpaul	uint16_t		*unicode;
591123526Swpaul	ndis_unicode_string	*ustr;
592123526Swpaul
593123526Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
594123526Swpaul
595123526Swpaul	switch(parm->ncp_type) {
596123526Swpaul	case ndis_parm_string:
597123526Swpaul		ustr = &parm->ncp_parmdata.ncp_stringdata;
598123526Swpaul		ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &val);
599123526Swpaul		break;
600123526Swpaul	case ndis_parm_int:
601123526Swpaul		sprintf(val, "%ul", parm->ncp_parmdata.ncp_intdata);
602123526Swpaul		break;
603123526Swpaul	case ndis_parm_hexint:
604123526Swpaul		sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
605123526Swpaul		break;
606123526Swpaul	default:
607123526Swpaul		return(NDIS_STATUS_FAILURE);
608123526Swpaul		break;
609123526Swpaul	}
610123526Swpaul	return(NDIS_STATUS_SUCCESS);
611123526Swpaul}
612123526Swpaul
613123474Swpaul__stdcall static void
614123526Swpaulndis_write_cfg(status, cfg, key, parm)
615123526Swpaul	ndis_status		*status;
616123526Swpaul	ndis_handle		cfg;
617123526Swpaul	ndis_unicode_string	*key;
618123526Swpaul	ndis_config_parm	*parm;
619123526Swpaul{
620123526Swpaul	char			*keystr = NULL;
621123526Swpaul	ndis_miniport_block	*block;
622123526Swpaul	struct ndis_softc	*sc;
623123526Swpaul        struct sysctl_oid	*oidp;
624123526Swpaul	struct sysctl_ctx_entry	*e;
625123526Swpaul	char			val[256];
626123526Swpaul
627123526Swpaul	block = (ndis_miniport_block *)cfg;
628123526Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
629123526Swpaul
630123526Swpaul	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
631123526Swpaul
632123526Swpaul	/* Decode the parameter into a string. */
633123526Swpaul	*status = ndis_decode_parm(block, parm, val);
634123526Swpaul	if (*status != NDIS_STATUS_SUCCESS) {
635123526Swpaul		free(keystr, M_DEVBUF);
636123526Swpaul		return;
637123526Swpaul	}
638123526Swpaul
639123526Swpaul	/* See if the key already exists. */
640123526Swpaul
641123526Swpaul	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
642123526Swpaul		oidp = e->entry;
643123526Swpaul		if (strcmp(oidp->oid_name, keystr) == 0) {
644123526Swpaul			/* Found it, set the value. */
645123526Swpaul			strcpy((char *)oidp->oid_arg1, val);
646123526Swpaul			free(keystr, M_DEVBUF);
647123526Swpaul			return;
648123526Swpaul		}
649123526Swpaul	}
650123526Swpaul
651123526Swpaul	/* Not found, add a new key with the specified value. */
652123526Swpaul	ndis_add_sysctl(sc, keystr, "(dynamically set key)",
653123526Swpaul		    val, CTLFLAG_RW);
654123526Swpaul
655123526Swpaul	free(keystr, M_DEVBUF);
656123526Swpaul	*status = NDIS_STATUS_SUCCESS;
657123526Swpaul	return;
658123526Swpaul}
659123526Swpaul
660123526Swpaul__stdcall static void
661123474Swpaulndis_close_cfg(cfg)
662123474Swpaul	ndis_handle		cfg;
663123474Swpaul{
664123474Swpaul	return;
665123474Swpaul}
666123474Swpaul
667123474Swpaul__stdcall static void
668123474Swpaulndis_create_lock(lock)
669123474Swpaul	ndis_spin_lock		*lock;
670123474Swpaul{
671123474Swpaul	struct mtx		*mtx;
672123474Swpaul
673123474Swpaul	mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO);
674123474Swpaul	if (mtx == NULL)
675123474Swpaul		return;
676123695Swpaul	mtx_init(mtx, "ndislock", "ndis spin lock",
677123474Swpaul	    MTX_DEF | MTX_RECURSE | MTX_DUPOK);
678123474Swpaul	lock->nsl_spinlock = (ndis_kspin_lock)mtx;
679123474Swpaul
680123474Swpaul	return;
681123474Swpaul}
682123474Swpaul
683123474Swpaul__stdcall static void
684123474Swpaulndis_destroy_lock(lock)
685123474Swpaul	ndis_spin_lock		*lock;
686123474Swpaul{
687123474Swpaul	struct mtx		*ndis_mtx;
688123474Swpaul
689123474Swpaul	ndis_mtx = (struct mtx *)lock->nsl_spinlock;
690123474Swpaul	mtx_destroy(ndis_mtx);
691123474Swpaul	free(ndis_mtx, M_DEVBUF);
692124100Swpaul	lock->nsl_spinlock = 0xdeadf00d; /* XXX */
693123474Swpaul
694123474Swpaul	return;
695123474Swpaul}
696123474Swpaul
697123474Swpaul__stdcall static void
698123474Swpaulndis_lock(lock)
699123474Swpaul	ndis_spin_lock		*lock;
700123474Swpaul{
701123474Swpaul	if (lock == NULL)
702123474Swpaul		return;
703124100Swpaul	/*
704124100Swpaul	 * Workaround for certain broken NDIS drivers. I have
705124100Swpaul	 * encountered one case where a driver creates a spinlock
706124100Swpaul	 * within its DriverEntry() routine, which is then destroyed
707124100Swpaul	 * in its MiniportHalt() routine. This is a bug, because
708124100Swpaul	 * MiniportHalt() is meant to only destroy what MiniportInit()
709124100Swpaul	 * creates. This leads to the following problem:
710124100Swpaul	 *     DriverEntry() <- spinlock created
711124100Swpaul	 *     MiniportInit() <- NIC initialized
712124100Swpaul	 *     MiniportHalt() <- NIC halted, spinlock destroyed
713124100Swpaul	 *     MiniportInit() <- NIC initialized, spinlock not recreated
714124100Swpaul	 *     NdisAcquireSpinLock(boguslock) <- panic
715124100Swpaul	 * To work around this, we poison the spinlock on destroy, and
716124100Swpaul	 * if we try to re-acquire the poison pill^Wspinlock, we init
717124100Swpaul	 * it again so subsequent calls will work.
718124100Swpaul	 *
719124100Swpaul	 * Drivers that behave in this way are likely not officially
720124100Swpaul	 * certified by Microsoft, since their I would expect the
721124100Swpaul	 * Microsoft NDIS test tool to catch mistakes like this.
722124100Swpaul	 */
723124100Swpaul	if (lock->nsl_spinlock == 0xdeadf00d)
724124100Swpaul		ndis_create_lock(lock);
725123474Swpaul	mtx_lock((struct mtx *)lock->nsl_spinlock);
726123474Swpaul
727123474Swpaul	return;
728123474Swpaul}
729123474Swpaul
730123474Swpaul__stdcall static void
731123474Swpaulndis_unlock(lock)
732123474Swpaul	ndis_spin_lock		*lock;
733123474Swpaul{
734123474Swpaul	if (lock == NULL)
735123474Swpaul		return;
736123474Swpaul	mtx_unlock((struct mtx *)lock->nsl_spinlock);
737123474Swpaul
738123474Swpaul	return;
739123474Swpaul}
740123474Swpaul
741123474Swpaul__stdcall static uint32_t
742123474Swpaulndis_read_pci(adapter, slot, offset, buf, len)
743123474Swpaul	ndis_handle		adapter;
744123474Swpaul	uint32_t		slot;
745123474Swpaul	uint32_t		offset;
746123474Swpaul	void			*buf;
747123474Swpaul	uint32_t		len;
748123474Swpaul{
749123474Swpaul	ndis_miniport_block	*block;
750123474Swpaul	int			i;
751123474Swpaul	char			*dest;
752123474Swpaul
753123474Swpaul	block = (ndis_miniport_block *)adapter;
754123474Swpaul	dest = buf;
755123474Swpaul	if (block == NULL || block->nmb_dev == NULL)
756123474Swpaul		return(0);
757123474Swpaul
758123474Swpaul	for (i = 0; i < len; i++)
759123474Swpaul		dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
760123474Swpaul
761123474Swpaul	return(len);
762123474Swpaul}
763123474Swpaul
764123474Swpaul__stdcall static uint32_t
765123474Swpaulndis_write_pci(adapter, slot, offset, buf, len)
766123474Swpaul	ndis_handle		adapter;
767123474Swpaul	uint32_t		slot;
768123474Swpaul	uint32_t		offset;
769123474Swpaul	void			*buf;
770123474Swpaul	uint32_t		len;
771123474Swpaul{
772123474Swpaul	ndis_miniport_block	*block;
773123474Swpaul	int			i;
774123474Swpaul	char			*dest;
775123474Swpaul
776123474Swpaul	block = (ndis_miniport_block *)adapter;
777123474Swpaul	dest = buf;
778123474Swpaul
779123474Swpaul	if (block == NULL || block->nmb_dev == NULL)
780123474Swpaul		return(0);
781123474Swpaul
782123474Swpaul	for (i = 0; i < len; i++)
783123474Swpaul		pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
784123474Swpaul
785123474Swpaul	return(len);
786123474Swpaul}
787123474Swpaul
788123474Swpaul/*
789123474Swpaul * The errorlog routine uses a variable argument list, so we
790123474Swpaul * have to declare it this way.
791123474Swpaul */
792123474Swpaulstatic void
793123474Swpaulndis_syslog(ndis_handle adapter, ndis_error_code code,
794123474Swpaul	uint32_t numerrors, ...)
795123474Swpaul{
796123474Swpaul	ndis_miniport_block	*block;
797123474Swpaul	va_list			ap;
798123474Swpaul	int			i;
799123474Swpaul
800123474Swpaul	block = (ndis_miniport_block *)adapter;
801123474Swpaul
802124060Swpaul	device_printf (block->nmb_dev, "NDIS ERROR: %x\n", code);
803124060Swpaul	device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
804123474Swpaul
805123474Swpaul	va_start(ap, numerrors);
806123474Swpaul	for (i = 0; i < numerrors; i++)
807124060Swpaul		device_printf (block->nmb_dev, "argptr: %p\n",
808124060Swpaul		    va_arg(ap, void *));
809123474Swpaul	va_end(ap);
810123474Swpaul
811123474Swpaul	return;
812123474Swpaul}
813123474Swpaul
814123474Swpaulstatic void
815123474Swpaulndis_map_cb(arg, segs, nseg, error)
816123474Swpaul	void			*arg;
817123474Swpaul	bus_dma_segment_t	*segs;
818123474Swpaul	int			nseg;
819123474Swpaul	int			error;
820123474Swpaul{
821123474Swpaul	struct ndis_map_arg	*ctx;
822123474Swpaul	int			i;
823123474Swpaul
824123474Swpaul	if (error)
825123474Swpaul		return;
826123474Swpaul
827123474Swpaul	ctx = arg;
828123474Swpaul
829123474Swpaul	for (i = 0; i < nseg; i++) {
830123474Swpaul		ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
831123474Swpaul		ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
832123474Swpaul	}
833123474Swpaul
834123474Swpaul	ctx->nma_cnt = nseg;
835123474Swpaul
836123474Swpaul	return;
837123474Swpaul}
838123474Swpaul
839123474Swpaul__stdcall static void
840123474Swpaulndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
841123474Swpaul	ndis_handle		adapter;
842123474Swpaul	ndis_buffer		*buf;
843123474Swpaul	uint32_t		mapreg;
844123474Swpaul	uint8_t			writedev;
845123474Swpaul	ndis_paddr_unit		*addrarray;
846123474Swpaul	uint32_t		*arraysize;
847123474Swpaul{
848123474Swpaul	ndis_miniport_block	*block;
849123474Swpaul	struct ndis_softc	*sc;
850123474Swpaul	struct ndis_map_arg	nma;
851123474Swpaul	bus_dmamap_t		map;
852123474Swpaul	int			error;
853123474Swpaul
854123474Swpaul	if (adapter == NULL)
855123474Swpaul		return;
856123474Swpaul
857123474Swpaul	block = (ndis_miniport_block *)adapter;
858123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
859123474Swpaul
860123474Swpaul	if (mapreg > sc->ndis_mmapcnt)
861123474Swpaul		return;
862123474Swpaul
863123474Swpaul	map = sc->ndis_mmaps[mapreg];
864123474Swpaul	nma.nma_fraglist = addrarray;
865123474Swpaul
866123474Swpaul	error = bus_dmamap_load(sc->ndis_mtag, map,
867123757Swpaul	    MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
868123474Swpaul	    (void *)&nma, BUS_DMA_NOWAIT);
869123474Swpaul
870123474Swpaul	if (error)
871123474Swpaul		return;
872123474Swpaul
873123474Swpaul	bus_dmamap_sync(sc->ndis_mtag, map,
874123474Swpaul	    writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
875123474Swpaul
876123474Swpaul	*arraysize = nma.nma_cnt;
877123474Swpaul
878123474Swpaul	return;
879123474Swpaul}
880123474Swpaul
881123474Swpaul__stdcall static void
882123474Swpaulndis_vtophys_unload(adapter, buf, mapreg)
883123474Swpaul	ndis_handle		adapter;
884123474Swpaul	ndis_buffer		*buf;
885123474Swpaul	uint32_t		mapreg;
886123474Swpaul{
887123474Swpaul	ndis_miniport_block	*block;
888123474Swpaul	struct ndis_softc	*sc;
889123474Swpaul	bus_dmamap_t		map;
890123474Swpaul
891123474Swpaul	if (adapter == NULL)
892123474Swpaul		return;
893123474Swpaul
894123474Swpaul	block = (ndis_miniport_block *)adapter;
895123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
896123474Swpaul
897123474Swpaul	if (mapreg > sc->ndis_mmapcnt)
898123474Swpaul		return;
899123474Swpaul
900123474Swpaul	map = sc->ndis_mmaps[mapreg];
901123474Swpaul
902123474Swpaul	bus_dmamap_sync(sc->ndis_mtag, map,
903123474Swpaul	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
904123474Swpaul
905123474Swpaul	bus_dmamap_unload(sc->ndis_mtag, map);
906123474Swpaul
907123474Swpaul	return;
908123474Swpaul}
909123474Swpaul
910123474Swpaul__stdcall static void
911123474Swpaulndis_create_timer(timer, handle, func, ctx)
912123474Swpaul	ndis_miniport_timer	*timer;
913123474Swpaul	ndis_handle		*handle;
914123474Swpaul	ndis_timer_function	func;
915123474Swpaul	void			*ctx;
916123474Swpaul{
917123821Swpaul	struct ndis_timer_entry	*ne = NULL;
918123821Swpaul	ndis_miniport_block	*block;
919123821Swpaul	block = (ndis_miniport_block *)handle;
920123474Swpaul
921123821Swpaul	ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT);
922123832Swpaul	callout_init(&ne->nte_ch, CALLOUT_MPSAFE);
923123821Swpaul	TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link);
924123821Swpaul	ne->nte_timer = timer;
925123821Swpaul
926123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
927123821Swpaul	timer->nmt_dpc.nk_deferredctx = &ne->nte_ch;
928123474Swpaul	timer->nmt_timerfunc = func;
929123474Swpaul	timer->nmt_timerctx = ctx;
930123474Swpaul
931123474Swpaul	return;
932123474Swpaul}
933123474Swpaul
934123474Swpaul/*
935123474Swpaul * The driver's timer callout is __stdcall function, so we need this
936123474Swpaul * intermediate step.
937123474Swpaul */
938123474Swpaul
939123474Swpaulstatic void
940123474Swpaulndis_timercall(arg)
941123474Swpaul	void		*arg;
942123474Swpaul{
943123474Swpaul	ndis_miniport_timer	*timer;
944123474Swpaul	__stdcall ndis_timer_function	timerfunc;
945123474Swpaul
946123474Swpaul	timer = arg;
947123474Swpaul
948123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
949123474Swpaul	timerfunc = timer->nmt_timerfunc;
950123474Swpaul	timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
951123474Swpaul
952123474Swpaul	return;
953123474Swpaul}
954123474Swpaul
955123474Swpaul/*
956123474Swpaul * Windows specifies timeouts in milliseconds. We specify timeouts
957123474Swpaul * in hz. Trying to compute a tenth of a second based on hz is tricky.
958123474Swpaul * so we approximate. Note that we abuse the dpc portion of the
959123474Swpaul * miniport timer structure to hold the UNIX callout handle.
960123474Swpaul */
961123474Swpaul__stdcall static void
962123474Swpaulndis_set_timer(timer, msecs)
963123474Swpaul	ndis_miniport_timer	*timer;
964123474Swpaul	uint32_t		msecs;
965123474Swpaul{
966123832Swpaul	struct callout		*ch;
967123474Swpaul	struct timeval		tv;
968123474Swpaul
969123474Swpaul	tv.tv_sec = 0;
970123474Swpaul	tv.tv_usec = msecs * 1000;
971123474Swpaul
972123821Swpaul	ch = timer->nmt_dpc.nk_deferredctx;
973123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_timercall;
974123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
975123832Swpaul	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
976123474Swpaul
977123474Swpaul	return;
978123474Swpaul}
979123474Swpaul
980123474Swpaulstatic void
981123474Swpaulndis_tick(arg)
982123474Swpaul	void			*arg;
983123474Swpaul{
984123474Swpaul	ndis_miniport_timer	*timer;
985123832Swpaul	struct callout		*ch;
986123474Swpaul	__stdcall ndis_timer_function	timerfunc;
987123474Swpaul	struct timeval		tv;
988123474Swpaul
989123474Swpaul	timer = arg;
990123474Swpaul
991123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
992123474Swpaul	timerfunc = timer->nmt_timerfunc;
993123474Swpaul	timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
994123474Swpaul
995123474Swpaul	/* Automatically reload timer. */
996123474Swpaul
997123474Swpaul	tv.tv_sec = 0;
998123474Swpaul	tv.tv_usec = timer->nmt_ktimer.nk_period * 1000;
999123821Swpaul	ch = timer->nmt_dpc.nk_deferredctx;
1000123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
1001123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
1002123832Swpaul	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1003123474Swpaul
1004123474Swpaul	return;
1005123474Swpaul}
1006123474Swpaul
1007123474Swpaul__stdcall static void
1008123474Swpaulndis_set_periodic_timer(timer, msecs)
1009123474Swpaul	ndis_miniport_timer	*timer;
1010123474Swpaul	uint32_t		msecs;
1011123474Swpaul{
1012123832Swpaul	struct callout		*ch;
1013123474Swpaul	struct timeval		tv;
1014123474Swpaul
1015123474Swpaul	tv.tv_sec = 0;
1016123474Swpaul	tv.tv_usec = msecs * 1000;
1017123474Swpaul
1018123474Swpaul	timer->nmt_ktimer.nk_period = msecs;
1019123821Swpaul	ch = timer->nmt_dpc.nk_deferredctx;
1020123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
1021123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
1022123832Swpaul	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1023123474Swpaul
1024123474Swpaul	return;
1025123474Swpaul}
1026123474Swpaul
1027123474Swpaul__stdcall static void
1028123474Swpaulndis_cancel_timer(timer, cancelled)
1029123474Swpaul	ndis_miniport_timer	*timer;
1030123474Swpaul	uint8_t			*cancelled;
1031123474Swpaul{
1032123832Swpaul	struct callout		*ch;
1033123474Swpaul
1034124097Swpaul	if (timer == NULL)
1035124097Swpaul		return;
1036123821Swpaul	ch = timer->nmt_dpc.nk_deferredctx;
1037124097Swpaul	if (ch == NULL)
1038124097Swpaul		return;
1039123832Swpaul	callout_stop(ch);
1040123821Swpaul	*cancelled = timer->nmt_ktimer.nk_header.dh_sigstate;
1041123474Swpaul
1042123474Swpaul	return;
1043123474Swpaul}
1044123474Swpaul
1045123474Swpaul__stdcall static void
1046123474Swpaulndis_query_resources(status, adapter, list, buflen)
1047123474Swpaul	ndis_status		*status;
1048123474Swpaul	ndis_handle		adapter;
1049123474Swpaul	ndis_resource_list	*list;
1050123474Swpaul	uint32_t		*buflen;
1051123474Swpaul{
1052123474Swpaul	ndis_miniport_block	*block;
1053123474Swpaul	struct ndis_softc	*sc;
1054124094Swpaul	int			rsclen;
1055123474Swpaul
1056123474Swpaul	block = (ndis_miniport_block *)adapter;
1057123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1058124094Swpaul
1059124094Swpaul	rsclen = sizeof(ndis_resource_list) +
1060123474Swpaul	    (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1061124094Swpaul	if (*buflen < rsclen) {
1062124094Swpaul		*buflen = rsclen;
1063124094Swpaul		*status = NDIS_STATUS_INVALID_LENGTH;
1064124094Swpaul		return;
1065124094Swpaul	}
1066123474Swpaul
1067123474Swpaul	bcopy((char *)block->nmb_rlist, (char *)list, *buflen);
1068123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1069123474Swpaul	return;
1070123474Swpaul}
1071123474Swpaul
1072123474Swpaul__stdcall static ndis_status
1073123474Swpaulndis_register_ioport(offset, adapter, port, numports)
1074123474Swpaul	void			**offset;
1075123474Swpaul	ndis_handle		adapter;
1076123474Swpaul	uint32_t		port;
1077123474Swpaul	uint32_t		numports;
1078123474Swpaul{
1079123474Swpaul	struct ndis_miniport_block	*block;
1080123474Swpaul	struct ndis_softc	*sc;
1081123474Swpaul
1082123474Swpaul	if (adapter == NULL)
1083123474Swpaul		return(NDIS_STATUS_FAILURE);
1084123474Swpaul
1085123474Swpaul	block = (ndis_miniport_block *)adapter;
1086123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1087123474Swpaul
1088123474Swpaul	if (sc->ndis_res_io == NULL)
1089123474Swpaul		return(NDIS_STATUS_FAILURE);
1090123474Swpaul
1091123474Swpaul	if (rman_get_size(sc->ndis_res_io) != numports)
1092123474Swpaul		return(NDIS_STATUS_INVALID_LENGTH);
1093123474Swpaul
1094123474Swpaul	*offset = (void *)rman_get_start(sc->ndis_res_io);
1095123474Swpaul
1096123474Swpaul	return(NDIS_STATUS_SUCCESS);
1097123474Swpaul}
1098123474Swpaul
1099123474Swpaul__stdcall static void
1100123474Swpaulndis_deregister_ioport(adapter, port, numports, offset)
1101123474Swpaul	ndis_handle		adapter;
1102123474Swpaul	uint32_t		port;
1103123474Swpaul	uint32_t		numports;
1104123474Swpaul	void			*offset;
1105123474Swpaul{
1106123474Swpaul	return;
1107123474Swpaul}
1108123474Swpaul
1109123474Swpaul__stdcall static void
1110123474Swpaulndis_read_netaddr(status, addr, addrlen, adapter)
1111123474Swpaul	ndis_status		*status;
1112123474Swpaul	void			**addr;
1113123474Swpaul	uint32_t		*addrlen;
1114123474Swpaul	ndis_handle		adapter;
1115123474Swpaul{
1116123474Swpaul	struct ndis_softc	*sc;
1117123474Swpaul	ndis_miniport_block	*block;
1118123474Swpaul	uint8_t			empty[] = { 0, 0, 0, 0, 0, 0 };
1119123474Swpaul
1120123474Swpaul	block = (ndis_miniport_block *)adapter;
1121123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1122123474Swpaul
1123123474Swpaul	if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1124123474Swpaul		*status = NDIS_STATUS_FAILURE;
1125123474Swpaul	else {
1126123474Swpaul		*addr = sc->arpcom.ac_enaddr;
1127123474Swpaul		*addrlen = ETHER_ADDR_LEN;
1128123474Swpaul		*status = NDIS_STATUS_SUCCESS;
1129123474Swpaul	}
1130123474Swpaul
1131123474Swpaul	return;
1132123474Swpaul}
1133123474Swpaul
1134123474Swpaul__stdcall static ndis_status
1135123848Swpaulndis_mapreg_cnt(bustype, cnt)
1136123848Swpaul	uint32_t		bustype;
1137123848Swpaul	uint32_t		*cnt;
1138123848Swpaul{
1139124097Swpaul	*cnt = 8192;
1140123848Swpaul	return(NDIS_STATUS_SUCCESS);
1141123848Swpaul}
1142123848Swpaul
1143123848Swpaul__stdcall static ndis_status
1144123474Swpaulndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
1145123474Swpaul	ndis_handle		adapter;
1146123474Swpaul	uint32_t		dmachannel;
1147123474Swpaul	uint8_t			dmasize;
1148123474Swpaul	uint32_t		physmapneeded;
1149123474Swpaul	uint32_t		maxmap;
1150123474Swpaul{
1151123474Swpaul	struct ndis_softc	*sc;
1152123474Swpaul	ndis_miniport_block	*block;
1153123474Swpaul	int			error, i, nseg = NDIS_MAXSEG;
1154123474Swpaul
1155123474Swpaul	block = (ndis_miniport_block *)adapter;
1156123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1157123474Swpaul
1158123474Swpaul	sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1159123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1160123474Swpaul
1161123474Swpaul	if (sc->ndis_mmaps == NULL)
1162123474Swpaul		return(NDIS_STATUS_RESOURCES);
1163123474Swpaul
1164123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1165123474Swpaul	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1166123474Swpaul	    NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1167123474Swpaul	    NULL, NULL, &sc->ndis_mtag);
1168123474Swpaul
1169123474Swpaul	if (error) {
1170123474Swpaul		free(sc->ndis_mmaps, M_DEVBUF);
1171123474Swpaul		return(NDIS_STATUS_RESOURCES);
1172123474Swpaul	}
1173123474Swpaul
1174123474Swpaul	for (i = 0; i < physmapneeded; i++)
1175123474Swpaul		bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1176123474Swpaul
1177123474Swpaul	sc->ndis_mmapcnt = physmapneeded;
1178123474Swpaul
1179123474Swpaul	return(NDIS_STATUS_SUCCESS);
1180123474Swpaul}
1181123474Swpaul
1182123474Swpaul__stdcall static void
1183123474Swpaulndis_free_mapreg(adapter)
1184123474Swpaul	ndis_handle		adapter;
1185123474Swpaul{
1186123474Swpaul	struct ndis_softc	*sc;
1187123474Swpaul	ndis_miniport_block	*block;
1188123474Swpaul	int			i;
1189123474Swpaul
1190123474Swpaul	block = (ndis_miniport_block *)adapter;
1191123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1192123474Swpaul
1193123474Swpaul	for (i = 0; i < sc->ndis_mmapcnt; i++)
1194123474Swpaul		bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1195123474Swpaul
1196123474Swpaul	free(sc->ndis_mmaps, M_DEVBUF);
1197123474Swpaul
1198123474Swpaul	bus_dma_tag_destroy(sc->ndis_mtag);
1199123474Swpaul
1200123474Swpaul	return;
1201123474Swpaul}
1202123474Swpaul
1203123474Swpaulstatic void
1204123474Swpaulndis_mapshared_cb(arg, segs, nseg, error)
1205123474Swpaul	void			*arg;
1206123474Swpaul	bus_dma_segment_t	*segs;
1207123474Swpaul	int			nseg;
1208123474Swpaul	int			error;
1209123474Swpaul{
1210123474Swpaul	ndis_physaddr		*p;
1211123474Swpaul
1212123474Swpaul	if (error || nseg > 1)
1213123474Swpaul		return;
1214123474Swpaul
1215123474Swpaul	p = arg;
1216123474Swpaul
1217123474Swpaul	p->np_quad = segs[0].ds_addr;
1218123474Swpaul
1219123474Swpaul	return;
1220123474Swpaul}
1221123474Swpaul
1222123474Swpaul/*
1223123474Swpaul * This maps to bus_dmamem_alloc().
1224123474Swpaul */
1225123474Swpaul__stdcall static void
1226123474Swpaulndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
1227123474Swpaul	ndis_handle		adapter;
1228123474Swpaul	uint32_t		len;
1229123474Swpaul	uint8_t			cached;
1230123474Swpaul	void			**vaddr;
1231123474Swpaul	ndis_physaddr		*paddr;
1232123474Swpaul{
1233123474Swpaul	ndis_miniport_block	*block;
1234123474Swpaul	struct ndis_softc	*sc;
1235123474Swpaul	struct ndis_shmem	*sh;
1236123474Swpaul	int			error;
1237123474Swpaul
1238123474Swpaul	if (adapter == NULL)
1239123474Swpaul		return;
1240123474Swpaul
1241123474Swpaul	block = (ndis_miniport_block *)adapter;
1242123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1243123474Swpaul
1244123474Swpaul	sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1245123474Swpaul	if (sh == NULL)
1246123474Swpaul		return;
1247123474Swpaul
1248123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1249123474Swpaul	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1250123474Swpaul	    NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
1251123474Swpaul	    &sh->ndis_stag);
1252123474Swpaul
1253123474Swpaul	if (error) {
1254123474Swpaul		free(sh, M_DEVBUF);
1255123474Swpaul		return;
1256123474Swpaul	}
1257123474Swpaul
1258123474Swpaul	error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1259123474Swpaul	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1260123474Swpaul
1261123474Swpaul	if (error) {
1262123474Swpaul		bus_dma_tag_destroy(sh->ndis_stag);
1263123474Swpaul		free(sh, M_DEVBUF);
1264123474Swpaul		return;
1265123474Swpaul	}
1266123474Swpaul
1267123474Swpaul	error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1268123474Swpaul	    len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1269123474Swpaul
1270123474Swpaul	if (error) {
1271123474Swpaul		bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1272123474Swpaul		bus_dma_tag_destroy(sh->ndis_stag);
1273123474Swpaul		free(sh, M_DEVBUF);
1274123474Swpaul		return;
1275123474Swpaul	}
1276123474Swpaul
1277123474Swpaul	sh->ndis_saddr = *vaddr;
1278123474Swpaul	sh->ndis_next = sc->ndis_shlist;
1279123474Swpaul	sc->ndis_shlist = sh;
1280123474Swpaul
1281123474Swpaul	return;
1282123474Swpaul}
1283123474Swpaul
1284123474Swpaul__stdcall static void
1285123474Swpaulndis_alloc_sharedmem_async(adapter, len, cached, ctx)
1286123474Swpaul	ndis_handle		adapter;
1287123474Swpaul	uint32_t		len;
1288123474Swpaul	uint8_t			cached;
1289123474Swpaul	void			*ctx;
1290123474Swpaul{
1291123474Swpaul	ndis_miniport_block	*block;
1292123474Swpaul	struct ndis_softc	*sc;
1293123474Swpaul	void			*vaddr;
1294123474Swpaul	ndis_physaddr		paddr;
1295123474Swpaul	__stdcall ndis_allocdone_handler	donefunc;
1296123474Swpaul
1297123474Swpaul	if (adapter == NULL)
1298123474Swpaul		return;
1299123474Swpaul
1300123474Swpaul	block = (ndis_miniport_block *)adapter;
1301123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1302123474Swpaul	donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1303123474Swpaul
1304123474Swpaul	ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr);
1305123474Swpaul	donefunc(adapter, vaddr, &paddr, len, ctx);
1306123474Swpaul
1307123474Swpaul	return;
1308123474Swpaul}
1309123474Swpaul
1310123474Swpaul__stdcall static void
1311123474Swpaulndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
1312123474Swpaul	ndis_handle		adapter;
1313123474Swpaul	uint32_t		len;
1314123474Swpaul	uint8_t			cached;
1315123474Swpaul	void			*vaddr;
1316123474Swpaul	ndis_physaddr		paddr;
1317123474Swpaul{
1318123474Swpaul	ndis_miniport_block	*block;
1319123474Swpaul	struct ndis_softc	*sc;
1320123474Swpaul	struct ndis_shmem	*sh, *prev;
1321123474Swpaul
1322123474Swpaul	if (vaddr == NULL || adapter == NULL)
1323123474Swpaul		return;
1324123474Swpaul
1325123474Swpaul	block = (ndis_miniport_block *)adapter;
1326123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1327123474Swpaul	sh = prev = sc->ndis_shlist;
1328123474Swpaul
1329123474Swpaul	while (sh) {
1330123474Swpaul		if (sh->ndis_saddr == vaddr)
1331123474Swpaul			break;
1332123474Swpaul		prev = sh;
1333123474Swpaul		sh = sh->ndis_next;
1334123474Swpaul	}
1335123474Swpaul
1336123474Swpaul	bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1337123474Swpaul	bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1338123474Swpaul	bus_dma_tag_destroy(sh->ndis_stag);
1339123474Swpaul
1340123474Swpaul	if (sh == sc->ndis_shlist)
1341123474Swpaul		sc->ndis_shlist = sh->ndis_next;
1342123474Swpaul	else
1343123474Swpaul		prev->ndis_next = sh->ndis_next;
1344123474Swpaul
1345123474Swpaul	free(sh, M_DEVBUF);
1346123474Swpaul
1347123474Swpaul	return;
1348123474Swpaul}
1349123474Swpaul
1350123474Swpaul__stdcall static ndis_status
1351123474Swpaulndis_map_iospace(vaddr, adapter, paddr, len)
1352123474Swpaul	void			**vaddr;
1353123474Swpaul	ndis_handle		adapter;
1354123474Swpaul	ndis_physaddr		paddr;
1355123474Swpaul	uint32_t		len;
1356123474Swpaul{
1357123474Swpaul	ndis_miniport_block	*block;
1358123474Swpaul	struct ndis_softc	*sc;
1359123474Swpaul
1360123474Swpaul	if (adapter == NULL)
1361123474Swpaul		return(NDIS_STATUS_FAILURE);
1362123474Swpaul
1363123474Swpaul	block = (ndis_miniport_block *)adapter;
1364123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1365123474Swpaul
1366123474Swpaul	if (sc->ndis_res_mem == NULL)
1367123474Swpaul		return(NDIS_STATUS_FAILURE);
1368123474Swpaul
1369123474Swpaul	*vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1370123474Swpaul
1371123474Swpaul	return(NDIS_STATUS_SUCCESS);
1372123474Swpaul}
1373123474Swpaul
1374123474Swpaul__stdcall static void
1375123474Swpaulndis_unmap_iospace(adapter, vaddr, len)
1376123474Swpaul	ndis_handle		adapter;
1377123474Swpaul	void			*vaddr;
1378123474Swpaul	uint32_t		len;
1379123474Swpaul{
1380123474Swpaul	return;
1381123474Swpaul}
1382123474Swpaul
1383123474Swpaul__stdcall static uint32_t
1384123474Swpaulndis_cachefill(void)
1385123474Swpaul{
1386123474Swpaul	return(128);
1387123474Swpaul}
1388123474Swpaul
1389123474Swpaul__stdcall static uint32_t
1390123474Swpaulndis_dma_align(handle)
1391123474Swpaul	ndis_handle		handle;
1392123474Swpaul{
1393123474Swpaul	return(128);
1394123474Swpaul}
1395123474Swpaul
1396123474Swpaul/*
1397123474Swpaul * NDIS has two methods for dealing with NICs that support DMA.
1398123474Swpaul * One is to just pass packets to the driver and let it call
1399123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1400123474Swpaul * all by itself, and the other is to let the NDIS library handle the
1401123474Swpaul * buffer mapping internally, and hand the driver an already populated
1402123474Swpaul * scatter/gather fragment list. If the driver calls
1403123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter
1404123474Swpaul * method.
1405123474Swpaul */
1406123474Swpaul
1407123474Swpaul__stdcall static ndis_status
1408123474Swpaulndis_init_sc_dma(adapter, is64, maxphysmap)
1409123474Swpaul	ndis_handle		adapter;
1410123474Swpaul	uint8_t			is64;
1411123474Swpaul	uint32_t		maxphysmap;
1412123474Swpaul{
1413123474Swpaul	struct ndis_softc	*sc;
1414123474Swpaul	ndis_miniport_block	*block;
1415123474Swpaul	int			error;
1416123474Swpaul
1417123474Swpaul	if (adapter == NULL)
1418123474Swpaul		return(NDIS_STATUS_FAILURE);
1419123474Swpaul	block = (ndis_miniport_block *)adapter;
1420123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1421123474Swpaul
1422123474Swpaul	/* Don't do this twice. */
1423123474Swpaul	if (sc->ndis_sc == 1)
1424123474Swpaul		return(NDIS_STATUS_SUCCESS);
1425123474Swpaul
1426123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1427123474Swpaul	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1428123474Swpaul	    MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1429123474Swpaul	    NULL, NULL, &sc->ndis_ttag);
1430123474Swpaul
1431123474Swpaul	sc->ndis_sc = 1;
1432123474Swpaul
1433123474Swpaul	return(NDIS_STATUS_SUCCESS);
1434123474Swpaul}
1435123474Swpaul
1436123474Swpaul__stdcall static void
1437123474Swpaulndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
1438123474Swpaul	ndis_status		*status;
1439123474Swpaul	ndis_handle		*pool;
1440123474Swpaul	uint32_t		descnum;
1441123474Swpaul	uint32_t		protrsvdlen;
1442123474Swpaul{
1443123474Swpaul	ndis_packet		*cur;
1444123474Swpaul	int			i;
1445123474Swpaul
1446124116Swpaul	*pool = malloc(sizeof(ndis_packet) *
1447124116Swpaul	    ((descnum + NDIS_POOL_EXTRA) + 1),
1448123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1449123474Swpaul
1450123474Swpaul	if (pool == NULL) {
1451123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1452123474Swpaul		return;
1453123474Swpaul	}
1454123474Swpaul
1455123474Swpaul	cur = (ndis_packet *)*pool;
1456123474Swpaul	cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1457124116Swpaul	for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1458123474Swpaul		cur->np_private.npp_head = (ndis_handle)(cur + 1);
1459123474Swpaul		cur++;
1460123474Swpaul	}
1461123474Swpaul
1462123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1463123474Swpaul	return;
1464123474Swpaul}
1465123474Swpaul
1466123474Swpaul__stdcall static void
1467123474Swpaulndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
1468123474Swpaul	ndis_status		*status;
1469123474Swpaul	ndis_handle		*pool;
1470123474Swpaul	uint32_t		descnum;
1471123474Swpaul	uint32_t		oflowdescnum;
1472123474Swpaul	uint32_t		protrsvdlen;
1473123474Swpaul{
1474123474Swpaul	return(ndis_alloc_packetpool(status, pool,
1475123474Swpaul	    descnum + oflowdescnum, protrsvdlen));
1476123474Swpaul}
1477123474Swpaul
1478123474Swpaul__stdcall static uint32_t
1479123474Swpaulndis_packetpool_use(pool)
1480123474Swpaul	ndis_handle		pool;
1481123474Swpaul{
1482123474Swpaul	ndis_packet		*head;
1483123474Swpaul
1484123474Swpaul	head = (ndis_packet *)pool;
1485123474Swpaul
1486123474Swpaul	return(head->np_private.npp_count);
1487123474Swpaul}
1488123474Swpaul
1489123474Swpaul__stdcall static void
1490123474Swpaulndis_free_packetpool(pool)
1491123474Swpaul	ndis_handle		pool;
1492123474Swpaul{
1493123474Swpaul	free(pool, M_DEVBUF);
1494123474Swpaul	return;
1495123474Swpaul}
1496123474Swpaul
1497123474Swpaul__stdcall static void
1498123474Swpaulndis_alloc_packet(status, packet, pool)
1499123474Swpaul	ndis_status		*status;
1500123474Swpaul	ndis_packet		**packet;
1501123474Swpaul	ndis_handle		pool;
1502123474Swpaul{
1503123474Swpaul	ndis_packet		*head, *pkt;
1504123474Swpaul
1505123474Swpaul	head = (ndis_packet *)pool;
1506123474Swpaul
1507123474Swpaul	if (head->np_private.npp_flags != 0x1) {
1508123474Swpaul		*status = NDIS_STATUS_FAILURE;
1509123474Swpaul		return;
1510123474Swpaul	}
1511123474Swpaul
1512123474Swpaul	pkt = (ndis_packet *)head->np_private.npp_head;
1513123474Swpaul
1514123474Swpaul	if (pkt == NULL) {
1515123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1516123474Swpaul		return;
1517123474Swpaul	}
1518123474Swpaul
1519123474Swpaul	head->np_private.npp_head = pkt->np_private.npp_head;
1520123474Swpaul
1521123474Swpaul	pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1522123474Swpaul	/* Save pointer to the pool. */
1523123474Swpaul	pkt->np_private.npp_pool = head;
1524123474Swpaul
1525123474Swpaul	/* Set the oob offset pointer. Lots of things expect this. */
1526123474Swpaul	pkt->np_private.npp_packetooboffset =
1527123474Swpaul	    offsetof(ndis_packet, np_oob);
1528123474Swpaul
1529123474Swpaul	*packet = pkt;
1530123474Swpaul
1531123474Swpaul	head->np_private.npp_count++;
1532123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1533123474Swpaul	return;
1534123474Swpaul}
1535123474Swpaul
1536123848Swpaul__stdcall static void
1537123848Swpaulndis_release_packet(packet)
1538123474Swpaul	ndis_packet		*packet;
1539123474Swpaul{
1540123474Swpaul	ndis_packet		*head;
1541123474Swpaul
1542123474Swpaul	if (packet == NULL || packet->np_private.npp_pool == NULL)
1543123474Swpaul		return;
1544123474Swpaul
1545123474Swpaul	head = packet->np_private.npp_pool;
1546123474Swpaul	if (head->np_private.npp_flags != 0x1)
1547123474Swpaul		return;
1548123474Swpaul
1549123474Swpaul	packet->np_private.npp_head = head->np_private.npp_head;
1550123474Swpaul	head->np_private.npp_head = (ndis_buffer *)packet;
1551123474Swpaul	head->np_private.npp_count--;
1552123474Swpaul
1553123474Swpaul	return;
1554123474Swpaul}
1555123474Swpaul
1556123474Swpaul__stdcall static void
1557123474Swpaulndis_unchain_headbuf(packet, buf)
1558123474Swpaul	ndis_packet		*packet;
1559123474Swpaul	ndis_buffer		**buf;
1560123474Swpaul{
1561123474Swpaul	ndis_packet_private	*priv;
1562123474Swpaul
1563123474Swpaul	if (packet == NULL || buf == NULL)
1564123474Swpaul		return;
1565123474Swpaul
1566123474Swpaul	priv = &packet->np_private;
1567123474Swpaul
1568123474Swpaul	priv->npp_validcounts = FALSE;
1569123474Swpaul
1570123474Swpaul	if (priv->npp_head == priv->npp_tail) {
1571123474Swpaul		*buf = priv->npp_head;
1572123474Swpaul		priv->npp_head = priv->npp_tail = NULL;
1573123474Swpaul	} else {
1574123474Swpaul		*buf = priv->npp_head;
1575123474Swpaul		priv->npp_head = (*buf)->nb_next;
1576123474Swpaul	}
1577123474Swpaul
1578123474Swpaul	return;
1579123474Swpaul}
1580123474Swpaul
1581123721Swpaul__stdcall static void
1582123721Swpaulndis_unchain_tailbuf(packet, buf)
1583123721Swpaul	ndis_packet		*packet;
1584123721Swpaul	ndis_buffer		**buf;
1585123721Swpaul{
1586123721Swpaul	ndis_packet_private	*priv;
1587123721Swpaul	ndis_buffer		*tmp;
1588123721Swpaul
1589123721Swpaul	if (packet == NULL || buf == NULL)
1590123721Swpaul		return;
1591123721Swpaul
1592123721Swpaul	priv = &packet->np_private;
1593123721Swpaul
1594123721Swpaul	priv->npp_validcounts = FALSE;
1595123721Swpaul
1596123721Swpaul	if (priv->npp_head == priv->npp_tail) {
1597123721Swpaul		*buf = priv->npp_head;
1598123721Swpaul		priv->npp_head = priv->npp_tail = NULL;
1599123721Swpaul	} else {
1600123721Swpaul		*buf = priv->npp_tail;
1601123721Swpaul		tmp = priv->npp_head;
1602123721Swpaul		while (tmp->nb_next != priv->npp_tail)
1603123721Swpaul			tmp = tmp->nb_next;
1604123721Swpaul		priv->npp_tail = tmp;
1605123721Swpaul		tmp->nb_next = NULL;
1606123721Swpaul	}
1607123721Swpaul
1608123721Swpaul	return;
1609123721Swpaul}
1610123721Swpaul
1611123474Swpaul/*
1612123474Swpaul * The NDIS "buffer" manipulation functions are somewhat misnamed.
1613123474Swpaul * They don't really allocate buffers: they allocate buffer mappings.
1614123474Swpaul * The idea is you reserve a chunk of DMA-able memory using
1615123474Swpaul * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1616123474Swpaul * to obtain the virtual address of the DMA-able region.
1617123474Swpaul * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1618123474Swpaul */
1619123474Swpaul
1620123474Swpaul__stdcall static void
1621123474Swpaulndis_alloc_bufpool(status, pool, descnum)
1622123474Swpaul	ndis_status		*status;
1623123474Swpaul	ndis_handle		*pool;
1624123474Swpaul	uint32_t		descnum;
1625123474Swpaul{
1626123474Swpaul	ndis_buffer		*cur;
1627123474Swpaul	int			i;
1628123474Swpaul
1629124116Swpaul	*pool = malloc(sizeof(ndis_buffer) *
1630124116Swpaul	    ((descnum + NDIS_POOL_EXTRA) + 1),
1631123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1632123474Swpaul
1633123474Swpaul	if (pool == NULL) {
1634123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1635123474Swpaul		return;
1636123474Swpaul	}
1637123474Swpaul
1638123474Swpaul	cur = (ndis_buffer *)*pool;
1639123474Swpaul	cur->nb_flags = 0x1; /* mark the head of the list */
1640124116Swpaul	for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1641123474Swpaul		cur->nb_next = cur + 1;
1642123474Swpaul		cur++;
1643123474Swpaul	}
1644123474Swpaul
1645123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1646123474Swpaul	return;
1647123474Swpaul}
1648123474Swpaul
1649123474Swpaul__stdcall static void
1650123474Swpaulndis_free_bufpool(pool)
1651123474Swpaul	ndis_handle		pool;
1652123474Swpaul{
1653123474Swpaul	free(pool, M_DEVBUF);
1654123474Swpaul	return;
1655123474Swpaul}
1656123474Swpaul
1657123474Swpaul/*
1658123474Swpaul * This maps to a bus_dmamap_create() and bus_dmamap_load().
1659123474Swpaul */
1660123474Swpaul__stdcall static void
1661123474Swpaulndis_alloc_buf(status, buffer, pool, vaddr, len)
1662123474Swpaul	ndis_status		*status;
1663123474Swpaul	ndis_buffer		**buffer;
1664123474Swpaul	ndis_handle		pool;
1665123474Swpaul	void			*vaddr;
1666123474Swpaul	uint32_t		len;
1667123474Swpaul{
1668123474Swpaul	ndis_buffer		*head, *buf;
1669123474Swpaul
1670123474Swpaul	head = (ndis_buffer *)pool;
1671123474Swpaul	if (head->nb_flags != 0x1) {
1672123474Swpaul		*status = NDIS_STATUS_FAILURE;
1673123474Swpaul		return;
1674123474Swpaul	}
1675123474Swpaul
1676123474Swpaul	buf = head->nb_next;
1677123474Swpaul
1678123474Swpaul	if (buf == NULL) {
1679123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1680123474Swpaul		return;
1681123474Swpaul	}
1682123474Swpaul
1683123474Swpaul	head->nb_next = buf->nb_next;
1684123474Swpaul
1685123474Swpaul	/* Save pointer to the pool. */
1686123474Swpaul	buf->nb_process = head;
1687123474Swpaul
1688123757Swpaul	MDL_INIT(buf, vaddr, len);
1689123474Swpaul
1690123474Swpaul	*buffer = buf;
1691123474Swpaul
1692123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1693123474Swpaul	return;
1694123474Swpaul}
1695123474Swpaul
1696123848Swpaul__stdcall static void
1697123848Swpaulndis_release_buf(buf)
1698123474Swpaul	ndis_buffer		*buf;
1699123474Swpaul{
1700123474Swpaul	ndis_buffer		*head;
1701123474Swpaul
1702123474Swpaul	if (buf == NULL || buf->nb_process == NULL)
1703123474Swpaul		return;
1704123474Swpaul
1705123474Swpaul	head = buf->nb_process;
1706123474Swpaul
1707123474Swpaul	if (head->nb_flags != 0x1)
1708123474Swpaul		return;
1709123474Swpaul
1710123474Swpaul	buf->nb_next = head->nb_next;
1711123474Swpaul	head->nb_next = buf;
1712123474Swpaul
1713123474Swpaul	return;
1714123474Swpaul}
1715123474Swpaul
1716124100Swpaul/* Aw c'mon. */
1717124100Swpaul
1718124100Swpaul__stdcall static uint32_t
1719124100Swpaulndis_buflen(buf)
1720124100Swpaul	ndis_buffer		*buf;
1721124100Swpaul{
1722124100Swpaul	return(buf->nb_bytecount);
1723124100Swpaul}
1724124100Swpaul
1725123723Swpaul/*
1726123723Swpaul * Get the virtual address and length of a buffer.
1727123723Swpaul * Note: the vaddr argument is optional.
1728123723Swpaul */
1729123474Swpaul
1730123474Swpaul__stdcall static void
1731123474Swpaulndis_query_buf(buf, vaddr, len)
1732123474Swpaul	ndis_buffer		*buf;
1733123474Swpaul	void			**vaddr;
1734123474Swpaul	uint32_t		*len;
1735123474Swpaul{
1736123723Swpaul	if (vaddr != NULL)
1737123757Swpaul		*vaddr = MDL_VA(buf);
1738123474Swpaul	*len = buf->nb_bytecount;
1739123474Swpaul
1740123474Swpaul	return;
1741123474Swpaul}
1742123474Swpaul
1743123474Swpaul/* Same as above -- we don't care about the priority. */
1744123474Swpaul
1745123474Swpaul__stdcall static void
1746123474Swpaulndis_query_buf_safe(buf, vaddr, len, prio)
1747123474Swpaul	ndis_buffer		*buf;
1748123474Swpaul	void			**vaddr;
1749123474Swpaul	uint32_t		*len;
1750123474Swpaul	uint32_t		prio;
1751123474Swpaul{
1752123723Swpaul	if (vaddr != NULL)
1753123757Swpaul		*vaddr = MDL_VA(buf);
1754123474Swpaul	*len = buf->nb_bytecount;
1755123474Swpaul
1756123474Swpaul	return;
1757123474Swpaul}
1758123474Swpaul
1759123474Swpaul__stdcall static void
1760123474Swpaulndis_adjust_buflen(buf, len)
1761123474Swpaul	ndis_buffer		*buf;
1762123474Swpaul	int			len;
1763123474Swpaul{
1764123474Swpaul	buf->nb_bytecount = len;
1765123474Swpaul
1766123474Swpaul	return;
1767123474Swpaul}
1768123474Swpaul
1769123474Swpaul__stdcall static uint32_t
1770123474Swpaulndis_interlock_inc(addend)
1771123474Swpaul	uint32_t		*addend;
1772123474Swpaul{
1773123474Swpaul	mtx_lock(&ndis_interlock);
1774123474Swpaul	*addend++;
1775123474Swpaul	mtx_unlock(&ndis_interlock);
1776123474Swpaul	return(*addend);
1777123474Swpaul}
1778123474Swpaul
1779123474Swpaul__stdcall static uint32_t
1780123474Swpaulndis_interlock_dec(addend)
1781123474Swpaul	uint32_t		*addend;
1782123474Swpaul{
1783123474Swpaul	mtx_lock(&ndis_interlock);
1784123474Swpaul	*addend--;
1785123474Swpaul	mtx_unlock(&ndis_interlock);
1786123474Swpaul	return(*addend);
1787123474Swpaul}
1788123474Swpaul
1789123474Swpaul__stdcall static void
1790123474Swpaulndis_init_event(event)
1791123474Swpaul	ndis_event		*event;
1792123474Swpaul{
1793123474Swpaul	event->ne_event.nk_header.dh_sigstate = FALSE;
1794123474Swpaul	return;
1795123474Swpaul}
1796123474Swpaul
1797123474Swpaul__stdcall static void
1798123474Swpaulndis_set_event(event)
1799123474Swpaul	ndis_event		*event;
1800123474Swpaul{
1801123474Swpaul	event->ne_event.nk_header.dh_sigstate = TRUE;
1802123474Swpaul	wakeup(event);
1803123474Swpaul	return;
1804123474Swpaul}
1805123474Swpaul
1806123474Swpaul__stdcall static void
1807123474Swpaulndis_reset_event(event)
1808123474Swpaul	ndis_event		*event;
1809123474Swpaul{
1810123474Swpaul	event->ne_event.nk_header.dh_sigstate = FALSE;
1811123474Swpaul	wakeup(event);
1812123474Swpaul	return;
1813123474Swpaul}
1814123474Swpaul
1815123474Swpaul__stdcall static uint8_t
1816123474Swpaulndis_wait_event(event, msecs)
1817123474Swpaul	ndis_event		*event;
1818123474Swpaul	uint32_t		msecs;
1819123474Swpaul{
1820123474Swpaul	int			error;
1821123474Swpaul	struct timeval		tv;
1822123474Swpaul
1823123474Swpaul	if (event->ne_event.nk_header.dh_sigstate == TRUE)
1824123474Swpaul		return(TRUE);
1825123474Swpaul
1826123474Swpaul	tv.tv_sec = 0;
1827123474Swpaul	tv.tv_usec = msecs * 1000;
1828123474Swpaul
1829123474Swpaul	error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
1830123474Swpaul
1831123474Swpaul	return(event->ne_event.nk_header.dh_sigstate);
1832123474Swpaul}
1833123474Swpaul
1834123474Swpaul__stdcall static ndis_status
1835123474Swpaulndis_unicode2ansi(dstr, sstr)
1836123526Swpaul	ndis_ansi_string	*dstr;
1837123526Swpaul	ndis_unicode_string	*sstr;
1838123474Swpaul{
1839123526Swpaul	if (dstr == NULL || sstr == NULL)
1840123526Swpaul		return(NDIS_STATUS_FAILURE);
1841123526Swpaul	if (ndis_unicode_to_ascii(sstr->nus_buf,
1842123526Swpaul	    sstr->nus_len, &dstr->nas_buf))
1843123526Swpaul		return(NDIS_STATUS_FAILURE);
1844123526Swpaul	dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
1845123474Swpaul	return (NDIS_STATUS_SUCCESS);
1846123474Swpaul}
1847123474Swpaul
1848123474Swpaul__stdcall static ndis_status
1849123526Swpaulndis_ansi2unicode(dstr, sstr)
1850123526Swpaul	ndis_unicode_string	*dstr;
1851123526Swpaul	ndis_ansi_string	*sstr;
1852123526Swpaul{
1853123526Swpaul	char			*str;
1854123526Swpaul	if (dstr == NULL || sstr == NULL)
1855123526Swpaul		return(NDIS_STATUS_FAILURE);
1856123526Swpaul	str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
1857123526Swpaul	if (str == NULL)
1858123526Swpaul		return(NDIS_STATUS_FAILURE);
1859123526Swpaul	strncpy(str, sstr->nas_buf, sstr->nas_len);
1860123526Swpaul	*(str + sstr->nas_len) = '\0';
1861123526Swpaul	if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
1862123526Swpaul		free(str, M_DEVBUF);
1863123526Swpaul		return(NDIS_STATUS_FAILURE);
1864123526Swpaul	}
1865123526Swpaul	dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
1866123526Swpaul	free(str, M_DEVBUF);
1867123526Swpaul	return (NDIS_STATUS_SUCCESS);
1868123526Swpaul}
1869123526Swpaul
1870123526Swpaul__stdcall static ndis_status
1871123474Swpaulndis_assign_pcirsrc(adapter, slot, list)
1872123474Swpaul	ndis_handle		adapter;
1873123474Swpaul	uint32_t		slot;
1874123474Swpaul	ndis_resource_list	**list;
1875123474Swpaul{
1876123474Swpaul	ndis_miniport_block	*block;
1877123474Swpaul
1878123474Swpaul	if (adapter == NULL || list == NULL)
1879123474Swpaul		return (NDIS_STATUS_FAILURE);
1880123474Swpaul
1881123474Swpaul	block = (ndis_miniport_block *)adapter;
1882123474Swpaul	*list = block->nmb_rlist;
1883123474Swpaul
1884123474Swpaul	return (NDIS_STATUS_SUCCESS);
1885123474Swpaul}
1886123474Swpaul
1887123474Swpaul__stdcall static ndis_status
1888123474Swpaulndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
1889123474Swpaul	ndis_miniport_interrupt	*intr;
1890123474Swpaul	ndis_handle		adapter;
1891123474Swpaul	uint32_t		ivec;
1892123474Swpaul	uint32_t		ilevel;
1893123474Swpaul	uint8_t			reqisr;
1894123474Swpaul	uint8_t			shared;
1895123474Swpaul	ndis_interrupt_mode	imode;
1896123474Swpaul{
1897123474Swpaul
1898123474Swpaul	return(NDIS_STATUS_SUCCESS);
1899123474Swpaul}
1900123474Swpaul
1901123474Swpaul__stdcall static void
1902123474Swpaulndis_deregister_intr(intr)
1903123474Swpaul	ndis_miniport_interrupt	*intr;
1904123474Swpaul{
1905123474Swpaul	return;
1906123474Swpaul}
1907123474Swpaul
1908123474Swpaul__stdcall static void
1909123474Swpaulndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
1910123474Swpaul	ndis_handle		adapter;
1911123474Swpaul	void			*shutdownctx;
1912123474Swpaul	ndis_shutdown_handler	shutdownfunc;
1913123474Swpaul{
1914123474Swpaul	ndis_miniport_block	*block;
1915123474Swpaul	ndis_miniport_characteristics *chars;
1916123474Swpaul	struct ndis_softc	*sc;
1917123474Swpaul
1918123474Swpaul	if (adapter == NULL)
1919123474Swpaul		return;
1920123474Swpaul
1921123474Swpaul	block = (ndis_miniport_block *)adapter;
1922123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1923123474Swpaul	chars = &sc->ndis_chars;
1924123474Swpaul
1925123474Swpaul	chars->nmc_shutdown_handler = shutdownfunc;
1926123474Swpaul	chars->nmc_rsvd0 = shutdownctx;
1927123474Swpaul
1928123474Swpaul	return;
1929123474Swpaul}
1930123474Swpaul
1931123474Swpaul__stdcall static void
1932123474Swpaulndis_deregister_shutdown(adapter)
1933123474Swpaul	ndis_handle		adapter;
1934123474Swpaul{
1935123474Swpaul	ndis_miniport_block	*block;
1936123474Swpaul	ndis_miniport_characteristics *chars;
1937123474Swpaul	struct ndis_softc	*sc;
1938123474Swpaul
1939123474Swpaul	if (adapter == NULL)
1940123474Swpaul		return;
1941123474Swpaul
1942123474Swpaul	block = (ndis_miniport_block *)adapter;
1943123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1944123474Swpaul	chars = &sc->ndis_chars;
1945123474Swpaul
1946123474Swpaul	chars->nmc_shutdown_handler = NULL;
1947123474Swpaul	chars->nmc_rsvd0 = NULL;
1948123474Swpaul
1949123474Swpaul	return;
1950123474Swpaul}
1951123474Swpaul
1952123474Swpaul__stdcall static uint32_t
1953123474Swpaulndis_numpages(buf)
1954123474Swpaul	ndis_buffer		*buf;
1955123474Swpaul{
1956123757Swpaul	if (buf == NULL)
1957123757Swpaul		return(0);
1958123512Swpaul	if (buf->nb_bytecount == 0)
1959123512Swpaul		return(1);
1960123757Swpaul	return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
1961123474Swpaul}
1962123474Swpaul
1963123474Swpaul__stdcall static void
1964123573Swpaulndis_buf_physpages(buf, pages)
1965123573Swpaul	ndis_buffer		*buf;
1966123573Swpaul	uint32_t		*pages;
1967123573Swpaul{
1968123757Swpaul	if (buf == NULL)
1969123757Swpaul		return;
1970123757Swpaul
1971123573Swpaul	*pages = ndis_numpages(buf);
1972123573Swpaul	return;
1973123573Swpaul}
1974123573Swpaul
1975123573Swpaul__stdcall static void
1976123474Swpaulndis_query_bufoffset(buf, off, len)
1977123474Swpaul	ndis_buffer		*buf;
1978123474Swpaul	uint32_t		*off;
1979123474Swpaul	uint32_t		*len;
1980123474Swpaul{
1981123757Swpaul	if (buf == NULL)
1982123757Swpaul		return;
1983123757Swpaul
1984123757Swpaul	*off = buf->nb_byteoffset;
1985123474Swpaul	*len = buf->nb_bytecount;
1986123474Swpaul
1987123474Swpaul	return;
1988123474Swpaul}
1989123474Swpaul
1990123474Swpaul__stdcall static void
1991123474Swpaulndis_sleep(usecs)
1992123474Swpaul	uint32_t		usecs;
1993123474Swpaul{
1994123474Swpaul	struct timeval		tv;
1995123474Swpaul	uint32_t		dummy;
1996123474Swpaul
1997123474Swpaul	tv.tv_sec = 0;
1998123474Swpaul	tv.tv_usec = usecs;
1999123474Swpaul
2000123474Swpaul	tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
2001124100Swpaul
2002123474Swpaul	return;
2003123474Swpaul}
2004123474Swpaul
2005123474Swpaul__stdcall static uint32_t
2006123474Swpaulndis_read_pccard_amem(handle, offset, buf, len)
2007123474Swpaul	ndis_handle		handle;
2008123474Swpaul	uint32_t		offset;
2009123474Swpaul	void			*buf;
2010123474Swpaul	uint32_t		len;
2011123474Swpaul{
2012123474Swpaul	struct ndis_softc	*sc;
2013123474Swpaul	ndis_miniport_block	*block;
2014123474Swpaul	bus_space_handle_t	bh;
2015123474Swpaul	bus_space_tag_t		bt;
2016123474Swpaul	char			*dest;
2017123474Swpaul	int			i;
2018123474Swpaul
2019123474Swpaul	if (handle == NULL)
2020123474Swpaul		return(0);
2021123474Swpaul
2022123474Swpaul	block = (ndis_miniport_block *)handle;
2023123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
2024123474Swpaul	dest = buf;
2025123474Swpaul
2026123474Swpaul	bh = rman_get_bushandle(sc->ndis_res_am);
2027123474Swpaul	bt = rman_get_bustag(sc->ndis_res_am);
2028123474Swpaul
2029123474Swpaul	for (i = 0; i < len; i++)
2030123474Swpaul		dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2));
2031123474Swpaul
2032123474Swpaul	return(i);
2033123474Swpaul}
2034123474Swpaul
2035123474Swpaul__stdcall static uint32_t
2036123474Swpaulndis_write_pccard_amem(handle, offset, buf, len)
2037123474Swpaul	ndis_handle		handle;
2038123474Swpaul	uint32_t		offset;
2039123474Swpaul	void			*buf;
2040123474Swpaul	uint32_t		len;
2041123474Swpaul{
2042123474Swpaul	struct ndis_softc	*sc;
2043123474Swpaul	ndis_miniport_block	*block;
2044123474Swpaul	bus_space_handle_t	bh;
2045123474Swpaul	bus_space_tag_t		bt;
2046123474Swpaul	char			*src;
2047123474Swpaul	int			i;
2048123474Swpaul
2049123474Swpaul	if (handle == NULL)
2050123474Swpaul		return(0);
2051123474Swpaul
2052123474Swpaul	block = (ndis_miniport_block *)handle;
2053123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
2054123474Swpaul	src = buf;
2055123474Swpaul
2056123474Swpaul	bh = rman_get_bushandle(sc->ndis_res_am);
2057123474Swpaul	bt = rman_get_bustag(sc->ndis_res_am);
2058123474Swpaul
2059123474Swpaul	for (i = 0; i < len; i++)
2060123474Swpaul		bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]);
2061123474Swpaul
2062123474Swpaul	return(i);
2063123474Swpaul}
2064123474Swpaul
2065123474Swpaul__stdcall static ndis_list_entry *
2066123474Swpaulndis_insert_head(head, entry, lock)
2067123474Swpaul	ndis_list_entry		*head;
2068123474Swpaul	ndis_list_entry		*entry;
2069123474Swpaul	ndis_spin_lock		*lock;
2070123474Swpaul{
2071123474Swpaul	ndis_list_entry		*flink;
2072123474Swpaul
2073123474Swpaul	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
2074123474Swpaul	flink = head->nle_flink;
2075123474Swpaul	entry->nle_flink = flink;
2076123474Swpaul	entry->nle_blink = head;
2077123474Swpaul	flink->nle_blink = entry;
2078123474Swpaul	head->nle_flink = entry;
2079123474Swpaul	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
2080123474Swpaul
2081123474Swpaul	return(flink);
2082123474Swpaul}
2083123474Swpaul
2084123474Swpaul__stdcall static ndis_list_entry *
2085123474Swpaulndis_remove_head(head, lock)
2086123474Swpaul	ndis_list_entry		*head;
2087123474Swpaul	ndis_spin_lock		*lock;
2088123474Swpaul{
2089123474Swpaul	ndis_list_entry		*flink;
2090123474Swpaul	ndis_list_entry		*entry;
2091123474Swpaul
2092123474Swpaul	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
2093123474Swpaul	entry = head->nle_flink;
2094123474Swpaul	flink = entry->nle_flink;
2095123474Swpaul	head->nle_flink = flink;
2096123474Swpaul	flink->nle_blink = head;
2097123474Swpaul	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
2098123474Swpaul
2099123474Swpaul	return(entry);
2100123474Swpaul}
2101123474Swpaul
2102123474Swpaul__stdcall static ndis_list_entry *
2103123474Swpaulndis_insert_tail(head, entry, lock)
2104123474Swpaul	ndis_list_entry		*head;
2105123474Swpaul	ndis_list_entry		*entry;
2106123474Swpaul	ndis_spin_lock		*lock;
2107123474Swpaul{
2108123474Swpaul	ndis_list_entry		*blink;
2109123474Swpaul
2110123474Swpaul	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
2111123474Swpaul	blink = head->nle_blink;
2112123474Swpaul	entry->nle_flink = head;
2113123474Swpaul	entry->nle_blink = blink;
2114123474Swpaul	blink->nle_flink = entry;
2115123474Swpaul	head->nle_blink = entry;
2116123474Swpaul	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
2117123474Swpaul
2118123474Swpaul	return(blink);
2119123474Swpaul}
2120123474Swpaul
2121123474Swpaul__stdcall static uint8_t
2122123474Swpaulndis_sync_with_intr(intr, syncfunc, syncctx)
2123123474Swpaul	ndis_miniport_interrupt	*intr;
2124123474Swpaul	void			*syncfunc;
2125123474Swpaul	void			*syncctx;
2126123474Swpaul{
2127123474Swpaul	__stdcall uint8_t (*sync)(void *);
2128123474Swpaul
2129123474Swpaul	if (syncfunc == NULL || syncctx == NULL)
2130123474Swpaul		return(0);
2131123474Swpaul
2132123474Swpaul	sync = syncfunc;
2133123474Swpaul	return(sync(syncctx));
2134123474Swpaul}
2135123474Swpaul
2136123504Swpaul/*
2137123504Swpaul * Return the number of 100 nanosecond intervals since
2138123504Swpaul * January 1, 1601. (?!?!)
2139123504Swpaul */
2140123474Swpaul__stdcall static void
2141123504Swpaulndis_time(tval)
2142123504Swpaul	uint64_t		*tval;
2143123504Swpaul{
2144123504Swpaul	struct timespec		ts;
2145123822Swpaul
2146123504Swpaul	nanotime(&ts);
2147123822Swpaul	*tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2148123822Swpaul	    11644473600;
2149123504Swpaul}
2150123504Swpaul
2151123822Swpaul/*
2152123822Swpaul * Return the number of milliseconds since the system booted.
2153123822Swpaul */
2154123504Swpaul__stdcall static void
2155123822Swpaulndis_uptime(tval)
2156123822Swpaul	uint32_t		*tval;
2157123822Swpaul{
2158123822Swpaul	struct timespec		ts;
2159123822Swpaul
2160123822Swpaul	nanouptime(&ts);
2161123822Swpaul	*tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
2162123822Swpaul}
2163123822Swpaul
2164123822Swpaul__stdcall static void
2165123507Swpaulndis_init_string(dst, src)
2166124100Swpaul	ndis_unicode_string	*dst;
2167123507Swpaul	char			*src;
2168123507Swpaul{
2169123507Swpaul	ndis_unicode_string	*u;
2170123507Swpaul
2171124100Swpaul	u = dst;
2172124116Swpaul	u->nus_buf = NULL;
2173124100Swpaul	if (ndis_ascii_to_unicode(src, &u->nus_buf))
2174123507Swpaul		return;
2175123507Swpaul	u->nus_len = u->nus_maxlen = strlen(src) * 2;
2176123507Swpaul	return;
2177123507Swpaul}
2178123507Swpaul
2179123507Swpaul__stdcall static void
2180123507Swpaulndis_free_string(str)
2181123507Swpaul	ndis_unicode_string	*str;
2182123507Swpaul{
2183123507Swpaul	if (str == NULL)
2184123507Swpaul		return;
2185123507Swpaul	if (str->nus_buf != NULL)
2186123507Swpaul		free(str->nus_buf, M_DEVBUF);
2187123507Swpaul	free(str, M_DEVBUF);
2188123507Swpaul	return;
2189123507Swpaul}
2190123507Swpaul
2191123507Swpaul__stdcall static ndis_status
2192123507Swpaulndis_remove_miniport(adapter)
2193123507Swpaul	ndis_handle		*adapter;
2194123507Swpaul{
2195123507Swpaul	return(NDIS_STATUS_SUCCESS);
2196123507Swpaul}
2197123507Swpaul
2198123507Swpaul__stdcall static void
2199123526Swpaulndis_init_ansi_string(dst, src)
2200123526Swpaul	ndis_ansi_string	*dst;
2201123526Swpaul	char			*src;
2202123526Swpaul{
2203123526Swpaul	ndis_ansi_string	*a;
2204123526Swpaul
2205123526Swpaul	a = dst;
2206123526Swpaul	if (a == NULL)
2207123526Swpaul		return;
2208123526Swpaul	if (src == NULL) {
2209123526Swpaul		a->nas_len = a->nas_maxlen = 0;
2210123526Swpaul		a->nas_buf = NULL;
2211123526Swpaul	} else {
2212123526Swpaul		a->nas_buf = src;
2213123526Swpaul		a->nas_len = a->nas_maxlen = strlen(src);
2214123526Swpaul	}
2215123526Swpaul
2216123526Swpaul	return;
2217123526Swpaul}
2218123526Swpaul
2219123941Swpaul__stdcall static void
2220123941Swpaulndis_init_unicode_string(dst, src)
2221123941Swpaul	ndis_unicode_string	*dst;
2222123941Swpaul	uint16_t		*src;
2223123941Swpaul{
2224123941Swpaul	ndis_unicode_string	*u;
2225123941Swpaul	int			i;
2226123941Swpaul
2227123941Swpaul	u = dst;
2228123941Swpaul	if (u == NULL)
2229123941Swpaul		return;
2230123941Swpaul	if (src == NULL) {
2231123941Swpaul		u->nus_len = u->nus_maxlen = 0;
2232123941Swpaul		u->nus_buf = NULL;
2233123941Swpaul	} else {
2234123941Swpaul		i = 0;
2235123941Swpaul		while(src[i] != 0)
2236123941Swpaul			i++;
2237123941Swpaul		u->nus_buf = src;
2238123941Swpaul		u->nus_len = u->nus_maxlen = i * 2;
2239123941Swpaul	}
2240123941Swpaul
2241123941Swpaul	return;
2242123941Swpaul}
2243123941Swpaul
2244123526Swpaul__stdcall static void ndis_get_devprop(adapter, phydevobj,
2245123526Swpaul	funcdevobj, nextdevobj, resources, transresources)
2246123526Swpaul	ndis_handle		adapter;
2247123526Swpaul	void			*phydevobj;
2248123526Swpaul	void			*funcdevobj;
2249123526Swpaul	void			*nextdevobj;
2250123526Swpaul	cm_resource_list	*resources;
2251123526Swpaul	cm_resource_list	*transresources;
2252123526Swpaul{
2253123526Swpaul	return;
2254123526Swpaul}
2255123526Swpaul
2256123526Swpaul__stdcall static void
2257123721Swpaulndis_firstbuf(packet, buf, firstva, firstlen, totlen)
2258123721Swpaul	ndis_packet		*packet;
2259123721Swpaul	ndis_buffer		**buf;
2260123721Swpaul	void			**firstva;
2261123721Swpaul	uint32_t		*firstlen;
2262123721Swpaul	uint32_t		*totlen;
2263123721Swpaul{
2264123721Swpaul	ndis_buffer		*tmp;
2265123721Swpaul
2266123721Swpaul	tmp = packet->np_private.npp_head;
2267123721Swpaul	*buf = tmp;
2268123721Swpaul	if (tmp == NULL) {
2269123721Swpaul		*firstva = NULL;
2270123721Swpaul		*firstlen = *totlen = 0;
2271123721Swpaul	} else {
2272123757Swpaul		*firstva = MDL_VA(tmp);
2273123721Swpaul		*firstlen = *totlen = tmp->nb_bytecount;
2274123721Swpaul		for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
2275123721Swpaul			*totlen += tmp->nb_bytecount;
2276123721Swpaul	}
2277123721Swpaul
2278123721Swpaul	return;
2279123721Swpaul}
2280123721Swpaul
2281123721Swpaul__stdcall static void
2282123721Swpaulndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio)
2283123721Swpaul	ndis_packet		*packet;
2284123721Swpaul	ndis_buffer		**buf;
2285123721Swpaul	void			**firstva;
2286123721Swpaul	uint32_t		*firstlen;
2287123721Swpaul	uint32_t		*totlen;
2288123721Swpaul	uint32_t		prio;
2289123721Swpaul{
2290123721Swpaul	ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
2291123721Swpaul}
2292123721Swpaul
2293123822Swpaul/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2294123721Swpaul__stdcall static void
2295123822Swpaulndis_open_file(status, filehandle, filelength, filename, highestaddr)
2296123822Swpaul	ndis_status		*status;
2297123822Swpaul	ndis_handle		*filehandle;
2298123822Swpaul	uint32_t		*filelength;
2299123822Swpaul	ndis_unicode_string	*filename;
2300123822Swpaul	ndis_physaddr		highestaddr;
2301123822Swpaul{
2302123822Swpaul	char			*afilename = NULL;
2303123822Swpaul
2304123822Swpaul	ndis_unicode_to_ascii(filename->nus_buf, filename->nus_len, &afilename);
2305123822Swpaul	printf("ndis_open_file(\"%s\", %ju)\n", afilename,
2306123822Swpaul	    highestaddr.np_quad);
2307123822Swpaul	free(afilename, M_DEVBUF);
2308123822Swpaul	*status = NDIS_STATUS_FILE_NOT_FOUND;
2309123822Swpaul	return;
2310123822Swpaul}
2311123822Swpaul
2312123822Swpaul__stdcall static void
2313123822Swpaulndis_map_file(status, mappedbuffer, filehandle)
2314123822Swpaul	ndis_status		*status;
2315123822Swpaul	void			**mappedbuffer;
2316123822Swpaul	ndis_handle		filehandle;
2317123822Swpaul{
2318123822Swpaul
2319123822Swpaul	*status = NDIS_STATUS_ALREADY_MAPPED;
2320123822Swpaul	return;
2321123822Swpaul}
2322123822Swpaul
2323123822Swpaul__stdcall static void
2324123822Swpaulndis_unmap_file(filehandle)
2325123822Swpaul	ndis_handle		filehandle;
2326123822Swpaul{
2327123822Swpaul	return;
2328123822Swpaul}
2329123822Swpaul
2330123822Swpaul__stdcall static void
2331123822Swpaulndis_close_file(filehandle)
2332123822Swpaul	ndis_handle		filehandle;
2333123822Swpaul{
2334123822Swpaul	return;
2335123822Swpaul}
2336123822Swpaul
2337123848Swpaul__stdcall static uint8_t
2338123848Swpaulndis_cpu_cnt()
2339123848Swpaul{
2340123848Swpaul#ifdef SMP
2341123848Swpaul	return(mp_ncpus);
2342123848Swpaul#else
2343123848Swpaul	return(1);
2344123848Swpaul#endif
2345123848Swpaul};
2346123848Swpaul
2347124116Swpaultypedef void (*ndis_statusdone_handler)(ndis_handle);
2348124116Swpaultypedef void (*ndis_status_handler)(ndis_handle, ndis_status,
2349124116Swpaul        void *, uint32_t);
2350124116Swpaul
2351123822Swpaul__stdcall static void
2352124116Swpaulndis_ind_statusdone(adapter)
2353124116Swpaul	ndis_handle		adapter;
2354124116Swpaul{
2355124116Swpaul	ndis_miniport_block	*block;
2356124116Swpaul	__stdcall ndis_statusdone_handler	statusdonefunc;
2357124116Swpaul
2358124116Swpaul	block = (ndis_miniport_block *)adapter;
2359124116Swpaul	statusdonefunc = block->nmb_statusdone_func;
2360124116Swpaul
2361124116Swpaul	statusdonefunc(adapter);
2362124116Swpaul	return;
2363124116Swpaul}
2364124116Swpaul
2365124116Swpaul__stdcall static void
2366124116Swpaulndis_ind_status(adapter, status, sbuf, slen)
2367124116Swpaul	ndis_handle		adapter;
2368124116Swpaul	ndis_status		status;
2369124116Swpaul	void			*sbuf;
2370124116Swpaul	uint32_t		slen;
2371124116Swpaul{
2372124116Swpaul	ndis_miniport_block	*block;
2373124116Swpaul	__stdcall ndis_status_handler	statusfunc;
2374124116Swpaul
2375124116Swpaul	block = (ndis_miniport_block *)adapter;
2376124116Swpaul	statusfunc = block->nmb_status_func;
2377124116Swpaul
2378124116Swpaul	statusfunc(adapter, status, sbuf, slen);
2379124116Swpaul	return;
2380124116Swpaul}
2381124116Swpaul
2382124122Swpaulstatic void
2383124122Swpaulndis_workfunc(ctx, pending)
2384124122Swpaul	void			*ctx;
2385124122Swpaul	int			pending;
2386124122Swpaul{
2387124122Swpaul	ndis_work_item		*work;
2388124122Swpaul	__stdcall ndis_proc	workfunc;
2389124122Swpaul
2390124122Swpaul	work = ctx;
2391124122Swpaul	workfunc = work->nwi_func;
2392124122Swpaul	workfunc(work, work->nwi_ctx);
2393124122Swpaul	return;
2394124122Swpaul}
2395124122Swpaul
2396124122Swpaul__stdcall static ndis_status
2397124122Swpaulndis_sched_workitem(work)
2398124122Swpaul	ndis_work_item		*work;
2399124122Swpaul{
2400124122Swpaul	struct task		*t;
2401124122Swpaul
2402124122Swpaul	t = (struct task *)&work->nwi_wraprsvd;
2403124122Swpaul	TASK_INIT(t, 0, ndis_workfunc, work);
2404124122Swpaul	taskqueue_enqueue(taskqueue_swi, t);
2405124122Swpaul	return(NDIS_STATUS_SUCCESS);
2406124122Swpaul}
2407124122Swpaul
2408124116Swpaul__stdcall static void
2409123474Swpauldummy()
2410123474Swpaul{
2411123474Swpaul	printf ("NDIS dummy called...\n");
2412123474Swpaul	return;
2413123474Swpaul}
2414123474Swpaul
2415123474Swpaulimage_patch_table ndis_functbl[] = {
2416124122Swpaul	{ "NdisScheduleWorkItem",	(FUNC)ndis_sched_workitem },
2417124116Swpaul	{ "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone },
2418124116Swpaul	{ "NdisMIndicateStatus",	(FUNC)ndis_ind_status },
2419123848Swpaul	{ "NdisSystemProcessorCount",	(FUNC)ndis_cpu_cnt },
2420123721Swpaul	{ "NdisUnchainBufferAtBack",	(FUNC)ndis_unchain_tailbuf, },
2421123721Swpaul	{ "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf },
2422123721Swpaul	{ "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe },
2423123573Swpaul	{ "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2424123526Swpaul	{ "NdisMGetDeviceProperty",	(FUNC)ndis_get_devprop },
2425123526Swpaul	{ "NdisInitAnsiString",		(FUNC)ndis_init_ansi_string },
2426123941Swpaul	{ "NdisInitUnicodeString",	(FUNC)ndis_init_unicode_string },
2427123526Swpaul	{ "NdisWriteConfiguration",	(FUNC)ndis_write_cfg },
2428123526Swpaul	{ "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2429123526Swpaul	{ "NdisTerminateWrapper",	(FUNC)ndis_termwrap },
2430123526Swpaul	{ "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2431123526Swpaul	{ "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2432123507Swpaul	{ "NdisMRemoveMiniport",	(FUNC)ndis_remove_miniport },
2433123507Swpaul	{ "NdisInitializeString",	(FUNC)ndis_init_string },
2434123507Swpaul	{ "NdisFreeString",		(FUNC)ndis_free_string },
2435123504Swpaul	{ "NdisGetCurrentSystemTime",	(FUNC)ndis_time },
2436123822Swpaul	{ "NdisGetSystemUpTime",	(FUNC)ndis_uptime },
2437123474Swpaul	{ "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2438123474Swpaul	{ "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2439123474Swpaul	{ "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2440123474Swpaul	{ "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2441123474Swpaul	{ "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2442123474Swpaul	{ "NdisInitializeWrapper",	(FUNC)ndis_initwrap },
2443123474Swpaul	{ "NdisMRegisterMiniport",	(FUNC)ndis_register_miniport },
2444123474Swpaul	{ "NdisAllocateMemoryWithTag",	(FUNC)ndis_malloc_withtag },
2445123474Swpaul	{ "NdisAllocateMemory",		(FUNC)ndis_malloc },
2446123474Swpaul	{ "NdisMSetAttributesEx",	(FUNC)ndis_setattr_ex },
2447123474Swpaul	{ "NdisCloseConfiguration",	(FUNC)ndis_close_cfg },
2448123474Swpaul	{ "NdisReadConfiguration",	(FUNC)ndis_read_cfg },
2449123474Swpaul	{ "NdisOpenConfiguration",	(FUNC)ndis_open_cfg },
2450123474Swpaul	{ "NdisReleaseSpinLock",	(FUNC)ndis_unlock },
2451123474Swpaul	{ "NdisDprAcquireSpinLock",	(FUNC)ndis_lock },
2452123474Swpaul	{ "NdisDprReleaseSpinLock",	(FUNC)ndis_unlock },
2453123474Swpaul	{ "NdisAcquireSpinLock",	(FUNC)ndis_lock },
2454123474Swpaul	{ "NdisAllocateSpinLock",	(FUNC)ndis_create_lock },
2455123474Swpaul	{ "NdisFreeSpinLock",		(FUNC)ndis_destroy_lock },
2456123474Swpaul	{ "NdisFreeMemory",		(FUNC)ndis_free },
2457123474Swpaul	{ "NdisReadPciSlotInformation",	(FUNC)ndis_read_pci },
2458123474Swpaul	{ "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2459124100Swpaul	{ "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci },
2460124100Swpaul	{ "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci },
2461123474Swpaul	{ "NdisWriteErrorLogEntry",	(FUNC)ndis_syslog },
2462123474Swpaul	{ "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2463123474Swpaul	{ "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2464123474Swpaul	{ "NdisMInitializeTimer",	(FUNC)ndis_create_timer },
2465123474Swpaul	{ "NdisSetTimer",		(FUNC)ndis_set_timer },
2466123474Swpaul	{ "NdisMCancelTimer",		(FUNC)ndis_cancel_timer },
2467123474Swpaul	{ "NdisMSetPeriodicTimer",	(FUNC)ndis_set_periodic_timer },
2468123474Swpaul	{ "NdisMQueryAdapterResources",	(FUNC)ndis_query_resources },
2469123474Swpaul	{ "NdisMRegisterIoPortRange",	(FUNC)ndis_register_ioport },
2470123474Swpaul	{ "NdisMDeregisterIoPortRange",	(FUNC)ndis_deregister_ioport },
2471123474Swpaul	{ "NdisReadNetworkAddress",	(FUNC)ndis_read_netaddr },
2472123848Swpaul	{ "NdisQueryMapRegisterCount",	(FUNC)ndis_mapreg_cnt },
2473123474Swpaul	{ "NdisMAllocateMapRegisters",	(FUNC)ndis_alloc_mapreg },
2474123848Swpaul	{ "NdisMFreeMapRegisters",	(FUNC)ndis_free_mapreg },
2475123474Swpaul	{ "NdisMAllocateSharedMemory",	(FUNC)ndis_alloc_sharedmem },
2476123474Swpaul	{ "NdisMMapIoSpace",		(FUNC)ndis_map_iospace },
2477123474Swpaul	{ "NdisMUnmapIoSpace",		(FUNC)ndis_unmap_iospace },
2478123474Swpaul	{ "NdisGetCacheFillSize",	(FUNC)ndis_cachefill },
2479123474Swpaul	{ "NdisMGetDmaAlignment",	(FUNC)ndis_dma_align },
2480123474Swpaul	{ "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2481123474Swpaul	{ "NdisAllocatePacketPool",	(FUNC)ndis_alloc_packetpool },
2482123474Swpaul	{ "NdisAllocatePacketPoolEx",	(FUNC)ndis_ex_alloc_packetpool },
2483123474Swpaul	{ "NdisAllocatePacket",		(FUNC)ndis_alloc_packet },
2484123474Swpaul	{ "NdisFreePacket",		(FUNC)ndis_release_packet },
2485123474Swpaul	{ "NdisFreePacketPool",		(FUNC)ndis_free_packetpool },
2486124097Swpaul	{ "NdisDprAllocatePacket",	(FUNC)ndis_alloc_packet },
2487124097Swpaul	{ "NdisDprFreePacket",		(FUNC)ndis_release_packet },
2488123474Swpaul	{ "NdisAllocateBufferPool",	(FUNC)ndis_alloc_bufpool },
2489123474Swpaul	{ "NdisAllocateBuffer",		(FUNC)ndis_alloc_buf },
2490123474Swpaul	{ "NdisQueryBuffer",		(FUNC)ndis_query_buf },
2491123474Swpaul	{ "NdisQueryBufferSafe",	(FUNC)ndis_query_buf_safe },
2492124100Swpaul	{ "NdisBufferLength",		(FUNC)ndis_buflen },
2493123474Swpaul	{ "NdisFreeBuffer",		(FUNC)ndis_release_buf },
2494123474Swpaul	{ "NdisFreeBufferPool",		(FUNC)ndis_free_bufpool },
2495123474Swpaul	{ "NdisInterlockedIncrement",	(FUNC)ndis_interlock_inc },
2496123474Swpaul	{ "NdisInterlockedDecrement",	(FUNC)ndis_interlock_dec },
2497123474Swpaul	{ "NdisInitializeEvent",	(FUNC)ndis_init_event },
2498123474Swpaul	{ "NdisSetEvent",		(FUNC)ndis_set_event },
2499123474Swpaul	{ "NdisResetEvent",		(FUNC)ndis_reset_event },
2500123474Swpaul	{ "NdisWaitEvent",		(FUNC)ndis_wait_event },
2501123474Swpaul	{ "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2502123474Swpaul	{ "NdisMPciAssignResources",	(FUNC)ndis_assign_pcirsrc },
2503123474Swpaul	{ "NdisMFreeSharedMemory",	(FUNC)ndis_free_sharedmem },
2504123474Swpaul	{ "NdisMRegisterInterrupt",	(FUNC)ndis_register_intr },
2505123474Swpaul	{ "NdisMDeregisterInterrupt",	(FUNC)ndis_deregister_intr },
2506123474Swpaul	{ "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2507123474Swpaul	{ "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
2508123474Swpaul	{ "NDIS_BUFFER_TO_SPAN_PAGES",	(FUNC)ndis_numpages },
2509123474Swpaul	{ "NdisQueryBufferOffset",	(FUNC)ndis_query_bufoffset },
2510123474Swpaul	{ "NdisAdjustBufferLength",	(FUNC)ndis_adjust_buflen },
2511123474Swpaul	{ "NdisPacketPoolUsage",	(FUNC)ndis_packetpool_use },
2512123474Swpaul	{ "NdisMSleep",			(FUNC)ndis_sleep },
2513123474Swpaul	{ "NdisUnchainBufferAtFront",	(FUNC)ndis_unchain_headbuf },
2514123474Swpaul	{ "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
2515123474Swpaul	{ "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
2516123822Swpaul	{ "NdisOpenFile",		(FUNC)ndis_open_file },
2517123822Swpaul	{ "NdisMapFile",		(FUNC)ndis_map_file },
2518123822Swpaul	{ "NdisUnmapFile",		(FUNC)ndis_unmap_file },
2519123822Swpaul	{ "NdisCloseFile",		(FUNC)ndis_close_file },
2520123474Swpaul
2521123474Swpaul	/*
2522123474Swpaul	 * This last entry is a catch-all for any function we haven't
2523123474Swpaul	 * implemented yet. The PE import list patching routine will
2524123474Swpaul	 * use it for any function that doesn't have an explicit match
2525123474Swpaul	 * in this table.
2526123474Swpaul	 */
2527123474Swpaul
2528123474Swpaul	{ NULL, (FUNC)dummy },
2529123474Swpaul
2530123474Swpaul	/* End of list. */
2531123474Swpaul
2532123474Swpaul	{ NULL, NULL },
2533123474Swpaul};
2534