3 * Bill Paul <wpaul@windriver.com>. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
32 * $FreeBSD: src/sys/compat/ndis/subr_ndis.c,v 1.62 2004/07/11 00:19:30 wpaul Exp $
33 * $DragonFly: src/sys/emulation/ndis/subr_ndis.c,v 1.13 2006/05/06 02:43:11 dillon Exp $
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.
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
51 #include <sys/ctype.h>
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/kernel.h>
55 #include <sys/types.h>
56 #include <sys/errno.h>
58 #include <sys/callout.h>
59 #include <sys/malloc.h>
61 #include <sys/socket.h>
62 #include <sys/sysctl.h>
63 #include <sys/queue.h>
65 #include <sys/filedesc.h>
66 #include <sys/nlookup.h>
67 #include <sys/fcntl.h>
68 #include <sys/vnode.h>
69 #include <sys/kthread.h>
72 #include <net/if_arp.h>
73 #include <net/ethernet.h>
74 #include <net/if_dl.h>
75 #include <net/if_media.h>
77 #include <machine/atomic.h>
78 #include <machine/bus_memio.h>
79 #include <machine/bus_pio.h>
80 #include <machine/bus.h>
81 #include <machine/resource.h>
86 #include <machine/stdarg.h>
88 #include <netproto/802_11/ieee80211_var.h>
89 #include <netproto/802_11/ieee80211_ioctl.h>
91 #include <bus/pci/pcireg.h>
92 #include <bus/pci/pcivar.h>
96 #include "resource_var.h"
97 #include "ntoskrnl_var.h"
101 #include <dev/netif/ndis/if_ndisvar.h>
103 #define FUNC void(*)(void)
105 static char ndis_filepath[MAXPATHLEN];
106 extern struct nd_head ndis_devhead;
108 SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
109 MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
111 __stdcall static void ndis_initwrap(ndis_handle *,
112 device_object *, void *, void *);
113 __stdcall static ndis_status ndis_register_miniport(ndis_handle,
114 ndis_miniport_characteristics *, int);
115 __stdcall static ndis_status ndis_malloc_withtag(void **, uint32_t, uint32_t);
116 __stdcall static ndis_status ndis_malloc(void **,
117 uint32_t, uint32_t, ndis_physaddr);
118 __stdcall static void ndis_free(void *, uint32_t, uint32_t);
119 __stdcall static ndis_status ndis_setattr_ex(ndis_handle, ndis_handle,
120 uint32_t, uint32_t, ndis_interface_type);
121 __stdcall static void ndis_open_cfg(ndis_status *, ndis_handle *, ndis_handle);
122 __stdcall static void ndis_open_cfgbyidx(ndis_status *, ndis_handle,
123 uint32_t, ndis_unicode_string *, ndis_handle *);
124 __stdcall static void ndis_open_cfgbyname(ndis_status *, ndis_handle,
125 ndis_unicode_string *, ndis_handle *);
126 static ndis_status ndis_encode_parm(ndis_miniport_block *,
127 struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
128 static ndis_status ndis_decode_parm(ndis_miniport_block *,
129 ndis_config_parm *, char *);
130 __stdcall static void ndis_read_cfg(ndis_status *, ndis_config_parm **,
131 ndis_handle, ndis_unicode_string *, ndis_parm_type);
132 __stdcall static void ndis_write_cfg(ndis_status *, ndis_handle,
133 ndis_unicode_string *, ndis_config_parm *);
134 __stdcall static void ndis_close_cfg(ndis_handle);
135 __stdcall static void ndis_create_lock(ndis_spin_lock *);
136 __stdcall static void ndis_destroy_lock(ndis_spin_lock *);
137 __stdcall static void ndis_lock(ndis_spin_lock *);
138 __stdcall static void ndis_unlock(ndis_spin_lock *);
139 __stdcall static void ndis_lock_dpr(ndis_spin_lock *);
140 __stdcall static void ndis_unlock_dpr(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);
145 static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
146 static 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 *);
152 __stdcall static void ndis_init_timer(ndis_timer *,
153 ndis_timer_function, void *);
154 __stdcall static void ndis_set_timer(ndis_timer *, uint32_t);
155 __stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
156 __stdcall static void ndis_cancel_timer(ndis_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);
169 static 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 static void ndis_asyncmem_complete(void *);
173 __stdcall static ndis_status ndis_alloc_sharedmem_async(ndis_handle,
174 uint32_t, uint8_t, void *);
175 __stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
176 uint8_t, void *, ndis_physaddr);
177 __stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
178 ndis_physaddr, uint32_t);
179 __stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
180 __stdcall static uint32_t ndis_cachefill(void);
181 __stdcall static uint32_t ndis_dma_align(ndis_handle);
182 __stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
184 __stdcall static void ndis_alloc_packetpool(ndis_status *,
185 ndis_handle *, uint32_t, uint32_t);
186 __stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
187 ndis_handle *, uint32_t, uint32_t, uint32_t);
188 __stdcall static uint32_t ndis_packetpool_use(ndis_handle);
189 __stdcall static void ndis_free_packetpool(ndis_handle);
190 __stdcall static void ndis_alloc_packet(ndis_status *,
191 ndis_packet **, ndis_handle);
192 __stdcall static void ndis_release_packet(ndis_packet *);
193 __stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
194 __stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **);
195 __stdcall static void ndis_alloc_bufpool(ndis_status *,
196 ndis_handle *, uint32_t);
197 __stdcall static void ndis_free_bufpool(ndis_handle);
198 __stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
199 ndis_handle, void *, uint32_t);
200 __stdcall static void ndis_release_buf(ndis_buffer *);
201 __stdcall static uint32_t ndis_buflen(ndis_buffer *);
202 __stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
203 __stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
204 uint32_t *, uint32_t);
205 __stdcall static void *ndis_buf_vaddr(ndis_buffer *);
206 __stdcall static void *ndis_buf_vaddr_safe(ndis_buffer *, uint32_t);
207 __stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
208 __stdcall static uint32_t ndis_interlock_inc(uint32_t *);
209 __stdcall static uint32_t ndis_interlock_dec(uint32_t *);
210 __stdcall static void ndis_init_event(ndis_event *);
211 __stdcall static void ndis_set_event(ndis_event *);
212 __stdcall static void ndis_reset_event(ndis_event *);
213 __stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
214 __stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
215 ndis_unicode_string *);
216 __stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
218 __stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
219 uint32_t, ndis_resource_list **);
220 __stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
221 ndis_handle, uint32_t, uint32_t, uint8_t,
222 uint8_t, ndis_interrupt_mode);
223 __stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
224 __stdcall static void ndis_register_shutdown(ndis_handle, void *,
225 ndis_shutdown_handler);
226 __stdcall static void ndis_deregister_shutdown(ndis_handle);
227 __stdcall static uint32_t ndis_numpages(ndis_buffer *);
228 __stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
229 __stdcall static void ndis_query_bufoffset(ndis_buffer *,
230 uint32_t *, uint32_t *);
231 __stdcall static void ndis_sleep(uint32_t);
232 __stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
233 uint32_t, void *, uint32_t);
234 __stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
235 uint32_t, void *, uint32_t);
236 __stdcall static list_entry *ndis_insert_head(list_entry *,
237 list_entry *, ndis_spin_lock *);
238 __stdcall static list_entry *ndis_remove_head(list_entry *,
240 __stdcall static list_entry *ndis_insert_tail(list_entry *,
241 list_entry *, ndis_spin_lock *);
242 __stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
244 __stdcall static void ndis_time(uint64_t *);
245 __stdcall static void ndis_uptime(uint32_t *);
246 __stdcall static void ndis_init_string(ndis_unicode_string *, char *);
247 __stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
248 __stdcall static void ndis_init_unicode_string(ndis_unicode_string *,
250 __stdcall static void ndis_free_string(ndis_unicode_string *);
251 __stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
252 __stdcall static void ndis_termwrap(ndis_handle, void *);
253 __stdcall static void ndis_get_devprop(ndis_handle, device_object **,
254 device_object **, device_object **, cm_resource_list *,
256 __stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
257 void **, uint32_t *, uint32_t *);
258 __stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
259 void **, uint32_t *, uint32_t *, uint32_t);
260 __stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
261 ndis_unicode_string *, ndis_physaddr);
262 __stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
263 __stdcall static void ndis_unmap_file(ndis_handle);
264 __stdcall static void ndis_close_file(ndis_handle);
265 __stdcall static u_int8_t ndis_cpu_cnt(void);
266 __stdcall static void ndis_ind_statusdone(ndis_handle);
267 __stdcall static void ndis_ind_status(ndis_handle, ndis_status,
269 static void ndis_workfunc(void *);
270 __stdcall static ndis_status ndis_sched_workitem(ndis_work_item *);
271 __stdcall static void ndis_pkt_to_pkt(ndis_packet *, uint32_t, uint32_t,
272 ndis_packet *, uint32_t, uint32_t *);
273 __stdcall static void ndis_pkt_to_pkt_safe(ndis_packet *, uint32_t, uint32_t,
274 ndis_packet *, uint32_t, uint32_t *, uint32_t);
275 __stdcall static ndis_status ndis_register_dev(ndis_handle,
276 ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **,
277 void **, ndis_handle *);
278 __stdcall static ndis_status ndis_deregister_dev(ndis_handle);
279 __stdcall static ndis_status ndis_query_name(ndis_unicode_string *,
281 __stdcall static void ndis_register_unload(ndis_handle, void *);
282 __stdcall static void dummy(void);
285 * Some really old drivers do not properly check the return value
286 * from NdisAllocatePacket() and NdisAllocateBuffer() and will
287 * sometimes allocate few more buffers/packets that they originally
288 * requested when they created the pool. To prevent this from being
289 * a problem, we allocate a few extra buffers/packets beyond what
290 * the driver asks for. This #define controls how many.
292 #define NDIS_POOL_EXTRA 16
297 strcpy(ndis_filepath, "/compat/ndis");
308 * NDIS deals with strings in unicode format, so we have
309 * do deal with them that way too. For now, we only handle
310 * conversion between unicode and ASCII since that's all
311 * that device drivers care about.
315 ndis_ascii_to_unicode(char *ascii, uint16_t **unicode)
320 if (*unicode == NULL)
321 *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
323 for (i = 0; i < strlen(ascii); i++) {
324 *ustr = (uint16_t)ascii[i];
332 ndis_unicode_to_ascii(uint16_t *unicode, int ulen, char **ascii)
338 *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO);
340 for (i = 0; i < ulen / 2; i++) {
341 *astr = (uint8_t)unicode[i];
348 __stdcall static void
349 ndis_initwrap(ndis_handle *wrapper, device_object *drv_obj, void *path,
352 ndis_miniport_block *block;
354 block = drv_obj->do_rsvd;
360 __stdcall static void
361 ndis_termwrap(ndis_handle handle, void *syspec)
366 __stdcall static ndis_status
367 ndis_register_miniport(ndis_handle handle,
368 ndis_miniport_characteristics *characteristics,
371 ndis_miniport_block *block;
372 struct ndis_softc *sc;
374 block = (ndis_miniport_block *)handle;
375 sc = (struct ndis_softc *)block->nmb_ifp;
376 bcopy((char *)characteristics, (char *)&sc->ndis_chars,
377 sizeof(ndis_miniport_characteristics));
378 if (sc->ndis_chars.nmc_version_major < 5 ||
379 sc->ndis_chars.nmc_version_minor < 1) {
380 sc->ndis_chars.nmc_shutdown_handler = NULL;
381 sc->ndis_chars.nmc_canceltxpkts_handler = NULL;
382 sc->ndis_chars.nmc_pnpevent_handler = NULL;
385 return(NDIS_STATUS_SUCCESS);
388 __stdcall static ndis_status
389 ndis_malloc_withtag(void **vaddr, uint32_t len, uint32_t tag)
393 mem = malloc(len, M_DEVBUF, M_INTWAIT|M_NULLOK);
395 return(NDIS_STATUS_RESOURCES);
398 return(NDIS_STATUS_SUCCESS);
401 __stdcall static ndis_status
402 ndis_malloc(void **vaddr, uint32_t len, uint32_t flags,
403 ndis_physaddr highaddr)
407 mem = malloc(len, M_DEVBUF, M_INTWAIT|M_NULLOK);
409 return(NDIS_STATUS_RESOURCES);
412 return(NDIS_STATUS_SUCCESS);
415 __stdcall static void
416 ndis_free(void *vaddr, uint32_t len, uint32_t flags)
420 free(vaddr, M_DEVBUF);
425 __stdcall static ndis_status
426 ndis_setattr_ex(ndis_handle adapter_handle, ndis_handle adapter_ctx,
427 uint32_t hangsecs, uint32_t flags,
428 ndis_interface_type iftype)
430 ndis_miniport_block *block;
433 * Save the adapter context, we need it for calling
434 * the driver's internal functions.
436 block = (ndis_miniport_block *)adapter_handle;
437 block->nmb_miniportadapterctx = adapter_ctx;
438 block->nmb_checkforhangsecs = hangsecs;
439 block->nmb_flags = flags;
441 return(NDIS_STATUS_SUCCESS);
444 __stdcall static void
445 ndis_open_cfg(ndis_status *status, ndis_handle *cfg, ndis_handle wrapctx)
448 *status = NDIS_STATUS_SUCCESS;
452 __stdcall static void
453 ndis_open_cfgbyname(ndis_status *status, ndis_handle cfg,
454 ndis_unicode_string *subkey, ndis_handle *subhandle)
457 *status = NDIS_STATUS_SUCCESS;
461 __stdcall static void
462 ndis_open_cfgbyidx(ndis_status *status, ndis_handle cfg, uint32_t idx,
463 ndis_unicode_string *subkey, ndis_handle *subhandle)
465 *status = NDIS_STATUS_FAILURE;
470 ndis_encode_parm(ndis_miniport_block *block, struct sysctl_oid *oid,
471 ndis_parm_type type, ndis_config_parm **parm)
474 ndis_unicode_string *ustr;
477 unicode = (uint16_t *)&block->nmb_dummybuf;
480 case ndis_parm_string:
481 ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
482 (*parm)->ncp_type = ndis_parm_string;
483 ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
484 ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
485 ustr->nus_buf = unicode;
488 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
492 (*parm)->ncp_type = ndis_parm_int;
493 (*parm)->ncp_parmdata.ncp_intdata =
494 strtol((char *)oid->oid_arg1, NULL, base);
496 case ndis_parm_hexint:
497 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
501 (*parm)->ncp_type = ndis_parm_hexint;
502 (*parm)->ncp_parmdata.ncp_intdata =
503 strtoul((char *)oid->oid_arg1, NULL, base);
506 return(NDIS_STATUS_FAILURE);
510 return(NDIS_STATUS_SUCCESS);
514 ndis_strcasecmp(const char *s1, const char *s2)
519 * In the kernel, toupper() is a macro. Have to be careful
520 * not to use pointer arithmetic when passing it arguments.
526 if (toupper(a) != toupper(b))
532 return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
535 __stdcall static void
536 ndis_read_cfg(ndis_status *status, ndis_config_parm **parm, ndis_handle cfg,
537 ndis_unicode_string *key, ndis_parm_type type)
541 ndis_miniport_block *block;
542 struct ndis_softc *sc;
543 struct sysctl_oid *oidp;
544 struct sysctl_ctx_entry *e;
546 block = (ndis_miniport_block *)cfg;
547 sc = (struct ndis_softc *)block->nmb_ifp;
549 if (key->nus_len == 0 || key->nus_buf == NULL) {
550 *status = NDIS_STATUS_FAILURE;
554 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
556 *parm = &block->nmb_replyparm;
557 bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
558 unicode = (uint16_t *)&block->nmb_dummybuf;
561 * See if registry key is already in a list of known keys
562 * included with the driver.
564 #if __FreeBSD_version < 502113
565 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
567 TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
570 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
571 if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
572 free(keystr, M_DEVBUF);
573 *status = NDIS_STATUS_FAILURE;
576 *status = ndis_encode_parm(block, oidp, type, parm);
577 free(keystr, M_DEVBUF);
583 * If the key didn't match, add it to the list of dynamically
584 * created ones. Sometimes, drivers refer to registry keys
585 * that aren't documented in their .INF files. These keys
586 * are supposed to be created by some sort of utility or
587 * control panel snap-in that comes with the driver software.
588 * Sometimes it's useful to be able to manipulate these.
589 * If the driver requests the key in the form of a string,
590 * make its default value an empty string, otherwise default
594 if (type == ndis_parm_int || type == ndis_parm_hexint)
595 ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
596 "UNSET", CTLFLAG_RW);
598 ndis_add_sysctl(sc, keystr, "(dynamic string key)",
599 "UNSET", CTLFLAG_RW);
601 free(keystr, M_DEVBUF);
602 *status = NDIS_STATUS_FAILURE;
607 ndis_decode_parm(ndis_miniport_block *block, ndis_config_parm *parm,
610 ndis_unicode_string *ustr;
613 switch(parm->ncp_type) {
614 case ndis_parm_string:
615 ustr = &parm->ncp_parmdata.ncp_stringdata;
616 ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &astr);
617 bcopy(astr, val, 254);
618 free(astr, M_DEVBUF);
621 sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
623 case ndis_parm_hexint:
624 sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
627 return(NDIS_STATUS_FAILURE);
630 return(NDIS_STATUS_SUCCESS);
633 __stdcall static void
634 ndis_write_cfg(ndis_status *status, ndis_handle cfg, ndis_unicode_string *key,
635 ndis_config_parm *parm)
638 ndis_miniport_block *block;
639 struct ndis_softc *sc;
640 struct sysctl_oid *oidp;
641 struct sysctl_ctx_entry *e;
644 block = (ndis_miniport_block *)cfg;
645 sc = (struct ndis_softc *)block->nmb_ifp;
647 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
649 /* Decode the parameter into a string. */
650 bzero(val, sizeof(val));
651 *status = ndis_decode_parm(block, parm, val);
652 if (*status != NDIS_STATUS_SUCCESS) {
653 free(keystr, M_DEVBUF);
657 /* See if the key already exists. */
659 #if __FreeBSD_version < 502113
660 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
662 TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
665 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
666 /* Found it, set the value. */
667 strcpy((char *)oidp->oid_arg1, val);
668 free(keystr, M_DEVBUF);
673 /* Not found, add a new key with the specified value. */
674 ndis_add_sysctl(sc, keystr, "(dynamically set key)",
677 free(keystr, M_DEVBUF);
678 *status = NDIS_STATUS_SUCCESS;
682 __stdcall static void
683 ndis_close_cfg(ndis_handle cfg)
689 * Initialize a Windows spinlock.
691 __stdcall static void
692 ndis_create_lock(ndis_spin_lock *lock)
694 lock->nsl_spinlock = 0;
701 * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
702 * for this. One is that it's sort of superfluous: we don't have to do anything
703 * special to deallocate the spinlock. The other is that there are some buggy
704 * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
705 * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
708 __stdcall static void
709 ndis_destroy_lock(ndis_spin_lock *lock)
712 lock->nsl_spinlock = 0;
719 * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
722 __stdcall static void
723 ndis_lock(ndis_spin_lock *lock)
725 lock->nsl_kirql = FASTCALL2(hal_lock,
726 &lock->nsl_spinlock, DISPATCH_LEVEL);
731 * Release a spinlock from IRQL == DISPATCH_LEVEL.
734 __stdcall static void
735 ndis_unlock(ndis_spin_lock *lock)
737 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
742 * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
744 __stdcall static void
745 ndis_lock_dpr(ndis_spin_lock *lock)
747 FASTCALL1(ntoskrnl_lock_dpc, &lock->nsl_spinlock);
752 * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
754 __stdcall static void
755 ndis_unlock_dpr(ndis_spin_lock *lock)
757 FASTCALL1(ntoskrnl_unlock_dpc, &lock->nsl_spinlock);
761 __stdcall static uint32_t
762 ndis_read_pci(ndis_handle adapter, uint32_t slot, uint32_t offset,
763 void *buf, uint32_t len)
765 ndis_miniport_block *block;
769 block = (ndis_miniport_block *)adapter;
771 if (block == NULL || block->nmb_dev == NULL)
774 for (i = 0; i < len; i++)
775 dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
780 __stdcall static uint32_t
781 ndis_write_pci(ndis_handle adapter, uint32_t slot, uint32_t offset,
782 void *buf, uint32_t len)
784 ndis_miniport_block *block;
788 block = (ndis_miniport_block *)adapter;
791 if (block == NULL || block->nmb_dev == NULL)
794 for (i = 0; i < len; i++)
795 pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
801 * The errorlog routine uses a variable argument list, so we
802 * have to declare it this way.
804 #define ERRMSGLEN 512
806 ndis_syslog(ndis_handle adapter, ndis_error_code code,
807 uint32_t numerrors, ...)
809 ndis_miniport_block *block;
812 char *str = NULL, *ustr = NULL;
814 char msgbuf[ERRMSGLEN];
817 block = (ndis_miniport_block *)adapter;
819 error = pe_get_message(block->nmb_img, code, &str, &i, &flags);
820 if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
822 ndis_unicode_to_ascii((uint16_t *)str,
823 ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
826 device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code,
827 str == NULL ? "unknown error" : str);
828 device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
830 __va_start(ap, numerrors);
831 for (i = 0; i < numerrors; i++)
832 device_printf (block->nmb_dev, "argptr: %p\n",
833 __va_arg(ap, void *));
840 ndis_map_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
842 struct ndis_map_arg *ctx;
850 for (i = 0; i < nseg; i++) {
851 ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
852 ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
860 __stdcall static void
861 ndis_vtophys_load(ndis_handle adapter, ndis_buffer *buf, uint32_t mapreg,
862 uint8_t writedev, ndis_paddr_unit *addrarray,
865 ndis_miniport_block *block;
866 struct ndis_softc *sc;
867 struct ndis_map_arg nma;
874 block = (ndis_miniport_block *)adapter;
875 sc = (struct ndis_softc *)(block->nmb_ifp);
877 if (mapreg > sc->ndis_mmapcnt)
880 map = sc->ndis_mmaps[mapreg];
881 nma.nma_fraglist = addrarray;
883 error = bus_dmamap_load(sc->ndis_mtag, map,
884 MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
885 (void *)&nma, BUS_DMA_NOWAIT);
890 bus_dmamap_sync(sc->ndis_mtag, map,
891 writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
893 *arraysize = nma.nma_cnt;
898 __stdcall static void
899 ndis_vtophys_unload(ndis_handle adapter, ndis_buffer *buf,
902 ndis_miniport_block *block;
903 struct ndis_softc *sc;
909 block = (ndis_miniport_block *)adapter;
910 sc = (struct ndis_softc *)(block->nmb_ifp);
912 if (mapreg > sc->ndis_mmapcnt)
915 map = sc->ndis_mmaps[mapreg];
917 bus_dmamap_sync(sc->ndis_mtag, map,
918 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
920 bus_dmamap_unload(sc->ndis_mtag, map);
926 * This is an older pre-miniport timer init routine which doesn't
927 * accept a miniport context handle. The function context (ctx)
928 * is supposed to be a pointer to the adapter handle, which should
929 * have been handed to us via NdisSetAttributesEx(). We use this
930 * function context to track down the corresponding ndis_miniport_block
931 * structure. It's vital that we track down the miniport block structure,
932 * so if we can't do it, we panic. Note that we also play some games
933 * here by treating ndis_timer and ndis_miniport_timer as the same
937 __stdcall static void
938 ndis_init_timer(ndis_timer *timer, ndis_timer_function func, void *ctx)
940 ntoskrnl_init_timer(&timer->nt_ktimer);
941 ntoskrnl_init_dpc(&timer->nt_kdpc, func, ctx);
946 __stdcall static void
947 ndis_create_timer(ndis_miniport_timer *timer, ndis_handle handle,
948 ndis_timer_function func, void *ctx)
950 /* Save the funcptr and context */
952 timer->nmt_timerfunc = func;
953 timer->nmt_timerctx = ctx;
954 timer->nmt_block = handle;
956 ntoskrnl_init_timer(&timer->nmt_ktimer);
957 ntoskrnl_init_dpc(&timer->nmt_kdpc, func, ctx);
963 * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
964 * but the former is just a macro wrapper around the latter.
966 __stdcall static void
967 ndis_set_timer(ndis_timer *timer, uint32_t msecs)
970 * KeSetTimer() wants the period in
971 * hundred nanosecond intervals.
973 ntoskrnl_set_timer(&timer->nt_ktimer,
974 ((int64_t)msecs * -10000), &timer->nt_kdpc);
979 __stdcall static void
980 ndis_set_periodic_timer(ndis_miniport_timer *timer, uint32_t msecs)
982 ntoskrnl_set_timer_ex(&timer->nmt_ktimer,
983 ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc);
989 * Technically, this is really NdisCancelTimer(), but we also
990 * (ab)use it for NdisMCancelTimer(), since in our implementation
991 * we don't need the extra info in the ndis_miniport_timer
995 __stdcall static void
996 ndis_cancel_timer(ndis_timer *timer, uint8_t *cancelled)
998 *cancelled = ntoskrnl_cancel_timer(&timer->nt_ktimer);
1003 __stdcall static void
1004 ndis_query_resources(ndis_status *status, ndis_handle adapter,
1005 ndis_resource_list *list, uint32_t *buflen)
1007 ndis_miniport_block *block;
1008 struct ndis_softc *sc;
1011 block = (ndis_miniport_block *)adapter;
1012 sc = (struct ndis_softc *)block->nmb_ifp;
1014 rsclen = sizeof(ndis_resource_list) +
1015 (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1016 if (*buflen < rsclen) {
1018 *status = NDIS_STATUS_INVALID_LENGTH;
1022 bcopy((char *)block->nmb_rlist, (char *)list, rsclen);
1023 *status = NDIS_STATUS_SUCCESS;
1027 __stdcall static ndis_status
1028 ndis_register_ioport(void **offset, ndis_handle adapter,
1029 uint32_t port, uint32_t numports)
1031 struct ndis_miniport_block *block;
1032 struct ndis_softc *sc;
1034 if (adapter == NULL)
1035 return(NDIS_STATUS_FAILURE);
1037 block = (ndis_miniport_block *)adapter;
1038 sc = (struct ndis_softc *)(block->nmb_ifp);
1040 if (sc->ndis_res_io == NULL)
1041 return(NDIS_STATUS_FAILURE);
1043 /* Don't let the device map more ports than we have. */
1044 if (rman_get_size(sc->ndis_res_io) < numports)
1045 return(NDIS_STATUS_INVALID_LENGTH);
1047 *offset = (void *)rman_get_start(sc->ndis_res_io);
1049 return(NDIS_STATUS_SUCCESS);
1052 __stdcall static void
1053 ndis_deregister_ioport(ndis_handle adapter, uint32_t port,
1054 uint32_t numports, void *offset)
1059 __stdcall static void
1060 ndis_read_netaddr(ndis_status *status, void **addr,
1061 uint32_t *addrlen, ndis_handle adapter)
1063 struct ndis_softc *sc;
1064 ndis_miniport_block *block;
1065 uint8_t empty[] = { 0, 0, 0, 0, 0, 0 };
1067 block = (ndis_miniport_block *)adapter;
1068 sc = (struct ndis_softc *)block->nmb_ifp;
1070 if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1071 *status = NDIS_STATUS_FAILURE;
1073 *addr = sc->arpcom.ac_enaddr;
1074 *addrlen = ETHER_ADDR_LEN;
1075 *status = NDIS_STATUS_SUCCESS;
1081 __stdcall static ndis_status
1082 ndis_mapreg_cnt(uint32_t bustype, uint32_t *cnt)
1085 return(NDIS_STATUS_SUCCESS);
1088 __stdcall static ndis_status
1089 ndis_alloc_mapreg(ndis_handle adapter, uint32_t dmachannel, uint8_t dmasize,
1090 uint32_t physmapneeded, uint32_t maxmap)
1092 struct ndis_softc *sc;
1093 ndis_miniport_block *block;
1094 int error, i, nseg = NDIS_MAXSEG;
1096 block = (ndis_miniport_block *)adapter;
1097 sc = (struct ndis_softc *)block->nmb_ifp;
1099 sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1100 M_DEVBUF, M_INTWAIT|M_ZERO);
1102 if (sc->ndis_mmaps == NULL)
1103 return(NDIS_STATUS_RESOURCES);
1105 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1106 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1107 NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1111 free(sc->ndis_mmaps, M_DEVBUF);
1112 return(NDIS_STATUS_RESOURCES);
1115 for (i = 0; i < physmapneeded; i++)
1116 bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1118 sc->ndis_mmapcnt = physmapneeded;
1120 return(NDIS_STATUS_SUCCESS);
1123 __stdcall static void
1124 ndis_free_mapreg(ndis_handle adapter)
1126 struct ndis_softc *sc;
1127 ndis_miniport_block *block;
1130 block = (ndis_miniport_block *)adapter;
1131 sc = (struct ndis_softc *)block->nmb_ifp;
1133 for (i = 0; i < sc->ndis_mmapcnt; i++)
1134 bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1136 free(sc->ndis_mmaps, M_DEVBUF);
1138 bus_dma_tag_destroy(sc->ndis_mtag);
1144 ndis_mapshared_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1148 if (error || nseg > 1)
1153 p->np_quad = segs[0].ds_addr;
1159 * This maps to bus_dmamem_alloc().
1161 __stdcall static void
1162 ndis_alloc_sharedmem(ndis_handle adapter, uint32_t len, uint8_t cached,
1163 void **vaddr, ndis_physaddr *paddr)
1165 ndis_miniport_block *block;
1166 struct ndis_softc *sc;
1167 struct ndis_shmem *sh;
1170 if (adapter == NULL)
1173 block = (ndis_miniport_block *)adapter;
1174 sc = (struct ndis_softc *)(block->nmb_ifp);
1176 sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_INTWAIT|M_ZERO);
1181 * When performing shared memory allocations, create a tag
1182 * with a lowaddr limit that restricts physical memory mappings
1183 * so that they all fall within the first 1GB of memory.
1184 * At least one device/driver combination (Linksys Instant
1185 * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
1186 * problems with performing DMA operations with physical
1187 * that lie above the 1GB mark. I don't know if this is a
1188 * hardware limitation or if the addresses are being truncated
1189 * within the driver, but this seems to be the only way to
1190 * make these cards work reliably in systems with more than
1191 * 1GB of physical memory.
1194 error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1195 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL,
1196 NULL, len, 1, len, BUS_DMA_ALLOCNOW,
1204 error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1205 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1208 bus_dma_tag_destroy(sh->ndis_stag);
1213 error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1214 len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1217 bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1218 bus_dma_tag_destroy(sh->ndis_stag);
1223 sh->ndis_saddr = *vaddr;
1224 sh->ndis_next = sc->ndis_shlist;
1225 sc->ndis_shlist = sh;
1230 struct ndis_allocwork {
1231 ndis_handle na_adapter;
1238 ndis_asyncmem_complete(void *arg)
1240 ndis_miniport_block *block;
1241 struct ndis_softc *sc;
1242 struct ndis_allocwork *w;
1244 ndis_physaddr paddr;
1245 ndis_allocdone_handler donefunc;
1248 block = (ndis_miniport_block *)w->na_adapter;
1249 sc = (struct ndis_softc *)(block->nmb_ifp);
1254 donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1255 ndis_alloc_sharedmem(w->na_adapter, w->na_len,
1256 w->na_cached, &vaddr, &paddr);
1257 donefunc(w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
1259 free(arg, M_DEVBUF);
1264 __stdcall static ndis_status
1265 ndis_alloc_sharedmem_async(ndis_handle adapter, uint32_t len,
1266 uint8_t cached, void *ctx)
1268 struct ndis_allocwork *w;
1270 if (adapter == NULL)
1271 return(NDIS_STATUS_FAILURE);
1273 w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_INTWAIT);
1276 return(NDIS_STATUS_FAILURE);
1278 w->na_adapter = adapter;
1279 w->na_cached = cached;
1284 * Pawn this work off on the SWI thread instead of the
1285 * taskqueue thread, because sometimes drivers will queue
1286 * up work items on the taskqueue thread that will block,
1287 * which would prevent the memory allocation from completing
1290 ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI);
1292 return(NDIS_STATUS_PENDING);
1295 __stdcall static void
1296 ndis_free_sharedmem(ndis_handle adapter, uint32_t len, uint8_t cached,
1297 void *vaddr, ndis_physaddr paddr)
1299 ndis_miniport_block *block;
1300 struct ndis_softc *sc;
1301 struct ndis_shmem *sh, *prev;
1303 if (vaddr == NULL || adapter == NULL)
1306 block = (ndis_miniport_block *)adapter;
1307 sc = (struct ndis_softc *)(block->nmb_ifp);
1308 sh = prev = sc->ndis_shlist;
1311 if (sh->ndis_saddr == vaddr)
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);
1321 if (sh == sc->ndis_shlist)
1322 sc->ndis_shlist = sh->ndis_next;
1324 prev->ndis_next = sh->ndis_next;
1331 __stdcall static ndis_status
1332 ndis_map_iospace(void **vaddr, ndis_handle adapter, ndis_physaddr paddr,
1335 ndis_miniport_block *block;
1336 struct ndis_softc *sc;
1338 if (adapter == NULL)
1339 return(NDIS_STATUS_FAILURE);
1341 block = (ndis_miniport_block *)adapter;
1342 sc = (struct ndis_softc *)(block->nmb_ifp);
1344 if (sc->ndis_res_mem != NULL &&
1345 paddr.np_quad == rman_get_start(sc->ndis_res_mem))
1346 *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1347 else if (sc->ndis_res_altmem != NULL &&
1348 paddr.np_quad == rman_get_start(sc->ndis_res_altmem))
1349 *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem);
1350 else if (sc->ndis_res_am != NULL &&
1351 paddr.np_quad == rman_get_start(sc->ndis_res_am))
1352 *vaddr = (void *)rman_get_virtual(sc->ndis_res_am);
1354 return(NDIS_STATUS_FAILURE);
1356 return(NDIS_STATUS_SUCCESS);
1359 __stdcall static void
1360 ndis_unmap_iospace(ndis_handle adapter, void *vaddr, uint32_t len)
1365 __stdcall static uint32_t
1366 ndis_cachefill(void)
1371 __stdcall static uint32_t
1372 ndis_dma_align(ndis_handle handle)
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
1388 __stdcall static ndis_status
1389 ndis_init_sc_dma(ndis_handle adapter, uint8_t is64, uint32_t maxphysmap)
1391 struct ndis_softc *sc;
1392 ndis_miniport_block *block;
1395 if (adapter == NULL)
1396 return(NDIS_STATUS_FAILURE);
1397 block = (ndis_miniport_block *)adapter;
1398 sc = (struct ndis_softc *)block->nmb_ifp;
1400 /* Don't do this twice. */
1401 if (sc->ndis_sc == 1)
1402 return(NDIS_STATUS_SUCCESS);
1404 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1405 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1406 MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1411 return(NDIS_STATUS_SUCCESS);
1414 __stdcall static void
1415 ndis_alloc_packetpool(ndis_status *status, ndis_handle *pool,
1416 uint32_t descnum, uint32_t protrsvdlen)
1421 *pool = malloc(sizeof(ndis_packet) *
1422 ((descnum + NDIS_POOL_EXTRA) + 1),
1423 M_DEVBUF, M_WAITOK|M_ZERO);
1424 cur = (ndis_packet *)*pool;
1425 cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1426 cur->np_private.npp_totlen = 0; /* init deletetion flag */
1427 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1428 cur->np_private.npp_head = (ndis_handle)(cur + 1);
1432 *status = NDIS_STATUS_SUCCESS;
1436 __stdcall static void
1437 ndis_ex_alloc_packetpool(ndis_status *status, ndis_handle *pool,
1438 uint32_t descnum, uint32_t oflowdescnum,
1439 uint32_t protrsvdlen)
1441 return(ndis_alloc_packetpool(status, pool,
1442 descnum + oflowdescnum, protrsvdlen));
1445 __stdcall static uint32_t
1446 ndis_packetpool_use(ndis_handle pool)
1450 head = (ndis_packet *)pool;
1452 return(head->np_private.npp_count);
1455 __stdcall static void
1456 ndis_free_packetpool(ndis_handle pool)
1462 /* Mark this pool as 'going away.' */
1464 head->np_private.npp_totlen = 1;
1466 /* If there are no buffers loaned out, destroy the pool. */
1468 if (head->np_private.npp_count == 0)
1469 free(pool, M_DEVBUF);
1471 printf("NDIS: buggy driver deleting active packet pool!\n");
1476 __stdcall static void
1477 ndis_alloc_packet(ndis_status *status, ndis_packet **packet, ndis_handle pool)
1479 ndis_packet *head, *pkt;
1481 head = (ndis_packet *)pool;
1483 if (head->np_private.npp_flags != 0x1) {
1484 *status = NDIS_STATUS_FAILURE;
1489 * If this pool is marked as 'going away' don't allocate any
1490 * more packets out of it.
1493 if (head->np_private.npp_totlen) {
1494 *status = NDIS_STATUS_FAILURE;
1498 pkt = (ndis_packet *)head->np_private.npp_head;
1501 *status = NDIS_STATUS_RESOURCES;
1505 head->np_private.npp_head = pkt->np_private.npp_head;
1507 pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1508 /* Save pointer to the pool. */
1509 pkt->np_private.npp_pool = head;
1511 /* Set the oob offset pointer. Lots of things expect this. */
1512 pkt->np_private.npp_packetooboffset =
1513 offsetof(ndis_packet, np_oob);
1516 * We must initialize the packet flags correctly in order
1517 * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
1518 * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly.
1520 pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
1524 head->np_private.npp_count++;
1525 *status = NDIS_STATUS_SUCCESS;
1529 __stdcall static void
1530 ndis_release_packet(ndis_packet *packet)
1534 if (packet == NULL || packet->np_private.npp_pool == NULL)
1537 head = packet->np_private.npp_pool;
1538 if (head->np_private.npp_flags != 0x1)
1541 packet->np_private.npp_head = head->np_private.npp_head;
1542 head->np_private.npp_head = (ndis_buffer *)packet;
1543 head->np_private.npp_count--;
1546 * If the pool has been marked for deletion and there are
1547 * no more packets outstanding, nuke the pool.
1550 if (head->np_private.npp_totlen && head->np_private.npp_count == 0)
1551 free(head, M_DEVBUF);
1556 __stdcall static void
1557 ndis_unchain_headbuf(ndis_packet *packet, ndis_buffer **buf)
1559 ndis_packet_private *priv;
1561 if (packet == NULL || buf == NULL)
1564 priv = &packet->np_private;
1566 priv->npp_validcounts = FALSE;
1568 if (priv->npp_head == priv->npp_tail) {
1569 *buf = priv->npp_head;
1570 priv->npp_head = priv->npp_tail = NULL;
1572 *buf = priv->npp_head;
1573 priv->npp_head = (*buf)->nb_next;
1579 __stdcall static void
1580 ndis_unchain_tailbuf(ndis_packet *packet, ndis_buffer **buf)
1582 ndis_packet_private *priv;
1585 if (packet == NULL || buf == NULL)
1588 priv = &packet->np_private;
1590 priv->npp_validcounts = FALSE;
1592 if (priv->npp_head == priv->npp_tail) {
1593 *buf = priv->npp_head;
1594 priv->npp_head = priv->npp_tail = NULL;
1596 *buf = priv->npp_tail;
1597 tmp = priv->npp_head;
1598 while (tmp->nb_next != priv->npp_tail)
1600 priv->npp_tail = tmp;
1601 tmp->nb_next = NULL;
1608 * The NDIS "buffer" manipulation functions are somewhat misnamed.
1609 * They don't really allocate buffers: they allocate buffer mappings.
1610 * The idea is you reserve a chunk of DMA-able memory using
1611 * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1612 * to obtain the virtual address of the DMA-able region.
1613 * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1616 __stdcall static void
1617 ndis_alloc_bufpool(ndis_status *status, ndis_handle *pool,
1623 *pool = malloc(sizeof(ndis_buffer) *
1624 ((descnum + NDIS_POOL_EXTRA) + 1),
1625 M_DEVBUF, M_WAITOK|M_ZERO);
1626 cur = (ndis_buffer *)*pool;
1627 cur->nb_flags = 0x1; /* mark the head of the list */
1628 cur->nb_bytecount = 0; /* init usage count */
1629 cur->nb_byteoffset = 0; /* init deletetion flag */
1630 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1631 cur->nb_next = cur + 1;
1635 *status = NDIS_STATUS_SUCCESS;
1639 __stdcall static void
1640 ndis_free_bufpool(ndis_handle pool)
1646 /* Mark this pool as 'going away.' */
1648 head->nb_byteoffset = 1;
1650 /* If there are no buffers loaned out, destroy the pool. */
1651 if (head->nb_bytecount == 0)
1652 free(pool, M_DEVBUF);
1654 printf("NDIS: buggy driver deleting active buffer pool!\n");
1660 * This maps to a bus_dmamap_create() and bus_dmamap_load().
1662 __stdcall static void
1663 ndis_alloc_buf(ndis_status *status, ndis_buffer **buffer, ndis_handle pool,
1664 void *vaddr, uint32_t len)
1666 ndis_buffer *head, *buf;
1668 head = (ndis_buffer *)pool;
1669 if (head->nb_flags != 0x1) {
1670 *status = NDIS_STATUS_FAILURE;
1675 * If this pool is marked as 'going away' don't allocate any
1676 * more buffers out of it.
1679 if (head->nb_byteoffset) {
1680 *status = NDIS_STATUS_FAILURE;
1684 buf = head->nb_next;
1687 *status = NDIS_STATUS_RESOURCES;
1691 head->nb_next = buf->nb_next;
1693 /* Save pointer to the pool. */
1694 buf->nb_process = head;
1696 MDL_INIT(buf, vaddr, len);
1700 /* Increment count of busy buffers. */
1702 head->nb_bytecount++;
1704 *status = NDIS_STATUS_SUCCESS;
1708 __stdcall static void
1709 ndis_release_buf(ndis_buffer *buf)
1713 if (buf == NULL || buf->nb_process == NULL)
1716 head = buf->nb_process;
1718 if (head->nb_flags != 0x1)
1721 buf->nb_next = head->nb_next;
1722 head->nb_next = buf;
1724 /* Decrement count of busy buffers. */
1726 head->nb_bytecount--;
1729 * If the pool has been marked for deletion and there are
1730 * no more buffers outstanding, nuke the pool.
1733 if (head->nb_byteoffset && head->nb_bytecount == 0)
1734 free(head, M_DEVBUF);
1741 __stdcall static uint32_t
1742 ndis_buflen(ndis_buffer *buf)
1744 return(buf->nb_bytecount);
1748 * Get the virtual address and length of a buffer.
1749 * Note: the vaddr argument is optional.
1752 __stdcall static void
1753 ndis_query_buf(ndis_buffer *buf, void **vaddr, uint32_t *len)
1756 *vaddr = MDL_VA(buf);
1757 *len = buf->nb_bytecount;
1762 /* Same as above -- we don't care about the priority. */
1764 __stdcall static void
1765 ndis_query_buf_safe(ndis_buffer *buf, void **vaddr,
1766 uint32_t *len, uint32_t prio)
1769 *vaddr = MDL_VA(buf);
1770 *len = buf->nb_bytecount;
1775 /* Damnit Microsoft!! How many ways can you do the same thing?! */
1777 __stdcall static void *
1778 ndis_buf_vaddr(ndis_buffer *buf)
1780 return(MDL_VA(buf));
1783 __stdcall static void *
1784 ndis_buf_vaddr_safe(ndis_buffer *buf, uint32_t prio)
1786 return(MDL_VA(buf));
1789 __stdcall static void
1790 ndis_adjust_buflen(ndis_buffer *buf, int len)
1792 buf->nb_bytecount = len;
1797 __stdcall static uint32_t
1798 ndis_interlock_inc(uint32_t *addend)
1800 atomic_add_long((u_long *)addend, 1);
1804 __stdcall static uint32_t
1805 ndis_interlock_dec(uint32_t *addend)
1807 atomic_subtract_long((u_long *)addend, 1);
1811 __stdcall static void
1812 ndis_init_event(ndis_event *event)
1815 * NDIS events are always notification
1816 * events, and should be initialized to the
1817 * not signaled state.
1820 ntoskrnl_init_event(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE);
1824 __stdcall static void
1825 ndis_set_event(ndis_event *event)
1827 ntoskrnl_set_event(&event->ne_event, 0, 0);
1831 __stdcall static void
1832 ndis_reset_event(ndis_event *event)
1834 ntoskrnl_reset_event(&event->ne_event);
1838 __stdcall static uint8_t
1839 ndis_wait_event(ndis_event *event, uint32_t msecs)
1844 duetime = ((int64_t)msecs * -10000);
1846 rval = ntoskrnl_waitforobj((nt_dispatch_header *)event,
1847 0, 0, TRUE, msecs ? &duetime : NULL);
1849 if (rval == STATUS_TIMEOUT)
1855 __stdcall static ndis_status
1856 ndis_unicode2ansi(ndis_ansi_string *dstr, ndis_unicode_string *sstr)
1858 if (dstr == NULL || sstr == NULL)
1859 return(NDIS_STATUS_FAILURE);
1860 if (ndis_unicode_to_ascii(sstr->nus_buf,
1861 sstr->nus_len, &dstr->nas_buf))
1862 return(NDIS_STATUS_FAILURE);
1863 dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
1864 return (NDIS_STATUS_SUCCESS);
1867 __stdcall static ndis_status
1868 ndis_ansi2unicode(ndis_unicode_string *dstr, ndis_ansi_string *sstr)
1871 if (dstr == NULL || sstr == NULL)
1872 return(NDIS_STATUS_FAILURE);
1873 str = malloc(sstr->nas_len + 1, M_DEVBUF, M_WAITOK);
1874 strncpy(str, sstr->nas_buf, sstr->nas_len);
1875 *(str + sstr->nas_len) = '\0';
1876 if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
1877 free(str, M_DEVBUF);
1878 return(NDIS_STATUS_FAILURE);
1880 dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
1881 free(str, M_DEVBUF);
1882 return (NDIS_STATUS_SUCCESS);
1885 __stdcall static ndis_status
1886 ndis_assign_pcirsrc(ndis_handle adapter, uint32_t slot,
1887 ndis_resource_list **list)
1889 ndis_miniport_block *block;
1891 if (adapter == NULL || list == NULL)
1892 return (NDIS_STATUS_FAILURE);
1894 block = (ndis_miniport_block *)adapter;
1895 *list = block->nmb_rlist;
1897 return (NDIS_STATUS_SUCCESS);
1900 __stdcall static ndis_status
1901 ndis_register_intr(ndis_miniport_interrupt *intr, ndis_handle adapter,
1902 uint32_t ivec, uint32_t ilevel, uint8_t reqisr,
1903 uint8_t shared, ndis_interrupt_mode imode)
1905 ndis_miniport_block *block;
1909 intr->ni_block = adapter;
1910 intr->ni_isrreq = reqisr;
1911 intr->ni_shared = shared;
1912 block->nmb_interrupt = intr;
1913 return(NDIS_STATUS_SUCCESS);
1916 __stdcall static void
1917 ndis_deregister_intr(ndis_miniport_interrupt *intr)
1922 __stdcall static void
1923 ndis_register_shutdown(ndis_handle adapter, void *shutdownctx,
1924 ndis_shutdown_handler shutdownfunc)
1926 ndis_miniport_block *block;
1927 ndis_miniport_characteristics *chars;
1928 struct ndis_softc *sc;
1930 if (adapter == NULL)
1933 block = (ndis_miniport_block *)adapter;
1934 sc = (struct ndis_softc *)block->nmb_ifp;
1935 chars = &sc->ndis_chars;
1937 chars->nmc_shutdown_handler = shutdownfunc;
1938 chars->nmc_rsvd0 = shutdownctx;
1943 __stdcall static void
1944 ndis_deregister_shutdown(ndis_handle adapter)
1946 ndis_miniport_block *block;
1947 ndis_miniport_characteristics *chars;
1948 struct ndis_softc *sc;
1950 if (adapter == NULL)
1953 block = (ndis_miniport_block *)adapter;
1954 sc = (struct ndis_softc *)block->nmb_ifp;
1955 chars = &sc->ndis_chars;
1957 chars->nmc_shutdown_handler = NULL;
1958 chars->nmc_rsvd0 = NULL;
1963 __stdcall static uint32_t
1964 ndis_numpages(ndis_buffer *buf)
1968 if (buf->nb_bytecount == 0)
1970 return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
1973 __stdcall static void
1974 ndis_buf_physpages(ndis_buffer *buf, uint32_t *pages)
1979 *pages = ndis_numpages(buf);
1983 __stdcall static void
1984 ndis_query_bufoffset(ndis_buffer *buf, uint32_t *off, uint32_t *len)
1989 *off = buf->nb_byteoffset;
1990 *len = buf->nb_bytecount;
1995 __stdcall static void
1996 ndis_sleep(uint32_t usecs)
2003 ndis_thsuspend(curthread, 1 + usecs * hz / 1000000);
2008 __stdcall static uint32_t
2009 ndis_read_pccard_amem(ndis_handle handle, uint32_t offset, void *buf,
2012 struct ndis_softc *sc;
2013 ndis_miniport_block *block;
2014 bus_space_handle_t bh;
2022 block = (ndis_miniport_block *)handle;
2023 sc = (struct ndis_softc *)block->nmb_ifp;
2026 bh = rman_get_bushandle(sc->ndis_res_am);
2027 bt = rman_get_bustag(sc->ndis_res_am);
2029 for (i = 0; i < len; i++)
2030 dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2);
2035 __stdcall static uint32_t
2036 ndis_write_pccard_amem(ndis_handle handle, uint32_t offset, void *buf,
2039 struct ndis_softc *sc;
2040 ndis_miniport_block *block;
2041 bus_space_handle_t bh;
2049 block = (ndis_miniport_block *)handle;
2050 sc = (struct ndis_softc *)block->nmb_ifp;
2053 bh = rman_get_bushandle(sc->ndis_res_am);
2054 bt = rman_get_bustag(sc->ndis_res_am);
2056 for (i = 0; i < len; i++)
2057 bus_space_write_1(bt, bh, (offset + i) * 2, src[i]);
2062 __stdcall static list_entry *
2063 ndis_insert_head(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
2067 lock->nsl_kirql = FASTCALL2(hal_lock,
2068 &lock->nsl_spinlock, DISPATCH_LEVEL);
2069 flink = head->nle_flink;
2070 entry->nle_flink = flink;
2071 entry->nle_blink = head;
2072 flink->nle_blink = entry;
2073 head->nle_flink = entry;
2074 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2079 __stdcall static list_entry *
2080 ndis_remove_head(list_entry *head, ndis_spin_lock *lock)
2085 lock->nsl_kirql = FASTCALL2(hal_lock,
2086 &lock->nsl_spinlock, DISPATCH_LEVEL);
2087 entry = head->nle_flink;
2088 flink = entry->nle_flink;
2089 head->nle_flink = flink;
2090 flink->nle_blink = head;
2091 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2096 __stdcall static list_entry *
2097 ndis_insert_tail(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
2101 lock->nsl_kirql = FASTCALL2(hal_lock,
2102 &lock->nsl_spinlock, DISPATCH_LEVEL);
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 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2113 __stdcall static uint8_t
2114 ndis_sync_with_intr(ndis_miniport_interrupt *intr, void *syncfunc,
2117 struct ndis_softc *sc;
2119 __stdcall uint8_t (*sync)(void *);
2122 if (syncfunc == NULL || syncctx == NULL)
2125 sc = (struct ndis_softc *)intr->ni_block->nmb_ifp;
2126 ifp = &sc->arpcom.ac_if;
2128 rval = sync(syncctx);
2134 * Return the number of 100 nanosecond intervals since
2135 * January 1, 1601. (?!?!)
2137 __stdcall static void
2138 ndis_time(uint64_t *tval)
2143 *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2150 * Return the number of milliseconds since the system booted.
2152 __stdcall static void
2153 ndis_uptime(uint32_t *tval)
2158 *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
2163 __stdcall static void
2164 ndis_init_string(ndis_unicode_string *dst, char *src)
2166 ndis_unicode_string *u;
2170 if (ndis_ascii_to_unicode(src, &u->nus_buf))
2172 u->nus_len = u->nus_maxlen = strlen(src) * 2;
2176 __stdcall static void
2177 ndis_free_string(ndis_unicode_string *str)
2181 if (str->nus_buf != NULL)
2182 free(str->nus_buf, M_DEVBUF);
2183 free(str, M_DEVBUF);
2187 __stdcall static ndis_status
2188 ndis_remove_miniport(ndis_handle *adapter)
2190 return(NDIS_STATUS_SUCCESS);
2193 __stdcall static void
2194 ndis_init_ansi_string(ndis_ansi_string *dst, char *src)
2196 ndis_ansi_string *a;
2202 a->nas_len = a->nas_maxlen = 0;
2206 a->nas_len = a->nas_maxlen = strlen(src);
2212 __stdcall static void
2213 ndis_init_unicode_string(ndis_unicode_string *dst, uint16_t *src)
2215 ndis_unicode_string *u;
2222 u->nus_len = u->nus_maxlen = 0;
2229 u->nus_len = u->nus_maxlen = i * 2;
2235 __stdcall static void
2236 ndis_get_devprop(ndis_handle adapter, device_object **phydevobj,
2237 device_object **funcdevobj, device_object **nextdevobj,
2238 cm_resource_list *resources, cm_resource_list *transresources)
2240 ndis_miniport_block *block;
2242 block = (ndis_miniport_block *)adapter;
2244 if (phydevobj != NULL)
2245 *phydevobj = &block->nmb_devobj;
2246 if (funcdevobj != NULL)
2247 *funcdevobj = &block->nmb_devobj;
2252 __stdcall static void
2253 ndis_firstbuf(ndis_packet *packet, ndis_buffer **buf, void **firstva,
2254 uint32_t *firstlen, uint32_t *totlen)
2258 tmp = packet->np_private.npp_head;
2262 *firstlen = *totlen = 0;
2264 *firstva = MDL_VA(tmp);
2265 *firstlen = *totlen = tmp->nb_bytecount;
2266 for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
2267 *totlen += tmp->nb_bytecount;
2273 __stdcall static void
2274 ndis_firstbuf_safe(ndis_packet *packet, ndis_buffer **buf, void **firstva,
2275 uint32_t *firstlen, uint32_t *totlen, uint32_t prio)
2277 ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
2280 /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2281 __stdcall static void
2282 ndis_open_file(ndis_status *status, ndis_handle *filehandle, uint32_t *filelength,
2283 ndis_unicode_string *filename, ndis_physaddr highestaddr)
2285 char *afilename = NULL;
2286 struct nlookupdata nd;
2289 struct vattr *vap = &vat;
2292 char path[MAXPATHLEN];
2294 ndis_unicode_to_ascii(filename->nus_buf,
2295 filename->nus_len, &afilename);
2297 sprintf(path, "%s/%s", ndis_filepath, afilename);
2298 free(afilename, M_DEVBUF);
2300 fh = malloc(sizeof(ndis_fh), M_TEMP, M_WAITOK);
2302 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW|NLC_LOCKVP);
2304 error = vn_open(&nd, NULL, FREAD, 0);
2306 *status = NDIS_STATUS_FILE_NOT_FOUND;
2308 printf("NDIS: open file %s failed: %d\n", path, error);
2313 nd.nl_open_vp = NULL;
2315 /* Get the file size. */
2316 VOP_GETATTR(vp, vap);
2322 *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
2323 *status = NDIS_STATUS_SUCCESS;
2330 __stdcall static void
2331 ndis_map_file(ndis_status *status, void **mappedbuffer, ndis_handle filehandle)
2336 if (filehandle == NULL) {
2337 *status = NDIS_STATUS_FAILURE;
2341 fh = (ndis_fh *)filehandle;
2343 if (fh->nf_vp == NULL) {
2344 *status = NDIS_STATUS_FAILURE;
2348 if (fh->nf_map != NULL) {
2349 *status = NDIS_STATUS_ALREADY_MAPPED;
2353 fh->nf_map = malloc(fh->nf_maplen, M_DEVBUF, M_WAITOK);
2355 error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
2356 UIO_SYSSPACE, 0, proc0.p_ucred, &resid);
2359 *status = NDIS_STATUS_FAILURE;
2361 *status = NDIS_STATUS_SUCCESS;
2362 *mappedbuffer = fh->nf_map;
2368 __stdcall static void
2369 ndis_unmap_file(ndis_handle filehandle)
2372 fh = (ndis_fh *)filehandle;
2374 if (fh->nf_map == NULL)
2376 free(fh->nf_map, M_DEVBUF);
2382 __stdcall static void
2383 ndis_close_file(ndis_handle filehandle)
2387 if (filehandle == NULL)
2390 fh = (ndis_fh *)filehandle;
2391 if (fh->nf_map != NULL) {
2392 free(fh->nf_map, M_DEVBUF);
2396 if (fh->nf_vp == NULL)
2399 vn_close(fh->nf_vp, FREAD);
2407 __stdcall static uint8_t
2413 typedef __stdcall void (*ndis_statusdone_handler)(ndis_handle);
2414 typedef __stdcall void (*ndis_status_handler)(ndis_handle, ndis_status,
2417 __stdcall static void
2418 ndis_ind_statusdone(ndis_handle adapter)
2420 ndis_miniport_block *block;
2421 ndis_statusdone_handler statusdonefunc;
2423 block = (ndis_miniport_block *)adapter;
2424 statusdonefunc = block->nmb_statusdone_func;
2426 statusdonefunc(adapter);
2430 __stdcall static void
2431 ndis_ind_status(ndis_handle adapter, ndis_status status, void *sbuf,
2434 ndis_miniport_block *block;
2435 ndis_status_handler statusfunc;
2437 block = (ndis_miniport_block *)adapter;
2438 statusfunc = block->nmb_status_func;
2440 statusfunc(adapter, status, sbuf, slen);
2445 ndis_workfunc(void *ctx)
2447 ndis_work_item *work;
2451 workfunc = work->nwi_func;
2452 workfunc(work, work->nwi_ctx);
2456 __stdcall static ndis_status
2457 ndis_sched_workitem(ndis_work_item *work)
2459 ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
2460 return(NDIS_STATUS_SUCCESS);
2463 __stdcall static void
2464 ndis_pkt_to_pkt(ndis_packet *dpkt, uint32_t doff, uint32_t reqlen,
2465 ndis_packet *spkt, uint32_t soff, uint32_t *cpylen)
2467 ndis_buffer *src, *dst;
2469 int resid, copied, len, scnt, dcnt;
2473 src = spkt->np_private.npp_head;
2474 dst = dpkt->np_private.npp_head;
2478 scnt = src->nb_bytecount;
2479 dcnt = dst->nb_bytecount;
2482 if (src->nb_bytecount > soff) {
2484 scnt = src->nb_bytecount - soff;
2487 soff -= src->nb_bytecount;
2495 if (dst->nb_bytecount > doff) {
2497 dcnt = dst->nb_bytecount - doff;
2500 doff -= dst->nb_bytecount;
2518 bcopy(sptr, dptr, len);
2531 dcnt = dst->nb_bytecount;
2540 scnt = src->nb_bytecount;
2548 __stdcall static void
2549 ndis_pkt_to_pkt_safe(ndis_packet *dpkt, uint32_t doff, uint32_t reqlen,
2550 ndis_packet *spkt, uint32_t soff, uint32_t *cpylen,
2553 ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen);
2557 __stdcall static ndis_status
2558 ndis_register_dev(ndis_handle handle, ndis_unicode_string *devname,
2559 ndis_unicode_string *symname, driver_dispatch **majorfuncs,
2560 void **devobj, ndis_handle *devhandle)
2562 ndis_miniport_block *block;
2564 block = (ndis_miniport_block *)handle;
2565 *devobj = &block->nmb_devobj;
2566 *devhandle = handle;
2568 return(NDIS_STATUS_SUCCESS);
2571 __stdcall static ndis_status
2572 ndis_deregister_dev(ndis_handle handle)
2574 return(NDIS_STATUS_SUCCESS);
2577 __stdcall static ndis_status
2578 ndis_query_name(ndis_unicode_string *name, ndis_handle handle)
2580 ndis_miniport_block *block;
2582 block = (ndis_miniport_block *)handle;
2583 ndis_ascii_to_unicode(__DECONST(char *,
2584 device_get_nameunit(block->nmb_dev)), &name->nus_buf);
2585 name->nus_len = strlen(device_get_nameunit(block->nmb_dev)) * 2;
2587 return(NDIS_STATUS_SUCCESS);
2590 __stdcall static void
2591 ndis_register_unload(ndis_handle handle, void *func)
2596 __stdcall static void
2599 printf ("NDIS dummy called...\n");
2603 image_patch_table ndis_functbl[] = {
2604 { "NdisCopyFromPacketToPacket", (FUNC)ndis_pkt_to_pkt },
2605 { "NdisCopyFromPacketToPacketSafe", (FUNC)ndis_pkt_to_pkt_safe },
2606 { "NdisScheduleWorkItem", (FUNC)ndis_sched_workitem },
2607 { "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone },
2608 { "NdisMIndicateStatus", (FUNC)ndis_ind_status },
2609 { "NdisSystemProcessorCount", (FUNC)ndis_cpu_cnt },
2610 { "NdisUnchainBufferAtBack", (FUNC)ndis_unchain_tailbuf, },
2611 { "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf },
2612 { "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe },
2613 { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2614 { "NdisMGetDeviceProperty", (FUNC)ndis_get_devprop },
2615 { "NdisInitAnsiString", (FUNC)ndis_init_ansi_string },
2616 { "NdisInitUnicodeString", (FUNC)ndis_init_unicode_string },
2617 { "NdisWriteConfiguration", (FUNC)ndis_write_cfg },
2618 { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2619 { "NdisTerminateWrapper", (FUNC)ndis_termwrap },
2620 { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2621 { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2622 { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport },
2623 { "NdisInitializeString", (FUNC)ndis_init_string },
2624 { "NdisFreeString", (FUNC)ndis_free_string },
2625 { "NdisGetCurrentSystemTime", (FUNC)ndis_time },
2626 { "NdisGetSystemUpTime", (FUNC)ndis_uptime },
2627 { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2628 { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2629 { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2630 { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2631 { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2632 { "NdisInitializeWrapper", (FUNC)ndis_initwrap },
2633 { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport },
2634 { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag },
2635 { "NdisAllocateMemory", (FUNC)ndis_malloc },
2636 { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex },
2637 { "NdisCloseConfiguration", (FUNC)ndis_close_cfg },
2638 { "NdisReadConfiguration", (FUNC)ndis_read_cfg },
2639 { "NdisOpenConfiguration", (FUNC)ndis_open_cfg },
2640 { "NdisAcquireSpinLock", (FUNC)ndis_lock },
2641 { "NdisReleaseSpinLock", (FUNC)ndis_unlock },
2642 { "NdisDprAcquireSpinLock", (FUNC)ndis_lock_dpr },
2643 { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock_dpr },
2644 { "NdisAllocateSpinLock", (FUNC)ndis_create_lock },
2645 { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock },
2646 { "NdisFreeMemory", (FUNC)ndis_free },
2647 { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci },
2648 { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2649 { "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci },
2650 { "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci },
2651 { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog },
2652 { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2653 { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2654 { "NdisMInitializeTimer", (FUNC)ndis_create_timer },
2655 { "NdisInitializeTimer", (FUNC)ndis_init_timer },
2656 { "NdisSetTimer", (FUNC)ndis_set_timer },
2657 { "NdisMCancelTimer", (FUNC)ndis_cancel_timer },
2658 { "NdisCancelTimer", (FUNC)ndis_cancel_timer },
2659 { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer },
2660 { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources },
2661 { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport },
2662 { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport },
2663 { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr },
2664 { "NdisQueryMapRegisterCount", (FUNC)ndis_mapreg_cnt },
2665 { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg },
2666 { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg },
2667 { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem },
2668 { "NdisMMapIoSpace", (FUNC)ndis_map_iospace },
2669 { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace },
2670 { "NdisGetCacheFillSize", (FUNC)ndis_cachefill },
2671 { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align },
2672 { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2673 { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool },
2674 { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool },
2675 { "NdisAllocatePacket", (FUNC)ndis_alloc_packet },
2676 { "NdisFreePacket", (FUNC)ndis_release_packet },
2677 { "NdisFreePacketPool", (FUNC)ndis_free_packetpool },
2678 { "NdisDprAllocatePacket", (FUNC)ndis_alloc_packet },
2679 { "NdisDprFreePacket", (FUNC)ndis_release_packet },
2680 { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool },
2681 { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf },
2682 { "NdisQueryBuffer", (FUNC)ndis_query_buf },
2683 { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe },
2684 { "NdisBufferVirtualAddress", (FUNC)ndis_buf_vaddr },
2685 { "NdisBufferVirtualAddressSafe", (FUNC)ndis_buf_vaddr_safe },
2686 { "NdisBufferLength", (FUNC)ndis_buflen },
2687 { "NdisFreeBuffer", (FUNC)ndis_release_buf },
2688 { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool },
2689 { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc },
2690 { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec },
2691 { "NdisInitializeEvent", (FUNC)ndis_init_event },
2692 { "NdisSetEvent", (FUNC)ndis_set_event },
2693 { "NdisResetEvent", (FUNC)ndis_reset_event },
2694 { "NdisWaitEvent", (FUNC)ndis_wait_event },
2695 { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2696 { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc },
2697 { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem },
2698 { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr },
2699 { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr },
2700 { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2701 { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
2702 { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages },
2703 { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset },
2704 { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen },
2705 { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use },
2706 { "NdisMSleep", (FUNC)ndis_sleep },
2707 { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf },
2708 { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
2709 { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
2710 { "NdisOpenFile", (FUNC)ndis_open_file },
2711 { "NdisMapFile", (FUNC)ndis_map_file },
2712 { "NdisUnmapFile", (FUNC)ndis_unmap_file },
2713 { "NdisCloseFile", (FUNC)ndis_close_file },
2714 { "NdisMRegisterDevice", (FUNC)ndis_register_dev },
2715 { "NdisMDeregisterDevice", (FUNC)ndis_deregister_dev },
2716 { "NdisMQueryAdapterInstanceName", (FUNC)ndis_query_name },
2717 { "NdisMRegisterUnloadHandler", (FUNC)ndis_register_unload },
2720 * This last entry is a catch-all for any function we haven't
2721 * implemented yet. The PE import list patching routine will
2722 * use it for any function that doesn't have an explicit match
2726 { NULL, (FUNC)dummy },