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$ 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 */ 45struct unicode_string { 46 uint16_t us_len; 47 uint16_t us_maxlen; 48 uint16_t *us_buf; 49}; 50 51typedef struct unicode_string unicode_string; 52 53struct ansi_string { 54 uint16_t as_len; 55 uint16_t as_maxlen; 56 char *as_buf; 57}; 58 59typedef 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 84struct 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 95typedef 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 165enum nt_caching_type { 166 MmNonCached = 0, 167 MmCached = 1, 168 MmWriteCombined = 2, 169 MmHardwareCoherentCached = 3, 170 MmNonCachedUnordered = 4, 171 MmUSWCCached = 5, 172 MmMaximumCacheType = 6 173}; 174 175/*- 176 * The ndis_kspin_lock type is called KSPIN_LOCK in MS-Windows. 177 * According to the Windows DDK header files, KSPIN_LOCK is defined like this: 178 * typedef ULONG_PTR KSPIN_LOCK; 179 * 180 * From basetsd.h (SDK, Feb. 2003): 181 * typedef [public] unsigned __int3264 ULONG_PTR, *PULONG_PTR; 182 * typedef unsigned __int64 ULONG_PTR, *PULONG_PTR; 183 * typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR; 184 * 185 * The keyword __int3264 specifies an integral type that has the following 186 * properties: 187 * + It is 32-bit on 32-bit platforms 188 * + It is 64-bit on 64-bit platforms 189 * + It is 32-bit on the wire for backward compatibility. 190 * It gets truncated on the sending side and extended appropriately 191 * (signed or unsigned) on the receiving side. 192 * 193 * Thus register_t seems the proper mapping onto FreeBSD for spin locks. 194 */ 195 196typedef register_t kspin_lock; 197 198struct slist_entry { 199 struct slist_entry *sl_next; 200}; 201 202typedef struct slist_entry slist_entry; 203 204union slist_header { 205 uint64_t slh_align; 206 struct { 207 struct slist_entry *slh_next; 208 uint16_t slh_depth; 209 uint16_t slh_seq; 210 } slh_list; 211}; 212 213typedef union slist_header slist_header; 214 215struct list_entry { 216 struct list_entry *nle_flink; 217 struct list_entry *nle_blink; 218}; 219 220typedef struct list_entry list_entry; 221 222#define InitializeListHead(l) \ 223 (l)->nle_flink = (l)->nle_blink = (l) 224 225#define IsListEmpty(h) \ 226 ((h)->nle_flink == (h)) 227 228#define RemoveEntryList(e) \ 229 do { \ 230 list_entry *b; \ 231 list_entry *f; \ 232 \ 233 f = (e)->nle_flink; \ 234 b = (e)->nle_blink; \ 235 b->nle_flink = f; \ 236 f->nle_blink = b; \ 237 } while (0) 238 239/* These two have to be inlined since they return things. */ 240 241static __inline__ list_entry * 242RemoveHeadList(list_entry *l) 243{ 244 list_entry *f; 245 list_entry *e; 246 247 e = l->nle_flink; 248 f = e->nle_flink; 249 l->nle_flink = f; 250 f->nle_blink = l; 251 252 return (e); 253} 254 255static __inline__ list_entry * 256RemoveTailList(list_entry *l) 257{ 258 list_entry *b; 259 list_entry *e; 260 261 e = l->nle_blink; 262 b = e->nle_blink; 263 l->nle_blink = b; 264 b->nle_flink = l; 265 266 return (e); 267} 268 269#define InsertTailList(l, e) \ 270 do { \ 271 list_entry *b; \ 272 \ 273 b = l->nle_blink; \ 274 e->nle_flink = l; \ 275 e->nle_blink = b; \ 276 b->nle_flink = (e); \ 277 l->nle_blink = (e); \ 278 } while (0) 279 280#define InsertHeadList(l, e) \ 281 do { \ 282 list_entry *f; \ 283 \ 284 f = l->nle_flink; \ 285 e->nle_flink = f; \ 286 e->nle_blink = l; \ 287 f->nle_blink = e; \ 288 l->nle_flink = e; \ 289 } while (0) 290 291#define CONTAINING_RECORD(addr, type, field) \ 292 ((type *)((vm_offset_t)(addr) - (vm_offset_t)(&((type *)0)->field))) 293 294struct nt_dispatch_header { 295 uint8_t dh_type; 296 uint8_t dh_abs; 297 uint8_t dh_size; 298 uint8_t dh_inserted; 299 int32_t dh_sigstate; 300 list_entry dh_waitlisthead; 301}; 302 303typedef struct nt_dispatch_header nt_dispatch_header; 304 305/* Dispatcher object types */ 306 307#define DISP_TYPE_NOTIFICATION_EVENT 0 /* KEVENT */ 308#define DISP_TYPE_SYNCHRONIZATION_EVENT 1 /* KEVENT */ 309#define DISP_TYPE_MUTANT 2 /* KMUTANT/KMUTEX */ 310#define DISP_TYPE_PROCESS 3 /* KPROCESS */ 311#define DISP_TYPE_QUEUE 4 /* KQUEUE */ 312#define DISP_TYPE_SEMAPHORE 5 /* KSEMAPHORE */ 313#define DISP_TYPE_THREAD 6 /* KTHREAD */ 314#define DISP_TYPE_NOTIFICATION_TIMER 8 /* KTIMER */ 315#define DISP_TYPE_SYNCHRONIZATION_TIMER 9 /* KTIMER */ 316 317#define OTYPE_EVENT 0 318#define OTYPE_MUTEX 1 319#define OTYPE_THREAD 2 320#define OTYPE_TIMER 3 321 322/* Windows dispatcher levels. */ 323 324#define PASSIVE_LEVEL 0 325#define LOW_LEVEL 0 326#define APC_LEVEL 1 327#define DISPATCH_LEVEL 2 328#define DEVICE_LEVEL (DISPATCH_LEVEL + 1) 329#define PROFILE_LEVEL 27 330#define CLOCK1_LEVEL 28 331#define CLOCK2_LEVEL 28 332#define IPI_LEVEL 29 333#define POWER_LEVEL 30 334#define HIGH_LEVEL 31 335 336#define SYNC_LEVEL_UP DISPATCH_LEVEL 337#define SYNC_LEVEL_MP (IPI_LEVEL - 1) 338 339#define AT_PASSIVE_LEVEL(td) \ 340 ((td)->td_proc->p_flag & P_KTHREAD == FALSE) 341 342#define AT_DISPATCH_LEVEL(td) \ 343 ((td)->td_base_pri == PI_REALTIME) 344 345#define AT_DIRQL_LEVEL(td) \ 346 ((td)->td_priority <= PI_NET) 347 348#define AT_HIGH_LEVEL(td) \ 349 ((td)->td_critnest != 0) 350 351struct nt_objref { 352 nt_dispatch_header no_dh; 353 void *no_obj; 354 TAILQ_ENTRY(nt_objref) link; 355}; 356 357TAILQ_HEAD(nt_objref_head, nt_objref); 358 359typedef struct nt_objref nt_objref; 360 361#define EVENT_TYPE_NOTIFY 0 362#define EVENT_TYPE_SYNC 1 363 364/* 365 * We need to use the timeout()/untimeout() API for ktimers 366 * since timers can be initialized, but not destroyed (so 367 * malloc()ing our own callout structures would mean a leak, 368 * since there'd be no way to free() them). This means we 369 * need to use struct callout_handle, which is really just a 370 * pointer. To make it easier to deal with, we use a union 371 * to overlay the callout_handle over the k_timerlistentry. 372 * The latter is a list_entry, which is two pointers, so 373 * there's enough space available to hide a callout_handle 374 * there. 375 */ 376 377struct ktimer { 378 nt_dispatch_header k_header; 379 uint64_t k_duetime; 380 union { 381 list_entry k_timerlistentry; 382 struct callout *k_callout; 383 } u; 384 void *k_dpc; 385 uint32_t k_period; 386}; 387 388#define k_timerlistentry u.k_timerlistentry 389#define k_callout u.k_callout 390 391typedef struct ktimer ktimer; 392 393struct nt_kevent { 394 nt_dispatch_header k_header; 395}; 396 397typedef struct nt_kevent nt_kevent; 398 399/* Kernel defered procedure call (i.e. timer callback) */ 400 401struct kdpc; 402typedef void (*kdpc_func)(struct kdpc *, void *, void *, void *); 403 404struct kdpc { 405 uint16_t k_type; 406 uint8_t k_num; /* CPU number */ 407 uint8_t k_importance; /* priority */ 408 list_entry k_dpclistentry; 409 void *k_deferedfunc; 410 void *k_deferredctx; 411 void *k_sysarg1; 412 void *k_sysarg2; 413 void *k_lock; 414}; 415 416#define KDPC_IMPORTANCE_LOW 0 417#define KDPC_IMPORTANCE_MEDIUM 1 418#define KDPC_IMPORTANCE_HIGH 2 419 420#define KDPC_CPU_DEFAULT 255 421 422typedef struct kdpc kdpc; 423 424/* 425 * Note: the acquisition count is BSD-specific. The Microsoft 426 * documentation says that mutexes can be acquired recursively 427 * by a given thread, but that you must release the mutex as 428 * many times as you acquired it before it will be set to the 429 * signalled state (i.e. before any other threads waiting on 430 * the object will be woken up). However the Windows KMUTANT 431 * structure has no field for keeping track of the number of 432 * acquisitions, so we need to add one ourselves. As long as 433 * driver code treats the mutex as opaque, we should be ok. 434 */ 435struct kmutant { 436 nt_dispatch_header km_header; 437 list_entry km_listentry; 438 void *km_ownerthread; 439 uint8_t km_abandoned; 440 uint8_t km_apcdisable; 441}; 442 443typedef struct kmutant kmutant; 444 445#define LOOKASIDE_DEPTH 256 446 447struct general_lookaside { 448 slist_header gl_listhead; 449 uint16_t gl_depth; 450 uint16_t gl_maxdepth; 451 uint32_t gl_totallocs; 452 union { 453 uint32_t gl_allocmisses; 454 uint32_t gl_allochits; 455 } u_a; 456 uint32_t gl_totalfrees; 457 union { 458 uint32_t gl_freemisses; 459 uint32_t gl_freehits; 460 } u_m; 461 uint32_t gl_type; 462 uint32_t gl_tag; 463 uint32_t gl_size; 464 void *gl_allocfunc; 465 void *gl_freefunc; 466 list_entry gl_listent; 467 uint32_t gl_lasttotallocs; 468 union { 469 uint32_t gl_lastallocmisses; 470 uint32_t gl_lastallochits; 471 } u_l; 472 uint32_t gl_rsvd[2]; 473}; 474 475typedef struct general_lookaside general_lookaside; 476 477struct npaged_lookaside_list { 478 general_lookaside nll_l; 479#ifdef __i386__ 480 kspin_lock nll_obsoletelock; 481#endif 482}; 483 484typedef struct npaged_lookaside_list npaged_lookaside_list; 485typedef struct npaged_lookaside_list paged_lookaside_list; 486 487typedef void * (*lookaside_alloc_func)(uint32_t, size_t, uint32_t); 488typedef void (*lookaside_free_func)(void *); 489 490struct irp; 491 492struct kdevice_qentry { 493 list_entry kqe_devlistent; 494 uint32_t kqe_sortkey; 495 uint8_t kqe_inserted; 496}; 497 498typedef struct kdevice_qentry kdevice_qentry; 499 500struct kdevice_queue { 501 uint16_t kq_type; 502 uint16_t kq_size; 503 list_entry kq_devlisthead; 504 kspin_lock kq_lock; 505 uint8_t kq_busy; 506}; 507 508typedef struct kdevice_queue kdevice_queue; 509 510struct wait_ctx_block { 511 kdevice_qentry wcb_waitqueue; 512 void *wcb_devfunc; 513 void *wcb_devctx; 514 uint32_t wcb_mapregcnt; 515 void *wcb_devobj; 516 void *wcb_curirp; 517 void *wcb_bufchaindpc; 518}; 519 520typedef struct wait_ctx_block wait_ctx_block; 521 522struct wait_block { 523 list_entry wb_waitlist; 524 void *wb_kthread; 525 nt_dispatch_header *wb_object; 526 struct wait_block *wb_next; 527#ifdef notdef 528 uint16_t wb_waitkey; 529 uint16_t wb_waittype; 530#endif 531 uint8_t wb_waitkey; 532 uint8_t wb_waittype; 533 uint8_t wb_awakened; 534 uint8_t wb_oldpri; 535}; 536 537typedef struct wait_block wait_block; 538 539#define wb_ext wb_kthread 540 541#define THREAD_WAIT_OBJECTS 3 542#define MAX_WAIT_OBJECTS 64 543 544#define WAITTYPE_ALL 0 545#define WAITTYPE_ANY 1 546 547#define WAITKEY_VALID 0x8000 548 549/* kthread priority */ 550#define LOW_PRIORITY 0 551#define LOW_REALTIME_PRIORITY 16 552#define HIGH_PRIORITY 31 553 554struct thread_context { 555 void *tc_thrctx; 556 void *tc_thrfunc; 557}; 558 559typedef struct thread_context thread_context; 560 561/* Forward declaration */ 562struct driver_object; 563struct devobj_extension; 564 565struct driver_extension { 566 struct driver_object *dre_driverobj; 567 void *dre_adddevicefunc; 568 uint32_t dre_reinitcnt; 569 unicode_string dre_srvname; 570 571 /* 572 * Drivers are allowed to add one or more custom extensions 573 * to the driver object, but there's no special pointer 574 * for them. Hang them off here for now. 575 */ 576 577 list_entry dre_usrext; 578}; 579 580typedef struct driver_extension driver_extension; 581 582struct custom_extension { 583 list_entry ce_list; 584 void *ce_clid; 585}; 586 587typedef struct custom_extension custom_extension; 588 589/* 590 * The KINTERRUPT structure in Windows is opaque to drivers. 591 * We define our own custom version with things we need. 592 */ 593 594struct kinterrupt { 595 list_entry ki_list; 596 device_t ki_dev; 597 int ki_rid; 598 void *ki_cookie; 599 struct resource *ki_irq; 600 kspin_lock ki_lock_priv; 601 kspin_lock *ki_lock; 602 void *ki_svcfunc; 603 void *ki_svcctx; 604}; 605 606typedef struct kinterrupt kinterrupt; 607 608struct ksystem_time { 609 uint32_t low_part; 610 int32_t high1_time; 611 int32_t high2_time; 612}; 613 614enum nt_product_type { 615 NT_PRODUCT_WIN_NT = 1, 616 NT_PRODUCT_LAN_MAN_NT, 617 NT_PRODUCT_SERVER 618}; 619 620enum alt_arch_type { 621 STANDARD_DESIGN, 622 NEC98x86, 623 END_ALTERNATIVES 624}; 625 626struct kuser_shared_data { 627 uint32_t tick_count; 628 uint32_t tick_count_multiplier; 629 volatile struct ksystem_time interrupt_time; 630 volatile struct ksystem_time system_time; 631 volatile struct ksystem_time time_zone_bias; 632 uint16_t image_number_low; 633 uint16_t image_number_high; 634 int16_t nt_system_root[260]; 635 uint32_t max_stack_trace_depth; 636 uint32_t crypto_exponent; 637 uint32_t time_zone_id; 638 uint32_t large_page_min; 639 uint32_t reserved2[7]; 640 enum nt_product_type nt_product_type; 641 uint8_t product_type_is_valid; 642 uint32_t nt_major_version; 643 uint32_t nt_minor_version; 644 uint8_t processor_features[64]; 645 uint32_t reserved1; 646 uint32_t reserved3; 647 volatile uint32_t time_slip; 648 enum alt_arch_type alt_arch_type; 649 int64_t system_expiration_date; 650 uint32_t suite_mask; 651 uint8_t kdbg_enabled; 652 volatile uint32_t active_console; 653 volatile uint32_t dismount_count; 654 uint32_t com_plus_package; 655 uint32_t last_system_rit_event_tick_count; 656 uint32_t num_phys_pages; 657 uint8_t safe_boot_mode; 658 uint32_t trace_log; 659 uint64_t fill0; 660 uint64_t sys_call[4]; 661 union { 662 volatile struct ksystem_time tick_count; 663 volatile uint64_t tick_count_quad; 664 } tick; 665}; 666 667/* 668 * In Windows, there are Physical Device Objects (PDOs) and 669 * Functional Device Objects (FDOs). Physical Device Objects are 670 * created and maintained by bus drivers. For example, the PCI 671 * bus driver might detect two PCI ethernet cards on a given 672 * bus. The PCI bus driver will then allocate two device_objects 673 * for its own internal bookeeping purposes. This is analagous 674 * to the device_t that the FreeBSD PCI code allocates and passes 675 * into each PCI driver's probe and attach routines. 676 * 677 * When an ethernet driver claims one of the ethernet cards 678 * on the bus, it will create its own device_object. This is 679 * the Functional Device Object. This object is analagous to the 680 * device-specific softc structure. 681 */ 682 683struct device_object { 684 uint16_t do_type; 685 uint16_t do_size; 686 uint32_t do_refcnt; 687 struct driver_object *do_drvobj; 688 struct device_object *do_nextdev; 689 struct device_object *do_attacheddev; 690 struct irp *do_currirp; 691 void *do_iotimer; 692 uint32_t do_flags; 693 uint32_t do_characteristics; 694 void *do_vpb; 695 void *do_devext; 696 uint32_t do_devtype; 697 uint8_t do_stacksize; 698 union { 699 list_entry do_listent; 700 wait_ctx_block do_wcb; 701 } queue; 702 uint32_t do_alignreq; 703 kdevice_queue do_devqueue; 704 struct kdpc do_dpc; 705 uint32_t do_activethreads; 706 void *do_securitydesc; 707 struct nt_kevent do_devlock; 708 uint16_t do_sectorsz; 709 uint16_t do_spare1; 710 struct devobj_extension *do_devobj_ext; 711 void *do_rsvd; 712}; 713 714typedef struct device_object device_object; 715 716struct devobj_extension { 717 uint16_t dve_type; 718 uint16_t dve_size; 719 device_object *dve_devobj; 720}; 721 722typedef struct devobj_extension devobj_extension; 723 724/* Device object flags */ 725 726#define DO_VERIFY_VOLUME 0x00000002 727#define DO_BUFFERED_IO 0x00000004 728#define DO_EXCLUSIVE 0x00000008 729#define DO_DIRECT_IO 0x00000010 730#define DO_MAP_IO_BUFFER 0x00000020 731#define DO_DEVICE_HAS_NAME 0x00000040 732#define DO_DEVICE_INITIALIZING 0x00000080 733#define DO_SYSTEM_BOOT_PARTITION 0x00000100 734#define DO_LONG_TERM_REQUESTS 0x00000200 735#define DO_NEVER_LAST_DEVICE 0x00000400 736#define DO_SHUTDOWN_REGISTERED 0x00000800 737#define DO_BUS_ENUMERATED_DEVICE 0x00001000 738#define DO_POWER_PAGABLE 0x00002000 739#define DO_POWER_INRUSH 0x00004000 740#define DO_LOW_PRIORITY_FILESYSTEM 0x00010000 741 742/* Priority boosts */ 743 744#define IO_NO_INCREMENT 0 745#define IO_CD_ROM_INCREMENT 1 746#define IO_DISK_INCREMENT 1 747#define IO_KEYBOARD_INCREMENT 6 748#define IO_MAILSLOT_INCREMENT 2 749#define IO_MOUSE_INCREMENT 6 750#define IO_NAMED_PIPE_INCREMENT 2 751#define IO_NETWORK_INCREMENT 2 752#define IO_PARALLEL_INCREMENT 1 753#define IO_SERIAL_INCREMENT 2 754#define IO_SOUND_INCREMENT 8 755#define IO_VIDEO_INCREMENT 1 756 757/* IRP major codes */ 758 759#define IRP_MJ_CREATE 0x00 760#define IRP_MJ_CREATE_NAMED_PIPE 0x01 761#define IRP_MJ_CLOSE 0x02 762#define IRP_MJ_READ 0x03 763#define IRP_MJ_WRITE 0x04 764#define IRP_MJ_QUERY_INFORMATION 0x05 765#define IRP_MJ_SET_INFORMATION 0x06 766#define IRP_MJ_QUERY_EA 0x07 767#define IRP_MJ_SET_EA 0x08 768#define IRP_MJ_FLUSH_BUFFERS 0x09 769#define IRP_MJ_QUERY_VOLUME_INFORMATION 0x0a 770#define IRP_MJ_SET_VOLUME_INFORMATION 0x0b 771#define IRP_MJ_DIRECTORY_CONTROL 0x0c 772#define IRP_MJ_FILE_SYSTEM_CONTROL 0x0d 773#define IRP_MJ_DEVICE_CONTROL 0x0e 774#define IRP_MJ_INTERNAL_DEVICE_CONTROL 0x0f 775#define IRP_MJ_SHUTDOWN 0x10 776#define IRP_MJ_LOCK_CONTROL 0x11 777#define IRP_MJ_CLEANUP 0x12 778#define IRP_MJ_CREATE_MAILSLOT 0x13 779#define IRP_MJ_QUERY_SECURITY 0x14 780#define IRP_MJ_SET_SECURITY 0x15 781#define IRP_MJ_POWER 0x16 782#define IRP_MJ_SYSTEM_CONTROL 0x17 783#define IRP_MJ_DEVICE_CHANGE 0x18 784#define IRP_MJ_QUERY_QUOTA 0x19 785#define IRP_MJ_SET_QUOTA 0x1a 786#define IRP_MJ_PNP 0x1b 787#define IRP_MJ_PNP_POWER IRP_MJ_PNP // Obsolete.... 788#define IRP_MJ_MAXIMUM_FUNCTION 0x1b 789#define IRP_MJ_SCSI IRP_MJ_INTERNAL_DEVICE_CONTROL 790 791/* IRP minor codes */ 792 793#define IRP_MN_QUERY_DIRECTORY 0x01 794#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x02 795#define IRP_MN_USER_FS_REQUEST 0x00 796 797#define IRP_MN_MOUNT_VOLUME 0x01 798#define IRP_MN_VERIFY_VOLUME 0x02 799#define IRP_MN_LOAD_FILE_SYSTEM 0x03 800#define IRP_MN_TRACK_LINK 0x04 801#define IRP_MN_KERNEL_CALL 0x04 802 803#define IRP_MN_LOCK 0x01 804#define IRP_MN_UNLOCK_SINGLE 0x02 805#define IRP_MN_UNLOCK_ALL 0x03 806#define IRP_MN_UNLOCK_ALL_BY_KEY 0x04 807 808#define IRP_MN_NORMAL 0x00 809#define IRP_MN_DPC 0x01 810#define IRP_MN_MDL 0x02 811#define IRP_MN_COMPLETE 0x04 812#define IRP_MN_COMPRESSED 0x08 813 814#define IRP_MN_MDL_DPC (IRP_MN_MDL | IRP_MN_DPC) 815#define IRP_MN_COMPLETE_MDL (IRP_MN_COMPLETE | IRP_MN_MDL) 816#define IRP_MN_COMPLETE_MDL_DPC (IRP_MN_COMPLETE_MDL | IRP_MN_DPC) 817 818#define IRP_MN_SCSI_CLASS 0x01 819 820#define IRP_MN_START_DEVICE 0x00 821#define IRP_MN_QUERY_REMOVE_DEVICE 0x01 822#define IRP_MN_REMOVE_DEVICE 0x02 823#define IRP_MN_CANCEL_REMOVE_DEVICE 0x03 824#define IRP_MN_STOP_DEVICE 0x04 825#define IRP_MN_QUERY_STOP_DEVICE 0x05 826#define IRP_MN_CANCEL_STOP_DEVICE 0x06 827 828#define IRP_MN_QUERY_DEVICE_RELATIONS 0x07 829#define IRP_MN_QUERY_INTERFACE 0x08 830#define IRP_MN_QUERY_CAPABILITIES 0x09 831#define IRP_MN_QUERY_RESOURCES 0x0A 832#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS 0x0B 833#define IRP_MN_QUERY_DEVICE_TEXT 0x0C 834#define IRP_MN_FILTER_RESOURCE_REQUIREMENTS 0x0D 835 836#define IRP_MN_READ_CONFIG 0x0F 837#define IRP_MN_WRITE_CONFIG 0x10 838#define IRP_MN_EJECT 0x11 839#define IRP_MN_SET_LOCK 0x12 840#define IRP_MN_QUERY_ID 0x13 841#define IRP_MN_QUERY_PNP_DEVICE_STATE 0x14 842#define IRP_MN_QUERY_BUS_INFORMATION 0x15 843#define IRP_MN_DEVICE_USAGE_NOTIFICATION 0x16 844#define IRP_MN_SURPRISE_REMOVAL 0x17 845#define IRP_MN_QUERY_LEGACY_BUS_INFORMATION 0x18 846 847#define IRP_MN_WAIT_WAKE 0x00 848#define IRP_MN_POWER_SEQUENCE 0x01 849#define IRP_MN_SET_POWER 0x02 850#define IRP_MN_QUERY_POWER 0x03 851 852#define IRP_MN_QUERY_ALL_DATA 0x00 853#define IRP_MN_QUERY_SINGLE_INSTANCE 0x01 854#define IRP_MN_CHANGE_SINGLE_INSTANCE 0x02 855#define IRP_MN_CHANGE_SINGLE_ITEM 0x03 856#define IRP_MN_ENABLE_EVENTS 0x04 857#define IRP_MN_DISABLE_EVENTS 0x05 858#define IRP_MN_ENABLE_COLLECTION 0x06 859#define IRP_MN_DISABLE_COLLECTION 0x07 860#define IRP_MN_REGINFO 0x08 861#define IRP_MN_EXECUTE_METHOD 0x09 862#define IRP_MN_REGINFO_EX 0x0b 863 864/* IRP flags */ 865 866#define IRP_NOCACHE 0x00000001 867#define IRP_PAGING_IO 0x00000002 868#define IRP_MOUNT_COMPLETION 0x00000002 869#define IRP_SYNCHRONOUS_API 0x00000004 870#define IRP_ASSOCIATED_IRP 0x00000008 871#define IRP_BUFFERED_IO 0x00000010 872#define IRP_DEALLOCATE_BUFFER 0x00000020 873#define IRP_INPUT_OPERATION 0x00000040 874#define IRP_SYNCHRONOUS_PAGING_IO 0x00000040 875#define IRP_CREATE_OPERATION 0x00000080 876#define IRP_READ_OPERATION 0x00000100 877#define IRP_WRITE_OPERATION 0x00000200 878#define IRP_CLOSE_OPERATION 0x00000400 879#define IRP_DEFER_IO_COMPLETION 0x00000800 880#define IRP_OB_QUERY_NAME 0x00001000 881#define IRP_HOLD_DEVICE_QUEUE 0x00002000 882#define IRP_RETRY_IO_COMPLETION 0x00004000 883#define IRP_CLASS_CACHE_OPERATION 0x00008000 884#define IRP_SET_USER_EVENT IRP_CLOSE_OPERATION 885 886/* IRP I/O control flags */ 887 888#define IRP_QUOTA_CHARGED 0x01 889#define IRP_ALLOCATED_MUST_SUCCEED 0x02 890#define IRP_ALLOCATED_FIXED_SIZE 0x04 891#define IRP_LOOKASIDE_ALLOCATION 0x08 892 893/* I/O method types */ 894 895#define METHOD_BUFFERED 0 896#define METHOD_IN_DIRECT 1 897#define METHOD_OUT_DIRECT 2 898#define METHOD_NEITHER 3 899 900/* File access types */ 901 902#define FILE_ANY_ACCESS 0x0000 903#define FILE_SPECIAL_ACCESS FILE_ANY_ACCESS 904#define FILE_READ_ACCESS 0x0001 905#define FILE_WRITE_ACCESS 0x0002 906 907/* Recover I/O access method from IOCTL code. */ 908 909#define IO_METHOD(x) ((x) & 0xFFFFFFFC) 910 911/* Recover function code from IOCTL code */ 912 913#define IO_FUNC(x) (((x) & 0x7FFC) >> 2) 914 915/* Macro to construct an IOCTL code. */ 916 917#define IOCTL_CODE(dev, func, iomethod, acc) \ 918 ((dev) << 16) | (acc << 14) | (func << 2) | (iomethod)) 919 920 921struct io_status_block { 922 union { 923 uint32_t isb_status; 924 void *isb_ptr; 925 } u; 926 register_t isb_info; 927}; 928#define isb_status u.isb_status 929#define isb_ptr u.isb_ptr 930 931typedef struct io_status_block io_status_block; 932 933struct kapc { 934 uint16_t apc_type; 935 uint16_t apc_size; 936 uint32_t apc_spare0; 937 void *apc_thread; 938 list_entry apc_list; 939 void *apc_kernfunc; 940 void *apc_rundownfunc; 941 void *apc_normalfunc; 942 void *apc_normctx; 943 void *apc_sysarg1; 944 void *apc_sysarg2; 945 uint8_t apc_stateidx; 946 uint8_t apc_cpumode; 947 uint8_t apc_inserted; 948}; 949 950typedef struct kapc kapc; 951 952typedef uint32_t (*completion_func)(device_object *, 953 struct irp *, void *); 954typedef uint32_t (*cancel_func)(device_object *, 955 struct irp *); 956 957struct io_stack_location { 958 uint8_t isl_major; 959 uint8_t isl_minor; 960 uint8_t isl_flags; 961 uint8_t isl_ctl; 962 963 /* 964 * There's a big-ass union here in the actual Windows 965 * definition of the stucture, but it contains stuff 966 * that doesn't really apply to BSD, and defining it 967 * all properly would require duplicating over a dozen 968 * other structures that we'll never use. Since the 969 * io_stack_location structure is opaque to drivers 970 * anyway, I'm not going to bother with the extra crap. 971 */ 972 973 union { 974 struct { 975 uint32_t isl_len; 976 uint32_t *isl_key; 977 uint64_t isl_byteoff; 978 } isl_read; 979 struct { 980 uint32_t isl_len; 981 uint32_t *isl_key; 982 uint64_t isl_byteoff; 983 } isl_write; 984 struct { 985 uint32_t isl_obuflen; 986 uint32_t isl_ibuflen; 987 uint32_t isl_iocode; 988 void *isl_type3ibuf; 989 } isl_ioctl; 990 struct { 991 void *isl_arg1; 992 void *isl_arg2; 993 void *isl_arg3; 994 void *isl_arg4; 995 } isl_others; 996 } isl_parameters __attribute__((packed)); 997 998 void *isl_devobj; 999 void *isl_fileobj; 1000 completion_func isl_completionfunc; 1001 void *isl_completionctx; 1002}; 1003 1004typedef struct io_stack_location io_stack_location; 1005 1006/* Stack location control flags */ 1007 1008#define SL_PENDING_RETURNED 0x01 1009#define SL_INVOKE_ON_CANCEL 0x20 1010#define SL_INVOKE_ON_SUCCESS 0x40 1011#define SL_INVOKE_ON_ERROR 0x80 1012 1013struct irp { 1014 uint16_t irp_type; 1015 uint16_t irp_size; 1016 mdl *irp_mdl; 1017 uint32_t irp_flags; 1018 union { 1019 struct irp *irp_master; 1020 uint32_t irp_irpcnt; 1021 void *irp_sysbuf; 1022 } irp_assoc; 1023 list_entry irp_thlist; 1024 io_status_block irp_iostat; 1025 uint8_t irp_reqmode; 1026 uint8_t irp_pendingreturned; 1027 uint8_t irp_stackcnt; 1028 uint8_t irp_currentstackloc; 1029 uint8_t irp_cancel; 1030 uint8_t irp_cancelirql; 1031 uint8_t irp_apcenv; 1032 uint8_t irp_allocflags; 1033 io_status_block *irp_usriostat; 1034 nt_kevent *irp_usrevent; 1035 union { 1036 struct { 1037 void *irp_apcfunc; 1038 void *irp_apcctx; 1039 } irp_asyncparms; 1040 uint64_t irp_allocsz; 1041 } irp_overlay; 1042 cancel_func irp_cancelfunc; 1043 void *irp_userbuf; 1044 1045 /* Windows kernel info */ 1046 1047 union { 1048 struct { 1049 union { 1050 kdevice_qentry irp_dqe; 1051 struct { 1052 void *irp_drvctx[4]; 1053 } s1; 1054 } u1; 1055 void *irp_thread; 1056 char *irp_auxbuf; 1057 struct { 1058 list_entry irp_list; 1059 union { 1060 io_stack_location *irp_csl; 1061 uint32_t irp_pkttype; 1062 } u2; 1063 } s2; 1064 void *irp_fileobj; 1065 } irp_overlay; 1066 union { 1067 kapc irp_apc; 1068 struct { 1069 void *irp_ep; 1070 void *irp_dev; 1071 } irp_usb; 1072 } irp_misc; 1073 void *irp_compkey; 1074 } irp_tail; 1075}; 1076 1077#define irp_csl s2.u2.irp_csl 1078#define irp_pkttype s2.u2.irp_pkttype 1079 1080#define IRP_NDIS_DEV(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_dev 1081#define IRP_NDISUSB_EP(irp) (irp)->irp_tail.irp_misc.irp_usb.irp_ep 1082 1083typedef struct irp irp; 1084 1085#define InterlockedExchangePointer(dst, val) \ 1086 (void *)InterlockedExchange((uint32_t *)(dst), (uintptr_t)(val)) 1087 1088#define IoSizeOfIrp(ssize) \ 1089 ((uint16_t) (sizeof(irp) + ((ssize) * (sizeof(io_stack_location))))) 1090 1091#define IoSetCancelRoutine(irp, func) \ 1092 (cancel_func)InterlockedExchangePointer( \ 1093 (void *)&(ip)->irp_cancelfunc, (void *)(func)) 1094 1095#define IoSetCancelValue(irp, val) \ 1096 (u_long)InterlockedExchangePointer( \ 1097 (void *)&(ip)->irp_cancel, (void *)(val)) 1098 1099#define IoGetCurrentIrpStackLocation(irp) \ 1100 (irp)->irp_tail.irp_overlay.irp_csl 1101 1102#define IoGetNextIrpStackLocation(irp) \ 1103 ((irp)->irp_tail.irp_overlay.irp_csl - 1) 1104 1105#define IoSetNextIrpStackLocation(irp) \ 1106 do { \ 1107 irp->irp_currentstackloc--; \ 1108 irp->irp_tail.irp_overlay.irp_csl--; \ 1109 } while(0) 1110 1111#define IoSetCompletionRoutine(irp, func, ctx, ok, err, cancel) \ 1112 do { \ 1113 io_stack_location *s; \ 1114 s = IoGetNextIrpStackLocation((irp)); \ 1115 s->isl_completionfunc = (func); \ 1116 s->isl_completionctx = (ctx); \ 1117 s->isl_ctl = 0; \ 1118 if (ok) s->isl_ctl = SL_INVOKE_ON_SUCCESS; \ 1119 if (err) s->isl_ctl |= SL_INVOKE_ON_ERROR; \ 1120 if (cancel) s->isl_ctl |= SL_INVOKE_ON_CANCEL; \ 1121 } while(0) 1122 1123#define IoMarkIrpPending(irp) \ 1124 IoGetCurrentIrpStackLocation(irp)->isl_ctl |= SL_PENDING_RETURNED 1125#define IoUnmarkIrpPending(irp) \ 1126 IoGetCurrentIrpStackLocation(irp)->isl_ctl &= ~SL_PENDING_RETURNED 1127 1128#define IoCopyCurrentIrpStackLocationToNext(irp) \ 1129 do { \ 1130 io_stack_location *src, *dst; \ 1131 src = IoGetCurrentIrpStackLocation(irp); \ 1132 dst = IoGetNextIrpStackLocation(irp); \ 1133 bcopy((char *)src, (char *)dst, \ 1134 offsetof(io_stack_location, isl_completionfunc)); \ 1135 } while(0) 1136 1137#define IoSkipCurrentIrpStackLocation(irp) \ 1138 do { \ 1139 (irp)->irp_currentstackloc++; \ 1140 (irp)->irp_tail.irp_overlay.irp_csl++; \ 1141 } while(0) 1142 1143#define IoInitializeDpcRequest(dobj, dpcfunc) \ 1144 KeInitializeDpc(&(dobj)->do_dpc, dpcfunc, dobj) 1145 1146#define IoRequestDpc(dobj, irp, ctx) \ 1147 KeInsertQueueDpc(&(dobj)->do_dpc, irp, ctx) 1148 1149typedef uint32_t (*driver_dispatch)(device_object *, irp *); 1150 1151/* 1152 * The driver_object is allocated once for each driver that's loaded 1153 * into the system. A new one is allocated for each driver and 1154 * populated a bit via the driver's DriverEntry function. 1155 * In general, a Windows DriverEntry() function will provide a pointer 1156 * to its AddDevice() method and set up the dispatch table. 1157 * For NDIS drivers, this is all done behind the scenes in the 1158 * NdisInitializeWrapper() and/or NdisMRegisterMiniport() routines. 1159 */ 1160 1161struct driver_object { 1162 uint16_t dro_type; 1163 uint16_t dro_size; 1164 device_object *dro_devobj; 1165 uint32_t dro_flags; 1166 void *dro_driverstart; 1167 uint32_t dro_driversize; 1168 void *dro_driversection; 1169 driver_extension *dro_driverext; 1170 unicode_string dro_drivername; 1171 unicode_string *dro_hwdb; 1172 void *dro_pfastiodispatch; 1173 void *dro_driverinitfunc; 1174 void *dro_driverstartiofunc; 1175 void *dro_driverunloadfunc; 1176 driver_dispatch dro_dispatch[IRP_MJ_MAXIMUM_FUNCTION + 1]; 1177}; 1178 1179typedef struct driver_object driver_object; 1180 1181#define DEVPROP_DEVICE_DESCRIPTION 0x00000000 1182#define DEVPROP_HARDWARE_ID 0x00000001 1183#define DEVPROP_COMPATIBLE_IDS 0x00000002 1184#define DEVPROP_BOOTCONF 0x00000003 1185#define DEVPROP_BOOTCONF_TRANSLATED 0x00000004 1186#define DEVPROP_CLASS_NAME 0x00000005 1187#define DEVPROP_CLASS_GUID 0x00000006 1188#define DEVPROP_DRIVER_KEYNAME 0x00000007 1189#define DEVPROP_MANUFACTURER 0x00000008 1190#define DEVPROP_FRIENDLYNAME 0x00000009 1191#define DEVPROP_LOCATION_INFO 0x0000000A 1192#define DEVPROP_PHYSDEV_NAME 0x0000000B 1193#define DEVPROP_BUSTYPE_GUID 0x0000000C 1194#define DEVPROP_LEGACY_BUSTYPE 0x0000000D 1195#define DEVPROP_BUS_NUMBER 0x0000000E 1196#define DEVPROP_ENUMERATOR_NAME 0x0000000F 1197#define DEVPROP_ADDRESS 0x00000010 1198#define DEVPROP_UINUMBER 0x00000011 1199#define DEVPROP_INSTALL_STATE 0x00000012 1200#define DEVPROP_REMOVAL_POLICY 0x00000013 1201 1202/* Various supported device types (used with IoCreateDevice()) */ 1203 1204#define FILE_DEVICE_BEEP 0x00000001 1205#define FILE_DEVICE_CD_ROM 0x00000002 1206#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003 1207#define FILE_DEVICE_CONTROLLER 0x00000004 1208#define FILE_DEVICE_DATALINK 0x00000005 1209#define FILE_DEVICE_DFS 0x00000006 1210#define FILE_DEVICE_DISK 0x00000007 1211#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008 1212#define FILE_DEVICE_FILE_SYSTEM 0x00000009 1213#define FILE_DEVICE_INPORT_PORT 0x0000000A 1214#define FILE_DEVICE_KEYBOARD 0x0000000B 1215#define FILE_DEVICE_MAILSLOT 0x0000000C 1216#define FILE_DEVICE_MIDI_IN 0x0000000D 1217#define FILE_DEVICE_MIDI_OUT 0x0000000E 1218#define FILE_DEVICE_MOUSE 0x0000000F 1219#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010 1220#define FILE_DEVICE_NAMED_PIPE 0x00000011 1221#define FILE_DEVICE_NETWORK 0x00000012 1222#define FILE_DEVICE_NETWORK_BROWSER 0x00000013 1223#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014 1224#define FILE_DEVICE_NULL 0x00000015 1225#define FILE_DEVICE_PARALLEL_PORT 0x00000016 1226#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017 1227#define FILE_DEVICE_PRINTER 0x00000018 1228#define FILE_DEVICE_SCANNER 0x00000019 1229#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001A 1230#define FILE_DEVICE_SERIAL_PORT 0x0000001B 1231#define FILE_DEVICE_SCREEN 0x0000001C 1232#define FILE_DEVICE_SOUND 0x0000001D 1233#define FILE_DEVICE_STREAMS 0x0000001E 1234#define FILE_DEVICE_TAPE 0x0000001F 1235#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020 1236#define FILE_DEVICE_TRANSPORT 0x00000021 1237#define FILE_DEVICE_UNKNOWN 0x00000022 1238#define FILE_DEVICE_VIDEO 0x00000023 1239#define FILE_DEVICE_VIRTUAL_DISK 0x00000024 1240#define FILE_DEVICE_WAVE_IN 0x00000025 1241#define FILE_DEVICE_WAVE_OUT 0x00000026 1242#define FILE_DEVICE_8042_PORT 0x00000027 1243#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028 1244#define FILE_DEVICE_BATTERY 0x00000029 1245#define FILE_DEVICE_BUS_EXTENDER 0x0000002A 1246#define FILE_DEVICE_MODEM 0x0000002B 1247#define FILE_DEVICE_VDM 0x0000002C 1248#define FILE_DEVICE_MASS_STORAGE 0x0000002D 1249#define FILE_DEVICE_SMB 0x0000002E 1250#define FILE_DEVICE_KS 0x0000002F 1251#define FILE_DEVICE_CHANGER 0x00000030 1252#define FILE_DEVICE_SMARTCARD 0x00000031 1253#define FILE_DEVICE_ACPI 0x00000032 1254#define FILE_DEVICE_DVD 0x00000033 1255#define FILE_DEVICE_FULLSCREEN_VIDEO 0x00000034 1256#define FILE_DEVICE_DFS_FILE_SYSTEM 0x00000035 1257#define FILE_DEVICE_DFS_VOLUME 0x00000036 1258#define FILE_DEVICE_SERENUM 0x00000037 1259#define FILE_DEVICE_TERMSRV 0x00000038 1260#define FILE_DEVICE_KSEC 0x00000039 1261#define FILE_DEVICE_FIPS 0x0000003A 1262 1263/* Device characteristics */ 1264 1265#define FILE_REMOVABLE_MEDIA 0x00000001 1266#define FILE_READ_ONLY_DEVICE 0x00000002 1267#define FILE_FLOPPY_DISKETTE 0x00000004 1268#define FILE_WRITE_ONCE_MEDIA 0x00000008 1269#define FILE_REMOTE_DEVICE 0x00000010 1270#define FILE_DEVICE_IS_MOUNTED 0x00000020 1271#define FILE_VIRTUAL_VOLUME 0x00000040 1272#define FILE_AUTOGENERATED_DEVICE_NAME 0x00000080 1273#define FILE_DEVICE_SECURE_OPEN 0x00000100 1274 1275/* Status codes */ 1276 1277#define STATUS_SUCCESS 0x00000000 1278#define STATUS_USER_APC 0x000000C0 1279#define STATUS_KERNEL_APC 0x00000100 1280#define STATUS_ALERTED 0x00000101 1281#define STATUS_TIMEOUT 0x00000102 1282#define STATUS_PENDING 0x00000103 1283#define STATUS_FAILURE 0xC0000001 1284#define STATUS_NOT_IMPLEMENTED 0xC0000002 1285#define STATUS_ACCESS_VIOLATION 0xC0000005 1286#define STATUS_INVALID_PARAMETER 0xC000000D 1287#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 1288#define STATUS_MORE_PROCESSING_REQUIRED 0xC0000016 1289#define STATUS_NO_MEMORY 0xC0000017 1290#define STATUS_BUFFER_TOO_SMALL 0xC0000023 1291#define STATUS_MUTANT_NOT_OWNED 0xC0000046 1292#define STATUS_NOT_SUPPORTED 0xC00000BB 1293#define STATUS_INVALID_PARAMETER_2 0xC00000F0 1294#define STATUS_INSUFFICIENT_RESOURCES 0xC000009A 1295#define STATUS_DEVICE_NOT_CONNECTED 0xC000009D 1296#define STATUS_CANCELLED 0xC0000120 1297#define STATUS_NOT_FOUND 0xC0000225 1298#define STATUS_DEVICE_REMOVED 0xC00002B6 1299 1300#define STATUS_WAIT_0 0x00000000 1301 1302/* Memory pool types, for ExAllocatePoolWithTag() */ 1303 1304#define NonPagedPool 0x00000000 1305#define PagedPool 0x00000001 1306#define NonPagedPoolMustSucceed 0x00000002 1307#define DontUseThisType 0x00000003 1308#define NonPagedPoolCacheAligned 0x00000004 1309#define PagedPoolCacheAligned 0x00000005 1310#define NonPagedPoolCacheAlignedMustS 0x00000006 1311#define MaxPoolType 0x00000007 1312 1313/* 1314 * IO_WORKITEM is an opaque structures that must be allocated 1315 * via IoAllocateWorkItem() and released via IoFreeWorkItem(). 1316 * Consequently, we can define it any way we want. 1317 */ 1318typedef void (*io_workitem_func)(device_object *, void *); 1319 1320struct io_workitem { 1321 io_workitem_func iw_func; 1322 void *iw_ctx; 1323 list_entry iw_listentry; 1324 device_object *iw_dobj; 1325 int iw_idx; 1326}; 1327 1328typedef struct io_workitem io_workitem; 1329 1330#define WORKQUEUE_CRITICAL 0 1331#define WORKQUEUE_DELAYED 1 1332#define WORKQUEUE_HYPERCRITICAL 2 1333 1334#define WORKITEM_THREADS 4 1335#define WORKITEM_LEGACY_THREAD 3 1336#define WORKIDX_INC(x) (x) = (x + 1) % WORKITEM_LEGACY_THREAD 1337 1338/* 1339 * Older, deprecated work item API, needed to support NdisQueueWorkItem(). 1340 */ 1341 1342struct work_queue_item; 1343 1344typedef void (*work_item_func)(struct work_queue_item *, void *); 1345 1346struct work_queue_item { 1347 list_entry wqi_entry; 1348 work_item_func wqi_func; 1349 void *wqi_ctx; 1350}; 1351 1352typedef struct work_queue_item work_queue_item; 1353 1354#define ExInitializeWorkItem(w, func, ctx) \ 1355 do { \ 1356 (w)->wqi_func = (func); \ 1357 (w)->wqi_ctx = (ctx); \ 1358 InitializeListHead(&((w)->wqi_entry)); \ 1359 } while (0) 1360 1361/* 1362 * FreeBSD's kernel stack is 2 pages in size by default. The 1363 * Windows stack is larger, so we need to give our threads more 1364 * stack pages. 4 should be enough, we use 8 just to extra safe. 1365 */ 1366#define NDIS_KSTACK_PAGES 8 1367 1368/* 1369 * Different kinds of function wrapping we can do. 1370 */ 1371 1372#define WINDRV_WRAP_STDCALL 1 1373#define WINDRV_WRAP_FASTCALL 2 1374#define WINDRV_WRAP_REGPARM 3 1375#define WINDRV_WRAP_CDECL 4 1376#define WINDRV_WRAP_AMD64 5 1377 1378struct drvdb_ent { 1379 driver_object *windrv_object; 1380 void *windrv_devlist; 1381 ndis_cfg *windrv_regvals; 1382 interface_type windrv_bustype; 1383 STAILQ_ENTRY(drvdb_ent) link; 1384}; 1385 1386extern image_patch_table ntoskrnl_functbl[]; 1387#ifdef __amd64__ 1388extern struct kuser_shared_data kuser_shared_data; 1389#endif 1390typedef void (*funcptr)(void); 1391typedef int (*matchfuncptr)(interface_type, void *, void *); 1392 1393__BEGIN_DECLS 1394extern int windrv_libinit(void); 1395extern int windrv_libfini(void); 1396extern driver_object *windrv_lookup(vm_offset_t, char *); 1397extern struct drvdb_ent *windrv_match(matchfuncptr, void *); 1398extern int windrv_load(module_t, vm_offset_t, int, interface_type, 1399 void *, ndis_cfg *); 1400extern int windrv_unload(module_t, vm_offset_t, int); 1401extern int windrv_create_pdo(driver_object *, device_t); 1402extern void windrv_destroy_pdo(driver_object *, device_t); 1403extern device_object *windrv_find_pdo(driver_object *, device_t); 1404extern int windrv_bus_attach(driver_object *, char *); 1405extern int windrv_wrap(funcptr, funcptr *, int, int); 1406extern int windrv_unwrap(funcptr); 1407extern void ctxsw_utow(void); 1408extern void ctxsw_wtou(void); 1409 1410extern int ntoskrnl_libinit(void); 1411extern int ntoskrnl_libfini(void); 1412 1413extern void ntoskrnl_intr(void *); 1414extern void ntoskrnl_time(uint64_t *); 1415 1416extern uint16_t ExQueryDepthSList(slist_header *); 1417extern slist_entry 1418 *InterlockedPushEntrySList(slist_header *, slist_entry *); 1419extern slist_entry *InterlockedPopEntrySList(slist_header *); 1420extern uint32_t RtlUnicodeStringToAnsiString(ansi_string *, 1421 unicode_string *, uint8_t); 1422extern uint32_t RtlAnsiStringToUnicodeString(unicode_string *, 1423 ansi_string *, uint8_t); 1424extern void RtlInitAnsiString(ansi_string *, char *); 1425extern void RtlInitUnicodeString(unicode_string *, 1426 uint16_t *); 1427extern void RtlFreeUnicodeString(unicode_string *); 1428extern void RtlFreeAnsiString(ansi_string *); 1429extern void KeInitializeDpc(kdpc *, void *, void *); 1430extern uint8_t KeInsertQueueDpc(kdpc *, void *, void *); 1431extern uint8_t KeRemoveQueueDpc(kdpc *); 1432extern void KeSetImportanceDpc(kdpc *, uint32_t); 1433extern void KeSetTargetProcessorDpc(kdpc *, uint8_t); 1434extern void KeFlushQueuedDpcs(void); 1435extern uint32_t KeGetCurrentProcessorNumber(void); 1436extern void KeInitializeTimer(ktimer *); 1437extern void KeInitializeTimerEx(ktimer *, uint32_t); 1438extern uint8_t KeSetTimer(ktimer *, int64_t, kdpc *); 1439extern uint8_t KeSetTimerEx(ktimer *, int64_t, uint32_t, kdpc *); 1440extern uint8_t KeCancelTimer(ktimer *); 1441extern uint8_t KeReadStateTimer(ktimer *); 1442extern uint32_t KeWaitForSingleObject(void *, uint32_t, 1443 uint32_t, uint8_t, int64_t *); 1444extern void KeInitializeEvent(nt_kevent *, uint32_t, uint8_t); 1445extern void KeClearEvent(nt_kevent *); 1446extern uint32_t KeReadStateEvent(nt_kevent *); 1447extern uint32_t KeSetEvent(nt_kevent *, uint32_t, uint8_t); 1448extern uint32_t KeResetEvent(nt_kevent *); 1449#ifdef __i386__ 1450extern void KefAcquireSpinLockAtDpcLevel(kspin_lock *); 1451extern void KefReleaseSpinLockFromDpcLevel(kspin_lock *); 1452extern uint8_t KeAcquireSpinLockRaiseToDpc(kspin_lock *); 1453#else 1454extern void KeAcquireSpinLockAtDpcLevel(kspin_lock *); 1455extern void KeReleaseSpinLockFromDpcLevel(kspin_lock *); 1456#endif 1457extern void KeInitializeSpinLock(kspin_lock *); 1458extern uint8_t KeAcquireInterruptSpinLock(kinterrupt *); 1459extern void KeReleaseInterruptSpinLock(kinterrupt *, uint8_t); 1460extern uint8_t KeSynchronizeExecution(kinterrupt *, void *, void *); 1461extern uintptr_t InterlockedExchange(volatile uint32_t *, 1462 uintptr_t); 1463extern void *ExAllocatePoolWithTag(uint32_t, size_t, uint32_t); 1464extern void ExFreePool(void *); 1465extern uint32_t IoConnectInterrupt(kinterrupt **, void *, void *, 1466 kspin_lock *, uint32_t, uint8_t, uint8_t, uint8_t, uint8_t, 1467 uint32_t, uint8_t); 1468extern uint8_t MmIsAddressValid(void *); 1469extern void *MmGetSystemRoutineAddress(unicode_string *); 1470extern void *MmMapIoSpace(uint64_t, uint32_t, uint32_t); 1471extern void MmUnmapIoSpace(void *, size_t); 1472extern void MmBuildMdlForNonPagedPool(mdl *); 1473extern void IoDisconnectInterrupt(kinterrupt *); 1474extern uint32_t IoAllocateDriverObjectExtension(driver_object *, 1475 void *, uint32_t, void **); 1476extern void *IoGetDriverObjectExtension(driver_object *, void *); 1477extern uint32_t IoCreateDevice(driver_object *, uint32_t, 1478 unicode_string *, uint32_t, uint32_t, uint8_t, device_object **); 1479extern void IoDeleteDevice(device_object *); 1480extern device_object *IoGetAttachedDevice(device_object *); 1481extern uint32_t IofCallDriver(device_object *, irp *); 1482extern void IofCompleteRequest(irp *, uint8_t); 1483extern void IoAcquireCancelSpinLock(uint8_t *); 1484extern void IoReleaseCancelSpinLock(uint8_t); 1485extern uint8_t IoCancelIrp(irp *); 1486extern void IoDetachDevice(device_object *); 1487extern device_object *IoAttachDeviceToDeviceStack(device_object *, 1488 device_object *); 1489extern mdl *IoAllocateMdl(void *, uint32_t, uint8_t, uint8_t, irp *); 1490extern void IoFreeMdl(mdl *); 1491extern io_workitem *IoAllocateWorkItem(device_object *); 1492extern void ExQueueWorkItem(work_queue_item *, u_int32_t); 1493extern void IoFreeWorkItem(io_workitem *); 1494extern void IoQueueWorkItem(io_workitem *, io_workitem_func, 1495 uint32_t, void *); 1496 1497#define IoCallDriver(a, b) IofCallDriver(a, b) 1498#define IoCompleteRequest(a, b) IofCompleteRequest(a, b) 1499 1500/* 1501 * On the Windows x86 arch, KeAcquireSpinLock() and KeReleaseSpinLock() 1502 * routines live in the HAL. We try to imitate this behavior. 1503 */ 1504#ifdef __i386__ 1505#define KI_USER_SHARED_DATA 0xffdf0000 1506#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a) 1507#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b) 1508#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a) 1509#define KeLowerIrql(a) KfLowerIrql(a) 1510#define KeAcquireSpinLockAtDpcLevel(a) KefAcquireSpinLockAtDpcLevel(a) 1511#define KeReleaseSpinLockFromDpcLevel(a) KefReleaseSpinLockFromDpcLevel(a) 1512#endif /* __i386__ */ 1513 1514#ifdef __amd64__ 1515#define KI_USER_SHARED_DATA 0xfffff78000000000UL 1516#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a) 1517#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b) 1518 1519/* 1520 * These may need to be redefined later; 1521 * not sure where they live on amd64 yet. 1522 */ 1523#define KeRaiseIrql(a, b) *(b) = KfRaiseIrql(a) 1524#define KeLowerIrql(a) KfLowerIrql(a) 1525#endif /* __amd64__ */ 1526 1527__END_DECLS 1528 1529#endif /* _NTOSKRNL_VAR_H_ */ 1530