1139743Simp/*-
2123474Swpaul * Copyright (c) 2003
3123474Swpaul *	Bill Paul <wpaul@windriver.com>.  All rights reserved.
4123474Swpaul *
5123474Swpaul * Redistribution and use in source and binary forms, with or without
6123474Swpaul * modification, are permitted provided that the following conditions
7123474Swpaul * are met:
8123474Swpaul * 1. Redistributions of source code must retain the above copyright
9123474Swpaul *    notice, this list of conditions and the following disclaimer.
10123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright
11123474Swpaul *    notice, this list of conditions and the following disclaimer in the
12123474Swpaul *    documentation and/or other materials provided with the distribution.
13123474Swpaul * 3. All advertising materials mentioning features or use of this software
14123474Swpaul *    must display the following acknowledgement:
15123474Swpaul *	This product includes software developed by Bill Paul.
16123474Swpaul * 4. Neither the name of the author nor the names of any co-contributors
17123474Swpaul *    may be used to endorse or promote products derived from this software
18123474Swpaul *    without specific prior written permission.
19123474Swpaul *
20123474Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
21123474Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22123474Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23123474Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
24123474Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25123474Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26123474Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27123474Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28123474Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29123474Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30123474Swpaul * THE POSSIBILITY OF SUCH DAMAGE.
31123474Swpaul *
32123474Swpaul * $FreeBSD$
33123474Swpaul */
34123474Swpaul
35123474Swpaul#ifndef _NTOSKRNL_VAR_H_
36189488Sweongyo#define	_NTOSKRNL_VAR_H_
37123474Swpaul
38189488Sweongyo#define	MTX_NTOSKRNL_SPIN_LOCK "NDIS thread lock"
39151451Swpaul
40140751Swpaul/*
41140751Swpaul * us_buf is really a wchar_t *, but it's inconvenient to include
42140751Swpaul * all the necessary header goop needed to define it, and it's a
43140751Swpaul * pointer anyway, so for now, just make it a uint16_t *.
44140751Swpaul */
45140751Swpaulstruct unicode_string {
46140751Swpaul	uint16_t		us_len;
47140751Swpaul	uint16_t		us_maxlen;
48140751Swpaul	uint16_t		*us_buf;
49140751Swpaul};
50140751Swpaul
51140751Swpaultypedef struct unicode_string unicode_string;
52140751Swpaul
53151207Swpaulstruct ansi_string {
54151207Swpaul	uint16_t		as_len;
55151207Swpaul	uint16_t		as_maxlen;
56151207Swpaul	char			*as_buf;
57151207Swpaul};
58151207Swpaul
59151207Swpaultypedef struct ansi_string ansi_string;
60151207Swpaul
61140751Swpaul/*
62140751Swpaul * Windows memory descriptor list. In Windows, it's possible for
63140751Swpaul * buffers to be passed between user and kernel contexts without
64140751Swpaul * copying. Buffers may also be allocated in either paged or
65140751Swpaul * non-paged memory regions. An MDL describes the pages of memory
66140751Swpaul * used to contain a particular buffer. Note that a single MDL
67140751Swpaul * may describe a buffer that spans multiple pages. An array of
68140751Swpaul * page addresses appears immediately after the MDL structure itself.
69140751Swpaul * MDLs are therefore implicitly variably sized, even though they
70140751Swpaul * don't look it.
71140751Swpaul *
72140751Swpaul * Note that in FreeBSD, we can take many shortcuts in the way
73140751Swpaul * we handle MDLs because:
74140751Swpaul *
75140751Swpaul * - We are only concerned with pages in kernel context. This means
76140751Swpaul *   we will only ever use the kernel's memory map, and remapping
77140751Swpaul *   of buffers is never needed.
78140751Swpaul *
79140751Swpaul * - Kernel pages can never be paged out, so we don't have to worry
80140751Swpaul *   about whether or not a page is actually mapped before going to
81140751Swpaul *   touch it.
82140751Swpaul */
83140751Swpaul
84140751Swpaulstruct mdl {
85189488Sweongyo	struct mdl		*mdl_next;
86140751Swpaul	uint16_t		mdl_size;
87140751Swpaul	uint16_t		mdl_flags;
88140751Swpaul	void			*mdl_process;
89140751Swpaul	void			*mdl_mappedsystemva;
90140751Swpaul	void			*mdl_startva;
91140751Swpaul	uint32_t		mdl_bytecount;
92140751Swpaul	uint32_t		mdl_byteoffset;
93140751Swpaul};
94140751Swpaul
95140751Swpaultypedef struct mdl mdl, ndis_buffer;
96140751Swpaul
97140751Swpaul/* MDL flags */
98140751Swpaul
99189488Sweongyo#define	MDL_MAPPED_TO_SYSTEM_VA		0x0001
100189488Sweongyo#define	MDL_PAGES_LOCKED		0x0002
101189488Sweongyo#define	MDL_SOURCE_IS_NONPAGED_POOL	0x0004
102189488Sweongyo#define	MDL_ALLOCATED_FIXED_SIZE	0x0008
103189488Sweongyo#define	MDL_PARTIAL			0x0010
104189488Sweongyo#define	MDL_PARTIAL_HAS_BEEN_MAPPED	0x0020
105189488Sweongyo#define	MDL_IO_PAGE_READ		0x0040
106189488Sweongyo#define	MDL_WRITE_OPERATION		0x0080
107189488Sweongyo#define	MDL_PARENT_MAPPED_SYSTEM_VA	0x0100
108189488Sweongyo#define	MDL_FREE_EXTRA_PTES		0x0200
109189488Sweongyo#define	MDL_IO_SPACE			0x0800
110189488Sweongyo#define	MDL_NETWORK_HEADER		0x1000
111189488Sweongyo#define	MDL_MAPPING_CAN_FAIL		0x2000
112189488Sweongyo#define	MDL_ALLOCATED_MUST_SUCCEED	0x4000
113189488Sweongyo#define	MDL_ZONE_ALLOCED		0x8000	/* BSD private */
114140751Swpaul
115189488Sweongyo#define	MDL_ZONE_PAGES 16
116189488Sweongyo#define	MDL_ZONE_SIZE (sizeof(mdl) + (sizeof(vm_offset_t) * MDL_ZONE_PAGES))
117142530Swpaul
118123512Swpaul/* Note: assumes x86 page size of 4K. */
119140751Swpaul
120183003Sthompsa#ifndef PAGE_SHIFT
121140751Swpaul#if PAGE_SIZE == 4096
122189488Sweongyo#define	PAGE_SHIFT	12
123140751Swpaul#elif PAGE_SIZE == 8192
124189488Sweongyo#define	PAGE_SHIFT	13
125140751Swpaul#else
126140751Swpaul#error PAGE_SHIFT undefined!
127140751Swpaul#endif
128183003Sthompsa#endif
129140751Swpaul
130189488Sweongyo#define	SPAN_PAGES(ptr, len)					\
131140751Swpaul	((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE - 1)) +	\
132123512Swpaul	(len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
133140751Swpaul
134189488Sweongyo#define	PAGE_ALIGN(ptr)						\
135123757Swpaul	((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
136140751Swpaul
137189488Sweongyo#define	BYTE_OFFSET(ptr)					\
138123757Swpaul	((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
139140751Swpaul
140189488Sweongyo#define	MDL_PAGES(m)	(vm_offset_t *)(m + 1)
141140751Swpaul
142189488Sweongyo#define	MmInitializeMdl(b, baseva, len)					\
143140751Swpaul	(b)->mdl_next = NULL;						\
144140751Swpaul	(b)->mdl_size = (uint16_t)(sizeof(mdl) +			\
145144175Swpaul		(sizeof(vm_offset_t) * SPAN_PAGES((baseva), (len))));	\
146140751Swpaul	(b)->mdl_flags = 0;						\
147140751Swpaul	(b)->mdl_startva = (void *)PAGE_ALIGN((baseva));		\
148140751Swpaul	(b)->mdl_byteoffset = BYTE_OFFSET((baseva));			\
149140751Swpaul	(b)->mdl_bytecount = (uint32_t)(len);
150123512Swpaul
151189488Sweongyo#define	MmGetMdlByteOffset(mdl)		((mdl)->mdl_byteoffset)
152189488Sweongyo#define	MmGetMdlByteCount(mdl)		((mdl)->mdl_bytecount)
153189488Sweongyo#define	MmGetMdlVirtualAddress(mdl)					\
154140751Swpaul	((void *)((char *)((mdl)->mdl_startva) + (mdl)->mdl_byteoffset))
155189488Sweongyo#define	MmGetMdlStartVa(mdl)		((mdl)->mdl_startva)
156189488Sweongyo#define	MmGetMdlPfnArray(mdl)		MDL_PAGES(mdl)
157140751Swpaul
158189488Sweongyo#define	WDM_MAJOR		1
159189488Sweongyo#define	WDM_MINOR_WIN98		0x00
160189488Sweongyo#define	WDM_MINOR_WINME		0x05
161189488Sweongyo#define	WDM_MINOR_WIN2000	0x10
162189488Sweongyo#define	WDM_MINOR_WINXP		0x20
163189488Sweongyo#define	WDM_MINOR_WIN2003	0x30
164124729Swpaul
165215419Sbschmidtenum nt_caching_type {
166215419Sbschmidt	MmNonCached			= 0,
167215419Sbschmidt	MmCached			= 1,
168215419Sbschmidt	MmWriteCombined			= 2,
169215419Sbschmidt	MmHardwareCoherentCached	= 3,
170215419Sbschmidt	MmNonCachedUnordered		= 4,
171215419Sbschmidt	MmUSWCCached			= 5,
172215419Sbschmidt	MmMaximumCacheType		= 6
173215419Sbschmidt};
174215419Sbschmidt
175124582Sobrien/*-
176124582Sobrien * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
177124582Sobrien * According to the Windows DDK header files, KSPIN_LOCK is defined like this:
178124582Sobrien *	typedef ULONG_PTR KSPIN_LOCK;
179124582Sobrien *
180124582Sobrien * From basetsd.h (SDK, Feb. 2003):
181189488Sweongyo *	typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
182189488Sweongyo *	typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
183189488Sweongyo *	typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
184189488Sweongyo *
185124582Sobrien * The keyword __int3264 specifies an integral type that has the following
186124582Sobrien * properties:
187124582Sobrien *	+ It is 32-bit on 32-bit platforms
188124582Sobrien *	+ It is 64-bit on 64-bit platforms
189124582Sobrien *	+ It is 32-bit on the wire for backward compatibility.
190124582Sobrien *	  It gets truncated on the sending side and extended appropriately
191124582Sobrien *	  (signed or unsigned) on the receiving side.
192124582Sobrien *
193124582Sobrien * Thus register_t seems the proper mapping onto FreeBSD for spin locks.
194124582Sobrien */
195123474Swpaul
196124582Sobrientypedef register_t kspin_lock;
197124582Sobrien
198123474Swpaulstruct slist_entry {
199123474Swpaul	struct slist_entry	*sl_next;
200123474Swpaul};
201123474Swpaul
202123474Swpaultypedef struct slist_entry slist_entry;
203123474Swpaul
204123474Swpaulunion slist_header {
205123474Swpaul	uint64_t		slh_align;
206123474Swpaul	struct {
207123474Swpaul		struct slist_entry	*slh_next;
208123474Swpaul		uint16_t		slh_depth;
209123474Swpaul		uint16_t		slh_seq;
210123474Swpaul	} slh_list;
211123474Swpaul};
212123474Swpaul
213123474Swpaultypedef union slist_header slist_header;
214123474Swpaul
215123507Swpaulstruct list_entry {
216189488Sweongyo	struct list_entry *nle_flink;
217189488Sweongyo	struct list_entry *nle_blink;
218123507Swpaul};
219123507Swpaul
220123507Swpaultypedef struct list_entry list_entry;
221123507Swpaul
222189488Sweongyo#define	InitializeListHead(l)			\
223141524Swpaul	(l)->nle_flink = (l)->nle_blink = (l)
224125551Swpaul
225189488Sweongyo#define	IsListEmpty(h)				\
226151207Swpaul	((h)->nle_flink == (h))
227151207Swpaul
228189488Sweongyo#define	RemoveEntryList(e)			\
229125551Swpaul	do {					\
230125551Swpaul		list_entry		*b;	\
231125551Swpaul		list_entry		*f;	\
232125551Swpaul						\
233151207Swpaul		f = (e)->nle_flink;		\
234151207Swpaul		b = (e)->nle_blink;		\
235125551Swpaul		b->nle_flink = f;		\
236125551Swpaul		f->nle_blink = b;		\
237125551Swpaul	} while (0)
238125551Swpaul
239151207Swpaul/* These two have to be inlined since they return things. */
240125551Swpaul
241151207Swpaulstatic __inline__ list_entry *
242151207SwpaulRemoveHeadList(list_entry *l)
243151207Swpaul{
244151207Swpaul	list_entry		*f;
245151207Swpaul	list_entry		*e;
246125551Swpaul
247151207Swpaul	e = l->nle_flink;
248151207Swpaul	f = e->nle_flink;
249151207Swpaul	l->nle_flink = f;
250151207Swpaul	f->nle_blink = l;
251151207Swpaul
252151207Swpaul	return (e);
253151207Swpaul}
254151207Swpaul
255151207Swpaulstatic __inline__ list_entry *
256151207SwpaulRemoveTailList(list_entry *l)
257151207Swpaul{
258151207Swpaul	list_entry		*b;
259151207Swpaul	list_entry		*e;
260151207Swpaul
261151207Swpaul	e = l->nle_blink;
262151207Swpaul	b = e->nle_blink;
263151207Swpaul	l->nle_blink = b;
264151207Swpaul	b->nle_flink = l;
265151207Swpaul
266151207Swpaul	return (e);
267151207Swpaul}
268151207Swpaul
269189488Sweongyo#define	InsertTailList(l, e)			\
270125551Swpaul	do {					\
271125551Swpaul		list_entry		*b;	\
272125551Swpaul						\
273125551Swpaul		b = l->nle_blink;		\
274125860Swpaul		e->nle_flink = l;		\
275125551Swpaul		e->nle_blink = b;		\
276141524Swpaul		b->nle_flink = (e);		\
277141524Swpaul		l->nle_blink = (e);		\
278125551Swpaul	} while (0)
279125551Swpaul
280189488Sweongyo#define	InsertHeadList(l, e)			\
281125551Swpaul	do {					\
282125551Swpaul		list_entry		*f;	\
283125551Swpaul						\
284125551Swpaul		f = l->nle_flink;		\
285125551Swpaul		e->nle_flink = f;		\
286125551Swpaul		e->nle_blink = l;		\
287125551Swpaul		f->nle_blink = e;		\
288125551Swpaul		l->nle_flink = e;		\
289125551Swpaul	} while (0)
290125551Swpaul
291189488Sweongyo#define	CONTAINING_RECORD(addr, type, field)	\
292145895Swpaul	((type *)((vm_offset_t)(addr) - (vm_offset_t)(&((type *)0)->field)))
293145895Swpaul
294125551Swpaulstruct nt_dispatch_header {
295125551Swpaul	uint8_t			dh_type;
296125551Swpaul	uint8_t			dh_abs;
297125551Swpaul	uint8_t			dh_size;
298125551Swpaul	uint8_t			dh_inserted;
299151207Swpaul	int32_t			dh_sigstate;
300125551Swpaul	list_entry		dh_waitlisthead;
301125551Swpaul};
302125551Swpaul
303125551Swpaultypedef struct nt_dispatch_header nt_dispatch_header;
304125551Swpaul
305151207Swpaul/* Dispatcher object types */
306151207Swpaul
307189488Sweongyo#define	DISP_TYPE_NOTIFICATION_EVENT	0	/* KEVENT */
308189488Sweongyo#define	DISP_TYPE_SYNCHRONIZATION_EVENT	1	/* KEVENT */
309189488Sweongyo#define	DISP_TYPE_MUTANT		2	/* KMUTANT/KMUTEX */
310189488Sweongyo#define	DISP_TYPE_PROCESS		3	/* KPROCESS */
311189488Sweongyo#define	DISP_TYPE_QUEUE			4	/* KQUEUE */
312189488Sweongyo#define	DISP_TYPE_SEMAPHORE		5	/* KSEMAPHORE */
313189488Sweongyo#define	DISP_TYPE_THREAD		6	/* KTHREAD */
314189488Sweongyo#define	DISP_TYPE_NOTIFICATION_TIMER	8	/* KTIMER */
315189488Sweongyo#define	DISP_TYPE_SYNCHRONIZATION_TIMER	9	/* KTIMER */
316151207Swpaul
317189488Sweongyo#define	OTYPE_EVENT		0
318189488Sweongyo#define	OTYPE_MUTEX		1
319189488Sweongyo#define	OTYPE_THREAD		2
320189488Sweongyo#define	OTYPE_TIMER		3
321125551Swpaul
322125551Swpaul/* Windows dispatcher levels. */
323125551Swpaul
324189488Sweongyo#define	PASSIVE_LEVEL		0
325189488Sweongyo#define	LOW_LEVEL		0
326189488Sweongyo#define	APC_LEVEL		1
327189488Sweongyo#define	DISPATCH_LEVEL		2
328189488Sweongyo#define	DEVICE_LEVEL		(DISPATCH_LEVEL + 1)
329189488Sweongyo#define	PROFILE_LEVEL		27
330189488Sweongyo#define	CLOCK1_LEVEL		28
331189488Sweongyo#define	CLOCK2_LEVEL		28
332189488Sweongyo#define	IPI_LEVEL		29
333189488Sweongyo#define	POWER_LEVEL		30
334189488Sweongyo#define	HIGH_LEVEL		31
335125551Swpaul
336189488Sweongyo#define	SYNC_LEVEL_UP		DISPATCH_LEVEL
337189488Sweongyo#define	SYNC_LEVEL_MP		(IPI_LEVEL - 1)
338125551Swpaul
339189488Sweongyo#define	AT_PASSIVE_LEVEL(td)		\
340128229Swpaul	((td)->td_proc->p_flag & P_KTHREAD == FALSE)
341128229Swpaul
342189488Sweongyo#define	AT_DISPATCH_LEVEL(td)		\
343128449Swpaul	((td)->td_base_pri == PI_REALTIME)
344128229Swpaul
345189488Sweongyo#define	AT_DIRQL_LEVEL(td)		\
346128295Swpaul	((td)->td_priority <= PI_NET)
347128229Swpaul
348189488Sweongyo#define	AT_HIGH_LEVEL(td)		\
349128229Swpaul	((td)->td_critnest != 0)
350128229Swpaul
351125551Swpaulstruct nt_objref {
352125551Swpaul	nt_dispatch_header	no_dh;
353125551Swpaul	void			*no_obj;
354125551Swpaul	TAILQ_ENTRY(nt_objref)	link;
355125551Swpaul};
356125551Swpaul
357125551SwpaulTAILQ_HEAD(nt_objref_head, nt_objref);
358125551Swpaul
359125551Swpaultypedef struct nt_objref nt_objref;
360125551Swpaul
361189488Sweongyo#define	EVENT_TYPE_NOTIFY	0
362189488Sweongyo#define	EVENT_TYPE_SYNC		1
363125551Swpaul
364126620Swpaul/*
365126620Swpaul * We need to use the timeout()/untimeout() API for ktimers
366126620Swpaul * since timers can be initialized, but not destroyed (so
367126620Swpaul * malloc()ing our own callout structures would mean a leak,
368126620Swpaul * since there'd be no way to free() them). This means we
369126620Swpaul * need to use struct callout_handle, which is really just a
370126620Swpaul * pointer. To make it easier to deal with, we use a union
371126620Swpaul * to overlay the callout_handle over the k_timerlistentry.
372126620Swpaul * The latter is a list_entry, which is two pointers, so
373126620Swpaul * there's enough space available to hide a callout_handle
374126620Swpaul * there.
375126620Swpaul */
376126620Swpaul
377125551Swpaulstruct ktimer {
378125551Swpaul	nt_dispatch_header	k_header;
379125551Swpaul	uint64_t		k_duetime;
380126620Swpaul	union {
381126620Swpaul		list_entry		k_timerlistentry;
382151207Swpaul		struct callout		*k_callout;
383126620Swpaul	} u;
384125551Swpaul	void			*k_dpc;
385125551Swpaul	uint32_t		k_period;
386125551Swpaul};
387125551Swpaul
388189488Sweongyo#define	k_timerlistentry	u.k_timerlistentry
389189488Sweongyo#define	k_callout		u.k_callout
390126620Swpaul
391126620Swpaultypedef struct ktimer ktimer;
392126620Swpaul
393125551Swpaulstruct nt_kevent {
394125551Swpaul	nt_dispatch_header	k_header;
395125551Swpaul};
396125551Swpaul
397125551Swpaultypedef struct nt_kevent nt_kevent;
398125551Swpaul
399125551Swpaul/* Kernel defered procedure call (i.e. timer callback) */
400125551Swpaul
401125551Swpaulstruct kdpc;
402144888Swpaultypedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
403125551Swpaul
404125551Swpaulstruct kdpc {
405125551Swpaul	uint16_t		k_type;
406145895Swpaul	uint8_t			k_num;		/* CPU number */
407145895Swpaul	uint8_t			k_importance;	/* priority */
408125551Swpaul	list_entry		k_dpclistentry;
409140827Swpaul	void			*k_deferedfunc;
410125551Swpaul	void			*k_deferredctx;
411125551Swpaul	void			*k_sysarg1;
412125551Swpaul	void			*k_sysarg2;
413145895Swpaul	void			*k_lock;
414125551Swpaul};
415125551Swpaul
416189488Sweongyo#define	KDPC_IMPORTANCE_LOW	0
417189488Sweongyo#define	KDPC_IMPORTANCE_MEDIUM	1
418189488Sweongyo#define	KDPC_IMPORTANCE_HIGH	2
419145895Swpaul
420189488Sweongyo#define	KDPC_CPU_DEFAULT	255
421145895Swpaul
422126620Swpaultypedef struct kdpc kdpc;
423126620Swpaul
424125551Swpaul/*
425125551Swpaul * Note: the acquisition count is BSD-specific. The Microsoft
426125551Swpaul * documentation says that mutexes can be acquired recursively
427125551Swpaul * by a given thread, but that you must release the mutex as
428125551Swpaul * many times as you acquired it before it will be set to the
429125551Swpaul * signalled state (i.e. before any other threads waiting on
430125551Swpaul * the object will be woken up). However the Windows KMUTANT
431125551Swpaul * structure has no field for keeping track of the number of
432125551Swpaul * acquisitions, so we need to add one ourselves. As long as
433125551Swpaul * driver code treats the mutex as opaque, we should be ok.
434125551Swpaul */
435125551Swpaulstruct kmutant {
436125551Swpaul	nt_dispatch_header	km_header;
437151207Swpaul	list_entry		km_listentry;
438125551Swpaul	void			*km_ownerthread;
439125551Swpaul	uint8_t			km_abandoned;
440125551Swpaul	uint8_t			km_apcdisable;
441125551Swpaul};
442125551Swpaul
443125551Swpaultypedef struct kmutant kmutant;
444125551Swpaul
445189488Sweongyo#define	LOOKASIDE_DEPTH 256
446125860Swpaul
447123474Swpaulstruct general_lookaside {
448123474Swpaul	slist_header		gl_listhead;
449123474Swpaul	uint16_t		gl_depth;
450123474Swpaul	uint16_t		gl_maxdepth;
451123474Swpaul	uint32_t		gl_totallocs;
452123474Swpaul	union {
453123474Swpaul		uint32_t		gl_allocmisses;
454123474Swpaul		uint32_t		gl_allochits;
455123474Swpaul	} u_a;
456123474Swpaul	uint32_t		gl_totalfrees;
457123474Swpaul	union {
458123474Swpaul		uint32_t		gl_freemisses;
459123474Swpaul		uint32_t		gl_freehits;
460123474Swpaul	} u_m;
461123474Swpaul	uint32_t		gl_type;
462123474Swpaul	uint32_t		gl_tag;
463123474Swpaul	uint32_t		gl_size;
464123474Swpaul	void			*gl_allocfunc;
465123474Swpaul	void			*gl_freefunc;
466123507Swpaul	list_entry		gl_listent;
467123474Swpaul	uint32_t		gl_lasttotallocs;
468123474Swpaul	union {
469123474Swpaul		uint32_t		gl_lastallocmisses;
470123474Swpaul		uint32_t		gl_lastallochits;
471123474Swpaul	} u_l;
472123474Swpaul	uint32_t		gl_rsvd[2];
473123474Swpaul};
474123474Swpaul
475123474Swpaultypedef struct general_lookaside general_lookaside;
476123474Swpaul
477123474Swpaulstruct npaged_lookaside_list {
478123474Swpaul	general_lookaside	nll_l;
479144240Swpaul#ifdef __i386__
480123474Swpaul	kspin_lock		nll_obsoletelock;
481144240Swpaul#endif
482123474Swpaul};
483123474Swpaul
484123474Swpaultypedef struct npaged_lookaside_list npaged_lookaside_list;
485123474Swpaultypedef struct npaged_lookaside_list paged_lookaside_list;
486123474Swpaul
487123474Swpaultypedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
488123474Swpaultypedef void (*lookaside_free_func)(void *);
489123474Swpaul
490125551Swpaulstruct irp;
491123474Swpaul
492125551Swpaulstruct kdevice_qentry {
493125551Swpaul	list_entry		kqe_devlistent;
494125551Swpaul	uint32_t		kqe_sortkey;
495125551Swpaul	uint8_t			kqe_inserted;
496125551Swpaul};
497125551Swpaul
498125551Swpaultypedef struct kdevice_qentry kdevice_qentry;
499125551Swpaul
500125551Swpaulstruct kdevice_queue {
501125551Swpaul	uint16_t		kq_type;
502125551Swpaul	uint16_t		kq_size;
503125551Swpaul	list_entry		kq_devlisthead;
504125551Swpaul	kspin_lock		kq_lock;
505125551Swpaul	uint8_t			kq_busy;
506125551Swpaul};
507125551Swpaul
508125551Swpaultypedef struct kdevice_queue kdevice_queue;
509125551Swpaul
510125551Swpaulstruct wait_ctx_block {
511125551Swpaul	kdevice_qentry		wcb_waitqueue;
512125551Swpaul	void			*wcb_devfunc;
513125551Swpaul	void			*wcb_devctx;
514125551Swpaul	uint32_t		wcb_mapregcnt;
515125551Swpaul	void			*wcb_devobj;
516125551Swpaul	void			*wcb_curirp;
517125551Swpaul	void			*wcb_bufchaindpc;
518125551Swpaul};
519125551Swpaul
520125551Swpaultypedef struct wait_ctx_block wait_ctx_block;
521125551Swpaul
522125551Swpaulstruct wait_block {
523125551Swpaul	list_entry		wb_waitlist;
524125551Swpaul	void			*wb_kthread;
525125551Swpaul	nt_dispatch_header	*wb_object;
526125551Swpaul	struct wait_block	*wb_next;
527151207Swpaul#ifdef notdef
528125551Swpaul	uint16_t		wb_waitkey;
529125551Swpaul	uint16_t		wb_waittype;
530151207Swpaul#endif
531151207Swpaul	uint8_t			wb_waitkey;
532151207Swpaul	uint8_t			wb_waittype;
533151207Swpaul	uint8_t			wb_awakened;
534151207Swpaul	uint8_t			wb_oldpri;
535125551Swpaul};
536125551Swpaul
537125551Swpaultypedef struct wait_block wait_block;
538125551Swpaul
539189488Sweongyo#define	wb_ext wb_kthread
540151207Swpaul
541189488Sweongyo#define	THREAD_WAIT_OBJECTS	3
542189488Sweongyo#define	MAX_WAIT_OBJECTS	64
543125551Swpaul
544189488Sweongyo#define	WAITTYPE_ALL		0
545189488Sweongyo#define	WAITTYPE_ANY		1
546125551Swpaul
547189488Sweongyo#define	WAITKEY_VALID		0x8000
548151207Swpaul
549186507Sweongyo/* kthread priority  */
550186507Sweongyo#define	LOW_PRIORITY		0
551186507Sweongyo#define	LOW_REALTIME_PRIORITY	16
552186507Sweongyo#define	HIGH_PRIORITY		31
553186507Sweongyo
554125551Swpaulstruct thread_context {
555125551Swpaul	void			*tc_thrctx;
556125551Swpaul	void			*tc_thrfunc;
557125551Swpaul};
558125551Swpaul
559125551Swpaultypedef struct thread_context thread_context;
560125551Swpaul
561140751Swpaul/* Forward declaration */
562140751Swpaulstruct driver_object;
563140751Swpaulstruct devobj_extension;
564140751Swpaul
565140751Swpaulstruct driver_extension {
566140751Swpaul	struct driver_object	*dre_driverobj;
567140751Swpaul	void			*dre_adddevicefunc;
568140751Swpaul	uint32_t		dre_reinitcnt;
569140751Swpaul	unicode_string		dre_srvname;
570141524Swpaul
571141524Swpaul	/*
572141524Swpaul	 * Drivers are allowed to add one or more custom extensions
573141524Swpaul	 * to the driver object, but there's no special pointer
574141524Swpaul	 * for them. Hang them off here for now.
575141524Swpaul	 */
576141524Swpaul
577141524Swpaul	list_entry		dre_usrext;
578140751Swpaul};
579140751Swpaul
580140751Swpaultypedef struct driver_extension driver_extension;
581140751Swpaul
582141524Swpaulstruct custom_extension {
583141524Swpaul	list_entry		ce_list;
584141524Swpaul	void			*ce_clid;
585141524Swpaul};
586141524Swpaul
587141524Swpaultypedef struct custom_extension custom_extension;
588141524Swpaul
589140751Swpaul/*
590151207Swpaul * The KINTERRUPT structure in Windows is opaque to drivers.
591151207Swpaul * We define our own custom version with things we need.
592151207Swpaul */
593151207Swpaul
594151207Swpaulstruct kinterrupt {
595151451Swpaul	list_entry		ki_list;
596151207Swpaul	device_t		ki_dev;
597151451Swpaul	int			ki_rid;
598151207Swpaul	void			*ki_cookie;
599151207Swpaul	struct resource		*ki_irq;
600151207Swpaul	kspin_lock		ki_lock_priv;
601151207Swpaul	kspin_lock		*ki_lock;
602151207Swpaul	void			*ki_svcfunc;
603151207Swpaul	void			*ki_svcctx;
604151207Swpaul};
605151207Swpaul
606151207Swpaultypedef struct kinterrupt kinterrupt;
607151207Swpaul
608215708Sbschmidtstruct ksystem_time {
609215708Sbschmidt	uint32_t	low_part;
610215708Sbschmidt	int32_t		high1_time;
611215708Sbschmidt	int32_t		high2_time;
612215708Sbschmidt};
613215708Sbschmidt
614215708Sbschmidtenum nt_product_type {
615215708Sbschmidt	NT_PRODUCT_WIN_NT = 1,
616215708Sbschmidt	NT_PRODUCT_LAN_MAN_NT,
617215708Sbschmidt	NT_PRODUCT_SERVER
618215708Sbschmidt};
619215708Sbschmidt
620215708Sbschmidtenum alt_arch_type {
621215708Sbschmidt	STANDARD_DESIGN,
622215708Sbschmidt	NEC98x86,
623215708Sbschmidt	END_ALTERNATIVES
624215708Sbschmidt};
625215708Sbschmidt
626215708Sbschmidtstruct kuser_shared_data {
627215708Sbschmidt	uint32_t		tick_count;
628215708Sbschmidt	uint32_t		tick_count_multiplier;
629215708Sbschmidt	volatile struct		ksystem_time interrupt_time;
630215708Sbschmidt	volatile struct		ksystem_time system_time;
631215708Sbschmidt	volatile struct		ksystem_time time_zone_bias;
632215708Sbschmidt	uint16_t		image_number_low;
633215708Sbschmidt	uint16_t		image_number_high;
634215708Sbschmidt	int16_t			nt_system_root[260];
635215708Sbschmidt	uint32_t		max_stack_trace_depth;
636215708Sbschmidt	uint32_t		crypto_exponent;
637215708Sbschmidt	uint32_t		time_zone_id;
638215708Sbschmidt	uint32_t		large_page_min;
639215708Sbschmidt	uint32_t		reserved2[7];
640215708Sbschmidt	enum nt_product_type	nt_product_type;
641215708Sbschmidt	uint8_t			product_type_is_valid;
642215708Sbschmidt	uint32_t		nt_major_version;
643215708Sbschmidt	uint32_t		nt_minor_version;
644215708Sbschmidt	uint8_t			processor_features[64];
645215708Sbschmidt	uint32_t		reserved1;
646215708Sbschmidt	uint32_t		reserved3;
647215708Sbschmidt	volatile uint32_t	time_slip;
648215708Sbschmidt	enum alt_arch_type	alt_arch_type;
649215708Sbschmidt	int64_t			system_expiration_date;
650215708Sbschmidt	uint32_t		suite_mask;
651215708Sbschmidt	uint8_t			kdbg_enabled;
652215708Sbschmidt	volatile uint32_t	active_console;
653215708Sbschmidt	volatile uint32_t	dismount_count;
654215708Sbschmidt	uint32_t		com_plus_package;
655215708Sbschmidt	uint32_t		last_system_rit_event_tick_count;
656215708Sbschmidt	uint32_t		num_phys_pages;
657215708Sbschmidt	uint8_t			safe_boot_mode;
658215708Sbschmidt	uint32_t		trace_log;
659215708Sbschmidt	uint64_t		fill0;
660215708Sbschmidt	uint64_t		sys_call[4];
661215708Sbschmidt	union {
662215708Sbschmidt		volatile struct	ksystem_time	tick_count;
663215708Sbschmidt		volatile uint64_t		tick_count_quad;
664215708Sbschmidt	} tick;
665215708Sbschmidt};
666215708Sbschmidt
667151207Swpaul/*
668140751Swpaul * In Windows, there are Physical Device Objects (PDOs) and
669140751Swpaul * Functional Device Objects (FDOs). Physical Device Objects are
670140751Swpaul * created and maintained by bus drivers. For example, the PCI
671140751Swpaul * bus driver might detect two PCI ethernet cards on a given
672140751Swpaul * bus. The PCI bus driver will then allocate two device_objects
673140751Swpaul * for its own internal bookeeping purposes. This is analagous
674140751Swpaul * to the device_t that the FreeBSD PCI code allocates and passes
675140751Swpaul * into each PCI driver's probe and attach routines.
676140751Swpaul *
677140751Swpaul * When an ethernet driver claims one of the ethernet cards
678140751Swpaul * on the bus, it will create its own device_object. This is
679140751Swpaul * the Functional Device Object. This object is analagous to the
680140751Swpaul * device-specific softc structure.
681140751Swpaul */
682140751Swpaul
683125551Swpaulstruct device_object {
684125551Swpaul	uint16_t		do_type;
685125551Swpaul	uint16_t		do_size;
686125551Swpaul	uint32_t		do_refcnt;
687141524Swpaul	struct driver_object	*do_drvobj;
688125551Swpaul	struct device_object	*do_nextdev;
689125551Swpaul	struct device_object	*do_attacheddev;
690125551Swpaul	struct irp		*do_currirp;
691125551Swpaul	void			*do_iotimer;
692125551Swpaul	uint32_t		do_flags;
693125551Swpaul	uint32_t		do_characteristics;
694125551Swpaul	void			*do_vpb;
695125551Swpaul	void			*do_devext;
696141524Swpaul	uint32_t		do_devtype;
697125551Swpaul	uint8_t			do_stacksize;
698125551Swpaul	union {
699125551Swpaul		list_entry		do_listent;
700125551Swpaul		wait_ctx_block		do_wcb;
701125551Swpaul	} queue;
702125551Swpaul	uint32_t		do_alignreq;
703125551Swpaul	kdevice_queue		do_devqueue;
704125551Swpaul	struct kdpc		do_dpc;
705125551Swpaul	uint32_t		do_activethreads;
706125551Swpaul	void			*do_securitydesc;
707125551Swpaul	struct nt_kevent	do_devlock;
708125551Swpaul	uint16_t		do_sectorsz;
709125551Swpaul	uint16_t		do_spare1;
710140751Swpaul	struct devobj_extension	*do_devobj_ext;
711125551Swpaul	void			*do_rsvd;
712125551Swpaul};
713125551Swpaul
714125551Swpaultypedef struct device_object device_object;
715125551Swpaul
716140751Swpaulstruct devobj_extension {
717140751Swpaul	uint16_t		dve_type;
718140751Swpaul	uint16_t		dve_size;
719140751Swpaul	device_object		*dve_devobj;
720140751Swpaul};
721140751Swpaul
722140751Swpaultypedef struct devobj_extension devobj_extension;
723140751Swpaul
724142311Swpaul/* Device object flags */
725142311Swpaul
726189488Sweongyo#define	DO_VERIFY_VOLUME		0x00000002
727189488Sweongyo#define	DO_BUFFERED_IO			0x00000004
728189488Sweongyo#define	DO_EXCLUSIVE			0x00000008
729189488Sweongyo#define	DO_DIRECT_IO			0x00000010
730189488Sweongyo#define	DO_MAP_IO_BUFFER		0x00000020
731189488Sweongyo#define	DO_DEVICE_HAS_NAME		0x00000040
732189488Sweongyo#define	DO_DEVICE_INITIALIZING		0x00000080
733189488Sweongyo#define	DO_SYSTEM_BOOT_PARTITION	0x00000100
734189488Sweongyo#define	DO_LONG_TERM_REQUESTS		0x00000200
735189488Sweongyo#define	DO_NEVER_LAST_DEVICE		0x00000400
736189488Sweongyo#define	DO_SHUTDOWN_REGISTERED		0x00000800
737189488Sweongyo#define	DO_BUS_ENUMERATED_DEVICE	0x00001000
738189488Sweongyo#define	DO_POWER_PAGABLE		0x00002000
739189488Sweongyo#define	DO_POWER_INRUSH			0x00004000
740189488Sweongyo#define	DO_LOW_PRIORITY_FILESYSTEM	0x00010000
741142311Swpaul
742142311Swpaul/* Priority boosts */
743142311Swpaul
744189488Sweongyo#define	IO_NO_INCREMENT			0
745189488Sweongyo#define	IO_CD_ROM_INCREMENT		1
746189488Sweongyo#define	IO_DISK_INCREMENT		1
747189488Sweongyo#define	IO_KEYBOARD_INCREMENT		6
748189488Sweongyo#define	IO_MAILSLOT_INCREMENT		2
749189488Sweongyo#define	IO_MOUSE_INCREMENT		6
750189488Sweongyo#define	IO_NAMED_PIPE_INCREMENT		2
751189488Sweongyo#define	IO_NETWORK_INCREMENT		2
752189488Sweongyo#define	IO_PARALLEL_INCREMENT		1
753189488Sweongyo#define	IO_SERIAL_INCREMENT		2
754189488Sweongyo#define	IO_SOUND_INCREMENT		8
755189488Sweongyo#define	IO_VIDEO_INCREMENT		1
756140751Swpaul
757140751Swpaul/* IRP major codes */
758140751Swpaul
759189488Sweongyo#define	IRP_MJ_CREATE                   0x00
760189488Sweongyo#define	IRP_MJ_CREATE_NAMED_PIPE        0x01
761189488Sweongyo#define	IRP_MJ_CLOSE                    0x02
762189488Sweongyo#define	IRP_MJ_READ                     0x03
763189488Sweongyo#define	IRP_MJ_WRITE                    0x04
764189488Sweongyo#define	IRP_MJ_QUERY_INFORMATION        0x05
765189488Sweongyo#define	IRP_MJ_SET_INFORMATION          0x06
766189488Sweongyo#define	IRP_MJ_QUERY_EA                 0x07
767189488Sweongyo#define	IRP_MJ_SET_EA                   0x08
768189488Sweongyo#define	IRP_MJ_FLUSH_BUFFERS            0x09
769189488Sweongyo#define	IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
770189488Sweongyo#define	IRP_MJ_SET_VOLUME_INFORMATION   0x0b
771189488Sweongyo#define	IRP_MJ_DIRECTORY_CONTROL        0x0c
772189488Sweongyo#define	IRP_MJ_FILE_SYSTEM_CONTROL      0x0d
773189488Sweongyo#define	IRP_MJ_DEVICE_CONTROL           0x0e
774189488Sweongyo#define	IRP_MJ_INTERNAL_DEVICE_CONTROL  0x0f
775189488Sweongyo#define	IRP_MJ_SHUTDOWN                 0x10
776189488Sweongyo#define	IRP_MJ_LOCK_CONTROL             0x11
777189488Sweongyo#define	IRP_MJ_CLEANUP                  0x12
778189488Sweongyo#define	IRP_MJ_CREATE_MAILSLOT          0x13
779189488Sweongyo#define	IRP_MJ_QUERY_SECURITY           0x14
780189488Sweongyo#define	IRP_MJ_SET_SECURITY             0x15
781189488Sweongyo#define	IRP_MJ_POWER                    0x16
782189488Sweongyo#define	IRP_MJ_SYSTEM_CONTROL           0x17
783189488Sweongyo#define	IRP_MJ_DEVICE_CHANGE            0x18
784189488Sweongyo#define	IRP_MJ_QUERY_QUOTA              0x19
785189488Sweongyo#define	IRP_MJ_SET_QUOTA                0x1a
786189488Sweongyo#define	IRP_MJ_PNP                      0x1b
787189488Sweongyo#define	IRP_MJ_PNP_POWER                IRP_MJ_PNP      // Obsolete....
788189488Sweongyo#define	IRP_MJ_MAXIMUM_FUNCTION         0x1b
789189488Sweongyo#define	IRP_MJ_SCSI                     IRP_MJ_INTERNAL_DEVICE_CONTROL
790140751Swpaul
791140751Swpaul/* IRP minor codes */
792140751Swpaul
793189488Sweongyo#define	IRP_MN_QUERY_DIRECTORY          0x01
794189488Sweongyo#define	IRP_MN_NOTIFY_CHANGE_DIRECTORY  0x02
795189488Sweongyo#define	IRP_MN_USER_FS_REQUEST          0x00
796140751Swpaul
797189488Sweongyo#define	IRP_MN_MOUNT_VOLUME             0x01
798189488Sweongyo#define	IRP_MN_VERIFY_VOLUME            0x02
799189488Sweongyo#define	IRP_MN_LOAD_FILE_SYSTEM         0x03
800189488Sweongyo#define	IRP_MN_TRACK_LINK               0x04
801189488Sweongyo#define	IRP_MN_KERNEL_CALL              0x04
802140751Swpaul
803189488Sweongyo#define	IRP_MN_LOCK                     0x01
804189488Sweongyo#define	IRP_MN_UNLOCK_SINGLE            0x02
805189488Sweongyo#define	IRP_MN_UNLOCK_ALL               0x03
806189488Sweongyo#define	IRP_MN_UNLOCK_ALL_BY_KEY        0x04
807140751Swpaul
808189488Sweongyo#define	IRP_MN_NORMAL                   0x00
809189488Sweongyo#define	IRP_MN_DPC                      0x01
810189488Sweongyo#define	IRP_MN_MDL                      0x02
811189488Sweongyo#define	IRP_MN_COMPLETE                 0x04
812189488Sweongyo#define	IRP_MN_COMPRESSED               0x08
813140751Swpaul
814189488Sweongyo#define	IRP_MN_MDL_DPC                  (IRP_MN_MDL | IRP_MN_DPC)
815189488Sweongyo#define	IRP_MN_COMPLETE_MDL             (IRP_MN_COMPLETE | IRP_MN_MDL)
816189488Sweongyo#define	IRP_MN_COMPLETE_MDL_DPC         (IRP_MN_COMPLETE_MDL | IRP_MN_DPC)
817140751Swpaul
818189488Sweongyo#define	IRP_MN_SCSI_CLASS               0x01
819140751Swpaul
820189488Sweongyo#define	IRP_MN_START_DEVICE                 0x00
821189488Sweongyo#define	IRP_MN_QUERY_REMOVE_DEVICE          0x01
822189488Sweongyo#define	IRP_MN_REMOVE_DEVICE                0x02
823189488Sweongyo#define	IRP_MN_CANCEL_REMOVE_DEVICE         0x03
824189488Sweongyo#define	IRP_MN_STOP_DEVICE                  0x04
825189488Sweongyo#define	IRP_MN_QUERY_STOP_DEVICE            0x05
826189488Sweongyo#define	IRP_MN_CANCEL_STOP_DEVICE           0x06
827140751Swpaul
828189488Sweongyo#define	IRP_MN_QUERY_DEVICE_RELATIONS       0x07
829189488Sweongyo#define	IRP_MN_QUERY_INTERFACE              0x08
830189488Sweongyo#define	IRP_MN_QUERY_CAPABILITIES           0x09
831189488Sweongyo#define	IRP_MN_QUERY_RESOURCES              0x0A
832189488Sweongyo#define	IRP_MN_QUERY_RESOURCE_REQUIREMENTS  0x0B
833189488Sweongyo#define	IRP_MN_QUERY_DEVICE_TEXT            0x0C
834189488Sweongyo#define	IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
835140751Swpaul
836189488Sweongyo#define	IRP_MN_READ_CONFIG                  0x0F
837189488Sweongyo#define	IRP_MN_WRITE_CONFIG                 0x10
838189488Sweongyo#define	IRP_MN_EJECT                        0x11
839189488Sweongyo#define	IRP_MN_SET_LOCK                     0x12
840189488Sweongyo#define	IRP_MN_QUERY_ID                     0x13
841189488Sweongyo#define	IRP_MN_QUERY_PNP_DEVICE_STATE       0x14
842189488Sweongyo#define	IRP_MN_QUERY_BUS_INFORMATION        0x15
843189488Sweongyo#define	IRP_MN_DEVICE_USAGE_NOTIFICATION    0x16
844189488Sweongyo#define	IRP_MN_SURPRISE_REMOVAL             0x17
845189488Sweongyo#define	IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
846140751Swpaul
847189488Sweongyo#define	IRP_MN_WAIT_WAKE                    0x00
848189488Sweongyo#define	IRP_MN_POWER_SEQUENCE               0x01
849189488Sweongyo#define	IRP_MN_SET_POWER                    0x02
850189488Sweongyo#define	IRP_MN_QUERY_POWER                  0x03
851140751Swpaul
852189488Sweongyo#define	IRP_MN_QUERY_ALL_DATA               0x00
853189488Sweongyo#define	IRP_MN_QUERY_SINGLE_INSTANCE        0x01
854189488Sweongyo#define	IRP_MN_CHANGE_SINGLE_INSTANCE       0x02
855189488Sweongyo#define	IRP_MN_CHANGE_SINGLE_ITEM           0x03
856189488Sweongyo#define	IRP_MN_ENABLE_EVENTS                0x04
857189488Sweongyo#define	IRP_MN_DISABLE_EVENTS               0x05
858189488Sweongyo#define	IRP_MN_ENABLE_COLLECTION            0x06
859189488Sweongyo#define	IRP_MN_DISABLE_COLLECTION           0x07
860189488Sweongyo#define	IRP_MN_REGINFO                      0x08
861189488Sweongyo#define	IRP_MN_EXECUTE_METHOD               0x09
862189488Sweongyo#define	IRP_MN_REGINFO_EX                   0x0b
863140751Swpaul
864140751Swpaul/* IRP flags */
865140751Swpaul
866189488Sweongyo#define	IRP_NOCACHE                     0x00000001
867189488Sweongyo#define	IRP_PAGING_IO                   0x00000002
868189488Sweongyo#define	IRP_MOUNT_COMPLETION            0x00000002
869189488Sweongyo#define	IRP_SYNCHRONOUS_API             0x00000004
870189488Sweongyo#define	IRP_ASSOCIATED_IRP              0x00000008
871189488Sweongyo#define	IRP_BUFFERED_IO                 0x00000010
872189488Sweongyo#define	IRP_DEALLOCATE_BUFFER           0x00000020
873189488Sweongyo#define	IRP_INPUT_OPERATION             0x00000040
874189488Sweongyo#define	IRP_SYNCHRONOUS_PAGING_IO       0x00000040
875189488Sweongyo#define	IRP_CREATE_OPERATION            0x00000080
876189488Sweongyo#define	IRP_READ_OPERATION              0x00000100
877189488Sweongyo#define	IRP_WRITE_OPERATION             0x00000200
878189488Sweongyo#define	IRP_CLOSE_OPERATION             0x00000400
879189488Sweongyo#define	IRP_DEFER_IO_COMPLETION         0x00000800
880189488Sweongyo#define	IRP_OB_QUERY_NAME               0x00001000
881189488Sweongyo#define	IRP_HOLD_DEVICE_QUEUE           0x00002000
882189488Sweongyo#define	IRP_RETRY_IO_COMPLETION         0x00004000
883189488Sweongyo#define	IRP_CLASS_CACHE_OPERATION       0x00008000
884189488Sweongyo#define	IRP_SET_USER_EVENT              IRP_CLOSE_OPERATION
885140751Swpaul
886140751Swpaul/* IRP I/O control flags */
887140751Swpaul
888189488Sweongyo#define	IRP_QUOTA_CHARGED               0x01
889189488Sweongyo#define	IRP_ALLOCATED_MUST_SUCCEED      0x02
890189488Sweongyo#define	IRP_ALLOCATED_FIXED_SIZE        0x04
891189488Sweongyo#define	IRP_LOOKASIDE_ALLOCATION        0x08
892140751Swpaul
893142311Swpaul/* I/O method types */
894142311Swpaul
895189488Sweongyo#define	METHOD_BUFFERED			0
896189488Sweongyo#define	METHOD_IN_DIRECT		1
897189488Sweongyo#define	METHOD_OUT_DIRECT		2
898189488Sweongyo#define	METHOD_NEITHER			3
899142311Swpaul
900142497Swpaul/* File access types */
901142497Swpaul
902189488Sweongyo#define	FILE_ANY_ACCESS			0x0000
903189488Sweongyo#define	FILE_SPECIAL_ACCESS		FILE_ANY_ACCESS
904189488Sweongyo#define	FILE_READ_ACCESS		0x0001
905189488Sweongyo#define	FILE_WRITE_ACCESS		0x0002
906142497Swpaul
907142497Swpaul/* Recover I/O access method from IOCTL code. */
908142497Swpaul
909189488Sweongyo#define	IO_METHOD(x)			((x) & 0xFFFFFFFC)
910142311Swpaul
911142497Swpaul/* Recover function code from IOCTL code */
912142497Swpaul
913189488Sweongyo#define	IO_FUNC(x)			(((x) & 0x7FFC) >> 2)
914142497Swpaul
915142497Swpaul/* Macro to construct an IOCTL code. */
916142497Swpaul
917189488Sweongyo#define	IOCTL_CODE(dev, func, iomethod, acc)	\
918142497Swpaul	((dev) << 16) | (acc << 14) | (func << 2) | (iomethod))
919142497Swpaul
920142497Swpaul
921140751Swpaulstruct io_status_block {
922140751Swpaul	union {
923140751Swpaul		uint32_t		isb_status;
924140751Swpaul		void			*isb_ptr;
925140751Swpaul	} u;
926140751Swpaul	register_t		isb_info;
927140751Swpaul};
928189488Sweongyo#define	isb_status		u.isb_status
929189488Sweongyo#define	isb_ptr			u.isb_ptr
930140751Swpaul
931140751Swpaultypedef struct io_status_block io_status_block;
932140751Swpaul
933140751Swpaulstruct kapc {
934140751Swpaul	uint16_t		apc_type;
935140751Swpaul	uint16_t		apc_size;
936140751Swpaul	uint32_t		apc_spare0;
937140751Swpaul	void			*apc_thread;
938140751Swpaul	list_entry		apc_list;
939140751Swpaul	void			*apc_kernfunc;
940140751Swpaul	void			*apc_rundownfunc;
941140751Swpaul	void			*apc_normalfunc;
942140751Swpaul	void			*apc_normctx;
943140751Swpaul	void			*apc_sysarg1;
944140751Swpaul	void			*apc_sysarg2;
945140751Swpaul	uint8_t			apc_stateidx;
946140751Swpaul	uint8_t			apc_cpumode;
947140751Swpaul	uint8_t			apc_inserted;
948140751Swpaul};
949140751Swpaul
950140751Swpaultypedef struct kapc kapc;
951140751Swpaul
952144888Swpaultypedef uint32_t (*completion_func)(device_object *,
953141524Swpaul	struct irp *, void *);
954144888Swpaultypedef uint32_t (*cancel_func)(device_object *,
955142311Swpaul	struct irp *);
956141524Swpaul
957140751Swpaulstruct io_stack_location {
958140751Swpaul	uint8_t			isl_major;
959140751Swpaul	uint8_t			isl_minor;
960140751Swpaul	uint8_t			isl_flags;
961140751Swpaul	uint8_t			isl_ctl;
962140751Swpaul
963140751Swpaul	/*
964140751Swpaul	 * There's a big-ass union here in the actual Windows
965140751Swpaul	 * definition of the stucture, but it contains stuff
966140751Swpaul	 * that doesn't really apply to BSD, and defining it
967140751Swpaul	 * all properly would require duplicating over a dozen
968140751Swpaul	 * other structures that we'll never use. Since the
969140751Swpaul	 * io_stack_location structure is opaque to drivers
970140751Swpaul	 * anyway, I'm not going to bother with the extra crap.
971140751Swpaul	 */
972140751Swpaul
973140751Swpaul	union {
974140751Swpaul		struct {
975142311Swpaul			uint32_t		isl_len;
976142311Swpaul			uint32_t		*isl_key;
977142311Swpaul			uint64_t		isl_byteoff;
978142311Swpaul		} isl_read;
979142311Swpaul		struct {
980142311Swpaul			uint32_t		isl_len;
981142311Swpaul			uint32_t		*isl_key;
982142311Swpaul			uint64_t		isl_byteoff;
983142311Swpaul		} isl_write;
984142311Swpaul		struct {
985142311Swpaul			uint32_t		isl_obuflen;
986142311Swpaul			uint32_t		isl_ibuflen;
987142311Swpaul			uint32_t		isl_iocode;
988142311Swpaul			void			*isl_type3ibuf;
989142311Swpaul		} isl_ioctl;
990142311Swpaul		struct {
991140751Swpaul			void			*isl_arg1;
992140751Swpaul			void			*isl_arg2;
993140751Swpaul			void			*isl_arg3;
994140751Swpaul			void			*isl_arg4;
995140751Swpaul		} isl_others;
996142311Swpaul	} isl_parameters __attribute__((packed));
997140751Swpaul
998140751Swpaul	void			*isl_devobj;
999140751Swpaul	void			*isl_fileobj;
1000141524Swpaul	completion_func		isl_completionfunc;
1001140751Swpaul	void			*isl_completionctx;
1002140751Swpaul};
1003140751Swpaul
1004140751Swpaultypedef struct io_stack_location io_stack_location;
1005140751Swpaul
1006140751Swpaul/* Stack location control flags */
1007140751Swpaul
1008189488Sweongyo#define	SL_PENDING_RETURNED		0x01
1009189488Sweongyo#define	SL_INVOKE_ON_CANCEL		0x20
1010189488Sweongyo#define	SL_INVOKE_ON_SUCCESS		0x40
1011189488Sweongyo#define	SL_INVOKE_ON_ERROR		0x80
1012140751Swpaul
1013125551Swpaulstruct irp {
1014140751Swpaul	uint16_t		irp_type;
1015140751Swpaul	uint16_t		irp_size;
1016140751Swpaul	mdl			*irp_mdl;
1017140751Swpaul	uint32_t		irp_flags;
1018140751Swpaul	union {
1019140751Swpaul		struct irp		*irp_master;
1020140751Swpaul		uint32_t		irp_irpcnt;
1021140751Swpaul		void			*irp_sysbuf;
1022140751Swpaul	} irp_assoc;
1023140751Swpaul	list_entry		irp_thlist;
1024140751Swpaul	io_status_block		irp_iostat;
1025140751Swpaul	uint8_t			irp_reqmode;
1026140751Swpaul	uint8_t			irp_pendingreturned;
1027140751Swpaul	uint8_t			irp_stackcnt;
1028140751Swpaul	uint8_t			irp_currentstackloc;
1029140751Swpaul	uint8_t			irp_cancel;
1030140751Swpaul	uint8_t			irp_cancelirql;
1031140751Swpaul	uint8_t			irp_apcenv;
1032140751Swpaul	uint8_t			irp_allocflags;
1033140751Swpaul	io_status_block		*irp_usriostat;
1034141524Swpaul	nt_kevent		*irp_usrevent;
1035140751Swpaul	union {
1036140751Swpaul		struct {
1037140751Swpaul			void			*irp_apcfunc;
1038140751Swpaul			void			*irp_apcctx;
1039140751Swpaul		} irp_asyncparms;
1040140751Swpaul		uint64_t			irp_allocsz;
1041140751Swpaul	} irp_overlay;
1042142311Swpaul	cancel_func		irp_cancelfunc;
1043140751Swpaul	void			*irp_userbuf;
1044140751Swpaul
1045140751Swpaul	/* Windows kernel info */
1046140751Swpaul
1047140751Swpaul	union {
1048140751Swpaul		struct {
1049140751Swpaul			union {
1050140751Swpaul				kdevice_qentry			irp_dqe;
1051140751Swpaul				struct {
1052189488Sweongyo					void			*irp_drvctx[4];
1053140751Swpaul				} s1;
1054140751Swpaul			} u1;
1055140751Swpaul			void			*irp_thread;
1056140751Swpaul			char			*irp_auxbuf;
1057140751Swpaul			struct {
1058140751Swpaul				list_entry			irp_list;
1059140751Swpaul				union {
1060140751Swpaul					io_stack_location	*irp_csl;
1061140751Swpaul					uint32_t		irp_pkttype;
1062140751Swpaul				} u2;
1063140751Swpaul			} s2;
1064140751Swpaul			void			*irp_fileobj;
1065140751Swpaul		} irp_overlay;
1066186507Sweongyo		union {
1067186507Sweongyo			kapc			irp_apc;
1068186507Sweongyo			struct {
1069189488Sweongyo				void		*irp_ep;
1070186507Sweongyo				void		*irp_dev;
1071186507Sweongyo			} irp_usb;
1072186507Sweongyo		} irp_misc;
1073140751Swpaul		void			*irp_compkey;
1074140751Swpaul	} irp_tail;
1075125551Swpaul};
1076125551Swpaul
1077189488Sweongyo#define	irp_csl			s2.u2.irp_csl
1078189488Sweongyo#define	irp_pkttype		s2.u2.irp_pkttype
1079140751Swpaul
1080186507Sweongyo#define	IRP_NDIS_DEV(irp)	(irp)->irp_tail.irp_misc.irp_usb.irp_dev
1081189488Sweongyo#define	IRP_NDISUSB_EP(irp)	(irp)->irp_tail.irp_misc.irp_usb.irp_ep
1082186507Sweongyo
1083125551Swpaultypedef struct irp irp;
1084125551Swpaul
1085189488Sweongyo#define	InterlockedExchangePointer(dst, val)				\
1086144888Swpaul	(void *)InterlockedExchange((uint32_t *)(dst), (uintptr_t)(val))
1087142311Swpaul
1088189488Sweongyo#define	IoSizeOfIrp(ssize)						\
1089141524Swpaul	((uint16_t) (sizeof(irp) + ((ssize) * (sizeof(io_stack_location)))))
1090141524Swpaul
1091189488Sweongyo#define	IoSetCancelRoutine(irp, func)					\
1092142311Swpaul	(cancel_func)InterlockedExchangePointer(			\
1093142311Swpaul	(void *)&(ip)->irp_cancelfunc, (void *)(func))
1094141524Swpaul
1095186507Sweongyo#define	IoSetCancelValue(irp, val)					\
1096186507Sweongyo	(u_long)InterlockedExchangePointer(				\
1097186507Sweongyo	(void *)&(ip)->irp_cancel, (void *)(val))
1098186507Sweongyo
1099189488Sweongyo#define	IoGetCurrentIrpStackLocation(irp)				\
1100140751Swpaul	(irp)->irp_tail.irp_overlay.irp_csl
1101140751Swpaul
1102189488Sweongyo#define	IoGetNextIrpStackLocation(irp)					\
1103140751Swpaul	((irp)->irp_tail.irp_overlay.irp_csl - 1)
1104140751Swpaul
1105189488Sweongyo#define	IoSetNextIrpStackLocation(irp)					\
1106141524Swpaul	do {								\
1107141524Swpaul		irp->irp_currentstackloc--;				\
1108141524Swpaul		irp->irp_tail.irp_overlay.irp_csl--;			\
1109141524Swpaul	} while(0)
1110141524Swpaul
1111189488Sweongyo#define	IoSetCompletionRoutine(irp, func, ctx, ok, err, cancel)		\
1112140751Swpaul	do {								\
1113140751Swpaul		io_stack_location		*s;			\
1114140751Swpaul		s = IoGetNextIrpStackLocation((irp));			\
1115140751Swpaul		s->isl_completionfunc = (func);				\
1116140751Swpaul		s->isl_completionctx = (ctx);				\
1117140751Swpaul		s->isl_ctl = 0;						\
1118141524Swpaul		if (ok) s->isl_ctl = SL_INVOKE_ON_SUCCESS;		\
1119141524Swpaul		if (err) s->isl_ctl |= SL_INVOKE_ON_ERROR;		\
1120141524Swpaul		if (cancel) s->isl_ctl |= SL_INVOKE_ON_CANCEL;		\
1121140751Swpaul	} while(0)
1122140751Swpaul
1123189488Sweongyo#define	IoMarkIrpPending(irp)						\
1124140751Swpaul	IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED
1125186507Sweongyo#define	IoUnmarkIrpPending(irp)						\
1126186507Sweongyo	IoGetCurrentIrpStackLocation(irp)->isl_ctl &= ~SL_PENDING_RETURNED
1127140751Swpaul
1128189488Sweongyo#define	IoCopyCurrentIrpStackLocationToNext(irp)			\
1129140751Swpaul	do {								\
1130140751Swpaul		io_stack_location *src, *dst;				\
1131140751Swpaul		src = IoGetCurrentIrpStackLocation(irp);		\
1132140751Swpaul		dst = IoGetNextIrpStackLocation(irp);			\
1133140751Swpaul		bcopy((char *)src, (char *)dst,				\
1134140751Swpaul		    offsetof(io_stack_location, isl_completionfunc));	\
1135140751Swpaul	} while(0)
1136140751Swpaul
1137189488Sweongyo#define	IoSkipCurrentIrpStackLocation(irp)				\
1138140751Swpaul	do {								\
1139140751Swpaul		(irp)->irp_currentstackloc++;				\
1140140751Swpaul		(irp)->irp_tail.irp_overlay.irp_csl++;			\
1141140751Swpaul	} while(0)
1142140751Swpaul
1143189488Sweongyo#define	IoInitializeDpcRequest(dobj, dpcfunc)				\
1144144175Swpaul	KeInitializeDpc(&(dobj)->do_dpc, dpcfunc, dobj)
1145144175Swpaul
1146189488Sweongyo#define	IoRequestDpc(dobj, irp, ctx)					\
1147144175Swpaul	KeInsertQueueDpc(&(dobj)->do_dpc, irp, ctx)
1148144175Swpaul
1149144888Swpaultypedef uint32_t (*driver_dispatch)(device_object *, irp *);
1150125551Swpaul
1151140751Swpaul/*
1152140751Swpaul * The driver_object is allocated once for each driver that's loaded
1153140751Swpaul * into the system. A new one is allocated for each driver and
1154140751Swpaul * populated a bit via the driver's DriverEntry function.
1155140751Swpaul * In general, a Windows DriverEntry() function will provide a pointer
1156140751Swpaul * to its AddDevice() method and set up the dispatch table.
1157140751Swpaul * For NDIS drivers, this is all done behind the scenes in the
1158140751Swpaul * NdisInitializeWrapper() and/or NdisMRegisterMiniport() routines.
1159140751Swpaul */
1160140751Swpaul
1161140751Swpaulstruct driver_object {
1162140751Swpaul	uint16_t		dro_type;
1163140751Swpaul	uint16_t		dro_size;
1164140751Swpaul	device_object		*dro_devobj;
1165140751Swpaul	uint32_t		dro_flags;
1166140751Swpaul	void			*dro_driverstart;
1167140751Swpaul	uint32_t		dro_driversize;
1168140751Swpaul	void			*dro_driversection;
1169141524Swpaul	driver_extension	*dro_driverext;
1170140751Swpaul	unicode_string		dro_drivername;
1171140751Swpaul	unicode_string		*dro_hwdb;
1172140751Swpaul	void			*dro_pfastiodispatch;
1173140751Swpaul	void			*dro_driverinitfunc;
1174140751Swpaul	void			*dro_driverstartiofunc;
1175140751Swpaul	void			*dro_driverunloadfunc;
1176141524Swpaul	driver_dispatch		dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1];
1177140751Swpaul};
1178140751Swpaul
1179140751Swpaultypedef struct driver_object driver_object;
1180140751Swpaul
1181189488Sweongyo#define	DEVPROP_DEVICE_DESCRIPTION	0x00000000
1182189488Sweongyo#define	DEVPROP_HARDWARE_ID		0x00000001
1183189488Sweongyo#define	DEVPROP_COMPATIBLE_IDS		0x00000002
1184189488Sweongyo#define	DEVPROP_BOOTCONF		0x00000003
1185189488Sweongyo#define	DEVPROP_BOOTCONF_TRANSLATED	0x00000004
1186189488Sweongyo#define	DEVPROP_CLASS_NAME		0x00000005
1187189488Sweongyo#define	DEVPROP_CLASS_GUID		0x00000006
1188189488Sweongyo#define	DEVPROP_DRIVER_KEYNAME		0x00000007
1189189488Sweongyo#define	DEVPROP_MANUFACTURER		0x00000008
1190189488Sweongyo#define	DEVPROP_FRIENDLYNAME		0x00000009
1191189488Sweongyo#define	DEVPROP_LOCATION_INFO		0x0000000A
1192189488Sweongyo#define	DEVPROP_PHYSDEV_NAME		0x0000000B
1193189488Sweongyo#define	DEVPROP_BUSTYPE_GUID		0x0000000C
1194189488Sweongyo#define	DEVPROP_LEGACY_BUSTYPE		0x0000000D
1195189488Sweongyo#define	DEVPROP_BUS_NUMBER		0x0000000E
1196189488Sweongyo#define	DEVPROP_ENUMERATOR_NAME		0x0000000F
1197189488Sweongyo#define	DEVPROP_ADDRESS			0x00000010
1198189488Sweongyo#define	DEVPROP_UINUMBER		0x00000011
1199189488Sweongyo#define	DEVPROP_INSTALL_STATE		0x00000012
1200189488Sweongyo#define	DEVPROP_REMOVAL_POLICY		0x00000013
1201125551Swpaul
1202141524Swpaul/* Various supported device types (used with IoCreateDevice()) */
1203141524Swpaul
1204189488Sweongyo#define	FILE_DEVICE_BEEP		0x00000001
1205189488Sweongyo#define	FILE_DEVICE_CD_ROM		0x00000002
1206189488Sweongyo#define	FILE_DEVICE_CD_ROM_FILE_SYSTEM	0x00000003
1207189488Sweongyo#define	FILE_DEVICE_CONTROLLER		0x00000004
1208189488Sweongyo#define	FILE_DEVICE_DATALINK		0x00000005
1209189488Sweongyo#define	FILE_DEVICE_DFS			0x00000006
1210189488Sweongyo#define	FILE_DEVICE_DISK		0x00000007
1211189488Sweongyo#define	FILE_DEVICE_DISK_FILE_SYSTEM	0x00000008
1212189488Sweongyo#define	FILE_DEVICE_FILE_SYSTEM		0x00000009
1213189488Sweongyo#define	FILE_DEVICE_INPORT_PORT		0x0000000A
1214189488Sweongyo#define	FILE_DEVICE_KEYBOARD		0x0000000B
1215189488Sweongyo#define	FILE_DEVICE_MAILSLOT		0x0000000C
1216189488Sweongyo#define	FILE_DEVICE_MIDI_IN		0x0000000D
1217189488Sweongyo#define	FILE_DEVICE_MIDI_OUT		0x0000000E
1218189488Sweongyo#define	FILE_DEVICE_MOUSE		0x0000000F
1219189488Sweongyo#define	FILE_DEVICE_MULTI_UNC_PROVIDER	0x00000010
1220189488Sweongyo#define	FILE_DEVICE_NAMED_PIPE		0x00000011
1221189488Sweongyo#define	FILE_DEVICE_NETWORK		0x00000012
1222189488Sweongyo#define	FILE_DEVICE_NETWORK_BROWSER	0x00000013
1223189488Sweongyo#define	FILE_DEVICE_NETWORK_FILE_SYSTEM	0x00000014
1224189488Sweongyo#define	FILE_DEVICE_NULL		0x00000015
1225189488Sweongyo#define	FILE_DEVICE_PARALLEL_PORT	0x00000016
1226189488Sweongyo#define	FILE_DEVICE_PHYSICAL_NETCARD	0x00000017
1227189488Sweongyo#define	FILE_DEVICE_PRINTER		0x00000018
1228189488Sweongyo#define	FILE_DEVICE_SCANNER		0x00000019
1229189488Sweongyo#define	FILE_DEVICE_SERIAL_MOUSE_PORT	0x0000001A
1230189488Sweongyo#define	FILE_DEVICE_SERIAL_PORT		0x0000001B
1231189488Sweongyo#define	FILE_DEVICE_SCREEN		0x0000001C
1232189488Sweongyo#define	FILE_DEVICE_SOUND		0x0000001D
1233189488Sweongyo#define	FILE_DEVICE_STREAMS		0x0000001E
1234189488Sweongyo#define	FILE_DEVICE_TAPE		0x0000001F
1235189488Sweongyo#define	FILE_DEVICE_TAPE_FILE_SYSTEM	0x00000020
1236189488Sweongyo#define	FILE_DEVICE_TRANSPORT		0x00000021
1237189488Sweongyo#define	FILE_DEVICE_UNKNOWN		0x00000022
1238189488Sweongyo#define	FILE_DEVICE_VIDEO		0x00000023
1239189488Sweongyo#define	FILE_DEVICE_VIRTUAL_DISK	0x00000024
1240189488Sweongyo#define	FILE_DEVICE_WAVE_IN		0x00000025
1241189488Sweongyo#define	FILE_DEVICE_WAVE_OUT		0x00000026
1242189488Sweongyo#define	FILE_DEVICE_8042_PORT		0x00000027
1243189488Sweongyo#define	FILE_DEVICE_NETWORK_REDIRECTOR	0x00000028
1244189488Sweongyo#define	FILE_DEVICE_BATTERY		0x00000029
1245189488Sweongyo#define	FILE_DEVICE_BUS_EXTENDER	0x0000002A
1246189488Sweongyo#define	FILE_DEVICE_MODEM		0x0000002B
1247189488Sweongyo#define	FILE_DEVICE_VDM			0x0000002C
1248189488Sweongyo#define	FILE_DEVICE_MASS_STORAGE	0x0000002D
1249189488Sweongyo#define	FILE_DEVICE_SMB			0x0000002E
1250189488Sweongyo#define	FILE_DEVICE_KS			0x0000002F
1251189488Sweongyo#define	FILE_DEVICE_CHANGER		0x00000030
1252189488Sweongyo#define	FILE_DEVICE_SMARTCARD		0x00000031
1253189488Sweongyo#define	FILE_DEVICE_ACPI		0x00000032
1254189488Sweongyo#define	FILE_DEVICE_DVD			0x00000033
1255189488Sweongyo#define	FILE_DEVICE_FULLSCREEN_VIDEO	0x00000034
1256189488Sweongyo#define	FILE_DEVICE_DFS_FILE_SYSTEM	0x00000035
1257189488Sweongyo#define	FILE_DEVICE_DFS_VOLUME		0x00000036
1258189488Sweongyo#define	FILE_DEVICE_SERENUM		0x00000037
1259189488Sweongyo#define	FILE_DEVICE_TERMSRV		0x00000038
1260189488Sweongyo#define	FILE_DEVICE_KSEC		0x00000039
1261189488Sweongyo#define	FILE_DEVICE_FIPS		0x0000003A
1262141524Swpaul
1263141524Swpaul/* Device characteristics */
1264141524Swpaul
1265189488Sweongyo#define	FILE_REMOVABLE_MEDIA		0x00000001
1266189488Sweongyo#define	FILE_READ_ONLY_DEVICE		0x00000002
1267189488Sweongyo#define	FILE_FLOPPY_DISKETTE		0x00000004
1268189488Sweongyo#define	FILE_WRITE_ONCE_MEDIA		0x00000008
1269189488Sweongyo#define	FILE_REMOTE_DEVICE		0x00000010
1270189488Sweongyo#define	FILE_DEVICE_IS_MOUNTED		0x00000020
1271189488Sweongyo#define	FILE_VIRTUAL_VOLUME		0x00000040
1272189488Sweongyo#define	FILE_AUTOGENERATED_DEVICE_NAME	0x00000080
1273189488Sweongyo#define	FILE_DEVICE_SECURE_OPEN		0x00000100
1274141524Swpaul
1275141524Swpaul/* Status codes */
1276141524Swpaul
1277189488Sweongyo#define	STATUS_SUCCESS			0x00000000
1278189488Sweongyo#define	STATUS_USER_APC			0x000000C0
1279189488Sweongyo#define	STATUS_KERNEL_APC		0x00000100
1280189488Sweongyo#define	STATUS_ALERTED			0x00000101
1281189488Sweongyo#define	STATUS_TIMEOUT			0x00000102
1282189488Sweongyo#define	STATUS_PENDING			0x00000103
1283186507Sweongyo#define	STATUS_FAILURE			0xC0000001
1284186507Sweongyo#define	STATUS_NOT_IMPLEMENTED		0xC0000002
1285215779Sbschmidt#define	STATUS_ACCESS_VIOLATION		0xC0000005
1286189488Sweongyo#define	STATUS_INVALID_PARAMETER	0xC000000D
1287189488Sweongyo#define	STATUS_INVALID_DEVICE_REQUEST	0xC0000010
1288189488Sweongyo#define	STATUS_MORE_PROCESSING_REQUIRED	0xC0000016
1289186507Sweongyo#define	STATUS_NO_MEMORY		0xC0000017
1290189488Sweongyo#define	STATUS_BUFFER_TOO_SMALL		0xC0000023
1291189488Sweongyo#define	STATUS_MUTANT_NOT_OWNED		0xC0000046
1292186507Sweongyo#define	STATUS_NOT_SUPPORTED		0xC00000BB
1293189488Sweongyo#define	STATUS_INVALID_PARAMETER_2	0xC00000F0
1294189488Sweongyo#define	STATUS_INSUFFICIENT_RESOURCES	0xC000009A
1295186507Sweongyo#define	STATUS_DEVICE_NOT_CONNECTED	0xC000009D
1296186507Sweongyo#define	STATUS_CANCELLED		0xC0000120
1297189488Sweongyo#define	STATUS_NOT_FOUND		0xC0000225
1298186507Sweongyo#define	STATUS_DEVICE_REMOVED		0xC00002B6
1299125551Swpaul
1300189488Sweongyo#define	STATUS_WAIT_0			0x00000000
1301125551Swpaul
1302141524Swpaul/* Memory pool types, for ExAllocatePoolWithTag() */
1303141524Swpaul
1304189488Sweongyo#define	NonPagedPool			0x00000000
1305189488Sweongyo#define	PagedPool			0x00000001
1306189488Sweongyo#define	NonPagedPoolMustSucceed		0x00000002
1307189488Sweongyo#define	DontUseThisType			0x00000003
1308189488Sweongyo#define	NonPagedPoolCacheAligned	0x00000004
1309189488Sweongyo#define	PagedPoolCacheAligned		0x00000005
1310189488Sweongyo#define	NonPagedPoolCacheAlignedMustS	0x00000006
1311189488Sweongyo#define	MaxPoolType			0x00000007
1312141524Swpaul
1313127284Swpaul/*
1314145895Swpaul * IO_WORKITEM is an opaque structures that must be allocated
1315145895Swpaul * via IoAllocateWorkItem() and released via IoFreeWorkItem().
1316145895Swpaul * Consequently, we can define it any way we want.
1317145895Swpaul */
1318145895Swpaultypedef void (*io_workitem_func)(device_object *, void *);
1319145895Swpaul
1320145895Swpaulstruct io_workitem {
1321145895Swpaul	io_workitem_func	iw_func;
1322145895Swpaul	void			*iw_ctx;
1323145895Swpaul	list_entry		iw_listentry;
1324145895Swpaul	device_object		*iw_dobj;
1325146364Swpaul	int			iw_idx;
1326145895Swpaul};
1327145895Swpaul
1328145895Swpaultypedef struct io_workitem io_workitem;
1329145895Swpaul
1330189488Sweongyo#define	WORKQUEUE_CRITICAL	0
1331189488Sweongyo#define	WORKQUEUE_DELAYED	1
1332189488Sweongyo#define	WORKQUEUE_HYPERCRITICAL	2
1333145895Swpaul
1334189488Sweongyo#define	WORKITEM_THREADS	4
1335189488Sweongyo#define	WORKITEM_LEGACY_THREAD	3
1336189488Sweongyo#define	WORKIDX_INC(x)		(x) = (x + 1) % WORKITEM_LEGACY_THREAD
1337146364Swpaul
1338145895Swpaul/*
1339145895Swpaul * Older, deprecated work item API, needed to support NdisQueueWorkItem().
1340145895Swpaul */
1341145895Swpaul
1342145895Swpaulstruct work_queue_item;
1343145895Swpaul
1344145895Swpaultypedef void (*work_item_func)(struct work_queue_item *, void *);
1345145895Swpaul
1346145895Swpaulstruct work_queue_item {
1347145895Swpaul	list_entry		wqi_entry;
1348145895Swpaul	work_item_func		wqi_func;
1349145895Swpaul	void			*wqi_ctx;
1350145895Swpaul};
1351145895Swpaul
1352145895Swpaultypedef struct work_queue_item work_queue_item;
1353145895Swpaul
1354189488Sweongyo#define	ExInitializeWorkItem(w, func, ctx)		\
1355145895Swpaul	do {						\
1356145895Swpaul		(w)->wqi_func = (func);			\
1357145895Swpaul		(w)->wqi_ctx = (ctx);			\
1358151207Swpaul		InitializeListHead(&((w)->wqi_entry));	\
1359161425Simp	} while (0)
1360145895Swpaul
1361145895Swpaul/*
1362127284Swpaul * FreeBSD's kernel stack is 2 pages in size by default. The
1363127284Swpaul * Windows stack is larger, so we need to give our threads more
1364127284Swpaul * stack pages. 4 should be enough, we use 8 just to extra safe.
1365127284Swpaul */
1366189488Sweongyo#define	NDIS_KSTACK_PAGES	8
1367127284Swpaul
1368144888Swpaul/*
1369144888Swpaul * Different kinds of function wrapping we can do.
1370144888Swpaul */
1371144888Swpaul
1372189488Sweongyo#define	WINDRV_WRAP_STDCALL	1
1373189488Sweongyo#define	WINDRV_WRAP_FASTCALL	2
1374189488Sweongyo#define	WINDRV_WRAP_REGPARM	3
1375189488Sweongyo#define	WINDRV_WRAP_CDECL	4
1376189488Sweongyo#define	WINDRV_WRAP_AMD64	5
1377144888Swpaul
1378145485Swpaulstruct drvdb_ent {
1379145485Swpaul	driver_object		*windrv_object;
1380145485Swpaul	void			*windrv_devlist;
1381145485Swpaul	ndis_cfg		*windrv_regvals;
1382145485Swpaul	interface_type		windrv_bustype;
1383145485Swpaul	STAILQ_ENTRY(drvdb_ent) link;
1384145485Swpaul};
1385145485Swpaul
1386123474Swpaulextern image_patch_table ntoskrnl_functbl[];
1387215708Sbschmidt#ifdef __amd64__
1388215708Sbschmidtextern struct kuser_shared_data kuser_shared_data;
1389215708Sbschmidt#endif
1390141963Swpaultypedef void (*funcptr)(void);
1391146016Swpaultypedef int (*matchfuncptr)(interface_type, void *, void *);
1392123474Swpaul
1393123474Swpaul__BEGIN_DECLS
1394141524Swpaulextern int windrv_libinit(void);
1395141524Swpaulextern int windrv_libfini(void);
1396142399Swpaulextern driver_object *windrv_lookup(vm_offset_t, char *);
1397145485Swpaulextern struct drvdb_ent *windrv_match(matchfuncptr, void *);
1398145485Swpaulextern int windrv_load(module_t, vm_offset_t, int, interface_type,
1399145485Swpaul	void *, ndis_cfg *);
1400141524Swpaulextern int windrv_unload(module_t, vm_offset_t, int);
1401141524Swpaulextern int windrv_create_pdo(driver_object *, device_t);
1402141524Swpaulextern void windrv_destroy_pdo(driver_object *, device_t);
1403141524Swpaulextern device_object *windrv_find_pdo(driver_object *, device_t);
1404141524Swpaulextern int windrv_bus_attach(driver_object *, char *);
1405144888Swpaulextern int windrv_wrap(funcptr, funcptr *, int, int);
1406141963Swpaulextern int windrv_unwrap(funcptr);
1407144888Swpaulextern void ctxsw_utow(void);
1408144888Swpaulextern void ctxsw_wtou(void);
1409141524Swpaul
1410123474Swpaulextern int ntoskrnl_libinit(void);
1411123474Swpaulextern int ntoskrnl_libfini(void);
1412151207Swpaul
1413151451Swpaulextern void ntoskrnl_intr(void *);
1414174150Sthompsaextern void ntoskrnl_time(uint64_t *);
1415151451Swpaul
1416151451Swpaulextern uint16_t ExQueryDepthSList(slist_header *);
1417151451Swpaulextern slist_entry
1418151451Swpaul	*InterlockedPushEntrySList(slist_header *, slist_entry *);
1419151451Swpaulextern slist_entry *InterlockedPopEntrySList(slist_header *);
1420151207Swpaulextern uint32_t RtlUnicodeStringToAnsiString(ansi_string *,
1421151207Swpaul	unicode_string *, uint8_t);
1422151207Swpaulextern uint32_t RtlAnsiStringToUnicodeString(unicode_string *,
1423151207Swpaul	ansi_string *, uint8_t);
1424151207Swpaulextern void RtlInitAnsiString(ansi_string *, char *);
1425151207Swpaulextern void RtlInitUnicodeString(unicode_string *,
1426151207Swpaul	uint16_t *);
1427151207Swpaulextern void RtlFreeUnicodeString(unicode_string *);
1428151207Swpaulextern void RtlFreeAnsiString(ansi_string *);
1429144888Swpaulextern void KeInitializeDpc(kdpc *, void *, void *);
1430144888Swpaulextern uint8_t KeInsertQueueDpc(kdpc *, void *, void *);
1431144888Swpaulextern uint8_t KeRemoveQueueDpc(kdpc *);
1432145895Swpaulextern void KeSetImportanceDpc(kdpc *, uint32_t);
1433145895Swpaulextern void KeSetTargetProcessorDpc(kdpc *, uint8_t);
1434145895Swpaulextern void KeFlushQueuedDpcs(void);
1435145895Swpaulextern uint32_t KeGetCurrentProcessorNumber(void);
1436144888Swpaulextern void KeInitializeTimer(ktimer *);
1437144888Swpaulextern void KeInitializeTimerEx(ktimer *, uint32_t);
1438189488Sweongyoextern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *);
1439144888Swpaulextern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *);
1440144888Swpaulextern uint8_t KeCancelTimer(ktimer *);
1441144888Swpaulextern uint8_t KeReadStateTimer(ktimer *);
1442151248Swpaulextern uint32_t KeWaitForSingleObject(void *, uint32_t,
1443127248Swpaul	uint32_t, uint8_t, int64_t *);
1444144888Swpaulextern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t);
1445144888Swpaulextern void KeClearEvent(nt_kevent *);
1446144888Swpaulextern uint32_t KeReadStateEvent(nt_kevent *);
1447144888Swpaulextern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t);
1448144888Swpaulextern uint32_t KeResetEvent(nt_kevent *);
1449144175Swpaul#ifdef __i386__
1450144888Swpaulextern void KefAcquireSpinLockAtDpcLevel(kspin_lock *);
1451144888Swpaulextern void KefReleaseSpinLockFromDpcLevel(kspin_lock *);
1452144888Swpaulextern uint8_t KeAcquireSpinLockRaiseToDpc(kspin_lock *);
1453144175Swpaul#else
1454144888Swpaulextern void KeAcquireSpinLockAtDpcLevel(kspin_lock *);
1455144888Swpaulextern void KeReleaseSpinLockFromDpcLevel(kspin_lock *);
1456144175Swpaul#endif
1457144888Swpaulextern void KeInitializeSpinLock(kspin_lock *);
1458151451Swpaulextern uint8_t KeAcquireInterruptSpinLock(kinterrupt *);
1459151451Swpaulextern void KeReleaseInterruptSpinLock(kinterrupt *, uint8_t);
1460151207Swpaulextern uint8_t KeSynchronizeExecution(kinterrupt *, void *, void *);
1461144888Swpaulextern uintptr_t InterlockedExchange(volatile uint32_t *,
1462144888Swpaul	uintptr_t);
1463144888Swpaulextern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t);
1464144888Swpaulextern void ExFreePool(void *);
1465151207Swpaulextern uint32_t IoConnectInterrupt(kinterrupt **, void *, void *,
1466151207Swpaul	kspin_lock *, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t,
1467151207Swpaul	uint32_t, uint8_t);
1468186507Sweongyoextern uint8_t MmIsAddressValid(void *);
1469216242Sbschmidtextern void *MmGetSystemRoutineAddress(unicode_string *);
1470151691Swpaulextern void *MmMapIoSpace(uint64_t, uint32_t, uint32_t);
1471151691Swpaulextern void MmUnmapIoSpace(void *, size_t);
1472151207Swpaulextern void MmBuildMdlForNonPagedPool(mdl *);
1473151207Swpaulextern void IoDisconnectInterrupt(kinterrupt *);
1474144888Swpaulextern uint32_t IoAllocateDriverObjectExtension(driver_object *,
1475141524Swpaul	void *, uint32_t, void **);
1476144888Swpaulextern void *IoGetDriverObjectExtension(driver_object *, void *);
1477144888Swpaulextern uint32_t IoCreateDevice(driver_object *, uint32_t,
1478141524Swpaul	unicode_string *, uint32_t, uint32_t, uint8_t, device_object **);
1479144888Swpaulextern void IoDeleteDevice(device_object *);
1480144888Swpaulextern device_object *IoGetAttachedDevice(device_object *);
1481144888Swpaulextern uint32_t IofCallDriver(device_object *, irp *);
1482144888Swpaulextern void IofCompleteRequest(irp *, uint8_t);
1483144888Swpaulextern void IoAcquireCancelSpinLock(uint8_t *);
1484144888Swpaulextern void IoReleaseCancelSpinLock(uint8_t);
1485144888Swpaulextern uint8_t IoCancelIrp(irp *);
1486144888Swpaulextern void IoDetachDevice(device_object *);
1487144888Swpaulextern device_object *IoAttachDeviceToDeviceStack(device_object *,
1488141524Swpaul	device_object *);
1489145895Swpaulextern mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *);
1490145895Swpaulextern void IoFreeMdl(mdl *);
1491145895Swpaulextern io_workitem *IoAllocateWorkItem(device_object *);
1492145895Swpaulextern void ExQueueWorkItem(work_queue_item *, u_int32_t);
1493145895Swpaulextern void IoFreeWorkItem(io_workitem *);
1494145895Swpaulextern void IoQueueWorkItem(io_workitem *, io_workitem_func,
1495145895Swpaul	uint32_t, void *);
1496128229Swpaul
1497189488Sweongyo#define	IoCallDriver(a, b)		IofCallDriver(a, b)
1498189488Sweongyo#define	IoCompleteRequest(a, b)		IofCompleteRequest(a, b)
1499140751Swpaul
1500128229Swpaul/*
1501128229Swpaul * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock()
1502128229Swpaul * routines live in the HAL. We try to imitate this behavior.
1503128229Swpaul */
1504128229Swpaul#ifdef __i386__
1505215708Sbschmidt#define	KI_USER_SHARED_DATA 0xffdf0000
1506189488Sweongyo#define	KeAcquireSpinLock(a, b)	*(b) = KfAcquireSpinLock(a)
1507189488Sweongyo#define	KeReleaseSpinLock(a, b)	KfReleaseSpinLock(a, b)
1508189488Sweongyo#define	KeRaiseIrql(a, b)	*(b) = KfRaiseIrql(a)
1509189488Sweongyo#define	KeLowerIrql(a)		KfLowerIrql(a)
1510189488Sweongyo#define	KeAcquireSpinLockAtDpcLevel(a)	KefAcquireSpinLockAtDpcLevel(a)
1511189488Sweongyo#define	KeReleaseSpinLockFromDpcLevel(a)  KefReleaseSpinLockFromDpcLevel(a)
1512128229Swpaul#endif /* __i386__ */
1513141963Swpaul
1514141963Swpaul#ifdef __amd64__
1515215708Sbschmidt#define	KI_USER_SHARED_DATA 0xfffff78000000000UL
1516189488Sweongyo#define	KeAcquireSpinLock(a, b)	*(b) = KfAcquireSpinLock(a)
1517189488Sweongyo#define	KeReleaseSpinLock(a, b)	KfReleaseSpinLock(a, b)
1518141963Swpaul
1519141963Swpaul/*
1520141963Swpaul * These may need to be redefined later;
1521141963Swpaul * not sure where they live on amd64 yet.
1522141963Swpaul */
1523189488Sweongyo#define	KeRaiseIrql(a, b)	*(b) = KfRaiseIrql(a)
1524189488Sweongyo#define	KeLowerIrql(a)		KfLowerIrql(a)
1525141963Swpaul#endif /* __amd64__ */
1526141963Swpaul
1527123474Swpaul__END_DECLS
1528123474Swpaul
1529123474Swpaul#endif /* _NTOSKRNL_VAR_H_ */
1530