Deleted Added
full compact
ntoskrnl_var.h (215779) ntoskrnl_var.h (216242)
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 *
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: head/sys/compat/ndis/ntoskrnl_var.h 215779 2010-11-23 21:49:32Z bschmidt $
32 * $FreeBSD: head/sys/compat/ndis/ntoskrnl_var.h 216242 2010-12-06 20:54:53Z bschmidt $
33 */
34
35#ifndef _NTOSKRNL_VAR_H_
36#define _NTOSKRNL_VAR_H_
37
38#define MTX_NTOSKRNL_SPIN_LOCK "NDIS thread lock"
39
40/*
41 * us_buf is really a wchar_t *, but it's inconvenient to include
42 * all the necessary header goop needed to define it, and it's a
43 * pointer anyway, so for now, just make it a uint16_t *.
44 */
45struct unicode_string {
46 uint16_t us_len;
47 uint16_t us_maxlen;
48 uint16_t *us_buf;
49};
50
51typedef struct unicode_string unicode_string;
52
53struct ansi_string {
54 uint16_t as_len;
55 uint16_t as_maxlen;
56 char *as_buf;
57};
58
59typedef struct ansi_string ansi_string;
60
61/*
62 * Windows memory descriptor list. In Windows, it's possible for
63 * buffers to be passed between user and kernel contexts without
64 * copying. Buffers may also be allocated in either paged or
65 * non-paged memory regions. An MDL describes the pages of memory
66 * used to contain a particular buffer. Note that a single MDL
67 * may describe a buffer that spans multiple pages. An array of
68 * page addresses appears immediately after the MDL structure itself.
69 * MDLs are therefore implicitly variably sized, even though they
70 * don't look it.
71 *
72 * Note that in FreeBSD, we can take many shortcuts in the way
73 * we handle MDLs because:
74 *
75 * - We are only concerned with pages in kernel context. This means
76 * we will only ever use the kernel's memory map, and remapping
77 * of buffers is never needed.
78 *
79 * - Kernel pages can never be paged out, so we don't have to worry
80 * about whether or not a page is actually mapped before going to
81 * touch it.
82 */
83
84struct mdl {
85 struct mdl *mdl_next;
86 uint16_t mdl_size;
87 uint16_t mdl_flags;
88 void *mdl_process;
89 void *mdl_mappedsystemva;
90 void *mdl_startva;
91 uint32_t mdl_bytecount;
92 uint32_t mdl_byteoffset;
93};
94
95typedef struct mdl mdl, ndis_buffer;
96
97/* MDL flags */
98
99#define MDL_MAPPED_TO_SYSTEM_VA 0x0001
100#define MDL_PAGES_LOCKED 0x0002
101#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004
102#define MDL_ALLOCATED_FIXED_SIZE 0x0008
103#define MDL_PARTIAL 0x0010
104#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020
105#define MDL_IO_PAGE_READ 0x0040
106#define MDL_WRITE_OPERATION 0x0080
107#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100
108#define MDL_FREE_EXTRA_PTES 0x0200
109#define MDL_IO_SPACE 0x0800
110#define MDL_NETWORK_HEADER 0x1000
111#define MDL_MAPPING_CAN_FAIL 0x2000
112#define MDL_ALLOCATED_MUST_SUCCEED 0x4000
113#define MDL_ZONE_ALLOCED 0x8000 /* BSD private */
114
115#define MDL_ZONE_PAGES 16
116#define MDL_ZONE_SIZE (sizeof(mdl) + (sizeof(vm_offset_t) * MDL_ZONE_PAGES))
117
118/* Note: assumes x86 page size of 4K. */
119
120#ifndef PAGE_SHIFT
121#if PAGE_SIZE == 4096
122#define PAGE_SHIFT 12
123#elif PAGE_SIZE == 8192
124#define PAGE_SHIFT 13
125#else
126#error PAGE_SHIFT undefined!
127#endif
128#endif
129
130#define SPAN_PAGES(ptr, len) \
131 ((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE - 1)) + \
132 (len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
133
134#define PAGE_ALIGN(ptr) \
135 ((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
136
137#define BYTE_OFFSET(ptr) \
138 ((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
139
140#define MDL_PAGES(m) (vm_offset_t *)(m + 1)
141
142#define MmInitializeMdl(b, baseva, len) \
143 (b)->mdl_next = NULL; \
144 (b)->mdl_size = (uint16_t)(sizeof(mdl) + \
145 (sizeof(vm_offset_t) * SPAN_PAGES((baseva), (len)))); \
146 (b)->mdl_flags = 0; \
147 (b)->mdl_startva = (void *)PAGE_ALIGN((baseva)); \
148 (b)->mdl_byteoffset = BYTE_OFFSET((baseva)); \
149 (b)->mdl_bytecount = (uint32_t)(len);
150
151#define MmGetMdlByteOffset(mdl) ((mdl)->mdl_byteoffset)
152#define MmGetMdlByteCount(mdl) ((mdl)->mdl_bytecount)
153#define MmGetMdlVirtualAddress(mdl) \
154 ((void *)((char *)((mdl)->mdl_startva) + (mdl)->mdl_byteoffset))
155#define MmGetMdlStartVa(mdl) ((mdl)->mdl_startva)
156#define MmGetMdlPfnArray(mdl) MDL_PAGES(mdl)
157
158#define WDM_MAJOR 1
159#define WDM_MINOR_WIN98 0x00
160#define WDM_MINOR_WINME 0x05
161#define WDM_MINOR_WIN2000 0x10
162#define WDM_MINOR_WINXP 0x20
163#define WDM_MINOR_WIN2003 0x30
164
165enum nt_caching_type {
166 MmNonCached = 0,
167 MmCached = 1,
168 MmWriteCombined = 2,
169 MmHardwareCoherentCached = 3,
170 MmNonCachedUnordered = 4,
171 MmUSWCCached = 5,
172 MmMaximumCacheType = 6
173};
174
175/*-
176 * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
177 * According to the Windows DDK header files, KSPIN_LOCK is defined like this:
178 * typedef ULONG_PTR KSPIN_LOCK;
179 *
180 * From basetsd.h (SDK, Feb. 2003):
181 * typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
182 * typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
183 * typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
184 *
185 * The keyword __int3264 specifies an integral type that has the following
186 * properties:
187 * + It is 32-bit on 32-bit platforms
188 * + It is 64-bit on 64-bit platforms
189 * + It is 32-bit on the wire for backward compatibility.
190 * It gets truncated on the sending side and extended appropriately
191 * (signed or unsigned) on the receiving side.
192 *
193 * Thus register_t seems the proper mapping onto FreeBSD for spin locks.
194 */
195
196typedef register_t kspin_lock;
197
198struct slist_entry {
199 struct slist_entry *sl_next;
200};
201
202typedef struct slist_entry slist_entry;
203
204union slist_header {
205 uint64_t slh_align;
206 struct {
207 struct slist_entry *slh_next;
208 uint16_t slh_depth;
209 uint16_t slh_seq;
210 } slh_list;
211};
212
213typedef union slist_header slist_header;
214
215struct list_entry {
216 struct list_entry *nle_flink;
217 struct list_entry *nle_blink;
218};
219
220typedef struct list_entry list_entry;
221
222#define InitializeListHead(l) \
223 (l)->nle_flink = (l)->nle_blink = (l)
224
225#define IsListEmpty(h) \
226 ((h)->nle_flink == (h))
227
228#define RemoveEntryList(e) \
229 do { \
230 list_entry *b; \
231 list_entry *f; \
232 \
233 f = (e)->nle_flink; \
234 b = (e)->nle_blink; \
235 b->nle_flink = f; \
236 f->nle_blink = b; \
237 } while (0)
238
239/* These two have to be inlined since they return things. */
240
241static __inline__ list_entry *
242RemoveHeadList(list_entry *l)
243{
244 list_entry *f;
245 list_entry *e;
246
247 e = l->nle_flink;
248 f = e->nle_flink;
249 l->nle_flink = f;
250 f->nle_blink = l;
251
252 return (e);
253}
254
255static __inline__ list_entry *
256RemoveTailList(list_entry *l)
257{
258 list_entry *b;
259 list_entry *e;
260
261 e = l->nle_blink;
262 b = e->nle_blink;
263 l->nle_blink = b;
264 b->nle_flink = l;
265
266 return (e);
267}
268
269#define InsertTailList(l, e) \
270 do { \
271 list_entry *b; \
272 \
273 b = l->nle_blink; \
274 e->nle_flink = l; \
275 e->nle_blink = b; \
276 b->nle_flink = (e); \
277 l->nle_blink = (e); \
278 } while (0)
279
280#define InsertHeadList(l, e) \
281 do { \
282 list_entry *f; \
283 \
284 f = l->nle_flink; \
285 e->nle_flink = f; \
286 e->nle_blink = l; \
287 f->nle_blink = e; \
288 l->nle_flink = e; \
289 } while (0)
290
291#define CONTAINING_RECORD(addr, type, field) \
292 ((type *)((vm_offset_t)(addr) - (vm_offset_t)(&((type *)0)->field)))
293
294struct nt_dispatch_header {
295 uint8_t dh_type;
296 uint8_t dh_abs;
297 uint8_t dh_size;
298 uint8_t dh_inserted;
299 int32_t dh_sigstate;
300 list_entry dh_waitlisthead;
301};
302
303typedef struct nt_dispatch_header nt_dispatch_header;
304
305/* Dispatcher object types */
306
307#define DISP_TYPE_NOTIFICATION_EVENT 0 /* KEVENT */
308#define DISP_TYPE_SYNCHRONIZATION_EVENT 1 /* KEVENT */
309#define DISP_TYPE_MUTANT 2 /* KMUTANT/KMUTEX */
310#define DISP_TYPE_PROCESS 3 /* KPROCESS */
311#define DISP_TYPE_QUEUE 4 /* KQUEUE */
312#define DISP_TYPE_SEMAPHORE 5 /* KSEMAPHORE */
313#define DISP_TYPE_THREAD 6 /* KTHREAD */
314#define DISP_TYPE_NOTIFICATION_TIMER 8 /* KTIMER */
315#define DISP_TYPE_SYNCHRONIZATION_TIMER 9 /* KTIMER */
316
317#define OTYPE_EVENT 0
318#define OTYPE_MUTEX 1
319#define OTYPE_THREAD 2
320#define OTYPE_TIMER 3
321
322/* Windows dispatcher levels. */
323
324#define PASSIVE_LEVEL 0
325#define LOW_LEVEL 0
326#define APC_LEVEL 1
327#define DISPATCH_LEVEL 2
328#define DEVICE_LEVEL (DISPATCH_LEVEL + 1)
329#define PROFILE_LEVEL 27
330#define CLOCK1_LEVEL 28
331#define CLOCK2_LEVEL 28
332#define IPI_LEVEL 29
333#define POWER_LEVEL 30
334#define HIGH_LEVEL 31
335
336#define SYNC_LEVEL_UP DISPATCH_LEVEL
337#define SYNC_LEVEL_MP (IPI_LEVEL - 1)
338
339#define AT_PASSIVE_LEVEL(td) \
340 ((td)->td_proc->p_flag & P_KTHREAD == FALSE)
341
342#define AT_DISPATCH_LEVEL(td) \
343 ((td)->td_base_pri == PI_REALTIME)
344
345#define AT_DIRQL_LEVEL(td) \
346 ((td)->td_priority <= PI_NET)
347
348#define AT_HIGH_LEVEL(td) \
349 ((td)->td_critnest != 0)
350
351struct nt_objref {
352 nt_dispatch_header no_dh;
353 void *no_obj;
354 TAILQ_ENTRY(nt_objref) link;
355};
356
357TAILQ_HEAD(nt_objref_head, nt_objref);
358
359typedef struct nt_objref nt_objref;
360
361#define EVENT_TYPE_NOTIFY 0
362#define EVENT_TYPE_SYNC 1
363
364/*
365 * We need to use the timeout()/untimeout() API for ktimers
366 * since timers can be initialized, but not destroyed (so
367 * malloc()ing our own callout structures would mean a leak,
368 * since there'd be no way to free() them). This means we
369 * need to use struct callout_handle, which is really just a
370 * pointer. To make it easier to deal with, we use a union
371 * to overlay the callout_handle over the k_timerlistentry.
372 * The latter is a list_entry, which is two pointers, so
373 * there's enough space available to hide a callout_handle
374 * there.
375 */
376
377struct ktimer {
378 nt_dispatch_header k_header;
379 uint64_t k_duetime;
380 union {
381 list_entry k_timerlistentry;
382 struct callout *k_callout;
383 } u;
384 void *k_dpc;
385 uint32_t k_period;
386};
387
388#define k_timerlistentry u.k_timerlistentry
389#define k_callout u.k_callout
390
391typedef struct ktimer ktimer;
392
393struct nt_kevent {
394 nt_dispatch_header k_header;
395};
396
397typedef struct nt_kevent nt_kevent;
398
399/* Kernel defered procedure call (i.e. timer callback) */
400
401struct kdpc;
402typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
403
404struct kdpc {
405 uint16_t k_type;
406 uint8_t k_num; /* CPU number */
407 uint8_t k_importance; /* priority */
408 list_entry k_dpclistentry;
409 void *k_deferedfunc;
410 void *k_deferredctx;
411 void *k_sysarg1;
412 void *k_sysarg2;
413 void *k_lock;
414};
415
416#define KDPC_IMPORTANCE_LOW 0
417#define KDPC_IMPORTANCE_MEDIUM 1
418#define KDPC_IMPORTANCE_HIGH 2
419
420#define KDPC_CPU_DEFAULT 255
421
422typedef struct kdpc kdpc;
423
424/*
425 * Note: the acquisition count is BSD-specific. The Microsoft
426 * documentation says that mutexes can be acquired recursively
427 * by a given thread, but that you must release the mutex as
428 * many times as you acquired it before it will be set to the
429 * signalled state (i.e. before any other threads waiting on
430 * the object will be woken up). However the Windows KMUTANT
431 * structure has no field for keeping track of the number of
432 * acquisitions, so we need to add one ourselves. As long as
433 * driver code treats the mutex as opaque, we should be ok.
434 */
435struct kmutant {
436 nt_dispatch_header km_header;
437 list_entry km_listentry;
438 void *km_ownerthread;
439 uint8_t km_abandoned;
440 uint8_t km_apcdisable;
441};
442
443typedef struct kmutant kmutant;
444
445#define LOOKASIDE_DEPTH 256
446
447struct general_lookaside {
448 slist_header gl_listhead;
449 uint16_t gl_depth;
450 uint16_t gl_maxdepth;
451 uint32_t gl_totallocs;
452 union {
453 uint32_t gl_allocmisses;
454 uint32_t gl_allochits;
455 } u_a;
456 uint32_t gl_totalfrees;
457 union {
458 uint32_t gl_freemisses;
459 uint32_t gl_freehits;
460 } u_m;
461 uint32_t gl_type;
462 uint32_t gl_tag;
463 uint32_t gl_size;
464 void *gl_allocfunc;
465 void *gl_freefunc;
466 list_entry gl_listent;
467 uint32_t gl_lasttotallocs;
468 union {
469 uint32_t gl_lastallocmisses;
470 uint32_t gl_lastallochits;
471 } u_l;
472 uint32_t gl_rsvd[2];
473};
474
475typedef struct general_lookaside general_lookaside;
476
477struct npaged_lookaside_list {
478 general_lookaside nll_l;
479#ifdef __i386__
480 kspin_lock nll_obsoletelock;
481#endif
482};
483
484typedef struct npaged_lookaside_list npaged_lookaside_list;
485typedef struct npaged_lookaside_list paged_lookaside_list;
486
487typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
488typedef void (*lookaside_free_func)(void *);
489
490struct irp;
491
492struct kdevice_qentry {
493 list_entry kqe_devlistent;
494 uint32_t kqe_sortkey;
495 uint8_t kqe_inserted;
496};
497
498typedef struct kdevice_qentry kdevice_qentry;
499
500struct kdevice_queue {
501 uint16_t kq_type;
502 uint16_t kq_size;
503 list_entry kq_devlisthead;
504 kspin_lock kq_lock;
505 uint8_t kq_busy;
506};
507
508typedef struct kdevice_queue kdevice_queue;
509
510struct wait_ctx_block {
511 kdevice_qentry wcb_waitqueue;
512 void *wcb_devfunc;
513 void *wcb_devctx;
514 uint32_t wcb_mapregcnt;
515 void *wcb_devobj;
516 void *wcb_curirp;
517 void *wcb_bufchaindpc;
518};
519
520typedef struct wait_ctx_block wait_ctx_block;
521
522struct wait_block {
523 list_entry wb_waitlist;
524 void *wb_kthread;
525 nt_dispatch_header *wb_object;
526 struct wait_block *wb_next;
527#ifdef notdef
528 uint16_t wb_waitkey;
529 uint16_t wb_waittype;
530#endif
531 uint8_t wb_waitkey;
532 uint8_t wb_waittype;
533 uint8_t wb_awakened;
534 uint8_t wb_oldpri;
535};
536
537typedef struct wait_block wait_block;
538
539#define wb_ext wb_kthread
540
541#define THREAD_WAIT_OBJECTS 3
542#define MAX_WAIT_OBJECTS 64
543
544#define WAITTYPE_ALL 0
545#define WAITTYPE_ANY 1
546
547#define WAITKEY_VALID 0x8000
548
549/* kthread priority */
550#define LOW_PRIORITY 0
551#define LOW_REALTIME_PRIORITY 16
552#define HIGH_PRIORITY 31
553
554struct thread_context {
555 void *tc_thrctx;
556 void *tc_thrfunc;
557};
558
559typedef struct thread_context thread_context;
560
561/* Forward declaration */
562struct driver_object;
563struct devobj_extension;
564
565struct driver_extension {
566 struct driver_object *dre_driverobj;
567 void *dre_adddevicefunc;
568 uint32_t dre_reinitcnt;
569 unicode_string dre_srvname;
570
571 /*
572 * Drivers are allowed to add one or more custom extensions
573 * to the driver object, but there's no special pointer
574 * for them. Hang them off here for now.
575 */
576
577 list_entry dre_usrext;
578};
579
580typedef struct driver_extension driver_extension;
581
582struct custom_extension {
583 list_entry ce_list;
584 void *ce_clid;
585};
586
587typedef struct custom_extension custom_extension;
588
589/*
590 * The KINTERRUPT structure in Windows is opaque to drivers.
591 * We define our own custom version with things we need.
592 */
593
594struct kinterrupt {
595 list_entry ki_list;
596 device_t ki_dev;
597 int ki_rid;
598 void *ki_cookie;
599 struct resource *ki_irq;
600 kspin_lock ki_lock_priv;
601 kspin_lock *ki_lock;
602 void *ki_svcfunc;
603 void *ki_svcctx;
604};
605
606typedef struct kinterrupt kinterrupt;
607
608struct ksystem_time {
609 uint32_t low_part;
610 int32_t high1_time;
611 int32_t high2_time;
612};
613
614enum nt_product_type {
615 NT_PRODUCT_WIN_NT = 1,
616 NT_PRODUCT_LAN_MAN_NT,
617 NT_PRODUCT_SERVER
618};
619
620enum alt_arch_type {
621 STANDARD_DESIGN,
622 NEC98x86,
623 END_ALTERNATIVES
624};
625
626struct kuser_shared_data {
627 uint32_t tick_count;
628 uint32_t tick_count_multiplier;
629 volatile struct ksystem_time interrupt_time;
630 volatile struct ksystem_time system_time;
631 volatile struct ksystem_time time_zone_bias;
632 uint16_t image_number_low;
633 uint16_t image_number_high;
634 int16_t nt_system_root[260];
635 uint32_t max_stack_trace_depth;
636 uint32_t crypto_exponent;
637 uint32_t time_zone_id;
638 uint32_t large_page_min;
639 uint32_t reserved2[7];
640 enum nt_product_type nt_product_type;
641 uint8_t product_type_is_valid;
642 uint32_t nt_major_version;
643 uint32_t nt_minor_version;
644 uint8_t processor_features[64];
645 uint32_t reserved1;
646 uint32_t reserved3;
647 volatile uint32_t time_slip;
648 enum alt_arch_type alt_arch_type;
649 int64_t system_expiration_date;
650 uint32_t suite_mask;
651 uint8_t kdbg_enabled;
652 volatile uint32_t active_console;
653 volatile uint32_t dismount_count;
654 uint32_t com_plus_package;
655 uint32_t last_system_rit_event_tick_count;
656 uint32_t num_phys_pages;
657 uint8_t safe_boot_mode;
658 uint32_t trace_log;
659 uint64_t fill0;
660 uint64_t sys_call[4];
661 union {
662 volatile struct ksystem_time tick_count;
663 volatile uint64_t tick_count_quad;
664 } tick;
665};
666
667/*
668 * In Windows, there are Physical Device Objects (PDOs) and
669 * Functional Device Objects (FDOs). Physical Device Objects are
670 * created and maintained by bus drivers. For example, the PCI
671 * bus driver might detect two PCI ethernet cards on a given
672 * bus. The PCI bus driver will then allocate two device_objects
673 * for its own internal bookeeping purposes. This is analagous
674 * to the device_t that the FreeBSD PCI code allocates and passes
675 * into each PCI driver's probe and attach routines.
676 *
677 * When an ethernet driver claims one of the ethernet cards
678 * on the bus, it will create its own device_object. This is
679 * the Functional Device Object. This object is analagous to the
680 * device-specific softc structure.
681 */
682
683struct device_object {
684 uint16_t do_type;
685 uint16_t do_size;
686 uint32_t do_refcnt;
687 struct driver_object *do_drvobj;
688 struct device_object *do_nextdev;
689 struct device_object *do_attacheddev;
690 struct irp *do_currirp;
691 void *do_iotimer;
692 uint32_t do_flags;
693 uint32_t do_characteristics;
694 void *do_vpb;
695 void *do_devext;
696 uint32_t do_devtype;
697 uint8_t do_stacksize;
698 union {
699 list_entry do_listent;
700 wait_ctx_block do_wcb;
701 } queue;
702 uint32_t do_alignreq;
703 kdevice_queue do_devqueue;
704 struct kdpc do_dpc;
705 uint32_t do_activethreads;
706 void *do_securitydesc;
707 struct nt_kevent do_devlock;
708 uint16_t do_sectorsz;
709 uint16_t do_spare1;
710 struct devobj_extension *do_devobj_ext;
711 void *do_rsvd;
712};
713
714typedef struct device_object device_object;
715
716struct devobj_extension {
717 uint16_t dve_type;
718 uint16_t dve_size;
719 device_object *dve_devobj;
720};
721
722typedef struct devobj_extension devobj_extension;
723
724/* Device object flags */
725
726#define DO_VERIFY_VOLUME 0x00000002
727#define DO_BUFFERED_IO 0x00000004
728#define DO_EXCLUSIVE 0x00000008
729#define DO_DIRECT_IO 0x00000010
730#define DO_MAP_IO_BUFFER 0x00000020
731#define DO_DEVICE_HAS_NAME 0x00000040
732#define DO_DEVICE_INITIALIZING 0x00000080
733#define DO_SYSTEM_BOOT_PARTITION 0x00000100
734#define DO_LONG_TERM_REQUESTS 0x00000200
735#define DO_NEVER_LAST_DEVICE 0x00000400
736#define DO_SHUTDOWN_REGISTERED 0x00000800
737#define DO_BUS_ENUMERATED_DEVICE 0x00001000
738#define DO_POWER_PAGABLE 0x00002000
739#define DO_POWER_INRUSH 0x00004000
740#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000
741
742/* Priority boosts */
743
744#define IO_NO_INCREMENT 0
745#define IO_CD_ROM_INCREMENT 1
746#define IO_DISK_INCREMENT 1
747#define IO_KEYBOARD_INCREMENT 6
748#define IO_MAILSLOT_INCREMENT 2
749#define IO_MOUSE_INCREMENT 6
750#define IO_NAMED_PIPE_INCREMENT 2
751#define IO_NETWORK_INCREMENT 2
752#define IO_PARALLEL_INCREMENT 1
753#define IO_SERIAL_INCREMENT 2
754#define IO_SOUND_INCREMENT 8
755#define IO_VIDEO_INCREMENT 1
756
757/* IRP major codes */
758
759#define IRP_MJ_CREATE 0x00
760#define IRP_MJ_CREATE_NAMED_PIPE 0x01
761#define IRP_MJ_CLOSE 0x02
762#define IRP_MJ_READ 0x03
763#define IRP_MJ_WRITE 0x04
764#define IRP_MJ_QUERY_INFORMATION 0x05
765#define IRP_MJ_SET_INFORMATION 0x06
766#define IRP_MJ_QUERY_EA 0x07
767#define IRP_MJ_SET_EA 0x08
768#define IRP_MJ_FLUSH_BUFFERS 0x09
769#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
770#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b
771#define IRP_MJ_DIRECTORY_CONTROL 0x0c
772#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
773#define IRP_MJ_DEVICE_CONTROL 0x0e
774#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
775#define IRP_MJ_SHUTDOWN 0x10
776#define IRP_MJ_LOCK_CONTROL 0x11
777#define IRP_MJ_CLEANUP 0x12
778#define IRP_MJ_CREATE_MAILSLOT 0x13
779#define IRP_MJ_QUERY_SECURITY 0x14
780#define IRP_MJ_SET_SECURITY 0x15
781#define IRP_MJ_POWER 0x16
782#define IRP_MJ_SYSTEM_CONTROL 0x17
783#define IRP_MJ_DEVICE_CHANGE 0x18
784#define IRP_MJ_QUERY_QUOTA 0x19
785#define IRP_MJ_SET_QUOTA 0x1a
786#define IRP_MJ_PNP 0x1b
787#define IRP_MJ_PNP_POWER IRP_MJ_PNP // Obsolete....
788#define IRP_MJ_MAXIMUM_FUNCTION 0x1b
789#define IRP_MJ_SCSI IRP_MJ_INTERNAL_DEVICE_CONTROL
790
791/* IRP minor codes */
792
793#define IRP_MN_QUERY_DIRECTORY 0x01
794#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02
795#define IRP_MN_USER_FS_REQUEST 0x00
796
797#define IRP_MN_MOUNT_VOLUME 0x01
798#define IRP_MN_VERIFY_VOLUME 0x02
799#define IRP_MN_LOAD_FILE_SYSTEM 0x03
800#define IRP_MN_TRACK_LINK 0x04
801#define IRP_MN_KERNEL_CALL 0x04
802
803#define IRP_MN_LOCK 0x01
804#define IRP_MN_UNLOCK_SINGLE 0x02
805#define IRP_MN_UNLOCK_ALL 0x03
806#define IRP_MN_UNLOCK_ALL_BY_KEY 0x04
807
808#define IRP_MN_NORMAL 0x00
809#define IRP_MN_DPC 0x01
810#define IRP_MN_MDL 0x02
811#define IRP_MN_COMPLETE 0x04
812#define IRP_MN_COMPRESSED 0x08
813
814#define IRP_MN_MDL_DPC (IRP_MN_MDL | IRP_MN_DPC)
815#define IRP_MN_COMPLETE_MDL (IRP_MN_COMPLETE | IRP_MN_MDL)
816#define IRP_MN_COMPLETE_MDL_DPC (IRP_MN_COMPLETE_MDL | IRP_MN_DPC)
817
818#define IRP_MN_SCSI_CLASS 0x01
819
820#define IRP_MN_START_DEVICE 0x00
821#define IRP_MN_QUERY_REMOVE_DEVICE 0x01
822#define IRP_MN_REMOVE_DEVICE 0x02
823#define IRP_MN_CANCEL_REMOVE_DEVICE 0x03
824#define IRP_MN_STOP_DEVICE 0x04
825#define IRP_MN_QUERY_STOP_DEVICE 0x05
826#define IRP_MN_CANCEL_STOP_DEVICE 0x06
827
828#define IRP_MN_QUERY_DEVICE_RELATIONS 0x07
829#define IRP_MN_QUERY_INTERFACE 0x08
830#define IRP_MN_QUERY_CAPABILITIES 0x09
831#define IRP_MN_QUERY_RESOURCES 0x0A
832#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B
833#define IRP_MN_QUERY_DEVICE_TEXT 0x0C
834#define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
835
836#define IRP_MN_READ_CONFIG 0x0F
837#define IRP_MN_WRITE_CONFIG 0x10
838#define IRP_MN_EJECT 0x11
839#define IRP_MN_SET_LOCK 0x12
840#define IRP_MN_QUERY_ID 0x13
841#define IRP_MN_QUERY_PNP_DEVICE_STATE 0x14
842#define IRP_MN_QUERY_BUS_INFORMATION 0x15
843#define IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16
844#define IRP_MN_SURPRISE_REMOVAL 0x17
845#define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
846
847#define IRP_MN_WAIT_WAKE 0x00
848#define IRP_MN_POWER_SEQUENCE 0x01
849#define IRP_MN_SET_POWER 0x02
850#define IRP_MN_QUERY_POWER 0x03
851
852#define IRP_MN_QUERY_ALL_DATA 0x00
853#define IRP_MN_QUERY_SINGLE_INSTANCE 0x01
854#define IRP_MN_CHANGE_SINGLE_INSTANCE 0x02
855#define IRP_MN_CHANGE_SINGLE_ITEM 0x03
856#define IRP_MN_ENABLE_EVENTS 0x04
857#define IRP_MN_DISABLE_EVENTS 0x05
858#define IRP_MN_ENABLE_COLLECTION 0x06
859#define IRP_MN_DISABLE_COLLECTION 0x07
860#define IRP_MN_REGINFO 0x08
861#define IRP_MN_EXECUTE_METHOD 0x09
862#define IRP_MN_REGINFO_EX 0x0b
863
864/* IRP flags */
865
866#define IRP_NOCACHE 0x00000001
867#define IRP_PAGING_IO 0x00000002
868#define IRP_MOUNT_COMPLETION 0x00000002
869#define IRP_SYNCHRONOUS_API 0x00000004
870#define IRP_ASSOCIATED_IRP 0x00000008
871#define IRP_BUFFERED_IO 0x00000010
872#define IRP_DEALLOCATE_BUFFER 0x00000020
873#define IRP_INPUT_OPERATION 0x00000040
874#define IRP_SYNCHRONOUS_PAGING_IO 0x00000040
875#define IRP_CREATE_OPERATION 0x00000080
876#define IRP_READ_OPERATION 0x00000100
877#define IRP_WRITE_OPERATION 0x00000200
878#define IRP_CLOSE_OPERATION 0x00000400
879#define IRP_DEFER_IO_COMPLETION 0x00000800
880#define IRP_OB_QUERY_NAME 0x00001000
881#define IRP_HOLD_DEVICE_QUEUE 0x00002000
882#define IRP_RETRY_IO_COMPLETION 0x00004000
883#define IRP_CLASS_CACHE_OPERATION 0x00008000
884#define IRP_SET_USER_EVENT IRP_CLOSE_OPERATION
885
886/* IRP I/O control flags */
887
888#define IRP_QUOTA_CHARGED 0x01
889#define IRP_ALLOCATED_MUST_SUCCEED 0x02
890#define IRP_ALLOCATED_FIXED_SIZE 0x04
891#define IRP_LOOKASIDE_ALLOCATION 0x08
892
893/* I/O method types */
894
895#define METHOD_BUFFERED 0
896#define METHOD_IN_DIRECT 1
897#define METHOD_OUT_DIRECT 2
898#define METHOD_NEITHER 3
899
900/* File access types */
901
902#define FILE_ANY_ACCESS 0x0000
903#define FILE_SPECIAL_ACCESS FILE_ANY_ACCESS
904#define FILE_READ_ACCESS 0x0001
905#define FILE_WRITE_ACCESS 0x0002
906
907/* Recover I/O access method from IOCTL code. */
908
909#define IO_METHOD(x) ((x) & 0xFFFFFFFC)
910
911/* Recover function code from IOCTL code */
912
913#define IO_FUNC(x) (((x) & 0x7FFC) >> 2)
914
915/* Macro to construct an IOCTL code. */
916
917#define IOCTL_CODE(dev, func, iomethod, acc) \
918 ((dev) << 16) | (acc << 14) | (func << 2) | (iomethod))
919
920
921struct io_status_block {
922 union {
923 uint32_t isb_status;
924 void *isb_ptr;
925 } u;
926 register_t isb_info;
927};
928#define isb_status u.isb_status
929#define isb_ptr u.isb_ptr
930
931typedef struct io_status_block io_status_block;
932
933struct kapc {
934 uint16_t apc_type;
935 uint16_t apc_size;
936 uint32_t apc_spare0;
937 void *apc_thread;
938 list_entry apc_list;
939 void *apc_kernfunc;
940 void *apc_rundownfunc;
941 void *apc_normalfunc;
942 void *apc_normctx;
943 void *apc_sysarg1;
944 void *apc_sysarg2;
945 uint8_t apc_stateidx;
946 uint8_t apc_cpumode;
947 uint8_t apc_inserted;
948};
949
950typedef struct kapc kapc;
951
952typedef uint32_t (*completion_func)(device_object *,
953 struct irp *, void *);
954typedef uint32_t (*cancel_func)(device_object *,
955 struct irp *);
956
957struct io_stack_location {
958 uint8_t isl_major;
959 uint8_t isl_minor;
960 uint8_t isl_flags;
961 uint8_t isl_ctl;
962
963 /*
964 * There's a big-ass union here in the actual Windows
965 * definition of the stucture, but it contains stuff
966 * that doesn't really apply to BSD, and defining it
967 * all properly would require duplicating over a dozen
968 * other structures that we'll never use. Since the
969 * io_stack_location structure is opaque to drivers
970 * anyway, I'm not going to bother with the extra crap.
971 */
972
973 union {
974 struct {
975 uint32_t isl_len;
976 uint32_t *isl_key;
977 uint64_t isl_byteoff;
978 } isl_read;
979 struct {
980 uint32_t isl_len;
981 uint32_t *isl_key;
982 uint64_t isl_byteoff;
983 } isl_write;
984 struct {
985 uint32_t isl_obuflen;
986 uint32_t isl_ibuflen;
987 uint32_t isl_iocode;
988 void *isl_type3ibuf;
989 } isl_ioctl;
990 struct {
991 void *isl_arg1;
992 void *isl_arg2;
993 void *isl_arg3;
994 void *isl_arg4;
995 } isl_others;
996 } isl_parameters __attribute__((packed));
997
998 void *isl_devobj;
999 void *isl_fileobj;
1000 completion_func isl_completionfunc;
1001 void *isl_completionctx;
1002};
1003
1004typedef struct io_stack_location io_stack_location;
1005
1006/* Stack location control flags */
1007
1008#define SL_PENDING_RETURNED 0x01
1009#define SL_INVOKE_ON_CANCEL 0x20
1010#define SL_INVOKE_ON_SUCCESS 0x40
1011#define SL_INVOKE_ON_ERROR 0x80
1012
1013struct irp {
1014 uint16_t irp_type;
1015 uint16_t irp_size;
1016 mdl *irp_mdl;
1017 uint32_t irp_flags;
1018 union {
1019 struct irp *irp_master;
1020 uint32_t irp_irpcnt;
1021 void *irp_sysbuf;
1022 } irp_assoc;
1023 list_entry irp_thlist;
1024 io_status_block irp_iostat;
1025 uint8_t irp_reqmode;
1026 uint8_t irp_pendingreturned;
1027 uint8_t irp_stackcnt;
1028 uint8_t irp_currentstackloc;
1029 uint8_t irp_cancel;
1030 uint8_t irp_cancelirql;
1031 uint8_t irp_apcenv;
1032 uint8_t irp_allocflags;
1033 io_status_block *irp_usriostat;
1034 nt_kevent *irp_usrevent;
1035 union {
1036 struct {
1037 void *irp_apcfunc;
1038 void *irp_apcctx;
1039 } irp_asyncparms;
1040 uint64_t irp_allocsz;
1041 } irp_overlay;
1042 cancel_func irp_cancelfunc;
1043 void *irp_userbuf;
1044
1045 /* Windows kernel info */
1046
1047 union {
1048 struct {
1049 union {
1050 kdevice_qentry irp_dqe;
1051 struct {
1052 void *irp_drvctx[4];
1053 } s1;
1054 } u1;
1055 void *irp_thread;
1056 char *irp_auxbuf;
1057 struct {
1058 list_entry irp_list;
1059 union {
1060 io_stack_location *irp_csl;
1061 uint32_t irp_pkttype;
1062 } u2;
1063 } s2;
1064 void *irp_fileobj;
1065 } irp_overlay;
1066 union {
1067 kapc irp_apc;
1068 struct {
1069 void *irp_ep;
1070 void *irp_dev;
1071 } irp_usb;
1072 } irp_misc;
1073 void *irp_compkey;
1074 } irp_tail;
1075};
1076
1077#define irp_csl s2.u2.irp_csl
1078#define irp_pkttype s2.u2.irp_pkttype
1079
1080#define IRP_NDIS_DEV(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_dev
1081#define IRP_NDISUSB_EP(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_ep
1082
1083typedef struct irp irp;
1084
1085#define InterlockedExchangePointer(dst, val) \
1086 (void *)InterlockedExchange((uint32_t *)(dst), (uintptr_t)(val))
1087
1088#define IoSizeOfIrp(ssize) \
1089 ((uint16_t) (sizeof(irp) + ((ssize) * (sizeof(io_stack_location)))))
1090
1091#define IoSetCancelRoutine(irp, func) \
1092 (cancel_func)InterlockedExchangePointer( \
1093 (void *)&(ip)->irp_cancelfunc, (void *)(func))
1094
1095#define IoSetCancelValue(irp, val) \
1096 (u_long)InterlockedExchangePointer( \
1097 (void *)&(ip)->irp_cancel, (void *)(val))
1098
1099#define IoGetCurrentIrpStackLocation(irp) \
1100 (irp)->irp_tail.irp_overlay.irp_csl
1101
1102#define IoGetNextIrpStackLocation(irp) \
1103 ((irp)->irp_tail.irp_overlay.irp_csl - 1)
1104
1105#define IoSetNextIrpStackLocation(irp) \
1106 do { \
1107 irp->irp_currentstackloc--; \
1108 irp->irp_tail.irp_overlay.irp_csl--; \
1109 } while(0)
1110
1111#define IoSetCompletionRoutine(irp, func, ctx, ok, err, cancel) \
1112 do { \
1113 io_stack_location *s; \
1114 s = IoGetNextIrpStackLocation((irp)); \
1115 s->isl_completionfunc = (func); \
1116 s->isl_completionctx = (ctx); \
1117 s->isl_ctl = 0; \
1118 if (ok) s->isl_ctl = SL_INVOKE_ON_SUCCESS; \
1119 if (err) s->isl_ctl |= SL_INVOKE_ON_ERROR; \
1120 if (cancel) s->isl_ctl |= SL_INVOKE_ON_CANCEL; \
1121 } while(0)
1122
1123#define IoMarkIrpPending(irp) \
1124 IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED
1125#define IoUnmarkIrpPending(irp) \
1126 IoGetCurrentIrpStackLocation(irp)->isl_ctl &= ~SL_PENDING_RETURNED
1127
1128#define IoCopyCurrentIrpStackLocationToNext(irp) \
1129 do { \
1130 io_stack_location *src, *dst; \
1131 src = IoGetCurrentIrpStackLocation(irp); \
1132 dst = IoGetNextIrpStackLocation(irp); \
1133 bcopy((char *)src, (char *)dst, \
1134 offsetof(io_stack_location, isl_completionfunc)); \
1135 } while(0)
1136
1137#define IoSkipCurrentIrpStackLocation(irp) \
1138 do { \
1139 (irp)->irp_currentstackloc++; \
1140 (irp)->irp_tail.irp_overlay.irp_csl++; \
1141 } while(0)
1142
1143#define IoInitializeDpcRequest(dobj, dpcfunc) \
1144 KeInitializeDpc(&(dobj)->do_dpc, dpcfunc, dobj)
1145
1146#define IoRequestDpc(dobj, irp, ctx) \
1147 KeInsertQueueDpc(&(dobj)->do_dpc, irp, ctx)
1148
1149typedef uint32_t (*driver_dispatch)(device_object *, irp *);
1150
1151/*
1152 * The driver_object is allocated once for each driver that's loaded
1153 * into the system. A new one is allocated for each driver and
1154 * populated a bit via the driver's DriverEntry function.
1155 * In general, a Windows DriverEntry() function will provide a pointer
1156 * to its AddDevice() method and set up the dispatch table.
1157 * For NDIS drivers, this is all done behind the scenes in the
1158 * NdisInitializeWrapper() and/or NdisMRegisterMiniport() routines.
1159 */
1160
1161struct driver_object {
1162 uint16_t dro_type;
1163 uint16_t dro_size;
1164 device_object *dro_devobj;
1165 uint32_t dro_flags;
1166 void *dro_driverstart;
1167 uint32_t dro_driversize;
1168 void *dro_driversection;
1169 driver_extension *dro_driverext;
1170 unicode_string dro_drivername;
1171 unicode_string *dro_hwdb;
1172 void *dro_pfastiodispatch;
1173 void *dro_driverinitfunc;
1174 void *dro_driverstartiofunc;
1175 void *dro_driverunloadfunc;
1176 driver_dispatch dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1];
1177};
1178
1179typedef struct driver_object driver_object;
1180
1181#define DEVPROP_DEVICE_DESCRIPTION 0x00000000
1182#define DEVPROP_HARDWARE_ID 0x00000001
1183#define DEVPROP_COMPATIBLE_IDS 0x00000002
1184#define DEVPROP_BOOTCONF 0x00000003
1185#define DEVPROP_BOOTCONF_TRANSLATED 0x00000004
1186#define DEVPROP_CLASS_NAME 0x00000005
1187#define DEVPROP_CLASS_GUID 0x00000006
1188#define DEVPROP_DRIVER_KEYNAME 0x00000007
1189#define DEVPROP_MANUFACTURER 0x00000008
1190#define DEVPROP_FRIENDLYNAME 0x00000009
1191#define DEVPROP_LOCATION_INFO 0x0000000A
1192#define DEVPROP_PHYSDEV_NAME 0x0000000B
1193#define DEVPROP_BUSTYPE_GUID 0x0000000C
1194#define DEVPROP_LEGACY_BUSTYPE 0x0000000D
1195#define DEVPROP_BUS_NUMBER 0x0000000E
1196#define DEVPROP_ENUMERATOR_NAME 0x0000000F
1197#define DEVPROP_ADDRESS 0x00000010
1198#define DEVPROP_UINUMBER 0x00000011
1199#define DEVPROP_INSTALL_STATE 0x00000012
1200#define DEVPROP_REMOVAL_POLICY 0x00000013
1201
1202/* Various supported device types (used with IoCreateDevice()) */
1203
1204#define FILE_DEVICE_BEEP 0x00000001
1205#define FILE_DEVICE_CD_ROM 0x00000002
1206#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
1207#define FILE_DEVICE_CONTROLLER 0x00000004
1208#define FILE_DEVICE_DATALINK 0x00000005
1209#define FILE_DEVICE_DFS 0x00000006
1210#define FILE_DEVICE_DISK 0x00000007
1211#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
1212#define FILE_DEVICE_FILE_SYSTEM 0x00000009
1213#define FILE_DEVICE_INPORT_PORT 0x0000000A
1214#define FILE_DEVICE_KEYBOARD 0x0000000B
1215#define FILE_DEVICE_MAILSLOT 0x0000000C
1216#define FILE_DEVICE_MIDI_IN 0x0000000D
1217#define FILE_DEVICE_MIDI_OUT 0x0000000E
1218#define FILE_DEVICE_MOUSE 0x0000000F
1219#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
1220#define FILE_DEVICE_NAMED_PIPE 0x00000011
1221#define FILE_DEVICE_NETWORK 0x00000012
1222#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
1223#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
1224#define FILE_DEVICE_NULL 0x00000015
1225#define FILE_DEVICE_PARALLEL_PORT 0x00000016
1226#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
1227#define FILE_DEVICE_PRINTER 0x00000018
1228#define FILE_DEVICE_SCANNER 0x00000019
1229#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001A
1230#define FILE_DEVICE_SERIAL_PORT 0x0000001B
1231#define FILE_DEVICE_SCREEN 0x0000001C
1232#define FILE_DEVICE_SOUND 0x0000001D
1233#define FILE_DEVICE_STREAMS 0x0000001E
1234#define FILE_DEVICE_TAPE 0x0000001F
1235#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
1236#define FILE_DEVICE_TRANSPORT 0x00000021
1237#define FILE_DEVICE_UNKNOWN 0x00000022
1238#define FILE_DEVICE_VIDEO 0x00000023
1239#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
1240#define FILE_DEVICE_WAVE_IN 0x00000025
1241#define FILE_DEVICE_WAVE_OUT 0x00000026
1242#define FILE_DEVICE_8042_PORT 0x00000027
1243#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
1244#define FILE_DEVICE_BATTERY 0x00000029
1245#define FILE_DEVICE_BUS_EXTENDER 0x0000002A
1246#define FILE_DEVICE_MODEM 0x0000002B
1247#define FILE_DEVICE_VDM 0x0000002C
1248#define FILE_DEVICE_MASS_STORAGE 0x0000002D
1249#define FILE_DEVICE_SMB 0x0000002E
1250#define FILE_DEVICE_KS 0x0000002F
1251#define FILE_DEVICE_CHANGER 0x00000030
1252#define FILE_DEVICE_SMARTCARD 0x00000031
1253#define FILE_DEVICE_ACPI 0x00000032
1254#define FILE_DEVICE_DVD 0x00000033
1255#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034
1256#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035
1257#define FILE_DEVICE_DFS_VOLUME 0x00000036
1258#define FILE_DEVICE_SERENUM 0x00000037
1259#define FILE_DEVICE_TERMSRV 0x00000038
1260#define FILE_DEVICE_KSEC 0x00000039
1261#define FILE_DEVICE_FIPS 0x0000003A
1262
1263/* Device characteristics */
1264
1265#define FILE_REMOVABLE_MEDIA 0x00000001
1266#define FILE_READ_ONLY_DEVICE 0x00000002
1267#define FILE_FLOPPY_DISKETTE 0x00000004
1268#define FILE_WRITE_ONCE_MEDIA 0x00000008
1269#define FILE_REMOTE_DEVICE 0x00000010
1270#define FILE_DEVICE_IS_MOUNTED 0x00000020
1271#define FILE_VIRTUAL_VOLUME 0x00000040
1272#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
1273#define FILE_DEVICE_SECURE_OPEN 0x00000100
1274
1275/* Status codes */
1276
1277#define STATUS_SUCCESS 0x00000000
1278#define STATUS_USER_APC 0x000000C0
1279#define STATUS_KERNEL_APC 0x00000100
1280#define STATUS_ALERTED 0x00000101
1281#define STATUS_TIMEOUT 0x00000102
1282#define STATUS_PENDING 0x00000103
1283#define STATUS_FAILURE 0xC0000001
1284#define STATUS_NOT_IMPLEMENTED 0xC0000002
1285#define STATUS_ACCESS_VIOLATION 0xC0000005
1286#define STATUS_INVALID_PARAMETER 0xC000000D
1287#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010
1288#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016
1289#define STATUS_NO_MEMORY 0xC0000017
1290#define STATUS_BUFFER_TOO_SMALL 0xC0000023
1291#define STATUS_MUTANT_NOT_OWNED 0xC0000046
1292#define STATUS_NOT_SUPPORTED 0xC00000BB
1293#define STATUS_INVALID_PARAMETER_2 0xC00000F0
1294#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A
1295#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D
1296#define STATUS_CANCELLED 0xC0000120
1297#define STATUS_NOT_FOUND 0xC0000225
1298#define STATUS_DEVICE_REMOVED 0xC00002B6
1299
1300#define STATUS_WAIT_0 0x00000000
1301
1302/* Memory pool types, for ExAllocatePoolWithTag() */
1303
1304#define NonPagedPool 0x00000000
1305#define PagedPool 0x00000001
1306#define NonPagedPoolMustSucceed 0x00000002
1307#define DontUseThisType 0x00000003
1308#define NonPagedPoolCacheAligned 0x00000004
1309#define PagedPoolCacheAligned 0x00000005
1310#define NonPagedPoolCacheAlignedMustS 0x00000006
1311#define MaxPoolType 0x00000007
1312
1313/*
1314 * IO_WORKITEM is an opaque structures that must be allocated
1315 * via IoAllocateWorkItem() and released via IoFreeWorkItem().
1316 * Consequently, we can define it any way we want.
1317 */
1318typedef void (*io_workitem_func)(device_object *, void *);
1319
1320struct io_workitem {
1321 io_workitem_func iw_func;
1322 void *iw_ctx;
1323 list_entry iw_listentry;
1324 device_object *iw_dobj;
1325 int iw_idx;
1326};
1327
1328typedef struct io_workitem io_workitem;
1329
1330#define WORKQUEUE_CRITICAL 0
1331#define WORKQUEUE_DELAYED 1
1332#define WORKQUEUE_HYPERCRITICAL 2
1333
1334#define WORKITEM_THREADS 4
1335#define WORKITEM_LEGACY_THREAD 3
1336#define WORKIDX_INC(x) (x) = (x + 1) % WORKITEM_LEGACY_THREAD
1337
1338/*
1339 * Older, deprecated work item API, needed to support NdisQueueWorkItem().
1340 */
1341
1342struct work_queue_item;
1343
1344typedef void (*work_item_func)(struct work_queue_item *, void *);
1345
1346struct work_queue_item {
1347 list_entry wqi_entry;
1348 work_item_func wqi_func;
1349 void *wqi_ctx;
1350};
1351
1352typedef struct work_queue_item work_queue_item;
1353
1354#define ExInitializeWorkItem(w, func, ctx) \
1355 do { \
1356 (w)->wqi_func = (func); \
1357 (w)->wqi_ctx = (ctx); \
1358 InitializeListHead(&((w)->wqi_entry)); \
1359 } while (0)
1360
1361/*
1362 * FreeBSD's kernel stack is 2 pages in size by default. The
1363 * Windows stack is larger, so we need to give our threads more
1364 * stack pages. 4 should be enough, we use 8 just to extra safe.
1365 */
1366#define NDIS_KSTACK_PAGES 8
1367
1368/*
1369 * Different kinds of function wrapping we can do.
1370 */
1371
1372#define WINDRV_WRAP_STDCALL 1
1373#define WINDRV_WRAP_FASTCALL 2
1374#define WINDRV_WRAP_REGPARM 3
1375#define WINDRV_WRAP_CDECL 4
1376#define WINDRV_WRAP_AMD64 5
1377
1378struct drvdb_ent {
1379 driver_object *windrv_object;
1380 void *windrv_devlist;
1381 ndis_cfg *windrv_regvals;
1382 interface_type windrv_bustype;
1383 STAILQ_ENTRY(drvdb_ent) link;
1384};
1385
1386extern image_patch_table ntoskrnl_functbl[];
1387#ifdef __amd64__
1388extern struct kuser_shared_data kuser_shared_data;
1389#endif
1390typedef void (*funcptr)(void);
1391typedef int (*matchfuncptr)(interface_type, void *, void *);
1392
1393__BEGIN_DECLS
1394extern int windrv_libinit(void);
1395extern int windrv_libfini(void);
1396extern driver_object *windrv_lookup(vm_offset_t, char *);
1397extern struct drvdb_ent *windrv_match(matchfuncptr, void *);
1398extern int windrv_load(module_t, vm_offset_t, int, interface_type,
1399 void *, ndis_cfg *);
1400extern int windrv_unload(module_t, vm_offset_t, int);
1401extern int windrv_create_pdo(driver_object *, device_t);
1402extern void windrv_destroy_pdo(driver_object *, device_t);
1403extern device_object *windrv_find_pdo(driver_object *, device_t);
1404extern int windrv_bus_attach(driver_object *, char *);
1405extern int windrv_wrap(funcptr, funcptr *, int, int);
1406extern int windrv_unwrap(funcptr);
1407extern void ctxsw_utow(void);
1408extern void ctxsw_wtou(void);
1409
1410extern int ntoskrnl_libinit(void);
1411extern int ntoskrnl_libfini(void);
1412
1413extern void ntoskrnl_intr(void *);
1414extern void ntoskrnl_time(uint64_t *);
1415
1416extern uint16_t ExQueryDepthSList(slist_header *);
1417extern slist_entry
1418 *InterlockedPushEntrySList(slist_header *, slist_entry *);
1419extern slist_entry *InterlockedPopEntrySList(slist_header *);
1420extern uint32_t RtlUnicodeStringToAnsiString(ansi_string *,
1421 unicode_string *, uint8_t);
1422extern uint32_t RtlAnsiStringToUnicodeString(unicode_string *,
1423 ansi_string *, uint8_t);
1424extern void RtlInitAnsiString(ansi_string *, char *);
1425extern void RtlInitUnicodeString(unicode_string *,
1426 uint16_t *);
1427extern void RtlFreeUnicodeString(unicode_string *);
1428extern void RtlFreeAnsiString(ansi_string *);
1429extern void KeInitializeDpc(kdpc *, void *, void *);
1430extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *);
1431extern uint8_t KeRemoveQueueDpc(kdpc *);
1432extern void KeSetImportanceDpc(kdpc *, uint32_t);
1433extern void KeSetTargetProcessorDpc(kdpc *, uint8_t);
1434extern void KeFlushQueuedDpcs(void);
1435extern uint32_t KeGetCurrentProcessorNumber(void);
1436extern void KeInitializeTimer(ktimer *);
1437extern void KeInitializeTimerEx(ktimer *, uint32_t);
1438extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *);
1439extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *);
1440extern uint8_t KeCancelTimer(ktimer *);
1441extern uint8_t KeReadStateTimer(ktimer *);
1442extern uint32_t KeWaitForSingleObject(void *, uint32_t,
1443 uint32_t, uint8_t, int64_t *);
1444extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t);
1445extern void KeClearEvent(nt_kevent *);
1446extern uint32_t KeReadStateEvent(nt_kevent *);
1447extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t);
1448extern uint32_t KeResetEvent(nt_kevent *);
1449#ifdef __i386__
1450extern void KefAcquireSpinLockAtDpcLevel(kspin_lock *);
1451extern void KefReleaseSpinLockFromDpcLevel(kspin_lock *);
1452extern uint8_t KeAcquireSpinLockRaiseToDpc(kspin_lock *);
1453#else
1454extern void KeAcquireSpinLockAtDpcLevel(kspin_lock *);
1455extern void KeReleaseSpinLockFromDpcLevel(kspin_lock *);
1456#endif
1457extern void KeInitializeSpinLock(kspin_lock *);
1458extern uint8_t KeAcquireInterruptSpinLock(kinterrupt *);
1459extern void KeReleaseInterruptSpinLock(kinterrupt *, uint8_t);
1460extern uint8_t KeSynchronizeExecution(kinterrupt *, void *, void *);
1461extern uintptr_t InterlockedExchange(volatile uint32_t *,
1462 uintptr_t);
1463extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t);
1464extern void ExFreePool(void *);
1465extern uint32_t IoConnectInterrupt(kinterrupt **, void *, void *,
1466 kspin_lock *, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
1467 uint32_t, uint8_t);
1468extern uint8_t MmIsAddressValid(void *);
33 */
34
35#ifndef _NTOSKRNL_VAR_H_
36#define _NTOSKRNL_VAR_H_
37
38#define MTX_NTOSKRNL_SPIN_LOCK "NDIS thread lock"
39
40/*
41 * us_buf is really a wchar_t *, but it's inconvenient to include
42 * all the necessary header goop needed to define it, and it's a
43 * pointer anyway, so for now, just make it a uint16_t *.
44 */
45struct unicode_string {
46 uint16_t us_len;
47 uint16_t us_maxlen;
48 uint16_t *us_buf;
49};
50
51typedef struct unicode_string unicode_string;
52
53struct ansi_string {
54 uint16_t as_len;
55 uint16_t as_maxlen;
56 char *as_buf;
57};
58
59typedef struct ansi_string ansi_string;
60
61/*
62 * Windows memory descriptor list. In Windows, it's possible for
63 * buffers to be passed between user and kernel contexts without
64 * copying. Buffers may also be allocated in either paged or
65 * non-paged memory regions. An MDL describes the pages of memory
66 * used to contain a particular buffer. Note that a single MDL
67 * may describe a buffer that spans multiple pages. An array of
68 * page addresses appears immediately after the MDL structure itself.
69 * MDLs are therefore implicitly variably sized, even though they
70 * don't look it.
71 *
72 * Note that in FreeBSD, we can take many shortcuts in the way
73 * we handle MDLs because:
74 *
75 * - We are only concerned with pages in kernel context. This means
76 * we will only ever use the kernel's memory map, and remapping
77 * of buffers is never needed.
78 *
79 * - Kernel pages can never be paged out, so we don't have to worry
80 * about whether or not a page is actually mapped before going to
81 * touch it.
82 */
83
84struct mdl {
85 struct mdl *mdl_next;
86 uint16_t mdl_size;
87 uint16_t mdl_flags;
88 void *mdl_process;
89 void *mdl_mappedsystemva;
90 void *mdl_startva;
91 uint32_t mdl_bytecount;
92 uint32_t mdl_byteoffset;
93};
94
95typedef struct mdl mdl, ndis_buffer;
96
97/* MDL flags */
98
99#define MDL_MAPPED_TO_SYSTEM_VA 0x0001
100#define MDL_PAGES_LOCKED 0x0002
101#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004
102#define MDL_ALLOCATED_FIXED_SIZE 0x0008
103#define MDL_PARTIAL 0x0010
104#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020
105#define MDL_IO_PAGE_READ 0x0040
106#define MDL_WRITE_OPERATION 0x0080
107#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100
108#define MDL_FREE_EXTRA_PTES 0x0200
109#define MDL_IO_SPACE 0x0800
110#define MDL_NETWORK_HEADER 0x1000
111#define MDL_MAPPING_CAN_FAIL 0x2000
112#define MDL_ALLOCATED_MUST_SUCCEED 0x4000
113#define MDL_ZONE_ALLOCED 0x8000 /* BSD private */
114
115#define MDL_ZONE_PAGES 16
116#define MDL_ZONE_SIZE (sizeof(mdl) + (sizeof(vm_offset_t) * MDL_ZONE_PAGES))
117
118/* Note: assumes x86 page size of 4K. */
119
120#ifndef PAGE_SHIFT
121#if PAGE_SIZE == 4096
122#define PAGE_SHIFT 12
123#elif PAGE_SIZE == 8192
124#define PAGE_SHIFT 13
125#else
126#error PAGE_SHIFT undefined!
127#endif
128#endif
129
130#define SPAN_PAGES(ptr, len) \
131 ((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE - 1)) + \
132 (len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
133
134#define PAGE_ALIGN(ptr) \
135 ((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
136
137#define BYTE_OFFSET(ptr) \
138 ((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
139
140#define MDL_PAGES(m) (vm_offset_t *)(m + 1)
141
142#define MmInitializeMdl(b, baseva, len) \
143 (b)->mdl_next = NULL; \
144 (b)->mdl_size = (uint16_t)(sizeof(mdl) + \
145 (sizeof(vm_offset_t) * SPAN_PAGES((baseva), (len)))); \
146 (b)->mdl_flags = 0; \
147 (b)->mdl_startva = (void *)PAGE_ALIGN((baseva)); \
148 (b)->mdl_byteoffset = BYTE_OFFSET((baseva)); \
149 (b)->mdl_bytecount = (uint32_t)(len);
150
151#define MmGetMdlByteOffset(mdl) ((mdl)->mdl_byteoffset)
152#define MmGetMdlByteCount(mdl) ((mdl)->mdl_bytecount)
153#define MmGetMdlVirtualAddress(mdl) \
154 ((void *)((char *)((mdl)->mdl_startva) + (mdl)->mdl_byteoffset))
155#define MmGetMdlStartVa(mdl) ((mdl)->mdl_startva)
156#define MmGetMdlPfnArray(mdl) MDL_PAGES(mdl)
157
158#define WDM_MAJOR 1
159#define WDM_MINOR_WIN98 0x00
160#define WDM_MINOR_WINME 0x05
161#define WDM_MINOR_WIN2000 0x10
162#define WDM_MINOR_WINXP 0x20
163#define WDM_MINOR_WIN2003 0x30
164
165enum nt_caching_type {
166 MmNonCached = 0,
167 MmCached = 1,
168 MmWriteCombined = 2,
169 MmHardwareCoherentCached = 3,
170 MmNonCachedUnordered = 4,
171 MmUSWCCached = 5,
172 MmMaximumCacheType = 6
173};
174
175/*-
176 * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
177 * According to the Windows DDK header files, KSPIN_LOCK is defined like this:
178 * typedef ULONG_PTR KSPIN_LOCK;
179 *
180 * From basetsd.h (SDK, Feb. 2003):
181 * typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
182 * typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
183 * typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
184 *
185 * The keyword __int3264 specifies an integral type that has the following
186 * properties:
187 * + It is 32-bit on 32-bit platforms
188 * + It is 64-bit on 64-bit platforms
189 * + It is 32-bit on the wire for backward compatibility.
190 * It gets truncated on the sending side and extended appropriately
191 * (signed or unsigned) on the receiving side.
192 *
193 * Thus register_t seems the proper mapping onto FreeBSD for spin locks.
194 */
195
196typedef register_t kspin_lock;
197
198struct slist_entry {
199 struct slist_entry *sl_next;
200};
201
202typedef struct slist_entry slist_entry;
203
204union slist_header {
205 uint64_t slh_align;
206 struct {
207 struct slist_entry *slh_next;
208 uint16_t slh_depth;
209 uint16_t slh_seq;
210 } slh_list;
211};
212
213typedef union slist_header slist_header;
214
215struct list_entry {
216 struct list_entry *nle_flink;
217 struct list_entry *nle_blink;
218};
219
220typedef struct list_entry list_entry;
221
222#define InitializeListHead(l) \
223 (l)->nle_flink = (l)->nle_blink = (l)
224
225#define IsListEmpty(h) \
226 ((h)->nle_flink == (h))
227
228#define RemoveEntryList(e) \
229 do { \
230 list_entry *b; \
231 list_entry *f; \
232 \
233 f = (e)->nle_flink; \
234 b = (e)->nle_blink; \
235 b->nle_flink = f; \
236 f->nle_blink = b; \
237 } while (0)
238
239/* These two have to be inlined since they return things. */
240
241static __inline__ list_entry *
242RemoveHeadList(list_entry *l)
243{
244 list_entry *f;
245 list_entry *e;
246
247 e = l->nle_flink;
248 f = e->nle_flink;
249 l->nle_flink = f;
250 f->nle_blink = l;
251
252 return (e);
253}
254
255static __inline__ list_entry *
256RemoveTailList(list_entry *l)
257{
258 list_entry *b;
259 list_entry *e;
260
261 e = l->nle_blink;
262 b = e->nle_blink;
263 l->nle_blink = b;
264 b->nle_flink = l;
265
266 return (e);
267}
268
269#define InsertTailList(l, e) \
270 do { \
271 list_entry *b; \
272 \
273 b = l->nle_blink; \
274 e->nle_flink = l; \
275 e->nle_blink = b; \
276 b->nle_flink = (e); \
277 l->nle_blink = (e); \
278 } while (0)
279
280#define InsertHeadList(l, e) \
281 do { \
282 list_entry *f; \
283 \
284 f = l->nle_flink; \
285 e->nle_flink = f; \
286 e->nle_blink = l; \
287 f->nle_blink = e; \
288 l->nle_flink = e; \
289 } while (0)
290
291#define CONTAINING_RECORD(addr, type, field) \
292 ((type *)((vm_offset_t)(addr) - (vm_offset_t)(&((type *)0)->field)))
293
294struct nt_dispatch_header {
295 uint8_t dh_type;
296 uint8_t dh_abs;
297 uint8_t dh_size;
298 uint8_t dh_inserted;
299 int32_t dh_sigstate;
300 list_entry dh_waitlisthead;
301};
302
303typedef struct nt_dispatch_header nt_dispatch_header;
304
305/* Dispatcher object types */
306
307#define DISP_TYPE_NOTIFICATION_EVENT 0 /* KEVENT */
308#define DISP_TYPE_SYNCHRONIZATION_EVENT 1 /* KEVENT */
309#define DISP_TYPE_MUTANT 2 /* KMUTANT/KMUTEX */
310#define DISP_TYPE_PROCESS 3 /* KPROCESS */
311#define DISP_TYPE_QUEUE 4 /* KQUEUE */
312#define DISP_TYPE_SEMAPHORE 5 /* KSEMAPHORE */
313#define DISP_TYPE_THREAD 6 /* KTHREAD */
314#define DISP_TYPE_NOTIFICATION_TIMER 8 /* KTIMER */
315#define DISP_TYPE_SYNCHRONIZATION_TIMER 9 /* KTIMER */
316
317#define OTYPE_EVENT 0
318#define OTYPE_MUTEX 1
319#define OTYPE_THREAD 2
320#define OTYPE_TIMER 3
321
322/* Windows dispatcher levels. */
323
324#define PASSIVE_LEVEL 0
325#define LOW_LEVEL 0
326#define APC_LEVEL 1
327#define DISPATCH_LEVEL 2
328#define DEVICE_LEVEL (DISPATCH_LEVEL + 1)
329#define PROFILE_LEVEL 27
330#define CLOCK1_LEVEL 28
331#define CLOCK2_LEVEL 28
332#define IPI_LEVEL 29
333#define POWER_LEVEL 30
334#define HIGH_LEVEL 31
335
336#define SYNC_LEVEL_UP DISPATCH_LEVEL
337#define SYNC_LEVEL_MP (IPI_LEVEL - 1)
338
339#define AT_PASSIVE_LEVEL(td) \
340 ((td)->td_proc->p_flag & P_KTHREAD == FALSE)
341
342#define AT_DISPATCH_LEVEL(td) \
343 ((td)->td_base_pri == PI_REALTIME)
344
345#define AT_DIRQL_LEVEL(td) \
346 ((td)->td_priority <= PI_NET)
347
348#define AT_HIGH_LEVEL(td) \
349 ((td)->td_critnest != 0)
350
351struct nt_objref {
352 nt_dispatch_header no_dh;
353 void *no_obj;
354 TAILQ_ENTRY(nt_objref) link;
355};
356
357TAILQ_HEAD(nt_objref_head, nt_objref);
358
359typedef struct nt_objref nt_objref;
360
361#define EVENT_TYPE_NOTIFY 0
362#define EVENT_TYPE_SYNC 1
363
364/*
365 * We need to use the timeout()/untimeout() API for ktimers
366 * since timers can be initialized, but not destroyed (so
367 * malloc()ing our own callout structures would mean a leak,
368 * since there'd be no way to free() them). This means we
369 * need to use struct callout_handle, which is really just a
370 * pointer. To make it easier to deal with, we use a union
371 * to overlay the callout_handle over the k_timerlistentry.
372 * The latter is a list_entry, which is two pointers, so
373 * there's enough space available to hide a callout_handle
374 * there.
375 */
376
377struct ktimer {
378 nt_dispatch_header k_header;
379 uint64_t k_duetime;
380 union {
381 list_entry k_timerlistentry;
382 struct callout *k_callout;
383 } u;
384 void *k_dpc;
385 uint32_t k_period;
386};
387
388#define k_timerlistentry u.k_timerlistentry
389#define k_callout u.k_callout
390
391typedef struct ktimer ktimer;
392
393struct nt_kevent {
394 nt_dispatch_header k_header;
395};
396
397typedef struct nt_kevent nt_kevent;
398
399/* Kernel defered procedure call (i.e. timer callback) */
400
401struct kdpc;
402typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
403
404struct kdpc {
405 uint16_t k_type;
406 uint8_t k_num; /* CPU number */
407 uint8_t k_importance; /* priority */
408 list_entry k_dpclistentry;
409 void *k_deferedfunc;
410 void *k_deferredctx;
411 void *k_sysarg1;
412 void *k_sysarg2;
413 void *k_lock;
414};
415
416#define KDPC_IMPORTANCE_LOW 0
417#define KDPC_IMPORTANCE_MEDIUM 1
418#define KDPC_IMPORTANCE_HIGH 2
419
420#define KDPC_CPU_DEFAULT 255
421
422typedef struct kdpc kdpc;
423
424/*
425 * Note: the acquisition count is BSD-specific. The Microsoft
426 * documentation says that mutexes can be acquired recursively
427 * by a given thread, but that you must release the mutex as
428 * many times as you acquired it before it will be set to the
429 * signalled state (i.e. before any other threads waiting on
430 * the object will be woken up). However the Windows KMUTANT
431 * structure has no field for keeping track of the number of
432 * acquisitions, so we need to add one ourselves. As long as
433 * driver code treats the mutex as opaque, we should be ok.
434 */
435struct kmutant {
436 nt_dispatch_header km_header;
437 list_entry km_listentry;
438 void *km_ownerthread;
439 uint8_t km_abandoned;
440 uint8_t km_apcdisable;
441};
442
443typedef struct kmutant kmutant;
444
445#define LOOKASIDE_DEPTH 256
446
447struct general_lookaside {
448 slist_header gl_listhead;
449 uint16_t gl_depth;
450 uint16_t gl_maxdepth;
451 uint32_t gl_totallocs;
452 union {
453 uint32_t gl_allocmisses;
454 uint32_t gl_allochits;
455 } u_a;
456 uint32_t gl_totalfrees;
457 union {
458 uint32_t gl_freemisses;
459 uint32_t gl_freehits;
460 } u_m;
461 uint32_t gl_type;
462 uint32_t gl_tag;
463 uint32_t gl_size;
464 void *gl_allocfunc;
465 void *gl_freefunc;
466 list_entry gl_listent;
467 uint32_t gl_lasttotallocs;
468 union {
469 uint32_t gl_lastallocmisses;
470 uint32_t gl_lastallochits;
471 } u_l;
472 uint32_t gl_rsvd[2];
473};
474
475typedef struct general_lookaside general_lookaside;
476
477struct npaged_lookaside_list {
478 general_lookaside nll_l;
479#ifdef __i386__
480 kspin_lock nll_obsoletelock;
481#endif
482};
483
484typedef struct npaged_lookaside_list npaged_lookaside_list;
485typedef struct npaged_lookaside_list paged_lookaside_list;
486
487typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
488typedef void (*lookaside_free_func)(void *);
489
490struct irp;
491
492struct kdevice_qentry {
493 list_entry kqe_devlistent;
494 uint32_t kqe_sortkey;
495 uint8_t kqe_inserted;
496};
497
498typedef struct kdevice_qentry kdevice_qentry;
499
500struct kdevice_queue {
501 uint16_t kq_type;
502 uint16_t kq_size;
503 list_entry kq_devlisthead;
504 kspin_lock kq_lock;
505 uint8_t kq_busy;
506};
507
508typedef struct kdevice_queue kdevice_queue;
509
510struct wait_ctx_block {
511 kdevice_qentry wcb_waitqueue;
512 void *wcb_devfunc;
513 void *wcb_devctx;
514 uint32_t wcb_mapregcnt;
515 void *wcb_devobj;
516 void *wcb_curirp;
517 void *wcb_bufchaindpc;
518};
519
520typedef struct wait_ctx_block wait_ctx_block;
521
522struct wait_block {
523 list_entry wb_waitlist;
524 void *wb_kthread;
525 nt_dispatch_header *wb_object;
526 struct wait_block *wb_next;
527#ifdef notdef
528 uint16_t wb_waitkey;
529 uint16_t wb_waittype;
530#endif
531 uint8_t wb_waitkey;
532 uint8_t wb_waittype;
533 uint8_t wb_awakened;
534 uint8_t wb_oldpri;
535};
536
537typedef struct wait_block wait_block;
538
539#define wb_ext wb_kthread
540
541#define THREAD_WAIT_OBJECTS 3
542#define MAX_WAIT_OBJECTS 64
543
544#define WAITTYPE_ALL 0
545#define WAITTYPE_ANY 1
546
547#define WAITKEY_VALID 0x8000
548
549/* kthread priority */
550#define LOW_PRIORITY 0
551#define LOW_REALTIME_PRIORITY 16
552#define HIGH_PRIORITY 31
553
554struct thread_context {
555 void *tc_thrctx;
556 void *tc_thrfunc;
557};
558
559typedef struct thread_context thread_context;
560
561/* Forward declaration */
562struct driver_object;
563struct devobj_extension;
564
565struct driver_extension {
566 struct driver_object *dre_driverobj;
567 void *dre_adddevicefunc;
568 uint32_t dre_reinitcnt;
569 unicode_string dre_srvname;
570
571 /*
572 * Drivers are allowed to add one or more custom extensions
573 * to the driver object, but there's no special pointer
574 * for them. Hang them off here for now.
575 */
576
577 list_entry dre_usrext;
578};
579
580typedef struct driver_extension driver_extension;
581
582struct custom_extension {
583 list_entry ce_list;
584 void *ce_clid;
585};
586
587typedef struct custom_extension custom_extension;
588
589/*
590 * The KINTERRUPT structure in Windows is opaque to drivers.
591 * We define our own custom version with things we need.
592 */
593
594struct kinterrupt {
595 list_entry ki_list;
596 device_t ki_dev;
597 int ki_rid;
598 void *ki_cookie;
599 struct resource *ki_irq;
600 kspin_lock ki_lock_priv;
601 kspin_lock *ki_lock;
602 void *ki_svcfunc;
603 void *ki_svcctx;
604};
605
606typedef struct kinterrupt kinterrupt;
607
608struct ksystem_time {
609 uint32_t low_part;
610 int32_t high1_time;
611 int32_t high2_time;
612};
613
614enum nt_product_type {
615 NT_PRODUCT_WIN_NT = 1,
616 NT_PRODUCT_LAN_MAN_NT,
617 NT_PRODUCT_SERVER
618};
619
620enum alt_arch_type {
621 STANDARD_DESIGN,
622 NEC98x86,
623 END_ALTERNATIVES
624};
625
626struct kuser_shared_data {
627 uint32_t tick_count;
628 uint32_t tick_count_multiplier;
629 volatile struct ksystem_time interrupt_time;
630 volatile struct ksystem_time system_time;
631 volatile struct ksystem_time time_zone_bias;
632 uint16_t image_number_low;
633 uint16_t image_number_high;
634 int16_t nt_system_root[260];
635 uint32_t max_stack_trace_depth;
636 uint32_t crypto_exponent;
637 uint32_t time_zone_id;
638 uint32_t large_page_min;
639 uint32_t reserved2[7];
640 enum nt_product_type nt_product_type;
641 uint8_t product_type_is_valid;
642 uint32_t nt_major_version;
643 uint32_t nt_minor_version;
644 uint8_t processor_features[64];
645 uint32_t reserved1;
646 uint32_t reserved3;
647 volatile uint32_t time_slip;
648 enum alt_arch_type alt_arch_type;
649 int64_t system_expiration_date;
650 uint32_t suite_mask;
651 uint8_t kdbg_enabled;
652 volatile uint32_t active_console;
653 volatile uint32_t dismount_count;
654 uint32_t com_plus_package;
655 uint32_t last_system_rit_event_tick_count;
656 uint32_t num_phys_pages;
657 uint8_t safe_boot_mode;
658 uint32_t trace_log;
659 uint64_t fill0;
660 uint64_t sys_call[4];
661 union {
662 volatile struct ksystem_time tick_count;
663 volatile uint64_t tick_count_quad;
664 } tick;
665};
666
667/*
668 * In Windows, there are Physical Device Objects (PDOs) and
669 * Functional Device Objects (FDOs). Physical Device Objects are
670 * created and maintained by bus drivers. For example, the PCI
671 * bus driver might detect two PCI ethernet cards on a given
672 * bus. The PCI bus driver will then allocate two device_objects
673 * for its own internal bookeeping purposes. This is analagous
674 * to the device_t that the FreeBSD PCI code allocates and passes
675 * into each PCI driver's probe and attach routines.
676 *
677 * When an ethernet driver claims one of the ethernet cards
678 * on the bus, it will create its own device_object. This is
679 * the Functional Device Object. This object is analagous to the
680 * device-specific softc structure.
681 */
682
683struct device_object {
684 uint16_t do_type;
685 uint16_t do_size;
686 uint32_t do_refcnt;
687 struct driver_object *do_drvobj;
688 struct device_object *do_nextdev;
689 struct device_object *do_attacheddev;
690 struct irp *do_currirp;
691 void *do_iotimer;
692 uint32_t do_flags;
693 uint32_t do_characteristics;
694 void *do_vpb;
695 void *do_devext;
696 uint32_t do_devtype;
697 uint8_t do_stacksize;
698 union {
699 list_entry do_listent;
700 wait_ctx_block do_wcb;
701 } queue;
702 uint32_t do_alignreq;
703 kdevice_queue do_devqueue;
704 struct kdpc do_dpc;
705 uint32_t do_activethreads;
706 void *do_securitydesc;
707 struct nt_kevent do_devlock;
708 uint16_t do_sectorsz;
709 uint16_t do_spare1;
710 struct devobj_extension *do_devobj_ext;
711 void *do_rsvd;
712};
713
714typedef struct device_object device_object;
715
716struct devobj_extension {
717 uint16_t dve_type;
718 uint16_t dve_size;
719 device_object *dve_devobj;
720};
721
722typedef struct devobj_extension devobj_extension;
723
724/* Device object flags */
725
726#define DO_VERIFY_VOLUME 0x00000002
727#define DO_BUFFERED_IO 0x00000004
728#define DO_EXCLUSIVE 0x00000008
729#define DO_DIRECT_IO 0x00000010
730#define DO_MAP_IO_BUFFER 0x00000020
731#define DO_DEVICE_HAS_NAME 0x00000040
732#define DO_DEVICE_INITIALIZING 0x00000080
733#define DO_SYSTEM_BOOT_PARTITION 0x00000100
734#define DO_LONG_TERM_REQUESTS 0x00000200
735#define DO_NEVER_LAST_DEVICE 0x00000400
736#define DO_SHUTDOWN_REGISTERED 0x00000800
737#define DO_BUS_ENUMERATED_DEVICE 0x00001000
738#define DO_POWER_PAGABLE 0x00002000
739#define DO_POWER_INRUSH 0x00004000
740#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000
741
742/* Priority boosts */
743
744#define IO_NO_INCREMENT 0
745#define IO_CD_ROM_INCREMENT 1
746#define IO_DISK_INCREMENT 1
747#define IO_KEYBOARD_INCREMENT 6
748#define IO_MAILSLOT_INCREMENT 2
749#define IO_MOUSE_INCREMENT 6
750#define IO_NAMED_PIPE_INCREMENT 2
751#define IO_NETWORK_INCREMENT 2
752#define IO_PARALLEL_INCREMENT 1
753#define IO_SERIAL_INCREMENT 2
754#define IO_SOUND_INCREMENT 8
755#define IO_VIDEO_INCREMENT 1
756
757/* IRP major codes */
758
759#define IRP_MJ_CREATE 0x00
760#define IRP_MJ_CREATE_NAMED_PIPE 0x01
761#define IRP_MJ_CLOSE 0x02
762#define IRP_MJ_READ 0x03
763#define IRP_MJ_WRITE 0x04
764#define IRP_MJ_QUERY_INFORMATION 0x05
765#define IRP_MJ_SET_INFORMATION 0x06
766#define IRP_MJ_QUERY_EA 0x07
767#define IRP_MJ_SET_EA 0x08
768#define IRP_MJ_FLUSH_BUFFERS 0x09
769#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
770#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b
771#define IRP_MJ_DIRECTORY_CONTROL 0x0c
772#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
773#define IRP_MJ_DEVICE_CONTROL 0x0e
774#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
775#define IRP_MJ_SHUTDOWN 0x10
776#define IRP_MJ_LOCK_CONTROL 0x11
777#define IRP_MJ_CLEANUP 0x12
778#define IRP_MJ_CREATE_MAILSLOT 0x13
779#define IRP_MJ_QUERY_SECURITY 0x14
780#define IRP_MJ_SET_SECURITY 0x15
781#define IRP_MJ_POWER 0x16
782#define IRP_MJ_SYSTEM_CONTROL 0x17
783#define IRP_MJ_DEVICE_CHANGE 0x18
784#define IRP_MJ_QUERY_QUOTA 0x19
785#define IRP_MJ_SET_QUOTA 0x1a
786#define IRP_MJ_PNP 0x1b
787#define IRP_MJ_PNP_POWER IRP_MJ_PNP // Obsolete....
788#define IRP_MJ_MAXIMUM_FUNCTION 0x1b
789#define IRP_MJ_SCSI IRP_MJ_INTERNAL_DEVICE_CONTROL
790
791/* IRP minor codes */
792
793#define IRP_MN_QUERY_DIRECTORY 0x01
794#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02
795#define IRP_MN_USER_FS_REQUEST 0x00
796
797#define IRP_MN_MOUNT_VOLUME 0x01
798#define IRP_MN_VERIFY_VOLUME 0x02
799#define IRP_MN_LOAD_FILE_SYSTEM 0x03
800#define IRP_MN_TRACK_LINK 0x04
801#define IRP_MN_KERNEL_CALL 0x04
802
803#define IRP_MN_LOCK 0x01
804#define IRP_MN_UNLOCK_SINGLE 0x02
805#define IRP_MN_UNLOCK_ALL 0x03
806#define IRP_MN_UNLOCK_ALL_BY_KEY 0x04
807
808#define IRP_MN_NORMAL 0x00
809#define IRP_MN_DPC 0x01
810#define IRP_MN_MDL 0x02
811#define IRP_MN_COMPLETE 0x04
812#define IRP_MN_COMPRESSED 0x08
813
814#define IRP_MN_MDL_DPC (IRP_MN_MDL | IRP_MN_DPC)
815#define IRP_MN_COMPLETE_MDL (IRP_MN_COMPLETE | IRP_MN_MDL)
816#define IRP_MN_COMPLETE_MDL_DPC (IRP_MN_COMPLETE_MDL | IRP_MN_DPC)
817
818#define IRP_MN_SCSI_CLASS 0x01
819
820#define IRP_MN_START_DEVICE 0x00
821#define IRP_MN_QUERY_REMOVE_DEVICE 0x01
822#define IRP_MN_REMOVE_DEVICE 0x02
823#define IRP_MN_CANCEL_REMOVE_DEVICE 0x03
824#define IRP_MN_STOP_DEVICE 0x04
825#define IRP_MN_QUERY_STOP_DEVICE 0x05
826#define IRP_MN_CANCEL_STOP_DEVICE 0x06
827
828#define IRP_MN_QUERY_DEVICE_RELATIONS 0x07
829#define IRP_MN_QUERY_INTERFACE 0x08
830#define IRP_MN_QUERY_CAPABILITIES 0x09
831#define IRP_MN_QUERY_RESOURCES 0x0A
832#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B
833#define IRP_MN_QUERY_DEVICE_TEXT 0x0C
834#define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
835
836#define IRP_MN_READ_CONFIG 0x0F
837#define IRP_MN_WRITE_CONFIG 0x10
838#define IRP_MN_EJECT 0x11
839#define IRP_MN_SET_LOCK 0x12
840#define IRP_MN_QUERY_ID 0x13
841#define IRP_MN_QUERY_PNP_DEVICE_STATE 0x14
842#define IRP_MN_QUERY_BUS_INFORMATION 0x15
843#define IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16
844#define IRP_MN_SURPRISE_REMOVAL 0x17
845#define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
846
847#define IRP_MN_WAIT_WAKE 0x00
848#define IRP_MN_POWER_SEQUENCE 0x01
849#define IRP_MN_SET_POWER 0x02
850#define IRP_MN_QUERY_POWER 0x03
851
852#define IRP_MN_QUERY_ALL_DATA 0x00
853#define IRP_MN_QUERY_SINGLE_INSTANCE 0x01
854#define IRP_MN_CHANGE_SINGLE_INSTANCE 0x02
855#define IRP_MN_CHANGE_SINGLE_ITEM 0x03
856#define IRP_MN_ENABLE_EVENTS 0x04
857#define IRP_MN_DISABLE_EVENTS 0x05
858#define IRP_MN_ENABLE_COLLECTION 0x06
859#define IRP_MN_DISABLE_COLLECTION 0x07
860#define IRP_MN_REGINFO 0x08
861#define IRP_MN_EXECUTE_METHOD 0x09
862#define IRP_MN_REGINFO_EX 0x0b
863
864/* IRP flags */
865
866#define IRP_NOCACHE 0x00000001
867#define IRP_PAGING_IO 0x00000002
868#define IRP_MOUNT_COMPLETION 0x00000002
869#define IRP_SYNCHRONOUS_API 0x00000004
870#define IRP_ASSOCIATED_IRP 0x00000008
871#define IRP_BUFFERED_IO 0x00000010
872#define IRP_DEALLOCATE_BUFFER 0x00000020
873#define IRP_INPUT_OPERATION 0x00000040
874#define IRP_SYNCHRONOUS_PAGING_IO 0x00000040
875#define IRP_CREATE_OPERATION 0x00000080
876#define IRP_READ_OPERATION 0x00000100
877#define IRP_WRITE_OPERATION 0x00000200
878#define IRP_CLOSE_OPERATION 0x00000400
879#define IRP_DEFER_IO_COMPLETION 0x00000800
880#define IRP_OB_QUERY_NAME 0x00001000
881#define IRP_HOLD_DEVICE_QUEUE 0x00002000
882#define IRP_RETRY_IO_COMPLETION 0x00004000
883#define IRP_CLASS_CACHE_OPERATION 0x00008000
884#define IRP_SET_USER_EVENT IRP_CLOSE_OPERATION
885
886/* IRP I/O control flags */
887
888#define IRP_QUOTA_CHARGED 0x01
889#define IRP_ALLOCATED_MUST_SUCCEED 0x02
890#define IRP_ALLOCATED_FIXED_SIZE 0x04
891#define IRP_LOOKASIDE_ALLOCATION 0x08
892
893/* I/O method types */
894
895#define METHOD_BUFFERED 0
896#define METHOD_IN_DIRECT 1
897#define METHOD_OUT_DIRECT 2
898#define METHOD_NEITHER 3
899
900/* File access types */
901
902#define FILE_ANY_ACCESS 0x0000
903#define FILE_SPECIAL_ACCESS FILE_ANY_ACCESS
904#define FILE_READ_ACCESS 0x0001
905#define FILE_WRITE_ACCESS 0x0002
906
907/* Recover I/O access method from IOCTL code. */
908
909#define IO_METHOD(x) ((x) & 0xFFFFFFFC)
910
911/* Recover function code from IOCTL code */
912
913#define IO_FUNC(x) (((x) & 0x7FFC) >> 2)
914
915/* Macro to construct an IOCTL code. */
916
917#define IOCTL_CODE(dev, func, iomethod, acc) \
918 ((dev) << 16) | (acc << 14) | (func << 2) | (iomethod))
919
920
921struct io_status_block {
922 union {
923 uint32_t isb_status;
924 void *isb_ptr;
925 } u;
926 register_t isb_info;
927};
928#define isb_status u.isb_status
929#define isb_ptr u.isb_ptr
930
931typedef struct io_status_block io_status_block;
932
933struct kapc {
934 uint16_t apc_type;
935 uint16_t apc_size;
936 uint32_t apc_spare0;
937 void *apc_thread;
938 list_entry apc_list;
939 void *apc_kernfunc;
940 void *apc_rundownfunc;
941 void *apc_normalfunc;
942 void *apc_normctx;
943 void *apc_sysarg1;
944 void *apc_sysarg2;
945 uint8_t apc_stateidx;
946 uint8_t apc_cpumode;
947 uint8_t apc_inserted;
948};
949
950typedef struct kapc kapc;
951
952typedef uint32_t (*completion_func)(device_object *,
953 struct irp *, void *);
954typedef uint32_t (*cancel_func)(device_object *,
955 struct irp *);
956
957struct io_stack_location {
958 uint8_t isl_major;
959 uint8_t isl_minor;
960 uint8_t isl_flags;
961 uint8_t isl_ctl;
962
963 /*
964 * There's a big-ass union here in the actual Windows
965 * definition of the stucture, but it contains stuff
966 * that doesn't really apply to BSD, and defining it
967 * all properly would require duplicating over a dozen
968 * other structures that we'll never use. Since the
969 * io_stack_location structure is opaque to drivers
970 * anyway, I'm not going to bother with the extra crap.
971 */
972
973 union {
974 struct {
975 uint32_t isl_len;
976 uint32_t *isl_key;
977 uint64_t isl_byteoff;
978 } isl_read;
979 struct {
980 uint32_t isl_len;
981 uint32_t *isl_key;
982 uint64_t isl_byteoff;
983 } isl_write;
984 struct {
985 uint32_t isl_obuflen;
986 uint32_t isl_ibuflen;
987 uint32_t isl_iocode;
988 void *isl_type3ibuf;
989 } isl_ioctl;
990 struct {
991 void *isl_arg1;
992 void *isl_arg2;
993 void *isl_arg3;
994 void *isl_arg4;
995 } isl_others;
996 } isl_parameters __attribute__((packed));
997
998 void *isl_devobj;
999 void *isl_fileobj;
1000 completion_func isl_completionfunc;
1001 void *isl_completionctx;
1002};
1003
1004typedef struct io_stack_location io_stack_location;
1005
1006/* Stack location control flags */
1007
1008#define SL_PENDING_RETURNED 0x01
1009#define SL_INVOKE_ON_CANCEL 0x20
1010#define SL_INVOKE_ON_SUCCESS 0x40
1011#define SL_INVOKE_ON_ERROR 0x80
1012
1013struct irp {
1014 uint16_t irp_type;
1015 uint16_t irp_size;
1016 mdl *irp_mdl;
1017 uint32_t irp_flags;
1018 union {
1019 struct irp *irp_master;
1020 uint32_t irp_irpcnt;
1021 void *irp_sysbuf;
1022 } irp_assoc;
1023 list_entry irp_thlist;
1024 io_status_block irp_iostat;
1025 uint8_t irp_reqmode;
1026 uint8_t irp_pendingreturned;
1027 uint8_t irp_stackcnt;
1028 uint8_t irp_currentstackloc;
1029 uint8_t irp_cancel;
1030 uint8_t irp_cancelirql;
1031 uint8_t irp_apcenv;
1032 uint8_t irp_allocflags;
1033 io_status_block *irp_usriostat;
1034 nt_kevent *irp_usrevent;
1035 union {
1036 struct {
1037 void *irp_apcfunc;
1038 void *irp_apcctx;
1039 } irp_asyncparms;
1040 uint64_t irp_allocsz;
1041 } irp_overlay;
1042 cancel_func irp_cancelfunc;
1043 void *irp_userbuf;
1044
1045 /* Windows kernel info */
1046
1047 union {
1048 struct {
1049 union {
1050 kdevice_qentry irp_dqe;
1051 struct {
1052 void *irp_drvctx[4];
1053 } s1;
1054 } u1;
1055 void *irp_thread;
1056 char *irp_auxbuf;
1057 struct {
1058 list_entry irp_list;
1059 union {
1060 io_stack_location *irp_csl;
1061 uint32_t irp_pkttype;
1062 } u2;
1063 } s2;
1064 void *irp_fileobj;
1065 } irp_overlay;
1066 union {
1067 kapc irp_apc;
1068 struct {
1069 void *irp_ep;
1070 void *irp_dev;
1071 } irp_usb;
1072 } irp_misc;
1073 void *irp_compkey;
1074 } irp_tail;
1075};
1076
1077#define irp_csl s2.u2.irp_csl
1078#define irp_pkttype s2.u2.irp_pkttype
1079
1080#define IRP_NDIS_DEV(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_dev
1081#define IRP_NDISUSB_EP(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_ep
1082
1083typedef struct irp irp;
1084
1085#define InterlockedExchangePointer(dst, val) \
1086 (void *)InterlockedExchange((uint32_t *)(dst), (uintptr_t)(val))
1087
1088#define IoSizeOfIrp(ssize) \
1089 ((uint16_t) (sizeof(irp) + ((ssize) * (sizeof(io_stack_location)))))
1090
1091#define IoSetCancelRoutine(irp, func) \
1092 (cancel_func)InterlockedExchangePointer( \
1093 (void *)&(ip)->irp_cancelfunc, (void *)(func))
1094
1095#define IoSetCancelValue(irp, val) \
1096 (u_long)InterlockedExchangePointer( \
1097 (void *)&(ip)->irp_cancel, (void *)(val))
1098
1099#define IoGetCurrentIrpStackLocation(irp) \
1100 (irp)->irp_tail.irp_overlay.irp_csl
1101
1102#define IoGetNextIrpStackLocation(irp) \
1103 ((irp)->irp_tail.irp_overlay.irp_csl - 1)
1104
1105#define IoSetNextIrpStackLocation(irp) \
1106 do { \
1107 irp->irp_currentstackloc--; \
1108 irp->irp_tail.irp_overlay.irp_csl--; \
1109 } while(0)
1110
1111#define IoSetCompletionRoutine(irp, func, ctx, ok, err, cancel) \
1112 do { \
1113 io_stack_location *s; \
1114 s = IoGetNextIrpStackLocation((irp)); \
1115 s->isl_completionfunc = (func); \
1116 s->isl_completionctx = (ctx); \
1117 s->isl_ctl = 0; \
1118 if (ok) s->isl_ctl = SL_INVOKE_ON_SUCCESS; \
1119 if (err) s->isl_ctl |= SL_INVOKE_ON_ERROR; \
1120 if (cancel) s->isl_ctl |= SL_INVOKE_ON_CANCEL; \
1121 } while(0)
1122
1123#define IoMarkIrpPending(irp) \
1124 IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED
1125#define IoUnmarkIrpPending(irp) \
1126 IoGetCurrentIrpStackLocation(irp)->isl_ctl &= ~SL_PENDING_RETURNED
1127
1128#define IoCopyCurrentIrpStackLocationToNext(irp) \
1129 do { \
1130 io_stack_location *src, *dst; \
1131 src = IoGetCurrentIrpStackLocation(irp); \
1132 dst = IoGetNextIrpStackLocation(irp); \
1133 bcopy((char *)src, (char *)dst, \
1134 offsetof(io_stack_location, isl_completionfunc)); \
1135 } while(0)
1136
1137#define IoSkipCurrentIrpStackLocation(irp) \
1138 do { \
1139 (irp)->irp_currentstackloc++; \
1140 (irp)->irp_tail.irp_overlay.irp_csl++; \
1141 } while(0)
1142
1143#define IoInitializeDpcRequest(dobj, dpcfunc) \
1144 KeInitializeDpc(&(dobj)->do_dpc, dpcfunc, dobj)
1145
1146#define IoRequestDpc(dobj, irp, ctx) \
1147 KeInsertQueueDpc(&(dobj)->do_dpc, irp, ctx)
1148
1149typedef uint32_t (*driver_dispatch)(device_object *, irp *);
1150
1151/*
1152 * The driver_object is allocated once for each driver that's loaded
1153 * into the system. A new one is allocated for each driver and
1154 * populated a bit via the driver's DriverEntry function.
1155 * In general, a Windows DriverEntry() function will provide a pointer
1156 * to its AddDevice() method and set up the dispatch table.
1157 * For NDIS drivers, this is all done behind the scenes in the
1158 * NdisInitializeWrapper() and/or NdisMRegisterMiniport() routines.
1159 */
1160
1161struct driver_object {
1162 uint16_t dro_type;
1163 uint16_t dro_size;
1164 device_object *dro_devobj;
1165 uint32_t dro_flags;
1166 void *dro_driverstart;
1167 uint32_t dro_driversize;
1168 void *dro_driversection;
1169 driver_extension *dro_driverext;
1170 unicode_string dro_drivername;
1171 unicode_string *dro_hwdb;
1172 void *dro_pfastiodispatch;
1173 void *dro_driverinitfunc;
1174 void *dro_driverstartiofunc;
1175 void *dro_driverunloadfunc;
1176 driver_dispatch dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1];
1177};
1178
1179typedef struct driver_object driver_object;
1180
1181#define DEVPROP_DEVICE_DESCRIPTION 0x00000000
1182#define DEVPROP_HARDWARE_ID 0x00000001
1183#define DEVPROP_COMPATIBLE_IDS 0x00000002
1184#define DEVPROP_BOOTCONF 0x00000003
1185#define DEVPROP_BOOTCONF_TRANSLATED 0x00000004
1186#define DEVPROP_CLASS_NAME 0x00000005
1187#define DEVPROP_CLASS_GUID 0x00000006
1188#define DEVPROP_DRIVER_KEYNAME 0x00000007
1189#define DEVPROP_MANUFACTURER 0x00000008
1190#define DEVPROP_FRIENDLYNAME 0x00000009
1191#define DEVPROP_LOCATION_INFO 0x0000000A
1192#define DEVPROP_PHYSDEV_NAME 0x0000000B
1193#define DEVPROP_BUSTYPE_GUID 0x0000000C
1194#define DEVPROP_LEGACY_BUSTYPE 0x0000000D
1195#define DEVPROP_BUS_NUMBER 0x0000000E
1196#define DEVPROP_ENUMERATOR_NAME 0x0000000F
1197#define DEVPROP_ADDRESS 0x00000010
1198#define DEVPROP_UINUMBER 0x00000011
1199#define DEVPROP_INSTALL_STATE 0x00000012
1200#define DEVPROP_REMOVAL_POLICY 0x00000013
1201
1202/* Various supported device types (used with IoCreateDevice()) */
1203
1204#define FILE_DEVICE_BEEP 0x00000001
1205#define FILE_DEVICE_CD_ROM 0x00000002
1206#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
1207#define FILE_DEVICE_CONTROLLER 0x00000004
1208#define FILE_DEVICE_DATALINK 0x00000005
1209#define FILE_DEVICE_DFS 0x00000006
1210#define FILE_DEVICE_DISK 0x00000007
1211#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
1212#define FILE_DEVICE_FILE_SYSTEM 0x00000009
1213#define FILE_DEVICE_INPORT_PORT 0x0000000A
1214#define FILE_DEVICE_KEYBOARD 0x0000000B
1215#define FILE_DEVICE_MAILSLOT 0x0000000C
1216#define FILE_DEVICE_MIDI_IN 0x0000000D
1217#define FILE_DEVICE_MIDI_OUT 0x0000000E
1218#define FILE_DEVICE_MOUSE 0x0000000F
1219#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
1220#define FILE_DEVICE_NAMED_PIPE 0x00000011
1221#define FILE_DEVICE_NETWORK 0x00000012
1222#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
1223#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
1224#define FILE_DEVICE_NULL 0x00000015
1225#define FILE_DEVICE_PARALLEL_PORT 0x00000016
1226#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
1227#define FILE_DEVICE_PRINTER 0x00000018
1228#define FILE_DEVICE_SCANNER 0x00000019
1229#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001A
1230#define FILE_DEVICE_SERIAL_PORT 0x0000001B
1231#define FILE_DEVICE_SCREEN 0x0000001C
1232#define FILE_DEVICE_SOUND 0x0000001D
1233#define FILE_DEVICE_STREAMS 0x0000001E
1234#define FILE_DEVICE_TAPE 0x0000001F
1235#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
1236#define FILE_DEVICE_TRANSPORT 0x00000021
1237#define FILE_DEVICE_UNKNOWN 0x00000022
1238#define FILE_DEVICE_VIDEO 0x00000023
1239#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
1240#define FILE_DEVICE_WAVE_IN 0x00000025
1241#define FILE_DEVICE_WAVE_OUT 0x00000026
1242#define FILE_DEVICE_8042_PORT 0x00000027
1243#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
1244#define FILE_DEVICE_BATTERY 0x00000029
1245#define FILE_DEVICE_BUS_EXTENDER 0x0000002A
1246#define FILE_DEVICE_MODEM 0x0000002B
1247#define FILE_DEVICE_VDM 0x0000002C
1248#define FILE_DEVICE_MASS_STORAGE 0x0000002D
1249#define FILE_DEVICE_SMB 0x0000002E
1250#define FILE_DEVICE_KS 0x0000002F
1251#define FILE_DEVICE_CHANGER 0x00000030
1252#define FILE_DEVICE_SMARTCARD 0x00000031
1253#define FILE_DEVICE_ACPI 0x00000032
1254#define FILE_DEVICE_DVD 0x00000033
1255#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034
1256#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035
1257#define FILE_DEVICE_DFS_VOLUME 0x00000036
1258#define FILE_DEVICE_SERENUM 0x00000037
1259#define FILE_DEVICE_TERMSRV 0x00000038
1260#define FILE_DEVICE_KSEC 0x00000039
1261#define FILE_DEVICE_FIPS 0x0000003A
1262
1263/* Device characteristics */
1264
1265#define FILE_REMOVABLE_MEDIA 0x00000001
1266#define FILE_READ_ONLY_DEVICE 0x00000002
1267#define FILE_FLOPPY_DISKETTE 0x00000004
1268#define FILE_WRITE_ONCE_MEDIA 0x00000008
1269#define FILE_REMOTE_DEVICE 0x00000010
1270#define FILE_DEVICE_IS_MOUNTED 0x00000020
1271#define FILE_VIRTUAL_VOLUME 0x00000040
1272#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080
1273#define FILE_DEVICE_SECURE_OPEN 0x00000100
1274
1275/* Status codes */
1276
1277#define STATUS_SUCCESS 0x00000000
1278#define STATUS_USER_APC 0x000000C0
1279#define STATUS_KERNEL_APC 0x00000100
1280#define STATUS_ALERTED 0x00000101
1281#define STATUS_TIMEOUT 0x00000102
1282#define STATUS_PENDING 0x00000103
1283#define STATUS_FAILURE 0xC0000001
1284#define STATUS_NOT_IMPLEMENTED 0xC0000002
1285#define STATUS_ACCESS_VIOLATION 0xC0000005
1286#define STATUS_INVALID_PARAMETER 0xC000000D
1287#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010
1288#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016
1289#define STATUS_NO_MEMORY 0xC0000017
1290#define STATUS_BUFFER_TOO_SMALL 0xC0000023
1291#define STATUS_MUTANT_NOT_OWNED 0xC0000046
1292#define STATUS_NOT_SUPPORTED 0xC00000BB
1293#define STATUS_INVALID_PARAMETER_2 0xC00000F0
1294#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A
1295#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D
1296#define STATUS_CANCELLED 0xC0000120
1297#define STATUS_NOT_FOUND 0xC0000225
1298#define STATUS_DEVICE_REMOVED 0xC00002B6
1299
1300#define STATUS_WAIT_0 0x00000000
1301
1302/* Memory pool types, for ExAllocatePoolWithTag() */
1303
1304#define NonPagedPool 0x00000000
1305#define PagedPool 0x00000001
1306#define NonPagedPoolMustSucceed 0x00000002
1307#define DontUseThisType 0x00000003
1308#define NonPagedPoolCacheAligned 0x00000004
1309#define PagedPoolCacheAligned 0x00000005
1310#define NonPagedPoolCacheAlignedMustS 0x00000006
1311#define MaxPoolType 0x00000007
1312
1313/*
1314 * IO_WORKITEM is an opaque structures that must be allocated
1315 * via IoAllocateWorkItem() and released via IoFreeWorkItem().
1316 * Consequently, we can define it any way we want.
1317 */
1318typedef void (*io_workitem_func)(device_object *, void *);
1319
1320struct io_workitem {
1321 io_workitem_func iw_func;
1322 void *iw_ctx;
1323 list_entry iw_listentry;
1324 device_object *iw_dobj;
1325 int iw_idx;
1326};
1327
1328typedef struct io_workitem io_workitem;
1329
1330#define WORKQUEUE_CRITICAL 0
1331#define WORKQUEUE_DELAYED 1
1332#define WORKQUEUE_HYPERCRITICAL 2
1333
1334#define WORKITEM_THREADS 4
1335#define WORKITEM_LEGACY_THREAD 3
1336#define WORKIDX_INC(x) (x) = (x + 1) % WORKITEM_LEGACY_THREAD
1337
1338/*
1339 * Older, deprecated work item API, needed to support NdisQueueWorkItem().
1340 */
1341
1342struct work_queue_item;
1343
1344typedef void (*work_item_func)(struct work_queue_item *, void *);
1345
1346struct work_queue_item {
1347 list_entry wqi_entry;
1348 work_item_func wqi_func;
1349 void *wqi_ctx;
1350};
1351
1352typedef struct work_queue_item work_queue_item;
1353
1354#define ExInitializeWorkItem(w, func, ctx) \
1355 do { \
1356 (w)->wqi_func = (func); \
1357 (w)->wqi_ctx = (ctx); \
1358 InitializeListHead(&((w)->wqi_entry)); \
1359 } while (0)
1360
1361/*
1362 * FreeBSD's kernel stack is 2 pages in size by default. The
1363 * Windows stack is larger, so we need to give our threads more
1364 * stack pages. 4 should be enough, we use 8 just to extra safe.
1365 */
1366#define NDIS_KSTACK_PAGES 8
1367
1368/*
1369 * Different kinds of function wrapping we can do.
1370 */
1371
1372#define WINDRV_WRAP_STDCALL 1
1373#define WINDRV_WRAP_FASTCALL 2
1374#define WINDRV_WRAP_REGPARM 3
1375#define WINDRV_WRAP_CDECL 4
1376#define WINDRV_WRAP_AMD64 5
1377
1378struct drvdb_ent {
1379 driver_object *windrv_object;
1380 void *windrv_devlist;
1381 ndis_cfg *windrv_regvals;
1382 interface_type windrv_bustype;
1383 STAILQ_ENTRY(drvdb_ent) link;
1384};
1385
1386extern image_patch_table ntoskrnl_functbl[];
1387#ifdef __amd64__
1388extern struct kuser_shared_data kuser_shared_data;
1389#endif
1390typedef void (*funcptr)(void);
1391typedef int (*matchfuncptr)(interface_type, void *, void *);
1392
1393__BEGIN_DECLS
1394extern int windrv_libinit(void);
1395extern int windrv_libfini(void);
1396extern driver_object *windrv_lookup(vm_offset_t, char *);
1397extern struct drvdb_ent *windrv_match(matchfuncptr, void *);
1398extern int windrv_load(module_t, vm_offset_t, int, interface_type,
1399 void *, ndis_cfg *);
1400extern int windrv_unload(module_t, vm_offset_t, int);
1401extern int windrv_create_pdo(driver_object *, device_t);
1402extern void windrv_destroy_pdo(driver_object *, device_t);
1403extern device_object *windrv_find_pdo(driver_object *, device_t);
1404extern int windrv_bus_attach(driver_object *, char *);
1405extern int windrv_wrap(funcptr, funcptr *, int, int);
1406extern int windrv_unwrap(funcptr);
1407extern void ctxsw_utow(void);
1408extern void ctxsw_wtou(void);
1409
1410extern int ntoskrnl_libinit(void);
1411extern int ntoskrnl_libfini(void);
1412
1413extern void ntoskrnl_intr(void *);
1414extern void ntoskrnl_time(uint64_t *);
1415
1416extern uint16_t ExQueryDepthSList(slist_header *);
1417extern slist_entry
1418 *InterlockedPushEntrySList(slist_header *, slist_entry *);
1419extern slist_entry *InterlockedPopEntrySList(slist_header *);
1420extern uint32_t RtlUnicodeStringToAnsiString(ansi_string *,
1421 unicode_string *, uint8_t);
1422extern uint32_t RtlAnsiStringToUnicodeString(unicode_string *,
1423 ansi_string *, uint8_t);
1424extern void RtlInitAnsiString(ansi_string *, char *);
1425extern void RtlInitUnicodeString(unicode_string *,
1426 uint16_t *);
1427extern void RtlFreeUnicodeString(unicode_string *);
1428extern void RtlFreeAnsiString(ansi_string *);
1429extern void KeInitializeDpc(kdpc *, void *, void *);
1430extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *);
1431extern uint8_t KeRemoveQueueDpc(kdpc *);
1432extern void KeSetImportanceDpc(kdpc *, uint32_t);
1433extern void KeSetTargetProcessorDpc(kdpc *, uint8_t);
1434extern void KeFlushQueuedDpcs(void);
1435extern uint32_t KeGetCurrentProcessorNumber(void);
1436extern void KeInitializeTimer(ktimer *);
1437extern void KeInitializeTimerEx(ktimer *, uint32_t);
1438extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *);
1439extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *);
1440extern uint8_t KeCancelTimer(ktimer *);
1441extern uint8_t KeReadStateTimer(ktimer *);
1442extern uint32_t KeWaitForSingleObject(void *, uint32_t,
1443 uint32_t, uint8_t, int64_t *);
1444extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t);
1445extern void KeClearEvent(nt_kevent *);
1446extern uint32_t KeReadStateEvent(nt_kevent *);
1447extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t);
1448extern uint32_t KeResetEvent(nt_kevent *);
1449#ifdef __i386__
1450extern void KefAcquireSpinLockAtDpcLevel(kspin_lock *);
1451extern void KefReleaseSpinLockFromDpcLevel(kspin_lock *);
1452extern uint8_t KeAcquireSpinLockRaiseToDpc(kspin_lock *);
1453#else
1454extern void KeAcquireSpinLockAtDpcLevel(kspin_lock *);
1455extern void KeReleaseSpinLockFromDpcLevel(kspin_lock *);
1456#endif
1457extern void KeInitializeSpinLock(kspin_lock *);
1458extern uint8_t KeAcquireInterruptSpinLock(kinterrupt *);
1459extern void KeReleaseInterruptSpinLock(kinterrupt *, uint8_t);
1460extern uint8_t KeSynchronizeExecution(kinterrupt *, void *, void *);
1461extern uintptr_t InterlockedExchange(volatile uint32_t *,
1462 uintptr_t);
1463extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t);
1464extern void ExFreePool(void *);
1465extern uint32_t IoConnectInterrupt(kinterrupt **, void *, void *,
1466 kspin_lock *, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
1467 uint32_t, uint8_t);
1468extern uint8_t MmIsAddressValid(void *);
1469extern void *MmGetSystemRoutineAddress(unicode_string *);
1469extern void *MmMapIoSpace(uint64_t, uint32_t, uint32_t);
1470extern void MmUnmapIoSpace(void *, size_t);
1471extern void MmBuildMdlForNonPagedPool(mdl *);
1472extern void IoDisconnectInterrupt(kinterrupt *);
1473extern uint32_t IoAllocateDriverObjectExtension(driver_object *,
1474 void *, uint32_t, void **);
1475extern void *IoGetDriverObjectExtension(driver_object *, void *);
1476extern uint32_t IoCreateDevice(driver_object *, uint32_t,
1477 unicode_string *, uint32_t, uint32_t, uint8_t, device_object **);
1478extern void IoDeleteDevice(device_object *);
1479extern device_object *IoGetAttachedDevice(device_object *);
1480extern uint32_t IofCallDriver(device_object *, irp *);
1481extern void IofCompleteRequest(irp *, uint8_t);
1482extern void IoAcquireCancelSpinLock(uint8_t *);
1483extern void IoReleaseCancelSpinLock(uint8_t);
1484extern uint8_t IoCancelIrp(irp *);
1485extern void IoDetachDevice(device_object *);
1486extern device_object *IoAttachDeviceToDeviceStack(device_object *,
1487 device_object *);
1488extern mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *);
1489extern void IoFreeMdl(mdl *);
1490extern io_workitem *IoAllocateWorkItem(device_object *);
1491extern void ExQueueWorkItem(work_queue_item *, u_int32_t);
1492extern void IoFreeWorkItem(io_workitem *);
1493extern void IoQueueWorkItem(io_workitem *, io_workitem_func,
1494 uint32_t, void *);
1495
1496#define IoCallDriver(a, b) IofCallDriver(a, b)
1497#define IoCompleteRequest(a, b) IofCompleteRequest(a, b)
1498
1499/*
1500 * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock()
1501 * routines live in the HAL. We try to imitate this behavior.
1502 */
1503#ifdef __i386__
1504#define KI_USER_SHARED_DATA 0xffdf0000
1505#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a)
1506#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b)
1507#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a)
1508#define KeLowerIrql(a) KfLowerIrql(a)
1509#define KeAcquireSpinLockAtDpcLevel(a) KefAcquireSpinLockAtDpcLevel(a)
1510#define KeReleaseSpinLockFromDpcLevel(a) KefReleaseSpinLockFromDpcLevel(a)
1511#endif /* __i386__ */
1512
1513#ifdef __amd64__
1514#define KI_USER_SHARED_DATA 0xfffff78000000000UL
1515#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a)
1516#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b)
1517
1518/*
1519 * These may need to be redefined later;
1520 * not sure where they live on amd64 yet.
1521 */
1522#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a)
1523#define KeLowerIrql(a) KfLowerIrql(a)
1524#endif /* __amd64__ */
1525
1526__END_DECLS
1527
1528#endif /* _NTOSKRNL_VAR_H_ */
1470extern void *MmMapIoSpace(uint64_t, uint32_t, uint32_t);
1471extern void MmUnmapIoSpace(void *, size_t);
1472extern void MmBuildMdlForNonPagedPool(mdl *);
1473extern void IoDisconnectInterrupt(kinterrupt *);
1474extern uint32_t IoAllocateDriverObjectExtension(driver_object *,
1475 void *, uint32_t, void **);
1476extern void *IoGetDriverObjectExtension(driver_object *, void *);
1477extern uint32_t IoCreateDevice(driver_object *, uint32_t,
1478 unicode_string *, uint32_t, uint32_t, uint8_t, device_object **);
1479extern void IoDeleteDevice(device_object *);
1480extern device_object *IoGetAttachedDevice(device_object *);
1481extern uint32_t IofCallDriver(device_object *, irp *);
1482extern void IofCompleteRequest(irp *, uint8_t);
1483extern void IoAcquireCancelSpinLock(uint8_t *);
1484extern void IoReleaseCancelSpinLock(uint8_t);
1485extern uint8_t IoCancelIrp(irp *);
1486extern void IoDetachDevice(device_object *);
1487extern device_object *IoAttachDeviceToDeviceStack(device_object *,
1488 device_object *);
1489extern mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *);
1490extern void IoFreeMdl(mdl *);
1491extern io_workitem *IoAllocateWorkItem(device_object *);
1492extern void ExQueueWorkItem(work_queue_item *, u_int32_t);
1493extern void IoFreeWorkItem(io_workitem *);
1494extern void IoQueueWorkItem(io_workitem *, io_workitem_func,
1495 uint32_t, void *);
1496
1497#define IoCallDriver(a, b) IofCallDriver(a, b)
1498#define IoCompleteRequest(a, b) IofCompleteRequest(a, b)
1499
1500/*
1501 * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock()
1502 * routines live in the HAL. We try to imitate this behavior.
1503 */
1504#ifdef __i386__
1505#define KI_USER_SHARED_DATA 0xffdf0000
1506#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a)
1507#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b)
1508#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a)
1509#define KeLowerIrql(a) KfLowerIrql(a)
1510#define KeAcquireSpinLockAtDpcLevel(a) KefAcquireSpinLockAtDpcLevel(a)
1511#define KeReleaseSpinLockFromDpcLevel(a) KefReleaseSpinLockFromDpcLevel(a)
1512#endif /* __i386__ */
1513
1514#ifdef __amd64__
1515#define KI_USER_SHARED_DATA 0xfffff78000000000UL
1516#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a)
1517#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b)
1518
1519/*
1520 * These may need to be redefined later;
1521 * not sure where they live on amd64 yet.
1522 */
1523#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a)
1524#define KeLowerIrql(a) KfLowerIrql(a)
1525#endif /* __amd64__ */
1526
1527__END_DECLS
1528
1529#endif /* _NTOSKRNL_VAR_H_ */