Bring in NDIS emulation support from FreeBSD-5. NDIS is a Windows device
[dragonfly.git] / sys / emulation / ndis / ntoskrnl_var.h
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  * $FreeBSD: src/sys/compat/ndis/ntoskrnl_var.h,v 1.15 2004/04/20 02:27:38 wpaul Exp $
33  * $DragonFly: src/sys/emulation/ndis/ntoskrnl_var.h,v 1.1 2004/07/29 20:51:33 dillon Exp $
34  */
35
36 #ifndef _NTOSKRNL_VAR_H_
37 #define _NTOSKRNL_VAR_H_
38
39 /* Note: assumes x86 page size of 4K. */
40 #define PAGE_SHIFT      12
41 #define SPAN_PAGES(ptr, len)                                    \
42         ((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE -1)) +      \
43         (len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
44 #define PAGE_ALIGN(ptr)                                         \
45         ((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
46 #define BYTE_OFFSET(ptr)                                        \
47         ((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
48 #define MDL_INIT(b, baseva, len)                                        \
49         (b)->nb_next = NULL;                                            \
50         (b)->nb_size = (uint16_t)(sizeof(struct ndis_buffer) +          \
51                 (sizeof(uint32_t) * SPAN_PAGES((baseva), (len))));      \
52         (b)->nb_flags = 0;                                              \
53         (b)->nb_startva = (void *)PAGE_ALIGN((baseva));                 \
54         (b)->nb_byteoffset = BYTE_OFFSET((baseva));                     \
55         (b)->nb_bytecount = (uint32_t)(len);
56 #define MDL_VA(b)                                               \
57         ((void *)((char *)((b)->nb_startva) + (b)->nb_byteoffset))
58
59 #define WDM_MAJOR               1
60 #define WDM_MINOR_WIN98         0x00
61 #define WDM_MINOR_WINME         0x05
62 #define WDM_MINOR_WIN2000       0x10
63 #define WDM_MINOR_WINXP         0x20
64 #define WDM_MINOR_WIN2003       0x30
65
66 /*-
67  * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
68  * According to the Windows DDK header files, KSPIN_LOCK is defined like this:
69  *      typedef ULONG_PTR KSPIN_LOCK;
70  *
71  * From basetsd.h (SDK, Feb. 2003):
72  *      typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
73  *      typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
74  *      typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
75  * 
76  * The keyword __int3264 specifies an integral type that has the following
77  * properties:
78  *      + It is 32-bit on 32-bit platforms
79  *      + It is 64-bit on 64-bit platforms
80  *      + It is 32-bit on the wire for backward compatibility.
81  *        It gets truncated on the sending side and extended appropriately
82  *        (signed or unsigned) on the receiving side.
83  *
84  * Thus register_t seems the proper mapping onto FreeBSD for spin locks.
85  */
86
87 typedef register_t kspin_lock;
88
89 struct slist_entry {
90         struct slist_entry      *sl_next;
91 };
92
93 typedef struct slist_entry slist_entry;
94
95 union slist_header {
96         uint64_t                slh_align;
97         struct {
98                 struct slist_entry      *slh_next;
99                 uint16_t                slh_depth;
100                 uint16_t                slh_seq;
101         } slh_list;
102 };
103
104 typedef union slist_header slist_header;
105
106 struct list_entry {
107         struct list_entry *nle_flink;
108         struct list_entry *nle_blink;
109 };
110
111 typedef struct list_entry list_entry;
112
113 #define INIT_LIST_HEAD(l)       \
114         l->nle_flink = l->nle_blink = l
115
116 #define REMOVE_LIST_ENTRY(e)                    \
117         do {                                    \
118                 list_entry              *b;     \
119                 list_entry              *f;     \
120                                                 \
121                 f = e->nle_flink;               \
122                 b = e->nle_blink;               \
123                 b->nle_flink = f;               \
124                 f->nle_blink = b;               \
125         } while (0)
126
127 #define REMOVE_LIST_HEAD(l)                     \
128         do {                                    \
129                 list_entry              *f;     \
130                 list_entry              *e;     \
131                                                 \
132                 e = l->nle_flink;               \
133                 f = e->nle_flink;               \
134                 l->nle_flink = f;               \
135                 f->nle_blink = l;               \
136         } while (0)
137
138 #define REMOVE_LIST_TAIL(l)                     \
139         do {                                    \
140                 list_entry              *b;     \
141                 list_entry              *e;     \
142                                                 \
143                 e = l->nle_blink;               \
144                 b = e->nle_blink;               \
145                 l->nle_blink = b;               \
146                 b->nle_flink = l;               \
147         } while (0)
148
149 #define INSERT_LIST_TAIL(l, e)                  \
150         do {                                    \
151                 list_entry              *b;     \
152                                                 \
153                 b = l->nle_blink;               \
154                 e->nle_flink = l;               \
155                 e->nle_blink = b;               \
156                 b->nle_flink = e;               \
157                 l->nle_blink = e;               \
158         } while (0)
159
160 #define INSERT_LIST_HEAD(l, e)                  \
161         do {                                    \
162                 list_entry              *f;     \
163                                                 \
164                 f = l->nle_flink;               \
165                 e->nle_flink = f;               \
166                 e->nle_blink = l;               \
167                 f->nle_blink = e;               \
168                 l->nle_flink = e;               \
169         } while (0)
170
171 struct nt_dispatch_header {
172         uint8_t                 dh_type;
173         uint8_t                 dh_abs;
174         uint8_t                 dh_size;
175         uint8_t                 dh_inserted;
176         uint32_t                dh_sigstate;
177         list_entry              dh_waitlisthead;
178 };
179
180 typedef struct nt_dispatch_header nt_dispatch_header;
181
182 #define OTYPE_EVENT             0
183 #define OTYPE_MUTEX             1
184 #define OTYPE_THREAD            2
185 #define OTYPE_TIMER             3
186
187 /* Windows dispatcher levels. */
188
189 #define PASSIVE_LEVEL           0
190 #define LOW_LEVEL               0
191 #define APC_LEVEL               1
192 #define DISPATCH_LEVEL          2
193 #define DEVICE_LEVEL            (DISPATCH_LEVEL + 1)
194 #define PROFILE_LEVEL           27
195 #define CLOCK1_LEVEL            28
196 #define CLOCK2_LEVEL            28
197 #define IPI_LEVEL               29
198 #define POWER_LEVEL             30
199 #define HIGH_LEVEL              31
200
201 #define SYNC_LEVEL_UP           DISPATCH_LEVEL
202 #define SYNC_LEVEL_MP           (IPI_LEVEL - 1)
203
204 #define AT_PASSIVE_LEVEL(td)            \
205         ((td)->td_proc->p_flag & P_KTHREAD == FALSE)
206
207 #define AT_DISPATCH_LEVEL(td)           \
208         (lwkt_getpri(td) == TDPRI_INT_HIGH)
209
210 struct nt_objref {
211         nt_dispatch_header      no_dh;
212         void                    *no_obj;
213         TAILQ_ENTRY(nt_objref)  link;
214 };
215
216 TAILQ_HEAD(nt_objref_head, nt_objref);
217
218 typedef struct nt_objref nt_objref;
219
220 #define EVENT_TYPE_NOTIFY       0
221 #define EVENT_TYPE_SYNC         1
222
223 /*
224  * We need to use the timeout()/untimeout() API for ktimers
225  * since timers can be initialized, but not destroyed (so
226  * malloc()ing our own callout structures would mean a leak,
227  * since there'd be no way to free() them). This means we
228  * need to use struct callout_handle, which is really just a
229  * pointer. To make it easier to deal with, we use a union
230  * to overlay the callout_handle over the k_timerlistentry.
231  * The latter is a list_entry, which is two pointers, so
232  * there's enough space available to hide a callout_handle
233  * there.
234  */
235
236 struct ktimer {
237         nt_dispatch_header      k_header;
238         uint64_t                k_duetime;
239         union {
240                 list_entry              k_timerlistentry;
241                 struct callout_handle   k_handle;
242         } u;
243         void                    *k_dpc;
244         uint32_t                k_period;
245 };
246
247 #define k_timerlistentry        u.k_timerlistentry
248 #define k_handle                u.k_handle
249
250 typedef struct ktimer ktimer;
251
252 struct nt_kevent {
253         nt_dispatch_header      k_header;
254 };
255
256 typedef struct nt_kevent nt_kevent;
257
258 /* Kernel defered procedure call (i.e. timer callback) */
259
260 struct kdpc;
261 typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
262
263 struct kdpc {
264         uint16_t                k_type;
265         uint8_t                 k_num;
266         uint8_t                 k_importance;
267         list_entry              k_dpclistentry;
268         kdpc_func               k_deferedfunc;
269         void                    *k_deferredctx;
270         void                    *k_sysarg1;
271         void                    *k_sysarg2;
272         register_t              k_lock;
273 };
274
275 typedef struct kdpc kdpc;
276
277 /*
278  * Note: the acquisition count is BSD-specific. The Microsoft
279  * documentation says that mutexes can be acquired recursively
280  * by a given thread, but that you must release the mutex as
281  * many times as you acquired it before it will be set to the
282  * signalled state (i.e. before any other threads waiting on
283  * the object will be woken up). However the Windows KMUTANT
284  * structure has no field for keeping track of the number of
285  * acquisitions, so we need to add one ourselves. As long as
286  * driver code treats the mutex as opaque, we should be ok.
287  */
288 struct kmutant {
289         nt_dispatch_header      km_header;
290         union {
291                 list_entry              km_listentry;
292                 uint32_t                km_acquirecnt;
293         } u;
294         void                    *km_ownerthread;
295         uint8_t                 km_abandoned;
296         uint8_t                 km_apcdisable;
297 };
298
299 #define km_listentry            u.km_listentry
300 #define km_acquirecnt           u.km_acquirecnt
301
302 typedef struct kmutant kmutant;
303
304 #define LOOKASIDE_DEPTH 256
305
306 struct general_lookaside {
307         slist_header            gl_listhead;
308         uint16_t                gl_depth;
309         uint16_t                gl_maxdepth;
310         uint32_t                gl_totallocs;
311         union {
312                 uint32_t                gl_allocmisses;
313                 uint32_t                gl_allochits;
314         } u_a;
315         uint32_t                gl_totalfrees;
316         union {
317                 uint32_t                gl_freemisses;
318                 uint32_t                gl_freehits;
319         } u_m;
320         uint32_t                gl_type;
321         uint32_t                gl_tag;
322         uint32_t                gl_size;
323         void                    *gl_allocfunc;
324         void                    *gl_freefunc;
325         list_entry              gl_listent;
326         uint32_t                gl_lasttotallocs;
327         union {
328                 uint32_t                gl_lastallocmisses;
329                 uint32_t                gl_lastallochits;
330         } u_l;
331         uint32_t                gl_rsvd[2];
332 };
333
334 typedef struct general_lookaside general_lookaside;
335
336 struct npaged_lookaside_list {
337         general_lookaside       nll_l;
338         kspin_lock              nll_obsoletelock;
339 };
340
341 typedef struct npaged_lookaside_list npaged_lookaside_list;
342 typedef struct npaged_lookaside_list paged_lookaside_list;
343
344 typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
345 typedef void (*lookaside_free_func)(void *);
346
347 struct irp;
348
349 struct kdevice_qentry {
350         list_entry              kqe_devlistent;
351         uint32_t                kqe_sortkey;
352         uint8_t                 kqe_inserted;
353 };
354
355 typedef struct kdevice_qentry kdevice_qentry;
356
357 struct kdevice_queue {
358         uint16_t                kq_type;
359         uint16_t                kq_size;
360         list_entry              kq_devlisthead;
361         kspin_lock              kq_lock;
362         uint8_t                 kq_busy;
363 };
364
365 typedef struct kdevice_queue kdevice_queue;
366
367 struct wait_ctx_block {
368         kdevice_qentry          wcb_waitqueue;
369         void                    *wcb_devfunc;
370         void                    *wcb_devctx;
371         uint32_t                wcb_mapregcnt;
372         void                    *wcb_devobj;
373         void                    *wcb_curirp;
374         void                    *wcb_bufchaindpc;
375 };
376
377 typedef struct wait_ctx_block wait_ctx_block;
378
379 struct wait_block {
380         list_entry              wb_waitlist;
381         void                    *wb_kthread;
382         nt_dispatch_header      *wb_object;
383         struct wait_block       *wb_next;
384         uint16_t                wb_waitkey;
385         uint16_t                wb_waittype;
386 };
387
388 typedef struct wait_block wait_block;
389
390 #define THREAD_WAIT_OBJECTS     3
391 #define MAX_WAIT_OBJECTS        64
392
393 #define WAITTYPE_ALL            0
394 #define WAITTYPE_ANY            1
395
396 struct thread_context {
397         void                    *tc_thrctx;
398         void                    *tc_thrfunc;
399 };
400
401 typedef struct thread_context thread_context;
402
403 struct device_object {
404         uint16_t                do_type;
405         uint16_t                do_size;
406         uint32_t                do_refcnt;
407         struct device_object    *do_drvobj;
408         struct device_object    *do_nextdev;
409         struct device_object    *do_attacheddev;
410         struct irp              *do_currirp;
411         void                    *do_iotimer;
412         uint32_t                do_flags;
413         uint32_t                do_characteristics;
414         void                    *do_vpb;
415         void                    *do_devext;
416         uint8_t                 do_stacksize;
417         union {
418                 list_entry              do_listent;
419                 wait_ctx_block          do_wcb;
420         } queue;
421         uint32_t                do_alignreq;
422         kdevice_queue           do_devqueue;
423         struct kdpc             do_dpc;
424         uint32_t                do_activethreads;
425         void                    *do_securitydesc;
426         struct nt_kevent        do_devlock;
427         uint16_t                do_sectorsz;
428         uint16_t                do_spare1;
429         void                    *do_devobj_ext;
430         void                    *do_rsvd;
431 };
432
433 typedef struct device_object device_object;
434
435 struct irp {
436         uint32_t                i_dummy;
437 };
438
439 typedef struct irp irp;
440
441 typedef uint32_t (*driver_dispatch)(device_object *, irp *);
442
443 #define DEVPROP_DEVICE_DESCRIPTION      0x00000000
444 #define DEVPROP_HARDWARE_ID             0x00000001
445 #define DEVPROP_COMPATIBLE_IDS          0x00000002
446 #define DEVPROP_BOOTCONF                0x00000003
447 #define DEVPROP_BOOTCONF_TRANSLATED     0x00000004
448 #define DEVPROP_CLASS_NAME              0x00000005
449 #define DEVPROP_CLASS_GUID              0x00000006
450 #define DEVPROP_DRIVER_KEYNAME          0x00000007
451 #define DEVPROP_MANUFACTURER            0x00000008
452 #define DEVPROP_FRIENDLYNAME            0x00000009
453 #define DEVPROP_LOCATION_INFO           0x0000000A
454 #define DEVPROP_PHYSDEV_NAME            0x0000000B
455 #define DEVPROP_BUSTYPE_GUID            0x0000000C
456 #define DEVPROP_LEGACY_BUSTYPE          0x0000000D
457 #define DEVPROP_BUS_NUMBER              0x0000000E
458 #define DEVPROP_ENUMERATOR_NAME         0x0000000F
459 #define DEVPROP_ADDRESS                 0x00000010
460 #define DEVPROP_UINUMBER                0x00000011
461 #define DEVPROP_INSTALL_STATE           0x00000012
462 #define DEVPROP_REMOVAL_POLICY          0x00000013
463
464 #define STATUS_SUCCESS                  0x00000000
465 #define STATUS_USER_APC                 0x000000C0
466 #define STATUS_KERNEL_APC               0x00000100
467 #define STATUS_ALERTED                  0x00000101
468 #define STATUS_TIMEOUT                  0x00000102
469 #define STATUS_INVALID_PARAMETER        0xC000000D
470 #define STATUS_INVALID_DEVICE_REQUEST   0xC0000010
471 #define STATUS_BUFFER_TOO_SMALL         0xC0000023
472 #define STATUS_MUTANT_NOT_OWNED         0xC0000046
473 #define STATUS_INVALID_PARAMETER_2      0xC00000F0
474
475 #define STATUS_WAIT_0                   0x00000000
476
477 /*
478  * FreeBSD's kernel stack is 2 pages in size by default. The
479  * Windows stack is larger, so we need to give our threads more
480  * stack pages. 4 should be enough, we use 8 just to extra safe.
481  */
482 #define NDIS_KSTACK_PAGES       8
483
484 extern image_patch_table ntoskrnl_functbl[];
485
486 __BEGIN_DECLS
487 extern int ntoskrnl_libinit(void);
488 extern int ntoskrnl_libfini(void);
489 __stdcall extern void ntoskrnl_init_dpc(kdpc *, void *, void *);
490 __stdcall extern uint8_t ntoskrnl_queue_dpc(kdpc *, void *, void *);
491 __stdcall extern uint8_t ntoskrnl_dequeue_dpc(kdpc *);
492 __stdcall extern void ntoskrnl_init_timer(ktimer *);
493 __stdcall extern void ntoskrnl_init_timer_ex(ktimer *, uint32_t);
494 __stdcall extern uint8_t ntoskrnl_set_timer(ktimer *, int64_t, kdpc *);  
495 __stdcall extern uint8_t ntoskrnl_set_timer_ex(ktimer *, int64_t,
496         uint32_t, kdpc *);
497 __stdcall extern uint8_t ntoskrnl_cancel_timer(ktimer *);
498 __stdcall extern uint8_t ntoskrnl_read_timer(ktimer *);
499 __stdcall extern uint32_t ntoskrnl_waitforobj(nt_dispatch_header *, uint32_t,
500         uint32_t, uint8_t, int64_t *);
501 __stdcall extern void ntoskrnl_init_event(nt_kevent *, uint32_t, uint8_t);
502 __stdcall extern void ntoskrnl_clear_event(nt_kevent *);
503 __stdcall extern uint32_t ntoskrnl_read_event(nt_kevent *);
504 __stdcall extern uint32_t ntoskrnl_set_event(nt_kevent *, uint32_t, uint8_t);
505 __stdcall extern uint32_t ntoskrnl_reset_event(nt_kevent *);
506 __stdcall __regcall void ntoskrnl_lock_dpc(REGARGS1(kspin_lock *lock));
507 __stdcall __regcall void ntoskrnl_unlock_dpc(REGARGS1(kspin_lock *lock));
508
509 /*
510  * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock()
511  * routines live in the HAL. We try to imitate this behavior.
512  */
513 #ifdef __i386__
514 #define ntoskrnl_acquire_spinlock(a, b)         \
515         *(b) = FASTCALL(hal_lock, a, 0)
516 #define ntoskrnl_release_spinlock(a, b)         \
517         FASTCALL(hal_unlock, a, b)
518 #endif /* __i386__ */
519 __END_DECLS
520
521 #endif /* _NTOSKRNL_VAR_H_ */