summaryrefslogtreecommitdiff
path: root/storage/miniports/storahci/src/entrypts.h
blob: df1aa9eae8168430db022a82ecd1c69fd533ab48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
/*++

Copyright (C) Microsoft Corporation, 2009

Module Name:

    entrypts.h

Abstract:

    This header contains the declaration of functions that will be called by Storport driver.

Authors:

--*/

#pragma once

#if _MSC_VER >= 1200
#pragma warning(push)
#endif

#pragma warning(disable:4214)   // bit field types other than int
#pragma warning(disable:4201)   // nameless struct/union

#include "data.h"

#define AHCI_POOL_TAG               'ichA'  // "Ahci" - StorAHCI miniport driver

#define NUM_ACCESS_RANGES           6

#define AHCI_MAX_PORT_COUNT         32
#define AHCI_MAX_DEVICE             1       //not support Port Multiplier
#define AHCI_MAX_LUN                8       //ATAport supports this much in old implementation.
#define AHCI_MAX_NCQ_REQUEST_COUNT  32

#define KB                          (1024)
#define AHCI_MAX_TRANSFER_LENGTH_DEFAULT    (128 * KB)
#define AHCI_MAX_TRANSFER_LENGTH            (1024 * KB)
#define MAX_SETTINGS_PRESERVED      32
#define MAX_CRB_LOG_INDEX           64

#define INQUIRYDATABUFFERSIZE       36

// timeout values and counters for channel start
// some big HDDs (e.g. 2TB) takes ~ 20 seconds to spin up.  We hit timeout during S3 resume for now,
// we reset after 1/3 * AHCI_PORT_START_TIMEOUT_IN_SECONDS Busy, and give up after AHCI_PORT_START_TIMEOUT_IN_SECONDS seconds

#define AHCI_PORT_START_TIMEOUT_IN_SECONDS  60      // 60 sec.

#define AHCI_PORT_WAIT_ON_DET_COUNT         3       // in unit of 10ms, default 30ms.


// port start states
#define WaitOnDET       0x11
#define WaitWhileDET1   0x12
#define WaitOnDET3      0x13
#define WaitOnFRE       0x14
#define WaitOnBSYDRQ    0x15
#define StartComplete   0x16
#define Stopped         0x20
#define StartFailed     0xff

//
// Bit field definitions for PortProperties field in CHANNEL_EXTENSION
//

// Clear: Internal port
// Set:   External port
#define PORT_PROPERTIES_EXTERNAL_PORT  ( 1 << 0 )

// registry flags apply to port or device
typedef struct _CHANNEL_REGISTRY_FLAGS {

    ULONG Reserved : 20;

} CHANNEL_REGISTRY_FLAGS, *PCHANNEL_REGISTRY_FLAGS;

// registry flags apply to the whole adapter
typedef struct _ADAPTER_REGISTRY_FLAGS {

    ULONG Reserved2 : 13;

} ADAPTER_REGISTRY_FLAGS, *PADAPTER_REGISTRY_FLAGS;

typedef struct _CHANNEL_STATE_FLAGS {
    ULONG Initialized : 1;
    ULONG NoMoreIO : 1;
    ULONG QueuePaused : 1;
    ULONG ReservedSlotInUse : 1;    //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 3) is used there.

    ULONG NCQ_Activated : 1;
    ULONG NCQ_Succeeded : 1;
    ULONG RestorePreservedSettingsActiveReferenced : 1; // this bit will be set if active reference is acquired for RestorePreservedSettings process
    ULONG HybridInfoEnabledOnHiberFile : 1;             // this bit indicates if priority level should be put for NCQ Write by StorAHCI when writes a hiber file.

    ULONG CallAhciReset : 1;
    ULONG CallAhciNonQueuedErrorRecovery : 1;
    ULONG CallAhciReportBusChange : 1;
    ULONG IgnoreHotplugInterrupt : 1;

    ULONG PowerDown : 1;            //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 12) is used there.
    ULONG PoFxEnabled : 1;
    ULONG PoFxActive : 1;
    ULONG D3ColdEnabled : 1;

    ULONG D3ColdSupported : 1;
    ULONG CallAhciNcqErrorRecovery : 1;
    ULONG NcqErrorRecoveryInProcess : 1;
    ULONG PuisEnabled : 1;

    ULONG IdentifyDeviceSuccess : 1;
    ULONG NeedQDR : 1;
    ULONG PowerUpInitializationInProgress : 1; //Note: this field indicates that init/preserved settings commands(invoked by power up) are not completed yet.
    ULONG Reserved0 : 9;

    ULONG Reserved1;
} CHANNEL_STATE_FLAGS, *PCHANNEL_STATE_FLAGS;

