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