Sync usage with man page.
[netbsd-mini2440.git] / sys / compat / ndis / subr_ndis.c
blob2228b3084f4855adbacf2b7f3c2535a494f03d9a
1 /*-
2 * Copyright (c) 2003
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
7 * are met:
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.
33 #include <sys/cdefs.h>
34 #ifdef __FreeBSD__
35 __FBSDID("$FreeBSD: src/sys/compat/ndis/subr_ndis.c,v 1.67.2.7 2005/03/31 21:50:11 wpaul Exp $");
36 #endif
37 #ifdef __NetBSD__
38 __KERNEL_RCSID(0, "$NetBSD: subr_ndis.c,v 1.21 2009/05/11 21:34:55 cegger Exp $");
39 #endif
42 * This file implements a translation layer between the BSD networking
43 * infrasturcture and Windows(R) NDIS network driver modules. A Windows
44 * NDIS driver calls into several functions in the NDIS.SYS Windows
45 * kernel module and exports a table of functions designed to be called
46 * by the NDIS subsystem. Using the PE loader, we can patch our own
47 * versions of the NDIS routines into a given Windows driver module and
48 * convince the driver that it is in fact running on Windows.
50 * We provide a table of all our implemented NDIS routines which is patched
51 * into the driver object code. All our exported routines must use the
52 * _stdcall calling convention, since that's what the Windows object code
53 * expects.
56 #ifdef __FreeBSD__
57 #include <sys/ctype.h>
58 #endif
59 #include <sys/param.h>
60 #include <sys/types.h>
61 #include <sys/errno.h>
63 #include <sys/callout.h>
64 #include <sys/kernel.h>
65 #include <sys/systm.h>
66 #include <sys/malloc.h>
67 #include <sys/lock.h>
68 #ifdef __FreeBSD__
69 #include <sys/mutex.h>
70 #endif
71 #include <sys/socket.h>
72 #include <sys/sysctl.h>
73 #ifdef __FreeBSD__
74 #include <sys/timespec.h>
75 #include <sys/smp.h>
76 #endif
77 #include <sys/queue.h>
78 #include <sys/proc.h>
79 #include <sys/filedesc.h>
80 #include <sys/namei.h>
81 #include <sys/fcntl.h>
82 #include <sys/vnode.h>
83 #include <sys/kthread.h>
84 #ifdef __FreeBSD__
85 #include <sys/linker.h>
86 #include <sys/sysproto.h>
87 #endif
88 #include <sys/mount.h>
90 #include <net/if.h>
91 #include <net/if_arp.h>
92 #ifdef __FreeBSD__
93 #include <net/ethernet.h>
94 #else
95 #include <net/if_ether.h>
96 #endif
97 #include <net/if_dl.h>
98 #include <net/if_media.h>
100 #include <sys/atomic.h>
101 #ifdef __FreeBSD__
102 #include <machine/bus_memio.h>
103 #include <machine/bus_pio.h>
104 #include <machine/resource.h>
105 #include <sys/bus.h>
106 #include <sys/rman.h>
107 #endif
108 #include <sys/bus.h>
110 #include <machine/stdarg.h>
112 #include <net80211/ieee80211_var.h>
113 #include <net80211/ieee80211_ioctl.h>
115 #include <dev/pci/pcireg.h>
116 #include <dev/pci/pcivar.h>
118 #include <compat/ndis/pe_var.h>
119 #include <compat/ndis/resource_var.h>
120 #include <compat/ndis/ntoskrnl_var.h>
121 #include <compat/ndis/hal_var.h>
122 #include <compat/ndis/ndis_var.h>
123 #include <compat/ndis/cfg_var.h>
124 #include <dev/if_ndis/if_ndisvar.h>
126 #ifdef __NetBSD__
127 #include "nbcompat.h"
128 #endif
130 #ifdef __NetBSD__
131 #define PN(name) /* printf(#name "\n"); */
132 #endif
134 static char ndis_filepath[MAXPATHLEN];
135 extern struct nd_head ndis_devhead;
137 #ifdef __FreeBSD__
138 SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
139 MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
140 #endif
142 __stdcall static void NdisInitializeWrapper(ndis_handle *,
143 driver_object *, void *, void *);
144 __stdcall static ndis_status NdisMRegisterMiniport(ndis_handle,
145 ndis_miniport_characteristics *, int);
146 __stdcall static ndis_status NdisAllocateMemoryWithTag(void **,
147 uint32_t, uint32_t);
148 __stdcall static ndis_status NdisAllocateMemory(void **,
149 uint32_t, uint32_t, ndis_physaddr);
150 __stdcall static void NdisFreeMemory(void *, uint32_t, uint32_t);
151 __stdcall static ndis_status NdisMSetAttributesEx(ndis_handle, ndis_handle,
152 uint32_t, uint32_t, ndis_interface_type);
153 __stdcall static void NdisOpenConfiguration(ndis_status *,
154 ndis_handle *, ndis_handle);
155 __stdcall static void NdisOpenConfigurationKeyByIndex(ndis_status *,
156 ndis_handle, uint32_t, ndis_unicode_string *, ndis_handle *);
157 __stdcall static void NdisOpenConfigurationKeyByName(ndis_status *,
158 ndis_handle, ndis_unicode_string *, ndis_handle *);
159 #ifdef __FreeBSD__
160 static ndis_status ndis_encode_parm(ndis_miniport_block *,
161 struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
162 static ndis_status ndis_decode_parm(ndis_miniport_block *,
163 ndis_config_parm *, char *);
164 #else /* __NetBSD__ */
165 static ndis_status ndis_encode_parm(ndis_miniport_block *,
166 void *, ndis_parm_type, ndis_config_parm **);
167 #endif
168 __stdcall static void NdisReadConfiguration(ndis_status *, ndis_config_parm **,
169 ndis_handle, ndis_unicode_string *, ndis_parm_type);
170 __stdcall static void NdisWriteConfiguration(ndis_status *, ndis_handle,
171 ndis_unicode_string *, ndis_config_parm *);
172 __stdcall static void NdisCloseConfiguration(ndis_handle);
173 __stdcall static void NdisAllocateSpinLock(ndis_spin_lock *);
174 __stdcall static void NdisFreeSpinLock(ndis_spin_lock *);
175 __stdcall static void NdisAcquireSpinLock(ndis_spin_lock *);
176 __stdcall static void NdisReleaseSpinLock(ndis_spin_lock *);
177 __stdcall static void NdisDprAcquireSpinLock(ndis_spin_lock *);
178 __stdcall static void NdisDprReleaseSpinLock(ndis_spin_lock *);
179 __stdcall static uint32_t NdisReadPciSlotInformation(ndis_handle, uint32_t,
180 uint32_t, void *, uint32_t);
181 __stdcall static uint32_t NdisWritePciSlotInformation(ndis_handle, uint32_t,
182 uint32_t, void *, uint32_t);
183 static void NdisWriteErrorLogEntry(ndis_handle, ndis_error_code, uint32_t, ...);
184 static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
185 __stdcall static void NdisMStartBufferPhysicalMapping(ndis_handle,
186 ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
187 __stdcall static void NdisMCompleteBufferPhysicalMapping(ndis_handle,
188 ndis_buffer *, uint32_t);
189 __stdcall static void NdisMInitializeTimer(ndis_miniport_timer *, ndis_handle,
190 ndis_timer_function, void *);
191 __stdcall static void NdisInitializeTimer(ndis_timer *,
192 ndis_timer_function, void *);
193 __stdcall static void NdisSetTimer(ndis_timer *, uint32_t);
194 __stdcall static void NdisMSetPeriodicTimer(ndis_miniport_timer *, uint32_t);
195 __stdcall static void NdisMCancelTimer(ndis_timer *, uint8_t *);
196 __stdcall static void ndis_timercall(kdpc *, ndis_miniport_timer *,
197 void *, void *);
198 __stdcall static void NdisMQueryAdapterResources(ndis_status *, ndis_handle,
199 ndis_resource_list *, uint32_t *);
200 __stdcall static ndis_status NdisMRegisterIoPortRange(void **,
201 ndis_handle, uint32_t, uint32_t);
202 __stdcall static void NdisMDeregisterIoPortRange(ndis_handle,
203 uint32_t, uint32_t, void *);
204 __stdcall static void NdisReadNetworkAddress(ndis_status *, void **,
205 uint32_t *, ndis_handle);
206 __stdcall static ndis_status NdisQueryMapRegisterCount(uint32_t, uint32_t *);
207 __stdcall static ndis_status NdisMAllocateMapRegisters(ndis_handle,
208 uint32_t, uint8_t, uint32_t, uint32_t);
209 __stdcall static void NdisMFreeMapRegisters(ndis_handle);
210 static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
211 __stdcall static void NdisMAllocateSharedMemory(ndis_handle, uint32_t,
212 uint8_t, void **, ndis_physaddr *);
213 static void ndis_asyncmem_complete(void *);
214 __stdcall static ndis_status NdisMAllocateSharedMemoryAsync(ndis_handle,
215 uint32_t, uint8_t, void *);
216 __stdcall static void NdisMFreeSharedMemory(ndis_handle, uint32_t,
217 uint8_t, void *, ndis_physaddr);
218 __stdcall static ndis_status NdisMMapIoSpace(void **, ndis_handle,
219 ndis_physaddr, uint32_t);
220 __stdcall static void NdisMUnmapIoSpace(ndis_handle, void *, uint32_t);
221 __stdcall static uint32_t NdisGetCacheFillSize(void);
222 __stdcall static uint32_t NdisMGetDmaAlignment(ndis_handle);
223 __stdcall static ndis_status NdisMInitializeScatterGatherDma(ndis_handle,
224 uint8_t, uint32_t);
225 __stdcall static void NdisUnchainBufferAtFront(ndis_packet *, ndis_buffer **);
226 __stdcall static void NdisUnchainBufferAtBack(ndis_packet *, ndis_buffer **);
227 __stdcall static void NdisAllocateBufferPool(ndis_status *,
228 ndis_handle *, uint32_t);
229 __stdcall static void NdisFreeBufferPool(ndis_handle);
230 __stdcall static void NdisAllocateBuffer(ndis_status *, ndis_buffer **,
231 ndis_handle, void *, uint32_t);
232 __stdcall static void NdisFreeBuffer(ndis_buffer *);
233 __stdcall static uint32_t NdisBufferLength(ndis_buffer *);
234 __stdcall static void NdisQueryBuffer(ndis_buffer *, void **, uint32_t *);
235 __stdcall static void NdisQueryBufferSafe(ndis_buffer *, void **,
236 uint32_t *, uint32_t);
237 __stdcall static void *NdisBufferVirtualAddress(ndis_buffer *);
238 __stdcall static void *NdisBufferVirtualAddressSafe(ndis_buffer *, uint32_t);
239 __stdcall static void NdisAdjustBufferLength(ndis_buffer *, int);
240 __stdcall static uint32_t NdisInterlockedIncrement(uint32_t *);
241 __stdcall static uint32_t NdisInterlockedDecrement(uint32_t *);
242 __stdcall static void NdisInitializeEvent(ndis_event *);
243 __stdcall static void NdisSetEvent(ndis_event *);
244 __stdcall static void NdisResetEvent(ndis_event *);
245 __stdcall static uint8_t NdisWaitEvent(ndis_event *, uint32_t);
246 __stdcall static ndis_status NdisUnicodeStringToAnsiString(ndis_ansi_string *,
247 ndis_unicode_string *);
248 __stdcall static ndis_status
249 NdisAnsiStringToUnicodeString(ndis_unicode_string *,
250 ndis_ansi_string *);
251 __stdcall static ndis_status NdisMPciAssignResources(ndis_handle,
252 uint32_t, ndis_resource_list **);
253 __stdcall static ndis_status NdisMRegisterInterrupt(ndis_miniport_interrupt *,
254 ndis_handle, uint32_t, uint32_t, uint8_t,
255 uint8_t, ndis_interrupt_mode);
256 __stdcall static void NdisMDeregisterInterrupt(ndis_miniport_interrupt *);
257 __stdcall static void NdisMRegisterAdapterShutdownHandler(ndis_handle, void *,
258 ndis_shutdown_handler);
259 __stdcall static void NdisMDeregisterAdapterShutdownHandler(ndis_handle);
260 __stdcall static uint32_t NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *);
261 __stdcall static void NdisGetBufferPhysicalArraySize(ndis_buffer *,
262 uint32_t *);
263 __stdcall static void NdisQueryBufferOffset(ndis_buffer *,
264 uint32_t *, uint32_t *);
265 __stdcall static void NdisMSleep(uint32_t);
266 __stdcall static uint32_t NdisReadPcmciaAttributeMemory(ndis_handle,
267 uint32_t, void *, uint32_t);
268 __stdcall static uint32_t NdisWritePcmciaAttributeMemory(ndis_handle,
269 uint32_t, void *, uint32_t);
270 __stdcall static list_entry *NdisInterlockedInsertHeadList(list_entry *,
271 list_entry *, ndis_spin_lock *);
272 __stdcall static list_entry *NdisInterlockedRemoveHeadList(list_entry *,
273 ndis_spin_lock *);
274 __stdcall static list_entry *NdisInterlockedInsertTailList(list_entry *,
275 list_entry *, ndis_spin_lock *);
276 __stdcall static uint8_t
277 NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *,
278 void *, void *);
279 __stdcall static void NdisGetCurrentSystemTime(uint64_t *);
280 __stdcall static void NdisGetSystemUpTime(uint32_t *);
281 __stdcall static void NdisInitializeString(ndis_unicode_string *, char *);
282 __stdcall static void NdisInitAnsiString(ndis_ansi_string *, char *);
283 __stdcall static void NdisInitUnicodeString(ndis_unicode_string *,
284 uint16_t *);
285 __stdcall static void NdisFreeString(ndis_unicode_string *);
286 __stdcall static ndis_status NdisMRemoveMiniport(ndis_handle *);
287 __stdcall static void NdisTerminateWrapper(ndis_handle, void *);
288 __stdcall static void NdisMGetDeviceProperty(ndis_handle, device_object **,
289 device_object **, device_object **, cm_resource_list *,
290 cm_resource_list *);
291 __stdcall static void NdisGetFirstBufferFromPacket(ndis_packet *,
292 ndis_buffer **, void **, uint32_t *, uint32_t *);
293 __stdcall static void NdisGetFirstBufferFromPacketSafe(ndis_packet *,
294 ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t);
295 #ifdef __FreeBSD__
296 static int ndis_find_sym(linker_file_t, char *, char *, void **);
297 __stdcall static void NdisOpenFile(ndis_status *, ndis_handle *, uint32_t *,
298 ndis_unicode_string *, ndis_physaddr);
299 __stdcall static void NdisMapFile(ndis_status *, void **, ndis_handle);
300 __stdcall static void NdisUnmapFile(ndis_handle);
301 __stdcall static void NdisCloseFile(ndis_handle);
302 #endif
303 __stdcall static uint8_t NdisSystemProcessorCount(void);
304 __stdcall static void NdisMIndicateStatusComplete(ndis_handle);
305 __stdcall static void NdisMIndicateStatus(ndis_handle, ndis_status,
306 void *, uint32_t);
307 static void ndis_workfunc(void *);
308 static funcptr ndis_findwrap(funcptr);
309 __stdcall static ndis_status NdisScheduleWorkItem(ndis_work_item *);
310 __stdcall static void NdisCopyFromPacketToPacket(ndis_packet *,
311 uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *);
312 __stdcall static void NdisCopyFromPacketToPacketSafe(ndis_packet *,
313 uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t);
314 __stdcall static ndis_status NdisMRegisterDevice(ndis_handle,
315 ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **,
316 void **, ndis_handle *);
317 __stdcall static ndis_status NdisMDeregisterDevice(ndis_handle);
318 __stdcall static ndis_status
319 NdisMQueryAdapterInstanceName(ndis_unicode_string *,
320 ndis_handle);
321 __stdcall static void NdisMRegisterUnloadHandler(ndis_handle, void *);
322 __stdcall static void dummy(void);
325 * Some really old drivers do not properly check the return value
326 * from NdisAllocatePacket() and NdisAllocateBuffer() and will
327 * sometimes allocate few more buffers/packets that they originally
328 * requested when they created the pool. To prevent this from being
329 * a problem, we allocate a few extra buffers/packets beyond what
330 * the driver asks for. This #define controls how many.
332 #define NDIS_POOL_EXTRA 16
335 ndis_libinit(void)
337 image_patch_table *patch;
339 strcpy(ndis_filepath, "/compat/ndis");
341 patch = ndis_functbl;
342 while (patch->ipt_func != NULL) {
343 windrv_wrap((funcptr)patch->ipt_func,
344 (funcptr *)&patch->ipt_wrap);
345 patch++;
348 return(0);
352 ndis_libfini(void)
354 image_patch_table *patch;
356 patch = ndis_functbl;
357 while (patch->ipt_func != NULL) {
358 windrv_unwrap(patch->ipt_wrap);
359 patch++;
362 return(0);
365 static funcptr
366 ndis_findwrap(funcptr func)
368 image_patch_table *patch;
370 patch = ndis_functbl;
371 while (patch->ipt_func != NULL) {
372 if ((funcptr)patch->ipt_func == func)
373 return((funcptr)patch->ipt_wrap);
374 patch++;
377 return(NULL);
381 * NDIS deals with strings in unicode format, so we have
382 * do deal with them that way too. For now, we only handle
383 * conversion between unicode and ASCII since that's all
384 * that device drivers care about.
388 ndis_ascii_to_unicode(const char *ascii, uint16_t **unicode)
390 uint16_t *ustr;
391 int i;
393 if (*unicode == NULL)
394 *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_NOWAIT);
396 if (*unicode == NULL)
397 return(ENOMEM);
398 ustr = *unicode;
399 for (i = 0; i < strlen(ascii); i++) {
400 *ustr = (uint16_t)ascii[i];
401 ustr++;
404 return(0);
408 ndis_unicode_to_ascii(uint16_t *unicode, int ulen, char **ascii)
410 uint8_t *astr;
411 int i;
413 if (*ascii == NULL)
414 *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_NOWAIT|M_ZERO);
415 if (*ascii == NULL)
416 return(ENOMEM);
417 astr = *ascii;
418 for (i = 0; i < ulen / 2; i++) {
419 *astr = (uint8_t)unicode[i];
420 astr++;
423 return(0);
427 * This routine does the messy Windows Driver Model device attachment
428 * stuff on behalf of NDIS drivers. We register our own AddDevice
429 * routine here
431 __stdcall static void
432 NdisInitializeWrapper(
433 ndis_handle *wrapper,
434 driver_object *drv,
435 void *path,
436 void *unused)
438 PN(NdisInitializeWrapper)
440 * As of yet, I haven't come up with a compelling
441 * reason to define a private NDIS wrapper structure,
442 * so we use a pointer to the driver object as the
443 * wrapper handle. The driver object has the miniport
444 * characteristics struct for this driver hung off it
445 * via IoAllocateDriverObjectExtension(), and that's
446 * really all the private data we need.
449 *wrapper = drv;
452 * If this was really Windows, we'd be registering dispatch
453 * routines for the NDIS miniport module here, but we're
454 * not Windows so all we really need to do is set up an
455 * AddDevice function that'll be invoked when a new device
456 * instance appears.
459 drv->dro_driverext->dre_adddevicefunc = NdisAddDevice;
461 return;
464 __stdcall static void
465 NdisTerminateWrapper(
466 ndis_handle handle,
467 void *syspec)
469 /* Nothing to see here, move along. */
470 return;
473 __stdcall static ndis_status
474 NdisMRegisterMiniport(ndis_handle handle, ndis_miniport_characteristics *characteristics, int len)
476 ndis_miniport_characteristics *pch = NULL;
477 void *ch = NULL;
478 driver_object *drv;
480 PN(NdisMRegisterMiniport);
482 drv = (driver_object *)handle;
485 * We need to save the NDIS miniport characteristics
486 * somewhere. This data is per-driver, not per-device
487 * (all devices handled by the same driver have the
488 * same characteristics) so we hook it onto the driver
489 * object using IoAllocateDriverObjectExtension().
490 * The extra extension info is automagically deleted when
491 * the driver is unloaded (see windrv_unload()).
493 if (IoAllocateDriverObjectExtension(drv, (void *)1,
494 sizeof(ndis_miniport_characteristics), /*(void **)*/&ch) !=
495 STATUS_SUCCESS)
496 return(NDIS_STATUS_RESOURCES);
497 pch = (ndis_miniport_characteristics *)ch;
499 memset((char *)pch, 0, sizeof(ndis_miniport_characteristics));
501 #ifdef __FreeBSD__
502 memcpy( (char *)pch, (char *)characteristics, len);
503 #else /* __NetBSD__ */
504 memcpy(pch, characteristics, len);
505 #endif
507 if (pch->nmc_version_major < 5 || pch->nmc_version_minor < 1) {
508 pch->nmc_shutdown_handler = NULL;
509 pch->nmc_canceltxpkts_handler = NULL;
510 pch->nmc_pnpevent_handler = NULL;
513 return(NDIS_STATUS_SUCCESS);
516 __stdcall static ndis_status
517 NdisAllocateMemoryWithTag(void **vaddr, uint32_t len, uint32_t tag)
519 void *mem;
522 mem = ExAllocatePoolWithTag(NonPagedPool, len, tag);
523 if (mem == NULL)
524 return(NDIS_STATUS_RESOURCES);
525 *vaddr = mem;
527 return(NDIS_STATUS_SUCCESS);
530 __stdcall static ndis_status
531 NdisAllocateMemory(
532 void **vaddr,
533 uint32_t len,
534 uint32_t flags,
535 ndis_physaddr highaddr)
537 void *mem;
539 mem = ExAllocatePoolWithTag(NonPagedPool, len, 0);
540 if (mem == NULL)
541 return(NDIS_STATUS_RESOURCES);
542 *vaddr = mem;
544 return(NDIS_STATUS_SUCCESS);
547 __stdcall static void
548 NdisFreeMemory(
549 void *vaddr,
550 uint32_t len,
551 uint32_t flags)
553 if (len == 0)
554 return;
556 ExFreePool(vaddr);
558 return;
561 __stdcall static ndis_status
562 NdisMSetAttributesEx(
563 ndis_handle adapter_handle,
564 ndis_handle adapter_ctx,
565 uint32_t hangsecs,
566 uint32_t flags,
567 ndis_interface_type iftype)
569 ndis_miniport_block *block;
571 PN(NdisMSetAttributesEx)
573 * Save the adapter context, we need it for calling
574 * the driver's internal functions.
576 block = (ndis_miniport_block *)adapter_handle;
577 block->nmb_miniportadapterctx = adapter_ctx;
578 block->nmb_checkforhangsecs = hangsecs;
579 block->nmb_flags = flags;
581 return(NDIS_STATUS_SUCCESS);
584 __stdcall static void
585 NdisOpenConfiguration(ndis_status *status, ndis_handle *cfg, ndis_handle wrapctx)
587 PN(NdisOpenConfiguration)
588 *cfg = wrapctx;
589 *status = NDIS_STATUS_SUCCESS;
591 return;
594 __stdcall static void
595 NdisOpenConfigurationKeyByName(
596 ndis_status *status,
597 ndis_handle cfg,
598 ndis_unicode_string *subkey,
599 ndis_handle *subhandle)
601 PN(NdisOpenConfiguration)
602 *subhandle = cfg;
603 *status = NDIS_STATUS_SUCCESS;
604 return;
607 __stdcall static void
608 NdisOpenConfigurationKeyByIndex(
609 ndis_status *status,
610 ndis_handle cfg,
611 uint32_t idx,
612 ndis_unicode_string *subkey,
613 ndis_handle *subhandle)
615 *status = NDIS_STATUS_FAILURE;
616 return;
619 static ndis_status
620 #ifdef __FreeBSD__
621 ndis_encode_parm(block, oid, type, parm)
622 ndis_miniport_block *block;
623 struct sysctl_oid *oid;
624 ndis_parm_type type;
625 ndis_config_parm **parm;
626 #else /* __NetBSD__ */
627 ndis_encode_parm(block, data, type, parm)
628 ndis_miniport_block *block;
629 void *data;
630 ndis_parm_type type;
631 ndis_config_parm **parm;
632 #endif
634 uint16_t *unicode;
635 ndis_unicode_string *ustr;
636 int base = 0;
638 PN(ndis_encode_parm)
640 unicode = (uint16_t *)&block->nmb_dummybuf;
642 switch(type) {
643 case ndis_parm_string:
644 #ifdef __FreeBSD__
645 ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
646 #else /* __NetBSD__ */
647 ndis_ascii_to_unicode((char *)data, &unicode);
648 #endif
649 (*parm)->ncp_type = ndis_parm_string;
650 ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
651 #ifdef __FreeBSD__
652 ustr->us_len = strlen((char *)oid->oid_arg1) * 2;
653 #else /* __NetBSD__ */
654 ustr->us_len = strlen((char *)data) * 2;
655 #endif
656 ustr->us_buf = unicode;
657 break;
658 case ndis_parm_int:
659 #ifdef __FreeBSD__
660 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) {
661 #else /* __NetBSD__ */
662 if (strncmp((char *)data, "0x", 2) == 0) {
663 #endif
664 base = 16;
666 else
667 base = 10;
668 (*parm)->ncp_type = ndis_parm_int;
669 (*parm)->ncp_parmdata.ncp_intdata =
670 #ifdef __FreeBSD__
671 strtol((char *)oid->oid_arg1, NULL, base);
672 #else /* __NetBSD__ */
673 /* TODO: NetBSD dosen't seem to have a strtol in sys/lib/libkern I hope strtoul is OK */
674 strtoul((char *)data, NULL, base);
675 #endif
676 break;
677 case ndis_parm_hexint:
678 #ifdef __FreeBSD__
679 if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) {
680 #else /* __NetBSD__ */
681 if (strncmp((char *)data, "0x", 2) == 0) {
682 #endif
683 base = 16;
685 else
686 base = 10;
687 (*parm)->ncp_type = ndis_parm_hexint;
688 (*parm)->ncp_parmdata.ncp_intdata =
689 #ifdef __FreeBSD__
690 strtoul((char *)oid->oid_arg1, NULL, base);
691 #else /* __NetBSD__ */
692 strtoul((char *)data, NULL, base);
693 #endif
694 break;
695 default:
696 return(NDIS_STATUS_FAILURE);
697 break;
700 return(NDIS_STATUS_SUCCESS);
704 ndis_strcasecmp(const char *s1, const char *s2)
706 char a, b;
709 * In the kernel, toupper() is a macro. Have to be careful
710 * not to use pointer arithmetic when passing it arguments.
713 while(1) {
714 a = *s1;
715 b = *s2++;
716 if (toupper(a) != toupper(b))
717 break;
718 if (*s1++ == '\0')
719 return(0);
722 return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
726 ndis_strncasecmp(const char *s1, const char *s2, size_t n)
728 char a, b;
730 if (n != 0) {
731 do {
732 a = *s1;
733 b = *s2++;
734 if (toupper(a) != toupper(b))
735 return (*(const unsigned char *)s1 -
736 *(const unsigned char *)(s2 - 1));
737 if (*s1++ == '\0')
738 break;
739 } while (--n != 0);
742 return(0);
745 __stdcall static void
746 NdisReadConfiguration(ndis_status *status, ndis_config_parm **parm, ndis_handle cfg, ndis_unicode_string *key, ndis_parm_type type)
748 char *keystr = NULL;
749 uint16_t *unicode;
750 ndis_miniport_block *block;
751 struct ndis_softc *sc;
752 #ifdef __FreeBSD__
753 struct sysctl_oid *oidp;
754 struct sysctl_ctx_entry *e;
755 #endif
757 #ifdef __NetBSD__
758 const struct sysctlnode *pnode = NULL;
759 struct sysctlnode *ndiscld = NULL;
760 int error;
761 int numcld;
762 int mib[1];
763 int i;
764 char new_keystr[MAX_SYSCTL_LEN+1];
765 char *old_keystr;
766 #endif
768 block = (ndis_miniport_block *)cfg;
769 #ifdef __FreeBSD__
770 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
771 #else /* __NetBSD__ */
772 sc = block->nmb_physdeviceobj->pdo_sc;
773 #endif
774 PN(NdisReadConfiguration)
776 if (key->us_len == 0 || key->us_buf == NULL) {
777 *status = NDIS_STATUS_FAILURE;
778 return;
781 ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr);
782 *parm = &block->nmb_replyparm;
783 memset((char *)&block->nmb_replyparm, 0, sizeof(ndis_config_parm));
784 unicode = (uint16_t *)&block->nmb_dummybuf;
786 #ifdef __NetBSD__
787 if(strlen(keystr) + strlen("ndis_") > MAX_SYSCTL_LEN) {
788 panic("sysctl name too long: %s\n", keystr);
790 strcpy(new_keystr, "ndis_");
791 strcpy(new_keystr + strlen("ndis_"), keystr);
792 old_keystr = keystr;
793 keystr = new_keystr;
794 #endif
797 * See if registry key is already in a list of known keys
798 * included with the driver.
800 #ifdef __FreeBSD__
801 #if __FreeBSD_version < 502113
802 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
803 #else
804 TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
805 #endif
806 oidp = e->entry;
807 #ifdef __FreeBSD__
808 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
809 #else /* __NetBSD__ */
810 if (ndis_strcasecmp(oidp->ctl_name, keystr) == 0) {
811 #endif
812 if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
813 free(keystr, M_DEVBUF);
814 *status = NDIS_STATUS_FAILURE;
815 return;
817 *status = ndis_encode_parm(block, oidp, type, parm);
819 free(keystr, M_DEVBUF);
820 return;
823 #else /* __NetBSD__ */
824 mib[0] = sc->ndis_sysctl_mib;
826 sysctl_lock(false);
827 error = sysctl_locate(curlwp, &mib[0], 1, &pnode, NULL);
829 numcld = pnode->sysctl_csize;
830 ndiscld = pnode->sysctl_child;
832 /* find the node whose name is keystr */
833 for(i=0; i < numcld; i++) {
834 if(strcmp(keystr, ndiscld->sysctl_name) == 0) {
835 /* Found it */
836 break;
838 ndiscld++;
840 sysctl_unlock();
842 if(i < numcld) {
843 /* Found it */
844 if(strcmp(ndiscld->sysctl_data, "UNSET") == 0) {
845 free(keystr, M_DEVBUF);
846 *status = NDIS_STATUS_FAILURE;
847 return;
850 *status = ndis_encode_parm(block, ndiscld->sysctl_data, type, parm);
851 free(keystr, M_DEVBUF);
852 return;
855 #endif
857 #ifdef __NetBSD__
858 free(keystr, M_DEVBUF);
859 keystr = old_keystr;
860 #endif
863 * If the key didn't match, add it to the list of dynamically
864 * created ones. Sometimes, drivers refer to registry keys
865 * that aren't documented in their .INF files. These keys
866 * are supposed to be created by some sort of utility or
867 * control panel snap-in that comes with the driver software.
868 * Sometimes it's useful to be able to manipulate these.
869 * If the driver requests the key in the form of a string,
870 * make its default value an empty string, otherwise default
871 * it to "0".
873 if (type == ndis_parm_int || type == ndis_parm_hexint)
874 ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
875 "UNSET", CTLFLAG_RW);
876 else
877 ndis_add_sysctl(sc, keystr, "(dynamic string key)",
878 "UNSET", CTLFLAG_RW);
880 free(keystr, M_DEVBUF);
881 *status = NDIS_STATUS_FAILURE;
882 return;
885 #ifdef __FreeBSD__
886 static ndis_status
887 ndis_decode_parm(ndis_miniport_block *block, ndis_config_parm *parm, char *val)
889 ndis_unicode_string *ustr;
890 char *astr = NULL;
892 PN(ndis_decode_parm)
894 switch(parm->ncp_type) {
895 case ndis_parm_string:
896 ustr = &parm->ncp_parmdata.ncp_stringdata;
897 ndis_unicode_to_ascii(ustr->us_buf, ustr->us_len, &astr);
898 memcpy( val, astr, 254);
899 free(astr, M_DEVBUF);
900 break;
901 case ndis_parm_int:
902 sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
903 break;
904 case ndis_parm_hexint:
905 sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
906 break;
907 default:
908 return(NDIS_STATUS_FAILURE);
909 break;
911 return(NDIS_STATUS_SUCCESS);
913 #endif
915 __stdcall static void
916 NdisWriteConfiguration(
917 ndis_status *status,
918 ndis_handle cfg,
919 ndis_unicode_string *key,
920 ndis_config_parm *parm)
922 #ifdef __FreeBSD__
923 char *keystr = NULL;
924 ndis_miniport_block *block;
925 struct ndis_softc *sc;
926 struct sysctl_oid *oidp;
927 struct sysctl_ctx_entry *e;
928 char val[256];
930 block = (ndis_miniport_block *)cfg;
932 PN(NdisWriteConfiguration)
934 #ifdef __FreeBSD__
935 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
936 #else /* __NetBSD__ */
937 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
938 #endif
940 ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr);
942 /* Decode the parameter into a string. */
943 memset(val, 0, sizeof(val));
944 *status = ndis_decode_parm(block, parm, val);
945 if (*status != NDIS_STATUS_SUCCESS) {
946 free(keystr, M_DEVBUF);
947 return;
950 /* See if the key already exists. */
952 #if __FreeBSD_version < 502113 || !defined(__FreeBSD__)
953 TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
954 #else
955 TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
956 #endif
957 oidp = e->entry;
958 if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
959 /* Found it, set the value. */
960 strcpy((char *)oidp->oid_arg1, val);
961 free(keystr, M_DEVBUF);
962 return;
966 /* Not found, add a new key with the specified value. */
967 ndis_add_sysctl(sc, keystr, "(dynamically set key)",
968 val, CTLFLAG_RW);
970 free(keystr, M_DEVBUF);
971 *status = NDIS_STATUS_SUCCESS;
972 return;
973 #else /* __FreeBSD__ */
974 *status = NDIS_STATUS_SUCCESS;
975 return;
976 #endif
979 __stdcall static void
980 NdisCloseConfiguration(ndis_handle cfg)
982 return;
986 * Initialize a Windows spinlock.
988 __stdcall static void
989 NdisAllocateSpinLock(ndis_spin_lock *lock)
991 KeInitializeSpinLock(&lock->nsl_spinlock);
992 lock->nsl_kirql = 0;
994 return;
998 * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
999 * for this. One is that it's sort of superfluous: we don't have to do anything
1000 * special to deallocate the spinlock. The other is that there are some buggy
1001 * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
1002 * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
1003 * talking to you.)
1005 __stdcall static void
1006 NdisFreeSpinLock(ndis_spin_lock *lock)
1008 #ifdef notdef
1009 KeInitializeSpinLock(&lock->nsl_spinlock);
1010 lock->nsl_kirql = 0;
1011 #endif
1012 return;
1016 * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
1019 __stdcall static void
1020 NdisAcquireSpinLock(ndis_spin_lock *lock)
1022 KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
1023 return;
1027 * Release a spinlock from IRQL == DISPATCH_LEVEL.
1030 __stdcall static void
1031 NdisReleaseSpinLock(ndis_spin_lock *lock)
1033 KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
1034 return;
1038 * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
1040 __stdcall static void
1041 NdisDprAcquireSpinLock(ndis_spin_lock *lock)
1043 KeAcquireSpinLockAtDpcLevel(&lock->nsl_spinlock);
1044 return;
1048 * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
1050 __stdcall static void
1051 NdisDprReleaseSpinLock(ndis_spin_lock *lock)
1053 KeReleaseSpinLockFromDpcLevel(&lock->nsl_spinlock);
1054 return;
1057 __stdcall static uint32_t
1058 NdisReadPciSlotInformation(
1059 ndis_handle adapter,
1060 uint32_t slot,
1061 uint32_t offset,
1062 void *buf,
1063 uint32_t len)
1065 ndis_miniport_block *block;
1066 int i;
1067 #ifdef __FreeBSD__
1068 char *dest;
1069 #else
1070 pcireg_t *dest;
1071 #endif
1073 /* PN(NdisReadPciSlotInformation) */
1074 device_t dev;
1075 struct ndis_softc *sc;
1077 block = (ndis_miniport_block *)adapter;
1078 dest = buf;
1079 if (block == NULL)
1080 return(0);
1082 dev = (device_t)block->nmb_physdeviceobj->do_devext;
1083 #ifdef __FreeBSD__
1084 sc = device_get_softc(dev);
1085 #else /* __NetBSD__ */
1086 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1087 #endif
1090 * I have a test system consisting of a Sun w2100z
1091 * dual 2.4Ghz Opteron machine and an Atheros 802.11a/b/g
1092 * "Aries" miniPCI NIC. (The NIC is installed in the
1093 * machine using a miniPCI to PCI bus adapter card.)
1094 * When running in SMP mode, I found that
1095 * performing a large number of consecutive calls to
1096 * NdisReadPciSlotInformation() would result in a
1097 * sudden system reset (or in some cases a freeze).
1098 * My suspicion is that the multiple reads are somehow
1099 * triggering a fatal PCI bus error that leads to a
1100 * machine check. The 1us delay in the loop below
1101 * seems to prevent this problem.
1104 #ifdef __FreeBSD__
1105 for (i = 0; i < len; i++) {
1106 #else /* __NetBSD__ */
1107 for (i = 0; i < len/4; i += 4) {
1108 #endif
1109 DELAY(1);
1110 #ifdef __FreeBSD__
1111 dest[i] = pci_read_config(dev, i + offset, 1);
1112 #else
1113 dest[i/4] = pci_conf_read(sc->ndis_res_pc,sc->ndis_res_pctag, (i + offset));
1114 #endif
1118 return(len);
1121 __stdcall static uint32_t
1122 NdisWritePciSlotInformation(
1123 ndis_handle adapter,
1124 uint32_t slot,
1125 uint32_t offset,
1126 void *buf,
1127 uint32_t len)
1129 ndis_miniport_block *block;
1130 int i;
1131 #ifdef __FreeBSD__
1132 char *dest;
1133 #else
1134 pcireg_t *dest;
1135 #endif
1137 device_t dev;
1139 /* PN(NdisWritePciSlotInformation) */
1141 block = (ndis_miniport_block *)adapter;
1142 dest = buf;
1143 struct ndis_softc *sc;
1146 if (block == NULL)
1147 return(0);
1149 dev = block->nmb_physdeviceobj->do_devext;
1150 #ifdef __FreeBSD__
1151 sc = device_get_softc(dev);
1152 #else /* __NetBSD__ */
1153 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1154 #endif
1156 #ifdef __FreeBSD__
1157 for (i = 0; i < len; i++) {
1158 #else /* __NetBSD__ */
1159 for (i = 0; i < len/4; i++) {
1160 #endif
1161 DELAY(1);
1162 #ifdef __FreeBSD__
1163 pci_write_config(dev, i + offset, dest[i], 1);
1164 #else
1165 pci_conf_write(sc->ndis_res_pc,sc->ndis_res_pctag,
1166 (i + offset), dest[i/4]);
1167 #endif
1171 return(len);
1175 * The errorlog routine uses a variable argument list, so we
1176 * have to declare it this way.
1178 #define ERRMSGLEN 512
1179 static void
1180 NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code,
1181 uint32_t numerrors, ...)
1183 ndis_miniport_block *block;
1184 va_list ap;
1185 int i, error;
1186 char *str = NULL, *ustr = NULL;
1187 uint16_t flags;
1188 char msgbuf[ERRMSGLEN];
1189 device_t dev;
1190 driver_object *drv;
1192 PN(NdisWriteErrorLogEntry)
1194 block = (ndis_miniport_block *)adapter;
1195 dev = block->nmb_physdeviceobj->do_devext;
1196 drv = block->nmb_physdeviceobj->do_drvobj;
1198 error = pe_get_message((vm_offset_t)drv->dro_driverstart,
1199 code, &str, &i, &flags);
1200 if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
1201 ustr = msgbuf;
1202 ndis_unicode_to_ascii((uint16_t *)str,
1203 ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
1204 str = ustr;
1207 printf ("%s: NDIS ERROR: %x (%s)\n", device_xname(dev), code,
1208 str == NULL ? "unknown error" : str);
1209 printf ("%s: NDIS NUMERRORS: %x\n", device_xname(dev), numerrors);
1211 va_start(ap, numerrors);
1212 for (i = 0; i < numerrors; i++)
1213 printf ("%s: argptr: %p\n",
1214 device_xname(dev),
1215 va_arg(ap, void *));
1217 va_end(ap);
1219 return;
1222 static void
1223 ndis_map_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1225 struct ndis_map_arg *ctx;
1226 int i;
1228 PN(ndis_map_cb)
1230 if (error)
1231 return;
1233 ctx = arg;
1235 for (i = 0; i < nseg; i++) {
1236 ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
1237 ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
1240 ctx->nma_cnt = nseg;
1242 return;
1245 __stdcall static void
1246 NdisMStartBufferPhysicalMapping(ndis_handle adapter, ndis_buffer *buf, uint32_t mapreg, uint8_t writedev, ndis_paddr_unit *addrarray, uint32_t *arraysize)
1248 ndis_miniport_block *block;
1249 struct ndis_softc *sc;
1250 struct ndis_map_arg nma;
1251 bus_dmamap_t map;
1252 int error;
1254 PN(NdisMStartBufferPhysicalMapping)
1256 if (adapter == NULL)
1257 return;
1259 block = (ndis_miniport_block *)adapter;
1260 #ifdef __FreeBSD__
1261 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1262 #else /* __NetBSD__ */
1263 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1264 #endif
1266 if (mapreg > sc->ndis_mmapcnt)
1267 return;
1269 map = sc->ndis_mmaps[mapreg];
1270 nma.nma_fraglist = addrarray;
1272 #ifdef __FreeBSD__
1273 error = bus_dmamap_load(sc->ndis_mtag, map,
1274 MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf), ndis_map_cb,
1275 (void *)&nma, BUS_DMA_NOWAIT);
1276 #else
1277 error = bus_dmamap_load(sc->ndis_mtag, map,
1278 MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf),
1279 NULL /* kernel space */, BUS_DMA_NOWAIT);
1280 /* callback function called "by hand" */
1281 ndis_map_cb((void *)&nma, map->dm_segs, map->dm_nsegs, error);
1282 #endif
1283 if (error)
1284 return;
1286 #ifdef __FreeBSD__
1287 bus_dmamap_sync(sc->ndis_mtag, map,
1288 writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
1289 #else
1290 bus_dmamap_sync(sc->ndis_mtag, map, 0, map->dm_mapsize,
1291 writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
1292 #endif
1293 *arraysize = nma.nma_cnt;
1295 return;
1298 __stdcall static void
1299 NdisMCompleteBufferPhysicalMapping(
1300 ndis_handle adapter,
1301 ndis_buffer *buf,
1302 uint32_t mapreg)
1304 ndis_miniport_block *block;
1305 struct ndis_softc *sc;
1306 bus_dmamap_t map;
1308 PN(NdisMCompleteBufferPhysicalMapping)
1310 if (adapter == NULL)
1311 return;
1313 block = (ndis_miniport_block *)adapter;
1314 #ifdef __FreeBSD__
1315 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1316 #else /* __NetBSD__ */
1317 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1318 #endif
1320 if (mapreg > sc->ndis_mmapcnt)
1321 return;
1323 map = sc->ndis_mmaps[mapreg];
1325 #ifdef __FreeBSD__
1326 bus_dmamap_sync(sc->ndis_mtag, map,
1327 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1328 #else
1329 bus_dmamap_sync(sc->ndis_mtag, map, 0, map->dm_mapsize,
1330 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1331 #endif
1332 bus_dmamap_unload(sc->ndis_mtag, map);
1334 return;
1338 * This is an older (?) timer init routine which doesn't
1339 * accept a miniport context handle. Serialized miniports should
1340 * never call this function.
1343 __stdcall static void
1344 NdisInitializeTimer(ndis_timer *timer, ndis_timer_function func, void *ctx)
1346 KeInitializeTimer(&timer->nt_ktimer);
1347 KeInitializeDpc(&timer->nt_kdpc, func, ctx);
1349 return;
1352 __stdcall static void
1353 ndis_timercall(kdpc *dpc, ndis_miniport_timer *timer, void *sysarg1, void *sysarg2)
1355 //PN(ndis_timercall)
1358 * Since we're called as a DPC, we should be running
1359 * at DISPATCH_LEVEL here. This means to acquire the
1360 * spinlock, we can use KeAcquireSpinLockAtDpcLevel()
1361 * rather than KeAcquireSpinLock().
1363 if (NDIS_SERIALIZED(timer->nmt_block))
1364 KeAcquireSpinLockAtDpcLevel(&timer->nmt_block->nmb_lock);
1366 MSCALL4(timer->nmt_timerfunc, dpc, timer->nmt_timerctx,
1367 sysarg1, sysarg2);
1369 if (NDIS_SERIALIZED(timer->nmt_block))
1370 KeReleaseSpinLockFromDpcLevel(&timer->nmt_block->nmb_lock);
1372 return;
1376 * For a long time I wondered why there were two NDIS timer initialization
1377 * routines, and why this one needed an NDIS_MINIPORT_TIMER and the
1378 * MiniportAdapterHandle. The NDIS_MINIPORT_TIMER has its own callout
1379 * function and context pointers separate from those in the DPC, which
1380 * allows for another level of indirection: when the timer fires, we
1381 * can have our own timer function invoked, and from there we can call
1382 * the driver's function. But why go to all that trouble? Then it hit
1383 * me: for serialized miniports, the timer callouts are not re-entrant.
1384 * By trapping the callouts and having access to the MiniportAdapterHandle,
1385 * we can protect the driver callouts by acquiring the NDIS serialization
1386 * lock. This is essential for allowing serialized miniports to work
1387 * correctly on SMP systems. On UP hosts, setting IRQL to DISPATCH_LEVEL
1388 * is enough to prevent other threads from pre-empting you, but with
1389 * SMP, you must acquire a lock as well, otherwise the other CPU is
1390 * free to clobber you.
1393 /* Just to test out how much memory is wasted*/
1394 int ndis_num_timers_allocated = 0;
1396 __stdcall static void
1397 NdisMInitializeTimer(ndis_miniport_timer *timer, ndis_handle handle, ndis_timer_function func, void *ctx)
1399 /* Save the driver's funcptr and context */
1401 PN(NdisMInitializeTimer)
1403 timer->nmt_timerfunc = func;
1404 timer->nmt_timerctx = ctx;
1405 timer->nmt_block = handle;
1407 #ifdef __NetBSD__
1408 /* TODO: free this memory somewhere! */
1409 printf("Allocating callout struct\n");
1410 if(timer->nmt_ktimer.k_handle == NULL) {
1411 timer->nmt_ktimer.k_handle =
1412 malloc(sizeof(struct callout), M_DEVBUF, M_NOWAIT|M_ZERO);
1413 ndis_num_timers_allocated++;
1415 #endif
1418 * Set up the timer so it will call our intermediate DPC.
1419 * Be sure to use the wrapped entry point, since
1420 * ntoskrnl_run_dpc() expects to invoke a function with
1421 * Microsoft calling conventions.
1423 KeInitializeTimer(&timer->nmt_ktimer);
1424 KeInitializeDpc(&timer->nmt_kdpc,
1425 ndis_findwrap((funcptr)ndis_timercall), timer);
1427 return;
1431 * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
1432 * but the former is just a macro wrapper around the latter.
1434 __stdcall static void
1435 NdisSetTimer(ndis_timer *timer, uint32_t msecs)
1437 PN(NdisSetTimer)
1439 * KeSetTimer() wants the period in
1440 * hundred nanosecond intervals.
1442 KeSetTimer(&timer->nt_ktimer,
1443 ((int64_t)msecs * -10000), &timer->nt_kdpc);
1445 return;
1448 __stdcall static void
1449 NdisMSetPeriodicTimer(ndis_miniport_timer *timer, uint32_t msecs)
1451 PN(NdisMSetPeriodicTimer)
1453 KeSetTimerEx(&timer->nmt_ktimer,
1454 ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc);
1456 return;
1460 * Technically, this is really NdisCancelTimer(), but we also
1461 * (ab)use it for NdisMCancelTimer(), since in our implementation
1462 * we don't need the extra info in the ndis_miniport_timer
1463 * structure just to cancel a timer.
1466 __stdcall static void
1467 NdisMCancelTimer(ndis_timer *timer, uint8_t *cancelled)
1469 PN(NdisMCancelTimer)
1470 *cancelled = KeCancelTimer(&timer->nt_ktimer);
1472 return;
1475 __stdcall static void
1476 NdisMQueryAdapterResources(ndis_status *status, ndis_handle adapter, ndis_resource_list *list, uint32_t *buflen)
1478 ndis_miniport_block *block;
1479 struct ndis_softc *sc;
1480 int rsclen;
1482 PN(NdisMQueryAdapterResources)
1484 block = (ndis_miniport_block *)adapter;
1486 #ifdef __FreeBSD__
1487 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1488 #else /* __NetBSD__ */
1489 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1490 #endif
1492 rsclen = sizeof(ndis_resource_list) +
1493 (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1494 if (*buflen < rsclen) {
1495 *buflen = rsclen;
1496 *status = NDIS_STATUS_INVALID_LENGTH;
1497 return;
1500 #ifdef __FreeBSD__
1501 memcpy( (char *)list, (char *)block->nmb_rlist, rsclen);
1502 #else /* __NetBSD__ */
1503 memcpy(list, block->nmb_rlist, rsclen);
1504 #endif
1506 *status = NDIS_STATUS_SUCCESS;
1508 return;
1511 __stdcall static ndis_status
1512 NdisMRegisterIoPortRange(
1513 void **offset,
1514 ndis_handle adapter,
1515 uint32_t port,
1516 uint32_t numports)
1518 struct ndis_miniport_block *block;
1519 struct ndis_softc *sc;
1521 PN(NdisMRegisterIoPortRange)
1523 if (adapter == NULL)
1524 return(NDIS_STATUS_FAILURE);
1526 block = (ndis_miniport_block *)adapter;
1527 #ifdef __FreeBSD__
1528 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1529 #else /* __NetBSD__ */
1530 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1531 #endif
1533 #ifdef __FreeBSD__
1534 if (sc->ndis_res_io == NULL)
1535 #else
1536 if (sc->ndis_res_io == NULL && sc->ndis_iftype != PCMCIABus)
1537 #endif
1538 return(NDIS_STATUS_FAILURE);
1540 /* Don't let the device map more ports than we have. */
1541 #ifdef __FreeBSD__
1542 if (rman_get_size(sc->ndis_res_io) < numports)
1543 #else /* __NetBSD__ */
1544 if ( (sc->ndis_iftype != PCMCIABus && sc->ndis_res_io->res_size < numports)
1545 || (sc->ndis_iftype == PCMCIABus && sc->ndis_res_pcioh.size < numports) )
1546 #endif
1547 return(NDIS_STATUS_INVALID_LENGTH);
1549 #ifdef __FreeBSD__
1550 *offset = (void *)rman_get_start(sc->ndis_res_io);
1551 #else /* __NetBSD__ */
1552 switch (sc->ndis_iftype){
1553 case PCIBus:
1554 case CBus: /* CardBus */
1555 *offset = (void*)sc->ndis_res_io->res_base;
1556 break;
1557 case PCMCIABus:
1558 *offset = (void*)sc->ndis_res_pcioh.addr;
1559 break;
1560 default:
1561 return(NDIS_STATUS_FAILURE);
1563 #endif /* __NetBSD__ */
1565 return(NDIS_STATUS_SUCCESS);
1568 __stdcall static void
1569 NdisMDeregisterIoPortRange(
1570 ndis_handle adapter,
1571 uint32_t port,
1572 uint32_t numports,
1573 void *offset)
1575 return;
1578 __stdcall static void
1579 NdisReadNetworkAddress(ndis_status *status, void **addr, uint32_t *addrlen, ndis_handle adapter)
1581 struct ndis_softc *sc;
1582 ndis_miniport_block *block;
1583 uint8_t empty[] = { 0, 0, 0, 0, 0, 0 };
1585 PN(NdisReadNetworkAddress)
1587 block = (ndis_miniport_block *)adapter;
1588 #ifdef __FreeBSD__
1589 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1590 #else /* __NetBSD__ */
1591 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1592 #endif
1594 #ifdef __FreeBSD__
1595 if (memcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1596 #else
1597 if (memcmp(CLLADDR(sc->arpcom.ec_if.if_sadl),
1598 empty, ETHER_ADDR_LEN) == 0)
1599 #endif
1601 *status = NDIS_STATUS_FAILURE;
1602 else {
1603 #ifdef __FreeBSD__
1604 *addr = sc->arpcom.ac_enaddr;
1605 #else
1606 memcpy(sc->ndis_mac, CLLADDR(sc->arpcom.ec_if.if_sadl),
1607 ETHER_ADDR_LEN);
1608 *addr = sc->ndis_mac;
1609 #endif
1610 *addrlen = ETHER_ADDR_LEN;
1611 *status = NDIS_STATUS_SUCCESS;
1614 return;
1617 __stdcall static ndis_status
1618 NdisQueryMapRegisterCount(
1619 uint32_t bustype,
1620 uint32_t *cnt)
1622 PN(NdisQueryMapRegisterCount)
1624 *cnt = 8192;
1625 return(NDIS_STATUS_SUCCESS);
1628 __stdcall static ndis_status
1629 NdisMAllocateMapRegisters(
1630 ndis_handle adapter,
1631 uint32_t dmachannel,
1632 uint8_t dmasize,
1633 uint32_t physmapneeded,
1634 uint32_t maxmap)
1636 struct ndis_softc *sc;
1637 ndis_miniport_block *block;
1638 #ifdef __FreeBSD__
1639 int error;
1640 #endif
1641 int i, nseg = NDIS_MAXSEG;
1643 PN(NdisMAllocateMapRegisters)
1645 block = (ndis_miniport_block *)adapter;
1646 #ifdef __FreeBSD__
1647 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1648 #else /* __NetBSD__ */
1649 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1650 #endif
1652 sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1653 M_DEVBUF, M_NOWAIT|M_ZERO);
1655 if (sc->ndis_mmaps == NULL)
1656 return(NDIS_STATUS_RESOURCES);
1658 #ifdef __FreeBSD__
1659 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1660 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1661 NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1662 NULL, NULL, &sc->ndis_mtag);
1664 if (error) {
1665 free(sc->ndis_mmaps, M_DEVBUF);
1666 return(NDIS_STATUS_RESOURCES);
1668 #else
1669 sc->ndis_mtag = sc->ndis_parent_tag;
1670 #endif
1672 for (i = 0; i < physmapneeded; i++) {
1673 #ifdef __FreeBSD__
1674 bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1675 #else
1676 bus_dmamap_create(sc->ndis_mtag, maxmap * nseg,
1677 nseg, maxmap, BUS_DMA_NOWAIT,
1678 0, &sc->ndis_mmaps[i]);
1679 #endif
1682 sc->ndis_mmapcnt = physmapneeded;
1684 return(NDIS_STATUS_SUCCESS);
1687 __stdcall static void
1688 NdisMFreeMapRegisters(ndis_handle adapter)
1690 struct ndis_softc *sc;
1691 ndis_miniport_block *block;
1692 int i;
1694 PN(NdisMFreeMapRegisters)
1696 block = (ndis_miniport_block *)adapter;
1697 #ifdef __FreeBSD__
1698 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1699 #else /* __NetBSD__ */
1700 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1701 #endif
1703 for (i = 0; i < sc->ndis_mmapcnt; i++)
1704 bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1706 free(sc->ndis_mmaps, M_DEVBUF);
1708 #ifdef __FreeBSD__
1709 bus_dma_tag_destroy(sc->ndis_mtag);
1710 #endif
1712 return;
1715 static void
1716 ndis_mapshared_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1718 ndis_physaddr *p;
1720 /* PN(ndis_mapshared_cb) */
1722 if (error || nseg > 1)
1723 return;
1725 p = arg;
1727 p->np_quad = segs[0].ds_addr;
1729 return;
1733 * This maps to bus_dmamem_alloc().
1735 __stdcall static void
1736 NdisMAllocateSharedMemory(
1737 ndis_handle adapter,
1738 uint32_t len,
1739 uint8_t cached,
1740 void **vaddr,
1741 ndis_physaddr *paddr)
1743 ndis_miniport_block *block;
1744 struct ndis_softc *sc;
1745 struct ndis_shmem *sh;
1746 int error;
1747 #ifdef __NetBSD__
1748 bus_dma_segment_t segs;
1749 int nsegs;
1750 #endif
1752 /* PN(NdisMAllocateSharedMemory) */
1754 if (adapter == NULL)
1755 return;
1757 block = (ndis_miniport_block *)adapter;
1758 #ifdef __FreeBSD__
1759 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1760 #else /* __NetBSD__ */
1761 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1762 #endif
1764 sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1765 if (sh == NULL)
1766 return;
1769 * When performing shared memory allocations, create a tag
1770 * with a lowaddr limit that restricts physical memory mappings
1771 * so that they all fall within the first 1GB of memory.
1772 * At least one device/driver combination (Linksys Instant
1773 * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
1774 * problems with performing DMA operations with physical
1775 * addresses that lie above the 1GB mark. I don't know if this
1776 * is a hardware limitation or if the addresses are being
1777 * truncated within the driver, but this seems to be the only
1778 * way to make these cards work reliably in systems with more
1779 * than 1GB of physical memory.
1782 #ifdef __FreeBSD__
1783 error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1784 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL,
1785 NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
1786 &sh->ndis_stag);
1788 if (error) {
1789 free(sh, M_DEVBUF);
1790 return;
1793 error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1794 BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1796 if (error) {
1797 bus_dma_tag_destroy(sh->ndis_stag);
1798 free(sh, M_DEVBUF);
1799 return;
1802 error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1803 len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1805 if (error) {
1806 bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1807 bus_dma_tag_destroy(sh->ndis_stag);
1808 free(sh, M_DEVBUF);
1809 return;
1811 #else
1812 sh->ndis_stag = sc->ndis_parent_tag;
1814 error = bus_dmamem_alloc(sh->ndis_stag, len, 64, 0,
1815 &segs, 1, &nsegs, BUS_DMA_NOWAIT);
1817 if (error) {
1818 printf("bus_dmamem_alloc failed(1)\n");
1819 return;
1822 error = bus_dmamem_map(sh->ndis_stag, &segs, nsegs,
1823 len, /*(void **)&vaddr*/ (void **)vaddr, BUS_DMA_NOWAIT);
1825 /* printf("*vaddr = %x\n", (unsigned int)*vaddr); */
1827 if (error) {
1828 printf("bus_dmamem_alloc failed(2)\n");
1829 /* XXX free */
1830 return;
1833 error = bus_dmamap_create(sh->ndis_stag, len, nsegs,
1834 BUS_SPACE_MAXSIZE_32BIT, 0,
1835 BUS_DMA_ALLOCNOW, &sh->ndis_smap);
1837 if (error) {
1838 printf("bus_dmamem_alloc failed(3)\n");
1839 /* XXX free, unmap */
1840 return;
1843 error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, /*vaddr*/ *vaddr,
1844 len, NULL, BUS_DMA_NOWAIT);
1845 ndis_mapshared_cb((void *)paddr,
1846 sh->ndis_smap->dm_segs,
1847 sh->ndis_smap->dm_nsegs, error);
1849 if (error) {
1850 printf("bus_dmamem_alloc failed(3)\n");
1851 /* XXX free, unmap, destroy */
1852 return;
1854 #endif
1856 sh->ndis_saddr = *vaddr;
1857 sh->ndis_next = sc->ndis_shlist;
1858 sc->ndis_shlist = sh;
1860 return;
1863 struct ndis_allocwork {
1864 ndis_handle na_adapter;
1865 uint32_t na_len;
1866 uint8_t na_cached;
1867 void *na_ctx;
1870 static void
1871 ndis_asyncmem_complete(void *arg)
1873 ndis_miniport_block *block;
1874 struct ndis_softc *sc;
1875 struct ndis_allocwork *w;
1876 void *vaddr;
1877 ndis_physaddr paddr;
1878 __stdcall ndis_allocdone_handler donefunc;
1880 w = arg;
1881 block = (ndis_miniport_block *)w->na_adapter;
1882 #ifdef __FreeBSD__
1883 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1884 #else /* __NetBSD__ */
1885 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1886 #endif
1888 PN(ndis_asyncmem_complete)
1890 vaddr = NULL;
1891 paddr.np_quad = 0;
1893 donefunc = sc->ndis_chars->nmc_allocate_complete_func;
1894 NdisMAllocateSharedMemory(w->na_adapter, w->na_len,
1895 w->na_cached, &vaddr, &paddr);
1896 MSCALL5(donefunc, w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
1898 free(arg, M_DEVBUF);
1900 return;
1903 __stdcall static ndis_status
1904 NdisMAllocateSharedMemoryAsync(ndis_handle adapter, uint32_t len, uint8_t cached, void *ctx)
1906 struct ndis_allocwork *w;
1908 PN(NdisMAllocateSharedMemoryAsync)
1910 if (adapter == NULL)
1911 return(NDIS_STATUS_FAILURE);
1913 w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT);
1915 if (w == NULL)
1916 return(NDIS_STATUS_FAILURE);
1918 w->na_adapter = adapter;
1919 w->na_cached = cached;
1920 w->na_len = len;
1921 w->na_ctx = ctx;
1924 * Pawn this work off on the SWI thread instead of the
1925 * taskqueue thread, because sometimes drivers will queue
1926 * up work items on the taskqueue thread that will block,
1927 * which would prevent the memory allocation from completing
1928 * when we need it.
1930 ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI);
1932 return(NDIS_STATUS_PENDING);
1935 __stdcall static void
1936 NdisMFreeSharedMemory(
1937 ndis_handle adapter,
1938 uint32_t len,
1939 uint8_t cached,
1940 void *vaddr,
1941 ndis_physaddr paddr)
1943 ndis_miniport_block *block;
1944 struct ndis_softc *sc;
1945 struct ndis_shmem *sh, *prev;
1947 PN(NdisMFreeSharedMemory)
1949 if (vaddr == NULL || adapter == NULL)
1950 return;
1952 block = (ndis_miniport_block *)adapter;
1953 #ifdef __FreeBSD__
1954 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1955 #else /* __NetBSD__ */
1956 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1957 #endif
1958 sh = prev = sc->ndis_shlist;
1960 /* Sanity check: is list empty? */
1962 if (sh == NULL)
1963 return;
1965 while (sh) {
1966 if (sh->ndis_saddr == vaddr)
1967 break;
1968 prev = sh;
1969 sh = sh->ndis_next;
1972 bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1973 #ifdef __FreeBSD__
1974 bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1975 bus_dma_tag_destroy(sh->ndis_stag);
1976 #else
1977 bus_dmamem_unmap(sh->ndis_stag, vaddr, sh->ndis_smap->dm_mapsize);
1978 bus_dmamem_free(sh->ndis_stag,
1979 sh->ndis_smap->dm_segs, sh->ndis_smap->dm_nsegs );
1980 #endif
1981 if (sh == sc->ndis_shlist)
1982 sc->ndis_shlist = sh->ndis_next;
1983 else
1984 prev->ndis_next = sh->ndis_next;
1986 free(sh, M_DEVBUF);
1988 return;
1991 __stdcall static ndis_status
1992 NdisMMapIoSpace(
1993 void **vaddr,
1994 ndis_handle adapter,
1995 ndis_physaddr paddr,
1996 uint32_t len)
1998 ndis_miniport_block *block;
1999 struct ndis_softc *sc;
2001 PN(NdisMMapIoSpace)
2003 if (adapter == NULL)
2004 return(NDIS_STATUS_FAILURE);
2006 block = (ndis_miniport_block *)adapter;
2007 #ifdef __FreeBSD__
2008 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
2009 #else /* __NetBSD__ */
2010 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2011 #endif
2014 #ifdef __FreeBSD__
2015 if (sc->ndis_res_mem != NULL &&
2016 paddr.np_quad == rman_get_start(sc->ndis_res_mem))
2017 *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
2018 else if (sc->ndis_res_altmem != NULL &&
2019 paddr.np_quad == rman_get_start(sc->ndis_res_altmem))
2020 *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem);
2021 else if (sc->ndis_res_am != NULL &&
2022 paddr.np_quad == rman_get_start(sc->ndis_res_am))
2023 *vaddr = (void *)rman_get_virtual(sc->ndis_res_am);
2024 else
2025 return(NDIS_STATUS_FAILURE);
2026 #else
2027 /* TODO: add one for sc->ndis_res_am once PCMCIA is going */
2028 if (sc->ndis_res_mem != NULL &&
2029 paddr.np_quad == sc->ndis_res_mem->res_base)
2030 *vaddr = bus_space_vaddr(sc->ndis_res_mem->res_tag,
2031 sc->ndis_res_mem->res_handle);
2032 else if (sc->ndis_res_altmem != NULL &&
2033 paddr.np_quad == sc->ndis_res_altmem->res_base)
2034 *vaddr = bus_space_vaddr(sc->ndis_res_altmem->res_tag,
2035 sc->ndis_res_altmem->res_handle);
2036 else
2037 return(NDIS_STATUS_FAILURE);
2039 *vaddr = bus_space_vaddr(sc->ndis_res_mem->res_tag,
2040 sc->ndis_res_mem->res_handle);
2042 #endif
2044 return(NDIS_STATUS_SUCCESS);
2047 __stdcall static void
2048 NdisMUnmapIoSpace(
2049 ndis_handle adapter,
2050 void *vaddr,
2051 uint32_t len)
2053 return;
2056 __stdcall static uint32_t
2057 NdisGetCacheFillSize(void)
2059 return(128);
2062 __stdcall static uint32_t
2063 NdisMGetDmaAlignment(ndis_handle handle)
2065 return(128);
2069 * NDIS has two methods for dealing with NICs that support DMA.
2070 * One is to just pass packets to the driver and let it call
2071 * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
2072 * all by itself, and the other is to let the NDIS library handle the
2073 * buffer mapping internally, and hand the driver an already populated
2074 * scatter/gather fragment list. If the driver calls
2075 * NdisMInitializeScatterGatherDma(), it wants to use the latter
2076 * method.
2079 __stdcall static ndis_status
2080 NdisMInitializeScatterGatherDma(
2081 ndis_handle adapter,
2082 uint8_t is64,
2083 uint32_t maxphysmap)
2085 struct ndis_softc *sc;
2086 ndis_miniport_block *block;
2087 #ifdef __FreeBSD__
2088 int error;
2089 #endif
2091 PN(NdisMInitializeScatterGatherDma)
2093 if (adapter == NULL)
2094 return(NDIS_STATUS_FAILURE);
2095 block = (ndis_miniport_block *)adapter;
2096 #ifdef __FreeBSD__
2097 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
2098 #else /* __NetBSD__ */
2099 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2100 #endif
2102 /* Don't do this twice. */
2103 if (sc->ndis_sc == 1)
2104 return(NDIS_STATUS_SUCCESS);
2106 #ifdef __FreeBSD__
2107 error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
2108 BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
2109 MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
2110 NULL, NULL, &sc->ndis_ttag);
2111 #else /* __NetBSD__ */
2112 /* TODO: Is this correct to just use the parent tag? */
2113 sc->ndis_ttag = sc->ndis_parent_tag;
2114 #endif
2116 sc->ndis_sc = 1;
2118 return(NDIS_STATUS_SUCCESS);
2121 __stdcall void
2122 NdisAllocatePacketPool(ndis_status *status, ndis_handle *pool, uint32_t descnum, uint32_t protrsvdlen)
2124 ndis_packet *cur;
2125 int i;
2127 PN(NdisAllocatePacketPool)
2129 *pool = malloc((sizeof(ndis_packet) + protrsvdlen) *
2130 ((descnum + NDIS_POOL_EXTRA) + 1),
2131 M_DEVBUF, M_NOWAIT|M_ZERO);
2133 if (*pool == NULL) {
2134 *status = NDIS_STATUS_RESOURCES;
2135 return;
2138 cur = (ndis_packet *)*pool;
2139 KeInitializeSpinLock(&cur->np_lock);
2140 cur->np_private.npp_flags = 0x1; /* mark the head of the list */
2141 cur->np_private.npp_totlen = 0; /* init deletetion flag */
2142 for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
2143 cur->np_private.npp_head = (ndis_handle)(cur + 1);
2144 cur++;
2147 *status = NDIS_STATUS_SUCCESS;
2148 return;
2151 __stdcall void
2152 NdisAllocatePacketPoolEx(ndis_status *status, ndis_handle *pool, uint32_t descnum, uint32_t oflowdescnum, uint32_t protrsvdlen)
2154 return(NdisAllocatePacketPool(status, pool,
2155 descnum + oflowdescnum, protrsvdlen));
2158 __stdcall uint32_t
2159 NdisPacketPoolUsage(ndis_handle pool)
2161 ndis_packet *head;
2162 uint8_t irql;
2163 uint32_t cnt;
2165 head = (ndis_packet *)pool;
2166 KeAcquireSpinLock(&head->np_lock, &irql);
2167 cnt = head->np_private.npp_count;
2168 KeReleaseSpinLock(&head->np_lock, irql);
2170 return(cnt);
2173 __stdcall void
2174 NdisFreePacketPool(ndis_handle pool)
2176 ndis_packet *head;
2177 uint8_t irql;
2179 head = pool;
2181 /* Mark this pool as 'going away.' */
2183 KeAcquireSpinLock(&head->np_lock, &irql);
2184 head->np_private.npp_totlen = 1;
2186 /* If there are no buffers loaned out, destroy the pool. */
2188 if (head->np_private.npp_count == 0) {
2189 KeReleaseSpinLock(&head->np_lock, irql);
2190 free(pool, M_DEVBUF);
2191 } else {
2192 printf("NDIS: buggy driver deleting active packet pool!\n");
2193 KeReleaseSpinLock(&head->np_lock, irql);
2196 return;
2199 __stdcall void
2200 NdisAllocatePacket(ndis_status *status, ndis_packet **packet, ndis_handle pool)
2202 ndis_packet *head, *pkt;
2203 uint8_t irql;
2205 #ifdef __NetBSD__
2206 /*TODO: For some reason NdisAllocatePacket was getting called once with pool being NULL
2207 *TODO: and this was causing a seg-fault. This seems to solve the problem, but I'm not
2208 *TODO: should happen at all in the first place.
2210 if(pool == NULL) {
2211 *status = NDIS_STATUS_FAILURE;
2212 return;
2214 #endif
2216 head = (ndis_packet *)pool;
2217 KeAcquireSpinLock(&head->np_lock, &irql);
2219 if (head->np_private.npp_flags != 0x1) {
2220 *status = NDIS_STATUS_FAILURE;
2221 KeReleaseSpinLock(&head->np_lock, irql);
2222 return;
2226 * If this pool is marked as 'going away' don't allocate any
2227 * more packets out of it.
2230 if (head->np_private.npp_totlen) {
2231 *status = NDIS_STATUS_FAILURE;
2232 KeReleaseSpinLock(&head->np_lock, irql);
2233 return;
2236 pkt = (ndis_packet *)head->np_private.npp_head;
2238 if (pkt == NULL) {
2239 *status = NDIS_STATUS_RESOURCES;
2240 KeReleaseSpinLock(&head->np_lock, irql);
2241 return;
2244 head->np_private.npp_head = pkt->np_private.npp_head;
2246 pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
2247 /* Save pointer to the pool. */
2248 pkt->np_private.npp_pool = head;
2250 /* Set the oob offset pointer. Lots of things expect this. */
2251 pkt->np_private.npp_packetooboffset =
2252 offsetof(ndis_packet, np_oob);
2255 * We must initialize the packet flags correctly in order
2256 * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
2257 * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work
2258 * correctly.
2260 pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
2261 pkt->np_private.npp_validcounts = FALSE;
2263 *packet = pkt;
2265 head->np_private.npp_count++;
2266 *status = NDIS_STATUS_SUCCESS;
2268 KeReleaseSpinLock(&head->np_lock, irql);
2270 return;
2273 __stdcall void
2274 NdisFreePacket(ndis_packet *packet)
2276 ndis_packet *head;
2277 uint8_t irql;
2279 if (packet == NULL || packet->np_private.npp_pool == NULL)
2280 return;
2282 head = packet->np_private.npp_pool;
2283 KeAcquireSpinLock(&head->np_lock, &irql);
2285 if (head->np_private.npp_flags != 0x1) {
2286 KeReleaseSpinLock(&head->np_lock, irql);
2287 return;
2290 packet->np_private.npp_head = head->np_private.npp_head;
2291 head->np_private.npp_head = (ndis_buffer *)packet;
2292 head->np_private.npp_count--;
2295 * If the pool has been marked for deletion and there are
2296 * no more packets outstanding, nuke the pool.
2299 if (head->np_private.npp_totlen && head->np_private.npp_count == 0) {
2300 KeReleaseSpinLock(&head->np_lock, irql);
2301 free(head, M_DEVBUF);
2302 } else
2303 KeReleaseSpinLock(&head->np_lock, irql);
2305 return;
2308 __stdcall static void
2309 NdisUnchainBufferAtFront(ndis_packet *packet, ndis_buffer **buf)
2311 ndis_packet_private *priv;
2313 if (packet == NULL || buf == NULL)
2314 return;
2316 priv = &packet->np_private;
2318 priv->npp_validcounts = FALSE;
2320 if (priv->npp_head == priv->npp_tail) {
2321 *buf = priv->npp_head;
2322 priv->npp_head = priv->npp_tail = NULL;
2323 } else {
2324 *buf = priv->npp_head;
2325 priv->npp_head = (*buf)->mdl_next;
2328 return;
2331 __stdcall static void
2332 NdisUnchainBufferAtBack(ndis_packet *packet, ndis_buffer **buf)
2334 ndis_packet_private *priv;
2335 ndis_buffer *tmp;
2337 if (packet == NULL || buf == NULL)
2338 return;
2340 priv = &packet->np_private;
2342 priv->npp_validcounts = FALSE;
2344 if (priv->npp_head == priv->npp_tail) {
2345 *buf = priv->npp_head;
2346 priv->npp_head = priv->npp_tail = NULL;
2347 } else {
2348 *buf = priv->npp_tail;
2349 tmp = priv->npp_head;
2350 while (tmp->mdl_next != priv->npp_tail)
2351 tmp = tmp->mdl_next;
2352 priv->npp_tail = tmp;
2353 tmp->mdl_next = NULL;
2356 return;
2360 * The NDIS "buffer" is really an MDL (memory descriptor list)
2361 * which is used to describe a buffer in a way that allows it
2362 * to mapped into different contexts. We have to be careful how
2363 * we handle them: in some versions of Windows, the NdisFreeBuffer()
2364 * routine is an actual function in the NDIS API, but in others
2365 * it's just a macro wrapper around IoFreeMdl(). There's really
2366 * no way to use the 'descnum' parameter to count how many
2367 * "buffers" are allocated since in order to use IoFreeMdl() to
2368 * dispose of a buffer, we have to use IoAllocateMdl() to allocate
2369 * them, and IoAllocateMdl() just grabs them out of the heap.
2372 __stdcall static void
2373 NdisAllocateBufferPool(
2374 ndis_status *status,
2375 ndis_handle *pool,
2376 uint32_t descnum)
2379 * The only thing we can really do here is verify that descnum
2380 * is a reasonable value, but I really don't know what to check
2381 * it against.
2384 *pool = NonPagedPool;
2385 *status = NDIS_STATUS_SUCCESS;
2386 return;
2389 __stdcall static void
2390 NdisFreeBufferPool(ndis_handle pool)
2392 return;
2395 __stdcall static void
2396 NdisAllocateBuffer(
2397 ndis_status *status,
2398 ndis_buffer **buffer,
2399 ndis_handle pool,
2400 void *vaddr,
2401 uint32_t len)
2403 ndis_buffer *buf;
2405 buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL);
2406 if (buf == NULL) {
2407 *status = NDIS_STATUS_RESOURCES;
2408 return;
2411 *buffer = buf;
2412 *status = NDIS_STATUS_SUCCESS;
2414 return;
2417 __stdcall static void
2418 NdisFreeBuffer(ndis_buffer *buf)
2420 IoFreeMdl(buf);
2421 return;
2424 /* Aw c'mon. */
2426 __stdcall static uint32_t
2427 NdisBufferLength(ndis_buffer *buf)
2429 return(MmGetMdlByteCount(buf));
2433 * Get the virtual address and length of a buffer.
2434 * Note: the vaddr argument is optional.
2437 __stdcall static void
2438 NdisQueryBuffer(ndis_buffer *buf, void **vaddr, uint32_t *len)
2440 if (vaddr != NULL)
2441 *vaddr = MmGetMdlVirtualAddress(buf);
2442 *len = MmGetMdlByteCount(buf);
2444 return;
2447 /* Same as above -- we don't care about the priority. */
2449 __stdcall static void
2450 NdisQueryBufferSafe(
2451 ndis_buffer *buf,
2452 void **vaddr,
2453 uint32_t *len,
2454 uint32_t prio)
2456 if (vaddr != NULL)
2457 *vaddr = MmGetMdlVirtualAddress(buf);
2458 *len = MmGetMdlByteCount(buf);
2460 return;
2463 /* Damnit Microsoft!! How many ways can you do the same thing?! */
2465 __stdcall static void *
2466 NdisBufferVirtualAddress(ndis_buffer *buf)
2468 return(MmGetMdlVirtualAddress(buf));
2471 __stdcall static void *
2472 NdisBufferVirtualAddressSafe(
2473 ndis_buffer *buf,
2474 uint32_t prio)
2476 return(MmGetMdlVirtualAddress(buf));
2479 __stdcall static void
2480 NdisAdjustBufferLength(ndis_buffer *buf, int len)
2482 MmGetMdlByteCount(buf) = len;
2484 return;
2487 __stdcall static uint32_t
2488 NdisInterlockedIncrement(uint32_t *addend)
2490 atomic_inc_32(addend);
2491 return(*addend);
2494 __stdcall static uint32_t
2495 NdisInterlockedDecrement(uint32_t *addend)
2497 atomic_dec_32(addend);
2498 return(*addend);
2501 __stdcall static void
2502 NdisInitializeEvent(ndis_event *event)
2505 * NDIS events are always notification
2506 * events, and should be initialized to the
2507 * not signaled state.
2510 KeInitializeEvent(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE);
2511 return;
2514 __stdcall static void
2515 NdisSetEvent(ndis_event *event)
2517 KeSetEvent(&event->ne_event, 0, 0);
2518 return;
2521 __stdcall static void
2522 NdisResetEvent(ndis_event *event)
2524 KeResetEvent(&event->ne_event);
2525 return;
2528 __stdcall static uint8_t
2529 NdisWaitEvent(ndis_event *event, uint32_t msecs)
2531 int64_t duetime;
2532 uint32_t rval;
2534 duetime = ((int64_t)msecs * -10000);
2536 rval = KeWaitForSingleObject((nt_dispatch_header *)event,
2537 0, 0, TRUE, msecs ? &duetime : NULL);
2539 if (rval == STATUS_TIMEOUT)
2540 return(FALSE);
2542 return(TRUE);
2545 __stdcall static ndis_status
2546 NdisUnicodeStringToAnsiString(ndis_ansi_string *dstr, ndis_unicode_string *sstr)
2548 if (dstr == NULL || sstr == NULL)
2549 return(NDIS_STATUS_FAILURE);
2550 if (ndis_unicode_to_ascii(sstr->us_buf,
2551 sstr->us_len, &dstr->nas_buf))
2552 return(NDIS_STATUS_FAILURE);
2553 dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
2554 return (NDIS_STATUS_SUCCESS);
2557 __stdcall static ndis_status
2558 NdisAnsiStringToUnicodeString(ndis_unicode_string *dstr, ndis_ansi_string *sstr)
2560 char *str;
2561 if (dstr == NULL || sstr == NULL)
2562 return(NDIS_STATUS_FAILURE);
2563 str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
2564 if (str == NULL)
2565 return(NDIS_STATUS_FAILURE);
2566 strncpy(str, sstr->nas_buf, sstr->nas_len);
2567 *(str + sstr->nas_len) = '\0';
2568 if (ndis_ascii_to_unicode(str, &dstr->us_buf)) {
2569 free(str, M_DEVBUF);
2570 return(NDIS_STATUS_FAILURE);
2572 dstr->us_len = dstr->us_maxlen = sstr->nas_len * 2;
2573 free(str, M_DEVBUF);
2574 return (NDIS_STATUS_SUCCESS);
2577 __stdcall static ndis_status
2578 NdisMPciAssignResources(
2579 ndis_handle adapter,
2580 uint32_t slot,
2581 ndis_resource_list **list)
2583 ndis_miniport_block *block;
2585 if (adapter == NULL || list == NULL)
2586 return (NDIS_STATUS_FAILURE);
2588 block = (ndis_miniport_block *)adapter;
2589 *list = block->nmb_rlist;
2591 return (NDIS_STATUS_SUCCESS);
2594 __stdcall static ndis_status
2595 NdisMRegisterInterrupt(
2596 ndis_miniport_interrupt *intr,
2597 ndis_handle adapter,
2598 uint32_t ivec,
2599 uint32_t ilevel,
2600 uint8_t reqisr,
2601 uint8_t shared,
2602 ndis_interrupt_mode imode)
2604 ndis_miniport_block *block;
2606 block = adapter;
2608 intr->ni_block = adapter;
2609 intr->ni_isrreq = reqisr;
2610 intr->ni_shared = shared;
2611 block->nmb_interrupt = intr;
2613 KeInitializeSpinLock(&intr->ni_dpccountlock);
2615 return(NDIS_STATUS_SUCCESS);
2618 __stdcall static void
2619 NdisMDeregisterInterrupt(ndis_miniport_interrupt *intr)
2621 return;
2624 __stdcall static void
2625 NdisMRegisterAdapterShutdownHandler(ndis_handle adapter, void *shutdownctx, ndis_shutdown_handler shutdownfunc)
2627 ndis_miniport_block *block;
2628 ndis_miniport_characteristics *chars;
2629 struct ndis_softc *sc;
2631 if (adapter == NULL)
2632 return;
2634 block = (ndis_miniport_block *)adapter;
2635 #ifdef __FreeBSD__
2636 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
2637 #else /* __NetBSD__ */
2638 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2639 #endif
2640 chars = sc->ndis_chars;
2642 chars->nmc_shutdown_handler = shutdownfunc;
2643 chars->nmc_rsvd0 = shutdownctx;
2645 return;
2648 __stdcall static void
2649 NdisMDeregisterAdapterShutdownHandler(ndis_handle adapter)
2651 ndis_miniport_block *block;
2652 ndis_miniport_characteristics *chars;
2653 struct ndis_softc *sc;
2655 if (adapter == NULL)
2656 return;
2658 block = (ndis_miniport_block *)adapter;
2659 #ifdef __FreeBSD__
2660 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
2661 #else /* __NetBSD__ */
2662 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2663 #endif
2664 chars = sc->ndis_chars;
2666 chars->nmc_shutdown_handler = NULL;
2667 chars->nmc_rsvd0 = NULL;
2669 return;
2672 __stdcall static uint32_t
2673 NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *buf)
2675 if (buf == NULL)
2676 return(0);
2677 if (MmGetMdlByteCount(buf) == 0)
2678 return(1);
2679 return(SPAN_PAGES(MmGetMdlVirtualAddress(buf),
2680 MmGetMdlByteCount(buf)));
2683 __stdcall static void
2684 NdisGetBufferPhysicalArraySize(ndis_buffer *buf, uint32_t *pages)
2686 if (buf == NULL)
2687 return;
2689 *pages = NDIS_BUFFER_TO_SPAN_PAGES(buf);
2690 return;
2693 __stdcall static void
2694 NdisQueryBufferOffset(ndis_buffer *buf, uint32_t *off, uint32_t *len)
2696 if (buf == NULL)
2697 return;
2699 *off = MmGetMdlByteOffset(buf);
2700 *len = MmGetMdlByteCount(buf);
2702 return;
2705 __stdcall static void
2706 NdisMSleep(uint32_t usecs)
2708 struct timeval tv;
2710 tv.tv_sec = 0;
2711 tv.tv_usec = usecs;
2713 #ifdef __FreeBSD__
2714 ndis_thsuspend(curthread->td_proc, NULL, tvtohz(&tv));
2715 #else
2716 ndis_thsuspend(curproc, NULL, tvtohz(&tv));
2717 #endif
2719 return;
2722 __stdcall static uint32_t
2723 NdisReadPcmciaAttributeMemory(ndis_handle handle, uint32_t offset, void *buf, uint32_t len)
2725 struct ndis_softc *sc;
2726 ndis_miniport_block *block;
2727 bus_space_handle_t bh;
2728 bus_space_tag_t bt;
2729 char *dest;
2730 int i;
2732 if (handle == NULL)
2733 return(0);
2735 block = (ndis_miniport_block *)handle;
2736 #ifdef __FreeBSD__
2737 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
2738 #else /* __NetBSD__ */
2739 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2740 #endif
2741 dest = buf;
2743 #ifdef __FreeBSD__
2744 bh = rman_get_bushandle(sc->ndis_res_am);
2745 bt = rman_get_bustag(sc->ndis_res_am);
2747 #else
2748 if ( sc->ndis_iftype == PCMCIABus ){
2749 bt = sc->ndis_res_pcmem.memt;
2750 bh = sc->ndis_res_pcmem.memh;
2751 } else { /* cardbus case */
2752 /* TODO what does it really wait for ? */
2753 bt = sc->ndis_res_mem->res_tag;
2754 bh = sc->ndis_res_mem->res_handle;
2756 #endif
2758 for (i = 0; i < len; i++)
2759 dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2);
2761 return(i);
2764 __stdcall static uint32_t
2765 NdisWritePcmciaAttributeMemory(ndis_handle handle, uint32_t offset, void *buf, uint32_t len)
2767 struct ndis_softc *sc;
2768 ndis_miniport_block *block;
2769 bus_space_handle_t bh;
2770 bus_space_tag_t bt;
2771 char *src;
2772 int i;
2774 if (handle == NULL)
2775 return(0);
2777 block = (ndis_miniport_block *)handle;
2778 #ifdef __FreeBSD__
2779 sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
2780 #else /* __NetBSD__ */
2781 sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2782 #endif
2783 src = buf;
2784 #ifdef __FreeBSD__
2785 bh = rman_get_bushandle(sc->ndis_res_am);
2786 bt = rman_get_bustag(sc->ndis_res_am);
2787 #else
2788 if ( sc->ndis_iftype == PCMCIABus ){
2789 bt = sc->ndis_res_pcmem.memt;
2790 bh = sc->ndis_res_pcmem.memh;
2791 } else { /* cardbus case */
2792 /* TODO what does it really wait for ? */
2793 bt = sc->ndis_res_mem->res_tag;
2794 bh = sc->ndis_res_mem->res_handle;
2796 #endif
2798 for (i = 0; i < len; i++)
2799 bus_space_write_1(bt, bh, (offset + i) * 2, src[i]);
2801 return(i);
2804 __stdcall static list_entry *
2805 NdisInterlockedInsertHeadList(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
2807 list_entry *flink;
2809 KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
2810 flink = head->nle_flink;
2811 entry->nle_flink = flink;
2812 entry->nle_blink = head;
2813 flink->nle_blink = entry;
2814 head->nle_flink = entry;
2815 KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
2817 return(flink);
2820 __stdcall static list_entry *
2821 NdisInterlockedRemoveHeadList(list_entry *head, ndis_spin_lock *lock)
2823 list_entry *flink;
2824 list_entry *entry;
2826 KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
2827 entry = head->nle_flink;
2828 flink = entry->nle_flink;
2829 head->nle_flink = flink;
2830 flink->nle_blink = head;
2831 KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
2833 return(entry);
2836 __stdcall static list_entry *
2837 NdisInterlockedInsertTailList(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
2839 list_entry *blink;
2841 KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
2842 blink = head->nle_blink;
2843 entry->nle_flink = head;
2844 entry->nle_blink = blink;
2845 blink->nle_flink = entry;
2846 head->nle_blink = entry;
2847 KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
2849 return(blink);
2852 __stdcall static uint8_t
2853 NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *intr, void *syncfunc, void *syncctx)
2855 __stdcall uint8_t (*sync)(void *);
2856 uint8_t rval;
2857 uint8_t irql;
2859 if (syncfunc == NULL || syncctx == NULL)
2860 return(0);
2862 sync = syncfunc;
2863 KeAcquireSpinLock(&intr->ni_dpccountlock, &irql);
2864 rval = MSCALL1(sync, syncctx);
2865 KeReleaseSpinLock(&intr->ni_dpccountlock, irql);
2867 return(rval);
2871 * Return the number of 100 nanosecond intervals since
2872 * January 1, 1601. (?!?!)
2874 __stdcall static void
2875 NdisGetCurrentSystemTime(uint64_t *tval)
2877 struct timespec ts;
2878 #ifdef __NetBSD__
2879 struct timeval tv;
2881 microtime(&tv);
2882 TIMEVAL_TO_TIMESPEC(&tv,&ts);
2883 #else
2884 nanotime(&ts);
2885 #endif
2887 *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
2888 (uint64_t)11644473600ULL;
2890 return;
2894 * Return the number of milliseconds since the system booted.
2896 __stdcall static void
2897 NdisGetSystemUpTime(uint32_t *tval)
2899 *tval = (ticks * hz) / 1000;
2901 return;
2904 __stdcall static void
2905 NdisInitializeString(ndis_unicode_string *dst, char *src)
2907 ndis_unicode_string *u;
2909 u = dst;
2910 u->us_buf = NULL;
2911 if (ndis_ascii_to_unicode(src, &u->us_buf))
2912 return;
2913 u->us_len = u->us_maxlen = strlen(src) * 2;
2914 return;
2917 __stdcall static void
2918 NdisFreeString(ndis_unicode_string *str)
2920 if (str == NULL)
2921 return;
2922 if (str->us_buf != NULL)
2923 free(str->us_buf, M_DEVBUF);
2924 free(str, M_DEVBUF);
2925 return;
2928 __stdcall static ndis_status
2929 NdisMRemoveMiniport(ndis_handle *adapter)
2931 return(NDIS_STATUS_SUCCESS);
2934 __stdcall static void
2935 NdisInitAnsiString(ndis_ansi_string *dst, char *src)
2937 ndis_ansi_string *a;
2939 a = dst;
2940 if (a == NULL)
2941 return;
2942 if (src == NULL) {
2943 a->nas_len = a->nas_maxlen = 0;
2944 a->nas_buf = NULL;
2945 } else {
2946 a->nas_buf = src;
2947 a->nas_len = a->nas_maxlen = strlen(src);
2950 return;
2953 __stdcall static void
2954 NdisInitUnicodeString(ndis_unicode_string *dst, uint16_t *src)
2956 ndis_unicode_string *u;
2957 int i;
2959 u = dst;
2960 if (u == NULL)
2961 return;
2962 if (src == NULL) {
2963 u->us_len = u->us_maxlen = 0;
2964 u->us_buf = NULL;
2965 } else {
2966 i = 0;
2967 while(src[i] != 0)
2968 i++;
2969 u->us_buf = src;
2970 u->us_len = u->us_maxlen = i * 2;
2973 return;
2976 __stdcall static void NdisMGetDeviceProperty(
2977 ndis_handle adapter,
2978 device_object **phydevobj,
2979 device_object **funcdevobj,
2980 device_object **nextdevobj,
2981 cm_resource_list *resources,
2982 cm_resource_list *transresources)
2984 ndis_miniport_block *block;
2986 block = (ndis_miniport_block *)adapter;
2988 if (phydevobj != NULL)
2989 *phydevobj = block->nmb_physdeviceobj;
2990 if (funcdevobj != NULL)
2991 *funcdevobj = block->nmb_deviceobj;
2992 if (nextdevobj != NULL)
2993 *nextdevobj = block->nmb_nextdeviceobj;
2995 return;
2998 __stdcall static void
2999 NdisGetFirstBufferFromPacket(ndis_packet *packet, ndis_buffer **buf, void **firstva, uint32_t *firstlen, uint32_t *totlen)
3001 ndis_buffer *tmp;
3003 tmp = packet->np_private.npp_head;
3004 *buf = tmp;
3005 if (tmp == NULL) {
3006 *firstva = NULL;
3007 *firstlen = *totlen = 0;
3008 } else {
3009 *firstva = MmGetMdlVirtualAddress(tmp);
3010 *firstlen = *totlen = MmGetMdlByteCount(tmp);
3011 for (tmp = tmp->mdl_next; tmp != NULL; tmp = tmp->mdl_next)
3012 *totlen += MmGetMdlByteCount(tmp);
3015 return;
3018 __stdcall static void
3019 NdisGetFirstBufferFromPacketSafe(
3020 ndis_packet *packet,
3021 ndis_buffer **buf,
3022 void **firstva,
3023 uint32_t *firstlen,
3024 uint32_t *totlen,
3025 uint32_t prio)
3027 NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen);
3030 #ifdef __FreeBSD__
3031 static int
3032 ndis_find_sym(linker_file_t lf, char *filename, char *suffix, void * *sym)
3034 char *fullsym;
3035 char *suf;
3036 int i;
3038 fullsym = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
3039 if (fullsym == NULL)
3040 return(ENOMEM);
3042 memset(fullsym, 0, MAXPATHLEN);
3043 strncpy(fullsym, filename, MAXPATHLEN);
3044 if (strlen(filename) < 4) {
3045 ExFreePool(fullsym);
3046 return(EINVAL);
3049 /* If the filename has a .ko suffix, strip if off. */
3050 suf = fullsym + (strlen(filename) - 3);
3051 if (strcmp(suf, ".ko") == 0)
3052 *suf = '\0';
3054 for (i = 0; i < strlen(fullsym); i++) {
3055 if (fullsym[i] == '.')
3056 fullsym[i] = '_';
3057 else
3058 fullsym[i] = tolower(fullsym[i]);
3060 strcat(fullsym, suffix);
3061 *sym = linker_file_lookup_symbol(lf, fullsym, 0);
3062 ExFreePool(fullsym);
3063 if (*sym == 0)
3064 return(ENOENT);
3066 return(0);
3069 /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
3070 __stdcall static void
3071 NdisOpenFile(ndis_status *status, ndis_handle *filehandle, uint32_t *filelength, ndis_unicode_string *filename, ndis_physaddr highestaddr)
3073 char *afilename = NULL;
3074 struct thread *td = curthread;
3075 struct nameidata nd;
3076 int flags, error;
3077 struct vattr vat;
3078 struct vattr *vap = &vat;
3079 ndis_fh *fh;
3080 char *path;
3081 linker_file_t head, lf;
3082 void *kldstart, *kldend;
3084 ndis_unicode_to_ascii(filename->us_buf,
3085 filename->us_len, &afilename);
3087 fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0);
3088 if (fh == NULL) {
3089 *status = NDIS_STATUS_RESOURCES;
3090 return;
3094 * During system bootstrap, it's impossible to load files
3095 * from the rootfs since it's not mounted yet. We therefore
3096 * offer the possibility of opening files that have been
3097 * preloaded as modules instead. Both choices will work
3098 * when kldloading a module from multiuser, but only the
3099 * module option will work during bootstrap. The module
3100 * loading option works by using the ndiscvt(8) utility
3101 * to convert the arbitrary file into a .ko using objcopy(1).
3102 * This file will contain two special symbols: filename_start
3103 * and filename_end. All we have to do is traverse the KLD
3104 * list in search of those symbols and we've found the file
3105 * data. As an added bonus, ndiscvt(8) will also generate
3106 * a normal .o file which can be linked statically with
3107 * the kernel. This means that the symbols will actual reside
3108 * in the kernel's symbol table, but that doesn't matter to
3109 * us since the kernel appears to us as just another module.
3113 * This is an evil trick for getting the head of the linked
3114 * file list, which is not exported from kern_linker.o. It
3115 * happens that linker file #1 is always the kernel, and is
3116 * always the first element in the list.
3119 head = linker_find_file_by_id(1);
3120 for (lf = head; lf != NULL; lf = TAILQ_NEXT(lf, link)) {
3121 if (ndis_find_sym(lf, afilename, "_start", &kldstart))
3122 continue;
3123 if (ndis_find_sym(lf, afilename, "_end", &kldend))
3124 continue;
3125 fh->nf_vp = lf;
3126 fh->nf_map = NULL;
3127 fh->nf_type = NDIS_FH_TYPE_MODULE;
3128 *filelength = fh->nf_maplen = (kldend - kldstart) & 0xFFFFFFFF;
3129 *filehandle = fh;
3130 free(afilename, M_DEVBUF);
3131 *status = NDIS_STATUS_SUCCESS;
3132 return;
3135 if (TAILQ_EMPTY(&mountlist)) {
3136 ExFreePool(fh);
3137 *status = NDIS_STATUS_FILE_NOT_FOUND;
3138 printf("NDIS: could not find file %s in linker list\n",
3139 afilename);
3140 printf("NDIS: and no filesystems mounted yet, "
3141 "aborting NdisOpenFile()\n");
3142 free(afilename, M_DEVBUF);
3143 return;
3146 path = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
3147 if (path == NULL) {
3148 ExFreePool(fh);
3149 *status = NDIS_STATUS_RESOURCES;
3150 return;
3153 snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename);
3154 free(afilename, M_DEVBUF);
3156 mtx_lock(&Giant);
3158 /* Some threads don't have a current working directory. */
3160 if (td->td_proc->p_fd->fd_rdir == NULL)
3161 td->td_proc->p_fd->fd_rdir = rootvnode;
3162 if (td->td_proc->p_fd->fd_cdir == NULL)
3163 td->td_proc->p_fd->fd_cdir = rootvnode;
3165 /* freebsd-only code; don't modernize this - dholland */
3166 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
3168 flags = FREAD;
3169 error = vn_open(&nd, &flags, 0, -1);
3170 if (error) {
3171 mtx_unlock(&Giant);
3172 *status = NDIS_STATUS_FILE_NOT_FOUND;
3173 ExFreePool(fh);
3174 printf("NDIS: open file %s failed: %d\n", path, error);
3175 ExFreePool(path);
3176 return;
3179 ExFreePool(path);
3181 NDFREE(&nd, NDF_ONLY_PNBUF);
3183 /* Get the file size. */
3184 VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td);
3185 VOP_UNLOCK(nd.ni_vp, 0, td);
3186 mtx_unlock(&Giant);
3188 fh->nf_vp = nd.ni_vp;
3189 fh->nf_map = NULL;
3190 fh->nf_type = NDIS_FH_TYPE_VFS;
3191 *filehandle = fh;
3192 *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
3193 *status = NDIS_STATUS_SUCCESS;
3195 return;
3198 __stdcall static void
3199 NdisMapFile(ndis_status *status, void **mappedbuffer, ndis_handle filehandle)
3201 ndis_fh *fh;
3202 struct thread *td = curthread;
3203 linker_file_t lf;
3204 void * kldstart;
3205 int error, resid;
3207 if (filehandle == NULL) {
3208 *status = NDIS_STATUS_FAILURE;
3209 return;
3212 fh = (ndis_fh *)filehandle;
3214 if (fh->nf_vp == NULL) {
3215 *status = NDIS_STATUS_FAILURE;
3216 return;
3219 if (fh->nf_map != NULL) {
3220 *status = NDIS_STATUS_ALREADY_MAPPED;
3221 return;
3224 if (fh->nf_type == NDIS_FH_TYPE_MODULE) {
3225 lf = fh->nf_vp;
3226 if (ndis_find_sym(lf, lf->filename, "_start", &kldstart)) {
3227 *status = NDIS_STATUS_FAILURE;
3228 return;
3230 fh->nf_map = kldstart;
3231 *status = NDIS_STATUS_SUCCESS;
3232 *mappedbuffer = fh->nf_map;
3233 return;
3236 fh->nf_map = ExAllocatePoolWithTag(NonPagedPool, fh->nf_maplen, 0);
3238 if (fh->nf_map == NULL) {
3239 *status = NDIS_STATUS_RESOURCES;
3240 return;
3243 mtx_lock(&Giant);
3244 error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
3245 UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td);
3246 mtx_unlock(&Giant);
3248 if (error)
3249 *status = NDIS_STATUS_FAILURE;
3250 else {
3251 *status = NDIS_STATUS_SUCCESS;
3252 *mappedbuffer = fh->nf_map;
3255 return;
3258 __stdcall static void
3259 NdisUnmapFile(ndis_handle filehandle)
3261 ndis_fh *fh;
3262 fh = (ndis_fh *)filehandle;
3264 if (fh->nf_map == NULL)
3265 return;
3267 if (fh->nf_type == NDIS_FH_TYPE_VFS)
3268 ExFreePool(fh->nf_map);
3269 fh->nf_map = NULL;
3271 return;
3274 __stdcall static void
3275 NdisCloseFile(ndis_handle filehandle)
3277 struct thread *td = curthread;
3278 ndis_fh *fh;
3280 if (filehandle == NULL)
3281 return;
3283 fh = (ndis_fh *)filehandle;
3284 if (fh->nf_map != NULL) {
3285 if (fh->nf_type == NDIS_FH_TYPE_VFS)
3286 ExFreePool(fh->nf_map);
3287 fh->nf_map = NULL;
3290 if (fh->nf_vp == NULL)
3291 return;
3293 if (fh->nf_type == NDIS_FH_TYPE_VFS) {
3294 mtx_lock(&Giant);
3295 vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
3296 mtx_unlock(&Giant);
3299 fh->nf_vp = NULL;
3300 ExFreePool(fh);
3302 return;
3304 #endif /* __FreeBSD__ */
3305 __stdcall static uint8_t
3306 NdisSystemProcessorCount(void)
3308 #ifdef __FreeBSD__
3309 return(mp_ncpus);
3310 #else
3311 return(nprocs);
3312 #endif
3315 typedef void (*ndis_statusdone_handler)(ndis_handle);
3316 typedef void (*ndis_status_handler)(ndis_handle, ndis_status,
3317 void *, uint32_t);
3319 __stdcall static void
3320 NdisMIndicateStatusComplete(ndis_handle adapter)
3322 ndis_miniport_block *block;
3323 __stdcall ndis_statusdone_handler statusdonefunc;
3325 block = (ndis_miniport_block *)adapter;
3326 statusdonefunc = block->nmb_statusdone_func;
3328 MSCALL1(statusdonefunc, adapter);
3329 return;
3332 __stdcall static void
3333 NdisMIndicateStatus(ndis_handle adapter, ndis_status status, void *sbuf, uint32_t slen)
3335 ndis_miniport_block *block;
3336 __stdcall ndis_status_handler statusfunc;
3338 block = (ndis_miniport_block *)adapter;
3339 statusfunc = block->nmb_status_func;
3341 MSCALL4(statusfunc, adapter, status, sbuf, slen);
3342 return;
3345 static void
3346 ndis_workfunc(void *ctx)
3348 ndis_work_item *work;
3349 __stdcall ndis_proc workfunc;
3351 work = ctx;
3352 workfunc = work->nwi_func;
3353 MSCALL2(workfunc, work, work->nwi_ctx);
3354 return;
3357 __stdcall static ndis_status
3358 NdisScheduleWorkItem(ndis_work_item *work)
3360 ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
3361 return(NDIS_STATUS_SUCCESS);
3364 __stdcall static void
3365 NdisCopyFromPacketToPacket(ndis_packet *dpkt, uint32_t doff, uint32_t reqlen, ndis_packet *spkt, uint32_t soff, uint32_t *cpylen)
3367 ndis_buffer *src, *dst;
3368 char *sptr, *dptr;
3369 int resid, copied, len, scnt, dcnt;
3371 *cpylen = 0;
3373 src = spkt->np_private.npp_head;
3374 dst = dpkt->np_private.npp_head;
3376 sptr = MmGetMdlVirtualAddress(src);
3377 dptr = MmGetMdlVirtualAddress(dst);
3378 scnt = MmGetMdlByteCount(src);
3379 dcnt = MmGetMdlByteCount(dst);
3381 while (soff) {
3382 if (MmGetMdlByteCount(src) > soff) {
3383 sptr += soff;
3384 scnt = MmGetMdlByteCount(src)- soff;
3385 break;
3387 soff -= MmGetMdlByteCount(src);
3388 src = src->mdl_next;
3389 if (src == NULL)
3390 return;
3391 sptr = MmGetMdlVirtualAddress(src);
3394 while (doff) {
3395 if (MmGetMdlByteCount(dst) > doff) {
3396 dptr += doff;
3397 dcnt = MmGetMdlByteCount(dst) - doff;
3398 break;
3400 doff -= MmGetMdlByteCount(dst);
3401 dst = dst->mdl_next;
3402 if (dst == NULL)
3403 return;
3404 dptr = MmGetMdlVirtualAddress(dst);
3407 resid = reqlen;
3408 copied = 0;
3410 while(1) {
3411 if (resid < scnt)
3412 len = resid;
3413 else
3414 len = scnt;
3415 if (dcnt < len)
3416 len = dcnt;
3418 memcpy( dptr, sptr, len);
3420 copied += len;
3421 resid -= len;
3422 if (resid == 0)
3423 break;
3425 dcnt -= len;
3426 if (dcnt == 0) {
3427 dst = dst->mdl_next;
3428 if (dst == NULL)
3429 break;
3430 dptr = MmGetMdlVirtualAddress(dst);
3431 dcnt = MmGetMdlByteCount(dst);
3434 scnt -= len;
3435 if (scnt == 0) {
3436 src = src->mdl_next;
3437 if (src == NULL)
3438 break;
3439 sptr = MmGetMdlVirtualAddress(src);
3440 scnt = MmGetMdlByteCount(src);
3444 *cpylen = copied;
3445 return;
3448 __stdcall static void
3449 NdisCopyFromPacketToPacketSafe(
3450 ndis_packet *dpkt,
3451 uint32_t doff,
3452 uint32_t reqlen,
3453 ndis_packet *spkt,
3454 uint32_t soff,
3455 uint32_t *cpylen,
3456 uint32_t prio)
3458 NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen);
3459 return;
3462 __stdcall static ndis_status
3463 NdisMRegisterDevice(
3464 ndis_handle handle,
3465 ndis_unicode_string *devname,
3466 ndis_unicode_string *symname,
3467 driver_dispatch *majorfuncs[],
3468 void **devobj,
3469 ndis_handle *devhandle)
3471 ndis_miniport_block *block;
3473 block = (ndis_miniport_block *)handle;
3474 *devobj = block->nmb_deviceobj;
3475 *devhandle = handle;
3477 return(NDIS_STATUS_SUCCESS);
3480 __stdcall static ndis_status
3481 NdisMDeregisterDevice(ndis_handle handle)
3483 return(NDIS_STATUS_SUCCESS);
3486 __stdcall static ndis_status
3487 NdisMQueryAdapterInstanceName(ndis_unicode_string *name, ndis_handle handle)
3489 ndis_miniport_block *block;
3490 device_t dev;
3492 block = (ndis_miniport_block *)handle;
3493 dev = block->nmb_physdeviceobj->do_devext;
3495 ndis_ascii_to_unicode(__DECONST(char *,
3496 device_get_nameunit(dev)), &name->us_buf);
3497 name->us_len = strlen(device_get_nameunit(dev)) * 2;
3499 return(NDIS_STATUS_SUCCESS);
3502 __stdcall static void
3503 NdisMRegisterUnloadHandler(
3504 ndis_handle handle,
3505 void *func)
3507 return;
3510 __stdcall static void
3511 dummy(void)
3513 printf ("NDIS dummy called...\n");
3514 return;
3517 image_patch_table ndis_functbl[] = {
3518 IMPORT_FUNC(NdisCopyFromPacketToPacket),
3519 IMPORT_FUNC(NdisCopyFromPacketToPacketSafe),
3520 IMPORT_FUNC(NdisScheduleWorkItem),
3521 IMPORT_FUNC(NdisMIndicateStatusComplete),
3522 IMPORT_FUNC(NdisMIndicateStatus),
3523 IMPORT_FUNC(NdisSystemProcessorCount),
3524 IMPORT_FUNC(NdisUnchainBufferAtBack),
3525 IMPORT_FUNC(NdisGetFirstBufferFromPacket),
3526 IMPORT_FUNC(NdisGetFirstBufferFromPacketSafe),
3527 IMPORT_FUNC(NdisGetBufferPhysicalArraySize),
3528 IMPORT_FUNC(NdisMGetDeviceProperty),
3529 IMPORT_FUNC(NdisInitAnsiString),
3530 IMPORT_FUNC(NdisInitUnicodeString),
3531 IMPORT_FUNC(NdisWriteConfiguration),
3532 IMPORT_FUNC(NdisAnsiStringToUnicodeString),
3533 IMPORT_FUNC(NdisTerminateWrapper),
3534 IMPORT_FUNC(NdisOpenConfigurationKeyByName),
3535 IMPORT_FUNC(NdisOpenConfigurationKeyByIndex),
3536 IMPORT_FUNC(NdisMRemoveMiniport),
3537 IMPORT_FUNC(NdisInitializeString),
3538 IMPORT_FUNC(NdisFreeString),
3539 IMPORT_FUNC(NdisGetCurrentSystemTime),
3540 IMPORT_FUNC(NdisGetSystemUpTime),
3541 IMPORT_FUNC(NdisMSynchronizeWithInterrupt),
3542 IMPORT_FUNC(NdisMAllocateSharedMemoryAsync),
3543 IMPORT_FUNC(NdisInterlockedInsertHeadList),
3544 IMPORT_FUNC(NdisInterlockedInsertTailList),
3545 IMPORT_FUNC(NdisInterlockedRemoveHeadList),
3546 IMPORT_FUNC(NdisInitializeWrapper),
3547 IMPORT_FUNC(NdisMRegisterMiniport),
3548 IMPORT_FUNC(NdisAllocateMemoryWithTag),
3549 IMPORT_FUNC(NdisAllocateMemory),
3550 IMPORT_FUNC(NdisMSetAttributesEx),
3551 IMPORT_FUNC(NdisCloseConfiguration),
3552 IMPORT_FUNC(NdisReadConfiguration),
3553 IMPORT_FUNC(NdisOpenConfiguration),
3554 IMPORT_FUNC(NdisAcquireSpinLock),
3555 IMPORT_FUNC(NdisReleaseSpinLock),
3556 IMPORT_FUNC(NdisDprAcquireSpinLock),
3557 IMPORT_FUNC(NdisDprReleaseSpinLock),
3558 IMPORT_FUNC(NdisAllocateSpinLock),
3559 IMPORT_FUNC(NdisFreeSpinLock),
3560 IMPORT_FUNC(NdisFreeMemory),
3561 IMPORT_FUNC(NdisReadPciSlotInformation),
3562 IMPORT_FUNC(NdisWritePciSlotInformation),
3563 IMPORT_FUNC_MAP(NdisImmediateReadPciSlotInformation,
3564 NdisReadPciSlotInformation),
3565 IMPORT_FUNC_MAP(NdisImmediateWritePciSlotInformation,
3566 NdisWritePciSlotInformation),
3567 IMPORT_FUNC(NdisWriteErrorLogEntry),
3568 IMPORT_FUNC(NdisMStartBufferPhysicalMapping),
3569 IMPORT_FUNC(NdisMCompleteBufferPhysicalMapping),
3570 IMPORT_FUNC(NdisMInitializeTimer),
3571 IMPORT_FUNC(NdisInitializeTimer),
3572 IMPORT_FUNC(NdisSetTimer),
3573 IMPORT_FUNC(NdisMCancelTimer),
3574 IMPORT_FUNC_MAP(NdisCancelTimer, NdisMCancelTimer),
3575 IMPORT_FUNC(NdisMSetPeriodicTimer),
3576 IMPORT_FUNC(NdisMQueryAdapterResources),
3577 IMPORT_FUNC(NdisMRegisterIoPortRange),
3578 IMPORT_FUNC(NdisMDeregisterIoPortRange),
3579 IMPORT_FUNC(NdisReadNetworkAddress),
3580 IMPORT_FUNC(NdisQueryMapRegisterCount),
3581 IMPORT_FUNC(NdisMAllocateMapRegisters),
3582 IMPORT_FUNC(NdisMFreeMapRegisters),
3583 IMPORT_FUNC(NdisMAllocateSharedMemory),
3584 IMPORT_FUNC(NdisMMapIoSpace),
3585 IMPORT_FUNC(NdisMUnmapIoSpace),
3586 IMPORT_FUNC(NdisGetCacheFillSize),
3587 IMPORT_FUNC(NdisMGetDmaAlignment),
3588 IMPORT_FUNC(NdisMInitializeScatterGatherDma),
3589 IMPORT_FUNC(NdisAllocatePacketPool),
3590 IMPORT_FUNC(NdisAllocatePacketPoolEx),
3591 IMPORT_FUNC(NdisAllocatePacket),
3592 IMPORT_FUNC(NdisFreePacket),
3593 IMPORT_FUNC(NdisFreePacketPool),
3594 IMPORT_FUNC_MAP(NdisDprAllocatePacket, NdisAllocatePacket),
3595 IMPORT_FUNC_MAP(NdisDprFreePacket, NdisFreePacket),
3596 IMPORT_FUNC(NdisAllocateBufferPool),
3597 IMPORT_FUNC(NdisAllocateBuffer),
3598 IMPORT_FUNC(NdisQueryBuffer),
3599 IMPORT_FUNC(NdisQueryBufferSafe),
3600 IMPORT_FUNC(NdisBufferVirtualAddress),
3601 IMPORT_FUNC(NdisBufferVirtualAddressSafe),
3602 IMPORT_FUNC(NdisBufferLength),
3603 IMPORT_FUNC(NdisFreeBuffer),
3604 IMPORT_FUNC(NdisFreeBufferPool),
3605 IMPORT_FUNC(NdisInterlockedIncrement),
3606 IMPORT_FUNC(NdisInterlockedDecrement),
3607 IMPORT_FUNC(NdisInitializeEvent),
3608 IMPORT_FUNC(NdisSetEvent),
3609 IMPORT_FUNC(NdisResetEvent),
3610 IMPORT_FUNC(NdisWaitEvent),
3611 IMPORT_FUNC(NdisUnicodeStringToAnsiString),
3612 IMPORT_FUNC(NdisMPciAssignResources),
3613 IMPORT_FUNC(NdisMFreeSharedMemory),
3614 IMPORT_FUNC(NdisMRegisterInterrupt),
3615 IMPORT_FUNC(NdisMDeregisterInterrupt),
3616 IMPORT_FUNC(NdisMRegisterAdapterShutdownHandler),
3617 IMPORT_FUNC(NdisMDeregisterAdapterShutdownHandler),
3618 IMPORT_FUNC(NDIS_BUFFER_TO_SPAN_PAGES),
3619 IMPORT_FUNC(NdisQueryBufferOffset),
3620 IMPORT_FUNC(NdisAdjustBufferLength),
3621 IMPORT_FUNC(NdisPacketPoolUsage),
3622 IMPORT_FUNC(NdisMSleep),
3623 IMPORT_FUNC(NdisUnchainBufferAtFront),
3624 IMPORT_FUNC(NdisReadPcmciaAttributeMemory),
3625 IMPORT_FUNC(NdisWritePcmciaAttributeMemory),
3626 #ifdef __FreeBSD__
3627 IMPORT_FUNC(NdisOpenFile),
3628 IMPORT_FUNC(NdisMapFile),
3629 IMPORT_FUNC(NdisUnmapFile),
3630 IMPORT_FUNC(NdisCloseFile),
3631 #endif
3632 IMPORT_FUNC(NdisMRegisterDevice),
3633 IMPORT_FUNC(NdisMDeregisterDevice),
3634 IMPORT_FUNC(NdisMQueryAdapterInstanceName),
3635 IMPORT_FUNC(NdisMRegisterUnloadHandler),
3636 IMPORT_FUNC(ndis_timercall),
3639 * This last entry is a catch-all for any function we haven't
3640 * implemented yet. The PE import list patching routine will
3641 * use it for any function that doesn't have an explicit match
3642 * in this table.
3645 { NULL, (FUNC)dummy, NULL },
3647 /* End of list. */
3649 { NULL, NULL, NULL }