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