subr_ndis.c revision 124097
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 124097 2004-01-03 09:20:48Z 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>
66123474Swpaul
67123474Swpaul#include <net/if.h>
68123474Swpaul#include <net/if_arp.h>
69123474Swpaul#include <net/ethernet.h>
70123474Swpaul#include <net/if_dl.h>
71123474Swpaul#include <net/if_media.h>
72123474Swpaul
73123474Swpaul#include <machine/bus_memio.h>
74123474Swpaul#include <machine/bus_pio.h>
75123474Swpaul#include <machine/bus.h>
76123474Swpaul#include <machine/resource.h>
77123474Swpaul
78123474Swpaul#include <sys/bus.h>
79123474Swpaul#include <sys/rman.h>
80123474Swpaul
81123474Swpaul#include <machine/stdarg.h>
82123474Swpaul
83123695Swpaul#include <net80211/ieee80211_var.h>
84123695Swpaul#include <net80211/ieee80211_ioctl.h>
85123695Swpaul
86123474Swpaul#include <dev/pci/pcireg.h>
87123474Swpaul#include <dev/pci/pcivar.h>
88123474Swpaul
89123474Swpaul#include <compat/ndis/pe_var.h>
90123474Swpaul#include <compat/ndis/resource_var.h>
91123512Swpaul#include <compat/ndis/ntoskrnl_var.h>
92123474Swpaul#include <compat/ndis/ndis_var.h>
93123474Swpaul#include <compat/ndis/cfg_var.h>
94123474Swpaul#include <dev/if_ndis/if_ndisvar.h>
95123474Swpaul
96123474Swpaul#define __stdcall __attribute__((__stdcall__))
97123474Swpaul#define FUNC void(*)(void)
98123474Swpaul
99123474Swpaulstatic struct mtx ndis_interlock;
100123474Swpaulstatic int ndis_inits = 0;
101123474Swpaul
102123474Swpaul__stdcall static void ndis_initwrap(ndis_handle,
103123474Swpaul	ndis_driver_object *, void *, void *);
104123474Swpaul__stdcall static ndis_status ndis_register_miniport(ndis_handle,
105123474Swpaul	ndis_miniport_characteristics *, int);
106123474Swpaul__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
107123474Swpaul__stdcall static ndis_status ndis_malloc(void **,
108123474Swpaul	uint32_t, uint32_t, ndis_physaddr);
109123474Swpaul__stdcall static void ndis_free(void *, uint32_t, uint32_t);
110123474Swpaul__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
111123474Swpaul	uint32_t, uint32_t, ndis_interface_type);
112123474Swpaul__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
113123526Swpaul__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle,
114123526Swpaul	uint32_t, ndis_unicode_string *, ndis_handle *);
115123526Swpaul__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle,
116123526Swpaul	ndis_unicode_string *, ndis_handle *);
117123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *,
118123474Swpaul	struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
119123526Swpaulstatic ndis_status ndis_decode_parm(ndis_miniport_block *,
120123526Swpaul	ndis_config_parm *, char *);
121123474Swpaul__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
122123474Swpaul	ndis_handle, ndis_unicode_string *, ndis_parm_type);
123123526Swpaul__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle,
124123526Swpaul	ndis_unicode_string *, ndis_config_parm *);
125123474Swpaul__stdcall static void ndis_close_cfg(ndis_handle);
126123474Swpaul__stdcall static void ndis_create_lock(ndis_spin_lock *);
127123474Swpaul__stdcall static void ndis_destroy_lock(ndis_spin_lock *);
128123474Swpaul__stdcall static void ndis_lock(ndis_spin_lock *);
129123474Swpaul__stdcall static void ndis_unlock(ndis_spin_lock *);
130123474Swpaul__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
131123474Swpaul	uint32_t, void *, uint32_t);
132123474Swpaul__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
133123474Swpaul	uint32_t, void *, uint32_t);
134123474Swpaulstatic void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
135123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
136123474Swpaul__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
137123474Swpaul	uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
138123474Swpaul__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
139123474Swpaul__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *,
140123474Swpaul	ndis_timer_function, void *);
141123474Swpaulstatic void ndis_timercall(void *);
142123474Swpaul__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t);
143123474Swpaulstatic void ndis_tick(void *);
144123474Swpaul__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
145123474Swpaul__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *);
146123474Swpaul__stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
147123474Swpaul	ndis_resource_list *, uint32_t *);
148123474Swpaul__stdcall static ndis_status ndis_register_ioport(void **,
149123474Swpaul	ndis_handle, uint32_t, uint32_t);
150123474Swpaul__stdcall static void ndis_deregister_ioport(ndis_handle,
151123474Swpaul	uint32_t, uint32_t, void *);
152123474Swpaul__stdcall static void ndis_read_netaddr(ndis_status *, void **,
153123474Swpaul	uint32_t *, ndis_handle);
154123848Swpaul__stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *);
155123474Swpaul__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
156123474Swpaul	uint32_t, uint8_t, uint32_t, uint32_t);
157123474Swpaul__stdcall static void ndis_free_mapreg(ndis_handle);
158123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
159123474Swpaul__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
160123474Swpaul	uint8_t, void **, ndis_physaddr *);
161123474Swpaul__stdcall static void ndis_alloc_sharedmem_async(ndis_handle,
162123474Swpaul	uint32_t, uint8_t, void *);
163123474Swpaul__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
164123474Swpaul	uint8_t, void *, ndis_physaddr);
165123474Swpaul__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
166123474Swpaul	ndis_physaddr, uint32_t);
167123474Swpaul__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
168123474Swpaul__stdcall static uint32_t ndis_cachefill(void);
169123474Swpaul__stdcall static uint32_t ndis_dma_align(ndis_handle);
170123474Swpaul__stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
171123474Swpaul	uint8_t, uint32_t);
172123474Swpaul__stdcall static void ndis_alloc_packetpool(ndis_status *,
173123474Swpaul	ndis_handle *, uint32_t, uint32_t);
174123474Swpaul__stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
175123474Swpaul	ndis_handle *, uint32_t, uint32_t, uint32_t);
176123474Swpaul__stdcall static uint32_t ndis_packetpool_use(ndis_handle);
177123474Swpaul__stdcall static void ndis_free_packetpool(ndis_handle);
178123474Swpaul__stdcall static void ndis_alloc_packet(ndis_status *,
179123474Swpaul	ndis_packet **, ndis_handle);
180123474Swpaul__stdcall static void ndis_release_packet(ndis_packet *);
181123474Swpaul__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
182123721Swpaul__stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **);
183123474Swpaul__stdcall static void ndis_alloc_bufpool(ndis_status *,
184123474Swpaul	ndis_handle *, uint32_t);
185123474Swpaul__stdcall static void ndis_free_bufpool(ndis_handle);
186123474Swpaul__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
187123474Swpaul	ndis_handle, void *, uint32_t);
188123474Swpaul__stdcall static void ndis_release_buf(ndis_buffer *);
189123474Swpaul__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
190123474Swpaul__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
191123474Swpaul	uint32_t *, uint32_t);
192123474Swpaul__stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
193123474Swpaul__stdcall static uint32_t ndis_interlock_inc(uint32_t *);
194123474Swpaul__stdcall static uint32_t ndis_interlock_dec(uint32_t *);
195123474Swpaul__stdcall static void ndis_init_event(ndis_event *);
196123474Swpaul__stdcall static void ndis_set_event(ndis_event *);
197123474Swpaul__stdcall static void ndis_reset_event(ndis_event *);
198123474Swpaul__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
199123474Swpaul__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
200123474Swpaul	ndis_unicode_string *);
201123526Swpaul__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
202123526Swpaul	ndis_ansi_string *);
203123474Swpaul__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
204123474Swpaul	uint32_t, ndis_resource_list **);
205123474Swpaul__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
206123474Swpaul	ndis_handle, uint32_t, uint32_t, uint8_t,
207123474Swpaul	uint8_t, ndis_interrupt_mode);
208123474Swpaul__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
209123474Swpaul__stdcall static void ndis_register_shutdown(ndis_handle, void *,
210123474Swpaul	ndis_shutdown_handler);
211123474Swpaul__stdcall static void ndis_deregister_shutdown(ndis_handle);
212123474Swpaul__stdcall static uint32_t ndis_numpages(ndis_buffer *);
213123573Swpaul__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
214123474Swpaul__stdcall static void ndis_query_bufoffset(ndis_buffer *,
215123474Swpaul	uint32_t *, uint32_t *);
216123474Swpaul__stdcall static void ndis_sleep(uint32_t);
217123474Swpaul__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
218123474Swpaul	uint32_t, void *, uint32_t);
219123474Swpaul__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
220123474Swpaul	uint32_t, void *, uint32_t);
221123474Swpaul__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *,
222123474Swpaul	ndis_list_entry *, ndis_spin_lock *);
223123474Swpaul__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *,
224123474Swpaul	ndis_spin_lock *);
225123474Swpaul__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *,
226123474Swpaul	ndis_list_entry *, ndis_spin_lock *);
227123474Swpaul__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
228123474Swpaul	void *, void *);
229123504Swpaul__stdcall static void ndis_time(uint64_t *);
230123822Swpaul__stdcall static void ndis_uptime(uint32_t *);
231123507Swpaul__stdcall static void ndis_init_string(ndis_unicode_string **, char *);
232123526Swpaul__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
233123941Swpaul__stdcall static void ndis_init_unicode_string(ndis_unicode_string *,
234123941Swpaul	uint16_t *);
235123507Swpaul__stdcall static void ndis_free_string(ndis_unicode_string *);
236123507Swpaul__stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
237123526Swpaul__stdcall static void ndis_termwrap(ndis_handle, void *);
238123526Swpaul__stdcall static void ndis_get_devprop(ndis_handle, void *, void *,
239123526Swpaul	void *, cm_resource_list *, cm_resource_list *);
240123721Swpaul__stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
241123721Swpaul	void **, uint32_t *, uint32_t *);
242123721Swpaul__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
243123721Swpaul	void **, uint32_t *, uint32_t *, uint32_t);
244123822Swpaul__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
245123822Swpaul	ndis_unicode_string *, ndis_physaddr);
246123822Swpaul__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
247123822Swpaul__stdcall static void ndis_unmap_file(ndis_handle);
248123822Swpaul__stdcall static void ndis_close_file(ndis_handle);
249123848Swpaul__stdcall static u_int8_t ndis_cpu_cnt(void);
250123474Swpaul__stdcall static void dummy(void);
251123474Swpaul
252123474Swpaul
253123474Swpaulint
254123474Swpaulndis_libinit()
255123474Swpaul{
256123474Swpaul	if (ndis_inits) {
257123474Swpaul		ndis_inits++;
258123474Swpaul		return(0);
259123474Swpaul	}
260123474Swpaul
261123474Swpaul	mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK,
262123474Swpaul	    MTX_DEF | MTX_RECURSE | MTX_DUPOK);
263123474Swpaul
264123474Swpaul	ndis_inits++;
265123474Swpaul	return(0);
266123474Swpaul}
267123474Swpaul
268123474Swpaulint
269123474Swpaulndis_libfini()
270123474Swpaul{
271123474Swpaul	if (ndis_inits != 1) {
272123474Swpaul		ndis_inits--;
273123474Swpaul		return(0);
274123474Swpaul	}
275123474Swpaul
276123474Swpaul	mtx_destroy(&ndis_interlock);
277123474Swpaul	ndis_inits--;
278123474Swpaul
279123474Swpaul	return(0);
280123474Swpaul}
281123474Swpaul
282123474Swpaul/*
283123474Swpaul * NDIS deals with strings in unicode format, so we have
284123474Swpaul * do deal with them that way too. For now, we only handle
285123474Swpaul * conversion between unicode and ASCII since that's all
286123474Swpaul * that device drivers care about.
287123474Swpaul */
288123474Swpaul
289123474Swpaulint
290123474Swpaulndis_ascii_to_unicode(ascii, unicode)
291123474Swpaul	char			*ascii;
292123474Swpaul	uint16_t		**unicode;
293123474Swpaul{
294123474Swpaul	uint16_t		*ustr;
295123474Swpaul	int			i;
296123474Swpaul
297123474Swpaul	if (*unicode == NULL)
298123474Swpaul		*unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
299123474Swpaul
300123474Swpaul	if (*unicode == NULL)
301123474Swpaul		return(ENOMEM);
302123474Swpaul	ustr = *unicode;
303123474Swpaul	for (i = 0; i < strlen(ascii); i++) {
304123474Swpaul		*ustr = (uint16_t)ascii[i];
305123474Swpaul		ustr++;
306123474Swpaul	}
307123474Swpaul
308123474Swpaul	return(0);
309123474Swpaul}
310123474Swpaul
311123474Swpaulint
312123474Swpaulndis_unicode_to_ascii(unicode, ulen, ascii)
313123474Swpaul	uint16_t		*unicode;
314123474Swpaul	int			ulen;
315123474Swpaul	char			**ascii;
316123474Swpaul{
317123474Swpaul	uint8_t			*astr;
318123474Swpaul	int			i;
319123474Swpaul
320123474Swpaul	if (*ascii == NULL)
321123474Swpaul		*ascii = malloc(ulen, M_DEVBUF, M_WAITOK);
322123474Swpaul
323123474Swpaul	if (*ascii == NULL)
324123474Swpaul		return(ENOMEM);
325123474Swpaul	astr = *ascii;
326123474Swpaul	for (i = 0; i < ulen; i++) {
327123474Swpaul		*astr = (uint8_t)unicode[i];
328123474Swpaul		astr++;
329123474Swpaul	}
330123474Swpaul
331123474Swpaul	return(0);
332123474Swpaul}
333123474Swpaul
334123474Swpaul__stdcall static void
335123474Swpaulndis_initwrap(wrapper, drv_obj, path, unused)
336123474Swpaul	ndis_handle		wrapper;
337123474Swpaul	ndis_driver_object	*drv_obj;
338123474Swpaul	void			*path;
339123474Swpaul	void			*unused;
340123474Swpaul{
341123474Swpaul	ndis_driver_object	**drv;
342123474Swpaul
343123474Swpaul	drv = wrapper;
344123474Swpaul	*drv = drv_obj;
345123474Swpaul
346123474Swpaul	return;
347123474Swpaul}
348123474Swpaul
349123526Swpaul__stdcall static void
350123526Swpaulndis_termwrap(handle, syspec)
351123526Swpaul	ndis_handle		handle;
352123526Swpaul	void			*syspec;
353123526Swpaul{
354123526Swpaul	return;
355123526Swpaul}
356123526Swpaul
357123474Swpaul__stdcall static ndis_status
358123474Swpaulndis_register_miniport(handle, characteristics, len)
359123474Swpaul	ndis_handle		handle;
360123474Swpaul	ndis_miniport_characteristics *characteristics;
361123474Swpaul	int			len;
362123474Swpaul{
363123474Swpaul	ndis_driver_object	*drv;
364123474Swpaul
365123474Swpaul	drv = handle;
366123474Swpaul	bcopy((char *)characteristics, (char *)&drv->ndo_chars,
367123474Swpaul	    sizeof(ndis_miniport_characteristics));
368123474Swpaul	return(NDIS_STATUS_SUCCESS);
369123474Swpaul}
370123474Swpaul
371123474Swpaul__stdcall static ndis_status
372123474Swpaulndis_malloc_withtag(vaddr, len, tag)
373123474Swpaul	void			**vaddr;
374123474Swpaul	uint32_t		len;
375123474Swpaul	uint32_t		tag;
376123474Swpaul{
377123474Swpaul	void			*mem;
378123474Swpaul
379123474Swpaul	mem = malloc(len, M_DEVBUF, M_NOWAIT);
380123474Swpaul	if (mem == NULL)
381123474Swpaul		return(NDIS_STATUS_RESOURCES);
382123474Swpaul	*vaddr = mem;
383123474Swpaul
384123474Swpaul	return(NDIS_STATUS_SUCCESS);
385123474Swpaul}
386123474Swpaul
387123474Swpaul__stdcall static ndis_status
388123474Swpaulndis_malloc(vaddr, len, flags, highaddr)
389123474Swpaul	void			**vaddr;
390123474Swpaul	uint32_t		len;
391123474Swpaul	uint32_t		flags;
392123474Swpaul	ndis_physaddr		highaddr;
393123474Swpaul{
394123474Swpaul	void			*mem;
395123474Swpaul
396123474Swpaul	mem = malloc(len, M_DEVBUF, M_NOWAIT);
397123474Swpaul	if (mem == NULL)
398123474Swpaul		return(NDIS_STATUS_RESOURCES);
399123474Swpaul	*vaddr = mem;
400123474Swpaul
401123474Swpaul	return(NDIS_STATUS_SUCCESS);
402123474Swpaul}
403123474Swpaul
404123474Swpaul__stdcall static void
405123474Swpaulndis_free(vaddr, len, flags)
406123474Swpaul	void			*vaddr;
407123474Swpaul	uint32_t		len;
408123474Swpaul	uint32_t		flags;
409123474Swpaul{
410123474Swpaul	if (len == 0)
411123474Swpaul		return;
412123474Swpaul	free(vaddr, M_DEVBUF);
413123474Swpaul	return;
414123474Swpaul}
415123474Swpaul
416123474Swpaul__stdcall static ndis_status
417123474Swpaulndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
418123474Swpaul			flags, iftype)
419123474Swpaul	ndis_handle			adapter_handle;
420123474Swpaul	ndis_handle			adapter_ctx;
421123474Swpaul	uint32_t			hangsecs;
422123474Swpaul	uint32_t			flags;
423123474Swpaul	ndis_interface_type		iftype;
424123474Swpaul{
425123474Swpaul	ndis_miniport_block		*block;
426123474Swpaul
427123474Swpaul	/*
428123474Swpaul	 * Save the adapter context, we need it for calling
429123474Swpaul	 * the driver's internal functions.
430123474Swpaul	 */
431123474Swpaul	block = (ndis_miniport_block *)adapter_handle;
432123474Swpaul	block->nmb_miniportadapterctx = adapter_ctx;
433123474Swpaul	block->nmb_checkforhangsecs = hangsecs;
434123474Swpaul
435123474Swpaul	return(NDIS_STATUS_SUCCESS);
436123474Swpaul}
437123474Swpaul
438123474Swpaul__stdcall static void
439123474Swpaulndis_open_cfg(status, cfg, wrapctx)
440123474Swpaul	ndis_status		*status;
441123474Swpaul	ndis_handle		*cfg;
442123474Swpaul	ndis_handle		wrapctx;
443123474Swpaul{
444123474Swpaul	*cfg = wrapctx;
445123474Swpaul	*status = NDIS_STATUS_SUCCESS;
446123474Swpaul	return;
447123474Swpaul}
448123474Swpaul
449123526Swpaul__stdcall static void
450123526Swpaulndis_open_cfgbyname(status, cfg, subkey, subhandle)
451123526Swpaul	ndis_status		*status;
452123526Swpaul	ndis_handle		cfg;
453123526Swpaul	ndis_unicode_string	*subkey;
454123526Swpaul	ndis_handle		*subhandle;
455123526Swpaul{
456123526Swpaul	*subhandle = cfg;
457123526Swpaul	*status = NDIS_STATUS_SUCCESS;
458123526Swpaul	return;
459123526Swpaul}
460123526Swpaul
461123526Swpaul__stdcall static void
462123526Swpaulndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle)
463123526Swpaul	ndis_status		*status;
464123526Swpaul	ndis_handle		cfg;
465123526Swpaul	uint32_t		idx;
466123526Swpaul	ndis_unicode_string	*subkey;
467123526Swpaul	ndis_handle		*subhandle;
468123526Swpaul{
469123526Swpaul	*status = NDIS_STATUS_FAILURE;
470123526Swpaul	return;
471123526Swpaul}
472123526Swpaul
473123474Swpaulstatic ndis_status
474123474Swpaulndis_encode_parm(block, oid, type, parm)
475123474Swpaul	ndis_miniport_block	*block;
476123474Swpaul        struct sysctl_oid	*oid;
477123474Swpaul	ndis_parm_type		type;
478123474Swpaul	ndis_config_parm	**parm;
479123474Swpaul{
480123474Swpaul	uint16_t		*unicode;
481123474Swpaul	ndis_unicode_string	*ustr;
482123474Swpaul
483123474Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
484123474Swpaul
485123474Swpaul	switch(type) {
486123474Swpaul	case ndis_parm_string:
487123474Swpaul		ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
488123474Swpaul		(*parm)->ncp_type = ndis_parm_string;
489123474Swpaul		ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
490123474Swpaul		ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
491123474Swpaul		ustr->nus_buf = unicode;
492123474Swpaul		break;
493123474Swpaul	case ndis_parm_int:
494123474Swpaul		(*parm)->ncp_type = ndis_parm_int;
495123474Swpaul		(*parm)->ncp_parmdata.ncp_intdata =
496123474Swpaul		    strtol((char *)oid->oid_arg1, NULL, 10);
497123474Swpaul		break;
498123474Swpaul	case ndis_parm_hexint:
499123474Swpaul		(*parm)->ncp_type = ndis_parm_hexint;
500123474Swpaul		(*parm)->ncp_parmdata.ncp_intdata =
501123474Swpaul		    strtoul((char *)oid->oid_arg1, NULL, 16);
502123474Swpaul		break;
503123474Swpaul	default:
504123474Swpaul		return(NDIS_STATUS_FAILURE);
505123474Swpaul		break;
506123474Swpaul	}
507123474Swpaul
508123474Swpaul	return(NDIS_STATUS_SUCCESS);
509123474Swpaul}
510123474Swpaul
511123474Swpaul__stdcall static void
512123474Swpaulndis_read_cfg(status, parm, cfg, key, type)
513123474Swpaul	ndis_status		*status;
514123474Swpaul	ndis_config_parm	**parm;
515123474Swpaul	ndis_handle		cfg;
516123474Swpaul	ndis_unicode_string	*key;
517123474Swpaul	ndis_parm_type		type;
518123474Swpaul{
519123474Swpaul	char			*keystr = NULL;
520123474Swpaul	uint16_t		*unicode;
521123474Swpaul	ndis_miniport_block	*block;
522123474Swpaul	struct ndis_softc	*sc;
523123474Swpaul        struct sysctl_oid	*oidp;
524123474Swpaul	struct sysctl_ctx_entry	*e;
525123474Swpaul
526123474Swpaul	block = (ndis_miniport_block *)cfg;
527123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
528123474Swpaul
529123474Swpaul	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
530123474Swpaul
531123474Swpaul	*parm = &block->nmb_replyparm;
532123474Swpaul	bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
533123474Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
534123474Swpaul
535123474Swpaul	/*
536123474Swpaul	 * See if registry key is already in a list of known keys
537123474Swpaul	 * included with the driver.
538123474Swpaul	 */
539123474Swpaul	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
540123474Swpaul		oidp = e->entry;
541123474Swpaul		if (strcmp(oidp->oid_name, keystr) == 0) {
542123488Swpaul			if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
543123488Swpaul				free(keystr, M_DEVBUF);
544123488Swpaul				*status = NDIS_STATUS_FAILURE;
545123488Swpaul				return;
546123488Swpaul			}
547123474Swpaul			*status = ndis_encode_parm(block, oidp, type, parm);
548123474Swpaul			free(keystr, M_DEVBUF);
549123474Swpaul			return;
550123474Swpaul		}
551123474Swpaul	}
552123474Swpaul
553123474Swpaul	/*
554123474Swpaul	 * If the key didn't match, add it to the list of dynamically
555123474Swpaul	 * created ones. Sometimes, drivers refer to registry keys
556123474Swpaul	 * that aren't documented in their .INF files. These keys
557123474Swpaul	 * are supposed to be created by some sort of utility or
558123474Swpaul	 * control panel snap-in that comes with the driver software.
559123474Swpaul	 * Sometimes it's useful to be able to manipulate these.
560123474Swpaul	 * If the driver requests the key in the form of a string,
561123474Swpaul	 * make its default value an empty string, otherwise default
562123474Swpaul	 * it to "0".
563123474Swpaul	 */
564123474Swpaul
565123474Swpaul	if (type == ndis_parm_int || type == ndis_parm_hexint)
566123488Swpaul		ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
567123488Swpaul		    "UNSET", CTLFLAG_RW);
568123474Swpaul	else
569123488Swpaul		ndis_add_sysctl(sc, keystr, "(dynamic string key)",
570123488Swpaul		    "UNSET", CTLFLAG_RW);
571123474Swpaul
572123474Swpaul	free(keystr, M_DEVBUF);
573123474Swpaul	*status = NDIS_STATUS_FAILURE;
574123474Swpaul	return;
575123474Swpaul}
576123474Swpaul
577123526Swpaulstatic ndis_status
578123526Swpaulndis_decode_parm(block, parm, val)
579123526Swpaul	ndis_miniport_block	*block;
580123526Swpaul	ndis_config_parm	*parm;
581123526Swpaul	char			*val;
582123526Swpaul{
583123526Swpaul	uint16_t		*unicode;
584123526Swpaul	ndis_unicode_string	*ustr;
585123526Swpaul
586123526Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
587123526Swpaul
588123526Swpaul	switch(parm->ncp_type) {
589123526Swpaul	case ndis_parm_string:
590123526Swpaul		ustr = &parm->ncp_parmdata.ncp_stringdata;
591123526Swpaul		ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &val);
592123526Swpaul		break;
593123526Swpaul	case ndis_parm_int:
594123526Swpaul		sprintf(val, "%ul", parm->ncp_parmdata.ncp_intdata);
595123526Swpaul		break;
596123526Swpaul	case ndis_parm_hexint:
597123526Swpaul		sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
598123526Swpaul		break;
599123526Swpaul	default:
600123526Swpaul		return(NDIS_STATUS_FAILURE);
601123526Swpaul		break;
602123526Swpaul	}
603123526Swpaul	return(NDIS_STATUS_SUCCESS);
604123526Swpaul}
605123526Swpaul
606123474Swpaul__stdcall static void
607123526Swpaulndis_write_cfg(status, cfg, key, parm)
608123526Swpaul	ndis_status		*status;
609123526Swpaul	ndis_handle		cfg;
610123526Swpaul	ndis_unicode_string	*key;
611123526Swpaul	ndis_config_parm	*parm;
612123526Swpaul{
613123526Swpaul	char			*keystr = NULL;
614123526Swpaul	ndis_miniport_block	*block;
615123526Swpaul	struct ndis_softc	*sc;
616123526Swpaul        struct sysctl_oid	*oidp;
617123526Swpaul	struct sysctl_ctx_entry	*e;
618123526Swpaul	char			val[256];
619123526Swpaul
620123526Swpaul	block = (ndis_miniport_block *)cfg;
621123526Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
622123526Swpaul
623123526Swpaul	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
624123526Swpaul
625123526Swpaul	/* Decode the parameter into a string. */
626123526Swpaul	*status = ndis_decode_parm(block, parm, val);
627123526Swpaul	if (*status != NDIS_STATUS_SUCCESS) {
628123526Swpaul		free(keystr, M_DEVBUF);
629123526Swpaul		return;
630123526Swpaul	}
631123526Swpaul
632123526Swpaul	/* See if the key already exists. */
633123526Swpaul
634123526Swpaul	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
635123526Swpaul		oidp = e->entry;
636123526Swpaul		if (strcmp(oidp->oid_name, keystr) == 0) {
637123526Swpaul			/* Found it, set the value. */
638123526Swpaul			strcpy((char *)oidp->oid_arg1, val);
639123526Swpaul			free(keystr, M_DEVBUF);
640123526Swpaul			return;
641123526Swpaul		}
642123526Swpaul	}
643123526Swpaul
644123526Swpaul	/* Not found, add a new key with the specified value. */
645123526Swpaul	ndis_add_sysctl(sc, keystr, "(dynamically set key)",
646123526Swpaul		    val, CTLFLAG_RW);
647123526Swpaul
648123526Swpaul	free(keystr, M_DEVBUF);
649123526Swpaul	*status = NDIS_STATUS_SUCCESS;
650123526Swpaul	return;
651123526Swpaul}
652123526Swpaul
653123526Swpaul__stdcall static void
654123474Swpaulndis_close_cfg(cfg)
655123474Swpaul	ndis_handle		cfg;
656123474Swpaul{
657123474Swpaul	return;
658123474Swpaul}
659123474Swpaul
660123474Swpaul__stdcall static void
661123474Swpaulndis_create_lock(lock)
662123474Swpaul	ndis_spin_lock		*lock;
663123474Swpaul{
664123474Swpaul	struct mtx		*mtx;
665123474Swpaul
666123474Swpaul	mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO);
667123474Swpaul	if (mtx == NULL)
668123474Swpaul		return;
669123695Swpaul	mtx_init(mtx, "ndislock", "ndis spin lock",
670123474Swpaul	    MTX_DEF | MTX_RECURSE | MTX_DUPOK);
671123474Swpaul	lock->nsl_spinlock = (ndis_kspin_lock)mtx;
672123474Swpaul
673123474Swpaul	return;
674123474Swpaul}
675123474Swpaul
676123474Swpaul__stdcall static void
677123474Swpaulndis_destroy_lock(lock)
678123474Swpaul	ndis_spin_lock		*lock;
679123474Swpaul{
680123474Swpaul	struct mtx		*ndis_mtx;
681123474Swpaul
682123474Swpaul	ndis_mtx = (struct mtx *)lock->nsl_spinlock;
683123474Swpaul	mtx_destroy(ndis_mtx);
684123474Swpaul	free(ndis_mtx, M_DEVBUF);
685123474Swpaul
686123474Swpaul	return;
687123474Swpaul}
688123474Swpaul
689123474Swpaul__stdcall static void
690123474Swpaulndis_lock(lock)
691123474Swpaul	ndis_spin_lock		*lock;
692123474Swpaul{
693123474Swpaul	if (lock == NULL)
694123474Swpaul		return;
695123474Swpaul	mtx_lock((struct mtx *)lock->nsl_spinlock);
696123474Swpaul
697123474Swpaul	return;
698123474Swpaul}
699123474Swpaul
700123474Swpaul__stdcall static void
701123474Swpaulndis_unlock(lock)
702123474Swpaul	ndis_spin_lock		*lock;
703123474Swpaul{
704123474Swpaul	if (lock == NULL)
705123474Swpaul		return;
706123474Swpaul	mtx_unlock((struct mtx *)lock->nsl_spinlock);
707123474Swpaul
708123474Swpaul	return;
709123474Swpaul}
710123474Swpaul
711123474Swpaul__stdcall static uint32_t
712123474Swpaulndis_read_pci(adapter, slot, offset, buf, len)
713123474Swpaul	ndis_handle		adapter;
714123474Swpaul	uint32_t		slot;
715123474Swpaul	uint32_t		offset;
716123474Swpaul	void			*buf;
717123474Swpaul	uint32_t		len;
718123474Swpaul{
719123474Swpaul	ndis_miniport_block	*block;
720123474Swpaul	int			i;
721123474Swpaul	char			*dest;
722123474Swpaul
723123474Swpaul	block = (ndis_miniport_block *)adapter;
724123474Swpaul	dest = buf;
725123474Swpaul	if (block == NULL || block->nmb_dev == NULL)
726123474Swpaul		return(0);
727123474Swpaul
728123474Swpaul	for (i = 0; i < len; i++)
729123474Swpaul		dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
730123474Swpaul
731123474Swpaul	return(len);
732123474Swpaul}
733123474Swpaul
734123474Swpaul__stdcall static uint32_t
735123474Swpaulndis_write_pci(adapter, slot, offset, buf, len)
736123474Swpaul	ndis_handle		adapter;
737123474Swpaul	uint32_t		slot;
738123474Swpaul	uint32_t		offset;
739123474Swpaul	void			*buf;
740123474Swpaul	uint32_t		len;
741123474Swpaul{
742123474Swpaul	ndis_miniport_block	*block;
743123474Swpaul	int			i;
744123474Swpaul	char			*dest;
745123474Swpaul
746123474Swpaul	block = (ndis_miniport_block *)adapter;
747123474Swpaul	dest = buf;
748123474Swpaul
749123474Swpaul	if (block == NULL || block->nmb_dev == NULL)
750123474Swpaul		return(0);
751123474Swpaul
752123474Swpaul	for (i = 0; i < len; i++)
753123474Swpaul		pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
754123474Swpaul
755123474Swpaul	return(len);
756123474Swpaul}
757123474Swpaul
758123474Swpaul/*
759123474Swpaul * The errorlog routine uses a variable argument list, so we
760123474Swpaul * have to declare it this way.
761123474Swpaul */
762123474Swpaulstatic void
763123474Swpaulndis_syslog(ndis_handle adapter, ndis_error_code code,
764123474Swpaul	uint32_t numerrors, ...)
765123474Swpaul{
766123474Swpaul	ndis_miniport_block	*block;
767123474Swpaul	va_list			ap;
768123474Swpaul	int			i;
769123474Swpaul
770123474Swpaul	block = (ndis_miniport_block *)adapter;
771123474Swpaul
772124060Swpaul	device_printf (block->nmb_dev, "NDIS ERROR: %x\n", code);
773124060Swpaul	device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
774123474Swpaul
775123474Swpaul	va_start(ap, numerrors);
776123474Swpaul	for (i = 0; i < numerrors; i++)
777124060Swpaul		device_printf (block->nmb_dev, "argptr: %p\n",
778124060Swpaul		    va_arg(ap, void *));
779123474Swpaul	va_end(ap);
780123474Swpaul
781123474Swpaul	return;
782123474Swpaul}
783123474Swpaul
784123474Swpaulstatic void
785123474Swpaulndis_map_cb(arg, segs, nseg, error)
786123474Swpaul	void			*arg;
787123474Swpaul	bus_dma_segment_t	*segs;
788123474Swpaul	int			nseg;
789123474Swpaul	int			error;
790123474Swpaul{
791123474Swpaul	struct ndis_map_arg	*ctx;
792123474Swpaul	int			i;
793123474Swpaul
794123474Swpaul	if (error)
795123474Swpaul		return;
796123474Swpaul
797123474Swpaul	ctx = arg;
798123474Swpaul
799123474Swpaul	for (i = 0; i < nseg; i++) {
800123474Swpaul		ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
801123474Swpaul		ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
802123474Swpaul	}
803123474Swpaul
804123474Swpaul	ctx->nma_cnt = nseg;
805123474Swpaul
806123474Swpaul	return;
807123474Swpaul}
808123474Swpaul
809123474Swpaul__stdcall static void
810123474Swpaulndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
811123474Swpaul	ndis_handle		adapter;
812123474Swpaul	ndis_buffer		*buf;
813123474Swpaul	uint32_t		mapreg;
814123474Swpaul	uint8_t			writedev;
815123474Swpaul	ndis_paddr_unit		*addrarray;
816123474Swpaul	uint32_t		*arraysize;
817123474Swpaul{
818123474Swpaul	ndis_miniport_block	*block;
819123474Swpaul	struct ndis_softc	*sc;
820123474Swpaul	struct ndis_map_arg	nma;
821123474Swpaul	bus_dmamap_t		map;
822123474Swpaul	int			error;
823123474Swpaul
824123474Swpaul	if (adapter == NULL)
825123474Swpaul		return;
826123474Swpaul
827123474Swpaul	block = (ndis_miniport_block *)adapter;
828123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
829123474Swpaul
830123474Swpaul	if (mapreg > sc->ndis_mmapcnt)
831123474Swpaul		return;
832123474Swpaul
833123474Swpaul	map = sc->ndis_mmaps[mapreg];
834123474Swpaul	nma.nma_fraglist = addrarray;
835123474Swpaul
836123474Swpaul	error = bus_dmamap_load(sc->ndis_mtag, map,
837123757Swpaul	    MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
838123474Swpaul	    (void *)&nma, BUS_DMA_NOWAIT);
839123474Swpaul
840123474Swpaul	if (error)
841123474Swpaul		return;
842123474Swpaul
843123474Swpaul	bus_dmamap_sync(sc->ndis_mtag, map,
844123474Swpaul	    writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
845123474Swpaul
846123474Swpaul	*arraysize = nma.nma_cnt;
847123474Swpaul
848123474Swpaul	return;
849123474Swpaul}
850123474Swpaul
851123474Swpaul__stdcall static void
852123474Swpaulndis_vtophys_unload(adapter, buf, mapreg)
853123474Swpaul	ndis_handle		adapter;
854123474Swpaul	ndis_buffer		*buf;
855123474Swpaul	uint32_t		mapreg;
856123474Swpaul{
857123474Swpaul	ndis_miniport_block	*block;
858123474Swpaul	struct ndis_softc	*sc;
859123474Swpaul	bus_dmamap_t		map;
860123474Swpaul
861123474Swpaul	if (adapter == NULL)
862123474Swpaul		return;
863123474Swpaul
864123474Swpaul	block = (ndis_miniport_block *)adapter;
865123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
866123474Swpaul
867123474Swpaul	if (mapreg > sc->ndis_mmapcnt)
868123474Swpaul		return;
869123474Swpaul
870123474Swpaul	map = sc->ndis_mmaps[mapreg];
871123474Swpaul
872123474Swpaul	bus_dmamap_sync(sc->ndis_mtag, map,
873123474Swpaul	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
874123474Swpaul
875123474Swpaul	bus_dmamap_unload(sc->ndis_mtag, map);
876123474Swpaul
877123474Swpaul	return;
878123474Swpaul}
879123474Swpaul
880123474Swpaul__stdcall static void
881123474Swpaulndis_create_timer(timer, handle, func, ctx)
882123474Swpaul	ndis_miniport_timer	*timer;
883123474Swpaul	ndis_handle		*handle;
884123474Swpaul	ndis_timer_function	func;
885123474Swpaul	void			*ctx;
886123474Swpaul{
887123821Swpaul	struct ndis_timer_entry	*ne = NULL;
888123821Swpaul	ndis_miniport_block	*block;
889123821Swpaul	block = (ndis_miniport_block *)handle;
890123474Swpaul
891123821Swpaul	ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT);
892123832Swpaul	callout_init(&ne->nte_ch, CALLOUT_MPSAFE);
893123821Swpaul	TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link);
894123821Swpaul	ne->nte_timer = timer;
895123821Swpaul
896123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
897123821Swpaul	timer->nmt_dpc.nk_deferredctx = &ne->nte_ch;
898123474Swpaul	timer->nmt_timerfunc = func;
899123474Swpaul	timer->nmt_timerctx = ctx;
900123474Swpaul
901123474Swpaul	return;
902123474Swpaul}
903123474Swpaul
904123474Swpaul/*
905123474Swpaul * The driver's timer callout is __stdcall function, so we need this
906123474Swpaul * intermediate step.
907123474Swpaul */
908123474Swpaul
909123474Swpaulstatic void
910123474Swpaulndis_timercall(arg)
911123474Swpaul	void		*arg;
912123474Swpaul{
913123474Swpaul	ndis_miniport_timer	*timer;
914123474Swpaul	__stdcall ndis_timer_function	timerfunc;
915123474Swpaul
916123474Swpaul	timer = arg;
917123474Swpaul
918123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
919123474Swpaul	timerfunc = timer->nmt_timerfunc;
920123474Swpaul	timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
921123474Swpaul
922123474Swpaul	return;
923123474Swpaul}
924123474Swpaul
925123474Swpaul/*
926123474Swpaul * Windows specifies timeouts in milliseconds. We specify timeouts
927123474Swpaul * in hz. Trying to compute a tenth of a second based on hz is tricky.
928123474Swpaul * so we approximate. Note that we abuse the dpc portion of the
929123474Swpaul * miniport timer structure to hold the UNIX callout handle.
930123474Swpaul */
931123474Swpaul__stdcall static void
932123474Swpaulndis_set_timer(timer, msecs)
933123474Swpaul	ndis_miniport_timer	*timer;
934123474Swpaul	uint32_t		msecs;
935123474Swpaul{
936123832Swpaul	struct callout		*ch;
937123474Swpaul	struct timeval		tv;
938123474Swpaul
939123474Swpaul	tv.tv_sec = 0;
940123474Swpaul	tv.tv_usec = msecs * 1000;
941123474Swpaul
942123821Swpaul	ch = timer->nmt_dpc.nk_deferredctx;
943123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_timercall;
944123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
945123832Swpaul	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
946123474Swpaul
947123474Swpaul	return;
948123474Swpaul}
949123474Swpaul
950123474Swpaulstatic void
951123474Swpaulndis_tick(arg)
952123474Swpaul	void			*arg;
953123474Swpaul{
954123474Swpaul	ndis_miniport_timer	*timer;
955123832Swpaul	struct callout		*ch;
956123474Swpaul	__stdcall ndis_timer_function	timerfunc;
957123474Swpaul	struct timeval		tv;
958123474Swpaul
959123474Swpaul	timer = arg;
960123474Swpaul
961123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
962123474Swpaul	timerfunc = timer->nmt_timerfunc;
963123474Swpaul	timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
964123474Swpaul
965123474Swpaul	/* Automatically reload timer. */
966123474Swpaul
967123474Swpaul	tv.tv_sec = 0;
968123474Swpaul	tv.tv_usec = timer->nmt_ktimer.nk_period * 1000;
969123821Swpaul	ch = timer->nmt_dpc.nk_deferredctx;
970123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
971123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
972123832Swpaul	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
973123474Swpaul
974123474Swpaul	return;
975123474Swpaul}
976123474Swpaul
977123474Swpaul__stdcall static void
978123474Swpaulndis_set_periodic_timer(timer, msecs)
979123474Swpaul	ndis_miniport_timer	*timer;
980123474Swpaul	uint32_t		msecs;
981123474Swpaul{
982123832Swpaul	struct callout		*ch;
983123474Swpaul	struct timeval		tv;
984123474Swpaul
985123474Swpaul	tv.tv_sec = 0;
986123474Swpaul	tv.tv_usec = msecs * 1000;
987123474Swpaul
988123474Swpaul	timer->nmt_ktimer.nk_period = msecs;
989123821Swpaul	ch = timer->nmt_dpc.nk_deferredctx;
990123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
991123821Swpaul	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
992123832Swpaul	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
993123474Swpaul
994123474Swpaul	return;
995123474Swpaul}
996123474Swpaul
997123474Swpaul__stdcall static void
998123474Swpaulndis_cancel_timer(timer, cancelled)
999123474Swpaul	ndis_miniport_timer	*timer;
1000123474Swpaul	uint8_t			*cancelled;
1001123474Swpaul{
1002123832Swpaul	struct callout		*ch;
1003123474Swpaul
1004124097Swpaul	if (timer == NULL)
1005124097Swpaul		return;
1006123821Swpaul	ch = timer->nmt_dpc.nk_deferredctx;
1007124097Swpaul	if (ch == NULL)
1008124097Swpaul		return;
1009123832Swpaul	callout_stop(ch);
1010123821Swpaul	*cancelled = timer->nmt_ktimer.nk_header.dh_sigstate;
1011123474Swpaul
1012123474Swpaul	return;
1013123474Swpaul}
1014123474Swpaul
1015123474Swpaul__stdcall static void
1016123474Swpaulndis_query_resources(status, adapter, list, buflen)
1017123474Swpaul	ndis_status		*status;
1018123474Swpaul	ndis_handle		adapter;
1019123474Swpaul	ndis_resource_list	*list;
1020123474Swpaul	uint32_t		*buflen;
1021123474Swpaul{
1022123474Swpaul	ndis_miniport_block	*block;
1023123474Swpaul	struct ndis_softc	*sc;
1024124094Swpaul	int			rsclen;
1025123474Swpaul
1026123474Swpaul	block = (ndis_miniport_block *)adapter;
1027123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1028124094Swpaul
1029124094Swpaul	rsclen = sizeof(ndis_resource_list) +
1030123474Swpaul	    (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1031124094Swpaul	if (*buflen < rsclen) {
1032124094Swpaul		*buflen = rsclen;
1033124094Swpaul		*status = NDIS_STATUS_INVALID_LENGTH;
1034124094Swpaul		return;
1035124094Swpaul	}
1036123474Swpaul
1037123474Swpaul	bcopy((char *)block->nmb_rlist, (char *)list, *buflen);
1038123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1039123474Swpaul	return;
1040123474Swpaul}
1041123474Swpaul
1042123474Swpaul__stdcall static ndis_status
1043123474Swpaulndis_register_ioport(offset, adapter, port, numports)
1044123474Swpaul	void			**offset;
1045123474Swpaul	ndis_handle		adapter;
1046123474Swpaul	uint32_t		port;
1047123474Swpaul	uint32_t		numports;
1048123474Swpaul{
1049123474Swpaul	struct ndis_miniport_block	*block;
1050123474Swpaul	struct ndis_softc	*sc;
1051123474Swpaul
1052123474Swpaul	if (adapter == NULL)
1053123474Swpaul		return(NDIS_STATUS_FAILURE);
1054123474Swpaul
1055123474Swpaul	block = (ndis_miniport_block *)adapter;
1056123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1057123474Swpaul
1058123474Swpaul	if (sc->ndis_res_io == NULL)
1059123474Swpaul		return(NDIS_STATUS_FAILURE);
1060123474Swpaul
1061123474Swpaul	if (rman_get_size(sc->ndis_res_io) != numports)
1062123474Swpaul		return(NDIS_STATUS_INVALID_LENGTH);
1063123474Swpaul
1064123474Swpaul	*offset = (void *)rman_get_start(sc->ndis_res_io);
1065123474Swpaul
1066123474Swpaul	return(NDIS_STATUS_SUCCESS);
1067123474Swpaul}
1068123474Swpaul
1069123474Swpaul__stdcall static void
1070123474Swpaulndis_deregister_ioport(adapter, port, numports, offset)
1071123474Swpaul	ndis_handle		adapter;
1072123474Swpaul	uint32_t		port;
1073123474Swpaul	uint32_t		numports;
1074123474Swpaul	void			*offset;
1075123474Swpaul{
1076123474Swpaul	return;
1077123474Swpaul}
1078123474Swpaul
1079123474Swpaul__stdcall static void
1080123474Swpaulndis_read_netaddr(status, addr, addrlen, adapter)
1081123474Swpaul	ndis_status		*status;
1082123474Swpaul	void			**addr;
1083123474Swpaul	uint32_t		*addrlen;
1084123474Swpaul	ndis_handle		adapter;
1085123474Swpaul{
1086123474Swpaul	struct ndis_softc	*sc;
1087123474Swpaul	ndis_miniport_block	*block;
1088123474Swpaul	uint8_t			empty[] = { 0, 0, 0, 0, 0, 0 };
1089123474Swpaul
1090123474Swpaul	block = (ndis_miniport_block *)adapter;
1091123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1092123474Swpaul
1093123474Swpaul	if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1094123474Swpaul		*status = NDIS_STATUS_FAILURE;
1095123474Swpaul	else {
1096123474Swpaul		*addr = sc->arpcom.ac_enaddr;
1097123474Swpaul		*addrlen = ETHER_ADDR_LEN;
1098123474Swpaul		*status = NDIS_STATUS_SUCCESS;
1099123474Swpaul	}
1100123474Swpaul
1101123474Swpaul	return;
1102123474Swpaul}
1103123474Swpaul
1104123474Swpaul__stdcall static ndis_status
1105123848Swpaulndis_mapreg_cnt(bustype, cnt)
1106123848Swpaul	uint32_t		bustype;
1107123848Swpaul	uint32_t		*cnt;
1108123848Swpaul{
1109124097Swpaul	*cnt = 8192;
1110123848Swpaul	return(NDIS_STATUS_SUCCESS);
1111123848Swpaul}
1112123848Swpaul
1113123848Swpaul__stdcall static ndis_status
1114123474Swpaulndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
1115123474Swpaul	ndis_handle		adapter;
1116123474Swpaul	uint32_t		dmachannel;
1117123474Swpaul	uint8_t			dmasize;
1118123474Swpaul	uint32_t		physmapneeded;
1119123474Swpaul	uint32_t		maxmap;
1120123474Swpaul{
1121123474Swpaul	struct ndis_softc	*sc;
1122123474Swpaul	ndis_miniport_block	*block;
1123123474Swpaul	int			error, i, nseg = NDIS_MAXSEG;
1124123474Swpaul
1125123474Swpaul	block = (ndis_miniport_block *)adapter;
1126123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1127123474Swpaul
1128123474Swpaul	sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1129123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1130123474Swpaul
1131123474Swpaul	if (sc->ndis_mmaps == NULL)
1132123474Swpaul		return(NDIS_STATUS_RESOURCES);
1133123474Swpaul
1134123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1135123474Swpaul	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1136123474Swpaul	    NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1137123474Swpaul	    NULL, NULL, &sc->ndis_mtag);
1138123474Swpaul
1139123474Swpaul	if (error) {
1140123474Swpaul		free(sc->ndis_mmaps, M_DEVBUF);
1141123474Swpaul		return(NDIS_STATUS_RESOURCES);
1142123474Swpaul	}
1143123474Swpaul
1144123474Swpaul	for (i = 0; i < physmapneeded; i++)
1145123474Swpaul		bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1146123474Swpaul
1147123474Swpaul	sc->ndis_mmapcnt = physmapneeded;
1148123474Swpaul
1149123474Swpaul	return(NDIS_STATUS_SUCCESS);
1150123474Swpaul}
1151123474Swpaul
1152123474Swpaul__stdcall static void
1153123474Swpaulndis_free_mapreg(adapter)
1154123474Swpaul	ndis_handle		adapter;
1155123474Swpaul{
1156123474Swpaul	struct ndis_softc	*sc;
1157123474Swpaul	ndis_miniport_block	*block;
1158123474Swpaul	int			i;
1159123474Swpaul
1160123474Swpaul	block = (ndis_miniport_block *)adapter;
1161123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1162123474Swpaul
1163123474Swpaul	for (i = 0; i < sc->ndis_mmapcnt; i++)
1164123474Swpaul		bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1165123474Swpaul
1166123474Swpaul	free(sc->ndis_mmaps, M_DEVBUF);
1167123474Swpaul
1168123474Swpaul	bus_dma_tag_destroy(sc->ndis_mtag);
1169123474Swpaul
1170123474Swpaul	return;
1171123474Swpaul}
1172123474Swpaul
1173123474Swpaulstatic void
1174123474Swpaulndis_mapshared_cb(arg, segs, nseg, error)
1175123474Swpaul	void			*arg;
1176123474Swpaul	bus_dma_segment_t	*segs;
1177123474Swpaul	int			nseg;
1178123474Swpaul	int			error;
1179123474Swpaul{
1180123474Swpaul	ndis_physaddr		*p;
1181123474Swpaul
1182123474Swpaul	if (error || nseg > 1)
1183123474Swpaul		return;
1184123474Swpaul
1185123474Swpaul	p = arg;
1186123474Swpaul
1187123474Swpaul	p->np_quad = segs[0].ds_addr;
1188123474Swpaul
1189123474Swpaul	return;
1190123474Swpaul}
1191123474Swpaul
1192123474Swpaul/*
1193123474Swpaul * This maps to bus_dmamem_alloc().
1194123474Swpaul */
1195123474Swpaul__stdcall static void
1196123474Swpaulndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
1197123474Swpaul	ndis_handle		adapter;
1198123474Swpaul	uint32_t		len;
1199123474Swpaul	uint8_t			cached;
1200123474Swpaul	void			**vaddr;
1201123474Swpaul	ndis_physaddr		*paddr;
1202123474Swpaul{
1203123474Swpaul	ndis_miniport_block	*block;
1204123474Swpaul	struct ndis_softc	*sc;
1205123474Swpaul	struct ndis_shmem	*sh;
1206123474Swpaul	int			error;
1207123474Swpaul
1208123474Swpaul	if (adapter == NULL)
1209123474Swpaul		return;
1210123474Swpaul
1211123474Swpaul	block = (ndis_miniport_block *)adapter;
1212123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1213123474Swpaul
1214123474Swpaul	sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1215123474Swpaul	if (sh == NULL)
1216123474Swpaul		return;
1217123474Swpaul
1218123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1219123474Swpaul	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1220123474Swpaul	    NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
1221123474Swpaul	    &sh->ndis_stag);
1222123474Swpaul
1223123474Swpaul	if (error) {
1224123474Swpaul		free(sh, M_DEVBUF);
1225123474Swpaul		return;
1226123474Swpaul	}
1227123474Swpaul
1228123474Swpaul	error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1229123474Swpaul	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1230123474Swpaul
1231123474Swpaul	if (error) {
1232123474Swpaul		bus_dma_tag_destroy(sh->ndis_stag);
1233123474Swpaul		free(sh, M_DEVBUF);
1234123474Swpaul		return;
1235123474Swpaul	}
1236123474Swpaul
1237123474Swpaul	error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1238123474Swpaul	    len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1239123474Swpaul
1240123474Swpaul	if (error) {
1241123474Swpaul		bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1242123474Swpaul		bus_dma_tag_destroy(sh->ndis_stag);
1243123474Swpaul		free(sh, M_DEVBUF);
1244123474Swpaul		return;
1245123474Swpaul	}
1246123474Swpaul
1247123474Swpaul	sh->ndis_saddr = *vaddr;
1248123474Swpaul	sh->ndis_next = sc->ndis_shlist;
1249123474Swpaul	sc->ndis_shlist = sh;
1250123474Swpaul
1251123474Swpaul	return;
1252123474Swpaul}
1253123474Swpaul
1254123474Swpaul__stdcall static void
1255123474Swpaulndis_alloc_sharedmem_async(adapter, len, cached, ctx)
1256123474Swpaul	ndis_handle		adapter;
1257123474Swpaul	uint32_t		len;
1258123474Swpaul	uint8_t			cached;
1259123474Swpaul	void			*ctx;
1260123474Swpaul{
1261123474Swpaul	ndis_miniport_block	*block;
1262123474Swpaul	struct ndis_softc	*sc;
1263123474Swpaul	void			*vaddr;
1264123474Swpaul	ndis_physaddr		paddr;
1265123474Swpaul	__stdcall ndis_allocdone_handler	donefunc;
1266123474Swpaul
1267123474Swpaul	if (adapter == NULL)
1268123474Swpaul		return;
1269123474Swpaul
1270123474Swpaul	block = (ndis_miniport_block *)adapter;
1271123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1272123474Swpaul	donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1273123474Swpaul
1274123474Swpaul	ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr);
1275123474Swpaul	donefunc(adapter, vaddr, &paddr, len, ctx);
1276123474Swpaul
1277123474Swpaul	return;
1278123474Swpaul}
1279123474Swpaul
1280123474Swpaul__stdcall static void
1281123474Swpaulndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
1282123474Swpaul	ndis_handle		adapter;
1283123474Swpaul	uint32_t		len;
1284123474Swpaul	uint8_t			cached;
1285123474Swpaul	void			*vaddr;
1286123474Swpaul	ndis_physaddr		paddr;
1287123474Swpaul{
1288123474Swpaul	ndis_miniport_block	*block;
1289123474Swpaul	struct ndis_softc	*sc;
1290123474Swpaul	struct ndis_shmem	*sh, *prev;
1291123474Swpaul
1292123474Swpaul	if (vaddr == NULL || adapter == NULL)
1293123474Swpaul		return;
1294123474Swpaul
1295123474Swpaul	block = (ndis_miniport_block *)adapter;
1296123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1297123474Swpaul	sh = prev = sc->ndis_shlist;
1298123474Swpaul
1299123474Swpaul	while (sh) {
1300123474Swpaul		if (sh->ndis_saddr == vaddr)
1301123474Swpaul			break;
1302123474Swpaul		prev = sh;
1303123474Swpaul		sh = sh->ndis_next;
1304123474Swpaul	}
1305123474Swpaul
1306123474Swpaul	bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1307123474Swpaul	bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1308123474Swpaul	bus_dma_tag_destroy(sh->ndis_stag);
1309123474Swpaul
1310123474Swpaul	if (sh == sc->ndis_shlist)
1311123474Swpaul		sc->ndis_shlist = sh->ndis_next;
1312123474Swpaul	else
1313123474Swpaul		prev->ndis_next = sh->ndis_next;
1314123474Swpaul
1315123474Swpaul	free(sh, M_DEVBUF);
1316123474Swpaul
1317123474Swpaul	return;
1318123474Swpaul}
1319123474Swpaul
1320123474Swpaul__stdcall static ndis_status
1321123474Swpaulndis_map_iospace(vaddr, adapter, paddr, len)
1322123474Swpaul	void			**vaddr;
1323123474Swpaul	ndis_handle		adapter;
1324123474Swpaul	ndis_physaddr		paddr;
1325123474Swpaul	uint32_t		len;
1326123474Swpaul{
1327123474Swpaul	ndis_miniport_block	*block;
1328123474Swpaul	struct ndis_softc	*sc;
1329123474Swpaul
1330123474Swpaul	if (adapter == NULL)
1331123474Swpaul		return(NDIS_STATUS_FAILURE);
1332123474Swpaul
1333123474Swpaul	block = (ndis_miniport_block *)adapter;
1334123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1335123474Swpaul
1336123474Swpaul	if (sc->ndis_res_mem == NULL)
1337123474Swpaul		return(NDIS_STATUS_FAILURE);
1338123474Swpaul
1339123474Swpaul	*vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1340123474Swpaul
1341123474Swpaul	return(NDIS_STATUS_SUCCESS);
1342123474Swpaul}
1343123474Swpaul
1344123474Swpaul__stdcall static void
1345123474Swpaulndis_unmap_iospace(adapter, vaddr, len)
1346123474Swpaul	ndis_handle		adapter;
1347123474Swpaul	void			*vaddr;
1348123474Swpaul	uint32_t		len;
1349123474Swpaul{
1350123474Swpaul	return;
1351123474Swpaul}
1352123474Swpaul
1353123474Swpaul__stdcall static uint32_t
1354123474Swpaulndis_cachefill(void)
1355123474Swpaul{
1356123474Swpaul	return(128);
1357123474Swpaul}
1358123474Swpaul
1359123474Swpaul__stdcall static uint32_t
1360123474Swpaulndis_dma_align(handle)
1361123474Swpaul	ndis_handle		handle;
1362123474Swpaul{
1363123474Swpaul	return(128);
1364123474Swpaul}
1365123474Swpaul
1366123474Swpaul/*
1367123474Swpaul * NDIS has two methods for dealing with NICs that support DMA.
1368123474Swpaul * One is to just pass packets to the driver and let it call
1369123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1370123474Swpaul * all by itself, and the other is to let the NDIS library handle the
1371123474Swpaul * buffer mapping internally, and hand the driver an already populated
1372123474Swpaul * scatter/gather fragment list. If the driver calls
1373123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter
1374123474Swpaul * method.
1375123474Swpaul */
1376123474Swpaul
1377123474Swpaul__stdcall static ndis_status
1378123474Swpaulndis_init_sc_dma(adapter, is64, maxphysmap)
1379123474Swpaul	ndis_handle		adapter;
1380123474Swpaul	uint8_t			is64;
1381123474Swpaul	uint32_t		maxphysmap;
1382123474Swpaul{
1383123474Swpaul	struct ndis_softc	*sc;
1384123474Swpaul	ndis_miniport_block	*block;
1385123474Swpaul	int			error;
1386123474Swpaul
1387123474Swpaul	if (adapter == NULL)
1388123474Swpaul		return(NDIS_STATUS_FAILURE);
1389123474Swpaul	block = (ndis_miniport_block *)adapter;
1390123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1391123474Swpaul
1392123474Swpaul	/* Don't do this twice. */
1393123474Swpaul	if (sc->ndis_sc == 1)
1394123474Swpaul		return(NDIS_STATUS_SUCCESS);
1395123474Swpaul
1396123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1397123474Swpaul	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1398123474Swpaul	    MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1399123474Swpaul	    NULL, NULL, &sc->ndis_ttag);
1400123474Swpaul
1401123474Swpaul	sc->ndis_sc = 1;
1402123474Swpaul
1403123474Swpaul	return(NDIS_STATUS_SUCCESS);
1404123474Swpaul}
1405123474Swpaul
1406123474Swpaul__stdcall static void
1407123474Swpaulndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
1408123474Swpaul	ndis_status		*status;
1409123474Swpaul	ndis_handle		*pool;
1410123474Swpaul	uint32_t		descnum;
1411123474Swpaul	uint32_t		protrsvdlen;
1412123474Swpaul{
1413123474Swpaul	ndis_packet		*cur;
1414123474Swpaul	int			i;
1415123474Swpaul
1416123474Swpaul	*pool = malloc(sizeof(ndis_packet) * (descnum + 1),
1417123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1418123474Swpaul
1419123474Swpaul	if (pool == NULL) {
1420123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1421123474Swpaul		return;
1422123474Swpaul	}
1423123474Swpaul
1424123474Swpaul	cur = (ndis_packet *)*pool;
1425123474Swpaul	cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1426123474Swpaul	for (i = 0; i < descnum; i++) {
1427123474Swpaul		cur->np_private.npp_head = (ndis_handle)(cur + 1);
1428123474Swpaul		cur++;
1429123474Swpaul	}
1430123474Swpaul
1431123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1432123474Swpaul	return;
1433123474Swpaul}
1434123474Swpaul
1435123474Swpaul__stdcall static void
1436123474Swpaulndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
1437123474Swpaul	ndis_status		*status;
1438123474Swpaul	ndis_handle		*pool;
1439123474Swpaul	uint32_t		descnum;
1440123474Swpaul	uint32_t		oflowdescnum;
1441123474Swpaul	uint32_t		protrsvdlen;
1442123474Swpaul{
1443123474Swpaul	return(ndis_alloc_packetpool(status, pool,
1444123474Swpaul	    descnum + oflowdescnum, protrsvdlen));
1445123474Swpaul}
1446123474Swpaul
1447123474Swpaul__stdcall static uint32_t
1448123474Swpaulndis_packetpool_use(pool)
1449123474Swpaul	ndis_handle		pool;
1450123474Swpaul{
1451123474Swpaul	ndis_packet		*head;
1452123474Swpaul
1453123474Swpaul	head = (ndis_packet *)pool;
1454123474Swpaul
1455123474Swpaul	return(head->np_private.npp_count);
1456123474Swpaul}
1457123474Swpaul
1458123474Swpaul__stdcall static void
1459123474Swpaulndis_free_packetpool(pool)
1460123474Swpaul	ndis_handle		pool;
1461123474Swpaul{
1462123474Swpaul	free(pool, M_DEVBUF);
1463123474Swpaul	return;
1464123474Swpaul}
1465123474Swpaul
1466123474Swpaul__stdcall static void
1467123474Swpaulndis_alloc_packet(status, packet, pool)
1468123474Swpaul	ndis_status		*status;
1469123474Swpaul	ndis_packet		**packet;
1470123474Swpaul	ndis_handle		pool;
1471123474Swpaul{
1472123474Swpaul	ndis_packet		*head, *pkt;
1473123474Swpaul
1474123474Swpaul	head = (ndis_packet *)pool;
1475123474Swpaul
1476123474Swpaul	if (head->np_private.npp_flags != 0x1) {
1477123474Swpaul		*status = NDIS_STATUS_FAILURE;
1478123474Swpaul		return;
1479123474Swpaul	}
1480123474Swpaul
1481123474Swpaul	pkt = (ndis_packet *)head->np_private.npp_head;
1482123474Swpaul
1483123474Swpaul	if (pkt == NULL) {
1484123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1485123474Swpaul		return;
1486123474Swpaul	}
1487123474Swpaul
1488123474Swpaul	head->np_private.npp_head = pkt->np_private.npp_head;
1489123474Swpaul
1490123474Swpaul	pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1491123474Swpaul	/* Save pointer to the pool. */
1492123474Swpaul	pkt->np_private.npp_pool = head;
1493123474Swpaul
1494123474Swpaul	/* Set the oob offset pointer. Lots of things expect this. */
1495123474Swpaul	pkt->np_private.npp_packetooboffset =
1496123474Swpaul	    offsetof(ndis_packet, np_oob);
1497123474Swpaul
1498123474Swpaul	*packet = pkt;
1499123474Swpaul
1500123474Swpaul	head->np_private.npp_count++;
1501123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1502123474Swpaul	return;
1503123474Swpaul}
1504123474Swpaul
1505123848Swpaul__stdcall static void
1506123848Swpaulndis_release_packet(packet)
1507123474Swpaul	ndis_packet		*packet;
1508123474Swpaul{
1509123474Swpaul	ndis_packet		*head;
1510123474Swpaul
1511123474Swpaul	if (packet == NULL || packet->np_private.npp_pool == NULL)
1512123474Swpaul		return;
1513123474Swpaul
1514123474Swpaul	head = packet->np_private.npp_pool;
1515123474Swpaul	if (head->np_private.npp_flags != 0x1)
1516123474Swpaul		return;
1517123474Swpaul
1518123474Swpaul	packet->np_private.npp_head = head->np_private.npp_head;
1519123474Swpaul	head->np_private.npp_head = (ndis_buffer *)packet;
1520123474Swpaul	head->np_private.npp_count--;
1521123474Swpaul
1522123474Swpaul	return;
1523123474Swpaul}
1524123474Swpaul
1525123474Swpaul__stdcall static void
1526123474Swpaulndis_unchain_headbuf(packet, buf)
1527123474Swpaul	ndis_packet		*packet;
1528123474Swpaul	ndis_buffer		**buf;
1529123474Swpaul{
1530123474Swpaul	ndis_packet_private	*priv;
1531123474Swpaul
1532123474Swpaul	if (packet == NULL || buf == NULL)
1533123474Swpaul		return;
1534123474Swpaul
1535123474Swpaul	priv = &packet->np_private;
1536123474Swpaul
1537123474Swpaul	priv->npp_validcounts = FALSE;
1538123474Swpaul
1539123474Swpaul	if (priv->npp_head == priv->npp_tail) {
1540123474Swpaul		*buf = priv->npp_head;
1541123474Swpaul		priv->npp_head = priv->npp_tail = NULL;
1542123474Swpaul	} else {
1543123474Swpaul		*buf = priv->npp_head;
1544123474Swpaul		priv->npp_head = (*buf)->nb_next;
1545123474Swpaul	}
1546123474Swpaul
1547123474Swpaul	return;
1548123474Swpaul}
1549123474Swpaul
1550123721Swpaul__stdcall static void
1551123721Swpaulndis_unchain_tailbuf(packet, buf)
1552123721Swpaul	ndis_packet		*packet;
1553123721Swpaul	ndis_buffer		**buf;
1554123721Swpaul{
1555123721Swpaul	ndis_packet_private	*priv;
1556123721Swpaul	ndis_buffer		*tmp;
1557123721Swpaul
1558123721Swpaul	if (packet == NULL || buf == NULL)
1559123721Swpaul		return;
1560123721Swpaul
1561123721Swpaul	priv = &packet->np_private;
1562123721Swpaul
1563123721Swpaul	priv->npp_validcounts = FALSE;
1564123721Swpaul
1565123721Swpaul	if (priv->npp_head == priv->npp_tail) {
1566123721Swpaul		*buf = priv->npp_head;
1567123721Swpaul		priv->npp_head = priv->npp_tail = NULL;
1568123721Swpaul	} else {
1569123721Swpaul		*buf = priv->npp_tail;
1570123721Swpaul		tmp = priv->npp_head;
1571123721Swpaul		while (tmp->nb_next != priv->npp_tail)
1572123721Swpaul			tmp = tmp->nb_next;
1573123721Swpaul		priv->npp_tail = tmp;
1574123721Swpaul		tmp->nb_next = NULL;
1575123721Swpaul	}
1576123721Swpaul
1577123721Swpaul	return;
1578123721Swpaul}
1579123721Swpaul
1580123474Swpaul/*
1581123474Swpaul * The NDIS "buffer" manipulation functions are somewhat misnamed.
1582123474Swpaul * They don't really allocate buffers: they allocate buffer mappings.
1583123474Swpaul * The idea is you reserve a chunk of DMA-able memory using
1584123474Swpaul * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1585123474Swpaul * to obtain the virtual address of the DMA-able region.
1586123474Swpaul * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1587123474Swpaul */
1588123474Swpaul
1589123474Swpaul__stdcall static void
1590123474Swpaulndis_alloc_bufpool(status, pool, descnum)
1591123474Swpaul	ndis_status		*status;
1592123474Swpaul	ndis_handle		*pool;
1593123474Swpaul	uint32_t		descnum;
1594123474Swpaul{
1595123474Swpaul	ndis_buffer		*cur;
1596123474Swpaul	int			i;
1597123474Swpaul
1598123474Swpaul	*pool = malloc(sizeof(ndis_buffer) * (descnum + 1),
1599123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1600123474Swpaul
1601123474Swpaul	if (pool == NULL) {
1602123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1603123474Swpaul		return;
1604123474Swpaul	}
1605123474Swpaul
1606123474Swpaul	cur = (ndis_buffer *)*pool;
1607123474Swpaul	cur->nb_flags = 0x1; /* mark the head of the list */
1608123474Swpaul	for (i = 0; i < descnum; i++) {
1609123474Swpaul		cur->nb_next = cur + 1;
1610123474Swpaul		cur++;
1611123474Swpaul	}
1612123474Swpaul
1613123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1614123474Swpaul	return;
1615123474Swpaul}
1616123474Swpaul
1617123474Swpaul__stdcall static void
1618123474Swpaulndis_free_bufpool(pool)
1619123474Swpaul	ndis_handle		pool;
1620123474Swpaul{
1621123474Swpaul	free(pool, M_DEVBUF);
1622123474Swpaul	return;
1623123474Swpaul}
1624123474Swpaul
1625123474Swpaul/*
1626123474Swpaul * This maps to a bus_dmamap_create() and bus_dmamap_load().
1627123474Swpaul */
1628123474Swpaul__stdcall static void
1629123474Swpaulndis_alloc_buf(status, buffer, pool, vaddr, len)
1630123474Swpaul	ndis_status		*status;
1631123474Swpaul	ndis_buffer		**buffer;
1632123474Swpaul	ndis_handle		pool;
1633123474Swpaul	void			*vaddr;
1634123474Swpaul	uint32_t		len;
1635123474Swpaul{
1636123474Swpaul	ndis_buffer		*head, *buf;
1637123474Swpaul
1638123474Swpaul	head = (ndis_buffer *)pool;
1639123474Swpaul	if (head->nb_flags != 0x1) {
1640123474Swpaul		*status = NDIS_STATUS_FAILURE;
1641123474Swpaul		return;
1642123474Swpaul	}
1643123474Swpaul
1644123474Swpaul	buf = head->nb_next;
1645123474Swpaul
1646123474Swpaul	if (buf == NULL) {
1647123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1648123474Swpaul		return;
1649123474Swpaul	}
1650123474Swpaul
1651123474Swpaul	head->nb_next = buf->nb_next;
1652123474Swpaul
1653123474Swpaul	/* Save pointer to the pool. */
1654123474Swpaul	buf->nb_process = head;
1655123474Swpaul
1656123757Swpaul	MDL_INIT(buf, vaddr, len);
1657123474Swpaul
1658123474Swpaul	*buffer = buf;
1659123474Swpaul
1660123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1661123474Swpaul	return;
1662123474Swpaul}
1663123474Swpaul
1664123848Swpaul__stdcall static void
1665123848Swpaulndis_release_buf(buf)
1666123474Swpaul	ndis_buffer		*buf;
1667123474Swpaul{
1668123474Swpaul	ndis_buffer		*head;
1669123474Swpaul
1670123474Swpaul	if (buf == NULL || buf->nb_process == NULL)
1671123474Swpaul		return;
1672123474Swpaul
1673123474Swpaul	head = buf->nb_process;
1674123474Swpaul
1675123474Swpaul	if (head->nb_flags != 0x1)
1676123474Swpaul		return;
1677123474Swpaul
1678123474Swpaul	buf->nb_next = head->nb_next;
1679123474Swpaul	head->nb_next = buf;
1680123474Swpaul
1681123474Swpaul	return;
1682123474Swpaul}
1683123474Swpaul
1684123723Swpaul/*
1685123723Swpaul * Get the virtual address and length of a buffer.
1686123723Swpaul * Note: the vaddr argument is optional.
1687123723Swpaul */
1688123474Swpaul
1689123474Swpaul__stdcall static void
1690123474Swpaulndis_query_buf(buf, vaddr, len)
1691123474Swpaul	ndis_buffer		*buf;
1692123474Swpaul	void			**vaddr;
1693123474Swpaul	uint32_t		*len;
1694123474Swpaul{
1695123723Swpaul	if (vaddr != NULL)
1696123757Swpaul		*vaddr = MDL_VA(buf);
1697123474Swpaul	*len = buf->nb_bytecount;
1698123474Swpaul
1699123474Swpaul	return;
1700123474Swpaul}
1701123474Swpaul
1702123474Swpaul/* Same as above -- we don't care about the priority. */
1703123474Swpaul
1704123474Swpaul__stdcall static void
1705123474Swpaulndis_query_buf_safe(buf, vaddr, len, prio)
1706123474Swpaul	ndis_buffer		*buf;
1707123474Swpaul	void			**vaddr;
1708123474Swpaul	uint32_t		*len;
1709123474Swpaul	uint32_t		prio;
1710123474Swpaul{
1711123723Swpaul	if (vaddr != NULL)
1712123757Swpaul		*vaddr = MDL_VA(buf);
1713123474Swpaul	*len = buf->nb_bytecount;
1714123474Swpaul
1715123474Swpaul	return;
1716123474Swpaul}
1717123474Swpaul
1718123474Swpaul__stdcall static void
1719123474Swpaulndis_adjust_buflen(buf, len)
1720123474Swpaul	ndis_buffer		*buf;
1721123474Swpaul	int			len;
1722123474Swpaul{
1723123474Swpaul	buf->nb_bytecount = len;
1724123474Swpaul
1725123474Swpaul	return;
1726123474Swpaul}
1727123474Swpaul
1728123474Swpaul__stdcall static uint32_t
1729123474Swpaulndis_interlock_inc(addend)
1730123474Swpaul	uint32_t		*addend;
1731123474Swpaul{
1732123474Swpaul	mtx_lock(&ndis_interlock);
1733123474Swpaul	*addend++;
1734123474Swpaul	mtx_unlock(&ndis_interlock);
1735123474Swpaul	return(*addend);
1736123474Swpaul}
1737123474Swpaul
1738123474Swpaul__stdcall static uint32_t
1739123474Swpaulndis_interlock_dec(addend)
1740123474Swpaul	uint32_t		*addend;
1741123474Swpaul{
1742123474Swpaul	mtx_lock(&ndis_interlock);
1743123474Swpaul	*addend--;
1744123474Swpaul	mtx_unlock(&ndis_interlock);
1745123474Swpaul	return(*addend);
1746123474Swpaul}
1747123474Swpaul
1748123474Swpaul__stdcall static void
1749123474Swpaulndis_init_event(event)
1750123474Swpaul	ndis_event		*event;
1751123474Swpaul{
1752123474Swpaul	event->ne_event.nk_header.dh_sigstate = FALSE;
1753123474Swpaul	return;
1754123474Swpaul}
1755123474Swpaul
1756123474Swpaul__stdcall static void
1757123474Swpaulndis_set_event(event)
1758123474Swpaul	ndis_event		*event;
1759123474Swpaul{
1760123474Swpaul	event->ne_event.nk_header.dh_sigstate = TRUE;
1761123474Swpaul	wakeup(event);
1762123474Swpaul	return;
1763123474Swpaul}
1764123474Swpaul
1765123474Swpaul__stdcall static void
1766123474Swpaulndis_reset_event(event)
1767123474Swpaul	ndis_event		*event;
1768123474Swpaul{
1769123474Swpaul	event->ne_event.nk_header.dh_sigstate = FALSE;
1770123474Swpaul	wakeup(event);
1771123474Swpaul	return;
1772123474Swpaul}
1773123474Swpaul
1774123474Swpaul__stdcall static uint8_t
1775123474Swpaulndis_wait_event(event, msecs)
1776123474Swpaul	ndis_event		*event;
1777123474Swpaul	uint32_t		msecs;
1778123474Swpaul{
1779123474Swpaul	int			error;
1780123474Swpaul	struct timeval		tv;
1781123474Swpaul
1782123474Swpaul	if (event->ne_event.nk_header.dh_sigstate == TRUE)
1783123474Swpaul		return(TRUE);
1784123474Swpaul
1785123474Swpaul	tv.tv_sec = 0;
1786123474Swpaul	tv.tv_usec = msecs * 1000;
1787123474Swpaul
1788123474Swpaul	error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
1789123474Swpaul
1790123474Swpaul	return(event->ne_event.nk_header.dh_sigstate);
1791123474Swpaul}
1792123474Swpaul
1793123474Swpaul__stdcall static ndis_status
1794123474Swpaulndis_unicode2ansi(dstr, sstr)
1795123526Swpaul	ndis_ansi_string	*dstr;
1796123526Swpaul	ndis_unicode_string	*sstr;
1797123474Swpaul{
1798123526Swpaul	if (dstr == NULL || sstr == NULL)
1799123526Swpaul		return(NDIS_STATUS_FAILURE);
1800123526Swpaul	if (ndis_unicode_to_ascii(sstr->nus_buf,
1801123526Swpaul	    sstr->nus_len, &dstr->nas_buf))
1802123526Swpaul		return(NDIS_STATUS_FAILURE);
1803123526Swpaul	dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
1804123474Swpaul	return (NDIS_STATUS_SUCCESS);
1805123474Swpaul}
1806123474Swpaul
1807123474Swpaul__stdcall static ndis_status
1808123526Swpaulndis_ansi2unicode(dstr, sstr)
1809123526Swpaul	ndis_unicode_string	*dstr;
1810123526Swpaul	ndis_ansi_string	*sstr;
1811123526Swpaul{
1812123526Swpaul	char			*str;
1813123526Swpaul	if (dstr == NULL || sstr == NULL)
1814123526Swpaul		return(NDIS_STATUS_FAILURE);
1815123526Swpaul	str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
1816123526Swpaul	if (str == NULL)
1817123526Swpaul		return(NDIS_STATUS_FAILURE);
1818123526Swpaul	strncpy(str, sstr->nas_buf, sstr->nas_len);
1819123526Swpaul	*(str + sstr->nas_len) = '\0';
1820123526Swpaul	if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
1821123526Swpaul		free(str, M_DEVBUF);
1822123526Swpaul		return(NDIS_STATUS_FAILURE);
1823123526Swpaul	}
1824123526Swpaul	dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
1825123526Swpaul	free(str, M_DEVBUF);
1826123526Swpaul	return (NDIS_STATUS_SUCCESS);
1827123526Swpaul}
1828123526Swpaul
1829123526Swpaul__stdcall static ndis_status
1830123474Swpaulndis_assign_pcirsrc(adapter, slot, list)
1831123474Swpaul	ndis_handle		adapter;
1832123474Swpaul	uint32_t		slot;
1833123474Swpaul	ndis_resource_list	**list;
1834123474Swpaul{
1835123474Swpaul	ndis_miniport_block	*block;
1836123474Swpaul
1837123474Swpaul	if (adapter == NULL || list == NULL)
1838123474Swpaul		return (NDIS_STATUS_FAILURE);
1839123474Swpaul
1840123474Swpaul	block = (ndis_miniport_block *)adapter;
1841123474Swpaul	*list = block->nmb_rlist;
1842123474Swpaul
1843124060Swpaul	device_printf (block->nmb_dev, "assign PCI resources...\n");
1844123474Swpaul	return (NDIS_STATUS_SUCCESS);
1845123474Swpaul}
1846123474Swpaul
1847123474Swpaul__stdcall static ndis_status
1848123474Swpaulndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
1849123474Swpaul	ndis_miniport_interrupt	*intr;
1850123474Swpaul	ndis_handle		adapter;
1851123474Swpaul	uint32_t		ivec;
1852123474Swpaul	uint32_t		ilevel;
1853123474Swpaul	uint8_t			reqisr;
1854123474Swpaul	uint8_t			shared;
1855123474Swpaul	ndis_interrupt_mode	imode;
1856123474Swpaul{
1857123474Swpaul
1858123474Swpaul	return(NDIS_STATUS_SUCCESS);
1859123474Swpaul}
1860123474Swpaul
1861123474Swpaul__stdcall static void
1862123474Swpaulndis_deregister_intr(intr)
1863123474Swpaul	ndis_miniport_interrupt	*intr;
1864123474Swpaul{
1865123474Swpaul	return;
1866123474Swpaul}
1867123474Swpaul
1868123474Swpaul__stdcall static void
1869123474Swpaulndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
1870123474Swpaul	ndis_handle		adapter;
1871123474Swpaul	void			*shutdownctx;
1872123474Swpaul	ndis_shutdown_handler	shutdownfunc;
1873123474Swpaul{
1874123474Swpaul	ndis_miniport_block	*block;
1875123474Swpaul	ndis_miniport_characteristics *chars;
1876123474Swpaul	struct ndis_softc	*sc;
1877123474Swpaul
1878123474Swpaul	if (adapter == NULL)
1879123474Swpaul		return;
1880123474Swpaul
1881123474Swpaul	block = (ndis_miniport_block *)adapter;
1882123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1883123474Swpaul	chars = &sc->ndis_chars;
1884123474Swpaul
1885123474Swpaul	chars->nmc_shutdown_handler = shutdownfunc;
1886123474Swpaul	chars->nmc_rsvd0 = shutdownctx;
1887123474Swpaul
1888123474Swpaul	return;
1889123474Swpaul}
1890123474Swpaul
1891123474Swpaul__stdcall static void
1892123474Swpaulndis_deregister_shutdown(adapter)
1893123474Swpaul	ndis_handle		adapter;
1894123474Swpaul{
1895123474Swpaul	ndis_miniport_block	*block;
1896123474Swpaul	ndis_miniport_characteristics *chars;
1897123474Swpaul	struct ndis_softc	*sc;
1898123474Swpaul
1899123474Swpaul	if (adapter == NULL)
1900123474Swpaul		return;
1901123474Swpaul
1902123474Swpaul	block = (ndis_miniport_block *)adapter;
1903123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1904123474Swpaul	chars = &sc->ndis_chars;
1905123474Swpaul
1906123474Swpaul	chars->nmc_shutdown_handler = NULL;
1907123474Swpaul	chars->nmc_rsvd0 = NULL;
1908123474Swpaul
1909123474Swpaul	return;
1910123474Swpaul}
1911123474Swpaul
1912123474Swpaul__stdcall static uint32_t
1913123474Swpaulndis_numpages(buf)
1914123474Swpaul	ndis_buffer		*buf;
1915123474Swpaul{
1916123757Swpaul	if (buf == NULL)
1917123757Swpaul		return(0);
1918123512Swpaul	if (buf->nb_bytecount == 0)
1919123512Swpaul		return(1);
1920123757Swpaul	return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
1921123474Swpaul}
1922123474Swpaul
1923123474Swpaul__stdcall static void
1924123573Swpaulndis_buf_physpages(buf, pages)
1925123573Swpaul	ndis_buffer		*buf;
1926123573Swpaul	uint32_t		*pages;
1927123573Swpaul{
1928123757Swpaul	if (buf == NULL)
1929123757Swpaul		return;
1930123757Swpaul
1931123573Swpaul	*pages = ndis_numpages(buf);
1932123573Swpaul	return;
1933123573Swpaul}
1934123573Swpaul
1935123573Swpaul__stdcall static void
1936123474Swpaulndis_query_bufoffset(buf, off, len)
1937123474Swpaul	ndis_buffer		*buf;
1938123474Swpaul	uint32_t		*off;
1939123474Swpaul	uint32_t		*len;
1940123474Swpaul{
1941123757Swpaul	if (buf == NULL)
1942123757Swpaul		return;
1943123757Swpaul
1944123757Swpaul	*off = buf->nb_byteoffset;
1945123474Swpaul	*len = buf->nb_bytecount;
1946123474Swpaul
1947123474Swpaul	return;
1948123474Swpaul}
1949123474Swpaul
1950123474Swpaul__stdcall static void
1951123474Swpaulndis_sleep(usecs)
1952123474Swpaul	uint32_t		usecs;
1953123474Swpaul{
1954123474Swpaul	struct timeval		tv;
1955123474Swpaul	uint32_t		dummy;
1956123474Swpaul
1957123474Swpaul	tv.tv_sec = 0;
1958123474Swpaul	tv.tv_usec = usecs;
1959123474Swpaul
1960123474Swpaul	tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
1961123474Swpaul	return;
1962123474Swpaul}
1963123474Swpaul
1964123474Swpaul__stdcall static uint32_t
1965123474Swpaulndis_read_pccard_amem(handle, offset, buf, len)
1966123474Swpaul	ndis_handle		handle;
1967123474Swpaul	uint32_t		offset;
1968123474Swpaul	void			*buf;
1969123474Swpaul	uint32_t		len;
1970123474Swpaul{
1971123474Swpaul	struct ndis_softc	*sc;
1972123474Swpaul	ndis_miniport_block	*block;
1973123474Swpaul	bus_space_handle_t	bh;
1974123474Swpaul	bus_space_tag_t		bt;
1975123474Swpaul	char			*dest;
1976123474Swpaul	int			i;
1977123474Swpaul
1978123474Swpaul	if (handle == NULL)
1979123474Swpaul		return(0);
1980123474Swpaul
1981123474Swpaul	block = (ndis_miniport_block *)handle;
1982123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1983123474Swpaul	dest = buf;
1984123474Swpaul
1985123474Swpaul	bh = rman_get_bushandle(sc->ndis_res_am);
1986123474Swpaul	bt = rman_get_bustag(sc->ndis_res_am);
1987123474Swpaul
1988123474Swpaul	for (i = 0; i < len; i++)
1989123474Swpaul		dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2));
1990123474Swpaul
1991123474Swpaul	return(i);
1992123474Swpaul}
1993123474Swpaul
1994123474Swpaul__stdcall static uint32_t
1995123474Swpaulndis_write_pccard_amem(handle, offset, buf, len)
1996123474Swpaul	ndis_handle		handle;
1997123474Swpaul	uint32_t		offset;
1998123474Swpaul	void			*buf;
1999123474Swpaul	uint32_t		len;
2000123474Swpaul{
2001123474Swpaul	struct ndis_softc	*sc;
2002123474Swpaul	ndis_miniport_block	*block;
2003123474Swpaul	bus_space_handle_t	bh;
2004123474Swpaul	bus_space_tag_t		bt;
2005123474Swpaul	char			*src;
2006123474Swpaul	int			i;
2007123474Swpaul
2008123474Swpaul	if (handle == NULL)
2009123474Swpaul		return(0);
2010123474Swpaul
2011123474Swpaul	block = (ndis_miniport_block *)handle;
2012123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
2013123474Swpaul	src = buf;
2014123474Swpaul
2015123474Swpaul	bh = rman_get_bushandle(sc->ndis_res_am);
2016123474Swpaul	bt = rman_get_bustag(sc->ndis_res_am);
2017123474Swpaul
2018123474Swpaul	for (i = 0; i < len; i++)
2019123474Swpaul		bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]);
2020123474Swpaul
2021123474Swpaul	return(i);
2022123474Swpaul}
2023123474Swpaul
2024123474Swpaul__stdcall static ndis_list_entry *
2025123474Swpaulndis_insert_head(head, entry, lock)
2026123474Swpaul	ndis_list_entry		*head;
2027123474Swpaul	ndis_list_entry		*entry;
2028123474Swpaul	ndis_spin_lock		*lock;
2029123474Swpaul{
2030123474Swpaul	ndis_list_entry		*flink;
2031123474Swpaul
2032123474Swpaul	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
2033123474Swpaul	flink = head->nle_flink;
2034123474Swpaul	entry->nle_flink = flink;
2035123474Swpaul	entry->nle_blink = head;
2036123474Swpaul	flink->nle_blink = entry;
2037123474Swpaul	head->nle_flink = entry;
2038123474Swpaul	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
2039123474Swpaul
2040123474Swpaul	return(flink);
2041123474Swpaul}
2042123474Swpaul
2043123474Swpaul__stdcall static ndis_list_entry *
2044123474Swpaulndis_remove_head(head, lock)
2045123474Swpaul	ndis_list_entry		*head;
2046123474Swpaul	ndis_spin_lock		*lock;
2047123474Swpaul{
2048123474Swpaul	ndis_list_entry		*flink;
2049123474Swpaul	ndis_list_entry		*entry;
2050123474Swpaul
2051123474Swpaul	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
2052123474Swpaul	entry = head->nle_flink;
2053123474Swpaul	flink = entry->nle_flink;
2054123474Swpaul	head->nle_flink = flink;
2055123474Swpaul	flink->nle_blink = head;
2056123474Swpaul	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
2057123474Swpaul
2058123474Swpaul	return(entry);
2059123474Swpaul}
2060123474Swpaul
2061123474Swpaul__stdcall static ndis_list_entry *
2062123474Swpaulndis_insert_tail(head, entry, lock)
2063123474Swpaul	ndis_list_entry		*head;
2064123474Swpaul	ndis_list_entry		*entry;
2065123474Swpaul	ndis_spin_lock		*lock;
2066123474Swpaul{
2067123474Swpaul	ndis_list_entry		*blink;
2068123474Swpaul
2069123474Swpaul	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
2070123474Swpaul	blink = head->nle_blink;
2071123474Swpaul	entry->nle_flink = head;
2072123474Swpaul	entry->nle_blink = blink;
2073123474Swpaul	blink->nle_flink = entry;
2074123474Swpaul	head->nle_blink = entry;
2075123474Swpaul	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
2076123474Swpaul
2077123474Swpaul	return(blink);
2078123474Swpaul}
2079123474Swpaul
2080123474Swpaul__stdcall static uint8_t
2081123474Swpaulndis_sync_with_intr(intr, syncfunc, syncctx)
2082123474Swpaul	ndis_miniport_interrupt	*intr;
2083123474Swpaul	void			*syncfunc;
2084123474Swpaul	void			*syncctx;
2085123474Swpaul{
2086123474Swpaul	__stdcall uint8_t (*sync)(void *);
2087123474Swpaul
2088123474Swpaul	if (syncfunc == NULL || syncctx == NULL)
2089123474Swpaul		return(0);
2090123474Swpaul
2091123474Swpaul	sync = syncfunc;
2092123474Swpaul	return(sync(syncctx));
2093123474Swpaul}
2094123474Swpaul
2095123504Swpaul/*
2096123504Swpaul * Return the number of 100 nanosecond intervals since
2097123504Swpaul * January 1, 1601. (?!?!)
2098123504Swpaul */
2099123474Swpaul__stdcall static void
2100123504Swpaulndis_time(tval)
2101123504Swpaul	uint64_t		*tval;
2102123504Swpaul{
2103123504Swpaul	struct timespec		ts;
2104123822Swpaul
2105123504Swpaul	nanotime(&ts);
2106123822Swpaul	*tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2107123822Swpaul	    11644473600;
2108123504Swpaul}
2109123504Swpaul
2110123822Swpaul/*
2111123822Swpaul * Return the number of milliseconds since the system booted.
2112123822Swpaul */
2113123504Swpaul__stdcall static void
2114123822Swpaulndis_uptime(tval)
2115123822Swpaul	uint32_t		*tval;
2116123822Swpaul{
2117123822Swpaul	struct timespec		ts;
2118123822Swpaul
2119123822Swpaul	nanouptime(&ts);
2120123822Swpaul	*tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
2121123822Swpaul}
2122123822Swpaul
2123123822Swpaul__stdcall static void
2124123507Swpaulndis_init_string(dst, src)
2125123507Swpaul	ndis_unicode_string	**dst;
2126123507Swpaul	char			*src;
2127123507Swpaul{
2128123507Swpaul	ndis_unicode_string	*u;
2129123507Swpaul
2130123507Swpaul	u = malloc(sizeof(ndis_unicode_string), M_DEVBUF, M_NOWAIT);
2131123507Swpaul	if (u == NULL)
2132123507Swpaul		return;
2133123507Swpaul	u->nus_buf = NULL;
2134123507Swpaul	if (ndis_ascii_to_unicode(src, &u->nus_buf)) {
2135123507Swpaul		free(u, M_DEVBUF);
2136123507Swpaul		return;
2137123507Swpaul	}
2138123507Swpaul	u->nus_len = u->nus_maxlen = strlen(src) * 2;
2139123507Swpaul	return;
2140123507Swpaul}
2141123507Swpaul
2142123507Swpaul__stdcall static void
2143123507Swpaulndis_free_string(str)
2144123507Swpaul	ndis_unicode_string	*str;
2145123507Swpaul{
2146123507Swpaul	if (str == NULL)
2147123507Swpaul		return;
2148123507Swpaul	if (str->nus_buf != NULL)
2149123507Swpaul		free(str->nus_buf, M_DEVBUF);
2150123507Swpaul	free(str, M_DEVBUF);
2151123507Swpaul	return;
2152123507Swpaul}
2153123507Swpaul
2154123507Swpaul__stdcall static ndis_status
2155123507Swpaulndis_remove_miniport(adapter)
2156123507Swpaul	ndis_handle		*adapter;
2157123507Swpaul{
2158123507Swpaul	return(NDIS_STATUS_SUCCESS);
2159123507Swpaul}
2160123507Swpaul
2161123507Swpaul__stdcall static void
2162123526Swpaulndis_init_ansi_string(dst, src)
2163123526Swpaul	ndis_ansi_string	*dst;
2164123526Swpaul	char			*src;
2165123526Swpaul{
2166123526Swpaul	ndis_ansi_string	*a;
2167123526Swpaul
2168123526Swpaul	a = dst;
2169123526Swpaul	if (a == NULL)
2170123526Swpaul		return;
2171123526Swpaul	if (src == NULL) {
2172123526Swpaul		a->nas_len = a->nas_maxlen = 0;
2173123526Swpaul		a->nas_buf = NULL;
2174123526Swpaul	} else {
2175123526Swpaul		a->nas_buf = src;
2176123526Swpaul		a->nas_len = a->nas_maxlen = strlen(src);
2177123526Swpaul	}
2178123526Swpaul
2179123526Swpaul	return;
2180123526Swpaul}
2181123526Swpaul
2182123941Swpaul__stdcall static void
2183123941Swpaulndis_init_unicode_string(dst, src)
2184123941Swpaul	ndis_unicode_string	*dst;
2185123941Swpaul	uint16_t		*src;
2186123941Swpaul{
2187123941Swpaul	ndis_unicode_string	*u;
2188123941Swpaul	int			i;
2189123941Swpaul
2190123941Swpaul	u = dst;
2191123941Swpaul	if (u == NULL)
2192123941Swpaul		return;
2193123941Swpaul	if (src == NULL) {
2194123941Swpaul		u->nus_len = u->nus_maxlen = 0;
2195123941Swpaul		u->nus_buf = NULL;
2196123941Swpaul	} else {
2197123941Swpaul		i = 0;
2198123941Swpaul		while(src[i] != 0)
2199123941Swpaul			i++;
2200123941Swpaul		u->nus_buf = src;
2201123941Swpaul		u->nus_len = u->nus_maxlen = i * 2;
2202123941Swpaul	}
2203123941Swpaul
2204123941Swpaul	return;
2205123941Swpaul}
2206123941Swpaul
2207123526Swpaul__stdcall static void ndis_get_devprop(adapter, phydevobj,
2208123526Swpaul	funcdevobj, nextdevobj, resources, transresources)
2209123526Swpaul	ndis_handle		adapter;
2210123526Swpaul	void			*phydevobj;
2211123526Swpaul	void			*funcdevobj;
2212123526Swpaul	void			*nextdevobj;
2213123526Swpaul	cm_resource_list	*resources;
2214123526Swpaul	cm_resource_list	*transresources;
2215123526Swpaul{
2216123526Swpaul	return;
2217123526Swpaul}
2218123526Swpaul
2219123526Swpaul__stdcall static void
2220123721Swpaulndis_firstbuf(packet, buf, firstva, firstlen, totlen)
2221123721Swpaul	ndis_packet		*packet;
2222123721Swpaul	ndis_buffer		**buf;
2223123721Swpaul	void			**firstva;
2224123721Swpaul	uint32_t		*firstlen;
2225123721Swpaul	uint32_t		*totlen;
2226123721Swpaul{
2227123721Swpaul	ndis_buffer		*tmp;
2228123721Swpaul
2229123721Swpaul	tmp = packet->np_private.npp_head;
2230123721Swpaul	*buf = tmp;
2231123721Swpaul	if (tmp == NULL) {
2232123721Swpaul		*firstva = NULL;
2233123721Swpaul		*firstlen = *totlen = 0;
2234123721Swpaul	} else {
2235123757Swpaul		*firstva = MDL_VA(tmp);
2236123721Swpaul		*firstlen = *totlen = tmp->nb_bytecount;
2237123721Swpaul		for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
2238123721Swpaul			*totlen += tmp->nb_bytecount;
2239123721Swpaul	}
2240123721Swpaul
2241123721Swpaul	return;
2242123721Swpaul}
2243123721Swpaul
2244123721Swpaul__stdcall static void
2245123721Swpaulndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio)
2246123721Swpaul	ndis_packet		*packet;
2247123721Swpaul	ndis_buffer		**buf;
2248123721Swpaul	void			**firstva;
2249123721Swpaul	uint32_t		*firstlen;
2250123721Swpaul	uint32_t		*totlen;
2251123721Swpaul	uint32_t		prio;
2252123721Swpaul{
2253123721Swpaul	ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
2254123721Swpaul}
2255123721Swpaul
2256123822Swpaul/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2257123721Swpaul__stdcall static void
2258123822Swpaulndis_open_file(status, filehandle, filelength, filename, highestaddr)
2259123822Swpaul	ndis_status		*status;
2260123822Swpaul	ndis_handle		*filehandle;
2261123822Swpaul	uint32_t		*filelength;
2262123822Swpaul	ndis_unicode_string	*filename;
2263123822Swpaul	ndis_physaddr		highestaddr;
2264123822Swpaul{
2265123822Swpaul	char			*afilename = NULL;
2266123822Swpaul
2267123822Swpaul	ndis_unicode_to_ascii(filename->nus_buf, filename->nus_len, &afilename);
2268123822Swpaul	printf("ndis_open_file(\"%s\", %ju)\n", afilename,
2269123822Swpaul	    highestaddr.np_quad);
2270123822Swpaul	free(afilename, M_DEVBUF);
2271123822Swpaul	*status = NDIS_STATUS_FILE_NOT_FOUND;
2272123822Swpaul	return;
2273123822Swpaul}
2274123822Swpaul
2275123822Swpaul__stdcall static void
2276123822Swpaulndis_map_file(status, mappedbuffer, filehandle)
2277123822Swpaul	ndis_status		*status;
2278123822Swpaul	void			**mappedbuffer;
2279123822Swpaul	ndis_handle		filehandle;
2280123822Swpaul{
2281123822Swpaul
2282123822Swpaul	*status = NDIS_STATUS_ALREADY_MAPPED;
2283123822Swpaul	return;
2284123822Swpaul}
2285123822Swpaul
2286123822Swpaul__stdcall static void
2287123822Swpaulndis_unmap_file(filehandle)
2288123822Swpaul	ndis_handle		filehandle;
2289123822Swpaul{
2290123822Swpaul	return;
2291123822Swpaul}
2292123822Swpaul
2293123822Swpaul__stdcall static void
2294123822Swpaulndis_close_file(filehandle)
2295123822Swpaul	ndis_handle		filehandle;
2296123822Swpaul{
2297123822Swpaul	return;
2298123822Swpaul}
2299123822Swpaul
2300123848Swpaul__stdcall static uint8_t
2301123848Swpaulndis_cpu_cnt()
2302123848Swpaul{
2303123848Swpaul#ifdef SMP
2304123848Swpaul	return(mp_ncpus);
2305123848Swpaul#else
2306123848Swpaul	return(1);
2307123848Swpaul#endif
2308123848Swpaul};
2309123848Swpaul
2310123822Swpaul__stdcall static void
2311123474Swpauldummy()
2312123474Swpaul{
2313123474Swpaul	printf ("NDIS dummy called...\n");
2314123474Swpaul	return;
2315123474Swpaul}
2316123474Swpaul
2317123474Swpaulimage_patch_table ndis_functbl[] = {
2318123848Swpaul	{ "NdisSystemProcessorCount",	(FUNC)ndis_cpu_cnt },
2319123721Swpaul	{ "NdisUnchainBufferAtBack",	(FUNC)ndis_unchain_tailbuf, },
2320123721Swpaul	{ "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf },
2321123721Swpaul	{ "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe },
2322123573Swpaul	{ "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2323123526Swpaul	{ "NdisMGetDeviceProperty",	(FUNC)ndis_get_devprop },
2324123526Swpaul	{ "NdisInitAnsiString",		(FUNC)ndis_init_ansi_string },
2325123941Swpaul	{ "NdisInitUnicodeString",	(FUNC)ndis_init_unicode_string },
2326123526Swpaul	{ "NdisWriteConfiguration",	(FUNC)ndis_write_cfg },
2327123526Swpaul	{ "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2328123526Swpaul	{ "NdisTerminateWrapper",	(FUNC)ndis_termwrap },
2329123526Swpaul	{ "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2330123526Swpaul	{ "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2331123507Swpaul	{ "NdisMRemoveMiniport",	(FUNC)ndis_remove_miniport },
2332123507Swpaul	{ "NdisInitializeString",	(FUNC)ndis_init_string },
2333123507Swpaul	{ "NdisFreeString",		(FUNC)ndis_free_string },
2334123504Swpaul	{ "NdisGetCurrentSystemTime",	(FUNC)ndis_time },
2335123822Swpaul	{ "NdisGetSystemUpTime",	(FUNC)ndis_uptime },
2336123474Swpaul	{ "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2337123474Swpaul	{ "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2338123474Swpaul	{ "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2339123474Swpaul	{ "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2340123474Swpaul	{ "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2341123474Swpaul	{ "NdisInitializeWrapper",	(FUNC)ndis_initwrap },
2342123474Swpaul	{ "NdisMRegisterMiniport",	(FUNC)ndis_register_miniport },
2343123474Swpaul	{ "NdisAllocateMemoryWithTag",	(FUNC)ndis_malloc_withtag },
2344123474Swpaul	{ "NdisAllocateMemory",		(FUNC)ndis_malloc },
2345123474Swpaul	{ "NdisMSetAttributesEx",	(FUNC)ndis_setattr_ex },
2346123474Swpaul	{ "NdisCloseConfiguration",	(FUNC)ndis_close_cfg },
2347123474Swpaul	{ "NdisReadConfiguration",	(FUNC)ndis_read_cfg },
2348123474Swpaul	{ "NdisOpenConfiguration",	(FUNC)ndis_open_cfg },
2349123474Swpaul	{ "NdisReleaseSpinLock",	(FUNC)ndis_unlock },
2350123474Swpaul	{ "NdisDprAcquireSpinLock",	(FUNC)ndis_lock },
2351123474Swpaul	{ "NdisDprReleaseSpinLock",	(FUNC)ndis_unlock },
2352123474Swpaul	{ "NdisAcquireSpinLock",	(FUNC)ndis_lock },
2353123474Swpaul	{ "NdisAllocateSpinLock",	(FUNC)ndis_create_lock },
2354123474Swpaul	{ "NdisFreeSpinLock",		(FUNC)ndis_destroy_lock },
2355123474Swpaul	{ "NdisFreeMemory",		(FUNC)ndis_free },
2356123474Swpaul	{ "NdisReadPciSlotInformation",	(FUNC)ndis_read_pci },
2357123474Swpaul	{ "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2358123474Swpaul	{ "NdisWriteErrorLogEntry",	(FUNC)ndis_syslog },
2359123474Swpaul	{ "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2360123474Swpaul	{ "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2361123474Swpaul	{ "NdisMInitializeTimer",	(FUNC)ndis_create_timer },
2362123474Swpaul	{ "NdisSetTimer",		(FUNC)ndis_set_timer },
2363123474Swpaul	{ "NdisMCancelTimer",		(FUNC)ndis_cancel_timer },
2364123474Swpaul	{ "NdisMSetPeriodicTimer",	(FUNC)ndis_set_periodic_timer },
2365123474Swpaul	{ "NdisMQueryAdapterResources",	(FUNC)ndis_query_resources },
2366123474Swpaul	{ "NdisMRegisterIoPortRange",	(FUNC)ndis_register_ioport },
2367123474Swpaul	{ "NdisMDeregisterIoPortRange",	(FUNC)ndis_deregister_ioport },
2368123474Swpaul	{ "NdisReadNetworkAddress",	(FUNC)ndis_read_netaddr },
2369123848Swpaul	{ "NdisQueryMapRegisterCount",	(FUNC)ndis_mapreg_cnt },
2370123474Swpaul	{ "NdisMAllocateMapRegisters",	(FUNC)ndis_alloc_mapreg },
2371123848Swpaul	{ "NdisMFreeMapRegisters",	(FUNC)ndis_free_mapreg },
2372123474Swpaul	{ "NdisMAllocateSharedMemory",	(FUNC)ndis_alloc_sharedmem },
2373123474Swpaul	{ "NdisMMapIoSpace",		(FUNC)ndis_map_iospace },
2374123474Swpaul	{ "NdisMUnmapIoSpace",		(FUNC)ndis_unmap_iospace },
2375123474Swpaul	{ "NdisGetCacheFillSize",	(FUNC)ndis_cachefill },
2376123474Swpaul	{ "NdisMGetDmaAlignment",	(FUNC)ndis_dma_align },
2377123474Swpaul	{ "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2378123474Swpaul	{ "NdisAllocatePacketPool",	(FUNC)ndis_alloc_packetpool },
2379123474Swpaul	{ "NdisAllocatePacketPoolEx",	(FUNC)ndis_ex_alloc_packetpool },
2380123474Swpaul	{ "NdisAllocatePacket",		(FUNC)ndis_alloc_packet },
2381123474Swpaul	{ "NdisFreePacket",		(FUNC)ndis_release_packet },
2382123474Swpaul	{ "NdisFreePacketPool",		(FUNC)ndis_free_packetpool },
2383124097Swpaul	{ "NdisDprAllocatePacket",	(FUNC)ndis_alloc_packet },
2384124097Swpaul	{ "NdisDprFreePacket",		(FUNC)ndis_release_packet },
2385123474Swpaul	{ "NdisAllocateBufferPool",	(FUNC)ndis_alloc_bufpool },
2386123474Swpaul	{ "NdisAllocateBuffer",		(FUNC)ndis_alloc_buf },
2387123474Swpaul	{ "NdisQueryBuffer",		(FUNC)ndis_query_buf },
2388123474Swpaul	{ "NdisQueryBufferSafe",	(FUNC)ndis_query_buf_safe },
2389123474Swpaul	{ "NdisFreeBuffer",		(FUNC)ndis_release_buf },
2390123474Swpaul	{ "NdisFreeBufferPool",		(FUNC)ndis_free_bufpool },
2391123474Swpaul	{ "NdisInterlockedIncrement",	(FUNC)ndis_interlock_inc },
2392123474Swpaul	{ "NdisInterlockedDecrement",	(FUNC)ndis_interlock_dec },
2393123474Swpaul	{ "NdisInitializeEvent",	(FUNC)ndis_init_event },
2394123474Swpaul	{ "NdisSetEvent",		(FUNC)ndis_set_event },
2395123474Swpaul	{ "NdisResetEvent",		(FUNC)ndis_reset_event },
2396123474Swpaul	{ "NdisWaitEvent",		(FUNC)ndis_wait_event },
2397123474Swpaul	{ "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2398123474Swpaul	{ "NdisMPciAssignResources",	(FUNC)ndis_assign_pcirsrc },
2399123474Swpaul	{ "NdisMFreeSharedMemory",	(FUNC)ndis_free_sharedmem },
2400123474Swpaul	{ "NdisMRegisterInterrupt",	(FUNC)ndis_register_intr },
2401123474Swpaul	{ "NdisMDeregisterInterrupt",	(FUNC)ndis_deregister_intr },
2402123474Swpaul	{ "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2403123474Swpaul	{ "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
2404123474Swpaul	{ "NDIS_BUFFER_TO_SPAN_PAGES",	(FUNC)ndis_numpages },
2405123474Swpaul	{ "NdisQueryBufferOffset",	(FUNC)ndis_query_bufoffset },
2406123474Swpaul	{ "NdisAdjustBufferLength",	(FUNC)ndis_adjust_buflen },
2407123474Swpaul	{ "NdisPacketPoolUsage",	(FUNC)ndis_packetpool_use },
2408123474Swpaul	{ "NdisMSleep",			(FUNC)ndis_sleep },
2409123474Swpaul	{ "NdisUnchainBufferAtFront",	(FUNC)ndis_unchain_headbuf },
2410123474Swpaul	{ "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
2411123474Swpaul	{ "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
2412123822Swpaul	{ "NdisOpenFile",		(FUNC)ndis_open_file },
2413123822Swpaul	{ "NdisMapFile",		(FUNC)ndis_map_file },
2414123822Swpaul	{ "NdisUnmapFile",		(FUNC)ndis_unmap_file },
2415123822Swpaul	{ "NdisCloseFile",		(FUNC)ndis_close_file },
2416123474Swpaul
2417123474Swpaul	/*
2418123474Swpaul	 * This last entry is a catch-all for any function we haven't
2419123474Swpaul	 * implemented yet. The PE import list patching routine will
2420123474Swpaul	 * use it for any function that doesn't have an explicit match
2421123474Swpaul	 * in this table.
2422123474Swpaul	 */
2423123474Swpaul
2424123474Swpaul	{ NULL, (FUNC)dummy },
2425123474Swpaul
2426123474Swpaul	/* End of list. */
2427123474Swpaul
2428123474Swpaul	{ NULL, NULL },
2429123474Swpaul};
2430