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.3 2004/07/29 21:35:57 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/namei.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 if (*unicode == NULL)
329 for (i = 0; i < strlen(ascii); i++) {
330 *ustr = (uint16_t)ascii[i];
338 ndis_unicode_to_ascii(unicode, ulen, ascii)
347 *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_WAITOK|M_ZERO);
351 for (i = 0; i < ulen / 2; i++) {
352 *astr = (uint8_t)unicode[i];
359 __stdcall static void
360 ndis_initwrap(wrapper, drv_obj, path, unused)
361 ndis_handle *wrapper;
362 device_object *drv_obj;
366 ndis_miniport_block *block;
368 block = drv_obj->do_rsvd;
374 __stdcall static void
375 ndis_termwrap(handle, syspec)
382 __stdcall static ndis_status
383 ndis_register_miniport(handle, characteristics, len)
385 ndis_miniport_characteristics *characteristics;
388 ndis_miniport_block *block;
389 struct ndis_softc *sc;
391 block = (ndis_miniport_block *)handle;
392 sc = (struct ndis_softc *)block->nmb_ifp;
393 bcopy((char *)characteristics, (char *)&sc->ndis_chars,
394 sizeof(ndis_miniport_characteristics));
395 if (sc->ndis_chars.nmc_version_major < 5 ||
396 sc->ndis_chars.nmc_version_minor < 1) {
397 sc->ndis_chars.nmc_shutdown_handler = NULL;
398 sc->ndis_chars.nmc_canceltxpkts_handler = NULL;
399 sc->ndis_chars.nmc_pnpevent_handler = NULL;
402 return(NDIS_STATUS_SUCCESS);
405 __stdcall static ndis_status
406 ndis_malloc_withtag(vaddr, len, tag)
413 mem = malloc(len, M_DEVBUF, M_NOWAIT);
415 return(NDIS_STATUS_RESOURCES);
418 return(NDIS_STATUS_SUCCESS);
421 __stdcall static ndis_status
422 ndis_malloc(vaddr, len, flags, highaddr)
426 ndis_physaddr highaddr;
430 mem = malloc(len, M_DEVBUF, M_NOWAIT);
432 return(NDIS_STATUS_RESOURCES);
435 return(NDIS_STATUS_SUCCESS);
438 __stdcall static void
439 ndis_free(vaddr, len, flags)
446 free(vaddr, M_DEVBUF);
451 __stdcall static ndis_status
452 ndis_setattr_ex(adapter_handle, adapter_ctx, hangsecs,
454 ndis_handle adapter_handle;
455 ndis_handle adapter_ctx;
458 ndis_interface_type iftype;
460 ndis_miniport_block *block;
463 * Save the adapter context, we need it for calling
464 * the driver's internal functions.
466 block = (ndis_miniport_block *)adapter_handle;
467 block->nmb_miniportadapterctx = adapter_ctx;
468 block->nmb_checkforhangsecs = hangsecs;
469 block->nmb_flags = flags;
471 return(NDIS_STATUS_SUCCESS);
474 __stdcall static void
475 ndis_open_cfg(status, cfg, wrapctx)
481 *status = NDIS_STATUS_SUCCESS;
485 __stdcall static void
486 ndis_open_cfgbyname(status, cfg, subkey, subhandle)
489 ndis_unicode_string *subkey;
490 ndis_handle *subhandle;
493 *status = NDIS_STATUS_SUCCESS;
497 __stdcall static void
498 ndis_open_cfgbyidx(status, cfg, idx, subkey, subhandle)
502 ndis_unicode_string *subkey;
503 ndis_handle *subhandle;
505 *status = NDIS_STATUS_FAILURE;
510 ndis_encode_parm(block, oid, type, parm)
511 ndis_miniport_block *block;
512 struct sysctl_oid *oid;
514 ndis_config_parm **parm;
517 ndis_unicode_string *ustr;
520 unicode = (uint16_t *)&block->nmb_dummybuf;
523 case ndis_parm_string:
524 ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
525 (*parm)->ncp_type = ndis_parm_string;
526 ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
527 ustr->nus_len = strlen((char *)oid->oid_arg1) * 2;
528 ustr->nus_buf = unicode;
531 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
535 (*parm)->ncp_type = ndis_parm_int;
536 (*parm)->ncp_parmdata.ncp_intdata =
537 strtol((char *)oid->oid_arg1, NULL, base);
539 case ndis_parm_hexint:
540 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0)
544 (*parm)->ncp_type = ndis_parm_hexint;
545 (*parm)->ncp_parmdata.ncp_intdata =
546 strtoul((char *)oid->oid_arg1, NULL, base);
549 return(NDIS_STATUS_FAILURE);
553 return(NDIS_STATUS_SUCCESS);
557 ndis_strcasecmp(s1, s2)
564 * In the kernel, toupper() is a macro. Have to be careful
565 * not to use pointer arithmetic when passing it arguments.
571 if (toupper(a) != toupper(b))
577 return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
580 __stdcall static void
581 ndis_read_cfg(status, parm, cfg, key, type)
583 ndis_config_parm **parm;
585 ndis_unicode_string *key;
590 ndis_miniport_block *block;
591 struct ndis_softc *sc;
592 struct sysctl_oid *oidp;
593 struct sysctl_ctx_entry *e;
595 block = (ndis_miniport_block *)cfg;
596 sc = (struct ndis_softc *)block->nmb_ifp;
598 if (key->nus_len == 0 || key->nus_buf == NULL) {
599 *status = NDIS_STATUS_FAILURE;
603 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
605 *parm = &block->nmb_replyparm;
606 bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
607 unicode = (uint16_t *)&block->nmb_dummybuf;
610 * See if registry key is already in a list of known keys
611 * included with the driver.
613 #if __FreeBSD_version < 502113
614 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
616 TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
619 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
620 if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
621 free(keystr, M_DEVBUF);
622 *status = NDIS_STATUS_FAILURE;
625 *status = ndis_encode_parm(block, oidp, type, parm);
626 free(keystr, M_DEVBUF);
632 * If the key didn't match, add it to the list of dynamically
633 * created ones. Sometimes, drivers refer to registry keys
634 * that aren't documented in their .INF files. These keys
635 * are supposed to be created by some sort of utility or
636 * control panel snap-in that comes with the driver software.
637 * Sometimes it's useful to be able to manipulate these.
638 * If the driver requests the key in the form of a string,
639 * make its default value an empty string, otherwise default
643 if (type == ndis_parm_int || type == ndis_parm_hexint)
644 ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
645 "UNSET", CTLFLAG_RW);
647 ndis_add_sysctl(sc, keystr, "(dynamic string key)",
648 "UNSET", CTLFLAG_RW);
650 free(keystr, M_DEVBUF);
651 *status = NDIS_STATUS_FAILURE;
656 ndis_decode_parm(block, parm, val)
657 ndis_miniport_block *block;
658 ndis_config_parm *parm;
661 ndis_unicode_string *ustr;
664 switch(parm->ncp_type) {
665 case ndis_parm_string:
666 ustr = &parm->ncp_parmdata.ncp_stringdata;
667 ndis_unicode_to_ascii(ustr->nus_buf, ustr->nus_len, &astr);
668 bcopy(astr, val, 254);
669 free(astr, M_DEVBUF);
672 sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
674 case ndis_parm_hexint:
675 sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
678 return(NDIS_STATUS_FAILURE);
681 return(NDIS_STATUS_SUCCESS);
684 __stdcall static void
685 ndis_write_cfg(status, cfg, key, parm)
688 ndis_unicode_string *key;
689 ndis_config_parm *parm;
692 ndis_miniport_block *block;
693 struct ndis_softc *sc;
694 struct sysctl_oid *oidp;
695 struct sysctl_ctx_entry *e;
698 block = (ndis_miniport_block *)cfg;
699 sc = (struct ndis_softc *)block->nmb_ifp;
701 ndis_unicode_to_ascii(key->nus_buf, key->nus_len, &keystr);
703 /* Decode the parameter into a string. */
704 bzero(val, sizeof(val));
705 *status = ndis_decode_parm(block, parm, val);
706 if (*status != NDIS_STATUS_SUCCESS) {
707 free(keystr, M_DEVBUF);
711 /* See if the key already exists. */
713 #if __FreeBSD_version < 502113
714 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
716 TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
719 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
720 /* Found it, set the value. */
721 strcpy((char *)oidp->oid_arg1, val);
722 free(keystr, M_DEVBUF);
727 /* Not found, add a new key with the specified value. */
728 ndis_add_sysctl(sc, keystr, "(dynamically set key)",
731 free(keystr, M_DEVBUF);
732 *status = NDIS_STATUS_SUCCESS;
736 __stdcall static void
744 * Initialize a Windows spinlock.
746 __stdcall static void
747 ndis_create_lock(lock)
748 ndis_spin_lock *lock;
750 lock->nsl_spinlock = 0;
757 * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
758 * for this. One is that it's sort of superfluous: we don't have to do anything
759 * special to deallocate the spinlock. The other is that there are some buggy
760 * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
761 * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
764 __stdcall static void
765 ndis_destroy_lock(lock)
766 ndis_spin_lock *lock;
769 lock->nsl_spinlock = 0;
776 * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
779 __stdcall static void
781 ndis_spin_lock *lock;
783 lock->nsl_kirql = FASTCALL2(hal_lock,
784 &lock->nsl_spinlock, DISPATCH_LEVEL);
789 * Release a spinlock from IRQL == DISPATCH_LEVEL.
792 __stdcall static void
794 ndis_spin_lock *lock;
796 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
801 * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
803 __stdcall static void
805 ndis_spin_lock *lock;
807 FASTCALL1(ntoskrnl_lock_dpc, &lock->nsl_spinlock);
812 * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
814 __stdcall static void
815 ndis_unlock_dpr(lock)
816 ndis_spin_lock *lock;
818 FASTCALL1(ntoskrnl_unlock_dpc, &lock->nsl_spinlock);
822 __stdcall static uint32_t
823 ndis_read_pci(adapter, slot, offset, buf, len)
830 ndis_miniport_block *block;
834 block = (ndis_miniport_block *)adapter;
836 if (block == NULL || block->nmb_dev == NULL)
839 for (i = 0; i < len; i++)
840 dest[i] = pci_read_config(block->nmb_dev, i + offset, 1);
845 __stdcall static uint32_t
846 ndis_write_pci(adapter, slot, offset, buf, len)
853 ndis_miniport_block *block;
857 block = (ndis_miniport_block *)adapter;
860 if (block == NULL || block->nmb_dev == NULL)
863 for (i = 0; i < len; i++)
864 pci_write_config(block->nmb_dev, i + offset, dest[i], 1);
870 * The errorlog routine uses a variable argument list, so we
871 * have to declare it this way.
873 #define ERRMSGLEN 512
875 ndis_syslog(ndis_handle adapter, ndis_error_code code,
876 uint32_t numerrors, ...)
878 ndis_miniport_block *block;
881 char *str = NULL, *ustr = NULL;
883 char msgbuf[ERRMSGLEN];
886 block = (ndis_miniport_block *)adapter;
888 error = pe_get_message(block->nmb_img, code, &str, &i, &flags);
889 if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
891 ndis_unicode_to_ascii((uint16_t *)str,
892 ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
895 device_printf (block->nmb_dev, "NDIS ERROR: %x (%s)\n", code,
896 str == NULL ? "unknown error" : str);
897 device_printf (block->nmb_dev, "NDIS NUMERRORS: %x\n", numerrors);
899 __va_start(ap, numerrors);
900 for (i = 0; i < numerrors; i++)
901 device_printf (block->nmb_dev, "argptr: %p\n",
902 __va_arg(ap, void *));
909 ndis_map_cb(arg, segs, nseg, error)
911 bus_dma_segment_t *segs;
915 struct ndis_map_arg *ctx;
923 for (i = 0; i < nseg; i++) {
924 ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
925 ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
933 __stdcall static void
934 ndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
939 ndis_paddr_unit *addrarray;
942 ndis_miniport_block *block;
943 struct ndis_softc *sc;
944 struct ndis_map_arg nma;
951 block = (ndis_miniport_block *)adapter;
952 sc = (struct ndis_softc *)(block->nmb_ifp);
954 if (mapreg > sc->ndis_mmapcnt)
957 map = sc->ndis_mmaps[mapreg];
958 nma.nma_fraglist = addrarray;
960 error = bus_dmamap_load(sc->ndis_mtag, map,
961 MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
962 (void *)&nma, BUS_DMA_NOWAIT);
967 bus_dmamap_sync(sc->ndis_mtag, map,
968 writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
970 *arraysize = nma.nma_cnt;
975 __stdcall static void
976 ndis_vtophys_unload(adapter, buf, mapreg)
981 ndis_miniport_block *block;
982 struct ndis_softc *sc;
988 block = (ndis_miniport_block *)adapter;
989 sc = (struct ndis_softc *)(block->nmb_ifp);
991 if (mapreg > sc->ndis_mmapcnt)
994 map = sc->ndis_mmaps[mapreg];
996 bus_dmamap_sync(sc->ndis_mtag, map,
997 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
999 bus_dmamap_unload(sc->ndis_mtag, map);
1005 * This is an older pre-miniport timer init routine which doesn't
1006 * accept a miniport context handle. The function context (ctx)
1007 * is supposed to be a pointer to the adapter handle, which should
1008 * have been handed to us via NdisSetAttributesEx(). We use this
1009 * function context to track down the corresponding ndis_miniport_block
1010 * structure. It's vital that we track down the miniport block structure,
1011 * so if we can't do it, we panic. Note that we also play some games
1012 * here by treating ndis_timer and ndis_miniport_timer as the same
1016 __stdcall static void
1017 ndis_init_timer(timer, func, ctx)
1019 ndis_timer_function func;
1022 ntoskrnl_init_timer(&timer->nt_ktimer);
1023 ntoskrnl_init_dpc(&timer->nt_kdpc, func, ctx);
1028 __stdcall static void
1029 ndis_create_timer(timer, handle, func, ctx)
1030 ndis_miniport_timer *timer;
1032 ndis_timer_function func;
1035 /* Save the funcptr and context */
1037 timer->nmt_timerfunc = func;
1038 timer->nmt_timerctx = ctx;
1039 timer->nmt_block = handle;
1041 ntoskrnl_init_timer(&timer->nmt_ktimer);
1042 ntoskrnl_init_dpc(&timer->nmt_kdpc, func, ctx);
1048 * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
1049 * but the former is just a macro wrapper around the latter.
1051 __stdcall static void
1052 ndis_set_timer(timer, msecs)
1057 * KeSetTimer() wants the period in
1058 * hundred nanosecond intervals.
1060 ntoskrnl_set_timer(&timer->nt_ktimer,
1061 ((int64_t)msecs * -10000), &timer->nt_kdpc);
1066 __stdcall static void
1067 ndis_set_periodic_timer(timer, msecs)
1068 ndis_miniport_timer *timer;
1071 ntoskrnl_set_timer_ex(&timer->nmt_ktimer,
1072 ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc);
1078 * Technically, this is really NdisCancelTimer(), but we also
1079 * (ab)use it for NdisMCancelTimer(), since in our implementation
1080 * we don't need the extra info in the ndis_miniport_timer
1084 __stdcall static void
1085 ndis_cancel_timer(timer, cancelled)
1089 *cancelled = ntoskrnl_cancel_timer(&timer->nt_ktimer);
1094 __stdcall static void
1095 ndis_query_resources(status, adapter, list, buflen)
1096 ndis_status *status;
1097 ndis_handle adapter;
1098 ndis_resource_list *list;
1101 ndis_miniport_block *block;
1102 struct ndis_softc *sc;
1105 block = (ndis_miniport_block *)adapter;
1106 sc = (struct ndis_softc *)block->nmb_ifp;
1108 rsclen = sizeof(ndis_resource_list) +
1109 (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1110 if (*buflen < rsclen) {
1112 *status = NDIS_STATUS_INVALID_LENGTH;
1116 bcopy((char *)block->nmb_rlist, (char *)list, rsclen);
1117 *status = NDIS_STATUS_SUCCESS;
1121 __stdcall static ndis_status
1122 ndis_register_ioport(offset, adapter, port, numports)
1124 ndis_handle adapter;
1128 struct ndis_miniport_block *block;
1129 struct ndis_softc *sc;
1131 if (adapter == NULL)
1132 return(NDIS_STATUS_FAILURE);
1134 block = (ndis_miniport_block *)adapter;
1135 sc = (struct ndis_softc *)(block->nmb_ifp);
1137 if (sc->ndis_res_io == NULL)
1138 return(NDIS_STATUS_FAILURE);
1140 /* Don't let the device map more ports than we have. */
1141 if (rman_get_size(sc->ndis_res_io) < numports)
1142 return(NDIS_STATUS_INVALID_LENGTH);
1144 *offset = (void *)rman_get_start(sc->ndis_res_io);
1146 return(NDIS_STATUS_SUCCESS);
1149 __stdcall static void
1150 ndis_deregister_ioport(adapter, port, numports, offset)
1151 ndis_handle adapter;
1159 __stdcall static void
1160 ndis_read_netaddr(status, addr, addrlen, adapter)
1161 ndis_status *status;
1164 ndis_handle adapter;
1166 struct ndis_softc *sc;
1167 ndis_miniport_block *block;
1168 uint8_t empty[] = { 0, 0, 0, 0, 0, 0 };
1170 block = (ndis_miniport_block *)adapter;
1171 sc = (struct ndis_softc *)block->nmb_ifp;
1173 if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1174 *status = NDIS_STATUS_FAILURE;
1176 *addr = sc->arpcom.ac_enaddr;
1177 *addrlen = ETHER_ADDR_LEN;
1178 *status = NDIS_STATUS_SUCCESS;
1184 __stdcall static ndis_status
1185 ndis_mapreg_cnt(bustype, cnt)
1190 return(NDIS_STATUS_SUCCESS);
1193 __stdcall static ndis_status
1194 ndis_alloc_mapreg(adapter, dmachannel, dmasize, physmapneeded, maxmap)
1195 ndis_handle adapter;
1196 uint32_t dmachannel;
1198 uint32_t physmapneeded;
1201 struct ndis_softc *sc;
1202 ndis_miniport_block *block;
1203 int error, i, nseg = NDIS_MAXSEG;
1205 block = (ndis_miniport_block *)adapter;
1206 sc = (struct ndis_softc *)block->nmb_ifp;
1208 sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1209 M_DEVBUF, M_NOWAIT|M_ZERO);
1211 if (sc->ndis_mmaps == NULL)
1212 return(NDIS_STATUS_RESOURCES);
1214 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1215 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1216 NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1220 free(sc->ndis_mmaps, M_DEVBUF);
1221 return(NDIS_STATUS_RESOURCES);
1224 for (i = 0; i < physmapneeded; i++)
1225 bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1227 sc->ndis_mmapcnt = physmapneeded;
1229 return(NDIS_STATUS_SUCCESS);
1232 __stdcall static void
1233 ndis_free_mapreg(adapter)
1234 ndis_handle adapter;
1236 struct ndis_softc *sc;
1237 ndis_miniport_block *block;
1240 block = (ndis_miniport_block *)adapter;
1241 sc = (struct ndis_softc *)block->nmb_ifp;
1243 for (i = 0; i < sc->ndis_mmapcnt; i++)
1244 bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1246 free(sc->ndis_mmaps, M_DEVBUF);
1248 bus_dma_tag_destroy(sc->ndis_mtag);
1254 ndis_mapshared_cb(arg, segs, nseg, error)
1256 bus_dma_segment_t *segs;
1262 if (error || nseg > 1)
1267 p->np_quad = segs[0].ds_addr;
1273 * This maps to bus_dmamem_alloc().
1275 __stdcall static void
1276 ndis_alloc_sharedmem(adapter, len, cached, vaddr, paddr)
1277 ndis_handle adapter;
1281 ndis_physaddr *paddr;
1283 ndis_miniport_block *block;
1284 struct ndis_softc *sc;
1285 struct ndis_shmem *sh;
1288 if (adapter == NULL)
1291 block = (ndis_miniport_block *)adapter;
1292 sc = (struct ndis_softc *)(block->nmb_ifp);
1294 sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1299 * When performing shared memory allocations, create a tag
1300 * with a lowaddr limit that restricts physical memory mappings
1301 * so that they all fall within the first 1GB of memory.
1302 * At least one device/driver combination (Linksys Instant
1303 * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
1304 * problems with performing DMA operations with physical
1305 * that lie above the 1GB mark. I don't know if this is a
1306 * hardware limitation or if the addresses are being truncated
1307 * within the driver, but this seems to be the only way to
1308 * make these cards work reliably in systems with more than
1309 * 1GB of physical memory.
1312 error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1313 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL,
1314 NULL, len, 1, len, BUS_DMA_ALLOCNOW,
1322 error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1323 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1326 bus_dma_tag_destroy(sh->ndis_stag);
1331 error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1332 len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1335 bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1336 bus_dma_tag_destroy(sh->ndis_stag);
1341 sh->ndis_saddr = *vaddr;
1342 sh->ndis_next = sc->ndis_shlist;
1343 sc->ndis_shlist = sh;
1348 struct ndis_allocwork {
1349 ndis_handle na_adapter;
1356 ndis_asyncmem_complete(arg)
1359 ndis_miniport_block *block;
1360 struct ndis_softc *sc;
1361 struct ndis_allocwork *w;
1363 ndis_physaddr paddr;
1364 ndis_allocdone_handler donefunc;
1367 block = (ndis_miniport_block *)w->na_adapter;
1368 sc = (struct ndis_softc *)(block->nmb_ifp);
1373 donefunc = sc->ndis_chars.nmc_allocate_complete_func;
1374 ndis_alloc_sharedmem(w->na_adapter, w->na_len,
1375 w->na_cached, &vaddr, &paddr);
1376 donefunc(w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
1378 free(arg, M_DEVBUF);
1383 __stdcall static ndis_status
1384 ndis_alloc_sharedmem_async(adapter, len, cached, ctx)
1385 ndis_handle adapter;
1390 struct ndis_allocwork *w;
1392 if (adapter == NULL)
1393 return(NDIS_STATUS_FAILURE);
1395 w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT);
1398 return(NDIS_STATUS_FAILURE);
1400 w->na_adapter = adapter;
1401 w->na_cached = cached;
1406 * Pawn this work off on the SWI thread instead of the
1407 * taskqueue thread, because sometimes drivers will queue
1408 * up work items on the taskqueue thread that will block,
1409 * which would prevent the memory allocation from completing
1412 ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI);
1414 return(NDIS_STATUS_PENDING);
1417 __stdcall static void
1418 ndis_free_sharedmem(adapter, len, cached, vaddr, paddr)
1419 ndis_handle adapter;
1423 ndis_physaddr paddr;
1425 ndis_miniport_block *block;
1426 struct ndis_softc *sc;
1427 struct ndis_shmem *sh, *prev;
1429 if (vaddr == NULL || adapter == NULL)
1432 block = (ndis_miniport_block *)adapter;
1433 sc = (struct ndis_softc *)(block->nmb_ifp);
1434 sh = prev = sc->ndis_shlist;
1437 if (sh->ndis_saddr == vaddr)
1443 bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1444 bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1445 bus_dma_tag_destroy(sh->ndis_stag);
1447 if (sh == sc->ndis_shlist)
1448 sc->ndis_shlist = sh->ndis_next;
1450 prev->ndis_next = sh->ndis_next;
1457 __stdcall static ndis_status
1458 ndis_map_iospace(vaddr, adapter, paddr, len)
1460 ndis_handle adapter;
1461 ndis_physaddr paddr;
1464 ndis_miniport_block *block;
1465 struct ndis_softc *sc;
1467 if (adapter == NULL)
1468 return(NDIS_STATUS_FAILURE);
1470 block = (ndis_miniport_block *)adapter;
1471 sc = (struct ndis_softc *)(block->nmb_ifp);
1473 if (sc->ndis_res_mem != NULL &&
1474 paddr.np_quad == rman_get_start(sc->ndis_res_mem))
1475 *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
1476 else if (sc->ndis_res_altmem != NULL &&
1477 paddr.np_quad == rman_get_start(sc->ndis_res_altmem))
1478 *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem);
1479 else if (sc->ndis_res_am != NULL &&
1480 paddr.np_quad == rman_get_start(sc->ndis_res_am))
1481 *vaddr = (void *)rman_get_virtual(sc->ndis_res_am);
1483 return(NDIS_STATUS_FAILURE);
1485 return(NDIS_STATUS_SUCCESS);
1488 __stdcall static void
1489 ndis_unmap_iospace(adapter, vaddr, len)
1490 ndis_handle adapter;
1497 __stdcall static uint32_t
1498 ndis_cachefill(void)
1503 __stdcall static uint32_t
1504 ndis_dma_align(handle)
1511 * NDIS has two methods for dealing with NICs that support DMA.
1512 * One is to just pass packets to the driver and let it call
1513 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1514 * all by itself, and the other is to let the NDIS library handle the
1515 * buffer mapping internally, and hand the driver an already populated
1516 * scatter/gather fragment list. If the driver calls
1517 * NdisMInitializeScatterGatherDma(), it wants to use the latter
1521 __stdcall static ndis_status
1522 ndis_init_sc_dma(adapter, is64, maxphysmap)
1523 ndis_handle adapter;
1525 uint32_t maxphysmap;
1527 struct ndis_softc *sc;
1528 ndis_miniport_block *block;
1531 if (adapter == NULL)
1532 return(NDIS_STATUS_FAILURE);
1533 block = (ndis_miniport_block *)adapter;
1534 sc = (struct ndis_softc *)block->nmb_ifp;
1536 /* Don't do this twice. */
1537 if (sc->ndis_sc == 1)
1538 return(NDIS_STATUS_SUCCESS);
1540 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1541 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
1542 MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
1547 return(NDIS_STATUS_SUCCESS);
1550 __stdcall static void
1551 ndis_alloc_packetpool(status, pool, descnum, protrsvdlen)
1552 ndis_status *status;
1555 uint32_t protrsvdlen;
1560 *pool = malloc(sizeof(ndis_packet) *
1561 ((descnum + NDIS_POOL_EXTRA) + 1),
1562 M_DEVBUF, M_NOWAIT|M_ZERO);
1565 *status = NDIS_STATUS_RESOURCES;
1569 cur = (ndis_packet *)*pool;
1570 cur->np_private.npp_flags = 0x1; /* mark the head of the list */
1571 cur->np_private.npp_totlen = 0; /* init deletetion flag */
1572 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1573 cur->np_private.npp_head = (ndis_handle)(cur + 1);
1577 *status = NDIS_STATUS_SUCCESS;
1581 __stdcall static void
1582 ndis_ex_alloc_packetpool(status, pool, descnum, oflowdescnum, protrsvdlen)
1583 ndis_status *status;
1586 uint32_t oflowdescnum;
1587 uint32_t protrsvdlen;
1589 return(ndis_alloc_packetpool(status, pool,
1590 descnum + oflowdescnum, protrsvdlen));
1593 __stdcall static uint32_t
1594 ndis_packetpool_use(pool)
1599 head = (ndis_packet *)pool;
1601 return(head->np_private.npp_count);
1604 __stdcall static void
1605 ndis_free_packetpool(pool)
1612 /* Mark this pool as 'going away.' */
1614 head->np_private.npp_totlen = 1;
1616 /* If there are no buffers loaned out, destroy the pool. */
1618 if (head->np_private.npp_count == 0)
1619 free(pool, M_DEVBUF);
1621 printf("NDIS: buggy driver deleting active packet pool!\n");
1626 __stdcall static void
1627 ndis_alloc_packet(status, packet, pool)
1628 ndis_status *status;
1629 ndis_packet **packet;
1632 ndis_packet *head, *pkt;
1634 head = (ndis_packet *)pool;
1636 if (head->np_private.npp_flags != 0x1) {
1637 *status = NDIS_STATUS_FAILURE;
1642 * If this pool is marked as 'going away' don't allocate any
1643 * more packets out of it.
1646 if (head->np_private.npp_totlen) {
1647 *status = NDIS_STATUS_FAILURE;
1651 pkt = (ndis_packet *)head->np_private.npp_head;
1654 *status = NDIS_STATUS_RESOURCES;
1658 head->np_private.npp_head = pkt->np_private.npp_head;
1660 pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
1661 /* Save pointer to the pool. */
1662 pkt->np_private.npp_pool = head;
1664 /* Set the oob offset pointer. Lots of things expect this. */
1665 pkt->np_private.npp_packetooboffset =
1666 offsetof(ndis_packet, np_oob);
1669 * We must initialize the packet flags correctly in order
1670 * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
1671 * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly.
1673 pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
1677 head->np_private.npp_count++;
1678 *status = NDIS_STATUS_SUCCESS;
1682 __stdcall static void
1683 ndis_release_packet(packet)
1684 ndis_packet *packet;
1688 if (packet == NULL || packet->np_private.npp_pool == NULL)
1691 head = packet->np_private.npp_pool;
1692 if (head->np_private.npp_flags != 0x1)
1695 packet->np_private.npp_head = head->np_private.npp_head;
1696 head->np_private.npp_head = (ndis_buffer *)packet;
1697 head->np_private.npp_count--;
1700 * If the pool has been marked for deletion and there are
1701 * no more packets outstanding, nuke the pool.
1704 if (head->np_private.npp_totlen && head->np_private.npp_count == 0)
1705 free(head, M_DEVBUF);
1710 __stdcall static void
1711 ndis_unchain_headbuf(packet, buf)
1712 ndis_packet *packet;
1715 ndis_packet_private *priv;
1717 if (packet == NULL || buf == NULL)
1720 priv = &packet->np_private;
1722 priv->npp_validcounts = FALSE;
1724 if (priv->npp_head == priv->npp_tail) {
1725 *buf = priv->npp_head;
1726 priv->npp_head = priv->npp_tail = NULL;
1728 *buf = priv->npp_head;
1729 priv->npp_head = (*buf)->nb_next;
1735 __stdcall static void
1736 ndis_unchain_tailbuf(packet, buf)
1737 ndis_packet *packet;
1740 ndis_packet_private *priv;
1743 if (packet == NULL || buf == NULL)
1746 priv = &packet->np_private;
1748 priv->npp_validcounts = FALSE;
1750 if (priv->npp_head == priv->npp_tail) {
1751 *buf = priv->npp_head;
1752 priv->npp_head = priv->npp_tail = NULL;
1754 *buf = priv->npp_tail;
1755 tmp = priv->npp_head;
1756 while (tmp->nb_next != priv->npp_tail)
1758 priv->npp_tail = tmp;
1759 tmp->nb_next = NULL;
1766 * The NDIS "buffer" manipulation functions are somewhat misnamed.
1767 * They don't really allocate buffers: they allocate buffer mappings.
1768 * The idea is you reserve a chunk of DMA-able memory using
1769 * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1770 * to obtain the virtual address of the DMA-able region.
1771 * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1774 __stdcall static void
1775 ndis_alloc_bufpool(status, pool, descnum)
1776 ndis_status *status;
1783 *pool = malloc(sizeof(ndis_buffer) *
1784 ((descnum + NDIS_POOL_EXTRA) + 1),
1785 M_DEVBUF, M_NOWAIT|M_ZERO);
1788 *status = NDIS_STATUS_RESOURCES;
1792 cur = (ndis_buffer *)*pool;
1793 cur->nb_flags = 0x1; /* mark the head of the list */
1794 cur->nb_bytecount = 0; /* init usage count */
1795 cur->nb_byteoffset = 0; /* init deletetion flag */
1796 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
1797 cur->nb_next = cur + 1;
1801 *status = NDIS_STATUS_SUCCESS;
1805 __stdcall static void
1806 ndis_free_bufpool(pool)
1813 /* Mark this pool as 'going away.' */
1815 head->nb_byteoffset = 1;
1817 /* If there are no buffers loaned out, destroy the pool. */
1818 if (head->nb_bytecount == 0)
1819 free(pool, M_DEVBUF);
1821 printf("NDIS: buggy driver deleting active buffer pool!\n");
1827 * This maps to a bus_dmamap_create() and bus_dmamap_load().
1829 __stdcall static void
1830 ndis_alloc_buf(status, buffer, pool, vaddr, len)
1831 ndis_status *status;
1832 ndis_buffer **buffer;
1837 ndis_buffer *head, *buf;
1839 head = (ndis_buffer *)pool;
1840 if (head->nb_flags != 0x1) {
1841 *status = NDIS_STATUS_FAILURE;
1846 * If this pool is marked as 'going away' don't allocate any
1847 * more buffers out of it.
1850 if (head->nb_byteoffset) {
1851 *status = NDIS_STATUS_FAILURE;
1855 buf = head->nb_next;
1858 *status = NDIS_STATUS_RESOURCES;
1862 head->nb_next = buf->nb_next;
1864 /* Save pointer to the pool. */
1865 buf->nb_process = head;
1867 MDL_INIT(buf, vaddr, len);
1871 /* Increment count of busy buffers. */
1873 head->nb_bytecount++;
1875 *status = NDIS_STATUS_SUCCESS;
1879 __stdcall static void
1880 ndis_release_buf(buf)
1885 if (buf == NULL || buf->nb_process == NULL)
1888 head = buf->nb_process;
1890 if (head->nb_flags != 0x1)
1893 buf->nb_next = head->nb_next;
1894 head->nb_next = buf;
1896 /* Decrement count of busy buffers. */
1898 head->nb_bytecount--;
1901 * If the pool has been marked for deletion and there are
1902 * no more buffers outstanding, nuke the pool.
1905 if (head->nb_byteoffset && head->nb_bytecount == 0)
1906 free(head, M_DEVBUF);
1913 __stdcall static uint32_t
1917 return(buf->nb_bytecount);
1921 * Get the virtual address and length of a buffer.
1922 * Note: the vaddr argument is optional.
1925 __stdcall static void
1926 ndis_query_buf(buf, vaddr, len)
1932 *vaddr = MDL_VA(buf);
1933 *len = buf->nb_bytecount;
1938 /* Same as above -- we don't care about the priority. */
1940 __stdcall static void
1941 ndis_query_buf_safe(buf, vaddr, len, prio)
1948 *vaddr = MDL_VA(buf);
1949 *len = buf->nb_bytecount;
1954 /* Damnit Microsoft!! How many ways can you do the same thing?! */
1956 __stdcall static void *
1960 return(MDL_VA(buf));
1963 __stdcall static void *
1964 ndis_buf_vaddr_safe(buf, prio)
1968 return(MDL_VA(buf));
1971 __stdcall static void
1972 ndis_adjust_buflen(buf, len)
1976 buf->nb_bytecount = len;
1981 __stdcall static uint32_t
1982 ndis_interlock_inc(addend)
1985 atomic_add_long((u_long *)addend, 1);
1989 __stdcall static uint32_t
1990 ndis_interlock_dec(addend)
1993 atomic_subtract_long((u_long *)addend, 1);
1997 __stdcall static void
1998 ndis_init_event(event)
2002 * NDIS events are always notification
2003 * events, and should be initialized to the
2004 * not signaled state.
2007 ntoskrnl_init_event(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE);
2011 __stdcall static void
2012 ndis_set_event(event)
2015 ntoskrnl_set_event(&event->ne_event, 0, 0);
2019 __stdcall static void
2020 ndis_reset_event(event)
2023 ntoskrnl_reset_event(&event->ne_event);
2027 __stdcall static uint8_t
2028 ndis_wait_event(event, msecs)
2035 duetime = ((int64_t)msecs * -10000);
2037 rval = ntoskrnl_waitforobj((nt_dispatch_header *)event,
2038 0, 0, TRUE, msecs ? &duetime : NULL);
2040 if (rval == STATUS_TIMEOUT)
2046 __stdcall static ndis_status
2047 ndis_unicode2ansi(dstr, sstr)
2048 ndis_ansi_string *dstr;
2049 ndis_unicode_string *sstr;
2051 if (dstr == NULL || sstr == NULL)
2052 return(NDIS_STATUS_FAILURE);
2053 if (ndis_unicode_to_ascii(sstr->nus_buf,
2054 sstr->nus_len, &dstr->nas_buf))
2055 return(NDIS_STATUS_FAILURE);
2056 dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
2057 return (NDIS_STATUS_SUCCESS);
2060 __stdcall static ndis_status
2061 ndis_ansi2unicode(dstr, sstr)
2062 ndis_unicode_string *dstr;
2063 ndis_ansi_string *sstr;
2066 if (dstr == NULL || sstr == NULL)
2067 return(NDIS_STATUS_FAILURE);
2068 str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
2070 return(NDIS_STATUS_FAILURE);
2071 strncpy(str, sstr->nas_buf, sstr->nas_len);
2072 *(str + sstr->nas_len) = '\0';
2073 if (ndis_ascii_to_unicode(str, &dstr->nus_buf)) {
2074 free(str, M_DEVBUF);
2075 return(NDIS_STATUS_FAILURE);
2077 dstr->nus_len = dstr->nus_maxlen = sstr->nas_len * 2;
2078 free(str, M_DEVBUF);
2079 return (NDIS_STATUS_SUCCESS);
2082 __stdcall static ndis_status
2083 ndis_assign_pcirsrc(adapter, slot, list)
2084 ndis_handle adapter;
2086 ndis_resource_list **list;
2088 ndis_miniport_block *block;
2090 if (adapter == NULL || list == NULL)
2091 return (NDIS_STATUS_FAILURE);
2093 block = (ndis_miniport_block *)adapter;
2094 *list = block->nmb_rlist;
2096 return (NDIS_STATUS_SUCCESS);
2099 __stdcall static ndis_status
2100 ndis_register_intr(intr, adapter, ivec, ilevel, reqisr, shared, imode)
2101 ndis_miniport_interrupt *intr;
2102 ndis_handle adapter;
2107 ndis_interrupt_mode imode;
2109 ndis_miniport_block *block;
2113 intr->ni_block = adapter;
2114 intr->ni_isrreq = reqisr;
2115 intr->ni_shared = shared;
2116 block->nmb_interrupt = intr;
2117 return(NDIS_STATUS_SUCCESS);
2120 __stdcall static void
2121 ndis_deregister_intr(intr)
2122 ndis_miniport_interrupt *intr;
2127 __stdcall static void
2128 ndis_register_shutdown(adapter, shutdownctx, shutdownfunc)
2129 ndis_handle adapter;
2131 ndis_shutdown_handler shutdownfunc;
2133 ndis_miniport_block *block;
2134 ndis_miniport_characteristics *chars;
2135 struct ndis_softc *sc;
2137 if (adapter == NULL)
2140 block = (ndis_miniport_block *)adapter;
2141 sc = (struct ndis_softc *)block->nmb_ifp;
2142 chars = &sc->ndis_chars;
2144 chars->nmc_shutdown_handler = shutdownfunc;
2145 chars->nmc_rsvd0 = shutdownctx;
2150 __stdcall static void
2151 ndis_deregister_shutdown(adapter)
2152 ndis_handle adapter;
2154 ndis_miniport_block *block;
2155 ndis_miniport_characteristics *chars;
2156 struct ndis_softc *sc;
2158 if (adapter == NULL)
2161 block = (ndis_miniport_block *)adapter;
2162 sc = (struct ndis_softc *)block->nmb_ifp;
2163 chars = &sc->ndis_chars;
2165 chars->nmc_shutdown_handler = NULL;
2166 chars->nmc_rsvd0 = NULL;
2171 __stdcall static uint32_t
2177 if (buf->nb_bytecount == 0)
2179 return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
2182 __stdcall static void
2183 ndis_buf_physpages(buf, pages)
2190 *pages = ndis_numpages(buf);
2194 __stdcall static void
2195 ndis_query_bufoffset(buf, off, len)
2203 *off = buf->nb_byteoffset;
2204 *len = buf->nb_bytecount;
2209 __stdcall static void
2218 ndis_thsuspend(curthread, 1 + usecs * hz / 1000000);
2223 __stdcall static uint32_t
2224 ndis_read_pccard_amem(handle, offset, buf, len)
2230 struct ndis_softc *sc;
2231 ndis_miniport_block *block;
2232 bus_space_handle_t bh;
2240 block = (ndis_miniport_block *)handle;
2241 sc = (struct ndis_softc *)block->nmb_ifp;
2244 bh = rman_get_bushandle(sc->ndis_res_am);
2245 bt = rman_get_bustag(sc->ndis_res_am);
2247 for (i = 0; i < len; i++)
2248 dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2);
2253 __stdcall static uint32_t
2254 ndis_write_pccard_amem(handle, offset, buf, len)
2260 struct ndis_softc *sc;
2261 ndis_miniport_block *block;
2262 bus_space_handle_t bh;
2270 block = (ndis_miniport_block *)handle;
2271 sc = (struct ndis_softc *)block->nmb_ifp;
2274 bh = rman_get_bushandle(sc->ndis_res_am);
2275 bt = rman_get_bustag(sc->ndis_res_am);
2277 for (i = 0; i < len; i++)
2278 bus_space_write_1(bt, bh, (offset + i) * 2, src[i]);
2283 __stdcall static list_entry *
2284 ndis_insert_head(head, entry, lock)
2287 ndis_spin_lock *lock;
2291 lock->nsl_kirql = FASTCALL2(hal_lock,
2292 &lock->nsl_spinlock, DISPATCH_LEVEL);
2293 flink = head->nle_flink;
2294 entry->nle_flink = flink;
2295 entry->nle_blink = head;
2296 flink->nle_blink = entry;
2297 head->nle_flink = entry;
2298 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2303 __stdcall static list_entry *
2304 ndis_remove_head(head, lock)
2306 ndis_spin_lock *lock;
2311 lock->nsl_kirql = FASTCALL2(hal_lock,
2312 &lock->nsl_spinlock, DISPATCH_LEVEL);
2313 entry = head->nle_flink;
2314 flink = entry->nle_flink;
2315 head->nle_flink = flink;
2316 flink->nle_blink = head;
2317 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2322 __stdcall static list_entry *
2323 ndis_insert_tail(head, entry, lock)
2326 ndis_spin_lock *lock;
2330 lock->nsl_kirql = FASTCALL2(hal_lock,
2331 &lock->nsl_spinlock, DISPATCH_LEVEL);
2332 blink = head->nle_blink;
2333 entry->nle_flink = head;
2334 entry->nle_blink = blink;
2335 blink->nle_flink = entry;
2336 head->nle_blink = entry;
2337 FASTCALL2(hal_unlock, &lock->nsl_spinlock, lock->nsl_kirql);
2342 __stdcall static uint8_t
2343 ndis_sync_with_intr(intr, syncfunc, syncctx)
2344 ndis_miniport_interrupt *intr;
2348 struct ndis_softc *sc;
2349 __stdcall uint8_t (*sync)(void *);
2353 if (syncfunc == NULL || syncctx == NULL)
2356 sc = (struct ndis_softc *)intr->ni_block->nmb_ifp;
2359 rval = sync(syncctx);
2360 NDIS_INTRUNLOCK(sc);
2366 * Return the number of 100 nanosecond intervals since
2367 * January 1, 1601. (?!?!)
2369 __stdcall static void
2376 *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2383 * Return the number of milliseconds since the system booted.
2385 __stdcall static void
2392 *tval = ts.tv_nsec / 1000000 + ts.tv_sec * 1000;
2397 __stdcall static void
2398 ndis_init_string(dst, src)
2399 ndis_unicode_string *dst;
2402 ndis_unicode_string *u;
2406 if (ndis_ascii_to_unicode(src, &u->nus_buf))
2408 u->nus_len = u->nus_maxlen = strlen(src) * 2;
2412 __stdcall static void
2413 ndis_free_string(str)
2414 ndis_unicode_string *str;
2418 if (str->nus_buf != NULL)
2419 free(str->nus_buf, M_DEVBUF);
2420 free(str, M_DEVBUF);
2424 __stdcall static ndis_status
2425 ndis_remove_miniport(adapter)
2426 ndis_handle *adapter;
2428 return(NDIS_STATUS_SUCCESS);
2431 __stdcall static void
2432 ndis_init_ansi_string(dst, src)
2433 ndis_ansi_string *dst;
2436 ndis_ansi_string *a;
2442 a->nas_len = a->nas_maxlen = 0;
2446 a->nas_len = a->nas_maxlen = strlen(src);
2452 __stdcall static void
2453 ndis_init_unicode_string(dst, src)
2454 ndis_unicode_string *dst;
2457 ndis_unicode_string *u;
2464 u->nus_len = u->nus_maxlen = 0;
2471 u->nus_len = u->nus_maxlen = i * 2;
2477 __stdcall static void ndis_get_devprop(adapter, phydevobj,
2478 funcdevobj, nextdevobj, resources, transresources)
2479 ndis_handle adapter;
2480 device_object **phydevobj;
2481 device_object **funcdevobj;
2482 device_object **nextdevobj;
2483 cm_resource_list *resources;
2484 cm_resource_list *transresources;
2486 ndis_miniport_block *block;
2488 block = (ndis_miniport_block *)adapter;
2490 if (phydevobj != NULL)
2491 *phydevobj = &block->nmb_devobj;
2492 if (funcdevobj != NULL)
2493 *funcdevobj = &block->nmb_devobj;
2498 __stdcall static void
2499 ndis_firstbuf(packet, buf, firstva, firstlen, totlen)
2500 ndis_packet *packet;
2508 tmp = packet->np_private.npp_head;
2512 *firstlen = *totlen = 0;
2514 *firstva = MDL_VA(tmp);
2515 *firstlen = *totlen = tmp->nb_bytecount;
2516 for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
2517 *totlen += tmp->nb_bytecount;
2523 __stdcall static void
2524 ndis_firstbuf_safe(packet, buf, firstva, firstlen, totlen, prio)
2525 ndis_packet *packet;
2532 ndis_firstbuf(packet, buf, firstva, firstlen, totlen);
2535 /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2536 __stdcall static void
2537 ndis_open_file(status, filehandle, filelength, filename, highestaddr)
2538 ndis_status *status;
2539 ndis_handle *filehandle;
2540 uint32_t *filelength;
2541 ndis_unicode_string *filename;
2542 ndis_physaddr highestaddr;
2544 char *afilename = NULL;
2545 struct thread *td = curthread;
2546 struct nameidata nd;
2549 struct vattr *vap = &vat;
2551 char path[MAXPATHLEN];
2553 ndis_unicode_to_ascii(filename->nus_buf,
2554 filename->nus_len, &afilename);
2556 sprintf(path, "%s/%s", ndis_filepath, afilename);
2557 free(afilename, M_DEVBUF);
2559 fh = malloc(sizeof(ndis_fh), M_TEMP, M_NOWAIT);
2561 *status = NDIS_STATUS_RESOURCES;
2565 NDINIT2(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, path,
2568 error = vn_open(&nd, FREAD, 0);
2570 *status = NDIS_STATUS_FILE_NOT_FOUND;
2572 printf("NDIS: open file %s failed: %d\n", path, error);
2576 NDFREE(&nd, NDF_ONLY_PNBUF);
2578 /* Get the file size. */
2579 VOP_GETATTR(nd.ni_vp, vap, td);
2580 VOP_UNLOCK(nd.ni_vp, NULL, 0, td);
2582 fh->nf_vp = nd.ni_vp;
2585 *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
2586 *status = NDIS_STATUS_SUCCESS;
2591 __stdcall static void
2592 ndis_map_file(status, mappedbuffer, filehandle)
2593 ndis_status *status;
2594 void **mappedbuffer;
2595 ndis_handle filehandle;
2598 struct thread *td = curthread;
2601 if (filehandle == NULL) {
2602 *status = NDIS_STATUS_FAILURE;
2606 fh = (ndis_fh *)filehandle;
2608 if (fh->nf_vp == NULL) {
2609 *status = NDIS_STATUS_FAILURE;
2613 if (fh->nf_map != NULL) {
2614 *status = NDIS_STATUS_ALREADY_MAPPED;
2618 fh->nf_map = malloc(fh->nf_maplen, M_DEVBUF, M_NOWAIT);
2620 if (fh->nf_map == NULL) {
2621 *status = NDIS_STATUS_RESOURCES;
2625 error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
2626 UIO_SYSSPACE, 0, proc0.p_ucred, &resid, td);
2629 *status = NDIS_STATUS_FAILURE;
2631 *status = NDIS_STATUS_SUCCESS;
2632 *mappedbuffer = fh->nf_map;
2638 __stdcall static void
2639 ndis_unmap_file(filehandle)
2640 ndis_handle filehandle;
2643 fh = (ndis_fh *)filehandle;
2645 if (fh->nf_map == NULL)
2647 free(fh->nf_map, M_DEVBUF);
2653 __stdcall static void
2654 ndis_close_file(filehandle)
2655 ndis_handle filehandle;
2657 struct thread *td = curthread;
2660 if (filehandle == NULL)
2663 fh = (ndis_fh *)filehandle;
2664 if (fh->nf_map != NULL) {
2665 free(fh->nf_map, M_DEVBUF);
2669 if (fh->nf_vp == NULL)
2672 vn_close(fh->nf_vp, FREAD, td);
2680 __stdcall static uint8_t
2686 typedef __stdcall void (*ndis_statusdone_handler)(ndis_handle);
2687 typedef __stdcall void (*ndis_status_handler)(ndis_handle, ndis_status,
2690 __stdcall static void
2691 ndis_ind_statusdone(adapter)
2692 ndis_handle adapter;
2694 ndis_miniport_block *block;
2695 ndis_statusdone_handler statusdonefunc;
2697 block = (ndis_miniport_block *)adapter;
2698 statusdonefunc = block->nmb_statusdone_func;
2700 statusdonefunc(adapter);
2704 __stdcall static void
2705 ndis_ind_status(adapter, status, sbuf, slen)
2706 ndis_handle adapter;
2711 ndis_miniport_block *block;
2712 ndis_status_handler statusfunc;
2714 block = (ndis_miniport_block *)adapter;
2715 statusfunc = block->nmb_status_func;
2717 statusfunc(adapter, status, sbuf, slen);
2725 ndis_work_item *work;
2729 workfunc = work->nwi_func;
2730 workfunc(work, work->nwi_ctx);
2734 __stdcall static ndis_status
2735 ndis_sched_workitem(work)
2736 ndis_work_item *work;
2738 ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
2739 return(NDIS_STATUS_SUCCESS);
2742 __stdcall static void
2743 ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen)
2751 ndis_buffer *src, *dst;
2753 int resid, copied, len, scnt, dcnt;
2757 src = spkt->np_private.npp_head;
2758 dst = dpkt->np_private.npp_head;
2762 scnt = src->nb_bytecount;
2763 dcnt = dst->nb_bytecount;
2766 if (src->nb_bytecount > soff) {
2768 scnt = src->nb_bytecount - soff;
2771 soff -= src->nb_bytecount;
2779 if (dst->nb_bytecount > doff) {
2781 dcnt = dst->nb_bytecount - doff;
2784 doff -= dst->nb_bytecount;
2802 bcopy(sptr, dptr, len);
2815 dcnt = dst->nb_bytecount;
2824 scnt = src->nb_bytecount;
2832 __stdcall static void
2833 ndis_pkt_to_pkt_safe(dpkt, doff, reqlen, spkt, soff, cpylen, prio)
2842 ndis_pkt_to_pkt(dpkt, doff, reqlen, spkt, soff, cpylen);
2846 __stdcall static ndis_status
2847 ndis_register_dev(handle, devname, symname, majorfuncs, devobj, devhandle)
2849 ndis_unicode_string *devname;
2850 ndis_unicode_string *symname;
2851 driver_dispatch *majorfuncs[];
2853 ndis_handle *devhandle;
2855 ndis_miniport_block *block;
2857 block = (ndis_miniport_block *)handle;
2858 *devobj = &block->nmb_devobj;
2859 *devhandle = handle;
2861 return(NDIS_STATUS_SUCCESS);
2864 __stdcall static ndis_status
2865 ndis_deregister_dev(handle)
2868 return(NDIS_STATUS_SUCCESS);
2871 __stdcall static ndis_status
2872 ndis_query_name(name, handle)
2873 ndis_unicode_string *name;
2876 ndis_miniport_block *block;
2878 block = (ndis_miniport_block *)handle;
2879 ndis_ascii_to_unicode(__DECONST(char *,
2880 device_get_nameunit(block->nmb_dev)), &name->nus_buf);
2881 name->nus_len = strlen(device_get_nameunit(block->nmb_dev)) * 2;
2883 return(NDIS_STATUS_SUCCESS);
2886 __stdcall static void
2887 ndis_register_unload(handle, func)
2894 __stdcall static void
2897 printf ("NDIS dummy called...\n");
2901 image_patch_table ndis_functbl[] = {
2902 { "NdisCopyFromPacketToPacket", (FUNC)ndis_pkt_to_pkt },
2903 { "NdisCopyFromPacketToPacketSafe", (FUNC)ndis_pkt_to_pkt_safe },
2904 { "NdisScheduleWorkItem", (FUNC)ndis_sched_workitem },
2905 { "NdisMIndicateStatusComplete", (FUNC)ndis_ind_statusdone },
2906 { "NdisMIndicateStatus", (FUNC)ndis_ind_status },
2907 { "NdisSystemProcessorCount", (FUNC)ndis_cpu_cnt },
2908 { "NdisUnchainBufferAtBack", (FUNC)ndis_unchain_tailbuf, },
2909 { "NdisGetFirstBufferFromPacket", (FUNC)ndis_firstbuf },
2910 { "NdisGetFirstBufferFromPacketSafe", (FUNC)ndis_firstbuf_safe },
2911 { "NdisGetBufferPhysicalArraySize", (FUNC)ndis_buf_physpages },
2912 { "NdisMGetDeviceProperty", (FUNC)ndis_get_devprop },
2913 { "NdisInitAnsiString", (FUNC)ndis_init_ansi_string },
2914 { "NdisInitUnicodeString", (FUNC)ndis_init_unicode_string },
2915 { "NdisWriteConfiguration", (FUNC)ndis_write_cfg },
2916 { "NdisAnsiStringToUnicodeString", (FUNC)ndis_ansi2unicode },
2917 { "NdisTerminateWrapper", (FUNC)ndis_termwrap },
2918 { "NdisOpenConfigurationKeyByName", (FUNC)ndis_open_cfgbyname },
2919 { "NdisOpenConfigurationKeyByIndex", (FUNC)ndis_open_cfgbyidx },
2920 { "NdisMRemoveMiniport", (FUNC)ndis_remove_miniport },
2921 { "NdisInitializeString", (FUNC)ndis_init_string },
2922 { "NdisFreeString", (FUNC)ndis_free_string },
2923 { "NdisGetCurrentSystemTime", (FUNC)ndis_time },
2924 { "NdisGetSystemUpTime", (FUNC)ndis_uptime },
2925 { "NdisMSynchronizeWithInterrupt", (FUNC)ndis_sync_with_intr },
2926 { "NdisMAllocateSharedMemoryAsync", (FUNC)ndis_alloc_sharedmem_async },
2927 { "NdisInterlockedInsertHeadList", (FUNC)ndis_insert_head },
2928 { "NdisInterlockedInsertTailList", (FUNC)ndis_insert_tail },
2929 { "NdisInterlockedRemoveHeadList", (FUNC)ndis_remove_head },
2930 { "NdisInitializeWrapper", (FUNC)ndis_initwrap },
2931 { "NdisMRegisterMiniport", (FUNC)ndis_register_miniport },
2932 { "NdisAllocateMemoryWithTag", (FUNC)ndis_malloc_withtag },
2933 { "NdisAllocateMemory", (FUNC)ndis_malloc },
2934 { "NdisMSetAttributesEx", (FUNC)ndis_setattr_ex },
2935 { "NdisCloseConfiguration", (FUNC)ndis_close_cfg },
2936 { "NdisReadConfiguration", (FUNC)ndis_read_cfg },
2937 { "NdisOpenConfiguration", (FUNC)ndis_open_cfg },
2938 { "NdisAcquireSpinLock", (FUNC)ndis_lock },
2939 { "NdisReleaseSpinLock", (FUNC)ndis_unlock },
2940 { "NdisDprAcquireSpinLock", (FUNC)ndis_lock_dpr },
2941 { "NdisDprReleaseSpinLock", (FUNC)ndis_unlock_dpr },
2942 { "NdisAllocateSpinLock", (FUNC)ndis_create_lock },
2943 { "NdisFreeSpinLock", (FUNC)ndis_destroy_lock },
2944 { "NdisFreeMemory", (FUNC)ndis_free },
2945 { "NdisReadPciSlotInformation", (FUNC)ndis_read_pci },
2946 { "NdisWritePciSlotInformation",(FUNC)ndis_write_pci },
2947 { "NdisImmediateReadPciSlotInformation", (FUNC)ndis_read_pci },
2948 { "NdisImmediateWritePciSlotInformation", (FUNC)ndis_write_pci },
2949 { "NdisWriteErrorLogEntry", (FUNC)ndis_syslog },
2950 { "NdisMStartBufferPhysicalMapping", (FUNC)ndis_vtophys_load },
2951 { "NdisMCompleteBufferPhysicalMapping", (FUNC)ndis_vtophys_unload },
2952 { "NdisMInitializeTimer", (FUNC)ndis_create_timer },
2953 { "NdisInitializeTimer", (FUNC)ndis_init_timer },
2954 { "NdisSetTimer", (FUNC)ndis_set_timer },
2955 { "NdisMCancelTimer", (FUNC)ndis_cancel_timer },
2956 { "NdisCancelTimer", (FUNC)ndis_cancel_timer },
2957 { "NdisMSetPeriodicTimer", (FUNC)ndis_set_periodic_timer },
2958 { "NdisMQueryAdapterResources", (FUNC)ndis_query_resources },
2959 { "NdisMRegisterIoPortRange", (FUNC)ndis_register_ioport },
2960 { "NdisMDeregisterIoPortRange", (FUNC)ndis_deregister_ioport },
2961 { "NdisReadNetworkAddress", (FUNC)ndis_read_netaddr },
2962 { "NdisQueryMapRegisterCount", (FUNC)ndis_mapreg_cnt },
2963 { "NdisMAllocateMapRegisters", (FUNC)ndis_alloc_mapreg },
2964 { "NdisMFreeMapRegisters", (FUNC)ndis_free_mapreg },
2965 { "NdisMAllocateSharedMemory", (FUNC)ndis_alloc_sharedmem },
2966 { "NdisMMapIoSpace", (FUNC)ndis_map_iospace },
2967 { "NdisMUnmapIoSpace", (FUNC)ndis_unmap_iospace },
2968 { "NdisGetCacheFillSize", (FUNC)ndis_cachefill },
2969 { "NdisMGetDmaAlignment", (FUNC)ndis_dma_align },
2970 { "NdisMInitializeScatterGatherDma", (FUNC)ndis_init_sc_dma },
2971 { "NdisAllocatePacketPool", (FUNC)ndis_alloc_packetpool },
2972 { "NdisAllocatePacketPoolEx", (FUNC)ndis_ex_alloc_packetpool },
2973 { "NdisAllocatePacket", (FUNC)ndis_alloc_packet },
2974 { "NdisFreePacket", (FUNC)ndis_release_packet },
2975 { "NdisFreePacketPool", (FUNC)ndis_free_packetpool },
2976 { "NdisDprAllocatePacket", (FUNC)ndis_alloc_packet },
2977 { "NdisDprFreePacket", (FUNC)ndis_release_packet },
2978 { "NdisAllocateBufferPool", (FUNC)ndis_alloc_bufpool },
2979 { "NdisAllocateBuffer", (FUNC)ndis_alloc_buf },
2980 { "NdisQueryBuffer", (FUNC)ndis_query_buf },
2981 { "NdisQueryBufferSafe", (FUNC)ndis_query_buf_safe },
2982 { "NdisBufferVirtualAddress", (FUNC)ndis_buf_vaddr },
2983 { "NdisBufferVirtualAddressSafe", (FUNC)ndis_buf_vaddr_safe },
2984 { "NdisBufferLength", (FUNC)ndis_buflen },
2985 { "NdisFreeBuffer", (FUNC)ndis_release_buf },
2986 { "NdisFreeBufferPool", (FUNC)ndis_free_bufpool },
2987 { "NdisInterlockedIncrement", (FUNC)ndis_interlock_inc },
2988 { "NdisInterlockedDecrement", (FUNC)ndis_interlock_dec },
2989 { "NdisInitializeEvent", (FUNC)ndis_init_event },
2990 { "NdisSetEvent", (FUNC)ndis_set_event },
2991 { "NdisResetEvent", (FUNC)ndis_reset_event },
2992 { "NdisWaitEvent", (FUNC)ndis_wait_event },
2993 { "NdisUnicodeStringToAnsiString", (FUNC)ndis_unicode2ansi },
2994 { "NdisMPciAssignResources", (FUNC)ndis_assign_pcirsrc },
2995 { "NdisMFreeSharedMemory", (FUNC)ndis_free_sharedmem },
2996 { "NdisMRegisterInterrupt", (FUNC)ndis_register_intr },
2997 { "NdisMDeregisterInterrupt", (FUNC)ndis_deregister_intr },
2998 { "NdisMRegisterAdapterShutdownHandler", (FUNC)ndis_register_shutdown },
2999 { "NdisMDeregisterAdapterShutdownHandler", (FUNC)ndis_deregister_shutdown },
3000 { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC)ndis_numpages },
3001 { "NdisQueryBufferOffset", (FUNC)ndis_query_bufoffset },
3002 { "NdisAdjustBufferLength", (FUNC)ndis_adjust_buflen },
3003 { "NdisPacketPoolUsage", (FUNC)ndis_packetpool_use },
3004 { "NdisMSleep", (FUNC)ndis_sleep },
3005 { "NdisUnchainBufferAtFront", (FUNC)ndis_unchain_headbuf },
3006 { "NdisReadPcmciaAttributeMemory", (FUNC)ndis_read_pccard_amem },
3007 { "NdisWritePcmciaAttributeMemory", (FUNC)ndis_write_pccard_amem },
3008 { "NdisOpenFile", (FUNC)ndis_open_file },
3009 { "NdisMapFile", (FUNC)ndis_map_file },
3010 { "NdisUnmapFile", (FUNC)ndis_unmap_file },
3011 { "NdisCloseFile", (FUNC)ndis_close_file },
3012 { "NdisMRegisterDevice", (FUNC)ndis_register_dev },
3013 { "NdisMDeregisterDevice", (FUNC)ndis_deregister_dev },
3014 { "NdisMQueryAdapterInstanceName", (FUNC)ndis_query_name },
3015 { "NdisMRegisterUnloadHandler", (FUNC)ndis_register_unload },
3018 * This last entry is a catch-all for any function we haven't
3019 * implemented yet. The PE import list patching routine will
3020 * use it for any function that doesn't have an explicit match
3024 { NULL, (FUNC)dummy },