Annotation of src/sys/compat/ndis/subr_ndis.c, Revision 1.9
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.9 ! dyoung 38: __KERNEL_RCSID(0, "$NetBSD: subr_ndis.c,v 1.8 2007/03/05 21:05:02 dogcow 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>
1.2 rittera 66: #ifdef __NetBSD__
67: #include <sys/lkm.h>
68: #endif
1.1 rittera 69: #include <sys/malloc.h>
70: #include <sys/lock.h>
1.2 rittera 71: #ifdef __FreeBSD__
1.1 rittera 72: #include <sys/mutex.h>
1.2 rittera 73: #endif
1.1 rittera 74: #include <sys/socket.h>
75: #include <sys/sysctl.h>
1.2 rittera 76: #ifdef __FreeBSD__
1.1 rittera 77: #include <sys/timespec.h>
78: #include <sys/smp.h>
1.2 rittera 79: #endif
1.1 rittera 80: #include <sys/queue.h>
81: #include <sys/proc.h>
82: #include <sys/filedesc.h>
83: #include <sys/namei.h>
84: #include <sys/fcntl.h>
85: #include <sys/vnode.h>
86: #include <sys/kthread.h>
1.2 rittera 87: #ifdef __FreeBSD__
1.1 rittera 88: #include <sys/linker.h>
1.2 rittera 89: #include <sys/sysproto.h>
90: #endif
1.1 rittera 91: #include <sys/mount.h>
92:
93: #include <net/if.h>
94: #include <net/if_arp.h>
1.2 rittera 95: #ifdef __FreeBSD__
1.1 rittera 96: #include <net/ethernet.h>
1.2 rittera 97: #else
98: #include <net/if_ether.h>
99: #endif
1.1 rittera 100: #include <net/if_dl.h>
101: #include <net/if_media.h>
102:
103: #include <machine/atomic.h>
1.2 rittera 104: #ifdef __FreeBSD__
1.1 rittera 105: #include <machine/bus_memio.h>
106: #include <machine/bus_pio.h>
107: #include <machine/resource.h>
108: #include <sys/bus.h>
109: #include <sys/rman.h>
1.2 rittera 110: #endif
111: #include <machine/bus.h>
1.1 rittera 112:
113: #include <machine/stdarg.h>
114:
115: #include <net80211/ieee80211_var.h>
116: #include <net80211/ieee80211_ioctl.h>
117:
118: #include <dev/pci/pcireg.h>
119: #include <dev/pci/pcivar.h>
120:
121: #include <compat/ndis/pe_var.h>
122: #include <compat/ndis/resource_var.h>
123: #include <compat/ndis/ntoskrnl_var.h>
124: #include <compat/ndis/hal_var.h>
125: #include <compat/ndis/ndis_var.h>
126: #include <compat/ndis/cfg_var.h>
127: #include <dev/if_ndis/if_ndisvar.h>
128:
1.3 rittera 129: #ifdef __NetBSD__
130: #include "nbcompat.h"
131: #endif
132:
133: #ifdef __NetBSD__
134: #define PN(name) /* printf(#name "\n"); */
135: #endif
136:
1.1 rittera 137: static char ndis_filepath[MAXPATHLEN];
138: extern struct nd_head ndis_devhead;
139:
1.2 rittera 140: #ifdef __FreeBSD__
1.1 rittera 141: SYSCTL_STRING(_hw, OID_AUTO, ndis_filepath, CTLFLAG_RW, ndis_filepath,
142: MAXPATHLEN, "Path used by NdisOpenFile() to search for files");
1.2 rittera 143: #endif
1.1 rittera 144:
145: __stdcall static void NdisInitializeWrapper(ndis_handle *,
146: driver_object *, void *, void *);
147: __stdcall static ndis_status NdisMRegisterMiniport(ndis_handle,
148: ndis_miniport_characteristics *, int);
149: __stdcall static ndis_status NdisAllocateMemoryWithTag(void **,
150: uint32_t, uint32_t);
151: __stdcall static ndis_status NdisAllocateMemory(void **,
152: uint32_t, uint32_t, ndis_physaddr);
153: __stdcall static void NdisFreeMemory(void *, uint32_t, uint32_t);
154: __stdcall static ndis_status NdisMSetAttributesEx(ndis_handle, ndis_handle,
155: uint32_t, uint32_t, ndis_interface_type);
156: __stdcall static void NdisOpenConfiguration(ndis_status *,
157: ndis_handle *, ndis_handle);
158: __stdcall static void NdisOpenConfigurationKeyByIndex(ndis_status *,
159: ndis_handle, uint32_t, ndis_unicode_string *, ndis_handle *);
160: __stdcall static void NdisOpenConfigurationKeyByName(ndis_status *,
161: ndis_handle, ndis_unicode_string *, ndis_handle *);
1.2 rittera 162: #ifdef __FreeBSD__
1.1 rittera 163: static ndis_status ndis_encode_parm(ndis_miniport_block *,
164: struct sysctl_oid *, ndis_parm_type, ndis_config_parm **);
165: static ndis_status ndis_decode_parm(ndis_miniport_block *,
166: ndis_config_parm *, char *);
1.3 rittera 167: #else /* __NetBSD__ */
168: static ndis_status ndis_encode_parm(ndis_miniport_block *,
169: void *, ndis_parm_type, ndis_config_parm **);
170: #endif
1.1 rittera 171: __stdcall static void NdisReadConfiguration(ndis_status *, ndis_config_parm **,
172: ndis_handle, ndis_unicode_string *, ndis_parm_type);
173: __stdcall static void NdisWriteConfiguration(ndis_status *, ndis_handle,
174: ndis_unicode_string *, ndis_config_parm *);
175: __stdcall static void NdisCloseConfiguration(ndis_handle);
176: __stdcall static void NdisAllocateSpinLock(ndis_spin_lock *);
177: __stdcall static void NdisFreeSpinLock(ndis_spin_lock *);
178: __stdcall static void NdisAcquireSpinLock(ndis_spin_lock *);
179: __stdcall static void NdisReleaseSpinLock(ndis_spin_lock *);
180: __stdcall static void NdisDprAcquireSpinLock(ndis_spin_lock *);
181: __stdcall static void NdisDprReleaseSpinLock(ndis_spin_lock *);
182: __stdcall static uint32_t NdisReadPciSlotInformation(ndis_handle, uint32_t,
183: uint32_t, void *, uint32_t);
184: __stdcall static uint32_t NdisWritePciSlotInformation(ndis_handle, uint32_t,
185: uint32_t, void *, uint32_t);
186: static void NdisWriteErrorLogEntry(ndis_handle, ndis_error_code, uint32_t, ...);
187: static void ndis_map_cb(void *, bus_dma_segment_t *, int, int);
188: __stdcall static void NdisMStartBufferPhysicalMapping(ndis_handle,
189: ndis_buffer *, uint32_t, uint8_t, ndis_paddr_unit *, uint32_t *);
190: __stdcall static void NdisMCompleteBufferPhysicalMapping(ndis_handle,
191: ndis_buffer *, uint32_t);
192: __stdcall static void NdisMInitializeTimer(ndis_miniport_timer *, ndis_handle,
193: ndis_timer_function, void *);
194: __stdcall static void NdisInitializeTimer(ndis_timer *,
195: ndis_timer_function, void *);
196: __stdcall static void NdisSetTimer(ndis_timer *, uint32_t);
197: __stdcall static void NdisMSetPeriodicTimer(ndis_miniport_timer *, uint32_t);
198: __stdcall static void NdisMCancelTimer(ndis_timer *, uint8_t *);
199: __stdcall static void ndis_timercall(kdpc *, ndis_miniport_timer *,
200: void *, void *);
201: __stdcall static void NdisMQueryAdapterResources(ndis_status *, ndis_handle,
202: ndis_resource_list *, uint32_t *);
203: __stdcall static ndis_status NdisMRegisterIoPortRange(void **,
204: ndis_handle, uint32_t, uint32_t);
205: __stdcall static void NdisMDeregisterIoPortRange(ndis_handle,
206: uint32_t, uint32_t, void *);
207: __stdcall static void NdisReadNetworkAddress(ndis_status *, void **,
208: uint32_t *, ndis_handle);
209: __stdcall static ndis_status NdisQueryMapRegisterCount(uint32_t, uint32_t *);
210: __stdcall static ndis_status NdisMAllocateMapRegisters(ndis_handle,
211: uint32_t, uint8_t, uint32_t, uint32_t);
212: __stdcall static void NdisMFreeMapRegisters(ndis_handle);
213: static void ndis_mapshared_cb(void *, bus_dma_segment_t *, int, int);
214: __stdcall static void NdisMAllocateSharedMemory(ndis_handle, uint32_t,
215: uint8_t, void **, ndis_physaddr *);
216: static void ndis_asyncmem_complete(void *);
217: __stdcall static ndis_status NdisMAllocateSharedMemoryAsync(ndis_handle,
218: uint32_t, uint8_t, void *);
219: __stdcall static void NdisMFreeSharedMemory(ndis_handle, uint32_t,
220: uint8_t, void *, ndis_physaddr);
221: __stdcall static ndis_status NdisMMapIoSpace(void **, ndis_handle,
222: ndis_physaddr, uint32_t);
223: __stdcall static void NdisMUnmapIoSpace(ndis_handle, void *, uint32_t);
224: __stdcall static uint32_t NdisGetCacheFillSize(void);
225: __stdcall static uint32_t NdisMGetDmaAlignment(ndis_handle);
226: __stdcall static ndis_status NdisMInitializeScatterGatherDma(ndis_handle,
227: uint8_t, uint32_t);
228: __stdcall static void NdisUnchainBufferAtFront(ndis_packet *, ndis_buffer **);
229: __stdcall static void NdisUnchainBufferAtBack(ndis_packet *, ndis_buffer **);
230: __stdcall static void NdisAllocateBufferPool(ndis_status *,
231: ndis_handle *, uint32_t);
232: __stdcall static void NdisFreeBufferPool(ndis_handle);
233: __stdcall static void NdisAllocateBuffer(ndis_status *, ndis_buffer **,
234: ndis_handle, void *, uint32_t);
235: __stdcall static void NdisFreeBuffer(ndis_buffer *);
236: __stdcall static uint32_t NdisBufferLength(ndis_buffer *);
237: __stdcall static void NdisQueryBuffer(ndis_buffer *, void **, uint32_t *);
238: __stdcall static void NdisQueryBufferSafe(ndis_buffer *, void **,
239: uint32_t *, uint32_t);
240: __stdcall static void *NdisBufferVirtualAddress(ndis_buffer *);
241: __stdcall static void *NdisBufferVirtualAddressSafe(ndis_buffer *, uint32_t);
242: __stdcall static void NdisAdjustBufferLength(ndis_buffer *, int);
243: __stdcall static uint32_t NdisInterlockedIncrement(uint32_t *);
244: __stdcall static uint32_t NdisInterlockedDecrement(uint32_t *);
245: __stdcall static void NdisInitializeEvent(ndis_event *);
246: __stdcall static void NdisSetEvent(ndis_event *);
247: __stdcall static void NdisResetEvent(ndis_event *);
248: __stdcall static uint8_t NdisWaitEvent(ndis_event *, uint32_t);
249: __stdcall static ndis_status NdisUnicodeStringToAnsiString(ndis_ansi_string *,
250: ndis_unicode_string *);
251: __stdcall static ndis_status
252: NdisAnsiStringToUnicodeString(ndis_unicode_string *,
253: ndis_ansi_string *);
254: __stdcall static ndis_status NdisMPciAssignResources(ndis_handle,
255: uint32_t, ndis_resource_list **);
256: __stdcall static ndis_status NdisMRegisterInterrupt(ndis_miniport_interrupt *,
257: ndis_handle, uint32_t, uint32_t, uint8_t,
258: uint8_t, ndis_interrupt_mode);
259: __stdcall static void NdisMDeregisterInterrupt(ndis_miniport_interrupt *);
260: __stdcall static void NdisMRegisterAdapterShutdownHandler(ndis_handle, void *,
261: ndis_shutdown_handler);
262: __stdcall static void NdisMDeregisterAdapterShutdownHandler(ndis_handle);
263: __stdcall static uint32_t NDIS_BUFFER_TO_SPAN_PAGES(ndis_buffer *);
264: __stdcall static void NdisGetBufferPhysicalArraySize(ndis_buffer *,
265: uint32_t *);
266: __stdcall static void NdisQueryBufferOffset(ndis_buffer *,
267: uint32_t *, uint32_t *);
268: __stdcall static void NdisMSleep(uint32_t);
269: __stdcall static uint32_t NdisReadPcmciaAttributeMemory(ndis_handle,
270: uint32_t, void *, uint32_t);
271: __stdcall static uint32_t NdisWritePcmciaAttributeMemory(ndis_handle,
272: uint32_t, void *, uint32_t);
273: __stdcall static list_entry *NdisInterlockedInsertHeadList(list_entry *,
274: list_entry *, ndis_spin_lock *);
275: __stdcall static list_entry *NdisInterlockedRemoveHeadList(list_entry *,
276: ndis_spin_lock *);
277: __stdcall static list_entry *NdisInterlockedInsertTailList(list_entry *,
278: list_entry *, ndis_spin_lock *);
279: __stdcall static uint8_t
280: NdisMSynchronizeWithInterrupt(ndis_miniport_interrupt *,
281: void *, void *);
282: __stdcall static void NdisGetCurrentSystemTime(uint64_t *);
283: __stdcall static void NdisGetSystemUpTime(uint32_t *);
284: __stdcall static void NdisInitializeString(ndis_unicode_string *, char *);
285: __stdcall static void NdisInitAnsiString(ndis_ansi_string *, char *);
286: __stdcall static void NdisInitUnicodeString(ndis_unicode_string *,
287: uint16_t *);
288: __stdcall static void NdisFreeString(ndis_unicode_string *);
289: __stdcall static ndis_status NdisMRemoveMiniport(ndis_handle *);
290: __stdcall static void NdisTerminateWrapper(ndis_handle, void *);
291: __stdcall static void NdisMGetDeviceProperty(ndis_handle, device_object **,
292: device_object **, device_object **, cm_resource_list *,
293: cm_resource_list *);
294: __stdcall static void NdisGetFirstBufferFromPacket(ndis_packet *,
295: ndis_buffer **, void **, uint32_t *, uint32_t *);
296: __stdcall static void NdisGetFirstBufferFromPacketSafe(ndis_packet *,
297: ndis_buffer **, void **, uint32_t *, uint32_t *, uint32_t);
1.2 rittera 298: #ifdef __FreeBSD__
1.7 christos 299: static int ndis_find_sym(linker_file_t, char *, char *, void **);
1.1 rittera 300: __stdcall static void NdisOpenFile(ndis_status *, ndis_handle *, uint32_t *,
301: ndis_unicode_string *, ndis_physaddr);
302: __stdcall static void NdisMapFile(ndis_status *, void **, ndis_handle);
303: __stdcall static void NdisUnmapFile(ndis_handle);
304: __stdcall static void NdisCloseFile(ndis_handle);
1.2 rittera 305: #endif
1.1 rittera 306: __stdcall static uint8_t NdisSystemProcessorCount(void);
307: __stdcall static void NdisMIndicateStatusComplete(ndis_handle);
308: __stdcall static void NdisMIndicateStatus(ndis_handle, ndis_status,
309: void *, uint32_t);
310: static void ndis_workfunc(void *);
311: static funcptr ndis_findwrap(funcptr);
312: __stdcall static ndis_status NdisScheduleWorkItem(ndis_work_item *);
313: __stdcall static void NdisCopyFromPacketToPacket(ndis_packet *,
314: uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *);
315: __stdcall static void NdisCopyFromPacketToPacketSafe(ndis_packet *,
316: uint32_t, uint32_t, ndis_packet *, uint32_t, uint32_t *, uint32_t);
317: __stdcall static ndis_status NdisMRegisterDevice(ndis_handle,
318: ndis_unicode_string *, ndis_unicode_string *, driver_dispatch **,
319: void **, ndis_handle *);
320: __stdcall static ndis_status NdisMDeregisterDevice(ndis_handle);
321: __stdcall static ndis_status
322: NdisMQueryAdapterInstanceName(ndis_unicode_string *,
323: ndis_handle);
324: __stdcall static void NdisMRegisterUnloadHandler(ndis_handle, void *);
325: __stdcall static void dummy(void);
326:
327: /*
328: * Some really old drivers do not properly check the return value
329: * from NdisAllocatePacket() and NdisAllocateBuffer() and will
330: * sometimes allocate few more buffers/packets that they originally
331: * requested when they created the pool. To prevent this from being
332: * a problem, we allocate a few extra buffers/packets beyond what
333: * the driver asks for. This #define controls how many.
334: */
335: #define NDIS_POOL_EXTRA 16
336:
337: int
338: ndis_libinit()
339: {
340: image_patch_table *patch;
341:
342: strcpy(ndis_filepath, "/compat/ndis");
343:
344: patch = ndis_functbl;
345: while (patch->ipt_func != NULL) {
346: windrv_wrap((funcptr)patch->ipt_func,
347: (funcptr *)&patch->ipt_wrap);
348: patch++;
349: }
350:
351: return(0);
352: }
353:
354: int
355: ndis_libfini()
356: {
357: image_patch_table *patch;
358:
359: patch = ndis_functbl;
360: while (patch->ipt_func != NULL) {
361: windrv_unwrap(patch->ipt_wrap);
362: patch++;
363: }
364:
365: return(0);
366: }
367:
368: static funcptr
369: ndis_findwrap(func)
370: funcptr func;
371: {
372: image_patch_table *patch;
373:
374: patch = ndis_functbl;
375: while (patch->ipt_func != NULL) {
376: if ((funcptr)patch->ipt_func == func)
377: return((funcptr)patch->ipt_wrap);
378: patch++;
379: }
380:
381: return(NULL);
382: }
383:
384: /*
385: * NDIS deals with strings in unicode format, so we have
386: * do deal with them that way too. For now, we only handle
387: * conversion between unicode and ASCII since that's all
388: * that device drivers care about.
389: */
390:
391: int
392: ndis_ascii_to_unicode(ascii, unicode)
1.3 rittera 393: const char *ascii;
1.1 rittera 394: uint16_t **unicode;
395: {
396: uint16_t *ustr;
397: int i;
398:
399: if (*unicode == NULL)
400: *unicode = malloc(strlen(ascii) * 2, M_DEVBUF, M_NOWAIT);
401:
402: if (*unicode == NULL)
403: return(ENOMEM);
404: ustr = *unicode;
405: for (i = 0; i < strlen(ascii); i++) {
406: *ustr = (uint16_t)ascii[i];
407: ustr++;
408: }
409:
410: return(0);
411: }
412:
413: int
414: ndis_unicode_to_ascii(unicode, ulen, ascii)
415: uint16_t *unicode;
416: int ulen;
417: char **ascii;
418: {
419: uint8_t *astr;
420: int i;
421:
422: if (*ascii == NULL)
423: *ascii = malloc((ulen / 2) + 1, M_DEVBUF, M_NOWAIT|M_ZERO);
424: if (*ascii == NULL)
425: return(ENOMEM);
426: astr = *ascii;
427: for (i = 0; i < ulen / 2; i++) {
428: *astr = (uint8_t)unicode[i];
429: astr++;
430: }
431:
432: return(0);
433: }
434:
435: /*
436: * This routine does the messy Windows Driver Model device attachment
437: * stuff on behalf of NDIS drivers. We register our own AddDevice
438: * routine here
439: */
440: __stdcall static void
1.5 christos 441: NdisInitializeWrapper(
1.6 christos 442: ndis_handle *wrapper,
1.5 christos 443: driver_object *drv,
1.6 christos 444: void *path,
445: void *unused)
1.1 rittera 446: {
1.3 rittera 447: PN(NdisInitializeWrapper)
1.1 rittera 448: /*
449: * As of yet, I haven't come up with a compelling
450: * reason to define a private NDIS wrapper structure,
451: * so we use a pointer to the driver object as the
452: * wrapper handle. The driver object has the miniport
453: * characteristics struct for this driver hung off it
454: * via IoAllocateDriverObjectExtension(), and that's
455: * really all the private data we need.
456: */
457:
458: *wrapper = drv;
459:
460: /*
461: * If this was really Windows, we'd be registering dispatch
462: * routines for the NDIS miniport module here, but we're
463: * not Windows so all we really need to do is set up an
464: * AddDevice function that'll be invoked when a new device
465: * instance appears.
466: */
467:
468: drv->dro_driverext->dre_adddevicefunc = NdisAddDevice;
469:
470: return;
471: }
472:
473: __stdcall static void
1.5 christos 474: NdisTerminateWrapper(
1.6 christos 475: ndis_handle handle,
476: void *syspec)
1.1 rittera 477: {
478: /* Nothing to see here, move along. */
479: return;
480: }
481:
482: __stdcall static ndis_status
483: NdisMRegisterMiniport(handle, characteristics, len)
484: ndis_handle handle;
485: ndis_miniport_characteristics *characteristics;
486: int len;
487: {
1.3 rittera 488: ndis_miniport_characteristics *pch = NULL;
489: void *ch = NULL;
1.1 rittera 490: driver_object *drv;
491:
1.3 rittera 492: PN(NdisMRegisterMiniport);
493:
1.1 rittera 494: drv = (driver_object *)handle;
495:
496: /*
497: * We need to save the NDIS miniport characteristics
498: * somewhere. This data is per-driver, not per-device
499: * (all devices handled by the same driver have the
500: * same characteristics) so we hook it onto the driver
501: * object using IoAllocateDriverObjectExtension().
502: * The extra extension info is automagically deleted when
503: * the driver is unloaded (see windrv_unload()).
504: */
505: if (IoAllocateDriverObjectExtension(drv, (void *)1,
1.3 rittera 506: sizeof(ndis_miniport_characteristics), /*(void **)*/&ch) !=
1.1 rittera 507: STATUS_SUCCESS)
508: return(NDIS_STATUS_RESOURCES);
1.3 rittera 509: pch = (ndis_miniport_characteristics *)ch;
1.1 rittera 510:
1.3 rittera 511: bzero((char *)pch, sizeof(ndis_miniport_characteristics));
1.1 rittera 512:
1.3 rittera 513: #ifdef __FreeBSD__
514: bcopy((char *)characteristics, (char *)pch, len);
515: #else /* __NetBSD__ */
516: memcpy(pch, characteristics, len);
517: #endif
518:
519: if (pch->nmc_version_major < 5 || pch->nmc_version_minor < 1) {
520: pch->nmc_shutdown_handler = NULL;
521: pch->nmc_canceltxpkts_handler = NULL;
522: pch->nmc_pnpevent_handler = NULL;
1.1 rittera 523: }
524:
525: return(NDIS_STATUS_SUCCESS);
526: }
527:
528: __stdcall static ndis_status
529: NdisAllocateMemoryWithTag(vaddr, len, tag)
530: void **vaddr;
531: uint32_t len;
532: uint32_t tag;
533: {
534: void *mem;
535:
536:
537: mem = ExAllocatePoolWithTag(NonPagedPool, len, tag);
538: if (mem == NULL)
539: return(NDIS_STATUS_RESOURCES);
540: *vaddr = mem;
541:
542: return(NDIS_STATUS_SUCCESS);
543: }
544:
545: __stdcall static ndis_status
1.5 christos 546: NdisAllocateMemory(
547: void **vaddr,
548: uint32_t len,
1.6 christos 549: uint32_t flags,
550: ndis_physaddr highaddr)
1.1 rittera 551: {
552: void *mem;
553:
554: mem = ExAllocatePoolWithTag(NonPagedPool, len, 0);
555: if (mem == NULL)
556: return(NDIS_STATUS_RESOURCES);
557: *vaddr = mem;
558:
559: return(NDIS_STATUS_SUCCESS);
560: }
561:
562: __stdcall static void
1.5 christos 563: NdisFreeMemory(
564: void *vaddr,
565: uint32_t len,
1.6 christos 566: uint32_t flags)
1.1 rittera 567: {
568: if (len == 0)
569: return;
570:
571: ExFreePool(vaddr);
572:
573: return;
574: }
575:
576: __stdcall static ndis_status
1.5 christos 577: NdisMSetAttributesEx(
578: ndis_handle adapter_handle,
579: ndis_handle adapter_ctx,
580: uint32_t hangsecs,
581: uint32_t flags,
1.6 christos 582: ndis_interface_type iftype)
1.1 rittera 583: {
584: ndis_miniport_block *block;
585:
1.3 rittera 586: PN(NdisMSetAttributesEx)
1.1 rittera 587: /*
588: * Save the adapter context, we need it for calling
589: * the driver's internal functions.
590: */
591: block = (ndis_miniport_block *)adapter_handle;
592: block->nmb_miniportadapterctx = adapter_ctx;
593: block->nmb_checkforhangsecs = hangsecs;
594: block->nmb_flags = flags;
595:
596: return(NDIS_STATUS_SUCCESS);
597: }
598:
599: __stdcall static void
600: NdisOpenConfiguration(status, cfg, wrapctx)
601: ndis_status *status;
602: ndis_handle *cfg;
603: ndis_handle wrapctx;
604: {
1.3 rittera 605: PN(NdisOpenConfiguration)
1.1 rittera 606: *cfg = wrapctx;
607: *status = NDIS_STATUS_SUCCESS;
608:
609: return;
610: }
611:
612: __stdcall static void
1.5 christos 613: NdisOpenConfigurationKeyByName(
614: ndis_status *status,
615: ndis_handle cfg,
1.6 christos 616: ndis_unicode_string *subkey,
1.5 christos 617: ndis_handle *subhandle)
1.1 rittera 618: {
1.3 rittera 619: PN(NdisOpenConfiguration)
1.1 rittera 620: *subhandle = cfg;
621: *status = NDIS_STATUS_SUCCESS;
622: return;
623: }
624:
625: __stdcall static void
1.5 christos 626: NdisOpenConfigurationKeyByIndex(
627: ndis_status *status,
1.6 christos 628: ndis_handle cfg,
629: uint32_t idx,
630: ndis_unicode_string *subkey,
631: ndis_handle *subhandle)
1.1 rittera 632: {
633: *status = NDIS_STATUS_FAILURE;
634: return;
635: }
636:
1.3 rittera 637: static ndis_status
1.2 rittera 638: #ifdef __FreeBSD__
1.1 rittera 639: ndis_encode_parm(block, oid, type, parm)
1.3 rittera 640: ndis_miniport_block *block;
641: struct sysctl_oid *oid;
642: ndis_parm_type type;
643: ndis_config_parm **parm;
644: #else /* __NetBSD__ */
645: ndis_encode_parm(block, data, type, parm)
646: ndis_miniport_block *block;
647: void *data;
1.1 rittera 648: ndis_parm_type type;
649: ndis_config_parm **parm;
1.3 rittera 650: #endif
1.1 rittera 651: {
652: uint16_t *unicode;
653: ndis_unicode_string *ustr;
654: int base = 0;
655:
1.3 rittera 656: PN(ndis_encode_parm)
657:
1.1 rittera 658: unicode = (uint16_t *)&block->nmb_dummybuf;
659:
660: switch(type) {
661: case ndis_parm_string:
1.3 rittera 662: #ifdef __FreeBSD__
1.1 rittera 663: ndis_ascii_to_unicode((char *)oid->oid_arg1, &unicode);
1.3 rittera 664: #else /* __NetBSD__ */
665: ndis_ascii_to_unicode((char *)data, &unicode);
666: #endif
1.1 rittera 667: (*parm)->ncp_type = ndis_parm_string;
668: ustr = &(*parm)->ncp_parmdata.ncp_stringdata;
1.3 rittera 669: #ifdef __FreeBSD__
1.1 rittera 670: ustr->us_len = strlen((char *)oid->oid_arg1) * 2;
1.3 rittera 671: #else /* __NetBSD__ */
672: ustr->us_len = strlen((char *)data) * 2;
673: #endif
1.1 rittera 674: ustr->us_buf = unicode;
675: break;
676: case ndis_parm_int:
1.3 rittera 677: #ifdef __FreeBSD__
678: if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) {
679: #else /* __NetBSD__ */
680: if (strncmp((char *)data, "0x", 2) == 0) {
681: #endif
1.1 rittera 682: base = 16;
1.3 rittera 683: }
1.1 rittera 684: else
685: base = 10;
686: (*parm)->ncp_type = ndis_parm_int;
687: (*parm)->ncp_parmdata.ncp_intdata =
1.3 rittera 688: #ifdef __FreeBSD__
1.1 rittera 689: strtol((char *)oid->oid_arg1, NULL, base);
1.3 rittera 690: #else /* __NetBSD__ */
691: /* TODO: NetBSD dosen't seem to have a strtol in sys/lib/libkern I hope strtoul is OK */
692: strtoul((char *)data, NULL, base);
693: #endif
1.1 rittera 694: break;
695: case ndis_parm_hexint:
1.3 rittera 696: #ifdef __FreeBSD__
697: if (strncmp((char *)oid->oid_arg1, "0x", 2) == 0) {
698: #else /* __NetBSD__ */
699: if (strncmp((char *)data, "0x", 2) == 0) {
700: #endif
1.1 rittera 701: base = 16;
1.3 rittera 702: }
1.1 rittera 703: else
704: base = 10;
705: (*parm)->ncp_type = ndis_parm_hexint;
706: (*parm)->ncp_parmdata.ncp_intdata =
1.3 rittera 707: #ifdef __FreeBSD__
1.1 rittera 708: strtoul((char *)oid->oid_arg1, NULL, base);
1.3 rittera 709: #else /* __NetBSD__ */
710: strtoul((char *)data, NULL, base);
711: #endif
1.1 rittera 712: break;
713: default:
714: return(NDIS_STATUS_FAILURE);
715: break;
716: }
717:
718: return(NDIS_STATUS_SUCCESS);
719: }
720:
721: int
722: ndis_strcasecmp(s1, s2)
723: const char *s1;
724: const char *s2;
725: {
726: char a, b;
727:
728: /*
729: * In the kernel, toupper() is a macro. Have to be careful
730: * not to use pointer arithmetic when passing it arguments.
731: */
732:
733: while(1) {
734: a = *s1;
735: b = *s2++;
736: if (toupper(a) != toupper(b))
737: break;
738: if (*s1++ == '\0')
739: return(0);
740: }
741:
742: return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
743: }
744:
745: int
746: ndis_strncasecmp(s1, s2, n)
747: const char *s1;
748: const char *s2;
749: size_t n;
750: {
751: char a, b;
752:
753: if (n != 0) {
754: do {
755: a = *s1;
756: b = *s2++;
757: if (toupper(a) != toupper(b))
758: return (*(const unsigned char *)s1 -
759: *(const unsigned char *)(s2 - 1));
760: if (*s1++ == '\0')
761: break;
762: } while (--n != 0);
763: }
764:
765: return(0);
766: }
767:
768: __stdcall static void
769: NdisReadConfiguration(status, parm, cfg, key, type)
770: ndis_status *status;
771: ndis_config_parm **parm;
772: ndis_handle cfg;
773: ndis_unicode_string *key;
774: ndis_parm_type type;
775: {
776: char *keystr = NULL;
777: uint16_t *unicode;
778: ndis_miniport_block *block;
779: struct ndis_softc *sc;
1.3 rittera 780: #ifdef __FreeBSD__
781: struct sysctl_oid *oidp;
1.1 rittera 782: struct sysctl_ctx_entry *e;
1.3 rittera 783: #endif
784:
785: #ifdef __NetBSD__
786: const struct sysctlnode *pnode = NULL;
787: struct sysctlnode *ndiscld = NULL;
788: int error;
789: int numcld;
790: int mib[1];
791: int i;
792: char new_keystr[MAX_SYSCTL_LEN+1];
793: char *old_keystr;
794: #endif
1.1 rittera 795:
796: block = (ndis_miniport_block *)cfg;
1.3 rittera 797: #ifdef __FreeBSD__
1.1 rittera 798: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 799: #else /* __NetBSD__ */
800: sc = block->nmb_physdeviceobj->pdo_sc;
801: #endif
802: PN(NdisReadConfiguration)
1.1 rittera 803:
804: if (key->us_len == 0 || key->us_buf == NULL) {
805: *status = NDIS_STATUS_FAILURE;
806: return;
807: }
808:
809: ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr);
810: *parm = &block->nmb_replyparm;
811: bzero((char *)&block->nmb_replyparm, sizeof(ndis_config_parm));
812: unicode = (uint16_t *)&block->nmb_dummybuf;
1.3 rittera 813:
814: #ifdef __NetBSD__
815: if(strlen(keystr) + strlen("ndis_") > MAX_SYSCTL_LEN) {
816: panic("sysctl name too long: %s\n", keystr);
817: }
818: strcpy(new_keystr, "ndis_");
819: strcpy(new_keystr + strlen("ndis_"), keystr);
820: old_keystr = keystr;
821: keystr = new_keystr;
822: #endif
1.1 rittera 823:
824: /*
825: * See if registry key is already in a list of known keys
826: * included with the driver.
827: */
1.3 rittera 828: #ifdef __FreeBSD__
1.1 rittera 829: #if __FreeBSD_version < 502113
830: TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
831: #else
832: TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
833: #endif
834: oidp = e->entry;
1.3 rittera 835: #ifdef __FreeBSD__
1.1 rittera 836: if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
1.3 rittera 837: #else /* __NetBSD__ */
838: if (ndis_strcasecmp(oidp->ctl_name, keystr) == 0) {
839: #endif
1.1 rittera 840: if (strcmp((char *)oidp->oid_arg1, "UNSET") == 0) {
841: free(keystr, M_DEVBUF);
842: *status = NDIS_STATUS_FAILURE;
843: return;
1.3 rittera 844: }
845: *status = ndis_encode_parm(block, oidp, type, parm);
846:
847: free(keystr, M_DEVBUF);
848: return;
849: }
850: }
851: #else /* __NetBSD__ */
852: mib[0] = sc->ndis_sysctl_mib;
853:
854: sysctl_lock(curlwp, NULL, 0);
855: error = sysctl_locate(curlwp, &mib[0], 1, &pnode, NULL);
856:
857: numcld = pnode->sysctl_csize;
858: ndiscld = pnode->sysctl_child;
859:
860: /* find the node whose name is keystr */
861: for(i=0; i < numcld; i++) {
862: if(strcmp(keystr, ndiscld->sysctl_name) == 0) {
863: /* Found it */
864: break;
1.1 rittera 865: }
1.3 rittera 866: ndiscld++;
867: }
868: sysctl_unlock(curlwp);
869:
870: if(i < numcld) {
871: /* Found it */
872: if(strcmp(ndiscld->sysctl_data, "UNSET") == 0) {
1.1 rittera 873: free(keystr, M_DEVBUF);
1.3 rittera 874: *status = NDIS_STATUS_FAILURE;
1.1 rittera 875: return;
876: }
1.3 rittera 877:
878: *status = ndis_encode_parm(block, ndiscld->sysctl_data, type, parm);
879: free(keystr, M_DEVBUF);
880: return;
1.1 rittera 881: }
1.3 rittera 882:
883: #endif
884:
885: #ifdef __NetBSD__
886: free(keystr, M_DEVBUF);
887: keystr = old_keystr;
888: #endif
1.1 rittera 889:
890: /*
891: * If the key didn't match, add it to the list of dynamically
892: * created ones. Sometimes, drivers refer to registry keys
893: * that aren't documented in their .INF files. These keys
894: * are supposed to be created by some sort of utility or
895: * control panel snap-in that comes with the driver software.
896: * Sometimes it's useful to be able to manipulate these.
897: * If the driver requests the key in the form of a string,
898: * make its default value an empty string, otherwise default
899: * it to "0".
900: */
901: if (type == ndis_parm_int || type == ndis_parm_hexint)
902: ndis_add_sysctl(sc, keystr, "(dynamic integer key)",
903: "UNSET", CTLFLAG_RW);
904: else
905: ndis_add_sysctl(sc, keystr, "(dynamic string key)",
1.3 rittera 906: "UNSET", CTLFLAG_RW);
1.1 rittera 907:
908: free(keystr, M_DEVBUF);
909: *status = NDIS_STATUS_FAILURE;
910: return;
911: }
912:
1.3 rittera 913: #ifdef __FreeBSD__
1.1 rittera 914: static ndis_status
915: ndis_decode_parm(block, parm, val)
916: ndis_miniport_block *block;
917: ndis_config_parm *parm;
918: char *val;
919: {
920: ndis_unicode_string *ustr;
921: char *astr = NULL;
922:
1.3 rittera 923: PN(ndis_decode_parm)
924:
1.1 rittera 925: switch(parm->ncp_type) {
926: case ndis_parm_string:
927: ustr = &parm->ncp_parmdata.ncp_stringdata;
928: ndis_unicode_to_ascii(ustr->us_buf, ustr->us_len, &astr);
929: bcopy(astr, val, 254);
930: free(astr, M_DEVBUF);
931: break;
932: case ndis_parm_int:
933: sprintf(val, "%d", parm->ncp_parmdata.ncp_intdata);
934: break;
935: case ndis_parm_hexint:
936: sprintf(val, "%xu", parm->ncp_parmdata.ncp_intdata);
937: break;
938: default:
939: return(NDIS_STATUS_FAILURE);
940: break;
941: }
942: return(NDIS_STATUS_SUCCESS);
943: }
1.3 rittera 944: #endif
1.1 rittera 945:
946: __stdcall static void
1.5 christos 947: NdisWriteConfiguration(
948: ndis_status *status,
1.6 christos 949: ndis_handle cfg,
950: ndis_unicode_string *key,
951: ndis_config_parm *parm)
1.1 rittera 952: {
1.2 rittera 953: #ifdef __FreeBSD__
1.1 rittera 954: char *keystr = NULL;
955: ndis_miniport_block *block;
956: struct ndis_softc *sc;
957: struct sysctl_oid *oidp;
958: struct sysctl_ctx_entry *e;
959: char val[256];
960:
961: block = (ndis_miniport_block *)cfg;
1.2 rittera 962:
1.3 rittera 963: PN(NdisWriteConfiguration)
964:
965: #ifdef __FreeBSD__
1.1 rittera 966: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 967: #else /* __NetBSD__ */
968: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
969: #endif
1.1 rittera 970:
971: ndis_unicode_to_ascii(key->us_buf, key->us_len, &keystr);
972:
973: /* Decode the parameter into a string. */
974: bzero(val, sizeof(val));
975: *status = ndis_decode_parm(block, parm, val);
976: if (*status != NDIS_STATUS_SUCCESS) {
977: free(keystr, M_DEVBUF);
978: return;
979: }
980:
981: /* See if the key already exists. */
982:
1.2 rittera 983: #if __FreeBSD_version < 502113 || !defined(__FreeBSD__)
1.1 rittera 984: TAILQ_FOREACH(e, &sc->ndis_ctx, link) {
985: #else
986: TAILQ_FOREACH(e, device_get_sysctl_ctx(sc->ndis_dev), link) {
987: #endif
988: oidp = e->entry;
989: if (ndis_strcasecmp(oidp->oid_name, keystr) == 0) {
990: /* Found it, set the value. */
991: strcpy((char *)oidp->oid_arg1, val);
992: free(keystr, M_DEVBUF);
993: return;
994: }
995: }
996:
997: /* Not found, add a new key with the specified value. */
998: ndis_add_sysctl(sc, keystr, "(dynamically set key)",
999: val, CTLFLAG_RW);
1000:
1001: free(keystr, M_DEVBUF);
1002: *status = NDIS_STATUS_SUCCESS;
1003: return;
1.2 rittera 1004: #else /* __FreeBSD__ */
1005: *status = NDIS_STATUS_SUCCESS;
1006: return;
1007: #endif
1.1 rittera 1008: }
1009:
1010: __stdcall static void
1.6 christos 1011: NdisCloseConfiguration(ndis_handle cfg)
1.1 rittera 1012: {
1013: return;
1014: }
1015:
1016: /*
1017: * Initialize a Windows spinlock.
1018: */
1019: __stdcall static void
1020: NdisAllocateSpinLock(lock)
1021: ndis_spin_lock *lock;
1022: {
1023: KeInitializeSpinLock(&lock->nsl_spinlock);
1024: lock->nsl_kirql = 0;
1025:
1026: return;
1027: }
1028:
1029: /*
1030: * Destroy a Windows spinlock. This is a no-op for now. There are two reasons
1031: * for this. One is that it's sort of superfluous: we don't have to do anything
1032: * special to deallocate the spinlock. The other is that there are some buggy
1033: * drivers which call NdisFreeSpinLock() _after_ calling NdisFreeMemory() on
1034: * the block of memory in which the spinlock resides. (Yes, ADMtek, I'm
1035: * talking to you.)
1036: */
1037: __stdcall static void
1.6 christos 1038: NdisFreeSpinLock(ndis_spin_lock *lock)
1.1 rittera 1039: {
1040: #ifdef notdef
1041: KeInitializeSpinLock(&lock->nsl_spinlock);
1042: lock->nsl_kirql = 0;
1043: #endif
1044: return;
1045: }
1046:
1047: /*
1048: * Acquire a spinlock from IRQL <= DISPATCH_LEVEL.
1049: */
1050:
1051: __stdcall static void
1052: NdisAcquireSpinLock(lock)
1053: ndis_spin_lock *lock;
1054: {
1055: KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
1056: return;
1057: }
1058:
1059: /*
1060: * Release a spinlock from IRQL == DISPATCH_LEVEL.
1061: */
1062:
1063: __stdcall static void
1064: NdisReleaseSpinLock(lock)
1065: ndis_spin_lock *lock;
1066: {
1067: KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
1068: return;
1069: }
1070:
1071: /*
1072: * Acquire a spinlock when already running at IRQL == DISPATCH_LEVEL.
1073: */
1074: __stdcall static void
1075: NdisDprAcquireSpinLock(lock)
1076: ndis_spin_lock *lock;
1077: {
1078: KeAcquireSpinLockAtDpcLevel(&lock->nsl_spinlock);
1079: return;
1080: }
1081:
1082: /*
1083: * Release a spinlock without leaving IRQL == DISPATCH_LEVEL.
1084: */
1085: __stdcall static void
1086: NdisDprReleaseSpinLock(lock)
1087: ndis_spin_lock *lock;
1088: {
1089: KeReleaseSpinLockFromDpcLevel(&lock->nsl_spinlock);
1090: return;
1091: }
1092:
1093: __stdcall static uint32_t
1.5 christos 1094: NdisReadPciSlotInformation(
1095: ndis_handle adapter,
1.6 christos 1096: uint32_t slot,
1.5 christos 1097: uint32_t offset,
1098: void *buf,
1099: uint32_t len)
1.1 rittera 1100: {
1101: ndis_miniport_block *block;
1102: int i;
1.3 rittera 1103: #ifdef __FreeBSD__
1104: char *dest;
1105: #else
1106: pcireg_t *dest;
1107: #endif
1108:
1109: /* PN(NdisReadPciSlotInformation) */
1.1 rittera 1110: device_t dev;
1.3 rittera 1111: struct ndis_softc *sc;
1.1 rittera 1112:
1113: block = (ndis_miniport_block *)adapter;
1114: dest = buf;
1115: if (block == NULL)
1116: return(0);
1117:
1.2 rittera 1118: dev = (device_t)block->nmb_physdeviceobj->do_devext;
1.3 rittera 1119: #ifdef __FreeBSD__
1120: sc = device_get_softc(dev);
1121: #else /* __NetBSD__ */
1122: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1123: #endif
1.1 rittera 1124:
1125: /*
1126: * I have a test system consisting of a Sun w2100z
1127: * dual 2.4Ghz Opteron machine and an Atheros 802.11a/b/g
1128: * "Aries" miniPCI NIC. (The NIC is installed in the
1129: * machine using a miniPCI to PCI bus adapter card.)
1130: * When running in SMP mode, I found that
1131: * performing a large number of consecutive calls to
1132: * NdisReadPciSlotInformation() would result in a
1133: * sudden system reset (or in some cases a freeze).
1134: * My suspicion is that the multiple reads are somehow
1135: * triggering a fatal PCI bus error that leads to a
1136: * machine check. The 1us delay in the loop below
1137: * seems to prevent this problem.
1138: */
1139:
1.3 rittera 1140: #ifdef __FreeBSD__
1.1 rittera 1141: for (i = 0; i < len; i++) {
1.3 rittera 1142: #else /* __NetBSD__ */
1143: for (i = 0; i < len/4; i += 4) {
1144: #endif
1.1 rittera 1145: DELAY(1);
1.3 rittera 1146: #ifdef __FreeBSD__
1147: dest[i] = pci_read_config(dev, i + offset, 1);
1148: #else
1149: dest[i/4] = pci_conf_read(sc->ndis_res_pc,sc->ndis_res_pctag, (i + offset));
1150: #endif
1151:
1.1 rittera 1152: }
1153:
1154: return(len);
1155: }
1156:
1157: __stdcall static uint32_t
1.5 christos 1158: NdisWritePciSlotInformation(
1159: ndis_handle adapter,
1.6 christos 1160: uint32_t slot,
1.5 christos 1161: uint32_t offset,
1162: void *buf,
1163: uint32_t len)
1.1 rittera 1164: {
1165: ndis_miniport_block *block;
1166: int i;
1.3 rittera 1167: #ifdef __FreeBSD__
1168: char *dest;
1169: #else
1170: pcireg_t *dest;
1171: #endif
1172:
1.1 rittera 1173: device_t dev;
1174:
1.3 rittera 1175: /* PN(NdisWritePciSlotInformation) */
1176:
1.1 rittera 1177: block = (ndis_miniport_block *)adapter;
1178: dest = buf;
1.3 rittera 1179: struct ndis_softc *sc;
1180:
1.1 rittera 1181:
1182: if (block == NULL)
1183: return(0);
1184:
1185: dev = block->nmb_physdeviceobj->do_devext;
1.3 rittera 1186: #ifdef __FreeBSD__
1187: sc = device_get_softc(dev);
1188: #else /* __NetBSD__ */
1189: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1190: #endif
1191:
1192: #ifdef __FreeBSD__
1.1 rittera 1193: for (i = 0; i < len; i++) {
1.3 rittera 1194: #else /* __NetBSD__ */
1195: for (i = 0; i < len/4; i++) {
1196: #endif
1.1 rittera 1197: DELAY(1);
1.3 rittera 1198: #ifdef __FreeBSD__
1199: pci_write_config(dev, i + offset, dest[i], 1);
1200: #else
1201: pci_conf_write(sc->ndis_res_pc,sc->ndis_res_pctag,
1202: (i + offset), dest[i/4]);
1203: #endif
1204:
1.1 rittera 1205: }
1206:
1207: return(len);
1208: }
1209:
1210: /*
1211: * The errorlog routine uses a variable argument list, so we
1212: * have to declare it this way.
1213: */
1214: #define ERRMSGLEN 512
1215: static void
1216: NdisWriteErrorLogEntry(ndis_handle adapter, ndis_error_code code,
1217: uint32_t numerrors, ...)
1218: {
1219: ndis_miniport_block *block;
1220: va_list ap;
1221: int i, error;
1222: char *str = NULL, *ustr = NULL;
1223: uint16_t flags;
1224: char msgbuf[ERRMSGLEN];
1225: device_t dev;
1226: driver_object *drv;
1227:
1.3 rittera 1228: PN(NdisWriteErrorLogEntry)
1229:
1.1 rittera 1230: block = (ndis_miniport_block *)adapter;
1231: dev = block->nmb_physdeviceobj->do_devext;
1232: drv = block->nmb_physdeviceobj->do_drvobj;
1233:
1234: error = pe_get_message((vm_offset_t)drv->dro_driverstart,
1235: code, &str, &i, &flags);
1236: if (error == 0 && flags & MESSAGE_RESOURCE_UNICODE) {
1237: ustr = msgbuf;
1238: ndis_unicode_to_ascii((uint16_t *)str,
1239: ((i / 2)) > (ERRMSGLEN - 1) ? ERRMSGLEN : i, &ustr);
1240: str = ustr;
1241: }
1.3 rittera 1242:
1.4 rittera 1243: printf ("%s: NDIS ERROR: %x (%s)\n", dev->dv_xname, code,
1244: str == NULL ? "unknown error" : str);
1245: printf ("%s: NDIS NUMERRORS: %x\n", dev->dv_xname, numerrors);
1.1 rittera 1246:
1247: va_start(ap, numerrors);
1248: for (i = 0; i < numerrors; i++)
1.4 rittera 1249: printf ("%s: argptr: %p\n",
1250: dev->dv_xname,
1251: va_arg(ap, void *));
1252:
1.1 rittera 1253: va_end(ap);
1254:
1255: return;
1256: }
1257:
1258: static void
1259: ndis_map_cb(arg, segs, nseg, error)
1260: void *arg;
1261: bus_dma_segment_t *segs;
1262: int nseg;
1263: int error;
1264: {
1265: struct ndis_map_arg *ctx;
1266: int i;
1267:
1.3 rittera 1268: PN(ndis_map_cb)
1269:
1.1 rittera 1270: if (error)
1271: return;
1272:
1273: ctx = arg;
1274:
1275: for (i = 0; i < nseg; i++) {
1276: ctx->nma_fraglist[i].npu_physaddr.np_quad = segs[i].ds_addr;
1277: ctx->nma_fraglist[i].npu_len = segs[i].ds_len;
1278: }
1279:
1280: ctx->nma_cnt = nseg;
1281:
1282: return;
1283: }
1284:
1285: __stdcall static void
1286: NdisMStartBufferPhysicalMapping(adapter, buf, mapreg, writedev, addrarray, arraysize)
1287: ndis_handle adapter;
1288: ndis_buffer *buf;
1289: uint32_t mapreg;
1290: uint8_t writedev;
1291: ndis_paddr_unit *addrarray;
1292: uint32_t *arraysize;
1293: {
1294: ndis_miniport_block *block;
1295: struct ndis_softc *sc;
1296: struct ndis_map_arg nma;
1297: bus_dmamap_t map;
1298: int error;
1299:
1.3 rittera 1300: PN(NdisMStartBufferPhysicalMapping)
1301:
1.1 rittera 1302: if (adapter == NULL)
1303: return;
1304:
1305: block = (ndis_miniport_block *)adapter;
1.3 rittera 1306: #ifdef __FreeBSD__
1.1 rittera 1307: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1308: #else /* __NetBSD__ */
1309: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1310: #endif
1.1 rittera 1311:
1312: if (mapreg > sc->ndis_mmapcnt)
1313: return;
1314:
1315: map = sc->ndis_mmaps[mapreg];
1316: nma.nma_fraglist = addrarray;
1317:
1.2 rittera 1318: #ifdef __FreeBSD__
1.1 rittera 1319: error = bus_dmamap_load(sc->ndis_mtag, map,
1320: MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf), ndis_map_cb,
1321: (void *)&nma, BUS_DMA_NOWAIT);
1.2 rittera 1322: #else
1323: error = bus_dmamap_load(sc->ndis_mtag, map,
1324: MmGetMdlVirtualAddress(buf), MmGetMdlByteCount(buf),
1325: NULL /* kernel space */, BUS_DMA_NOWAIT);
1326: /* callback function called "by hand" */
1327: ndis_map_cb((void *)&nma, map->dm_segs, map->dm_nsegs, error);
1328: #endif
1.1 rittera 1329: if (error)
1330: return;
1331:
1.2 rittera 1332: #ifdef __FreeBSD__
1.1 rittera 1333: bus_dmamap_sync(sc->ndis_mtag, map,
1334: writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
1.2 rittera 1335: #else
1336: bus_dmamap_sync(sc->ndis_mtag, map, 0, map->dm_mapsize,
1337: writedev ? BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
1338: #endif
1.1 rittera 1339: *arraysize = nma.nma_cnt;
1340:
1341: return;
1342: }
1343:
1344: __stdcall static void
1.5 christos 1345: NdisMCompleteBufferPhysicalMapping(
1346: ndis_handle adapter,
1.6 christos 1347: ndis_buffer *buf,
1.5 christos 1348: uint32_t mapreg)
1.1 rittera 1349: {
1350: ndis_miniport_block *block;
1351: struct ndis_softc *sc;
1352: bus_dmamap_t map;
1353:
1.3 rittera 1354: PN(NdisMCompleteBufferPhysicalMapping)
1355:
1.1 rittera 1356: if (adapter == NULL)
1357: return;
1358:
1359: block = (ndis_miniport_block *)adapter;
1.3 rittera 1360: #ifdef __FreeBSD__
1.1 rittera 1361: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1362: #else /* __NetBSD__ */
1363: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1364: #endif
1.1 rittera 1365:
1366: if (mapreg > sc->ndis_mmapcnt)
1367: return;
1368:
1369: map = sc->ndis_mmaps[mapreg];
1370:
1.2 rittera 1371: #ifdef __FreeBSD__
1.1 rittera 1372: bus_dmamap_sync(sc->ndis_mtag, map,
1373: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1.2 rittera 1374: #else
1375: bus_dmamap_sync(sc->ndis_mtag, map, 0, map->dm_mapsize,
1376: BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1377: #endif
1.1 rittera 1378: bus_dmamap_unload(sc->ndis_mtag, map);
1379:
1380: return;
1381: }
1382:
1383: /*
1384: * This is an older (?) timer init routine which doesn't
1385: * accept a miniport context handle. Serialized miniports should
1386: * never call this function.
1387: */
1388:
1389: __stdcall static void
1390: NdisInitializeTimer(timer, func, ctx)
1391: ndis_timer *timer;
1392: ndis_timer_function func;
1393: void *ctx;
1394: {
1395: KeInitializeTimer(&timer->nt_ktimer);
1396: KeInitializeDpc(&timer->nt_kdpc, func, ctx);
1397:
1398: return;
1399: }
1400:
1401: __stdcall static void
1402: ndis_timercall(dpc, timer, sysarg1, sysarg2)
1403: kdpc *dpc;
1404: ndis_miniport_timer *timer;
1405: void *sysarg1;
1406: void *sysarg2;
1407: {
1.3 rittera 1408: //PN(ndis_timercall)
1409:
1.1 rittera 1410: /*
1411: * Since we're called as a DPC, we should be running
1412: * at DISPATCH_LEVEL here. This means to acquire the
1413: * spinlock, we can use KeAcquireSpinLockAtDpcLevel()
1414: * rather than KeAcquireSpinLock().
1415: */
1416: if (NDIS_SERIALIZED(timer->nmt_block))
1417: KeAcquireSpinLockAtDpcLevel(&timer->nmt_block->nmb_lock);
1418:
1419: MSCALL4(timer->nmt_timerfunc, dpc, timer->nmt_timerctx,
1420: sysarg1, sysarg2);
1421:
1422: if (NDIS_SERIALIZED(timer->nmt_block))
1423: KeReleaseSpinLockFromDpcLevel(&timer->nmt_block->nmb_lock);
1424:
1425: return;
1426: }
1427:
1428: /*
1429: * For a long time I wondered why there were two NDIS timer initialization
1430: * routines, and why this one needed an NDIS_MINIPORT_TIMER and the
1431: * MiniportAdapterHandle. The NDIS_MINIPORT_TIMER has its own callout
1432: * function and context pointers separate from those in the DPC, which
1433: * allows for another level of indirection: when the timer fires, we
1434: * can have our own timer function invoked, and from there we can call
1435: * the driver's function. But why go to all that trouble? Then it hit
1436: * me: for serialized miniports, the timer callouts are not re-entrant.
1437: * By trapping the callouts and having access to the MiniportAdapterHandle,
1438: * we can protect the driver callouts by acquiring the NDIS serialization
1439: * lock. This is essential for allowing serialized miniports to work
1440: * correctly on SMP systems. On UP hosts, setting IRQL to DISPATCH_LEVEL
1441: * is enough to prevent other threads from pre-empting you, but with
1442: * SMP, you must acquire a lock as well, otherwise the other CPU is
1443: * free to clobber you.
1444: */
1.3 rittera 1445:
1446: /* Just to test out how much memory is wasted*/
1447: int ndis_num_timers_allocated = 0;
1448:
1.1 rittera 1449: __stdcall static void
1450: NdisMInitializeTimer(timer, handle, func, ctx)
1451: ndis_miniport_timer *timer;
1452: ndis_handle handle;
1453: ndis_timer_function func;
1454: void *ctx;
1455: {
1456: /* Save the driver's funcptr and context */
1457:
1.3 rittera 1458: PN(NdisMInitializeTimer)
1459:
1.1 rittera 1460: timer->nmt_timerfunc = func;
1461: timer->nmt_timerctx = ctx;
1462: timer->nmt_block = handle;
1.3 rittera 1463:
1464: #ifdef __NetBSD__
1465: /* TODO: free this memory somewhere! */
1466: printf("Allocating callout struct\n");
1467: if(timer->nmt_ktimer.k_handle == NULL) {
1468: timer->nmt_ktimer.k_handle =
1469: malloc(sizeof(struct callout), M_DEVBUF, M_NOWAIT|M_ZERO);
1470: ndis_num_timers_allocated++;
1471: }
1472: #endif
1.1 rittera 1473:
1474: /*
1475: * Set up the timer so it will call our intermediate DPC.
1476: * Be sure to use the wrapped entry point, since
1477: * ntoskrnl_run_dpc() expects to invoke a function with
1478: * Microsoft calling conventions.
1479: */
1480: KeInitializeTimer(&timer->nmt_ktimer);
1481: KeInitializeDpc(&timer->nmt_kdpc,
1482: ndis_findwrap((funcptr)ndis_timercall), timer);
1483:
1484: return;
1485: }
1486:
1487: /*
1488: * In Windows, there's both an NdisMSetTimer() and an NdisSetTimer(),
1489: * but the former is just a macro wrapper around the latter.
1490: */
1491: __stdcall static void
1492: NdisSetTimer(timer, msecs)
1493: ndis_timer *timer;
1494: uint32_t msecs;
1495: {
1.3 rittera 1496: PN(NdisSetTimer)
1.1 rittera 1497: /*
1498: * KeSetTimer() wants the period in
1499: * hundred nanosecond intervals.
1.3 rittera 1500: */
1.1 rittera 1501: KeSetTimer(&timer->nt_ktimer,
1.3 rittera 1502: ((int64_t)msecs * -10000), &timer->nt_kdpc);
1.1 rittera 1503:
1504: return;
1505: }
1506:
1507: __stdcall static void
1508: NdisMSetPeriodicTimer(timer, msecs)
1509: ndis_miniport_timer *timer;
1510: uint32_t msecs;
1511: {
1.3 rittera 1512: PN(NdisMSetPeriodicTimer)
1513:
1.1 rittera 1514: KeSetTimerEx(&timer->nmt_ktimer,
1515: ((int64_t)msecs * -10000), msecs, &timer->nmt_kdpc);
1516:
1517: return;
1518: }
1519:
1520: /*
1521: * Technically, this is really NdisCancelTimer(), but we also
1522: * (ab)use it for NdisMCancelTimer(), since in our implementation
1523: * we don't need the extra info in the ndis_miniport_timer
1524: * structure just to cancel a timer.
1525: */
1526:
1527: __stdcall static void
1528: NdisMCancelTimer(timer, cancelled)
1529: ndis_timer *timer;
1530: uint8_t *cancelled;
1531: {
1.3 rittera 1532: PN(NdisMCancelTimer)
1.1 rittera 1533: *cancelled = KeCancelTimer(&timer->nt_ktimer);
1534:
1535: return;
1536: }
1537:
1538: __stdcall static void
1539: NdisMQueryAdapterResources(status, adapter, list, buflen)
1540: ndis_status *status;
1541: ndis_handle adapter;
1542: ndis_resource_list *list;
1543: uint32_t *buflen;
1544: {
1545: ndis_miniport_block *block;
1546: struct ndis_softc *sc;
1547: int rsclen;
1548:
1.3 rittera 1549: PN(NdisMQueryAdapterResources)
1550:
1.1 rittera 1551: block = (ndis_miniport_block *)adapter;
1.3 rittera 1552:
1553: #ifdef __FreeBSD__
1.1 rittera 1554: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1555: #else /* __NetBSD__ */
1556: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1557: #endif
1.1 rittera 1558:
1559: rsclen = sizeof(ndis_resource_list) +
1560: (sizeof(cm_partial_resource_desc) * (sc->ndis_rescnt - 1));
1561: if (*buflen < rsclen) {
1562: *buflen = rsclen;
1563: *status = NDIS_STATUS_INVALID_LENGTH;
1564: return;
1565: }
1566:
1.3 rittera 1567: #ifdef __FreeBSD__
1.1 rittera 1568: bcopy((char *)block->nmb_rlist, (char *)list, rsclen);
1.3 rittera 1569: #else /* __NetBSD__ */
1570: memcpy(list, block->nmb_rlist, rsclen);
1571: #endif
1572:
1.1 rittera 1573: *status = NDIS_STATUS_SUCCESS;
1574:
1575: return;
1576: }
1577:
1578: __stdcall static ndis_status
1.5 christos 1579: NdisMRegisterIoPortRange(
1580: void **offset,
1581: ndis_handle adapter,
1.6 christos 1582: uint32_t port,
1.5 christos 1583: uint32_t numports)
1.1 rittera 1584: {
1585: struct ndis_miniport_block *block;
1586: struct ndis_softc *sc;
1587:
1.3 rittera 1588: PN(NdisMRegisterIoPortRange)
1589:
1.1 rittera 1590: if (adapter == NULL)
1591: return(NDIS_STATUS_FAILURE);
1592:
1593: block = (ndis_miniport_block *)adapter;
1.3 rittera 1594: #ifdef __FreeBSD__
1.1 rittera 1595: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1596: #else /* __NetBSD__ */
1597: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1598: #endif
1.1 rittera 1599:
1.3 rittera 1600: #ifdef __FreeBSD__
1.1 rittera 1601: if (sc->ndis_res_io == NULL)
1.3 rittera 1602: #else
1603: if (sc->ndis_res_io == NULL && sc->ndis_iftype != PCMCIABus)
1604: #endif
1.1 rittera 1605: return(NDIS_STATUS_FAILURE);
1606:
1607: /* Don't let the device map more ports than we have. */
1.3 rittera 1608: #ifdef __FreeBSD__
1.1 rittera 1609: if (rman_get_size(sc->ndis_res_io) < numports)
1.3 rittera 1610: #else /* __NetBSD__ */
1611: if ( (sc->ndis_iftype != PCMCIABus && sc->ndis_res_io->res_size < numports)
1612: || (sc->ndis_iftype == PCMCIABus && sc->ndis_res_pcioh.size < numports) )
1613: #endif
1.1 rittera 1614: return(NDIS_STATUS_INVALID_LENGTH);
1.3 rittera 1615:
1616: #ifdef __FreeBSD__
1617: *offset = (void *)rman_get_start(sc->ndis_res_io);
1618: #else /* __NetBSD__ */
1619: switch (sc->ndis_iftype){
1620: case PCIBus:
1621: case CBus: /* CardBus */
1622: *offset = (void*)sc->ndis_res_io->res_base;
1623: break;
1624: case PCMCIABus:
1625: *offset = (void*)sc->ndis_res_pcioh.addr;
1626: break;
1627: default:
1628: return(NDIS_STATUS_FAILURE);
1629: }
1630: #endif /* __NetBSD__ */
1.1 rittera 1631:
1632: return(NDIS_STATUS_SUCCESS);
1633: }
1634:
1635: __stdcall static void
1.5 christos 1636: NdisMDeregisterIoPortRange(
1.6 christos 1637: ndis_handle adapter,
1638: uint32_t port,
1639: uint32_t numports,
1640: void *offset)
1.1 rittera 1641: {
1642: return;
1643: }
1644:
1645: __stdcall static void
1646: NdisReadNetworkAddress(status, addr, addrlen, adapter)
1647: ndis_status *status;
1648: void **addr;
1649: uint32_t *addrlen;
1650: ndis_handle adapter;
1651: {
1652: struct ndis_softc *sc;
1653: ndis_miniport_block *block;
1654: uint8_t empty[] = { 0, 0, 0, 0, 0, 0 };
1.3 rittera 1655:
1656: PN(NdisReadNetworkAddress)
1.1 rittera 1657:
1658: block = (ndis_miniport_block *)adapter;
1.3 rittera 1659: #ifdef __FreeBSD__
1.1 rittera 1660: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1661: #else /* __NetBSD__ */
1662: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1663: #endif
1.1 rittera 1664:
1.2 rittera 1665: #ifdef __FreeBSD__
1.1 rittera 1666: if (bcmp(sc->arpcom.ac_enaddr, empty, ETHER_ADDR_LEN) == 0)
1.2 rittera 1667: #else
1.9 ! dyoung 1668: if (bcmp(CLLADDR(sc->arpcom.ec_if.if_sadl),
1.2 rittera 1669: empty, ETHER_ADDR_LEN) == 0)
1670: #endif
1671:
1.1 rittera 1672: *status = NDIS_STATUS_FAILURE;
1673: else {
1.2 rittera 1674: #ifdef __FreeBSD__
1.1 rittera 1675: *addr = sc->arpcom.ac_enaddr;
1.2 rittera 1676: #else
1677: *addr = LLADDR(sc->arpcom.ec_if.if_sadl);
1678: #endif
1.1 rittera 1679: *addrlen = ETHER_ADDR_LEN;
1680: *status = NDIS_STATUS_SUCCESS;
1681: }
1682:
1683: return;
1684: }
1685:
1686: __stdcall static ndis_status
1.5 christos 1687: NdisQueryMapRegisterCount(
1.6 christos 1688: uint32_t bustype,
1.5 christos 1689: uint32_t *cnt)
1.1 rittera 1690: {
1.3 rittera 1691: PN(NdisQueryMapRegisterCount)
1692:
1.1 rittera 1693: *cnt = 8192;
1694: return(NDIS_STATUS_SUCCESS);
1695: }
1696:
1697: __stdcall static ndis_status
1.5 christos 1698: NdisMAllocateMapRegisters(
1699: ndis_handle adapter,
1.6 christos 1700: uint32_t dmachannel,
1701: uint8_t dmasize,
1.5 christos 1702: uint32_t physmapneeded,
1703: uint32_t maxmap)
1.1 rittera 1704: {
1705: struct ndis_softc *sc;
1706: ndis_miniport_block *block;
1.3 rittera 1707: #ifdef __FreeBSD__
1708: int error;
1709: #endif
1710: int i, nseg = NDIS_MAXSEG;
1.1 rittera 1711:
1.3 rittera 1712: PN(NdisMAllocateMapRegisters)
1713:
1.1 rittera 1714: block = (ndis_miniport_block *)adapter;
1.3 rittera 1715: #ifdef __FreeBSD__
1.1 rittera 1716: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1717: #else /* __NetBSD__ */
1718: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1719: #endif
1.1 rittera 1720:
1721: sc->ndis_mmaps = malloc(sizeof(bus_dmamap_t) * physmapneeded,
1722: M_DEVBUF, M_NOWAIT|M_ZERO);
1723:
1724: if (sc->ndis_mmaps == NULL)
1725: return(NDIS_STATUS_RESOURCES);
1726:
1.2 rittera 1727: #ifdef __FreeBSD__
1.1 rittera 1728: error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
1729: BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL,
1730: NULL, maxmap * nseg, nseg, maxmap, BUS_DMA_ALLOCNOW,
1731: NULL, NULL, &sc->ndis_mtag);
1732:
1733: if (error) {
1734: free(sc->ndis_mmaps, M_DEVBUF);
1735: return(NDIS_STATUS_RESOURCES);
1736: }
1.2 rittera 1737: #else
1738: sc->ndis_mtag = sc->ndis_parent_tag;
1739: #endif
1.3 rittera 1740:
1741: for (i = 0; i < physmapneeded; i++) {
1.2 rittera 1742: #ifdef __FreeBSD__
1.1 rittera 1743: bus_dmamap_create(sc->ndis_mtag, 0, &sc->ndis_mmaps[i]);
1.2 rittera 1744: #else
1745: bus_dmamap_create(sc->ndis_mtag, maxmap * nseg,
1746: nseg, maxmap, BUS_DMA_NOWAIT,
1747: 0, &sc->ndis_mmaps[i]);
1748: #endif
1.3 rittera 1749: }
1.1 rittera 1750:
1751: sc->ndis_mmapcnt = physmapneeded;
1752:
1753: return(NDIS_STATUS_SUCCESS);
1754: }
1755:
1756: __stdcall static void
1757: NdisMFreeMapRegisters(adapter)
1758: ndis_handle adapter;
1759: {
1760: struct ndis_softc *sc;
1761: ndis_miniport_block *block;
1762: int i;
1763:
1.3 rittera 1764: PN(NdisMFreeMapRegisters)
1765:
1.1 rittera 1766: block = (ndis_miniport_block *)adapter;
1.3 rittera 1767: #ifdef __FreeBSD__
1.1 rittera 1768: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1769: #else /* __NetBSD__ */
1770: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1771: #endif
1.1 rittera 1772:
1773: for (i = 0; i < sc->ndis_mmapcnt; i++)
1774: bus_dmamap_destroy(sc->ndis_mtag, sc->ndis_mmaps[i]);
1775:
1776: free(sc->ndis_mmaps, M_DEVBUF);
1777:
1.3 rittera 1778: #ifdef __FreeBSD__
1.1 rittera 1779: bus_dma_tag_destroy(sc->ndis_mtag);
1.3 rittera 1780: #endif
1.1 rittera 1781:
1782: return;
1783: }
1784:
1785: static void
1786: ndis_mapshared_cb(arg, segs, nseg, error)
1787: void *arg;
1788: bus_dma_segment_t *segs;
1789: int nseg;
1790: int error;
1791: {
1792: ndis_physaddr *p;
1793:
1.3 rittera 1794: /* PN(ndis_mapshared_cb) */
1795:
1.1 rittera 1796: if (error || nseg > 1)
1797: return;
1798:
1799: p = arg;
1800:
1801: p->np_quad = segs[0].ds_addr;
1802:
1803: return;
1804: }
1805:
1806: /*
1807: * This maps to bus_dmamem_alloc().
1808: */
1809: __stdcall static void
1.5 christos 1810: NdisMAllocateSharedMemory(
1811: ndis_handle adapter,
1812: uint32_t len,
1.6 christos 1813: uint8_t cached,
1.5 christos 1814: void **vaddr,
1815: ndis_physaddr *paddr)
1.1 rittera 1816: {
1817: ndis_miniport_block *block;
1818: struct ndis_softc *sc;
1819: struct ndis_shmem *sh;
1820: int error;
1.3 rittera 1821: #ifdef __NetBSD__
1.2 rittera 1822: bus_dma_segment_t segs;
1.3 rittera 1823: int nsegs;
1.2 rittera 1824: #endif
1.1 rittera 1825:
1.3 rittera 1826: /* PN(NdisMAllocateSharedMemory) */
1827:
1.1 rittera 1828: if (adapter == NULL)
1829: return;
1830:
1831: block = (ndis_miniport_block *)adapter;
1.3 rittera 1832: #ifdef __FreeBSD__
1.1 rittera 1833: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1834: #else /* __NetBSD__ */
1835: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1836: #endif
1.1 rittera 1837:
1838: sh = malloc(sizeof(struct ndis_shmem), M_DEVBUF, M_NOWAIT|M_ZERO);
1839: if (sh == NULL)
1840: return;
1841:
1842: /*
1843: * When performing shared memory allocations, create a tag
1844: * with a lowaddr limit that restricts physical memory mappings
1845: * so that they all fall within the first 1GB of memory.
1846: * At least one device/driver combination (Linksys Instant
1847: * Wireless PCI Card V2.7, Broadcom 802.11b) seems to have
1848: * problems with performing DMA operations with physical
1849: * addresses that lie above the 1GB mark. I don't know if this
1850: * is a hardware limitation or if the addresses are being
1851: * truncated within the driver, but this seems to be the only
1852: * way to make these cards work reliably in systems with more
1853: * than 1GB of physical memory.
1854: */
1855:
1.2 rittera 1856: #ifdef __FreeBSD__
1.1 rittera 1857: error = bus_dma_tag_create(sc->ndis_parent_tag, 64,
1858: 0, NDIS_BUS_SPACE_SHARED_MAXADDR, BUS_SPACE_MAXADDR, NULL,
1859: NULL, len, 1, len, BUS_DMA_ALLOCNOW, NULL, NULL,
1860: &sh->ndis_stag);
1861:
1862: if (error) {
1863: free(sh, M_DEVBUF);
1864: return;
1865: }
1866:
1867: error = bus_dmamem_alloc(sh->ndis_stag, vaddr,
1868: BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sh->ndis_smap);
1869:
1870: if (error) {
1871: bus_dma_tag_destroy(sh->ndis_stag);
1872: free(sh, M_DEVBUF);
1873: return;
1874: }
1875:
1876: error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, *vaddr,
1877: len, ndis_mapshared_cb, (void *)paddr, BUS_DMA_NOWAIT);
1878:
1879: if (error) {
1880: bus_dmamem_free(sh->ndis_stag, *vaddr, sh->ndis_smap);
1881: bus_dma_tag_destroy(sh->ndis_stag);
1882: free(sh, M_DEVBUF);
1883: return;
1884: }
1.2 rittera 1885: #else
1.3 rittera 1886: sh->ndis_stag = sc->ndis_parent_tag;
1887:
1.2 rittera 1888: error = bus_dmamem_alloc(sh->ndis_stag, len, 64, 0,
1889: &segs, 1, &nsegs, BUS_DMA_NOWAIT);
1.3 rittera 1890:
1.2 rittera 1891: if (error) {
1892: printf("bus_dmamem_alloc failed(1)\n");
1893: return;
1894: }
1895:
1896: error = bus_dmamem_map(sh->ndis_stag, &segs, nsegs,
1.7 christos 1897: len, /*(void **)&vaddr*/ (void **)vaddr, BUS_DMA_NOWAIT);
1.2 rittera 1898:
1.3 rittera 1899: /* printf("*vaddr = %x\n", (unsigned int)*vaddr); */
1900:
1.2 rittera 1901: if (error) {
1902: printf("bus_dmamem_alloc failed(2)\n");
1903: /* XXX free */
1904: return;
1905: }
1906:
1907: error = bus_dmamap_create(sh->ndis_stag, len, nsegs,
1908: BUS_SPACE_MAXSIZE_32BIT, 0,
1.3 rittera 1909: BUS_DMA_ALLOCNOW, &sh->ndis_smap);
1.2 rittera 1910:
1911: if (error) {
1912: printf("bus_dmamem_alloc failed(3)\n");
1913: /* XXX free, unmap */
1914: return;
1915: }
1.3 rittera 1916:
1917: error = bus_dmamap_load(sh->ndis_stag, sh->ndis_smap, /*vaddr*/ *vaddr,
1.2 rittera 1918: len, NULL, BUS_DMA_NOWAIT);
1919: ndis_mapshared_cb((void *)paddr,
1920: sh->ndis_smap->dm_segs,
1921: sh->ndis_smap->dm_nsegs, error);
1922:
1923: if (error) {
1924: printf("bus_dmamem_alloc failed(3)\n");
1925: /* XXX free, unmap, destroy */
1926: return;
1927: }
1928: #endif
1.1 rittera 1929:
1930: sh->ndis_saddr = *vaddr;
1931: sh->ndis_next = sc->ndis_shlist;
1932: sc->ndis_shlist = sh;
1933:
1934: return;
1935: }
1936:
1937: struct ndis_allocwork {
1938: ndis_handle na_adapter;
1939: uint32_t na_len;
1940: uint8_t na_cached;
1941: void *na_ctx;
1942: };
1943:
1944: static void
1945: ndis_asyncmem_complete(arg)
1946: void *arg;
1947: {
1948: ndis_miniport_block *block;
1949: struct ndis_softc *sc;
1950: struct ndis_allocwork *w;
1951: void *vaddr;
1952: ndis_physaddr paddr;
1953: __stdcall ndis_allocdone_handler donefunc;
1954:
1955: w = arg;
1956: block = (ndis_miniport_block *)w->na_adapter;
1.3 rittera 1957: #ifdef __FreeBSD__
1.1 rittera 1958: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 1959: #else /* __NetBSD__ */
1960: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
1961: #endif
1962:
1963: PN(ndis_asyncmem_complete)
1.1 rittera 1964:
1965: vaddr = NULL;
1966: paddr.np_quad = 0;
1967:
1968: donefunc = sc->ndis_chars->nmc_allocate_complete_func;
1969: NdisMAllocateSharedMemory(w->na_adapter, w->na_len,
1970: w->na_cached, &vaddr, &paddr);
1971: MSCALL5(donefunc, w->na_adapter, vaddr, &paddr, w->na_len, w->na_ctx);
1972:
1973: free(arg, M_DEVBUF);
1974:
1975: return;
1976: }
1977:
1978: __stdcall static ndis_status
1979: NdisMAllocateSharedMemoryAsync(adapter, len, cached, ctx)
1980: ndis_handle adapter;
1981: uint32_t len;
1982: uint8_t cached;
1983: void *ctx;
1984: {
1985: struct ndis_allocwork *w;
1986:
1.3 rittera 1987: PN(NdisMAllocateSharedMemoryAsync)
1988:
1.1 rittera 1989: if (adapter == NULL)
1990: return(NDIS_STATUS_FAILURE);
1991:
1992: w = malloc(sizeof(struct ndis_allocwork), M_TEMP, M_NOWAIT);
1993:
1994: if (w == NULL)
1995: return(NDIS_STATUS_FAILURE);
1996:
1997: w->na_adapter = adapter;
1998: w->na_cached = cached;
1999: w->na_len = len;
2000: w->na_ctx = ctx;
2001:
2002: /*
2003: * Pawn this work off on the SWI thread instead of the
2004: * taskqueue thread, because sometimes drivers will queue
2005: * up work items on the taskqueue thread that will block,
2006: * which would prevent the memory allocation from completing
2007: * when we need it.
2008: */
2009: ndis_sched(ndis_asyncmem_complete, w, NDIS_SWI);
2010:
2011: return(NDIS_STATUS_PENDING);
2012: }
2013:
2014: __stdcall static void
1.5 christos 2015: NdisMFreeSharedMemory(
2016: ndis_handle adapter,
1.6 christos 2017: uint32_t len,
2018: uint8_t cached,
1.5 christos 2019: void *vaddr,
1.6 christos 2020: ndis_physaddr paddr)
1.1 rittera 2021: {
2022: ndis_miniport_block *block;
2023: struct ndis_softc *sc;
2024: struct ndis_shmem *sh, *prev;
2025:
1.3 rittera 2026: PN(NdisMFreeSharedMemory)
2027:
1.1 rittera 2028: if (vaddr == NULL || adapter == NULL)
2029: return;
2030:
2031: block = (ndis_miniport_block *)adapter;
1.3 rittera 2032: #ifdef __FreeBSD__
1.1 rittera 2033: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2034: #else /* __NetBSD__ */
2035: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2036: #endif
1.1 rittera 2037: sh = prev = sc->ndis_shlist;
2038:
2039: /* Sanity check: is list empty? */
2040:
2041: if (sh == NULL)
2042: return;
2043:
2044: while (sh) {
2045: if (sh->ndis_saddr == vaddr)
2046: break;
2047: prev = sh;
2048: sh = sh->ndis_next;
2049: }
2050:
2051: bus_dmamap_unload(sh->ndis_stag, sh->ndis_smap);
1.2 rittera 2052: #ifdef __FreeBSD__
1.1 rittera 2053: bus_dmamem_free(sh->ndis_stag, vaddr, sh->ndis_smap);
1.3 rittera 2054: bus_dma_tag_destroy(sh->ndis_stag);
1.2 rittera 2055: #else
2056: bus_dmamem_unmap(sh->ndis_stag, vaddr, sh->ndis_smap->dm_mapsize);
2057: bus_dmamem_free(sh->ndis_stag,
2058: sh->ndis_smap->dm_segs, sh->ndis_smap->dm_nsegs );
2059: #endif
1.1 rittera 2060: if (sh == sc->ndis_shlist)
2061: sc->ndis_shlist = sh->ndis_next;
2062: else
2063: prev->ndis_next = sh->ndis_next;
2064:
2065: free(sh, M_DEVBUF);
2066:
2067: return;
2068: }
2069:
2070: __stdcall static ndis_status
1.5 christos 2071: NdisMMapIoSpace(
2072: void **vaddr,
2073: ndis_handle adapter,
2074: ndis_physaddr paddr,
1.6 christos 2075: uint32_t len)
1.1 rittera 2076: {
2077: ndis_miniport_block *block;
2078: struct ndis_softc *sc;
2079:
1.3 rittera 2080: PN(NdisMMapIoSpace)
2081:
1.1 rittera 2082: if (adapter == NULL)
2083: return(NDIS_STATUS_FAILURE);
2084:
2085: block = (ndis_miniport_block *)adapter;
1.3 rittera 2086: #ifdef __FreeBSD__
1.1 rittera 2087: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2088: #else /* __NetBSD__ */
2089: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2090: #endif
2091:
1.1 rittera 2092:
1.3 rittera 2093: #ifdef __FreeBSD__
1.1 rittera 2094: if (sc->ndis_res_mem != NULL &&
2095: paddr.np_quad == rman_get_start(sc->ndis_res_mem))
2096: *vaddr = (void *)rman_get_virtual(sc->ndis_res_mem);
2097: else if (sc->ndis_res_altmem != NULL &&
2098: paddr.np_quad == rman_get_start(sc->ndis_res_altmem))
2099: *vaddr = (void *)rman_get_virtual(sc->ndis_res_altmem);
2100: else if (sc->ndis_res_am != NULL &&
2101: paddr.np_quad == rman_get_start(sc->ndis_res_am))
2102: *vaddr = (void *)rman_get_virtual(sc->ndis_res_am);
2103: else
2104: return(NDIS_STATUS_FAILURE);
1.3 rittera 2105: #else
2106: /* TODO: add one for sc->ndis_res_am once PCMCIA is going */
2107: if (sc->ndis_res_mem != NULL &&
2108: paddr.np_quad == sc->ndis_res_mem->res_base)
2109: *vaddr = bus_space_vaddr(sc->ndis_res_mem->res_tag,
2110: sc->ndis_res_mem->res_handle);
2111: else if (sc->ndis_res_altmem != NULL &&
2112: paddr.np_quad == sc->ndis_res_altmem->res_base)
2113: *vaddr = bus_space_vaddr(sc->ndis_res_altmem->res_tag,
2114: sc->ndis_res_altmem->res_handle);
2115: else
2116: return(NDIS_STATUS_FAILURE);
2117: /*
2118: *vaddr = bus_space_vaddr(sc->ndis_res_mem->res_tag,
2119: sc->ndis_res_mem->res_handle);
2120: */
2121: #endif
1.1 rittera 2122:
2123: return(NDIS_STATUS_SUCCESS);
2124: }
2125:
2126: __stdcall static void
1.5 christos 2127: NdisMUnmapIoSpace(
1.6 christos 2128: ndis_handle adapter,
2129: void *vaddr,
2130: uint32_t len)
1.1 rittera 2131: {
2132: return;
2133: }
2134:
2135: __stdcall static uint32_t
2136: NdisGetCacheFillSize(void)
2137: {
2138: return(128);
2139: }
2140:
2141: __stdcall static uint32_t
1.6 christos 2142: NdisMGetDmaAlignment(ndis_handle handle)
1.1 rittera 2143: {
2144: return(128);
2145: }
2146:
2147: /*
2148: * NDIS has two methods for dealing with NICs that support DMA.
2149: * One is to just pass packets to the driver and let it call
2150: * NdisMStartBufferPhysicalMapping() to map each buffer in the packet
2151: * all by itself, and the other is to let the NDIS library handle the
2152: * buffer mapping internally, and hand the driver an already populated
2153: * scatter/gather fragment list. If the driver calls
2154: * NdisMInitializeScatterGatherDma(), it wants to use the latter
2155: * method.
2156: */
2157:
2158: __stdcall static ndis_status
1.5 christos 2159: NdisMInitializeScatterGatherDma(
2160: ndis_handle adapter,
1.6 christos 2161: uint8_t is64,
2162: uint32_t maxphysmap)
1.1 rittera 2163: {
2164: struct ndis_softc *sc;
2165: ndis_miniport_block *block;
1.3 rittera 2166: #ifdef __FreeBSD__
1.1 rittera 2167: int error;
1.3 rittera 2168: #endif
2169:
2170: PN(NdisMInitializeScatterGatherDma)
1.1 rittera 2171:
2172: if (adapter == NULL)
2173: return(NDIS_STATUS_FAILURE);
2174: block = (ndis_miniport_block *)adapter;
1.3 rittera 2175: #ifdef __FreeBSD__
1.1 rittera 2176: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2177: #else /* __NetBSD__ */
2178: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2179: #endif
1.1 rittera 2180:
2181: /* Don't do this twice. */
2182: if (sc->ndis_sc == 1)
2183: return(NDIS_STATUS_SUCCESS);
2184:
1.3 rittera 2185: #ifdef __FreeBSD__
1.1 rittera 2186: error = bus_dma_tag_create(sc->ndis_parent_tag, ETHER_ALIGN, 0,
2187: BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
2188: MCLBYTES * NDIS_MAXSEG, NDIS_MAXSEG, MCLBYTES, BUS_DMA_ALLOCNOW,
2189: NULL, NULL, &sc->ndis_ttag);
1.3 rittera 2190: #else /* __NetBSD__ */
2191: /* TODO: Is this correct to just use the parent tag? */
2192: sc->ndis_ttag = sc->ndis_parent_tag;
2193: #endif
1.1 rittera 2194:
2195: sc->ndis_sc = 1;
2196:
2197: return(NDIS_STATUS_SUCCESS);
2198: }
2199:
2200: __stdcall void
2201: NdisAllocatePacketPool(status, pool, descnum, protrsvdlen)
2202: ndis_status *status;
2203: ndis_handle *pool;
2204: uint32_t descnum;
2205: uint32_t protrsvdlen;
2206: {
2207: ndis_packet *cur;
2208: int i;
1.3 rittera 2209:
2210: PN(NdisAllocatePacketPool)
1.1 rittera 2211:
2212: *pool = malloc((sizeof(ndis_packet) + protrsvdlen) *
2213: ((descnum + NDIS_POOL_EXTRA) + 1),
2214: M_DEVBUF, M_NOWAIT|M_ZERO);
2215:
2216: if (*pool == NULL) {
2217: *status = NDIS_STATUS_RESOURCES;
2218: return;
2219: }
2220:
2221: cur = (ndis_packet *)*pool;
2222: KeInitializeSpinLock(&cur->np_lock);
2223: cur->np_private.npp_flags = 0x1; /* mark the head of the list */
2224: cur->np_private.npp_totlen = 0; /* init deletetion flag */
2225: for (i = 0; i < (descnum + NDIS_POOL_EXTRA); i++) {
2226: cur->np_private.npp_head = (ndis_handle)(cur + 1);
2227: cur++;
2228: }
2229:
2230: *status = NDIS_STATUS_SUCCESS;
2231: return;
2232: }
2233:
2234: __stdcall void
2235: NdisAllocatePacketPoolEx(status, pool, descnum, oflowdescnum, protrsvdlen)
2236: ndis_status *status;
2237: ndis_handle *pool;
2238: uint32_t descnum;
2239: uint32_t oflowdescnum;
2240: uint32_t protrsvdlen;
2241: {
2242: return(NdisAllocatePacketPool(status, pool,
2243: descnum + oflowdescnum, protrsvdlen));
2244: }
2245:
2246: __stdcall uint32_t
2247: NdisPacketPoolUsage(pool)
2248: ndis_handle pool;
2249: {
2250: ndis_packet *head;
2251: uint8_t irql;
2252: uint32_t cnt;
2253:
2254: head = (ndis_packet *)pool;
2255: KeAcquireSpinLock(&head->np_lock, &irql);
2256: cnt = head->np_private.npp_count;
2257: KeReleaseSpinLock(&head->np_lock, irql);
2258:
2259: return(cnt);
2260: }
2261:
2262: __stdcall void
2263: NdisFreePacketPool(pool)
2264: ndis_handle pool;
2265: {
2266: ndis_packet *head;
2267: uint8_t irql;
2268:
2269: head = pool;
2270:
2271: /* Mark this pool as 'going away.' */
2272:
2273: KeAcquireSpinLock(&head->np_lock, &irql);
2274: head->np_private.npp_totlen = 1;
2275:
2276: /* If there are no buffers loaned out, destroy the pool. */
2277:
2278: if (head->np_private.npp_count == 0) {
2279: KeReleaseSpinLock(&head->np_lock, irql);
2280: free(pool, M_DEVBUF);
2281: } else {
2282: printf("NDIS: buggy driver deleting active packet pool!\n");
2283: KeReleaseSpinLock(&head->np_lock, irql);
2284: }
2285:
2286: return;
2287: }
2288:
2289: __stdcall void
2290: NdisAllocatePacket(status, packet, pool)
2291: ndis_status *status;
2292: ndis_packet **packet;
2293: ndis_handle pool;
2294: {
2295: ndis_packet *head, *pkt;
2296: uint8_t irql;
2297:
1.3 rittera 2298: #ifdef __NetBSD__
2299: /*TODO: For some reason NdisAllocatePacket was getting called once with pool being NULL
2300: *TODO: and this was causing a seg-fault. This seems to solve the problem, but I'm not
2301: *TODO: should happen at all in the first place.
2302: */
2303: if(pool == NULL) {
2304: *status = NDIS_STATUS_FAILURE;
2305: return;
2306: }
2307: #endif
2308:
1.1 rittera 2309: head = (ndis_packet *)pool;
2310: KeAcquireSpinLock(&head->np_lock, &irql);
2311:
2312: if (head->np_private.npp_flags != 0x1) {
2313: *status = NDIS_STATUS_FAILURE;
2314: KeReleaseSpinLock(&head->np_lock, irql);
2315: return;
2316: }
2317:
2318: /*
2319: * If this pool is marked as 'going away' don't allocate any
2320: * more packets out of it.
2321: */
2322:
2323: if (head->np_private.npp_totlen) {
2324: *status = NDIS_STATUS_FAILURE;
2325: KeReleaseSpinLock(&head->np_lock, irql);
2326: return;
2327: }
2328:
2329: pkt = (ndis_packet *)head->np_private.npp_head;
2330:
2331: if (pkt == NULL) {
2332: *status = NDIS_STATUS_RESOURCES;
2333: KeReleaseSpinLock(&head->np_lock, irql);
2334: return;
2335: }
2336:
2337: head->np_private.npp_head = pkt->np_private.npp_head;
2338:
2339: pkt->np_private.npp_head = pkt->np_private.npp_tail = NULL;
2340: /* Save pointer to the pool. */
2341: pkt->np_private.npp_pool = head;
2342:
2343: /* Set the oob offset pointer. Lots of things expect this. */
2344: pkt->np_private.npp_packetooboffset =
2345: offsetof(ndis_packet, np_oob);
2346:
2347: /*
2348: * We must initialize the packet flags correctly in order
2349: * for the NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO() and
2350: * NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO() macros to work
2351: * correctly.
2352: */
2353: pkt->np_private.npp_ndispktflags = NDIS_PACKET_ALLOCATED_BY_NDIS;
2354: pkt->np_private.npp_validcounts = FALSE;
2355:
2356: *packet = pkt;
2357:
2358: head->np_private.npp_count++;
2359: *status = NDIS_STATUS_SUCCESS;
2360:
2361: KeReleaseSpinLock(&head->np_lock, irql);
2362:
2363: return;
2364: }
2365:
2366: __stdcall void
2367: NdisFreePacket(packet)
2368: ndis_packet *packet;
2369: {
2370: ndis_packet *head;
2371: uint8_t irql;
2372:
2373: if (packet == NULL || packet->np_private.npp_pool == NULL)
2374: return;
2375:
2376: head = packet->np_private.npp_pool;
2377: KeAcquireSpinLock(&head->np_lock, &irql);
2378:
2379: if (head->np_private.npp_flags != 0x1) {
2380: KeReleaseSpinLock(&head->np_lock, irql);
2381: return;
2382: }
2383:
2384: packet->np_private.npp_head = head->np_private.npp_head;
2385: head->np_private.npp_head = (ndis_buffer *)packet;
2386: head->np_private.npp_count--;
2387:
2388: /*
2389: * If the pool has been marked for deletion and there are
2390: * no more packets outstanding, nuke the pool.
2391: */
2392:
2393: if (head->np_private.npp_totlen && head->np_private.npp_count == 0) {
2394: KeReleaseSpinLock(&head->np_lock, irql);
2395: free(head, M_DEVBUF);
2396: } else
2397: KeReleaseSpinLock(&head->np_lock, irql);
2398:
2399: return;
2400: }
2401:
2402: __stdcall static void
2403: NdisUnchainBufferAtFront(packet, buf)
2404: ndis_packet *packet;
2405: ndis_buffer **buf;
2406: {
2407: ndis_packet_private *priv;
2408:
2409: if (packet == NULL || buf == NULL)
2410: return;
2411:
2412: priv = &packet->np_private;
2413:
2414: priv->npp_validcounts = FALSE;
2415:
2416: if (priv->npp_head == priv->npp_tail) {
2417: *buf = priv->npp_head;
2418: priv->npp_head = priv->npp_tail = NULL;
2419: } else {
2420: *buf = priv->npp_head;
2421: priv->npp_head = (*buf)->mdl_next;
2422: }
2423:
2424: return;
2425: }
2426:
2427: __stdcall static void
2428: NdisUnchainBufferAtBack(packet, buf)
2429: ndis_packet *packet;
2430: ndis_buffer **buf;
2431: {
2432: ndis_packet_private *priv;
2433: ndis_buffer *tmp;
2434:
2435: if (packet == NULL || buf == NULL)
2436: return;
2437:
2438: priv = &packet->np_private;
2439:
2440: priv->npp_validcounts = FALSE;
2441:
2442: if (priv->npp_head == priv->npp_tail) {
2443: *buf = priv->npp_head;
2444: priv->npp_head = priv->npp_tail = NULL;
2445: } else {
2446: *buf = priv->npp_tail;
2447: tmp = priv->npp_head;
2448: while (tmp->mdl_next != priv->npp_tail)
2449: tmp = tmp->mdl_next;
2450: priv->npp_tail = tmp;
2451: tmp->mdl_next = NULL;
2452: }
2453:
2454: return;
2455: }
2456:
2457: /*
2458: * The NDIS "buffer" is really an MDL (memory descriptor list)
2459: * which is used to describe a buffer in a way that allows it
2460: * to mapped into different contexts. We have to be careful how
2461: * we handle them: in some versions of Windows, the NdisFreeBuffer()
2462: * routine is an actual function in the NDIS API, but in others
2463: * it's just a macro wrapper around IoFreeMdl(). There's really
2464: * no way to use the 'descnum' parameter to count how many
2465: * "buffers" are allocated since in order to use IoFreeMdl() to
2466: * dispose of a buffer, we have to use IoAllocateMdl() to allocate
2467: * them, and IoAllocateMdl() just grabs them out of the heap.
2468: */
2469:
2470: __stdcall static void
1.5 christos 2471: NdisAllocateBufferPool(
2472: ndis_status *status,
2473: ndis_handle *pool,
1.6 christos 2474: uint32_t descnum)
1.1 rittera 2475: {
2476: /*
2477: * The only thing we can really do here is verify that descnum
2478: * is a reasonable value, but I really don't know what to check
2479: * it against.
2480: */
2481:
2482: *pool = NonPagedPool;
2483: *status = NDIS_STATUS_SUCCESS;
2484: return;
2485: }
2486:
2487: __stdcall static void
1.6 christos 2488: NdisFreeBufferPool(ndis_handle pool)
1.1 rittera 2489: {
2490: return;
2491: }
2492:
2493: __stdcall static void
1.5 christos 2494: NdisAllocateBuffer(
2495: ndis_status *status,
2496: ndis_buffer **buffer,
1.6 christos 2497: ndis_handle pool,
1.5 christos 2498: void *vaddr,
2499: uint32_t len)
1.1 rittera 2500: {
2501: ndis_buffer *buf;
2502:
2503: buf = IoAllocateMdl(vaddr, len, FALSE, FALSE, NULL);
2504: if (buf == NULL) {
2505: *status = NDIS_STATUS_RESOURCES;
2506: return;
2507: }
2508:
2509: *buffer = buf;
2510: *status = NDIS_STATUS_SUCCESS;
2511:
2512: return;
2513: }
2514:
2515: __stdcall static void
2516: NdisFreeBuffer(buf)
2517: ndis_buffer *buf;
2518: {
2519: IoFreeMdl(buf);
2520: return;
2521: }
2522:
2523: /* Aw c'mon. */
2524:
2525: __stdcall static uint32_t
2526: NdisBufferLength(buf)
2527: ndis_buffer *buf;
2528: {
2529: return(MmGetMdlByteCount(buf));
2530: }
2531:
2532: /*
2533: * Get the virtual address and length of a buffer.
2534: * Note: the vaddr argument is optional.
2535: */
2536:
2537: __stdcall static void
2538: NdisQueryBuffer(buf, vaddr, len)
2539: ndis_buffer *buf;
2540: void **vaddr;
2541: uint32_t *len;
2542: {
2543: if (vaddr != NULL)
2544: *vaddr = MmGetMdlVirtualAddress(buf);
2545: *len = MmGetMdlByteCount(buf);
2546:
2547: return;
2548: }
2549:
2550: /* Same as above -- we don't care about the priority. */
2551:
2552: __stdcall static void
1.5 christos 2553: NdisQueryBufferSafe(
2554: ndis_buffer *buf,
2555: void **vaddr,
2556: uint32_t *len,
1.6 christos 2557: uint32_t prio)
1.1 rittera 2558: {
2559: if (vaddr != NULL)
2560: *vaddr = MmGetMdlVirtualAddress(buf);
2561: *len = MmGetMdlByteCount(buf);
2562:
2563: return;
2564: }
2565:
2566: /* Damnit Microsoft!! How many ways can you do the same thing?! */
2567:
2568: __stdcall static void *
2569: NdisBufferVirtualAddress(buf)
2570: ndis_buffer *buf;
2571: {
2572: return(MmGetMdlVirtualAddress(buf));
2573: }
2574:
2575: __stdcall static void *
1.5 christos 2576: NdisBufferVirtualAddressSafe(
2577: ndis_buffer *buf,
1.6 christos 2578: uint32_t prio)
1.1 rittera 2579: {
2580: return(MmGetMdlVirtualAddress(buf));
2581: }
2582:
2583: __stdcall static void
2584: NdisAdjustBufferLength(buf, len)
2585: ndis_buffer *buf;
2586: int len;
2587: {
2588: MmGetMdlByteCount(buf) = len;
2589:
2590: return;
2591: }
2592:
2593: __stdcall static uint32_t
2594: NdisInterlockedIncrement(addend)
2595: uint32_t *addend;
2596: {
2597: atomic_add_long((u_long *)addend, 1);
2598: return(*addend);
2599: }
2600:
2601: __stdcall static uint32_t
2602: NdisInterlockedDecrement(addend)
2603: uint32_t *addend;
2604: {
2605: atomic_subtract_long((u_long *)addend, 1);
2606: return(*addend);
2607: }
2608:
2609: __stdcall static void
2610: NdisInitializeEvent(event)
2611: ndis_event *event;
2612: {
2613: /*
2614: * NDIS events are always notification
2615: * events, and should be initialized to the
2616: * not signaled state.
2617: */
2618:
2619: KeInitializeEvent(&event->ne_event, EVENT_TYPE_NOTIFY, FALSE);
2620: return;
2621: }
2622:
2623: __stdcall static void
2624: NdisSetEvent(event)
2625: ndis_event *event;
2626: {
2627: KeSetEvent(&event->ne_event, 0, 0);
2628: return;
2629: }
2630:
2631: __stdcall static void
2632: NdisResetEvent(event)
2633: ndis_event *event;
2634: {
2635: KeResetEvent(&event->ne_event);
2636: return;
2637: }
2638:
2639: __stdcall static uint8_t
2640: NdisWaitEvent(event, msecs)
2641: ndis_event *event;
2642: uint32_t msecs;
2643: {
2644: int64_t duetime;
2645: uint32_t rval;
2646:
2647: duetime = ((int64_t)msecs * -10000);
2648:
2649: rval = KeWaitForSingleObject((nt_dispatch_header *)event,
2650: 0, 0, TRUE, msecs ? &duetime : NULL);
2651:
2652: if (rval == STATUS_TIMEOUT)
2653: return(FALSE);
2654:
2655: return(TRUE);
2656: }
2657:
2658: __stdcall static ndis_status
2659: NdisUnicodeStringToAnsiString(dstr, sstr)
2660: ndis_ansi_string *dstr;
2661: ndis_unicode_string *sstr;
2662: {
2663: if (dstr == NULL || sstr == NULL)
2664: return(NDIS_STATUS_FAILURE);
2665: if (ndis_unicode_to_ascii(sstr->us_buf,
2666: sstr->us_len, &dstr->nas_buf))
2667: return(NDIS_STATUS_FAILURE);
2668: dstr->nas_len = dstr->nas_maxlen = strlen(dstr->nas_buf);
2669: return (NDIS_STATUS_SUCCESS);
2670: }
2671:
2672: __stdcall static ndis_status
2673: NdisAnsiStringToUnicodeString(dstr, sstr)
2674: ndis_unicode_string *dstr;
2675: ndis_ansi_string *sstr;
2676: {
2677: char *str;
2678: if (dstr == NULL || sstr == NULL)
2679: return(NDIS_STATUS_FAILURE);
2680: str = malloc(sstr->nas_len + 1, M_DEVBUF, M_NOWAIT);
2681: if (str == NULL)
2682: return(NDIS_STATUS_FAILURE);
2683: strncpy(str, sstr->nas_buf, sstr->nas_len);
2684: *(str + sstr->nas_len) = '\0';
2685: if (ndis_ascii_to_unicode(str, &dstr->us_buf)) {
2686: free(str, M_DEVBUF);
2687: return(NDIS_STATUS_FAILURE);
2688: }
2689: dstr->us_len = dstr->us_maxlen = sstr->nas_len * 2;
2690: free(str, M_DEVBUF);
2691: return (NDIS_STATUS_SUCCESS);
2692: }
2693:
2694: __stdcall static ndis_status
1.5 christos 2695: NdisMPciAssignResources(
2696: ndis_handle adapter,
1.6 christos 2697: uint32_t slot,
1.5 christos 2698: ndis_resource_list **list)
1.1 rittera 2699: {
2700: ndis_miniport_block *block;
2701:
2702: if (adapter == NULL || list == NULL)
2703: return (NDIS_STATUS_FAILURE);
2704:
2705: block = (ndis_miniport_block *)adapter;
2706: *list = block->nmb_rlist;
2707:
2708: return (NDIS_STATUS_SUCCESS);
2709: }
2710:
2711: __stdcall static ndis_status
1.5 christos 2712: NdisMRegisterInterrupt(
2713: ndis_miniport_interrupt *intr,
2714: ndis_handle adapter,
1.6 christos 2715: uint32_t ivec,
2716: uint32_t ilevel,
1.5 christos 2717: uint8_t reqisr,
2718: uint8_t shared,
1.6 christos 2719: ndis_interrupt_mode imode)
1.1 rittera 2720: {
2721: ndis_miniport_block *block;
2722:
2723: block = adapter;
2724:
2725: intr->ni_block = adapter;
2726: intr->ni_isrreq = reqisr;
2727: intr->ni_shared = shared;
2728: block->nmb_interrupt = intr;
2729:
2730: KeInitializeSpinLock(&intr->ni_dpccountlock);
2731:
2732: return(NDIS_STATUS_SUCCESS);
2733: }
2734:
2735: __stdcall static void
1.6 christos 2736: NdisMDeregisterInterrupt(ndis_miniport_interrupt *intr)
1.1 rittera 2737: {
2738: return;
2739: }
2740:
2741: __stdcall static void
2742: NdisMRegisterAdapterShutdownHandler(adapter, shutdownctx, shutdownfunc)
2743: ndis_handle adapter;
2744: void *shutdownctx;
2745: ndis_shutdown_handler shutdownfunc;
2746: {
2747: ndis_miniport_block *block;
2748: ndis_miniport_characteristics *chars;
2749: struct ndis_softc *sc;
2750:
2751: if (adapter == NULL)
2752: return;
2753:
2754: block = (ndis_miniport_block *)adapter;
1.3 rittera 2755: #ifdef __FreeBSD__
1.1 rittera 2756: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2757: #else /* __NetBSD__ */
2758: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2759: #endif
1.1 rittera 2760: chars = sc->ndis_chars;
2761:
2762: chars->nmc_shutdown_handler = shutdownfunc;
2763: chars->nmc_rsvd0 = shutdownctx;
2764:
2765: return;
2766: }
2767:
2768: __stdcall static void
2769: NdisMDeregisterAdapterShutdownHandler(adapter)
2770: ndis_handle adapter;
2771: {
2772: ndis_miniport_block *block;
2773: ndis_miniport_characteristics *chars;
2774: struct ndis_softc *sc;
2775:
2776: if (adapter == NULL)
2777: return;
2778:
2779: block = (ndis_miniport_block *)adapter;
1.3 rittera 2780: #ifdef __FreeBSD__
1.1 rittera 2781: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2782: #else /* __NetBSD__ */
2783: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2784: #endif
1.1 rittera 2785: chars = sc->ndis_chars;
2786:
2787: chars->nmc_shutdown_handler = NULL;
2788: chars->nmc_rsvd0 = NULL;
2789:
2790: return;
2791: }
2792:
2793: __stdcall static uint32_t
2794: NDIS_BUFFER_TO_SPAN_PAGES(buf)
2795: ndis_buffer *buf;
2796: {
2797: if (buf == NULL)
2798: return(0);
2799: if (MmGetMdlByteCount(buf) == 0)
2800: return(1);
2801: return(SPAN_PAGES(MmGetMdlVirtualAddress(buf),
2802: MmGetMdlByteCount(buf)));
2803: }
2804:
2805: __stdcall static void
2806: NdisGetBufferPhysicalArraySize(buf, pages)
2807: ndis_buffer *buf;
2808: uint32_t *pages;
2809: {
2810: if (buf == NULL)
2811: return;
2812:
2813: *pages = NDIS_BUFFER_TO_SPAN_PAGES(buf);
2814: return;
2815: }
2816:
2817: __stdcall static void
2818: NdisQueryBufferOffset(buf, off, len)
2819: ndis_buffer *buf;
2820: uint32_t *off;
2821: uint32_t *len;
2822: {
2823: if (buf == NULL)
2824: return;
2825:
2826: *off = MmGetMdlByteOffset(buf);
2827: *len = MmGetMdlByteCount(buf);
2828:
2829: return;
2830: }
2831:
2832: __stdcall static void
2833: NdisMSleep(usecs)
2834: uint32_t usecs;
2835: {
2836: struct timeval tv;
2837:
2838: tv.tv_sec = 0;
2839: tv.tv_usec = usecs;
2840:
1.2 rittera 2841: #ifdef __FreeBSD__
1.1 rittera 2842: ndis_thsuspend(curthread->td_proc, NULL, tvtohz(&tv));
1.2 rittera 2843: #else
2844: ndis_thsuspend(curproc, NULL, tvtohz(&tv));
2845: #endif
1.1 rittera 2846:
2847: return;
2848: }
2849:
2850: __stdcall static uint32_t
2851: NdisReadPcmciaAttributeMemory(handle, offset, buf, len)
2852: ndis_handle handle;
2853: uint32_t offset;
2854: void *buf;
2855: uint32_t len;
2856: {
2857: struct ndis_softc *sc;
2858: ndis_miniport_block *block;
2859: bus_space_handle_t bh;
2860: bus_space_tag_t bt;
2861: char *dest;
2862: int i;
2863:
2864: if (handle == NULL)
2865: return(0);
2866:
2867: block = (ndis_miniport_block *)handle;
1.3 rittera 2868: #ifdef __FreeBSD__
1.1 rittera 2869: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2870: #else /* __NetBSD__ */
2871: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2872: #endif
1.1 rittera 2873: dest = buf;
2874:
1.3 rittera 2875: #ifdef __FreeBSD__
2876: bh = rman_get_bushandle(sc->ndis_res_am);
2877: bt = rman_get_bustag(sc->ndis_res_am);
2878:
2879: #else
2880: if ( sc->ndis_iftype == PCMCIABus ){
2881: bt = sc->ndis_res_pcmem.memt;
2882: bh = sc->ndis_res_pcmem.memh;
2883: } else { /* cardbus case */
2884: /* TODO what does it really wait for ? */
2885: bt = sc->ndis_res_mem->res_tag;
2886: bh = sc->ndis_res_mem->res_handle;
2887: }
2888: #endif
1.1 rittera 2889:
2890: for (i = 0; i < len; i++)
2891: dest[i] = bus_space_read_1(bt, bh, (offset + i) * 2);
2892:
2893: return(i);
2894: }
2895:
2896: __stdcall static uint32_t
2897: NdisWritePcmciaAttributeMemory(handle, offset, buf, len)
2898: ndis_handle handle;
2899: uint32_t offset;
2900: void *buf;
2901: uint32_t len;
2902: {
2903: struct ndis_softc *sc;
2904: ndis_miniport_block *block;
2905: bus_space_handle_t bh;
2906: bus_space_tag_t bt;
2907: char *src;
2908: int i;
2909:
2910: if (handle == NULL)
2911: return(0);
2912:
2913: block = (ndis_miniport_block *)handle;
1.3 rittera 2914: #ifdef __FreeBSD__
1.1 rittera 2915: sc = device_get_softc(block->nmb_physdeviceobj->do_devext);
1.3 rittera 2916: #else /* __NetBSD__ */
2917: sc = (struct ndis_softc *)block->nmb_physdeviceobj->pdo_sc;
2918: #endif
1.1 rittera 2919: src = buf;
1.3 rittera 2920: #ifdef __FreeBSD__
2921: bh = rman_get_bushandle(sc->ndis_res_am);
2922: bt = rman_get_bustag(sc->ndis_res_am);
2923: #else
2924: if ( sc->ndis_iftype == PCMCIABus ){
2925: bt = sc->ndis_res_pcmem.memt;
2926: bh = sc->ndis_res_pcmem.memh;
2927: } else { /* cardbus case */
2928: /* TODO what does it really wait for ? */
2929: bt = sc->ndis_res_mem->res_tag;
2930: bh = sc->ndis_res_mem->res_handle;
2931: }
2932: #endif
1.1 rittera 2933:
2934: for (i = 0; i < len; i++)
2935: bus_space_write_1(bt, bh, (offset + i) * 2, src[i]);
2936:
2937: return(i);
2938: }
2939:
2940: __stdcall static list_entry *
2941: NdisInterlockedInsertHeadList(head, entry, lock)
2942: list_entry *head;
2943: list_entry *entry;
2944: ndis_spin_lock *lock;
2945: {
2946: list_entry *flink;
2947:
2948: KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
2949: flink = head->nle_flink;
2950: entry->nle_flink = flink;
2951: entry->nle_blink = head;
2952: flink->nle_blink = entry;
2953: head->nle_flink = entry;
2954: KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
2955:
2956: return(flink);
2957: }
2958:
2959: __stdcall static list_entry *
2960: NdisInterlockedRemoveHeadList(head, lock)
2961: list_entry *head;
2962: ndis_spin_lock *lock;
2963: {
2964: list_entry *flink;
2965: list_entry *entry;
2966:
2967: KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
2968: entry = head->nle_flink;
2969: flink = entry->nle_flink;
2970: head->nle_flink = flink;
2971: flink->nle_blink = head;
2972: KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
2973:
2974: return(entry);
2975: }
2976:
2977: __stdcall static list_entry *
2978: NdisInterlockedInsertTailList(head, entry, lock)
2979: list_entry *head;
2980: list_entry *entry;
2981: ndis_spin_lock *lock;
2982: {
2983: list_entry *blink;
2984:
2985: KeAcquireSpinLock(&lock->nsl_spinlock, &lock->nsl_kirql);
2986: blink = head->nle_blink;
2987: entry->nle_flink = head;
2988: entry->nle_blink = blink;
2989: blink->nle_flink = entry;
2990: head->nle_blink = entry;
2991: KeReleaseSpinLock(&lock->nsl_spinlock, lock->nsl_kirql);
2992:
2993: return(blink);
2994: }
2995:
2996: __stdcall static uint8_t
2997: NdisMSynchronizeWithInterrupt(intr, syncfunc, syncctx)
2998: ndis_miniport_interrupt *intr;
2999: void *syncfunc;
3000: void *syncctx;
3001: {
3002: __stdcall uint8_t (*sync)(void *);
3003: uint8_t rval;
3004: uint8_t irql;
3005:
3006: if (syncfunc == NULL || syncctx == NULL)
3007: return(0);
3008:
3009: sync = syncfunc;
3010: KeAcquireSpinLock(&intr->ni_dpccountlock, &irql);
3011: rval = MSCALL1(sync, syncctx);
3012: KeReleaseSpinLock(&intr->ni_dpccountlock, irql);
3013:
3014: return(rval);
3015: }
3016:
3017: /*
3018: * Return the number of 100 nanosecond intervals since
3019: * January 1, 1601. (?!?!)
3020: */
3021: __stdcall static void
3022: NdisGetCurrentSystemTime(tval)
3023: uint64_t *tval;
3024: {
3025: struct timespec ts;
1.3 rittera 3026: #ifdef __NetBSD__
3027: struct timeval tv;
3028:
3029: microtime(&tv);
3030: TIMEVAL_TO_TIMESPEC(&tv,&ts);
3031: #else
3032: nanotime(&ts);
3033: #endif
1.1 rittera 3034:
3035: *tval = (uint64_t)ts.tv_nsec / 100 + (uint64_t)ts.tv_sec * 10000000 +
1.2 rittera 3036: (uint64_t)11644473600ULL;
1.1 rittera 3037:
3038: return;
3039: }
3040:
3041: /*
3042: * Return the number of milliseconds since the system booted.
3043: */
3044: __stdcall static void
3045: NdisGetSystemUpTime(tval)
3046: uint32_t *tval;
3047: {
3048: *tval = (ticks * hz) / 1000;
3049:
3050: return;
3051: }
3052:
3053: __stdcall static void
3054: NdisInitializeString(dst, src)
3055: ndis_unicode_string *dst;
3056: char *src;
3057: {
3058: ndis_unicode_string *u;
3059:
3060: u = dst;
3061: u->us_buf = NULL;
3062: if (ndis_ascii_to_unicode(src, &u->us_buf))
3063: return;
3064: u->us_len = u->us_maxlen = strlen(src) * 2;
3065: return;
3066: }
3067:
3068: __stdcall static void
3069: NdisFreeString(str)
3070: ndis_unicode_string *str;
3071: {
3072: if (str == NULL)
3073: return;
3074: if (str->us_buf != NULL)
3075: free(str->us_buf, M_DEVBUF);
3076: free(str, M_DEVBUF);
3077: return;
3078: }
3079:
3080: __stdcall static ndis_status
1.6 christos 3081: NdisMRemoveMiniport(ndis_handle *adapter)
1.1 rittera 3082: {
3083: return(NDIS_STATUS_SUCCESS);
3084: }
3085:
3086: __stdcall static void
3087: NdisInitAnsiString(dst, src)
3088: ndis_ansi_string *dst;
3089: char *src;
3090: {
3091: ndis_ansi_string *a;
3092:
3093: a = dst;
3094: if (a == NULL)
3095: return;
3096: if (src == NULL) {
3097: a->nas_len = a->nas_maxlen = 0;
3098: a->nas_buf = NULL;
3099: } else {
3100: a->nas_buf = src;
3101: a->nas_len = a->nas_maxlen = strlen(src);
3102: }
3103:
3104: return;
3105: }
3106:
3107: __stdcall static void
3108: NdisInitUnicodeString(dst, src)
3109: ndis_unicode_string *dst;
3110: uint16_t *src;
3111: {
3112: ndis_unicode_string *u;
3113: int i;
3114:
3115: u = dst;
3116: if (u == NULL)
3117: return;
3118: if (src == NULL) {
3119: u->us_len = u->us_maxlen = 0;
3120: u->us_buf = NULL;
3121: } else {
3122: i = 0;
3123: while(src[i] != 0)
3124: i++;
3125: u->us_buf = src;
3126: u->us_len = u->us_maxlen = i * 2;
3127: }
3128:
3129: return;
3130: }
3131:
1.5 christos 3132: __stdcall static void NdisMGetDeviceProperty(
3133: ndis_handle adapter,
3134: device_object **phydevobj,
3135: device_object **funcdevobj,
3136: device_object **nextdevobj,
1.6 christos 3137: cm_resource_list *resources,
3138: cm_resource_list *transresources)
1.1 rittera 3139: {
3140: ndis_miniport_block *block;
3141:
3142: block = (ndis_miniport_block *)adapter;
3143:
3144: if (phydevobj != NULL)
3145: *phydevobj = block->nmb_physdeviceobj;
3146: if (funcdevobj != NULL)
3147: *funcdevobj = block->nmb_deviceobj;
3148: if (nextdevobj != NULL)
3149: *nextdevobj = block->nmb_nextdeviceobj;
3150:
3151: return;
3152: }
3153:
3154: __stdcall static void
3155: NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen)
3156: ndis_packet *packet;
3157: ndis_buffer **buf;
3158: void **firstva;
3159: uint32_t *firstlen;
3160: uint32_t *totlen;
3161: {
3162: ndis_buffer *tmp;
3163:
3164: tmp = packet->np_private.npp_head;
3165: *buf = tmp;
3166: if (tmp == NULL) {
3167: *firstva = NULL;
3168: *firstlen = *totlen = 0;
3169: } else {
3170: *firstva = MmGetMdlVirtualAddress(tmp);
3171: *firstlen = *totlen = MmGetMdlByteCount(tmp);
3172: for (tmp = tmp->mdl_next; tmp != NULL; tmp = tmp->mdl_next)
3173: *totlen += MmGetMdlByteCount(tmp);
3174: }
3175:
3176: return;
3177: }
3178:
3179: __stdcall static void
1.5 christos 3180: NdisGetFirstBufferFromPacketSafe(
3181: ndis_packet *packet,
3182: ndis_buffer **buf,
3183: void **firstva,
3184: uint32_t *firstlen,
3185: uint32_t *totlen,
1.6 christos 3186: uint32_t prio)
1.1 rittera 3187: {
3188: NdisGetFirstBufferFromPacket(packet, buf, firstva, firstlen, totlen);
3189: }
3190:
1.2 rittera 3191: #ifdef __FreeBSD__
1.1 rittera 3192: static int
3193: ndis_find_sym(lf, filename, suffix, sym)
3194: linker_file_t lf;
3195: char *filename;
3196: char *suffix;
1.7 christos 3197: void * *sym;
1.1 rittera 3198: {
3199: char *fullsym;
3200: char *suf;
3201: int i;
3202:
3203: fullsym = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
3204: if (fullsym == NULL)
3205: return(ENOMEM);
3206:
3207: bzero(fullsym, MAXPATHLEN);
3208: strncpy(fullsym, filename, MAXPATHLEN);
3209: if (strlen(filename) < 4) {
3210: ExFreePool(fullsym);
3211: return(EINVAL);
3212: }
3213:
3214: /* If the filename has a .ko suffix, strip if off. */
3215: suf = fullsym + (strlen(filename) - 3);
3216: if (strcmp(suf, ".ko") == 0)
3217: *suf = '\0';
3218:
3219: for (i = 0; i < strlen(fullsym); i++) {
3220: if (fullsym[i] == '.')
3221: fullsym[i] = '_';
3222: else
3223: fullsym[i] = tolower(fullsym[i]);
3224: }
3225: strcat(fullsym, suffix);
3226: *sym = linker_file_lookup_symbol(lf, fullsym, 0);
3227: ExFreePool(fullsym);
3228: if (*sym == 0)
3229: return(ENOENT);
3230:
3231: return(0);
3232: }
3233:
3234: /* can also return NDIS_STATUS_RESOURCES/NDIS_STATUS_ERROR_READING_FILE */
3235: __stdcall static void
3236: NdisOpenFile(status, filehandle, filelength, filename, highestaddr)
3237: ndis_status *status;
3238: ndis_handle *filehandle;
3239: uint32_t *filelength;
3240: ndis_unicode_string *filename;
3241: ndis_physaddr highestaddr;
3242: {
3243: char *afilename = NULL;
3244: struct thread *td = curthread;
3245: struct nameidata nd;
3246: int flags, error;
3247: struct vattr vat;
3248: struct vattr *vap = &vat;
3249: ndis_fh *fh;
3250: char *path;
3251: linker_file_t head, lf;
1.8 dogcow 3252: void *kldstart, *kldend;
1.1 rittera 3253:
3254: ndis_unicode_to_ascii(filename->us_buf,
3255: filename->us_len, &afilename);
3256:
3257: fh = ExAllocatePoolWithTag(NonPagedPool, sizeof(ndis_fh), 0);
3258: if (fh == NULL) {
3259: *status = NDIS_STATUS_RESOURCES;
3260: return;
3261: }
3262:
3263: /*
3264: * During system bootstrap, it's impossible to load files
3265: * from the rootfs since it's not mounted yet. We therefore
3266: * offer the possibility of opening files that have been
3267: * preloaded as modules instead. Both choices will work
3268: * when kldloading a module from multiuser, but only the
3269: * module option will work during bootstrap. The module
3270: * loading option works by using the ndiscvt(8) utility
3271: * to convert the arbitrary file into a .ko using objcopy(1).
3272: * This file will contain two special symbols: filename_start
3273: * and filename_end. All we have to do is traverse the KLD
3274: * list in search of those symbols and we've found the file
3275: * data. As an added bonus, ndiscvt(8) will also generate
3276: * a normal .o file which can be linked statically with
3277: * the kernel. This means that the symbols will actual reside
3278: * in the kernel's symbol table, but that doesn't matter to
3279: * us since the kernel appears to us as just another module.
3280: */
3281:
3282: /*
3283: * This is an evil trick for getting the head of the linked
3284: * file list, which is not exported from kern_linker.o. It
3285: * happens that linker file #1 is always the kernel, and is
3286: * always the first element in the list.
3287: */
3288:
3289: head = linker_find_file_by_id(1);
3290: for (lf = head; lf != NULL; lf = TAILQ_NEXT(lf, link)) {
3291: if (ndis_find_sym(lf, afilename, "_start", &kldstart))
3292: continue;
3293: if (ndis_find_sym(lf, afilename, "_end", &kldend))
3294: continue;
3295: fh->nf_vp = lf;
3296: fh->nf_map = NULL;
3297: fh->nf_type = NDIS_FH_TYPE_MODULE;
3298: *filelength = fh->nf_maplen = (kldend - kldstart) & 0xFFFFFFFF;
3299: *filehandle = fh;
3300: free(afilename, M_DEVBUF);
3301: *status = NDIS_STATUS_SUCCESS;
3302: return;
3303: }
3304:
3305: if (TAILQ_EMPTY(&mountlist)) {
3306: ExFreePool(fh);
3307: *status = NDIS_STATUS_FILE_NOT_FOUND;
3308: printf("NDIS: could not find file %s in linker list\n",
3309: afilename);
3310: printf("NDIS: and no filesystems mounted yet, "
3311: "aborting NdisOpenFile()\n");
3312: free(afilename, M_DEVBUF);
3313: return;
3314: }
3315:
3316: path = ExAllocatePoolWithTag(NonPagedPool, MAXPATHLEN, 0);
3317: if (path == NULL) {
3318: ExFreePool(fh);
3319: *status = NDIS_STATUS_RESOURCES;
3320: return;
3321: }
3322:
3323: snprintf(path, MAXPATHLEN, "%s/%s", ndis_filepath, afilename);
3324: free(afilename, M_DEVBUF);
3325:
3326: mtx_lock(&Giant);
3327:
3328: /* Some threads don't have a current working directory. */
3329:
3330: if (td->td_proc->p_fd->fd_rdir == NULL)
3331: td->td_proc->p_fd->fd_rdir = rootvnode;
3332: if (td->td_proc->p_fd->fd_cdir == NULL)
3333: td->td_proc->p_fd->fd_cdir = rootvnode;
3334:
3335: NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td);
3336:
3337: flags = FREAD;
3338: error = vn_open(&nd, &flags, 0, -1);
3339: if (error) {
3340: mtx_unlock(&Giant);
3341: *status = NDIS_STATUS_FILE_NOT_FOUND;
3342: ExFreePool(fh);
3343: printf("NDIS: open file %s failed: %d\n", path, error);
3344: ExFreePool(path);
3345: return;
3346: }
3347:
3348: ExFreePool(path);
3349:
3350: NDFREE(&nd, NDF_ONLY_PNBUF);
3351:
3352: /* Get the file size. */
3353: VOP_GETATTR(nd.ni_vp, vap, td->td_ucred, td);
3354: VOP_UNLOCK(nd.ni_vp, 0, td);
3355: mtx_unlock(&Giant);
3356:
3357: fh->nf_vp = nd.ni_vp;
3358: fh->nf_map = NULL;
3359: fh->nf_type = NDIS_FH_TYPE_VFS;
3360: *filehandle = fh;
3361: *filelength = fh->nf_maplen = vap->va_size & 0xFFFFFFFF;
3362: *status = NDIS_STATUS_SUCCESS;
3363:
3364: return;
3365: }
3366:
3367: __stdcall static void
3368: NdisMapFile(status, mappedbuffer, filehandle)
3369: ndis_status *status;
3370: void **mappedbuffer;
3371: ndis_handle filehandle;
3372: {
3373: ndis_fh *fh;
3374: struct thread *td = curthread;
3375: linker_file_t lf;
1.7 christos 3376: void * kldstart;
1.1 rittera 3377: int error, resid;
3378:
3379: if (filehandle == NULL) {
3380: *status = NDIS_STATUS_FAILURE;
3381: return;
3382: }
3383:
3384: fh = (ndis_fh *)filehandle;
3385:
3386: if (fh->nf_vp == NULL) {
3387: *status = NDIS_STATUS_FAILURE;
3388: return;
3389: }
3390:
3391: if (fh->nf_map != NULL) {
3392: *status = NDIS_STATUS_ALREADY_MAPPED;
3393: return;
3394: }
3395:
3396: if (fh->nf_type == NDIS_FH_TYPE_MODULE) {
3397: lf = fh->nf_vp;
3398: if (ndis_find_sym(lf, lf->filename, "_start", &kldstart)) {
3399: *status = NDIS_STATUS_FAILURE;
3400: return;
3401: }
3402: fh->nf_map = kldstart;
3403: *status = NDIS_STATUS_SUCCESS;
3404: *mappedbuffer = fh->nf_map;
3405: return;
3406: }
3407:
3408: fh->nf_map = ExAllocatePoolWithTag(NonPagedPool, fh->nf_maplen, 0);
3409:
3410: if (fh->nf_map == NULL) {
3411: *status = NDIS_STATUS_RESOURCES;
3412: return;
3413: }
3414:
3415: mtx_lock(&Giant);
3416: error = vn_rdwr(UIO_READ, fh->nf_vp, fh->nf_map, fh->nf_maplen, 0,
3417: UIO_SYSSPACE, 0, td->td_ucred, NOCRED, &resid, td);
3418: mtx_unlock(&Giant);
3419:
3420: if (error)
3421: *status = NDIS_STATUS_FAILURE;
3422: else {
3423: *status = NDIS_STATUS_SUCCESS;
3424: *mappedbuffer = fh->nf_map;
3425: }
3426:
3427: return;
3428: }
3429:
3430: __stdcall static void
3431: NdisUnmapFile(filehandle)
3432: ndis_handle filehandle;
3433: {
3434: ndis_fh *fh;
3435: fh = (ndis_fh *)filehandle;
3436:
3437: if (fh->nf_map == NULL)
3438: return;
3439:
3440: if (fh->nf_type == NDIS_FH_TYPE_VFS)
3441: ExFreePool(fh->nf_map);
3442: fh->nf_map = NULL;
3443:
3444: return;
3445: }
3446:
3447: __stdcall static void
3448: NdisCloseFile(filehandle)
3449: ndis_handle filehandle;
3450: {
3451: struct thread *td = curthread;
3452: ndis_fh *fh;
3453:
3454: if (filehandle == NULL)
3455: return;
3456:
3457: fh = (ndis_fh *)filehandle;
3458: if (fh->nf_map != NULL) {
3459: if (fh->nf_type == NDIS_FH_TYPE_VFS)
3460: ExFreePool(fh->nf_map);
3461: fh->nf_map = NULL;
3462: }
3463:
3464: if (fh->nf_vp == NULL)
3465: return;
3466:
3467: if (fh->nf_type == NDIS_FH_TYPE_VFS) {
3468: mtx_lock(&Giant);
3469: vn_close(fh->nf_vp, FREAD, td->td_ucred, td);
3470: mtx_unlock(&Giant);
3471: }
3472:
3473: fh->nf_vp = NULL;
3474: ExFreePool(fh);
3475:
3476: return;
3477: }
1.2 rittera 3478: #endif /* __FreeBSD__ */
1.1 rittera 3479: __stdcall static uint8_t
3480: NdisSystemProcessorCount()
3481: {
1.2 rittera 3482: #ifdef __FreeBSD__
1.1 rittera 3483: return(mp_ncpus);
1.2 rittera 3484: #else
3485: return(nprocs);
3486: #endif
1.1 rittera 3487: }
3488:
3489: typedef void (*ndis_statusdone_handler)(ndis_handle);
3490: typedef void (*ndis_status_handler)(ndis_handle, ndis_status,
3491: void *, uint32_t);
3492:
3493: __stdcall static void
3494: NdisMIndicateStatusComplete(adapter)
3495: ndis_handle adapter;
3496: {
3497: ndis_miniport_block *block;
3498: __stdcall ndis_statusdone_handler statusdonefunc;
3499:
3500: block = (ndis_miniport_block *)adapter;
3501: statusdonefunc = block->nmb_statusdone_func;
3502:
3503: MSCALL1(statusdonefunc, adapter);
3504: return;
3505: }
3506:
3507: __stdcall static void
3508: NdisMIndicateStatus(adapter, status, sbuf, slen)
3509: ndis_handle adapter;
3510: ndis_status status;
3511: void *sbuf;
3512: uint32_t slen;
3513: {
3514: ndis_miniport_block *block;
3515: __stdcall ndis_status_handler statusfunc;
3516:
3517: block = (ndis_miniport_block *)adapter;
3518: statusfunc = block->nmb_status_func;
3519:
3520: MSCALL4(statusfunc, adapter, status, sbuf, slen);
3521: return;
3522: }
3523:
3524: static void
3525: ndis_workfunc(ctx)
3526: void *ctx;
3527: {
3528: ndis_work_item *work;
3529: __stdcall ndis_proc workfunc;
3530:
3531: work = ctx;
3532: workfunc = work->nwi_func;
3533: MSCALL2(workfunc, work, work->nwi_ctx);
3534: return;
3535: }
3536:
3537: __stdcall static ndis_status
3538: NdisScheduleWorkItem(work)
3539: ndis_work_item *work;
3540: {
3541: ndis_sched(ndis_workfunc, work, NDIS_TASKQUEUE);
3542: return(NDIS_STATUS_SUCCESS);
3543: }
3544:
3545: __stdcall static void
3546: NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen)
3547: ndis_packet *dpkt;
3548: uint32_t doff;
3549: uint32_t reqlen;
3550: ndis_packet *spkt;
3551: uint32_t soff;
3552: uint32_t *cpylen;
3553: {
3554: ndis_buffer *src, *dst;
3555: char *sptr, *dptr;
3556: int resid, copied, len, scnt, dcnt;
3557:
3558: *cpylen = 0;
3559:
3560: src = spkt->np_private.npp_head;
3561: dst = dpkt->np_private.npp_head;
3562:
3563: sptr = MmGetMdlVirtualAddress(src);
3564: dptr = MmGetMdlVirtualAddress(dst);
3565: scnt = MmGetMdlByteCount(src);
3566: dcnt = MmGetMdlByteCount(dst);
3567:
3568: while (soff) {
3569: if (MmGetMdlByteCount(src) > soff) {
3570: sptr += soff;
3571: scnt = MmGetMdlByteCount(src)- soff;
3572: break;
3573: }
3574: soff -= MmGetMdlByteCount(src);
3575: src = src->mdl_next;
3576: if (src == NULL)
3577: return;
3578: sptr = MmGetMdlVirtualAddress(src);
3579: }
3580:
3581: while (doff) {
3582: if (MmGetMdlByteCount(dst) > doff) {
3583: dptr += doff;
3584: dcnt = MmGetMdlByteCount(dst) - doff;
3585: break;
3586: }
3587: doff -= MmGetMdlByteCount(dst);
3588: dst = dst->mdl_next;
3589: if (dst == NULL)
3590: return;
3591: dptr = MmGetMdlVirtualAddress(dst);
3592: }
3593:
3594: resid = reqlen;
3595: copied = 0;
3596:
3597: while(1) {
3598: if (resid < scnt)
3599: len = resid;
3600: else
3601: len = scnt;
3602: if (dcnt < len)
3603: len = dcnt;
3604:
3605: bcopy(sptr, dptr, len);
3606:
3607: copied += len;
3608: resid -= len;
3609: if (resid == 0)
3610: break;
3611:
3612: dcnt -= len;
3613: if (dcnt == 0) {
3614: dst = dst->mdl_next;
3615: if (dst == NULL)
3616: break;
3617: dptr = MmGetMdlVirtualAddress(dst);
3618: dcnt = MmGetMdlByteCount(dst);
3619: }
3620:
3621: scnt -= len;
3622: if (scnt == 0) {
3623: src = src->mdl_next;
3624: if (src == NULL)
3625: break;
3626: sptr = MmGetMdlVirtualAddress(src);
3627: scnt = MmGetMdlByteCount(src);
3628: }
3629: }
3630:
3631: *cpylen = copied;
3632: return;
3633: }
3634:
3635: __stdcall static void
1.5 christos 3636: NdisCopyFromPacketToPacketSafe(
3637: ndis_packet *dpkt,
3638: uint32_t doff,
3639: uint32_t reqlen,
3640: ndis_packet *spkt,
3641: uint32_t soff,
3642: uint32_t *cpylen,
1.6 christos 3643: uint32_t prio)
1.1 rittera 3644: {
3645: NdisCopyFromPacketToPacket(dpkt, doff, reqlen, spkt, soff, cpylen);
3646: return;
3647: }
3648:
3649: __stdcall static ndis_status
1.5 christos 3650: NdisMRegisterDevice(
3651: ndis_handle handle,
1.6 christos 3652: ndis_unicode_string *devname,
3653: ndis_unicode_string *symname,
3654: driver_dispatch *majorfuncs[],
1.5 christos 3655: void **devobj,
3656: ndis_handle *devhandle)
1.1 rittera 3657: {
3658: ndis_miniport_block *block;
3659:
3660: block = (ndis_miniport_block *)handle;
3661: *devobj = block->nmb_deviceobj;
3662: *devhandle = handle;
3663:
3664: return(NDIS_STATUS_SUCCESS);
3665: }
3666:
3667: __stdcall static ndis_status
1.6 christos 3668: NdisMDeregisterDevice(ndis_handle handle)
1.1 rittera 3669: {
3670: return(NDIS_STATUS_SUCCESS);
3671: }
3672:
3673: __stdcall static ndis_status
3674: NdisMQueryAdapterInstanceName(name, handle)
3675: ndis_unicode_string *name;
3676: ndis_handle handle;
3677: {
3678: ndis_miniport_block *block;
3679: device_t dev;
3680:
3681: block = (ndis_miniport_block *)handle;
3682: dev = block->nmb_physdeviceobj->do_devext;
3683:
3684: ndis_ascii_to_unicode(__DECONST(char *,
3685: device_get_nameunit(dev)), &name->us_buf);
3686: name->us_len = strlen(device_get_nameunit(dev)) * 2;
3687:
3688: return(NDIS_STATUS_SUCCESS);
3689: }
3690:
3691: __stdcall static void
1.5 christos 3692: NdisMRegisterUnloadHandler(
1.6 christos 3693: ndis_handle handle,
3694: void *func)
1.1 rittera 3695: {
3696: return;
3697: }
3698:
3699: __stdcall static void
3700: dummy()
3701: {
3702: printf ("NDIS dummy called...\n");
3703: return;
3704: }
3705:
3706: image_patch_table ndis_functbl[] = {
3707: IMPORT_FUNC(NdisCopyFromPacketToPacket),
3708: IMPORT_FUNC(NdisCopyFromPacketToPacketSafe),
3709: IMPORT_FUNC(NdisScheduleWorkItem),
3710: IMPORT_FUNC(NdisMIndicateStatusComplete),
3711: IMPORT_FUNC(NdisMIndicateStatus),
3712: IMPORT_FUNC(NdisSystemProcessorCount),
3713: IMPORT_FUNC(NdisUnchainBufferAtBack),
3714: IMPORT_FUNC(NdisGetFirstBufferFromPacket),
3715: IMPORT_FUNC(NdisGetFirstBufferFromPacketSafe),
3716: IMPORT_FUNC(NdisGetBufferPhysicalArraySize),
3717: IMPORT_FUNC(NdisMGetDeviceProperty),
3718: IMPORT_FUNC(NdisInitAnsiString),
3719: IMPORT_FUNC(NdisInitUnicodeString),
3720: IMPORT_FUNC(NdisWriteConfiguration),
3721: IMPORT_FUNC(NdisAnsiStringToUnicodeString),
3722: IMPORT_FUNC(NdisTerminateWrapper),
3723: IMPORT_FUNC(NdisOpenConfigurationKeyByName),
3724: IMPORT_FUNC(NdisOpenConfigurationKeyByIndex),
3725: IMPORT_FUNC(NdisMRemoveMiniport),
3726: IMPORT_FUNC(NdisInitializeString),
3727: IMPORT_FUNC(NdisFreeString),
3728: IMPORT_FUNC(NdisGetCurrentSystemTime),
3729: IMPORT_FUNC(NdisGetSystemUpTime),
3730: IMPORT_FUNC(NdisMSynchronizeWithInterrupt),
3731: IMPORT_FUNC(NdisMAllocateSharedMemoryAsync),
3732: IMPORT_FUNC(NdisInterlockedInsertHeadList),
3733: IMPORT_FUNC(NdisInterlockedInsertTailList),
3734: IMPORT_FUNC(NdisInterlockedRemoveHeadList),
3735: IMPORT_FUNC(NdisInitializeWrapper),
3736: IMPORT_FUNC(NdisMRegisterMiniport),
3737: IMPORT_FUNC(NdisAllocateMemoryWithTag),
3738: IMPORT_FUNC(NdisAllocateMemory),
3739: IMPORT_FUNC(NdisMSetAttributesEx),
3740: IMPORT_FUNC(NdisCloseConfiguration),
3741: IMPORT_FUNC(NdisReadConfiguration),
3742: IMPORT_FUNC(NdisOpenConfiguration),
3743: IMPORT_FUNC(NdisAcquireSpinLock),
3744: IMPORT_FUNC(NdisReleaseSpinLock),
3745: IMPORT_FUNC(NdisDprAcquireSpinLock),
3746: IMPORT_FUNC(NdisDprReleaseSpinLock),
3747: IMPORT_FUNC(NdisAllocateSpinLock),
3748: IMPORT_FUNC(NdisFreeSpinLock),
3749: IMPORT_FUNC(NdisFreeMemory),
3750: IMPORT_FUNC(NdisReadPciSlotInformation),
3751: IMPORT_FUNC(NdisWritePciSlotInformation),
3752: IMPORT_FUNC_MAP(NdisImmediateReadPciSlotInformation,
3753: NdisReadPciSlotInformation),
3754: IMPORT_FUNC_MAP(NdisImmediateWritePciSlotInformation,
3755: NdisWritePciSlotInformation),
3756: IMPORT_FUNC(NdisWriteErrorLogEntry),
3757: IMPORT_FUNC(NdisMStartBufferPhysicalMapping),
3758: IMPORT_FUNC(NdisMCompleteBufferPhysicalMapping),
3759: IMPORT_FUNC(NdisMInitializeTimer),
3760: IMPORT_FUNC(NdisInitializeTimer),
3761: IMPORT_FUNC(NdisSetTimer),
3762: IMPORT_FUNC(NdisMCancelTimer),
3763: IMPORT_FUNC_MAP(NdisCancelTimer, NdisMCancelTimer),
3764: IMPORT_FUNC(NdisMSetPeriodicTimer),
3765: IMPORT_FUNC(NdisMQueryAdapterResources),
3766: IMPORT_FUNC(NdisMRegisterIoPortRange),
3767: IMPORT_FUNC(NdisMDeregisterIoPortRange),
3768: IMPORT_FUNC(NdisReadNetworkAddress),
3769: IMPORT_FUNC(NdisQueryMapRegisterCount),
3770: IMPORT_FUNC(NdisMAllocateMapRegisters),
3771: IMPORT_FUNC(NdisMFreeMapRegisters),
3772: IMPORT_FUNC(NdisMAllocateSharedMemory),
3773: IMPORT_FUNC(NdisMMapIoSpace),
3774: IMPORT_FUNC(NdisMUnmapIoSpace),
3775: IMPORT_FUNC(NdisGetCacheFillSize),
3776: IMPORT_FUNC(NdisMGetDmaAlignment),
3777: IMPORT_FUNC(NdisMInitializeScatterGatherDma),
3778: IMPORT_FUNC(NdisAllocatePacketPool),
3779: IMPORT_FUNC(NdisAllocatePacketPoolEx),
3780: IMPORT_FUNC(NdisAllocatePacket),
3781: IMPORT_FUNC(NdisFreePacket),
3782: IMPORT_FUNC(NdisFreePacketPool),
3783: IMPORT_FUNC_MAP(NdisDprAllocatePacket, NdisAllocatePacket),
3784: IMPORT_FUNC_MAP(NdisDprFreePacket, NdisFreePacket),
3785: IMPORT_FUNC(NdisAllocateBufferPool),
3786: IMPORT_FUNC(NdisAllocateBuffer),
3787: IMPORT_FUNC(NdisQueryBuffer),
3788: IMPORT_FUNC(NdisQueryBufferSafe),
3789: IMPORT_FUNC(NdisBufferVirtualAddress),
3790: IMPORT_FUNC(NdisBufferVirtualAddressSafe),
3791: IMPORT_FUNC(NdisBufferLength),
3792: IMPORT_FUNC(NdisFreeBuffer),
3793: IMPORT_FUNC(NdisFreeBufferPool),
3794: IMPORT_FUNC(NdisInterlockedIncrement),
3795: IMPORT_FUNC(NdisInterlockedDecrement),
3796: IMPORT_FUNC(NdisInitializeEvent),
3797: IMPORT_FUNC(NdisSetEvent),
3798: IMPORT_FUNC(NdisResetEvent),
3799: IMPORT_FUNC(NdisWaitEvent),
3800: IMPORT_FUNC(NdisUnicodeStringToAnsiString),
3801: IMPORT_FUNC(NdisMPciAssignResources),
3802: IMPORT_FUNC(NdisMFreeSharedMemory),
3803: IMPORT_FUNC(NdisMRegisterInterrupt),
3804: IMPORT_FUNC(NdisMDeregisterInterrupt),
3805: IMPORT_FUNC(NdisMRegisterAdapterShutdownHandler),
3806: IMPORT_FUNC(NdisMDeregisterAdapterShutdownHandler),
3807: IMPORT_FUNC(NDIS_BUFFER_TO_SPAN_PAGES),
3808: IMPORT_FUNC(NdisQueryBufferOffset),
3809: IMPORT_FUNC(NdisAdjustBufferLength),
3810: IMPORT_FUNC(NdisPacketPoolUsage),
3811: IMPORT_FUNC(NdisMSleep),
3812: IMPORT_FUNC(NdisUnchainBufferAtFront),
3813: IMPORT_FUNC(NdisReadPcmciaAttributeMemory),
3814: IMPORT_FUNC(NdisWritePcmciaAttributeMemory),
1.2 rittera 3815: #ifdef __FreeBSD__
1.1 rittera 3816: IMPORT_FUNC(NdisOpenFile),
3817: IMPORT_FUNC(NdisMapFile),
3818: IMPORT_FUNC(NdisUnmapFile),
3819: IMPORT_FUNC(NdisCloseFile),
1.2 rittera 3820: #endif
1.1 rittera 3821: IMPORT_FUNC(NdisMRegisterDevice),
3822: IMPORT_FUNC(NdisMDeregisterDevice),
3823: IMPORT_FUNC(NdisMQueryAdapterInstanceName),
3824: IMPORT_FUNC(NdisMRegisterUnloadHandler),
3825: IMPORT_FUNC(ndis_timercall),
3826:
3827: /*
3828: * This last entry is a catch-all for any function we haven't
3829: * implemented yet. The PE import list patching routine will
3830: * use it for any function that doesn't have an explicit match
3831: * in this table.
3832: */
3833:
3834: { NULL, (FUNC)dummy, NULL },
3835:
3836: /* End of list. */
3837:
3838: { NULL, NULL, NULL }
3839: };
CVSweb <webmaster@jp.NetBSD.org>