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.46 2008/12/27 08:03:32 weongyo Exp $
33 */
34
35 #ifndef _NTOSKRNL_VAR_H_
36 #define _NTOSKRNL_VAR_H_
37
38 #define MTX_NTOSKRNL_SPIN_LOCK "NDIS thread lock"
39
40 /*
41 * us_buf is really a wchar_t *, but it's inconvenient to include
42 * all the necessary header goop needed to define it, and it's a
43 * pointer anyway, so for now, just make it a uint16_t *.
44 */
45 struct unicode_string {
46 uint16_t us_len;
47 uint16_t us_maxlen;
48 uint16_t *us_buf;
49 };
50
51 typedef struct unicode_string unicode_string;
52
53 struct ansi_string {
54 uint16_t as_len;
55 uint16_t as_maxlen;
56 char *as_buf;
57 };
58
59 typedef struct ansi_string ansi_string;
60
61 /*
62 * Windows memory descriptor list. In Windows, it's possible for
63 * buffers to be passed between user and kernel contexts without
64 * copying. Buffers may also be allocated in either paged or
65 * non-paged memory regions. An MDL describes the pages of memory
66 * used to contain a particular buffer. Note that a single MDL
67 * may describe a buffer that spans multiple pages. An array of
68 * page addresses appears immediately after the MDL structure itself.
69 * MDLs are therefore implicitly variably sized, even though they
70 * don't look it.
71 *
72 * Note that in FreeBSD, we can take many shortcuts in the way
73 * we handle MDLs because:
74 *
75 * - We are only concerned with pages in kernel context. This means
76 * we will only ever use the kernel's memory map, and remapping
77 * of buffers is never needed.
78 *
79 * - Kernel pages can never be paged out, so we don't have to worry
80 * about whether or not a page is actually mapped before going to
81 * touch it.
82 */
83
84 struct mdl {
85 struct mdl *mdl_next;
86 uint16_t mdl_size;
87 uint16_t mdl_flags;
88 void *mdl_process;
89 void *mdl_mappedsystemva;
90 void *mdl_startva;
91 uint32_t mdl_bytecount;
92 uint32_t mdl_byteoffset;
93 };
94
95 typedef struct mdl mdl, ndis_buffer;
96
97 /* MDL flags */
98
99 #define MDL_MAPPED_TO_SYSTEM_VA 0x0001
100 #define MDL_PAGES_LOCKED 0x0002
101 #define MDL_SOURCE_IS_NONPAGED_POOL 0x0004
102 #define MDL_ALLOCATED_FIXED_SIZE 0x0008
103 #define MDL_PARTIAL 0x0010
104 #define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020
105 #define MDL_IO_PAGE_READ 0x0040
106 #define MDL_WRITE_OPERATION 0x0080
107 #define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100
108 #define MDL_FREE_EXTRA_PTES 0x0200
109 #define MDL_IO_SPACE 0x0800
110 #define MDL_NETWORK_HEADER 0x1000
111 #define MDL_MAPPING_CAN_FAIL 0x2000
112 #define MDL_ALLOCATED_MUST_SUCCEED 0x4000
113 #define MDL_ZONE_ALLOCED 0x8000 /* BSD private */
114
115 #define MDL_ZONE_PAGES 16
116 #define MDL_ZONE_SIZE (sizeof(mdl) + (sizeof(vm_offset_t) * MDL_ZONE_PAGES))
117
118 /* Note: assumes x86 page size of 4K. */
119
120 #ifndef PAGE_SHIFT
121 #if PAGE_SIZE == 4096
122 #define PAGE_SHIFT 12
123 #elif PAGE_SIZE == 8192
124 #define PAGE_SHIFT 13
125 #else
126 #error PAGE_SHIFT undefined!
127 #endif
128 #endif
129
130 #define SPAN_PAGES(ptr, len) \
131 ((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE - 1)) + \
132 (len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
133
134 #define PAGE_ALIGN(ptr) \
135 ((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
136
137 #define BYTE_OFFSET(ptr) \
138 ((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
139
140 #define MDL_PAGES(m) (vm_offset_t *)(m + 1)
141
142 #define MmInitializeMdl(b, baseva, len) \
143 (b)->mdl_next = NULL; \
144 (b)->mdl_size = (uint16_t)(sizeof(mdl) + \
145 (sizeof(vm_offset_t) * SPAN_PAGES((baseva), (len)))); \
146 (b)->mdl_flags = 0; \
147 (b)->mdl_startva = (void *)PAGE_ALIGN((baseva)); \
148 (b)->mdl_byteoffset = BYTE_OFFSET((baseva)); \
149 (b)->mdl_bytecount = (uint32_t)(len);
150
151 #define MmGetMdlByteOffset(mdl) ((mdl)->mdl_byteoffset)
152 #define MmGetMdlByteCount(mdl) ((mdl)->mdl_bytecount)
153 #define MmGetMdlVirtualAddress(mdl) \
154 ((void *)((char *)((mdl)->mdl_startva) + (mdl)->mdl_byteoffset))
155 #define MmGetMdlStartVa(mdl) ((mdl)->mdl_startva)
156 #define MmGetMdlPfnArray(mdl) MDL_PAGES(mdl)
157
158 #define WDM_MAJOR 1
159 #define WDM_MINOR_WIN98 0x00
160 #define WDM_MINOR_WINME 0x05
161 #define WDM_MINOR_WIN2000 0x10
162 #define WDM_MINOR_WINXP 0x20
163 #define WDM_MINOR_WIN2003 0x30
164
165 /*-
166 * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows.
167 * According to the Windows DDK header files, KSPIN_LOCK is defined like this:
168 * typedef ULONG_PTR KSPIN_LOCK;
169 *
170 * From basetsd.h (SDK, Feb. 2003):
171 * typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR;
172 * typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;
173 * typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;
174 *
175 * The keyword __int3264 specifies an integral type that has the following
176 * properties:
177 * + It is 32-bit on 32-bit platforms
178 * + It is 64-bit on 64-bit platforms
179 * + It is 32-bit on the wire for backward compatibility.
180 * It gets truncated on the sending side and extended appropriately
181 * (signed or unsigned) on the receiving side.
182 *
183 * Thus register_t seems the proper mapping onto FreeBSD for spin locks.
184 */
185
186 typedef register_t kspin_lock;
187
188 struct slist_entry {
189 struct slist_entry *sl_next;
190 };
191
192 typedef struct slist_entry slist_entry;
193
194 union slist_header {
195 uint64_t slh_align;
196 struct {
197 struct slist_entry *slh_next;
198 uint16_t slh_depth;
199 uint16_t slh_seq;
200 } slh_list;
201 };
202
203 typedef union slist_header slist_header;
204
205 struct list_entry {
206 struct list_entry *nle_flink;
207 struct list_entry *nle_blink;
208 };
209
210 typedef struct list_entry list_entry;
211
212 #define InitializeListHead(l) \
213 (l)->nle_flink = (l)->nle_blink = (l)
214
215 #define IsListEmpty(h) \
216 ((h)->nle_flink == (h))
217
218 #define RemoveEntryList(e) \
219 do { \
220 list_entry *b; \
221 list_entry *f; \
222 \
223 f = (e)->nle_flink; \
224 b = (e)->nle_blink; \
225 b->nle_flink = f; \
226 f->nle_blink = b; \
227 } while (0)
228
229 /* These two have to be inlined since they return things. */
230
231 static __inline__ list_entry *
232 RemoveHeadList(list_entry *l)
233 {
234 list_entry *f;
235 list_entry *e;
236
237 e = l->nle_flink;
238 f = e->nle_flink;
239 l->nle_flink = f;
240 f->nle_blink = l;
241
242 return (e);
243 }
244
245 static __inline__ list_entry *
246 RemoveTailList(list_entry *l)
247 {
248 list_entry *b;
249 list_entry *e;
250
251 e = l->nle_blink;
252 b = e->nle_blink;
253 l->nle_blink = b;
254 b->nle_flink = l;
255
256 return (e);
257 }
258
259 #define InsertTailList(l, e) \
260 do { \
261 list_entry *b; \
262 \
263 b = l->nle_blink; \
264 e->nle_flink = l; \
265 e->nle_blink = b; \
266 b->nle_flink = (e); \
267 l->nle_blink = (e); \
268 } while (0)
269
270 #define InsertHeadList(l, e) \
271 do { \
272 list_entry *f; \
273 \
274 f = l->nle_flink; \
275 e->nle_flink = f; \
276 e->nle_blink = l; \
277 f->nle_blink = e; \
278 l->nle_flink = e; \
279 } while (0)
280
281 #define CONTAINING_RECORD(addr, type, field) \
282 ((type *)((vm_offset_t)(addr) - (vm_offset_t)(&((type *)0)->field)))
283
284 struct nt_dispatch_header {
285 uint8_t dh_type;
286 uint8_t dh_abs;
287 uint8_t dh_size;
288 uint8_t dh_inserted;
289 int32_t dh_sigstate;
290 list_entry dh_waitlisthead;
291 };
292
293 typedef struct nt_dispatch_header nt_dispatch_header;
294
295 /* Dispatcher object types */
296
297 #define DISP_TYPE_NOTIFICATION_EVENT 0 /* KEVENT */
298 #define DISP_TYPE_SYNCHRONIZATION_EVENT 1 /* KEVENT */
299 #define DISP_TYPE_MUTANT 2 /* KMUTANT/KMUTEX */
300 #define DISP_TYPE_PROCESS 3 /* KPROCESS */
301 #define DISP_TYPE_QUEUE 4 /* KQUEUE */
302 #define DISP_TYPE_SEMAPHORE 5 /* KSEMAPHORE */
303 #define DISP_TYPE_THREAD 6 /* KTHREAD */
304 #define DISP_TYPE_NOTIFICATION_TIMER 8 /* KTIMER */
305 #define DISP_TYPE_SYNCHRONIZATION_TIMER 9 /* KTIMER */
306
307 #define OTYPE_EVENT 0
308 #define OTYPE_MUTEX 1
309 #define OTYPE_THREAD 2
310 #define OTYPE_TIMER 3
311
312 /* Windows dispatcher levels. */
313
314 #define PASSIVE_LEVEL 0
315 #define LOW_LEVEL 0
316 #define APC_LEVEL 1
317 #define DISPATCH_LEVEL 2
318 #define DEVICE_LEVEL (DISPATCH_LEVEL + 1)
319 #define PROFILE_LEVEL 27
320 #define CLOCK1_LEVEL 28
321 #define CLOCK2_LEVEL 28
322 #define IPI_LEVEL 29
323 #define POWER_LEVEL 30
324 #define HIGH_LEVEL 31
325
326 #define SYNC_LEVEL_UP DISPATCH_LEVEL
327 #define SYNC_LEVEL_MP (IPI_LEVEL - 1)
328
329 #define AT_PASSIVE_LEVEL(td) \
330 ((td)->td_proc->p_flag & P_KTHREAD == FALSE)
331
332 #define AT_DISPATCH_LEVEL(td) \
333 ((td)->td_base_pri == PI_REALTIME)
334
335 #define AT_DIRQL_LEVEL(td) \
336 ((td)->td_priority <= PI_NET)
337
338 #define AT_HIGH_LEVEL(td) \
339 ((td)->td_critnest != 0)
340
341 struct nt_objref {
342 nt_dispatch_header no_dh;
343 void *no_obj;
344 TAILQ_ENTRY(nt_objref) link;
345 };
346
347 TAILQ_HEAD(nt_objref_head, nt_objref);
348
349 typedef struct nt_objref nt_objref;
350
351 #define EVENT_TYPE_NOTIFY 0
352 #define EVENT_TYPE_SYNC 1
353
354 /*
355 * We need to use the timeout()/untimeout() API for ktimers
356 * since timers can be initialized, but not destroyed (so
357 * malloc()ing our own callout structures would mean a leak,
358 * since there'd be no way to free() them). This means we
359 * need to use struct callout_handle, which is really just a
360 * pointer. To make it easier to deal with, we use a union
361 * to overlay the callout_handle over the k_timerlistentry.
362 * The latter is a list_entry, which is two pointers, so
363 * there's enough space available to hide a callout_handle
364 * there.
365 */
366
367 struct ktimer {
368 nt_dispatch_header k_header;
369 uint64_t k_duetime;
370 union {
371 list_entry k_timerlistentry;
372 struct callout *k_callout;
373 } u;
374 void *k_dpc;
375 uint32_t k_period;
376 };
377
378 #define k_timerlistentry u.k_timerlistentry
379 #define k_callout u.k_callout
380
381 typedef struct ktimer ktimer;
382
383 struct nt_kevent {
384 nt_dispatch_header k_header;
385 };
386
387 typedef struct nt_kevent nt_kevent;
388
389 /* Kernel defered procedure call (i.e. timer callback) */
390
391 struct kdpc;
392 typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *);
393
394 struct kdpc {
395 uint16_t k_type;
396 uint8_t k_num; /* CPU number */
397 uint8_t k_importance; /* priority */
398 list_entry k_dpclistentry;
399 void *k_deferedfunc;
400 void *k_deferredctx;
401 void *k_sysarg1;
402 void *k_sysarg2;
403 void *k_lock;
404 };
405
406 #define KDPC_IMPORTANCE_LOW 0
407 #define KDPC_IMPORTANCE_MEDIUM 1
408 #define KDPC_IMPORTANCE_HIGH 2
409
410 #define KDPC_CPU_DEFAULT 255
411
412 typedef struct kdpc kdpc;
413
414 /*
415 * Note: the acquisition count is BSD-specific. The Microsoft
416 * documentation says that mutexes can be acquired recursively
417 * by a given thread, but that you must release the mutex as
418 * many times as you acquired it before it will be set to the
419 * signalled state (i.e. before any other threads waiting on
420 * the object will be woken up). However the Windows KMUTANT
421 * structure has no field for keeping track of the number of
422 * acquisitions, so we need to add one ourselves. As long as
423 * driver code treats the mutex as opaque, we should be ok.
424 */
425 struct kmutant {
426 nt_dispatch_header km_header;
427 list_entry km_listentry;
428 void *km_ownerthread;
429 uint8_t km_abandoned;
430 uint8_t km_apcdisable;
431 };
432
433 typedef struct kmutant kmutant;
434
435 #define LOOKASIDE_DEPTH 256
436
437 struct general_lookaside {
438 slist_header gl_listhead;
439 uint16_t gl_depth;
440 uint16_t gl_maxdepth;
441 uint32_t gl_totallocs;
442 union {
443 uint32_t gl_allocmisses;
444 uint32_t gl_allochits;
445 } u_a;
446 uint32_t gl_totalfrees;
447 union {
448 uint32_t gl_freemisses;
449 uint32_t gl_freehits;
450 } u_m;
451 uint32_t gl_type;
452 uint32_t gl_tag;
453 uint32_t gl_size;
454 void *gl_allocfunc;
455 void *gl_freefunc;
456 list_entry gl_listent;
457 uint32_t gl_lasttotallocs;
458 union {
459 uint32_t gl_lastallocmisses;
460 uint32_t gl_lastallochits;
461 } u_l;
462 uint32_t gl_rsvd[2];
463 };
464
465 typedef struct general_lookaside general_lookaside;
466
467 struct npaged_lookaside_list {
468 general_lookaside nll_l;
469 #ifdef __i386__
470 kspin_lock nll_obsoletelock;
471 #endif
472 };
473
474 typedef struct npaged_lookaside_list npaged_lookaside_list;
475 typedef struct npaged_lookaside_list paged_lookaside_list;
476
477 typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t);
478 typedef void (*lookaside_free_func)(void *);
479
480 struct irp;
481
482 struct kdevice_qentry {
483 list_entry kqe_devlistent;
484 uint32_t kqe_sortkey;
485 uint8_t kqe_inserted;
486 };
487
488 typedef struct kdevice_qentry kdevice_qentry;
489
490 struct kdevice_queue {
491 uint16_t kq_type;
492 uint16_t kq_size;
493 list_entry kq_devlisthead;
494 kspin_lock kq_lock;
495 uint8_t kq_busy;
496 };
497
498 typedef struct kdevice_queue kdevice_queue;
499
500 struct wait_ctx_block {
501 kdevice_qentry wcb_waitqueue;
502 void *wcb_devfunc;
503 void *wcb_devctx;
504 uint32_t wcb_mapregcnt;
505 void *wcb_devobj;
506 void *wcb_curirp;
507 void *wcb_bufchaindpc;
508 };
509
510 typedef struct wait_ctx_block wait_ctx_block;
511
512 struct wait_block {
513 list_entry wb_waitlist;
514 void *wb_kthread;
515 nt_dispatch_header *wb_object;
516 struct wait_block *wb_next;
517 #ifdef notdef
518 uint16_t wb_waitkey;
519 uint16_t wb_waittype;
520 #endif
521 uint8_t wb_waitkey;
522 uint8_t wb_waittype;
523 uint8_t wb_awakened;
524 uint8_t wb_oldpri;
525 };
526
527 typedef struct wait_block wait_block;
528
529 #define wb_ext wb_kthread
530
531 #define THREAD_WAIT_OBJECTS 3
532 #define MAX_WAIT_OBJECTS 64
533
534 #define WAITTYPE_ALL 0
535 #define WAITTYPE_ANY 1
536
537 #define WAITKEY_VALID 0x8000
538
539 /* kthread priority */
540 #define LOW_PRIORITY 0
541 #define LOW_REALTIME_PRIORITY 16
542 #define HIGH_PRIORITY 31
543
544 struct thread_context {
545 void *tc_thrctx;
546 void *tc_thrfunc;
547 };
548
549 typedef struct thread_context thread_context;
550
551 /* Forward declaration */
552 struct driver_object;
553 struct devobj_extension;
554
555 struct driver_extension {
556 struct driver_object *dre_driverobj;
557 void *dre_adddevicefunc;
558 uint32_t dre_reinitcnt;
559 unicode_string dre_srvname;
560
561 /*
562 * Drivers are allowed to add one or more custom extensions
563 * to the driver object, but there's no special pointer
564 * for them. Hang them off here for now.
565 */
566
567 list_entry dre_usrext;
568 };
569
570 typedef struct driver_extension driver_extension;
571
572 struct custom_extension {
573 list_entry ce_list;
574 void *ce_clid;
575 };
576
577 typedef struct custom_extension custom_extension;
578
579 /*
580 * The KINTERRUPT structure in Windows is opaque to drivers.
581 * We define our own custom version with things we need.
582 */
583
584 struct kinterrupt {
585 list_entry ki_list;
586 device_t ki_dev;
587 int ki_rid;
588 void *ki_cookie;
589 struct resource *ki_irq;
590 kspin_lock ki_lock_priv;
591 kspin_lock *ki_lock;
592 void *ki_svcfunc;
593 void *ki_svcctx;
594 };
595
596 typedef struct kinterrupt kinterrupt;
597
598 /*
599 * In Windows, there are Physical Device Objects (PDOs) and
600 * Functional Device Objects (FDOs). Physical Device Objects are
601 * created and maintained by bus drivers. For example, the PCI
602 * bus driver might detect two PCI ethernet cards on a given
603 * bus. The PCI bus driver will then allocate two device_objects
604 * for its own internal bookeeping purposes. This is analagous
605 * to the device_t that the FreeBSD PCI code allocates and passes
606 * into each PCI driver's probe and attach routines.
607 *
608 * When an ethernet driver claims one of the ethernet cards
609 * on the bus, it will create its own device_object. This is
610 * the Functional Device Object. This object is analagous to the
611 * device-specific softc structure.
612 */
613
614 struct device_object {
615 uint16_t do_type;
616 uint16_t do_size;
617 uint32_t do_refcnt;
618 struct driver_object *do_drvobj;
619 struct device_object *do_nextdev;
620 struct device_object *do_attacheddev;
621 struct irp *do_currirp;
622 void *do_iotimer;
623 uint32_t do_flags;
624 uint32_t do_characteristics;
625 void *do_vpb;
626 void *do_devext;
627 uint32_t do_devtype;
628 uint8_t do_stacksize;
629 union {
630 list_entry do_listent;
631 wait_ctx_block do_wcb;
632 } queue;
633 uint32_t do_alignreq;
634 kdevice_queue do_devqueue;
635 struct kdpc do_dpc;
636 uint32_t do_activethreads;
637 void *do_securitydesc;
638 struct nt_kevent do_devlock;
639 uint16_t do_sectorsz;
640 uint16_t do_spare1;
641 struct devobj_extension *do_devobj_ext;
642 void *do_rsvd;
643 };
644
645 typedef struct device_object device_object;
646
647 struct devobj_extension {
648 uint16_t dve_type;
649 uint16_t dve_size;
650 device_object *dve_devobj;
651 };
652
653 typedef struct devobj_extension devobj_extension;
654
655 /* Device object flags */
656
657 #define DO_VERIFY_VOLUME 0x00000002
658 #define DO_BUFFERED_IO 0x00000004
659 #define DO_EXCLUSIVE 0x00000008
660 #define DO_DIRECT_IO 0x00000010
661 #define DO_MAP_IO_BUFFER 0x00000020
662 #define DO_DEVICE_HAS_NAME 0x00000040
663 #define DO_DEVICE_INITIALIZING 0x00000080
664 #define DO_SYSTEM_BOOT_PARTITION 0x00000100
665 #define DO_LONG_TERM_REQUESTS 0x00000200
666 #define DO_NEVER_LAST_DEVICE 0x00000400
667 #define DO_SHUTDOWN_REGISTERED 0x00000800
668 #define DO_BUS_ENUMERATED_DEVICE 0x00001000
669 #define DO_POWER_PAGABLE 0x00002000
670 #define DO_POWER_INRUSH 0x00004000
671 #define DO_LOW_PRIORITY_FILESYSTEM 0x00010000
672
673 /* Priority boosts */
674
675 #define IO_NO_INCREMENT 0
676 #define IO_CD_ROM_INCREMENT 1
677 #define IO_DISK_INCREMENT 1
678 #define IO_KEYBOARD_INCREMENT 6
679 #define IO_MAILSLOT_INCREMENT 2
680 #define IO_MOUSE_INCREMENT 6
681 #define IO_NAMED_PIPE_INCREMENT 2
682 #define IO_NETWORK_INCREMENT 2
683 #define IO_PARALLEL_INCREMENT 1
684 #define IO_SERIAL_INCREMENT 2
685 #define IO_SOUND_INCREMENT 8
686 #define IO_VIDEO_INCREMENT 1
687
688 /* IRP major codes */
689
690 #define IRP_MJ_CREATE 0x00
691 #define IRP_MJ_CREATE_NAMED_PIPE 0x01
692 #define IRP_MJ_CLOSE 0x02
693 #define IRP_MJ_READ 0x03
694 #define IRP_MJ_WRITE 0x04
695 #define IRP_MJ_QUERY_INFORMATION 0x05
696 #define IRP_MJ_SET_INFORMATION 0x06
697 #define IRP_MJ_QUERY_EA 0x07
698 #define IRP_MJ_SET_EA 0x08
699 #define IRP_MJ_FLUSH_BUFFERS 0x09
700 #define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a
701 #define IRP_MJ_SET_VOLUME_INFORMATION 0x0b
702 #define IRP_MJ_DIRECTORY_CONTROL 0x0c
703 #define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d
704 #define IRP_MJ_DEVICE_CONTROL 0x0e
705 #define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f
706 #define IRP_MJ_SHUTDOWN 0x10
707 #define IRP_MJ_LOCK_CONTROL 0x11
708 #define IRP_MJ_CLEANUP 0x12
709 #define IRP_MJ_CREATE_MAILSLOT 0x13
710 #define IRP_MJ_QUERY_SECURITY 0x14
711 #define IRP_MJ_SET_SECURITY 0x15
712 #define IRP_MJ_POWER 0x16
713 #define IRP_MJ_SYSTEM_CONTROL 0x17
714 #define IRP_MJ_DEVICE_CHANGE 0x18
715 #define IRP_MJ_QUERY_QUOTA 0x19
716 #define IRP_MJ_SET_QUOTA 0x1a
717 #define IRP_MJ_PNP 0x1b
718 #define IRP_MJ_PNP_POWER IRP_MJ_PNP // Obsolete....
719 #define IRP_MJ_MAXIMUM_FUNCTION 0x1b
720 #define IRP_MJ_SCSI IRP_MJ_INTERNAL_DEVICE_CONTROL
721
722 /* IRP minor codes */
723
724 #define IRP_MN_QUERY_DIRECTORY 0x01
725 #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02
726 #define IRP_MN_USER_FS_REQUEST 0x00
727
728 #define IRP_MN_MOUNT_VOLUME 0x01
729 #define IRP_MN_VERIFY_VOLUME 0x02
730 #define IRP_MN_LOAD_FILE_SYSTEM 0x03
731 #define IRP_MN_TRACK_LINK 0x04
732 #define IRP_MN_KERNEL_CALL 0x04
733
734 #define IRP_MN_LOCK 0x01
735 #define IRP_MN_UNLOCK_SINGLE 0x02
736 #define IRP_MN_UNLOCK_ALL 0x03
737 #define IRP_MN_UNLOCK_ALL_BY_KEY 0x04
738
739 #define IRP_MN_NORMAL 0x00
740 #define IRP_MN_DPC 0x01
741 #define IRP_MN_MDL 0x02
742 #define IRP_MN_COMPLETE 0x04
743 #define IRP_MN_COMPRESSED 0x08
744
745 #define IRP_MN_MDL_DPC (IRP_MN_MDL | IRP_MN_DPC)
746 #define IRP_MN_COMPLETE_MDL (IRP_MN_COMPLETE | IRP_MN_MDL)
747 #define IRP_MN_COMPLETE_MDL_DPC (IRP_MN_COMPLETE_MDL | IRP_MN_DPC)
748
749 #define IRP_MN_SCSI_CLASS 0x01
750
751 #define IRP_MN_START_DEVICE 0x00
752 #define IRP_MN_QUERY_REMOVE_DEVICE 0x01
753 #define IRP_MN_REMOVE_DEVICE 0x02
754 #define IRP_MN_CANCEL_REMOVE_DEVICE 0x03
755 #define IRP_MN_STOP_DEVICE 0x04
756 #define IRP_MN_QUERY_STOP_DEVICE 0x05
757 #define IRP_MN_CANCEL_STOP_DEVICE 0x06
758
759 #define IRP_MN_QUERY_DEVICE_RELATIONS 0x07
760 #define IRP_MN_QUERY_INTERFACE 0x08
761 #define IRP_MN_QUERY_CAPABILITIES 0x09
762 #define IRP_MN_QUERY_RESOURCES 0x0A
763 #define IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B
764 #define IRP_MN_QUERY_DEVICE_TEXT 0x0C
765 #define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D
766
767 #define IRP_MN_READ_CONFIG 0x0F
768 #define IRP_MN_WRITE_CONFIG 0x10
769 #define IRP_MN_EJECT 0x11
770 #define IRP_MN_SET_LOCK 0x12
771 #define IRP_MN_QUERY_ID 0x13
772 #define IRP_MN_QUERY_PNP_DEVICE_STATE 0x14
773 #define IRP_MN_QUERY_BUS_INFORMATION 0x15
774 #define IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16
775 #define IRP_MN_SURPRISE_REMOVAL 0x17
776 #define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18
777
778 #define IRP_MN_WAIT_WAKE 0x00
779 #define IRP_MN_POWER_SEQUENCE 0x01
780 #define IRP_MN_SET_POWER 0x02
781 #define IRP_MN_QUERY_POWER 0x03
782
783 #define IRP_MN_QUERY_ALL_DATA 0x00
784 #define IRP_MN_QUERY_SINGLE_INSTANCE 0x01
785 #define IRP_MN_CHANGE_SINGLE_INSTANCE 0x02
786 #define IRP_MN_CHANGE_SINGLE_ITEM 0x03
787 #define IRP_MN_ENABLE_EVENTS 0x04
788 #define IRP_MN_DISABLE_EVENTS 0x05
789 #define IRP_MN_ENABLE_COLLECTION 0x06
790 #define IRP_MN_DISABLE_COLLECTION 0x07
791 #define IRP_MN_REGINFO 0x08
792 #define IRP_MN_EXECUTE_METHOD 0x09
793 #define IRP_MN_REGINFO_EX 0x0b
794
795 /* IRP flags */
796
797 #define IRP_NOCACHE 0x00000001
798 #define IRP_PAGING_IO 0x00000002
799 #define IRP_MOUNT_COMPLETION 0x00000002
800 #define IRP_SYNCHRONOUS_API 0x00000004
801 #define IRP_ASSOCIATED_IRP 0x00000008
802 #define IRP_BUFFERED_IO 0x00000010
803 #define IRP_DEALLOCATE_BUFFER 0x00000020
804 #define IRP_INPUT_OPERATION 0x00000040
805 #define IRP_SYNCHRONOUS_PAGING_IO 0x00000040
806 #define IRP_CREATE_OPERATION 0x00000080
807 #define IRP_READ_OPERATION 0x00000100
808 #define IRP_WRITE_OPERATION 0x00000200
809 #define IRP_CLOSE_OPERATION 0x00000400
810 #define IRP_DEFER_IO_COMPLETION 0x00000800
811 #define IRP_OB_QUERY_NAME 0x00001000
812 #define IRP_HOLD_DEVICE_QUEUE 0x00002000
813 #define IRP_RETRY_IO_COMPLETION 0x00004000
814 #define IRP_CLASS_CACHE_OPERATION 0x00008000
815 #define IRP_SET_USER_EVENT IRP_CLOSE_OPERATION
816
817 /* IRP I/O control flags */
818
819 #define IRP_QUOTA_CHARGED 0x01
820 #define IRP_ALLOCATED_MUST_SUCCEED 0x02
821 #define IRP_ALLOCATED_FIXED_SIZE 0x04
822 #define IRP_LOOKASIDE_ALLOCATION 0x08
823
824 /* I/O method types */
825
826 #define METHOD_BUFFERED 0
827 #define METHOD_IN_DIRECT 1
828 #define METHOD_OUT_DIRECT 2
829 #define METHOD_NEITHER 3
830
831 /* File access types */
832
833 #define FILE_ANY_ACCESS 0x0000
834 #define FILE_SPECIAL_ACCESS FILE_ANY_ACCESS
835 #define FILE_READ_ACCESS 0x0001
836 #define FILE_WRITE_ACCESS 0x0002
837
838 /* Recover I/O access method from IOCTL code. */
839
840 #define IO_METHOD(x) ((x) & 0xFFFFFFFC)
841
842 /* Recover function code from IOCTL code */
843
844 #define IO_FUNC(x) (((x) & 0x7FFC) >> 2)
845
846 /* Macro to construct an IOCTL code. */
847
848 #define IOCTL_CODE(dev, func, iomethod, acc) \
849 ((dev) << 16) | (acc << 14) | (func << 2) | (iomethod))
850
851
852 struct io_status_block {
853 union {
854 uint32_t isb_status;
855 void *isb_ptr;
856 } u;
857 register_t isb_info;
858 };
859 #define isb_status u.isb_status
860 #define isb_ptr u.isb_ptr
861
862 typedef struct io_status_block io_status_block;
863
864 struct kapc {
865 uint16_t apc_type;
866 uint16_t apc_size;
867 uint32_t apc_spare0;
868 void *apc_thread;
869 list_entry apc_list;
870 void *apc_kernfunc;
871 void *apc_rundownfunc;
872 void *apc_normalfunc;
873 void *apc_normctx;
874 void *apc_sysarg1;
875 void *apc_sysarg2;
876 uint8_t apc_stateidx;
877 uint8_t apc_cpumode;
878 uint8_t apc_inserted;
879 };
880
881 typedef struct kapc kapc;
882
883 typedef uint32_t (*completion_func)(device_object *,
884 struct irp *, void *);
885 typedef uint32_t (*cancel_func)(device_object *,
886 struct irp *);
887
888 struct io_stack_location {
889 uint8_t isl_major;
890 uint8_t isl_minor;
891 uint8_t isl_flags;
892 uint8_t isl_ctl;
893
894 /*
895 * There's a big-ass union here in the actual Windows
896 * definition of the stucture, but it contains stuff
897 * that doesn't really apply to BSD, and defining it
898 * all properly would require duplicating over a dozen
899 * other structures that we'll never use. Since the
900 * io_stack_location structure is opaque to drivers
901 * anyway, I'm not going to bother with the extra crap.
902 */
903
904 union {
905 struct {
906 uint32_t isl_len;
907 uint32_t *isl_key;
908 uint64_t isl_byteoff;
909 } isl_read;
910 struct {
911 uint32_t isl_len;
912 uint32_t *isl_key;
913 uint64_t isl_byteoff;
914 } isl_write;
915 struct {
916 uint32_t isl_obuflen;
917 uint32_t isl_ibuflen;
918 uint32_t isl_iocode;
919 void *isl_type3ibuf;
920 } isl_ioctl;
921 struct {
922 void *isl_arg1;
923 void *isl_arg2;
924 void *isl_arg3;
925 void *isl_arg4;
926 } isl_others;
927 } isl_parameters __attribute__((packed));
928
929 void *isl_devobj;
930 void *isl_fileobj;
931 completion_func isl_completionfunc;
932 void *isl_completionctx;
933 };
934
935 typedef struct io_stack_location io_stack_location;
936
937 /* Stack location control flags */
938
939 #define SL_PENDING_RETURNED 0x01
940 #define SL_INVOKE_ON_CANCEL 0x20
941 #define SL_INVOKE_ON_SUCCESS 0x40
942 #define SL_INVOKE_ON_ERROR 0x80
943
944 struct irp {
945 uint16_t irp_type;
946 uint16_t irp_size;
947 mdl *irp_mdl;
948 uint32_t irp_flags;
949 union {
950 struct irp *irp_master;
951 uint32_t irp_irpcnt;
952 void *irp_sysbuf;
953 } irp_assoc;
954 list_entry irp_thlist;
955 io_status_block irp_iostat;
956 uint8_t irp_reqmode;
957 uint8_t irp_pendingreturned;
958 uint8_t irp_stackcnt;
959 uint8_t irp_currentstackloc;
960 uint8_t irp_cancel;
961 uint8_t irp_cancelirql;
962 uint8_t irp_apcenv;
963 uint8_t irp_allocflags;
964 io_status_block *irp_usriostat;
965 nt_kevent *irp_usrevent;
966 union {
967 struct {
968 void *irp_apcfunc;
969 void *irp_apcctx;
970 } irp_asyncparms;
971 uint64_t irp_allocsz;
972 } irp_overlay;
973 cancel_func irp_cancelfunc;
974 void *irp_userbuf;
975
976 /* Windows kernel info */
977
978 union {
979 struct {
980 union {
981 kdevice_qentry irp_dqe;
982 struct {
983 |