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