//
// Data structure to retrieve a Log Page 
//
typedef struct _ATA_GPL_PAGE {
    BOOLEAN  Query;
    UCHAR    LogAddress;
    USHORT   PageNumber;
    USHORT   BlockCount;
    USHORT   FeatureField;
} ATA_GPL_PAGE, *PATA_GPL_PAGE;

#define ATA_GPL_PAGES_QUERY_COUNT       0x10
#define ATA_GPL_PAGES_INVALID_INDEX     0xFFFF

typedef struct _ATA_GPL_PAGES_TO_QUERY {
    USHORT          TotalPageCount;
    USHORT          CurrentPageIndex;

    ATA_GPL_PAGE    LogPage[ATA_GPL_PAGES_QUERY_COUNT];
} ATA_GPL_PAGES_TO_QUERY, *PATA_GPL_PAGES_TO_QUERY;

//
// This data structure defines supportive information of Log Address and Log Page
// If a Log Address contains more than one different Log Pages, there normally is Log Page 0x00 to get supported log pages.
//
typedef struct _ATA_SUPPORTED_GPL_PAGES {

    struct {
        ULONG  LogAddressSupported : 1;     // Log Address 0x04
        ULONG  GeneralStatistics : 1;           // Log Page 0x01
        ULONG  TemperatureStatistics : 1;       // Log Page 0x05
        ULONG  Reserved : 29;
    } DeviceStatistics;

    struct {
        ULONG  LogAddressSupported : 1;     // Log Address 0x30
        ULONG  SATA : 1;                        // Log Page 0x08
        ULONG  SupportedCapabilities : 1;       // Log Page 0x03
        ULONG  Reserved : 29;
    } IdentifyDeviceData;

    struct {
        ULONG  NcqCommandError                  : 1;         // Log Address 0x10
        ULONG  NcqNonData                       : 1;         // Log Address 0x12
        ULONG  NcqSendReceive                   : 1;         // Log Address 0x13
        ULONG  HybridInfo                       : 1;         // Log Address 0x14
        ULONG  CurrentDeviceInternalStatusData  : 1;         // Log Address 0x24
        ULONG  SavedDeviceInternalStatusData    : 1;         // Log Address 0x25

        ULONG  Reserved : 26;
    } SinglePage;

} ATA_SUPPORTED_GPL_PAGES, *PATA_SUPPORTED_GPL_PAGES;

typedef struct _ATA_COMMAND_SUPPORTED {

    ULONG  HybridDemoteBySize       : 1;
    ULONG  HybridChangeByLbaRange   : 1;
    ULONG  HybridControl            : 1;
    ULONG  HybridEvict              : 1;

    ULONG  SetDateAndTime           : 1;

    ULONG  Reserved                 : 27;

} ATA_COMMAND_SUPPORTED, *PATA_COMMAND_SUPPORTED;

typedef struct _DOWNLOAD_MICROCODE_CAPABILITIES {

    USHORT  DmMinTransferBlocks;

    USHORT  DmMaxTransferBlocks;

    BOOLEAN DmOffsetsDeferredSupported;     // subcommand 0Eh and 0Fh are supported.
    UCHAR   Reserved[3];

} DOWNLOAD_MICROCODE_CAPABILITIES, *PDOWNLOAD_MICROCODE_CAPABILITIES;


