Annotation of src/sys/compat/ndis/subr_ndis.c, Revision 1.15
1.1 rittera 1: /*-
2: * Copyright (c) 2003
3: * Bill Paul <wpaul@windriver.com>. All rights reserved.
4: *
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.
19: *
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.
31: */
32:
33: #include <sys/cdefs.h>
1.2 rittera 34: #ifdef __FreeBSD__
1.1 rittera 35: __FBSDID("$FreeBSD: src/sys/compat/ndis/subr_ndis.c,v 1.67.2.7 2005/03/31 21:50:11 wpaul Exp $");
1.2 rittera 36: #endif
37: #ifdef __NetBSD__
1.15 ! dsl 38: __KERNEL_RCSID(0, "$NetBSD: subr_ndis.c,v 1.14 2008/11/13 12:09:52 ad Exp $");
1.2 rittera 39: #endif
1.1 rittera 40:
41: /*
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.
49: *
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.
54: */
55:
1.2 rittera 56: #ifdef __FreeBSD__
1.1 rittera 57: #include <sys/ctype.h>
1.2 rittera 58: #endif
1.1 rittera 59: #include <sys/param.h>
60: #include <sys/types.h>
61: #include <sys/errno.h>
62:
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>
1.2 rittera 68: #ifdef __FreeBSD__
1.1 rittera 69: #include <sys/mutex.h>
1.2 rittera 70: #endif
1.1 rittera 71: #include <sys/socket.h>
72: #include <sys/sysctl.h>
1.2 rittera 73: #ifdef __FreeBSD__
1.1 rittera 74: #include <sys/timespec.h>
75: #include <sys/smp.h>
1.2 rittera 76: #endif
1.1 rittera 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>
1.2 rittera 84: #ifdef __FreeBSD__
1.1 rittera 85: #include <sys/linker.h>
1.2 rittera 86: #include <sys/sysproto.h>
87: #endif
1.1 rittera 88: #include <sys/mount.h>
89:
90: #include <net/if.h>
91: #include <net/if_arp.h>
1.2 rittera 92: #ifdef __FreeBSD__
1.1 rittera 93: #include <net/ethernet.h>
1.2 rittera 94: #else
95: #include <net/if_ether.h>
96: #endif
1.1 rittera 97: #include <net/if_dl.h>
98: #include <net/if_media.h>
99:
1.11 ad 100: #include <sys/atomic.h>
1.2 rittera 101: #ifdef __FreeBSD__
1.1 rittera 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>
1.2 rittera 107: #endif
1.10 ad 108: #include <sys/bus.h>
1.1 rittera 109:
110: #include <machine/stdarg.h>
111:
112: #include <net80211/ieee80211_var.h>
113: #include <net80211/ieee80211_ioctl.h>
114:
115: #include <dev/pci/pcireg.h>
116: #include <dev/pci/pcivar.h>
117:
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>
125:
1.3 rittera 126: #ifdef __NetBSD__
127: #include "nbcompat.h"
128: #endif
129:
130: #ifdef __NetBSD__
131: #define PN(name) /* printf(#name "\n"); */
132: #endif
133:
1.1 rittera 134: static char ndis_filepath[MAXPATHLEN];
135: extern struct nd_head ndis_devhead;
136:
1.2 rittera 137: #ifdef __FreeBSD__
1.1 rittera 138: SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
139: MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
1.2 rittera 140: #endif
1.1 rittera 141:
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 *);
1.2 rittera 159: #ifdef __FreeBSD__
1.1 rittera 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 *);
1.3 rittera 164: #else /* __NetBSD__ */
165: static ndis_status ndis_encode_parm(ndis_miniport_block *,
166: void *, ndis_parm_type, ndis_config_parm **);
167: #endif
1.1 rittera 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);
1.2 rittera 295: #ifdef __FreeBSD__
1.7 christos 296: static int ndis_find_sym(linker_file_t, char *, char *, void **);
1.1 rittera 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);
1.2 rittera 302: #endif
1.1 rittera 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);
323:
324: /*
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.
331: */
332: #define NDIS_POOL_EXTRA 16
333:
334: int
335: ndis_libinit()
336: {
337: image_patch_table *patch;
338:
339: strcpy(ndis_filepath, "/compat/ndis");
340:
341: patch = ndis_functbl;
342: while (patch->ipt_func != NULL) {
343: windrv_wrap((funcptr)patch->ipt_func,
344: (funcptr *)&patch->ipt_wrap);
345: patch++;
346: }
347:
348: return(0);
349: }
350:
351: int
352: ndis_libfini()
353: {
354: image_patch_table *patch;
355:
356: patch = ndis_functbl;
357: while (patch->ipt_func != NULL) {
358: windrv_unwrap(patch->ipt_wrap);
359: patch++;
360: }
361:
362: return(0);
363: }
364:
365: static funcptr
1.15 ! dsl 366: ndis_findwrap(funcptr func)
1.1 rittera 367: {
368: image_patch_table *patch;
369:
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++;
375: }
376:
377: return(NULL);
378: }
379:
380: /*
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.
385: */
386:
387: int
1.15 ! dsl 388: ndis_ascii_to_unicode(const char *ascii, uint16_t **unicode)
1.1 rittera 389: {
390: uint16_t *ustr;
391: int i;
392:
393: if (*unicode == NULL)
394: *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_NOWAIT);
395:
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++;
402: }
403:
404: return(0);
405: }
406:
407: int
1.15 ! dsl 408: ndis_unicode_to_ascii(uint16_t *unicode, int ulen, char **ascii)
1.1 rittera 409: {
410: uint8_t *astr;
411: int i;
412:
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++;
421: }
422:
423: return(0);
424: }
425:
426: /*
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
430: */
431: __stdcall static void
1.5 christos 432: NdisInitializeWrapper(
1.6 christos 433: ndis_handle *wrapper,
1.5 christos 434: driver_object *drv,
1.6 christos 435: void *path,
436: void *unused)
1.1 rittera 437: {
1.3 rittera 438: PN(NdisInitializeWrapper)
1.1 rittera 439: /*
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.
447: */
448:
449: *wrapper = drv;
450:
451: /*
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.
457: */
458:
459: drv->dro_driverext->dre_adddevicefunc = NdisAddDevice;
460:
461: return;
462: }
463:
464: __stdcall static void
1.5 christos 465: NdisTerminateWrapper(
1.6 christos 466: ndis_handle handle,
467: void *syspec)
1.1 rittera 468: {
469: /* Nothing to see here, move along. */
470: return;
471: }
472:
473: __stdcall static ndis_status
1.15 ! dsl 474: NdisMRegisterMiniport(ndis_handle handle, ndis_miniport_characteristics *characteristics, int len)
1.1 rittera 475: {
1.3 rittera 476: ndis_miniport_characteristics *pch = NULL;
477: void *ch = NULL;
1.1 rittera 478: driver_object *drv;
479:
1.3 rittera 480: PN(NdisMRegisterMiniport);
481:
1.1 rittera 482: drv = (driver_object *)handle;
483:
484: /*
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()).
492: */
493: if (IoAllocateDriverObjectExtension(drv, (void *)1,
1.3 rittera 494: sizeof(ndis_miniport_characteristics), /*(void **)*/&ch) !=
1.1 rittera 495: STATUS_SUCCESS)
496: return(NDIS_STATUS_RESOURCES);
1.3 rittera 497: pch = (ndis_miniport_characteristics *)ch;
1.1 rittera 498:
1.3 rittera 499: bzero((char *)pch, sizeof(ndis_miniport_characteristics));
1.1 rittera 500:
1.3 rittera 501: #ifdef __FreeBSD__
502: bcopy((char *)characteristics, (char *)pch, len);
503: #else /* __NetBSD__ */
504: memcpy(pch, characteristics, len);
505: #endif
506:
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;
1.1 rittera 511: }
512:
513: return(NDIS_STATUS_SUCCESS);
514: }
515:
516: __stdcall static ndis_status
1.15 ! dsl 517: NdisAllocateMemoryWithTag(void **vaddr, uint32_t len, uint32_t tag)
1.1 rittera 518: {
519: void *mem;
520:
521:
522: mem = ExAllocatePoolWithTag(NonPagedPool, len, tag);
523: if (mem == NULL)
524: return(NDIS_STATUS_RESOURCES);
525: *vaddr = mem;
526:
527: return(NDIS_STATUS_SUCCESS);
528: }
529:
530: __stdcall static ndis_status
1.5 christos 531: NdisAllocateMemory(
532: void **vaddr,
533: uint32_t len,
1.6 christos 534: uint32_t flags,
535: ndis_physaddr highaddr)
1.1 rittera 536: {
537: void *mem;
538:
539: mem = ExAllocatePoolWithTag(NonPagedPool, len, 0);
540: if (mem == NULL)
541: return(NDIS_STATUS_RESOURCES);
542: *vaddr = mem;
543:
544: return(NDIS_STATUS_SUCCESS);
545: }
546:
547: __stdcall static void
1.5 christos 548: NdisFreeMemory(
549: void *vaddr,
550: uint32_t len,
1.6 christos 551: uint32_t flags)
1.1 rittera 552: {
553: if (len == 0)
554: return;
555:
556: ExFreePool(vaddr);
557:
558: return;
559: }
560:
561: __stdcall static ndis_status
1.5 christos 562: NdisMSetAttributesEx(
563: ndis_handle adapter_handle,
564: ndis_handle adapter_ctx,
565: uint32_t hangsecs,
566: uint32_t flags,
1.6 christos 567: ndis_interface_type iftype)
1.1 rittera 568: {
569: ndis_miniport_block *block;
570:
1.3 rittera 571: PN(NdisMSetAttributesEx)
1.1 rittera 572: /*
573: * Save the adapter context, we need it for calling
574: * the driver's internal functions.
575: */
576: block = (ndis_miniport_block *)adapter_handle;
577: block->nmb_miniportadapterctx = adapter_ctx;
578: block->nmb_checkforhangsecs = hangsecs;
579: block->nmb_flags = flags;
580:
581: return(NDIS_STATUS_SUCCESS);
582: }
583:
584: __stdcall static void
1.15 ! dsl 585: NdisOpenConfiguration(ndis_status *status, ndis_handle *cfg, ndis_handle wrapctx)
1.1 rittera 586: {
1.3 rittera 587: PN(NdisOpenConfiguration)
1.1 rittera 588: *cfg = wrapctx;
589: *status = NDIS_STATUS_SUCCESS;
590:
591: return;
592: }
593:
594: __stdcall static void
1.5 christos 595: NdisOpenConfigurationKeyByName(
596: ndis_status *status,
597: ndis_handle cfg,
1.6 christos 598: ndis_unicode_string *subkey,
1.5 christos 599: ndis_handle *subhandle)
1.1 rittera 600: {
1.3 rittera 601: PN(NdisOpenConfiguration)
1.1 rittera 602: *subhandle = cfg;
603: *status = NDIS_STATUS_SUCCESS;
604: return;
605: }
606:
607: __stdcall static void
1.5 christos 608: NdisOpenConfigurationKeyByIndex(
609: ndis_status *status,
1.6 christos 610: ndis_handle cfg,
611: uint32_t idx,
612: ndis_unicode_string *subkey,
613: ndis_handle *subhandle)
1.1 rittera 614: {
615: *status = NDIS_STATUS_FAILURE;
616: return;
617: }
618:
1.3 rittera 619: static ndis_status
1.2 rittera 620: #ifdef __FreeBSD__
1.1 rittera 621: ndis_encode_parm(block, oid, type, parm)
1.3 rittera 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;
1.1 rittera 630: ndis_parm_type type;
631: ndis_config_parm **parm;
1.3 rittera 632: #endif
1.1 rittera 633: {
634: uint16_t *unicode;
635: ndis_unicode_string *ustr;
636: int base = 0;
637:
1.3 rittera 638: PN(ndis_encode_parm)
639:
1.1 rittera 640: unicode = (uint16_t *)&block->nmb_dummybuf;
641:
642: switch(type) {
643: case ndis_parm_string:
1.3 rittera 644: #ifdef __FreeBSD__
1.1 rittera 645: ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
1.3 rittera 646: #else /* __NetBSD__ */
647: ndis_ascii_to_unicode((char *)data, &unicode);
648: #endif
1.1 rittera 649: (*parm)->ncp_type = ndis_parm_string;
650: ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
1.3 rittera 651: #ifdef __FreeBSD__
1.1 rittera 652: ustr->us_len = strlen((char *)oid->oid_arg1) * 2;
1.3 rittera 653: #else /* __NetBSD__ */
654: ustr->us_len = strlen((char *)data) * 2;
655: #endif
1.1 rittera 656: ustr->us_buf = unicode;
657: break;
658: case ndis_parm_int:
1.3 rittera 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
1.1 rittera 664: base = 16;
1.3 rittera 665: }
1.1 rittera 666: else
667: base = 10;
668: (*parm)->ncp_type = ndis_parm_int;
669: (*parm)->ncp_parmdata.ncp_intdata =
1.3 rittera 670: #ifdef __FreeBSD__
1.1 rittera 671: strtol((char *)oid->oid_arg1, NULL, base);
1.3 rittera 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
1.1 rittera 676: break;
677: case ndis_parm_hexint:
1.3 rittera 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
1.1 rittera 683: base = 16;
1.3 rittera 684: }
1.1 rittera 685: else
686: base = 10;
687: (*parm)->ncp_type = ndis_parm_hexint;
688: (*parm)->ncp_parmdata.ncp_intdata =
1.3 rittera 689: #ifdef __FreeBSD__
1.1 rittera 690: strtoul((char *)oid->oid_arg1, NULL, base);
1.3 rittera 691: #else /* __NetBSD__ */
692: strtoul((char *)data, NULL, base);
693: #endif
1.1 rittera 694: break;
695: default:
696: return(NDIS_STATUS_FAILURE);
697: break;
698: }
699:
700: return(NDIS_STATUS_SUCCESS);
701: }
702:
703: int
1.15 ! dsl 704: ndis_strcasecmp(const char *s1, const char *s2)
1.1 rittera 705: {
706: char a, b;
707:
708: /*
709: * In the kernel, toupper() is a macro. Have to be careful
710: * not to use pointer arithmetic when passing it arguments.
711: */
712:
713: while(1) {
714: a = *s1;
715: b = *s2++;
716: if (toupper(a) != toupper(b))
717: break;
718: if (*s1++ == '\0')
719: return(0);
720: }
721:
722: return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
723: }
724:
725: int
1.15 ! dsl 726: ndis_strncasecmp(const char *s1, const char *s2, size_t n)
1.1 rittera 727: {
728: char a, b;
729:
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);
740: }
741:
742: return(0);
743: }
744:
745: __stdcall static void
1.15 ! dsl 746: NdisReadConfiguration(ndis_status *status, ndis_config_parm **parm, ndis_handle cfg, ndis_unicode_string *key, ndis_parm_type type)
1.1 rittera 747: {
748: char *keystr = NULL;
749: uint16_t *unicode;
750: ndis_miniport_block *block;
751: struct ndis_softc *sc;
1.3 rittera 752: #ifdef __FreeBSD__
753: struct sysctl_oid *oidp;
1.1 rittera 754: struct sysctl_ctx_entry *e;
1.3 rittera 755: #endif
756:
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
1.1 rittera 767:
768: block = (ndis_miniport_block *)cfg;
1.3 rittera 769: #ifdef __FreeBSD__
1.1 rittera 770: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 771: #else /* __NetBSD__ */
772: sc = block->nmb_physdeviceobj->pdo_sc;
773: #endif
774: PN(NdisReadConfiguration)
1.1 rittera 775:
776: if (key->us_len == 0 || key->us_buf == NULL) {
777: *status = NDIS_STATUS_FAILURE;
778: return;
779: }
780:
781: ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr);
782: *parm = &block->nmb_replyparm;
783: bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
784: unicode = (uint16_t *)&block->nmb_dummybuf;
1.3 rittera 785:
786: #ifdef __NetBSD__
787: if(strlen(keystr) + strlen("ndis_") > MAX_SYSCTL_LEN) {
788: panic("sysctl name too long: %s\n", keystr);
789: }
790: strcpy(new_keystr, "ndis_");
791: strcpy(new_keystr + strlen("ndis_"), keystr);
792: old_keystr = keystr;
793: keystr = new_keystr;
794: #endif
1.1 rittera 795:
796: /*
797: * See if registry key is already in a list of known keys
798: * included with the driver.
799: */
1.3 rittera 800: #ifdef __FreeBSD__
1.1 rittera 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;
1.3 rittera 807: #ifdef __FreeBSD__
1.1 rittera 808: if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
1.3 rittera 809: #else /* __NetBSD__ */
810: if (ndis_strcasecmp(oidp->ctl_name, keystr) == 0) {
811: #endif
1.1 rittera 812: if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
813: free(keystr, M_DEVBUF);
814: *status = NDIS_STATUS_FAILURE;
815: return;
1.3 rittera 816: }
817: *status = ndis_encode_parm(block, oidp, type, parm);
818:
819: free(keystr, M_DEVBUF);
820: return;
821: }
822: }
823: #else /* __NetBSD__ */
824: mib[0] = sc->ndis_sysctl_mib;
825:
1.13 ad 826: sysctl_lock(false);
1.3 rittera 827: error = sysctl_locate(curlwp, &mib[0], 1, &pnode, NULL);
828:
829: numcld = pnode->sysctl_csize;
830: ndiscld = pnode->sysctl_child;
831:
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;
1.1 rittera 837: }
1.3 rittera 838: ndiscld++;
839: }
1.13 ad 840: sysctl_unlock();
1.3 rittera 841:
842: if(i < numcld) {
843: /* Found it */
844: if(strcmp(ndiscld->sysctl_data, "UNSET") == 0) {
1.1 rittera 845: free(keystr, M_DEVBUF);
1.3 rittera 846: *status = NDIS_STATUS_FAILURE;
1.1 rittera 847: return;
848: }
1.3 rittera 849:
850: *status = ndis_encode_parm(block, ndiscld->sysctl_data, type, parm);
851: free(keystr, M_DEVBUF);
852: return;
1.1 rittera 853: }
1.3 rittera 854:
855: #endif
856:
857: #ifdef __NetBSD__
858: free(keystr, M_DEVBUF);
859: keystr = old_keystr;
860: #endif
1.1 rittera 861:
862: /*
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".
872: */
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)",
1.3 rittera 878: "UNSET", CTLFLAG_RW);
1.1 rittera 879:
880: free(keystr, M_DEVBUF);
881: *status = NDIS_STATUS_FAILURE;
882: return;
883: }
884:
1.3 rittera 885: #ifdef __FreeBSD__
1.1 rittera 886: static ndis_status
1.15 ! dsl 887: ndis_decode_parm(ndis_miniport_block *block, ndis_config_parm *parm, char *val)
1.1 rittera 888: {
889: ndis_unicode_string *ustr;
890: char *astr = NULL;
891:
1.3 rittera 892: PN(ndis_decode_parm)
893:
1.1 rittera 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: bcopy(astr, val, 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;
910: }
911: return(NDIS_STATUS_SUCCESS);
912: }
1.3 rittera 913: #endif
1.1 rittera 914:
915: __stdcall static void
1.5 christos 916: NdisWriteConfiguration(
917: ndis_status *status,
1.6 christos 918: ndis_handle cfg,
919: ndis_unicode_string *key,
920: ndis_config_parm *parm)
1.1 rittera 921: {
1.2 rittera 922: #ifdef __FreeBSD__
1.1 rittera 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];
929:
930: block = (ndis_miniport_block *)cfg;
1.2 rittera 931:
1.3 rittera 932: PN(NdisWriteConfiguration)
933:
934: #ifdef __FreeBSD__
1.1 rittera 935: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 936: #else /* __NetBSD__ */
937: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
938: #endif
1.1 rittera 939:
940: ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr);
941:
942: /* Decode the parameter into a string. */
943: bzero(val, sizeof(val));
944: *status = ndis_decode_parm(block, parm, val);
945: if (*status != NDIS_STATUS_SUCCESS) {
946: free(keystr, M_DEVBUF);
947: return;
948: }
949:
950: /* See if the key already exists. */
951:
1.2 rittera 952: #if __FreeBSD_version < 502113 || !defined(__FreeBSD__)
1.1 rittera 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;
963: }
964: }
965:
966: /* Not found, add a new key with the specified value. */
967: ndis_add_sysctl(sc, keystr, "(dynamically set key)",
968: val, CTLFLAG_RW);
969:
970: free(keystr, M_DEVBUF);
971: *status = NDIS_STATUS_SUCCESS;
972: return;
1.2 rittera 973: #else /* __FreeBSD__ */
974: *status = NDIS_STATUS_SUCCESS;
975: return;
976: #endif
1.1 rittera 977: }
978:
979: __stdcall static void
1.6 christos 980: NdisCloseConfiguration(ndis_handle cfg)
1.1 rittera 981: {
982: return;
983: }
984:
985: /*
986: * Initialize a Windows spinlock.
987: */
988: __stdcall static void
1.15 ! dsl 989: NdisAllocateSpinLock(ndis_spin_lock *lock)
1.1 rittera 990: {
991: KeInitializeSpinLock(&lock->nsl_spinlock);
992: lock->nsl_kirql = 0;
993:
994: return;
995: }
996:
997: /*
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.)
1004: */
1005: __stdcall static void
1.6 christos 1006: NdisFreeSpinLock(ndis_spin_lock *lock)
1.1 rittera 1007: {
1008: #ifdef notdef
1009: KeInitializeSpinLock(&lock->nsl_spinlock);
1010: lock->nsl_kirql = 0;
1011: #endif
1012: return;
1013: }
1014:
1015: /*
1016: * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
1017: */
1018:
1019: __stdcall static void
1.15 ! dsl 1020: NdisAcquireSpinLock(ndis_spin_lock *lock)
1.1 rittera 1021: {
1022: KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
1023: return;
1024: }
1025:
1026: /*
1027: * Release a spinlock from IRQL == DISPATCH_LEVEL.
1028: */
1029:
1030: __stdcall static void
1.15 ! dsl 1031: NdisReleaseSpinLock(ndis_spin_lock *lock)
1.1 rittera 1032: {
1033: KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
1034: return;
1035: }
1036:
1037: /*
1038: * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
1039: */
1040: __stdcall static void
1.15 ! dsl 1041: NdisDprAcquireSpinLock(ndis_spin_lock *lock)
1.1 rittera 1042: {
1043: KeAcquireSpinLockAtDpcLevel(&lock->nsl_spinlock);
1044: return;
1045: }
1046:
1047: /*
1048: * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
1049: */
1050: __stdcall static void
1.15 ! dsl 1051: NdisDprReleaseSpinLock(ndis_spin_lock *lock)
1.1 rittera 1052: {
1053: KeReleaseSpinLockFromDpcLevel(&lock->nsl_spinlock);
1054: return;
1055: }
1056:
1057: __stdcall static uint32_t
1.5 christos 1058: NdisReadPciSlotInformation(
1059: ndis_handle adapter,
1.6 christos 1060: uint32_t slot,
1.5 christos 1061: uint32_t offset,
1062: void *buf,
1063: uint32_t len)
1.1 rittera 1064: {
1065: ndis_miniport_block *block;
1066: int i;
1.3 rittera 1067: #ifdef __FreeBSD__
1068: char *dest;
1069: #else
1070: pcireg_t *dest;
1071: #endif
1072:
1073: /* PN(NdisReadPciSlotInformation) */
1.1 rittera 1074: device_t dev;
1.3 rittera 1075: struct ndis_softc *sc;
1.1 rittera 1076:
1077: block = (ndis_miniport_block *)adapter;
1078: dest = buf;
1079: if (block == NULL)
1080: return(0);
1081:
1.2 rittera 1082: dev = (device_t)block->nmb_physdeviceobj->do_devext;
1.3 rittera 1083: #ifdef __FreeBSD__
1084: sc = device_get_softc(dev);
1085: #else /* __NetBSD__ */
1086: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1087: #endif
1.1 rittera 1088:
1089: /*
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.
1102: */
1103:
1.3 rittera 1104: #ifdef __FreeBSD__
1.1 rittera 1105: for (i = 0; i < len; i++) {
1.3 rittera 1106: #else /* __NetBSD__ */
1107: for (i = 0; i < len/4; i += 4) {
1108: #endif
1.1 rittera 1109: DELAY(1);
1.3 rittera 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
1115:
1.1 rittera 1116: }
1117:
1118: return(len);
1119: }
1120:
1121: __stdcall static uint32_t
1.5 christos 1122: NdisWritePciSlotInformation(
1123: ndis_handle adapter,
1.6 christos 1124: uint32_t slot,
1.5 christos 1125: uint32_t offset,
1126: void *buf,
1127: uint32_t len)
1.1 rittera 1128: {
1129: ndis_miniport_block *block;
1130: int i;
1.3 rittera 1131: #ifdef __FreeBSD__
1132: char *dest;
1133: #else
1134: pcireg_t *dest;
1135: #endif
1136:
1.1 rittera 1137: device_t dev;
1138:
1.3 rittera 1139: /* PN(NdisWritePciSlotInformation) */
1140:
1.1 rittera 1141: block = (ndis_miniport_block *)adapter;
1142: dest = buf;
1.3 rittera 1143: struct ndis_softc *sc;
1144:
1.1 rittera 1145:
1146: if (block == NULL)
1147: return(0);
1148:
1149: dev = block->nmb_physdeviceobj->do_devext;
1.3 rittera 1150: #ifdef __FreeBSD__
1151: sc = device_get_softc(dev);
1152: #else /* __NetBSD__ */
1153: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1154: #endif
1155:
1156: #ifdef __FreeBSD__
1.1 rittera 1157: for (i = 0; i < len; i++) {
1.3 rittera 1158: #else /* __NetBSD__ */
1159: for (i = 0; i < len/4; i++) {
1160: #endif
1.1 rittera 1161: DELAY(1);
1.3 rittera 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
1168:
1.1 rittera 1169: }
1170:
1171: return(len);
1172: }
1173:
1174: /*
1175: * The errorlog routine uses a variable argument list, so we
1176: * have to declare it this way.
1177: */
1178: #define ERRMSGLEN 512
1179: static void
1180: NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code,
1181: uint32_t numerrors, ...)
1182: {
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;
1191:
1.3 rittera 1192: PN(NdisWriteErrorLogEntry)
1193:
1.1 rittera 1194: block = (ndis_miniport_block *)adapter;
1195: dev = block->nmb_physdeviceobj->do_devext;
1196: drv = block->nmb_physdeviceobj->do_drvobj;
1197:
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;
1205: }
1.3 rittera 1206:
1.4 rittera 1207: printf ("%s: NDIS ERROR: %x (%s)\n", dev->dv_xname, code,
1208: str == NULL ? "unknown error" : str);
1209: printf ("%s: NDIS NUMERRORS: %x\n", dev->dv_xname, numerrors);
1.1 rittera 1210:
1211: va_start(ap, numerrors);
1212: for (i = 0; i < numerrors; i++)
1.4 rittera 1213: printf ("%s: argptr: %p\n",
1214: dev->dv_xname,
1215: va_arg(ap, void *));
1216:
1.1 rittera 1217: va_end(ap);
1218:
1219: return;
1220: }
1221:
1222: static void
1.15 ! dsl 1223: ndis_map_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1.1 rittera 1224: {
1225: struct ndis_map_arg *ctx;
1226: int i;
1227:
1.3 rittera 1228: PN(ndis_map_cb)
1229:
1.1 rittera 1230: if (error)
1231: return;
1232:
1233: ctx = arg;
1234:
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;
1238: }
1239:
1240: ctx->nma_cnt = nseg;
1241:
1242: return;
1243: }
1244:
1245: __stdcall static void
1.15 ! dsl 1246: NdisMStartBufferPhysicalMapping(ndis_handle adapter, ndis_buffer *buf, uint32_t mapreg, uint8_t writedev, ndis_paddr_unit *addrarray, uint32_t *arraysize)
1.1 rittera 1247: {
1248: ndis_miniport_block *block;
1249: struct ndis_softc *sc;
1250: struct ndis_map_arg nma;
1251: bus_dmamap_t map;
1252: int error;
1253:
1.3 rittera 1254: PN(NdisMStartBufferPhysicalMapping)
1255:
1.1 rittera 1256: if (adapter == NULL)
1257: return;
1258:
1259: block = (ndis_miniport_block *)adapter;
1.3 rittera 1260: #ifdef __FreeBSD__
1.1 rittera 1261: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1262: #else /* __NetBSD__ */
1263: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1264: #endif
1.1 rittera 1265:
1266: if (mapreg > sc->ndis_mmapcnt)
1267: return;
1268:
1269: map = sc->ndis_mmaps[mapreg];
1270: nma.nma_fraglist = addrarray;
1271:
1.2 rittera 1272: #ifdef __FreeBSD__
1.1 rittera 1273: error = bus_dmamap_load(sc->ndis_mtag, map,
1274: MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf), ndis_map_cb,
1275: (void *)&nma, BUS_DMA_NOWAIT);
1.2 rittera 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
1.1 rittera 1283: if (error)
1284: return;
1285:
1.2 rittera 1286: #ifdef __FreeBSD__
1.1 rittera 1287: bus_dmamap_sync(sc->ndis_mtag, map,
1288: writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
1.2 rittera 1289: #else
1290: bus_dmamap_sync(sc->ndis_mtag, map, 0, map->dm_mapsize,
1291: writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
1292: #endif
1.1 rittera 1293: *arraysize = nma.nma_cnt;
1294:
1295: return;
1296: }
1297:
1298: __stdcall static void
1.5 christos 1299: NdisMCompleteBufferPhysicalMapping(
1300: ndis_handle adapter,
1.6 christos 1301: ndis_buffer *buf,
1.5 christos 1302: uint32_t mapreg)
1.1 rittera 1303: {
1304: ndis_miniport_block *block;
1305: struct ndis_softc *sc;
1306: bus_dmamap_t map;
1307:
1.3 rittera 1308: PN(NdisMCompleteBufferPhysicalMapping)
1309:
1.1 rittera 1310: if (adapter == NULL)
1311: return;
1312:
1313: block = (ndis_miniport_block *)adapter;
1.3 rittera 1314: #ifdef __FreeBSD__
1.1 rittera 1315: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1316: #else /* __NetBSD__ */
1317: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1318: #endif
1.1 rittera 1319:
1320: if (mapreg > sc->ndis_mmapcnt)
1321: return;
1322:
1323: map = sc->ndis_mmaps[mapreg];
1324:
1.2 rittera 1325: #ifdef __FreeBSD__
1.1 rittera 1326: bus_dmamap_sync(sc->ndis_mtag, map,
1327: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1.2 rittera 1328: #else
1329: bus_dmamap_sync(sc->ndis_mtag, map, 0, map->dm_mapsize,
1330: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1331: #endif
1.1 rittera 1332: bus_dmamap_unload(sc->ndis_mtag, map);
1333:
1334: return;
1335: }
1336:
1337: /*
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.
1341: */
1342:
1343: __stdcall static void
1.15 ! dsl 1344: NdisInitializeTimer(ndis_timer *timer, ndis_timer_function func, void *ctx)
1.1 rittera 1345: {
1346: KeInitializeTimer(&timer->nt_ktimer);
1347: KeInitializeDpc(&timer->nt_kdpc, func, ctx);
1348:
1349: return;
1350: }
1351:
1352: __stdcall static void
1.15 ! dsl 1353: ndis_timercall(kdpc *dpc, ndis_miniport_timer *timer, void *sysarg1, void *sysarg2)
1.1 rittera 1354: {
1.3 rittera 1355: //PN(ndis_timercall)
1356:
1.1 rittera 1357: /*
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().
1362: */
1363: if (NDIS_SERIALIZED(timer->nmt_block))
1364: KeAcquireSpinLockAtDpcLevel(&timer->nmt_block->nmb_lock);
1365:
1366: MSCALL4(timer->nmt_timerfunc, dpc, timer->nmt_timerctx,
1367: sysarg1, sysarg2);
1368:
1369: if (NDIS_SERIALIZED(timer->nmt_block))
1370: KeReleaseSpinLockFromDpcLevel(&timer->nmt_block->nmb_lock);
1371:
1372: return;
1373: }
1374:
1375: /*
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.
1391: */
1.3 rittera 1392:
1393: /* Just to test out how much memory is wasted*/
1394: int ndis_num_timers_allocated = 0;
1395:
1.1 rittera 1396: __stdcall static void
1.15 ! dsl 1397: NdisMInitializeTimer(ndis_miniport_timer *timer, ndis_handle handle, ndis_timer_function func, void *ctx)
1.1 rittera 1398: {
1399: /* Save the driver's funcptr and context */
1400:
1.3 rittera 1401: PN(NdisMInitializeTimer)
1402:
1.1 rittera 1403: timer->nmt_timerfunc = func;
1404: timer->nmt_timerctx = ctx;
1405: timer->nmt_block = handle;
1.3 rittera 1406:
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++;
1414: }
1415: #endif
1.1 rittera 1416:
1417: /*
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.
1422: */
1423: KeInitializeTimer(&timer->nmt_ktimer);
1424: KeInitializeDpc(&timer->nmt_kdpc,
1425: ndis_findwrap((funcptr)ndis_timercall), timer);
1426:
1427: return;
1428: }
1429:
1430: /*
1431: * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
1432: * but the former is just a macro wrapper around the latter.
1433: */
1434: __stdcall static void
1.15 ! dsl 1435: NdisSetTimer(ndis_timer *timer, uint32_t msecs)
1.1 rittera 1436: {
1.3 rittera 1437: PN(NdisSetTimer)
1.1 rittera 1438: /*
1439: * KeSetTimer() wants the period in
1440: * hundred nanosecond intervals.
1.3 rittera 1441: */
1.1 rittera 1442: KeSetTimer(&timer->nt_ktimer,
1.3 rittera 1443: ((int64_t)msecs * -10000), &timer->nt_kdpc);
1.1 rittera 1444:
1445: return;
1446: }
1447:
1448: __stdcall static void
1.15 ! dsl 1449: NdisMSetPeriodicTimer(ndis_miniport_timer *timer, uint32_t msecs)
1.1 rittera 1450: {
1.3 rittera 1451: PN(NdisMSetPeriodicTimer)
1452:
1.1 rittera 1453: KeSetTimerEx(&timer->nmt_ktimer,
1454: ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc);
1455:
1456: return;
1457: }
1458:
1459: /*
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.
1464: */
1465:
1466: __stdcall static void
1.15 ! dsl 1467: NdisMCancelTimer(ndis_timer *timer, uint8_t *cancelled)
1.1 rittera 1468: {
1.3 rittera 1469: PN(NdisMCancelTimer)
1.1 rittera 1470: *cancelled = KeCancelTimer(&timer->nt_ktimer);
1471:
1472: return;
1473: }
1474:
1475: __stdcall static void
1.15 ! dsl 1476: NdisMQueryAdapterResources(ndis_status *status, ndis_handle adapter, ndis_resource_list *list, uint32_t *buflen)
1.1 rittera 1477: {
1478: ndis_miniport_block *block;
1479: struct ndis_softc *sc;
1480: int rsclen;
1481:
1.3 rittera 1482: PN(NdisMQueryAdapterResources)
1483:
1.1 rittera 1484: block = (ndis_miniport_block *)adapter;
1.3 rittera 1485:
1486: #ifdef __FreeBSD__
1.1 rittera 1487: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1488: #else /* __NetBSD__ */
1489: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1490: #endif
1.1 rittera 1491:
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;
1498: }
1499:
1.3 rittera 1500: #ifdef __FreeBSD__
1.1 rittera 1501: bcopy((char *)block->nmb_rlist, (char *)list, rsclen);
1.3 rittera 1502: #else /* __NetBSD__ */
1503: memcpy(list, block->nmb_rlist, rsclen);
1504: #endif
1505:
1.1 rittera 1506: *status = NDIS_STATUS_SUCCESS;
1507:
1508: return;
1509: }
1510:
1511: __stdcall static ndis_status
1.5 christos 1512: NdisMRegisterIoPortRange(
1513: void **offset,
1514: ndis_handle adapter,
1.6 christos 1515: uint32_t port,
1.5 christos 1516: uint32_t numports)
1.1 rittera 1517: {
1518: struct ndis_miniport_block *block;
1519: struct ndis_softc *sc;
1520:
1.3 rittera 1521: PN(NdisMRegisterIoPortRange)
1522:
1.1 rittera 1523: if (adapter == NULL)
1524: return(NDIS_STATUS_FAILURE);
1525:
1526: block = (ndis_miniport_block *)adapter;
1.3 rittera 1527: #ifdef __FreeBSD__
1.1 rittera 1528: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1529: #else /* __NetBSD__ */
1530: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1531: #endif
1.1 rittera 1532:
1.3 rittera 1533: #ifdef __FreeBSD__
1.1 rittera 1534: if (sc->ndis_res_io == NULL)
1.3 rittera 1535: #else
1536: if (sc->ndis_res_io == NULL && sc->ndis_iftype != PCMCIABus)
1537: #endif
1.1 rittera 1538: return(NDIS_STATUS_FAILURE);
1539:
1540: /* Don't let the device map more ports than we have. */
1.3 rittera 1541: #ifdef __FreeBSD__
1.1 rittera 1542: if (rman_get_size(sc->ndis_res_io) < numports)
1.3 rittera 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
1.1 rittera 1547: return(NDIS_STATUS_INVALID_LENGTH);
1.3 rittera 1548:
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);
1562: }
1563: #endif /* __NetBSD__ */
1.1 rittera 1564:
1565: return(NDIS_STATUS_SUCCESS);
1566: }
1567:
1568: __stdcall static void
1.5 christos 1569: NdisMDeregisterIoPortRange(
1.6 christos 1570: ndis_handle adapter,
1571: uint32_t port,
1572: uint32_t numports,
1573: void *offset)
1.1 rittera 1574: {
1575: return;
1576: }
1577:
1578: __stdcall static void
1.15 ! dsl 1579: NdisReadNetworkAddress(ndis_status *status, void **addr, uint32_t *addrlen, ndis_handle adapter)
1.1 rittera 1580: {
1581: struct ndis_softc *sc;
1582: ndis_miniport_block *block;
1583: uint8_t empty[] = { 0, 0, 0, 0, 0, 0 };
1.3 rittera 1584:
1585: PN(NdisReadNetworkAddress)
1.1 rittera 1586:
1587: block = (ndis_miniport_block *)adapter;
1.3 rittera 1588: #ifdef __FreeBSD__
1.1 rittera 1589: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1590: #else /* __NetBSD__ */
1591: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1592: #endif
1.1 rittera 1593:
1.2 rittera 1594: #ifdef __FreeBSD__
1.1 rittera 1595: if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1.2 rittera 1596: #else
1.9 dyoung 1597: if (bcmp(CLLADDR(sc->arpcom.ec_if.if_sadl),
1.2 rittera 1598: empty, ETHER_ADDR_LEN) == 0)
1599: #endif
1600:
1.1 rittera 1601: *status = NDIS_STATUS_FAILURE;
1602: else {
1.2 rittera 1603: #ifdef __FreeBSD__
1.1 rittera 1604: *addr = sc->arpcom.ac_enaddr;
1.2 rittera 1605: #else
1.12 dyoung 1606: memcpy(sc->ndis_mac, CLLADDR(sc->arpcom.ec_if.if_sadl),
1607: ETHER_ADDR_LEN);
1608: *addr = sc->ndis_mac;
1.2 rittera 1609: #endif
1.1 rittera 1610: *addrlen = ETHER_ADDR_LEN;
1611: *status = NDIS_STATUS_SUCCESS;
1612: }
1613:
1614: return;
1615: }
1616:
1617: __stdcall static ndis_status
1.5 christos 1618: NdisQueryMapRegisterCount(
1.6 christos 1619: uint32_t bustype,
1.5 christos 1620: uint32_t *cnt)
1.1 rittera 1621: {
1.3 rittera 1622: PN(NdisQueryMapRegisterCount)
1623:
1.1 rittera 1624: *cnt = 8192;
1625: return(NDIS_STATUS_SUCCESS);
1626: }
1627:
1628: __stdcall static ndis_status
1.5 christos 1629: NdisMAllocateMapRegisters(
1630: ndis_handle adapter,
1.6 christos 1631: uint32_t dmachannel,
1632: uint8_t dmasize,
1.5 christos 1633: uint32_t physmapneeded,
1634: uint32_t maxmap)
1.1 rittera 1635: {
1636: struct ndis_softc *sc;
1637: ndis_miniport_block *block;
1.3 rittera 1638: #ifdef __FreeBSD__
1639: int error;
1640: #endif
1641: int i, nseg = NDIS_MAXSEG;
1.1 rittera 1642:
1.3 rittera 1643: PN(NdisMAllocateMapRegisters)
1644:
1.1 rittera 1645: block = (ndis_miniport_block *)adapter;
1.3 rittera 1646: #ifdef __FreeBSD__
1.1 rittera 1647: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1648: #else /* __NetBSD__ */
1649: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1650: #endif
1.1 rittera 1651:
1652: sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1653: M_DEVBUF, M_NOWAIT|M_ZERO);
1654:
1655: if (sc->ndis_mmaps == NULL)
1656: return(NDIS_STATUS_RESOURCES);
1657:
1.2 rittera 1658: #ifdef __FreeBSD__
1.1 rittera 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);
1663:
1664: if (error) {
1665: free(sc->ndis_mmaps, M_DEVBUF);
1666: return(NDIS_STATUS_RESOURCES);
1667: }
1.2 rittera 1668: #else
1669: sc->ndis_mtag = sc->ndis_parent_tag;
1670: #endif
1.3 rittera 1671:
1672: for (i = 0; i < physmapneeded; i++) {
1.2 rittera 1673: #ifdef __FreeBSD__
1.1 rittera 1674: bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1.2 rittera 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
1.3 rittera 1680: }
1.1 rittera 1681:
1682: sc->ndis_mmapcnt = physmapneeded;
1683:
1684: return(NDIS_STATUS_SUCCESS);
1685: }
1686:
1687: __stdcall static void
1.15 ! dsl 1688: NdisMFreeMapRegisters(ndis_handle adapter)
1.1 rittera 1689: {
1690: struct ndis_softc *sc;
1691: ndis_miniport_block *block;
1692: int i;
1693:
1.3 rittera 1694: PN(NdisMFreeMapRegisters)
1695:
1.1 rittera 1696: block = (ndis_miniport_block *)adapter;
1.3 rittera 1697: #ifdef __FreeBSD__
1.1 rittera 1698: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1699: #else /* __NetBSD__ */
1700: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1701: #endif
1.1 rittera 1702:
1703: for (i = 0; i < sc->ndis_mmapcnt; i++)
1704: bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1705:
1706: free(sc->ndis_mmaps, M_DEVBUF);
1707:
1.3 rittera 1708: #ifdef __FreeBSD__
1.1 rittera 1709: bus_dma_tag_destroy(sc->ndis_mtag);
1.3 rittera 1710: #endif
1.1 rittera 1711:
1712: return;
1713: }
1714:
1715: static void
1.15 ! dsl 1716: ndis_mapshared_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
1.1 rittera 1717: {
1718: ndis_physaddr *p;
1719:
1.3 rittera 1720: /* PN(ndis_mapshared_cb) */
1721:
1.1 rittera 1722: if (error || nseg > 1)
1723: return;
1724:
1725: p = arg;
1726:
1727: p->np_quad = segs[0].ds_addr;
1728:
1729: return;
1730: }
1731:
1732: /*
1733: * This maps to bus_dmamem_alloc().
1734: */
1735: __stdcall static void
1.5 christos 1736: NdisMAllocateSharedMemory(
1737: ndis_handle adapter,
1738: uint32_t len,
1.6 christos 1739: uint8_t cached,
1.5 christos 1740: void **vaddr,
1741: ndis_physaddr *paddr)
1.1 rittera 1742: {
1743: ndis_miniport_block *block;
1744: struct ndis_softc *sc;
1745: struct ndis_shmem *sh;
1746: int error;
1.3 rittera 1747: #ifdef __NetBSD__
1.2 rittera 1748: bus_dma_segment_t segs;
1.3 rittera 1749: int nsegs;
1.2 rittera 1750: #endif
1.1 rittera 1751:
1.3 rittera 1752: /* PN(NdisMAllocateSharedMemory) */
1753:
1.1 rittera 1754: if (adapter == NULL)
1755: return;
1756:
1757: block = (ndis_miniport_block *)adapter;
1.3 rittera 1758: #ifdef __FreeBSD__
1.1 rittera 1759: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1760: #else /* __NetBSD__ */
1761: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1762: #endif
1.1 rittera 1763:
1764: sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1765: if (sh == NULL)
1766: return;
1767:
1768: /*
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.
1780: */
1781:
1.2 rittera 1782: #ifdef __FreeBSD__
1.1 rittera 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);
1787:
1788: if (error) {
1789: free(sh, M_DEVBUF);
1790: return;
1791: }
1792:
1793: error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1794: BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1795:
1796: if (error) {
1797: bus_dma_tag_destroy(sh->ndis_stag);
1798: free(sh, M_DEVBUF);
1799: return;
1800: }
1801:
1802: error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1803: len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1804:
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;
1810: }
1.2 rittera 1811: #else
1.3 rittera 1812: sh->ndis_stag = sc->ndis_parent_tag;
1813:
1.2 rittera 1814: error = bus_dmamem_alloc(sh->ndis_stag, len, 64, 0,
1815: &segs, 1, &nsegs, BUS_DMA_NOWAIT);
1.3 rittera 1816:
1.2 rittera 1817: if (error) {
1818: printf("bus_dmamem_alloc failed(1)\n");
1819: return;
1820: }
1821:
1822: error = bus_dmamem_map(sh->ndis_stag, &segs, nsegs,
1.7 christos 1823: len, /*(void **)&vaddr*/ (void **)vaddr, BUS_DMA_NOWAIT);
1.2 rittera 1824:
1.3 rittera 1825: /* printf("*vaddr = %x\n", (unsigned int)*vaddr); */
1826:
1.2 rittera 1827: if (error) {
1828: printf("bus_dmamem_alloc failed(2)\n");
1829: /* XXX free */
1830: return;
1831: }
1832:
1833: error = bus_dmamap_create(sh->ndis_stag, len, nsegs,
1834: BUS_SPACE_MAXSIZE_32BIT, 0,
1.3 rittera 1835: BUS_DMA_ALLOCNOW, &sh->ndis_smap);
1.2 rittera 1836:
1837: if (error) {
1838: printf("bus_dmamem_alloc failed(3)\n");
1839: /* XXX free, unmap */
1840: return;
1841: }
1.3 rittera 1842:
1843: error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, /*vaddr*/ *vaddr,
1.2 rittera 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);
1848:
1849: if (error) {
1850: printf("bus_dmamem_alloc failed(3)\n");
1851: /* XXX free, unmap, destroy */
1852: return;
1853: }
1854: #endif
1.1 rittera 1855:
1856: sh->ndis_saddr = *vaddr;
1857: sh->ndis_next = sc->ndis_shlist;
1858: sc->ndis_shlist = sh;
1859:
1860: return;
1861: }
1862:
1863: struct ndis_allocwork {
1864: ndis_handle na_adapter;
1865: uint32_t na_len;
1866: uint8_t na_cached;
1867: void *na_ctx;
1868: };
1869:
1870: static void
1.15 ! dsl 1871: ndis_asyncmem_complete(void *arg)
1.1 rittera 1872: {
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;
1879:
1880: w = arg;
1881: block = (ndis_miniport_block *)w->na_adapter;
1.3 rittera 1882: #ifdef __FreeBSD__
1.1 rittera 1883: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1884: #else /* __NetBSD__ */
1885: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1886: #endif
1887:
1888: PN(ndis_asyncmem_complete)
1.1 rittera 1889:
1890: vaddr = NULL;
1891: paddr.np_quad = 0;
1892:
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);
1897:
1898: free(arg, M_DEVBUF);
1899:
1900: return;
1901: }
1902:
1903: __stdcall static ndis_status
1.15 ! dsl 1904: NdisMAllocateSharedMemoryAsync(ndis_handle adapter, uint32_t len, uint8_t cached, void *ctx)
1.1 rittera 1905: {
1906: struct ndis_allocwork *w;
1907:
1.3 rittera 1908: PN(NdisMAllocateSharedMemoryAsync)
1909:
1.1 rittera 1910: if (adapter == NULL)
1911: return(NDIS_STATUS_FAILURE);
1912:
1913: w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT);
1914:
1915: if (w == NULL)
1916: return(NDIS_STATUS_FAILURE);
1917:
1918: w->na_adapter = adapter;
1919: w->na_cached = cached;
1920: w->na_len = len;
1921: w->na_ctx = ctx;
1922:
1923: /*
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.
1929: */
1930: ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI);
1931:
1932: return(NDIS_STATUS_PENDING);
1933: }
1934:
1935: __stdcall static void
1.5 christos 1936: NdisMFreeSharedMemory(
1937: ndis_handle adapter,
1.6 christos 1938: uint32_t len,
1939: uint8_t cached,
1.5 christos 1940: void *vaddr,
1.6 christos 1941: ndis_physaddr paddr)
1.1 rittera 1942: {
1943: ndis_miniport_block *block;
1944: struct ndis_softc *sc;
1945: struct ndis_shmem *sh, *prev;
1946:
1.3 rittera 1947: PN(NdisMFreeSharedMemory)
1948:
1.1 rittera 1949: if (vaddr == NULL || adapter == NULL)
1950: return;
1951:
1952: block = (ndis_miniport_block *)adapter;
1.3 rittera 1953: #ifdef __FreeBSD__
1.1 rittera 1954: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1955: #else /* __NetBSD__ */
1956: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1957: #endif
1.1 rittera 1958: sh = prev = sc->ndis_shlist;
1959:
1960: /* Sanity check: is list empty? */
1961:
1962: if (sh == NULL)
1963: return;
1964:
1965: while (sh) {
1966: if (sh->ndis_saddr == vaddr)
1967: break;
1968: prev = sh;
1969: sh = sh->ndis_next;
1970: }
1971:
1972: bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1.2 rittera 1973: #ifdef __FreeBSD__
1.1 rittera 1974: bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1.3 rittera 1975: bus_dma_tag_destroy(sh->ndis_stag);
1.2 rittera 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
1.1 rittera 1981: if (sh == sc->ndis_shlist)
1982: sc->ndis_shlist = sh->ndis_next;
1983: else
1984: prev->ndis_next = sh->ndis_next;
1985:
1986: free(sh, M_DEVBUF);
1987:
1988: return;
1989: }
1990:
1991: __stdcall static ndis_status
1.5 christos 1992: NdisMMapIoSpace(
1993: void **vaddr,
1994: ndis_handle adapter,
1995: ndis_physaddr paddr,
1.6 christos 1996: uint32_t len)
1.1 rittera 1997: {
1998: ndis_miniport_block *block;
1999: struct ndis_softc *sc;
2000:
1.3 rittera 2001: PN(NdisMMapIoSpace)
2002:
1.1 rittera 2003: if (adapter == NULL)
2004: return(NDIS_STATUS_FAILURE);
2005:
2006: block = (ndis_miniport_block *)adapter;
1.3 rittera 2007: #ifdef __FreeBSD__
1.1 rittera 2008: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2009: #else /* __NetBSD__ */
2010: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2011: #endif
2012:
1.1 rittera 2013:
1.3 rittera 2014: #ifdef __FreeBSD__
1.1 rittera 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);
1.3 rittera 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);
2038: /*
2039: *vaddr = bus_space_vaddr(sc->ndis_res_mem->res_tag,
2040: sc->ndis_res_mem->res_handle);
2041: */
2042: #endif
1.1 rittera 2043:
2044: return(NDIS_STATUS_SUCCESS);
2045: }
2046:
2047: __stdcall static void
1.5 christos 2048: NdisMUnmapIoSpace(
1.6 christos 2049: ndis_handle adapter,
2050: void *vaddr,
2051: uint32_t len)
1.1 rittera 2052: {
2053: return;
2054: }
2055:
2056: __stdcall static uint32_t
2057: NdisGetCacheFillSize(void)
2058: {
2059: return(128);
2060: }
2061:
2062: __stdcall static uint32_t
1.6 christos 2063: NdisMGetDmaAlignment(ndis_handle handle)
1.1 rittera 2064: {
2065: return(128);
2066: }
2067:
2068: /*
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.
2077: */
2078:
2079: __stdcall static ndis_status
1.5 christos 2080: NdisMInitializeScatterGatherDma(
2081: ndis_handle adapter,
1.6 christos 2082: uint8_t is64,
2083: uint32_t maxphysmap)
1.1 rittera 2084: {
2085: struct ndis_softc *sc;
2086: ndis_miniport_block *block;
1.3 rittera 2087: #ifdef __FreeBSD__
1.1 rittera 2088: int error;
1.3 rittera 2089: #endif
2090:
2091: PN(NdisMInitializeScatterGatherDma)
1.1 rittera 2092:
2093: if (adapter == NULL)
2094: return(NDIS_STATUS_FAILURE);
2095: block = (ndis_miniport_block *)adapter;
1.3 rittera 2096: #ifdef __FreeBSD__
1.1 rittera 2097: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2098: #else /* __NetBSD__ */
2099: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2100: #endif
1.1 rittera 2101:
2102: /* Don't do this twice. */
2103: if (sc->ndis_sc == 1)
2104: return(NDIS_STATUS_SUCCESS);
2105:
1.3 rittera 2106: #ifdef __FreeBSD__
1.1 rittera 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);
1.3 rittera 2111: #else /* __NetBSD__ */
2112: /* TODO: Is this correct to just use the parent tag? */
2113: sc->ndis_ttag = sc->ndis_parent_tag;
2114: #endif
1.1 rittera 2115:
2116: sc->ndis_sc = 1;
2117:
2118: return(NDIS_STATUS_SUCCESS);
2119: }
2120:
2121: __stdcall void
1.15 ! dsl 2122: NdisAllocatePacketPool(ndis_status *status, ndis_handle *pool, uint32_t descnum, uint32_t protrsvdlen)
1.1 rittera 2123: {
2124: ndis_packet *cur;
2125: int i;
1.3 rittera 2126:
2127: PN(NdisAllocatePacketPool)
1.1 rittera 2128:
2129: *pool = malloc((sizeof(ndis_packet) + protrsvdlen) *
2130: ((descnum + NDIS_POOL_EXTRA) + 1),
2131: M_DEVBUF, M_NOWAIT|M_ZERO);
2132:
2133: if (*pool == NULL) {
2134: *status = NDIS_STATUS_RESOURCES;
2135: return;
2136: }
2137:
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++;
2145: }
2146:
2147: *status = NDIS_STATUS_SUCCESS;
2148: return;
2149: }
2150:
2151: __stdcall void
1.15 ! dsl 2152: NdisAllocatePacketPoolEx(ndis_status *status, ndis_handle *pool, uint32_t descnum, uint32_t oflowdescnum, uint32_t protrsvdlen)
1.1 rittera 2153: {
2154: return(NdisAllocatePacketPool(status, pool,
2155: descnum + oflowdescnum, protrsvdlen));
2156: }
2157:
2158: __stdcall uint32_t
1.15 ! dsl 2159: NdisPacketPoolUsage(ndis_handle pool)
1.1 rittera 2160: {
2161: ndis_packet *head;
2162: uint8_t irql;
2163: uint32_t cnt;
2164:
2165: head = (ndis_packet *)pool;
2166: KeAcquireSpinLock(&head->np_lock, &irql);
2167: cnt = head->np_private.npp_count;
2168: KeReleaseSpinLock(&head->np_lock, irql);
2169:
2170: return(cnt);
2171: }
2172:
2173: __stdcall void
1.15 ! dsl 2174: NdisFreePacketPool(ndis_handle pool)
1.1 rittera 2175: {
2176: ndis_packet *head;
2177: uint8_t irql;
2178:
2179: head = pool;
2180:
2181: /* Mark this pool as 'going away.' */
2182:
2183: KeAcquireSpinLock(&head->np_lock, &irql);
2184: head->np_private.npp_totlen = 1;
2185:
2186: /* If there are no buffers loaned out, destroy the pool. */
2187:
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);
2194: }
2195:
2196: return;
2197: }
2198:
2199: __stdcall void
1.15 ! dsl 2200: NdisAllocatePacket(ndis_status *status, ndis_packet **packet, ndis_handle pool)
1.1 rittera 2201: {
2202: ndis_packet *head, *pkt;
2203: uint8_t irql;
2204:
1.3 rittera 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.
2209: */
2210: if(pool == NULL) {
2211: *status = NDIS_STATUS_FAILURE;
2212: return;
2213: }
2214: #endif
2215:
1.1 rittera 2216: head = (ndis_packet *)pool;
2217: KeAcquireSpinLock(&head->np_lock, &irql);
2218:
2219: if (head->np_private.npp_flags != 0x1) {
2220: *status = NDIS_STATUS_FAILURE;
2221: KeReleaseSpinLock(&head->np_lock, irql);
2222: return;
2223: }
2224:
2225: /*
2226: * If this pool is marked as 'going away' don't allocate any
2227: * more packets out of it.
2228: */
2229:
2230: if (head->np_private.npp_totlen) {
2231: *status = NDIS_STATUS_FAILURE;
2232: KeReleaseSpinLock(&head->np_lock, irql);
2233: return;
2234: }
2235:
2236: pkt = (ndis_packet *)head->np_private.npp_head;
2237:
2238: if (pkt == NULL) {
2239: *status = NDIS_STATUS_RESOURCES;
2240: KeReleaseSpinLock(&head->np_lock, irql);
2241: return;
2242: }
2243:
2244: head->np_private.npp_head = pkt->np_private.npp_head;
2245:
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;
2249:
2250: /* Set the oob offset pointer. Lots of things expect this. */
2251: pkt->np_private.npp_packetooboffset =
2252: offsetof(ndis_packet, np_oob);
2253:
2254: /*
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.
2259: */
2260: pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
2261: pkt->np_private.npp_validcounts = FALSE;
2262:
2263: *packet = pkt;
2264:
2265: head->np_private.npp_count++;
2266: *status = NDIS_STATUS_SUCCESS;
2267:
2268: KeReleaseSpinLock(&head->np_lock, irql);
2269:
2270: return;
2271: }
2272:
2273: __stdcall void
1.15 ! dsl 2274: NdisFreePacket(ndis_packet *packet)
1.1 rittera 2275: {
2276: ndis_packet *head;
2277: uint8_t irql;
2278:
2279: if (packet == NULL || packet->np_private.npp_pool == NULL)
2280: return;
2281:
2282: head = packet->np_private.npp_pool;
2283: KeAcquireSpinLock(&head->np_lock, &irql);
2284:
2285: if (head->np_private.npp_flags != 0x1) {
2286: KeReleaseSpinLock(&head->np_lock, irql);
2287: return;
2288: }
2289:
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--;
2293:
2294: /*
2295: * If the pool has been marked for deletion and there are
2296: * no more packets outstanding, nuke the pool.
2297: */
2298:
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);
2304:
2305: return;
2306: }
2307:
2308: __stdcall static void
1.15 ! dsl 2309: NdisUnchainBufferAtFront(ndis_packet *packet, ndis_buffer **buf)
1.1 rittera 2310: {
2311: ndis_packet_private *priv;
2312:
2313: if (packet == NULL || buf == NULL)
2314: return;
2315:
2316: priv = &packet->np_private;
2317:
2318: priv->npp_validcounts = FALSE;
2319:
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;
2326: }
2327:
2328: return;
2329: }
2330:
2331: __stdcall static void
1.15 ! dsl 2332: NdisUnchainBufferAtBack(ndis_packet *packet, ndis_buffer **buf)
1.1 rittera 2333: {
2334: ndis_packet_private *priv;
2335: ndis_buffer *tmp;
2336:
2337: if (packet == NULL || buf == NULL)
2338: return;
2339:
2340: priv = &packet->np_private;
2341:
2342: priv->npp_validcounts = FALSE;
2343:
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;
2354: }
2355:
2356: return;
2357: }
2358:
2359: /*
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.
2370: */
2371:
2372: __stdcall static void
1.5 christos 2373: NdisAllocateBufferPool(
2374: ndis_status *status,
2375: ndis_handle *pool,
1.6 christos 2376: uint32_t descnum)
1.1 rittera 2377: {
2378: /*
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.
2382: */
2383:
2384: *pool = NonPagedPool;
2385: *status = NDIS_STATUS_SUCCESS;
2386: return;
2387: }
2388:
2389: __stdcall static void
1.6 christos 2390: NdisFreeBufferPool(ndis_handle pool)
1.1 rittera 2391: {
2392: return;
2393: }
2394:
2395: __stdcall static void
1.5 christos 2396: NdisAllocateBuffer(
2397: ndis_status *status,
2398: ndis_buffer **buffer,
1.6 christos 2399: ndis_handle pool,
1.5 christos 2400: void *vaddr,
2401: uint32_t len)
1.1 rittera 2402: {
2403: ndis_buffer *buf;
2404:
2405: buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL);
2406: if (buf == NULL) {
2407: *status = NDIS_STATUS_RESOURCES;
2408: return;
2409: }
2410:
2411: *buffer = buf;
2412: *status = NDIS_STATUS_SUCCESS;
2413:
2414: return;
2415: }
2416:
2417: __stdcall static void
1.15 ! dsl 2418: NdisFreeBuffer(ndis_buffer *buf)
1.1 rittera 2419: {
2420: IoFreeMdl(buf);
2421: return;
2422: }
2423:
2424: /* Aw c'mon. */
2425:
2426: __stdcall static uint32_t
1.15 ! dsl 2427: NdisBufferLength(ndis_buffer *buf)
1.1 rittera 2428: {
2429: return(MmGetMdlByteCount(buf));
2430: }
2431:
2432: /*
2433: * Get the virtual address and length of a buffer.
2434: * Note: the vaddr argument is optional.
2435: */
2436:
2437: __stdcall static void
1.15 ! dsl 2438: NdisQueryBuffer(ndis_buffer *buf, void **vaddr, uint32_t *len)
1.1 rittera 2439: {
2440: if (vaddr != NULL)
2441: *vaddr = MmGetMdlVirtualAddress(buf);
2442: *len = MmGetMdlByteCount(buf);
2443:
2444: return;
2445: }
2446:
2447: /* Same as above -- we don't care about the priority. */
2448:
2449: __stdcall static void
1.5 christos 2450: NdisQueryBufferSafe(
2451: ndis_buffer *buf,
2452: void **vaddr,
2453: uint32_t *len,
1.6 christos 2454: uint32_t prio)
1.1 rittera 2455: {
2456: if (vaddr != NULL)
2457: *vaddr = MmGetMdlVirtualAddress(buf);
2458: *len = MmGetMdlByteCount(buf);
2459:
2460: return;
2461: }
2462:
2463: /* Damnit Microsoft!! How many ways can you do the same thing?! */
2464:
2465: __stdcall static void *
1.15 ! dsl 2466: NdisBufferVirtualAddress(ndis_buffer *buf)
1.1 rittera 2467: {
2468: return(MmGetMdlVirtualAddress(buf));
2469: }
2470:
2471: __stdcall static void *
1.5 christos 2472: NdisBufferVirtualAddressSafe(
2473: ndis_buffer *buf,
1.6 christos 2474: uint32_t prio)
1.1 rittera 2475: {
2476: return(MmGetMdlVirtualAddress(buf));
2477: }
2478:
2479: __stdcall static void
1.15 ! dsl 2480: NdisAdjustBufferLength(ndis_buffer *buf, int len)
1.1 rittera 2481: {
2482: MmGetMdlByteCount(buf) = len;
2483:
2484: return;
2485: }
2486:
2487: __stdcall static uint32_t
1.15 ! dsl 2488: NdisInterlockedIncrement(uint32_t *addend)
1.1 rittera 2489: {
1.11 ad 2490: atomic_inc_32(addend);
1.1 rittera 2491: return(*addend);
2492: }
2493:
2494: __stdcall static uint32_t
1.15 ! dsl 2495: NdisInterlockedDecrement(uint32_t *addend)
1.1 rittera 2496: {
1.11 ad 2497: atomic_dec_32(addend);
1.1 rittera 2498: return(*addend);
2499: }
2500:
2501: __stdcall static void
1.15 ! dsl 2502: NdisInitializeEvent(ndis_event *event)
1.1 rittera 2503: {
2504: /*
2505: * NDIS events are always notification
2506: * events, and should be initialized to the
2507: * not signaled state.
2508: */
2509:
2510: KeInitializeEvent(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE);
2511: return;
2512: }
2513:
2514: __stdcall static void
1.15 ! dsl 2515: NdisSetEvent(ndis_event *event)
1.1 rittera 2516: {
2517: KeSetEvent(&event->ne_event, 0, 0);
2518: return;
2519: }
2520:
2521: __stdcall static void
1.15 ! dsl 2522: NdisResetEvent(ndis_event *event)
1.1 rittera 2523: {
2524: KeResetEvent(&event->ne_event);
2525: return;
2526: }
2527:
2528: __stdcall static uint8_t
1.15 ! dsl 2529: NdisWaitEvent(ndis_event *event, uint32_t msecs)
1.1 rittera 2530: {
2531: int64_t duetime;
2532: uint32_t rval;
2533:
2534: duetime = ((int64_t)msecs * -10000);
2535:
2536: rval = KeWaitForSingleObject((nt_dispatch_header *)event,
2537: 0, 0, TRUE, msecs ? &duetime : NULL);
2538:
2539: if (rval == STATUS_TIMEOUT)
2540: return(FALSE);
2541:
2542: return(TRUE);
2543: }
2544:
2545: __stdcall static ndis_status
1.15 ! dsl 2546: NdisUnicodeStringToAnsiString(ndis_ansi_string *dstr, ndis_unicode_string *sstr)
1.1 rittera 2547: {
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);
2555: }
2556:
2557: __stdcall static ndis_status
1.15 ! dsl 2558: NdisAnsiStringToUnicodeString(ndis_unicode_string *dstr, ndis_ansi_string *sstr)
1.1 rittera 2559: {
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);
2571: }
2572: dstr->us_len = dstr->us_maxlen = sstr->nas_len * 2;
2573: free(str, M_DEVBUF);
2574: return (NDIS_STATUS_SUCCESS);
2575: }
2576:
2577: __stdcall static ndis_status
1.5 christos 2578: NdisMPciAssignResources(
2579: ndis_handle adapter,
1.6 christos 2580: uint32_t slot,
1.5 christos 2581: ndis_resource_list **list)
1.1 rittera 2582: {
2583: ndis_miniport_block *block;
2584:
2585: if (adapter == NULL || list == NULL)
2586: return (NDIS_STATUS_FAILURE);
2587:
2588: block = (ndis_miniport_block *)adapter;
2589: *list = block->nmb_rlist;
2590:
2591: return (NDIS_STATUS_SUCCESS);
2592: }
2593:
2594: __stdcall static ndis_status
1.5 christos 2595: NdisMRegisterInterrupt(
2596: ndis_miniport_interrupt *intr,
2597: ndis_handle adapter,
1.6 christos 2598: uint32_t ivec,
2599: uint32_t ilevel,
1.5 christos 2600: uint8_t reqisr,
2601: uint8_t shared,
1.6 christos 2602: ndis_interrupt_mode imode)
1.1 rittera 2603: {
2604: ndis_miniport_block *block;
2605:
2606: block = adapter;
2607:
2608: intr->ni_block = adapter;
2609: intr->ni_isrreq = reqisr;
2610: intr->ni_shared = shared;
2611: block->nmb_interrupt = intr;
2612:
2613: KeInitializeSpinLock(&intr->ni_dpccountlock);
2614:
2615: return(NDIS_STATUS_SUCCESS);
2616: }
2617:
2618: __stdcall static void
1.6 christos 2619: NdisMDeregisterInterrupt(ndis_miniport_interrupt *intr)
1.1 rittera 2620: {
2621: return;
2622: }
2623:
2624: __stdcall static void
1.15 ! dsl 2625: NdisMRegisterAdapterShutdownHandler(ndis_handle adapter, void *shutdownctx, ndis_shutdown_handler shutdownfunc)
1.1 rittera 2626: {
2627: ndis_miniport_block *block;
2628: ndis_miniport_characteristics *chars;
2629: struct ndis_softc *sc;
2630:
2631: if (adapter == NULL)
2632: return;
2633:
2634: block = (ndis_miniport_block *)adapter;
1.3 rittera 2635: #ifdef __FreeBSD__
1.1 rittera 2636: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2637: #else /* __NetBSD__ */
2638: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2639: #endif
1.1 rittera 2640: chars = sc->ndis_chars;
2641:
2642: chars->nmc_shutdown_handler = shutdownfunc;
2643: chars->nmc_rsvd0 = shutdownctx;
2644:
2645: return;
2646: }
2647:
2648: __stdcall static void
1.15 ! dsl 2649: NdisMDeregisterAdapterShutdownHandler(ndis_handle adapter)
1.1 rittera 2650: {
2651: ndis_miniport_block *block;
2652: ndis_miniport_characteristics *chars;
2653: struct ndis_softc *sc;
2654:
2655: if (adapter == NULL)
2656: return;
2657:
2658: block = (ndis_miniport_block *)adapter;
1.3 rittera 2659: #ifdef __FreeBSD__
1.1 rittera 2660: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2661: #else /* __NetBSD__ */
2662: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2663: #endif
1.1 rittera 2664: chars = sc->ndis_chars;
2665:
2666: chars->nmc_shutdown_handler = NULL;
2667: chars->nmc_rsvd0 = NULL;
2668:
2669: return;
2670: }
2671:
2672: __stdcall static uint32_t
1.15 ! dsl 2673: NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *buf)
1.1 rittera 2674: {
2675: if (buf == NULL)
2676: return(0);
2677: if (MmGetMdlByteCount(buf) == 0)
2678: return(1);
2679: return(SPAN_PAGES(MmGetMdlVirtualAddress(buf),
2680: MmGetMdlByteCount(buf)));
2681: }
2682:
2683: __stdcall static void
1.15 ! dsl 2684: NdisGetBufferPhysicalArraySize(ndis_buffer *buf, uint32_t *pages)
1.1 rittera 2685: {
2686: if (buf == NULL)
2687: return;
2688:
2689: *pages = NDIS_BUFFER_TO_SPAN_PAGES(buf);
2690: return;
2691: }
2692:
2693: __stdcall static void
1.15 ! dsl 2694: NdisQueryBufferOffset(ndis_buffer *buf, uint32_t *off, uint32_t *len)
1.1 rittera 2695: {
2696: if (buf == NULL)
2697: return;
2698:
2699: *off = MmGetMdlByteOffset(buf);
2700: *len = MmGetMdlByteCount(buf);
2701:
2702: return;
2703: }
2704:
2705: __stdcall static void
1.15 ! dsl 2706: NdisMSleep(uint32_t usecs)
1.1 rittera 2707: {
2708: struct timeval tv;
2709:
2710: tv.tv_sec = 0;
2711: tv.tv_usec = usecs;
2712:
1.2 rittera 2713: #ifdef __FreeBSD__
1.1 rittera 2714: ndis_thsuspend(curthread->td_proc, NULL, tvtohz(&tv));
1.2 rittera 2715: #else
2716: ndis_thsuspend(curproc, NULL, tvtohz(&tv));
2717: #endif
1.1 rittera 2718:
2719: return;
2720: }
2721:
2722: __stdcall static uint32_t
1.15 ! dsl 2723: NdisReadPcmciaAttributeMemory(ndis_handle handle, uint32_t offset, void *buf, uint32_t len)
1.1 rittera 2724: {
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;
2731:
2732: if (handle == NULL)
2733: return(0);
2734:
2735: block = (ndis_miniport_block *)handle;
1.3 rittera 2736: #ifdef __FreeBSD__
1.1 rittera 2737: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2738: #else /* __NetBSD__ */
2739: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2740: #endif
1.1 rittera 2741: dest = buf;
2742:
1.3 rittera 2743: #ifdef __FreeBSD__
2744: bh = rman_get_bushandle(sc->ndis_res_am);
2745: bt = rman_get_bustag(sc->ndis_res_am);
2746:
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;
2755: }
2756: #endif
1.1 rittera 2757:
2758: for (i = 0; i < len; i++)
2759: dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2);
2760:
2761: return(i);
2762: }
2763:
2764: __stdcall static uint32_t
1.15 ! dsl 2765: NdisWritePcmciaAttributeMemory(ndis_handle handle, uint32_t offset, void *buf, uint32_t len)
1.1 rittera 2766: {
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;
2773:
2774: if (handle == NULL)
2775: return(0);
2776:
2777: block = (ndis_miniport_block *)handle;
1.3 rittera 2778: #ifdef __FreeBSD__
1.1 rittera 2779: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2780: #else /* __NetBSD__ */
2781: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2782: #endif
1.1 rittera 2783: src = buf;
1.3 rittera 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;
2795: }
2796: #endif
1.1 rittera 2797:
2798: for (i = 0; i < len; i++)
2799: bus_space_write_1(bt, bh, (offset + i) * 2, src[i]);
2800:
2801: return(i);
2802: }
2803:
2804: __stdcall static list_entry *
1.15 ! dsl 2805: NdisInterlockedInsertHeadList(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
1.1 rittera 2806: {
2807: list_entry *flink;
2808:
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);
2816:
2817: return(flink);
2818: }
2819:
2820: __stdcall static list_entry *
1.15 ! dsl 2821: NdisInterlockedRemoveHeadList(list_entry *head, ndis_spin_lock *lock)
1.1 rittera 2822: {
2823: list_entry *flink;
2824: list_entry *entry;
2825:
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);
2832:
2833: return(entry);
2834: }
2835:
2836: __stdcall static list_entry *
1.15 ! dsl 2837: NdisInterlockedInsertTailList(list_entry *head, list_entry *entry, ndis_spin_lock *lock)
1.1 rittera 2838: {
2839: list_entry *blink;
2840:
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);
2848:
2849: return(blink);
2850: }
2851:
2852: __stdcall static uint8_t
1.15 ! dsl 2853: NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *intr, void *syncfunc, void *syncctx)
1.1 rittera 2854: {
2855: __stdcall uint8_t (*sync)(void *);
2856: uint8_t rval;
2857: uint8_t irql;
2858:
2859: if (syncfunc == NULL || syncctx == NULL)
2860: return(0);
2861:
2862: sync = syncfunc;
2863: KeAcquireSpinLock(&intr->ni_dpccountlock, &irql);
2864: rval = MSCALL1(sync, syncctx);
2865: KeReleaseSpinLock(&intr->ni_dpccountlock, irql);
2866:
2867: return(rval);
2868: }
2869:
2870: /*
2871: * Return the number of 100 nanosecond intervals since
2872: * January 1, 1601. (?!?!)
2873: */
2874: __stdcall static void
1.15 ! dsl 2875: NdisGetCurrentSystemTime(uint64_t *tval)
1.1 rittera 2876: {
2877: struct timespec ts;
1.3 rittera 2878: #ifdef __NetBSD__
2879: struct timeval tv;
2880:
2881: microtime(&tv);
2882: TIMEVAL_TO_TIMESPEC(&tv,&ts);
2883: #else
2884: nanotime(&ts);
2885: #endif
1.1 rittera 2886:
2887: *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
1.2 rittera 2888: (uint64_t)11644473600ULL;
1.1 rittera 2889:
2890: return;
2891: }
2892:
2893: /*
2894: * Return the number of milliseconds since the system booted.
2895: */
2896: __stdcall static void
1.15 ! dsl 2897: NdisGetSystemUpTime(uint32_t *tval)
1.1 rittera 2898: {
2899: *tval = (ticks * hz) / 1000;
2900:
2901: return;
2902: }
2903:
2904: __stdcall static void
1.15 ! dsl 2905: NdisInitializeString(ndis_unicode_string *dst, char *src)
1.1 rittera 2906: {
2907: ndis_unicode_string *u;
2908:
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;
2915: }
2916:
2917: __stdcall static void
1.15 ! dsl 2918: NdisFreeString(ndis_unicode_string *str)
1.1 rittera 2919: {
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;
2926: }
2927:
2928: __stdcall static ndis_status
1.6 christos 2929: NdisMRemoveMiniport(ndis_handle *adapter)
1.1 rittera 2930: {
2931: return(NDIS_STATUS_SUCCESS);
2932: }
2933:
2934: __stdcall static void
1.15 ! dsl 2935: NdisInitAnsiString(ndis_ansi_string *dst, char *src)
1.1 rittera 2936: {
2937: ndis_ansi_string *a;
2938:
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);
2948: }
2949:
2950: return;
2951: }
2952:
2953: __stdcall static void
1.15 ! dsl 2954: NdisInitUnicodeString(ndis_unicode_string *dst, uint16_t *src)
1.1 rittera 2955: {
2956: ndis_unicode_string *u;
2957: int i;
2958:
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;
2971: }
2972:
2973: return;
2974: }
2975:
1.5 christos 2976: __stdcall static void NdisMGetDeviceProperty(
2977: ndis_handle adapter,
2978: device_object **phydevobj,
2979: device_object **funcdevobj,
2980: device_object **nextdevobj,
1.6 christos 2981: cm_resource_list *resources,
2982: cm_resource_list *transresources)
1.1 rittera 2983: {
2984: ndis_miniport_block *block;
2985:
2986: block = (ndis_miniport_block *)adapter;
2987:
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;
2994:
2995: return;
2996: }
2997:
2998: __stdcall static void
1.15 ! dsl 2999: NdisGetFirstBufferFromPacket(ndis_packet *packet, ndis_buffer **buf, void **firstva, uint32_t *firstlen, uint32_t *totlen)
1.1 rittera 3000: {
3001: ndis_buffer *tmp;
3002:
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);
3013: }
3014:
3015: return;
3016: }
3017:
3018: __stdcall static void
1.5 christos 3019: NdisGetFirstBufferFromPacketSafe(
3020: ndis_packet *packet,
3021: ndis_buffer **buf,
3022: void **firstva,
3023: uint32_t *firstlen,
3024: uint32_t *totlen,
1.6 christos 3025: uint32_t prio)
1.1 rittera 3026: {
3027: NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen);
3028: }
3029:
1.2 rittera 3030: #ifdef __FreeBSD__
1.1 rittera 3031: static int
1.15 ! dsl 3032: ndis_find_sym(linker_file_t lf, char *filename, char *suffix, void * *sym)
1.1 rittera 3033: {
3034: char *fullsym;
3035: char *suf;
3036: int i;
3037:
3038: fullsym = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
3039: if (fullsym == NULL)
3040: return(ENOMEM);
3041:
3042: bzero(fullsym, MAXPATHLEN);
3043: strncpy(fullsym, filename, MAXPATHLEN);
3044: if (strlen(filename) < 4) {
3045: ExFreePool(fullsym);
3046: return(EINVAL);
3047: }
3048:
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';
3053:
3054: for (i = 0; i < strlen(fullsym); i++) {
3055: if (fullsym[i] == '.')
3056: fullsym[i] = '_';
3057: else
3058: fullsym[i] = tolower(fullsym[i]);
3059: }
3060: strcat(fullsym, suffix);
3061: *sym = linker_file_lookup_symbol(lf, fullsym, 0);
3062: ExFreePool(fullsym);
3063: if (*sym == 0)
3064: return(ENOENT);
3065:
3066: return(0);
3067: }
3068:
3069: /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
3070: __stdcall static void
1.15 ! dsl 3071: NdisOpenFile(ndis_status *status, ndis_handle *filehandle, uint32_t *filelength, ndis_unicode_string *filename, ndis_physaddr highestaddr)
1.1 rittera 3072: {
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;
1.8 dogcow 3082: void *kldstart, *kldend;
1.1 rittera 3083:
3084: ndis_unicode_to_ascii(filename->us_buf,
3085: filename->us_len, &afilename);
3086:
3087: fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0);
3088: if (fh == NULL) {
3089: *status = NDIS_STATUS_RESOURCES;
3090: return;
3091: }
3092:
3093: /*
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.
3110: */
3111:
3112: /*
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.
3117: */
3118:
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;
3133: }
3134:
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;
3144: }
3145:
3146: path = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
3147: if (path == NULL) {
3148: ExFreePool(fh);
3149: *status = NDIS_STATUS_RESOURCES;
3150: return;
3151: }
3152:
3153: snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename);
3154: free(afilename, M_DEVBUF);
3155:
3156: mtx_lock(&Giant);
3157:
3158: /* Some threads don't have a current working directory. */
3159:
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;
3164:
3165: NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
3166:
3167: flags = FREAD;
3168: error = vn_open(&nd, &flags, 0, -1);
3169: if (error) {
3170: mtx_unlock(&Giant);
3171: *status = NDIS_STATUS_FILE_NOT_FOUND;
3172: ExFreePool(fh);
3173: printf("NDIS: open file %s failed: %d\n", path, error);
3174: ExFreePool(path);
3175: return;
3176: }
3177:
3178: ExFreePool(path);
3179:
3180: NDFREE(&nd, NDF_ONLY_PNBUF);
3181:
3182: /* Get the file size. */
3183: VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td);
3184: VOP_UNLOCK(nd.ni_vp, 0, td);
3185: mtx_unlock(&Giant);
3186:
3187: fh->nf_vp = nd.ni_vp;
3188: fh->nf_map = NULL;
3189: fh->nf_type = NDIS_FH_TYPE_VFS;
3190: *filehandle = fh;
3191: *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
3192: *status = NDIS_STATUS_SUCCESS;
3193:
3194: return;
3195: }
3196:
3197: __stdcall static void
1.15 ! dsl 3198: NdisMapFile(ndis_status *status, void **mappedbuffer, ndis_handle filehandle)
1.1 rittera 3199: {
3200: ndis_fh *fh;
3201: struct thread *td = curthread;
3202: linker_file_t lf;
1.7 christos 3203: void * kldstart;
1.1 rittera 3204: int error, resid;
3205:
3206: if (filehandle == NULL) {
3207: *status = NDIS_STATUS_FAILURE;
3208: return;
3209: }
3210:
3211: fh = (ndis_fh *)filehandle;
3212:
3213: if (fh->nf_vp == NULL) {
3214: *status = NDIS_STATUS_FAILURE;
3215: return;
3216: }
3217:
3218: if (fh->nf_map != NULL) {
3219: *status = NDIS_STATUS_ALREADY_MAPPED;
3220: return;
3221: }
3222:
3223: if (fh->nf_type == NDIS_FH_TYPE_MODULE) {
3224: lf = fh->nf_vp;
3225: if (ndis_find_sym(lf, lf->filename, "_start", &kldstart)) {
3226: *status = NDIS_STATUS_FAILURE;
3227: return;
3228: }
3229: fh->nf_map = kldstart;
3230: *status = NDIS_STATUS_SUCCESS;
3231: *mappedbuffer = fh->nf_map;
3232: return;
3233: }
3234:
3235: fh->nf_map = ExAllocatePoolWithTag(NonPagedPool, fh->nf_maplen, 0);
3236:
3237: if (fh->nf_map == NULL) {
3238: *status = NDIS_STATUS_RESOURCES;
3239: return;
3240: }
3241:
3242: mtx_lock(&Giant);
3243: error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
3244: UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td);
3245: mtx_unlock(&Giant);
3246:
3247: if (error)
3248: *status = NDIS_STATUS_FAILURE;
3249: else {
3250: *status = NDIS_STATUS_SUCCESS;
3251: *mappedbuffer = fh->nf_map;
3252: }
3253:
3254: return;
3255: }
3256:
3257: __stdcall static void
1.15 ! dsl 3258: NdisUnmapFile(ndis_handle filehandle)
1.1 rittera 3259: {
3260: ndis_fh *fh;
3261: fh = (ndis_fh *)filehandle;
3262:
3263: if (fh->nf_map == NULL)
3264: return;
3265:
3266: if (fh->nf_type == NDIS_FH_TYPE_VFS)
3267: ExFreePool(fh->nf_map);
3268: fh->nf_map = NULL;
3269:
3270: return;
3271: }
3272:
3273: __stdcall static void
1.15 ! dsl 3274: NdisCloseFile(ndis_handle filehandle)
1.1 rittera 3275: {
3276: struct thread *td = curthread;
3277: ndis_fh *fh;
3278:
3279: if (filehandle == NULL)
3280: return;
3281:
3282: fh = (ndis_fh *)filehandle;
3283: if (fh->nf_map != NULL) {
3284: if (fh->nf_type == NDIS_FH_TYPE_VFS)
3285: ExFreePool(fh->nf_map);
3286: fh->nf_map = NULL;
3287: }
3288:
3289: if (fh->nf_vp == NULL)
3290: return;
3291:
3292: if (fh->nf_type == NDIS_FH_TYPE_VFS) {
3293: mtx_lock(&Giant);
3294: vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
3295: mtx_unlock(&Giant);
3296: }
3297:
3298: fh->nf_vp = NULL;
3299: ExFreePool(fh);
3300:
3301: return;
3302: }
1.2 rittera 3303: #endif /* __FreeBSD__ */
1.1 rittera 3304: __stdcall static uint8_t
3305: NdisSystemProcessorCount()
3306: {
1.2 rittera 3307: #ifdef __FreeBSD__
1.1 rittera 3308: return(mp_ncpus);
1.2 rittera 3309: #else
3310: return(nprocs);
3311: #endif
1.1 rittera 3312: }
3313:
3314: typedef void (*ndis_statusdone_handler)(ndis_handle);
3315: typedef void (*ndis_status_handler)(ndis_handle, ndis_status,
3316: void *, uint32_t);
3317:
3318: __stdcall static void
1.15 ! dsl 3319: NdisMIndicateStatusComplete(ndis_handle adapter)
1.1 rittera 3320: {
3321: ndis_miniport_block *block;
3322: __stdcall ndis_statusdone_handler statusdonefunc;
3323:
3324: block = (ndis_miniport_block *)adapter;
3325: statusdonefunc = block->nmb_statusdone_func;
3326:
3327: MSCALL1(statusdonefunc, adapter);
3328: return;
3329: }
3330:
3331: __stdcall static void
1.15 ! dsl 3332: NdisMIndicateStatus(ndis_handle adapter, ndis_status status, void *sbuf, uint32_t slen)
1.1 rittera 3333: {
3334: ndis_miniport_block *block;
3335: __stdcall ndis_status_handler statusfunc;
3336:
3337: block = (ndis_miniport_block *)adapter;
3338: statusfunc = block->nmb_status_func;
3339:
3340: MSCALL4(statusfunc, adapter, status, sbuf, slen);
3341: return;
3342: }
3343:
3344: static void
1.15 ! dsl 3345: ndis_workfunc(void *ctx)
1.1 rittera 3346: {
3347: ndis_work_item *work;
3348: __stdcall ndis_proc workfunc;
3349:
3350: work = ctx;
3351: workfunc = work->nwi_func;
3352: MSCALL2(workfunc, work, work->nwi_ctx);
3353: return;
3354: }
3355:
3356: __stdcall static ndis_status
1.15 ! dsl 3357: NdisScheduleWorkItem(ndis_work_item *work)
1.1 rittera 3358: {
3359: ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
3360: return(NDIS_STATUS_SUCCESS);
3361: }
3362:
3363: __stdcall static void
1.15 ! dsl 3364: NdisCopyFromPacketToPacket(ndis_packet *dpkt, uint32_t doff, uint32_t reqlen, ndis_packet *spkt, uint32_t soff, uint32_t *cpylen)
1.1 rittera 3365: {
3366: ndis_buffer *src, *dst;
3367: char *sptr, *dptr;
3368: int resid, copied, len, scnt, dcnt;
3369:
3370: *cpylen = 0;
3371:
3372: src = spkt->np_private.npp_head;
3373: dst = dpkt->np_private.npp_head;
3374:
3375: sptr = MmGetMdlVirtualAddress(src);
3376: dptr = MmGetMdlVirtualAddress(dst);
3377: scnt = MmGetMdlByteCount(src);
3378: dcnt = MmGetMdlByteCount(dst);
3379:
3380: while (soff) {
3381: if (MmGetMdlByteCount(src) > soff) {
3382: sptr += soff;
3383: scnt = MmGetMdlByteCount(src)- soff;
3384: break;
3385: }
3386: soff -= MmGetMdlByteCount(src);
3387: src = src->mdl_next;
3388: if (src == NULL)
3389: return;
3390: sptr = MmGetMdlVirtualAddress(src);
3391: }
3392:
3393: while (doff) {
3394: if (MmGetMdlByteCount(dst) > doff) {
3395: dptr += doff;
3396: dcnt = MmGetMdlByteCount(dst) - doff;
3397: break;
3398: }
3399: doff -= MmGetMdlByteCount(dst);
3400: dst = dst->mdl_next;
3401: if (dst == NULL)
3402: return;
3403: dptr = MmGetMdlVirtualAddress(dst);
3404: }
3405:
3406: resid = reqlen;
3407: copied = 0;
3408:
3409: while(1) {
3410: if (resid < scnt)
3411: len = resid;
3412: else
3413: len = scnt;
3414: if (dcnt < len)
3415: len = dcnt;
3416:
3417: bcopy(sptr, dptr, len);
3418:
3419: copied += len;
3420: resid -= len;
3421: if (resid == 0)
3422: break;
3423:
3424: dcnt -= len;
3425: if (dcnt == 0) {
3426: dst = dst->mdl_next;
3427: if (dst == NULL)
3428: break;
3429: dptr = MmGetMdlVirtualAddress(dst);
3430: dcnt = MmGetMdlByteCount(dst);
3431: }
3432:
3433: scnt -= len;
3434: if (scnt == 0) {
3435: src = src->mdl_next;
3436: if (src == NULL)
3437: break;
3438: sptr = MmGetMdlVirtualAddress(src);
3439: scnt = MmGetMdlByteCount(src);
3440: }
3441: }
3442:
3443: *cpylen = copied;
3444: return;
3445: }
3446:
3447: __stdcall static void
1.5 christos 3448: NdisCopyFromPacketToPacketSafe(
3449: ndis_packet *dpkt,
3450: uint32_t doff,
3451: uint32_t reqlen,
3452: ndis_packet *spkt,
3453: uint32_t soff,
3454: uint32_t *cpylen,
1.6 christos 3455: uint32_t prio)
1.1 rittera 3456: {
3457: NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen);
3458: return;
3459: }
3460:
3461: __stdcall static ndis_status
1.5 christos 3462: NdisMRegisterDevice(
3463: ndis_handle handle,
1.6 christos 3464: ndis_unicode_string *devname,
3465: ndis_unicode_string *symname,
3466: driver_dispatch *majorfuncs[],
1.5 christos 3467: void **devobj,
3468: ndis_handle *devhandle)
1.1 rittera 3469: {
3470: ndis_miniport_block *block;
3471:
3472: block = (ndis_miniport_block *)handle;
3473: *devobj = block->nmb_deviceobj;
3474: *devhandle = handle;
3475:
3476: return(NDIS_STATUS_SUCCESS);
3477: }
3478:
3479: __stdcall static ndis_status
1.6 christos 3480: NdisMDeregisterDevice(ndis_handle handle)
1.1 rittera 3481: {
3482: return(NDIS_STATUS_SUCCESS);
3483: }
3484:
3485: __stdcall static ndis_status
1.15 ! dsl 3486: NdisMQueryAdapterInstanceName(ndis_unicode_string *name, ndis_handle handle)
1.1 rittera 3487: {
3488: ndis_miniport_block *block;
3489: device_t dev;
3490:
3491: block = (ndis_miniport_block *)handle;
3492: dev = block->nmb_physdeviceobj->do_devext;
3493:
3494: ndis_ascii_to_unicode(__DECONST(char *,
3495: device_get_nameunit(dev)), &name->us_buf);
3496: name->us_len = strlen(device_get_nameunit(dev)) * 2;
3497:
3498: return(NDIS_STATUS_SUCCESS);
3499: }
3500:
3501: __stdcall static void
1.5 christos 3502: NdisMRegisterUnloadHandler(
1.6 christos 3503: ndis_handle handle,
3504: void *func)
1.1 rittera 3505: {
3506: return;
3507: }
3508:
3509: __stdcall static void
3510: dummy()
3511: {
3512: printf ("NDIS dummy called...\n");
3513: return;
3514: }
3515:
3516: image_patch_table ndis_functbl[] = {
3517: IMPORT_FUNC(NdisCopyFromPacketToPacket),
3518: IMPORT_FUNC(NdisCopyFromPacketToPacketSafe),
3519: IMPORT_FUNC(NdisScheduleWorkItem),
3520: IMPORT_FUNC(NdisMIndicateStatusComplete),
3521: IMPORT_FUNC(NdisMIndicateStatus),
3522: IMPORT_FUNC(NdisSystemProcessorCount),
3523: IMPORT_FUNC(NdisUnchainBufferAtBack),
3524: IMPORT_FUNC(NdisGetFirstBufferFromPacket),
3525: IMPORT_FUNC(NdisGetFirstBufferFromPacketSafe),
3526: IMPORT_FUNC(NdisGetBufferPhysicalArraySize),
3527: IMPORT_FUNC(NdisMGetDeviceProperty),
3528: IMPORT_FUNC(NdisInitAnsiString),
3529: IMPORT_FUNC(NdisInitUnicodeString),
3530: IMPORT_FUNC(NdisWriteConfiguration),
3531: IMPORT_FUNC(NdisAnsiStringToUnicodeString),
3532: IMPORT_FUNC(NdisTerminateWrapper),
3533: IMPORT_FUNC(NdisOpenConfigurationKeyByName),
3534: IMPORT_FUNC(NdisOpenConfigurationKeyByIndex),
3535: IMPORT_FUNC(NdisMRemoveMiniport),
3536: IMPORT_FUNC(NdisInitializeString),
3537: IMPORT_FUNC(NdisFreeString),
3538: IMPORT_FUNC(NdisGetCurrentSystemTime),
3539: IMPORT_FUNC(NdisGetSystemUpTime),
3540: IMPORT_FUNC(NdisMSynchronizeWithInterrupt),
3541: IMPORT_FUNC(NdisMAllocateSharedMemoryAsync),
3542: IMPORT_FUNC(NdisInterlockedInsertHeadList),
3543: IMPORT_FUNC(NdisInterlockedInsertTailList),
3544: IMPORT_FUNC(NdisInterlockedRemoveHeadList),
3545: IMPORT_FUNC(NdisInitializeWrapper),
3546: IMPORT_FUNC(NdisMRegisterMiniport),
3547: IMPORT_FUNC(NdisAllocateMemoryWithTag),
3548: IMPORT_FUNC(NdisAllocateMemory),
3549: IMPORT_FUNC(NdisMSetAttributesEx),
3550: IMPORT_FUNC(NdisCloseConfiguration),
3551: IMPORT_FUNC(NdisReadConfiguration),
3552: IMPORT_FUNC(NdisOpenConfiguration),
3553: IMPORT_FUNC(NdisAcquireSpinLock),
3554: IMPORT_FUNC(NdisReleaseSpinLock),
3555: IMPORT_FUNC(NdisDprAcquireSpinLock),
3556: IMPORT_FUNC(NdisDprReleaseSpinLock),
3557: IMPORT_FUNC(NdisAllocateSpinLock),
3558: IMPORT_FUNC(NdisFreeSpinLock),
3559: IMPORT_FUNC(NdisFreeMemory),
3560: IMPORT_FUNC(NdisReadPciSlotInformation),
3561: IMPORT_FUNC(NdisWritePciSlotInformation),
3562: IMPORT_FUNC_MAP(NdisImmediateReadPciSlotInformation,
3563: NdisReadPciSlotInformation),
3564: IMPORT_FUNC_MAP(NdisImmediateWritePciSlotInformation,
3565: NdisWritePciSlotInformation),
3566: IMPORT_FUNC(NdisWriteErrorLogEntry),
3567: IMPORT_FUNC(NdisMStartBufferPhysicalMapping),
3568: IMPORT_FUNC(NdisMCompleteBufferPhysicalMapping),
3569: IMPORT_FUNC(NdisMInitializeTimer),
3570: IMPORT_FUNC(NdisInitializeTimer),
3571: IMPORT_FUNC(NdisSetTimer),
3572: IMPORT_FUNC(NdisMCancelTimer),
3573: IMPORT_FUNC_MAP(NdisCancelTimer, NdisMCancelTimer),
3574: IMPORT_FUNC(NdisMSetPeriodicTimer),
3575: IMPORT_FUNC(NdisMQueryAdapterResources),
3576: IMPORT_FUNC(NdisMRegisterIoPortRange),
3577: IMPORT_FUNC(NdisMDeregisterIoPortRange),
3578: IMPORT_FUNC(NdisReadNetworkAddress),
3579: IMPORT_FUNC(NdisQueryMapRegisterCount),
3580: IMPORT_FUNC(NdisMAllocateMapRegisters),
3581: IMPORT_FUNC(NdisMFreeMapRegisters),
3582: IMPORT_FUNC(NdisMAllocateSharedMemory),
3583: IMPORT_FUNC(NdisMMapIoSpace),
3584: IMPORT_FUNC(NdisMUnmapIoSpace),
3585: IMPORT_FUNC(NdisGetCacheFillSize),
3586: IMPORT_FUNC(NdisMGetDmaAlignment),
3587: IMPORT_FUNC(NdisMInitializeScatterGatherDma),
3588: IMPORT_FUNC(NdisAllocatePacketPool),
3589: IMPORT_FUNC(NdisAllocatePacketPoolEx),
3590: IMPORT_FUNC(NdisAllocatePacket),
3591: IMPORT_FUNC(NdisFreePacket),
3592: IMPORT_FUNC(NdisFreePacketPool),
3593: IMPORT_FUNC_MAP(NdisDprAllocatePacket, NdisAllocatePacket),
3594: IMPORT_FUNC_MAP(NdisDprFreePacket, NdisFreePacket),
3595: IMPORT_FUNC(NdisAllocateBufferPool),
3596: IMPORT_FUNC(NdisAllocateBuffer),
3597: IMPORT_FUNC(NdisQueryBuffer),
3598: IMPORT_FUNC(NdisQueryBufferSafe),
3599: IMPORT_FUNC(NdisBufferVirtualAddress),
3600: IMPORT_FUNC(NdisBufferVirtualAddressSafe),
3601: IMPORT_FUNC(NdisBufferLength),
3602: IMPORT_FUNC(NdisFreeBuffer),
3603: IMPORT_FUNC(NdisFreeBufferPool),
3604: IMPORT_FUNC(NdisInterlockedIncrement),
3605: IMPORT_FUNC(NdisInterlockedDecrement),
3606: IMPORT_FUNC(NdisInitializeEvent),
3607: IMPORT_FUNC(NdisSetEvent),
3608: IMPORT_FUNC(NdisResetEvent),
3609: IMPORT_FUNC(NdisWaitEvent),
3610: IMPORT_FUNC(NdisUnicodeStringToAnsiString),
3611: IMPORT_FUNC(NdisMPciAssignResources),
3612: IMPORT_FUNC(NdisMFreeSharedMemory),
3613: IMPORT_FUNC(NdisMRegisterInterrupt),
3614: IMPORT_FUNC(NdisMDeregisterInterrupt),
3615: IMPORT_FUNC(NdisMRegisterAdapterShutdownHandler),
3616: IMPORT_FUNC(NdisMDeregisterAdapterShutdownHandler),
3617: IMPORT_FUNC(NDIS_BUFFER_TO_SPAN_PAGES),
3618: IMPORT_FUNC(NdisQueryBufferOffset),
3619: IMPORT_FUNC(NdisAdjustBufferLength),
3620: IMPORT_FUNC(NdisPacketPoolUsage),
3621: IMPORT_FUNC(NdisMSleep),
3622: IMPORT_FUNC(NdisUnchainBufferAtFront),
3623: IMPORT_FUNC(NdisReadPcmciaAttributeMemory),
3624: IMPORT_FUNC(NdisWritePcmciaAttributeMemory),
1.2 rittera 3625: #ifdef __FreeBSD__
1.1 rittera 3626: IMPORT_FUNC(NdisOpenFile),
3627: IMPORT_FUNC(NdisMapFile),
3628: IMPORT_FUNC(NdisUnmapFile),
3629: IMPORT_FUNC(NdisCloseFile),
1.2 rittera 3630: #endif
1.1 rittera 3631: IMPORT_FUNC(NdisMRegisterDevice),
3632: IMPORT_FUNC(NdisMDeregisterDevice),
3633: IMPORT_FUNC(NdisMQueryAdapterInstanceName),
3634: IMPORT_FUNC(NdisMRegisterUnloadHandler),
3635: IMPORT_FUNC(ndis_timercall),
3636:
3637: /*
3638: * This last entry is a catch-all for any function we haven't
3639: * implemented yet. The PE import list patching routine will
3640: * use it for any function that doesn't have an explicit match
3641: * in this table.
3642: */
3643:
3644: { NULL, (FUNC)dummy, NULL },
3645:
3646: /* End of list. */
3647:
3648: { NULL, NULL, NULL }
3649: };
CVSweb <webmaster@jp.NetBSD.org>