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