typedef struct _AHCI_DEVICE_EXTENSION {
    STOR_ADDR_BTL8          DeviceAddress;
    ATA_DEVICE_PARAMETERS   DeviceParameters;
    ATA_IO_RECORD           IoRecord;       //IO counts completed by device, the count only change if an IO reaches hardware

    union {
      PIDENTIFY_DEVICE_DATA IdentifyDeviceData;
      PIDENTIFY_PACKET_DATA IdentifyPacketData;
    };
    STOR_PHYSICAL_ADDRESS   IdentifyDataPhysicalAddress;

    PUCHAR                  InquiryData;    //for ATAPI device, size:INQUIRYDATABUFFERSIZE
    STOR_PHYSICAL_ADDRESS   InquiryDataPhysicalAddress;

    ATA_GPL_PAGES_TO_QUERY  QueryLogPages;

    ATA_SUPPORTED_GPL_PAGES SupportedGPLPages;
    ATA_COMMAND_SUPPORTED   SupportedCommands;

    GP_LOG_HYBRID_INFORMATION_HEADER    HybridInfo;
    LONG                                HybridCachingMediumEnableRefs;

    DOWNLOAD_MICROCODE_CAPABILITIES FirmwareUpdate;

    PUSHORT                 ReadLogExtPageData;
    STOR_PHYSICAL_ADDRESS   ReadLogExtPageDataPhysicalAddress;

    BOOLEAN                 UpdateCachedLogPageInfo;
    UCHAR                   Reserved[3];
} AHCI_DEVICE_EXTENSION, *PAHCI_DEVICE_EXTENSION;

typedef struct _AHCI_DEVICE_LOG_PAGE_INFO {

    ATA_GPL_PAGES_TO_QUERY  QueryLogPages;

    ATA_SUPPORTED_GPL_PAGES SupportedGPLPages;
    ATA_COMMAND_SUPPORTED   SupportedCommands;

    DOWNLOAD_MICROCODE_CAPABILITIES FirmwareUpdate;

} AHCI_DEVICE_LOG_PAGE_INFO, *PAHCI_DEVICE_LOG_PAGE_INFO;

typedef struct _COMMAND_HISTORY {
    union {                              //0x10 bytes
        ATA_TASK_FILE InitialTaskFile;
        UCHAR         Cdb[16];
    };
    ULONG InitialPx[0x10];               //0x40 bytes
    ULONG CompletionPx[0x10];

    AHCI_D2H_REGISTER_FIS CompletionFIS; //0x14 bytes
    ULONG Tag;
    ULONG Function;
    ULONG SrbStatus;
} COMMAND_HISTORY, *PCOMMAND_HISTORY;

typedef struct _SLOT_STATE_FLAGS {
    UCHAR FUA :1;
    UCHAR Reserved :7;
} SLOT_STATE_FLAGS, *PSLOT_STATE_FLAGS;


typedef struct _SLOT_CONTENT {
    UCHAR                   CommandHistoryIndex;
    SLOT_STATE_FLAGS        StateFlags;
    UCHAR                   Reserved0[2];
    PSTORAGE_REQUEST_BLOCK  Srb;
    PAHCI_COMMAND_HEADER    CmdHeader;
    PVOID                   Reserved;
} SLOT_CONTENT, *PSLOT_CONTENT;

#pragma pack(1)
typedef struct _ACPI_GTF_IDE_REGISTERS {
    UCHAR    FeaturesReg;
    UCHAR    SectorCountReg;
    UCHAR    SectorNumberReg;
    UCHAR    CylLowReg;
    UCHAR    CylHighReg;
    UCHAR    DriveHeadReg;
    UCHAR    CommandReg;
} ACPI_GTF_IDE_REGISTERS, *PACPI_GTF_IDE_REGISTERS;
#pragma pack()

typedef struct _AHCI_DEVICE_INIT_COMMANDS {
    UCHAR           CommandCount;       // count of total commands, mainly used to allocate memory for CommandTaskFile
    UCHAR           ValidCommandCount;  // count of valid commands
    UCHAR           CommandToSend;      // command index indicating which command is to be sent
    PATA_TASK_FILE  CommandTaskFile;    // commands
} AHCI_DEVICE_INIT_COMMANDS, *PAHCI_DEVICE_INIT_COMMANDS;


typedef struct _SET_FEATURE_PARAMS {
    UCHAR Features;
    UCHAR SectorCount;
} SET_FEATURE_PARAMS, *PSET_FEATURE_PARAMS;

