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 */
47struct unicode_string {
48	uint16_t		us_len;
49	uint16_t		us_maxlen;
50	uint16_t		*us_buf;
51};
52
53typedef 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
78struct 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
89typedef 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
178typedef register_t kspin_lock;
179
180struct slist_entry {
181	struct slist_entry	*sl_next;
182};
183
184typedef struct slist_entry slist_entry;
185
186union 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
195typedef union slist_header slist_header;
196
197struct list_entry {
198        struct list_entry *nle_flink;
199        struct list_entry *nle_blink;
200};
201
202typedef 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
262struct 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
271typedef 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
305int 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
324struct nt_objref {
325	nt_dispatch_header	no_dh;
326	void			*no_obj;
327	TAILQ_ENTRY(nt_objref)	link;
328};
329
330TAILQ_HEAD(nt_objref_head, nt_objref);
331
332typedef 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
350struct 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
368typedef struct ktimer ktimer;
369
370struct nt_kevent {
371	nt_dispatch_header	k_header;
372};
373
374typedef struct nt_kevent nt_kevent;
375
376/* Kernel defered procedure call (i.e. timer callback) */
377
378struct kdpc;
379typedef __stdcall void (*kdpc_func)(struct kdpc *, void *, void *, void *);
380
381struct 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
393typedef 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 */
406struct 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
420typedef struct kmutant kmutant;
421
422#define LOOKASIDE_DEPTH 256
423
424struct 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
452typedef struct general_lookaside general_lookaside;
453
454struct npaged_lookaside_list {
455	general_lookaside	nll_l;
456#ifdef __i386__
457	kspin_lock		nll_obsoletelock;
458#endif
459};
460
461typedef struct npaged_lookaside_list npaged_lookaside_list;
462typedef struct npaged_lookaside_list paged_lookaside_list;
463
464typedef void *(*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
465typedef void (*lookaside_free_func)(void *);
466
467struct irp;
468
469struct kdevice_qentry {
470	list_entry		kqe_devlistent;
471	uint32_t		kqe_sortkey;
472	uint8_t			kqe_inserted;
473};
474
475typedef struct kdevice_qentry kdevice_qentry;
476
477struct 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
485typedef struct kdevice_queue kdevice_queue;
486
487struct 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
497typedef struct wait_ctx_block wait_ctx_block;
498
499struct 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
508typedef 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
516struct thread_context {
517	void			*tc_thrctx;
518	void			*tc_thrfunc;
519};
520
521typedef struct thread_context thread_context;
522
523/* Forward declaration */
524struct driver_object;
525struct devobj_extension;
526
527struct 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
542typedef struct driver_extension driver_extension;
543
544struct custom_extension {
545	list_entry		ce_list;
546	void			*ce_clid;
547};
548
549typedef 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
567struct 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
602typedef struct device_object device_object;
603
604struct devobj_extension {
605	uint16_t		dve_type;
606	uint16_t		dve_size;
607	device_object		*dve_devobj;
608};
609
610typedef 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
809struct 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
819typedef struct io_status_block io_status_block;
820
821struct 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
838typedef struct kapc kapc;
839
840typedef __stdcall uint32_t (*completion_func)(device_object *,
841	struct irp *, void *);
842typedef __stdcall uint32_t (*cancel_func)(device_object *,
843	struct irp *);
844
845struct 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
892typedef 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
901struct 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
962typedef 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
1023typedef __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
1035struct 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
1053typedef 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
1186extern image_patch_table ntoskrnl_functbl[];
1187typedef void (*funcptr)(void);
1188
1189__BEGIN_DECLS
1190extern int windrv_libinit(void);
1191extern int windrv_libfini(void);
1192extern driver_object *windrv_lookup(vm_offset_t, const char *);
1193extern int windrv_load(module_t, vm_offset_t, int);
1194extern int windrv_unload(module_t, vm_offset_t, int);
1195extern int windrv_create_pdo(driver_object *, device_t);
1196extern void windrv_destroy_pdo(driver_object *, device_t);
1197extern device_object *windrv_find_pdo(driver_object *, device_t);
1198extern int windrv_bus_attach(driver_object *, const char *);
1199extern int windrv_wrap(funcptr, funcptr *);
1200extern int windrv_unwrap(funcptr);
1201
1202extern int ntoskrnl_libinit(void);
1203extern 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