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