typedef struct _PERSISTENT_SETTINGS {
    ULONG Slots;
    ULONG SlotsToSend;
    SET_FEATURE_PARAMS CommandParams[MAX_SETTINGS_PRESERVED];
} PERSISTENT_SETTINGS, *PPERSISTENT_SETTINGS;

typedef struct _CHANNEL_START_STATE {
    UCHAR  ChannelNextStartState;
    UCHAR  ChannelStateDETCount;
    UCHAR  ChannelStateDET1Count;
    UCHAR  ChannelStateDET3Count;
    UCHAR  ChannelStateFRECount;
    UCHAR  AtDIRQL : 1;
    UCHAR  DirectStartInProcess : 1;
    UCHAR  Reserved : 6;
    USHORT ChannelStateBSYDRQCount;
} CHANNEL_START_STATE, *PCHANNEL_START_STATE;

typedef VOID
(*PSRB_COMPLETION_ROUTINE) (
    _In_ PAHCI_CHANNEL_EXTENSION    ChannelExtension,
    _In_opt_ PSTORAGE_REQUEST_BLOCK Srb
    );

typedef struct _LOCAL_SCATTER_GATHER_LIST {
    ULONG                       NumberOfElements;
    ULONG_PTR                   Reserved;
    _Field_size_(NumberOfElements)
    STOR_SCATTER_GATHER_ELEMENT List[257];
} LOCAL_SCATTER_GATHER_LIST, *PLOCAL_SCATTER_GATHER_LIST;

//
// Note: When adding new members to AHCI SRB extension, make sure the uncached extension allocation
//       is successful in dump mode because there is MAX size limitation.
//
typedef struct _AHCI_SRB_EXTENSION {
    AHCI_COMMAND_TABLE CommandTable;        // this field MUST to be the first one as it's asked to be 128 aligned
    USHORT             AtaFunction;         // if this field is 0, it means the command does not need to be sent to device
    UCHAR              AtaStatus;
    UCHAR              AtaError;
    ULONG              Flags;
    union {
        ATA_TASK_FILE           TaskFile;       // for ATA device
        CDB                     Cdb;            // for ATAPI device
        AHCI_H2D_REGISTER_FIS   Cfis;           // info related to Host to Device FIS (0x27) 
    };
    PVOID              DataBuffer;          // go with Cdb field when needed.
    STOR_PHYSICAL_ADDRESS DataBufferPhysicalAddress; // Physical address of DataBuffer.
    ULONG              DataTransferLength;  // go with Cdb field when needed.
    PLOCAL_SCATTER_GATHER_LIST  Sgl;        // pointer to the local or port provided SGL
    LOCAL_SCATTER_GATHER_LIST   LocalSgl;   // local SGL
    PSRB_COMPLETION_ROUTINE CompletionRoutine;   // go with Cdb field when needed.
    PVOID                   CompletionContext;   // context information for completionRoutine
    UCHAR              QueueTag;            // for AHCI controller slots
    UCHAR              RetryCount;          // how many times the command has been retired
    ULONGLONG          StartTime;

    PVOID               ResultBuffer;       // for requests marked with ATA_FLAGS_RETURN_RESULTS
    STOR_PHYSICAL_ADDRESS ResultBufferPhysicalAddress; // Physical address of ResultBuffer.
    ULONG               ResultBufferLength;
} AHCI_SRB_EXTENSION, *PAHCI_SRB_EXTENSION;

typedef struct _LOCAL_COMMAND {
    SCSI_REQUEST_BLOCK      Srb;
    PAHCI_SRB_EXTENSION     SrbExtension;
    STOR_PHYSICAL_ADDRESS   SrbExtensionPhysicalAddress;
} LOCAL_COMMAND, *PLOCAL_COMMAND;

typedef enum {
    CallbackTypeNone = 0,       //not used
    CallbackTypeStartPort,
    CallbackTypeLPM,
    CallbackTypeMax             //count
} TIMER_CALLBACK_TYPE;

typedef
BOOLEAN
(*PAHCI_TIMER_CALLBACK) (
    _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension,
    _In_ PVOID Context
    );

