subr_ndis.c revision 125069
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 125069 2004-01-27 08:10:34Z 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#include <sys/smp.h>
66#include <sys/queue.h>
67#include <sys/proc.h>
68#include <sys/namei.h>
69#include <sys/fcntl.h>
70#include <sys/vnode.h>
71
72#include <net/if.h>
73#include <net/if_arp.h>
74#include <net/ethernet.h>
75#include <net/if_dl.h>
76#include <net/if_media.h>
77
78#include <machine/atomic.h>
79#include <machine/bus_memio.h>
80#include <machine/bus_pio.h>
81#include <machine/bus.h>
82#include <machine/resource.h>
83
84#include <sys/bus.h>
85#include <sys/rman.h>
86
87#include <machine/stdarg.h>
88
89#include <net80211/ieee80211_var.h>
90#include <net80211/ieee80211_ioctl.h>
91
92#include <dev/pci/pcireg.h>
93#include <dev/pci/pcivar.h>
94
95#include <compat/ndis/pe_var.h>
96#include <compat/ndis/resource_var.h>
97#include <compat/ndis/ntoskrnl_var.h>
98#include <compat/ndis/ndis_var.h>
99#include <compat/ndis/cfg_var.h>
100#include <dev/if_ndis/if_ndisvar.h>
101
102#define FUNC void(*)(void)
103
104static struct mtx *ndis_interlock;
105static char ndis_filepath[MAXPATHLEN];
106struct mtx_pool *ndis_mtxpool;
107extern struct nd_head ndis_devhead;
108
109SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
110        MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
111
112__stdcall static void ndis_initwrap(ndis_handle,
113	ndis_driver_object *, void *, void *);
114__stdcall static ndis_status ndis_register_miniport(ndis_handle,
115	ndis_miniport_characteristics *, int);
116__stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
117__stdcall static ndis_status ndis_malloc(void **,
118	uint32_t, uint32_t, ndis_physaddr);
119__stdcall static void ndis_free(void *, uint32_t, uint32_t);
120__stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
121	uint32_t, uint32_t, ndis_interface_type);
122__stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
123__stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle,
124	uint32_t, ndis_unicode_string *, ndis_handle *);
125__stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle,
126	ndis_unicode_string *, ndis_handle *);
127static ndis_status ndis_encode_parm(ndis_miniport_block *,
128	struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
129static ndis_status ndis_decode_parm(ndis_miniport_block *,
130	ndis_config_parm *, char *);
131__stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
132	ndis_handle, ndis_unicode_string *, ndis_parm_type);
133__stdcall static void ndis_write_cfg(ndis_status *, ndis_handle,
134	ndis_unicode_string *, ndis_config_parm *);
135__stdcall static void ndis_close_cfg(ndis_handle);
136__stdcall static void ndis_create_lock(ndis_spin_lock *);
137__stdcall static void ndis_destroy_lock(ndis_spin_lock *);
138__stdcall static void ndis_lock(ndis_spin_lock *);
139__stdcall static void ndis_unlock(ndis_spin_lock *);
140__stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
141	uint32_t, void *, uint32_t);
142__stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
143	uint32_t, void *, uint32_t);
144static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
145static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
146__stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
147	uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
148__stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
149__stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle *,
150	ndis_timer_function, void *);
151__stdcall static void ndis_init_timer(ndis_timer *,
152	ndis_timer_function, void *);
153static void ndis_timercall(void *);
154__stdcall static void ndis_set_timer(ndis_miniport_timer *, uint32_t);
155static void ndis_tick(void *);
156__stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
157__stdcall static void ndis_cancel_timer(ndis_miniport_timer *, uint8_t *);
158__stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
159	ndis_resource_list *, uint32_t *);
160__stdcall static ndis_status ndis_register_ioport(void **,
161	ndis_handle, uint32_t, uint32_t);
162__stdcall static void ndis_deregister_ioport(ndis_handle,
163	uint32_t, uint32_t, void *);
164__stdcall static void ndis_read_netaddr(ndis_status *, void **,
165	uint32_t *, ndis_handle);
166__stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *);
167__stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
168	uint32_t, uint8_t, uint32_t, uint32_t);
169__stdcall static void ndis_free_mapreg(ndis_handle);
170static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
171__stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
172	uint8_t, void **, ndis_physaddr *);
173__stdcall static void ndis_alloc_sharedmem_async(ndis_handle,
174	uint32_t, uint8_t, void *);
175__stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
176	uint8_t, void *, ndis_physaddr);
177__stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
178	ndis_physaddr, uint32_t);
179__stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
180__stdcall static uint32_t ndis_cachefill(void);
181__stdcall static uint32_t ndis_dma_align(ndis_handle);
182__stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
183	uint8_t, uint32_t);
184__stdcall static void ndis_alloc_packetpool(ndis_status *,
185	ndis_handle *, uint32_t, uint32_t);
186__stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
187	ndis_handle *, uint32_t, uint32_t, uint32_t);
188__stdcall static uint32_t ndis_packetpool_use(ndis_handle);
189__stdcall static void ndis_free_packetpool(ndis_handle);
190__stdcall static void ndis_alloc_packet(ndis_status *,
191	ndis_packet **, ndis_handle);
192__stdcall static void ndis_release_packet(ndis_packet *);
193__stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
194__stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **);
195__stdcall static void ndis_alloc_bufpool(ndis_status *,
196	ndis_handle *, uint32_t);
197__stdcall static void ndis_free_bufpool(ndis_handle);
198__stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
199	ndis_handle, void *, uint32_t);
200__stdcall static void ndis_release_buf(ndis_buffer *);
201__stdcall static uint32_t ndis_buflen(ndis_buffer *);
202__stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
203__stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
204	uint32_t *, uint32_t);
205__stdcall static void *ndis_buf_vaddr(ndis_buffer *);
206__stdcall static void *ndis_buf_vaddr_safe(ndis_buffer *, uint32_t);
207__stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
208__stdcall static uint32_t ndis_interlock_inc(uint32_t *);
209__stdcall static uint32_t ndis_interlock_dec(uint32_t *);
210__stdcall static void ndis_init_event(ndis_event *);
211__stdcall static void ndis_set_event(ndis_event *);
212__stdcall static void ndis_reset_event(ndis_event *);
213__stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
214__stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
215	ndis_unicode_string *);
216__stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
217	ndis_ansi_string *);
218__stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
219	uint32_t, ndis_resource_list **);
220__stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
221	ndis_handle, uint32_t, uint32_t, uint8_t,
222	uint8_t, ndis_interrupt_mode);
223__stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
224__stdcall static void ndis_register_shutdown(ndis_handle, void *,
225	ndis_shutdown_handler);
226__stdcall static void ndis_deregister_shutdown(ndis_handle);
227__stdcall static uint32_t ndis_numpages(ndis_buffer *);
228__stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
229__stdcall static void ndis_query_bufoffset(ndis_buffer *,
230	uint32_t *, uint32_t *);
231__stdcall static void ndis_sleep(uint32_t);
232__stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
233	uint32_t, void *, uint32_t);
234__stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
235	uint32_t, void *, uint32_t);
236__stdcall static ndis_list_entry *ndis_insert_head(ndis_list_entry *,
237	ndis_list_entry *, ndis_spin_lock *);
238__stdcall static ndis_list_entry *ndis_remove_head(ndis_list_entry *,
239	ndis_spin_lock *);
240__stdcall static ndis_list_entry *ndis_insert_tail(ndis_list_entry *,
241	ndis_list_entry *, ndis_spin_lock *);
242__stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
243	void *, void *);
244__stdcall static void ndis_time(uint64_t *);
245__stdcall static void ndis_uptime(uint32_t *);
246__stdcall static void ndis_init_string(ndis_unicode_string *, char *);
247__stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
248__stdcall static void ndis_init_unicode_string(ndis_unicode_string *,
249	uint16_t *);
250__stdcall static void ndis_free_string(ndis_unicode_string *);
251__stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
252__stdcall static void ndis_termwrap(ndis_handle, void *);
253__stdcall static void ndis_get_devprop(ndis_handle, void *, void *,
254	void *, cm_resource_list *, cm_resource_list *);
255__stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
256	void **, uint32_t *, uint32_t *);
257__stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
258	void **, uint32_t *, uint32_t *, uint32_t);
259__stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
260	ndis_unicode_string *, ndis_physaddr);
261__stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
262__stdcall static void ndis_unmap_file(ndis_handle);
263__stdcall static void ndis_close_file(ndis_handle);
264__stdcall static u_int8_t ndis_cpu_cnt(void);
265__stdcall static void ndis_ind_statusdone(ndis_handle);
266__stdcall static void ndis_ind_status(ndis_handle, ndis_status,
267        void *, uint32_t);
268static void ndis_workfunc(void *);
269__stdcall static ndis_status ndis_sched_workitem(ndis_work_item *);
270__stdcall static void ndis_pkt_to_pkt(ndis_packet *, uint32_t, uint32_t,
271	ndis_packet *, uint32_t, uint32_t *);
272__stdcall static void ndis_pkt_to_pkt_safe(ndis_packet *, uint32_t, uint32_t,
273	ndis_packet *, uint32_t, uint32_t *, uint32_t);
274__stdcall static ndis_status ndis_register_dev(ndis_handle *,
275	ndis_unicode_string *, ndis_unicode_string *, void *,
276	void *, ndis_handle **);
277__stdcall static ndis_status ndis_deregister_dev(ndis_handle *);
278__stdcall static void dummy(void);
279
280/*
281 * Some really old drivers do not properly check the return value
282 * from NdisAllocatePacket() and NdisAllocateBuffer() and will
283 * sometimes allocate few more buffers/packets that they originally
284 * requested when they created the pool. To prevent this from being
285 * a problem, we allocate a few extra buffers/packets beyond what
286 * the driver asks for. This #define controls how many.
287 */
288#define NDIS_POOL_EXTRA		16
289
290int
291ndis_libinit()
292{
293	strcpy(ndis_filepath, "/compat/ndis");
294	ndis_mtxpool = mtx_pool_create("ndis mutex pool",
295	    1024, MTX_DEF | MTX_RECURSE | MTX_DUPOK);;
296	ndis_interlock = mtx_pool_alloc(ndis_mtxpool);
297	return(0);
298}
299
300int
301ndis_libfini()
302{
303	mtx_pool_destroy(&ndis_mtxpool);
304	return(0);
305}
306
307/*
308 * NDIS deals with strings in unicode format, so we have
309 * do deal with them that way too. For now, we only handle
310 * conversion between unicode and ASCII since that's all
311 * that device drivers care about.
312 */
313
314int
315ndis_ascii_to_unicode(ascii, unicode)
316	char			*ascii;
317	uint16_t		**unicode;
318{
319	uint16_t		*ustr;
320	int			i;
321
322	if (*unicode == NULL)
323		*unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
324
325	if (*unicode == NULL)
326		return(ENOMEM);
327	ustr = *unicode;
328	for (i = 0; i < strlen(ascii); i++) {
329		*ustr = (uint16_t)ascii[i];
330		ustr++;
331	}
332
333	return(0);
334}
335
336int
337ndis_unicode_to_ascii(unicode, ulen, ascii)
338	uint16_t		*unicode;
339	int			ulen;
340	char			**ascii;
341{
342	uint8_t			*astr;
343	int			i;
344
345	if (*ascii == NULL)
346		*ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO);
347	if (*ascii == NULL)
348		return(ENOMEM);
349	astr = *ascii;
350	for (i = 0; i < ulen / 2; i++) {
351		*astr = (uint8_t)unicode[i];
352		astr++;
353	}
354
355	return(0);
356}
357
358__stdcall static void
359ndis_initwrap(wrapper, drv_obj, path, unused)
360	ndis_handle		wrapper;
361	ndis_driver_object	*drv_obj;
362	void			*path;
363	void			*unused;
364{
365	ndis_driver_object	**drv;
366
367	drv = wrapper;
368	*drv = drv_obj;
369
370	return;
371}
372
373__stdcall static void
374ndis_termwrap(handle, syspec)
375	ndis_handle		handle;
376	void			*syspec;
377{
378	return;
379}
380
381__stdcall static ndis_status
382ndis_register_miniport(handle, characteristics, len)
383	ndis_handle		handle;
384	ndis_miniport_characteristics *characteristics;
385	int			len;
386{
387	ndis_driver_object	*drv;
388
389	drv = handle;
390	bcopy((char *)characteristics, (char *)&drv->ndo_chars,
391	    sizeof(ndis_miniport_characteristics));
392	return(NDIS_STATUS_SUCCESS);
393}
394
395__stdcall static ndis_status
396ndis_malloc_withtag(vaddr, len, tag)
397	void			**vaddr;
398	uint32_t		len;
399	uint32_t		tag;
400{
401	void			*mem;
402
403	mem = malloc(len, M_DEVBUF, M_NOWAIT);
404	if (mem == NULL)
405		return(NDIS_STATUS_RESOURCES);
406	*vaddr = mem;
407
408	return(NDIS_STATUS_SUCCESS);
409}
410
411__stdcall static ndis_status
412ndis_malloc(vaddr, len, flags, highaddr)
413	void			**vaddr;
414	uint32_t		len;
415	uint32_t		flags;
416	ndis_physaddr		highaddr;
417{
418	void			*mem;
419
420	mem = malloc(len, M_DEVBUF, M_NOWAIT);
421	if (mem == NULL)
422		return(NDIS_STATUS_RESOURCES);
423	*vaddr = mem;
424
425	return(NDIS_STATUS_SUCCESS);
426}
427
428__stdcall static void
429ndis_free(vaddr, len, flags)
430	void			*vaddr;
431	uint32_t		len;
432	uint32_t		flags;
433{
434	if (len == 0)
435		return;
436	free(vaddr, M_DEVBUF);
437	return;
438}
439
440__stdcall static ndis_status
441ndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
442			flags, iftype)
443	ndis_handle			adapter_handle;
444	ndis_handle			adapter_ctx;
445	uint32_t			hangsecs;
446	uint32_t			flags;
447	ndis_interface_type		iftype;
448{
449	ndis_miniport_block		*block;
450
451	/*
452	 * Save the adapter context, we need it for calling
453	 * the driver's internal functions.
454	 */
455	block = (ndis_miniport_block *)adapter_handle;
456	block->nmb_miniportadapterctx = adapter_ctx;
457	block->nmb_checkforhangsecs = hangsecs;
458
459	return(NDIS_STATUS_SUCCESS);
460}
461
462__stdcall static void
463ndis_open_cfg(status, cfg, wrapctx)
464	ndis_status		*status;
465	ndis_handle		*cfg;
466	ndis_handle		wrapctx;
467{
468	*cfg = wrapctx;
469	*status = NDIS_STATUS_SUCCESS;
470	return;
471}
472
473__stdcall static void
474ndis_open_cfgbyname(status, cfg, subkey, subhandle)
475	ndis_status		*status;
476	ndis_handle		cfg;
477	ndis_unicode_string	*subkey;
478	ndis_handle		*subhandle;
479{
480	*subhandle = cfg;
481	*status = NDIS_STATUS_SUCCESS;
482	return;
483}
484
485__stdcall static void
486ndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle)
487	ndis_status		*status;
488	ndis_handle		cfg;
489	uint32_t		idx;
490	ndis_unicode_string	*subkey;
491	ndis_handle		*subhandle;
492{
493	*status = NDIS_STATUS_FAILURE;
494	return;
495}
496
497static ndis_status
498ndis_encode_parm(block, oid, type, parm)
499	ndis_miniport_block	*block;
500        struct sysctl_oid	*oid;
501	ndis_parm_type		type;
502	ndis_config_parm	**parm;
503{
504	uint16_t		*unicode;
505	ndis_unicode_string	*ustr;
506
507	unicode = (uint16_t *)&block->nmb_dummybuf;
508
509	switch(type) {
510	case ndis_parm_string:
511		ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
512		(*parm)->ncp_type = ndis_parm_string;
513		ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
514		ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
515		ustr->nus_buf = unicode;
516		break;
517	case ndis_parm_int:
518		(*parm)->ncp_type = ndis_parm_int;
519		(*parm)->ncp_parmdata.ncp_intdata =
520		    strtol((char *)oid->oid_arg1, NULL, 10);
521		break;
522	case ndis_parm_hexint:
523		(*parm)->ncp_type = ndis_parm_hexint;
524		(*parm)->ncp_parmdata.ncp_intdata =
525		    strtoul((char *)oid->oid_arg1, NULL, 16);
526		break;
527	default:
528		return(NDIS_STATUS_FAILURE);
529		break;
530	}
531
532	return(NDIS_STATUS_SUCCESS);
533}
534
535__stdcall static void
536ndis_read_cfg(status, parm, cfg, key, type)
537	ndis_status		*status;
538	ndis_config_parm	**parm;
539	ndis_handle		cfg;
540	ndis_unicode_string	*key;
541	ndis_parm_type		type;
542{
543	char			*keystr = NULL;
544	uint16_t		*unicode;
545	ndis_miniport_block	*block;
546	struct ndis_softc	*sc;
547        struct sysctl_oid	*oidp;
548	struct sysctl_ctx_entry	*e;
549
550	block = (ndis_miniport_block *)cfg;
551	sc = (struct ndis_softc *)block->nmb_ifp;
552
553	if (key->nus_len == 0 || key->nus_buf == NULL) {
554		*status = NDIS_STATUS_FAILURE;
555		return;
556	}
557
558	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
559
560	*parm = &block->nmb_replyparm;
561	bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
562	unicode = (uint16_t *)&block->nmb_dummybuf;
563
564	/*
565	 * See if registry key is already in a list of known keys
566	 * included with the driver.
567	 */
568	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
569		oidp = e->entry;
570		if (strcmp(oidp->oid_name, keystr) == 0) {
571			if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
572				free(keystr, M_DEVBUF);
573				*status = NDIS_STATUS_FAILURE;
574				return;
575			}
576			*status = ndis_encode_parm(block, oidp, type, parm);
577			free(keystr, M_DEVBUF);
578			return;
579		}
580	}
581
582	/*
583	 * If the key didn't match, add it to the list of dynamically
584	 * created ones. Sometimes, drivers refer to registry keys
585	 * that aren't documented in their .INF files. These keys
586	 * are supposed to be created by some sort of utility or
587	 * control panel snap-in that comes with the driver software.
588	 * Sometimes it's useful to be able to manipulate these.
589	 * If the driver requests the key in the form of a string,
590	 * make its default value an empty string, otherwise default
591	 * it to "0".
592	 */
593
594	if (type == ndis_parm_int || type == ndis_parm_hexint)
595		ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
596		    "UNSET", CTLFLAG_RW);
597	else
598		ndis_add_sysctl(sc, keystr, "(dynamic string key)",
599		    "UNSET", CTLFLAG_RW);
600
601	free(keystr, M_DEVBUF);
602	*status = NDIS_STATUS_FAILURE;
603	return;
604}
605
606static ndis_status
607ndis_decode_parm(block, parm, val)
608	ndis_miniport_block	*block;
609	ndis_config_parm	*parm;
610	char			*val;
611{
612	ndis_unicode_string	*ustr;
613	char			*astr = NULL;
614
615	switch(parm->ncp_type) {
616	case ndis_parm_string:
617		ustr = &parm->ncp_parmdata.ncp_stringdata;
618		ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &astr);
619		bcopy(astr, val, 254);
620		free(astr, M_DEVBUF);
621		break;
622	case ndis_parm_int:
623		sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
624		break;
625	case ndis_parm_hexint:
626		sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
627		break;
628	default:
629		return(NDIS_STATUS_FAILURE);
630		break;
631	}
632	return(NDIS_STATUS_SUCCESS);
633}
634
635__stdcall static void
636ndis_write_cfg(status, cfg, key, parm)
637	ndis_status		*status;
638	ndis_handle		cfg;
639	ndis_unicode_string	*key;
640	ndis_config_parm	*parm;
641{
642	char			*keystr = NULL;
643	ndis_miniport_block	*block;
644	struct ndis_softc	*sc;
645        struct sysctl_oid	*oidp;
646	struct sysctl_ctx_entry	*e;
647	char			val[256];
648
649	block = (ndis_miniport_block *)cfg;
650	sc = (struct ndis_softc *)block->nmb_ifp;
651
652	ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
653
654	/* Decode the parameter into a string. */
655	bzero(val, sizeof(val));
656	*status = ndis_decode_parm(block, parm, val);
657	if (*status != NDIS_STATUS_SUCCESS) {
658		free(keystr, M_DEVBUF);
659		return;
660	}
661
662	/* See if the key already exists. */
663
664	TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
665		oidp = e->entry;
666		if (strcmp(oidp->oid_name, keystr) == 0) {
667			/* Found it, set the value. */
668			strcpy((char *)oidp->oid_arg1, val);
669			free(keystr, M_DEVBUF);
670			return;
671		}
672	}
673
674	/* Not found, add a new key with the specified value. */
675	ndis_add_sysctl(sc, keystr, "(dynamically set key)",
676		    val, CTLFLAG_RW);
677
678	free(keystr, M_DEVBUF);
679	*status = NDIS_STATUS_SUCCESS;
680	return;
681}
682
683__stdcall static void
684ndis_close_cfg(cfg)
685	ndis_handle		cfg;
686{
687	return;
688}
689
690__stdcall static void
691ndis_create_lock(lock)
692	ndis_spin_lock		*lock;
693{
694	lock->nsl_spinlock = (ndis_kspin_lock)mtx_pool_alloc(ndis_mtxpool);
695	return;
696}
697
698__stdcall static void
699ndis_destroy_lock(lock)
700	ndis_spin_lock		*lock;
701{
702	/* We use a mutex pool, so this is a no-op. */
703	return;
704}
705
706__stdcall static void
707ndis_lock(lock)
708	ndis_spin_lock		*lock;
709{
710	mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
711	return;
712}
713
714__stdcall static void
715ndis_unlock(lock)
716	ndis_spin_lock		*lock;
717{
718	mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
719	return;
720}
721
722__stdcall static uint32_t
723ndis_read_pci(adapter, slot, offset, buf, len)
724	ndis_handle		adapter;
725	uint32_t		slot;
726	uint32_t		offset;
727	void			*buf;
728	uint32_t		len;
729{
730	ndis_miniport_block	*block;
731	int			i;
732	char			*dest;
733
734	block = (ndis_miniport_block *)adapter;
735	dest = buf;
736	if (block == NULL || block->nmb_dev == NULL)
737		return(0);
738
739	for (i = 0; i < len; i++)
740		dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
741
742	return(len);
743}
744
745__stdcall static uint32_t
746ndis_write_pci(adapter, slot, offset, buf, len)
747	ndis_handle		adapter;
748	uint32_t		slot;
749	uint32_t		offset;
750	void			*buf;
751	uint32_t		len;
752{
753	ndis_miniport_block	*block;
754	int			i;
755	char			*dest;
756
757	block = (ndis_miniport_block *)adapter;
758	dest = buf;
759
760	if (block == NULL || block->nmb_dev == NULL)
761		return(0);
762
763	for (i = 0; i < len; i++)
764		pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
765
766	return(len);
767}
768
769/*
770 * The errorlog routine uses a variable argument list, so we
771 * have to declare it this way.
772 */
773#define ERRMSGLEN 512
774static void
775ndis_syslog(ndis_handle adapter, ndis_error_code code,
776	uint32_t numerrors, ...)
777{
778	ndis_miniport_block	*block;
779	va_list			ap;
780	int			i, error;
781	char			*str = NULL, *ustr = NULL;
782	uint16_t		flags;
783	char			msgbuf[ERRMSGLEN];
784
785	block = (ndis_miniport_block *)adapter;
786
787	error = pe_get_message(block->nmb_img, code, &str, &i, &flags);
788	if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
789		ustr = msgbuf;
790		ndis_unicode_to_ascii((uint16_t *)str,
791		    ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
792		str = ustr;
793	}
794	device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code,
795	    str == NULL ? "unknown error" : str);
796	device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
797
798	va_start(ap, numerrors);
799	for (i = 0; i < numerrors; i++)
800		device_printf (block->nmb_dev, "argptr: %p\n",
801		    va_arg(ap, void *));
802	va_end(ap);
803
804	return;
805}
806
807static void
808ndis_map_cb(arg, segs, nseg, error)
809	void			*arg;
810	bus_dma_segment_t	*segs;
811	int			nseg;
812	int			error;
813{
814	struct ndis_map_arg	*ctx;
815	int			i;
816
817	if (error)
818		return;
819
820	ctx = arg;
821
822	for (i = 0; i < nseg; i++) {
823		ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
824		ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
825	}
826
827	ctx->nma_cnt = nseg;
828
829	return;
830}
831
832__stdcall static void
833ndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
834	ndis_handle		adapter;
835	ndis_buffer		*buf;
836	uint32_t		mapreg;
837	uint8_t			writedev;
838	ndis_paddr_unit		*addrarray;
839	uint32_t		*arraysize;
840{
841	ndis_miniport_block	*block;
842	struct ndis_softc	*sc;
843	struct ndis_map_arg	nma;
844	bus_dmamap_t		map;
845	int			error;
846
847	if (adapter == NULL)
848		return;
849
850	block = (ndis_miniport_block *)adapter;
851	sc = (struct ndis_softc *)(block->nmb_ifp);
852
853	if (mapreg > sc->ndis_mmapcnt)
854		return;
855
856	map = sc->ndis_mmaps[mapreg];
857	nma.nma_fraglist = addrarray;
858
859	error = bus_dmamap_load(sc->ndis_mtag, map,
860	    MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
861	    (void *)&nma, BUS_DMA_NOWAIT);
862
863	if (error)
864		return;
865
866	bus_dmamap_sync(sc->ndis_mtag, map,
867	    writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
868
869	*arraysize = nma.nma_cnt;
870
871	return;
872}
873
874__stdcall static void
875ndis_vtophys_unload(adapter, buf, mapreg)
876	ndis_handle		adapter;
877	ndis_buffer		*buf;
878	uint32_t		mapreg;
879{
880	ndis_miniport_block	*block;
881	struct ndis_softc	*sc;
882	bus_dmamap_t		map;
883
884	if (adapter == NULL)
885		return;
886
887	block = (ndis_miniport_block *)adapter;
888	sc = (struct ndis_softc *)(block->nmb_ifp);
889
890	if (mapreg > sc->ndis_mmapcnt)
891		return;
892
893	map = sc->ndis_mmaps[mapreg];
894
895	bus_dmamap_sync(sc->ndis_mtag, map,
896	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
897
898	bus_dmamap_unload(sc->ndis_mtag, map);
899
900	return;
901}
902
903/*
904 * This is an older pre-miniport timer init routine which doesn't
905 * accept a miniport context handle. The function context (ctx)
906 * is supposed to be a pointer to the adapter handle, which should
907 * have been handed to us via NdisSetAttributesEx(). We use this
908 * function context to track down the corresponding ndis_miniport_block
909 * structure. It's vital that we track down the miniport block structure,
910 * so if we can't do it, we panic. Note that we also play some games
911 * here by treating ndis_timer and ndis_miniport_timer as the same
912 * thing.
913 */
914
915__stdcall static void
916ndis_init_timer(timer, func, ctx)
917	ndis_timer		*timer;
918	ndis_timer_function	func;
919	void			*ctx;
920{
921	struct ndis_timer_entry	*ne = NULL;
922	ndis_miniport_block	*block = NULL;
923
924	TAILQ_FOREACH(block, &ndis_devhead, link) {
925		if (block->nmb_miniportadapterctx == ctx)
926			break;
927	}
928
929	if (block->nmb_miniportadapterctx != ctx)
930		panic("NDIS driver timer context didn't "
931		    "match any adapter contexts");
932
933	ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT);
934	callout_init(&ne->nte_ch, CALLOUT_MPSAFE);
935	TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link);
936	ne->nte_timer = (ndis_miniport_timer *)timer;
937
938	timer->nt_timer.nk_header.dh_sigstate = TRUE;
939	timer->nt_dpc.nk_sysarg1 = &ne->nte_ch;
940	timer->nt_dpc.nk_deferedfunc = (ndis_kdpc_func)func;
941	timer->nt_dpc.nk_deferredctx = ctx;
942
943	return;
944}
945
946__stdcall static void
947ndis_create_timer(timer, handle, func, ctx)
948	ndis_miniport_timer	*timer;
949	ndis_handle		*handle;
950	ndis_timer_function	func;
951	void			*ctx;
952{
953	struct ndis_timer_entry	*ne = NULL;
954	ndis_miniport_block	*block;
955	block = (ndis_miniport_block *)handle;
956
957	ne = malloc(sizeof(struct ndis_timer_entry), M_DEVBUF, M_NOWAIT);
958	callout_init(&ne->nte_ch, CALLOUT_MPSAFE);
959	TAILQ_INSERT_TAIL(&block->nmb_timerlist, ne, link);
960	ne->nte_timer = timer;
961
962	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
963	timer->nmt_dpc.nk_sysarg1 = &ne->nte_ch;
964	timer->nmt_dpc.nk_deferedfunc = (ndis_kdpc_func)func;
965	timer->nmt_dpc.nk_deferredctx = ctx;
966
967	return;
968}
969
970/*
971 * The driver's timer callout is __stdcall function, so we need this
972 * intermediate step.
973 */
974
975static void
976ndis_timercall(arg)
977	void		*arg;
978{
979	ndis_miniport_timer	*timer;
980	__stdcall ndis_timer_function	timerfunc;
981
982	timer = arg;
983
984	timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
985	timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc;
986	timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL);
987
988	return;
989}
990
991/*
992 * Windows specifies timeouts in milliseconds. We specify timeouts
993 * in hz. Trying to compute a tenth of a second based on hz is tricky.
994 * so we approximate. Note that we abuse the dpc portion of the
995 * miniport timer structure to hold the UNIX callout handle.
996 */
997__stdcall static void
998ndis_set_timer(timer, msecs)
999	ndis_miniport_timer	*timer;
1000	uint32_t		msecs;
1001{
1002	struct callout		*ch;
1003	struct timeval		tv;
1004
1005	tv.tv_sec = 0;
1006	tv.tv_usec = msecs * 1000;
1007
1008	ch = timer->nmt_dpc.nk_sysarg1;
1009	timer->nmt_dpc.nk_sysarg2 = ndis_timercall;
1010	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
1011	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1012
1013	return;
1014}
1015
1016static void
1017ndis_tick(arg)
1018	void			*arg;
1019{
1020	ndis_miniport_timer	*timer;
1021	struct callout		*ch;
1022	__stdcall ndis_timer_function	timerfunc;
1023	struct timeval		tv;
1024
1025	timer = arg;
1026
1027	timer->nmt_ktimer.nk_header.dh_sigstate = FALSE;
1028	timerfunc = (ndis_timer_function)timer->nmt_dpc.nk_deferedfunc;
1029	timerfunc(NULL, timer->nmt_dpc.nk_deferredctx, NULL, NULL);
1030
1031	/* Automatically reload timer. */
1032
1033	tv.tv_sec = 0;
1034	tv.tv_usec = timer->nmt_ktimer.nk_period * 1000;
1035	ch = timer->nmt_dpc.nk_sysarg1;
1036	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
1037	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
1038	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1039
1040	return;
1041}
1042
1043__stdcall static void
1044ndis_set_periodic_timer(timer, msecs)
1045	ndis_miniport_timer	*timer;
1046	uint32_t		msecs;
1047{
1048	struct callout		*ch;
1049	struct timeval		tv;
1050
1051	tv.tv_sec = 0;
1052	tv.tv_usec = msecs * 1000;
1053
1054	timer->nmt_ktimer.nk_period = msecs;
1055	ch = timer->nmt_dpc.nk_sysarg1;
1056	timer->nmt_dpc.nk_sysarg2 = ndis_tick;
1057	timer->nmt_ktimer.nk_header.dh_sigstate = TRUE;
1058	callout_reset(ch, tvtohz(&tv), timer->nmt_dpc.nk_sysarg2, timer);
1059
1060	return;
1061}
1062
1063__stdcall static void
1064ndis_cancel_timer(timer, cancelled)
1065	ndis_miniport_timer	*timer;
1066	uint8_t			*cancelled;
1067{
1068	struct callout		*ch;
1069
1070	if (timer == NULL)
1071		return;
1072	ch = timer->nmt_dpc.nk_sysarg1;
1073	if (ch == NULL)
1074		return;
1075	callout_stop(ch);
1076	*cancelled = timer->nmt_ktimer.nk_header.dh_sigstate;
1077
1078	return;
1079}
1080
1081__stdcall static void
1082ndis_query_resources(status, adapter, list, buflen)
1083	ndis_status		*status;
1084	ndis_handle		adapter;
1085	ndis_resource_list	*list;
1086	uint32_t		*buflen;
1087{
1088	ndis_miniport_block	*block;
1089	struct ndis_softc	*sc;
1090	int			rsclen;
1091
1092	block = (ndis_miniport_block *)adapter;
1093	sc = (struct ndis_softc *)block->nmb_ifp;
1094
1095	rsclen = sizeof(ndis_resource_list) +
1096	    (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1097	if (*buflen < rsclen) {
1098		*buflen = rsclen;
1099		*status = NDIS_STATUS_INVALID_LENGTH;
1100		return;
1101	}
1102
1103	bcopy((char *)block->nmb_rlist, (char *)list, *buflen);
1104	*status = NDIS_STATUS_SUCCESS;
1105	return;
1106}
1107
1108__stdcall static ndis_status
1109ndis_register_ioport(offset, adapter, port, numports)
1110	void			**offset;
1111	ndis_handle		adapter;
1112	uint32_t		port;
1113	uint32_t		numports;
1114{
1115	struct ndis_miniport_block	*block;
1116	struct ndis_softc	*sc;
1117
1118	if (adapter == NULL)
1119		return(NDIS_STATUS_FAILURE);
1120
1121	block = (ndis_miniport_block *)adapter;
1122	sc = (struct ndis_softc *)(block->nmb_ifp);
1123
1124	if (sc->ndis_res_io == NULL)
1125		return(NDIS_STATUS_FAILURE);
1126
1127	/* Don't let the device map more ports than we have. */
1128	if (rman_get_size(sc->ndis_res_io) < numports)
1129		return(NDIS_STATUS_INVALID_LENGTH);
1130
1131	*offset = (void *)rman_get_start(sc->ndis_res_io);
1132
1133	return(NDIS_STATUS_SUCCESS);
1134}
1135
1136__stdcall static void
1137ndis_deregister_ioport(adapter, port, numports, offset)
1138	ndis_handle		adapter;
1139	uint32_t		port;
1140	uint32_t		numports;
1141	void			*offset;
1142{
1143	return;
1144}
1145
1146__stdcall static void
1147ndis_read_netaddr(status, addr, addrlen, adapter)
1148	ndis_status		*status;
1149	void			**addr;
1150	uint32_t		*addrlen;
1151	ndis_handle		adapter;
1152{
1153	struct ndis_softc	*sc;
1154	ndis_miniport_block	*block;
1155	uint8_t			empty[] = { 0, 0, 0, 0, 0, 0 };
1156
1157	block = (ndis_miniport_block *)adapter;
1158	sc = (struct ndis_softc *)block->nmb_ifp;
1159
1160	if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1161		*status = NDIS_STATUS_FAILURE;
1162	else {
1163		*addr = sc->arpcom.ac_enaddr;
1164		*addrlen = ETHER_ADDR_LEN;
1165		*status = NDIS_STATUS_SUCCESS;
1166	}
1167
1168	return;
1169}
1170
1171__stdcall static ndis_status
1172ndis_mapreg_cnt(bustype, cnt)
1173	uint32_t		bustype;
1174	uint32_t		*cnt;
1175{
1176	*cnt = 8192;
1177	return(NDIS_STATUS_SUCCESS);
1178}
1179
1180__stdcall static ndis_status
1181ndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
1182	ndis_handle		adapter;
1183	uint32_t		dmachannel;
1184	uint8_t			dmasize;
1185	uint32_t		physmapneeded;
1186	uint32_t		maxmap;
1187{
1188	struct ndis_softc	*sc;
1189	ndis_miniport_block	*block;
1190	int			error, i, nseg = NDIS_MAXSEG;
1191
1192	block = (ndis_miniport_block *)adapter;
1193	sc = (struct ndis_softc *)block->nmb_ifp;
1194
1195	sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1196	    M_DEVBUF, M_NOWAIT|M_ZERO);
1197
1198	if (sc->ndis_mmaps == NULL)
1199		return(NDIS_STATUS_RESOURCES);
1200
1201	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1202	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1203	    NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1204	    NULL, NULL, &sc->ndis_mtag);
1205
1206	if (error) {
1207		free(sc->ndis_mmaps, M_DEVBUF);
1208		return(NDIS_STATUS_RESOURCES);
1209	}
1210
1211	for (i = 0; i < physmapneeded; i++)
1212		bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1213
1214	sc->ndis_mmapcnt = physmapneeded;
1215
1216	return(NDIS_STATUS_SUCCESS);
1217}
1218
1219__stdcall static void
1220ndis_free_mapreg(adapter)
1221	ndis_handle		adapter;
1222{
1223	struct ndis_softc	*sc;
1224	ndis_miniport_block	*block;
1225	int			i;
1226
1227	block = (ndis_miniport_block *)adapter;
1228	sc = (struct ndis_softc *)block->nmb_ifp;
1229
1230	for (i = 0; i < sc->ndis_mmapcnt; i++)
1231		bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1232
1233	free(sc->ndis_mmaps, M_DEVBUF);
1234
1235	bus_dma_tag_destroy(sc->ndis_mtag);
1236
1237	return;
1238}
1239
1240static void
1241ndis_mapshared_cb(arg, segs, nseg, error)
1242	void			*arg;
1243	bus_dma_segment_t	*segs;
1244	int			nseg;
1245	int			error;
1246{
1247	ndis_physaddr		*p;
1248
1249	if (error || nseg > 1)
1250		return;
1251
1252	p = arg;
1253
1254	p->np_quad = segs[0].ds_addr;
1255
1256	return;
1257}
1258
1259/*
1260 * This maps to bus_dmamem_alloc().
1261 */
1262__stdcall static void
1263ndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
1264	ndis_handle		adapter;
1265	uint32_t		len;
1266	uint8_t			cached;
1267	void			**vaddr;
1268	ndis_physaddr		*paddr;
1269{
1270	ndis_miniport_block	*block;
1271	struct ndis_softc	*sc;
1272	struct ndis_shmem	*sh;
1273	int			error;
1274
1275	if (adapter == NULL)
1276		return;
1277
1278	block = (ndis_miniport_block *)adapter;
1279	sc = (struct ndis_softc *)(block->nmb_ifp);
1280
1281	sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1282	if (sh == NULL)
1283		return;
1284
1285	error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1286	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1287	    NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
1288	    &sh->ndis_stag);
1289
1290	if (error) {
1291		free(sh, M_DEVBUF);
1292		return;
1293	}
1294
1295	error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1296	    BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1297
1298	if (error) {
1299		bus_dma_tag_destroy(sh->ndis_stag);
1300		free(sh, M_DEVBUF);
1301		return;
1302	}
1303
1304	error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1305	    len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1306
1307	if (error) {
1308		bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1309		bus_dma_tag_destroy(sh->ndis_stag);
1310		free(sh, M_DEVBUF);
1311		return;
1312	}
1313
1314	sh->ndis_saddr = *vaddr;
1315	sh->ndis_next = sc->ndis_shlist;
1316	sc->ndis_shlist = sh;
1317
1318	return;
1319}
1320
1321__stdcall static void
1322ndis_alloc_sharedmem_async(adapter, len, cached, ctx)
1323	ndis_handle		adapter;
1324	uint32_t		len;
1325	uint8_t			cached;
1326	void			*ctx;
1327{
1328	ndis_miniport_block	*block;
1329	struct ndis_softc	*sc;
1330	void			*vaddr;
1331	ndis_physaddr		paddr;
1332	__stdcall ndis_allocdone_handler	donefunc;
1333
1334	if (adapter == NULL)
1335		return;
1336
1337	block = (ndis_miniport_block *)adapter;
1338	sc = (struct ndis_softc *)(block->nmb_ifp);
1339	donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1340
1341	ndis_alloc_sharedmem(adapter, len, cached, &vaddr, &paddr);
1342	donefunc(adapter, vaddr, &paddr, len, ctx);
1343
1344	return;
1345}
1346
1347__stdcall static void
1348ndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
1349	ndis_handle		adapter;
1350	uint32_t		len;
1351	uint8_t			cached;
1352	void			*vaddr;
1353	ndis_physaddr		paddr;
1354{
1355	ndis_miniport_block	*block;
1356	struct ndis_softc	*sc;
1357	struct ndis_shmem	*sh, *prev;
1358
1359	if (vaddr == NULL || adapter == NULL)
1360		return;
1361
1362	block = (ndis_miniport_block *)adapter;
1363	sc = (struct ndis_softc *)(block->nmb_ifp);
1364	sh = prev = sc->ndis_shlist;
1365
1366	while (sh) {
1367		if (sh->ndis_saddr == vaddr)
1368			break;
1369		prev = sh;
1370		sh = sh->ndis_next;
1371	}
1372
1373	bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1374	bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1375	bus_dma_tag_destroy(sh->ndis_stag);
1376
1377	if (sh == sc->ndis_shlist)
1378		sc->ndis_shlist = sh->ndis_next;
1379	else
1380		prev->ndis_next = sh->ndis_next;
1381
1382	free(sh, M_DEVBUF);
1383
1384	return;
1385}
1386
1387__stdcall static ndis_status
1388ndis_map_iospace(vaddr, adapter, paddr, len)
1389	void			**vaddr;
1390	ndis_handle		adapter;
1391	ndis_physaddr		paddr;
1392	uint32_t		len;
1393{
1394	ndis_miniport_block	*block;
1395	struct ndis_softc	*sc;
1396
1397	if (adapter == NULL)
1398		return(NDIS_STATUS_FAILURE);
1399
1400	block = (ndis_miniport_block *)adapter;
1401	sc = (struct ndis_softc *)(block->nmb_ifp);
1402
1403	if (sc->ndis_res_mem == NULL)
1404		return(NDIS_STATUS_FAILURE);
1405
1406	*vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1407
1408	return(NDIS_STATUS_SUCCESS);
1409}
1410
1411__stdcall static void
1412ndis_unmap_iospace(adapter, vaddr, len)
1413	ndis_handle		adapter;
1414	void			*vaddr;
1415	uint32_t		len;
1416{
1417	return;
1418}
1419
1420__stdcall static uint32_t
1421ndis_cachefill(void)
1422{
1423	return(128);
1424}
1425
1426__stdcall static uint32_t
1427ndis_dma_align(handle)
1428	ndis_handle		handle;
1429{
1430	return(128);
1431}
1432
1433/*
1434 * NDIS has two methods for dealing with NICs that support DMA.
1435 * One is to just pass packets to the driver and let it call
1436 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1437 * all by itself, and the other is to let the NDIS library handle the
1438 * buffer mapping internally, and hand the driver an already populated
1439 * scatter/gather fragment list. If the driver calls
1440 * NdisMInitializeScatterGatherDma(), it wants to use the latter
1441 * method.
1442 */
1443
1444__stdcall static ndis_status
1445ndis_init_sc_dma(adapter, is64, maxphysmap)
1446	ndis_handle		adapter;
1447	uint8_t			is64;
1448	uint32_t		maxphysmap;
1449{
1450	struct ndis_softc	*sc;
1451	ndis_miniport_block	*block;
1452	int			error;
1453
1454	if (adapter == NULL)
1455		return(NDIS_STATUS_FAILURE);
1456	block = (ndis_miniport_block *)adapter;
1457	sc = (struct ndis_softc *)block->nmb_ifp;
1458
1459	/* Don't do this twice. */
1460	if (sc->ndis_sc == 1)
1461		return(NDIS_STATUS_SUCCESS);
1462
1463	error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1464	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1465	    MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1466	    NULL, NULL, &sc->ndis_ttag);
1467
1468	sc->ndis_sc = 1;
1469
1470	return(NDIS_STATUS_SUCCESS);
1471}
1472
1473__stdcall static void
1474ndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
1475	ndis_status		*status;
1476	ndis_handle		*pool;
1477	uint32_t		descnum;
1478	uint32_t		protrsvdlen;
1479{
1480	ndis_packet		*cur;
1481	int			i;
1482
1483	*pool = malloc(sizeof(ndis_packet) *
1484	    ((descnum + NDIS_POOL_EXTRA) + 1),
1485	    M_DEVBUF, M_NOWAIT|M_ZERO);
1486
1487	if (pool == NULL) {
1488		*status = NDIS_STATUS_RESOURCES;
1489		return;
1490	}
1491
1492	cur = (ndis_packet *)*pool;
1493	cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1494	for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1495		cur->np_private.npp_head = (ndis_handle)(cur + 1);
1496		cur++;
1497	}
1498
1499	*status = NDIS_STATUS_SUCCESS;
1500	return;
1501}
1502
1503__stdcall static void
1504ndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
1505	ndis_status		*status;
1506	ndis_handle		*pool;
1507	uint32_t		descnum;
1508	uint32_t		oflowdescnum;
1509	uint32_t		protrsvdlen;
1510{
1511	return(ndis_alloc_packetpool(status, pool,
1512	    descnum + oflowdescnum, protrsvdlen));
1513}
1514
1515__stdcall static uint32_t
1516ndis_packetpool_use(pool)
1517	ndis_handle		pool;
1518{
1519	ndis_packet		*head;
1520
1521	head = (ndis_packet *)pool;
1522
1523	return(head->np_private.npp_count);
1524}
1525
1526__stdcall static void
1527ndis_free_packetpool(pool)
1528	ndis_handle		pool;
1529{
1530	free(pool, M_DEVBUF);
1531	return;
1532}
1533
1534__stdcall static void
1535ndis_alloc_packet(status, packet, pool)
1536	ndis_status		*status;
1537	ndis_packet		**packet;
1538	ndis_handle		pool;
1539{
1540	ndis_packet		*head, *pkt;
1541
1542	head = (ndis_packet *)pool;
1543
1544	if (head->np_private.npp_flags != 0x1) {
1545		*status = NDIS_STATUS_FAILURE;
1546		return;
1547	}
1548
1549	pkt = (ndis_packet *)head->np_private.npp_head;
1550
1551	if (pkt == NULL) {
1552		*status = NDIS_STATUS_RESOURCES;
1553		return;
1554	}
1555
1556	head->np_private.npp_head = pkt->np_private.npp_head;
1557
1558	pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1559	/* Save pointer to the pool. */
1560	pkt->np_private.npp_pool = head;
1561
1562	/* Set the oob offset pointer. Lots of things expect this. */
1563	pkt->np_private.npp_packetooboffset =
1564	    offsetof(ndis_packet, np_oob);
1565
1566	/*
1567	 * We must initialize the packet flags correctly in order
1568	 * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
1569	 * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly.
1570	 */
1571	pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
1572
1573	*packet = pkt;
1574
1575	head->np_private.npp_count++;
1576	*status = NDIS_STATUS_SUCCESS;
1577	return;
1578}
1579
1580__stdcall static void
1581ndis_release_packet(packet)
1582	ndis_packet		*packet;
1583{
1584	ndis_packet		*head;
1585
1586	if (packet == NULL || packet->np_private.npp_pool == NULL)
1587		return;
1588
1589	head = packet->np_private.npp_pool;
1590	if (head->np_private.npp_flags != 0x1)
1591		return;
1592
1593	packet->np_private.npp_head = head->np_private.npp_head;
1594	head->np_private.npp_head = (ndis_buffer *)packet;
1595	head->np_private.npp_count--;
1596
1597	return;
1598}
1599
1600__stdcall static void
1601ndis_unchain_headbuf(packet, buf)
1602	ndis_packet		*packet;
1603	ndis_buffer		**buf;
1604{
1605	ndis_packet_private	*priv;
1606
1607	if (packet == NULL || buf == NULL)
1608		return;
1609
1610	priv = &packet->np_private;
1611
1612	priv->npp_validcounts = FALSE;
1613
1614	if (priv->npp_head == priv->npp_tail) {
1615		*buf = priv->npp_head;
1616		priv->npp_head = priv->npp_tail = NULL;
1617	} else {
1618		*buf = priv->npp_head;
1619		priv->npp_head = (*buf)->nb_next;
1620	}
1621
1622	return;
1623}
1624
1625__stdcall static void
1626ndis_unchain_tailbuf(packet, buf)
1627	ndis_packet		*packet;
1628	ndis_buffer		**buf;
1629{
1630	ndis_packet_private	*priv;
1631	ndis_buffer		*tmp;
1632
1633	if (packet == NULL || buf == NULL)
1634		return;
1635
1636	priv = &packet->np_private;
1637
1638	priv->npp_validcounts = FALSE;
1639
1640	if (priv->npp_head == priv->npp_tail) {
1641		*buf = priv->npp_head;
1642		priv->npp_head = priv->npp_tail = NULL;
1643	} else {
1644		*buf = priv->npp_tail;
1645		tmp = priv->npp_head;
1646		while (tmp->nb_next != priv->npp_tail)
1647			tmp = tmp->nb_next;
1648		priv->npp_tail = tmp;
1649		tmp->nb_next = NULL;
1650	}
1651
1652	return;
1653}
1654
1655/*
1656 * The NDIS "buffer" manipulation functions are somewhat misnamed.
1657 * They don't really allocate buffers: they allocate buffer mappings.
1658 * The idea is you reserve a chunk of DMA-able memory using
1659 * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1660 * to obtain the virtual address of the DMA-able region.
1661 * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1662 */
1663
1664__stdcall static void
1665ndis_alloc_bufpool(status, pool, descnum)
1666	ndis_status		*status;
1667	ndis_handle		*pool;
1668	uint32_t		descnum;
1669{
1670	ndis_buffer		*cur;
1671	int			i;
1672
1673	*pool = malloc(sizeof(ndis_buffer) *
1674	    ((descnum + NDIS_POOL_EXTRA) + 1),
1675	    M_DEVBUF, M_NOWAIT|M_ZERO);
1676
1677	if (pool == NULL) {
1678		*status = NDIS_STATUS_RESOURCES;
1679		return;
1680	}
1681
1682	cur = (ndis_buffer *)*pool;
1683	cur->nb_flags = 0x1; /* mark the head of the list */
1684	for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1685		cur->nb_next = cur + 1;
1686		cur++;
1687	}
1688
1689	*status = NDIS_STATUS_SUCCESS;
1690	return;
1691}
1692
1693__stdcall static void
1694ndis_free_bufpool(pool)
1695	ndis_handle		pool;
1696{
1697	free(pool, M_DEVBUF);
1698	return;
1699}
1700
1701/*
1702 * This maps to a bus_dmamap_create() and bus_dmamap_load().
1703 */
1704__stdcall static void
1705ndis_alloc_buf(status, buffer, pool, vaddr, len)
1706	ndis_status		*status;
1707	ndis_buffer		**buffer;
1708	ndis_handle		pool;
1709	void			*vaddr;
1710	uint32_t		len;
1711{
1712	ndis_buffer		*head, *buf;
1713
1714	head = (ndis_buffer *)pool;
1715	if (head->nb_flags != 0x1) {
1716		*status = NDIS_STATUS_FAILURE;
1717		return;
1718	}
1719
1720	buf = head->nb_next;
1721
1722	if (buf == NULL) {
1723		*status = NDIS_STATUS_RESOURCES;
1724		return;
1725	}
1726
1727	head->nb_next = buf->nb_next;
1728
1729	/* Save pointer to the pool. */
1730	buf->nb_process = head;
1731
1732	MDL_INIT(buf, vaddr, len);
1733
1734	*buffer = buf;
1735
1736	*status = NDIS_STATUS_SUCCESS;
1737	return;
1738}
1739
1740__stdcall static void
1741ndis_release_buf(buf)
1742	ndis_buffer		*buf;
1743{
1744	ndis_buffer		*head;
1745
1746	if (buf == NULL || buf->nb_process == NULL)
1747		return;
1748
1749	head = buf->nb_process;
1750
1751	if (head->nb_flags != 0x1)
1752		return;
1753
1754	buf->nb_next = head->nb_next;
1755	head->nb_next = buf;
1756
1757	return;
1758}
1759
1760/* Aw c'mon. */
1761
1762__stdcall static uint32_t
1763ndis_buflen(buf)
1764	ndis_buffer		*buf;
1765{
1766	return(buf->nb_bytecount);
1767}
1768
1769/*
1770 * Get the virtual address and length of a buffer.
1771 * Note: the vaddr argument is optional.
1772 */
1773
1774__stdcall static void
1775ndis_query_buf(buf, vaddr, len)
1776	ndis_buffer		*buf;
1777	void			**vaddr;
1778	uint32_t		*len;
1779{
1780	if (vaddr != NULL)
1781		*vaddr = MDL_VA(buf);
1782	*len = buf->nb_bytecount;
1783
1784	return;
1785}
1786
1787/* Same as above -- we don't care about the priority. */
1788
1789__stdcall static void
1790ndis_query_buf_safe(buf, vaddr, len, prio)
1791	ndis_buffer		*buf;
1792	void			**vaddr;
1793	uint32_t		*len;
1794	uint32_t		prio;
1795{
1796	if (vaddr != NULL)
1797		*vaddr = MDL_VA(buf);
1798	*len = buf->nb_bytecount;
1799
1800	return;
1801}
1802
1803/* Damnit Microsoft!! How many ways can you do the same thing?! */
1804
1805__stdcall static void *
1806ndis_buf_vaddr(buf)
1807	ndis_buffer		*buf;
1808{
1809	return(MDL_VA(buf));
1810}
1811
1812__stdcall static void *
1813ndis_buf_vaddr_safe(buf, prio)
1814	ndis_buffer		*buf;
1815	uint32_t		prio;
1816{
1817	return(MDL_VA(buf));
1818}
1819
1820__stdcall static void
1821ndis_adjust_buflen(buf, len)
1822	ndis_buffer		*buf;
1823	int			len;
1824{
1825	buf->nb_bytecount = len;
1826
1827	return;
1828}
1829
1830__stdcall static uint32_t
1831ndis_interlock_inc(addend)
1832	uint32_t		*addend;
1833{
1834	atomic_add_long((u_long *)addend, 1);
1835	return(*addend);
1836}
1837
1838__stdcall static uint32_t
1839ndis_interlock_dec(addend)
1840	uint32_t		*addend;
1841{
1842	atomic_subtract_long((u_long *)addend, 1);
1843	return(*addend);
1844}
1845
1846__stdcall static void
1847ndis_init_event(event)
1848	ndis_event		*event;
1849{
1850	event->ne_event.nk_header.dh_sigstate = FALSE;
1851	return;
1852}
1853
1854__stdcall static void
1855ndis_set_event(event)
1856	ndis_event		*event;
1857{
1858	event->ne_event.nk_header.dh_sigstate = TRUE;
1859	wakeup(event);
1860	return;
1861}
1862
1863__stdcall static void
1864ndis_reset_event(event)
1865	ndis_event		*event;
1866{
1867	event->ne_event.nk_header.dh_sigstate = FALSE;
1868	wakeup(event);
1869	return;
1870}
1871
1872__stdcall static uint8_t
1873ndis_wait_event(event, msecs)
1874	ndis_event		*event;
1875	uint32_t		msecs;
1876{
1877	int			error;
1878	struct timeval		tv;
1879
1880	if (event->ne_event.nk_header.dh_sigstate == TRUE)
1881		return(TRUE);
1882
1883	tv.tv_sec = 0;
1884	tv.tv_usec = msecs * 1000;
1885
1886	error = tsleep(event, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
1887
1888	return(event->ne_event.nk_header.dh_sigstate);
1889}
1890
1891__stdcall static ndis_status
1892ndis_unicode2ansi(dstr, sstr)
1893	ndis_ansi_string	*dstr;
1894	ndis_unicode_string	*sstr;
1895{
1896	if (dstr == NULL || sstr == NULL)
1897		return(NDIS_STATUS_FAILURE);
1898	if (ndis_unicode_to_ascii(sstr->nus_buf,
1899	    sstr->nus_len, &dstr->nas_buf))
1900		return(NDIS_STATUS_FAILURE);
1901	dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
1902	return (NDIS_STATUS_SUCCESS);
1903}
1904
1905__stdcall static ndis_status
1906ndis_ansi2unicode(dstr, sstr)
1907	ndis_unicode_string	*dstr;
1908	ndis_ansi_string	*sstr;
1909{
1910	char			*str;
1911	if (dstr == NULL || sstr == NULL)
1912		return(NDIS_STATUS_FAILURE);
1913	str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
1914	if (str == NULL)
1915		return(NDIS_STATUS_FAILURE);
1916	strncpy(str, sstr->nas_buf, sstr->nas_len);
1917	*(str + sstr->nas_len) = '\0';
1918	if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
1919		free(str, M_DEVBUF);
1920		return(NDIS_STATUS_FAILURE);
1921	}
1922	dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
1923	free(str, M_DEVBUF);
1924	return (NDIS_STATUS_SUCCESS);
1925}
1926
1927__stdcall static ndis_status
1928ndis_assign_pcirsrc(adapter, slot, list)
1929	ndis_handle		adapter;
1930	uint32_t		slot;
1931	ndis_resource_list	**list;
1932{
1933	ndis_miniport_block	*block;
1934
1935	if (adapter == NULL || list == NULL)
1936		return (NDIS_STATUS_FAILURE);
1937
1938	block = (ndis_miniport_block *)adapter;
1939	*list = block->nmb_rlist;
1940
1941	return (NDIS_STATUS_SUCCESS);
1942}
1943
1944__stdcall static ndis_status
1945ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
1946	ndis_miniport_interrupt	*intr;
1947	ndis_handle		adapter;
1948	uint32_t		ivec;
1949	uint32_t		ilevel;
1950	uint8_t			reqisr;
1951	uint8_t			shared;
1952	ndis_interrupt_mode	imode;
1953{
1954	ndis_miniport_block	*block;
1955
1956	block = adapter;
1957
1958	intr->ni_block = adapter;
1959	intr->ni_isrreq = reqisr;
1960	intr->ni_shared = shared;
1961	block->nmb_interrupt = intr;
1962	return(NDIS_STATUS_SUCCESS);
1963}
1964
1965__stdcall static void
1966ndis_deregister_intr(intr)
1967	ndis_miniport_interrupt	*intr;
1968{
1969	return;
1970}
1971
1972__stdcall static void
1973ndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
1974	ndis_handle		adapter;
1975	void			*shutdownctx;
1976	ndis_shutdown_handler	shutdownfunc;
1977{
1978	ndis_miniport_block	*block;
1979	ndis_miniport_characteristics *chars;
1980	struct ndis_softc	*sc;
1981
1982	if (adapter == NULL)
1983		return;
1984
1985	block = (ndis_miniport_block *)adapter;
1986	sc = (struct ndis_softc *)block->nmb_ifp;
1987	chars = &sc->ndis_chars;
1988
1989	chars->nmc_shutdown_handler = shutdownfunc;
1990	chars->nmc_rsvd0 = shutdownctx;
1991
1992	return;
1993}
1994
1995__stdcall static void
1996ndis_deregister_shutdown(adapter)
1997	ndis_handle		adapter;
1998{
1999	ndis_miniport_block	*block;
2000	ndis_miniport_characteristics *chars;
2001	struct ndis_softc	*sc;
2002
2003	if (adapter == NULL)
2004		return;
2005
2006	block = (ndis_miniport_block *)adapter;
2007	sc = (struct ndis_softc *)block->nmb_ifp;
2008	chars = &sc->ndis_chars;
2009
2010	chars->nmc_shutdown_handler = NULL;
2011	chars->nmc_rsvd0 = NULL;
2012
2013	return;
2014}
2015
2016__stdcall static uint32_t
2017ndis_numpages(buf)
2018	ndis_buffer		*buf;
2019{
2020	if (buf == NULL)
2021		return(0);
2022	if (buf->nb_bytecount == 0)
2023		return(1);
2024	return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
2025}
2026
2027__stdcall static void
2028ndis_buf_physpages(buf, pages)
2029	ndis_buffer		*buf;
2030	uint32_t		*pages;
2031{
2032	if (buf == NULL)
2033		return;
2034
2035	*pages = ndis_numpages(buf);
2036	return;
2037}
2038
2039__stdcall static void
2040ndis_query_bufoffset(buf, off, len)
2041	ndis_buffer		*buf;
2042	uint32_t		*off;
2043	uint32_t		*len;
2044{
2045	if (buf == NULL)
2046		return;
2047
2048	*off = buf->nb_byteoffset;
2049	*len = buf->nb_bytecount;
2050
2051	return;
2052}
2053
2054__stdcall static void
2055ndis_sleep(usecs)
2056	uint32_t		usecs;
2057{
2058	struct timeval		tv;
2059	uint32_t		dummy;
2060
2061	tv.tv_sec = 0;
2062	tv.tv_usec = usecs;
2063
2064	tsleep(&dummy, PPAUSE|PCATCH, "ndis", tvtohz(&tv));
2065
2066	return;
2067}
2068
2069__stdcall static uint32_t
2070ndis_read_pccard_amem(handle, offset, buf, len)
2071	ndis_handle		handle;
2072	uint32_t		offset;
2073	void			*buf;
2074	uint32_t		len;
2075{
2076	struct ndis_softc	*sc;
2077	ndis_miniport_block	*block;
2078	bus_space_handle_t	bh;
2079	bus_space_tag_t		bt;
2080	char			*dest;
2081	int			i;
2082
2083	if (handle == NULL)
2084		return(0);
2085
2086	block = (ndis_miniport_block *)handle;
2087	sc = (struct ndis_softc *)block->nmb_ifp;
2088	dest = buf;
2089
2090	bh = rman_get_bushandle(sc->ndis_res_am);
2091	bt = rman_get_bustag(sc->ndis_res_am);
2092
2093	for (i = 0; i < len; i++)
2094		dest[i] = bus_space_read_1(bt, bh, (offset * 2) + (i * 2));
2095
2096	return(i);
2097}
2098
2099__stdcall static uint32_t
2100ndis_write_pccard_amem(handle, offset, buf, len)
2101	ndis_handle		handle;
2102	uint32_t		offset;
2103	void			*buf;
2104	uint32_t		len;
2105{
2106	struct ndis_softc	*sc;
2107	ndis_miniport_block	*block;
2108	bus_space_handle_t	bh;
2109	bus_space_tag_t		bt;
2110	char			*src;
2111	int			i;
2112
2113	if (handle == NULL)
2114		return(0);
2115
2116	block = (ndis_miniport_block *)handle;
2117	sc = (struct ndis_softc *)block->nmb_ifp;
2118	src = buf;
2119
2120	bh = rman_get_bushandle(sc->ndis_res_am);
2121	bt = rman_get_bustag(sc->ndis_res_am);
2122
2123	for (i = 0; i < len; i++)
2124		bus_space_write_1(bt, bh, (offset * 2) + (i * 2), src[i]);
2125
2126	return(i);
2127}
2128
2129__stdcall static ndis_list_entry *
2130ndis_insert_head(head, entry, lock)
2131	ndis_list_entry		*head;
2132	ndis_list_entry		*entry;
2133	ndis_spin_lock		*lock;
2134{
2135	ndis_list_entry		*flink;
2136
2137	mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2138	flink = head->nle_flink;
2139	entry->nle_flink = flink;
2140	entry->nle_blink = head;
2141	flink->nle_blink = entry;
2142	head->nle_flink = entry;
2143	mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2144
2145	return(flink);
2146}
2147
2148__stdcall static ndis_list_entry *
2149ndis_remove_head(head, lock)
2150	ndis_list_entry		*head;
2151	ndis_spin_lock		*lock;
2152{
2153	ndis_list_entry		*flink;
2154	ndis_list_entry		*entry;
2155
2156	mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2157	entry = head->nle_flink;
2158	flink = entry->nle_flink;
2159	head->nle_flink = flink;
2160	flink->nle_blink = head;
2161	mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2162
2163	return(entry);
2164}
2165
2166__stdcall static ndis_list_entry *
2167ndis_insert_tail(head, entry, lock)
2168	ndis_list_entry		*head;
2169	ndis_list_entry		*entry;
2170	ndis_spin_lock		*lock;
2171{
2172	ndis_list_entry		*blink;
2173
2174	mtx_pool_lock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2175	blink = head->nle_blink;
2176	entry->nle_flink = head;
2177	entry->nle_blink = blink;
2178	blink->nle_flink = entry;
2179	head->nle_blink = entry;
2180	mtx_pool_unlock(ndis_mtxpool, (struct mtx *)lock->nsl_spinlock);
2181
2182	return(blink);
2183}
2184
2185__stdcall static uint8_t
2186ndis_sync_with_intr(intr, syncfunc, syncctx)
2187	ndis_miniport_interrupt	*intr;
2188	void			*syncfunc;
2189	void			*syncctx;
2190{
2191	struct ndis_softc	*sc;
2192	__stdcall uint8_t (*sync)(void *);
2193	uint8_t			rval;
2194
2195	if (syncfunc == NULL || syncctx == NULL)
2196		return(0);
2197
2198	sc = (struct ndis_softc *)intr->ni_block->nmb_ifp;
2199	sync = syncfunc;
2200	mtx_pool_lock(ndis_mtxpool, sc->ndis_intrmtx);
2201	rval = sync(syncctx);
2202	mtx_pool_unlock(ndis_mtxpool, sc->ndis_intrmtx);
2203
2204	return(rval);
2205}
2206
2207/*
2208 * Return the number of 100 nanosecond intervals since
2209 * January 1, 1601. (?!?!)
2210 */
2211__stdcall static void
2212ndis_time(tval)
2213	uint64_t		*tval;
2214{
2215	struct timespec		ts;
2216
2217	nanotime(&ts);
2218	*tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2219	    11644473600;
2220}
2221
2222/*
2223 * Return the number of milliseconds since the system booted.
2224 */
2225__stdcall static void
2226ndis_uptime(tval)
2227	uint32_t		*tval;
2228{
2229	struct timespec		ts;
2230
2231	nanouptime(&ts);
2232	*tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
2233}
2234
2235__stdcall static void
2236ndis_init_string(dst, src)
2237	ndis_unicode_string	*dst;
2238	char			*src;
2239{
2240	ndis_unicode_string	*u;
2241
2242	u = dst;
2243	u->nus_buf = NULL;
2244	if (ndis_ascii_to_unicode(src, &u->nus_buf))
2245		return;
2246	u->nus_len = u->nus_maxlen = strlen(src) * 2;
2247	return;
2248}
2249
2250__stdcall static void
2251ndis_free_string(str)
2252	ndis_unicode_string	*str;
2253{
2254	if (str == NULL)
2255		return;
2256	if (str->nus_buf != NULL)
2257		free(str->nus_buf, M_DEVBUF);
2258	free(str, M_DEVBUF);
2259	return;
2260}
2261
2262__stdcall static ndis_status
2263ndis_remove_miniport(adapter)
2264	ndis_handle		*adapter;
2265{
2266	return(NDIS_STATUS_SUCCESS);
2267}
2268
2269__stdcall static void
2270ndis_init_ansi_string(dst, src)
2271	ndis_ansi_string	*dst;
2272	char			*src;
2273{
2274	ndis_ansi_string	*a;
2275
2276	a = dst;
2277	if (a == NULL)
2278		return;
2279	if (src == NULL) {
2280		a->nas_len = a->nas_maxlen = 0;
2281		a->nas_buf = NULL;
2282	} else {
2283		a->nas_buf = src;
2284		a->nas_len = a->nas_maxlen = strlen(src);
2285	}
2286
2287	return;
2288}
2289
2290__stdcall static void
2291ndis_init_unicode_string(dst, src)
2292	ndis_unicode_string	*dst;
2293	uint16_t		*src;
2294{
2295	ndis_unicode_string	*u;
2296	int			i;
2297
2298	u = dst;
2299	if (u == NULL)
2300		return;
2301	if (src == NULL) {
2302		u->nus_len = u->nus_maxlen = 0;
2303		u->nus_buf = NULL;
2304	} else {
2305		i = 0;
2306		while(src[i] != 0)
2307			i++;
2308		u->nus_buf = src;
2309		u->nus_len = u->nus_maxlen = i * 2;
2310	}
2311
2312	return;
2313}
2314
2315__stdcall static void ndis_get_devprop(adapter, phydevobj,
2316	funcdevobj, nextdevobj, resources, transresources)
2317	ndis_handle		adapter;
2318	void			*phydevobj;
2319	void			*funcdevobj;
2320	void			*nextdevobj;
2321	cm_resource_list	*resources;
2322	cm_resource_list	*transresources;
2323{
2324	return;
2325}
2326
2327__stdcall static void
2328ndis_firstbuf(packet, buf, firstva, firstlen, totlen)
2329	ndis_packet		*packet;
2330	ndis_buffer		**buf;
2331	void			**firstva;
2332	uint32_t		*firstlen;
2333	uint32_t		*totlen;
2334{
2335	ndis_buffer		*tmp;
2336
2337	tmp = packet->np_private.npp_head;
2338	*buf = tmp;
2339	if (tmp == NULL) {
2340		*firstva = NULL;
2341		*firstlen = *totlen = 0;
2342	} else {
2343		*firstva = MDL_VA(tmp);
2344		*firstlen = *totlen = tmp->nb_bytecount;
2345		for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
2346			*totlen += tmp->nb_bytecount;
2347	}
2348
2349	return;
2350}
2351
2352__stdcall static void
2353ndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio)
2354	ndis_packet		*packet;
2355	ndis_buffer		**buf;
2356	void			**firstva;
2357	uint32_t		*firstlen;
2358	uint32_t		*totlen;
2359	uint32_t		prio;
2360{
2361	ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
2362}
2363
2364/* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2365__stdcall static void
2366ndis_open_file(status, filehandle, filelength, filename, highestaddr)
2367	ndis_status		*status;
2368	ndis_handle		*filehandle;
2369	uint32_t		*filelength;
2370	ndis_unicode_string	*filename;
2371	ndis_physaddr		highestaddr;
2372{
2373	char			*afilename = NULL;
2374	struct thread		*td = curthread;
2375	struct nameidata	nd;
2376	int			flags, error;
2377	struct vattr		vat;
2378	struct vattr		*vap = &vat;
2379	ndis_fh			*fh;
2380	char			path[MAXPATHLEN];
2381
2382	ndis_unicode_to_ascii(filename->nus_buf,
2383	    filename->nus_len, &afilename);
2384
2385	sprintf(path, "%s/%s", ndis_filepath, afilename);
2386	free(afilename, M_DEVBUF);
2387
2388	fh = malloc(sizeof(ndis_fh), M_TEMP, M_NOWAIT);
2389	if (fh == NULL) {
2390		*status = NDIS_STATUS_RESOURCES;
2391		return;
2392	}
2393
2394	mtx_lock(&Giant);
2395	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
2396
2397	flags = FREAD;
2398	error = vn_open(&nd, &flags, 0, -1);
2399	if (error) {
2400		mtx_unlock(&Giant);
2401		*status = NDIS_STATUS_FILE_NOT_FOUND;
2402		free(fh, M_TEMP);
2403		return;
2404	}
2405
2406	NDFREE(&nd, NDF_ONLY_PNBUF);
2407
2408	/* Get the file size. */
2409	VOP_GETATTR(nd.ni_vp, vap, NOCRED, td);
2410	VOP_UNLOCK(nd.ni_vp, 0, td);
2411	mtx_unlock(&Giant);
2412
2413	fh->nf_vp = nd.ni_vp;
2414	fh->nf_map = NULL;
2415	*filehandle = fh;
2416	*filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
2417	*status = NDIS_STATUS_SUCCESS;
2418	return;
2419}
2420
2421__stdcall static void
2422ndis_map_file(status, mappedbuffer, filehandle)
2423	ndis_status		*status;
2424	void			**mappedbuffer;
2425	ndis_handle		filehandle;
2426{
2427	ndis_fh			*fh;
2428	struct thread		*td = curthread;
2429	int			error, resid;
2430
2431	if (filehandle == NULL) {
2432		*status = NDIS_STATUS_FAILURE;
2433		return;
2434	}
2435
2436	fh = (ndis_fh *)filehandle;
2437
2438	if (fh->nf_vp == NULL) {
2439		*status = NDIS_STATUS_FAILURE;
2440		return;
2441	}
2442
2443	if (fh->nf_map != NULL) {
2444		*status = NDIS_STATUS_ALREADY_MAPPED;
2445		return;
2446	}
2447
2448	fh->nf_map = malloc(fh->nf_maplen, M_DEVBUF, M_NOWAIT);
2449
2450	if (fh->nf_map == NULL) {
2451		*status = NDIS_STATUS_RESOURCES;
2452		return;
2453	}
2454
2455	mtx_lock(&Giant);
2456	error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
2457	    UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td);
2458	mtx_unlock(&Giant);
2459
2460	if (error)
2461		*status = NDIS_STATUS_FAILURE;
2462	else {
2463		*status = NDIS_STATUS_SUCCESS;
2464		*mappedbuffer = fh->nf_map;
2465	}
2466
2467	return;
2468}
2469
2470__stdcall static void
2471ndis_unmap_file(filehandle)
2472	ndis_handle		filehandle;
2473{
2474	ndis_fh			*fh;
2475	fh = (ndis_fh *)filehandle;
2476
2477	if (fh->nf_map == NULL)
2478		return;
2479	free(fh->nf_map, M_DEVBUF);
2480	fh->nf_map = NULL;
2481
2482	return;
2483}
2484
2485__stdcall static void
2486ndis_close_file(filehandle)
2487	ndis_handle		filehandle;
2488{
2489	struct thread		*td = curthread;
2490	ndis_fh			*fh;
2491
2492	if (filehandle == NULL)
2493		return;
2494
2495	fh = (ndis_fh *)filehandle;
2496	if (fh->nf_map != NULL) {
2497		free(fh->nf_map, M_DEVBUF);
2498		fh->nf_map = NULL;
2499	}
2500
2501	if (fh->nf_vp == NULL)
2502		return;
2503
2504	mtx_lock(&Giant);
2505	vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
2506	mtx_unlock(&Giant);
2507
2508	fh->nf_vp = NULL;
2509	free(fh, M_DEVBUF);
2510
2511	return;
2512}
2513
2514__stdcall static uint8_t
2515ndis_cpu_cnt()
2516{
2517	return(mp_ncpus);
2518}
2519
2520typedef void (*ndis_statusdone_handler)(ndis_handle);
2521typedef void (*ndis_status_handler)(ndis_handle, ndis_status,
2522        void *, uint32_t);
2523
2524__stdcall static void
2525ndis_ind_statusdone(adapter)
2526	ndis_handle		adapter;
2527{
2528	ndis_miniport_block	*block;
2529	__stdcall ndis_statusdone_handler	statusdonefunc;
2530
2531	block = (ndis_miniport_block *)adapter;
2532	statusdonefunc = block->nmb_statusdone_func;
2533
2534	statusdonefunc(adapter);
2535	return;
2536}
2537
2538__stdcall static void
2539ndis_ind_status(adapter, status, sbuf, slen)
2540	ndis_handle		adapter;
2541	ndis_status		status;
2542	void			*sbuf;
2543	uint32_t		slen;
2544{
2545	ndis_miniport_block	*block;
2546	__stdcall ndis_status_handler	statusfunc;
2547
2548	block = (ndis_miniport_block *)adapter;
2549	statusfunc = block->nmb_status_func;
2550
2551	statusfunc(adapter, status, sbuf, slen);
2552	return;
2553}
2554
2555static void
2556ndis_workfunc(ctx)
2557	void			*ctx;
2558{
2559	ndis_work_item		*work;
2560	__stdcall ndis_proc	workfunc;
2561
2562	work = ctx;
2563	workfunc = work->nwi_func;
2564	workfunc(work, work->nwi_ctx);
2565	return;
2566}
2567
2568__stdcall static ndis_status
2569ndis_sched_workitem(work)
2570	ndis_work_item		*work;
2571{
2572	ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
2573	return(NDIS_STATUS_SUCCESS);
2574}
2575
2576__stdcall static void
2577ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen)
2578	ndis_packet		*dpkt;
2579	uint32_t		doff;
2580	uint32_t		reqlen;
2581	ndis_packet		*spkt;
2582	uint32_t		soff;
2583	uint32_t		*cpylen;
2584{
2585	ndis_buffer		*src, *dst;
2586	char			*sptr, *dptr;
2587	int			resid, copied, len, scnt, dcnt;
2588
2589	*cpylen = 0;
2590
2591	src = spkt->np_private.npp_head;
2592	dst = dpkt->np_private.npp_head;
2593
2594	sptr = MDL_VA(src);
2595	dptr = MDL_VA(dst);
2596	scnt = src->nb_bytecount;
2597	dcnt = dst->nb_bytecount;
2598
2599	while (soff) {
2600		if (src->nb_bytecount > soff) {
2601			sptr += soff;
2602			scnt = src->nb_bytecount - soff;
2603			break;
2604		}
2605		soff -= src->nb_bytecount;
2606		src = src->nb_next;
2607		if (src == NULL)
2608			return;
2609		sptr = MDL_VA(src);
2610	}
2611
2612	while (doff) {
2613		if (dst->nb_bytecount > doff) {
2614			dptr += doff;
2615			dcnt = dst->nb_bytecount - doff;
2616			break;
2617		}
2618		doff -= dst->nb_bytecount;
2619		dst = dst->nb_next;
2620		if (dst == NULL)
2621			return;
2622		dptr = MDL_VA(dst);
2623	}
2624
2625	resid = reqlen;
2626	copied = 0;
2627
2628	while(1) {
2629		if (resid < scnt)
2630			len = resid;
2631		else
2632			len = scnt;
2633		if (dcnt < len)
2634			len = dcnt;
2635
2636		bcopy(sptr, dptr, len);
2637
2638		copied += len;
2639		resid -= len;
2640		if (resid == 0)
2641			break;
2642
2643		dcnt -= len;
2644		if (dcnt == 0) {
2645			dst = dst->nb_next;
2646			if (dst == NULL)
2647				break;
2648			dptr = MDL_VA(dst);
2649			dcnt = dst->nb_bytecount;
2650		}
2651
2652		scnt -= len;
2653		if (scnt == 0) {
2654			src = src->nb_next;
2655			if (src == NULL)
2656				break;
2657			sptr = MDL_VA(src);
2658			scnt = src->nb_bytecount;
2659		}
2660	}
2661
2662	*cpylen = copied;
2663	return;
2664}
2665
2666__stdcall static void
2667ndis_pkt_to_pkt_safe(dpkt, doff, reqlen, spkt, soff, cpylen, prio)
2668	ndis_packet		*dpkt;
2669	uint32_t		doff;
2670	uint32_t		reqlen;
2671	ndis_packet		*spkt;
2672	uint32_t		soff;
2673	uint32_t		*cpylen;
2674	uint32_t		prio;
2675{
2676	ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen);
2677	return;
2678}
2679
2680__stdcall static ndis_status
2681ndis_register_dev(handle, devname, symname, majorfuncs, devobj, devhandle)
2682	ndis_handle		*handle;
2683	ndis_unicode_string	*devname;
2684	ndis_unicode_string	*symname;
2685	void			*majorfuncs;
2686	void			*devobj;
2687	ndis_handle		**devhandle;
2688{
2689	return(NDIS_STATUS_SUCCESS);
2690}
2691
2692__stdcall static ndis_status
2693ndis_deregister_dev(devhandle)
2694	ndis_handle		*devhandle;
2695{
2696	return(NDIS_STATUS_SUCCESS);
2697}
2698
2699
2700__stdcall static void
2701dummy()
2702{
2703	printf ("NDIS dummy called...\n");
2704	return;
2705}
2706
2707image_patch_table ndis_functbl[] = {
2708	{ "NdisCopyFromPacketToPacket",	(FUNC)ndis_pkt_to_pkt },
2709	{ "NdisCopyFromPacketToPacketSafe", (FUNC)ndis_pkt_to_pkt_safe },
2710	{ "NdisScheduleWorkItem",	(FUNC)ndis_sched_workitem },
2711	{ "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone },
2712	{ "NdisMIndicateStatus",	(FUNC)ndis_ind_status },
2713	{ "NdisSystemProcessorCount",	(FUNC)ndis_cpu_cnt },
2714	{ "NdisUnchainBufferAtBack",	(FUNC)ndis_unchain_tailbuf, },
2715	{ "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf },
2716	{ "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe },
2717	{ "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2718	{ "NdisMGetDeviceProperty",	(FUNC)ndis_get_devprop },
2719	{ "NdisInitAnsiString",		(FUNC)ndis_init_ansi_string },
2720	{ "NdisInitUnicodeString",	(FUNC)ndis_init_unicode_string },
2721	{ "NdisWriteConfiguration",	(FUNC)ndis_write_cfg },
2722	{ "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2723	{ "NdisTerminateWrapper",	(FUNC)ndis_termwrap },
2724	{ "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2725	{ "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2726	{ "NdisMRemoveMiniport",	(FUNC)ndis_remove_miniport },
2727	{ "NdisInitializeString",	(FUNC)ndis_init_string },
2728	{ "NdisFreeString",		(FUNC)ndis_free_string },
2729	{ "NdisGetCurrentSystemTime",	(FUNC)ndis_time },
2730	{ "NdisGetSystemUpTime",	(FUNC)ndis_uptime },
2731	{ "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2732	{ "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2733	{ "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2734	{ "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2735	{ "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2736	{ "NdisInitializeWrapper",	(FUNC)ndis_initwrap },
2737	{ "NdisMRegisterMiniport",	(FUNC)ndis_register_miniport },
2738	{ "NdisAllocateMemoryWithTag",	(FUNC)ndis_malloc_withtag },
2739	{ "NdisAllocateMemory",		(FUNC)ndis_malloc },
2740	{ "NdisMSetAttributesEx",	(FUNC)ndis_setattr_ex },
2741	{ "NdisCloseConfiguration",	(FUNC)ndis_close_cfg },
2742	{ "NdisReadConfiguration",	(FUNC)ndis_read_cfg },
2743	{ "NdisOpenConfiguration",	(FUNC)ndis_open_cfg },
2744	{ "NdisReleaseSpinLock",	(FUNC)ndis_unlock },
2745	{ "NdisDprAcquireSpinLock",	(FUNC)ndis_lock },
2746	{ "NdisDprReleaseSpinLock",	(FUNC)ndis_unlock },
2747	{ "NdisAcquireSpinLock",	(FUNC)ndis_lock },
2748	{ "NdisAllocateSpinLock",	(FUNC)ndis_create_lock },
2749	{ "NdisFreeSpinLock",		(FUNC)ndis_destroy_lock },
2750	{ "NdisFreeMemory",		(FUNC)ndis_free },
2751	{ "NdisReadPciSlotInformation",	(FUNC)ndis_read_pci },
2752	{ "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2753	{ "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci },
2754	{ "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci },
2755	{ "NdisWriteErrorLogEntry",	(FUNC)ndis_syslog },
2756	{ "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2757	{ "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2758	{ "NdisMInitializeTimer",	(FUNC)ndis_create_timer },
2759	{ "NdisInitializeTimer",	(FUNC)ndis_init_timer },
2760	{ "NdisSetTimer",		(FUNC)ndis_set_timer },
2761	{ "NdisMCancelTimer",		(FUNC)ndis_cancel_timer },
2762	{ "NdisCancelTimer",		(FUNC)ndis_cancel_timer },
2763	{ "NdisMSetPeriodicTimer",	(FUNC)ndis_set_periodic_timer },
2764	{ "NdisMQueryAdapterResources",	(FUNC)ndis_query_resources },
2765	{ "NdisMRegisterIoPortRange",	(FUNC)ndis_register_ioport },
2766	{ "NdisMDeregisterIoPortRange",	(FUNC)ndis_deregister_ioport },
2767	{ "NdisReadNetworkAddress",	(FUNC)ndis_read_netaddr },
2768	{ "NdisQueryMapRegisterCount",	(FUNC)ndis_mapreg_cnt },
2769	{ "NdisMAllocateMapRegisters",	(FUNC)ndis_alloc_mapreg },
2770	{ "NdisMFreeMapRegisters",	(FUNC)ndis_free_mapreg },
2771	{ "NdisMAllocateSharedMemory",	(FUNC)ndis_alloc_sharedmem },
2772	{ "NdisMMapIoSpace",		(FUNC)ndis_map_iospace },
2773	{ "NdisMUnmapIoSpace",		(FUNC)ndis_unmap_iospace },
2774	{ "NdisGetCacheFillSize",	(FUNC)ndis_cachefill },
2775	{ "NdisMGetDmaAlignment",	(FUNC)ndis_dma_align },
2776	{ "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2777	{ "NdisAllocatePacketPool",	(FUNC)ndis_alloc_packetpool },
2778	{ "NdisAllocatePacketPoolEx",	(FUNC)ndis_ex_alloc_packetpool },
2779	{ "NdisAllocatePacket",		(FUNC)ndis_alloc_packet },
2780	{ "NdisFreePacket",		(FUNC)ndis_release_packet },
2781	{ "NdisFreePacketPool",		(FUNC)ndis_free_packetpool },
2782	{ "NdisDprAllocatePacket",	(FUNC)ndis_alloc_packet },
2783	{ "NdisDprFreePacket",		(FUNC)ndis_release_packet },
2784	{ "NdisAllocateBufferPool",	(FUNC)ndis_alloc_bufpool },
2785	{ "NdisAllocateBuffer",		(FUNC)ndis_alloc_buf },
2786	{ "NdisQueryBuffer",		(FUNC)ndis_query_buf },
2787	{ "NdisQueryBufferSafe",	(FUNC)ndis_query_buf_safe },
2788	{ "NdisBufferVirtualAddress",	(FUNC)ndis_buf_vaddr },
2789	{ "NdisBufferVirtualAddressSafe", (FUNC)ndis_buf_vaddr_safe },
2790	{ "NdisBufferLength",		(FUNC)ndis_buflen },
2791	{ "NdisFreeBuffer",		(FUNC)ndis_release_buf },
2792	{ "NdisFreeBufferPool",		(FUNC)ndis_free_bufpool },
2793	{ "NdisInterlockedIncrement",	(FUNC)ndis_interlock_inc },
2794	{ "NdisInterlockedDecrement",	(FUNC)ndis_interlock_dec },
2795	{ "NdisInitializeEvent",	(FUNC)ndis_init_event },
2796	{ "NdisSetEvent",		(FUNC)ndis_set_event },
2797	{ "NdisResetEvent",		(FUNC)ndis_reset_event },
2798	{ "NdisWaitEvent",		(FUNC)ndis_wait_event },
2799	{ "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2800	{ "NdisMPciAssignResources",	(FUNC)ndis_assign_pcirsrc },
2801	{ "NdisMFreeSharedMemory",	(FUNC)ndis_free_sharedmem },
2802	{ "NdisMRegisterInterrupt",	(FUNC)ndis_register_intr },
2803	{ "NdisMDeregisterInterrupt",	(FUNC)ndis_deregister_intr },
2804	{ "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2805	{ "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
2806	{ "NDIS_BUFFER_TO_SPAN_PAGES",	(FUNC)ndis_numpages },
2807	{ "NdisQueryBufferOffset",	(FUNC)ndis_query_bufoffset },
2808	{ "NdisAdjustBufferLength",	(FUNC)ndis_adjust_buflen },
2809	{ "NdisPacketPoolUsage",	(FUNC)ndis_packetpool_use },
2810	{ "NdisMSleep",			(FUNC)ndis_sleep },
2811	{ "NdisUnchainBufferAtFront",	(FUNC)ndis_unchain_headbuf },
2812	{ "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
2813	{ "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
2814	{ "NdisOpenFile",		(FUNC)ndis_open_file },
2815	{ "NdisMapFile",		(FUNC)ndis_map_file },
2816	{ "NdisUnmapFile",		(FUNC)ndis_unmap_file },
2817	{ "NdisCloseFile",		(FUNC)ndis_close_file },
2818	{ "NdisMRegisterDevice",	(FUNC)ndis_register_dev },
2819	{ "NdisMDeregisterDevice",	(FUNC)ndis_deregister_dev },
2820
2821	/*
2822	 * This last entry is a catch-all for any function we haven't
2823	 * implemented yet. The PE import list patching routine will
2824	 * use it for any function that doesn't have an explicit match
2825	 * in this table.
2826	 */
2827
2828	{ NULL, (FUNC)dummy },
2829
2830	/* End of list. */
2831
2832	{ NULL, NULL },
2833};
2834