xref: /NextBSD/sys/compat/ndis/ntoskrnl_var.h (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
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$
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  */
45 struct unicode_string {
46 	uint16_t		us_len;
47 	uint16_t		us_maxlen;
48 	uint16_t		*us_buf;
49 };
50 
51 typedef struct unicode_string unicode_string;
52 
53 struct ansi_string {
54 	uint16_t		as_len;
55 	uint16_t		as_maxlen;
56 	char			*as_buf;
57 };
58 
59 typedef 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 
84 struct 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 
95 typedef 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 
165 enum 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 
196 typedef register_t kspin_lock;
197 
198 struct slist_entry {
199 	struct slist_entry	*sl_next;
200 };
201 
202 typedef struct slist_entry slist_entry;
203 
204 union 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 
213 typedef union slist_header slist_header;
214 
215 struct list_entry {
216 	struct list_entry *nle_flink;
217 	struct list_entry *nle_blink;
218 };
219 
220 typedef 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 
241 static __inline__ list_entry *
RemoveHeadList(list_entry * l)242 RemoveHeadList(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 
255 static __inline__ list_entry *
RemoveTailList(list_entry * l)256 RemoveTailList(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 
294 struct 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 
303 typedef 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 
351 struct nt_objref {
352 	nt_dispatch_header	no_dh;
353 	void			*no_obj;
354 	TAILQ_ENTRY(nt_objref)	link;
355 };
356 
357 TAILQ_HEAD(nt_objref_head, nt_objref);
358 
359 typedef 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 
377 struct 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 
391 typedef struct ktimer ktimer;
392 
393 struct nt_kevent {
394 	nt_dispatch_header	k_header;
395 };
396 
397 typedef struct nt_kevent nt_kevent;
398 
399 /* Kernel defered procedure call (i.e. timer callback) */
400 
401 struct kdpc;
402 typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
403 
404 struct 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 
422 typedef 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  */
435 struct 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 
443 typedef struct kmutant kmutant;
444 
445 #define	LOOKASIDE_DEPTH 256
446 
447 struct 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 
475 typedef struct general_lookaside general_lookaside;
476 
477 struct npaged_lookaside_list {
478 	general_lookaside	nll_l;
479 #ifdef __i386__
480 	kspin_lock		nll_obsoletelock;
481 #endif
482 };
483 
484 typedef struct npaged_lookaside_list npaged_lookaside_list;
485 typedef struct npaged_lookaside_list paged_lookaside_list;
486 
487 typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
488 typedef void (*lookaside_free_func)(void *);
489 
490 struct irp;
491 
492 struct kdevice_qentry {
493 	list_entry		kqe_devlistent;
494 	uint32_t		kqe_sortkey;
495 	uint8_t			kqe_inserted;
496 };
497 
498 typedef struct kdevice_qentry kdevice_qentry;
499 
500 struct 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 
508 typedef struct kdevice_queue kdevice_queue;
509 
510 struct 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 
520 typedef struct wait_ctx_block wait_ctx_block;
521 
522 struct 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 
537 typedef 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 
554 struct thread_context {
555 	void			*tc_thrctx;
556 	void			*tc_thrfunc;
557 };
558 
559 typedef struct thread_context thread_context;
560 
561 /* Forward declaration */
562 struct driver_object;
563 struct devobj_extension;
564 
565 struct 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 
580 typedef struct driver_extension driver_extension;
581 
582 struct custom_extension {
583 	list_entry		ce_list;
584 	void			*ce_clid;
585 };
586 
587 typedef 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 
594 struct 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 
606 typedef struct kinterrupt kinterrupt;
607 
608 struct ksystem_time {
609 	uint32_t	low_part;
610 	int32_t		high1_time;
611 	int32_t		high2_time;
612 };
613 
614 enum nt_product_type {
615 	NT_PRODUCT_WIN_NT = 1,
616 	NT_PRODUCT_LAN_MAN_NT,
617 	NT_PRODUCT_SERVER
618 };
619 
620 enum alt_arch_type {
621 	STANDARD_DESIGN,
622 	NEC98x86,
623 	END_ALTERNATIVES
624 };
625 
626 struct 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 
683 struct 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 
714 typedef struct device_object device_object;
715 
716 struct devobj_extension {
717 	uint16_t		dve_type;
718 	uint16_t		dve_size;
719 	device_object		*dve_devobj;
720 };
721 
722 typedef 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 
921 struct 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 
931 typedef struct io_status_block io_status_block;
932 
933 struct 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 
950 typedef struct kapc kapc;
951 
952 typedef uint32_t (*completion_func)(device_object *,
953 	struct irp *, void *);
954 typedef uint32_t (*cancel_func)(device_object *,
955 	struct irp *);
956 
957 struct 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 
1004 typedef 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 
1013 struct 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 
1083 typedef 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 
1149 typedef 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 
1161 struct 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 
1179 typedef 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  */
1318 typedef void (*io_workitem_func)(device_object *, void *);
1319 
1320 struct 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 
1328 typedef 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 
1342 struct work_queue_item;
1343 
1344 typedef void (*work_item_func)(struct work_queue_item *, void *);
1345 
1346 struct work_queue_item {
1347 	list_entry		wqi_entry;
1348 	work_item_func		wqi_func;
1349 	void			*wqi_ctx;
1350 };
1351 
1352 typedef 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 
1378 struct 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 
1386 extern image_patch_table ntoskrnl_functbl[];
1387 #ifdef __amd64__
1388 extern struct kuser_shared_data kuser_shared_data;
1389 #endif
1390 typedef void (*funcptr)(void);
1391 typedef int (*matchfuncptr)(interface_type, void *, void *);
1392 
1393 __BEGIN_DECLS
1394 extern int windrv_libinit(void);
1395 extern int windrv_libfini(void);
1396 extern driver_object *windrv_lookup(vm_offset_t, char *);
1397 extern struct drvdb_ent *windrv_match(matchfuncptr, void *);
1398 extern int windrv_load(module_t, vm_offset_t, int, interface_type,
1399 	void *, ndis_cfg *);
1400 extern int windrv_unload(module_t, vm_offset_t, int);
1401 extern int windrv_create_pdo(driver_object *, device_t);
1402 extern void windrv_destroy_pdo(driver_object *, device_t);
1403 extern device_object *windrv_find_pdo(driver_object *, device_t);
1404 extern int windrv_bus_attach(driver_object *, char *);
1405 extern int windrv_wrap(funcptr, funcptr *, int, int);
1406 extern int windrv_unwrap(funcptr);
1407 extern void ctxsw_utow(void);
1408 extern void ctxsw_wtou(void);
1409 
1410 extern int ntoskrnl_libinit(void);
1411 extern int ntoskrnl_libfini(void);
1412 
1413 extern void ntoskrnl_intr(void *);
1414 extern void ntoskrnl_time(uint64_t *);
1415 
1416 extern uint16_t ExQueryDepthSList(slist_header *);
1417 extern slist_entry
1418 	*InterlockedPushEntrySList(slist_header *, slist_entry *);
1419 extern slist_entry *InterlockedPopEntrySList(slist_header *);
1420 extern uint32_t RtlUnicodeStringToAnsiString(ansi_string *,
1421 	unicode_string *, uint8_t);
1422 extern uint32_t RtlAnsiStringToUnicodeString(unicode_string *,
1423 	ansi_string *, uint8_t);
1424 extern void RtlInitAnsiString(ansi_string *, char *);
1425 extern void RtlInitUnicodeString(unicode_string *,
1426 	uint16_t *);
1427 extern void RtlFreeUnicodeString(unicode_string *);
1428 extern void RtlFreeAnsiString(ansi_string *);
1429 extern void KeInitializeDpc(kdpc *, void *, void *);
1430 extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *);
1431 extern uint8_t KeRemoveQueueDpc(kdpc *);
1432 extern void KeSetImportanceDpc(kdpc *, uint32_t);
1433 extern void KeSetTargetProcessorDpc(kdpc *, uint8_t);
1434 extern void KeFlushQueuedDpcs(void);
1435 extern uint32_t KeGetCurrentProcessorNumber(void);
1436 extern void KeInitializeTimer(ktimer *);
1437 extern void KeInitializeTimerEx(ktimer *, uint32_t);
1438 extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *);
1439 extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *);
1440 extern uint8_t KeCancelTimer(ktimer *);
1441 extern uint8_t KeReadStateTimer(ktimer *);
1442 extern uint32_t KeWaitForSingleObject(void *, uint32_t,
1443 	uint32_t, uint8_t, int64_t *);
1444 extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t);
1445 extern void KeClearEvent(nt_kevent *);
1446 extern uint32_t KeReadStateEvent(nt_kevent *);
1447 extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t);
1448 extern uint32_t KeResetEvent(nt_kevent *);
1449 #ifdef __i386__
1450 extern void KefAcquireSpinLockAtDpcLevel(kspin_lock *);
1451 extern void KefReleaseSpinLockFromDpcLevel(kspin_lock *);
1452 extern uint8_t KeAcquireSpinLockRaiseToDpc(kspin_lock *);
1453 #else
1454 extern void KeAcquireSpinLockAtDpcLevel(kspin_lock *);
1455 extern void KeReleaseSpinLockFromDpcLevel(kspin_lock *);
1456 #endif
1457 extern void KeInitializeSpinLock(kspin_lock *);
1458 extern uint8_t KeAcquireInterruptSpinLock(kinterrupt *);
1459 extern void KeReleaseInterruptSpinLock(kinterrupt *, uint8_t);
1460 extern uint8_t KeSynchronizeExecution(kinterrupt *, void *, void *);
1461 extern uintptr_t InterlockedExchange(volatile uint32_t *,
1462 	uintptr_t);
1463 extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t);
1464 extern void ExFreePool(void *);
1465 extern uint32_t IoConnectInterrupt(kinterrupt **, void *, void *,
1466 	kspin_lock *, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
1467 	uint32_t, uint8_t);
1468 extern uint8_t MmIsAddressValid(void *);
1469 extern void *MmGetSystemRoutineAddress(unicode_string *);
1470 extern void *MmMapIoSpace(uint64_t, uint32_t, uint32_t);
1471 extern void MmUnmapIoSpace(void *, size_t);
1472 extern void MmBuildMdlForNonPagedPool(mdl *);
1473 extern void IoDisconnectInterrupt(kinterrupt *);
1474 extern uint32_t IoAllocateDriverObjectExtension(driver_object *,
1475 	void *, uint32_t, void **);
1476 extern void *IoGetDriverObjectExtension(driver_object *, void *);
1477 extern uint32_t IoCreateDevice(driver_object *, uint32_t,
1478 	unicode_string *, uint32_t, uint32_t, uint8_t, device_object **);
1479 extern void IoDeleteDevice(device_object *);
1480 extern device_object *IoGetAttachedDevice(device_object *);
1481 extern uint32_t IofCallDriver(device_object *, irp *);
1482 extern void IofCompleteRequest(irp *, uint8_t);
1483 extern void IoAcquireCancelSpinLock(uint8_t *);
1484 extern void IoReleaseCancelSpinLock(uint8_t);
1485 extern uint8_t IoCancelIrp(irp *);
1486 extern void IoDetachDevice(device_object *);
1487 extern device_object *IoAttachDeviceToDeviceStack(device_object *,
1488 	device_object *);
1489 extern mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *);
1490 extern void IoFreeMdl(mdl *);
1491 extern io_workitem *IoAllocateWorkItem(device_object *);
1492 extern void ExQueueWorkItem(work_queue_item *, u_int32_t);
1493 extern void IoFreeWorkItem(io_workitem *);
1494 extern 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_ */
1530