typedef struct _STORAHCI_QUEUE {
    PVOID Head;
    PVOID Tail;
    ULONG CurrentDepth;
    ULONG DeepestDepth;
    ULONG DepthHistoryIndex;
    ULONG DepthHistory[100];
    LARGE_INTEGER LastTimeStampAddQueue;
    LARGE_INTEGER LastTimeStampRemoveQueue;
} STORAHCI_QUEUE, *PSTORAHCI_QUEUE;

typedef struct _AHCI_ADAPTER_EXTENSION  AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION;

//
// Note: When adding new members to AHCI channel extension, make sure the uncached extension allocation
//       is successful in dump mode because there is MAX size limitation.
//
typedef struct _AHCI_CHANNEL_EXTENSION {
//Adapter Characteristics
    PAHCI_ADAPTER_EXTENSION AdapterExtension;

//Device Characteristics
    AHCI_DEVICE_EXTENSION   DeviceExtension[1];

//Channel Characteristics
    ULONG                   PortNumber;
    ULONG                   PortProperties;               // See PORT_PROPERTIES_XYZ definitions above in this file.

//Channel State
    CHANNEL_START_STATE     StartState;
    CHANNEL_STATE_FLAGS     StateFlags;
    CHANNEL_REGISTRY_FLAGS  RegistryFlags;

    UCHAR                   MaxPortQueueDepth;
    UCHAR                   CurrentCommandSlot;           // miniport driver use to remember which slot to put command in.
    UCHAR                   LastActiveSlot;
    UCHAR                   LastUserLpmPowerSetting;      // bit 0: HIPM; bit 1: DIPM

    ULONG                   AutoPartialToSlumberInterval; // in milliSeconds, max: 300,000 (5 minutes)

    AHCI_TASK_FILE_DATA     TaskFileData;

// Port runtime power management
    PSTOR_POFX_DEVICE_V3    PoFxDevice;
    UCHAR                   PoFxFState;         // Current F-State of the unit
    STOR_DEVICE_POWER_STATE DevicePowerState;   // Current D-State of the unit.
    
    //
    // AutoPartialToSlumber statistics to aid in debugging.
    //
    struct {
        ULONG InterfaceNotReady;    // Number of times the interface was no ready (CMD.ICC != 0)
        ULONG InterfaceReady;       // Number of times the interface was ready (CMD.ICC == 0)
        ULONG ActiveFailCount;      // Number of times we failed to go to Active
        ULONG ActiveSuccessCount;   // Number of times we succeeded in going to Active
        ULONG SlumberFailCount;     // Number of times we failed to go to Slumber
        ULONG SlumberSuccessCount;  // Number of times we succeeded in going to Slumber
    } AutoPartialToSlumberDbgStats;



    struct {
        ULONG RestorePreservedSettings :1;  //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 0) is used there.
        ULONG BusChange :1;                 //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 1) is used there.

        ULONG Reserved: 30;
    } PoFxPendingWork;

//IO
    SLOT_MANAGER            SlotManager;
    SLOT_CONTENT            Slot[AHCI_MAX_NCQ_REQUEST_COUNT];

//IO Completion Queue and DPC
    STORAHCI_QUEUE          CompletionQueue;
    STOR_DPC                CompletionDpc;

//DPC to handle hotplug notification
    STOR_DPC                BusChangeDpc;

//AHCI defined register interface structures
    PAHCI_PORT              Px;
    PAHCI_COMMAND_HEADER    CommandList;
    PAHCI_RECEIVED_FIS      ReceivedFIS;
    STOR_PHYSICAL_ADDRESS   CommandListPhysicalAddress;
    STOR_PHYSICAL_ADDRESS   ReceivedFisPhysicalAddress;

//Local Command Structures
    LOCAL_COMMAND               Local;
    LOCAL_COMMAND               Sense;              // used to retrieve Sense Data from ATAPI device; or NCQ Log from ATA device that supports it.

    AHCI_DEVICE_INIT_COMMANDS   DeviceInitCommands;
    PERSISTENT_SETTINGS         PersistentSettings;

//Timer
    PVOID                   StartPortTimer;         // used for the Port Starting process
    PVOID                   WorkerTimer;            // used for LPM management for now
    PVOID                   BusChangeTimer;         // used to manage bus change processing

//Logging
    UCHAR                   CommandHistoryNextAvailableIndex;
    COMMAND_HISTORY         CommandHistory[64];

    UCHAR                   ExecutionHistoryNextAvailableIndex;
    PEXECUTION_HISTORY      ExecutionHistory;       // For non-dump mode, contains MAX_EXECUTION_HISTORY_ENTRY_COUNT elements.

//Statistics counters for telemetry event.
    ULONG                   TotalCountPortReset;
    ULONG                   TotalCountRunningStartFailed;
    ULONG                   TotalCountPortErrorRecovery;
    ULONG                   TotalCountNonQueuedErrorRecovery;
    ULONG                   TotalCountNCQError;
    ULONG                   TotalCountNCQErrorRecoveryComplete;
    ULONG                   TotalCountSurpriseRemove;
    ULONG                   TotalCountPowerSettingNotification;
    ULONGLONG               LastLogResetErrorRecoveryTime;
    ULONG                   TotalCountPowerUp;
    ULONG                   TotalCountPowerDown;
    ULONG                   TotalPortStartTime;
    ULONG                   TotalCountBusChange;
    ULONG                   DeviceFailureThrottleFlag;

//Statistics for tracking DPC.
    LARGE_INTEGER           LastTimeStampDpcStart;
    LARGE_INTEGER           LastTimeStampDpcCompletion;

} AHCI_CHANNEL_EXTENSION, *PAHCI_CHANNEL_EXTENSION;

