ntoskrnl_var.h revision 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 * 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 *)); 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__ 1139#define KeAcquireSpinLock(a, b) *(b) = KfAcquireSpinLock(a) 1140#define KeReleaseSpinLock(a, b) KfReleaseSpinLock(a, b) 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_ */ 1153