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.8 2004/11/17 18:59:21 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
52 #include <sys/ctype.h>
53 #include <sys/param.h>
54 #include <sys/types.h>
55 #include <sys/errno.h>
57 #include <sys/callout.h>
58 #include <sys/kernel.h>
59 #include <sys/systm.h>
60 #include <sys/malloc.h>
62 #include <sys/socket.h>
63 #include <sys/sysctl.h>
64 #include <sys/queue.h>
66 #include <sys/filedesc.h>
67 #include <sys/nlookup.h>
68 #include <sys/fcntl.h>
69 #include <sys/vnode.h>
70 #include <sys/kthread.h>
73 #include <net/if_arp.h>
74 #include <net/ethernet.h>
75 #include <net/if_dl.h>
76 #include <net/if_media.h>
78 #include <machine/atomic.h>
79 #include <machine/bus_memio.h>
80 #include <machine/bus_pio.h>
81 #include <machine/bus.h>
82 #include <machine/resource.h>
87 #include <machine/stdarg.h>
89 #include <netproto/802_11/ieee80211_var.h>
90 #include <netproto/802_11/ieee80211_ioctl.h>
92 #include <bus/pci/pcireg.h>
93 #include <bus/pci/pcivar.h>
97 #include "resource_var.h"
98 #include "ntoskrnl_var.h"
100 #include "ndis_var.h"
102 #include <dev/netif/ndis/if_ndisvar.h>
104 #define FUNC void(*)(void)
106 static char ndis_filepath[MAXPATHLEN];
107 extern struct nd_head ndis_devhead;
109 SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
110 MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
112 __stdcall static void ndis_initwrap(ndis_handle *,
113 device_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 *);
127 static ndis_status ndis_encode_parm(ndis_miniport_block *,
128 struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
129 static 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 void ndis_lock_dpr(ndis_spin_lock *);
141 __stdcall static void ndis_unlock_dpr(ndis_spin_lock *);
142 __stdcall static uint32_t ndis_read_pci(ndis_handle, uint32_t,
143 uint32_t, void *, uint32_t);
144 __stdcall static uint32_t ndis_write_pci(ndis_handle, uint32_t,
145 uint32_t, void *, uint32_t);
146 static void ndis_syslog(ndis_handle, ndis_error_code, uint32_t, ...);
147 static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
148 __stdcall static void ndis_vtophys_load(ndis_handle, ndis_buffer *,
149 uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
150 __stdcall static void ndis_vtophys_unload(ndis_handle, ndis_buffer *, uint32_t);
151 __stdcall static void ndis_create_timer(ndis_miniport_timer *, ndis_handle,
152 ndis_timer_function, void *);
153 __stdcall static void ndis_init_timer(ndis_timer *,
154 ndis_timer_function, void *);
155 __stdcall static void ndis_set_timer(ndis_timer *, uint32_t);
156 __stdcall static void ndis_set_periodic_timer(ndis_miniport_timer *, uint32_t);
157 __stdcall static void ndis_cancel_timer(ndis_timer *, uint8_t *);
158 __stdcall static void ndis_query_resources(ndis_status *, ndis_handle,
159 ndis_resource_list *, uint32_t *);
160 __stdcall static ndis_status ndis_register_ioport(void **,
161 ndis_handle, uint32_t, uint32_t);
162 __stdcall static void ndis_deregister_ioport(ndis_handle,
163 uint32_t, uint32_t, void *);
164 __stdcall static void ndis_read_netaddr(ndis_status *, void **,
165 uint32_t *, ndis_handle);
166 __stdcall static ndis_status ndis_mapreg_cnt(uint32_t, uint32_t *);
167 __stdcall static ndis_status ndis_alloc_mapreg(ndis_handle,
168 uint32_t, uint8_t, uint32_t, uint32_t);
169 __stdcall static void ndis_free_mapreg(ndis_handle);
170 static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
171 __stdcall static void ndis_alloc_sharedmem(ndis_handle, uint32_t,
172 uint8_t, void **, ndis_physaddr *);
173 static void ndis_asyncmem_complete(void *);
174 __stdcall static ndis_status ndis_alloc_sharedmem_async(ndis_handle,
175 uint32_t, uint8_t, void *);
176 __stdcall static void ndis_free_sharedmem(ndis_handle, uint32_t,
177 uint8_t, void *, ndis_physaddr);
178 __stdcall static ndis_status ndis_map_iospace(void **, ndis_handle,
179 ndis_physaddr, uint32_t);
180 __stdcall static void ndis_unmap_iospace(ndis_handle, void *, uint32_t);
181 __stdcall static uint32_t ndis_cachefill(void);
182 __stdcall static uint32_t ndis_dma_align(ndis_handle);
183 __stdcall static ndis_status ndis_init_sc_dma(ndis_handle,
185 __stdcall static void ndis_alloc_packetpool(ndis_status *,
186 ndis_handle *, uint32_t, uint32_t);
187 __stdcall static void ndis_ex_alloc_packetpool(ndis_status *,
188 ndis_handle *, uint32_t, uint32_t, uint32_t);
189 __stdcall static uint32_t ndis_packetpool_use(ndis_handle);
190 __stdcall static void ndis_free_packetpool(ndis_handle);
191 __stdcall static void ndis_alloc_packet(ndis_status *,
192 ndis_packet **, ndis_handle);
193 __stdcall static void ndis_release_packet(ndis_packet *);
194 __stdcall static void ndis_unchain_headbuf(ndis_packet *, ndis_buffer **);
195 __stdcall static void ndis_unchain_tailbuf(ndis_packet *, ndis_buffer **);
196 __stdcall static void ndis_alloc_bufpool(ndis_status *,
197 ndis_handle *, uint32_t);
198 __stdcall static void ndis_free_bufpool(ndis_handle);
199 __stdcall static void ndis_alloc_buf(ndis_status *, ndis_buffer **,
200 ndis_handle, void *, uint32_t);
201 __stdcall static void ndis_release_buf(ndis_buffer *);
202 __stdcall static uint32_t ndis_buflen(ndis_buffer *);
203 __stdcall static void ndis_query_buf(ndis_buffer *, void **, uint32_t *);
204 __stdcall static void ndis_query_buf_safe(ndis_buffer *, void **,
205 uint32_t *, uint32_t);
206 __stdcall static void *ndis_buf_vaddr(ndis_buffer *);
207 __stdcall static void *ndis_buf_vaddr_safe(ndis_buffer *, uint32_t);
208 __stdcall static void ndis_adjust_buflen(ndis_buffer *, int);
209 __stdcall static uint32_t ndis_interlock_inc(uint32_t *);
210 __stdcall static uint32_t ndis_interlock_dec(uint32_t *);
211 __stdcall static void ndis_init_event(ndis_event *);
212 __stdcall static void ndis_set_event(ndis_event *);
213 __stdcall static void ndis_reset_event(ndis_event *);
214 __stdcall static uint8_t ndis_wait_event(ndis_event *, uint32_t);
215 __stdcall static ndis_status ndis_unicode2ansi(ndis_ansi_string *,
216 ndis_unicode_string *);
217 __stdcall static ndis_status ndis_ansi2unicode(ndis_unicode_string *,
219 __stdcall static ndis_status ndis_assign_pcirsrc(ndis_handle,
220 uint32_t, ndis_resource_list **);
221 __stdcall static ndis_status ndis_register_intr(ndis_miniport_interrupt *,
222 ndis_handle, uint32_t, uint32_t, uint8_t,
223 uint8_t, ndis_interrupt_mode);
224 __stdcall static void ndis_deregister_intr(ndis_miniport_interrupt *);
225 __stdcall static void ndis_register_shutdown(ndis_handle, void *,
226 ndis_shutdown_handler);
227 __stdcall static void ndis_deregister_shutdown(ndis_handle);
228 __stdcall static uint32_t ndis_numpages(ndis_buffer *);
229 __stdcall static void ndis_buf_physpages(ndis_buffer *, uint32_t *);
230 __stdcall static void ndis_query_bufoffset(ndis_buffer *,
231 uint32_t *, uint32_t *);
232 __stdcall static void ndis_sleep(uint32_t);
233 __stdcall static uint32_t ndis_read_pccard_amem(ndis_handle,
234 uint32_t, void *, uint32_t);
235 __stdcall static uint32_t ndis_write_pccard_amem(ndis_handle,
236 uint32_t, void *, uint32_t);
237 __stdcall static list_entry *ndis_insert_head(list_entry *,
238 list_entry *, ndis_spin_lock *);
239 __stdcall static list_entry *ndis_remove_head(list_entry *,
241 __stdcall static list_entry *ndis_insert_tail(list_entry *,
242 list_entry *, ndis_spin_lock *);
243 __stdcall static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt *,
245 __stdcall static void ndis_time(uint64_t *);
246 __stdcall static void ndis_uptime(uint32_t *);
247 __stdcall static void ndis_init_string(ndis_unicode_string *, char *);
248 __stdcall static void ndis_init_ansi_string(ndis_ansi_string *, char *);
249 __stdcall static void ndis_init_unicode_string(ndis_unicode_string *,
251 __stdcall static void ndis_free_string(ndis_unicode_string *);
252 __stdcall static ndis_status ndis_remove_miniport(ndis_handle *);
253 __stdcall static void ndis_termwrap(ndis_handle, void *);
254 __stdcall static void ndis_get_devprop(ndis_handle, device_object **,
255 device_object **, device_object **, cm_resource_list *,
257 __stdcall static void ndis_firstbuf(ndis_packet *, ndis_buffer **,
258 void **, uint32_t *, uint32_t *);
259 __stdcall static void ndis_firstbuf_safe(ndis_packet *, ndis_buffer **,
260 void **, uint32_t *, uint32_t *, uint32_t);
261 __stdcall static void ndis_open_file(ndis_status *, ndis_handle *, uint32_t *,
262 ndis_unicode_string *, ndis_physaddr);
263 __stdcall static void ndis_map_file(ndis_status *, void **, ndis_handle);
264 __stdcall static void ndis_unmap_file(ndis_handle);
265 __stdcall static void ndis_close_file(ndis_handle);
266 __stdcall static u_int8_t ndis_cpu_cnt(void);
267 __stdcall static void ndis_ind_statusdone(ndis_handle);
268 __stdcall static void ndis_ind_status(ndis_handle, ndis_status,
270 static void ndis_workfunc(void *);
271 __stdcall static ndis_status ndis_sched_workitem(ndis_work_item *);
272 __stdcall static void ndis_pkt_to_pkt(ndis_packet *, uint32_t, uint32_t,
273 ndis_packet *, uint32_t, uint32_t *);
274 __stdcall static void ndis_pkt_to_pkt_safe(ndis_packet *, uint32_t, uint32_t,
275 ndis_packet *, uint32_t, uint32_t *, uint32_t);
276 __stdcall static ndis_status ndis_register_dev(ndis_handle,
277 ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **,
278 void **, ndis_handle *);
279 __stdcall static ndis_status ndis_deregister_dev(ndis_handle);
280 __stdcall static ndis_status ndis_query_name(ndis_unicode_string *,
282 __stdcall static void ndis_register_unload(ndis_handle, void *);
283 __stdcall static void dummy(void);
286 * Some really old drivers do not properly check the return value
287 * from NdisAllocatePacket() and NdisAllocateBuffer() and will
288 * sometimes allocate few more buffers/packets that they originally
289 * requested when they created the pool. To prevent this from being
290 * a problem, we allocate a few extra buffers/packets beyond what
291 * the driver asks for. This #define controls how many.
293 #define NDIS_POOL_EXTRA 16
298 strcpy(ndis_filepath, "/compat/ndis");
309 * NDIS deals with strings in unicode format, so we have
310 * do deal with them that way too. For now, we only handle
311 * conversion between unicode and ASCII since that's all
312 * that device drivers care about.
316 ndis_ascii_to_unicode(ascii, unicode)
323 if (*unicode == NULL)
324 *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_WAITOK);
326 for (i = 0; i < strlen(ascii); i++) {
327 *ustr = (uint16_t)ascii[i];
335 ndis_unicode_to_ascii(unicode, ulen, ascii)
344 *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO);
346 for (i = 0; i < ulen / 2; i++) {
347 *astr = (uint8_t)unicode[i];
354 __stdcall static void
355 ndis_initwrap(wrapper, drv_obj, path, unused)
356 ndis_handle *wrapper;
357 device_object *drv_obj;
361 ndis_miniport_block *block;
363 block = drv_obj->do_rsvd;
369 __stdcall static void
370 ndis_termwrap(handle, syspec)
377 __stdcall static ndis_status
378 ndis_register_miniport(handle, characteristics, len)
380 ndis_miniport_characteristics *characteristics;
383 ndis_miniport_block *block;
384 struct ndis_softc *sc;
386 block = (ndis_miniport_block *)handle;
387 sc = (struct ndis_softc *)block->nmb_ifp;
388 bcopy((char *)characteristics, (char *)&sc->ndis_chars,
389 sizeof(ndis_miniport_characteristics));
390 if (sc->ndis_chars.nmc_version_major < 5 ||
391 sc->ndis_chars.nmc_version_minor < 1) {
392 sc->ndis_chars.nmc_shutdown_handler = NULL;
393 sc->ndis_chars.nmc_canceltxpkts_handler = NULL;
394 sc->ndis_chars.nmc_pnpevent_handler = NULL;
397 return(NDIS_STATUS_SUCCESS);
400 __stdcall static ndis_status
401 ndis_malloc_withtag(vaddr, len, tag)
408 mem = malloc(len, M_DEVBUF, M_INTWAIT|M_NULLOK);
410 return(NDIS_STATUS_RESOURCES);
413 return(NDIS_STATUS_SUCCESS);
416 __stdcall static ndis_status
417 ndis_malloc(vaddr, len, flags, highaddr)
421 ndis_physaddr highaddr;
425 mem = malloc(len, M_DEVBUF, M_INTWAIT|M_NULLOK);
427 return(NDIS_STATUS_RESOURCES);
430 return(NDIS_STATUS_SUCCESS);
433 __stdcall static void
434 ndis_free(vaddr, len, flags)
441 free(vaddr, M_DEVBUF);
446 __stdcall static ndis_status
447 ndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
449 ndis_handle adapter_handle;
450 ndis_handle adapter_ctx;
453 ndis_interface_type iftype;
455 ndis_miniport_block *block;
458 * Save the adapter context, we need it for calling
459 * the driver's internal functions.
461 block = (ndis_miniport_block *)adapter_handle;
462 block->nmb_miniportadapterctx = adapter_ctx;
463 block->nmb_checkforhangsecs = hangsecs;
464 block->nmb_flags = flags;
466 return(NDIS_STATUS_SUCCESS);
469 __stdcall static void
470 ndis_open_cfg(status, cfg, wrapctx)
476 *status = NDIS_STATUS_SUCCESS;
480 __stdcall static void
481 ndis_open_cfgbyname(status, cfg, subkey, subhandle)
484 ndis_unicode_string *subkey;
485 ndis_handle *subhandle;
488 *status = NDIS_STATUS_SUCCESS;
492 __stdcall static void
493 ndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle)
497 ndis_unicode_string *subkey;
498 ndis_handle *subhandle;
500 *status = NDIS_STATUS_FAILURE;
505 ndis_encode_parm(block, oid, type, parm)
506 ndis_miniport_block *block;
507 struct sysctl_oid *oid;
509 ndis_config_parm **parm;
512 ndis_unicode_string *ustr;
515 unicode = (uint16_t *)&block->nmb_dummybuf;
518 case ndis_parm_string:
519 ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
520 (*parm)->ncp_type = ndis_parm_string;
521 ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
522 ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
523 ustr->nus_buf = unicode;
526 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
530 (*parm)->ncp_type = ndis_parm_int;
531 (*parm)->ncp_parmdata.ncp_intdata =
532 strtol((char *)oid->oid_arg1, NULL, base);
534 case ndis_parm_hexint:
535 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
539 (*parm)->ncp_type = ndis_parm_hexint;
540 (*parm)->ncp_parmdata.ncp_intdata =
541 strtoul((char *)oid->oid_arg1, NULL, base);
544 return(NDIS_STATUS_FAILURE);
548 return(NDIS_STATUS_SUCCESS);
552 ndis_strcasecmp(s1, s2)
559 * In the kernel, toupper() is a macro. Have to be careful
560 * not to use pointer arithmetic when passing it arguments.
566 if (toupper(a) != toupper(b))
572 return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
575 __stdcall static void
576 ndis_read_cfg(status, parm, cfg, key, type)
578 ndis_config_parm **parm;
580 ndis_unicode_string *key;
585 ndis_miniport_block *block;
586 struct ndis_softc *sc;
587 struct sysctl_oid *oidp;
588 struct sysctl_ctx_entry *e;
590 block = (ndis_miniport_block *)cfg;
591 sc = (struct ndis_softc *)block->nmb_ifp;
593 if (key->nus_len == 0 || key->nus_buf == NULL) {
594 *status = NDIS_STATUS_FAILURE;
598 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
600 *parm = &block->nmb_replyparm;
601 bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
602 unicode = (uint16_t *)&block->nmb_dummybuf;
605 * See if registry key is already in a list of known keys
606 * included with the driver.
608 #if __FreeBSD_version < 502113
609 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
611 TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
614 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
615 if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
616 free(keystr, M_DEVBUF);
617 *status = NDIS_STATUS_FAILURE;
620 *status = ndis_encode_parm(block, oidp, type, parm);
621 free(keystr, M_DEVBUF);
627 * If the key didn't match, add it to the list of dynamically
628 * created ones. Sometimes, drivers refer to registry keys
629 * that aren't documented in their .INF files. These keys
630 * are supposed to be created by some sort of utility or
631 * control panel snap-in that comes with the driver software.
632 * Sometimes it's useful to be able to manipulate these.
633 * If the driver requests the key in the form of a string,
634 * make its default value an empty string, otherwise default
638 if (type == ndis_parm_int || type == ndis_parm_hexint)
639 ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
640 "UNSET", CTLFLAG_RW);
642 ndis_add_sysctl(sc, keystr, "(dynamic string key)",
643 "UNSET", CTLFLAG_RW);
645 free(keystr, M_DEVBUF);
646 *status = NDIS_STATUS_FAILURE;
651 ndis_decode_parm(block, parm, val)
652 ndis_miniport_block *block;
653 ndis_config_parm *parm;
656 ndis_unicode_string *ustr;
659 switch(parm->ncp_type) {
660 case ndis_parm_string:
661 ustr = &parm->ncp_parmdata.ncp_stringdata;
662 ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &astr);
663 bcopy(astr, val, 254);
664 free(astr, M_DEVBUF);
667 sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
669 case ndis_parm_hexint:
670 sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
673 return(NDIS_STATUS_FAILURE);
676 return(NDIS_STATUS_SUCCESS);
679 __stdcall static void
680 ndis_write_cfg(status, cfg, key, parm)
683 ndis_unicode_string *key;
684 ndis_config_parm *parm;
687 ndis_miniport_block *block;
688 struct ndis_softc *sc;
689 struct sysctl_oid *oidp;
690 struct sysctl_ctx_entry *e;
693 block = (ndis_miniport_block *)cfg;
694 sc = (struct ndis_softc *)block->nmb_ifp;
696 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
698 /* Decode the parameter into a string. */
699 bzero(val, sizeof(val));
700 *status = ndis_decode_parm(block, parm, val);
701 if (*status != NDIS_STATUS_SUCCESS) {
702 free(keystr, M_DEVBUF);
706 /* See if the key already exists. */
708 #if __FreeBSD_version < 502113
709 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
711 TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
714 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
715 /* Found it, set the value. */
716 strcpy((char *)oidp->oid_arg1, val);
717 free(keystr, M_DEVBUF);
722 /* Not found, add a new key with the specified value. */
723 ndis_add_sysctl(sc, keystr, "(dynamically set key)",
726 free(keystr, M_DEVBUF);
727 *status = NDIS_STATUS_SUCCESS;
731 __stdcall static void
739 * Initialize a Windows spinlock.
741 __stdcall static void
742 ndis_create_lock(lock)
743 ndis_spin_lock *lock;
745 lock->nsl_spinlock = 0;
752 * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
753 * for this. One is that it's sort of superfluous: we don't have to do anything
754 * special to deallocate the spinlock. The other is that there are some buggy
755 * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
756 * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
759 __stdcall static void
760 ndis_destroy_lock(lock)
761 ndis_spin_lock *lock;
764 lock->nsl_spinlock = 0;
771 * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
774 __stdcall static void
776 ndis_spin_lock *lock;
778 lock->nsl_kirql = FASTCALL2(hal_lock,
779 &lock->nsl_spinlock, DISPATCH_LEVEL);
784 * Release a spinlock from IRQL == DISPATCH_LEVEL.
787 __stdcall static void
789 ndis_spin_lock *lock;
791 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
796 * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
798 __stdcall static void
800 ndis_spin_lock *lock;
802 FASTCALL1(ntoskrnl_lock_dpc, &lock->nsl_spinlock);
807 * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
809 __stdcall static void
810 ndis_unlock_dpr(lock)
811 ndis_spin_lock *lock;
813 FASTCALL1(ntoskrnl_unlock_dpc, &lock->nsl_spinlock);
817 __stdcall static uint32_t
818 ndis_read_pci(adapter, slot, offset, buf, len)
825 ndis_miniport_block *block;
829 block = (ndis_miniport_block *)adapter;
831 if (block == NULL || block->nmb_dev == NULL)
834 for (i = 0; i < len; i++)
835 dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
840 __stdcall static uint32_t
841 ndis_write_pci(adapter, slot, offset, buf, len)
848 ndis_miniport_block *block;
852 block = (ndis_miniport_block *)adapter;
855 if (block == NULL || block->nmb_dev == NULL)
858 for (i = 0; i < len; i++)
859 pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
865 * The errorlog routine uses a variable argument list, so we
866 * have to declare it this way.
868 #define ERRMSGLEN 512
870 ndis_syslog(ndis_handle adapter, ndis_error_code code,
871 uint32_t numerrors, ...)
873 ndis_miniport_block *block;
876 char *str = NULL, *ustr = NULL;
878 char msgbuf[ERRMSGLEN];
881 block = (ndis_miniport_block *)adapter;
883 error = pe_get_message(block->nmb_img, code, &str, &i, &flags);
884 if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
886 ndis_unicode_to_ascii((uint16_t *)str,
887 ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
890 device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code,
891 str == NULL ? "unknown error" : str);
892 device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
894 __va_start(ap, numerrors);
895 for (i = 0; i < numerrors; i++)
896 device_printf (block->nmb_dev, "argptr: %p\n",
897 __va_arg(ap, void *));
904 ndis_map_cb(arg, segs, nseg, error)
906 bus_dma_segment_t *segs;
910 struct ndis_map_arg *ctx;
918 for (i = 0; i < nseg; i++) {
919 ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
920 ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
928 __stdcall static void
929 ndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
934 ndis_paddr_unit *addrarray;
937 ndis_miniport_block *block;
938 struct ndis_softc *sc;
939 struct ndis_map_arg nma;
946 block = (ndis_miniport_block *)adapter;
947 sc = (struct ndis_softc *)(block->nmb_ifp);
949 if (mapreg > sc->ndis_mmapcnt)
952 map = sc->ndis_mmaps[mapreg];
953 nma.nma_fraglist = addrarray;
955 error = bus_dmamap_load(sc->ndis_mtag, map,
956 MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
957 (void *)&nma, BUS_DMA_NOWAIT);
962 bus_dmamap_sync(sc->ndis_mtag, map,
963 writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
965 *arraysize = nma.nma_cnt;
970 __stdcall static void
971 ndis_vtophys_unload(adapter, buf, mapreg)
976 ndis_miniport_block *block;
977 struct ndis_softc *sc;
983 block = (ndis_miniport_block *)adapter;
984 sc = (struct ndis_softc *)(block->nmb_ifp);
986 if (mapreg > sc->ndis_mmapcnt)
989 map = sc->ndis_mmaps[mapreg];
991 bus_dmamap_sync(sc->ndis_mtag, map,
992 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
994 bus_dmamap_unload(sc->ndis_mtag, map);
1000 * This is an older pre-miniport timer init routine which doesn't
1001 * accept a miniport context handle. The function context (ctx)
1002 * is supposed to be a pointer to the adapter handle, which should
1003 * have been handed to us via NdisSetAttributesEx(). We use this
1004 * function context to track down the corresponding ndis_miniport_block
1005 * structure. It's vital that we track down the miniport block structure,
1006 * so if we can't do it, we panic. Note that we also play some games
1007 * here by treating ndis_timer and ndis_miniport_timer as the same
1011 __stdcall static void
1012 ndis_init_timer(timer, func, ctx)
1014 ndis_timer_function func;
1017 ntoskrnl_init_timer(&timer->nt_ktimer);
1018 ntoskrnl_init_dpc(&timer->nt_kdpc, func, ctx);
1023 __stdcall static void
1024 ndis_create_timer(timer, handle, func, ctx)
1025 ndis_miniport_timer *timer;
1027 ndis_timer_function func;
1030 /* Save the funcptr and context */
1032 timer->nmt_timerfunc = func;
1033 timer->nmt_timerctx = ctx;
1034 timer->nmt_block = handle;
1036 ntoskrnl_init_timer(&timer->nmt_ktimer);
1037 ntoskrnl_init_dpc(&timer->nmt_kdpc, func, ctx);
1043 * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
1044 * but the former is just a macro wrapper around the latter.
1046 __stdcall static void
1047 ndis_set_timer(timer, msecs)
1052 * KeSetTimer() wants the period in
1053 * hundred nanosecond intervals.
1055 ntoskrnl_set_timer(&timer->nt_ktimer,
1056 ((int64_t)msecs * -10000), &timer->nt_kdpc);
1061 __stdcall static void
1062 ndis_set_periodic_timer(timer, msecs)
1063 ndis_miniport_timer *timer;
1066 ntoskrnl_set_timer_ex(&timer->nmt_ktimer,
1067 ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc);
1073 * Technically, this is really NdisCancelTimer(), but we also
1074 * (ab)use it for NdisMCancelTimer(), since in our implementation
1075 * we don't need the extra info in the ndis_miniport_timer
1079 __stdcall static void
1080 ndis_cancel_timer(timer, cancelled)
1084 *cancelled = ntoskrnl_cancel_timer(&timer->nt_ktimer);
1089 __stdcall static void
1090 ndis_query_resources(status, adapter, list, buflen)
1091 ndis_status *status;
1092 ndis_handle adapter;
1093 ndis_resource_list *list;
1096 ndis_miniport_block *block;
1097 struct ndis_softc *sc;
1100 block = (ndis_miniport_block *)adapter;
1101 sc = (struct ndis_softc *)block->nmb_ifp;
1103 rsclen = sizeof(ndis_resource_list) +
1104 (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1105 if (*buflen < rsclen) {
1107 *status = NDIS_STATUS_INVALID_LENGTH;
1111 bcopy((char *)block->nmb_rlist, (char *)list, rsclen);
1112 *status = NDIS_STATUS_SUCCESS;
1116 __stdcall static ndis_status
1117 ndis_register_ioport(offset, adapter, port, numports)
1119 ndis_handle adapter;
1123 struct ndis_miniport_block *block;
1124 struct ndis_softc *sc;
1126 if (adapter == NULL)
1127 return(NDIS_STATUS_FAILURE);
1129 block = (ndis_miniport_block *)adapter;
1130 sc = (struct ndis_softc *)(block->nmb_ifp);
1132 if (sc->ndis_res_io == NULL)
1133 return(NDIS_STATUS_FAILURE);
1135 /* Don't let the device map more ports than we have. */
1136 if (rman_get_size(sc->ndis_res_io) < numports)
1137 return(NDIS_STATUS_INVALID_LENGTH);
1139 *offset = (void *)rman_get_start(sc->ndis_res_io);
1141 return(NDIS_STATUS_SUCCESS);
1144 __stdcall static void
1145 ndis_deregister_ioport(adapter, port, numports, offset)
1146 ndis_handle adapter;
1154 __stdcall static void
1155 ndis_read_netaddr(status, addr, addrlen, adapter)
1156 ndis_status *status;
1159 ndis_handle adapter;
1161 struct ndis_softc *sc;
1162 ndis_miniport_block *block;
1163 uint8_t empty[] = { 0, 0, 0, 0, 0, 0 };
1165 block = (ndis_miniport_block *)adapter;
1166 sc = (struct ndis_softc *)block->nmb_ifp;
1168 if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1169 *status = NDIS_STATUS_FAILURE;
1171 *addr = sc->arpcom.ac_enaddr;
1172 *addrlen = ETHER_ADDR_LEN;
1173 *status = NDIS_STATUS_SUCCESS;
1179 __stdcall static ndis_status
1180 ndis_mapreg_cnt(bustype, cnt)
1185 return(NDIS_STATUS_SUCCESS);
1188 __stdcall static ndis_status
1189 ndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
1190 ndis_handle adapter;
1191 uint32_t dmachannel;
1193 uint32_t physmapneeded;
1196 struct ndis_softc *sc;
1197 ndis_miniport_block *block;
1198 int error, i, nseg = NDIS_MAXSEG;
1200 block = (ndis_miniport_block *)adapter;
1201 sc = (struct ndis_softc *)block->nmb_ifp;
1203 sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1204 M_DEVBUF, M_INTWAIT|M_ZERO);
1206 if (sc->ndis_mmaps == NULL)
1207 return(NDIS_STATUS_RESOURCES);
1209 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1210 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1211 NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1215 free(sc->ndis_mmaps, M_DEVBUF);
1216 return(NDIS_STATUS_RESOURCES);
1219 for (i = 0; i < physmapneeded; i++)
1220 bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1222 sc->ndis_mmapcnt = physmapneeded;
1224 return(NDIS_STATUS_SUCCESS);
1227 __stdcall static void
1228 ndis_free_mapreg(adapter)
1229 ndis_handle adapter;
1231 struct ndis_softc *sc;
1232 ndis_miniport_block *block;
1235 block = (ndis_miniport_block *)adapter;
1236 sc = (struct ndis_softc *)block->nmb_ifp;
1238 for (i = 0; i < sc->ndis_mmapcnt; i++)
1239 bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1241 free(sc->ndis_mmaps, M_DEVBUF);
1243 bus_dma_tag_destroy(sc->ndis_mtag);
1249 ndis_mapshared_cb(arg, segs, nseg, error)
1251 bus_dma_segment_t *segs;
1257 if (error || nseg > 1)
1262 p->np_quad = segs[0].ds_addr;
1268 * This maps to bus_dmamem_alloc().
1270 __stdcall static void
1271 ndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
1272 ndis_handle adapter;
1276 ndis_physaddr *paddr;
1278 ndis_miniport_block *block;
1279 struct ndis_softc *sc;
1280 struct ndis_shmem *sh;
1283 if (adapter == NULL)
1286 block = (ndis_miniport_block *)adapter;
1287 sc = (struct ndis_softc *)(block->nmb_ifp);
1289 sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_INTWAIT|M_ZERO);
1294 * When performing shared memory allocations, create a tag
1295 * with a lowaddr limit that restricts physical memory mappings
1296 * so that they all fall within the first 1GB of memory.
1297 * At least one device/driver combination (Linksys Instant
1298 * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
1299 * problems with performing DMA operations with physical
1300 * that lie above the 1GB mark. I don't know if this is a
1301 * hardware limitation or if the addresses are being truncated
1302 * within the driver, but this seems to be the only way to
1303 * make these cards work reliably in systems with more than
1304 * 1GB of physical memory.
1307 error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1308 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL,
1309 NULL, len, 1, len, BUS_DMA_ALLOCNOW,
1317 error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1318 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1321 bus_dma_tag_destroy(sh->ndis_stag);
1326 error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1327 len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1330 bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1331 bus_dma_tag_destroy(sh->ndis_stag);
1336 sh->ndis_saddr = *vaddr;
1337 sh->ndis_next = sc->ndis_shlist;
1338 sc->ndis_shlist = sh;
1343 struct ndis_allocwork {
1344 ndis_handle na_adapter;
1351 ndis_asyncmem_complete(arg)
1354 ndis_miniport_block *block;
1355 struct ndis_softc *sc;
1356 struct ndis_allocwork *w;
1358 ndis_physaddr paddr;
1359 ndis_allocdone_handler donefunc;
1362 block = (ndis_miniport_block *)w->na_adapter;
1363 sc = (struct ndis_softc *)(block->nmb_ifp);
1368 donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1369 ndis_alloc_sharedmem(w->na_adapter, w->na_len,
1370 w->na_cached, &vaddr, &paddr);
1371 donefunc(w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
1373 free(arg, M_DEVBUF);
1378 __stdcall static ndis_status
1379 ndis_alloc_sharedmem_async(adapter, len, cached, ctx)
1380 ndis_handle adapter;
1385 struct ndis_allocwork *w;
1387 if (adapter == NULL)
1388 return(NDIS_STATUS_FAILURE);
1390 w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_INTWAIT);
1393 return(NDIS_STATUS_FAILURE);
1395 w->na_adapter = adapter;
1396 w->na_cached = cached;
1401 * Pawn this work off on the SWI thread instead of the
1402 * taskqueue thread, because sometimes drivers will queue
1403 * up work items on the taskqueue thread that will block,
1404 * which would prevent the memory allocation from completing
1407 ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI);
1409 return(NDIS_STATUS_PENDING);
1412 __stdcall static void
1413 ndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
1414 ndis_handle adapter;
1418 ndis_physaddr paddr;
1420 ndis_miniport_block *block;
1421 struct ndis_softc *sc;
1422 struct ndis_shmem *sh, *prev;
1424 if (vaddr == NULL || adapter == NULL)
1427 block = (ndis_miniport_block *)adapter;
1428 sc = (struct ndis_softc *)(block->nmb_ifp);
1429 sh = prev = sc->ndis_shlist;
1432 if (sh->ndis_saddr == vaddr)
1438 bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1439 bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1440 bus_dma_tag_destroy(sh->ndis_stag);
1442 if (sh == sc->ndis_shlist)
1443 sc->ndis_shlist = sh->ndis_next;
1445 prev->ndis_next = sh->ndis_next;
1452 __stdcall static ndis_status
1453 ndis_map_iospace(vaddr, adapter, paddr, len)
1455 ndis_handle adapter;
1456 ndis_physaddr paddr;
1459 ndis_miniport_block *block;
1460 struct ndis_softc *sc;
1462 if (adapter == NULL)
1463 return(NDIS_STATUS_FAILURE);
1465 block = (ndis_miniport_block *)adapter;
1466 sc = (struct ndis_softc *)(block->nmb_ifp);
1468 if (sc->ndis_res_mem != NULL &&
1469 paddr.np_quad == rman_get_start(sc->ndis_res_mem))
1470 *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1471 else if (sc->ndis_res_altmem != NULL &&
1472 paddr.np_quad == rman_get_start(sc->ndis_res_altmem))
1473 *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem);
1474 else if (sc->ndis_res_am != NULL &&
1475 paddr.np_quad == rman_get_start(sc->ndis_res_am))
1476 *vaddr = (void *)rman_get_virtual(sc->ndis_res_am);
1478 return(NDIS_STATUS_FAILURE);
1480 return(NDIS_STATUS_SUCCESS);
1483 __stdcall static void
1484 ndis_unmap_iospace(adapter, vaddr, len)
1485 ndis_handle adapter;
1492 __stdcall static uint32_t
1493 ndis_cachefill(void)
1498 __stdcall static uint32_t
1499 ndis_dma_align(handle)
1506 * NDIS has two methods for dealing with NICs that support DMA.
1507 * One is to just pass packets to the driver and let it call
1508 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1509 * all by itself, and the other is to let the NDIS library handle the
1510 * buffer mapping internally, and hand the driver an already populated
1511 * scatter/gather fragment list. If the driver calls
1512 * NdisMInitializeScatterGatherDma(), it wants to use the latter
1516 __stdcall static ndis_status
1517 ndis_init_sc_dma(adapter, is64, maxphysmap)
1518 ndis_handle adapter;
1520 uint32_t maxphysmap;
1522 struct ndis_softc *sc;
1523 ndis_miniport_block *block;
1526 if (adapter == NULL)
1527 return(NDIS_STATUS_FAILURE);
1528 block = (ndis_miniport_block *)adapter;
1529 sc = (struct ndis_softc *)block->nmb_ifp;
1531 /* Don't do this twice. */
1532 if (sc->ndis_sc == 1)
1533 return(NDIS_STATUS_SUCCESS);
1535 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1536 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1537 MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1542 return(NDIS_STATUS_SUCCESS);
1545 __stdcall static void
1546 ndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
1547 ndis_status *status;
1550 uint32_t protrsvdlen;
1555 *pool = malloc(sizeof(ndis_packet) *
1556 ((descnum + NDIS_POOL_EXTRA) + 1),
1557 M_DEVBUF, M_WAITOK|M_ZERO);
1558 cur = (ndis_packet *)*pool;
1559 cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1560 cur->np_private.npp_totlen = 0; /* init deletetion flag */
1561 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1562 cur->np_private.npp_head = (ndis_handle)(cur + 1);
1566 *status = NDIS_STATUS_SUCCESS;
1570 __stdcall static void
1571 ndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
1572 ndis_status *status;
1575 uint32_t oflowdescnum;
1576 uint32_t protrsvdlen;
1578 return(ndis_alloc_packetpool(status, pool,
1579 descnum + oflowdescnum, protrsvdlen));
1582 __stdcall static uint32_t
1583 ndis_packetpool_use(pool)
1588 head = (ndis_packet *)pool;
1590 return(head->np_private.npp_count);
1593 __stdcall static void
1594 ndis_free_packetpool(pool)
1601 /* Mark this pool as 'going away.' */
1603 head->np_private.npp_totlen = 1;
1605 /* If there are no buffers loaned out, destroy the pool. */
1607 if (head->np_private.npp_count == 0)
1608 free(pool, M_DEVBUF);
1610 printf("NDIS: buggy driver deleting active packet pool!\n");
1615 __stdcall static void
1616 ndis_alloc_packet(status, packet, pool)
1617 ndis_status *status;
1618 ndis_packet **packet;
1621 ndis_packet *head, *pkt;
1623 head = (ndis_packet *)pool;
1625 if (head->np_private.npp_flags != 0x1) {
1626 *status = NDIS_STATUS_FAILURE;
1631 * If this pool is marked as 'going away' don't allocate any
1632 * more packets out of it.
1635 if (head->np_private.npp_totlen) {
1636 *status = NDIS_STATUS_FAILURE;
1640 pkt = (ndis_packet *)head->np_private.npp_head;
1643 *status = NDIS_STATUS_RESOURCES;
1647 head->np_private.npp_head = pkt->np_private.npp_head;
1649 pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1650 /* Save pointer to the pool. */
1651 pkt->np_private.npp_pool = head;
1653 /* Set the oob offset pointer. Lots of things expect this. */
1654 pkt->np_private.npp_packetooboffset =
1655 offsetof(ndis_packet, np_oob);
1658 * We must initialize the packet flags correctly in order
1659 * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
1660 * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly.
1662 pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
1666 head->np_private.npp_count++;
1667 *status = NDIS_STATUS_SUCCESS;
1671 __stdcall static void
1672 ndis_release_packet(packet)
1673 ndis_packet *packet;
1677 if (packet == NULL || packet->np_private.npp_pool == NULL)
1680 head = packet->np_private.npp_pool;
1681 if (head->np_private.npp_flags != 0x1)
1684 packet->np_private.npp_head = head->np_private.npp_head;
1685 head->np_private.npp_head = (ndis_buffer *)packet;
1686 head->np_private.npp_count--;
1689 * If the pool has been marked for deletion and there are
1690 * no more packets outstanding, nuke the pool.
1693 if (head->np_private.npp_totlen && head->np_private.npp_count == 0)
1694 free(head, M_DEVBUF);
1699 __stdcall static void
1700 ndis_unchain_headbuf(packet, buf)
1701 ndis_packet *packet;
1704 ndis_packet_private *priv;
1706 if (packet == NULL || buf == NULL)
1709 priv = &packet->np_private;
1711 priv->npp_validcounts = FALSE;
1713 if (priv->npp_head == priv->npp_tail) {
1714 *buf = priv->npp_head;
1715 priv->npp_head = priv->npp_tail = NULL;
1717 *buf = priv->npp_head;
1718 priv->npp_head = (*buf)->nb_next;
1724 __stdcall static void
1725 ndis_unchain_tailbuf(packet, buf)
1726 ndis_packet *packet;
1729 ndis_packet_private *priv;
1732 if (packet == NULL || buf == NULL)
1735 priv = &packet->np_private;
1737 priv->npp_validcounts = FALSE;
1739 if (priv->npp_head == priv->npp_tail) {
1740 *buf = priv->npp_head;
1741 priv->npp_head = priv->npp_tail = NULL;
1743 *buf = priv->npp_tail;
1744 tmp = priv->npp_head;
1745 while (tmp->nb_next != priv->npp_tail)
1747 priv->npp_tail = tmp;
1748 tmp->nb_next = NULL;
1755 * The NDIS "buffer" manipulation functions are somewhat misnamed.
1756 * They don't really allocate buffers: they allocate buffer mappings.
1757 * The idea is you reserve a chunk of DMA-able memory using
1758 * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1759 * to obtain the virtual address of the DMA-able region.
1760 * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1763 __stdcall static void
1764 ndis_alloc_bufpool(status, pool, descnum)
1765 ndis_status *status;
1772 *pool = malloc(sizeof(ndis_buffer) *
1773 ((descnum + NDIS_POOL_EXTRA) + 1),
1774 M_DEVBUF, M_WAITOK|M_ZERO);
1775 cur = (ndis_buffer *)*pool;
1776 cur->nb_flags = 0x1; /* mark the head of the list */
1777 cur->nb_bytecount = 0; /* init usage count */
1778 cur->nb_byteoffset = 0; /* init deletetion flag */
1779 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1780 cur->nb_next = cur + 1;
1784 *status = NDIS_STATUS_SUCCESS;
1788 __stdcall static void
1789 ndis_free_bufpool(pool)
1796 /* Mark this pool as 'going away.' */
1798 head->nb_byteoffset = 1;
1800 /* If there are no buffers loaned out, destroy the pool. */
1801 if (head->nb_bytecount == 0)
1802 free(pool, M_DEVBUF);
1804 printf("NDIS: buggy driver deleting active buffer pool!\n");
1810 * This maps to a bus_dmamap_create() and bus_dmamap_load().
1812 __stdcall static void
1813 ndis_alloc_buf(status, buffer, pool, vaddr, len)
1814 ndis_status *status;
1815 ndis_buffer **buffer;
1820 ndis_buffer *head, *buf;
1822 head = (ndis_buffer *)pool;
1823 if (head->nb_flags != 0x1) {
1824 *status = NDIS_STATUS_FAILURE;
1829 * If this pool is marked as 'going away' don't allocate any
1830 * more buffers out of it.
1833 if (head->nb_byteoffset) {
1834 *status = NDIS_STATUS_FAILURE;
1838 buf = head->nb_next;
1841 *status = NDIS_STATUS_RESOURCES;
1845 head->nb_next = buf->nb_next;
1847 /* Save pointer to the pool. */
1848 buf->nb_process = head;
1850 MDL_INIT(buf, vaddr, len);
1854 /* Increment count of busy buffers. */
1856 head->nb_bytecount++;
1858 *status = NDIS_STATUS_SUCCESS;
1862 __stdcall static void
1863 ndis_release_buf(buf)
1868 if (buf == NULL || buf->nb_process == NULL)
1871 head = buf->nb_process;
1873 if (head->nb_flags != 0x1)
1876 buf->nb_next = head->nb_next;
1877 head->nb_next = buf;
1879 /* Decrement count of busy buffers. */
1881 head->nb_bytecount--;
1884 * If the pool has been marked for deletion and there are
1885 * no more buffers outstanding, nuke the pool.
1888 if (head->nb_byteoffset && head->nb_bytecount == 0)
1889 free(head, M_DEVBUF);
1896 __stdcall static uint32_t
1900 return(buf->nb_bytecount);
1904 * Get the virtual address and length of a buffer.
1905 * Note: the vaddr argument is optional.
1908 __stdcall static void
1909 ndis_query_buf(buf, vaddr, len)
1915 *vaddr = MDL_VA(buf);
1916 *len = buf->nb_bytecount;
1921 /* Same as above -- we don't care about the priority. */
1923 __stdcall static void
1924 ndis_query_buf_safe(buf, vaddr, len, prio)
1931 *vaddr = MDL_VA(buf);
1932 *len = buf->nb_bytecount;
1937 /* Damnit Microsoft!! How many ways can you do the same thing?! */
1939 __stdcall static void *
1943 return(MDL_VA(buf));
1946 __stdcall static void *
1947 ndis_buf_vaddr_safe(buf, prio)
1951 return(MDL_VA(buf));
1954 __stdcall static void
1955 ndis_adjust_buflen(buf, len)
1959 buf->nb_bytecount = len;
1964 __stdcall static uint32_t
1965 ndis_interlock_inc(addend)
1968 atomic_add_long((u_long *)addend, 1);
1972 __stdcall static uint32_t
1973 ndis_interlock_dec(addend)
1976 atomic_subtract_long((u_long *)addend, 1);
1980 __stdcall static void
1981 ndis_init_event(event)
1985 * NDIS events are always notification
1986 * events, and should be initialized to the
1987 * not signaled state.
1990 ntoskrnl_init_event(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE);
1994 __stdcall static void
1995 ndis_set_event(event)
1998 ntoskrnl_set_event(&event->ne_event, 0, 0);
2002 __stdcall static void
2003 ndis_reset_event(event)
2006 ntoskrnl_reset_event(&event->ne_event);
2010 __stdcall static uint8_t
2011 ndis_wait_event(event, msecs)
2018 duetime = ((int64_t)msecs * -10000);
2020 rval = ntoskrnl_waitforobj((nt_dispatch_header *)event,
2021 0, 0, TRUE, msecs ? &duetime : NULL);
2023 if (rval == STATUS_TIMEOUT)
2029 __stdcall static ndis_status
2030 ndis_unicode2ansi(dstr, sstr)
2031 ndis_ansi_string *dstr;
2032 ndis_unicode_string *sstr;
2034 if (dstr == NULL || sstr == NULL)
2035 return(NDIS_STATUS_FAILURE);
2036 if (ndis_unicode_to_ascii(sstr->nus_buf,
2037 sstr->nus_len, &dstr->nas_buf))
2038 return(NDIS_STATUS_FAILURE);
2039 dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
2040 return (NDIS_STATUS_SUCCESS);
2043 __stdcall static ndis_status
2044 ndis_ansi2unicode(dstr, sstr)
2045 ndis_unicode_string *dstr;
2046 ndis_ansi_string *sstr;
2049 if (dstr == NULL || sstr == NULL)
2050 return(NDIS_STATUS_FAILURE);
2051 str = malloc(sstr->nas_len + 1, M_DEVBUF, M_WAITOK);
2052 strncpy(str, sstr->nas_buf, sstr->nas_len);
2053 *(str + sstr->nas_len) = '\0';
2054 if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
2055 free(str, M_DEVBUF);
2056 return(NDIS_STATUS_FAILURE);
2058 dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
2059 free(str, M_DEVBUF);
2060 return (NDIS_STATUS_SUCCESS);
2063 __stdcall static ndis_status
2064 ndis_assign_pcirsrc(adapter, slot, list)
2065 ndis_handle adapter;
2067 ndis_resource_list **list;
2069 ndis_miniport_block *block;
2071 if (adapter == NULL || list == NULL)
2072 return (NDIS_STATUS_FAILURE);
2074 block = (ndis_miniport_block *)adapter;
2075 *list = block->nmb_rlist;
2077 return (NDIS_STATUS_SUCCESS);
2080 __stdcall static ndis_status
2081 ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
2082 ndis_miniport_interrupt *intr;
2083 ndis_handle adapter;
2088 ndis_interrupt_mode imode;
2090 ndis_miniport_block *block;
2094 intr->ni_block = adapter;
2095 intr->ni_isrreq = reqisr;
2096 intr->ni_shared = shared;
2097 block->nmb_interrupt = intr;
2098 return(NDIS_STATUS_SUCCESS);
2101 __stdcall static void
2102 ndis_deregister_intr(intr)
2103 ndis_miniport_interrupt *intr;
2108 __stdcall static void
2109 ndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
2110 ndis_handle adapter;
2112 ndis_shutdown_handler shutdownfunc;
2114 ndis_miniport_block *block;
2115 ndis_miniport_characteristics *chars;
2116 struct ndis_softc *sc;
2118 if (adapter == NULL)
2121 block = (ndis_miniport_block *)adapter;
2122 sc = (struct ndis_softc *)block->nmb_ifp;
2123 chars = &sc->ndis_chars;
2125 chars->nmc_shutdown_handler = shutdownfunc;
2126 chars->nmc_rsvd0 = shutdownctx;
2131 __stdcall static void
2132 ndis_deregister_shutdown(adapter)
2133 ndis_handle adapter;
2135 ndis_miniport_block *block;
2136 ndis_miniport_characteristics *chars;
2137 struct ndis_softc *sc;
2139 if (adapter == NULL)
2142 block = (ndis_miniport_block *)adapter;
2143 sc = (struct ndis_softc *)block->nmb_ifp;
2144 chars = &sc->ndis_chars;
2146 chars->nmc_shutdown_handler = NULL;
2147 chars->nmc_rsvd0 = NULL;
2152 __stdcall static uint32_t
2158 if (buf->nb_bytecount == 0)
2160 return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
2163 __stdcall static void
2164 ndis_buf_physpages(buf, pages)
2171 *pages = ndis_numpages(buf);
2175 __stdcall static void
2176 ndis_query_bufoffset(buf, off, len)
2184 *off = buf->nb_byteoffset;
2185 *len = buf->nb_bytecount;
2190 __stdcall static void
2199 ndis_thsuspend(curthread, 1 + usecs * hz / 1000000);
2204 __stdcall static uint32_t
2205 ndis_read_pccard_amem(handle, offset, buf, len)
2211 struct ndis_softc *sc;
2212 ndis_miniport_block *block;
2213 bus_space_handle_t bh;
2221 block = (ndis_miniport_block *)handle;
2222 sc = (struct ndis_softc *)block->nmb_ifp;
2225 bh = rman_get_bushandle(sc->ndis_res_am);
2226 bt = rman_get_bustag(sc->ndis_res_am);
2228 for (i = 0; i < len; i++)
2229 dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2);
2234 __stdcall static uint32_t
2235 ndis_write_pccard_amem(handle, offset, buf, len)
2241 struct ndis_softc *sc;
2242 ndis_miniport_block *block;
2243 bus_space_handle_t bh;
2251 block = (ndis_miniport_block *)handle;
2252 sc = (struct ndis_softc *)block->nmb_ifp;
2255 bh = rman_get_bushandle(sc->ndis_res_am);
2256 bt = rman_get_bustag(sc->ndis_res_am);
2258 for (i = 0; i < len; i++)
2259 bus_space_write_1(bt, bh, (offset + i) * 2, src[i]);
2264 __stdcall static list_entry *
2265 ndis_insert_head(head, entry, lock)
2268 ndis_spin_lock *lock;
2272 lock->nsl_kirql = FASTCALL2(hal_lock,
2273 &lock->nsl_spinlock, DISPATCH_LEVEL);
2274 flink = head->nle_flink;
2275 entry->nle_flink = flink;
2276 entry->nle_blink = head;
2277 flink->nle_blink = entry;
2278 head->nle_flink = entry;
2279 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2284 __stdcall static list_entry *
2285 ndis_remove_head(head, lock)
2287 ndis_spin_lock *lock;
2292 lock->nsl_kirql = FASTCALL2(hal_lock,
2293 &lock->nsl_spinlock, DISPATCH_LEVEL);
2294 entry = head->nle_flink;
2295 flink = entry->nle_flink;
2296 head->nle_flink = flink;
2297 flink->nle_blink = head;
2298 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2303 __stdcall static list_entry *
2304 ndis_insert_tail(head, entry, lock)
2307 ndis_spin_lock *lock;
2311 lock->nsl_kirql = FASTCALL2(hal_lock,
2312 &lock->nsl_spinlock, DISPATCH_LEVEL);
2313 blink = head->nle_blink;
2314 entry->nle_flink = head;
2315 entry->nle_blink = blink;
2316 blink->nle_flink = entry;
2317 head->nle_blink = entry;
2318 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2323 __stdcall static uint8_t
2324 ndis_sync_with_intr(intr, syncfunc, syncctx)
2325 ndis_miniport_interrupt *intr;
2329 struct ndis_softc *sc;
2330 __stdcall uint8_t (*sync)(void *);
2334 if (syncfunc == NULL || syncctx == NULL)
2337 sc = (struct ndis_softc *)intr->ni_block->nmb_ifp;
2340 rval = sync(syncctx);
2341 NDIS_INTRUNLOCK(sc);
2347 * Return the number of 100 nanosecond intervals since
2348 * January 1, 1601. (?!?!)
2350 __stdcall static void
2357 *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2364 * Return the number of milliseconds since the system booted.
2366 __stdcall static void
2373 *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
2378 __stdcall static void
2379 ndis_init_string(dst, src)
2380 ndis_unicode_string *dst;
2383 ndis_unicode_string *u;
2387 if (ndis_ascii_to_unicode(src, &u->nus_buf))
2389 u->nus_len = u->nus_maxlen = strlen(src) * 2;
2393 __stdcall static void
2394 ndis_free_string(str)
2395 ndis_unicode_string *str;
2399 if (str->nus_buf != NULL)
2400 free(str->nus_buf, M_DEVBUF);
2401 free(str, M_DEVBUF);
2405 __stdcall static ndis_status
2406 ndis_remove_miniport(adapter)
2407 ndis_handle *adapter;
2409 return(NDIS_STATUS_SUCCESS);
2412 __stdcall static void
2413 ndis_init_ansi_string(dst, src)
2414 ndis_ansi_string *dst;
2417 ndis_ansi_string *a;
2423 a->nas_len = a->nas_maxlen = 0;
2427 a->nas_len = a->nas_maxlen = strlen(src);
2433 __stdcall static void
2434 ndis_init_unicode_string(dst, src)
2435 ndis_unicode_string *dst;
2438 ndis_unicode_string *u;
2445 u->nus_len = u->nus_maxlen = 0;
2452 u->nus_len = u->nus_maxlen = i * 2;
2458 __stdcall static void ndis_get_devprop(adapter, phydevobj,
2459 funcdevobj, nextdevobj, resources, transresources)
2460 ndis_handle adapter;
2461 device_object **phydevobj;
2462 device_object **funcdevobj;
2463 device_object **nextdevobj;
2464 cm_resource_list *resources;
2465 cm_resource_list *transresources;
2467 ndis_miniport_block *block;
2469 block = (ndis_miniport_block *)adapter;
2471 if (phydevobj != NULL)
2472 *phydevobj = &block->nmb_devobj;
2473 if (funcdevobj != NULL)
2474 *funcdevobj = &block->nmb_devobj;
2479 __stdcall static void
2480 ndis_firstbuf(packet, buf, firstva, firstlen, totlen)
2481 ndis_packet *packet;
2489 tmp = packet->np_private.npp_head;
2493 *firstlen = *totlen = 0;
2495 *firstva = MDL_VA(tmp);
2496 *firstlen = *totlen = tmp->nb_bytecount;
2497 for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
2498 *totlen += tmp->nb_bytecount;
2504 __stdcall static void
2505 ndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio)
2506 ndis_packet *packet;
2513 ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
2516 /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2517 __stdcall static void
2518 ndis_open_file(status, filehandle, filelength, filename, highestaddr)
2519 ndis_status *status;
2520 ndis_handle *filehandle;
2521 uint32_t *filelength;
2522 ndis_unicode_string *filename;
2523 ndis_physaddr highestaddr;
2525 char *afilename = NULL;
2526 struct thread *td = curthread;
2527 struct nlookupdata nd;
2530 struct vattr *vap = &vat;
2533 char path[MAXPATHLEN];
2535 ndis_unicode_to_ascii(filename->nus_buf,
2536 filename->nus_len, &afilename);
2538 sprintf(path, "%s/%s", ndis_filepath, afilename);
2539 free(afilename, M_DEVBUF);
2541 fh = malloc(sizeof(ndis_fh), M_TEMP, M_WAITOK);
2543 error = nlookup_init(&nd, path, UIO_SYSSPACE, NLC_FOLLOW|NLC_LOCKVP);
2545 error = vn_open(&nd, NULL, FREAD, 0);
2547 *status = NDIS_STATUS_FILE_NOT_FOUND;
2549 printf("NDIS: open file %s failed: %d\n", path, error);
2554 nd.nl_open_vp = NULL;
2556 /* Get the file size. */
2557 VOP_GETATTR(vp, vap, td);
2558 VOP_UNLOCK(vp, 0, td);
2563 *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
2564 *status = NDIS_STATUS_SUCCESS;
2571 __stdcall static void
2572 ndis_map_file(status, mappedbuffer, filehandle)
2573 ndis_status *status;
2574 void **mappedbuffer;
2575 ndis_handle filehandle;
2578 struct thread *td = curthread;
2581 if (filehandle == NULL) {
2582 *status = NDIS_STATUS_FAILURE;
2586 fh = (ndis_fh *)filehandle;
2588 if (fh->nf_vp == NULL) {
2589 *status = NDIS_STATUS_FAILURE;
2593 if (fh->nf_map != NULL) {
2594 *status = NDIS_STATUS_ALREADY_MAPPED;
2598 fh->nf_map = malloc(fh->nf_maplen, M_DEVBUF, M_WAITOK);
2600 error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
2601 UIO_SYSSPACE, 0, proc0.p_ucred, &resid, td);
2604 *status = NDIS_STATUS_FAILURE;
2606 *status = NDIS_STATUS_SUCCESS;
2607 *mappedbuffer = fh->nf_map;
2613 __stdcall static void
2614 ndis_unmap_file(filehandle)
2615 ndis_handle filehandle;
2618 fh = (ndis_fh *)filehandle;
2620 if (fh->nf_map == NULL)
2622 free(fh->nf_map, M_DEVBUF);
2628 __stdcall static void
2629 ndis_close_file(filehandle)
2630 ndis_handle filehandle;
2632 struct thread *td = curthread;
2635 if (filehandle == NULL)
2638 fh = (ndis_fh *)filehandle;
2639 if (fh->nf_map != NULL) {
2640 free(fh->nf_map, M_DEVBUF);
2644 if (fh->nf_vp == NULL)
2647 vn_close(fh->nf_vp, FREAD, td);
2655 __stdcall static uint8_t
2661 typedef __stdcall void (*ndis_statusdone_handler)(ndis_handle);
2662 typedef __stdcall void (*ndis_status_handler)(ndis_handle, ndis_status,
2665 __stdcall static void
2666 ndis_ind_statusdone(adapter)
2667 ndis_handle adapter;
2669 ndis_miniport_block *block;
2670 ndis_statusdone_handler statusdonefunc;
2672 block = (ndis_miniport_block *)adapter;
2673 statusdonefunc = block->nmb_statusdone_func;
2675 statusdonefunc(adapter);
2679 __stdcall static void
2680 ndis_ind_status(adapter, status, sbuf, slen)
2681 ndis_handle adapter;
2686 ndis_miniport_block *block;
2687 ndis_status_handler statusfunc;
2689 block = (ndis_miniport_block *)adapter;
2690 statusfunc = block->nmb_status_func;
2692 statusfunc(adapter, status, sbuf, slen);
2700 ndis_work_item *work;
2704 workfunc = work->nwi_func;
2705 workfunc(work, work->nwi_ctx);
2709 __stdcall static ndis_status
2710 ndis_sched_workitem(work)
2711 ndis_work_item *work;
2713 ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
2714 return(NDIS_STATUS_SUCCESS);
2717 __stdcall static void
2718 ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen)
2726 ndis_buffer *src, *dst;
2728 int resid, copied, len, scnt, dcnt;
2732 src = spkt->np_private.npp_head;
2733 dst = dpkt->np_private.npp_head;
2737 scnt = src->nb_bytecount;
2738 dcnt = dst->nb_bytecount;
2741 if (src->nb_bytecount > soff) {
2743 scnt = src->nb_bytecount - soff;
2746 soff -= src->nb_bytecount;
2754 if (dst->nb_bytecount > doff) {
2756 dcnt = dst->nb_bytecount - doff;
2759 doff -= dst->nb_bytecount;
2777 bcopy(sptr, dptr, len);
2790 dcnt = dst->nb_bytecount;
2799 scnt = src->nb_bytecount;
2807 __stdcall static void
2808 ndis_pkt_to_pkt_safe(dpkt, doff, reqlen, spkt, soff, cpylen, prio)
2817 ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen);
2821 __stdcall static ndis_status
2822 ndis_register_dev(handle, devname, symname, majorfuncs, devobj, devhandle)
2824 ndis_unicode_string *devname;
2825 ndis_unicode_string *symname;
2826 driver_dispatch *majorfuncs[];
2828 ndis_handle *devhandle;
2830 ndis_miniport_block *block;
2832 block = (ndis_miniport_block *)handle;
2833 *devobj = &block->nmb_devobj;
2834 *devhandle = handle;
2836 return(NDIS_STATUS_SUCCESS);
2839 __stdcall static ndis_status
2840 ndis_deregister_dev(handle)
2843 return(NDIS_STATUS_SUCCESS);
2846 __stdcall static ndis_status
2847 ndis_query_name(name, handle)
2848 ndis_unicode_string *name;
2851 ndis_miniport_block *block;
2853 block = (ndis_miniport_block *)handle;
2854 ndis_ascii_to_unicode(__DECONST(char *,
2855 device_get_nameunit(block->nmb_dev)), &name->nus_buf);
2856 name->nus_len = strlen(device_get_nameunit(block->nmb_dev)) * 2;
2858 return(NDIS_STATUS_SUCCESS);
2861 __stdcall static void
2862 ndis_register_unload(handle, func)
2869 __stdcall static void
2872 printf ("NDIS dummy called...\n");
2876 image_patch_table ndis_functbl[] = {
2877 { "NdisCopyFromPacketToPacket", (FUNC)ndis_pkt_to_pkt },
2878 { "NdisCopyFromPacketToPacketSafe", (FUNC)ndis_pkt_to_pkt_safe },
2879 { "NdisScheduleWorkItem", (FUNC)ndis_sched_workitem },
2880 { "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone },
2881 { "NdisMIndicateStatus", (FUNC)ndis_ind_status },
2882 { "NdisSystemProcessorCount", (FUNC)ndis_cpu_cnt },
2883 { "NdisUnchainBufferAtBack", (FUNC)ndis_unchain_tailbuf, },
2884 { "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf },
2885 { "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe },
2886 { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2887 { "NdisMGetDeviceProperty", (FUNC)ndis_get_devprop },
2888 { "NdisInitAnsiString", (FUNC)ndis_init_ansi_string },
2889 { "NdisInitUnicodeString", (FUNC)ndis_init_unicode_string },
2890 { "NdisWriteConfiguration", (FUNC)ndis_write_cfg },
2891 { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2892 { "NdisTerminateWrapper", (FUNC)ndis_termwrap },
2893 { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2894 { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2895 { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport },
2896 { "NdisInitializeString", (FUNC)ndis_init_string },
2897 { "NdisFreeString", (FUNC)ndis_free_string },
2898 { "NdisGetCurrentSystemTime", (FUNC)ndis_time },
2899 { "NdisGetSystemUpTime", (FUNC)ndis_uptime },
2900 { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2901 { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2902 { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2903 { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2904 { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2905 { "NdisInitializeWrapper", (FUNC)ndis_initwrap },
2906 { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport },
2907 { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag },
2908 { "NdisAllocateMemory", (FUNC)ndis_malloc },
2909 { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex },
2910 { "NdisCloseConfiguration", (FUNC)ndis_close_cfg },
2911 { "NdisReadConfiguration", (FUNC)ndis_read_cfg },
2912 { "NdisOpenConfiguration", (FUNC)ndis_open_cfg },
2913 { "NdisAcquireSpinLock", (FUNC)ndis_lock },
2914 { "NdisReleaseSpinLock", (FUNC)ndis_unlock },
2915 { "NdisDprAcquireSpinLock", (FUNC)ndis_lock_dpr },
2916 { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock_dpr },
2917 { "NdisAllocateSpinLock", (FUNC)ndis_create_lock },
2918 { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock },
2919 { "NdisFreeMemory", (FUNC)ndis_free },
2920 { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci },
2921 { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2922 { "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci },
2923 { "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci },
2924 { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog },
2925 { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2926 { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2927 { "NdisMInitializeTimer", (FUNC)ndis_create_timer },
2928 { "NdisInitializeTimer", (FUNC)ndis_init_timer },
2929 { "NdisSetTimer", (FUNC)ndis_set_timer },
2930 { "NdisMCancelTimer", (FUNC)ndis_cancel_timer },
2931 { "NdisCancelTimer", (FUNC)ndis_cancel_timer },
2932 { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer },
2933 { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources },
2934 { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport },
2935 { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport },
2936 { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr },
2937 { "NdisQueryMapRegisterCount", (FUNC)ndis_mapreg_cnt },
2938 { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg },
2939 { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg },
2940 { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem },
2941 { "NdisMMapIoSpace", (FUNC)ndis_map_iospace },
2942 { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace },
2943 { "NdisGetCacheFillSize", (FUNC)ndis_cachefill },
2944 { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align },
2945 { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2946 { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool },
2947 { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool },
2948 { "NdisAllocatePacket", (FUNC)ndis_alloc_packet },
2949 { "NdisFreePacket", (FUNC)ndis_release_packet },
2950 { "NdisFreePacketPool", (FUNC)ndis_free_packetpool },
2951 { "NdisDprAllocatePacket", (FUNC)ndis_alloc_packet },
2952 { "NdisDprFreePacket", (FUNC)ndis_release_packet },
2953 { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool },
2954 { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf },
2955 { "NdisQueryBuffer", (FUNC)ndis_query_buf },
2956 { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe },
2957 { "NdisBufferVirtualAddress", (FUNC)ndis_buf_vaddr },
2958 { "NdisBufferVirtualAddressSafe", (FUNC)ndis_buf_vaddr_safe },
2959 { "NdisBufferLength", (FUNC)ndis_buflen },
2960 { "NdisFreeBuffer", (FUNC)ndis_release_buf },
2961 { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool },
2962 { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc },
2963 { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec },
2964 { "NdisInitializeEvent", (FUNC)ndis_init_event },
2965 { "NdisSetEvent", (FUNC)ndis_set_event },
2966 { "NdisResetEvent", (FUNC)ndis_reset_event },
2967 { "NdisWaitEvent", (FUNC)ndis_wait_event },
2968 { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2969 { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc },
2970 { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem },
2971 { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr },
2972 { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr },
2973 { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2974 { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
2975 { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages },
2976 { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset },
2977 { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen },
2978 { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use },
2979 { "NdisMSleep", (FUNC)ndis_sleep },
2980 { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf },
2981 { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
2982 { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
2983 { "NdisOpenFile", (FUNC)ndis_open_file },
2984 { "NdisMapFile", (FUNC)ndis_map_file },
2985 { "NdisUnmapFile", (FUNC)ndis_unmap_file },
2986 { "NdisCloseFile", (FUNC)ndis_close_file },
2987 { "NdisMRegisterDevice", (FUNC)ndis_register_dev },
2988 { "NdisMDeregisterDevice", (FUNC)ndis_deregister_dev },
2989 { "NdisMQueryAdapterInstanceName", (FUNC)ndis_query_name },
2990 { "NdisMRegisterUnloadHandler", (FUNC)ndis_register_unload },
2993 * This last entry is a catch-all for any function we haven't
2994 * implemented yet. The PE import list patching routine will
2995 * use it for any function that doesn't have an explicit match
2999 { NULL, (FUNC)dummy },