typedef struct _ADAPTER_STATE_FLAGS {

    ULONG StoppedState : 1;
    ULONG PowerDown : 1;
    ULONG PoFxEnabled : 1;
    ULONG PoFxActive : 1;

    ULONG SupportsAcpiDSM : 1;      // indicates if the system has _DSM method implemented to control port/device power. when the value is 1, the _DSM method at least supports powering on all connected devices.
    ULONG Removed : 1;

    ULONG InterruptMessagePerPort : 1;

    ULONG D3ColdSupported : 1;
    ULONG D3ColdEnabled : 1;
    ULONG UseAdapterF1InsteadOfD3 : 1;
    ULONG Removable : 1;

    ULONG Reserved : 20;

} ADAPTER_STATE_FLAGS, *PADAPTER_STATE_FLAGS;

typedef union _ADAPTER_LOG_FLAGS {

    struct {
        ULONG ExecutionDetail :1;
        ULONG CommandHistory :1;

        ULONG Reserved: 30;
    };

    ULONG AsUlong;

} ADAPTER_LOG_FLAGS, *PADAPTER_LOG_FLAGS;

#define LogCommand(flags)           (flags.CommandHistory != 0)
#define LogExecuteFullDetail(flags) (flags.ExecutionDetail != 0)


typedef struct _AHCI_ADAPTER_EXTENSION {
    ULONG                   AdapterNumber;
    ULONG                   SystemIoBusNumber;
    ULONG                   SlotNumber;
    ULONG                   AhciBaseAddress;    // AHCI Base Address from bus. for example: BAR5 value on PCI bus

    USHORT                  VendorID;
    USHORT                  DeviceID;
    UCHAR                   RevisionID;

// Adapter runtime power management
    PSTOR_POFX_DEVICE_V2    PoFxDevice;
    RAID_SYSTEM_POWER       SystemPowerHintState;
    ULONG                   SystemPowerResumeLatencyMSec;

    struct {
        ULONG AdapterStop :1;    //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 0) is used there.

        ULONG Reserved: 31;
    } PoFxPendingWork;

//Flags
    ADAPTER_STATE_FLAGS     StateFlags;
    ULONG                   ErrorFlags;     // save adapter errors
    ADAPTER_LOG_FLAGS       LogFlags;       // internal log levels
    ADAPTER_REGISTRY_FLAGS  RegistryFlags;

//adapter attributes
    ULONG                   PortImplemented;
    ULONG                   HighestPort;
    ULONG                   LastInterruptedPort;

    UCHAR                   DumpMode;
    BOOLEAN                 InRunningPortsProcess;  //in process of starting every implemented ports
    BOOLEAN                 TracingEnabled;

//Memory structures
    PAHCI_MEMORY_REGISTERS  ABAR_Address;           //mapped AHCI Base Address. StorAHCI uses this field to control the adapter and ports.
    AHCI_VERSION            Version;

    PULONG                  IS;
    AHCI_HBA_CAPABILITIES   CAP;
    AHCI_HBA_CAPABILITIES2  CAP2;

//Channel Extensions
    PAHCI_CHANNEL_EXTENSION PortExtension[AHCI_MAX_PORT_COUNT];

//nonCacheExtension
    PVOID                   NonCachedExtension;

//buffer to preserve MSI message affinity information.
    PGROUP_AFFINITY         MessageGroupAffinity;

} AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION;

