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.19 2006/12/23 00:27:02 swildner Exp $
37 * This file implements a translation layer between the BSD networking
38 * infrasturcture and Windows(R) NDIS network driver modules. A Windows
39 * NDIS driver calls into several functions in the NDIS.SYS Windows
40 * kernel module and exports a table of functions designed to be called
41 * by the NDIS subsystem. Using the PE loader, we can patch our own
42 * versions of the NDIS routines into a given Windows driver module and
43 * convince the driver that it is in fact running on Windows.
45 * We provide a table of all our implemented NDIS routines which is patched
46 * into the driver object code. All our exported routines must use the
47 * _stdcall calling convention, since that's what the Windows object code
51 #include <sys/ctype.h>
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/kernel.h>
55 #include <sys/types.h>
56 #include <sys/errno.h>
58 #include <sys/callout.h>
59 #include <sys/malloc.h>
61 #include <sys/socket.h>
62 #include <sys/sysctl.h>
63 #include <sys/queue.h>
65 #include <sys/filedesc.h>
66 #include <sys/nlookup.h>
67 #include <sys/fcntl.h>
68 #include <sys/vnode.h>
69 #include <sys/kthread.h>
74 #include <net/if_arp.h>
75 #include <net/ethernet.h>
76 #include <net/if_dl.h>
77 #include <net/if_media.h>
79 #include <machine/atomic.h>
80 #include <machine/stdarg.h>
82 #include <netproto/802_11/ieee80211_var.h>
83 #include <netproto/802_11/ieee80211_ioctl.h>
85 #include <bus/pci/pcireg.h>
86 #include <bus/pci/pcivar.h>
90 #include "resource_var.h"
91 #include "ntoskrnl_var.h"
95 #include <dev/netif/ndis/if_ndisvar.h>
97 #define FUNC void(*)(void)
99 static char ndis_filepath
[MAXPATHLEN
];
100 extern struct nd_head ndis_devhead
;
102 SYSCTL_STRING(_hw
, OID_AUTO
, ndis_filepath
, CTLFLAG_RW
, ndis_filepath
,
103 MAXPATHLEN
, "Path used by NdisOpenFile() to search for files");
105 __stdcall
static void ndis_initwrap(ndis_handle
*,
106 device_object
*, void *, void *);
107 __stdcall
static ndis_status
ndis_register_miniport(ndis_handle
,
108 ndis_miniport_characteristics
*, int);
109 __stdcall
static ndis_status
ndis_malloc_withtag(void **, uint32_t, uint32_t);
110 __stdcall
static ndis_status
ndis_malloc(void **,
111 uint32_t, uint32_t, ndis_physaddr
);
112 __stdcall
static void ndis_free(void *, uint32_t, uint32_t);
113 __stdcall
static ndis_status
ndis_setattr_ex(ndis_handle
, ndis_handle
,
114 uint32_t, uint32_t, ndis_interface_type
);
115 __stdcall
static void ndis_open_cfg(ndis_status
*, ndis_handle
*, ndis_handle
);
116 __stdcall
static void ndis_open_cfgbyidx(ndis_status
*, ndis_handle
,
117 uint32_t, ndis_unicode_string
*, ndis_handle
*);
118 __stdcall
static void ndis_open_cfgbyname(ndis_status
*, ndis_handle
,
119 ndis_unicode_string
*, ndis_handle
*);
120 static ndis_status
ndis_encode_parm(ndis_miniport_block
*,
121 struct sysctl_oid
*, ndis_parm_type
, ndis_config_parm
**);
122 static ndis_status
ndis_decode_parm(ndis_miniport_block
*,
123 ndis_config_parm
*, char *);
124 __stdcall
static void ndis_read_cfg(ndis_status
*, ndis_config_parm
**,
125 ndis_handle
, ndis_unicode_string
*, ndis_parm_type
);
126 __stdcall
static void ndis_write_cfg(ndis_status
*, ndis_handle
,
127 ndis_unicode_string
*, ndis_config_parm
*);
128 __stdcall
static void ndis_close_cfg(ndis_handle
);
129 __stdcall
static void ndis_create_lock(ndis_spin_lock
*);
130 __stdcall
static void ndis_destroy_lock(ndis_spin_lock
*);
131 __stdcall
static void ndis_lock(ndis_spin_lock
*);
132 __stdcall
static void ndis_unlock(ndis_spin_lock
*);
133 __stdcall
static void ndis_lock_dpr(ndis_spin_lock
*);
134 __stdcall
static void ndis_unlock_dpr(ndis_spin_lock
*);
135 __stdcall
static uint32_t ndis_read_pci(ndis_handle
, uint32_t,
136 uint32_t, void *, uint32_t);
137 __stdcall
static uint32_t ndis_write_pci(ndis_handle
, uint32_t,
138 uint32_t, void *, uint32_t);
139 static void ndis_syslog(ndis_handle
, ndis_error_code
, uint32_t, ...);
140 static void ndis_map_cb(void *, bus_dma_segment_t
*, int, int);
141 __stdcall
static void ndis_vtophys_load(ndis_handle
, ndis_buffer
*,
142 uint32_t, uint8_t, ndis_paddr_unit
*, uint32_t *);
143 __stdcall
static void ndis_vtophys_unload(ndis_handle
, ndis_buffer
*, uint32_t);
144 __stdcall
static void ndis_create_timer(ndis_miniport_timer
*, ndis_handle
,
145 ndis_timer_function
, void *);
146 __stdcall
static void ndis_init_timer(ndis_timer
*,
147 ndis_timer_function
, void *);
148 __stdcall
static void ndis_set_timer(ndis_timer
*, uint32_t);
149 __stdcall
static void ndis_set_periodic_timer(ndis_miniport_timer
*, uint32_t);
150 __stdcall
static void ndis_cancel_timer(ndis_timer
*, uint8_t *);
151 __stdcall
static void ndis_query_resources(ndis_status
*, ndis_handle
,
152 ndis_resource_list
*, uint32_t *);
153 __stdcall
static ndis_status
ndis_register_ioport(void **,
154 ndis_handle
, uint32_t, uint32_t);
155 __stdcall
static void ndis_deregister_ioport(ndis_handle
,
156 uint32_t, uint32_t, void *);
157 __stdcall
static void ndis_read_netaddr(ndis_status
*, void **,
158 uint32_t *, ndis_handle
);
159 __stdcall
static ndis_status
ndis_mapreg_cnt(uint32_t, uint32_t *);
160 __stdcall
static ndis_status
ndis_alloc_mapreg(ndis_handle
,
161 uint32_t, uint8_t, uint32_t, uint32_t);
162 __stdcall
static void ndis_free_mapreg(ndis_handle
);
163 static void ndis_mapshared_cb(void *, bus_dma_segment_t
*, int, int);
164 __stdcall
static void ndis_alloc_sharedmem(ndis_handle
, uint32_t,
165 uint8_t, void **, ndis_physaddr
*);
166 static void ndis_asyncmem_complete(void *);
167 __stdcall
static ndis_status
ndis_alloc_sharedmem_async(ndis_handle
,
168 uint32_t, uint8_t, void *);
169 __stdcall
static void ndis_free_sharedmem(ndis_handle
, uint32_t,
170 uint8_t, void *, ndis_physaddr
);
171 __stdcall
static ndis_status
ndis_map_iospace(void **, ndis_handle
,
172 ndis_physaddr
, uint32_t);
173 __stdcall
static void ndis_unmap_iospace(ndis_handle
, void *, uint32_t);
174 __stdcall
static uint32_t ndis_cachefill(void);
175 __stdcall
static uint32_t ndis_dma_align(ndis_handle
);
176 __stdcall
static ndis_status
ndis_init_sc_dma(ndis_handle
,
178 __stdcall
static void ndis_alloc_packetpool(ndis_status
*,
179 ndis_handle
*, uint32_t, uint32_t);
180 __stdcall
static void ndis_ex_alloc_packetpool(ndis_status
*,
181 ndis_handle
*, uint32_t, uint32_t, uint32_t);
182 __stdcall
static uint32_t ndis_packetpool_use(ndis_handle
);
183 __stdcall
static void ndis_free_packetpool(ndis_handle
);
184 __stdcall
static void ndis_alloc_packet(ndis_status
*,
185 ndis_packet
**, ndis_handle
);
186 __stdcall
static void ndis_release_packet(ndis_packet
*);
187 __stdcall
static void ndis_unchain_headbuf(ndis_packet
*, ndis_buffer
**);
188 __stdcall
static void ndis_unchain_tailbuf(ndis_packet
*, ndis_buffer
**);
189 __stdcall
static void ndis_alloc_bufpool(ndis_status
*,
190 ndis_handle
*, uint32_t);
191 __stdcall
static void ndis_free_bufpool(ndis_handle
);
192 __stdcall
static void ndis_alloc_buf(ndis_status
*, ndis_buffer
**,
193 ndis_handle
, void *, uint32_t);
194 __stdcall
static void ndis_release_buf(ndis_buffer
*);
195 __stdcall
static uint32_t ndis_buflen(ndis_buffer
*);
196 __stdcall
static void ndis_query_buf(ndis_buffer
*, void **, uint32_t *);
197 __stdcall
static void ndis_query_buf_safe(ndis_buffer
*, void **,
198 uint32_t *, uint32_t);
199 __stdcall
static void *ndis_buf_vaddr(ndis_buffer
*);
200 __stdcall
static void *ndis_buf_vaddr_safe(ndis_buffer
*, uint32_t);
201 __stdcall
static void ndis_adjust_buflen(ndis_buffer
*, int);
202 __stdcall
static uint32_t ndis_interlock_inc(uint32_t *);
203 __stdcall
static uint32_t ndis_interlock_dec(uint32_t *);
204 __stdcall
static void ndis_init_event(ndis_event
*);
205 __stdcall
static void ndis_set_event(ndis_event
*);
206 __stdcall
static void ndis_reset_event(ndis_event
*);
207 __stdcall
static uint8_t ndis_wait_event(ndis_event
*, uint32_t);
208 __stdcall
static ndis_status
ndis_unicode2ansi(ndis_ansi_string
*,
209 ndis_unicode_string
*);
210 __stdcall
static ndis_status
ndis_ansi2unicode(ndis_unicode_string
*,
212 __stdcall
static ndis_status
ndis_assign_pcirsrc(ndis_handle
,
213 uint32_t, ndis_resource_list
**);
214 __stdcall
static ndis_status
ndis_register_intr(ndis_miniport_interrupt
*,
215 ndis_handle
, uint32_t, uint32_t, uint8_t,
216 uint8_t, ndis_interrupt_mode
);
217 __stdcall
static void ndis_deregister_intr(ndis_miniport_interrupt
*);
218 __stdcall
static void ndis_register_shutdown(ndis_handle
, void *,
219 ndis_shutdown_handler
);
220 __stdcall
static void ndis_deregister_shutdown(ndis_handle
);
221 __stdcall
static uint32_t ndis_numpages(ndis_buffer
*);
222 __stdcall
static void ndis_buf_physpages(ndis_buffer
*, uint32_t *);
223 __stdcall
static void ndis_query_bufoffset(ndis_buffer
*,
224 uint32_t *, uint32_t *);
225 __stdcall
static void ndis_sleep(uint32_t);
226 __stdcall
static uint32_t ndis_read_pccard_amem(ndis_handle
,
227 uint32_t, void *, uint32_t);
228 __stdcall
static uint32_t ndis_write_pccard_amem(ndis_handle
,
229 uint32_t, void *, uint32_t);
230 __stdcall
static list_entry
*ndis_insert_head(list_entry
*,
231 list_entry
*, ndis_spin_lock
*);
232 __stdcall
static list_entry
*ndis_remove_head(list_entry
*,
234 __stdcall
static list_entry
*ndis_insert_tail(list_entry
*,
235 list_entry
*, ndis_spin_lock
*);
236 __stdcall
static uint8_t ndis_sync_with_intr(ndis_miniport_interrupt
*,
238 __stdcall
static void ndis_time(uint64_t *);
239 __stdcall
static void ndis_uptime(uint32_t *);
240 __stdcall
static void ndis_init_string(ndis_unicode_string
*, char *);
241 __stdcall
static void ndis_init_ansi_string(ndis_ansi_string
*, char *);
242 __stdcall
static void ndis_init_unicode_string(ndis_unicode_string
*,
244 __stdcall
static void ndis_free_string(ndis_unicode_string
*);
245 __stdcall
static ndis_status
ndis_remove_miniport(ndis_handle
*);
246 __stdcall
static void ndis_termwrap(ndis_handle
, void *);
247 __stdcall
static void ndis_get_devprop(ndis_handle
, device_object
**,
248 device_object
**, device_object
**, cm_resource_list
*,
250 __stdcall
static void ndis_firstbuf(ndis_packet
*, ndis_buffer
**,
251 void **, uint32_t *, uint32_t *);
252 __stdcall
static void ndis_firstbuf_safe(ndis_packet
*, ndis_buffer
**,
253 void **, uint32_t *, uint32_t *, uint32_t);
254 __stdcall
static void ndis_open_file(ndis_status
*, ndis_handle
*, uint32_t *,
255 ndis_unicode_string
*, ndis_physaddr
);
256 __stdcall
static void ndis_map_file(ndis_status
*, void **, ndis_handle
);
257 __stdcall
static void ndis_unmap_file(ndis_handle
);
258 __stdcall
static void ndis_close_file(ndis_handle
);
259 __stdcall
static u_int8_t
ndis_cpu_cnt(void);
260 __stdcall
static void ndis_ind_statusdone(ndis_handle
);
261 __stdcall
static void ndis_ind_status(ndis_handle
, ndis_status
,
263 static void ndis_workfunc(void *);
264 __stdcall
static ndis_status
ndis_sched_workitem(ndis_work_item
*);
265 __stdcall
static void ndis_pkt_to_pkt(ndis_packet
*, uint32_t, uint32_t,
266 ndis_packet
*, uint32_t, uint32_t *);
267 __stdcall
static void ndis_pkt_to_pkt_safe(ndis_packet
*, uint32_t, uint32_t,
268 ndis_packet
*, uint32_t, uint32_t *, uint32_t);
269 __stdcall
static ndis_status
ndis_register_dev(ndis_handle
,
270 ndis_unicode_string
*, ndis_unicode_string
*, driver_dispatch
**,
271 void **, ndis_handle
*);
272 __stdcall
static ndis_status
ndis_deregister_dev(ndis_handle
);
273 __stdcall
static ndis_status
ndis_query_name(ndis_unicode_string
*,
275 __stdcall
static void ndis_register_unload(ndis_handle
, void *);
276 __stdcall
static void dummy(void);
279 * Some really old drivers do not properly check the return value
280 * from NdisAllocatePacket() and NdisAllocateBuffer() and will
281 * sometimes allocate few more buffers/packets that they originally
282 * requested when they created the pool. To prevent this from being
283 * a problem, we allocate a few extra buffers/packets beyond what
284 * the driver asks for. This #define controls how many.
286 #define NDIS_POOL_EXTRA 16
291 strcpy(ndis_filepath
, "/compat/ndis");
302 * NDIS deals with strings in unicode format, so we have
303 * do deal with them that way too. For now, we only handle
304 * conversion between unicode and ASCII since that's all
305 * that device drivers care about.
309 ndis_ascii_to_unicode(char *ascii
, uint16_t **unicode
)
314 if (*unicode
== NULL
)
315 *unicode
= kmalloc(strlen(ascii
) * 2, M_DEVBUF
, M_WAITOK
);
317 for (i
= 0; i
< strlen(ascii
); i
++) {
318 *ustr
= (uint16_t)ascii
[i
];
326 ndis_unicode_to_ascii(uint16_t *unicode
, int ulen
, char **ascii
)
332 *ascii
= kmalloc((ulen
/ 2) + 1, M_DEVBUF
, M_WAITOK
|M_ZERO
);
334 for (i
= 0; i
< ulen
/ 2; i
++) {
335 *astr
= (uint8_t)unicode
[i
];
342 __stdcall
static void
343 ndis_initwrap(ndis_handle
*wrapper
, device_object
*drv_obj
, void *path
,
346 ndis_miniport_block
*block
;
348 block
= drv_obj
->do_rsvd
;
354 __stdcall
static void
355 ndis_termwrap(ndis_handle handle
, void *syspec
)
360 __stdcall
static ndis_status
361 ndis_register_miniport(ndis_handle handle
,
362 ndis_miniport_characteristics
*characteristics
,
365 ndis_miniport_block
*block
;
366 struct ndis_softc
*sc
;
368 block
= (ndis_miniport_block
*)handle
;
369 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
370 bcopy((char *)characteristics
, (char *)&sc
->ndis_chars
,
371 sizeof(ndis_miniport_characteristics
));
372 if (sc
->ndis_chars
.nmc_version_major
< 5 ||
373 sc
->ndis_chars
.nmc_version_minor
< 1) {
374 sc
->ndis_chars
.nmc_shutdown_handler
= NULL
;
375 sc
->ndis_chars
.nmc_canceltxpkts_handler
= NULL
;
376 sc
->ndis_chars
.nmc_pnpevent_handler
= NULL
;
379 return(NDIS_STATUS_SUCCESS
);
382 __stdcall
static ndis_status
383 ndis_malloc_withtag(void **vaddr
, uint32_t len
, uint32_t tag
)
387 mem
= kmalloc(len
, M_DEVBUF
, M_INTWAIT
|M_NULLOK
);
389 return(NDIS_STATUS_RESOURCES
);
392 return(NDIS_STATUS_SUCCESS
);
395 __stdcall
static ndis_status
396 ndis_malloc(void **vaddr
, uint32_t len
, uint32_t flags
,
397 ndis_physaddr highaddr
)
401 mem
= kmalloc(len
, M_DEVBUF
, M_INTWAIT
|M_NULLOK
);
403 return(NDIS_STATUS_RESOURCES
);
406 return(NDIS_STATUS_SUCCESS
);
409 __stdcall
static void
410 ndis_free(void *vaddr
, uint32_t len
, uint32_t flags
)
414 kfree(vaddr
, M_DEVBUF
);
419 __stdcall
static ndis_status
420 ndis_setattr_ex(ndis_handle adapter_handle
, ndis_handle adapter_ctx
,
421 uint32_t hangsecs
, uint32_t flags
,
422 ndis_interface_type iftype
)
424 ndis_miniport_block
*block
;
427 * Save the adapter context, we need it for calling
428 * the driver's internal functions.
430 block
= (ndis_miniport_block
*)adapter_handle
;
431 block
->nmb_miniportadapterctx
= adapter_ctx
;
432 block
->nmb_checkforhangsecs
= hangsecs
;
433 block
->nmb_flags
= flags
;
435 return(NDIS_STATUS_SUCCESS
);
438 __stdcall
static void
439 ndis_open_cfg(ndis_status
*status
, ndis_handle
*cfg
, ndis_handle wrapctx
)
442 *status
= NDIS_STATUS_SUCCESS
;
446 __stdcall
static void
447 ndis_open_cfgbyname(ndis_status
*status
, ndis_handle cfg
,
448 ndis_unicode_string
*subkey
, ndis_handle
*subhandle
)
451 *status
= NDIS_STATUS_SUCCESS
;
455 __stdcall
static void
456 ndis_open_cfgbyidx(ndis_status
*status
, ndis_handle cfg
, uint32_t idx
,
457 ndis_unicode_string
*subkey
, ndis_handle
*subhandle
)
459 *status
= NDIS_STATUS_FAILURE
;
464 ndis_encode_parm(ndis_miniport_block
*block
, struct sysctl_oid
*oid
,
465 ndis_parm_type type
, ndis_config_parm
**parm
)
468 ndis_unicode_string
*ustr
;
471 unicode
= (uint16_t *)&block
->nmb_dummybuf
;
474 case ndis_parm_string
:
475 ndis_ascii_to_unicode((char *)oid
->oid_arg1
, &unicode
);
476 (*parm
)->ncp_type
= ndis_parm_string
;
477 ustr
= &(*parm
)->ncp_parmdata
.ncp_stringdata
;
478 ustr
->nus_len
= strlen((char *)oid
->oid_arg1
) * 2;
479 ustr
->nus_buf
= unicode
;
482 if (strncmp((char *)oid
->oid_arg1
, "0x", 2) == 0)
486 (*parm
)->ncp_type
= ndis_parm_int
;
487 (*parm
)->ncp_parmdata
.ncp_intdata
=
488 strtol((char *)oid
->oid_arg1
, NULL
, base
);
490 case ndis_parm_hexint
:
491 if (strncmp((char *)oid
->oid_arg1
, "0x", 2) == 0)
495 (*parm
)->ncp_type
= ndis_parm_hexint
;
496 (*parm
)->ncp_parmdata
.ncp_intdata
=
497 strtoul((char *)oid
->oid_arg1
, NULL
, base
);
500 return(NDIS_STATUS_FAILURE
);
504 return(NDIS_STATUS_SUCCESS
);
508 ndis_strcasecmp(const char *s1
, const char *s2
)
513 * In the kernel, toupper() is a macro. Have to be careful
514 * not to use pointer arithmetic when passing it arguments.
520 if (toupper(a
) != toupper(b
))
526 return (*(const unsigned char *)s1
- *(const unsigned char *)(s2
- 1));
529 __stdcall
static void
530 ndis_read_cfg(ndis_status
*status
, ndis_config_parm
**parm
, ndis_handle cfg
,
531 ndis_unicode_string
*key
, ndis_parm_type type
)
535 ndis_miniport_block
*block
;
536 struct ndis_softc
*sc
;
537 struct sysctl_oid
*oidp
;
538 struct sysctl_ctx_entry
*e
;
540 block
= (ndis_miniport_block
*)cfg
;
541 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
543 if (key
->nus_len
== 0 || key
->nus_buf
== NULL
) {
544 *status
= NDIS_STATUS_FAILURE
;
548 ndis_unicode_to_ascii(key
->nus_buf
, key
->nus_len
, &keystr
);
550 *parm
= &block
->nmb_replyparm
;
551 bzero((char *)&block
->nmb_replyparm
, sizeof(ndis_config_parm
));
552 unicode
= (uint16_t *)&block
->nmb_dummybuf
;
555 * See if registry key is already in a list of known keys
556 * included with the driver.
558 #if __FreeBSD_version < 502113
559 TAILQ_FOREACH(e
, &sc
->ndis_ctx
, link
) {
561 TAILQ_FOREACH(e
, device_get_sysctl_ctx(sc
->ndis_dev
), link
) {
564 if (ndis_strcasecmp(oidp
->oid_name
, keystr
) == 0) {
565 if (strcmp((char *)oidp
->oid_arg1
, "UNSET") == 0) {
566 kfree(keystr
, M_DEVBUF
);
567 *status
= NDIS_STATUS_FAILURE
;
570 *status
= ndis_encode_parm(block
, oidp
, type
, parm
);
571 kfree(keystr
, M_DEVBUF
);
577 * If the key didn't match, add it to the list of dynamically
578 * created ones. Sometimes, drivers refer to registry keys
579 * that aren't documented in their .INF files. These keys
580 * are supposed to be created by some sort of utility or
581 * control panel snap-in that comes with the driver software.
582 * Sometimes it's useful to be able to manipulate these.
583 * If the driver requests the key in the form of a string,
584 * make its default value an empty string, otherwise default
588 if (type
== ndis_parm_int
|| type
== ndis_parm_hexint
)
589 ndis_add_sysctl(sc
, keystr
, "(dynamic integer key)",
590 "UNSET", CTLFLAG_RW
);
592 ndis_add_sysctl(sc
, keystr
, "(dynamic string key)",
593 "UNSET", CTLFLAG_RW
);
595 kfree(keystr
, M_DEVBUF
);
596 *status
= NDIS_STATUS_FAILURE
;
601 ndis_decode_parm(ndis_miniport_block
*block
, ndis_config_parm
*parm
,
604 ndis_unicode_string
*ustr
;
607 switch(parm
->ncp_type
) {
608 case ndis_parm_string
:
609 ustr
= &parm
->ncp_parmdata
.ncp_stringdata
;
610 ndis_unicode_to_ascii(ustr
->nus_buf
, ustr
->nus_len
, &astr
);
611 bcopy(astr
, val
, 254);
612 kfree(astr
, M_DEVBUF
);
615 ksprintf(val
, "%d", parm
->ncp_parmdata
.ncp_intdata
);
617 case ndis_parm_hexint
:
618 ksprintf(val
, "%xu", parm
->ncp_parmdata
.ncp_intdata
);
621 return(NDIS_STATUS_FAILURE
);
624 return(NDIS_STATUS_SUCCESS
);
627 __stdcall
static void
628 ndis_write_cfg(ndis_status
*status
, ndis_handle cfg
, ndis_unicode_string
*key
,
629 ndis_config_parm
*parm
)
632 ndis_miniport_block
*block
;
633 struct ndis_softc
*sc
;
634 struct sysctl_oid
*oidp
;
635 struct sysctl_ctx_entry
*e
;
638 block
= (ndis_miniport_block
*)cfg
;
639 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
641 ndis_unicode_to_ascii(key
->nus_buf
, key
->nus_len
, &keystr
);
643 /* Decode the parameter into a string. */
644 bzero(val
, sizeof(val
));
645 *status
= ndis_decode_parm(block
, parm
, val
);
646 if (*status
!= NDIS_STATUS_SUCCESS
) {
647 kfree(keystr
, M_DEVBUF
);
651 /* See if the key already exists. */
653 #if __FreeBSD_version < 502113
654 TAILQ_FOREACH(e
, &sc
->ndis_ctx
, link
) {
656 TAILQ_FOREACH(e
, device_get_sysctl_ctx(sc
->ndis_dev
), link
) {
659 if (ndis_strcasecmp(oidp
->oid_name
, keystr
) == 0) {
660 /* Found it, set the value. */
661 strcpy((char *)oidp
->oid_arg1
, val
);
662 kfree(keystr
, M_DEVBUF
);
667 /* Not found, add a new key with the specified value. */
668 ndis_add_sysctl(sc
, keystr
, "(dynamically set key)",
671 kfree(keystr
, M_DEVBUF
);
672 *status
= NDIS_STATUS_SUCCESS
;
676 __stdcall
static void
677 ndis_close_cfg(ndis_handle cfg
)
683 * Initialize a Windows spinlock.
685 __stdcall
static void
686 ndis_create_lock(ndis_spin_lock
*lock
)
688 lock
->nsl_spinlock
= 0;
695 * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
696 * for this. One is that it's sort of superfluous: we don't have to do anything
697 * special to deallocate the spinlock. The other is that there are some buggy
698 * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
699 * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
702 __stdcall
static void
703 ndis_destroy_lock(ndis_spin_lock
*lock
)
706 lock
->nsl_spinlock
= 0;
713 * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
716 __stdcall
static void
717 ndis_lock(ndis_spin_lock
*lock
)
719 lock
->nsl_kirql
= FASTCALL2(hal_lock
,
720 &lock
->nsl_spinlock
, DISPATCH_LEVEL
);
725 * Release a spinlock from IRQL == DISPATCH_LEVEL.
728 __stdcall
static void
729 ndis_unlock(ndis_spin_lock
*lock
)
731 FASTCALL2(hal_unlock
, &lock
->nsl_spinlock
, lock
->nsl_kirql
);
736 * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
738 __stdcall
static void
739 ndis_lock_dpr(ndis_spin_lock
*lock
)
741 FASTCALL1(ntoskrnl_lock_dpc
, &lock
->nsl_spinlock
);
746 * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
748 __stdcall
static void
749 ndis_unlock_dpr(ndis_spin_lock
*lock
)
751 FASTCALL1(ntoskrnl_unlock_dpc
, &lock
->nsl_spinlock
);
755 __stdcall
static uint32_t
756 ndis_read_pci(ndis_handle adapter
, uint32_t slot
, uint32_t offset
,
757 void *buf
, uint32_t len
)
759 ndis_miniport_block
*block
;
763 block
= (ndis_miniport_block
*)adapter
;
765 if (block
== NULL
|| block
->nmb_dev
== NULL
)
768 for (i
= 0; i
< len
; i
++)
769 dest
[i
] = pci_read_config(block
->nmb_dev
, i
+ offset
, 1);
774 __stdcall
static uint32_t
775 ndis_write_pci(ndis_handle adapter
, uint32_t slot
, uint32_t offset
,
776 void *buf
, uint32_t len
)
778 ndis_miniport_block
*block
;
782 block
= (ndis_miniport_block
*)adapter
;
785 if (block
== NULL
|| block
->nmb_dev
== NULL
)
788 for (i
= 0; i
< len
; i
++)
789 pci_write_config(block
->nmb_dev
, i
+ offset
, dest
[i
], 1);
795 * The errorlog routine uses a variable argument list, so we
796 * have to declare it this way.
798 #define ERRMSGLEN 512
800 ndis_syslog(ndis_handle adapter
, ndis_error_code code
,
801 uint32_t numerrors
, ...)
803 ndis_miniport_block
*block
;
806 char *str
= NULL
, *ustr
= NULL
;
808 char msgbuf
[ERRMSGLEN
];
811 block
= (ndis_miniport_block
*)adapter
;
813 error
= pe_get_message(block
->nmb_img
, code
, &str
, &i
, &flags
);
814 if (error
== 0 && flags
& MESSAGE_RESOURCE_UNICODE
) {
816 ndis_unicode_to_ascii((uint16_t *)str
,
817 ((i
/ 2)) > (ERRMSGLEN
- 1) ? ERRMSGLEN
: i
, &ustr
);
820 device_printf (block
->nmb_dev
, "NDIS ERROR: %x (%s)\n", code
,
821 str
== NULL
? "unknown error" : str
);
822 device_printf (block
->nmb_dev
, "NDIS NUMERRORS: %x\n", numerrors
);
824 __va_start(ap
, numerrors
);
825 for (i
= 0; i
< numerrors
; i
++)
826 device_printf (block
->nmb_dev
, "argptr: %p\n",
827 __va_arg(ap
, void *));
834 ndis_map_cb(void *arg
, bus_dma_segment_t
*segs
, int nseg
, int error
)
836 struct ndis_map_arg
*ctx
;
844 for (i
= 0; i
< nseg
; i
++) {
845 ctx
->nma_fraglist
[i
].npu_physaddr
.np_quad
= segs
[i
].ds_addr
;
846 ctx
->nma_fraglist
[i
].npu_len
= segs
[i
].ds_len
;
854 __stdcall
static void
855 ndis_vtophys_load(ndis_handle adapter
, ndis_buffer
*buf
, uint32_t mapreg
,
856 uint8_t writedev
, ndis_paddr_unit
*addrarray
,
859 ndis_miniport_block
*block
;
860 struct ndis_softc
*sc
;
861 struct ndis_map_arg nma
;
868 block
= (ndis_miniport_block
*)adapter
;
869 sc
= (struct ndis_softc
*)(block
->nmb_ifp
);
871 if (mapreg
> sc
->ndis_mmapcnt
)
874 map
= sc
->ndis_mmaps
[mapreg
];
875 nma
.nma_fraglist
= addrarray
;
877 error
= bus_dmamap_load(sc
->ndis_mtag
, map
,
878 MDL_VA(buf
), buf
->nb_bytecount
, ndis_map_cb
,
879 (void *)&nma
, BUS_DMA_NOWAIT
);
884 bus_dmamap_sync(sc
->ndis_mtag
, map
,
885 writedev
? BUS_DMASYNC_PREWRITE
: BUS_DMASYNC_PREREAD
);
887 *arraysize
= nma
.nma_cnt
;
892 __stdcall
static void
893 ndis_vtophys_unload(ndis_handle adapter
, ndis_buffer
*buf
,
896 ndis_miniport_block
*block
;
897 struct ndis_softc
*sc
;
903 block
= (ndis_miniport_block
*)adapter
;
904 sc
= (struct ndis_softc
*)(block
->nmb_ifp
);
906 if (mapreg
> sc
->ndis_mmapcnt
)
909 map
= sc
->ndis_mmaps
[mapreg
];
911 bus_dmamap_sync(sc
->ndis_mtag
, map
,
912 BUS_DMASYNC_POSTREAD
|BUS_DMASYNC_POSTWRITE
);
914 bus_dmamap_unload(sc
->ndis_mtag
, map
);
920 * This is an older pre-miniport timer init routine which doesn't
921 * accept a miniport context handle. The function context (ctx)
922 * is supposed to be a pointer to the adapter handle, which should
923 * have been handed to us via NdisSetAttributesEx(). We use this
924 * function context to track down the corresponding ndis_miniport_block
925 * structure. It's vital that we track down the miniport block structure,
926 * so if we can't do it, we panic. Note that we also play some games
927 * here by treating ndis_timer and ndis_miniport_timer as the same
931 __stdcall
static void
932 ndis_init_timer(ndis_timer
*timer
, ndis_timer_function func
, void *ctx
)
934 ntoskrnl_init_timer(&timer
->nt_ktimer
);
935 ntoskrnl_init_dpc(&timer
->nt_kdpc
, func
, ctx
);
940 __stdcall
static void
941 ndis_create_timer(ndis_miniport_timer
*timer
, ndis_handle handle
,
942 ndis_timer_function func
, void *ctx
)
944 /* Save the funcptr and context */
946 timer
->nmt_timerfunc
= func
;
947 timer
->nmt_timerctx
= ctx
;
948 timer
->nmt_block
= handle
;
950 ntoskrnl_init_timer(&timer
->nmt_ktimer
);
951 ntoskrnl_init_dpc(&timer
->nmt_kdpc
, func
, ctx
);
957 * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
958 * but the former is just a macro wrapper around the latter.
960 __stdcall
static void
961 ndis_set_timer(ndis_timer
*timer
, uint32_t msecs
)
964 * KeSetTimer() wants the period in
965 * hundred nanosecond intervals.
967 ntoskrnl_set_timer(&timer
->nt_ktimer
,
968 ((int64_t)msecs
* -10000), &timer
->nt_kdpc
);
973 __stdcall
static void
974 ndis_set_periodic_timer(ndis_miniport_timer
*timer
, uint32_t msecs
)
976 ntoskrnl_set_timer_ex(&timer
->nmt_ktimer
,
977 ((int64_t)msecs
* -10000), msecs
, &timer
->nmt_kdpc
);
983 * Technically, this is really NdisCancelTimer(), but we also
984 * (ab)use it for NdisMCancelTimer(), since in our implementation
985 * we don't need the extra info in the ndis_miniport_timer
989 __stdcall
static void
990 ndis_cancel_timer(ndis_timer
*timer
, uint8_t *cancelled
)
992 *cancelled
= ntoskrnl_cancel_timer(&timer
->nt_ktimer
);
997 __stdcall
static void
998 ndis_query_resources(ndis_status
*status
, ndis_handle adapter
,
999 ndis_resource_list
*list
, uint32_t *buflen
)
1001 ndis_miniport_block
*block
;
1002 struct ndis_softc
*sc
;
1005 block
= (ndis_miniport_block
*)adapter
;
1006 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
1008 rsclen
= sizeof(ndis_resource_list
) +
1009 (sizeof(cm_partial_resource_desc
) * (sc
->ndis_rescnt
- 1));
1010 if (*buflen
< rsclen
) {
1012 *status
= NDIS_STATUS_INVALID_LENGTH
;
1016 bcopy((char *)block
->nmb_rlist
, (char *)list
, rsclen
);
1017 *status
= NDIS_STATUS_SUCCESS
;
1021 __stdcall
static ndis_status
1022 ndis_register_ioport(void **offset
, ndis_handle adapter
,
1023 uint32_t port
, uint32_t numports
)
1025 struct ndis_miniport_block
*block
;
1026 struct ndis_softc
*sc
;
1028 if (adapter
== NULL
)
1029 return(NDIS_STATUS_FAILURE
);
1031 block
= (ndis_miniport_block
*)adapter
;
1032 sc
= (struct ndis_softc
*)(block
->nmb_ifp
);
1034 if (sc
->ndis_res_io
== NULL
)
1035 return(NDIS_STATUS_FAILURE
);
1037 /* Don't let the device map more ports than we have. */
1038 if (rman_get_size(sc
->ndis_res_io
) < numports
)
1039 return(NDIS_STATUS_INVALID_LENGTH
);
1041 *offset
= (void *)rman_get_start(sc
->ndis_res_io
);
1043 return(NDIS_STATUS_SUCCESS
);
1046 __stdcall
static void
1047 ndis_deregister_ioport(ndis_handle adapter
, uint32_t port
,
1048 uint32_t numports
, void *offset
)
1053 __stdcall
static void
1054 ndis_read_netaddr(ndis_status
*status
, void **addr
,
1055 uint32_t *addrlen
, ndis_handle adapter
)
1057 struct ndis_softc
*sc
;
1058 ndis_miniport_block
*block
;
1059 uint8_t empty
[] = { 0, 0, 0, 0, 0, 0 };
1061 block
= (ndis_miniport_block
*)adapter
;
1062 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
1064 if (bcmp(sc
->arpcom
.ac_enaddr
, empty
, ETHER_ADDR_LEN
) == 0)
1065 *status
= NDIS_STATUS_FAILURE
;
1067 *addr
= sc
->arpcom
.ac_enaddr
;
1068 *addrlen
= ETHER_ADDR_LEN
;
1069 *status
= NDIS_STATUS_SUCCESS
;
1075 __stdcall
static ndis_status
1076 ndis_mapreg_cnt(uint32_t bustype
, uint32_t *cnt
)
1079 return(NDIS_STATUS_SUCCESS
);
1082 __stdcall
static ndis_status
1083 ndis_alloc_mapreg(ndis_handle adapter
, uint32_t dmachannel
, uint8_t dmasize
,
1084 uint32_t physmapneeded
, uint32_t maxmap
)
1086 struct ndis_softc
*sc
;
1087 ndis_miniport_block
*block
;
1088 int error
, i
, nseg
= NDIS_MAXSEG
;
1090 block
= (ndis_miniport_block
*)adapter
;
1091 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
1093 sc
->ndis_mmaps
= kmalloc(sizeof(bus_dmamap_t
) * physmapneeded
,
1094 M_DEVBUF
, M_INTWAIT
|M_ZERO
);
1096 if (sc
->ndis_mmaps
== NULL
)
1097 return(NDIS_STATUS_RESOURCES
);
1099 error
= bus_dma_tag_create(sc
->ndis_parent_tag
, ETHER_ALIGN
, 0,
1100 BUS_SPACE_MAXADDR_32BIT
, BUS_SPACE_MAXADDR
, NULL
,
1101 NULL
, maxmap
* nseg
, nseg
, maxmap
, BUS_DMA_ALLOCNOW
,
1105 kfree(sc
->ndis_mmaps
, M_DEVBUF
);
1106 return(NDIS_STATUS_RESOURCES
);
1109 for (i
= 0; i
< physmapneeded
; i
++)
1110 bus_dmamap_create(sc
->ndis_mtag
, 0, &sc
->ndis_mmaps
[i
]);
1112 sc
->ndis_mmapcnt
= physmapneeded
;
1114 return(NDIS_STATUS_SUCCESS
);
1117 __stdcall
static void
1118 ndis_free_mapreg(ndis_handle adapter
)
1120 struct ndis_softc
*sc
;
1121 ndis_miniport_block
*block
;
1124 block
= (ndis_miniport_block
*)adapter
;
1125 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
1127 for (i
= 0; i
< sc
->ndis_mmapcnt
; i
++)
1128 bus_dmamap_destroy(sc
->ndis_mtag
, sc
->ndis_mmaps
[i
]);
1130 kfree(sc
->ndis_mmaps
, M_DEVBUF
);
1132 bus_dma_tag_destroy(sc
->ndis_mtag
);
1138 ndis_mapshared_cb(void *arg
, bus_dma_segment_t
*segs
, int nseg
, int error
)
1142 if (error
|| nseg
> 1)
1147 p
->np_quad
= segs
[0].ds_addr
;
1153 * This maps to bus_dmamem_alloc().
1155 __stdcall
static void
1156 ndis_alloc_sharedmem(ndis_handle adapter
, uint32_t len
, uint8_t cached
,
1157 void **vaddr
, ndis_physaddr
*paddr
)
1159 ndis_miniport_block
*block
;
1160 struct ndis_softc
*sc
;
1161 struct ndis_shmem
*sh
;
1164 if (adapter
== NULL
)
1167 block
= (ndis_miniport_block
*)adapter
;
1168 sc
= (struct ndis_softc
*)(block
->nmb_ifp
);
1170 sh
= kmalloc(sizeof(struct ndis_shmem
), M_DEVBUF
, M_INTWAIT
|M_ZERO
);
1175 * When performing shared memory allocations, create a tag
1176 * with a lowaddr limit that restricts physical memory mappings
1177 * so that they all fall within the first 1GB of memory.
1178 * At least one device/driver combination (Linksys Instant
1179 * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
1180 * problems with performing DMA operations with physical
1181 * that lie above the 1GB mark. I don't know if this is a
1182 * hardware limitation or if the addresses are being truncated
1183 * within the driver, but this seems to be the only way to
1184 * make these cards work reliably in systems with more than
1185 * 1GB of physical memory.
1188 error
= bus_dma_tag_create(sc
->ndis_parent_tag
, 64,
1189 0, NDIS_BUS_SPACE_SHARED_MAXADDR
, BUS_SPACE_MAXADDR
, NULL
,
1190 NULL
, len
, 1, len
, BUS_DMA_ALLOCNOW
,
1194 kfree(sh
, M_DEVBUF
);
1198 error
= bus_dmamem_alloc(sh
->ndis_stag
, vaddr
,
1199 BUS_DMA_NOWAIT
| BUS_DMA_ZERO
, &sh
->ndis_smap
);
1202 bus_dma_tag_destroy(sh
->ndis_stag
);
1203 kfree(sh
, M_DEVBUF
);
1207 error
= bus_dmamap_load(sh
->ndis_stag
, sh
->ndis_smap
, *vaddr
,
1208 len
, ndis_mapshared_cb
, (void *)paddr
, BUS_DMA_NOWAIT
);
1211 bus_dmamem_free(sh
->ndis_stag
, *vaddr
, sh
->ndis_smap
);
1212 bus_dma_tag_destroy(sh
->ndis_stag
);
1213 kfree(sh
, M_DEVBUF
);
1217 sh
->ndis_saddr
= *vaddr
;
1218 sh
->ndis_next
= sc
->ndis_shlist
;
1219 sc
->ndis_shlist
= sh
;
1224 struct ndis_allocwork
{
1225 ndis_handle na_adapter
;
1232 ndis_asyncmem_complete(void *arg
)
1234 ndis_miniport_block
*block
;
1235 struct ndis_softc
*sc
;
1236 struct ndis_allocwork
*w
;
1238 ndis_physaddr paddr
;
1239 ndis_allocdone_handler donefunc
;
1242 block
= (ndis_miniport_block
*)w
->na_adapter
;
1243 sc
= (struct ndis_softc
*)(block
->nmb_ifp
);
1248 donefunc
= sc
->ndis_chars
.nmc_allocate_complete_func
;
1249 ndis_alloc_sharedmem(w
->na_adapter
, w
->na_len
,
1250 w
->na_cached
, &vaddr
, &paddr
);
1251 donefunc(w
->na_adapter
, vaddr
, &paddr
, w
->na_len
, w
->na_ctx
);
1253 kfree(arg
, M_DEVBUF
);
1258 __stdcall
static ndis_status
1259 ndis_alloc_sharedmem_async(ndis_handle adapter
, uint32_t len
,
1260 uint8_t cached
, void *ctx
)
1262 struct ndis_allocwork
*w
;
1264 if (adapter
== NULL
)
1265 return(NDIS_STATUS_FAILURE
);
1267 w
= kmalloc(sizeof(struct ndis_allocwork
), M_TEMP
, M_INTWAIT
);
1270 return(NDIS_STATUS_FAILURE
);
1272 w
->na_adapter
= adapter
;
1273 w
->na_cached
= cached
;
1278 * Pawn this work off on the SWI thread instead of the
1279 * taskqueue thread, because sometimes drivers will queue
1280 * up work items on the taskqueue thread that will block,
1281 * which would prevent the memory allocation from completing
1284 ndis_sched(ndis_asyncmem_complete
, w
, NDIS_SWI
);
1286 return(NDIS_STATUS_PENDING
);
1289 __stdcall
static void
1290 ndis_free_sharedmem(ndis_handle adapter
, uint32_t len
, uint8_t cached
,
1291 void *vaddr
, ndis_physaddr paddr
)
1293 ndis_miniport_block
*block
;
1294 struct ndis_softc
*sc
;
1295 struct ndis_shmem
*sh
, *prev
;
1297 if (vaddr
== NULL
|| adapter
== NULL
)
1300 block
= (ndis_miniport_block
*)adapter
;
1301 sc
= (struct ndis_softc
*)(block
->nmb_ifp
);
1302 sh
= prev
= sc
->ndis_shlist
;
1305 if (sh
->ndis_saddr
== vaddr
)
1311 bus_dmamap_unload(sh
->ndis_stag
, sh
->ndis_smap
);
1312 bus_dmamem_free(sh
->ndis_stag
, vaddr
, sh
->ndis_smap
);
1313 bus_dma_tag_destroy(sh
->ndis_stag
);
1315 if (sh
== sc
->ndis_shlist
)
1316 sc
->ndis_shlist
= sh
->ndis_next
;
1318 prev
->ndis_next
= sh
->ndis_next
;
1320 kfree(sh
, M_DEVBUF
);
1325 __stdcall
static ndis_status
1326 ndis_map_iospace(void **vaddr
, ndis_handle adapter
, ndis_physaddr paddr
,
1329 ndis_miniport_block
*block
;
1330 struct ndis_softc
*sc
;
1332 if (adapter
== NULL
)
1333 return(NDIS_STATUS_FAILURE
);
1335 block
= (ndis_miniport_block
*)adapter
;
1336 sc
= (struct ndis_softc
*)(block
->nmb_ifp
);
1338 if (sc
->ndis_res_mem
!= NULL
&&
1339 paddr
.np_quad
== rman_get_start(sc
->ndis_res_mem
))
1340 *vaddr
= (void *)rman_get_virtual(sc
->ndis_res_mem
);
1341 else if (sc
->ndis_res_altmem
!= NULL
&&
1342 paddr
.np_quad
== rman_get_start(sc
->ndis_res_altmem
))
1343 *vaddr
= (void *)rman_get_virtual(sc
->ndis_res_altmem
);
1344 else if (sc
->ndis_res_am
!= NULL
&&
1345 paddr
.np_quad
== rman_get_start(sc
->ndis_res_am
))
1346 *vaddr
= (void *)rman_get_virtual(sc
->ndis_res_am
);
1348 return(NDIS_STATUS_FAILURE
);
1350 return(NDIS_STATUS_SUCCESS
);
1353 __stdcall
static void
1354 ndis_unmap_iospace(ndis_handle adapter
, void *vaddr
, uint32_t len
)
1359 __stdcall
static uint32_t
1360 ndis_cachefill(void)
1365 __stdcall
static uint32_t
1366 ndis_dma_align(ndis_handle handle
)
1372 * NDIS has two methods for dealing with NICs that support DMA.
1373 * One is to just pass packets to the driver and let it call
1374 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1375 * all by itself, and the other is to let the NDIS library handle the
1376 * buffer mapping internally, and hand the driver an already populated
1377 * scatter/gather fragment list. If the driver calls
1378 * NdisMInitializeScatterGatherDma(), it wants to use the latter
1382 __stdcall
static ndis_status
1383 ndis_init_sc_dma(ndis_handle adapter
, uint8_t is64
, uint32_t maxphysmap
)
1385 struct ndis_softc
*sc
;
1386 ndis_miniport_block
*block
;
1389 if (adapter
== NULL
)
1390 return(NDIS_STATUS_FAILURE
);
1391 block
= (ndis_miniport_block
*)adapter
;
1392 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
1394 /* Don't do this twice. */
1395 if (sc
->ndis_sc
== 1)
1396 return(NDIS_STATUS_SUCCESS
);
1398 error
= bus_dma_tag_create(sc
->ndis_parent_tag
, ETHER_ALIGN
, 0,
1399 BUS_SPACE_MAXADDR_32BIT
, BUS_SPACE_MAXADDR
, NULL
, NULL
,
1400 MCLBYTES
* NDIS_MAXSEG
, NDIS_MAXSEG
, MCLBYTES
, BUS_DMA_ALLOCNOW
,
1405 return(NDIS_STATUS_SUCCESS
);
1408 __stdcall
static void
1409 ndis_alloc_packetpool(ndis_status
*status
, ndis_handle
*pool
,
1410 uint32_t descnum
, uint32_t protrsvdlen
)
1415 *pool
= kmalloc(sizeof(ndis_packet
) *
1416 ((descnum
+ NDIS_POOL_EXTRA
) + 1),
1417 M_DEVBUF
, M_WAITOK
|M_ZERO
);
1418 cur
= (ndis_packet
*)*pool
;
1419 cur
->np_private
.npp_flags
= 0x1; /* mark the head of the list */
1420 cur
->np_private
.npp_totlen
= 0; /* init deletetion flag */
1421 for (i
= 0; i
< (descnum
+ NDIS_POOL_EXTRA
); i
++) {
1422 cur
->np_private
.npp_head
= (ndis_handle
)(cur
+ 1);
1426 *status
= NDIS_STATUS_SUCCESS
;
1430 __stdcall
static void
1431 ndis_ex_alloc_packetpool(ndis_status
*status
, ndis_handle
*pool
,
1432 uint32_t descnum
, uint32_t oflowdescnum
,
1433 uint32_t protrsvdlen
)
1435 return(ndis_alloc_packetpool(status
, pool
,
1436 descnum
+ oflowdescnum
, protrsvdlen
));
1439 __stdcall
static uint32_t
1440 ndis_packetpool_use(ndis_handle pool
)
1444 head
= (ndis_packet
*)pool
;
1446 return(head
->np_private
.npp_count
);
1449 __stdcall
static void
1450 ndis_free_packetpool(ndis_handle pool
)
1456 /* Mark this pool as 'going away.' */
1458 head
->np_private
.npp_totlen
= 1;
1460 /* If there are no buffers loaned out, destroy the pool. */
1462 if (head
->np_private
.npp_count
== 0)
1463 kfree(pool
, M_DEVBUF
);
1465 kprintf("NDIS: buggy driver deleting active packet pool!\n");
1470 __stdcall
static void
1471 ndis_alloc_packet(ndis_status
*status
, ndis_packet
**packet
, ndis_handle pool
)
1473 ndis_packet
*head
, *pkt
;
1475 head
= (ndis_packet
*)pool
;
1477 if (head
->np_private
.npp_flags
!= 0x1) {
1478 *status
= NDIS_STATUS_FAILURE
;
1483 * If this pool is marked as 'going away' don't allocate any
1484 * more packets out of it.
1487 if (head
->np_private
.npp_totlen
) {
1488 *status
= NDIS_STATUS_FAILURE
;
1492 pkt
= (ndis_packet
*)head
->np_private
.npp_head
;
1495 *status
= NDIS_STATUS_RESOURCES
;
1499 head
->np_private
.npp_head
= pkt
->np_private
.npp_head
;
1501 pkt
->np_private
.npp_head
= pkt
->np_private
.npp_tail
= NULL
;
1502 /* Save pointer to the pool. */
1503 pkt
->np_private
.npp_pool
= head
;
1505 /* Set the oob offset pointer. Lots of things expect this. */
1506 pkt
->np_private
.npp_packetooboffset
=
1507 offsetof(ndis_packet
, np_oob
);
1510 * We must initialize the packet flags correctly in order
1511 * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
1512 * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() to work correctly.
1514 pkt
->np_private
.npp_ndispktflags
= NDIS_PACKET_ALLOCATED_BY_NDIS
;
1518 head
->np_private
.npp_count
++;
1519 *status
= NDIS_STATUS_SUCCESS
;
1523 __stdcall
static void
1524 ndis_release_packet(ndis_packet
*packet
)
1528 if (packet
== NULL
|| packet
->np_private
.npp_pool
== NULL
)
1531 head
= packet
->np_private
.npp_pool
;
1532 if (head
->np_private
.npp_flags
!= 0x1)
1535 packet
->np_private
.npp_head
= head
->np_private
.npp_head
;
1536 head
->np_private
.npp_head
= (ndis_buffer
*)packet
;
1537 head
->np_private
.npp_count
--;
1540 * If the pool has been marked for deletion and there are
1541 * no more packets outstanding, nuke the pool.
1544 if (head
->np_private
.npp_totlen
&& head
->np_private
.npp_count
== 0)
1545 kfree(head
, M_DEVBUF
);
1550 __stdcall
static void
1551 ndis_unchain_headbuf(ndis_packet
*packet
, ndis_buffer
**buf
)
1553 ndis_packet_private
*priv
;
1555 if (packet
== NULL
|| buf
== NULL
)
1558 priv
= &packet
->np_private
;
1560 priv
->npp_validcounts
= FALSE
;
1562 if (priv
->npp_head
== priv
->npp_tail
) {
1563 *buf
= priv
->npp_head
;
1564 priv
->npp_head
= priv
->npp_tail
= NULL
;
1566 *buf
= priv
->npp_head
;
1567 priv
->npp_head
= (*buf
)->nb_next
;
1573 __stdcall
static void
1574 ndis_unchain_tailbuf(ndis_packet
*packet
, ndis_buffer
**buf
)
1576 ndis_packet_private
*priv
;
1579 if (packet
== NULL
|| buf
== NULL
)
1582 priv
= &packet
->np_private
;
1584 priv
->npp_validcounts
= FALSE
;
1586 if (priv
->npp_head
== priv
->npp_tail
) {
1587 *buf
= priv
->npp_head
;
1588 priv
->npp_head
= priv
->npp_tail
= NULL
;
1590 *buf
= priv
->npp_tail
;
1591 tmp
= priv
->npp_head
;
1592 while (tmp
->nb_next
!= priv
->npp_tail
)
1594 priv
->npp_tail
= tmp
;
1595 tmp
->nb_next
= NULL
;
1602 * The NDIS "buffer" manipulation functions are somewhat misnamed.
1603 * They don't really allocate buffers: they allocate buffer mappings.
1604 * The idea is you reserve a chunk of DMA-able memory using
1605 * NdisMAllocateSharedMemory() and then use NdisAllocateBuffer()
1606 * to obtain the virtual address of the DMA-able region.
1607 * ndis_alloc_bufpool() is analagous to bus_dma_tag_create().
1610 __stdcall
static void
1611 ndis_alloc_bufpool(ndis_status
*status
, ndis_handle
*pool
,
1617 *pool
= kmalloc(sizeof(ndis_buffer
) *
1618 ((descnum
+ NDIS_POOL_EXTRA
) + 1),
1619 M_DEVBUF
, M_WAITOK
|M_ZERO
);
1620 cur
= (ndis_buffer
*)*pool
;
1621 cur
->nb_flags
= 0x1; /* mark the head of the list */
1622 cur
->nb_bytecount
= 0; /* init usage count */
1623 cur
->nb_byteoffset
= 0; /* init deletetion flag */
1624 for (i
= 0; i
< (descnum
+ NDIS_POOL_EXTRA
); i
++) {
1625 cur
->nb_next
= cur
+ 1;
1629 *status
= NDIS_STATUS_SUCCESS
;
1633 __stdcall
static void
1634 ndis_free_bufpool(ndis_handle pool
)
1640 /* Mark this pool as 'going away.' */
1642 head
->nb_byteoffset
= 1;
1644 /* If there are no buffers loaned out, destroy the pool. */
1645 if (head
->nb_bytecount
== 0)
1646 kfree(pool
, M_DEVBUF
);
1648 kprintf("NDIS: buggy driver deleting active buffer pool!\n");
1654 * This maps to a bus_dmamap_create() and bus_dmamap_load().
1656 __stdcall
static void
1657 ndis_alloc_buf(ndis_status
*status
, ndis_buffer
**buffer
, ndis_handle pool
,
1658 void *vaddr
, uint32_t len
)
1660 ndis_buffer
*head
, *buf
;
1662 head
= (ndis_buffer
*)pool
;
1663 if (head
->nb_flags
!= 0x1) {
1664 *status
= NDIS_STATUS_FAILURE
;
1669 * If this pool is marked as 'going away' don't allocate any
1670 * more buffers out of it.
1673 if (head
->nb_byteoffset
) {
1674 *status
= NDIS_STATUS_FAILURE
;
1678 buf
= head
->nb_next
;
1681 *status
= NDIS_STATUS_RESOURCES
;
1685 head
->nb_next
= buf
->nb_next
;
1687 /* Save pointer to the pool. */
1688 buf
->nb_process
= head
;
1690 MDL_INIT(buf
, vaddr
, len
);
1694 /* Increment count of busy buffers. */
1696 head
->nb_bytecount
++;
1698 *status
= NDIS_STATUS_SUCCESS
;
1702 __stdcall
static void
1703 ndis_release_buf(ndis_buffer
*buf
)
1707 if (buf
== NULL
|| buf
->nb_process
== NULL
)
1710 head
= buf
->nb_process
;
1712 if (head
->nb_flags
!= 0x1)
1715 buf
->nb_next
= head
->nb_next
;
1716 head
->nb_next
= buf
;
1718 /* Decrement count of busy buffers. */
1720 head
->nb_bytecount
--;
1723 * If the pool has been marked for deletion and there are
1724 * no more buffers outstanding, nuke the pool.
1727 if (head
->nb_byteoffset
&& head
->nb_bytecount
== 0)
1728 kfree(head
, M_DEVBUF
);
1735 __stdcall
static uint32_t
1736 ndis_buflen(ndis_buffer
*buf
)
1738 return(buf
->nb_bytecount
);
1742 * Get the virtual address and length of a buffer.
1743 * Note: the vaddr argument is optional.
1746 __stdcall
static void
1747 ndis_query_buf(ndis_buffer
*buf
, void **vaddr
, uint32_t *len
)
1750 *vaddr
= MDL_VA(buf
);
1751 *len
= buf
->nb_bytecount
;
1756 /* Same as above -- we don't care about the priority. */
1758 __stdcall
static void
1759 ndis_query_buf_safe(ndis_buffer
*buf
, void **vaddr
,
1760 uint32_t *len
, uint32_t prio
)
1763 *vaddr
= MDL_VA(buf
);
1764 *len
= buf
->nb_bytecount
;
1769 /* Damnit Microsoft!! How many ways can you do the same thing?! */
1771 __stdcall
static void *
1772 ndis_buf_vaddr(ndis_buffer
*buf
)
1774 return(MDL_VA(buf
));
1777 __stdcall
static void *
1778 ndis_buf_vaddr_safe(ndis_buffer
*buf
, uint32_t prio
)
1780 return(MDL_VA(buf
));
1783 __stdcall
static void
1784 ndis_adjust_buflen(ndis_buffer
*buf
, int len
)
1786 buf
->nb_bytecount
= len
;
1791 __stdcall
static uint32_t
1792 ndis_interlock_inc(uint32_t *addend
)
1794 atomic_add_long((u_long
*)addend
, 1);
1798 __stdcall
static uint32_t
1799 ndis_interlock_dec(uint32_t *addend
)
1801 atomic_subtract_long((u_long
*)addend
, 1);
1805 __stdcall
static void
1806 ndis_init_event(ndis_event
*event
)
1809 * NDIS events are always notification
1810 * events, and should be initialized to the
1811 * not signaled state.
1814 ntoskrnl_init_event(&event
->ne_event
, EVENT_TYPE_NOTIFY
, FALSE
);
1818 __stdcall
static void
1819 ndis_set_event(ndis_event
*event
)
1821 ntoskrnl_set_event(&event
->ne_event
, 0, 0);
1825 __stdcall
static void
1826 ndis_reset_event(ndis_event
*event
)
1828 ntoskrnl_reset_event(&event
->ne_event
);
1832 __stdcall
static uint8_t
1833 ndis_wait_event(ndis_event
*event
, uint32_t msecs
)
1838 duetime
= ((int64_t)msecs
* -10000);
1840 rval
= ntoskrnl_waitforobj((nt_dispatch_header
*)event
,
1841 0, 0, TRUE
, msecs
? &duetime
: NULL
);
1843 if (rval
== STATUS_TIMEOUT
)
1849 __stdcall
static ndis_status
1850 ndis_unicode2ansi(ndis_ansi_string
*dstr
, ndis_unicode_string
*sstr
)
1852 if (dstr
== NULL
|| sstr
== NULL
)
1853 return(NDIS_STATUS_FAILURE
);
1854 if (ndis_unicode_to_ascii(sstr
->nus_buf
,
1855 sstr
->nus_len
, &dstr
->nas_buf
))
1856 return(NDIS_STATUS_FAILURE
);
1857 dstr
->nas_len
= dstr
->nas_maxlen
= strlen(dstr
->nas_buf
);
1858 return (NDIS_STATUS_SUCCESS
);
1861 __stdcall
static ndis_status
1862 ndis_ansi2unicode(ndis_unicode_string
*dstr
, ndis_ansi_string
*sstr
)
1865 if (dstr
== NULL
|| sstr
== NULL
)
1866 return(NDIS_STATUS_FAILURE
);
1867 str
= kmalloc(sstr
->nas_len
+ 1, M_DEVBUF
, M_WAITOK
);
1868 strncpy(str
, sstr
->nas_buf
, sstr
->nas_len
);
1869 *(str
+ sstr
->nas_len
) = '\0';
1870 if (ndis_ascii_to_unicode(str
, &dstr
->nus_buf
)) {
1871 kfree(str
, M_DEVBUF
);
1872 return(NDIS_STATUS_FAILURE
);
1874 dstr
->nus_len
= dstr
->nus_maxlen
= sstr
->nas_len
* 2;
1875 kfree(str
, M_DEVBUF
);
1876 return (NDIS_STATUS_SUCCESS
);
1879 __stdcall
static ndis_status
1880 ndis_assign_pcirsrc(ndis_handle adapter
, uint32_t slot
,
1881 ndis_resource_list
**list
)
1883 ndis_miniport_block
*block
;
1885 if (adapter
== NULL
|| list
== NULL
)
1886 return (NDIS_STATUS_FAILURE
);
1888 block
= (ndis_miniport_block
*)adapter
;
1889 *list
= block
->nmb_rlist
;
1891 return (NDIS_STATUS_SUCCESS
);
1894 __stdcall
static ndis_status
1895 ndis_register_intr(ndis_miniport_interrupt
*intr
, ndis_handle adapter
,
1896 uint32_t ivec
, uint32_t ilevel
, uint8_t reqisr
,
1897 uint8_t shared
, ndis_interrupt_mode imode
)
1899 ndis_miniport_block
*block
;
1903 intr
->ni_block
= adapter
;
1904 intr
->ni_isrreq
= reqisr
;
1905 intr
->ni_shared
= shared
;
1906 block
->nmb_interrupt
= intr
;
1907 return(NDIS_STATUS_SUCCESS
);
1910 __stdcall
static void
1911 ndis_deregister_intr(ndis_miniport_interrupt
*intr
)
1916 __stdcall
static void
1917 ndis_register_shutdown(ndis_handle adapter
, void *shutdownctx
,
1918 ndis_shutdown_handler shutdownfunc
)
1920 ndis_miniport_block
*block
;
1921 ndis_miniport_characteristics
*chars
;
1922 struct ndis_softc
*sc
;
1924 if (adapter
== NULL
)
1927 block
= (ndis_miniport_block
*)adapter
;
1928 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
1929 chars
= &sc
->ndis_chars
;
1931 chars
->nmc_shutdown_handler
= shutdownfunc
;
1932 chars
->nmc_rsvd0
= shutdownctx
;
1937 __stdcall
static void
1938 ndis_deregister_shutdown(ndis_handle adapter
)
1940 ndis_miniport_block
*block
;
1941 ndis_miniport_characteristics
*chars
;
1942 struct ndis_softc
*sc
;
1944 if (adapter
== NULL
)
1947 block
= (ndis_miniport_block
*)adapter
;
1948 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
1949 chars
= &sc
->ndis_chars
;
1951 chars
->nmc_shutdown_handler
= NULL
;
1952 chars
->nmc_rsvd0
= NULL
;
1957 __stdcall
static uint32_t
1958 ndis_numpages(ndis_buffer
*buf
)
1962 if (buf
->nb_bytecount
== 0)
1964 return(SPAN_PAGES(MDL_VA(buf
), buf
->nb_bytecount
));
1967 __stdcall
static void
1968 ndis_buf_physpages(ndis_buffer
*buf
, uint32_t *pages
)
1973 *pages
= ndis_numpages(buf
);
1977 __stdcall
static void
1978 ndis_query_bufoffset(ndis_buffer
*buf
, uint32_t *off
, uint32_t *len
)
1983 *off
= buf
->nb_byteoffset
;
1984 *len
= buf
->nb_bytecount
;
1989 __stdcall
static void
1990 ndis_sleep(uint32_t usecs
)
1997 ndis_thsuspend(curthread
, 1 + usecs
* hz
/ 1000000);
2002 __stdcall
static uint32_t
2003 ndis_read_pccard_amem(ndis_handle handle
, uint32_t offset
, void *buf
,
2006 struct ndis_softc
*sc
;
2007 ndis_miniport_block
*block
;
2008 bus_space_handle_t bh
;
2016 block
= (ndis_miniport_block
*)handle
;
2017 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
2020 bh
= rman_get_bushandle(sc
->ndis_res_am
);
2021 bt
= rman_get_bustag(sc
->ndis_res_am
);
2023 for (i
= 0; i
< len
; i
++)
2024 dest
[i
] = bus_space_read_1(bt
, bh
, (offset
+ i
) * 2);
2029 __stdcall
static uint32_t
2030 ndis_write_pccard_amem(ndis_handle handle
, uint32_t offset
, void *buf
,
2033 struct ndis_softc
*sc
;
2034 ndis_miniport_block
*block
;
2035 bus_space_handle_t bh
;
2043 block
= (ndis_miniport_block
*)handle
;
2044 sc
= (struct ndis_softc
*)block
->nmb_ifp
;
2047 bh
= rman_get_bushandle(sc
->ndis_res_am
);
2048 bt
= rman_get_bustag(sc
->ndis_res_am
);
2050 for (i
= 0; i
< len
; i
++)
2051 bus_space_write_1(bt
, bh
, (offset
+ i
) * 2, src
[i
]);
2056 __stdcall
static list_entry
*
2057 ndis_insert_head(list_entry
*head
, list_entry
*entry
, ndis_spin_lock
*lock
)
2061 lock
->nsl_kirql
= FASTCALL2(hal_lock
,
2062 &lock
->nsl_spinlock
, DISPATCH_LEVEL
);
2063 flink
= head
->nle_flink
;
2064 entry
->nle_flink
= flink
;
2065 entry
->nle_blink
= head
;
2066 flink
->nle_blink
= entry
;
2067 head
->nle_flink
= entry
;
2068 FASTCALL2(hal_unlock
, &lock
->nsl_spinlock
, lock
->nsl_kirql
);
2073 __stdcall
static list_entry
*
2074 ndis_remove_head(list_entry
*head
, ndis_spin_lock
*lock
)
2079 lock
->nsl_kirql
= FASTCALL2(hal_lock
,
2080 &lock
->nsl_spinlock
, DISPATCH_LEVEL
);
2081 entry
= head
->nle_flink
;
2082 flink
= entry
->nle_flink
;
2083 head
->nle_flink
= flink
;
2084 flink
->nle_blink
= head
;
2085 FASTCALL2(hal_unlock
, &lock
->nsl_spinlock
, lock
->nsl_kirql
);
2090 __stdcall
static list_entry
*
2091 ndis_insert_tail(list_entry
*head
, list_entry
*entry
, ndis_spin_lock
*lock
)
2095 lock
->nsl_kirql
= FASTCALL2(hal_lock
,
2096 &lock
->nsl_spinlock
, DISPATCH_LEVEL
);
2097 blink
= head
->nle_blink
;
2098 entry
->nle_flink
= head
;
2099 entry
->nle_blink
= blink
;
2100 blink
->nle_flink
= entry
;
2101 head
->nle_blink
= entry
;
2102 FASTCALL2(hal_unlock
, &lock
->nsl_spinlock
, lock
->nsl_kirql
);
2107 __stdcall
static uint8_t
2108 ndis_sync_with_intr(ndis_miniport_interrupt
*intr
, void *syncfunc
,
2111 struct ndis_softc
*sc
;
2113 __stdcall
uint8_t (*sync
)(void *);
2116 if (syncfunc
== NULL
|| syncctx
== NULL
)
2119 sc
= (struct ndis_softc
*)intr
->ni_block
->nmb_ifp
;
2120 ifp
= &sc
->arpcom
.ac_if
;
2122 rval
= sync(syncctx
);
2128 * Return the number of 100 nanosecond intervals since
2129 * January 1, 1601. (?!?!)
2131 __stdcall
static void
2132 ndis_time(uint64_t *tval
)
2137 *tval
= (uint64_t)ts
.tv_nsec
/ 100 + (uint64_t)ts
.tv_sec
* 10000000 +
2144 * Return the number of milliseconds since the system booted.
2146 __stdcall
static void
2147 ndis_uptime(uint32_t *tval
)
2152 *tval
= ts
.tv_nsec
/ 1000000 + ts
.tv_sec
* 1000;
2157 __stdcall
static void
2158 ndis_init_string(ndis_unicode_string
*dst
, char *src
)
2160 ndis_unicode_string
*u
;
2164 if (ndis_ascii_to_unicode(src
, &u
->nus_buf
))
2166 u
->nus_len
= u
->nus_maxlen
= strlen(src
) * 2;
2170 __stdcall
static void
2171 ndis_free_string(ndis_unicode_string
*str
)
2175 if (str
->nus_buf
!= NULL
)
2176 kfree(str
->nus_buf
, M_DEVBUF
);
2177 kfree(str
, M_DEVBUF
);
2181 __stdcall
static ndis_status
2182 ndis_remove_miniport(ndis_handle
*adapter
)
2184 return(NDIS_STATUS_SUCCESS
);
2187 __stdcall
static void
2188 ndis_init_ansi_string(ndis_ansi_string
*dst
, char *src
)
2190 ndis_ansi_string
*a
;
2196 a
->nas_len
= a
->nas_maxlen
= 0;
2200 a
->nas_len
= a
->nas_maxlen
= strlen(src
);
2206 __stdcall
static void
2207 ndis_init_unicode_string(ndis_unicode_string
*dst
, uint16_t *src
)
2209 ndis_unicode_string
*u
;
2216 u
->nus_len
= u
->nus_maxlen
= 0;
2223 u
->nus_len
= u
->nus_maxlen
= i
* 2;
2229 __stdcall
static void
2230 ndis_get_devprop(ndis_handle adapter
, device_object
**phydevobj
,
2231 device_object
**funcdevobj
, device_object
**nextdevobj
,
2232 cm_resource_list
*resources
, cm_resource_list
*transresources
)
2234 ndis_miniport_block
*block
;
2236 block
= (ndis_miniport_block
*)adapter
;
2238 if (phydevobj
!= NULL
)
2239 *phydevobj
= &block
->nmb_devobj
;
2240 if (funcdevobj
!= NULL
)
2241 *funcdevobj
= &block
->nmb_devobj
;
2246 __stdcall
static void
2247 ndis_firstbuf(ndis_packet
*packet
, ndis_buffer
**buf
, void **firstva
,
2248 uint32_t *firstlen
, uint32_t *totlen
)
2252 tmp
= packet
->np_private
.npp_head
;
2256 *firstlen
= *totlen
= 0;
2258 *firstva
= MDL_VA(tmp
);
2259 *firstlen
= *totlen
= tmp
->nb_bytecount
;
2260 for (tmp
= tmp
->nb_next
; tmp
!= NULL
; tmp
= tmp
->nb_next
)
2261 *totlen
+= tmp
->nb_bytecount
;
2267 __stdcall
static void
2268 ndis_firstbuf_safe(ndis_packet
*packet
, ndis_buffer
**buf
, void **firstva
,
2269 uint32_t *firstlen
, uint32_t *totlen
, uint32_t prio
)
2271 ndis_firstbuf(packet
, buf
, firstva
, firstlen
, totlen
);
2274 /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2275 __stdcall
static void
2276 ndis_open_file(ndis_status
*status
, ndis_handle
*filehandle
, uint32_t *filelength
,
2277 ndis_unicode_string
*filename
, ndis_physaddr highestaddr
)
2279 char *afilename
= NULL
;
2280 struct nlookupdata nd
;
2283 struct vattr
*vap
= &vat
;
2286 char path
[MAXPATHLEN
];
2288 ndis_unicode_to_ascii(filename
->nus_buf
,
2289 filename
->nus_len
, &afilename
);
2291 ksprintf(path
, "%s/%s", ndis_filepath
, afilename
);
2292 kfree(afilename
, M_DEVBUF
);
2294 fh
= kmalloc(sizeof(ndis_fh
), M_TEMP
, M_WAITOK
);
2296 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
|NLC_LOCKVP
);
2298 error
= vn_open(&nd
, NULL
, FREAD
, 0);
2300 *status
= NDIS_STATUS_FILE_NOT_FOUND
;
2302 kprintf("NDIS: open file %s failed: %d\n", path
, error
);
2307 nd
.nl_open_vp
= NULL
;
2309 /* Get the file size. */
2310 VOP_GETATTR(vp
, vap
);
2316 *filelength
= fh
->nf_maplen
= vap
->va_size
& 0xFFFFFFFF;
2317 *status
= NDIS_STATUS_SUCCESS
;
2324 __stdcall
static void
2325 ndis_map_file(ndis_status
*status
, void **mappedbuffer
, ndis_handle filehandle
)
2330 if (filehandle
== NULL
) {
2331 *status
= NDIS_STATUS_FAILURE
;
2335 fh
= (ndis_fh
*)filehandle
;
2337 if (fh
->nf_vp
== NULL
) {
2338 *status
= NDIS_STATUS_FAILURE
;
2342 if (fh
->nf_map
!= NULL
) {
2343 *status
= NDIS_STATUS_ALREADY_MAPPED
;
2347 fh
->nf_map
= kmalloc(fh
->nf_maplen
, M_DEVBUF
, M_WAITOK
);
2349 error
= vn_rdwr(UIO_READ
, fh
->nf_vp
, fh
->nf_map
, fh
->nf_maplen
, 0,
2350 UIO_SYSSPACE
, 0, proc0
.p_ucred
, &resid
);
2353 *status
= NDIS_STATUS_FAILURE
;
2355 *status
= NDIS_STATUS_SUCCESS
;
2356 *mappedbuffer
= fh
->nf_map
;
2362 __stdcall
static void
2363 ndis_unmap_file(ndis_handle filehandle
)
2366 fh
= (ndis_fh
*)filehandle
;
2368 if (fh
->nf_map
== NULL
)
2370 kfree(fh
->nf_map
, M_DEVBUF
);
2376 __stdcall
static void
2377 ndis_close_file(ndis_handle filehandle
)
2381 if (filehandle
== NULL
)
2384 fh
= (ndis_fh
*)filehandle
;
2385 if (fh
->nf_map
!= NULL
) {
2386 kfree(fh
->nf_map
, M_DEVBUF
);
2390 if (fh
->nf_vp
== NULL
)
2393 vn_close(fh
->nf_vp
, FREAD
);
2396 kfree(fh
, M_DEVBUF
);
2401 __stdcall
static uint8_t
2407 typedef __stdcall
void (*ndis_statusdone_handler
)(ndis_handle
);
2408 typedef __stdcall
void (*ndis_status_handler
)(ndis_handle
, ndis_status
,
2411 __stdcall
static void
2412 ndis_ind_statusdone(ndis_handle adapter
)
2414 ndis_miniport_block
*block
;
2415 ndis_statusdone_handler statusdonefunc
;
2417 block
= (ndis_miniport_block
*)adapter
;
2418 statusdonefunc
= block
->nmb_statusdone_func
;
2420 statusdonefunc(adapter
);
2424 __stdcall
static void
2425 ndis_ind_status(ndis_handle adapter
, ndis_status status
, void *sbuf
,
2428 ndis_miniport_block
*block
;
2429 ndis_status_handler statusfunc
;
2431 block
= (ndis_miniport_block
*)adapter
;
2432 statusfunc
= block
->nmb_status_func
;
2434 statusfunc(adapter
, status
, sbuf
, slen
);
2439 ndis_workfunc(void *ctx
)
2441 ndis_work_item
*work
;
2445 workfunc
= work
->nwi_func
;
2446 workfunc(work
, work
->nwi_ctx
);
2450 __stdcall
static ndis_status
2451 ndis_sched_workitem(ndis_work_item
*work
)
2453 ndis_sched(ndis_workfunc
, work
, NDIS_TASKQUEUE
);
2454 return(NDIS_STATUS_SUCCESS
);
2457 __stdcall
static void
2458 ndis_pkt_to_pkt(ndis_packet
*dpkt
, uint32_t doff
, uint32_t reqlen
,
2459 ndis_packet
*spkt
, uint32_t soff
, uint32_t *cpylen
)
2461 ndis_buffer
*src
, *dst
;
2463 int resid
, copied
, len
, scnt
, dcnt
;
2467 src
= spkt
->np_private
.npp_head
;
2468 dst
= dpkt
->np_private
.npp_head
;
2472 scnt
= src
->nb_bytecount
;
2473 dcnt
= dst
->nb_bytecount
;
2476 if (src
->nb_bytecount
> soff
) {
2478 scnt
= src
->nb_bytecount
- soff
;
2481 soff
-= src
->nb_bytecount
;
2489 if (dst
->nb_bytecount
> doff
) {
2491 dcnt
= dst
->nb_bytecount
- doff
;
2494 doff
-= dst
->nb_bytecount
;
2512 bcopy(sptr
, dptr
, len
);
2525 dcnt
= dst
->nb_bytecount
;
2534 scnt
= src
->nb_bytecount
;
2542 __stdcall
static void
2543 ndis_pkt_to_pkt_safe(ndis_packet
*dpkt
, uint32_t doff
, uint32_t reqlen
,
2544 ndis_packet
*spkt
, uint32_t soff
, uint32_t *cpylen
,
2547 ndis_pkt_to_pkt(dpkt
, doff
, reqlen
, spkt
, soff
, cpylen
);
2551 __stdcall
static ndis_status
2552 ndis_register_dev(ndis_handle handle
, ndis_unicode_string
*devname
,
2553 ndis_unicode_string
*symname
, driver_dispatch
**majorfuncs
,
2554 void **devobj
, ndis_handle
*devhandle
)
2556 ndis_miniport_block
*block
;
2558 block
= (ndis_miniport_block
*)handle
;
2559 *devobj
= &block
->nmb_devobj
;
2560 *devhandle
= handle
;
2562 return(NDIS_STATUS_SUCCESS
);
2565 __stdcall
static ndis_status
2566 ndis_deregister_dev(ndis_handle handle
)
2568 return(NDIS_STATUS_SUCCESS
);
2571 __stdcall
static ndis_status
2572 ndis_query_name(ndis_unicode_string
*name
, ndis_handle handle
)
2574 ndis_miniport_block
*block
;
2576 block
= (ndis_miniport_block
*)handle
;
2577 ndis_ascii_to_unicode(__DECONST(char *,
2578 device_get_nameunit(block
->nmb_dev
)), &name
->nus_buf
);
2579 name
->nus_len
= strlen(device_get_nameunit(block
->nmb_dev
)) * 2;
2581 return(NDIS_STATUS_SUCCESS
);
2584 __stdcall
static void
2585 ndis_register_unload(ndis_handle handle
, void *func
)
2590 __stdcall
static void
2593 kprintf ("NDIS dummy called...\n");
2597 image_patch_table ndis_functbl
[] = {
2598 { "NdisCopyFromPacketToPacket", (FUNC
)ndis_pkt_to_pkt
},
2599 { "NdisCopyFromPacketToPacketSafe", (FUNC
)ndis_pkt_to_pkt_safe
},
2600 { "NdisScheduleWorkItem", (FUNC
)ndis_sched_workitem
},
2601 { "NdisMIndicateStatusComplete", (FUNC
)ndis_ind_statusdone
},
2602 { "NdisMIndicateStatus", (FUNC
)ndis_ind_status
},
2603 { "NdisSystemProcessorCount", (FUNC
)ndis_cpu_cnt
},
2604 { "NdisUnchainBufferAtBack", (FUNC
)ndis_unchain_tailbuf
, },
2605 { "NdisGetFirstBufferFromPacket", (FUNC
)ndis_firstbuf
},
2606 { "NdisGetFirstBufferFromPacketSafe", (FUNC
)ndis_firstbuf_safe
},
2607 { "NdisGetBufferPhysicalArraySize", (FUNC
)ndis_buf_physpages
},
2608 { "NdisMGetDeviceProperty", (FUNC
)ndis_get_devprop
},
2609 { "NdisInitAnsiString", (FUNC
)ndis_init_ansi_string
},
2610 { "NdisInitUnicodeString", (FUNC
)ndis_init_unicode_string
},
2611 { "NdisWriteConfiguration", (FUNC
)ndis_write_cfg
},
2612 { "NdisAnsiStringToUnicodeString", (FUNC
)ndis_ansi2unicode
},
2613 { "NdisTerminateWrapper", (FUNC
)ndis_termwrap
},
2614 { "NdisOpenConfigurationKeyByName", (FUNC
)ndis_open_cfgbyname
},
2615 { "NdisOpenConfigurationKeyByIndex", (FUNC
)ndis_open_cfgbyidx
},
2616 { "NdisMRemoveMiniport", (FUNC
)ndis_remove_miniport
},
2617 { "NdisInitializeString", (FUNC
)ndis_init_string
},
2618 { "NdisFreeString", (FUNC
)ndis_free_string
},
2619 { "NdisGetCurrentSystemTime", (FUNC
)ndis_time
},
2620 { "NdisGetSystemUpTime", (FUNC
)ndis_uptime
},
2621 { "NdisMSynchronizeWithInterrupt", (FUNC
)ndis_sync_with_intr
},
2622 { "NdisMAllocateSharedMemoryAsync", (FUNC
)ndis_alloc_sharedmem_async
},
2623 { "NdisInterlockedInsertHeadList", (FUNC
)ndis_insert_head
},
2624 { "NdisInterlockedInsertTailList", (FUNC
)ndis_insert_tail
},
2625 { "NdisInterlockedRemoveHeadList", (FUNC
)ndis_remove_head
},
2626 { "NdisInitializeWrapper", (FUNC
)ndis_initwrap
},
2627 { "NdisMRegisterMiniport", (FUNC
)ndis_register_miniport
},
2628 { "NdisAllocateMemoryWithTag", (FUNC
)ndis_malloc_withtag
},
2629 { "NdisAllocateMemory", (FUNC
)ndis_malloc
},
2630 { "NdisMSetAttributesEx", (FUNC
)ndis_setattr_ex
},
2631 { "NdisCloseConfiguration", (FUNC
)ndis_close_cfg
},
2632 { "NdisReadConfiguration", (FUNC
)ndis_read_cfg
},
2633 { "NdisOpenConfiguration", (FUNC
)ndis_open_cfg
},
2634 { "NdisAcquireSpinLock", (FUNC
)ndis_lock
},
2635 { "NdisReleaseSpinLock", (FUNC
)ndis_unlock
},
2636 { "NdisDprAcquireSpinLock", (FUNC
)ndis_lock_dpr
},
2637 { "NdisDprReleaseSpinLock", (FUNC
)ndis_unlock_dpr
},
2638 { "NdisAllocateSpinLock", (FUNC
)ndis_create_lock
},
2639 { "NdisFreeSpinLock", (FUNC
)ndis_destroy_lock
},
2640 { "NdisFreeMemory", (FUNC
)ndis_free
},
2641 { "NdisReadPciSlotInformation", (FUNC
)ndis_read_pci
},
2642 { "NdisWritePciSlotInformation",(FUNC
)ndis_write_pci
},
2643 { "NdisImmediateReadPciSlotInformation", (FUNC
)ndis_read_pci
},
2644 { "NdisImmediateWritePciSlotInformation", (FUNC
)ndis_write_pci
},
2645 { "NdisWriteErrorLogEntry", (FUNC
)ndis_syslog
},
2646 { "NdisMStartBufferPhysicalMapping", (FUNC
)ndis_vtophys_load
},
2647 { "NdisMCompleteBufferPhysicalMapping", (FUNC
)ndis_vtophys_unload
},
2648 { "NdisMInitializeTimer", (FUNC
)ndis_create_timer
},
2649 { "NdisInitializeTimer", (FUNC
)ndis_init_timer
},
2650 { "NdisSetTimer", (FUNC
)ndis_set_timer
},
2651 { "NdisMCancelTimer", (FUNC
)ndis_cancel_timer
},
2652 { "NdisCancelTimer", (FUNC
)ndis_cancel_timer
},
2653 { "NdisMSetPeriodicTimer", (FUNC
)ndis_set_periodic_timer
},
2654 { "NdisMQueryAdapterResources", (FUNC
)ndis_query_resources
},
2655 { "NdisMRegisterIoPortRange", (FUNC
)ndis_register_ioport
},
2656 { "NdisMDeregisterIoPortRange", (FUNC
)ndis_deregister_ioport
},
2657 { "NdisReadNetworkAddress", (FUNC
)ndis_read_netaddr
},
2658 { "NdisQueryMapRegisterCount", (FUNC
)ndis_mapreg_cnt
},
2659 { "NdisMAllocateMapRegisters", (FUNC
)ndis_alloc_mapreg
},
2660 { "NdisMFreeMapRegisters", (FUNC
)ndis_free_mapreg
},
2661 { "NdisMAllocateSharedMemory", (FUNC
)ndis_alloc_sharedmem
},
2662 { "NdisMMapIoSpace", (FUNC
)ndis_map_iospace
},
2663 { "NdisMUnmapIoSpace", (FUNC
)ndis_unmap_iospace
},
2664 { "NdisGetCacheFillSize", (FUNC
)ndis_cachefill
},
2665 { "NdisMGetDmaAlignment", (FUNC
)ndis_dma_align
},
2666 { "NdisMInitializeScatterGatherDma", (FUNC
)ndis_init_sc_dma
},
2667 { "NdisAllocatePacketPool", (FUNC
)ndis_alloc_packetpool
},
2668 { "NdisAllocatePacketPoolEx", (FUNC
)ndis_ex_alloc_packetpool
},
2669 { "NdisAllocatePacket", (FUNC
)ndis_alloc_packet
},
2670 { "NdisFreePacket", (FUNC
)ndis_release_packet
},
2671 { "NdisFreePacketPool", (FUNC
)ndis_free_packetpool
},
2672 { "NdisDprAllocatePacket", (FUNC
)ndis_alloc_packet
},
2673 { "NdisDprFreePacket", (FUNC
)ndis_release_packet
},
2674 { "NdisAllocateBufferPool", (FUNC
)ndis_alloc_bufpool
},
2675 { "NdisAllocateBuffer", (FUNC
)ndis_alloc_buf
},
2676 { "NdisQueryBuffer", (FUNC
)ndis_query_buf
},
2677 { "NdisQueryBufferSafe", (FUNC
)ndis_query_buf_safe
},
2678 { "NdisBufferVirtualAddress", (FUNC
)ndis_buf_vaddr
},
2679 { "NdisBufferVirtualAddressSafe", (FUNC
)ndis_buf_vaddr_safe
},
2680 { "NdisBufferLength", (FUNC
)ndis_buflen
},
2681 { "NdisFreeBuffer", (FUNC
)ndis_release_buf
},
2682 { "NdisFreeBufferPool", (FUNC
)ndis_free_bufpool
},
2683 { "NdisInterlockedIncrement", (FUNC
)ndis_interlock_inc
},
2684 { "NdisInterlockedDecrement", (FUNC
)ndis_interlock_dec
},
2685 { "NdisInitializeEvent", (FUNC
)ndis_init_event
},
2686 { "NdisSetEvent", (FUNC
)ndis_set_event
},
2687 { "NdisResetEvent", (FUNC
)ndis_reset_event
},
2688 { "NdisWaitEvent", (FUNC
)ndis_wait_event
},
2689 { "NdisUnicodeStringToAnsiString", (FUNC
)ndis_unicode2ansi
},
2690 { "NdisMPciAssignResources", (FUNC
)ndis_assign_pcirsrc
},
2691 { "NdisMFreeSharedMemory", (FUNC
)ndis_free_sharedmem
},
2692 { "NdisMRegisterInterrupt", (FUNC
)ndis_register_intr
},
2693 { "NdisMDeregisterInterrupt", (FUNC
)ndis_deregister_intr
},
2694 { "NdisMRegisterAdapterShutdownHandler", (FUNC
)ndis_register_shutdown
},
2695 { "NdisMDeregisterAdapterShutdownHandler", (FUNC
)ndis_deregister_shutdown
},
2696 { "NDIS_BUFFER_TO_SPAN_PAGES", (FUNC
)ndis_numpages
},
2697 { "NdisQueryBufferOffset", (FUNC
)ndis_query_bufoffset
},
2698 { "NdisAdjustBufferLength", (FUNC
)ndis_adjust_buflen
},
2699 { "NdisPacketPoolUsage", (FUNC
)ndis_packetpool_use
},
2700 { "NdisMSleep", (FUNC
)ndis_sleep
},
2701 { "NdisUnchainBufferAtFront", (FUNC
)ndis_unchain_headbuf
},
2702 { "NdisReadPcmciaAttributeMemory", (FUNC
)ndis_read_pccard_amem
},
2703 { "NdisWritePcmciaAttributeMemory", (FUNC
)ndis_write_pccard_amem
},
2704 { "NdisOpenFile", (FUNC
)ndis_open_file
},
2705 { "NdisMapFile", (FUNC
)ndis_map_file
},
2706 { "NdisUnmapFile", (FUNC
)ndis_unmap_file
},
2707 { "NdisCloseFile", (FUNC
)ndis_close_file
},
2708 { "NdisMRegisterDevice", (FUNC
)ndis_register_dev
},
2709 { "NdisMDeregisterDevice", (FUNC
)ndis_deregister_dev
},
2710 { "NdisMQueryAdapterInstanceName", (FUNC
)ndis_query_name
},
2711 { "NdisMRegisterUnloadHandler", (FUNC
)ndis_register_unload
},
2714 * This last entry is a catch-all for any function we haven't
2715 * implemented yet. The PE import list patching routine will
2716 * use it for any function that doesn't have an explicit match
2720 { NULL
, (FUNC
)dummy
},