ntoskrnl_var.h revision 141524
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: head/sys/compat/ndis/ntoskrnl_var.h 141524 2005-02-08 17:23:25Z wpaul $
33123474Swpaul */
34123474Swpaul
35123474Swpaul#ifndef _NTOSKRNL_VAR_H_
36123474Swpaul#define _NTOSKRNL_VAR_H_
37123474Swpaul
38140751Swpaul/*
39140751Swpaul * us_buf is really a wchar_t *, but it's inconvenient to include
40140751Swpaul * all the necessary header goop needed to define it, and it's a
41140751Swpaul * pointer anyway, so for now, just make it a uint16_t *.
42140751Swpaul */
43140751Swpaulstruct unicode_string {
44140751Swpaul	uint16_t		us_len;
45140751Swpaul	uint16_t		us_maxlen;
46140751Swpaul	uint16_t		*us_buf;
47140751Swpaul};
48140751Swpaul
49140751Swpaultypedef struct unicode_string unicode_string;
50140751Swpaul
51140751Swpaul/*
52140751Swpaul * Windows memory descriptor list. In Windows, it's possible for
53140751Swpaul * buffers to be passed between user and kernel contexts without
54140751Swpaul * copying. Buffers may also be allocated in either paged or
55140751Swpaul * non-paged memory regions. An MDL describes the pages of memory
56140751Swpaul * used to contain a particular buffer. Note that a single MDL
57140751Swpaul * may describe a buffer that spans multiple pages. An array of
58140751Swpaul * page addresses appears immediately after the MDL structure itself.
59140751Swpaul * MDLs are therefore implicitly variably sized, even though they
60140751Swpaul * don't look it.
61140751Swpaul *
62140751Swpaul * Note that in FreeBSD, we can take many shortcuts in the way
63140751Swpaul * we handle MDLs because:
64140751Swpaul *
65140751Swpaul * - We are only concerned with pages in kernel context. This means
66140751Swpaul *   we will only ever use the kernel's memory map, and remapping
67140751Swpaul *   of buffers is never needed.
68140751Swpaul *
69140751Swpaul * - Kernel pages can never be paged out, so we don't have to worry
70140751Swpaul *   about whether or not a page is actually mapped before going to
71140751Swpaul *   touch it.
72140751Swpaul */
73140751Swpaul
74140751Swpaulstruct mdl {
75140751Swpaul        struct mdl		*mdl_next;
76140751Swpaul	uint16_t		mdl_size;
77140751Swpaul	uint16_t		mdl_flags;
78140751Swpaul	void			*mdl_process;
79140751Swpaul	void			*mdl_mappedsystemva;
80140751Swpaul	void			*mdl_startva;
81140751Swpaul	uint32_t		mdl_bytecount;
82140751Swpaul	uint32_t		mdl_byteoffset;
83140751Swpaul};
84140751Swpaul
85140751Swpaultypedef struct mdl mdl, ndis_buffer;
86140751Swpaul
87140751Swpaul/* MDL flags */
88140751Swpaul
89140751Swpaul#define MDL_MAPPED_TO_SYSTEM_VA		0x0001
90140751Swpaul#define MDL_PAGES_LOCKED		0x0002
91140751Swpaul#define MDL_SOURCE_IS_NONPAGED_POOL	0x0004
92140751Swpaul#define MDL_ALLOCATED_FIXED_SIZE	0x0008
93140751Swpaul#define MDL_PARTIAL			0x0010
94140751Swpaul#define MDL_PARTIAL_HAS_BEEN_MAPPED	0x0020
95140751Swpaul#define MDL_IO_PAGE_READ		0x0040
96140751Swpaul#define MDL_WRITE_OPERATION		0x0080
97140751Swpaul#define MDL_PARENT_MAPPED_SYSTEM_VA	0x0100
98140751Swpaul#define MDL_FREE_EXTRA_PTES		0x0200
99140751Swpaul#define MDL_IO_SPACE			0x0800
100140751Swpaul#define MDL_NETWORK_HEADER		0x1000
101140751Swpaul#define MDL_MAPPING_CAN_FAIL		0x2000
102140751Swpaul#define MDL_ALLOCATED_MUST_SUCCEED	0x4000
103140751Swpaul
104123512Swpaul/* Note: assumes x86 page size of 4K. */
105140751Swpaul
106140751Swpaul#if PAGE_SIZE == 4096
107123512Swpaul#define PAGE_SHIFT	12
108140751Swpaul#elif PAGE_SIZE == 8192
109140751Swpaul#define PAGE_SHIFT	13
110140751Swpaul#else
111140751Swpaul#error PAGE_SHIFT undefined!
112140751Swpaul#endif
113140751Swpaul
114123512Swpaul#define SPAN_PAGES(ptr, len)					\
115140751Swpaul	((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE - 1)) +	\
116123512Swpaul	(len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
117140751Swpaul
118123757Swpaul#define PAGE_ALIGN(ptr)						\
119123757Swpaul	((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
120140751Swpaul
121123757Swpaul#define BYTE_OFFSET(ptr)					\
122123757Swpaul	((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
123140751Swpaul
124140751Swpaul#define MDL_PAGES(m)	(vm_offset_t *)(m + 1)
125140751Swpaul
126140751Swpaul#define MmInitializeMdl(b, baseva, len)					\
127140751Swpaul	(b)->mdl_next = NULL;						\
128140751Swpaul	(b)->mdl_size = (uint16_t)(sizeof(mdl) +			\
129123757Swpaul		(sizeof(uint32_t) * SPAN_PAGES((baseva), (len))));	\
130140751Swpaul	(b)->mdl_flags = 0;						\
131140751Swpaul	(b)->mdl_startva = (void *)PAGE_ALIGN((baseva));		\
132140751Swpaul	(b)->mdl_byteoffset = BYTE_OFFSET((baseva));			\
133140751Swpaul	(b)->mdl_bytecount = (uint32_t)(len);
134123512Swpaul
135140751Swpaul#define MmGetMdlByteOffset(mdl)		((mdl)->mdl_byteoffset)
136140751Swpaul#define MmGetMdlByteCount(mdl)		((mdl)->mdl_bytecount)
137140751Swpaul#define MmGetMdlVirtualAddress(mdl)					\
138140751Swpaul	((void *)((char *)((mdl)->mdl_startva) + (mdl)->mdl_byteoffset))
139140751Swpaul#define MmGetMdlStartVa(mdl)		((mdl)->mdl_startva)
140140751Swpaul#define MmGetMdlPfnArray(mdl)		MDL_PAGES(mdl)
141140751Swpaul
142124729Swpaul#define WDM_MAJOR		1
143124729Swpaul#define WDM_MINOR_WIN98		0x00
144124729Swpaul#define WDM_MINOR_WINME		0x05
145124729Swpaul#define WDM_MINOR_WIN2000	0x10
146124729Swpaul#define WDM_MINOR_WINXP		0x20
147124729Swpaul#define WDM_MINOR_WIN2003	0x30
148124729Swpaul
149124582Sobrien/*-
150124582Sobrien * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
151124582Sobrien * According to the Windows DDK header files, KSPIN_LOCK is defined like this:
152124582Sobrien *	typedef ULONG_PTR KSPIN_LOCK;
153124582Sobrien *
154124582Sobrien * From basetsd.h (SDK, Feb. 2003):
155124582Sobrien * 	typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
156124582Sobrien * 	typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
157124582Sobrien * 	typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
158124582Sobrien *
159124582Sobrien * The keyword __int3264 specifies an integral type that has the following
160124582Sobrien * properties:
161124582Sobrien *	+ It is 32-bit on 32-bit platforms
162124582Sobrien *	+ It is 64-bit on 64-bit platforms
163124582Sobrien *	+ It is 32-bit on the wire for backward compatibility.
164124582Sobrien *	  It gets truncated on the sending side and extended appropriately
165124582Sobrien *	  (signed or unsigned) on the receiving side.
166124582Sobrien *
167124582Sobrien * Thus register_t seems the proper mapping onto FreeBSD for spin locks.
168124582Sobrien */
169123474Swpaul
170124582Sobrientypedef register_t kspin_lock;
171124582Sobrien
172123474Swpaulstruct slist_entry {
173123474Swpaul	struct slist_entry	*sl_next;
174123474Swpaul};
175123474Swpaul
176123474Swpaultypedef struct slist_entry slist_entry;
177123474Swpaul
178123474Swpaulunion slist_header {
179123474Swpaul	uint64_t		slh_align;
180123474Swpaul	struct {
181123474Swpaul		struct slist_entry	*slh_next;
182123474Swpaul		uint16_t		slh_depth;
183123474Swpaul		uint16_t		slh_seq;
184123474Swpaul	} slh_list;
185123474Swpaul};
186123474Swpaul
187123474Swpaultypedef union slist_header slist_header;
188123474Swpaul
189123507Swpaulstruct list_entry {
190123507Swpaul        struct list_entry *nle_flink;
191123507Swpaul        struct list_entry *nle_blink;
192123507Swpaul};
193123507Swpaul
194123507Swpaultypedef struct list_entry list_entry;
195123507Swpaul
196125551Swpaul#define INIT_LIST_HEAD(l)	\
197141524Swpaul	(l)->nle_flink = (l)->nle_blink = (l)
198125551Swpaul
199125551Swpaul#define REMOVE_LIST_ENTRY(e)			\
200125551Swpaul	do {					\
201125551Swpaul		list_entry		*b;	\
202125551Swpaul		list_entry		*f;	\
203125551Swpaul						\
204125551Swpaul		f = e->nle_flink;		\
205125551Swpaul		b = e->nle_blink;		\
206125551Swpaul		b->nle_flink = f;		\
207125551Swpaul		f->nle_blink = b;		\
208125551Swpaul	} while (0)
209125551Swpaul
210125551Swpaul#define REMOVE_LIST_HEAD(l)			\
211125551Swpaul	do {					\
212125551Swpaul		list_entry		*f;	\
213125551Swpaul		list_entry		*e;	\
214125551Swpaul						\
215125551Swpaul		e = l->nle_flink;		\
216125551Swpaul		f = e->nle_flink;		\
217125551Swpaul		l->nle_flink = f;		\
218125551Swpaul		f->nle_blink = l;		\
219125551Swpaul	} while (0)
220125551Swpaul
221125551Swpaul#define REMOVE_LIST_TAIL(l)			\
222125551Swpaul	do {					\
223125551Swpaul		list_entry		*b;	\
224125551Swpaul		list_entry		*e;	\
225125551Swpaul						\
226125551Swpaul		e = l->nle_blink;		\
227125551Swpaul		b = e->nle_blink;		\
228125551Swpaul		l->nle_blink = b;		\
229125551Swpaul		b->nle_flink = l;		\
230125551Swpaul	} while (0)
231125551Swpaul
232125551Swpaul#define INSERT_LIST_TAIL(l, e)			\
233125551Swpaul	do {					\
234125551Swpaul		list_entry		*b;	\
235125551Swpaul						\
236125551Swpaul		b = l->nle_blink;		\
237125860Swpaul		e->nle_flink = l;		\
238125551Swpaul		e->nle_blink = b;		\
239141524Swpaul		b->nle_flink = (e);		\
240141524Swpaul		l->nle_blink = (e);		\
241125551Swpaul	} while (0)
242125551Swpaul
243125551Swpaul#define INSERT_LIST_HEAD(l, e)			\
244125551Swpaul	do {					\
245125551Swpaul		list_entry		*f;	\
246125551Swpaul						\
247125551Swpaul		f = l->nle_flink;		\
248125551Swpaul		e->nle_flink = f;		\
249125551Swpaul		e->nle_blink = l;		\
250125551Swpaul		f->nle_blink = e;		\
251125551Swpaul		l->nle_flink = e;		\
252125551Swpaul	} while (0)
253125551Swpaul
254125551Swpaulstruct nt_dispatch_header {
255125551Swpaul	uint8_t			dh_type;
256125551Swpaul	uint8_t			dh_abs;
257125551Swpaul	uint8_t			dh_size;
258125551Swpaul	uint8_t			dh_inserted;
259125551Swpaul	uint32_t		dh_sigstate;
260125551Swpaul	list_entry		dh_waitlisthead;
261125551Swpaul};
262125551Swpaul
263125551Swpaultypedef struct nt_dispatch_header nt_dispatch_header;
264125551Swpaul
265125551Swpaul#define OTYPE_EVENT		0
266125551Swpaul#define OTYPE_MUTEX		1
267125551Swpaul#define OTYPE_THREAD		2
268125551Swpaul#define OTYPE_TIMER		3
269125551Swpaul
270125551Swpaul/* Windows dispatcher levels. */
271125551Swpaul
272125551Swpaul#define PASSIVE_LEVEL		0
273125551Swpaul#define LOW_LEVEL		0
274125551Swpaul#define APC_LEVEL		1
275125551Swpaul#define DISPATCH_LEVEL		2
276128229Swpaul#define DEVICE_LEVEL		(DISPATCH_LEVEL + 1)
277125551Swpaul#define PROFILE_LEVEL		27
278125551Swpaul#define CLOCK1_LEVEL		28
279125551Swpaul#define CLOCK2_LEVEL		28
280125551Swpaul#define IPI_LEVEL		29
281125551Swpaul#define POWER_LEVEL		30
282125551Swpaul#define HIGH_LEVEL		31
283125551Swpaul
284125551Swpaul#define SYNC_LEVEL_UP		DISPATCH_LEVEL
285125551Swpaul#define SYNC_LEVEL_MP		(IPI_LEVEL - 1)
286125551Swpaul
287128229Swpaul#define AT_PASSIVE_LEVEL(td)		\
288128229Swpaul	((td)->td_proc->p_flag & P_KTHREAD == FALSE)
289128229Swpaul
290128229Swpaul#define AT_DISPATCH_LEVEL(td)		\
291128449Swpaul	((td)->td_base_pri == PI_REALTIME)
292128229Swpaul
293128229Swpaul#define AT_DIRQL_LEVEL(td)		\
294128295Swpaul	((td)->td_priority <= PI_NET)
295128229Swpaul
296128229Swpaul#define AT_HIGH_LEVEL(td)		\
297128229Swpaul	((td)->td_critnest != 0)
298128229Swpaul
299125551Swpaulstruct nt_objref {
300125551Swpaul	nt_dispatch_header	no_dh;
301125551Swpaul	void			*no_obj;
302125551Swpaul	TAILQ_ENTRY(nt_objref)	link;
303125551Swpaul};
304125551Swpaul
305125551SwpaulTAILQ_HEAD(nt_objref_head, nt_objref);
306125551Swpaul
307125551Swpaultypedef struct nt_objref nt_objref;
308125551Swpaul
309125551Swpaul#define EVENT_TYPE_NOTIFY	0
310125551Swpaul#define EVENT_TYPE_SYNC		1
311125551Swpaul
312126620Swpaul/*
313126620Swpaul * We need to use the timeout()/untimeout() API for ktimers
314126620Swpaul * since timers can be initialized, but not destroyed (so
315126620Swpaul * malloc()ing our own callout structures would mean a leak,
316126620Swpaul * since there'd be no way to free() them). This means we
317126620Swpaul * need to use struct callout_handle, which is really just a
318126620Swpaul * pointer. To make it easier to deal with, we use a union
319126620Swpaul * to overlay the callout_handle over the k_timerlistentry.
320126620Swpaul * The latter is a list_entry, which is two pointers, so
321126620Swpaul * there's enough space available to hide a callout_handle
322126620Swpaul * there.
323126620Swpaul */
324126620Swpaul
325125551Swpaulstruct ktimer {
326125551Swpaul	nt_dispatch_header	k_header;
327125551Swpaul	uint64_t		k_duetime;
328126620Swpaul	union {
329126620Swpaul		list_entry		k_timerlistentry;
330126620Swpaul		struct callout_handle	k_handle;
331126620Swpaul	} u;
332125551Swpaul	void			*k_dpc;
333125551Swpaul	uint32_t		k_period;
334125551Swpaul};
335125551Swpaul
336126620Swpaul#define k_timerlistentry	u.k_timerlistentry
337126620Swpaul#define k_handle		u.k_handle
338126620Swpaul
339126620Swpaultypedef struct ktimer ktimer;
340126620Swpaul
341125551Swpaulstruct nt_kevent {
342125551Swpaul	nt_dispatch_header	k_header;
343125551Swpaul};
344125551Swpaul
345125551Swpaultypedef struct nt_kevent nt_kevent;
346125551Swpaul
347125551Swpaul/* Kernel defered procedure call (i.e. timer callback) */
348125551Swpaul
349125551Swpaulstruct kdpc;
350125551Swpaultypedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
351125551Swpaul
352125551Swpaulstruct kdpc {
353125551Swpaul	uint16_t		k_type;
354125551Swpaul	uint8_t			k_num;
355125551Swpaul	uint8_t			k_importance;
356125551Swpaul	list_entry		k_dpclistentry;
357140827Swpaul	void			*k_deferedfunc;
358125551Swpaul	void			*k_deferredctx;
359125551Swpaul	void			*k_sysarg1;
360125551Swpaul	void			*k_sysarg2;
361127552Swpaul	register_t		k_lock;
362125551Swpaul};
363125551Swpaul
364126620Swpaultypedef struct kdpc kdpc;
365126620Swpaul
366125551Swpaul/*
367125551Swpaul * Note: the acquisition count is BSD-specific. The Microsoft
368125551Swpaul * documentation says that mutexes can be acquired recursively
369125551Swpaul * by a given thread, but that you must release the mutex as
370125551Swpaul * many times as you acquired it before it will be set to the
371125551Swpaul * signalled state (i.e. before any other threads waiting on
372125551Swpaul * the object will be woken up). However the Windows KMUTANT
373125551Swpaul * structure has no field for keeping track of the number of
374125551Swpaul * acquisitions, so we need to add one ourselves. As long as
375125551Swpaul * driver code treats the mutex as opaque, we should be ok.
376125551Swpaul */
377125551Swpaulstruct kmutant {
378125551Swpaul	nt_dispatch_header	km_header;
379126620Swpaul	union {
380126620Swpaul		list_entry		km_listentry;
381126620Swpaul		uint32_t		km_acquirecnt;
382126620Swpaul	} u;
383125551Swpaul	void			*km_ownerthread;
384125551Swpaul	uint8_t			km_abandoned;
385125551Swpaul	uint8_t			km_apcdisable;
386125551Swpaul};
387125551Swpaul
388126620Swpaul#define km_listentry		u.km_listentry
389126620Swpaul#define km_acquirecnt		u.km_acquirecnt
390126620Swpaul
391125551Swpaultypedef struct kmutant kmutant;
392125551Swpaul
393125860Swpaul#define LOOKASIDE_DEPTH 256
394125860Swpaul
395123474Swpaulstruct general_lookaside {
396123474Swpaul	slist_header		gl_listhead;
397123474Swpaul	uint16_t		gl_depth;
398123474Swpaul	uint16_t		gl_maxdepth;
399123474Swpaul	uint32_t		gl_totallocs;
400123474Swpaul	union {
401123474Swpaul		uint32_t		gl_allocmisses;
402123474Swpaul		uint32_t		gl_allochits;
403123474Swpaul	} u_a;
404123474Swpaul	uint32_t		gl_totalfrees;
405123474Swpaul	union {
406123474Swpaul		uint32_t		gl_freemisses;
407123474Swpaul		uint32_t		gl_freehits;
408123474Swpaul	} u_m;
409123474Swpaul	uint32_t		gl_type;
410123474Swpaul	uint32_t		gl_tag;
411123474Swpaul	uint32_t		gl_size;
412123474Swpaul	void			*gl_allocfunc;
413123474Swpaul	void			*gl_freefunc;
414123507Swpaul	list_entry		gl_listent;
415123474Swpaul	uint32_t		gl_lasttotallocs;
416123474Swpaul	union {
417123474Swpaul		uint32_t		gl_lastallocmisses;
418123474Swpaul		uint32_t		gl_lastallochits;
419123474Swpaul	} u_l;
420123474Swpaul	uint32_t		gl_rsvd[2];
421123474Swpaul};
422123474Swpaul
423123474Swpaultypedef struct general_lookaside general_lookaside;
424123474Swpaul
425123474Swpaulstruct npaged_lookaside_list {
426123474Swpaul	general_lookaside	nll_l;
427123474Swpaul	kspin_lock		nll_obsoletelock;
428123474Swpaul};
429123474Swpaul
430123474Swpaultypedef struct npaged_lookaside_list npaged_lookaside_list;
431123474Swpaultypedef struct npaged_lookaside_list paged_lookaside_list;
432123474Swpaul
433123474Swpaultypedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
434123474Swpaultypedef void (*lookaside_free_func)(void *);
435123474Swpaul
436125551Swpaulstruct irp;
437123474Swpaul
438125551Swpaulstruct kdevice_qentry {
439125551Swpaul	list_entry		kqe_devlistent;
440125551Swpaul	uint32_t		kqe_sortkey;
441125551Swpaul	uint8_t			kqe_inserted;
442125551Swpaul};
443125551Swpaul
444125551Swpaultypedef struct kdevice_qentry kdevice_qentry;
445125551Swpaul
446125551Swpaulstruct kdevice_queue {
447125551Swpaul	uint16_t		kq_type;
448125551Swpaul	uint16_t		kq_size;
449125551Swpaul	list_entry		kq_devlisthead;
450125551Swpaul	kspin_lock		kq_lock;
451125551Swpaul	uint8_t			kq_busy;
452125551Swpaul};
453125551Swpaul
454125551Swpaultypedef struct kdevice_queue kdevice_queue;
455125551Swpaul
456125551Swpaulstruct wait_ctx_block {
457125551Swpaul	kdevice_qentry		wcb_waitqueue;
458125551Swpaul	void			*wcb_devfunc;
459125551Swpaul	void			*wcb_devctx;
460125551Swpaul	uint32_t		wcb_mapregcnt;
461125551Swpaul	void			*wcb_devobj;
462125551Swpaul	void			*wcb_curirp;
463125551Swpaul	void			*wcb_bufchaindpc;
464125551Swpaul};
465125551Swpaul
466125551Swpaultypedef struct wait_ctx_block wait_ctx_block;
467125551Swpaul
468125551Swpaulstruct wait_block {
469125551Swpaul	list_entry		wb_waitlist;
470125551Swpaul	void			*wb_kthread;
471125551Swpaul	nt_dispatch_header	*wb_object;
472125551Swpaul	struct wait_block	*wb_next;
473125551Swpaul	uint16_t		wb_waitkey;
474125551Swpaul	uint16_t		wb_waittype;
475125551Swpaul};
476125551Swpaul
477125551Swpaultypedef struct wait_block wait_block;
478125551Swpaul
479125551Swpaul#define THREAD_WAIT_OBJECTS	3
480125551Swpaul#define MAX_WAIT_OBJECTS	64
481125551Swpaul
482125551Swpaul#define WAITTYPE_ALL		0
483125551Swpaul#define WAITTYPE_ANY		1
484125551Swpaul
485125551Swpaulstruct thread_context {
486125551Swpaul	void			*tc_thrctx;
487125551Swpaul	void			*tc_thrfunc;
488125551Swpaul};
489125551Swpaul
490125551Swpaultypedef struct thread_context thread_context;
491125551Swpaul
492140751Swpaul/* Forward declaration */
493140751Swpaulstruct driver_object;
494140751Swpaulstruct devobj_extension;
495140751Swpaul
496140751Swpaulstruct driver_extension {
497140751Swpaul	struct driver_object	*dre_driverobj;
498140751Swpaul	void			*dre_adddevicefunc;
499140751Swpaul	uint32_t		dre_reinitcnt;
500140751Swpaul	unicode_string		dre_srvname;
501141524Swpaul
502141524Swpaul	/*
503141524Swpaul	 * Drivers are allowed to add one or more custom extensions
504141524Swpaul	 * to the driver object, but there's no special pointer
505141524Swpaul	 * for them. Hang them off here for now.
506141524Swpaul	 */
507141524Swpaul
508141524Swpaul	list_entry		dre_usrext;
509140751Swpaul};
510140751Swpaul
511140751Swpaultypedef struct driver_extension driver_extension;
512140751Swpaul
513141524Swpaulstruct custom_extension {
514141524Swpaul	list_entry		ce_list;
515141524Swpaul	void			*ce_clid;
516141524Swpaul};
517141524Swpaul
518141524Swpaultypedef struct custom_extension custom_extension;
519141524Swpaul
520140751Swpaul/*
521140751Swpaul * In Windows, there are Physical Device Objects (PDOs) and
522140751Swpaul * Functional Device Objects (FDOs). Physical Device Objects are
523140751Swpaul * created and maintained by bus drivers. For example, the PCI
524140751Swpaul * bus driver might detect two PCI ethernet cards on a given
525140751Swpaul * bus. The PCI bus driver will then allocate two device_objects
526140751Swpaul * for its own internal bookeeping purposes. This is analagous
527140751Swpaul * to the device_t that the FreeBSD PCI code allocates and passes
528140751Swpaul * into each PCI driver's probe and attach routines.
529140751Swpaul *
530140751Swpaul * When an ethernet driver claims one of the ethernet cards
531140751Swpaul * on the bus, it will create its own device_object. This is
532140751Swpaul * the Functional Device Object. This object is analagous to the
533140751Swpaul * device-specific softc structure.
534140751Swpaul */
535140751Swpaul
536125551Swpaulstruct device_object {
537125551Swpaul	uint16_t		do_type;
538125551Swpaul	uint16_t		do_size;
539125551Swpaul	uint32_t		do_refcnt;
540141524Swpaul	struct driver_object	*do_drvobj;
541125551Swpaul	struct device_object	*do_nextdev;
542125551Swpaul	struct device_object	*do_attacheddev;
543125551Swpaul	struct irp		*do_currirp;
544125551Swpaul	void			*do_iotimer;
545125551Swpaul	uint32_t		do_flags;
546125551Swpaul	uint32_t		do_characteristics;
547125551Swpaul	void			*do_vpb;
548125551Swpaul	void			*do_devext;
549141524Swpaul	uint32_t		do_devtype;
550125551Swpaul	uint8_t			do_stacksize;
551125551Swpaul	union {
552125551Swpaul		list_entry		do_listent;
553125551Swpaul		wait_ctx_block		do_wcb;
554125551Swpaul	} queue;
555125551Swpaul	uint32_t		do_alignreq;
556125551Swpaul	kdevice_queue		do_devqueue;
557125551Swpaul	struct kdpc		do_dpc;
558125551Swpaul	uint32_t		do_activethreads;
559125551Swpaul	void			*do_securitydesc;
560125551Swpaul	struct nt_kevent	do_devlock;
561125551Swpaul	uint16_t		do_sectorsz;
562125551Swpaul	uint16_t		do_spare1;
563140751Swpaul	struct devobj_extension	*do_devobj_ext;
564125551Swpaul	void			*do_rsvd;
565125551Swpaul};
566125551Swpaul
567125551Swpaultypedef struct device_object device_object;
568125551Swpaul
569140751Swpaulstruct devobj_extension {
570140751Swpaul	uint16_t		dve_type;
571140751Swpaul	uint16_t		dve_size;
572140751Swpaul	device_object		*dve_devobj;
573140751Swpaul};
574140751Swpaul
575140751Swpaultypedef struct devobj_extension devobj_extension;
576140751Swpaul
577140751Swpaul#define IO_NO_INCREMENT			0
578140751Swpaul#define IO_CD_ROM_INCREMENT		1
579140751Swpaul#define IO_DISK_INCREMENT		1
580140751Swpaul#define IO_KEYBOARD_INCREMENT		6
581140751Swpaul#define IO_MAILSLOT_INCREMENT		2
582140751Swpaul#define IO_MOUSE_INCREMENT		6
583140751Swpaul#define IO_NAMED_PIPE_INCREMENT		2
584140751Swpaul#define IO_NETWORK_INCREMENT		2
585140751Swpaul#define IO_PARALLEL_INCREMENT		1
586140751Swpaul#define IO_SERIAL_INCREMENT		2
587140751Swpaul#define IO_SOUND_INCREMENT		8
588140751Swpaul#define IO_VIDEO_INCREMENT		1
589140751Swpaul
590140751Swpaul/* IRP major codes */
591140751Swpaul
592140751Swpaul#define IRP_MJ_CREATE                   0x00
593140751Swpaul#define IRP_MJ_CREATE_NAMED_PIPE        0x01
594140751Swpaul#define IRP_MJ_CLOSE                    0x02
595140751Swpaul#define IRP_MJ_READ                     0x03
596140751Swpaul#define IRP_MJ_WRITE                    0x04
597140751Swpaul#define IRP_MJ_QUERY_INFORMATION        0x05
598140751Swpaul#define IRP_MJ_SET_INFORMATION          0x06
599140751Swpaul#define IRP_MJ_QUERY_EA                 0x07
600140751Swpaul#define IRP_MJ_SET_EA                   0x08
601140751Swpaul#define IRP_MJ_FLUSH_BUFFERS            0x09
602140751Swpaul#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
603140751Swpaul#define IRP_MJ_SET_VOLUME_INFORMATION   0x0b
604140751Swpaul#define IRP_MJ_DIRECTORY_CONTROL        0x0c
605140751Swpaul#define IRP_MJ_FILE_SYSTEM_CONTROL      0x0d
606140751Swpaul#define IRP_MJ_DEVICE_CONTROL           0x0e
607140751Swpaul#define IRP_MJ_INTERNAL_DEVICE_CONTROL  0x0f
608140751Swpaul#define IRP_MJ_SHUTDOWN                 0x10
609140751Swpaul#define IRP_MJ_LOCK_CONTROL             0x11
610140751Swpaul#define IRP_MJ_CLEANUP                  0x12
611140751Swpaul#define IRP_MJ_CREATE_MAILSLOT          0x13
612140751Swpaul#define IRP_MJ_QUERY_SECURITY           0x14
613140751Swpaul#define IRP_MJ_SET_SECURITY             0x15
614140751Swpaul#define IRP_MJ_POWER                    0x16
615140751Swpaul#define IRP_MJ_SYSTEM_CONTROL           0x17
616140751Swpaul#define IRP_MJ_DEVICE_CHANGE            0x18
617140751Swpaul#define IRP_MJ_QUERY_QUOTA              0x19
618140751Swpaul#define IRP_MJ_SET_QUOTA                0x1a
619140751Swpaul#define IRP_MJ_PNP                      0x1b
620140751Swpaul#define IRP_MJ_PNP_POWER                IRP_MJ_PNP      // Obsolete....
621140751Swpaul#define IRP_MJ_MAXIMUM_FUNCTION         0x1b
622140751Swpaul#define IRP_MJ_SCSI                     IRP_MJ_INTERNAL_DEVICE_CONTROL
623140751Swpaul
624140751Swpaul/* IRP minor codes */
625140751Swpaul
626140751Swpaul#define IRP_MN_QUERY_DIRECTORY          0x01
627140751Swpaul#define IRP_MN_NOTIFY_CHANGE_DIRECTORY  0x02
628140751Swpaul#define IRP_MN_USER_FS_REQUEST          0x00
629140751Swpaul
630140751Swpaul#define IRP_MN_MOUNT_VOLUME             0x01
631140751Swpaul#define IRP_MN_VERIFY_VOLUME            0x02
632140751Swpaul#define IRP_MN_LOAD_FILE_SYSTEM         0x03
633140751Swpaul#define IRP_MN_TRACK_LINK               0x04    // To be obsoleted soon
634140751Swpaul#define IRP_MN_KERNEL_CALL              0x04
635140751Swpaul
636140751Swpaul#define IRP_MN_LOCK                     0x01
637140751Swpaul#define IRP_MN_UNLOCK_SINGLE            0x02
638140751Swpaul#define IRP_MN_UNLOCK_ALL               0x03
639140751Swpaul#define IRP_MN_UNLOCK_ALL_BY_KEY        0x04
640140751Swpaul
641140751Swpaul#define IRP_MN_NORMAL                   0x00
642140751Swpaul#define IRP_MN_DPC                      0x01
643140751Swpaul#define IRP_MN_MDL                      0x02
644140751Swpaul#define IRP_MN_COMPLETE                 0x04
645140751Swpaul#define IRP_MN_COMPRESSED               0x08
646140751Swpaul
647140751Swpaul#define IRP_MN_MDL_DPC                  (IRP_MN_MDL | IRP_MN_DPC)
648140751Swpaul#define IRP_MN_COMPLETE_MDL             (IRP_MN_COMPLETE | IRP_MN_MDL)
649140751Swpaul#define IRP_MN_COMPLETE_MDL_DPC         (IRP_MN_COMPLETE_MDL | IRP_MN_DPC)
650140751Swpaul
651140751Swpaul#define IRP_MN_SCSI_CLASS               0x01
652140751Swpaul
653140751Swpaul#define IRP_MN_START_DEVICE                 0x00
654140751Swpaul#define IRP_MN_QUERY_REMOVE_DEVICE          0x01
655140751Swpaul#define IRP_MN_REMOVE_DEVICE                0x02
656140751Swpaul#define IRP_MN_CANCEL_REMOVE_DEVICE         0x03
657140751Swpaul#define IRP_MN_STOP_DEVICE                  0x04
658140751Swpaul#define IRP_MN_QUERY_STOP_DEVICE            0x05
659140751Swpaul#define IRP_MN_CANCEL_STOP_DEVICE           0x06
660140751Swpaul
661140751Swpaul#define IRP_MN_QUERY_DEVICE_RELATIONS       0x07
662140751Swpaul#define IRP_MN_QUERY_INTERFACE              0x08
663140751Swpaul#define IRP_MN_QUERY_CAPABILITIES           0x09
664140751Swpaul#define IRP_MN_QUERY_RESOURCES              0x0A
665140751Swpaul#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS  0x0B
666140751Swpaul#define IRP_MN_QUERY_DEVICE_TEXT            0x0C
667140751Swpaul#define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
668140751Swpaul
669140751Swpaul#define IRP_MN_READ_CONFIG                  0x0F
670140751Swpaul#define IRP_MN_WRITE_CONFIG                 0x10
671140751Swpaul#define IRP_MN_EJECT                        0x11
672140751Swpaul#define IRP_MN_SET_LOCK                     0x12
673140751Swpaul#define IRP_MN_QUERY_ID                     0x13
674140751Swpaul#define IRP_MN_QUERY_PNP_DEVICE_STATE       0x14
675140751Swpaul#define IRP_MN_QUERY_BUS_INFORMATION        0x15
676140751Swpaul#define IRP_MN_DEVICE_USAGE_NOTIFICATION    0x16
677140751Swpaul#define IRP_MN_SURPRISE_REMOVAL             0x17
678140751Swpaul#define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
679140751Swpaul
680140751Swpaul#define IRP_MN_WAIT_WAKE                    0x00
681140751Swpaul#define IRP_MN_POWER_SEQUENCE               0x01
682140751Swpaul#define IRP_MN_SET_POWER                    0x02
683140751Swpaul#define IRP_MN_QUERY_POWER                  0x03
684140751Swpaul
685140751Swpaul#define IRP_MN_QUERY_ALL_DATA               0x00
686140751Swpaul#define IRP_MN_QUERY_SINGLE_INSTANCE        0x01
687140751Swpaul#define IRP_MN_CHANGE_SINGLE_INSTANCE       0x02
688140751Swpaul#define IRP_MN_CHANGE_SINGLE_ITEM           0x03
689140751Swpaul#define IRP_MN_ENABLE_EVENTS                0x04
690140751Swpaul#define IRP_MN_DISABLE_EVENTS               0x05
691140751Swpaul#define IRP_MN_ENABLE_COLLECTION            0x06
692140751Swpaul#define IRP_MN_DISABLE_COLLECTION           0x07
693140751Swpaul#define IRP_MN_REGINFO                      0x08
694140751Swpaul#define IRP_MN_EXECUTE_METHOD               0x09
695140751Swpaul#define IRP_MN_REGINFO_EX                   0x0b
696140751Swpaul
697140751Swpaul/* IRP flags */
698140751Swpaul
699140751Swpaul#define IRP_NOCACHE                     0x00000001
700140751Swpaul#define IRP_PAGING_IO                   0x00000002
701140751Swpaul#define IRP_MOUNT_COMPLETION            0x00000002
702140751Swpaul#define IRP_SYNCHRONOUS_API             0x00000004
703140751Swpaul#define IRP_ASSOCIATED_IRP              0x00000008
704140751Swpaul#define IRP_BUFFERED_IO                 0x00000010
705140751Swpaul#define IRP_DEALLOCATE_BUFFER           0x00000020
706140751Swpaul#define IRP_INPUT_OPERATION             0x00000040
707140751Swpaul#define IRP_SYNCHRONOUS_PAGING_IO       0x00000040
708140751Swpaul#define IRP_CREATE_OPERATION            0x00000080
709140751Swpaul#define IRP_READ_OPERATION              0x00000100
710140751Swpaul#define IRP_WRITE_OPERATION             0x00000200
711140751Swpaul#define IRP_CLOSE_OPERATION             0x00000400
712140751Swpaul#define IRP_DEFER_IO_COMPLETION         0x00000800
713140751Swpaul#define IRP_OB_QUERY_NAME               0x00001000
714140751Swpaul#define IRP_HOLD_DEVICE_QUEUE           0x00002000
715140751Swpaul#define IRP_RETRY_IO_COMPLETION         0x00004000
716140751Swpaul#define IRP_CLASS_CACHE_OPERATION       0x00008000
717140751Swpaul#define IRP_SET_USER_EVENT              IRP_CLOSE_OPERATION
718140751Swpaul
719140751Swpaul/* IRP I/O control flags */
720140751Swpaul
721140751Swpaul#define IRP_QUOTA_CHARGED               0x01
722140751Swpaul#define IRP_ALLOCATED_MUST_SUCCEED      0x02
723140751Swpaul#define IRP_ALLOCATED_FIXED_SIZE        0x04
724140751Swpaul#define IRP_LOOKASIDE_ALLOCATION        0x08
725140751Swpaul
726140751Swpaulstruct io_status_block {
727140751Swpaul	union {
728140751Swpaul		uint32_t		isb_status;
729140751Swpaul		void			*isb_ptr;
730140751Swpaul	} u;
731140751Swpaul	register_t		isb_info;
732140751Swpaul};
733141524Swpaul#define isb_status		u.isb_status
734141524Swpaul#define isb_ptr			u.isb_ptr
735140751Swpaul
736140751Swpaultypedef struct io_status_block io_status_block;
737140751Swpaul
738140751Swpaulstruct kapc {
739140751Swpaul	uint16_t		apc_type;
740140751Swpaul	uint16_t		apc_size;
741140751Swpaul	uint32_t		apc_spare0;
742140751Swpaul	void			*apc_thread;
743140751Swpaul	list_entry		apc_list;
744140751Swpaul	void			*apc_kernfunc;
745140751Swpaul	void			*apc_rundownfunc;
746140751Swpaul	void			*apc_normalfunc;
747140751Swpaul	void			*apc_normctx;
748140751Swpaul	void			*apc_sysarg1;
749140751Swpaul	void			*apc_sysarg2;
750140751Swpaul	uint8_t			apc_stateidx;
751140751Swpaul	uint8_t			apc_cpumode;
752140751Swpaul	uint8_t			apc_inserted;
753140751Swpaul};
754140751Swpaul
755140751Swpaultypedef struct kapc kapc;
756140751Swpaul
757141524Swpaultypedef __stdcall uint32_t (*completion_func)(device_object *,
758141524Swpaul	struct irp *, void *);
759141524Swpaul
760140751Swpaulstruct io_stack_location {
761140751Swpaul	uint8_t			isl_major;
762140751Swpaul	uint8_t			isl_minor;
763140751Swpaul	uint8_t			isl_flags;
764140751Swpaul	uint8_t			isl_ctl;
765140751Swpaul
766140751Swpaul	/*
767140751Swpaul	 * There's a big-ass union here in the actual Windows
768140751Swpaul	 * definition of the stucture, but it contains stuff
769140751Swpaul	 * that doesn't really apply to BSD, and defining it
770140751Swpaul	 * all properly would require duplicating over a dozen
771140751Swpaul	 * other structures that we'll never use. Since the
772140751Swpaul	 * io_stack_location structure is opaque to drivers
773140751Swpaul	 * anyway, I'm not going to bother with the extra crap.
774140751Swpaul	 */
775140751Swpaul
776140751Swpaul	union {
777140751Swpaul		struct {
778140751Swpaul			void			*isl_arg1;
779140751Swpaul			void			*isl_arg2;
780140751Swpaul			void			*isl_arg3;
781140751Swpaul			void			*isl_arg4;
782140751Swpaul		} isl_others;
783140751Swpaul	} isl_parameters;
784140751Swpaul
785140751Swpaul	void			*isl_devobj;
786140751Swpaul	void			*isl_fileobj;
787141524Swpaul	completion_func		isl_completionfunc;
788140751Swpaul	void			*isl_completionctx;
789140751Swpaul};
790140751Swpaul
791140751Swpaultypedef struct io_stack_location io_stack_location;
792140751Swpaul
793140751Swpaul/* Stack location control flags */
794140751Swpaul
795140751Swpaul#define SL_PENDING_RETURNED		0x01
796140751Swpaul#define SL_INVOKE_ON_CANCEL		0x20
797140751Swpaul#define SL_INVOKE_ON_SUCCESS		0x40
798140751Swpaul#define SL_INVOKE_ON_ERROR		0x80
799140751Swpaul
800125551Swpaulstruct irp {
801140751Swpaul	uint16_t		irp_type;
802140751Swpaul	uint16_t		irp_size;
803140751Swpaul	mdl			*irp_mdl;
804140751Swpaul	uint32_t		irp_flags;
805140751Swpaul	union {
806140751Swpaul		struct irp		*irp_master;
807140751Swpaul		uint32_t		irp_irpcnt;
808140751Swpaul		void			*irp_sysbuf;
809140751Swpaul	} irp_assoc;
810140751Swpaul	list_entry		irp_thlist;
811140751Swpaul	io_status_block		irp_iostat;
812140751Swpaul	uint8_t			irp_reqmode;
813140751Swpaul	uint8_t			irp_pendingreturned;
814140751Swpaul	uint8_t			irp_stackcnt;
815140751Swpaul	uint8_t			irp_currentstackloc;
816140751Swpaul	uint8_t			irp_cancel;
817140751Swpaul	uint8_t			irp_cancelirql;
818140751Swpaul	uint8_t			irp_apcenv;
819140751Swpaul	uint8_t			irp_allocflags;
820140751Swpaul	io_status_block		*irp_usriostat;
821141524Swpaul	nt_kevent		*irp_usrevent;
822140751Swpaul	union {
823140751Swpaul		struct {
824140751Swpaul			void			*irp_apcfunc;
825140751Swpaul			void			*irp_apcctx;
826140751Swpaul		} irp_asyncparms;
827140751Swpaul		uint64_t			irp_allocsz;
828140751Swpaul	} irp_overlay;
829140751Swpaul	void			*irp_cancelfunc;
830140751Swpaul	void			*irp_userbuf;
831140751Swpaul
832140751Swpaul	/* Windows kernel info */
833140751Swpaul
834140751Swpaul	union {
835140751Swpaul		struct {
836140751Swpaul			union {
837140751Swpaul				kdevice_qentry			irp_dqe;
838140751Swpaul				struct {
839140751Swpaul					void 			*irp_drvctx[4];
840140751Swpaul				} s1;
841140751Swpaul			} u1;
842140751Swpaul			void			*irp_thread;
843140751Swpaul			char			*irp_auxbuf;
844140751Swpaul			struct {
845140751Swpaul				list_entry			irp_list;
846140751Swpaul				union {
847140751Swpaul					io_stack_location	*irp_csl;
848140751Swpaul					uint32_t		irp_pkttype;
849140751Swpaul				} u2;
850140751Swpaul			} s2;
851140751Swpaul			void			*irp_fileobj;
852140751Swpaul		} irp_overlay;
853140751Swpaul		kapc			irp_apc;
854140751Swpaul		void			*irp_compkey;
855140751Swpaul	} irp_tail;
856125551Swpaul};
857125551Swpaul
858140751Swpaul#define irp_csl			s2.u2.irp_csl
859140751Swpaul#define irp_pkttype		s2.u2.irp_pkttype
860140751Swpaul
861125551Swpaultypedef struct irp irp;
862125551Swpaul
863141524Swpaul#define IoSizeOfIrp(ssize)						\
864141524Swpaul	((uint16_t) (sizeof(irp) + ((ssize) * (sizeof(io_stack_location)))))
865141524Swpaul
866141524Swpaul
867140751Swpaul#define IoGetCurrentIrpStackLocation(irp)				\
868140751Swpaul	(irp)->irp_tail.irp_overlay.irp_csl
869140751Swpaul
870140751Swpaul#define IoGetNextIrpStackLocation(irp)					\
871140751Swpaul	((irp)->irp_tail.irp_overlay.irp_csl - 1)
872140751Swpaul
873141524Swpaul#define IoSetNextIrpStackLocation(irp)					\
874141524Swpaul	do {								\
875141524Swpaul		irp->irp_currentstackloc--;				\
876141524Swpaul		irp->irp_tail.irp_overlay.irp_csl--;			\
877141524Swpaul	} while(0)
878141524Swpaul
879140751Swpaul#define IoSetCompletionRoutine(irp, func, ctx, ok, err, cancel)		\
880140751Swpaul	do {								\
881140751Swpaul		io_stack_location		*s;			\
882140751Swpaul		s = IoGetNextIrpStackLocation((irp));			\
883140751Swpaul		s->isl_completionfunc = (func);				\
884140751Swpaul		s->isl_completionctx = (ctx);				\
885140751Swpaul		s->isl_ctl = 0;						\
886141524Swpaul		if (ok) s->isl_ctl = SL_INVOKE_ON_SUCCESS;		\
887141524Swpaul		if (err) s->isl_ctl |= SL_INVOKE_ON_ERROR;		\
888141524Swpaul		if (cancel) s->isl_ctl |= SL_INVOKE_ON_CANCEL;		\
889140751Swpaul	} while(0)
890140751Swpaul
891140751Swpaul#define IoMarkIrpPending(irp)						\
892140751Swpaul	IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED
893140751Swpaul
894140751Swpaul#define IoCopyCurrentIrpStackLocationToNext(irp)			\
895140751Swpaul	do {								\
896140751Swpaul		io_stack_location *src, *dst;				\
897140751Swpaul		src = IoGetCurrentIrpStackLocation(irp);		\
898140751Swpaul		dst = IoGetNextIrpStackLocation(irp);			\
899140751Swpaul		bcopy((char *)src, (char *)dst,				\
900140751Swpaul		    offsetof(io_stack_location, isl_completionfunc));	\
901140751Swpaul	} while(0)
902140751Swpaul
903140751Swpaul#define IoSkipCurrentIrpStackLocation(irp)				\
904140751Swpaul	do {								\
905140751Swpaul		(irp)->irp_currentstackloc++;				\
906140751Swpaul		(irp)->irp_tail.irp_overlay.irp_csl++;			\
907140751Swpaul	} while(0)
908140751Swpaul
909141524Swpaultypedef __stdcall uint32_t (*driver_dispatch)(device_object *, irp *);
910125551Swpaul
911140751Swpaul/*
912140751Swpaul * The driver_object is allocated once for each driver that's loaded
913140751Swpaul * into the system. A new one is allocated for each driver and
914140751Swpaul * populated a bit via the driver's DriverEntry function.
915140751Swpaul * In general, a Windows DriverEntry() function will provide a pointer
916140751Swpaul * to its AddDevice() method and set up the dispatch table.
917140751Swpaul * For NDIS drivers, this is all done behind the scenes in the
918140751Swpaul * NdisInitializeWrapper() and/or NdisMRegisterMiniport() routines.
919140751Swpaul */
920140751Swpaul
921140751Swpaulstruct driver_object {
922140751Swpaul	uint16_t		dro_type;
923140751Swpaul	uint16_t		dro_size;
924140751Swpaul	device_object		*dro_devobj;
925140751Swpaul	uint32_t		dro_flags;
926140751Swpaul	void			*dro_driverstart;
927140751Swpaul	uint32_t		dro_driversize;
928140751Swpaul	void			*dro_driversection;
929141524Swpaul	driver_extension	*dro_driverext;
930140751Swpaul	unicode_string		dro_drivername;
931140751Swpaul	unicode_string		*dro_hwdb;
932140751Swpaul	void			*dro_pfastiodispatch;
933140751Swpaul	void			*dro_driverinitfunc;
934140751Swpaul	void			*dro_driverstartiofunc;
935140751Swpaul	void			*dro_driverunloadfunc;
936141524Swpaul	driver_dispatch		dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1];
937140751Swpaul};
938140751Swpaul
939140751Swpaultypedef struct driver_object driver_object;
940140751Swpaul
941125551Swpaul#define DEVPROP_DEVICE_DESCRIPTION	0x00000000
942125551Swpaul#define DEVPROP_HARDWARE_ID		0x00000001
943125551Swpaul#define DEVPROP_COMPATIBLE_IDS		0x00000002
944125551Swpaul#define DEVPROP_BOOTCONF		0x00000003
945125551Swpaul#define DEVPROP_BOOTCONF_TRANSLATED	0x00000004
946125551Swpaul#define DEVPROP_CLASS_NAME		0x00000005
947125551Swpaul#define DEVPROP_CLASS_GUID		0x00000006
948125551Swpaul#define DEVPROP_DRIVER_KEYNAME		0x00000007
949125551Swpaul#define DEVPROP_MANUFACTURER		0x00000008
950125551Swpaul#define DEVPROP_FRIENDLYNAME		0x00000009
951125551Swpaul#define DEVPROP_LOCATION_INFO		0x0000000A
952125551Swpaul#define DEVPROP_PHYSDEV_NAME		0x0000000B
953125551Swpaul#define DEVPROP_BUSTYPE_GUID		0x0000000C
954125551Swpaul#define DEVPROP_LEGACY_BUSTYPE		0x0000000D
955125551Swpaul#define DEVPROP_BUS_NUMBER		0x0000000E
956125551Swpaul#define DEVPROP_ENUMERATOR_NAME		0x0000000F
957125551Swpaul#define DEVPROP_ADDRESS			0x00000010
958125551Swpaul#define DEVPROP_UINUMBER		0x00000011
959125551Swpaul#define DEVPROP_INSTALL_STATE		0x00000012
960125551Swpaul#define DEVPROP_REMOVAL_POLICY		0x00000013
961125551Swpaul
962141524Swpaul/* Various supported device types (used with IoCreateDevice()) */
963141524Swpaul
964141524Swpaul#define FILE_DEVICE_BEEP		0x00000001
965141524Swpaul#define FILE_DEVICE_CD_ROM		0x00000002
966141524Swpaul#define FILE_DEVICE_CD_ROM_FILE_SYSTEM	0x00000003
967141524Swpaul#define FILE_DEVICE_CONTROLLER		0x00000004
968141524Swpaul#define FILE_DEVICE_DATALINK		0x00000005
969141524Swpaul#define FILE_DEVICE_DFS			0x00000006
970141524Swpaul#define FILE_DEVICE_DISK		0x00000007
971141524Swpaul#define FILE_DEVICE_DISK_FILE_SYSTEM	0x00000008
972141524Swpaul#define FILE_DEVICE_FILE_SYSTEM		0x00000009
973141524Swpaul#define FILE_DEVICE_INPORT_PORT		0x0000000A
974141524Swpaul#define FILE_DEVICE_KEYBOARD		0x0000000B
975141524Swpaul#define FILE_DEVICE_MAILSLOT		0x0000000C
976141524Swpaul#define FILE_DEVICE_MIDI_IN		0x0000000D
977141524Swpaul#define FILE_DEVICE_MIDI_OUT		0x0000000E
978141524Swpaul#define FILE_DEVICE_MOUSE		0x0000000F
979141524Swpaul#define FILE_DEVICE_MULTI_UNC_PROVIDER	0x00000010
980141524Swpaul#define FILE_DEVICE_NAMED_PIPE		0x00000011
981141524Swpaul#define FILE_DEVICE_NETWORK		0x00000012
982141524Swpaul#define FILE_DEVICE_NETWORK_BROWSER	0x00000013
983141524Swpaul#define FILE_DEVICE_NETWORK_FILE_SYSTEM	0x00000014
984141524Swpaul#define FILE_DEVICE_NULL		0x00000015
985141524Swpaul#define FILE_DEVICE_PARALLEL_PORT	0x00000016
986141524Swpaul#define FILE_DEVICE_PHYSICAL_NETCARD	0x00000017
987141524Swpaul#define FILE_DEVICE_PRINTER		0x00000018
988141524Swpaul#define FILE_DEVICE_SCANNER		0x00000019
989141524Swpaul#define FILE_DEVICE_SERIAL_MOUSE_PORT	0x0000001A
990141524Swpaul#define FILE_DEVICE_SERIAL_PORT		0x0000001B
991141524Swpaul#define FILE_DEVICE_SCREEN		0x0000001C
992141524Swpaul#define FILE_DEVICE_SOUND		0x0000001D
993141524Swpaul#define FILE_DEVICE_STREAMS		0x0000001E
994141524Swpaul#define FILE_DEVICE_TAPE		0x0000001F
995141524Swpaul#define FILE_DEVICE_TAPE_FILE_SYSTEM	0x00000020
996141524Swpaul#define FILE_DEVICE_TRANSPORT		0x00000021
997141524Swpaul#define FILE_DEVICE_UNKNOWN		0x00000022
998141524Swpaul#define FILE_DEVICE_VIDEO		0x00000023
999141524Swpaul#define FILE_DEVICE_VIRTUAL_DISK	0x00000024
1000141524Swpaul#define FILE_DEVICE_WAVE_IN		0x00000025
1001141524Swpaul#define FILE_DEVICE_WAVE_OUT		0x00000026
1002141524Swpaul#define FILE_DEVICE_8042_PORT		0x00000027
1003141524Swpaul#define FILE_DEVICE_NETWORK_REDIRECTOR	0x00000028
1004141524Swpaul#define FILE_DEVICE_BATTERY		0x00000029
1005141524Swpaul#define FILE_DEVICE_BUS_EXTENDER	0x0000002A
1006141524Swpaul#define FILE_DEVICE_MODEM		0x0000002B
1007141524Swpaul#define FILE_DEVICE_VDM			0x0000002C
1008141524Swpaul#define FILE_DEVICE_MASS_STORAGE	0x0000002D
1009141524Swpaul#define FILE_DEVICE_SMB			0x0000002E
1010141524Swpaul#define FILE_DEVICE_KS			0x0000002F
1011141524Swpaul#define FILE_DEVICE_CHANGER		0x00000030
1012141524Swpaul#define FILE_DEVICE_SMARTCARD		0x00000031
1013141524Swpaul#define FILE_DEVICE_ACPI		0x00000032
1014141524Swpaul#define FILE_DEVICE_DVD			0x00000033
1015141524Swpaul#define FILE_DEVICE_FULLSCREEN_VIDEO	0x00000034
1016141524Swpaul#define FILE_DEVICE_DFS_FILE_SYSTEM	0x00000035
1017141524Swpaul#define FILE_DEVICE_DFS_VOLUME		0x00000036
1018141524Swpaul#define FILE_DEVICE_SERENUM		0x00000037
1019141524Swpaul#define FILE_DEVICE_TERMSRV		0x00000038
1020141524Swpaul#define FILE_DEVICE_KSEC		0x00000039
1021141524Swpaul#define FILE_DEVICE_FIPS		0x0000003A
1022141524Swpaul
1023141524Swpaul/* Device characteristics */
1024141524Swpaul
1025141524Swpaul#define FILE_REMOVABLE_MEDIA		0x00000001
1026141524Swpaul#define FILE_READ_ONLY_DEVICE		0x00000002
1027141524Swpaul#define FILE_FLOPPY_DISKETTE		0x00000004
1028141524Swpaul#define FILE_WRITE_ONCE_MEDIA		0x00000008
1029141524Swpaul#define FILE_REMOTE_DEVICE		0x00000010
1030141524Swpaul#define FILE_DEVICE_IS_MOUNTED		0x00000020
1031141524Swpaul#define FILE_VIRTUAL_VOLUME		0x00000040
1032141524Swpaul#define FILE_AUTOGENERATED_DEVICE_NAME	0x00000080
1033141524Swpaul#define FILE_DEVICE_SECURE_OPEN		0x00000100
1034141524Swpaul
1035141524Swpaul/* Status codes */
1036141524Swpaul
1037125551Swpaul#define STATUS_SUCCESS			0x00000000
1038125551Swpaul#define STATUS_USER_APC			0x000000C0
1039125551Swpaul#define STATUS_KERNEL_APC		0x00000100
1040125551Swpaul#define STATUS_ALERTED			0x00000101
1041125551Swpaul#define STATUS_TIMEOUT			0x00000102
1042125551Swpaul#define STATUS_INVALID_PARAMETER	0xC000000D
1043125551Swpaul#define STATUS_INVALID_DEVICE_REQUEST	0xC0000010
1044141524Swpaul#define STATUS_MORE_PROCESSING_REQUIRED	0xC0000016
1045125551Swpaul#define STATUS_BUFFER_TOO_SMALL		0xC0000023
1046125551Swpaul#define STATUS_MUTANT_NOT_OWNED		0xC0000046
1047125551Swpaul#define STATUS_INVALID_PARAMETER_2	0xC00000F0
1048141524Swpaul#define STATUS_INSUFFICIENT_RESOURCES	0xC000009A
1049125551Swpaul
1050125551Swpaul#define STATUS_WAIT_0			0x00000000
1051125551Swpaul
1052141524Swpaul/* Memory pool types, for ExAllocatePoolWithTag() */
1053141524Swpaul
1054141524Swpaul#define NonPagedPool			0x00000000
1055141524Swpaul#define PagedPool			0x00000001
1056141524Swpaul#define NonPagedPoolMustSucceed		0x00000002
1057141524Swpaul#define DontUseThisType			0x00000003
1058141524Swpaul#define NonPagedPoolCacheAligned	0x00000004
1059141524Swpaul#define PagedPoolCacheAligned		0x00000005
1060141524Swpaul#define NonPagedPoolCacheAlignedMustS	0x00000006
1061141524Swpaul#define MaxPoolType			0x00000007
1062141524Swpaul
1063127284Swpaul/*
1064127284Swpaul * FreeBSD's kernel stack is 2 pages in size by default. The
1065127284Swpaul * Windows stack is larger, so we need to give our threads more
1066127284Swpaul * stack pages. 4 should be enough, we use 8 just to extra safe.
1067127284Swpaul */
1068127284Swpaul#define NDIS_KSTACK_PAGES	8
1069127284Swpaul
1070123474Swpaulextern image_patch_table ntoskrnl_functbl[];
1071123474Swpaul
1072123474Swpaul__BEGIN_DECLS
1073141524Swpaulextern int windrv_libinit(void);
1074141524Swpaulextern int windrv_libfini(void);
1075141524Swpaulextern driver_object *windrv_lookup(vm_offset_t);
1076141524Swpaulextern int windrv_load(module_t, vm_offset_t, int);
1077141524Swpaulextern int windrv_unload(module_t, vm_offset_t, int);
1078141524Swpaulextern int windrv_create_pdo(driver_object *, device_t);
1079141524Swpaulextern void windrv_destroy_pdo(driver_object *, device_t);
1080141524Swpaulextern device_object *windrv_find_pdo(driver_object *, device_t);
1081141524Swpaulextern int windrv_bus_attach(driver_object *, char *);
1082141524Swpaul
1083123474Swpaulextern int ntoskrnl_libinit(void);
1084123474Swpaulextern int ntoskrnl_libfini(void);
1085140751Swpaul__stdcall extern void KeInitializeDpc(kdpc *, void *, void *);
1086140751Swpaul__stdcall extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *);
1087140751Swpaul__stdcall extern uint8_t KeRemoveQueueDpc(kdpc *);
1088140751Swpaul__stdcall extern void KeInitializeTimer(ktimer *);
1089140751Swpaul__stdcall extern void KeInitializeTimerEx(ktimer *, uint32_t);
1090140751Swpaul__stdcall extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *);
1091141524Swpaul__stdcall extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *);
1092140751Swpaul__stdcall extern uint8_t KeCancelTimer(ktimer *);
1093140751Swpaul__stdcall extern uint8_t KeReadStateTimer(ktimer *);
1094140751Swpaul__stdcall extern uint32_t KeWaitForSingleObject(nt_dispatch_header *, uint32_t,
1095127248Swpaul	uint32_t, uint8_t, int64_t *);
1096140751Swpaul__stdcall extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t);
1097140751Swpaul__stdcall extern void KeClearEvent(nt_kevent *);
1098140751Swpaul__stdcall extern uint32_t KeReadStateEvent(nt_kevent *);
1099140751Swpaul__stdcall extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t);
1100140751Swpaul__stdcall extern uint32_t KeResetEvent(nt_kevent *);
1101140751Swpaul__fastcall extern void KefAcquireSpinLockAtDpcLevel(REGARGS1(kspin_lock *));
1102140751Swpaul__fastcall extern void KefReleaseSpinLockFromDpcLevel(REGARGS1(kspin_lock *));
1103140751Swpaul__stdcall extern void KeInitializeSpinLock(kspin_lock *);
1104141524Swpaul__stdcall extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t);
1105141524Swpaul__stdcall extern void ExFreePool(void *);
1106141524Swpaul__stdcall extern uint32_t IoAllocateDriverObjectExtension(driver_object *,
1107141524Swpaul	void *, uint32_t, void **);
1108141524Swpaul__stdcall extern void *IoGetDriverObjectExtension(driver_object *, void *);
1109141524Swpaul__stdcall extern uint32_t IoCreateDevice(driver_object *, uint32_t,
1110141524Swpaul	unicode_string *, uint32_t, uint32_t, uint8_t, device_object **);
1111141524Swpaul__stdcall extern void IoDeleteDevice(device_object *);
1112141524Swpaul__stdcall extern device_object *IoGetAttachedDevice(device_object *);
1113140751Swpaul__fastcall extern uint32_t IofCallDriver(REGARGS2(device_object *, irp *));
1114140751Swpaul__fastcall extern void IofCompleteRequest(REGARGS2(irp *, uint8_t));
1115141524Swpaul__stdcall extern void IoDetachDevice(device_object *);
1116141524Swpaul__stdcall extern device_object *IoAttachDeviceToDeviceStack(device_object *,
1117141524Swpaul	device_object *);
1118128229Swpaul
1119140751Swpaul#define IoCallDriver(a, b)		FASTCALL2(IofCallDriver, a, b)
1120140751Swpaul#define IoCompleteRequest(a, b)		FASTCALL2(IofCompleteRequest, a, b)
1121140751Swpaul
1122128229Swpaul/*
1123128229Swpaul * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock()
1124128229Swpaul * routines live in the HAL. We try to imitate this behavior.
1125128229Swpaul */
1126128229Swpaul#ifdef __i386__
1127140751Swpaul#define KeAcquireSpinLock(a, b)	*(b) = FASTCALL1(KfAcquireSpinLock, a)
1128140751Swpaul#define KeReleaseSpinLock(a, b)	FASTCALL2(KfReleaseSpinLock, a, b)
1129140751Swpaul#define KeRaiseIrql(a)		FASTCALL1(KfRaiseIrql, a)
1130140751Swpaul#define KeLowerIrql(a)		FASTCALL1(KfLowerIrql, a)
1131128229Swpaul#endif /* __i386__ */
1132123474Swpaul__END_DECLS
1133123474Swpaul
1134123474Swpaul#endif /* _NTOSKRNL_VAR_H_ */
1135