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.125 2010/12/06 20:54:53 bschmidt Exp $
36 * This file implements a translation layer between the BSD networking
37 * infrasturcture and Windows(R) NDIS network driver modules. A Windows
38 * NDIS driver calls into several functions in the NDIS.SYS Windows
39 * kernel module and exports a table of functions designed to be called
40 * by the NDIS subsystem. Using the PE loader, we can patch our own
41 * versions of the NDIS routines into a given Windows driver module and
42 * convince the driver that it is in fact running on Windows.
44 * We provide a table of all our implemented NDIS routines which is patched
45 * into the driver object code. All our exported routines must use the
46 * _stdcall calling convention, since that's what the Windows object code
50 #include <sys/ctype.h>
51 #include <sys/param.h>
52 #include <sys/types.h>
53 #include <sys/errno.h>
55 #include <sys/callout.h>
56 #include <sys/kernel.h>
57 #include <sys/systm.h>
58 #include <sys/malloc.h>
60 #include <sys/mutex.h>
61 #include <sys/socket.h>
62 #include <sys/sysctl.h>
63 #include <sys/_timespec.h>
64 #include <sys/queue.h>
66 #include <sys/filedesc.h>
67 #include <sys/nlookup.h>
68 #include <sys/fcntl.h>
69 #include <sys/vnode.h>
70 #include <sys/kthread.h>
71 #include <sys/linker.h>
72 #include <sys/mount.h>
73 #include <sys/sysproto.h>
76 #include <net/if_arp.h>
77 #include <net/ethernet.h>
78 #include <net/if_dl.h>
79 #include <net/if_media.h>
81 #include <machine/atomic.h>
85 #include <sys/mplock2.h>
87 #include <netproto/802_11/ieee80211_var.h>
88 #include <netproto/802_11/ieee80211_ioctl.h>
90 #include <bus/pci/pcireg.h>
91 #include <bus/pci/pcivar.h>
92 #include <bus/u4b/usb.h>
93 #include <bus/u4b/usbdi.h>
95 #include <emulation/ndis/pe_var.h>
96 #include <emulation/ndis/cfg_var.h>
97 #include <emulation/ndis/resource_var.h>
98 #include <emulation/ndis/ntoskrnl_var.h>
99 #include <emulation/ndis/hal_var.h>
100 #include <emulation/ndis/ndis_var.h>
101 #include <dev/netif/ndis/if_ndisvar.h>
104 #include <vm/vm_param.h>
106 #include <vm/vm_kern.h>
107 #include <vm/vm_map.h>
109 static char ndis_filepath
[MAXPATHLEN
];
111 SYSCTL_STRING(_hw
, OID_AUTO
, ndis_filepath
, CTLFLAG_RW
, ndis_filepath
,
112 MAXPATHLEN
, "Path used by NdisOpenFile() to search for files");
114 static void NdisInitializeWrapper(ndis_handle
*,
115 driver_object
*, void *, void *);
116 static ndis_status
NdisMRegisterMiniport(ndis_handle
,
117 ndis_miniport_characteristics
*, int);
118 static ndis_status
NdisAllocateMemoryWithTag(void **,
120 static ndis_status
NdisAllocateMemory(void **,
121 uint32_t, uint32_t, ndis_physaddr
);
122 static void NdisFreeMemory(void *, uint32_t, uint32_t);
123 static ndis_status
NdisMSetAttributesEx(ndis_handle
, ndis_handle
,
124 uint32_t, uint32_t, ndis_interface_type
);
125 static void NdisOpenConfiguration(ndis_status
*,
126 ndis_handle
*, ndis_handle
);
127 static void NdisOpenConfigurationKeyByIndex(ndis_status
*,
128 ndis_handle
, uint32_t, unicode_string
*, ndis_handle
*);
129 static void NdisOpenConfigurationKeyByName(ndis_status
*,
130 ndis_handle
, unicode_string
*, ndis_handle
*);
131 static ndis_status
ndis_encode_parm(ndis_miniport_block
*,
132 struct sysctl_oid
*, ndis_parm_type
, ndis_config_parm
**);
133 static ndis_status
ndis_decode_parm(ndis_miniport_block
*,
134 ndis_config_parm
*, char *);
135 static void NdisReadConfiguration(ndis_status
*, ndis_config_parm
**,
136 ndis_handle
, unicode_string
*, ndis_parm_type
);
137 static void NdisWriteConfiguration(ndis_status
*, ndis_handle
,
138 unicode_string
*, ndis_config_parm
*);
139 static void NdisCloseConfiguration(ndis_handle
);
140 static void NdisAllocateSpinLock(ndis_spin_lock
*);
141 static void NdisFreeSpinLock(ndis_spin_lock
*);
142 static void NdisAcquireSpinLock(ndis_spin_lock
*);
143 static void NdisReleaseSpinLock(ndis_spin_lock
*);
144 static void NdisDprAcquireSpinLock(ndis_spin_lock
*);
145 static void NdisDprReleaseSpinLock(ndis_spin_lock
*);
146 static void NdisInitializeReadWriteLock(ndis_rw_lock
*);
147 static void NdisAcquireReadWriteLock(ndis_rw_lock
*,
148 uint8_t, ndis_lock_state
*);
149 static void NdisReleaseReadWriteLock(ndis_rw_lock
*, ndis_lock_state
*);
150 static uint32_t NdisReadPciSlotInformation(ndis_handle
, uint32_t,
151 uint32_t, void *, uint32_t);
152 static uint32_t NdisWritePciSlotInformation(ndis_handle
, uint32_t,
153 uint32_t, void *, uint32_t);
154 static void NdisWriteErrorLogEntry(ndis_handle
, ndis_error_code
, uint32_t, ...);
155 static void ndis_map_cb(void *, bus_dma_segment_t
*, int, int);
156 static void NdisMStartBufferPhysicalMapping(ndis_handle
,
157 ndis_buffer
*, uint32_t, uint8_t, ndis_paddr_unit
*, uint32_t *);
158 static void NdisMCompleteBufferPhysicalMapping(ndis_handle
,
159 ndis_buffer
*, uint32_t);
160 static void NdisMInitializeTimer(ndis_miniport_timer
*, ndis_handle
,
161 ndis_timer_function
, void *);
162 static void NdisInitializeTimer(ndis_timer
*,
163 ndis_timer_function
, void *);
164 static void NdisSetTimer(ndis_timer
*, uint32_t);
165 static void NdisMSetPeriodicTimer(ndis_miniport_timer
*, uint32_t);
166 static void NdisMCancelTimer(ndis_timer
*, uint8_t *);
167 static void ndis_timercall(kdpc
*, ndis_miniport_timer
*,
169 static void NdisMQueryAdapterResources(ndis_status
*, ndis_handle
,
170 ndis_resource_list
*, uint32_t *);
171 static ndis_status
NdisMRegisterIoPortRange(void **,
172 ndis_handle
, uint32_t, uint32_t);
173 static void NdisMDeregisterIoPortRange(ndis_handle
,
174 uint32_t, uint32_t, void *);
175 static void NdisReadNetworkAddress(ndis_status
*, void **,
176 uint32_t *, ndis_handle
);
177 static ndis_status
NdisQueryMapRegisterCount(uint32_t, uint32_t *);
178 static ndis_status
NdisMAllocateMapRegisters(ndis_handle
,
179 uint32_t, uint8_t, uint32_t, uint32_t);
180 static void NdisMFreeMapRegisters(ndis_handle
);
181 static void ndis_mapshared_cb(void *, bus_dma_segment_t
*, int, int);
182 static void NdisMAllocateSharedMemory(ndis_handle
, uint32_t,
183 uint8_t, void **, ndis_physaddr
*);
184 static void ndis_asyncmem_complete(device_object
*, void *);
185 static ndis_status
NdisMAllocateSharedMemoryAsync(ndis_handle
,
186 uint32_t, uint8_t, void *);
187 static void NdisMFreeSharedMemory(ndis_handle
, uint32_t,
188 uint8_t, void *, ndis_physaddr
);
189 static ndis_status
NdisMMapIoSpace(void **, ndis_handle
,
190 ndis_physaddr
, uint32_t);
191 static void NdisMUnmapIoSpace(ndis_handle
, void *, uint32_t);
192 static uint32_t NdisGetCacheFillSize(void);
193 static void *NdisGetRoutineAddress(unicode_string
*);
194 static uint32_t NdisMGetDmaAlignment(ndis_handle
);
195 static ndis_status
NdisMInitializeScatterGatherDma(ndis_handle
,
197 static void NdisUnchainBufferAtFront(ndis_packet
*, ndis_buffer
**);
198 static void NdisUnchainBufferAtBack(ndis_packet
*, ndis_buffer
**);
199 static void NdisAllocateBufferPool(ndis_status
*,
200 ndis_handle
*, uint32_t);
201 static void NdisFreeBufferPool(ndis_handle
);
202 static void NdisAllocateBuffer(ndis_status
*, ndis_buffer
**,
203 ndis_handle
, void *, uint32_t);
204 static void NdisFreeBuffer(ndis_buffer
*);
205 static uint32_t NdisBufferLength(ndis_buffer
*);
206 static void NdisQueryBuffer(ndis_buffer
*, void **, uint32_t *);
207 static void NdisQueryBufferSafe(ndis_buffer
*, void **,
208 uint32_t *, uint32_t);
209 static void *NdisBufferVirtualAddress(ndis_buffer
*);
210 static void *NdisBufferVirtualAddressSafe(ndis_buffer
*, uint32_t);
211 static void NdisAdjustBufferLength(ndis_buffer
*, int);
212 static uint32_t NdisInterlockedIncrement(uint32_t *);
213 static uint32_t NdisInterlockedDecrement(uint32_t *);
214 static void NdisInitializeEvent(ndis_event
*);
215 static void NdisSetEvent(ndis_event
*);
216 static void NdisResetEvent(ndis_event
*);
217 static uint8_t NdisWaitEvent(ndis_event
*, uint32_t);
218 static ndis_status
NdisUnicodeStringToAnsiString(ansi_string
*,
221 NdisAnsiStringToUnicodeString(unicode_string
*, ansi_string
*);
222 static ndis_status
NdisMPciAssignResources(ndis_handle
,
223 uint32_t, ndis_resource_list
**);
224 static ndis_status
NdisMRegisterInterrupt(ndis_miniport_interrupt
*,
225 ndis_handle
, uint32_t, uint32_t, uint8_t,
226 uint8_t, ndis_interrupt_mode
);
227 static void NdisMDeregisterInterrupt(ndis_miniport_interrupt
*);
228 static void NdisMRegisterAdapterShutdownHandler(ndis_handle
, void *,
229 ndis_shutdown_handler
);
230 static void NdisMDeregisterAdapterShutdownHandler(ndis_handle
);
231 static uint32_t NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer
*);
232 static void NdisGetBufferPhysicalArraySize(ndis_buffer
*,
234 static void NdisQueryBufferOffset(ndis_buffer
*,
235 uint32_t *, uint32_t *);
236 static uint32_t NdisReadPcmciaAttributeMemory(ndis_handle
,
237 uint32_t, void *, uint32_t);
238 static uint32_t NdisWritePcmciaAttributeMemory(ndis_handle
,
239 uint32_t, void *, uint32_t);
240 static list_entry
*NdisInterlockedInsertHeadList(list_entry
*,
241 list_entry
*, ndis_spin_lock
*);
242 static list_entry
*NdisInterlockedRemoveHeadList(list_entry
*,
244 static list_entry
*NdisInterlockedInsertTailList(list_entry
*,
245 list_entry
*, ndis_spin_lock
*);
247 NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt
*,
249 static void NdisGetCurrentSystemTime(uint64_t *);
250 static void NdisGetSystemUpTime(uint32_t *);
251 static uint32_t NdisGetVersion(void);
252 static void NdisInitializeString(unicode_string
*, char *);
253 static void NdisInitAnsiString(ansi_string
*, char *);
254 static void NdisInitUnicodeString(unicode_string
*, uint16_t *);
255 static void NdisFreeString(unicode_string
*);
256 static ndis_status
NdisMRemoveMiniport(ndis_handle
*);
257 static void NdisTerminateWrapper(ndis_handle
, void *);
258 static void NdisMGetDeviceProperty(ndis_handle
, device_object
**,
259 device_object
**, device_object
**, cm_resource_list
*,
261 static void NdisGetFirstBufferFromPacket(ndis_packet
*,
262 ndis_buffer
**, void **, uint32_t *, uint32_t *);
263 static void NdisGetFirstBufferFromPacketSafe(ndis_packet
*,
264 ndis_buffer
**, void **, uint32_t *, uint32_t *, uint32_t);
265 static int ndis_find_sym(linker_file_t
, char *, char *, caddr_t
*);
266 static void NdisOpenFile(ndis_status
*, ndis_handle
*, uint32_t *,
267 unicode_string
*, ndis_physaddr
);
268 static void NdisMapFile(ndis_status
*, void **, ndis_handle
);
269 static void NdisUnmapFile(ndis_handle
);
270 static void NdisCloseFile(ndis_handle
);
271 static uint8_t NdisSystemProcessorCount(void);
272 static void NdisGetCurrentProcessorCounts(uint32_t *, uint32_t *, uint32_t *);
273 static void NdisMIndicateStatusComplete(ndis_handle
);
274 static void NdisMIndicateStatus(ndis_handle
, ndis_status
,
276 static uint8_t ndis_intr(kinterrupt
*, void *);
277 static void ndis_intrhand(kdpc
*, ndis_miniport_interrupt
*, void *, void *);
278 static funcptr
ndis_findwrap(funcptr
);
279 static void NdisCopyFromPacketToPacket(ndis_packet
*,
280 uint32_t, uint32_t, ndis_packet
*, uint32_t, uint32_t *);
281 static void NdisCopyFromPacketToPacketSafe(ndis_packet
*,
282 uint32_t, uint32_t, ndis_packet
*, uint32_t, uint32_t *, uint32_t);
283 static void NdisIMCopySendPerPacketInfo(ndis_packet
*, ndis_packet
*);
284 static ndis_status
NdisMRegisterDevice(ndis_handle
,
285 unicode_string
*, unicode_string
*, driver_dispatch
**,
286 void **, ndis_handle
*);
287 static ndis_status
NdisMDeregisterDevice(ndis_handle
);
289 NdisMQueryAdapterInstanceName(unicode_string
*, ndis_handle
);
290 static void NdisMRegisterUnloadHandler(ndis_handle
, void *);
291 static void dummy(void);
294 * Some really old drivers do not properly check the return value
295 * from NdisAllocatePacket() and NdisAllocateBuffer() and will
296 * sometimes allocate few more buffers/packets that they originally
297 * requested when they created the pool. To prevent this from being
298 * a problem, we allocate a few extra buffers/packets beyond what
299 * the driver asks for. This #define controls how many.
301 #define NDIS_POOL_EXTRA 16
306 image_patch_table
*patch
;
308 strcpy(ndis_filepath
, "/compat/ndis");
310 patch
= ndis_functbl
;
311 while (patch
->ipt_func
!= NULL
) {
312 windrv_wrap((funcptr
)patch
->ipt_func
,
313 (funcptr
*)&patch
->ipt_wrap
,
314 patch
->ipt_argcnt
, patch
->ipt_ftype
);
324 image_patch_table
*patch
;
326 patch
= ndis_functbl
;
327 while (patch
->ipt_func
!= NULL
) {
328 windrv_unwrap(patch
->ipt_wrap
);
336 ndis_findwrap(funcptr func
)
338 image_patch_table
*patch
;
340 patch
= ndis_functbl
;
341 while (patch
->ipt_func
!= NULL
) {
342 if ((funcptr
)patch
->ipt_func
== func
)
343 return((funcptr
)patch
->ipt_wrap
);
351 * This routine does the messy Windows Driver Model device attachment
352 * stuff on behalf of NDIS drivers. We register our own AddDevice
356 NdisInitializeWrapper(ndis_handle
*wrapper
, driver_object
*drv
, void *path
,
360 * As of yet, I haven't come up with a compelling
361 * reason to define a private NDIS wrapper structure,
362 * so we use a pointer to the driver object as the
363 * wrapper handle. The driver object has the miniport
364 * characteristics struct for this driver hung off it
365 * via IoAllocateDriverObjectExtension(), and that's
366 * really all the private data we need.
372 * If this was really Windows, we'd be registering dispatch
373 * routines for the NDIS miniport module here, but we're
374 * not Windows so all we really need to do is set up an
375 * AddDevice function that'll be invoked when a new device
379 drv
->dro_driverext
->dre_adddevicefunc
= NdisAddDevice
;
383 NdisTerminateWrapper(ndis_handle handle
, void *syspec
)
385 /* Nothing to see here, move along. */
389 NdisMRegisterMiniport(ndis_handle handle
,
390 ndis_miniport_characteristics
*characteristics
, int len
)
392 ndis_miniport_characteristics
*ch
= NULL
;
395 drv
= (driver_object
*)handle
;
398 * We need to save the NDIS miniport characteristics
399 * somewhere. This data is per-driver, not per-device
400 * (all devices handled by the same driver have the
401 * same characteristics) so we hook it onto the driver
402 * object using IoAllocateDriverObjectExtension().
403 * The extra extension info is automagically deleted when
404 * the driver is unloaded (see windrv_unload()).
407 if (IoAllocateDriverObjectExtension(drv
, (void *)1,
408 sizeof(ndis_miniport_characteristics
), (void **)&ch
) !=
410 return (NDIS_STATUS_RESOURCES
);
413 bzero((char *)ch
, sizeof(ndis_miniport_characteristics
));
415 bcopy((char *)characteristics
, (char *)ch
, len
);
417 if (ch
->nmc_version_major
< 5 || ch
->nmc_version_minor
< 1) {
418 ch
->nmc_shutdown_handler
= NULL
;
419 ch
->nmc_canceltxpkts_handler
= NULL
;
420 ch
->nmc_pnpevent_handler
= NULL
;
423 return (NDIS_STATUS_SUCCESS
);
427 NdisAllocateMemoryWithTag(void **vaddr
, uint32_t len
, uint32_t tag
)
431 mem
= ExAllocatePoolWithTag(NonPagedPool
, len
, tag
);
433 return (NDIS_STATUS_RESOURCES
);
437 return (NDIS_STATUS_SUCCESS
);
441 NdisAllocateMemory(void **vaddr
, uint32_t len
, uint32_t flags
,
442 ndis_physaddr highaddr
)
446 mem
= ExAllocatePoolWithTag(NonPagedPool
, len
, 0);
448 return (NDIS_STATUS_RESOURCES
);
451 return (NDIS_STATUS_SUCCESS
);
455 NdisFreeMemory(void *vaddr
, uint32_t len
, uint32_t flags
)
464 NdisMSetAttributesEx(ndis_handle adapter_handle
, ndis_handle adapter_ctx
,
465 uint32_t hangsecs
, uint32_t flags
, ndis_interface_type iftype
)
467 ndis_miniport_block
*block
;
470 * Save the adapter context, we need it for calling
471 * the driver's internal functions.
473 block
= (ndis_miniport_block
*)adapter_handle
;
474 block
->nmb_miniportadapterctx
= adapter_ctx
;
475 block
->nmb_checkforhangsecs
= hangsecs
;
476 block
->nmb_flags
= flags
;
478 return (NDIS_STATUS_SUCCESS
);
482 NdisOpenConfiguration(ndis_status
*status
, ndis_handle
*cfg
,
486 *status
= NDIS_STATUS_SUCCESS
;
490 NdisOpenConfigurationKeyByName(ndis_status
*status
, ndis_handle cfg
,
491 unicode_string
*subkey
, ndis_handle
*subhandle
)
494 *status
= NDIS_STATUS_SUCCESS
;
498 NdisOpenConfigurationKeyByIndex(ndis_status
*status
, ndis_handle cfg
,
499 uint32_t idx
, unicode_string
*subkey
, ndis_handle
*subhandle
)
501 *status
= NDIS_STATUS_FAILURE
;
505 ndis_encode_parm(ndis_miniport_block
*block
, struct sysctl_oid
*oid
,
506 ndis_parm_type type
, ndis_config_parm
**parm
)
509 ndis_parmlist_entry
*np
;
516 np
= ExAllocatePoolWithTag(NonPagedPool
,
517 sizeof(ndis_parmlist_entry
), 0);
519 return (NDIS_STATUS_RESOURCES
);
520 InsertHeadList((&block
->nmb_parmlist
), (&np
->np_list
));
521 *parm
= p
= &np
->np_parm
;
524 case ndis_parm_string
:
525 /* See if this might be a number. */
526 val
= strtoul((char *)oid
->oid_arg1
, NULL
, 10);
527 us
= &p
->ncp_parmdata
.ncp_stringdata
;
528 p
->ncp_type
= ndis_parm_string
;
530 ksnprintf(tmp
, 32, "%x", val
);
531 RtlInitAnsiString(&as
, tmp
);
533 RtlInitAnsiString(&as
, (char *)oid
->oid_arg1
);
536 if (RtlAnsiStringToUnicodeString(us
, &as
, TRUE
)) {
538 return (NDIS_STATUS_RESOURCES
);
542 if (strncmp((char *)oid
->oid_arg1
, "0x", 2) == 0)
546 p
->ncp_type
= ndis_parm_int
;
547 p
->ncp_parmdata
.ncp_intdata
=
548 strtol((char *)oid
->oid_arg1
, NULL
, base
);
550 case ndis_parm_hexint
:
552 if (strncmp((char *)oid
->oid_arg1
, "0x", 2) == 0)
558 p
->ncp_type
= ndis_parm_hexint
;
559 p
->ncp_parmdata
.ncp_intdata
=
560 strtoul((char *)oid
->oid_arg1
, NULL
, base
);
563 return (NDIS_STATUS_FAILURE
);
567 return (NDIS_STATUS_SUCCESS
);
571 NdisReadConfiguration(ndis_status
*status
, ndis_config_parm
**parm
,
572 ndis_handle cfg
, unicode_string
*key
, ndis_parm_type type
)
575 ndis_miniport_block
*block
;
576 struct ndis_softc
*sc
;
577 struct sysctl_oid
*oidp
;
578 struct sysctl_ctx_entry
*e
;
581 block
= (ndis_miniport_block
*)cfg
;
582 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
584 if (key
->us_len
== 0 || key
->us_buf
== NULL
) {
585 *status
= NDIS_STATUS_FAILURE
;
589 if (RtlUnicodeStringToAnsiString(&as
, key
, TRUE
)) {
590 *status
= NDIS_STATUS_RESOURCES
;
597 * See if registry key is already in a list of known keys
598 * included with the driver.
600 TAILQ_FOREACH(e
, device_get_sysctl_ctx(sc
->ndis_dev
), link
) {
602 if (strcasecmp(oidp
->oid_name
, keystr
) == 0) {
603 if (strcmp((char *)oidp
->oid_arg1
, "UNSET") == 0) {
604 RtlFreeAnsiString(&as
);
605 *status
= NDIS_STATUS_FAILURE
;
609 *status
= ndis_encode_parm(block
, oidp
, type
, parm
);
610 RtlFreeAnsiString(&as
);
616 * If the key didn't match, add it to the list of dynamically
617 * created ones. Sometimes, drivers refer to registry keys
618 * that aren't documented in their .INF files. These keys
619 * are supposed to be created by some sort of utility or
620 * control panel snap-in that comes with the driver software.
621 * Sometimes it's useful to be able to manipulate these.
622 * If the driver requests the key in the form of a string,
623 * make its default value an empty string, otherwise default
627 if (type
== ndis_parm_int
|| type
== ndis_parm_hexint
)
628 ndis_add_sysctl(sc
, keystr
, "(dynamic integer key)",
629 "UNSET", CTLFLAG_RW
);
631 ndis_add_sysctl(sc
, keystr
, "(dynamic string key)",
632 "UNSET", CTLFLAG_RW
);
634 RtlFreeAnsiString(&as
);
635 *status
= NDIS_STATUS_FAILURE
;
639 ndis_decode_parm(ndis_miniport_block
*block
, ndis_config_parm
*parm
, char *val
)
641 unicode_string
*ustr
;
644 switch(parm
->ncp_type
) {
645 case ndis_parm_string
:
646 ustr
= &parm
->ncp_parmdata
.ncp_stringdata
;
647 if (RtlUnicodeStringToAnsiString(&as
, ustr
, TRUE
))
648 return (NDIS_STATUS_RESOURCES
);
649 bcopy(as
.as_buf
, val
, as
.as_len
);
650 RtlFreeAnsiString(&as
);
653 ksprintf(val
, "%d", parm
->ncp_parmdata
.ncp_intdata
);
655 case ndis_parm_hexint
:
656 ksprintf(val
, "%xu", parm
->ncp_parmdata
.ncp_intdata
);
659 return (NDIS_STATUS_FAILURE
);
662 return (NDIS_STATUS_SUCCESS
);
666 NdisWriteConfiguration(ndis_status
*status
, ndis_handle cfg
,
667 unicode_string
*key
, ndis_config_parm
*parm
)
671 ndis_miniport_block
*block
;
672 struct ndis_softc
*sc
;
673 struct sysctl_oid
*oidp
;
674 struct sysctl_ctx_entry
*e
;
677 block
= (ndis_miniport_block
*)cfg
;
678 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
680 if (RtlUnicodeStringToAnsiString(&as
, key
, TRUE
)) {
681 *status
= NDIS_STATUS_RESOURCES
;
687 /* Decode the parameter into a string. */
688 bzero(val
, sizeof(val
));
689 *status
= ndis_decode_parm(block
, parm
, val
);
690 if (*status
!= NDIS_STATUS_SUCCESS
) {
691 RtlFreeAnsiString(&as
);
695 /* See if the key already exists. */
697 TAILQ_FOREACH(e
, device_get_sysctl_ctx(sc
->ndis_dev
), link
) {
699 if (strcasecmp(oidp
->oid_name
, keystr
) == 0) {
700 /* Found it, set the value. */
701 strcpy((char *)oidp
->oid_arg1
, val
);
702 RtlFreeAnsiString(&as
);
707 /* Not found, add a new key with the specified value. */
708 ndis_add_sysctl(sc
, keystr
, "(dynamically set key)",
711 RtlFreeAnsiString(&as
);
712 *status
= NDIS_STATUS_SUCCESS
;
716 NdisCloseConfiguration(ndis_handle cfg
)
719 ndis_parmlist_entry
*pe
;
720 ndis_miniport_block
*block
;
723 block
= (ndis_miniport_block
*)cfg
;
725 while (!IsListEmpty(&block
->nmb_parmlist
)) {
726 e
= RemoveHeadList(&block
->nmb_parmlist
);
727 pe
= CONTAINING_RECORD(e
, ndis_parmlist_entry
, np_list
);
729 if (p
->ncp_type
== ndis_parm_string
)
730 RtlFreeUnicodeString(&p
->ncp_parmdata
.ncp_stringdata
);
736 * Initialize a Windows spinlock.
739 NdisAllocateSpinLock(ndis_spin_lock
*lock
)
741 KeInitializeSpinLock(&lock
->nsl_spinlock
);
746 * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
747 * for this. One is that it's sort of superfluous: we don't have to do anything
748 * special to deallocate the spinlock. The other is that there are some buggy
749 * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
750 * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
754 NdisFreeSpinLock(ndis_spin_lock
*lock
)
757 KeInitializeSpinLock(&lock
->nsl_spinlock
);
763 * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
767 NdisAcquireSpinLock(ndis_spin_lock
*lock
)
769 KeAcquireSpinLock(&lock
->nsl_spinlock
, &lock
->nsl_kirql
);
773 * Release a spinlock from IRQL == DISPATCH_LEVEL.
777 NdisReleaseSpinLock(ndis_spin_lock
*lock
)
779 KeReleaseSpinLock(&lock
->nsl_spinlock
, lock
->nsl_kirql
);
783 * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
786 NdisDprAcquireSpinLock(ndis_spin_lock
*lock
)
788 KeAcquireSpinLockAtDpcLevel(&lock
->nsl_spinlock
);
792 * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
795 NdisDprReleaseSpinLock(ndis_spin_lock
*lock
)
797 KeReleaseSpinLockFromDpcLevel(&lock
->nsl_spinlock
);
801 NdisInitializeReadWriteLock(ndis_rw_lock
*lock
)
803 KeInitializeSpinLock(&lock
->nrl_spinlock
);
804 bzero((char *)&lock
->nrl_rsvd
, sizeof(lock
->nrl_rsvd
));
808 NdisAcquireReadWriteLock(ndis_rw_lock
*lock
, uint8_t writeacc
,
809 ndis_lock_state
*state
)
811 if (writeacc
== TRUE
) {
812 KeAcquireSpinLock(&lock
->nrl_spinlock
, &state
->nls_oldirql
);
819 NdisReleaseReadWriteLock(ndis_rw_lock
*lock
, ndis_lock_state
*state
)
821 if (lock
->nrl_rsvd
[0]) {
823 KeReleaseSpinLock(&lock
->nrl_spinlock
, state
->nls_oldirql
);
829 NdisReadPciSlotInformation(ndis_handle adapter
, uint32_t slot
, uint32_t offset
,
830 void *buf
, uint32_t len
)
832 ndis_miniport_block
*block
;
837 block
= (ndis_miniport_block
*)adapter
;
842 dev
= block
->nmb_physdeviceobj
->do_devext
;
845 * I have a test system consisting of a Sun w2100z
846 * dual 2.4Ghz Opteron machine and an Atheros 802.11a/b/g
847 * "Aries" miniPCI NIC. (The NIC is installed in the
848 * machine using a miniPCI to PCI bus adapter card.)
849 * When running in SMP mode, I found that
850 * performing a large number of consecutive calls to
851 * NdisReadPciSlotInformation() would result in a
852 * sudden system reset (or in some cases a freeze).
853 * My suspicion is that the multiple reads are somehow
854 * triggering a fatal PCI bus error that leads to a
855 * machine check. The 1us delay in the loop below
856 * seems to prevent this problem.
859 for (i
= 0; i
< len
; i
++) {
861 dest
[i
] = pci_read_config(dev
, i
+ offset
, 1);
868 NdisWritePciSlotInformation(ndis_handle adapter
, uint32_t slot
,
869 uint32_t offset
, void *buf
, uint32_t len
)
871 ndis_miniport_block
*block
;
876 block
= (ndis_miniport_block
*)adapter
;
882 dev
= block
->nmb_physdeviceobj
->do_devext
;
883 for (i
= 0; i
< len
; i
++) {
885 pci_write_config(dev
, i
+ offset
, dest
[i
], 1);
892 * The errorlog routine uses a variable argument list, so we
893 * have to declare it this way.
896 #define ERRMSGLEN 512
898 NdisWriteErrorLogEntry(ndis_handle adapter
, ndis_error_code code
,
899 uint32_t numerrors
, ...)
901 ndis_miniport_block
*block
;
908 struct ndis_softc
*sc
;
911 ansi_string as
= { 0, 0, NULL
};
913 block
= (ndis_miniport_block
*)adapter
;
914 dev
= block
->nmb_physdeviceobj
->do_devext
;
915 drv
= block
->nmb_deviceobj
->do_drvobj
;
916 sc
= device_get_softc(dev
);
919 if (ifp
!= NULL
&& ifp
->if_flags
& IFF_DEBUG
) {
920 error
= pe_get_message((vm_offset_t
)drv
->dro_driverstart
,
921 code
, &str
, &i
, &flags
);
923 if (flags
& MESSAGE_RESOURCE_UNICODE
) {
924 RtlInitUnicodeString(&us
, (uint16_t *)str
);
925 if (RtlUnicodeStringToAnsiString(&as
,
926 &us
, TRUE
) == STATUS_SUCCESS
)
934 device_printf(dev
, "NDIS ERROR: %x (%s)\n", code
,
935 str
== NULL
? "unknown error" : str
);
937 if (ifp
!= NULL
&& ifp
->if_flags
& IFF_DEBUG
) {
938 device_printf(dev
, "NDIS NUMERRORS: %x\n", numerrors
);
939 __va_start(ap
, numerrors
);
940 for (i
= 0; i
< numerrors
; i
++)
941 device_printf(dev
, "argptr: %p\n",
942 __va_arg(ap
, void *));
947 RtlFreeAnsiString(&as
);
951 ndis_map_cb(void *arg
, bus_dma_segment_t
*segs
, int nseg
, int error
)
953 struct ndis_map_arg
*ctx
;
961 for (i
= 0; i
< nseg
; i
++) {
962 ctx
->nma_fraglist
[i
].npu_physaddr
.np_quad
= segs
[i
].ds_addr
;
963 ctx
->nma_fraglist
[i
].npu_len
= segs
[i
].ds_len
;
970 NdisMStartBufferPhysicalMapping(ndis_handle adapter
, ndis_buffer
*buf
,
971 uint32_t mapreg
, uint8_t writedev
, ndis_paddr_unit
*addrarray
,
974 ndis_miniport_block
*block
;
975 struct ndis_softc
*sc
;
976 struct ndis_map_arg nma
;
983 block
= (ndis_miniport_block
*)adapter
;
984 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
986 if (mapreg
> sc
->ndis_mmapcnt
)
989 map
= sc
->ndis_mmaps
[mapreg
];
990 nma
.nma_fraglist
= addrarray
;
992 error
= bus_dmamap_load(sc
->ndis_mtag
, map
,
993 MmGetMdlVirtualAddress(buf
), MmGetMdlByteCount(buf
), ndis_map_cb
,
994 (void *)&nma
, BUS_DMA_NOWAIT
);
999 bus_dmamap_sync(sc
->ndis_mtag
, map
,
1000 writedev
? BUS_DMASYNC_PREWRITE
: BUS_DMASYNC_PREREAD
);
1002 *arraysize
= nma
.nma_cnt
;
1006 NdisMCompleteBufferPhysicalMapping(ndis_handle adapter
, ndis_buffer
*buf
,
1009 ndis_miniport_block
*block
;
1010 struct ndis_softc
*sc
;
1013 if (adapter
== NULL
)
1016 block
= (ndis_miniport_block
*)adapter
;
1017 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1019 if (mapreg
> sc
->ndis_mmapcnt
)
1022 map
= sc
->ndis_mmaps
[mapreg
];
1024 bus_dmamap_sync(sc
->ndis_mtag
, map
,
1025 BUS_DMASYNC_POSTREAD
|BUS_DMASYNC_POSTWRITE
);
1027 bus_dmamap_unload(sc
->ndis_mtag
, map
);
1031 * This is an older (?) timer init routine which doesn't
1032 * accept a miniport context handle. Serialized miniports should
1033 * never call this function.
1037 NdisInitializeTimer(ndis_timer
*timer
, ndis_timer_function func
, void *ctx
)
1039 KeInitializeTimer(&timer
->nt_ktimer
);
1040 KeInitializeDpc(&timer
->nt_kdpc
, func
, ctx
);
1041 KeSetImportanceDpc(&timer
->nt_kdpc
, KDPC_IMPORTANCE_LOW
);
1045 ndis_timercall(kdpc
*dpc
, ndis_miniport_timer
*timer
, void *sysarg1
,
1049 * Since we're called as a DPC, we should be running
1050 * at DISPATCH_LEVEL here. This means to acquire the
1051 * spinlock, we can use KeAcquireSpinLockAtDpcLevel()
1052 * rather than KeAcquireSpinLock().
1054 if (NDIS_SERIALIZED(timer
->nmt_block
))
1055 KeAcquireSpinLockAtDpcLevel(&timer
->nmt_block
->nmb_lock
);
1057 MSCALL4(timer
->nmt_timerfunc
, dpc
, timer
->nmt_timerctx
,
1060 if (NDIS_SERIALIZED(timer
->nmt_block
))
1061 KeReleaseSpinLockFromDpcLevel(&timer
->nmt_block
->nmb_lock
);
1065 * For a long time I wondered why there were two NDIS timer initialization
1066 * routines, and why this one needed an NDIS_MINIPORT_TIMER and the
1067 * MiniportAdapterHandle. The NDIS_MINIPORT_TIMER has its own callout
1068 * function and context pointers separate from those in the DPC, which
1069 * allows for another level of indirection: when the timer fires, we
1070 * can have our own timer function invoked, and from there we can call
1071 * the driver's function. But why go to all that trouble? Then it hit
1072 * me: for serialized miniports, the timer callouts are not re-entrant.
1073 * By trapping the callouts and having access to the MiniportAdapterHandle,
1074 * we can protect the driver callouts by acquiring the NDIS serialization
1075 * lock. This is essential for allowing serialized miniports to work
1076 * correctly on SMP systems. On UP hosts, setting IRQL to DISPATCH_LEVEL
1077 * is enough to prevent other threads from pre-empting you, but with
1078 * SMP, you must acquire a lock as well, otherwise the other CPU is
1079 * free to clobber you.
1082 NdisMInitializeTimer(ndis_miniport_timer
*timer
, ndis_handle handle
,
1083 ndis_timer_function func
, void *ctx
)
1085 /* Save the driver's funcptr and context */
1087 timer
->nmt_timerfunc
= func
;
1088 timer
->nmt_timerctx
= ctx
;
1089 timer
->nmt_block
= handle
;
1092 * Set up the timer so it will call our intermediate DPC.
1093 * Be sure to use the wrapped entry point, since
1094 * ntoskrnl_run_dpc() expects to invoke a function with
1095 * Microsoft calling conventions.
1097 KeInitializeTimer(&timer
->nmt_ktimer
);
1098 KeInitializeDpc(&timer
->nmt_kdpc
,
1099 ndis_findwrap((funcptr
)ndis_timercall
), timer
);
1100 timer
->nmt_ktimer
.k_dpc
= &timer
->nmt_kdpc
;
1104 * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
1105 * but the former is just a macro wrapper around the latter.
1108 NdisSetTimer(ndis_timer
*timer
, uint32_t msecs
)
1111 * KeSetTimer() wants the period in
1112 * hundred nanosecond intervals.
1114 KeSetTimer(&timer
->nt_ktimer
,
1115 ((int64_t)msecs
* -10000), &timer
->nt_kdpc
);
1119 NdisMSetPeriodicTimer(ndis_miniport_timer
*timer
, uint32_t msecs
)
1121 KeSetTimerEx(&timer
->nmt_ktimer
,
1122 ((int64_t)msecs
* -10000), msecs
, &timer
->nmt_kdpc
);
1126 * Technically, this is really NdisCancelTimer(), but we also
1127 * (ab)use it for NdisMCancelTimer(), since in our implementation
1128 * we don't need the extra info in the ndis_miniport_timer
1129 * structure just to cancel a timer.
1133 NdisMCancelTimer(ndis_timer
*timer
, uint8_t *cancelled
)
1136 *cancelled
= KeCancelTimer(&timer
->nt_ktimer
);
1140 NdisMQueryAdapterResources(ndis_status
*status
, ndis_handle adapter
,
1141 ndis_resource_list
*list
, uint32_t *buflen
)
1143 ndis_miniport_block
*block
;
1144 struct ndis_softc
*sc
;
1147 block
= (ndis_miniport_block
*)adapter
;
1148 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1150 rsclen
= sizeof(ndis_resource_list
) +
1151 (sizeof(cm_partial_resource_desc
) * (sc
->ndis_rescnt
- 1));
1152 if (*buflen
< rsclen
) {
1154 *status
= NDIS_STATUS_INVALID_LENGTH
;
1158 bcopy((char *)block
->nmb_rlist
, (char *)list
, rsclen
);
1159 *status
= NDIS_STATUS_SUCCESS
;
1163 NdisMRegisterIoPortRange(void **offset
, ndis_handle adapter
, uint32_t port
,
1166 struct ndis_miniport_block
*block
;
1167 struct ndis_softc
*sc
;
1169 if (adapter
== NULL
)
1170 return (NDIS_STATUS_FAILURE
);
1172 block
= (ndis_miniport_block
*)adapter
;
1173 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1175 if (sc
->ndis_res_io
== NULL
)
1176 return (NDIS_STATUS_FAILURE
);
1178 /* Don't let the device map more ports than we have. */
1179 if (rman_get_size(sc
->ndis_res_io
) < numports
)
1180 return (NDIS_STATUS_INVALID_LENGTH
);
1182 *offset
= (void *)rman_get_start(sc
->ndis_res_io
);
1184 return (NDIS_STATUS_SUCCESS
);
1188 NdisMDeregisterIoPortRange(ndis_handle adapter
, uint32_t port
,
1189 uint32_t numports
, void *offset
)
1194 NdisReadNetworkAddress(ndis_status
*status
, void **addr
, uint32_t *addrlen
,
1195 ndis_handle adapter
)
1197 struct ndis_softc
*sc
;
1198 ndis_miniport_block
*block
;
1199 uint8_t empty
[] = { 0, 0, 0, 0, 0, 0 };
1201 block
= (ndis_miniport_block
*)adapter
;
1202 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1203 if (sc
->ifp
== NULL
) {
1204 *status
= NDIS_STATUS_FAILURE
;
1208 if (sc
->ifp
->if_lladdr
== NULL
||
1209 bcmp(IF_LLADDR(sc
->ifp
), empty
, ETHER_ADDR_LEN
) == 0)
1210 *status
= NDIS_STATUS_FAILURE
;
1212 *addr
= IF_LLADDR(sc
->ifp
);
1213 *addrlen
= ETHER_ADDR_LEN
;
1214 *status
= NDIS_STATUS_SUCCESS
;
1219 NdisQueryMapRegisterCount(uint32_t bustype
, uint32_t *cnt
)
1222 return (NDIS_STATUS_SUCCESS
);
1226 NdisMAllocateMapRegisters(ndis_handle adapter
, uint32_t dmachannel
,
1227 uint8_t dmasize
, uint32_t physmapneeded
, uint32_t maxmap
)
1229 struct ndis_softc
*sc
;
1230 ndis_miniport_block
*block
;
1231 int error
, i
, nseg
= NDIS_MAXSEG
;
1233 block
= (ndis_miniport_block
*)adapter
;
1234 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1236 sc
->ndis_mmaps
= kmalloc(sizeof(bus_dmamap_t
) * physmapneeded
,
1237 M_DEVBUF
, M_NOWAIT
|M_ZERO
);
1239 if (sc
->ndis_mmaps
== NULL
)
1240 return (NDIS_STATUS_RESOURCES
);
1242 error
= bus_dma_tag_create(sc
->ndis_parent_tag
, ETHER_ALIGN
, 0,
1243 BUS_SPACE_MAXADDR_32BIT
, BUS_SPACE_MAXADDR
, NULL
,
1244 NULL
, maxmap
* nseg
, nseg
, maxmap
, BUS_DMA_ALLOCNOW
,
1248 kfree(sc
->ndis_mmaps
, M_DEVBUF
);
1249 return (NDIS_STATUS_RESOURCES
);
1252 for (i
= 0; i
< physmapneeded
; i
++)
1253 bus_dmamap_create(sc
->ndis_mtag
, 0, &sc
->ndis_mmaps
[i
]);
1255 sc
->ndis_mmapcnt
= physmapneeded
;
1257 return (NDIS_STATUS_SUCCESS
);
1261 NdisMFreeMapRegisters(ndis_handle adapter
)
1263 struct ndis_softc
*sc
;
1264 ndis_miniport_block
*block
;
1267 block
= (ndis_miniport_block
*)adapter
;
1268 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1270 for (i
= 0; i
< sc
->ndis_mmapcnt
; i
++)
1271 bus_dmamap_destroy(sc
->ndis_mtag
, sc
->ndis_mmaps
[i
]);
1273 kfree(sc
->ndis_mmaps
, M_DEVBUF
);
1275 bus_dma_tag_destroy(sc
->ndis_mtag
);
1279 ndis_mapshared_cb(void *arg
, bus_dma_segment_t
*segs
, int nseg
, int error
)
1283 if (error
|| nseg
> 1)
1288 p
->np_quad
= segs
[0].ds_addr
;
1292 * This maps to bus_dmamem_alloc().
1296 NdisMAllocateSharedMemory(ndis_handle adapter
, uint32_t len
, uint8_t cached
,
1297 void **vaddr
, ndis_physaddr
*paddr
)
1299 ndis_miniport_block
*block
;
1300 struct ndis_softc
*sc
;
1301 struct ndis_shmem
*sh
;
1304 if (adapter
== NULL
)
1307 block
= (ndis_miniport_block
*)adapter
;
1308 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1310 sh
= kmalloc(sizeof(struct ndis_shmem
), M_DEVBUF
, M_NOWAIT
|M_ZERO
);
1314 InitializeListHead(&sh
->ndis_list
);
1317 * When performing shared memory allocations, create a tag
1318 * with a lowaddr limit that restricts physical memory mappings
1319 * so that they all fall within the first 1GB of memory.
1320 * At least one device/driver combination (Linksys Instant
1321 * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
1322 * problems with performing DMA operations with physical
1323 * addresses that lie above the 1GB mark. I don't know if this
1324 * is a hardware limitation or if the addresses are being
1325 * truncated within the driver, but this seems to be the only
1326 * way to make these cards work reliably in systems with more
1327 * than 1GB of physical memory.
1330 error
= bus_dma_tag_create(sc
->ndis_parent_tag
, 64,
1331 0, NDIS_BUS_SPACE_SHARED_MAXADDR
, BUS_SPACE_MAXADDR
, NULL
,
1332 NULL
, len
, 1, len
, BUS_DMA_ALLOCNOW
, &sh
->ndis_stag
);
1335 kfree(sh
, M_DEVBUF
);
1339 error
= bus_dmamem_alloc(sh
->ndis_stag
, vaddr
,
1340 BUS_DMA_NOWAIT
| BUS_DMA_ZERO
, &sh
->ndis_smap
);
1343 bus_dma_tag_destroy(sh
->ndis_stag
);
1344 kfree(sh
, M_DEVBUF
);
1348 error
= bus_dmamap_load(sh
->ndis_stag
, sh
->ndis_smap
, *vaddr
,
1349 len
, ndis_mapshared_cb
, (void *)paddr
, BUS_DMA_NOWAIT
);
1352 bus_dmamem_free(sh
->ndis_stag
, *vaddr
, sh
->ndis_smap
);
1353 bus_dma_tag_destroy(sh
->ndis_stag
);
1354 kfree(sh
, M_DEVBUF
);
1359 * Save the physical address along with the source address.
1360 * The AirGo MIMO driver will call NdisMFreeSharedMemory()
1361 * with a bogus virtual address sometimes, but with a valid
1362 * physical address. To keep this from causing trouble, we
1363 * use the physical address to as a sanity check in case
1364 * searching based on the virtual address fails.
1368 sh
->ndis_paddr
.np_quad
= paddr
->np_quad
;
1369 sh
->ndis_saddr
= *vaddr
;
1370 InsertHeadList((&sc
->ndis_shlist
), (&sh
->ndis_list
));
1374 struct ndis_allocwork
{
1382 ndis_asyncmem_complete(device_object
*dobj
, void *arg
)
1384 ndis_miniport_block
*block
;
1385 struct ndis_softc
*sc
;
1386 struct ndis_allocwork
*w
;
1388 ndis_physaddr paddr
;
1389 ndis_allocdone_handler donefunc
;
1392 block
= (ndis_miniport_block
*)dobj
->do_devext
;
1393 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1398 donefunc
= sc
->ndis_chars
->nmc_allocate_complete_func
;
1399 NdisMAllocateSharedMemory(block
, w
->na_len
,
1400 w
->na_cached
, &vaddr
, &paddr
);
1401 MSCALL5(donefunc
, block
, vaddr
, &paddr
, w
->na_len
, w
->na_ctx
);
1403 IoFreeWorkItem(w
->na_iw
);
1408 NdisMAllocateSharedMemoryAsync(ndis_handle adapter
, uint32_t len
,
1409 uint8_t cached
, void *ctx
)
1411 ndis_miniport_block
*block
;
1412 struct ndis_allocwork
*w
;
1414 io_workitem_func ifw
;
1416 if (adapter
== NULL
)
1417 return (NDIS_STATUS_FAILURE
);
1421 iw
= IoAllocateWorkItem(block
->nmb_deviceobj
);
1423 return (NDIS_STATUS_FAILURE
);
1425 w
= kmalloc(sizeof(struct ndis_allocwork
), M_TEMP
, M_NOWAIT
);
1428 return (NDIS_STATUS_FAILURE
);
1430 w
->na_cached
= cached
;
1435 ifw
= (io_workitem_func
)ndis_findwrap((funcptr
)ndis_asyncmem_complete
);
1436 IoQueueWorkItem(iw
, ifw
, WORKQUEUE_DELAYED
, w
);
1438 return (NDIS_STATUS_PENDING
);
1442 NdisMFreeSharedMemory(ndis_handle adapter
, uint32_t len
, uint8_t cached
,
1443 void *vaddr
, ndis_physaddr paddr
)
1445 ndis_miniport_block
*block
;
1446 struct ndis_softc
*sc
;
1447 struct ndis_shmem
*sh
= NULL
;
1450 if (vaddr
== NULL
|| adapter
== NULL
)
1453 block
= (ndis_miniport_block
*)adapter
;
1454 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1456 /* Sanity check: is list empty? */
1458 if (IsListEmpty(&sc
->ndis_shlist
))
1462 l
= sc
->ndis_shlist
.nle_flink
;
1463 while (l
!= &sc
->ndis_shlist
) {
1464 sh
= CONTAINING_RECORD(l
, struct ndis_shmem
, ndis_list
);
1465 if (sh
->ndis_saddr
== vaddr
)
1468 * Check the physaddr too, just in case the driver lied
1469 * about the virtual address.
1471 if (sh
->ndis_paddr
.np_quad
== paddr
.np_quad
)
1478 kprintf("NDIS: buggy driver tried to free "
1479 "invalid shared memory: vaddr: %p paddr: 0x%jx\n",
1480 vaddr
, (uintmax_t)paddr
.np_quad
);
1484 RemoveEntryList(&sh
->ndis_list
);
1488 bus_dmamap_unload(sh
->ndis_stag
, sh
->ndis_smap
);
1489 bus_dmamem_free(sh
->ndis_stag
, sh
->ndis_saddr
, sh
->ndis_smap
);
1490 bus_dma_tag_destroy(sh
->ndis_stag
);
1492 kfree(sh
, M_DEVBUF
);
1496 NdisMMapIoSpace(void **vaddr
, ndis_handle adapter
, ndis_physaddr paddr
,
1499 if (adapter
== NULL
)
1500 return (NDIS_STATUS_FAILURE
);
1502 *vaddr
= MmMapIoSpace(paddr
.np_quad
, len
, 0);
1505 return (NDIS_STATUS_FAILURE
);
1507 return (NDIS_STATUS_SUCCESS
);
1511 NdisMUnmapIoSpace(ndis_handle adapter
, void *vaddr
, uint32_t len
)
1513 MmUnmapIoSpace(vaddr
, len
);
1517 NdisGetCacheFillSize(void)
1523 NdisGetRoutineAddress(unicode_string
*ustr
)
1527 if (RtlUnicodeStringToAnsiString(&astr
, ustr
, TRUE
))
1529 return (ndis_get_routine_address(ndis_functbl
, astr
.as_buf
));
1533 NdisMGetDmaAlignment(ndis_handle handle
)
1539 * NDIS has two methods for dealing with NICs that support DMA.
1540 * One is to just pass packets to the driver and let it call
1541 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
1542 * all by itself, and the other is to let the NDIS library handle the
1543 * buffer mapping internally, and hand the driver an already populated
1544 * scatter/gather fragment list. If the driver calls
1545 * NdisMInitializeScatterGatherDma(), it wants to use the latter
1550 NdisMInitializeScatterGatherDma(ndis_handle adapter
, uint8_t is64
,
1551 uint32_t maxphysmap
)
1553 struct ndis_softc
*sc
;
1554 ndis_miniport_block
*block
;
1557 if (adapter
== NULL
)
1558 return (NDIS_STATUS_FAILURE
);
1559 block
= (ndis_miniport_block
*)adapter
;
1560 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
1562 /* Don't do this twice. */
1563 if (sc
->ndis_sc
== 1)
1564 return (NDIS_STATUS_SUCCESS
);
1566 error
= bus_dma_tag_create(sc
->ndis_parent_tag
, ETHER_ALIGN
, 0,
1567 BUS_SPACE_MAXADDR_32BIT
, BUS_SPACE_MAXADDR
, NULL
, NULL
,
1568 MCLBYTES
* NDIS_MAXSEG
, NDIS_MAXSEG
, MCLBYTES
, BUS_DMA_ALLOCNOW
,
1573 return (NDIS_STATUS_SUCCESS
);
1577 NdisAllocatePacketPool(ndis_status
*status
, ndis_handle
*pool
,
1578 uint32_t descnum
, uint32_t protrsvdlen
)
1580 ndis_packet_pool
*p
;
1581 ndis_packet
*packets
;
1584 p
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(ndis_packet_pool
), 0);
1586 *status
= NDIS_STATUS_RESOURCES
;
1590 p
->np_cnt
= descnum
+ NDIS_POOL_EXTRA
;
1591 p
->np_protrsvd
= protrsvdlen
;
1592 p
->np_len
= sizeof(ndis_packet
) + protrsvdlen
;
1594 packets
= ExAllocatePoolWithTag(NonPagedPool
, p
->np_cnt
*
1598 if (packets
== NULL
) {
1600 *status
= NDIS_STATUS_RESOURCES
;
1604 p
->np_pktmem
= packets
;
1606 for (i
= 0; i
< p
->np_cnt
; i
++)
1607 InterlockedPushEntrySList(&p
->np_head
,
1608 (struct slist_entry
*)&packets
[i
]);
1610 #ifdef NDIS_DEBUG_PACKETS
1612 KeInitializeSpinLock(&p
->np_lock
);
1613 KeInitializeEvent(&p
->np_event
, EVENT_TYPE_NOTIFY
, TRUE
);
1617 *status
= NDIS_STATUS_SUCCESS
;
1621 NdisAllocatePacketPoolEx(ndis_status
*status
, ndis_handle
*pool
,
1622 uint32_t descnum
, uint32_t oflowdescnum
, uint32_t protrsvdlen
)
1624 NdisAllocatePacketPool(status
, pool
, descnum
+ oflowdescnum
,
1629 NdisPacketPoolUsage(ndis_handle pool
)
1631 ndis_packet_pool
*p
;
1633 p
= (ndis_packet_pool
*)pool
;
1634 return (p
->np_cnt
- ExQueryDepthSList(&p
->np_head
));
1638 NdisFreePacketPool(ndis_handle pool
)
1640 ndis_packet_pool
*p
;
1642 #ifdef NDIS_DEBUG_PACKETS
1646 p
= (ndis_packet_pool
*)pool
;
1648 #ifdef NDIS_DEBUG_PACKETS
1649 KeAcquireSpinLock(&p
->np_lock
, &irql
);
1652 usage
= NdisPacketPoolUsage(pool
);
1654 #ifdef NDIS_DEBUG_PACKETS
1657 KeResetEvent(&p
->np_event
);
1658 KeReleaseSpinLock(&p
->np_lock
, irql
);
1659 KeWaitForSingleObject(&p
->np_event
, 0, 0, FALSE
, NULL
);
1661 KeReleaseSpinLock(&p
->np_lock
, irql
);
1664 ExFreePool(p
->np_pktmem
);
1669 NdisAllocatePacket(ndis_status
*status
, ndis_packet
**packet
, ndis_handle pool
)
1671 ndis_packet_pool
*p
;
1673 #ifdef NDIS_DEBUG_PACKETS
1677 p
= (ndis_packet_pool
*)pool
;
1679 #ifdef NDIS_DEBUG_PACKETS
1680 KeAcquireSpinLock(&p
->np_lock
, &irql
);
1682 KeReleaseSpinLock(&p
->np_lock
, irql
);
1683 kprintf("NDIS: tried to allocate packet from dead pool %p\n",
1685 *status
= NDIS_STATUS_RESOURCES
;
1690 pkt
= (ndis_packet
*)InterlockedPopEntrySList(&p
->np_head
);
1692 #ifdef NDIS_DEBUG_PACKETS
1693 KeReleaseSpinLock(&p
->np_lock
, irql
);
1697 *status
= NDIS_STATUS_RESOURCES
;
1702 bzero((char *)pkt
, sizeof(ndis_packet
));
1704 /* Save pointer to the pool. */
1705 pkt
->np_private
.npp_pool
= pool
;
1707 /* Set the oob offset pointer. Lots of things expect this. */
1708 pkt
->np_private
.npp_packetooboffset
= offsetof(ndis_packet
, np_oob
);
1711 * We must initialize the packet flags correctly in order
1712 * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
1713 * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work
1716 pkt
->np_private
.npp_ndispktflags
= NDIS_PACKET_ALLOCATED_BY_NDIS
;
1717 pkt
->np_private
.npp_validcounts
= FALSE
;
1721 *status
= NDIS_STATUS_SUCCESS
;
1725 NdisFreePacket(ndis_packet
*packet
)
1727 ndis_packet_pool
*p
;
1728 #ifdef NDIS_DEBUG_PACKETS
1732 p
= (ndis_packet_pool
*)packet
->np_private
.npp_pool
;
1734 #ifdef NDIS_DEBUG_PACKETS
1735 KeAcquireSpinLock(&p
->np_lock
, &irql
);
1738 InterlockedPushEntrySList(&p
->np_head
, (slist_entry
*)packet
);
1740 #ifdef NDIS_DEBUG_PACKETS
1742 if (ExQueryDepthSList(&p
->np_head
) == p
->np_cnt
)
1743 KeSetEvent(&p
->np_event
, IO_NO_INCREMENT
, FALSE
);
1745 KeReleaseSpinLock(&p
->np_lock
, irql
);
1750 NdisUnchainBufferAtFront(ndis_packet
*packet
, ndis_buffer
**buf
)
1752 ndis_packet_private
*priv
;
1754 if (packet
== NULL
|| buf
== NULL
)
1757 priv
= &packet
->np_private
;
1759 priv
->npp_validcounts
= FALSE
;
1761 if (priv
->npp_head
== priv
->npp_tail
) {
1762 *buf
= priv
->npp_head
;
1763 priv
->npp_head
= priv
->npp_tail
= NULL
;
1765 *buf
= priv
->npp_head
;
1766 priv
->npp_head
= (*buf
)->mdl_next
;
1771 NdisUnchainBufferAtBack(ndis_packet
*packet
, ndis_buffer
**buf
)
1773 ndis_packet_private
*priv
;
1776 if (packet
== NULL
|| buf
== NULL
)
1779 priv
= &packet
->np_private
;
1781 priv
->npp_validcounts
= FALSE
;
1783 if (priv
->npp_head
== priv
->npp_tail
) {
1784 *buf
= priv
->npp_head
;
1785 priv
->npp_head
= priv
->npp_tail
= NULL
;
1787 *buf
= priv
->npp_tail
;
1788 tmp
= priv
->npp_head
;
1789 while (tmp
->mdl_next
!= priv
->npp_tail
)
1790 tmp
= tmp
->mdl_next
;
1791 priv
->npp_tail
= tmp
;
1792 tmp
->mdl_next
= NULL
;
1797 * The NDIS "buffer" is really an MDL (memory descriptor list)
1798 * which is used to describe a buffer in a way that allows it
1799 * to mapped into different contexts. We have to be careful how
1800 * we handle them: in some versions of Windows, the NdisFreeBuffer()
1801 * routine is an actual function in the NDIS API, but in others
1802 * it's just a macro wrapper around IoFreeMdl(). There's really
1803 * no way to use the 'descnum' parameter to count how many
1804 * "buffers" are allocated since in order to use IoFreeMdl() to
1805 * dispose of a buffer, we have to use IoAllocateMdl() to allocate
1806 * them, and IoAllocateMdl() just grabs them out of the heap.
1810 NdisAllocateBufferPool(ndis_status
*status
, ndis_handle
*pool
,
1815 * The only thing we can really do here is verify that descnum
1816 * is a reasonable value, but I really don't know what to check
1820 *pool
= NonPagedPool
;
1821 *status
= NDIS_STATUS_SUCCESS
;
1825 NdisFreeBufferPool(ndis_handle pool
)
1830 NdisAllocateBuffer(ndis_status
*status
, ndis_buffer
**buffer
, ndis_handle pool
,
1831 void *vaddr
, uint32_t len
)
1835 buf
= IoAllocateMdl(vaddr
, len
, FALSE
, FALSE
, NULL
);
1837 *status
= NDIS_STATUS_RESOURCES
;
1841 MmBuildMdlForNonPagedPool(buf
);
1844 *status
= NDIS_STATUS_SUCCESS
;
1848 NdisFreeBuffer(ndis_buffer
*buf
)
1856 NdisBufferLength(ndis_buffer
*buf
)
1858 return (MmGetMdlByteCount(buf
));
1862 * Get the virtual address and length of a buffer.
1863 * Note: the vaddr argument is optional.
1867 NdisQueryBuffer(ndis_buffer
*buf
, void **vaddr
, uint32_t *len
)
1870 *vaddr
= MmGetMdlVirtualAddress(buf
);
1871 *len
= MmGetMdlByteCount(buf
);
1874 /* Same as above -- we don't care about the priority. */
1877 NdisQueryBufferSafe(ndis_buffer
*buf
, void **vaddr
, uint32_t *len
,
1881 *vaddr
= MmGetMdlVirtualAddress(buf
);
1882 *len
= MmGetMdlByteCount(buf
);
1885 /* Damnit Microsoft!! How many ways can you do the same thing?! */
1888 NdisBufferVirtualAddress(ndis_buffer
*buf
)
1890 return (MmGetMdlVirtualAddress(buf
));
1894 NdisBufferVirtualAddressSafe(ndis_buffer
*buf
, uint32_t prio
)
1896 return (MmGetMdlVirtualAddress(buf
));
1900 NdisAdjustBufferLength(ndis_buffer
*buf
, int len
)
1902 MmGetMdlByteCount(buf
) = len
;
1906 NdisInterlockedIncrement(uint32_t *addend
)
1908 atomic_add_long((u_long
*)addend
, 1);
1913 NdisInterlockedDecrement(uint32_t *addend
)
1915 atomic_subtract_long((u_long
*)addend
, 1);
1920 NdisGetVersion(void)
1922 return (0x00050001);
1926 NdisInitializeEvent(ndis_event
*event
)
1929 * NDIS events are always notification
1930 * events, and should be initialized to the
1931 * not signaled state.
1933 KeInitializeEvent(&event
->ne_event
, EVENT_TYPE_NOTIFY
, FALSE
);
1937 NdisSetEvent(ndis_event
*event
)
1939 KeSetEvent(&event
->ne_event
, IO_NO_INCREMENT
, FALSE
);
1943 NdisResetEvent(ndis_event
*event
)
1945 KeResetEvent(&event
->ne_event
);
1949 NdisWaitEvent(ndis_event
*event
, uint32_t msecs
)
1954 duetime
= ((int64_t)msecs
* -10000);
1955 rval
= KeWaitForSingleObject(event
,
1956 0, 0, TRUE
, msecs
? & duetime
: NULL
);
1958 if (rval
== STATUS_TIMEOUT
)
1965 NdisUnicodeStringToAnsiString(ansi_string
*dstr
, unicode_string
*sstr
)
1969 rval
= RtlUnicodeStringToAnsiString(dstr
, sstr
, FALSE
);
1971 if (rval
== STATUS_INSUFFICIENT_RESOURCES
)
1972 return (NDIS_STATUS_RESOURCES
);
1974 return (NDIS_STATUS_FAILURE
);
1976 return (NDIS_STATUS_SUCCESS
);
1980 NdisAnsiStringToUnicodeString(unicode_string
*dstr
, ansi_string
*sstr
)
1984 rval
= RtlAnsiStringToUnicodeString(dstr
, sstr
, FALSE
);
1986 if (rval
== STATUS_INSUFFICIENT_RESOURCES
)
1987 return (NDIS_STATUS_RESOURCES
);
1989 return (NDIS_STATUS_FAILURE
);
1991 return (NDIS_STATUS_SUCCESS
);
1995 NdisMPciAssignResources(ndis_handle adapter
, uint32_t slot
,
1996 ndis_resource_list
**list
)
1998 ndis_miniport_block
*block
;
2000 if (adapter
== NULL
|| list
== NULL
)
2001 return (NDIS_STATUS_FAILURE
);
2003 block
= (ndis_miniport_block
*)adapter
;
2004 *list
= block
->nmb_rlist
;
2006 return (NDIS_STATUS_SUCCESS
);
2010 ndis_intr(kinterrupt
*iobj
, void *arg
)
2012 struct ndis_softc
*sc
;
2013 uint8_t is_our_intr
= FALSE
;
2015 ndis_miniport_interrupt
*intr
;
2018 intr
= sc
->ndis_block
->nmb_interrupt
;
2020 if (intr
== NULL
|| sc
->ndis_block
->nmb_miniportadapterctx
== NULL
)
2023 if (sc
->ndis_block
->nmb_interrupt
->ni_isrreq
== TRUE
)
2024 MSCALL3(intr
->ni_isrfunc
, &is_our_intr
, &call_isr
,
2025 sc
->ndis_block
->nmb_miniportadapterctx
);
2027 MSCALL1(sc
->ndis_chars
->nmc_disable_interrupts_func
,
2028 sc
->ndis_block
->nmb_miniportadapterctx
);
2033 IoRequestDpc(sc
->ndis_block
->nmb_deviceobj
, NULL
, sc
);
2035 return (is_our_intr
);
2039 ndis_intrhand(kdpc
*dpc
, ndis_miniport_interrupt
*intr
, void *sysarg1
,
2042 struct ndis_softc
*sc
;
2043 ndis_miniport_block
*block
;
2044 ndis_handle adapter
;
2046 block
= intr
->ni_block
;
2047 adapter
= block
->nmb_miniportadapterctx
;
2048 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
2050 if (NDIS_SERIALIZED(sc
->ndis_block
))
2051 KeAcquireSpinLockAtDpcLevel(&block
->nmb_lock
);
2053 MSCALL1(intr
->ni_dpcfunc
, adapter
);
2055 /* If there's a MiniportEnableInterrupt() routine, call it. */
2057 if (sc
->ndis_chars
->nmc_enable_interrupts_func
!= NULL
)
2058 MSCALL1(sc
->ndis_chars
->nmc_enable_interrupts_func
, adapter
);
2060 if (NDIS_SERIALIZED(sc
->ndis_block
))
2061 KeReleaseSpinLockFromDpcLevel(&block
->nmb_lock
);
2064 * Set the completion event if we've drained all
2065 * pending interrupts.
2068 KeAcquireSpinLockAtDpcLevel(&intr
->ni_dpccountlock
);
2070 if (intr
->ni_dpccnt
== 0)
2071 KeSetEvent(&intr
->ni_dpcevt
, IO_NO_INCREMENT
, FALSE
);
2072 KeReleaseSpinLockFromDpcLevel(&intr
->ni_dpccountlock
);
2076 NdisMRegisterInterrupt(ndis_miniport_interrupt
*intr
, ndis_handle adapter
,
2077 uint32_t ivec
, uint32_t ilevel
, uint8_t reqisr
, uint8_t shared
,
2078 ndis_interrupt_mode imode
)
2080 ndis_miniport_block
*block
;
2081 ndis_miniport_characteristics
*ch
;
2082 struct ndis_softc
*sc
;
2086 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
2087 ch
= IoGetDriverObjectExtension(block
->nmb_deviceobj
->do_drvobj
,
2090 intr
->ni_rsvd
= ExAllocatePoolWithTag(NonPagedPool
,
2091 sizeof(struct mtx
), 0);
2092 if (intr
->ni_rsvd
== NULL
)
2093 return (NDIS_STATUS_RESOURCES
);
2095 intr
->ni_block
= adapter
;
2096 intr
->ni_isrreq
= reqisr
;
2097 intr
->ni_shared
= shared
;
2098 intr
->ni_dpccnt
= 0;
2099 intr
->ni_isrfunc
= ch
->nmc_isr_func
;
2100 intr
->ni_dpcfunc
= ch
->nmc_interrupt_func
;
2102 KeInitializeEvent(&intr
->ni_dpcevt
, EVENT_TYPE_NOTIFY
, TRUE
);
2103 KeInitializeDpc(&intr
->ni_dpc
,
2104 ndis_findwrap((funcptr
)ndis_intrhand
), intr
);
2105 KeSetImportanceDpc(&intr
->ni_dpc
, KDPC_IMPORTANCE_LOW
);
2107 error
= IoConnectInterrupt(&intr
->ni_introbj
,
2108 ndis_findwrap((funcptr
)ndis_intr
), sc
, NULL
,
2109 ivec
, ilevel
, 0, imode
, shared
, 0, FALSE
);
2111 if (error
!= STATUS_SUCCESS
)
2112 return (NDIS_STATUS_FAILURE
);
2114 block
->nmb_interrupt
= intr
;
2116 return (NDIS_STATUS_SUCCESS
);
2120 NdisMDeregisterInterrupt(ndis_miniport_interrupt
*intr
)
2122 ndis_miniport_block
*block
;
2125 block
= intr
->ni_block
;
2127 /* Should really be KeSynchronizeExecution() */
2129 KeAcquireSpinLock(intr
->ni_introbj
->ki_lock
, &irql
);
2130 block
->nmb_interrupt
= NULL
;
2131 KeReleaseSpinLock(intr
->ni_introbj
->ki_lock
, irql
);
2133 KeFlushQueuedDpcs();
2135 /* Disconnect our ISR */
2137 IoDisconnectInterrupt(intr
->ni_introbj
);
2139 KeWaitForSingleObject(&intr
->ni_dpcevt
, 0, 0, FALSE
, NULL
);
2140 KeResetEvent(&intr
->ni_dpcevt
);
2144 NdisMRegisterAdapterShutdownHandler(ndis_handle adapter
, void *shutdownctx
,
2145 ndis_shutdown_handler shutdownfunc
)
2147 ndis_miniport_block
*block
;
2148 ndis_miniport_characteristics
*chars
;
2149 struct ndis_softc
*sc
;
2151 if (adapter
== NULL
)
2154 block
= (ndis_miniport_block
*)adapter
;
2155 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
2156 chars
= sc
->ndis_chars
;
2158 chars
->nmc_shutdown_handler
= shutdownfunc
;
2159 chars
->nmc_rsvd0
= shutdownctx
;
2163 NdisMDeregisterAdapterShutdownHandler(ndis_handle adapter
)
2165 ndis_miniport_block
*block
;
2166 ndis_miniport_characteristics
*chars
;
2167 struct ndis_softc
*sc
;
2169 if (adapter
== NULL
)
2172 block
= (ndis_miniport_block
*)adapter
;
2173 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
2174 chars
= sc
->ndis_chars
;
2176 chars
->nmc_shutdown_handler
= NULL
;
2177 chars
->nmc_rsvd0
= NULL
;
2181 NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer
*buf
)
2185 if (MmGetMdlByteCount(buf
) == 0)
2187 return (SPAN_PAGES(MmGetMdlVirtualAddress(buf
),
2188 MmGetMdlByteCount(buf
)));
2192 NdisGetBufferPhysicalArraySize(ndis_buffer
*buf
, uint32_t *pages
)
2197 *pages
= NDIS_BUFFER_TO_SPAN_PAGES(buf
);
2201 NdisQueryBufferOffset(ndis_buffer
*buf
, uint32_t *off
, uint32_t *len
)
2206 *off
= MmGetMdlByteOffset(buf
);
2207 *len
= MmGetMdlByteCount(buf
);
2211 NdisMSleep(uint32_t usecs
)
2216 * During system bootstrap, (i.e. cold == 1), we aren't
2217 * allowed to sleep, so we have to do a hard DELAY()
2224 KeInitializeTimer(&timer
);
2225 KeSetTimer(&timer
, ((int64_t)usecs
* -10), NULL
);
2226 KeWaitForSingleObject(&timer
, 0, 0, FALSE
, NULL
);
2231 NdisReadPcmciaAttributeMemory(ndis_handle handle
, uint32_t offset
, void *buf
,
2234 struct ndis_softc
*sc
;
2235 ndis_miniport_block
*block
;
2236 bus_space_handle_t bh
;
2244 block
= (ndis_miniport_block
*)handle
;
2245 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
2248 bh
= rman_get_bushandle(sc
->ndis_res_am
);
2249 bt
= rman_get_bustag(sc
->ndis_res_am
);
2251 for (i
= 0; i
< len
; i
++)
2252 dest
[i
] = bus_space_read_1(bt
, bh
, (offset
+ i
) * 2);
2258 NdisWritePcmciaAttributeMemory(ndis_handle handle
, uint32_t offset
, void *buf
,
2261 struct ndis_softc
*sc
;
2262 ndis_miniport_block
*block
;
2263 bus_space_handle_t bh
;
2271 block
= (ndis_miniport_block
*)handle
;
2272 sc
= device_get_softc(block
->nmb_physdeviceobj
->do_devext
);
2275 bh
= rman_get_bushandle(sc
->ndis_res_am
);
2276 bt
= rman_get_bustag(sc
->ndis_res_am
);
2278 for (i
= 0; i
< len
; i
++)
2279 bus_space_write_1(bt
, bh
, (offset
+ i
) * 2, src
[i
]);
2285 NdisInterlockedInsertHeadList(list_entry
*head
, list_entry
*entry
,
2286 ndis_spin_lock
*lock
)
2290 KeAcquireSpinLock(&lock
->nsl_spinlock
, &lock
->nsl_kirql
);
2291 flink
= head
->nle_flink
;
2292 entry
->nle_flink
= flink
;
2293 entry
->nle_blink
= head
;
2294 flink
->nle_blink
= entry
;
2295 head
->nle_flink
= entry
;
2296 KeReleaseSpinLock(&lock
->nsl_spinlock
, lock
->nsl_kirql
);
2302 NdisInterlockedRemoveHeadList(list_entry
*head
, ndis_spin_lock
*lock
)
2307 KeAcquireSpinLock(&lock
->nsl_spinlock
, &lock
->nsl_kirql
);
2308 entry
= head
->nle_flink
;
2309 flink
= entry
->nle_flink
;
2310 head
->nle_flink
= flink
;
2311 flink
->nle_blink
= head
;
2312 KeReleaseSpinLock(&lock
->nsl_spinlock
, lock
->nsl_kirql
);
2318 NdisInterlockedInsertTailList(list_entry
*head
, list_entry
*entry
,
2319 ndis_spin_lock
*lock
)
2323 KeAcquireSpinLock(&lock
->nsl_spinlock
, &lock
->nsl_kirql
);
2324 blink
= head
->nle_blink
;
2325 entry
->nle_flink
= head
;
2326 entry
->nle_blink
= blink
;
2327 blink
->nle_flink
= entry
;
2328 head
->nle_blink
= entry
;
2329 KeReleaseSpinLock(&lock
->nsl_spinlock
, lock
->nsl_kirql
);
2335 NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt
*intr
, void *syncfunc
,
2338 return (KeSynchronizeExecution(intr
->ni_introbj
, syncfunc
, syncctx
));
2342 NdisGetCurrentSystemTime(uint64_t *tval
)
2344 ntoskrnl_time(tval
);
2348 * Return the number of milliseconds since the system booted.
2351 NdisGetSystemUpTime(uint32_t *tval
)
2356 *tval
= ts
.tv_nsec
/ 1000000 + ts
.tv_sec
* 1000;
2360 NdisInitializeString(unicode_string
*dst
, char *src
)
2363 RtlInitAnsiString(&as
, src
);
2364 RtlAnsiStringToUnicodeString(dst
, &as
, TRUE
);
2368 NdisFreeString(unicode_string
*str
)
2370 RtlFreeUnicodeString(str
);
2374 NdisMRemoveMiniport(ndis_handle
*adapter
)
2376 return (NDIS_STATUS_SUCCESS
);
2380 NdisInitAnsiString(ansi_string
*dst
, char *src
)
2382 RtlInitAnsiString(dst
, src
);
2386 NdisInitUnicodeString(unicode_string
*dst
, uint16_t *src
)
2388 RtlInitUnicodeString(dst
, src
);
2391 static void NdisMGetDeviceProperty(ndis_handle adapter
,
2392 device_object
**phydevobj
, device_object
**funcdevobj
,
2393 device_object
**nextdevobj
, cm_resource_list
*resources
,
2394 cm_resource_list
*transresources
)
2396 ndis_miniport_block
*block
;
2398 block
= (ndis_miniport_block
*)adapter
;
2400 if (phydevobj
!= NULL
)
2401 *phydevobj
= block
->nmb_physdeviceobj
;
2402 if (funcdevobj
!= NULL
)
2403 *funcdevobj
= block
->nmb_deviceobj
;
2404 if (nextdevobj
!= NULL
)
2405 *nextdevobj
= block
->nmb_nextdeviceobj
;
2409 NdisGetFirstBufferFromPacket(ndis_packet
*packet
, ndis_buffer
**buf
,
2410 void **firstva
, uint32_t *firstlen
, uint32_t *totlen
)
2414 tmp
= packet
->np_private
.npp_head
;
2418 *firstlen
= *totlen
= 0;
2420 *firstva
= MmGetMdlVirtualAddress(tmp
);
2421 *firstlen
= *totlen
= MmGetMdlByteCount(tmp
);
2422 for (tmp
= tmp
->mdl_next
; tmp
!= NULL
; tmp
= tmp
->mdl_next
)
2423 *totlen
+= MmGetMdlByteCount(tmp
);
2428 NdisGetFirstBufferFromPacketSafe(ndis_packet
*packet
, ndis_buffer
**buf
,
2429 void **firstva
, uint32_t *firstlen
, uint32_t *totlen
, uint32_t prio
)
2431 NdisGetFirstBufferFromPacket(packet
, buf
, firstva
, firstlen
, totlen
);
2435 ndis_find_sym(linker_file_t lf
, char *filename
, char *suffix
, caddr_t
*sym
)
2441 fullsym
= ExAllocatePoolWithTag(NonPagedPool
, MAXPATHLEN
, 0);
2442 if (fullsym
== NULL
)
2445 bzero(fullsym
, MAXPATHLEN
);
2446 strncpy(fullsym
, filename
, MAXPATHLEN
);
2447 if (strlen(filename
) < 4) {
2448 ExFreePool(fullsym
);
2452 /* If the filename has a .ko suffix, strip if off. */
2453 suf
= fullsym
+ (strlen(filename
) - 3);
2454 if (strcmp(suf
, ".ko") == 0)
2457 for (i
= 0; i
< strlen(fullsym
); i
++) {
2458 if (fullsym
[i
] == '.')
2461 fullsym
[i
] = tolower(fullsym
[i
]);
2463 strcat(fullsym
, suffix
);
2464 linker_file_lookup_symbol(lf
, fullsym
, 0, sym
);
2465 ExFreePool(fullsym
);
2472 struct ndis_checkmodule
{
2478 * See if a single module contains the symbols for a specified file.
2481 NdisCheckModule(linker_file_t lf
, void *context
)
2483 struct ndis_checkmodule
*nc
;
2484 caddr_t kldstart
, kldend
;
2486 nc
= (struct ndis_checkmodule
*)context
;
2487 if (ndis_find_sym(lf
, nc
->afilename
, "_start", &kldstart
))
2489 if (ndis_find_sym(lf
, nc
->afilename
, "_end", &kldend
))
2492 nc
->fh
->nf_map
= NULL
;
2493 nc
->fh
->nf_type
= NDIS_FH_TYPE_MODULE
;
2494 nc
->fh
->nf_maplen
= (kldend
- kldstart
) & 0xFFFFFFFF;
2498 /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
2500 NdisOpenFile(ndis_status
*status
, ndis_handle
*filehandle
,
2501 uint32_t *filelength
, unicode_string
*filename
, ndis_physaddr highestaddr
)
2504 char *afilename
= NULL
;
2505 struct thread
*td
= curthread
;
2506 struct nlookupdata nd
;
2509 struct vattr
*vap
= &vat
;
2512 struct ndis_checkmodule nc
;
2515 if (RtlUnicodeStringToAnsiString(&as
, filename
, TRUE
)) {
2516 *status
= NDIS_STATUS_RESOURCES
;
2520 afilename
= kstrdup(as
.as_buf
, M_DEVBUF
);
2521 RtlFreeAnsiString(&as
);
2523 fh
= ExAllocatePoolWithTag(NonPagedPool
, sizeof(ndis_fh
), 0);
2525 kfree(afilename
, M_DEVBUF
);
2526 *status
= NDIS_STATUS_RESOURCES
;
2530 fh
->nf_name
= afilename
;
2533 * During system bootstrap, it's impossible to load files
2534 * from the rootfs since it's not mounted yet. We therefore
2535 * offer the possibility of opening files that have been
2536 * preloaded as modules instead. Both choices will work
2537 * when kldloading a module from multiuser, but only the
2538 * module option will work during bootstrap. The module
2539 * loading option works by using the ndiscvt(8) utility
2540 * to convert the arbitrary file into a .ko using objcopy(1).
2541 * This file will contain two special symbols: filename_start
2542 * and filename_end. All we have to do is traverse the KLD
2543 * list in search of those symbols and we've found the file
2544 * data. As an added bonus, ndiscvt(8) will also generate
2545 * a normal .o file which can be linked statically with
2546 * the kernel. This means that the symbols will actual reside
2547 * in the kernel's symbol table, but that doesn't matter to
2548 * us since the kernel appears to us as just another module.
2551 nc
.afilename
= afilename
;
2553 if (linker_file_foreach(NdisCheckModule
, &nc
)) {
2554 *filelength
= fh
->nf_maplen
;
2556 *status
= NDIS_STATUS_SUCCESS
;
2560 if (mountlist_boot_getfirst() == NULL
) {
2562 *status
= NDIS_STATUS_FILE_NOT_FOUND
;
2563 kprintf("NDIS: could not find file %s in linker list\n",
2565 kprintf("NDIS: and no filesystems mounted yet, "
2566 "aborting NdisOpenFile()\n");
2567 kfree(afilename
, M_DEVBUF
);
2571 path
= ExAllocatePoolWithTag(NonPagedPool
, MAXPATHLEN
, 0);
2574 kfree(afilename
, M_DEVBUF
);
2575 *status
= NDIS_STATUS_RESOURCES
;
2579 ksnprintf(path
, MAXPATHLEN
, "%s/%s", ndis_filepath
, afilename
);
2581 /* Some threads don't have a current working directory. */
2583 if (td
->td_proc
&& td
->td_proc
->p_fd
->fd_rdir
== NULL
)
2584 td
->td_proc
->p_fd
->fd_rdir
= rootvnode
;
2585 if (td
->td_proc
&& td
->td_proc
->p_fd
->fd_cdir
== NULL
)
2586 td
->td_proc
->p_fd
->fd_cdir
= rootvnode
;
2588 error
= nlookup_init(&nd
, path
, UIO_SYSSPACE
, NLC_FOLLOW
|NLC_LOCKVP
);
2591 error
= vn_open(&nd
, NULL
, FREAD
, 0);
2598 nd
.nl_open_vp
= NULL
;
2600 /* Get the file size. */
2601 VOP_GETATTR(vp
, vap
);
2604 fh
->nf_vp
= nd
.nl_open_vp
;
2606 fh
->nf_type
= NDIS_FH_TYPE_VFS
;
2608 *filelength
= fh
->nf_maplen
= vap
->va_size
& 0xFFFFFFFF;
2609 *status
= NDIS_STATUS_SUCCESS
;
2616 *status
= NDIS_STATUS_FILE_NOT_FOUND
;
2618 kprintf("NDIS: open file %s failed: %d\n", path
, error
);
2620 kfree(afilename
, M_DEVBUF
);
2624 NdisMapFile(ndis_status
*status
, void **mappedbuffer
, ndis_handle filehandle
)
2627 struct thread
*td
= curthread
;
2633 if (filehandle
== NULL
) {
2634 *status
= NDIS_STATUS_FAILURE
;
2638 fh
= (ndis_fh
*)filehandle
;
2640 if (fh
->nf_vp
== NULL
) {
2641 *status
= NDIS_STATUS_FAILURE
;
2645 if (fh
->nf_map
!= NULL
) {
2646 *status
= NDIS_STATUS_ALREADY_MAPPED
;
2650 if (fh
->nf_type
== NDIS_FH_TYPE_MODULE
) {
2652 if (ndis_find_sym(lf
, fh
->nf_name
, "_start", &kldstart
)) {
2653 *status
= NDIS_STATUS_FAILURE
;
2656 fh
->nf_map
= kldstart
;
2657 *status
= NDIS_STATUS_SUCCESS
;
2658 *mappedbuffer
= fh
->nf_map
;
2662 fh
->nf_map
= ExAllocatePoolWithTag(NonPagedPool
, fh
->nf_maplen
, 0);
2664 if (fh
->nf_map
== NULL
) {
2665 *status
= NDIS_STATUS_RESOURCES
;
2670 error
= vn_rdwr(UIO_READ
, vp
, fh
->nf_map
, fh
->nf_maplen
, 0,
2671 UIO_SYSSPACE
, 0, td
->td_ucred
, &resid
);
2674 *status
= NDIS_STATUS_FAILURE
;
2676 *status
= NDIS_STATUS_SUCCESS
;
2677 *mappedbuffer
= fh
->nf_map
;
2682 NdisUnmapFile(ndis_handle filehandle
)
2685 fh
= (ndis_fh
*)filehandle
;
2687 if (fh
->nf_map
== NULL
)
2690 if (fh
->nf_type
== NDIS_FH_TYPE_VFS
)
2691 ExFreePool(fh
->nf_map
);
2696 NdisCloseFile(ndis_handle filehandle
)
2701 if (filehandle
== NULL
)
2704 fh
= (ndis_fh
*)filehandle
;
2705 if (fh
->nf_map
!= NULL
) {
2706 if (fh
->nf_type
== NDIS_FH_TYPE_VFS
)
2707 ExFreePool(fh
->nf_map
);
2711 if (fh
->nf_vp
== NULL
)
2714 if (fh
->nf_type
== NDIS_FH_TYPE_VFS
) {
2716 vn_close(vp
, FREAD
, NULL
);
2720 kfree(fh
->nf_name
, M_DEVBUF
);
2725 NdisSystemProcessorCount(void)
2731 NdisGetCurrentProcessorCounts(uint32_t *idle_count
, uint32_t *kernel_and_user
,
2734 #if 0 /* XXX swildner */
2737 pcpu
= pcpu_find(curthread
->td_oncpu
);
2738 *index
= pcpu
->pc_cpuid
;
2739 *idle_count
= pcpu
->pc_cp_time
[CP_IDLE
];
2740 *kernel_and_user
= pcpu
->pc_cp_time
[CP_INTR
];
2742 panic("%s", __func__
);
2746 typedef void (*ndis_statusdone_handler
)(ndis_handle
);
2747 typedef void (*ndis_status_handler
)(ndis_handle
, ndis_status
,
2751 NdisMIndicateStatusComplete(ndis_handle adapter
)
2753 ndis_miniport_block
*block
;
2754 ndis_statusdone_handler statusdonefunc
;
2756 block
= (ndis_miniport_block
*)adapter
;
2757 statusdonefunc
= block
->nmb_statusdone_func
;
2759 MSCALL1(statusdonefunc
, adapter
);
2763 NdisMIndicateStatus(ndis_handle adapter
, ndis_status status
, void *sbuf
,
2766 ndis_miniport_block
*block
;
2767 ndis_status_handler statusfunc
;
2769 block
= (ndis_miniport_block
*)adapter
;
2770 statusfunc
= block
->nmb_status_func
;
2772 MSCALL4(statusfunc
, adapter
, status
, sbuf
, slen
);
2776 * The DDK documentation says that you should use IoQueueWorkItem()
2777 * instead of ExQueueWorkItem(). The problem is, IoQueueWorkItem()
2778 * is fundamentally incompatible with NdisScheduleWorkItem(), which
2779 * depends on the API semantics of ExQueueWorkItem(). In our world,
2780 * ExQueueWorkItem() is implemented on top of IoAllocateQueueItem()
2783 * There are actually three distinct APIs here. NdisScheduleWorkItem()
2784 * takes a pointer to an NDIS_WORK_ITEM. ExQueueWorkItem() takes a pointer
2785 * to a WORK_QUEUE_ITEM. And finally, IoQueueWorkItem() takes a pointer
2786 * to an opaque work item thingie which you get from IoAllocateWorkItem().
2787 * An NDIS_WORK_ITEM is not the same as a WORK_QUEUE_ITEM. However,
2788 * the NDIS_WORK_ITEM has some opaque storage at the end of it, and we
2789 * (ab)use this storage as a WORK_QUEUE_ITEM, which is what we submit
2790 * to ExQueueWorkItem().
2792 * Got all that? (Sheesh.)
2796 NdisScheduleWorkItem(ndis_work_item
*work
)
2798 work_queue_item
*wqi
;
2800 wqi
= (work_queue_item
*)work
->nwi_wraprsvd
;
2801 ExInitializeWorkItem(wqi
,
2802 (work_item_func
)work
->nwi_func
, work
->nwi_ctx
);
2803 ExQueueWorkItem(wqi
, WORKQUEUE_DELAYED
);
2805 return (NDIS_STATUS_SUCCESS
);
2809 NdisCopyFromPacketToPacket(ndis_packet
*dpkt
, uint32_t doff
, uint32_t reqlen
,
2810 ndis_packet
*spkt
, uint32_t soff
, uint32_t *cpylen
)
2812 ndis_buffer
*src
, *dst
;
2814 int resid
, copied
, len
, scnt
, dcnt
;
2818 src
= spkt
->np_private
.npp_head
;
2819 dst
= dpkt
->np_private
.npp_head
;
2821 sptr
= MmGetMdlVirtualAddress(src
);
2822 dptr
= MmGetMdlVirtualAddress(dst
);
2823 scnt
= MmGetMdlByteCount(src
);
2824 dcnt
= MmGetMdlByteCount(dst
);
2827 if (MmGetMdlByteCount(src
) > soff
) {
2829 scnt
= MmGetMdlByteCount(src
)- soff
;
2832 soff
-= MmGetMdlByteCount(src
);
2833 src
= src
->mdl_next
;
2836 sptr
= MmGetMdlVirtualAddress(src
);
2840 if (MmGetMdlByteCount(dst
) > doff
) {
2842 dcnt
= MmGetMdlByteCount(dst
) - doff
;
2845 doff
-= MmGetMdlByteCount(dst
);
2846 dst
= dst
->mdl_next
;
2849 dptr
= MmGetMdlVirtualAddress(dst
);
2863 bcopy(sptr
, dptr
, len
);
2872 dst
= dst
->mdl_next
;
2875 dptr
= MmGetMdlVirtualAddress(dst
);
2876 dcnt
= MmGetMdlByteCount(dst
);
2881 src
= src
->mdl_next
;
2884 sptr
= MmGetMdlVirtualAddress(src
);
2885 scnt
= MmGetMdlByteCount(src
);
2893 NdisCopyFromPacketToPacketSafe(ndis_packet
*dpkt
, uint32_t doff
,
2894 uint32_t reqlen
, ndis_packet
*spkt
, uint32_t soff
, uint32_t *cpylen
,
2897 NdisCopyFromPacketToPacket(dpkt
, doff
, reqlen
, spkt
, soff
, cpylen
);
2901 NdisIMCopySendPerPacketInfo(ndis_packet
*dpkt
, ndis_packet
*spkt
)
2903 memcpy(&dpkt
->np_ext
, &spkt
->np_ext
, sizeof(ndis_packet_extension
));
2907 NdisMRegisterDevice(ndis_handle handle
, unicode_string
*devname
,
2908 unicode_string
*symname
, driver_dispatch
*majorfuncs
[], void **devobj
,
2909 ndis_handle
*devhandle
)
2912 device_object
*dobj
;
2914 status
= IoCreateDevice(handle
, 0, devname
,
2915 FILE_DEVICE_UNKNOWN
, 0, FALSE
, &dobj
);
2917 if (status
== STATUS_SUCCESS
) {
2926 NdisMDeregisterDevice(ndis_handle handle
)
2928 IoDeleteDevice(handle
);
2929 return (NDIS_STATUS_SUCCESS
);
2933 NdisMQueryAdapterInstanceName(unicode_string
*name
, ndis_handle handle
)
2935 ndis_miniport_block
*block
;
2939 block
= (ndis_miniport_block
*)handle
;
2940 dev
= block
->nmb_physdeviceobj
->do_devext
;
2942 RtlInitAnsiString(&as
, __DECONST(char *, device_get_nameunit(dev
)));
2943 if (RtlAnsiStringToUnicodeString(name
, &as
, TRUE
))
2944 return (NDIS_STATUS_RESOURCES
);
2946 return (NDIS_STATUS_SUCCESS
);
2950 NdisMRegisterUnloadHandler(ndis_handle handle
, void *func
)
2957 kprintf("NDIS dummy called...\n");
2961 * Note: a couple of entries in this table specify the
2962 * number of arguments as "foo + 1". These are routines
2963 * that accept a 64-bit argument, passed by value. On
2964 * x86, these arguments consume two longwords on the stack,
2965 * so we lie and say there's one additional argument so
2966 * that the wrapping routines will do the right thing.
2969 image_patch_table ndis_functbl
[] = {
2970 IMPORT_SFUNC(NdisCopyFromPacketToPacket
, 6),
2971 IMPORT_SFUNC(NdisCopyFromPacketToPacketSafe
, 7),
2972 IMPORT_SFUNC(NdisIMCopySendPerPacketInfo
, 2),
2973 IMPORT_SFUNC(NdisScheduleWorkItem
, 1),
2974 IMPORT_SFUNC(NdisMIndicateStatusComplete
, 1),
2975 IMPORT_SFUNC(NdisMIndicateStatus
, 4),
2976 IMPORT_SFUNC(NdisSystemProcessorCount
, 0),
2977 IMPORT_SFUNC(NdisGetCurrentProcessorCounts
, 3),
2978 IMPORT_SFUNC(NdisUnchainBufferAtBack
, 2),
2979 IMPORT_SFUNC(NdisGetFirstBufferFromPacket
, 5),
2980 IMPORT_SFUNC(NdisGetFirstBufferFromPacketSafe
, 6),
2981 IMPORT_SFUNC(NdisGetBufferPhysicalArraySize
, 2),
2982 IMPORT_SFUNC(NdisMGetDeviceProperty
, 6),
2983 IMPORT_SFUNC(NdisInitAnsiString
, 2),
2984 IMPORT_SFUNC(NdisInitUnicodeString
, 2),
2985 IMPORT_SFUNC(NdisWriteConfiguration
, 4),
2986 IMPORT_SFUNC(NdisAnsiStringToUnicodeString
, 2),
2987 IMPORT_SFUNC(NdisTerminateWrapper
, 2),
2988 IMPORT_SFUNC(NdisOpenConfigurationKeyByName
, 4),
2989 IMPORT_SFUNC(NdisOpenConfigurationKeyByIndex
, 5),
2990 IMPORT_SFUNC(NdisMRemoveMiniport
, 1),
2991 IMPORT_SFUNC(NdisInitializeString
, 2),
2992 IMPORT_SFUNC(NdisFreeString
, 1),
2993 IMPORT_SFUNC(NdisGetCurrentSystemTime
, 1),
2994 IMPORT_SFUNC(NdisGetRoutineAddress
, 1),
2995 IMPORT_SFUNC(NdisGetSystemUpTime
, 1),
2996 IMPORT_SFUNC(NdisGetVersion
, 0),
2997 IMPORT_SFUNC(NdisMSynchronizeWithInterrupt
, 3),
2998 IMPORT_SFUNC(NdisMAllocateSharedMemoryAsync
, 4),
2999 IMPORT_SFUNC(NdisInterlockedInsertHeadList
, 3),
3000 IMPORT_SFUNC(NdisInterlockedInsertTailList
, 3),
3001 IMPORT_SFUNC(NdisInterlockedRemoveHeadList
, 2),
3002 IMPORT_SFUNC(NdisInitializeWrapper
, 4),
3003 IMPORT_SFUNC(NdisMRegisterMiniport
, 3),
3004 IMPORT_SFUNC(NdisAllocateMemoryWithTag
, 3),
3005 IMPORT_SFUNC(NdisAllocateMemory
, 4 + 1),
3006 IMPORT_SFUNC(NdisMSetAttributesEx
, 5),
3007 IMPORT_SFUNC(NdisCloseConfiguration
, 1),
3008 IMPORT_SFUNC(NdisReadConfiguration
, 5),
3009 IMPORT_SFUNC(NdisOpenConfiguration
, 3),
3010 IMPORT_SFUNC(NdisAcquireSpinLock
, 1),
3011 IMPORT_SFUNC(NdisReleaseSpinLock
, 1),
3012 IMPORT_SFUNC(NdisDprAcquireSpinLock
, 1),
3013 IMPORT_SFUNC(NdisDprReleaseSpinLock
, 1),
3014 IMPORT_SFUNC(NdisAllocateSpinLock
, 1),
3015 IMPORT_SFUNC(NdisInitializeReadWriteLock
, 1),
3016 IMPORT_SFUNC(NdisAcquireReadWriteLock
, 3),
3017 IMPORT_SFUNC(NdisReleaseReadWriteLock
, 2),
3018 IMPORT_SFUNC(NdisFreeSpinLock
, 1),
3019 IMPORT_SFUNC(NdisFreeMemory
, 3),
3020 IMPORT_SFUNC(NdisReadPciSlotInformation
, 5),
3021 IMPORT_SFUNC(NdisWritePciSlotInformation
, 5),
3022 IMPORT_SFUNC_MAP(NdisImmediateReadPciSlotInformation
,
3023 NdisReadPciSlotInformation
, 5),
3024 IMPORT_SFUNC_MAP(NdisImmediateWritePciSlotInformation
,
3025 NdisWritePciSlotInformation
, 5),
3026 IMPORT_CFUNC(NdisWriteErrorLogEntry
, 0),
3027 IMPORT_SFUNC(NdisMStartBufferPhysicalMapping
, 6),
3028 IMPORT_SFUNC(NdisMCompleteBufferPhysicalMapping
, 3),
3029 IMPORT_SFUNC(NdisMInitializeTimer
, 4),
3030 IMPORT_SFUNC(NdisInitializeTimer
, 3),
3031 IMPORT_SFUNC(NdisSetTimer
, 2),
3032 IMPORT_SFUNC(NdisMCancelTimer
, 2),
3033 IMPORT_SFUNC_MAP(NdisCancelTimer
, NdisMCancelTimer
, 2),
3034 IMPORT_SFUNC(NdisMSetPeriodicTimer
, 2),
3035 IMPORT_SFUNC(NdisMQueryAdapterResources
, 4),
3036 IMPORT_SFUNC(NdisMRegisterIoPortRange
, 4),
3037 IMPORT_SFUNC(NdisMDeregisterIoPortRange
, 4),
3038 IMPORT_SFUNC(NdisReadNetworkAddress
, 4),
3039 IMPORT_SFUNC(NdisQueryMapRegisterCount
, 2),
3040 IMPORT_SFUNC(NdisMAllocateMapRegisters
, 5),
3041 IMPORT_SFUNC(NdisMFreeMapRegisters
, 1),
3042 IMPORT_SFUNC(NdisMAllocateSharedMemory
, 5),
3043 IMPORT_SFUNC(NdisMMapIoSpace
, 4 + 1),
3044 IMPORT_SFUNC(NdisMUnmapIoSpace
, 3),
3045 IMPORT_SFUNC(NdisGetCacheFillSize
, 0),
3046 IMPORT_SFUNC(NdisMGetDmaAlignment
, 1),
3047 IMPORT_SFUNC(NdisMInitializeScatterGatherDma
, 3),
3048 IMPORT_SFUNC(NdisAllocatePacketPool
, 4),
3049 IMPORT_SFUNC(NdisAllocatePacketPoolEx
, 5),
3050 IMPORT_SFUNC(NdisAllocatePacket
, 3),
3051 IMPORT_SFUNC(NdisFreePacket
, 1),
3052 IMPORT_SFUNC(NdisFreePacketPool
, 1),
3053 IMPORT_SFUNC_MAP(NdisDprAllocatePacket
, NdisAllocatePacket
, 3),
3054 IMPORT_SFUNC_MAP(NdisDprFreePacket
, NdisFreePacket
, 1),
3055 IMPORT_SFUNC(NdisAllocateBufferPool
, 3),
3056 IMPORT_SFUNC(NdisAllocateBuffer
, 5),
3057 IMPORT_SFUNC(NdisQueryBuffer
, 3),
3058 IMPORT_SFUNC(NdisQueryBufferSafe
, 4),
3059 IMPORT_SFUNC(NdisBufferVirtualAddress
, 1),
3060 IMPORT_SFUNC(NdisBufferVirtualAddressSafe
, 2),
3061 IMPORT_SFUNC(NdisBufferLength
, 1),
3062 IMPORT_SFUNC(NdisFreeBuffer
, 1),
3063 IMPORT_SFUNC(NdisFreeBufferPool
, 1),
3064 IMPORT_SFUNC(NdisInterlockedIncrement
, 1),
3065 IMPORT_SFUNC(NdisInterlockedDecrement
, 1),
3066 IMPORT_SFUNC(NdisInitializeEvent
, 1),
3067 IMPORT_SFUNC(NdisSetEvent
, 1),
3068 IMPORT_SFUNC(NdisResetEvent
, 1),
3069 IMPORT_SFUNC(NdisWaitEvent
, 2),
3070 IMPORT_SFUNC(NdisUnicodeStringToAnsiString
, 2),
3071 IMPORT_SFUNC(NdisMPciAssignResources
, 3),
3072 IMPORT_SFUNC(NdisMFreeSharedMemory
, 5 + 1),
3073 IMPORT_SFUNC(NdisMRegisterInterrupt
, 7),
3074 IMPORT_SFUNC(NdisMDeregisterInterrupt
, 1),
3075 IMPORT_SFUNC(NdisMRegisterAdapterShutdownHandler
, 3),
3076 IMPORT_SFUNC(NdisMDeregisterAdapterShutdownHandler
, 1),
3077 IMPORT_SFUNC(NDIS_BUFFER_TO_SPAN_PAGES
, 1),
3078 IMPORT_SFUNC(NdisQueryBufferOffset
, 3),
3079 IMPORT_SFUNC(NdisAdjustBufferLength
, 2),
3080 IMPORT_SFUNC(NdisPacketPoolUsage
, 1),
3081 IMPORT_SFUNC(NdisMSleep
, 1),
3082 IMPORT_SFUNC(NdisUnchainBufferAtFront
, 2),
3083 IMPORT_SFUNC(NdisReadPcmciaAttributeMemory
, 4),
3084 IMPORT_SFUNC(NdisWritePcmciaAttributeMemory
, 4),
3085 IMPORT_SFUNC(NdisOpenFile
, 5 + 1),
3086 IMPORT_SFUNC(NdisMapFile
, 3),
3087 IMPORT_SFUNC(NdisUnmapFile
, 1),
3088 IMPORT_SFUNC(NdisCloseFile
, 1),
3089 IMPORT_SFUNC(NdisMRegisterDevice
, 6),
3090 IMPORT_SFUNC(NdisMDeregisterDevice
, 1),
3091 IMPORT_SFUNC(NdisMQueryAdapterInstanceName
, 2),
3092 IMPORT_SFUNC(NdisMRegisterUnloadHandler
, 2),
3093 IMPORT_SFUNC(ndis_timercall
, 4),
3094 IMPORT_SFUNC(ndis_asyncmem_complete
, 2),
3095 IMPORT_SFUNC(ndis_intr
, 2),
3096 IMPORT_SFUNC(ndis_intrhand
, 4),
3099 * This last entry is a catch-all for any function we haven't
3100 * implemented yet. The PE import list patching routine will
3101 * use it for any function that doesn't have an explicit match
3105 { NULL
, (FUNC
)dummy
, NULL
, 0, WINDRV_WRAP_STDCALL
},
3109 { NULL
, NULL
, NULL
}