subr_ndis.c revision 123695
1/*
2 * Copyright (c) 2003
3 *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *	This product includes software developed by Bill Paul.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD: head/sys/compat/ndis/subr_ndis.c 123695 2003-12-21 00:00:08Z wpaul $");
35
36/*
37 * This file implements a translation layer between the BSD networking
38 * infrasturcture and Windows(R) NDIS network driver modules. A Windows
39 * NDIS driver calls into several functions in the NDIS.SYS Windows
40 * kernel module and exports a table of functions designed to be called
41 * by the NDIS subsystem. Using the PE loader, we can patch our own
42 * versions of the NDIS routines into a given Windows driver module and
43 * convince the driver that it is in fact running on Windows.
44 *
45 * We provide a table of all our implemented NDIS routines which is patched
46 * into the driver object code. All our exported routines must use the
47 * _stdcall calling convention, since that's what the Windows object code
48 * expects.
49 */
50
51
52#include <sys/param.h>
53#include <sys/types.h>
54#include <sys/errno.h>
55
56#include <sys/callout.h>
57#include <sys/kernel.h>
58#include <sys/systm.h>
59#include <sys/malloc.h>
60#include <sys/lock.h>
61#include <sys/mutex.h>
62#include <sys/socket.h>
63#include <sys/sysctl.h>
64#include <sys/timespec.h>
65
66#include <net/if.h>
67#include <net/if_arp.h>
68#include <net/ethernet.h>
69#include <net/if_dl.h>
70#include <net/if_media.h>
71
72#include <machine/bus_memio.h>
73#include <machine/bus_pio.h>
74#include <machine/bus.h>
75#include <machine/resource.h>
76
77#include <sys/bus.h>
78#include <sys/rman.h>
79
80#include <machine/stdarg.h>
81
82#include <net80211/ieee80211_var.h>
83#include <net80211/ieee80211_ioctl.h>
84
85#include <dev/pci/pcireg.h>
86#include <dev/pci/pcivar.h>
87
88#include <compat/ndis/pe_var.h>
89#include <compat/ndis/resource_var.h>
90#include <compat/ndis/ntoskrnl_var.h>
91#include <compat/ndis/ndis_var.h>
92#include <compat/ndis/cfg_var.h>
93#include <dev/if_ndis/if_ndisvar.h>
94
95#define __stdcall __attribute__((__stdcall__))
96#define FUNC void(*)(void)
97
98static struct mtx ndis_interlock;
99static int ndis_inits = 0;
100
101__stdcall static void ndis_initwrap(ndis_handle,
102	ndis_driver_object *, void *, void *);
103__stdcall static ndis_status ndis_register_miniport(ndis_handle,
104	ndis_miniport_characteristics *, int);
105__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
106__stdcall static ndis_status ndis_malloc(void **,
107	uint32_t, uint32_t, ndis_physaddr);
108__stdcall static void ndis_free(void *, uint32_t, uint32_t);
109__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
110	uint32_t, uint32_t, ndis_interface_type);
111__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
112__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle,
113	uint32_t, ndis_unicode_string *, ndis_handle *);
114__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle,
115	ndis_unicode_string *, ndis_handle *);
116static ndis_status ndis_encode_parm(ndis_miniport_block *,
117	struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
118static ndis_status ndis_decode_parm(ndis_miniport_block *,
119	ndis_config_parm *, char *);
120__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
121	ndis_handle, ndis_unicode_string *, ndis_parm_type);
122__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle,
123	ndis_unicode_string *, ndis_config_parm *);
124__stdcall static void ndis_close_cfg(ndis_handle);
125__stdcall static void ndis_create_lock(ndis_spin_lock *);
126__stdcall static void ndis_destroy_lock(ndis_spin_lock *);
127__stdcall static void ndis_lock(ndis_spin_lock *);
128__stdcall static void ndis_unlock(ndis_spin_lock *);
129__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
130	uint32_t, void *, uint32_t);
131__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
132	uint32_t, void *, uint32_t);
133static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
134static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
135__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
136	uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
137__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
138__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *,
139	ndis_timer_function, void *);
140static void ndis_timercall(void *);
141__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t);
142static void ndis_tick(void *);
143__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
144__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *);
145__stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
146	ndis_resource_list *, uint32_t *);
147__stdcall static ndis_status ndis_register_ioport(void **,
148	ndis_handle, uint32_t, uint32_t);
149__stdcall static void ndis_deregister_ioport(ndis_handle,
150	uint32_t, uint32_t, void *);
151__stdcall static void ndis_read_netaddr(ndis_status *, void **,
152	uint32_t *, ndis_handle);
153__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
154	uint32_t, uint8_t, uint32_t, uint32_t);
155__stdcall static void ndis_free_mapreg(ndis_handle);
156static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
157__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
158	uint8_t, void **, ndis_physaddr *);
159__stdcall static void ndis_alloc_sharedmem_async(ndis_handle,
160	uint32_t, uint8_t, void *);
161__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
162	uint8_t, void *, ndis_physaddr);
163__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
164	ndis_physaddr, uint32_t);
165__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
166__stdcall static uint32_t ndis_cachefill(void);
167__stdcall static uint32_t ndis_dma_align(ndis_handle);
168__stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
169	uint8_t, uint32_t);
170__stdcall static void ndis_alloc_packetpool(ndis_status *,
171	ndis_handle *, uint32_t, uint32_t);
172__stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
173	ndis_handle *, uint32_t, uint32_t, uint32_t);
174__stdcall static uint32_t ndis_packetpool_use(ndis_handle);
175__stdcall static void ndis_free_packetpool(ndis_handle);
176__stdcall static void ndis_alloc_packet(ndis_status *,
177	ndis_packet **, ndis_handle);
178__stdcall static void ndis_release_packet(ndis_packet *);
179__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
180__stdcall static void ndis_alloc_bufpool(ndis_status *,
181	ndis_handle *, uint32_t);
182__stdcall static void ndis_free_bufpool(ndis_handle);
183__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
184	ndis_handle, void *, uint32_t);
185__stdcall static void ndis_release_buf(ndis_buffer *);
186__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
187__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
188	uint32_t *, uint32_t);
189__stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
190__stdcall static uint32_t ndis_interlock_inc(uint32_t *);
191__stdcall static uint32_t ndis_interlock_dec(uint32_t *);
192__stdcall static void ndis_init_event(ndis_event *);
193__stdcall static void ndis_set_event(ndis_event *);
194__stdcall static void ndis_reset_event(ndis_event *);
195__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
196__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
197	ndis_unicode_string *);
198__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
199	ndis_ansi_string *);
200__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
201	uint32_t, ndis_resource_list **);
202__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
203	ndis_handle, uint32_t, uint32_t, uint8_t,
204	uint8_t, ndis_interrupt_mode);
205__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
206__stdcall static void ndis_register_shutdown(ndis_handle, void *,
207	ndis_shutdown_handler);
208__stdcall static void ndis_deregister_shutdown(ndis_handle);
209__stdcall static uint32_t ndis_numpages(ndis_buffer *);
210__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
211__stdcall static void ndis_query_bufoffset(ndis_buffer *,
212	uint32_t *, uint32_t *);
213__stdcall static void ndis_sleep(uint32_t);
214__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
215	uint32_t, void *, uint32_t);
216__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
217	uint32_t, void *, uint32_t);
218__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *,
219	ndis_list_entry *, ndis_spin_lock *);
220__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *,
221	ndis_spin_lock *);
222__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *,
223	ndis_list_entry *, ndis_spin_lock *);
224__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
225	void *, void *);
226__stdcall static void ndis_time(uint64_t *);
227__stdcall static void ndis_init_string(ndis_unicode_string **, char *);
228__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
229__stdcall static void ndis_free_string(ndis_unicode_string *);
230__stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
231__stdcall static void ndis_termwrap(ndis_handle, void *);
232__stdcall static void ndis_get_devprop(ndis_handle, void *, void *,
233	void *, cm_resource_list *, cm_resource_list *);
234__stdcall static void dummy(void);
235
236
237int
238ndis_libinit()
239{
240	if (ndis_inits) {
241		ndis_inits++;
242		return(0);
243	}
244
245	mtx_init(&ndis_interlock, "ndislock", MTX_NETWORK_LOCK,
246	    MTX_DEF | MTX_RECURSE | MTX_DUPOK);
247
248	ndis_inits++;
249	return(0);
250}
251
252int
253ndis_libfini()
254{
255	if (ndis_inits != 1) {
256		ndis_inits--;
257		return(0);
258	}
259
260	mtx_destroy(&ndis_interlock);
261	ndis_inits--;
262
263	return(0);
264}
265
266/*
267 * NDIS deals with strings in unicode format, so we have
268 * do deal with them that way too. For now, we only handle
269 * conversion between unicode and ASCII since that's all
270 * that device drivers care about.
271 */
272
273int
274ndis_ascii_to_unicode(ascii, unicode)
275	char			*ascii;
276	uint16_t		**unicode;
277{
278	uint16_t		*ustr;
279	int			i;
280
281	if (*unicode == NULL)
282		*unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
283
284	if (*unicode == NULL)
285		return(ENOMEM);
286	ustr = *unicode;
287	for (i = 0; i < strlen(ascii); i++) {
288		*ustr = (uint16_t)ascii[i];
289		ustr++;
290	}
291
292	return(0);
293}
294
295int
296ndis_unicode_to_ascii(unicode, ulen, ascii)
297	uint16_t		*unicode;
298	int			ulen;
299	char			**ascii;
300{
301	uint8_t			*astr;
302	int			i;
303
304	if (*ascii == NULL)
305		*ascii = malloc(ulen, M_DEVBUF, M_WAITOK);
306
307	if (*ascii == NULL)
308		return(ENOMEM);
309	astr = *ascii;
310	for (i = 0; i < ulen; i++) {
311		*astr = (uint8_t)unicode[i];
312		astr++;
313	}
314
315	return(0);
316}
317
318__stdcall static void
319ndis_initwrap(wrapper, drv_obj, path, unused)
320	ndis_handle		wrapper;
321	ndis_driver_object	*drv_obj;
322	void			*path;
323	void			*unused;
324{
325	ndis_driver_object	**drv;
326
327	drv = wrapper;
328	*drv = drv_obj;
329
330	return;
331}
332
333__stdcall static void
334ndis_termwrap(handle, syspec)
335	ndis_handle		handle;
336	void			*syspec;
337{
338	return;
339}
340
341__stdcall static ndis_status
342ndis_register_miniport(handle, characteristics, len)
343	ndis_handle		handle;
344	ndis_miniport_characteristics *characteristics;
345	int			len;
346{
347	ndis_driver_object	*drv;
348
349	drv = handle;
350	bcopy((char *)characteristics, (char *)&drv->ndo_chars,
351	    sizeof(ndis_miniport_characteristics));
352	return(NDIS_STATUS_SUCCESS);
353}
354
355__stdcall static ndis_status
356ndis_malloc_withtag(vaddr, len, tag)
357	void			**vaddr;
358	uint32_t		len;
359	uint32_t		tag;
360{
361	void			*mem;
362
363	mem = malloc(len, M_DEVBUF, M_NOWAIT);
364	if (mem == NULL)
365		return(NDIS_STATUS_RESOURCES);
366	*vaddr = mem;
367
368	return(NDIS_STATUS_SUCCESS);
369}
370
371__stdcall static ndis_status
372ndis_malloc(vaddr, len, flags, highaddr)
373	void			**vaddr;
374	uint32_t		len;
375	uint32_t		flags;
376	ndis_physaddr		highaddr;
377{
378	void			*mem;
379
380	mem = malloc(len, M_DEVBUF, M_NOWAIT);
381	if (mem == NULL)
382		return(NDIS_STATUS_RESOURCES);
383	*vaddr = mem;
384
385	return(NDIS_STATUS_SUCCESS);
386}
387
388__stdcall static void
389ndis_free(vaddr, len, flags)
390	void			*vaddr;
391	uint32_t		len;
392	uint32_t		flags;
393{
394	if (len == 0)
395		return;
396	free(vaddr, M_DEVBUF);
397	return;
398}
399
400__stdcall static ndis_status
401ndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
402			flags, iftype)
403	ndis_handle			adapter_handle;
404	ndis_handle			adapter_ctx;
405	uint32_t			hangsecs;
406	uint32_t			flags;
407	ndis_interface_type		iftype;
408{
409	ndis_miniport_block		*block;
410
411	/*
412	 * Save the adapter context, we need it for calling
413	 * the driver's internal functions.
414	 */
415	block = (ndis_miniport_block *)adapter_handle;
416	block->nmb_miniportadapterctx = adapter_ctx;
417	block->nmb_checkforhangsecs = hangsecs;
418
419	return(NDIS_STATUS_SUCCESS);
420}
421
422__stdcall static void
423ndis_open_cfg(status, cfg, wrapctx)
424	ndis_status		*status;
425	ndis_handle		*cfg;
426	ndis_handle		wrapctx;
427{
428	*cfg = wrapctx;
429	*status = NDIS_STATUS_SUCCESS;
430	return;
431}
432
433__stdcall static void
434ndis_open_cfgbyname(status, cfg, subkey, subhandle)
435	ndis_status		*status;
436	ndis_handle		cfg;
437	ndis_unicode_string	*subkey;
438	ndis_handle		*subhandle;
439{
440	*subhandle = cfg;
441	*status = NDIS_STATUS_SUCCESS;
442	return;
443}
444
445__stdcall static void
446ndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle)
447	ndis_status		*status;
448	ndis_handle		cfg;
449	uint32_t		idx;
450	ndis_unicode_string	*subkey;
451	ndis_handle		*subhandle;
452{
453	*status = NDIS_STATUS_FAILURE;
454	return;
455}
456
457static ndis_status
458ndis_encode_parm(block, oid, type, parm)
459	ndis_miniport_block	*block;
460        struct sysctl_oid	*oid;
461	ndis_parm_type		type;
462	ndis_config_parm	**parm;
463{
464	uint16_t		*unicode;
465	ndis_unicode_string	*ustr;
466
467	unicode = (uint16_t *)&block->nmb_dummybuf;
468
469	switch(type) {
470	case ndis_parm_string:
471		ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
472		(*parm)->ncp_type = ndis_parm_string;
473		ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
474		ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
475		ustr->nus_buf = unicode;
476		break;
477	case ndis_parm_int:
478		(*parm)->ncp_type = ndis_parm_int;
479		(*parm)->ncp_parmdata.ncp_intdata =
480		    strtol((char *)oid->oid_arg1, NULL, 10);
481		break;
482	case ndis_parm_hexint:
483		(*parm)->ncp_type = ndis_parm_hexint;
484		(*parm)->ncp_parmdata.ncp_intdata =
485		    strtoul((char *)oid->oid_arg1, NULL, 16);
486		break;
487	default:
488		return(NDIS_STATUS_FAILURE);
489		break;
490	}
491
492	return(NDIS_STATUS_SUCCESS);
493}
494
495__stdcall static void
496ndis_read_cfg(status, parm, cfg, key, type)
497	ndis_status		*status;
498	ndis_config_parm	**parm;
499	ndis_handle		cfg;
500	ndis_unicode_string	*key;
501	ndis_parm_type		type;
502{
503	char			*keystr = NULL;
504	uint16_t		*unicode;
505	ndis_miniport_block	*block;
506	struct ndis_softc	*sc;
507        struct sysctl_oid	*oidp;
508	struct sysctl_ctx_entry	*e;
509
510	block = (ndis_miniport_block *)cfg;
511	sc = (struct ndis_softc *)block->nmb_ifp;
512
513	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
514
515	*parm = &block->nmb_replyparm;
516	bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
517	unicode = (uint16_t *)&block->nmb_dummybuf;
518
519	/*
520	 * See if registry key is already in a list of known keys
521	 * included with the driver.
522	 */
523	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
524		oidp = e->entry;
525		if (strcmp(oidp->oid_name, keystr) == 0) {
526			if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
527				free(keystr, M_DEVBUF);
528				*status = NDIS_STATUS_FAILURE;
529				return;
530			}
531			*status = ndis_encode_parm(block, oidp, type, parm);
532			free(keystr, M_DEVBUF);
533			return;
534		}
535	}
536
537	/*
538	 * If the key didn't match, add it to the list of dynamically
539	 * created ones. Sometimes, drivers refer to registry keys
540	 * that aren't documented in their .INF files. These keys
541	 * are supposed to be created by some sort of utility or
542	 * control panel snap-in that comes with the driver software.
543	 * Sometimes it's useful to be able to manipulate these.
544	 * If the driver requests the key in the form of a string,
545	 * make its default value an empty string, otherwise default
546	 * it to "0".
547	 */
548
549	if (type == ndis_parm_int || type == ndis_parm_hexint)
550		ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
551		    "UNSET", CTLFLAG_RW);
552	else
553		ndis_add_sysctl(sc, keystr, "(dynamic string key)",
554		    "UNSET", CTLFLAG_RW);
555
556	free(keystr, M_DEVBUF);
557	*status = NDIS_STATUS_FAILURE;
558	return;
559}
560
561static ndis_status
562ndis_decode_parm(block, parm, val)
563	ndis_miniport_block	*block;
564	ndis_config_parm	*parm;
565	char			*val;
566{
567	uint16_t		*unicode;
568	ndis_unicode_string	*ustr;
569
570	unicode = (uint16_t *)&block->nmb_dummybuf;
571
572	switch(parm->ncp_type) {
573	case ndis_parm_string:
574		ustr = &parm->ncp_parmdata.ncp_stringdata;
575		ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &val);
576		break;
577	case ndis_parm_int:
578		sprintf(val, "%ul", parm->ncp_parmdata.ncp_intdata);
579		break;
580	case ndis_parm_hexint:
581		sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
582		break;
583	default:
584		return(NDIS_STATUS_FAILURE);
585		break;
586	}
587	return(NDIS_STATUS_SUCCESS);
588}
589
590__stdcall static void
591ndis_write_cfg(status, cfg, key, parm)
592	ndis_status		*status;
593	ndis_handle		cfg;
594	ndis_unicode_string	*key;
595	ndis_config_parm	*parm;
596{
597	char			*keystr = NULL;
598	ndis_miniport_block	*block;
599	struct ndis_softc	*sc;
600        struct sysctl_oid	*oidp;
601	struct sysctl_ctx_entry	*e;
602	char			val[256];
603
604	block = (ndis_miniport_block *)cfg;
605	sc = (struct ndis_softc *)block->nmb_ifp;
606
607	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
608
609	/* Decode the parameter into a string. */
610	*status = ndis_decode_parm(block, parm, val);
611	if (*status != NDIS_STATUS_SUCCESS) {
612		free(keystr, M_DEVBUF);
613		return;
614	}
615
616	/* See if the key already exists. */
617
618	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
619		oidp = e->entry;
620		if (strcmp(oidp->oid_name, keystr) == 0) {
621			/* Found it, set the value. */
622			strcpy((char *)oidp->oid_arg1, val);
623			free(keystr, M_DEVBUF);
624			return;
625		}
626	}
627
628	/* Not found, add a new key with the specified value. */
629	ndis_add_sysctl(sc, keystr, "(dynamically set key)",
630		    val, CTLFLAG_RW);
631
632	free(keystr, M_DEVBUF);
633	*status = NDIS_STATUS_SUCCESS;
634	return;
635}
636
637__stdcall static void
638ndis_close_cfg(cfg)
639	ndis_handle		cfg;
640{
641	return;
642}
643
644__stdcall static void
645ndis_create_lock(lock)
646	ndis_spin_lock		*lock;
647{
648	struct mtx		*mtx;
649
650	mtx = malloc(sizeof(struct mtx), M_DEVBUF, M_NOWAIT|M_ZERO);
651	if (mtx == NULL)
652		return;
653	mtx_init(mtx, "ndislock", "ndis spin lock",
654	    MTX_DEF | MTX_RECURSE | MTX_DUPOK);
655	lock->nsl_spinlock = (ndis_kspin_lock)mtx;
656
657	return;
658}
659
660__stdcall static void
661ndis_destroy_lock(lock)
662	ndis_spin_lock		*lock;
663{
664	struct mtx		*ndis_mtx;
665
666	ndis_mtx = (struct mtx *)lock->nsl_spinlock;
667	mtx_destroy(ndis_mtx);
668	free(ndis_mtx, M_DEVBUF);
669
670	return;
671}
672
673__stdcall static void
674ndis_lock(lock)
675	ndis_spin_lock		*lock;
676{
677	if (lock == NULL)
678		return;
679	mtx_lock((struct mtx *)lock->nsl_spinlock);
680
681	return;
682}
683
684__stdcall static void
685ndis_unlock(lock)
686	ndis_spin_lock		*lock;
687{
688	if (lock == NULL)
689		return;
690	mtx_unlock((struct mtx *)lock->nsl_spinlock);
691
692	return;
693}
694
695__stdcall static uint32_t
696ndis_read_pci(adapter, slot, offset, buf, len)
697	ndis_handle		adapter;
698	uint32_t		slot;
699	uint32_t		offset;
700	void			*buf;
701	uint32_t		len;
702{
703	ndis_miniport_block	*block;
704	int			i;
705	char			*dest;
706
707	block = (ndis_miniport_block *)adapter;
708	dest = buf;
709	if (block == NULL || block->nmb_dev == NULL)
710		return(0);
711
712	for (i = 0; i < len; i++)
713		dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
714
715	return(len);
716}
717
718__stdcall static uint32_t
719ndis_write_pci(adapter, slot, offset, buf, len)
720	ndis_handle		adapter;
721	uint32_t		slot;
722	uint32_t		offset;
723	void			*buf;
724	uint32_t		len;
725{
726	ndis_miniport_block	*block;
727	int			i;
728	char			*dest;
729
730	block = (ndis_miniport_block *)adapter;
731	dest = buf;
732
733	if (block == NULL || block->nmb_dev == NULL)
734		return(0);
735
736	for (i = 0; i < len; i++)
737		pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
738
739	return(len);
740}
741
742/*
743 * The errorlog routine uses a variable argument list, so we
744 * have to declare it this way.
745 */
746static void
747ndis_syslog(ndis_handle adapter, ndis_error_code code,
748	uint32_t numerrors, ...)
749{
750	ndis_miniport_block	*block;
751	va_list			ap;
752	int			i;
753
754	block = (ndis_miniport_block *)adapter;
755
756	printf ("NDIS ERROR: %x\n", code);
757	printf ("NDIS NUMERRORS: %x\n", numerrors);
758
759	va_start(ap, numerrors);
760	for (i = 0; i < numerrors; i++)
761		printf ("argptr: %p\n", va_arg(ap, void *));
762	va_end(ap);
763
764	return;
765}
766
767static void
768ndis_map_cb(arg, segs, nseg, error)
769	void			*arg;
770	bus_dma_segment_t	*segs;
771	int			nseg;
772	int			error;
773{
774	struct ndis_map_arg	*ctx;
775	int			i;
776
777	if (error)
778		return;
779
780	ctx = arg;
781
782	for (i = 0; i < nseg; i++) {
783		ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
784		ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
785	}
786
787	ctx->nma_cnt = nseg;
788
789	return;
790}
791
792__stdcall static void
793ndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
794	ndis_handle		adapter;
795	ndis_buffer		*buf;
796	uint32_t		mapreg;
797	uint8_t			writedev;
798	ndis_paddr_unit		*addrarray;
799	uint32_t		*arraysize;
800{
801	ndis_miniport_block	*block;
802	struct ndis_softc	*sc;
803	struct ndis_map_arg	nma;
804	bus_dmamap_t		map;
805	int			error;
806
807	if (adapter == NULL)
808		return;
809
810	block = (ndis_miniport_block *)adapter;
811	sc = (struct ndis_softc *)(block->nmb_ifp);
812
813	if (mapreg > sc->ndis_mmapcnt)
814		return;
815
816	map = sc->ndis_mmaps[mapreg];
817	nma.nma_fraglist = addrarray;
818
819	error = bus_dmamap_load(sc->ndis_mtag, map,
820	    buf->nb_mappedsystemva, buf->nb_bytecount, ndis_map_cb,
821	    (void *)&nma, BUS_DMA_NOWAIT);
822
823	if (error)
824		return;
825
826	bus_dmamap_sync(sc->ndis_mtag, map,
827	    writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
828
829	*arraysize = nma.nma_cnt;
830
831	return;
832}
833
834__stdcall static void
835ndis_vtophys_unload(adapter, buf, mapreg)
836	ndis_handle		adapter;
837	ndis_buffer		*buf;
838	uint32_t		mapreg;
839{
840	ndis_miniport_block	*block;
841	struct ndis_softc	*sc;
842	bus_dmamap_t		map;
843
844	if (adapter == NULL)
845		return;
846
847	block = (ndis_miniport_block *)adapter;
848	sc = (struct ndis_softc *)(block->nmb_ifp);
849
850	if (mapreg > sc->ndis_mmapcnt)
851		return;
852
853	map = sc->ndis_mmaps[mapreg];
854
855	bus_dmamap_sync(sc->ndis_mtag, map,
856	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
857
858	bus_dmamap_unload(sc->ndis_mtag, map);
859
860	return;
861}
862
863__stdcall static void
864ndis_create_timer(timer, handle, func, ctx)
865	ndis_miniport_timer	*timer;
866	ndis_handle		*handle;
867	ndis_timer_function	func;
868	void			*ctx;
869{
870	struct callout_handle	*ch;
871
872	ch = (struct callout_handle *)&timer->nmt_dpc;
873	callout_handle_init(ch);
874	timer->nmt_timerfunc = func;
875	timer->nmt_timerctx = ctx;
876
877	return;
878}
879
880/*
881 * The driver's timer callout is __stdcall function, so we need this
882 * intermediate step.
883 */
884
885static void
886ndis_timercall(arg)
887	void		*arg;
888{
889	ndis_miniport_timer	*timer;
890	__stdcall ndis_timer_function	timerfunc;
891
892	timer = arg;
893
894	timerfunc = timer->nmt_timerfunc;
895	timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
896
897	return;
898}
899
900/*
901 * Windows specifies timeouts in milliseconds. We specify timeouts
902 * in hz. Trying to compute a tenth of a second based on hz is tricky.
903 * so we approximate. Note that we abuse the dpc portion of the
904 * miniport timer structure to hold the UNIX callout handle.
905 */
906__stdcall static void
907ndis_set_timer(timer, msecs)
908	ndis_miniport_timer	*timer;
909	uint32_t		msecs;
910{
911	struct callout_handle	*ch;
912	struct timeval		tv;
913
914	tv.tv_sec = 0;
915	tv.tv_usec = msecs * 1000;
916
917	ch = (struct callout_handle *)&timer->nmt_dpc;
918	timer->nmt_dpc.nk_sysarg2 = ndis_timercall;
919	*ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, (void *)timer,
920	    tvtohz(&tv));
921
922	return;
923}
924
925static void
926ndis_tick(arg)
927	void			*arg;
928{
929	ndis_miniport_timer	*timer;
930	struct callout_handle	*ch;
931	__stdcall ndis_timer_function	timerfunc;
932	struct timeval		tv;
933
934	timer = arg;
935
936	timerfunc = timer->nmt_timerfunc;
937	timerfunc(NULL, timer->nmt_timerctx, NULL, NULL);
938
939	/* Automatically reload timer. */
940
941	tv.tv_sec = 0;
942	tv.tv_usec = timer->nmt_ktimer.nk_period * 1000;
943	ch = (struct callout_handle *)&timer->nmt_dpc;
944	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
945	*ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer,
946	    tvtohz(&tv));
947
948	return;
949}
950
951__stdcall static void
952ndis_set_periodic_timer(timer, msecs)
953	ndis_miniport_timer	*timer;
954	uint32_t		msecs;
955{
956	struct callout_handle	*ch;
957	struct timeval		tv;
958
959	tv.tv_sec = 0;
960	tv.tv_usec = msecs * 1000;
961
962	timer->nmt_ktimer.nk_period = msecs;
963	ch = (struct callout_handle *)&timer->nmt_dpc;
964	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
965	*ch = timeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer,
966	    tvtohz(&tv));
967
968	return;
969}
970
971__stdcall static void
972ndis_cancel_timer(timer, cancelled)
973	ndis_miniport_timer	*timer;
974	uint8_t			*cancelled;
975{
976	struct callout_handle	*ch;
977
978	ch = (struct callout_handle *)&timer->nmt_dpc;
979	untimeout((timeout_t *)timer->nmt_dpc.nk_sysarg2, timer, *ch);
980
981	return;
982}
983
984__stdcall static void
985ndis_query_resources(status, adapter, list, buflen)
986	ndis_status		*status;
987	ndis_handle		adapter;
988	ndis_resource_list	*list;
989	uint32_t		*buflen;
990{
991	ndis_miniport_block	*block;
992	struct ndis_softc	*sc;
993
994	block = (ndis_miniport_block *)adapter;
995	sc = (struct ndis_softc *)block->nmb_ifp;
996
997	*buflen = sizeof(ndis_resource_list) +
998	    (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
999
1000	bcopy((char *)block->nmb_rlist, (char *)list, *buflen);
1001	*status = NDIS_STATUS_SUCCESS;
1002	return;
1003}
1004
1005__stdcall static ndis_status
1006ndis_register_ioport(offset, adapter, port, numports)
1007	void			**offset;
1008	ndis_handle		adapter;
1009	uint32_t		port;
1010	uint32_t		numports;
1011{
1012	struct ndis_miniport_block	*block;
1013	struct ndis_softc	*sc;
1014
1015	if (adapter == NULL)
1016		return(NDIS_STATUS_FAILURE);
1017
1018	block = (ndis_miniport_block *)adapter;
1019	sc = (struct ndis_softc *)(block->nmb_ifp);
1020
1021	if (sc->ndis_res_io == NULL)
1022		return(NDIS_STATUS_FAILURE);
1023
1024	if (rman_get_size(sc->ndis_res_io) != numports)
1025		return(NDIS_STATUS_INVALID_LENGTH);
1026
1027	*offset = (void *)rman_get_start(sc->ndis_res_io);
1028
1029	return(NDIS_STATUS_SUCCESS);
1030}
1031
1032__stdcall static void
1033ndis_deregister_ioport(adapter, port, numports, offset)
1034	ndis_handle		adapter;
1035	uint32_t		port;
1036	uint32_t		numports;
1037	void			*offset;
1038{
1039	return;
1040}
1041
1042__stdcall static void
1043ndis_read_netaddr(status, addr, addrlen, adapter)
1044	ndis_status		*status;
1045	void			**addr;
1046	uint32_t		*addrlen;
1047	ndis_handle		adapter;
1048{
1049	struct ndis_softc	*sc;
1050	ndis_miniport_block	*block;
1051	uint8_t			empty[] = { 0, 0, 0, 0, 0, 0 };
1052
1053	block = (ndis_miniport_block *)adapter;
1054	sc = (struct ndis_softc *)block->nmb_ifp;
1055
1056	if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1057		*status = NDIS_STATUS_FAILURE;
1058	else {
1059		*addr = sc->arpcom.ac_enaddr;
1060		*addrlen = ETHER_ADDR_LEN;
1061		*status = NDIS_STATUS_SUCCESS;
1062	}
1063
1064	return;
1065}
1066
1067__stdcall static ndis_status
1068ndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
1069	ndis_handle		adapter;
1070	uint32_t		dmachannel;
1071	uint8_t			dmasize;
1072	uint32_t		physmapneeded;
1073	uint32_t		maxmap;
1074{
1075	struct ndis_softc	*sc;
1076	ndis_miniport_block	*block;
1077	int			error, i, nseg = NDIS_MAXSEG;
1078
1079	block = (ndis_miniport_block *)adapter;
1080	sc = (struct ndis_softc *)block->nmb_ifp;
1081
1082	sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1083	    M_DEVBUF, M_NOWAIT|M_ZERO);
1084
1085	if (sc->ndis_mmaps == NULL)
1086		return(NDIS_STATUS_RESOURCES);
1087
1088	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1089	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1090	    NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1091	    NULL, NULL, &sc->ndis_mtag);
1092
1093	if (error) {
1094		free(sc->ndis_mmaps, M_DEVBUF);
1095		return(NDIS_STATUS_RESOURCES);
1096	}
1097
1098	for (i = 0; i < physmapneeded; i++)
1099		bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1100
1101	sc->ndis_mmapcnt = physmapneeded;
1102
1103	return(NDIS_STATUS_SUCCESS);
1104}
1105
1106__stdcall static void
1107ndis_free_mapreg(adapter)
1108	ndis_handle		adapter;
1109{
1110	struct ndis_softc	*sc;
1111	ndis_miniport_block	*block;
1112	int			i;
1113
1114	block = (ndis_miniport_block *)adapter;
1115	sc = (struct ndis_softc *)block->nmb_ifp;
1116
1117	for (i = 0; i < sc->ndis_mmapcnt; i++)
1118		bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1119
1120	free(sc->ndis_mmaps, M_DEVBUF);
1121
1122	bus_dma_tag_destroy(sc->ndis_mtag);
1123
1124	return;
1125}
1126
1127static void
1128ndis_mapshared_cb(arg, segs, nseg, error)
1129	void			*arg;
1130	bus_dma_segment_t	*segs;
1131	int			nseg;
1132	int			error;
1133{
1134	ndis_physaddr		*p;
1135
1136	if (error || nseg > 1)
1137		return;
1138
1139	p = arg;
1140
1141	p->np_quad = segs[0].ds_addr;
1142
1143	return;
1144}
1145
1146/*
1147 * This maps to bus_dmamem_alloc().
1148 */
1149__stdcall static void
1150ndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
1151	ndis_handle		adapter;
1152	uint32_t		len;
1153	uint8_t			cached;
1154	void			**vaddr;
1155	ndis_physaddr		*paddr;
1156{
1157	ndis_miniport_block	*block;
1158	struct ndis_softc	*sc;
1159	struct ndis_shmem	*sh;
1160	int			error;
1161
1162	if (adapter == NULL)
1163		return;
1164
1165	block = (ndis_miniport_block *)adapter;
1166	sc = (struct ndis_softc *)(block->nmb_ifp);
1167
1168	sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1169	if (sh == NULL)
1170		return;
1171
1172	error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1173	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1174	    NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
1175	    &sh->ndis_stag);
1176
1177	if (error) {
1178		free(sh, M_DEVBUF);
1179		return;
1180	}
1181
1182	error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1183	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1184
1185	if (error) {
1186		bus_dma_tag_destroy(sh->ndis_stag);
1187		free(sh, M_DEVBUF);
1188		return;
1189	}
1190
1191	error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1192	    len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1193
1194	if (error) {
1195		bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1196		bus_dma_tag_destroy(sh->ndis_stag);
1197		free(sh, M_DEVBUF);
1198		return;
1199	}
1200
1201	sh->ndis_saddr = *vaddr;
1202	sh->ndis_next = sc->ndis_shlist;
1203	sc->ndis_shlist = sh;
1204
1205	return;
1206}
1207
1208__stdcall static void
1209ndis_alloc_sharedmem_async(adapter, len, cached, ctx)
1210	ndis_handle		adapter;
1211	uint32_t		len;
1212	uint8_t			cached;
1213	void			*ctx;
1214{
1215	ndis_miniport_block	*block;
1216	struct ndis_softc	*sc;
1217	void			*vaddr;
1218	ndis_physaddr		paddr;
1219	__stdcall ndis_allocdone_handler	donefunc;
1220
1221	if (adapter == NULL)
1222		return;
1223
1224	block = (ndis_miniport_block *)adapter;
1225	sc = (struct ndis_softc *)(block->nmb_ifp);
1226	donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1227
1228	ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr);
1229	donefunc(adapter, vaddr, &paddr, len, ctx);
1230
1231	return;
1232}
1233
1234__stdcall static void
1235ndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
1236	ndis_handle		adapter;
1237	uint32_t		len;
1238	uint8_t			cached;
1239	void			*vaddr;
1240	ndis_physaddr		paddr;
1241{
1242	ndis_miniport_block	*block;
1243	struct ndis_softc	*sc;
1244	struct ndis_shmem	*sh, *prev;
1245
1246	if (vaddr == NULL || adapter == NULL)
1247		return;
1248
1249	block = (ndis_miniport_block *)adapter;
1250	sc = (struct ndis_softc *)(block->nmb_ifp);
1251	sh = prev = sc->ndis_shlist;
1252
1253	while (sh) {
1254		if (sh->ndis_saddr == vaddr)
1255			break;
1256		prev = sh;
1257		sh = sh->ndis_next;
1258	}
1259
1260	bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1261	bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1262	bus_dma_tag_destroy(sh->ndis_stag);
1263
1264	if (sh == sc->ndis_shlist)
1265		sc->ndis_shlist = sh->ndis_next;
1266	else
1267		prev->ndis_next = sh->ndis_next;
1268
1269	free(sh, M_DEVBUF);
1270
1271	return;
1272}
1273
1274__stdcall static ndis_status
1275ndis_map_iospace(vaddr, adapter, paddr, len)
1276	void			**vaddr;
1277	ndis_handle		adapter;
1278	ndis_physaddr		paddr;
1279	uint32_t		len;
1280{
1281	ndis_miniport_block	*block;
1282	struct ndis_softc	*sc;
1283
1284	if (adapter == NULL)
1285		return(NDIS_STATUS_FAILURE);
1286
1287	block = (ndis_miniport_block *)adapter;
1288	sc = (struct ndis_softc *)(block->nmb_ifp);
1289
1290	if (sc->ndis_res_mem == NULL)
1291		return(NDIS_STATUS_FAILURE);
1292
1293	*vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1294
1295	return(NDIS_STATUS_SUCCESS);
1296}
1297
1298__stdcall static void
1299ndis_unmap_iospace(adapter, vaddr, len)
1300	ndis_handle		adapter;
1301	void			*vaddr;
1302	uint32_t		len;
1303{
1304	return;
1305}
1306
1307__stdcall static uint32_t
1308ndis_cachefill(void)
1309{
1310	return(128);
1311}
1312
1313__stdcall static uint32_t
1314ndis_dma_align(handle)
1315	ndis_handle		handle;
1316{
1317	return(128);
1318}
1319
1320/*
1321 * NDIS has two methods for dealing with NICs that support DMA.
1322 * One is to just pass packets to the driver and let it call
1323 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1324 * all by itself, and the other is to let the NDIS library handle the
1325 * buffer mapping internally, and hand the driver an already populated
1326 * scatter/gather fragment list. If the driver calls
1327 * NdisMInitializeScatterGatherDma(), it wants to use the latter
1328 * method.
1329 */
1330
1331__stdcall static ndis_status
1332ndis_init_sc_dma(adapter, is64, maxphysmap)
1333	ndis_handle		adapter;
1334	uint8_t			is64;
1335	uint32_t		maxphysmap;
1336{
1337	struct ndis_softc	*sc;
1338	ndis_miniport_block	*block;
1339	int			error;
1340
1341	if (adapter == NULL)
1342		return(NDIS_STATUS_FAILURE);
1343	block = (ndis_miniport_block *)adapter;
1344	sc = (struct ndis_softc *)block->nmb_ifp;
1345
1346	/* Don't do this twice. */
1347	if (sc->ndis_sc == 1)
1348		return(NDIS_STATUS_SUCCESS);
1349
1350	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1351	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1352	    MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1353	    NULL, NULL, &sc->ndis_ttag);
1354
1355	sc->ndis_sc = 1;
1356
1357	return(NDIS_STATUS_SUCCESS);
1358}
1359
1360__stdcall static void
1361ndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
1362	ndis_status		*status;
1363	ndis_handle		*pool;
1364	uint32_t		descnum;
1365	uint32_t		protrsvdlen;
1366{
1367	ndis_packet		*cur;
1368	int			i;
1369
1370	*pool = malloc(sizeof(ndis_packet) * (descnum + 1),
1371	    M_DEVBUF, M_NOWAIT|M_ZERO);
1372
1373	if (pool == NULL) {
1374		*status = NDIS_STATUS_RESOURCES;
1375		return;
1376	}
1377
1378	cur = (ndis_packet *)*pool;
1379	cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1380	for (i = 0; i < descnum; i++) {
1381		cur->np_private.npp_head = (ndis_handle)(cur + 1);
1382		cur++;
1383	}
1384
1385	*status = NDIS_STATUS_SUCCESS;
1386	return;
1387}
1388
1389__stdcall static void
1390ndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
1391	ndis_status		*status;
1392	ndis_handle		*pool;
1393	uint32_t		descnum;
1394	uint32_t		oflowdescnum;
1395	uint32_t		protrsvdlen;
1396{
1397	return(ndis_alloc_packetpool(status, pool,
1398	    descnum + oflowdescnum, protrsvdlen));
1399}
1400
1401__stdcall static uint32_t
1402ndis_packetpool_use(pool)
1403	ndis_handle		pool;
1404{
1405	ndis_packet		*head;
1406
1407	head = (ndis_packet *)pool;
1408
1409	return(head->np_private.npp_count);
1410}
1411
1412__stdcall static void
1413ndis_free_packetpool(pool)
1414	ndis_handle		pool;
1415{
1416	free(pool, M_DEVBUF);
1417	return;
1418}
1419
1420__stdcall static void
1421ndis_alloc_packet(status, packet, pool)
1422	ndis_status		*status;
1423	ndis_packet		**packet;
1424	ndis_handle		pool;
1425{
1426	ndis_packet		*head, *pkt;
1427
1428	head = (ndis_packet *)pool;
1429
1430	if (head->np_private.npp_flags != 0x1) {
1431		*status = NDIS_STATUS_FAILURE;
1432		return;
1433	}
1434
1435	pkt = (ndis_packet *)head->np_private.npp_head;
1436
1437	if (pkt == NULL) {
1438		*status = NDIS_STATUS_RESOURCES;
1439		return;
1440	}
1441
1442	head->np_private.npp_head = pkt->np_private.npp_head;
1443
1444	pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1445	/* Save pointer to the pool. */
1446	pkt->np_private.npp_pool = head;
1447
1448	/* Set the oob offset pointer. Lots of things expect this. */
1449	pkt->np_private.npp_packetooboffset =
1450	    offsetof(ndis_packet, np_oob);
1451
1452	*packet = pkt;
1453
1454	head->np_private.npp_count++;
1455	*status = NDIS_STATUS_SUCCESS;
1456	return;
1457}
1458
1459__stdcall static void
1460ndis_release_packet(packet)
1461	ndis_packet		*packet;
1462{
1463	ndis_packet		*head;
1464
1465	if (packet == NULL || packet->np_private.npp_pool == NULL)
1466		return;
1467
1468	head = packet->np_private.npp_pool;
1469	if (head->np_private.npp_flags != 0x1)
1470		return;
1471
1472	packet->np_private.npp_head = head->np_private.npp_head;
1473	head->np_private.npp_head = (ndis_buffer *)packet;
1474	head->np_private.npp_count--;
1475
1476	return;
1477}
1478
1479__stdcall static void
1480ndis_unchain_headbuf(packet, buf)
1481	ndis_packet		*packet;
1482	ndis_buffer		**buf;
1483{
1484	ndis_packet_private	*priv;
1485
1486	if (packet == NULL || buf == NULL)
1487		return;
1488
1489	priv = &packet->np_private;
1490
1491	priv->npp_validcounts = FALSE;
1492
1493	if (priv->npp_head == priv->npp_tail) {
1494		*buf = priv->npp_head;
1495		priv->npp_head = priv->npp_tail = NULL;
1496	} else {
1497		*buf = priv->npp_head;
1498		priv->npp_head = (*buf)->nb_next;
1499	}
1500
1501	return;
1502}
1503
1504/*
1505 * The NDIS "buffer" manipulation functions are somewhat misnamed.
1506 * They don't really allocate buffers: they allocate buffer mappings.
1507 * The idea is you reserve a chunk of DMA-able memory using
1508 * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1509 * to obtain the virtual address of the DMA-able region.
1510 * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1511 */
1512
1513__stdcall static void
1514ndis_alloc_bufpool(status, pool, descnum)
1515	ndis_status		*status;
1516	ndis_handle		*pool;
1517	uint32_t		descnum;
1518{
1519	ndis_buffer		*cur;
1520	int			i;
1521
1522	*pool = malloc(sizeof(ndis_buffer) * (descnum + 1),
1523	    M_DEVBUF, M_NOWAIT|M_ZERO);
1524
1525	if (pool == NULL) {
1526		*status = NDIS_STATUS_RESOURCES;
1527		return;
1528	}
1529
1530	cur = (ndis_buffer *)*pool;
1531	cur->nb_flags = 0x1; /* mark the head of the list */
1532	for (i = 0; i < descnum; i++) {
1533		cur->nb_next = cur + 1;
1534		cur++;
1535	}
1536
1537	*status = NDIS_STATUS_SUCCESS;
1538	return;
1539}
1540
1541__stdcall static void
1542ndis_free_bufpool(pool)
1543	ndis_handle		pool;
1544{
1545	free(pool, M_DEVBUF);
1546	return;
1547}
1548
1549/*
1550 * This maps to a bus_dmamap_create() and bus_dmamap_load().
1551 */
1552__stdcall static void
1553ndis_alloc_buf(status, buffer, pool, vaddr, len)
1554	ndis_status		*status;
1555	ndis_buffer		**buffer;
1556	ndis_handle		pool;
1557	void			*vaddr;
1558	uint32_t		len;
1559{
1560	ndis_buffer		*head, *buf;
1561
1562	head = (ndis_buffer *)pool;
1563	if (head->nb_flags != 0x1) {
1564		*status = NDIS_STATUS_FAILURE;
1565		return;
1566	}
1567
1568	buf = head->nb_next;
1569
1570	if (buf == NULL) {
1571		*status = NDIS_STATUS_RESOURCES;
1572		return;
1573	}
1574
1575	head->nb_next = buf->nb_next;
1576
1577	/* Save pointer to the pool. */
1578	buf->nb_process = head;
1579
1580	buf->nb_mappedsystemva = vaddr;
1581	buf->nb_size = len;
1582	buf->nb_next = NULL;
1583
1584	*buffer = buf;
1585
1586	*status = NDIS_STATUS_SUCCESS;
1587	return;
1588}
1589
1590__stdcall static void
1591ndis_release_buf(buf)
1592	ndis_buffer		*buf;
1593{
1594	ndis_buffer		*head;
1595
1596	if (buf == NULL || buf->nb_process == NULL)
1597		return;
1598
1599	head = buf->nb_process;
1600
1601	if (head->nb_flags != 0x1)
1602		return;
1603
1604	buf->nb_next = head->nb_next;
1605	head->nb_next = buf;
1606
1607	return;
1608}
1609
1610/* Get the virtual address and length of a buffer */
1611
1612__stdcall static void
1613ndis_query_buf(buf, vaddr, len)
1614	ndis_buffer		*buf;
1615	void			**vaddr;
1616	uint32_t		*len;
1617{
1618	*vaddr = buf->nb_mappedsystemva;
1619	*len = buf->nb_bytecount;
1620
1621	return;
1622}
1623
1624/* Same as above -- we don't care about the priority. */
1625
1626__stdcall static void
1627ndis_query_buf_safe(buf, vaddr, len, prio)
1628	ndis_buffer		*buf;
1629	void			**vaddr;
1630	uint32_t		*len;
1631	uint32_t		prio;
1632{
1633	*vaddr = buf->nb_mappedsystemva;
1634	*len = buf->nb_bytecount;
1635
1636	return;
1637}
1638
1639__stdcall static void
1640ndis_adjust_buflen(buf, len)
1641	ndis_buffer		*buf;
1642	int			len;
1643{
1644	if (len > buf->nb_size)
1645		return;
1646	buf->nb_bytecount = len;
1647
1648	return;
1649}
1650
1651__stdcall static uint32_t
1652ndis_interlock_inc(addend)
1653	uint32_t		*addend;
1654{
1655	mtx_lock(&ndis_interlock);
1656	*addend++;
1657	mtx_unlock(&ndis_interlock);
1658	return(*addend);
1659}
1660
1661__stdcall static uint32_t
1662ndis_interlock_dec(addend)
1663	uint32_t		*addend;
1664{
1665	mtx_lock(&ndis_interlock);
1666	*addend--;
1667	mtx_unlock(&ndis_interlock);
1668	return(*addend);
1669}
1670
1671__stdcall static void
1672ndis_init_event(event)
1673	ndis_event		*event;
1674{
1675	event->ne_event.nk_header.dh_sigstate = FALSE;
1676	return;
1677}
1678
1679__stdcall static void
1680ndis_set_event(event)
1681	ndis_event		*event;
1682{
1683	event->ne_event.nk_header.dh_sigstate = TRUE;
1684	wakeup(event);
1685	return;
1686}
1687
1688__stdcall static void
1689ndis_reset_event(event)
1690	ndis_event		*event;
1691{
1692	event->ne_event.nk_header.dh_sigstate = FALSE;
1693	wakeup(event);
1694	return;
1695}
1696
1697__stdcall static uint8_t
1698ndis_wait_event(event, msecs)
1699	ndis_event		*event;
1700	uint32_t		msecs;
1701{
1702	int			error;
1703	struct timeval		tv;
1704
1705	if (event->ne_event.nk_header.dh_sigstate == TRUE)
1706		return(TRUE);
1707
1708	tv.tv_sec = 0;
1709	tv.tv_usec = msecs * 1000;
1710
1711	error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
1712
1713	return(event->ne_event.nk_header.dh_sigstate);
1714}
1715
1716__stdcall static ndis_status
1717ndis_unicode2ansi(dstr, sstr)
1718	ndis_ansi_string	*dstr;
1719	ndis_unicode_string	*sstr;
1720{
1721	if (dstr == NULL || sstr == NULL)
1722		return(NDIS_STATUS_FAILURE);
1723	if (ndis_unicode_to_ascii(sstr->nus_buf,
1724	    sstr->nus_len, &dstr->nas_buf))
1725		return(NDIS_STATUS_FAILURE);
1726	dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
1727	return (NDIS_STATUS_SUCCESS);
1728}
1729
1730__stdcall static ndis_status
1731ndis_ansi2unicode(dstr, sstr)
1732	ndis_unicode_string	*dstr;
1733	ndis_ansi_string	*sstr;
1734{
1735	char			*str;
1736	if (dstr == NULL || sstr == NULL)
1737		return(NDIS_STATUS_FAILURE);
1738	str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
1739	if (str == NULL)
1740		return(NDIS_STATUS_FAILURE);
1741	strncpy(str, sstr->nas_buf, sstr->nas_len);
1742	*(str + sstr->nas_len) = '\0';
1743	if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
1744		free(str, M_DEVBUF);
1745		return(NDIS_STATUS_FAILURE);
1746	}
1747	dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
1748	free(str, M_DEVBUF);
1749	return (NDIS_STATUS_SUCCESS);
1750}
1751
1752__stdcall static ndis_status
1753ndis_assign_pcirsrc(adapter, slot, list)
1754	ndis_handle		adapter;
1755	uint32_t		slot;
1756	ndis_resource_list	**list;
1757{
1758	ndis_miniport_block	*block;
1759
1760	if (adapter == NULL || list == NULL)
1761		return (NDIS_STATUS_FAILURE);
1762
1763	block = (ndis_miniport_block *)adapter;
1764	*list = block->nmb_rlist;
1765
1766	printf ("assign PCI resources...\n");
1767	return (NDIS_STATUS_SUCCESS);
1768}
1769
1770__stdcall static ndis_status
1771ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
1772	ndis_miniport_interrupt	*intr;
1773	ndis_handle		adapter;
1774	uint32_t		ivec;
1775	uint32_t		ilevel;
1776	uint8_t			reqisr;
1777	uint8_t			shared;
1778	ndis_interrupt_mode	imode;
1779{
1780
1781	return(NDIS_STATUS_SUCCESS);
1782}
1783
1784__stdcall static void
1785ndis_deregister_intr(intr)
1786	ndis_miniport_interrupt	*intr;
1787{
1788	return;
1789}
1790
1791__stdcall static void
1792ndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
1793	ndis_handle		adapter;
1794	void			*shutdownctx;
1795	ndis_shutdown_handler	shutdownfunc;
1796{
1797	ndis_miniport_block	*block;
1798	ndis_miniport_characteristics *chars;
1799	struct ndis_softc	*sc;
1800
1801	if (adapter == NULL)
1802		return;
1803
1804	block = (ndis_miniport_block *)adapter;
1805	sc = (struct ndis_softc *)block->nmb_ifp;
1806	chars = &sc->ndis_chars;
1807
1808	chars->nmc_shutdown_handler = shutdownfunc;
1809	chars->nmc_rsvd0 = shutdownctx;
1810
1811	return;
1812}
1813
1814__stdcall static void
1815ndis_deregister_shutdown(adapter)
1816	ndis_handle		adapter;
1817{
1818	ndis_miniport_block	*block;
1819	ndis_miniport_characteristics *chars;
1820	struct ndis_softc	*sc;
1821
1822	if (adapter == NULL)
1823		return;
1824
1825	block = (ndis_miniport_block *)adapter;
1826	sc = (struct ndis_softc *)block->nmb_ifp;
1827	chars = &sc->ndis_chars;
1828
1829	chars->nmc_shutdown_handler = NULL;
1830	chars->nmc_rsvd0 = NULL;
1831
1832	return;
1833}
1834
1835__stdcall static uint32_t
1836ndis_numpages(buf)
1837	ndis_buffer		*buf;
1838{
1839	if (buf->nb_bytecount == 0)
1840		return(1);
1841	return(SPAN_PAGES(buf->nb_mappedsystemva, buf->nb_bytecount));
1842}
1843
1844__stdcall static void
1845ndis_buf_physpages(buf, pages)
1846	ndis_buffer		*buf;
1847	uint32_t		*pages;
1848{
1849	*pages = ndis_numpages(buf);
1850	return;
1851}
1852
1853__stdcall static void
1854ndis_query_bufoffset(buf, off, len)
1855	ndis_buffer		*buf;
1856	uint32_t		*off;
1857	uint32_t		*len;
1858{
1859	*off = (uint32_t)buf->nb_mappedsystemva & (PAGE_SIZE - 1);
1860	*len = buf->nb_bytecount;
1861
1862	return;
1863}
1864
1865__stdcall static void
1866ndis_sleep(usecs)
1867	uint32_t		usecs;
1868{
1869	struct timeval		tv;
1870	uint32_t		dummy;
1871
1872	tv.tv_sec = 0;
1873	tv.tv_usec = usecs;
1874
1875	tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
1876	return;
1877}
1878
1879__stdcall static uint32_t
1880ndis_read_pccard_amem(handle, offset, buf, len)
1881	ndis_handle		handle;
1882	uint32_t		offset;
1883	void			*buf;
1884	uint32_t		len;
1885{
1886	struct ndis_softc	*sc;
1887	ndis_miniport_block	*block;
1888	bus_space_handle_t	bh;
1889	bus_space_tag_t		bt;
1890	char			*dest;
1891	int			i;
1892
1893	if (handle == NULL)
1894		return(0);
1895
1896	block = (ndis_miniport_block *)handle;
1897	sc = (struct ndis_softc *)block->nmb_ifp;
1898	dest = buf;
1899
1900	bh = rman_get_bushandle(sc->ndis_res_am);
1901	bt = rman_get_bustag(sc->ndis_res_am);
1902
1903	for (i = 0; i < len; i++)
1904		dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2));
1905
1906	return(i);
1907}
1908
1909__stdcall static uint32_t
1910ndis_write_pccard_amem(handle, offset, buf, len)
1911	ndis_handle		handle;
1912	uint32_t		offset;
1913	void			*buf;
1914	uint32_t		len;
1915{
1916	struct ndis_softc	*sc;
1917	ndis_miniport_block	*block;
1918	bus_space_handle_t	bh;
1919	bus_space_tag_t		bt;
1920	char			*src;
1921	int			i;
1922
1923	if (handle == NULL)
1924		return(0);
1925
1926	block = (ndis_miniport_block *)handle;
1927	sc = (struct ndis_softc *)block->nmb_ifp;
1928	src = buf;
1929
1930	bh = rman_get_bushandle(sc->ndis_res_am);
1931	bt = rman_get_bustag(sc->ndis_res_am);
1932
1933	for (i = 0; i < len; i++)
1934		bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]);
1935
1936	return(i);
1937}
1938
1939__stdcall static ndis_list_entry *
1940ndis_insert_head(head, entry, lock)
1941	ndis_list_entry		*head;
1942	ndis_list_entry		*entry;
1943	ndis_spin_lock		*lock;
1944{
1945	ndis_list_entry		*flink;
1946
1947	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
1948	flink = head->nle_flink;
1949	entry->nle_flink = flink;
1950	entry->nle_blink = head;
1951	flink->nle_blink = entry;
1952	head->nle_flink = entry;
1953	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
1954
1955	return(flink);
1956}
1957
1958__stdcall static ndis_list_entry *
1959ndis_remove_head(head, lock)
1960	ndis_list_entry		*head;
1961	ndis_spin_lock		*lock;
1962{
1963	ndis_list_entry		*flink;
1964	ndis_list_entry		*entry;
1965
1966	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
1967	entry = head->nle_flink;
1968	flink = entry->nle_flink;
1969	head->nle_flink = flink;
1970	flink->nle_blink = head;
1971	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
1972
1973	return(entry);
1974}
1975
1976__stdcall static ndis_list_entry *
1977ndis_insert_tail(head, entry, lock)
1978	ndis_list_entry		*head;
1979	ndis_list_entry		*entry;
1980	ndis_spin_lock		*lock;
1981{
1982	ndis_list_entry		*blink;
1983
1984	mtx_lock_spin((struct mtx *)lock->nsl_spinlock);
1985	blink = head->nle_blink;
1986	entry->nle_flink = head;
1987	entry->nle_blink = blink;
1988	blink->nle_flink = entry;
1989	head->nle_blink = entry;
1990	mtx_unlock_spin((struct mtx *)lock->nsl_spinlock);
1991
1992	return(blink);
1993}
1994
1995__stdcall static uint8_t
1996ndis_sync_with_intr(intr, syncfunc, syncctx)
1997	ndis_miniport_interrupt	*intr;
1998	void			*syncfunc;
1999	void			*syncctx;
2000{
2001	__stdcall uint8_t (*sync)(void *);
2002
2003	if (syncfunc == NULL || syncctx == NULL)
2004		return(0);
2005
2006	sync = syncfunc;
2007	return(sync(syncctx));
2008}
2009
2010/*
2011 * Return the number of 100 nanosecond intervals since
2012 * January 1, 1601. (?!?!)
2013 */
2014__stdcall static void
2015ndis_time(tval)
2016	uint64_t		*tval;
2017{
2018	struct timespec		ts;
2019	nanotime(&ts);
2020	*tval = (ts.tv_nsec / 100) + (ts.tv_nsec * 10000000);
2021	*tval += 11644473600;
2022	return;
2023}
2024
2025__stdcall static void
2026ndis_init_string(dst, src)
2027	ndis_unicode_string	**dst;
2028	char			*src;
2029{
2030	ndis_unicode_string	*u;
2031
2032	u = malloc(sizeof(ndis_unicode_string), M_DEVBUF, M_NOWAIT);
2033	if (u == NULL)
2034		return;
2035	u->nus_buf = NULL;
2036	if (ndis_ascii_to_unicode(src, &u->nus_buf)) {
2037		free(u, M_DEVBUF);
2038		return;
2039	}
2040	u->nus_len = u->nus_maxlen = strlen(src) * 2;
2041	return;
2042}
2043
2044__stdcall static void
2045ndis_free_string(str)
2046	ndis_unicode_string	*str;
2047{
2048	if (str == NULL)
2049		return;
2050	if (str->nus_buf != NULL)
2051		free(str->nus_buf, M_DEVBUF);
2052	free(str, M_DEVBUF);
2053	return;
2054}
2055
2056__stdcall static ndis_status
2057ndis_remove_miniport(adapter)
2058	ndis_handle		*adapter;
2059{
2060	return(NDIS_STATUS_SUCCESS);
2061}
2062
2063__stdcall static void
2064ndis_init_ansi_string(dst, src)
2065	ndis_ansi_string	*dst;
2066	char			*src;
2067{
2068	ndis_ansi_string	*a;
2069
2070	a = dst;
2071	if (a == NULL)
2072		return;
2073	if (src == NULL) {
2074		a->nas_len = a->nas_maxlen = 0;
2075		a->nas_buf = NULL;
2076	} else {
2077		a->nas_buf = src;
2078		a->nas_len = a->nas_maxlen = strlen(src);
2079	}
2080
2081	return;
2082}
2083
2084__stdcall static void ndis_get_devprop(adapter, phydevobj,
2085	funcdevobj, nextdevobj, resources, transresources)
2086	ndis_handle		adapter;
2087	void			*phydevobj;
2088	void			*funcdevobj;
2089	void			*nextdevobj;
2090	cm_resource_list	*resources;
2091	cm_resource_list	*transresources;
2092{
2093	return;
2094}
2095
2096__stdcall static void
2097dummy()
2098{
2099	printf ("NDIS dummy called...\n");
2100	return;
2101}
2102
2103image_patch_table ndis_functbl[] = {
2104	{ "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2105	{ "NdisMGetDeviceProperty",	(FUNC)ndis_get_devprop },
2106	{ "NdisInitAnsiString",		(FUNC)ndis_init_ansi_string },
2107	{ "NdisWriteConfiguration",	(FUNC)ndis_write_cfg },
2108	{ "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2109	{ "NdisTerminateWrapper",	(FUNC)ndis_termwrap },
2110	{ "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2111	{ "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2112	{ "NdisMRemoveMiniport",	(FUNC)ndis_remove_miniport },
2113	{ "NdisInitializeString",	(FUNC)ndis_init_string },
2114	{ "NdisFreeString",		(FUNC)ndis_free_string },
2115	{ "NdisGetCurrentSystemTime",	(FUNC)ndis_time },
2116	{ "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2117	{ "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2118	{ "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2119	{ "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2120	{ "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2121	{ "NdisInitializeWrapper",	(FUNC)ndis_initwrap },
2122	{ "NdisMRegisterMiniport",	(FUNC)ndis_register_miniport },
2123	{ "NdisAllocateMemoryWithTag",	(FUNC)ndis_malloc_withtag },
2124	{ "NdisAllocateMemory",		(FUNC)ndis_malloc },
2125	{ "NdisMSetAttributesEx",	(FUNC)ndis_setattr_ex },
2126	{ "NdisCloseConfiguration",	(FUNC)ndis_close_cfg },
2127	{ "NdisReadConfiguration",	(FUNC)ndis_read_cfg },
2128	{ "NdisOpenConfiguration",	(FUNC)ndis_open_cfg },
2129	{ "NdisReleaseSpinLock",	(FUNC)ndis_unlock },
2130	{ "NdisDprAcquireSpinLock",	(FUNC)ndis_lock },
2131	{ "NdisDprReleaseSpinLock",	(FUNC)ndis_unlock },
2132	{ "NdisAcquireSpinLock",	(FUNC)ndis_lock },
2133	{ "NdisAllocateSpinLock",	(FUNC)ndis_create_lock },
2134	{ "NdisFreeSpinLock",		(FUNC)ndis_destroy_lock },
2135	{ "NdisFreeMemory",		(FUNC)ndis_free },
2136	{ "NdisReadPciSlotInformation",	(FUNC)ndis_read_pci },
2137	{ "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2138	{ "NdisWriteErrorLogEntry",	(FUNC)ndis_syslog },
2139	{ "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2140	{ "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2141	{ "NdisMInitializeTimer",	(FUNC)ndis_create_timer },
2142	{ "NdisSetTimer",		(FUNC)ndis_set_timer },
2143	{ "NdisMCancelTimer",		(FUNC)ndis_cancel_timer },
2144	{ "NdisMSetPeriodicTimer",	(FUNC)ndis_set_periodic_timer },
2145	{ "NdisMQueryAdapterResources",	(FUNC)ndis_query_resources },
2146	{ "NdisMRegisterIoPortRange",	(FUNC)ndis_register_ioport },
2147	{ "NdisMDeregisterIoPortRange",	(FUNC)ndis_deregister_ioport },
2148	{ "NdisReadNetworkAddress",	(FUNC)ndis_read_netaddr },
2149	{ "NdisMAllocateMapRegisters",	(FUNC)ndis_alloc_mapreg },
2150        { "NdisMFreeMapRegisters",	(FUNC)ndis_free_mapreg },
2151	{ "NdisMAllocateSharedMemory",	(FUNC)ndis_alloc_sharedmem },
2152	{ "NdisMMapIoSpace",		(FUNC)ndis_map_iospace },
2153	{ "NdisMUnmapIoSpace",		(FUNC)ndis_unmap_iospace },
2154	{ "NdisGetCacheFillSize",	(FUNC)ndis_cachefill },
2155	{ "NdisMGetDmaAlignment",	(FUNC)ndis_dma_align },
2156	{ "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2157	{ "NdisAllocatePacketPool",	(FUNC)ndis_alloc_packetpool },
2158	{ "NdisAllocatePacketPoolEx",	(FUNC)ndis_ex_alloc_packetpool },
2159	{ "NdisAllocatePacket",		(FUNC)ndis_alloc_packet },
2160	{ "NdisFreePacket",		(FUNC)ndis_release_packet },
2161	{ "NdisFreePacketPool",		(FUNC)ndis_free_packetpool },
2162	{ "NdisAllocateBufferPool",	(FUNC)ndis_alloc_bufpool },
2163	{ "NdisAllocateBuffer",		(FUNC)ndis_alloc_buf },
2164	{ "NdisQueryBuffer",		(FUNC)ndis_query_buf },
2165	{ "NdisQueryBufferSafe",	(FUNC)ndis_query_buf_safe },
2166	{ "NdisFreeBuffer",		(FUNC)ndis_release_buf },
2167	{ "NdisFreeBufferPool",		(FUNC)ndis_free_bufpool },
2168	{ "NdisInterlockedIncrement",	(FUNC)ndis_interlock_inc },
2169	{ "NdisInterlockedDecrement",	(FUNC)ndis_interlock_dec },
2170	{ "NdisInitializeEvent",	(FUNC)ndis_init_event },
2171	{ "NdisSetEvent",		(FUNC)ndis_set_event },
2172	{ "NdisResetEvent",		(FUNC)ndis_reset_event },
2173	{ "NdisWaitEvent",		(FUNC)ndis_wait_event },
2174	{ "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2175	{ "NdisMPciAssignResources",	(FUNC)ndis_assign_pcirsrc },
2176	{ "NdisMFreeSharedMemory",	(FUNC)ndis_free_sharedmem },
2177	{ "NdisMRegisterInterrupt",	(FUNC)ndis_register_intr },
2178	{ "NdisMDeregisterInterrupt",	(FUNC)ndis_deregister_intr },
2179	{ "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2180	{ "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
2181	{ "NDIS_BUFFER_TO_SPAN_PAGES",	(FUNC)ndis_numpages },
2182	{ "NdisQueryBufferOffset",	(FUNC)ndis_query_bufoffset },
2183	{ "NdisAdjustBufferLength",	(FUNC)ndis_adjust_buflen },
2184	{ "NdisPacketPoolUsage",	(FUNC)ndis_packetpool_use },
2185	{ "NdisMSleep",			(FUNC)ndis_sleep },
2186	{ "NdisUnchainBufferAtFront",	(FUNC)ndis_unchain_headbuf },
2187	{ "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
2188	{ "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
2189
2190	/*
2191	 * This last entry is a catch-all for any function we haven't
2192	 * implemented yet. The PE import list patching routine will
2193	 * use it for any function that doesn't have an explicit match
2194	 * in this table.
2195	 */
2196
2197	{ NULL, (FUNC)dummy },
2198
2199	/* End of list. */
2200
2201	{ NULL, NULL },
2202};
2203
2204