subr_ndis.c revision 123504
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 123504 2003-12-12 22:35:13Z 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>
65123474Swpaul
66123474Swpaul#include <net/if.h>
67123474Swpaul#include <net/if_arp.h>
68123474Swpaul#include <net/ethernet.h>
69123474Swpaul#include <net/if_dl.h>
70123474Swpaul#include <net/if_media.h>
71123474Swpaul
72123474Swpaul#include <machine/bus_memio.h>
73123474Swpaul#include <machine/bus_pio.h>
74123474Swpaul#include <machine/bus.h>
75123474Swpaul#include <machine/resource.h>
76123474Swpaul
77123474Swpaul#include <sys/bus.h>
78123474Swpaul#include <sys/rman.h>
79123474Swpaul
80123474Swpaul#include <machine/stdarg.h>
81123474Swpaul
82123474Swpaul#include <dev/pci/pcireg.h>
83123474Swpaul#include <dev/pci/pcivar.h>
84123474Swpaul
85123474Swpaul#include <compat/ndis/pe_var.h>
86123474Swpaul#include <compat/ndis/resource_var.h>
87123474Swpaul#include <compat/ndis/ndis_var.h>
88123474Swpaul#include <compat/ndis/cfg_var.h>
89123474Swpaul#include <dev/if_ndis/if_ndisvar.h>
90123474Swpaul
91123474Swpaul#define __stdcall __attribute__((__stdcall__))
92123474Swpaul#define FUNC void(*)(void)
93123474Swpaul
94123474Swpaulstatic struct mtx ndis_interlock;
95123474Swpaulstatic int ndis_inits = 0;
96123474Swpaul
97123474Swpaul__stdcall static void ndis_initwrap(ndis_handle,
98123474Swpaul	ndis_driver_object *, void *, void *);
99123474Swpaul__stdcall static ndis_status ndis_register_miniport(ndis_handle,
100123474Swpaul	ndis_miniport_characteristics *, int);
101123474Swpaul__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
102123474Swpaul__stdcall static ndis_status ndis_malloc(void **,
103123474Swpaul	uint32_t, uint32_t, ndis_physaddr);
104123474Swpaul__stdcall static void ndis_free(void *, uint32_t, uint32_t);
105123474Swpaul__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
106123474Swpaul	uint32_t, uint32_t, ndis_interface_type);
107123474Swpaul__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
108123474Swpaulstatic ndis_status ndis_encode_parm(ndis_miniport_block *,
109123474Swpaul	struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
110123474Swpaul__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
111123474Swpaul	ndis_handle, ndis_unicode_string *, ndis_parm_type);
112123474Swpaul__stdcall static void ndis_close_cfg(ndis_handle);
113123474Swpaul__stdcall static void ndis_create_lock(ndis_spin_lock *);
114123474Swpaul__stdcall static void ndis_destroy_lock(ndis_spin_lock *);
115123474Swpaul__stdcall static void ndis_lock(ndis_spin_lock *);
116123474Swpaul__stdcall static void ndis_unlock(ndis_spin_lock *);
117123474Swpaul__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
118123474Swpaul	uint32_t, void *, uint32_t);
119123474Swpaul__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
120123474Swpaul	uint32_t, void *, uint32_t);
121123474Swpaulstatic void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
122123474Swpaulstatic void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
123123474Swpaul__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
124123474Swpaul	uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
125123474Swpaul__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
126123474Swpaul__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *,
127123474Swpaul	ndis_timer_function, void *);
128123474Swpaulstatic void ndis_timercall(void *);
129123474Swpaul__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t);
130123474Swpaulstatic void ndis_tick(void *);
131123474Swpaul__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
132123474Swpaul__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *);
133123474Swpaul__stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
134123474Swpaul	ndis_resource_list *, uint32_t *);
135123474Swpaul__stdcall static ndis_status ndis_register_ioport(void **,
136123474Swpaul	ndis_handle, uint32_t, uint32_t);
137123474Swpaul__stdcall static void ndis_deregister_ioport(ndis_handle,
138123474Swpaul	uint32_t, uint32_t, void *);
139123474Swpaul__stdcall static void ndis_read_netaddr(ndis_status *, void **,
140123474Swpaul	uint32_t *, ndis_handle);
141123474Swpaul__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
142123474Swpaul	uint32_t, uint8_t, uint32_t, uint32_t);
143123474Swpaul__stdcall static void ndis_free_mapreg(ndis_handle);
144123474Swpaulstatic void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
145123474Swpaul__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
146123474Swpaul	uint8_t, void **, ndis_physaddr *);
147123474Swpaul__stdcall static void ndis_alloc_sharedmem_async(ndis_handle,
148123474Swpaul	uint32_t, uint8_t, void *);
149123474Swpaul__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
150123474Swpaul	uint8_t, void *, ndis_physaddr);
151123474Swpaul__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
152123474Swpaul	ndis_physaddr, uint32_t);
153123474Swpaul__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
154123474Swpaul__stdcall static uint32_t ndis_cachefill(void);
155123474Swpaul__stdcall static uint32_t ndis_dma_align(ndis_handle);
156123474Swpaul__stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
157123474Swpaul	uint8_t, uint32_t);
158123474Swpaul__stdcall static void ndis_alloc_packetpool(ndis_status *,
159123474Swpaul	ndis_handle *, uint32_t, uint32_t);
160123474Swpaul__stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
161123474Swpaul	ndis_handle *, uint32_t, uint32_t, uint32_t);
162123474Swpaul__stdcall static uint32_t ndis_packetpool_use(ndis_handle);
163123474Swpaul__stdcall static void ndis_free_packetpool(ndis_handle);
164123474Swpaul__stdcall static void ndis_alloc_packet(ndis_status *,
165123474Swpaul	ndis_packet **, ndis_handle);
166123474Swpaul__stdcall static void ndis_release_packet(ndis_packet *);
167123474Swpaul__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
168123474Swpaul__stdcall static void ndis_alloc_bufpool(ndis_status *,
169123474Swpaul	ndis_handle *, uint32_t);
170123474Swpaul__stdcall static void ndis_free_bufpool(ndis_handle);
171123474Swpaul__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
172123474Swpaul	ndis_handle, void *, uint32_t);
173123474Swpaul__stdcall static void ndis_release_buf(ndis_buffer *);
174123474Swpaul__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
175123474Swpaul__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
176123474Swpaul	uint32_t *, uint32_t);
177123474Swpaul__stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
178123474Swpaul__stdcall static uint32_t ndis_interlock_inc(uint32_t *);
179123474Swpaul__stdcall static uint32_t ndis_interlock_dec(uint32_t *);
180123474Swpaul__stdcall static void ndis_init_event(ndis_event *);
181123474Swpaul__stdcall static void ndis_set_event(ndis_event *);
182123474Swpaul__stdcall static void ndis_reset_event(ndis_event *);
183123474Swpaul__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
184123474Swpaul__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
185123474Swpaul	ndis_unicode_string *);
186123474Swpaul__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
187123474Swpaul	uint32_t, ndis_resource_list **);
188123474Swpaul__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
189123474Swpaul	ndis_handle, uint32_t, uint32_t, uint8_t,
190123474Swpaul	uint8_t, ndis_interrupt_mode);
191123474Swpaul__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
192123474Swpaul__stdcall static void ndis_register_shutdown(ndis_handle, void *,
193123474Swpaul	ndis_shutdown_handler);
194123474Swpaul__stdcall static void ndis_deregister_shutdown(ndis_handle);
195123474Swpaul__stdcall static uint32_t ndis_numpages(ndis_buffer *);
196123474Swpaul__stdcall static void ndis_query_bufoffset(ndis_buffer *,
197123474Swpaul	uint32_t *, uint32_t *);
198123474Swpaul__stdcall static void ndis_sleep(uint32_t);
199123474Swpaul__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
200123474Swpaul	uint32_t, void *, uint32_t);
201123474Swpaul__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
202123474Swpaul	uint32_t, void *, uint32_t);
203123474Swpaul__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *,
204123474Swpaul	ndis_list_entry *, ndis_spin_lock *);
205123474Swpaul__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *,
206123474Swpaul	ndis_spin_lock *);
207123474Swpaul__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *,
208123474Swpaul	ndis_list_entry *, ndis_spin_lock *);
209123474Swpaul__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
210123474Swpaul	void *, void *);
211123504Swpaul__stdcall static void ndis_time(uint64_t *);
212123474Swpaul__stdcall static void dummy(void);
213123474Swpaul
214123474Swpaul
215123474Swpaulint
216123474Swpaulndis_libinit()
217123474Swpaul{
218123474Swpaul	if (ndis_inits) {
219123474Swpaul		ndis_inits++;
220123474Swpaul		return(0);
221123474Swpaul	}
222123474Swpaul
223123474Swpaul	mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK,
224123474Swpaul	    MTX_DEF | MTX_RECURSE | MTX_DUPOK);
225123474Swpaul
226123474Swpaul	ndis_inits++;
227123474Swpaul	return(0);
228123474Swpaul}
229123474Swpaul
230123474Swpaulint
231123474Swpaulndis_libfini()
232123474Swpaul{
233123474Swpaul	if (ndis_inits != 1) {
234123474Swpaul		ndis_inits--;
235123474Swpaul		return(0);
236123474Swpaul	}
237123474Swpaul
238123474Swpaul	mtx_destroy(&ndis_interlock);
239123474Swpaul	ndis_inits--;
240123474Swpaul
241123474Swpaul	return(0);
242123474Swpaul}
243123474Swpaul
244123474Swpaul/*
245123474Swpaul * NDIS deals with strings in unicode format, so we have
246123474Swpaul * do deal with them that way too. For now, we only handle
247123474Swpaul * conversion between unicode and ASCII since that's all
248123474Swpaul * that device drivers care about.
249123474Swpaul */
250123474Swpaul
251123474Swpaulint
252123474Swpaulndis_ascii_to_unicode(ascii, unicode)
253123474Swpaul	char			*ascii;
254123474Swpaul	uint16_t		**unicode;
255123474Swpaul{
256123474Swpaul	uint16_t		*ustr;
257123474Swpaul	int			i;
258123474Swpaul
259123474Swpaul	if (*unicode == NULL)
260123474Swpaul		*unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
261123474Swpaul
262123474Swpaul	if (*unicode == NULL)
263123474Swpaul		return(ENOMEM);
264123474Swpaul	ustr = *unicode;
265123474Swpaul	for (i = 0; i < strlen(ascii); i++) {
266123474Swpaul		*ustr = (uint16_t)ascii[i];
267123474Swpaul		ustr++;
268123474Swpaul	}
269123474Swpaul
270123474Swpaul	return(0);
271123474Swpaul}
272123474Swpaul
273123474Swpaulint
274123474Swpaulndis_unicode_to_ascii(unicode, ulen, ascii)
275123474Swpaul	uint16_t		*unicode;
276123474Swpaul	int			ulen;
277123474Swpaul	char			**ascii;
278123474Swpaul{
279123474Swpaul	uint8_t			*astr;
280123474Swpaul	int			i;
281123474Swpaul
282123474Swpaul	if (*ascii == NULL)
283123474Swpaul		*ascii = malloc(ulen, M_DEVBUF, M_WAITOK);
284123474Swpaul
285123474Swpaul	if (*ascii == NULL)
286123474Swpaul		return(ENOMEM);
287123474Swpaul	astr = *ascii;
288123474Swpaul	for (i = 0; i < ulen; i++) {
289123474Swpaul		*astr = (uint8_t)unicode[i];
290123474Swpaul		astr++;
291123474Swpaul	}
292123474Swpaul
293123474Swpaul	return(0);
294123474Swpaul}
295123474Swpaul
296123474Swpaul__stdcall static void
297123474Swpaulndis_initwrap(wrapper, drv_obj, path, unused)
298123474Swpaul	ndis_handle		wrapper;
299123474Swpaul	ndis_driver_object	*drv_obj;
300123474Swpaul	void			*path;
301123474Swpaul	void			*unused;
302123474Swpaul{
303123474Swpaul	ndis_driver_object	**drv;
304123474Swpaul
305123474Swpaul	drv = wrapper;
306123474Swpaul	*drv = drv_obj;
307123474Swpaul
308123474Swpaul	return;
309123474Swpaul}
310123474Swpaul
311123474Swpaul__stdcall static ndis_status
312123474Swpaulndis_register_miniport(handle, characteristics, len)
313123474Swpaul	ndis_handle		handle;
314123474Swpaul	ndis_miniport_characteristics *characteristics;
315123474Swpaul	int			len;
316123474Swpaul{
317123474Swpaul	ndis_driver_object	*drv;
318123474Swpaul
319123474Swpaul	drv = handle;
320123474Swpaul	bcopy((char *)characteristics, (char *)&drv->ndo_chars,
321123474Swpaul	    sizeof(ndis_miniport_characteristics));
322123474Swpaul	return(NDIS_STATUS_SUCCESS);
323123474Swpaul}
324123474Swpaul
325123474Swpaul__stdcall static ndis_status
326123474Swpaulndis_malloc_withtag(vaddr, len, tag)
327123474Swpaul	void			**vaddr;
328123474Swpaul	uint32_t		len;
329123474Swpaul	uint32_t		tag;
330123474Swpaul{
331123474Swpaul	void			*mem;
332123474Swpaul
333123474Swpaul	mem = malloc(len, M_DEVBUF, M_NOWAIT);
334123474Swpaul	if (mem == NULL)
335123474Swpaul		return(NDIS_STATUS_RESOURCES);
336123474Swpaul	*vaddr = mem;
337123474Swpaul
338123474Swpaul	return(NDIS_STATUS_SUCCESS);
339123474Swpaul}
340123474Swpaul
341123474Swpaul__stdcall static ndis_status
342123474Swpaulndis_malloc(vaddr, len, flags, highaddr)
343123474Swpaul	void			**vaddr;
344123474Swpaul	uint32_t		len;
345123474Swpaul	uint32_t		flags;
346123474Swpaul	ndis_physaddr		highaddr;
347123474Swpaul{
348123474Swpaul	void			*mem;
349123474Swpaul
350123474Swpaul	mem = malloc(len, M_DEVBUF, M_NOWAIT);
351123474Swpaul	if (mem == NULL)
352123474Swpaul		return(NDIS_STATUS_RESOURCES);
353123474Swpaul	*vaddr = mem;
354123474Swpaul
355123474Swpaul	return(NDIS_STATUS_SUCCESS);
356123474Swpaul}
357123474Swpaul
358123474Swpaul__stdcall static void
359123474Swpaulndis_free(vaddr, len, flags)
360123474Swpaul	void			*vaddr;
361123474Swpaul	uint32_t		len;
362123474Swpaul	uint32_t		flags;
363123474Swpaul{
364123474Swpaul	if (len == 0)
365123474Swpaul		return;
366123474Swpaul	free(vaddr, M_DEVBUF);
367123474Swpaul	return;
368123474Swpaul}
369123474Swpaul
370123474Swpaul__stdcall static ndis_status
371123474Swpaulndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
372123474Swpaul			flags, iftype)
373123474Swpaul	ndis_handle			adapter_handle;
374123474Swpaul	ndis_handle			adapter_ctx;
375123474Swpaul	uint32_t			hangsecs;
376123474Swpaul	uint32_t			flags;
377123474Swpaul	ndis_interface_type		iftype;
378123474Swpaul{
379123474Swpaul	ndis_miniport_block		*block;
380123474Swpaul
381123474Swpaul	/*
382123474Swpaul	 * Save the adapter context, we need it for calling
383123474Swpaul	 * the driver's internal functions.
384123474Swpaul	 */
385123474Swpaul	block = (ndis_miniport_block *)adapter_handle;
386123474Swpaul	block->nmb_miniportadapterctx = adapter_ctx;
387123474Swpaul	block->nmb_checkforhangsecs = hangsecs;
388123474Swpaul
389123474Swpaul	return(NDIS_STATUS_SUCCESS);
390123474Swpaul}
391123474Swpaul
392123474Swpaul__stdcall static void
393123474Swpaulndis_open_cfg(status, cfg, wrapctx)
394123474Swpaul	ndis_status		*status;
395123474Swpaul	ndis_handle		*cfg;
396123474Swpaul	ndis_handle		wrapctx;
397123474Swpaul{
398123474Swpaul	*cfg = wrapctx;
399123474Swpaul	*status = NDIS_STATUS_SUCCESS;
400123474Swpaul	return;
401123474Swpaul}
402123474Swpaul
403123474Swpaulstatic ndis_status
404123474Swpaulndis_encode_parm(block, oid, type, parm)
405123474Swpaul	ndis_miniport_block	*block;
406123474Swpaul        struct sysctl_oid	*oid;
407123474Swpaul	ndis_parm_type		type;
408123474Swpaul	ndis_config_parm	**parm;
409123474Swpaul{
410123474Swpaul	uint16_t		*unicode;
411123474Swpaul	ndis_unicode_string	*ustr;
412123474Swpaul
413123474Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
414123474Swpaul
415123474Swpaul	switch(type) {
416123474Swpaul	case ndis_parm_string:
417123474Swpaul		ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
418123474Swpaul		(*parm)->ncp_type = ndis_parm_string;
419123474Swpaul		ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
420123474Swpaul		ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
421123474Swpaul		ustr->nus_buf = unicode;
422123474Swpaul		break;
423123474Swpaul	case ndis_parm_int:
424123474Swpaul		(*parm)->ncp_type = ndis_parm_int;
425123474Swpaul		(*parm)->ncp_parmdata.ncp_intdata =
426123474Swpaul		    strtol((char *)oid->oid_arg1, NULL, 10);
427123474Swpaul		break;
428123474Swpaul	case ndis_parm_hexint:
429123474Swpaul		(*parm)->ncp_type = ndis_parm_hexint;
430123474Swpaul		(*parm)->ncp_parmdata.ncp_intdata =
431123474Swpaul		    strtoul((char *)oid->oid_arg1, NULL, 16);
432123474Swpaul		break;
433123474Swpaul	default:
434123474Swpaul		return(NDIS_STATUS_FAILURE);
435123474Swpaul		break;
436123474Swpaul	}
437123474Swpaul
438123474Swpaul	return(NDIS_STATUS_SUCCESS);
439123474Swpaul}
440123474Swpaul
441123474Swpaul__stdcall static void
442123474Swpaulndis_read_cfg(status, parm, cfg, key, type)
443123474Swpaul	ndis_status		*status;
444123474Swpaul	ndis_config_parm	**parm;
445123474Swpaul	ndis_handle		cfg;
446123474Swpaul	ndis_unicode_string	*key;
447123474Swpaul	ndis_parm_type		type;
448123474Swpaul{
449123474Swpaul	char			*keystr = NULL;
450123474Swpaul	uint16_t		*unicode;
451123474Swpaul	ndis_miniport_block	*block;
452123474Swpaul	struct ndis_softc	*sc;
453123474Swpaul        struct sysctl_oid	*oidp;
454123474Swpaul	struct sysctl_ctx_entry	*e;
455123474Swpaul
456123474Swpaul	block = (ndis_miniport_block *)cfg;
457123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
458123474Swpaul
459123474Swpaul	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
460123474Swpaul
461123474Swpaul	*parm = &block->nmb_replyparm;
462123474Swpaul	bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
463123474Swpaul	unicode = (uint16_t *)&block->nmb_dummybuf;
464123474Swpaul
465123474Swpaul	/*
466123474Swpaul	 * See if registry key is already in a list of known keys
467123474Swpaul	 * included with the driver.
468123474Swpaul	 */
469123474Swpaul	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
470123474Swpaul		oidp = e->entry;
471123474Swpaul		if (strcmp(oidp->oid_name, keystr) == 0) {
472123488Swpaul			if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
473123488Swpaul				free(keystr, M_DEVBUF);
474123488Swpaul				*status = NDIS_STATUS_FAILURE;
475123488Swpaul				return;
476123488Swpaul			}
477123474Swpaul			*status = ndis_encode_parm(block, oidp, type, parm);
478123474Swpaul			free(keystr, M_DEVBUF);
479123474Swpaul			return;
480123474Swpaul		}
481123474Swpaul	}
482123474Swpaul
483123474Swpaul	/*
484123474Swpaul	 * If the key didn't match, add it to the list of dynamically
485123474Swpaul	 * created ones. Sometimes, drivers refer to registry keys
486123474Swpaul	 * that aren't documented in their .INF files. These keys
487123474Swpaul	 * are supposed to be created by some sort of utility or
488123474Swpaul	 * control panel snap-in that comes with the driver software.
489123474Swpaul	 * Sometimes it's useful to be able to manipulate these.
490123474Swpaul	 * If the driver requests the key in the form of a string,
491123474Swpaul	 * make its default value an empty string, otherwise default
492123474Swpaul	 * it to "0".
493123474Swpaul	 */
494123474Swpaul
495123474Swpaul	if (type == ndis_parm_int || type == ndis_parm_hexint)
496123488Swpaul		ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
497123488Swpaul		    "UNSET", CTLFLAG_RW);
498123474Swpaul	else
499123488Swpaul		ndis_add_sysctl(sc, keystr, "(dynamic string key)",
500123488Swpaul		    "UNSET", CTLFLAG_RW);
501123474Swpaul
502123474Swpaul	free(keystr, M_DEVBUF);
503123474Swpaul	*status = NDIS_STATUS_FAILURE;
504123474Swpaul	return;
505123474Swpaul}
506123474Swpaul
507123474Swpaul__stdcall static void
508123474Swpaulndis_close_cfg(cfg)
509123474Swpaul	ndis_handle		cfg;
510123474Swpaul{
511123474Swpaul	return;
512123474Swpaul}
513123474Swpaul
514123474Swpaul__stdcall static void
515123474Swpaulndis_create_lock(lock)
516123474Swpaul	ndis_spin_lock		*lock;
517123474Swpaul{
518123474Swpaul	struct mtx		*mtx;
519123474Swpaul
520123474Swpaul	mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO);
521123474Swpaul	if (mtx == NULL)
522123474Swpaul		return;
523123474Swpaul	mtx_init(mtx, "ndislock", MTX_NETWORK_LOCK,
524123474Swpaul	    MTX_DEF | MTX_RECURSE | MTX_DUPOK);
525123474Swpaul	lock->nsl_spinlock = (ndis_kspin_lock)mtx;
526123474Swpaul
527123474Swpaul	return;
528123474Swpaul}
529123474Swpaul
530123474Swpaul__stdcall static void
531123474Swpaulndis_destroy_lock(lock)
532123474Swpaul	ndis_spin_lock		*lock;
533123474Swpaul{
534123474Swpaul	struct mtx		*ndis_mtx;
535123474Swpaul
536123474Swpaul	ndis_mtx = (struct mtx *)lock->nsl_spinlock;
537123474Swpaul	mtx_destroy(ndis_mtx);
538123474Swpaul	free(ndis_mtx, M_DEVBUF);
539123474Swpaul
540123474Swpaul	return;
541123474Swpaul}
542123474Swpaul
543123474Swpaul__stdcall static void
544123474Swpaulndis_lock(lock)
545123474Swpaul	ndis_spin_lock		*lock;
546123474Swpaul{
547123474Swpaul	if (lock == NULL)
548123474Swpaul		return;
549123474Swpaul	mtx_lock((struct mtx *)lock->nsl_spinlock);
550123474Swpaul
551123474Swpaul	return;
552123474Swpaul}
553123474Swpaul
554123474Swpaul__stdcall static void
555123474Swpaulndis_unlock(lock)
556123474Swpaul	ndis_spin_lock		*lock;
557123474Swpaul{
558123474Swpaul	if (lock == NULL)
559123474Swpaul		return;
560123474Swpaul	mtx_unlock((struct mtx *)lock->nsl_spinlock);
561123474Swpaul
562123474Swpaul	return;
563123474Swpaul}
564123474Swpaul
565123474Swpaul__stdcall static uint32_t
566123474Swpaulndis_read_pci(adapter, slot, offset, buf, len)
567123474Swpaul	ndis_handle		adapter;
568123474Swpaul	uint32_t		slot;
569123474Swpaul	uint32_t		offset;
570123474Swpaul	void			*buf;
571123474Swpaul	uint32_t		len;
572123474Swpaul{
573123474Swpaul	ndis_miniport_block	*block;
574123474Swpaul	int			i;
575123474Swpaul	char			*dest;
576123474Swpaul
577123474Swpaul	block = (ndis_miniport_block *)adapter;
578123474Swpaul	dest = buf;
579123474Swpaul	if (block == NULL || block->nmb_dev == NULL)
580123474Swpaul		return(0);
581123474Swpaul
582123474Swpaul	for (i = 0; i < len; i++)
583123474Swpaul		dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
584123474Swpaul
585123474Swpaul	return(len);
586123474Swpaul}
587123474Swpaul
588123474Swpaul__stdcall static uint32_t
589123474Swpaulndis_write_pci(adapter, slot, offset, buf, len)
590123474Swpaul	ndis_handle		adapter;
591123474Swpaul	uint32_t		slot;
592123474Swpaul	uint32_t		offset;
593123474Swpaul	void			*buf;
594123474Swpaul	uint32_t		len;
595123474Swpaul{
596123474Swpaul	ndis_miniport_block	*block;
597123474Swpaul	int			i;
598123474Swpaul	char			*dest;
599123474Swpaul
600123474Swpaul	block = (ndis_miniport_block *)adapter;
601123474Swpaul	dest = buf;
602123474Swpaul
603123474Swpaul	if (block == NULL || block->nmb_dev == NULL)
604123474Swpaul		return(0);
605123474Swpaul
606123474Swpaul	for (i = 0; i < len; i++)
607123474Swpaul		pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
608123474Swpaul
609123474Swpaul	return(len);
610123474Swpaul}
611123474Swpaul
612123474Swpaul/*
613123474Swpaul * The errorlog routine uses a variable argument list, so we
614123474Swpaul * have to declare it this way.
615123474Swpaul */
616123474Swpaulstatic void
617123474Swpaulndis_syslog(ndis_handle adapter, ndis_error_code code,
618123474Swpaul	uint32_t numerrors, ...)
619123474Swpaul{
620123474Swpaul	ndis_miniport_block	*block;
621123474Swpaul	va_list			ap;
622123474Swpaul	int			i;
623123474Swpaul
624123474Swpaul	block = (ndis_miniport_block *)adapter;
625123474Swpaul
626123474Swpaul	printf ("NDIS ERROR: %x\n", code);
627123474Swpaul	printf ("NDIS NUMERRORS: %x\n", numerrors);
628123474Swpaul
629123474Swpaul	va_start(ap, numerrors);
630123474Swpaul	for (i = 0; i < numerrors; i++)
631123474Swpaul		printf ("argptr: %p\n", va_arg(ap, void *));
632123474Swpaul	va_end(ap);
633123474Swpaul
634123474Swpaul	return;
635123474Swpaul}
636123474Swpaul
637123474Swpaulstatic void
638123474Swpaulndis_map_cb(arg, segs, nseg, error)
639123474Swpaul	void			*arg;
640123474Swpaul	bus_dma_segment_t	*segs;
641123474Swpaul	int			nseg;
642123474Swpaul	int			error;
643123474Swpaul{
644123474Swpaul	struct ndis_map_arg	*ctx;
645123474Swpaul	int			i;
646123474Swpaul
647123474Swpaul	if (error)
648123474Swpaul		return;
649123474Swpaul
650123474Swpaul	ctx = arg;
651123474Swpaul
652123474Swpaul	for (i = 0; i < nseg; i++) {
653123474Swpaul		ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
654123474Swpaul		ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
655123474Swpaul	}
656123474Swpaul
657123474Swpaul	ctx->nma_cnt = nseg;
658123474Swpaul
659123474Swpaul	return;
660123474Swpaul}
661123474Swpaul
662123474Swpaul__stdcall static void
663123474Swpaulndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
664123474Swpaul	ndis_handle		adapter;
665123474Swpaul	ndis_buffer		*buf;
666123474Swpaul	uint32_t		mapreg;
667123474Swpaul	uint8_t			writedev;
668123474Swpaul	ndis_paddr_unit		*addrarray;
669123474Swpaul	uint32_t		*arraysize;
670123474Swpaul{
671123474Swpaul	ndis_miniport_block	*block;
672123474Swpaul	struct ndis_softc	*sc;
673123474Swpaul	struct ndis_map_arg	nma;
674123474Swpaul	bus_dmamap_t		map;
675123474Swpaul	int			error;
676123474Swpaul
677123474Swpaul	if (adapter == NULL)
678123474Swpaul		return;
679123474Swpaul
680123474Swpaul	block = (ndis_miniport_block *)adapter;
681123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
682123474Swpaul
683123474Swpaul	if (mapreg > sc->ndis_mmapcnt)
684123474Swpaul		return;
685123474Swpaul
686123474Swpaul	map = sc->ndis_mmaps[mapreg];
687123474Swpaul	nma.nma_fraglist = addrarray;
688123474Swpaul
689123474Swpaul	error = bus_dmamap_load(sc->ndis_mtag, map,
690123474Swpaul	    buf->nb_mappedsystemva, buf->nb_bytecount, ndis_map_cb,
691123474Swpaul	    (void *)&nma, BUS_DMA_NOWAIT);
692123474Swpaul
693123474Swpaul	if (error)
694123474Swpaul		return;
695123474Swpaul
696123474Swpaul	bus_dmamap_sync(sc->ndis_mtag, map,
697123474Swpaul	    writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
698123474Swpaul
699123474Swpaul	*arraysize = nma.nma_cnt;
700123474Swpaul
701123474Swpaul	return;
702123474Swpaul}
703123474Swpaul
704123474Swpaul__stdcall static void
705123474Swpaulndis_vtophys_unload(adapter, buf, mapreg)
706123474Swpaul	ndis_handle		adapter;
707123474Swpaul	ndis_buffer		*buf;
708123474Swpaul	uint32_t		mapreg;
709123474Swpaul{
710123474Swpaul	ndis_miniport_block	*block;
711123474Swpaul	struct ndis_softc	*sc;
712123474Swpaul	bus_dmamap_t		map;
713123474Swpaul
714123474Swpaul	if (adapter == NULL)
715123474Swpaul		return;
716123474Swpaul
717123474Swpaul	block = (ndis_miniport_block *)adapter;
718123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
719123474Swpaul
720123474Swpaul	if (mapreg > sc->ndis_mmapcnt)
721123474Swpaul		return;
722123474Swpaul
723123474Swpaul	map = sc->ndis_mmaps[mapreg];
724123474Swpaul
725123474Swpaul	bus_dmamap_sync(sc->ndis_mtag, map,
726123474Swpaul	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
727123474Swpaul
728123474Swpaul	bus_dmamap_unload(sc->ndis_mtag, map);
729123474Swpaul
730123474Swpaul	return;
731123474Swpaul}
732123474Swpaul
733123474Swpaul__stdcall static void
734123474Swpaulndis_create_timer(timer, handle, func, ctx)
735123474Swpaul	ndis_miniport_timer	*timer;
736123474Swpaul	ndis_handle		*handle;
737123474Swpaul	ndis_timer_function	func;
738123474Swpaul	void			*ctx;
739123474Swpaul{
740123474Swpaul	struct callout_handle	*ch;
741123474Swpaul
742123474Swpaul	ch = (struct callout_handle *)&timer->nmt_dpc;
743123474Swpaul	callout_handle_init(ch);
744123474Swpaul	timer->nmt_timerfunc = func;
745123474Swpaul	timer->nmt_timerctx = ctx;
746123474Swpaul
747123474Swpaul	return;
748123474Swpaul}
749123474Swpaul
750123474Swpaul/*
751123474Swpaul * The driver's timer callout is __stdcall function, so we need this
752123474Swpaul * intermediate step.
753123474Swpaul */
754123474Swpaul
755123474Swpaulstatic void
756123474Swpaulndis_timercall(arg)
757123474Swpaul	void		*arg;
758123474Swpaul{
759123474Swpaul	ndis_miniport_timer	*timer;
760123474Swpaul	__stdcall ndis_timer_function	timerfunc;
761123474Swpaul
762123474Swpaul	timer = arg;
763123474Swpaul
764123474Swpaul	timerfunc = timer->nmt_timerfunc;
765123474Swpaul	timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
766123474Swpaul
767123474Swpaul	return;
768123474Swpaul}
769123474Swpaul
770123474Swpaul/*
771123474Swpaul * Windows specifies timeouts in milliseconds. We specify timeouts
772123474Swpaul * in hz. Trying to compute a tenth of a second based on hz is tricky.
773123474Swpaul * so we approximate. Note that we abuse the dpc portion of the
774123474Swpaul * miniport timer structure to hold the UNIX callout handle.
775123474Swpaul */
776123474Swpaul__stdcall static void
777123474Swpaulndis_set_timer(timer, msecs)
778123474Swpaul	ndis_miniport_timer	*timer;
779123474Swpaul	uint32_t		msecs;
780123474Swpaul{
781123474Swpaul	struct callout_handle	*ch;
782123474Swpaul	struct timeval		tv;
783123474Swpaul
784123474Swpaul	tv.tv_sec = 0;
785123474Swpaul	tv.tv_usec = msecs * 1000;
786123474Swpaul
787123474Swpaul	ch = (struct callout_handle *)&timer->nmt_dpc;
788123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_timercall;
789123474Swpaul	*ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, (void *)timer,
790123474Swpaul	    tvtohz(&tv));
791123474Swpaul
792123474Swpaul	return;
793123474Swpaul}
794123474Swpaul
795123474Swpaulstatic void
796123474Swpaulndis_tick(arg)
797123474Swpaul	void			*arg;
798123474Swpaul{
799123474Swpaul	ndis_miniport_timer	*timer;
800123474Swpaul	struct callout_handle	*ch;
801123474Swpaul	__stdcall ndis_timer_function	timerfunc;
802123474Swpaul	struct timeval		tv;
803123474Swpaul
804123474Swpaul	timer = arg;
805123474Swpaul
806123474Swpaul	timerfunc = timer->nmt_timerfunc;
807123474Swpaul	timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
808123474Swpaul
809123474Swpaul	/* Automatically reload timer. */
810123474Swpaul
811123474Swpaul	tv.tv_sec = 0;
812123474Swpaul	tv.tv_usec = timer->nmt_ktimer.nk_period * 1000;
813123474Swpaul	ch = (struct callout_handle *)&timer->nmt_dpc;
814123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
815123474Swpaul	*ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer,
816123474Swpaul	    tvtohz(&tv));
817123474Swpaul
818123474Swpaul	return;
819123474Swpaul}
820123474Swpaul
821123474Swpaul__stdcall static void
822123474Swpaulndis_set_periodic_timer(timer, msecs)
823123474Swpaul	ndis_miniport_timer	*timer;
824123474Swpaul	uint32_t		msecs;
825123474Swpaul{
826123474Swpaul	struct callout_handle	*ch;
827123474Swpaul	struct timeval		tv;
828123474Swpaul
829123474Swpaul	tv.tv_sec = 0;
830123474Swpaul	tv.tv_usec = msecs * 1000;
831123474Swpaul
832123474Swpaul	timer->nmt_ktimer.nk_period = msecs;
833123474Swpaul	ch = (struct callout_handle *)&timer->nmt_dpc;
834123474Swpaul	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
835123474Swpaul	*ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer,
836123474Swpaul	    tvtohz(&tv));
837123474Swpaul
838123474Swpaul	return;
839123474Swpaul}
840123474Swpaul
841123474Swpaul__stdcall static void
842123474Swpaulndis_cancel_timer(timer, cancelled)
843123474Swpaul	ndis_miniport_timer	*timer;
844123474Swpaul	uint8_t			*cancelled;
845123474Swpaul{
846123474Swpaul	struct callout_handle	*ch;
847123474Swpaul
848123474Swpaul	ch = (struct callout_handle *)&timer->nmt_dpc;
849123474Swpaul	untimeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer, *ch);
850123474Swpaul
851123474Swpaul	return;
852123474Swpaul}
853123474Swpaul
854123474Swpaul__stdcall static void
855123474Swpaulndis_query_resources(status, adapter, list, buflen)
856123474Swpaul	ndis_status		*status;
857123474Swpaul	ndis_handle		adapter;
858123474Swpaul	ndis_resource_list	*list;
859123474Swpaul	uint32_t		*buflen;
860123474Swpaul{
861123474Swpaul	ndis_miniport_block	*block;
862123474Swpaul	struct ndis_softc	*sc;
863123474Swpaul
864123474Swpaul	block = (ndis_miniport_block *)adapter;
865123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
866123474Swpaul
867123474Swpaul	*buflen = sizeof(ndis_resource_list) +
868123474Swpaul	    (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
869123474Swpaul
870123474Swpaul	bcopy((char *)block->nmb_rlist, (char *)list, *buflen);
871123474Swpaul	*status = NDIS_STATUS_SUCCESS;
872123474Swpaul	return;
873123474Swpaul}
874123474Swpaul
875123474Swpaul__stdcall static ndis_status
876123474Swpaulndis_register_ioport(offset, adapter, port, numports)
877123474Swpaul	void			**offset;
878123474Swpaul	ndis_handle		adapter;
879123474Swpaul	uint32_t		port;
880123474Swpaul	uint32_t		numports;
881123474Swpaul{
882123474Swpaul	struct ndis_miniport_block	*block;
883123474Swpaul	struct ndis_softc	*sc;
884123474Swpaul
885123474Swpaul	if (adapter == NULL)
886123474Swpaul		return(NDIS_STATUS_FAILURE);
887123474Swpaul
888123474Swpaul	block = (ndis_miniport_block *)adapter;
889123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
890123474Swpaul
891123474Swpaul	if (sc->ndis_res_io == NULL)
892123474Swpaul		return(NDIS_STATUS_FAILURE);
893123474Swpaul
894123474Swpaul	if (rman_get_size(sc->ndis_res_io) != numports)
895123474Swpaul		return(NDIS_STATUS_INVALID_LENGTH);
896123474Swpaul
897123474Swpaul	*offset = (void *)rman_get_start(sc->ndis_res_io);
898123474Swpaul
899123474Swpaul	return(NDIS_STATUS_SUCCESS);
900123474Swpaul}
901123474Swpaul
902123474Swpaul__stdcall static void
903123474Swpaulndis_deregister_ioport(adapter, port, numports, offset)
904123474Swpaul	ndis_handle		adapter;
905123474Swpaul	uint32_t		port;
906123474Swpaul	uint32_t		numports;
907123474Swpaul	void			*offset;
908123474Swpaul{
909123474Swpaul	return;
910123474Swpaul}
911123474Swpaul
912123474Swpaul__stdcall static void
913123474Swpaulndis_read_netaddr(status, addr, addrlen, adapter)
914123474Swpaul	ndis_status		*status;
915123474Swpaul	void			**addr;
916123474Swpaul	uint32_t		*addrlen;
917123474Swpaul	ndis_handle		adapter;
918123474Swpaul{
919123474Swpaul	struct ndis_softc	*sc;
920123474Swpaul	ndis_miniport_block	*block;
921123474Swpaul	uint8_t			empty[] = { 0, 0, 0, 0, 0, 0 };
922123474Swpaul
923123474Swpaul	block = (ndis_miniport_block *)adapter;
924123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
925123474Swpaul
926123474Swpaul	if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
927123474Swpaul		*status = NDIS_STATUS_FAILURE;
928123474Swpaul	else {
929123474Swpaul		*addr = sc->arpcom.ac_enaddr;
930123474Swpaul		*addrlen = ETHER_ADDR_LEN;
931123474Swpaul		*status = NDIS_STATUS_SUCCESS;
932123474Swpaul	}
933123474Swpaul
934123474Swpaul	return;
935123474Swpaul}
936123474Swpaul
937123474Swpaul__stdcall static ndis_status
938123474Swpaulndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
939123474Swpaul	ndis_handle		adapter;
940123474Swpaul	uint32_t		dmachannel;
941123474Swpaul	uint8_t			dmasize;
942123474Swpaul	uint32_t		physmapneeded;
943123474Swpaul	uint32_t		maxmap;
944123474Swpaul{
945123474Swpaul	struct ndis_softc	*sc;
946123474Swpaul	ndis_miniport_block	*block;
947123474Swpaul	int			error, i, nseg = NDIS_MAXSEG;
948123474Swpaul
949123474Swpaul	block = (ndis_miniport_block *)adapter;
950123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
951123474Swpaul
952123474Swpaul	sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
953123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
954123474Swpaul
955123474Swpaul	if (sc->ndis_mmaps == NULL)
956123474Swpaul		return(NDIS_STATUS_RESOURCES);
957123474Swpaul
958123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
959123474Swpaul	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
960123474Swpaul	    NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
961123474Swpaul	    NULL, NULL, &sc->ndis_mtag);
962123474Swpaul
963123474Swpaul	if (error) {
964123474Swpaul		free(sc->ndis_mmaps, M_DEVBUF);
965123474Swpaul		return(NDIS_STATUS_RESOURCES);
966123474Swpaul	}
967123474Swpaul
968123474Swpaul	for (i = 0; i < physmapneeded; i++)
969123474Swpaul		bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
970123474Swpaul
971123474Swpaul	sc->ndis_mmapcnt = physmapneeded;
972123474Swpaul
973123474Swpaul	return(NDIS_STATUS_SUCCESS);
974123474Swpaul}
975123474Swpaul
976123474Swpaul__stdcall static void
977123474Swpaulndis_free_mapreg(adapter)
978123474Swpaul	ndis_handle		adapter;
979123474Swpaul{
980123474Swpaul	struct ndis_softc	*sc;
981123474Swpaul	ndis_miniport_block	*block;
982123474Swpaul	int			i;
983123474Swpaul
984123474Swpaul	block = (ndis_miniport_block *)adapter;
985123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
986123474Swpaul
987123474Swpaul	for (i = 0; i < sc->ndis_mmapcnt; i++)
988123474Swpaul		bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
989123474Swpaul
990123474Swpaul	free(sc->ndis_mmaps, M_DEVBUF);
991123474Swpaul
992123474Swpaul	bus_dma_tag_destroy(sc->ndis_mtag);
993123474Swpaul
994123474Swpaul	return;
995123474Swpaul}
996123474Swpaul
997123474Swpaulstatic void
998123474Swpaulndis_mapshared_cb(arg, segs, nseg, error)
999123474Swpaul	void			*arg;
1000123474Swpaul	bus_dma_segment_t	*segs;
1001123474Swpaul	int			nseg;
1002123474Swpaul	int			error;
1003123474Swpaul{
1004123474Swpaul	ndis_physaddr		*p;
1005123474Swpaul
1006123474Swpaul	if (error || nseg > 1)
1007123474Swpaul		return;
1008123474Swpaul
1009123474Swpaul	p = arg;
1010123474Swpaul
1011123474Swpaul	p->np_quad = segs[0].ds_addr;
1012123474Swpaul
1013123474Swpaul	return;
1014123474Swpaul}
1015123474Swpaul
1016123474Swpaul/*
1017123474Swpaul * This maps to bus_dmamem_alloc().
1018123474Swpaul */
1019123474Swpaul__stdcall static void
1020123474Swpaulndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
1021123474Swpaul	ndis_handle		adapter;
1022123474Swpaul	uint32_t		len;
1023123474Swpaul	uint8_t			cached;
1024123474Swpaul	void			**vaddr;
1025123474Swpaul	ndis_physaddr		*paddr;
1026123474Swpaul{
1027123474Swpaul	ndis_miniport_block	*block;
1028123474Swpaul	struct ndis_softc	*sc;
1029123474Swpaul	struct ndis_shmem	*sh;
1030123474Swpaul	int			error;
1031123474Swpaul
1032123474Swpaul	if (adapter == NULL)
1033123474Swpaul		return;
1034123474Swpaul
1035123474Swpaul	block = (ndis_miniport_block *)adapter;
1036123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1037123474Swpaul
1038123474Swpaul	sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1039123474Swpaul	if (sh == NULL)
1040123474Swpaul		return;
1041123474Swpaul
1042123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1043123474Swpaul	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1044123474Swpaul	    NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
1045123474Swpaul	    &sh->ndis_stag);
1046123474Swpaul
1047123474Swpaul	if (error) {
1048123474Swpaul		free(sh, M_DEVBUF);
1049123474Swpaul		return;
1050123474Swpaul	}
1051123474Swpaul
1052123474Swpaul	error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1053123474Swpaul	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1054123474Swpaul
1055123474Swpaul	if (error) {
1056123474Swpaul		bus_dma_tag_destroy(sh->ndis_stag);
1057123474Swpaul		free(sh, M_DEVBUF);
1058123474Swpaul		return;
1059123474Swpaul	}
1060123474Swpaul
1061123474Swpaul	error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1062123474Swpaul	    len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1063123474Swpaul
1064123474Swpaul	if (error) {
1065123474Swpaul		bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1066123474Swpaul		bus_dma_tag_destroy(sh->ndis_stag);
1067123474Swpaul		free(sh, M_DEVBUF);
1068123474Swpaul		return;
1069123474Swpaul	}
1070123474Swpaul
1071123474Swpaul	sh->ndis_saddr = *vaddr;
1072123474Swpaul	sh->ndis_next = sc->ndis_shlist;
1073123474Swpaul	sc->ndis_shlist = sh;
1074123474Swpaul
1075123474Swpaul	return;
1076123474Swpaul}
1077123474Swpaul
1078123474Swpaul__stdcall static void
1079123474Swpaulndis_alloc_sharedmem_async(adapter, len, cached, ctx)
1080123474Swpaul	ndis_handle		adapter;
1081123474Swpaul	uint32_t		len;
1082123474Swpaul	uint8_t			cached;
1083123474Swpaul	void			*ctx;
1084123474Swpaul{
1085123474Swpaul	ndis_miniport_block	*block;
1086123474Swpaul	struct ndis_softc	*sc;
1087123474Swpaul	void			*vaddr;
1088123474Swpaul	ndis_physaddr		paddr;
1089123474Swpaul	__stdcall ndis_allocdone_handler	donefunc;
1090123474Swpaul
1091123474Swpaul	if (adapter == NULL)
1092123474Swpaul		return;
1093123474Swpaul
1094123474Swpaul	block = (ndis_miniport_block *)adapter;
1095123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1096123474Swpaul	donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1097123474Swpaul
1098123474Swpaul	ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr);
1099123474Swpaul	donefunc(adapter, vaddr, &paddr, len, ctx);
1100123474Swpaul
1101123474Swpaul	return;
1102123474Swpaul}
1103123474Swpaul
1104123474Swpaul__stdcall static void
1105123474Swpaulndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
1106123474Swpaul	ndis_handle		adapter;
1107123474Swpaul	uint32_t		len;
1108123474Swpaul	uint8_t			cached;
1109123474Swpaul	void			*vaddr;
1110123474Swpaul	ndis_physaddr		paddr;
1111123474Swpaul{
1112123474Swpaul	ndis_miniport_block	*block;
1113123474Swpaul	struct ndis_softc	*sc;
1114123474Swpaul	struct ndis_shmem	*sh, *prev;
1115123474Swpaul
1116123474Swpaul	if (vaddr == NULL || adapter == NULL)
1117123474Swpaul		return;
1118123474Swpaul
1119123474Swpaul	block = (ndis_miniport_block *)adapter;
1120123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1121123474Swpaul	sh = prev = sc->ndis_shlist;
1122123474Swpaul
1123123474Swpaul	while (sh) {
1124123474Swpaul		if (sh->ndis_saddr == vaddr)
1125123474Swpaul			break;
1126123474Swpaul		prev = sh;
1127123474Swpaul		sh = sh->ndis_next;
1128123474Swpaul	}
1129123474Swpaul
1130123474Swpaul	bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1131123474Swpaul	bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1132123474Swpaul	bus_dma_tag_destroy(sh->ndis_stag);
1133123474Swpaul
1134123474Swpaul	if (sh == sc->ndis_shlist)
1135123474Swpaul		sc->ndis_shlist = sh->ndis_next;
1136123474Swpaul	else
1137123474Swpaul		prev->ndis_next = sh->ndis_next;
1138123474Swpaul
1139123474Swpaul	free(sh, M_DEVBUF);
1140123474Swpaul
1141123474Swpaul	return;
1142123474Swpaul}
1143123474Swpaul
1144123474Swpaul__stdcall static ndis_status
1145123474Swpaulndis_map_iospace(vaddr, adapter, paddr, len)
1146123474Swpaul	void			**vaddr;
1147123474Swpaul	ndis_handle		adapter;
1148123474Swpaul	ndis_physaddr		paddr;
1149123474Swpaul	uint32_t		len;
1150123474Swpaul{
1151123474Swpaul	ndis_miniport_block	*block;
1152123474Swpaul	struct ndis_softc	*sc;
1153123474Swpaul
1154123474Swpaul	if (adapter == NULL)
1155123474Swpaul		return(NDIS_STATUS_FAILURE);
1156123474Swpaul
1157123474Swpaul	block = (ndis_miniport_block *)adapter;
1158123474Swpaul	sc = (struct ndis_softc *)(block->nmb_ifp);
1159123474Swpaul
1160123474Swpaul	if (sc->ndis_res_mem == NULL)
1161123474Swpaul		return(NDIS_STATUS_FAILURE);
1162123474Swpaul
1163123474Swpaul	*vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1164123474Swpaul
1165123474Swpaul	return(NDIS_STATUS_SUCCESS);
1166123474Swpaul}
1167123474Swpaul
1168123474Swpaul__stdcall static void
1169123474Swpaulndis_unmap_iospace(adapter, vaddr, len)
1170123474Swpaul	ndis_handle		adapter;
1171123474Swpaul	void			*vaddr;
1172123474Swpaul	uint32_t		len;
1173123474Swpaul{
1174123474Swpaul	return;
1175123474Swpaul}
1176123474Swpaul
1177123474Swpaul__stdcall static uint32_t
1178123474Swpaulndis_cachefill(void)
1179123474Swpaul{
1180123474Swpaul	return(128);
1181123474Swpaul}
1182123474Swpaul
1183123474Swpaul__stdcall static uint32_t
1184123474Swpaulndis_dma_align(handle)
1185123474Swpaul	ndis_handle		handle;
1186123474Swpaul{
1187123474Swpaul	return(128);
1188123474Swpaul}
1189123474Swpaul
1190123474Swpaul/*
1191123474Swpaul * NDIS has two methods for dealing with NICs that support DMA.
1192123474Swpaul * One is to just pass packets to the driver and let it call
1193123474Swpaul * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1194123474Swpaul * all by itself, and the other is to let the NDIS library handle the
1195123474Swpaul * buffer mapping internally, and hand the driver an already populated
1196123474Swpaul * scatter/gather fragment list. If the driver calls
1197123474Swpaul * NdisMInitializeScatterGatherDma(), it wants to use the latter
1198123474Swpaul * method.
1199123474Swpaul */
1200123474Swpaul
1201123474Swpaul__stdcall static ndis_status
1202123474Swpaulndis_init_sc_dma(adapter, is64, maxphysmap)
1203123474Swpaul	ndis_handle		adapter;
1204123474Swpaul	uint8_t			is64;
1205123474Swpaul	uint32_t		maxphysmap;
1206123474Swpaul{
1207123474Swpaul	struct ndis_softc	*sc;
1208123474Swpaul	ndis_miniport_block	*block;
1209123474Swpaul	int			error;
1210123474Swpaul
1211123474Swpaul	if (adapter == NULL)
1212123474Swpaul		return(NDIS_STATUS_FAILURE);
1213123474Swpaul	block = (ndis_miniport_block *)adapter;
1214123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1215123474Swpaul
1216123474Swpaul	/* Don't do this twice. */
1217123474Swpaul	if (sc->ndis_sc == 1)
1218123474Swpaul		return(NDIS_STATUS_SUCCESS);
1219123474Swpaul
1220123474Swpaul	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1221123474Swpaul	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1222123474Swpaul	    MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1223123474Swpaul	    NULL, NULL, &sc->ndis_ttag);
1224123474Swpaul
1225123474Swpaul	sc->ndis_sc = 1;
1226123474Swpaul
1227123474Swpaul	return(NDIS_STATUS_SUCCESS);
1228123474Swpaul}
1229123474Swpaul
1230123474Swpaul__stdcall static void
1231123474Swpaulndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
1232123474Swpaul	ndis_status		*status;
1233123474Swpaul	ndis_handle		*pool;
1234123474Swpaul	uint32_t		descnum;
1235123474Swpaul	uint32_t		protrsvdlen;
1236123474Swpaul{
1237123474Swpaul	ndis_packet		*cur;
1238123474Swpaul	int			i;
1239123474Swpaul
1240123474Swpaul	*pool = malloc(sizeof(ndis_packet) * (descnum + 1),
1241123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1242123474Swpaul
1243123474Swpaul	if (pool == NULL) {
1244123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1245123474Swpaul		return;
1246123474Swpaul	}
1247123474Swpaul
1248123474Swpaul	cur = (ndis_packet *)*pool;
1249123474Swpaul	cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1250123474Swpaul	for (i = 0; i < descnum; i++) {
1251123474Swpaul		cur->np_private.npp_head = (ndis_handle)(cur + 1);
1252123474Swpaul		cur++;
1253123474Swpaul	}
1254123474Swpaul
1255123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1256123474Swpaul	return;
1257123474Swpaul}
1258123474Swpaul
1259123474Swpaul__stdcall static void
1260123474Swpaulndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
1261123474Swpaul	ndis_status		*status;
1262123474Swpaul	ndis_handle		*pool;
1263123474Swpaul	uint32_t		descnum;
1264123474Swpaul	uint32_t		oflowdescnum;
1265123474Swpaul	uint32_t		protrsvdlen;
1266123474Swpaul{
1267123474Swpaul	return(ndis_alloc_packetpool(status, pool,
1268123474Swpaul	    descnum + oflowdescnum, protrsvdlen));
1269123474Swpaul}
1270123474Swpaul
1271123474Swpaul__stdcall static uint32_t
1272123474Swpaulndis_packetpool_use(pool)
1273123474Swpaul	ndis_handle		pool;
1274123474Swpaul{
1275123474Swpaul	ndis_packet		*head;
1276123474Swpaul
1277123474Swpaul	head = (ndis_packet *)pool;
1278123474Swpaul
1279123474Swpaul	return(head->np_private.npp_count);
1280123474Swpaul}
1281123474Swpaul
1282123474Swpaul__stdcall static void
1283123474Swpaulndis_free_packetpool(pool)
1284123474Swpaul	ndis_handle		pool;
1285123474Swpaul{
1286123474Swpaul	free(pool, M_DEVBUF);
1287123474Swpaul	return;
1288123474Swpaul}
1289123474Swpaul
1290123474Swpaul__stdcall static void
1291123474Swpaulndis_alloc_packet(status, packet, pool)
1292123474Swpaul	ndis_status		*status;
1293123474Swpaul	ndis_packet		**packet;
1294123474Swpaul	ndis_handle		pool;
1295123474Swpaul{
1296123474Swpaul	ndis_packet		*head, *pkt;
1297123474Swpaul
1298123474Swpaul	head = (ndis_packet *)pool;
1299123474Swpaul
1300123474Swpaul	if (head->np_private.npp_flags != 0x1) {
1301123474Swpaul		*status = NDIS_STATUS_FAILURE;
1302123474Swpaul		return;
1303123474Swpaul	}
1304123474Swpaul
1305123474Swpaul	pkt = (ndis_packet *)head->np_private.npp_head;
1306123474Swpaul
1307123474Swpaul	if (pkt == NULL) {
1308123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1309123474Swpaul		return;
1310123474Swpaul	}
1311123474Swpaul
1312123474Swpaul	head->np_private.npp_head = pkt->np_private.npp_head;
1313123474Swpaul
1314123474Swpaul	pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1315123474Swpaul	/* Save pointer to the pool. */
1316123474Swpaul	pkt->np_private.npp_pool = head;
1317123474Swpaul
1318123474Swpaul	/* Set the oob offset pointer. Lots of things expect this. */
1319123474Swpaul	pkt->np_private.npp_packetooboffset =
1320123474Swpaul	    offsetof(ndis_packet, np_oob);
1321123474Swpaul
1322123474Swpaul	*packet = pkt;
1323123474Swpaul
1324123474Swpaul	head->np_private.npp_count++;
1325123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1326123474Swpaul	return;
1327123474Swpaul}
1328123474Swpaul
1329123474Swpaul__stdcall static void
1330123474Swpaulndis_release_packet(packet)
1331123474Swpaul	ndis_packet		*packet;
1332123474Swpaul{
1333123474Swpaul	ndis_packet		*head;
1334123474Swpaul
1335123474Swpaul	if (packet == NULL || packet->np_private.npp_pool == NULL)
1336123474Swpaul		return;
1337123474Swpaul
1338123474Swpaul	head = packet->np_private.npp_pool;
1339123474Swpaul	if (head->np_private.npp_flags != 0x1)
1340123474Swpaul		return;
1341123474Swpaul
1342123474Swpaul	packet->np_private.npp_head = head->np_private.npp_head;
1343123474Swpaul	head->np_private.npp_head = (ndis_buffer *)packet;
1344123474Swpaul	head->np_private.npp_count--;
1345123474Swpaul
1346123474Swpaul	return;
1347123474Swpaul}
1348123474Swpaul
1349123474Swpaul__stdcall static void
1350123474Swpaulndis_unchain_headbuf(packet, buf)
1351123474Swpaul	ndis_packet		*packet;
1352123474Swpaul	ndis_buffer		**buf;
1353123474Swpaul{
1354123474Swpaul	ndis_packet_private	*priv;
1355123474Swpaul
1356123474Swpaul	if (packet == NULL || buf == NULL)
1357123474Swpaul		return;
1358123474Swpaul
1359123474Swpaul	priv = &packet->np_private;
1360123474Swpaul
1361123474Swpaul	priv->npp_validcounts = FALSE;
1362123474Swpaul
1363123474Swpaul	if (priv->npp_head == priv->npp_tail) {
1364123474Swpaul		*buf = priv->npp_head;
1365123474Swpaul		priv->npp_head = priv->npp_tail = NULL;
1366123474Swpaul	} else {
1367123474Swpaul		*buf = priv->npp_head;
1368123474Swpaul		priv->npp_head = (*buf)->nb_next;
1369123474Swpaul	}
1370123474Swpaul
1371123474Swpaul	return;
1372123474Swpaul}
1373123474Swpaul
1374123474Swpaul/*
1375123474Swpaul * The NDIS "buffer" manipulation functions are somewhat misnamed.
1376123474Swpaul * They don't really allocate buffers: they allocate buffer mappings.
1377123474Swpaul * The idea is you reserve a chunk of DMA-able memory using
1378123474Swpaul * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1379123474Swpaul * to obtain the virtual address of the DMA-able region.
1380123474Swpaul * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1381123474Swpaul */
1382123474Swpaul
1383123474Swpaul__stdcall static void
1384123474Swpaulndis_alloc_bufpool(status, pool, descnum)
1385123474Swpaul	ndis_status		*status;
1386123474Swpaul	ndis_handle		*pool;
1387123474Swpaul	uint32_t		descnum;
1388123474Swpaul{
1389123474Swpaul	ndis_buffer		*cur;
1390123474Swpaul	int			i;
1391123474Swpaul
1392123474Swpaul	*pool = malloc(sizeof(ndis_buffer) * (descnum + 1),
1393123474Swpaul	    M_DEVBUF, M_NOWAIT|M_ZERO);
1394123474Swpaul
1395123474Swpaul	if (pool == NULL) {
1396123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1397123474Swpaul		return;
1398123474Swpaul	}
1399123474Swpaul
1400123474Swpaul	cur = (ndis_buffer *)*pool;
1401123474Swpaul	cur->nb_flags = 0x1; /* mark the head of the list */
1402123474Swpaul	for (i = 0; i < descnum; i++) {
1403123474Swpaul		cur->nb_next = cur + 1;
1404123474Swpaul		cur++;
1405123474Swpaul	}
1406123474Swpaul
1407123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1408123474Swpaul	return;
1409123474Swpaul}
1410123474Swpaul
1411123474Swpaul__stdcall static void
1412123474Swpaulndis_free_bufpool(pool)
1413123474Swpaul	ndis_handle		pool;
1414123474Swpaul{
1415123474Swpaul	free(pool, M_DEVBUF);
1416123474Swpaul	return;
1417123474Swpaul}
1418123474Swpaul
1419123474Swpaul/*
1420123474Swpaul * This maps to a bus_dmamap_create() and bus_dmamap_load().
1421123474Swpaul */
1422123474Swpaul__stdcall static void
1423123474Swpaulndis_alloc_buf(status, buffer, pool, vaddr, len)
1424123474Swpaul	ndis_status		*status;
1425123474Swpaul	ndis_buffer		**buffer;
1426123474Swpaul	ndis_handle		pool;
1427123474Swpaul	void			*vaddr;
1428123474Swpaul	uint32_t		len;
1429123474Swpaul{
1430123474Swpaul	ndis_buffer		*head, *buf;
1431123474Swpaul
1432123474Swpaul	head = (ndis_buffer *)pool;
1433123474Swpaul	if (head->nb_flags != 0x1) {
1434123474Swpaul		*status = NDIS_STATUS_FAILURE;
1435123474Swpaul		return;
1436123474Swpaul	}
1437123474Swpaul
1438123474Swpaul	buf = head->nb_next;
1439123474Swpaul
1440123474Swpaul	if (buf == NULL) {
1441123474Swpaul		*status = NDIS_STATUS_RESOURCES;
1442123474Swpaul		return;
1443123474Swpaul	}
1444123474Swpaul
1445123474Swpaul	head->nb_next = buf->nb_next;
1446123474Swpaul
1447123474Swpaul	/* Save pointer to the pool. */
1448123474Swpaul	buf->nb_process = head;
1449123474Swpaul
1450123474Swpaul	buf->nb_mappedsystemva = vaddr;
1451123474Swpaul	buf->nb_size = len;
1452123474Swpaul	buf->nb_next = NULL;
1453123474Swpaul
1454123474Swpaul	*buffer = buf;
1455123474Swpaul
1456123474Swpaul	*status = NDIS_STATUS_SUCCESS;
1457123474Swpaul	return;
1458123474Swpaul}
1459123474Swpaul
1460123474Swpaul__stdcall static void
1461123474Swpaulndis_release_buf(buf)
1462123474Swpaul	ndis_buffer		*buf;
1463123474Swpaul{
1464123474Swpaul	ndis_buffer		*head;
1465123474Swpaul
1466123474Swpaul	if (buf == NULL || buf->nb_process == NULL)
1467123474Swpaul		return;
1468123474Swpaul
1469123474Swpaul	head = buf->nb_process;
1470123474Swpaul
1471123474Swpaul	if (head->nb_flags != 0x1)
1472123474Swpaul		return;
1473123474Swpaul
1474123474Swpaul	buf->nb_next = head->nb_next;
1475123474Swpaul	head->nb_next = buf;
1476123474Swpaul
1477123474Swpaul	return;
1478123474Swpaul}
1479123474Swpaul
1480123474Swpaul/* Get the virtual address and length of a buffer */
1481123474Swpaul
1482123474Swpaul__stdcall static void
1483123474Swpaulndis_query_buf(buf, vaddr, len)
1484123474Swpaul	ndis_buffer		*buf;
1485123474Swpaul	void			**vaddr;
1486123474Swpaul	uint32_t		*len;
1487123474Swpaul{
1488123474Swpaul	*vaddr = buf->nb_mappedsystemva;
1489123474Swpaul	*len = buf->nb_bytecount;
1490123474Swpaul
1491123474Swpaul	return;
1492123474Swpaul}
1493123474Swpaul
1494123474Swpaul/* Same as above -- we don't care about the priority. */
1495123474Swpaul
1496123474Swpaul__stdcall static void
1497123474Swpaulndis_query_buf_safe(buf, vaddr, len, prio)
1498123474Swpaul	ndis_buffer		*buf;
1499123474Swpaul	void			**vaddr;
1500123474Swpaul	uint32_t		*len;
1501123474Swpaul	uint32_t		prio;
1502123474Swpaul{
1503123474Swpaul	*vaddr = buf->nb_mappedsystemva;
1504123474Swpaul	*len = buf->nb_bytecount;
1505123474Swpaul
1506123474Swpaul	return;
1507123474Swpaul}
1508123474Swpaul
1509123474Swpaul__stdcall static void
1510123474Swpaulndis_adjust_buflen(buf, len)
1511123474Swpaul	ndis_buffer		*buf;
1512123474Swpaul	int			len;
1513123474Swpaul{
1514123488Swpaul	if (len > buf->nb_size)
1515123474Swpaul		return;
1516123474Swpaul	buf->nb_bytecount = len;
1517123474Swpaul
1518123474Swpaul	return;
1519123474Swpaul}
1520123474Swpaul
1521123474Swpaul__stdcall static uint32_t
1522123474Swpaulndis_interlock_inc(addend)
1523123474Swpaul	uint32_t		*addend;
1524123474Swpaul{
1525123474Swpaul	mtx_lock(&ndis_interlock);
1526123474Swpaul	*addend++;
1527123474Swpaul	mtx_unlock(&ndis_interlock);
1528123474Swpaul	return(*addend);
1529123474Swpaul}
1530123474Swpaul
1531123474Swpaul__stdcall static uint32_t
1532123474Swpaulndis_interlock_dec(addend)
1533123474Swpaul	uint32_t		*addend;
1534123474Swpaul{
1535123474Swpaul	mtx_lock(&ndis_interlock);
1536123474Swpaul	*addend--;
1537123474Swpaul	mtx_unlock(&ndis_interlock);
1538123474Swpaul	return(*addend);
1539123474Swpaul}
1540123474Swpaul
1541123474Swpaul__stdcall static void
1542123474Swpaulndis_init_event(event)
1543123474Swpaul	ndis_event		*event;
1544123474Swpaul{
1545123474Swpaul	event->ne_event.nk_header.dh_sigstate = FALSE;
1546123474Swpaul	return;
1547123474Swpaul}
1548123474Swpaul
1549123474Swpaul__stdcall static void
1550123474Swpaulndis_set_event(event)
1551123474Swpaul	ndis_event		*event;
1552123474Swpaul{
1553123474Swpaul	event->ne_event.nk_header.dh_sigstate = TRUE;
1554123474Swpaul	wakeup(event);
1555123474Swpaul	return;
1556123474Swpaul}
1557123474Swpaul
1558123474Swpaul__stdcall static void
1559123474Swpaulndis_reset_event(event)
1560123474Swpaul	ndis_event		*event;
1561123474Swpaul{
1562123474Swpaul	event->ne_event.nk_header.dh_sigstate = FALSE;
1563123474Swpaul	wakeup(event);
1564123474Swpaul	return;
1565123474Swpaul}
1566123474Swpaul
1567123474Swpaul__stdcall static uint8_t
1568123474Swpaulndis_wait_event(event, msecs)
1569123474Swpaul	ndis_event		*event;
1570123474Swpaul	uint32_t		msecs;
1571123474Swpaul{
1572123474Swpaul	int			error;
1573123474Swpaul	struct timeval		tv;
1574123474Swpaul
1575123474Swpaul	if (event->ne_event.nk_header.dh_sigstate == TRUE)
1576123474Swpaul		return(TRUE);
1577123474Swpaul
1578123474Swpaul	tv.tv_sec = 0;
1579123474Swpaul	tv.tv_usec = msecs * 1000;
1580123474Swpaul
1581123474Swpaul	error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
1582123474Swpaul
1583123474Swpaul	return(event->ne_event.nk_header.dh_sigstate);
1584123474Swpaul}
1585123474Swpaul
1586123474Swpaul__stdcall static ndis_status
1587123474Swpaulndis_unicode2ansi(dstr, sstr)
1588123474Swpaul	ndis_ansi_string		*dstr;
1589123474Swpaul	ndis_unicode_string		*sstr;
1590123474Swpaul{
1591123474Swpaul	ndis_unicode_to_ascii(sstr->nus_buf, sstr->nus_len, &dstr->nas_buf);
1592123474Swpaul	dstr->nas_len = strlen(dstr->nas_buf);
1593123474Swpaul	printf ("unicode 2 ansi...\n");
1594123474Swpaul	return (NDIS_STATUS_SUCCESS);
1595123474Swpaul}
1596123474Swpaul
1597123474Swpaul__stdcall static ndis_status
1598123474Swpaulndis_assign_pcirsrc(adapter, slot, list)
1599123474Swpaul	ndis_handle		adapter;
1600123474Swpaul	uint32_t		slot;
1601123474Swpaul	ndis_resource_list	**list;
1602123474Swpaul{
1603123474Swpaul	ndis_miniport_block	*block;
1604123474Swpaul
1605123474Swpaul	if (adapter == NULL || list == NULL)
1606123474Swpaul		return (NDIS_STATUS_FAILURE);
1607123474Swpaul
1608123474Swpaul	block = (ndis_miniport_block *)adapter;
1609123474Swpaul	*list = block->nmb_rlist;
1610123474Swpaul
1611123474Swpaul	printf ("assign PCI resources...\n");
1612123474Swpaul	return (NDIS_STATUS_SUCCESS);
1613123474Swpaul}
1614123474Swpaul
1615123474Swpaul__stdcall static ndis_status
1616123474Swpaulndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
1617123474Swpaul	ndis_miniport_interrupt	*intr;
1618123474Swpaul	ndis_handle		adapter;
1619123474Swpaul	uint32_t		ivec;
1620123474Swpaul	uint32_t		ilevel;
1621123474Swpaul	uint8_t			reqisr;
1622123474Swpaul	uint8_t			shared;
1623123474Swpaul	ndis_interrupt_mode	imode;
1624123474Swpaul{
1625123474Swpaul
1626123474Swpaul	return(NDIS_STATUS_SUCCESS);
1627123474Swpaul}
1628123474Swpaul
1629123474Swpaul__stdcall static void
1630123474Swpaulndis_deregister_intr(intr)
1631123474Swpaul	ndis_miniport_interrupt	*intr;
1632123474Swpaul{
1633123474Swpaul	return;
1634123474Swpaul}
1635123474Swpaul
1636123474Swpaul__stdcall static void
1637123474Swpaulndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
1638123474Swpaul	ndis_handle		adapter;
1639123474Swpaul	void			*shutdownctx;
1640123474Swpaul	ndis_shutdown_handler	shutdownfunc;
1641123474Swpaul{
1642123474Swpaul	ndis_miniport_block	*block;
1643123474Swpaul	ndis_miniport_characteristics *chars;
1644123474Swpaul	struct ndis_softc	*sc;
1645123474Swpaul
1646123474Swpaul	if (adapter == NULL)
1647123474Swpaul		return;
1648123474Swpaul
1649123474Swpaul	block = (ndis_miniport_block *)adapter;
1650123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1651123474Swpaul	chars = &sc->ndis_chars;
1652123474Swpaul
1653123474Swpaul	chars->nmc_shutdown_handler = shutdownfunc;
1654123474Swpaul	chars->nmc_rsvd0 = shutdownctx;
1655123474Swpaul
1656123474Swpaul	return;
1657123474Swpaul}
1658123474Swpaul
1659123474Swpaul__stdcall static void
1660123474Swpaulndis_deregister_shutdown(adapter)
1661123474Swpaul	ndis_handle		adapter;
1662123474Swpaul{
1663123474Swpaul	ndis_miniport_block	*block;
1664123474Swpaul	ndis_miniport_characteristics *chars;
1665123474Swpaul	struct ndis_softc	*sc;
1666123474Swpaul
1667123474Swpaul	if (adapter == NULL)
1668123474Swpaul		return;
1669123474Swpaul
1670123474Swpaul	block = (ndis_miniport_block *)adapter;
1671123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1672123474Swpaul	chars = &sc->ndis_chars;
1673123474Swpaul
1674123474Swpaul	chars->nmc_shutdown_handler = NULL;
1675123474Swpaul	chars->nmc_rsvd0 = NULL;
1676123474Swpaul
1677123474Swpaul	return;
1678123474Swpaul}
1679123474Swpaul
1680123474Swpaul__stdcall static uint32_t
1681123474Swpaulndis_numpages(buf)
1682123474Swpaul	ndis_buffer		*buf;
1683123474Swpaul{
1684123474Swpaul	return(howmany(buf->nb_bytecount, PAGE_SIZE));
1685123474Swpaul}
1686123474Swpaul
1687123474Swpaul__stdcall static void
1688123474Swpaulndis_query_bufoffset(buf, off, len)
1689123474Swpaul	ndis_buffer		*buf;
1690123474Swpaul	uint32_t		*off;
1691123474Swpaul	uint32_t		*len;
1692123474Swpaul{
1693123474Swpaul	*off = (uint32_t)buf->nb_mappedsystemva & (PAGE_SIZE - 1);
1694123474Swpaul	*len = buf->nb_bytecount;
1695123474Swpaul
1696123474Swpaul	return;
1697123474Swpaul}
1698123474Swpaul
1699123474Swpaul__stdcall static void
1700123474Swpaulndis_sleep(usecs)
1701123474Swpaul	uint32_t		usecs;
1702123474Swpaul{
1703123474Swpaul	struct timeval		tv;
1704123474Swpaul	uint32_t		dummy;
1705123474Swpaul
1706123474Swpaul	tv.tv_sec = 0;
1707123474Swpaul	tv.tv_usec = usecs;
1708123474Swpaul
1709123474Swpaul	tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
1710123474Swpaul	return;
1711123474Swpaul}
1712123474Swpaul
1713123474Swpaul__stdcall static uint32_t
1714123474Swpaulndis_read_pccard_amem(handle, offset, buf, len)
1715123474Swpaul	ndis_handle		handle;
1716123474Swpaul	uint32_t		offset;
1717123474Swpaul	void			*buf;
1718123474Swpaul	uint32_t		len;
1719123474Swpaul{
1720123474Swpaul	struct ndis_softc	*sc;
1721123474Swpaul	ndis_miniport_block	*block;
1722123474Swpaul	bus_space_handle_t	bh;
1723123474Swpaul	bus_space_tag_t		bt;
1724123474Swpaul	char			*dest;
1725123474Swpaul	int			i;
1726123474Swpaul
1727123474Swpaul	if (handle == NULL)
1728123474Swpaul		return(0);
1729123474Swpaul
1730123474Swpaul	block = (ndis_miniport_block *)handle;
1731123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1732123474Swpaul	dest = buf;
1733123474Swpaul
1734123474Swpaul	bh = rman_get_bushandle(sc->ndis_res_am);
1735123474Swpaul	bt = rman_get_bustag(sc->ndis_res_am);
1736123474Swpaul
1737123474Swpaul	for (i = 0; i < len; i++)
1738123474Swpaul		dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2));
1739123474Swpaul
1740123474Swpaul	return(i);
1741123474Swpaul}
1742123474Swpaul
1743123474Swpaul__stdcall static uint32_t
1744123474Swpaulndis_write_pccard_amem(handle, offset, buf, len)
1745123474Swpaul	ndis_handle		handle;
1746123474Swpaul	uint32_t		offset;
1747123474Swpaul	void			*buf;
1748123474Swpaul	uint32_t		len;
1749123474Swpaul{
1750123474Swpaul	struct ndis_softc	*sc;
1751123474Swpaul	ndis_miniport_block	*block;
1752123474Swpaul	bus_space_handle_t	bh;
1753123474Swpaul	bus_space_tag_t		bt;
1754123474Swpaul	char			*src;
1755123474Swpaul	int			i;
1756123474Swpaul
1757123474Swpaul	if (handle == NULL)
1758123474Swpaul		return(0);
1759123474Swpaul
1760123474Swpaul	block = (ndis_miniport_block *)handle;
1761123474Swpaul	sc = (struct ndis_softc *)block->nmb_ifp;
1762123474Swpaul	src = buf;
1763123474Swpaul
1764123474Swpaul	bh = rman_get_bushandle(sc->ndis_res_am);
1765123474Swpaul	bt = rman_get_bustag(sc->ndis_res_am);
1766123474Swpaul
1767123474Swpaul	for (i = 0; i < len; i++)
1768123474Swpaul		bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]);
1769123474Swpaul
1770123474Swpaul	return(i);
1771123474Swpaul}
1772123474Swpaul
1773123474Swpaul__stdcall static ndis_list_entry *
1774123474Swpaulndis_insert_head(head, entry, lock)
1775123474Swpaul	ndis_list_entry		*head;
1776123474Swpaul	ndis_list_entry		*entry;
1777123474Swpaul	ndis_spin_lock		*lock;
1778123474Swpaul{
1779123474Swpaul	ndis_list_entry		*flink;
1780123474Swpaul
1781123474Swpaul	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
1782123474Swpaul	flink = head->nle_flink;
1783123474Swpaul	entry->nle_flink = flink;
1784123474Swpaul	entry->nle_blink = head;
1785123474Swpaul	flink->nle_blink = entry;
1786123474Swpaul	head->nle_flink = entry;
1787123474Swpaul	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
1788123474Swpaul
1789123474Swpaul	return(flink);
1790123474Swpaul}
1791123474Swpaul
1792123474Swpaul__stdcall static ndis_list_entry *
1793123474Swpaulndis_remove_head(head, lock)
1794123474Swpaul	ndis_list_entry		*head;
1795123474Swpaul	ndis_spin_lock		*lock;
1796123474Swpaul{
1797123474Swpaul	ndis_list_entry		*flink;
1798123474Swpaul	ndis_list_entry		*entry;
1799123474Swpaul
1800123474Swpaul	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
1801123474Swpaul	entry = head->nle_flink;
1802123474Swpaul	flink = entry->nle_flink;
1803123474Swpaul	head->nle_flink = flink;
1804123474Swpaul	flink->nle_blink = head;
1805123474Swpaul	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
1806123474Swpaul
1807123474Swpaul	return(entry);
1808123474Swpaul}
1809123474Swpaul
1810123474Swpaul__stdcall static ndis_list_entry *
1811123474Swpaulndis_insert_tail(head, entry, lock)
1812123474Swpaul	ndis_list_entry		*head;
1813123474Swpaul	ndis_list_entry		*entry;
1814123474Swpaul	ndis_spin_lock		*lock;
1815123474Swpaul{
1816123474Swpaul	ndis_list_entry		*blink;
1817123474Swpaul
1818123474Swpaul	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
1819123474Swpaul	blink = head->nle_blink;
1820123474Swpaul	entry->nle_flink = head;
1821123474Swpaul	entry->nle_blink = blink;
1822123474Swpaul	blink->nle_flink = entry;
1823123474Swpaul	head->nle_blink = entry;
1824123474Swpaul	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
1825123474Swpaul
1826123474Swpaul	return(blink);
1827123474Swpaul}
1828123474Swpaul
1829123474Swpaul__stdcall static uint8_t
1830123474Swpaulndis_sync_with_intr(intr, syncfunc, syncctx)
1831123474Swpaul	ndis_miniport_interrupt	*intr;
1832123474Swpaul	void			*syncfunc;
1833123474Swpaul	void			*syncctx;
1834123474Swpaul{
1835123474Swpaul	__stdcall uint8_t (*sync)(void *);
1836123474Swpaul
1837123474Swpaul	if (syncfunc == NULL || syncctx == NULL)
1838123474Swpaul		return(0);
1839123474Swpaul
1840123474Swpaul	sync = syncfunc;
1841123474Swpaul	return(sync(syncctx));
1842123474Swpaul}
1843123474Swpaul
1844123504Swpaul/*
1845123504Swpaul * Return the number of 100 nanosecond intervals since
1846123504Swpaul * January 1, 1601. (?!?!)
1847123504Swpaul */
1848123474Swpaul__stdcall static void
1849123504Swpaulndis_time(tval)
1850123504Swpaul	uint64_t		*tval;
1851123504Swpaul{
1852123504Swpaul	struct timespec		ts;
1853123504Swpaul	nanotime(&ts);
1854123504Swpaul	*tval = (ts.tv_nsec / 100) + (ts.tv_nsec * 10000000);
1855123504Swpaul	return;
1856123504Swpaul}
1857123504Swpaul
1858123504Swpaul__stdcall static void
1859123474Swpauldummy()
1860123474Swpaul{
1861123474Swpaul	printf ("NDIS dummy called...\n");
1862123474Swpaul	return;
1863123474Swpaul}
1864123474Swpaul
1865123474Swpaulimage_patch_table ndis_functbl[] = {
1866123504Swpaul	{ "NdisGetCurrentSystemTime",	(FUNC)ndis_time },
1867123474Swpaul	{ "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
1868123474Swpaul	{ "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
1869123474Swpaul	{ "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
1870123474Swpaul	{ "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
1871123474Swpaul	{ "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
1872123474Swpaul	{ "NdisInitializeWrapper",	(FUNC)ndis_initwrap },
1873123474Swpaul	{ "NdisMRegisterMiniport",	(FUNC)ndis_register_miniport },
1874123474Swpaul	{ "NdisAllocateMemoryWithTag",	(FUNC)ndis_malloc_withtag },
1875123474Swpaul	{ "NdisAllocateMemory",		(FUNC)ndis_malloc },
1876123474Swpaul	{ "NdisMSetAttributesEx",	(FUNC)ndis_setattr_ex },
1877123474Swpaul	{ "NdisCloseConfiguration",	(FUNC)ndis_close_cfg },
1878123474Swpaul	{ "NdisReadConfiguration",	(FUNC)ndis_read_cfg },
1879123474Swpaul	{ "NdisOpenConfiguration",	(FUNC)ndis_open_cfg },
1880123474Swpaul	{ "NdisReleaseSpinLock",	(FUNC)ndis_unlock },
1881123474Swpaul	{ "NdisDprAcquireSpinLock",	(FUNC)ndis_lock },
1882123474Swpaul	{ "NdisDprReleaseSpinLock",	(FUNC)ndis_unlock },
1883123474Swpaul	{ "NdisAcquireSpinLock",	(FUNC)ndis_lock },
1884123474Swpaul	{ "NdisAllocateSpinLock",	(FUNC)ndis_create_lock },
1885123474Swpaul	{ "NdisFreeSpinLock",		(FUNC)ndis_destroy_lock },
1886123474Swpaul	{ "NdisFreeMemory",		(FUNC)ndis_free },
1887123474Swpaul	{ "NdisReadPciSlotInformation",	(FUNC)ndis_read_pci },
1888123474Swpaul	{ "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
1889123474Swpaul	{ "NdisWriteErrorLogEntry",	(FUNC)ndis_syslog },
1890123474Swpaul	{ "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
1891123474Swpaul	{ "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
1892123474Swpaul	{ "NdisMInitializeTimer",	(FUNC)ndis_create_timer },
1893123474Swpaul	{ "NdisSetTimer",		(FUNC)ndis_set_timer },
1894123474Swpaul	{ "NdisMCancelTimer",		(FUNC)ndis_cancel_timer },
1895123474Swpaul	{ "NdisMSetPeriodicTimer",	(FUNC)ndis_set_periodic_timer },
1896123474Swpaul	{ "NdisMQueryAdapterResources",	(FUNC)ndis_query_resources },
1897123474Swpaul	{ "NdisMRegisterIoPortRange",	(FUNC)ndis_register_ioport },
1898123474Swpaul	{ "NdisMDeregisterIoPortRange",	(FUNC)ndis_deregister_ioport },
1899123474Swpaul	{ "NdisReadNetworkAddress",	(FUNC)ndis_read_netaddr },
1900123474Swpaul	{ "NdisMAllocateMapRegisters",	(FUNC)ndis_alloc_mapreg },
1901123474Swpaul        { "NdisMFreeMapRegisters",	(FUNC)ndis_free_mapreg },
1902123474Swpaul	{ "NdisMAllocateSharedMemory",	(FUNC)ndis_alloc_sharedmem },
1903123474Swpaul	{ "NdisMMapIoSpace",		(FUNC)ndis_map_iospace },
1904123474Swpaul	{ "NdisMUnmapIoSpace",		(FUNC)ndis_unmap_iospace },
1905123474Swpaul	{ "NdisGetCacheFillSize",	(FUNC)ndis_cachefill },
1906123474Swpaul	{ "NdisMGetDmaAlignment",	(FUNC)ndis_dma_align },
1907123474Swpaul	{ "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
1908123474Swpaul	{ "NdisAllocatePacketPool",	(FUNC)ndis_alloc_packetpool },
1909123474Swpaul	{ "NdisAllocatePacketPoolEx",	(FUNC)ndis_ex_alloc_packetpool },
1910123474Swpaul	{ "NdisAllocatePacket",		(FUNC)ndis_alloc_packet },
1911123474Swpaul	{ "NdisFreePacket",		(FUNC)ndis_release_packet },
1912123474Swpaul	{ "NdisFreePacketPool",		(FUNC)ndis_free_packetpool },
1913123474Swpaul	{ "NdisAllocateBufferPool",	(FUNC)ndis_alloc_bufpool },
1914123474Swpaul	{ "NdisAllocateBuffer",		(FUNC)ndis_alloc_buf },
1915123474Swpaul	{ "NdisQueryBuffer",		(FUNC)ndis_query_buf },
1916123474Swpaul	{ "NdisQueryBufferSafe",	(FUNC)ndis_query_buf_safe },
1917123474Swpaul	{ "NdisFreeBuffer",		(FUNC)ndis_release_buf },
1918123474Swpaul	{ "NdisFreeBufferPool",		(FUNC)ndis_free_bufpool },
1919123474Swpaul	{ "NdisInterlockedIncrement",	(FUNC)ndis_interlock_inc },
1920123474Swpaul	{ "NdisInterlockedDecrement",	(FUNC)ndis_interlock_dec },
1921123474Swpaul	{ "NdisInitializeEvent",	(FUNC)ndis_init_event },
1922123474Swpaul	{ "NdisSetEvent",		(FUNC)ndis_set_event },
1923123474Swpaul	{ "NdisResetEvent",		(FUNC)ndis_reset_event },
1924123474Swpaul	{ "NdisWaitEvent",		(FUNC)ndis_wait_event },
1925123474Swpaul	{ "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
1926123474Swpaul	{ "NdisMPciAssignResources",	(FUNC)ndis_assign_pcirsrc },
1927123474Swpaul	{ "NdisMFreeSharedMemory",	(FUNC)ndis_free_sharedmem },
1928123474Swpaul	{ "NdisMRegisterInterrupt",	(FUNC)ndis_register_intr },
1929123474Swpaul	{ "NdisMDeregisterInterrupt",	(FUNC)ndis_deregister_intr },
1930123474Swpaul	{ "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
1931123474Swpaul	{ "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
1932123474Swpaul	{ "NDIS_BUFFER_TO_SPAN_PAGES",	(FUNC)ndis_numpages },
1933123474Swpaul	{ "NdisQueryBufferOffset",	(FUNC)ndis_query_bufoffset },
1934123474Swpaul	{ "NdisAdjustBufferLength",	(FUNC)ndis_adjust_buflen },
1935123474Swpaul	{ "NdisPacketPoolUsage",	(FUNC)ndis_packetpool_use },
1936123474Swpaul	{ "NdisMSleep",			(FUNC)ndis_sleep },
1937123474Swpaul	{ "NdisUnchainBufferAtFront",	(FUNC)ndis_unchain_headbuf },
1938123474Swpaul	{ "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
1939123474Swpaul	{ "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
1940123474Swpaul
1941123474Swpaul	/*
1942123474Swpaul	 * This last entry is a catch-all for any function we haven't
1943123474Swpaul	 * implemented yet. The PE import list patching routine will
1944123474Swpaul	 * use it for any function that doesn't have an explicit match
1945123474Swpaul	 * in this table.
1946123474Swpaul	 */
1947123474Swpaul
1948123474Swpaul	{ NULL, (FUNC)dummy },
1949123474Swpaul
1950123474Swpaul	/* End of list. */
1951123474Swpaul
1952123474Swpaul	{ NULL, NULL },
1953123474Swpaul};
1954123474Swpaul
1955