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