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