// information that will be transferred to dump/hibernate environment

typedef struct _AHCI_DUMP_PORT_CONTEXT {

    ULONG                            PortNumber;
    CHANNEL_REGISTRY_FLAGS           PortRegistryFlags;

    //
    // Hybrid Disk Information Log
    //
    GP_LOG_HYBRID_INFORMATION_HEADER HybridInfo;

} AHCI_DUMP_PORT_CONTEXT, *PAHCI_DUMP_PORT_CONTEXT;

typedef struct _AHCI_DUMP_CONTEXT {
    // adapter information
    USHORT                  VendorID;
    USHORT                  DeviceID;
    UCHAR                   RevisionID;
    UCHAR                   Reserved[3];

    ULONG                   AhciBaseAddress;

    ADAPTER_LOG_FLAGS       LogFlags;       // internal log levels
    ADAPTER_REGISTRY_FLAGS  AdapterRegistryFlags;

    //
    // Device telemetry descriptors for the boot device
    //
    ULONG                   PublicGPLogTableAddresses[TC_PUBLIC_DEVICEDUMP_CONTENT_GPLOG_MAX];
    ULONG                   PrivateGPLogPageAddress;

    //
    // Port information of dump devices
    //
    ULONG                   PortCount;
    AHCI_DUMP_PORT_CONTEXT  Ports[1];

} AHCI_DUMP_CONTEXT, *PAHCI_DUMP_CONTEXT;

typedef struct _ATA_COMMAND_ERROR_LOG {
    ULONG Version;
    ULONG Size;
    CHANNEL_STATE_FLAGS StateFlags;
    CHANNEL_START_STATE StartState;
    STORAGE_REQUEST_BLOCK Srb;
    CDB Cdb; // To differentiate SRBs if the struct is reused
    UCHAR Command; // ATA taksfile/AHCI FIS payload
    UCHAR AtaStatus;
    UCHAR AtaError;
} ATA_COMMAND_ERROR, *PATA_COMMAND_ERROR;


// Storport miniport driver entry routines, with prefix: "AhciHw"
sp_DRIVER_INITIALIZE DriverEntry;

HW_FIND_ADAPTER AhciHwFindAdapter;

HW_INITIALIZE AhciHwInitialize;

HW_PASSIVE_INITIALIZE_ROUTINE AhciHwPassiveInitialize;

HW_STARTIO AhciHwStartIo;

HW_BUILDIO AhciHwBuildIo;

HW_INTERRUPT AhciHwInterrupt;

HW_RESET_BUS AhciHwResetBus;

HW_ADAPTER_CONTROL AhciHwAdapterControl;

HW_TRACING_ENABLED AhciHwTracingEnabled;

HW_UNIT_CONTROL AhciHwUnitControl;


BOOLEAN
AhciHwMSIInterrupt (
    _In_ PVOID AdapterExtension,
    _In_ ULONG MessageId
    );

VOID
AhciDeviceStart (
    _In_ PAHCI_CHANNEL_EXTENSION ChannelExtension
    );

//
// References to globals
//
//
// Device telemetry descriptors for the boot device
//
extern ULONG AhciPublicGPLogTableAddresses[TC_PUBLIC_DEVICEDUMP_CONTENT_GPLOG_MAX];
extern ULONG AhciGPLogPageIntoPrivate;

#if _MSC_VER >= 1200
#pragma warning(pop)
#else
#pragma warning(default:4214)
#pragma warning(default:4201)
#endif