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