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