├── README.md ├── StorPortPatch.c ├── StorPortPatch.h ├── ahci.h ├── common.c ├── common.h ├── entrypts.c ├── entrypts.h ├── genahci.inf ├── genahci.rc ├── generic.h ├── gpl.txt ├── hbastat.c ├── hbastat.h ├── io.c ├── io.h ├── make_chk.cmd ├── make_fre.cmd ├── makefile ├── pnppower.c ├── pnppower.h ├── sources ├── srb_helper.h ├── stor_helper.h ├── txtsetup.oem ├── util.c └── util.h /README.md: -------------------------------------------------------------------------------- 1 | # GenAHCI 6.3.0.1 2 | 3 | GenAHCI is storage driver replacement for Windows XP, Vista, 7, 8.0 and their Server equivalents based on official Windows 8.1 StorAHCI source code sample. 4 | https://github.com/microsoftarchive/msdn-code-gallery-microsoft/tree/master/Official%20Windows%20Driver%20Kit%20Sample/Windows%20Driver%20Kit%20(WDK)%208.1%20Samples/%5BC%2B%2B%5D-windows-driver-kit-81-cpp/WDK%208.1%20C%2B%2B%20Samples/StorAhci%20StorPort%20Miniport%20Driver/C%2B%2B 5 | 6 | This patched source code is based on previously developed patch for Windows 8.0 source code sample by Kai Schtrom 7 | https://sourceforge.net/projects/storahci-for-windows-2003/ 8 | 9 | Even it looks like Windows 8.0 to 8.1 is small step, driver code was changed on many places. Almost everything was patched to be compatible with Windows XP and driver can be succesfully installed or integrated into Windows Setup 10 | -------------------------------------------------------------------------------- /StorPortPatch.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | ******************************************************************************* 4 | ** Copyright (C) 2020 Kai Schtrom ** 5 | ** ** 6 | ** All rights reserved. ** 7 | ** ** 8 | ******************************************************************************* 9 | ** ** 10 | ** Redistribution and use in source and binary forms, with or without ** 11 | ** modification, are permitted provided that the following conditions are ** 12 | ** met: ** 13 | ** ** 14 | ** 1. Redistributions of source code must retain the above copyright ** 15 | ** notice, this list of conditions and the following disclaimer. ** 16 | ** ** 17 | ** 2. Redistributions in binary form must reproduce the above copyright ** 18 | ** notice, this list of conditions and the following disclaimer in the ** 19 | ** documentation and/or other materials provided with the distribution. ** 20 | ** ** 21 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS ** 22 | ** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ** 23 | ** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ** 24 | ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ** 25 | ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT,INDIRECT, INCIDENTAL, SPECIAL, ** 26 | ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ** 27 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ** 28 | ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ** 29 | ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ** 30 | ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** 31 | ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** 32 | ** ** 33 | ** The views and conclusions contained in the software and documentation ** 34 | ** are those of the authors and should not be interpreted as representing ** 35 | ** official policies, either expressed or implied, of Intel Corporation, ** 36 | ** Integrated Device Technology Inc., or Sandforce Corporation. ** 37 | ** ** 38 | ******************************************************************************* 39 | **/ 40 | 41 | /* 42 | * File: StorPortPatch.c 43 | */ 44 | 45 | #include 46 | #include ".\inc\ddk\storport.h" 47 | #include 48 | 49 | 50 | //------------------------------------------------------------------------------ 51 | // StorpAllocatePool -> function code 0 52 | //------------------------------------------------------------------------------ 53 | ULONG StorpAllocatePool(__in PVOID HwDeviceExtension,__in ULONG NumberOfBytes,__in ULONG Tag,PVOID *BufferPointer) 54 | { 55 | UNREFERENCED_PARAMETER(HwDeviceExtension); 56 | 57 | if(BufferPointer == NULL) 58 | { 59 | return STOR_STATUS_INVALID_PARAMETER; 60 | } 61 | 62 | *BufferPointer = NULL; 63 | 64 | *BufferPointer = ExAllocatePoolWithTag(NonPagedPool,NumberOfBytes,Tag); 65 | if(*BufferPointer == NULL) 66 | { 67 | return STOR_STATUS_INSUFFICIENT_RESOURCES; 68 | } 69 | 70 | return STOR_STATUS_SUCCESS; 71 | } 72 | 73 | 74 | //------------------------------------------------------------------------------ 75 | // StorpFreePool -> function code 1 76 | //------------------------------------------------------------------------------ 77 | ULONG StorpFreePool(__in PVOID HwDeviceExtension,__in PVOID BufferPointer) 78 | { 79 | UNREFERENCED_PARAMETER(HwDeviceExtension); 80 | 81 | if(BufferPointer == NULL) 82 | { 83 | return STOR_STATUS_INVALID_PARAMETER; 84 | } 85 | 86 | ExFreePoolWithTag(BufferPointer,0); 87 | 88 | return STOR_STATUS_SUCCESS; 89 | } 90 | 91 | 92 | //------------------------------------------------------------------------------ 93 | // StorpAllocateContiguousMemorySpecifyCacheNode -> function code 24 94 | //------------------------------------------------------------------------------ 95 | ULONG StorpAllocateContiguousMemorySpecifyCacheNode(__in PVOID HwDeviceExtension,__in SIZE_T NumberOfBytes,__in PHYSICAL_ADDRESS LowestAcceptableAddress,__in PHYSICAL_ADDRESS HighestAcceptableAddress,__in_opt PHYSICAL_ADDRESS BoundaryAddressMultiple,__in MEMORY_CACHING_TYPE CacheType,__in NODE_REQUIREMENT PreferredNode,PVOID* BufferPointer) 96 | { 97 | UNREFERENCED_PARAMETER(HwDeviceExtension); 98 | UNREFERENCED_PARAMETER(PreferredNode); 99 | 100 | if(BufferPointer == NULL) 101 | { 102 | return STOR_STATUS_INVALID_PARAMETER; 103 | } 104 | 105 | *BufferPointer = NULL; 106 | 107 | // we can not use MmAllocateContiguousMemorySpecifyCacheNode for Windows Server 2003, because the minimum target OS is Windows Vista 108 | *BufferPointer = MmAllocateContiguousMemorySpecifyCache(NumberOfBytes,LowestAcceptableAddress,HighestAcceptableAddress,BoundaryAddressMultiple,CacheType); 109 | if(*BufferPointer == NULL) 110 | { 111 | return STOR_STATUS_INSUFFICIENT_RESOURCES; 112 | } 113 | 114 | return STOR_STATUS_SUCCESS; 115 | } 116 | 117 | 118 | //------------------------------------------------------------------------------ 119 | // StorpFreeContiguousMemorySpecifyCache -> function code 25 120 | //------------------------------------------------------------------------------ 121 | ULONG StorpFreeContiguousMemorySpecifyCache(__in PVOID HwDeviceExtension,__in_bcount (NumberOfBytes) PVOID BaseAddress,__in SIZE_T NumberOfBytes,__in MEMORY_CACHING_TYPE CacheType) 122 | { 123 | UNREFERENCED_PARAMETER(HwDeviceExtension); 124 | 125 | MmFreeContiguousMemorySpecifyCache(BaseAddress,NumberOfBytes,CacheType); 126 | 127 | return STOR_STATUS_SUCCESS; 128 | } 129 | 130 | 131 | //------------------------------------------------------------------------------ 132 | // StorpInitializeTimer -> function code 32 133 | //------------------------------------------------------------------------------ 134 | ULONG StorpInitializeTimer(__in PVOID HwDeviceExtension,__out PVOID *TimerHandle) 135 | { 136 | UNREFERENCED_PARAMETER(HwDeviceExtension); 137 | UNREFERENCED_PARAMETER(TimerHandle); 138 | 139 | // without success status we run into an NT_ASSERT 140 | return STOR_STATUS_SUCCESS; 141 | } 142 | 143 | 144 | //------------------------------------------------------------------------------ 145 | // StorpFreeTimer -> function code 34 146 | //------------------------------------------------------------------------------ 147 | ULONG StorpFreeTimer(__in PVOID HwDeviceExtension,__in PVOID TimerHandle) 148 | { 149 | UNREFERENCED_PARAMETER(HwDeviceExtension); 150 | UNREFERENCED_PARAMETER(TimerHandle); 151 | 152 | // without success status we run into an NT_ASSERT 153 | return STOR_STATUS_SUCCESS; 154 | } 155 | 156 | 157 | //------------------------------------------------------------------------------ 158 | // StorPortExtendedFunction 159 | //------------------------------------------------------------------------------ 160 | ULONG StorPortPatchExtendedFunction(__in STORPORT_FUNCTION_CODE FunctionCode,__in PVOID HwDeviceExtension,...) 161 | { 162 | ULONG status; 163 | va_list argptr; 164 | 165 | if(HwDeviceExtension == NULL) 166 | { 167 | return STOR_STATUS_INVALID_PARAMETER; 168 | } 169 | 170 | #if DBG 171 | DbgPrint("StorPortPatchExtendedFunction: Function code %d\n",FunctionCode); 172 | #endif 173 | 174 | va_start(argptr,HwDeviceExtension); 175 | 176 | switch(FunctionCode) 177 | { 178 | // without handling this function code we can not allocate memory 179 | // function code 0 180 | case ExtFunctionAllocatePool: 181 | { 182 | ULONG NumberOfBytes; 183 | ULONG Tag; 184 | PVOID *BufferPointer; 185 | NumberOfBytes = va_arg(argptr,ULONG); 186 | Tag = va_arg(argptr,ULONG); 187 | BufferPointer = va_arg(argptr,PVOID*); 188 | 189 | status = StorpAllocatePool(HwDeviceExtension,NumberOfBytes,Tag,BufferPointer); 190 | break; 191 | } 192 | // without handling this function code we can not free memory 193 | // function code 1 194 | case ExtFunctionFreePool: 195 | { 196 | PVOID BufferPointer; 197 | BufferPointer = va_arg(argptr,PVOID); 198 | 199 | status = StorpFreePool(HwDeviceExtension,BufferPointer); 200 | break; 201 | } 202 | // without handling this function code we can not allocate a range of physically contiguous and cache aligned memory 203 | // function code 24 204 | case ExtFunctionAllocateContiguousMemorySpecifyCacheNode: 205 | { 206 | SIZE_T NumberOfBytes; 207 | PHYSICAL_ADDRESS LowestAcceptableAddress; 208 | PHYSICAL_ADDRESS HighestAcceptableAddress; 209 | PHYSICAL_ADDRESS BoundaryAddressMultiple; 210 | MEMORY_CACHING_TYPE CacheType; 211 | NODE_REQUIREMENT PreferredNode; 212 | PVOID* BufferPointer; 213 | NumberOfBytes = va_arg(argptr,SIZE_T); 214 | LowestAcceptableAddress = va_arg(argptr,PHYSICAL_ADDRESS); 215 | HighestAcceptableAddress = va_arg(argptr,PHYSICAL_ADDRESS); 216 | BoundaryAddressMultiple = va_arg(argptr,PHYSICAL_ADDRESS); 217 | CacheType = va_arg(argptr,MEMORY_CACHING_TYPE); 218 | PreferredNode = va_arg(argptr,NODE_REQUIREMENT); 219 | BufferPointer = va_arg(argptr,PVOID*); 220 | 221 | status = StorpAllocateContiguousMemorySpecifyCacheNode(HwDeviceExtension,NumberOfBytes,LowestAcceptableAddress,HighestAcceptableAddress,BoundaryAddressMultiple,CacheType,PreferredNode,BufferPointer); 222 | break; 223 | } 224 | // without handling this function code we can not free a range of physically contiguous and cache aligned memory 225 | // function code 25 226 | case ExtFunctionFreeContiguousMemorySpecifyCache: 227 | { 228 | PVOID BaseAddress; 229 | SIZE_T NumberOfBytes; 230 | MEMORY_CACHING_TYPE CacheType; 231 | BaseAddress = va_arg(argptr,PVOID); 232 | NumberOfBytes = va_arg(argptr,SIZE_T); 233 | CacheType = va_arg(argptr,MEMORY_CACHING_TYPE); 234 | 235 | status = StorpFreeContiguousMemorySpecifyCache(HwDeviceExtension,BaseAddress,NumberOfBytes,CacheType); 236 | break; 237 | } 238 | // without handling this function code we run into an NT_ASSERT 239 | // function code 32 240 | case ExtFunctionInitializeTimer: 241 | { 242 | PVOID *TimerHandle; 243 | TimerHandle = va_arg(argptr,PVOID*); 244 | 245 | status = StorpInitializeTimer(HwDeviceExtension,TimerHandle); 246 | break; 247 | } 248 | // without handling this function code we run into an NT_ASSERT 249 | // function code 34 250 | case ExtFunctionFreeTimer: 251 | { 252 | PVOID TimerHandle; 253 | TimerHandle = va_arg(argptr,PVOID); 254 | 255 | status = StorpFreeTimer(HwDeviceExtension,TimerHandle); 256 | break; 257 | } 258 | // all other function codes go here 259 | default: 260 | { 261 | #if DBG 262 | DbgPrint("StorPortPatchExtendedFunction: Unknown function code %d\n",FunctionCode); 263 | #endif 264 | // we handle all other function codes as not implemented 265 | status = STOR_STATUS_NOT_IMPLEMENTED; 266 | break; 267 | } 268 | } 269 | 270 | va_end(argptr); 271 | return status; 272 | } 273 | 274 | -------------------------------------------------------------------------------- /StorPortPatch.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | ******************************************************************************* 4 | ** Copyright (C) 2020 Kai Schtrom ** 5 | ** ** 6 | ** All rights reserved. ** 7 | ** ** 8 | ******************************************************************************* 9 | ** ** 10 | ** Redistribution and use in source and binary forms, with or without ** 11 | ** modification, are permitted provided that the following conditions are ** 12 | ** met: ** 13 | ** ** 14 | ** 1. Redistributions of source code must retain the above copyright ** 15 | ** notice, this list of conditions and the following disclaimer. ** 16 | ** ** 17 | ** 2. Redistributions in binary form must reproduce the above copyright ** 18 | ** notice, this list of conditions and the following disclaimer in the ** 19 | ** documentation and/or other materials provided with the distribution. ** 20 | ** ** 21 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS ** 22 | ** IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, ** 23 | ** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR ** 24 | ** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ** 25 | ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT,INDIRECT, INCIDENTAL, SPECIAL, ** 26 | ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, ** 27 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR ** 28 | ** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ** 29 | ** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ** 30 | ** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** 31 | ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** 32 | ** ** 33 | ** The views and conclusions contained in the software and documentation ** 34 | ** are those of the authors and should not be interpreted as representing ** 35 | ** official policies, either expressed or implied, of Intel Corporation, ** 36 | ** Integrated Device Technology Inc., or Sandforce Corporation. ** 37 | ** ** 38 | ******************************************************************************* 39 | **/ 40 | 41 | /* 42 | * File: StorPortPatch.h 43 | */ 44 | 45 | #ifndef __STOR_PORT_PATCH_H__ 46 | #define __STOR_PORT_PATCH_H__ 47 | 48 | // our replacement function for StorPortExtendedFunction 49 | ULONG StorPortPatchExtendedFunction(__in STORPORT_FUNCTION_CODE FunctionCode,__in PVOID HwDeviceExtension,...); 50 | 51 | #endif /* __STOR_PORT_PATCH_H__ */ 52 | 53 | -------------------------------------------------------------------------------- /ahci.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeorgeK1ng/GenAHCI/b936a0d8bdf410928aefa9e0f373fb1d6c7c8240/ahci.h -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (C) Microsoft Corporation, 2009 4 | 5 | Module Name: 6 | 7 | common.h 8 | 9 | Abstract: 10 | 11 | Common functions that might be moved to port lib 12 | 13 | Notes: 14 | 15 | Revision History: 16 | 17 | Michael Xing (xiaoxing), December 2009 18 | --*/ 19 | 20 | #pragma once 21 | 22 | #if _MSC_VER >= 1200 23 | #pragma warning(push) 24 | #endif 25 | 26 | #pragma warning(disable:4214) // bit field types other than int 27 | #pragma warning(disable:4201) // nameless struct/union 28 | 29 | #define ATA_BLOCK_SIZE 512 //0x200 30 | 31 | //#define MAXULONG 0xFFFFFFFF // winnt 32 | 33 | #define ATA_INQUIRYDATA_SIZE 0x3C // contains 1 Version Descriptor for 1667 34 | 35 | #define DEFAULT_DSM_DATA_SIZE_CAP_IN_BLOCKS 0x8 36 | 37 | // per ATA spec, the SectorCount value range is 1 - 0xffff. 0 means this entry is not valid. 38 | #define MAX_ATA_LBA_RANGE_SECTOR_COUNT_VALUE 0xFFFF 39 | 40 | // Max of LBAs that can be represented using 28 bits. 41 | #define MAX_28BIT_LBA (1 << 28) 42 | 43 | 44 | #define NVC_ATA_NV_CACHE_COMMAND 0xB6 45 | 46 | #define IDE_FEATURE_INVALID 0xFF 47 | 48 | 49 | // 50 | // ATA function code 51 | // 52 | 53 | // 0x100 - 0x1FF indicate ATA commands 54 | #define ATA_FUNCTION_ATA_COMMAND 0x100 55 | #define ATA_FUNCTION_ATA_IDENTIFY 0x101 56 | #define ATA_FUNCTION_ATA_READ 0x102 57 | #define ATA_FUNCTION_ATA_WRITE 0x103 58 | #define ATA_FUNCTION_ATA_FLUSH 0x104 59 | #define ATA_FUNCTION_ATA_SMART 0x105 60 | #define ATA_FUNCTION_ATA_HINT_PAYLOAD 0x106 61 | 62 | // 0x200 - 0x2FF indicate ATAPI commands 63 | #define ATA_FUNCTION_ATAPI_COMMAND 0x200 64 | #define ATA_FUNCTION_REQUEST_SENSE 0x201 65 | 66 | // 0x400 - 0x4FF indicate SATA CFIS format 67 | #define ATA_FUNCTION_ATA_CFIS_PAYLOAD 0x400 68 | 69 | // 70 | // ATA flags 71 | // 72 | 73 | /* defined in ntscsi.h 74 | #define ATA_FLAGS_DRDY_REQUIRED (1 << 0) 75 | #define ATA_FLAGS_DATA_IN (1 << 1) 76 | #define ATA_FLAGS_DATA_OUT (1 << 2) 77 | #define ATA_FLAGS_48BIT_COMMAND (1 << 3) 78 | #define ATA_FLAGS_USE_DMA (1 << 4) 79 | #define ATA_FLAGS_NO_MULTIPLE (1 << 5) 80 | */ 81 | 82 | #define ATA_FLAGS_RETURN_RESULTS (1 << 6) // task file should be copied back into SenseInfoBuffer 83 | #define ATA_FLAGS_HIGH_PRIORITY (1 << 7) // the request should be processed as a high priority request 84 | #define ATA_FLAGS_NEW_CDB (1 << 8) // new CDB in SrbExtension should be issued to device rather than CDB in Srb 85 | #define ATA_FLAGS_COMPLETE_SRB (1 << 9) // indicates the Srb should be completed, AhciCompleteRequest will not send command from SrbExtension. 86 | #define ATA_FLAGS_ACTIVE_REFERENCE (1 << 10) // indicates Active Reference needs to be acquired before processing the Srb and released after processing the Srb 87 | 88 | // 89 | // helper macros 90 | // 91 | #define IsAtaCommand(AtaFunction) (AtaFunction & ATA_FUNCTION_ATA_COMMAND) 92 | #define IsAtapiCommand(AtaFunction) (AtaFunction & ATA_FUNCTION_ATAPI_COMMAND) 93 | #define IsRequestSenseSrb(AtaFunction) (AtaFunction == ATA_FUNCTION_REQUEST_SENSE) 94 | #define IsAtaCfisPayload(AtaFunction) (AtaFunction == ATA_FUNCTION_ATA_CFIS_PAYLOAD) 95 | 96 | #define IsReturnResults(AtaFlags) (AtaFlags & ATA_FLAGS_RETURN_RESULTS) 97 | #define IsNewCdbUsed(AtaFlags) (AtaFlags & ATA_FLAGS_NEW_CDB) 98 | #define Is48BitCommand(AtaFlags) (AtaFlags & ATA_FLAGS_48BIT_COMMAND) 99 | #define IsHighPriorityCommand(AtaFlags) (AtaFlags & ATA_FLAGS_HIGH_PRIORITY) 100 | #define IsDmaCommand(AtaFlags) (AtaFlags & ATA_FLAGS_USE_DMA) 101 | #define SrbShouldBeCompleted(AtaFlags) (AtaFlags & ATA_FLAGS_COMPLETE_SRB) 102 | 103 | 104 | #define CLRMASK(x, mask) ((x) &= ~(mask)); 105 | #define SETMASK(x, mask) ((x) |= (mask)); 106 | 107 | typedef enum _AHCI_ETW_EVENT_IDS { 108 | AhciEtwEventSystemPowerHint = 0 109 | } AHCI_ETW_EVENT_IDS, *PAHCI_ETW_EVENT_IDS; 110 | 111 | 112 | // 113 | // task file register contents 114 | // 115 | #include 116 | typedef struct _ATAREGISTERS { 117 | 118 | // ATA features/error register 119 | UCHAR bFeaturesReg; 120 | 121 | // sector count 122 | UCHAR bSectorCountReg; 123 | 124 | // block number (7:0) 125 | UCHAR bSectorNumberReg; 126 | 127 | // cylinder number (7:0) or LBA (15:8) 128 | UCHAR bCylLowReg; 129 | 130 | // cylinder number (15:8) or LBA (23:16) 131 | UCHAR bCylHighReg; 132 | 133 | // device/Head and LBA (27:24) 134 | UCHAR bDriveHeadReg; 135 | 136 | // command/status register 137 | UCHAR bCommandReg; 138 | 139 | // Reserved for future use. Shall be 0 140 | UCHAR bReserved; 141 | 142 | } ATAREGISTERS, *PATAREGISTERS; 143 | #include 144 | 145 | // 146 | // task file (to hold 48 bit) 147 | // 148 | typedef struct _ATA_TASK_FILE { 149 | ATAREGISTERS Current; 150 | ATAREGISTERS Previous; 151 | } ATA_TASK_FILE, *PATA_TASK_FILE; 152 | 153 | // helper functions for setting TaskFile fields 154 | #define SetFeaturesReg(reg, val) (reg->bFeaturesReg = val) 155 | #define SetSectorCount(reg, val) (reg->bSectorCountReg = val) 156 | #define SetSectorNumber(reg, val) (reg->bSectorNumberReg = val) 157 | #define SetCylinderLow(reg, val) (reg->bCylLowReg = val) 158 | #define SetCylinderHigh(reg, val) (reg->bCylHighReg = val) 159 | #define SetDeviceReg(reg, val) (reg->bDriveHeadReg |= (0xA0 | val)) // only have Device0 for SATA 160 | #define SetCommandReg(reg, val) (reg->bCommandReg = val) 161 | 162 | #define ATA_NCQ_FUA_BIT (1 << 7) 163 | 164 | // 165 | // Device type 166 | // 167 | typedef enum { 168 | DeviceUnknown = 0, 169 | DeviceIsAta, 170 | DeviceIsAtapi, 171 | DeviceNotExist 172 | } ATA_DEVICE_TYPE; 173 | 174 | // 175 | // addressing mode 176 | // 177 | typedef enum { 178 | UnknownMode = 0, 179 | LbaMode, 180 | Lba48BitMode 181 | } ATA_ADDRESS_TRANSLATION; 182 | 183 | 184 | typedef struct _ATA_DEVICE_PARAMETERS { 185 | 186 | ATA_DEVICE_TYPE AtaDeviceType; // device type (ata, atapi etc) 187 | UCHAR ScsiDeviceType; // Scsi device type from inquiry data; Ata device: DIRECT_ACCESS_DEVICE 188 | 189 | UCHAR MaximumLun; 190 | 191 | UCHAR MaxDeviceQueueDepth; // number of requests the device can handle at a time 192 | 193 | struct { 194 | ULONG RemovableMedia: 1; 195 | ULONG SystemPoweringDown: 1; 196 | ULONG FuaSupported: 1; 197 | ULONG FuaSucceeded: 1; 198 | 199 | } StateFlags; 200 | 201 | ULONG BytesPerLogicalSector; 202 | ULONG BytesPerPhysicalSector; 203 | ULONG BytesOffsetForSectorAlignment; 204 | 205 | // Geometry 206 | ATA_ADDRESS_TRANSLATION AddressTranslation; 207 | 208 | LARGE_INTEGER MaxLba; 209 | 210 | // Strings used to construct device ids, +1 for 'NULL' 211 | UCHAR VendorId[40 + 1]; 212 | UCHAR RevisionId[8 + 1]; 213 | UCHAR SerialNumber[20 + 1]; 214 | 215 | // max number of blocks that can be transferred for DSM - Trim command 216 | ULONG DsmCapBlockCount; 217 | 218 | } ATA_DEVICE_PARAMETERS, *PATA_DEVICE_PARAMETERS; 219 | 220 | typedef struct _ATA_LBA_RANGE { 221 | ULONGLONG StartSector:48; 222 | ULONGLONG SectorCount:16; 223 | } ATA_LBA_RANGE, *PATA_LBA_RANGE; 224 | 225 | typedef struct _ATA_TRIM_CONTEXT { 226 | // Block Descriptor for UNMAP request 227 | PUNMAP_BLOCK_DESCRIPTOR BlockDescriptors; 228 | 229 | // Block Descriptor count for UNMAP request 230 | ULONG BlockDescrCount; 231 | 232 | // count of ATA Lba Range entries can be sent by one Trim command 233 | ULONG MaxLbaRangeEntryCountPerCmd; 234 | 235 | // count of ATA Lba Range entries need for an UNMAP request 236 | // max Block Descirptors carried by one Unmap command: 0xFFFE; max ATA Lba Ranges need for a Unmap Block Descriptor: 0xFFFFFFFF/0xFFFF 237 | // ULONG is big enough to hold the value. 238 | ULONG NeededLbaRangeEntryCount; 239 | 240 | // the length of allocated. Need to cache the value for calling AhciFreeDmaBuffer 241 | ULONG AllocatedBufferLength; 242 | 243 | // count of ATA Lba Range entries that already be processed. 244 | ULONG ProcessedLbaRangeEntryCount; 245 | 246 | // current Index of the input UNMAP Block Descriptors 247 | ULONG BlockDescrIndex; 248 | 249 | // current UNMAP Block Descriptor being processed 250 | UNMAP_BLOCK_DESCRIPTOR CurrentBlockDescr; 251 | 252 | } ATA_TRIM_CONTEXT, *PATA_TRIM_CONTEXT; 253 | 254 | typedef struct _HYBRID_CHANGE_BY_LBA_CONTEXT { 255 | // Data Set Ranges of DSM CHANGE BY LBA request 256 | PDEVICE_DATA_SET_RANGE DataSetRanges; 257 | 258 | // Data Set Range count of DSM CHANGE BY LBA request 259 | ULONG DataSetRangeCount; 260 | 261 | // count of ATA Lba Range entries need for one DSM CHANGE BY LBA request 262 | ULONG NeededLbaRangeEntryCount; 263 | 264 | // count of ATA Lba Range entries that already be processed. 265 | ULONG ProcessedLbaRangeEntryCount; 266 | 267 | // current Index of the input Data Set Ranges of DSM CHANGE BY LBA request 268 | ULONG DataSetRangeIndex; 269 | 270 | // current Data Set Range (in sectors) being processed 271 | ULONGLONG CurrentRangeStartLba; 272 | ULONGLONG CurrentRangeLbaCount; 273 | 274 | UCHAR TargetPriority; 275 | UCHAR Reserved[7]; 276 | } HYBRID_CHANGE_BY_LBA_CONTEXT, *PHYBRID_CHANGE_BY_LBA_CONTEXT; 277 | 278 | typedef struct _HYBRID_EVICT_CONTEXT { 279 | // Data Set Ranges of DSM EVICT request 280 | PDEVICE_DATA_SET_RANGE DataSetRanges; 281 | 282 | // Data Set Range count of DSM EVICT request 283 | ULONG DataSetRangeCount; 284 | 285 | // count of ATA Lba Range entries can be sent by one Evict command 286 | ULONG MaxLbaRangeEntryCountPerCmd; 287 | 288 | // count of ATA Lba Range entries need for an Evict request 289 | ULONG NeededLbaRangeEntryCount; 290 | 291 | // the length of allocated. Need to cache the value for calling AhciFreeDmaBuffer 292 | ULONG AllocatedBufferLength; 293 | 294 | // count of ATA Lba Range entries that already be processed. 295 | ULONG ProcessedLbaRangeEntryCount; 296 | 297 | // current Index of the input DSM EVICT Data Set Ranges 298 | ULONG DataSetRangeIndex; 299 | 300 | // current DSM EVICT Data Set Range (in sectors) being processed 301 | ULONGLONG CurrentRangeStartLba; 302 | ULONGLONG CurrentRangeLbaCount; 303 | 304 | } HYBRID_EVICT_CONTEXT, *PHYBRID_EVICT_CONTEXT; 305 | 306 | __inline 307 | BOOLEAN 308 | IsUnknownDevice( 309 | __in PATA_DEVICE_PARAMETERS DeviceParameters 310 | ) 311 | { 312 | return (DeviceParameters->AtaDeviceType == DeviceUnknown); 313 | } 314 | 315 | __inline 316 | BOOLEAN 317 | IsAtapiDevice( 318 | __in PATA_DEVICE_PARAMETERS DeviceParameters 319 | ) 320 | { 321 | return (DeviceParameters->AtaDeviceType == DeviceIsAtapi); 322 | } 323 | 324 | __inline 325 | BOOLEAN 326 | IsAtaDevice( 327 | __in PATA_DEVICE_PARAMETERS DeviceParameters 328 | ) 329 | { 330 | return (DeviceParameters->AtaDeviceType == DeviceIsAta); 331 | } 332 | 333 | __inline 334 | BOOLEAN 335 | IsRemovableMedia( 336 | __in PATA_DEVICE_PARAMETERS DeviceParameters 337 | ) 338 | { 339 | return (DeviceParameters->StateFlags.RemovableMedia == 1); 340 | } 341 | 342 | 343 | 344 | __inline 345 | BOOLEAN 346 | Support48Bit( 347 | __in PATA_DEVICE_PARAMETERS DeviceParameters 348 | ) 349 | { 350 | return (DeviceParameters->AddressTranslation == Lba48BitMode); 351 | } 352 | 353 | 354 | __inline 355 | ULONG 356 | BytesPerLogicalSector( 357 | __in PATA_DEVICE_PARAMETERS DeviceParameters 358 | ) 359 | { 360 | return DeviceParameters->BytesPerLogicalSector; 361 | } 362 | 363 | __inline 364 | ULONG64 365 | MaxUserAddressableLba( 366 | __in PATA_DEVICE_PARAMETERS DeviceParameters 367 | ) 368 | { 369 | return (DeviceParameters->MaxLba.QuadPart); 370 | } 371 | 372 | __inline 373 | PCDB 374 | RequestGetSrbScsiData ( 375 | __in PSCSI_REQUEST_BLOCK_EX Srb, 376 | __in_opt PULONG CdbLength, 377 | __in_opt PUCHAR ScsiStatus, 378 | __in_opt PVOID* SenseInfoBuffer, 379 | __in_opt PUCHAR SenseInfoBufferLength 380 | ) 381 | /*++ 382 | 383 | Routine Description: 384 | 385 | Helper function to retrieve SCSI related fields from a SRB. 386 | 387 | Arguments: 388 | 389 | Srb - Pointer to Srb or SrbEx. 390 | 391 | CdbLength - Pointer to buffer to hold CdbLength field value for CDB 392 | 393 | ScsiStatus - Buffer to hold address ScsiStatus field value. 394 | 395 | SenseInfoBuffer - Pointer to SenseInfoBuffer buffer. 396 | 397 | SenseInfoBufferLength - Pointer to buffer to hold SenseInfoBufferLength value. 398 | 399 | Return Value: 400 | 401 | Pointer to Cdb field 402 | 403 | --*/ 404 | { 405 | PCDB cdb = NULL; 406 | 407 | if (Srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) { 408 | // 409 | // This is SrbEx - STORAGE_REQUEST_BLOCK 410 | // 411 | cdb = SrbGetScsiData((PSTORAGE_REQUEST_BLOCK)Srb, (PUCHAR)CdbLength, CdbLength, ScsiStatus, SenseInfoBuffer, SenseInfoBufferLength); 412 | 413 | } else if (Srb->Function == SRB_FUNCTION_EXECUTE_SCSI) { 414 | // 415 | // This is legacy SCSI_REQUEST_BLOCK_EX 416 | // 417 | PSCSI_REQUEST_BLOCK_EX srb = (PSCSI_REQUEST_BLOCK_EX)Srb; 418 | 419 | if (CdbLength) { 420 | *CdbLength = srb->CdbLength; 421 | } 422 | 423 | if (srb->CdbLength > 0) { 424 | cdb = (PCDB)srb->Cdb; 425 | } 426 | 427 | if (ScsiStatus) { 428 | *ScsiStatus = srb->ScsiStatus; 429 | } 430 | 431 | if (SenseInfoBuffer) { 432 | *SenseInfoBuffer = srb->SenseInfoBuffer; 433 | } 434 | 435 | if (SenseInfoBufferLength) { 436 | *SenseInfoBufferLength = srb->SenseInfoBufferLength; 437 | } 438 | 439 | } else { 440 | if (CdbLength) { 441 | *CdbLength = 0; 442 | } 443 | 444 | if (ScsiStatus) { 445 | *ScsiStatus = SCSISTAT_GOOD; 446 | } 447 | 448 | if (SenseInfoBuffer) { 449 | *SenseInfoBuffer = NULL; 450 | } 451 | 452 | if (SenseInfoBufferLength) { 453 | *SenseInfoBufferLength = 0; 454 | } 455 | } 456 | 457 | return cdb; 458 | } 459 | 460 | 461 | __inline 462 | ULONG64 463 | GetLbaFromCdb( 464 | __in PCDB Cdb, 465 | __in ULONG CdbLength 466 | ) 467 | { 468 | LARGE_INTEGER lba; 469 | 470 | lba.QuadPart = 0; 471 | 472 | if (CdbLength == 0x10) { 473 | // 16 bytes CDB 474 | REVERSE_BYTES_QUAD((&lba.QuadPart), Cdb->CDB16.LogicalBlock); 475 | } else { 476 | lba.LowPart = (ULONG)(Cdb->CDB10.LogicalBlockByte3 | 477 | Cdb->CDB10.LogicalBlockByte2 << 8 | 478 | Cdb->CDB10.LogicalBlockByte1 << 16 | 479 | Cdb->CDB10.LogicalBlockByte0 << 24 ); 480 | lba.HighPart = 0; 481 | } 482 | 483 | return (ULONG64)lba.QuadPart; 484 | } 485 | 486 | __inline 487 | ULONG 488 | GetSectorCountFromCdb( 489 | PCDB Cdb, 490 | ULONG CdbLength 491 | ) 492 | { 493 | ULONG sectorCount = 0; 494 | 495 | if (CdbLength == 0x10) { 496 | // 16 byte cdb 497 | REVERSE_BYTES(§orCount, Cdb->CDB16.TransferLength); 498 | 499 | } else { 500 | sectorCount = (ULONG)(Cdb->CDB10.TransferBlocksMsb << 8 | 501 | Cdb->CDB10.TransferBlocksLsb); 502 | } 503 | 504 | return sectorCount; 505 | } 506 | 507 | // 508 | // Util routines 509 | // 510 | VOID 511 | __inline 512 | ByteSwap ( 513 | __inout_bcount(Length) PUCHAR Buffer, 514 | __in ULONG Length 515 | ) 516 | /*++ 517 | 518 | Routine Description: 519 | 520 | Swap the bytes in the buffer. 521 | 522 | Arguments: 523 | 524 | Buffer 525 | Length 526 | 527 | Return Value: 528 | 529 | None. 530 | 531 | --*/ 532 | { 533 | UCHAR temp; 534 | ULONG i; 535 | 536 | if (Length == 0) { 537 | return; 538 | } 539 | 540 | // swap the bytes 541 | for (i=0; i < Length-1; i+=2) { 542 | temp = Buffer[i]; 543 | Buffer[i] = Buffer[i+1]; 544 | #pragma warning (suppress: 6386) // i is within bound 545 | Buffer[i+1] = temp; 546 | } 547 | 548 | return; 549 | } 550 | 551 | ULONG 552 | __inline 553 | RemoveTrailingBlanks ( 554 | __inout_bcount(Length) __nullterminated PUCHAR Buffer, 555 | __in ULONG Length 556 | ) 557 | /*++ 558 | 559 | Routine Description: 560 | 561 | Remove trailing blanks from the buffer and null terminates it 562 | 563 | Arguments: 564 | 565 | Buffer 566 | Length 567 | 568 | Return Value: 569 | 570 | Returns the length of the string excluding the null character. 571 | 572 | --*/ 573 | { 574 | LONG i; 575 | 576 | if (Length < 2) { 577 | return 0; 578 | } 579 | 580 | Buffer[Length-1] = '\0'; 581 | 582 | // find the first non-space char from the end 583 | for (i=Length-2; i >= 0; i--) { 584 | 585 | if (Buffer[i] != ' ') { 586 | break; 587 | } 588 | } 589 | 590 | NT_ASSERT((i + 1) >= 0); 591 | 592 | Buffer[i+1] = '\0'; 593 | 594 | return (i+1); 595 | } 596 | 597 | __success(return == STOR_STATUS_SUCCESS) 598 | ULONG 599 | __inline 600 | AhciAllocateDmaBuffer ( 601 | __in PVOID AdapterExtension, 602 | __in ULONG BufferLength, 603 | __bcount(BufferLength) PVOID* Buffer 604 | ) 605 | { 606 | ULONG status; 607 | PHYSICAL_ADDRESS minPhysicalAddress; 608 | PHYSICAL_ADDRESS maxPhysicalAddress; 609 | PHYSICAL_ADDRESS boundaryPhysicalAddress; 610 | 611 | minPhysicalAddress.QuadPart = 0; 612 | // if we use 0x7FFFFFFF as the maximum physical address the call to the function 613 | // MmAllocateContiguousMemorySpecifyCache in StorPortPatch.c fails 614 | maxPhysicalAddress.QuadPart = -1; // maxPhysicalAddress.QuadPart = 0x7FFFFFFF; // (2GB - 1) 615 | boundaryPhysicalAddress.QuadPart = 0; 616 | 617 | 618 | status = StorPortAllocateContiguousMemorySpecifyCacheNode(AdapterExtension, 619 | BufferLength, 620 | minPhysicalAddress, 621 | maxPhysicalAddress, 622 | boundaryPhysicalAddress, 623 | MmCached, 624 | MM_ANY_NODE_OK, 625 | Buffer); 626 | return status; 627 | } 628 | 629 | __success(return == STOR_STATUS_SUCCESS) 630 | ULONG 631 | __inline 632 | AhciFreeDmaBuffer ( 633 | __in PVOID AdapterExtension, 634 | __in ULONG_PTR BufferLength, 635 | __in_bcount(BufferLength) PVOID Buffer 636 | ) 637 | { 638 | ULONG status; 639 | status = StorPortFreeContiguousMemorySpecifyCache(AdapterExtension, 640 | Buffer, 641 | BufferLength, 642 | MmCached); 643 | return status; 644 | } 645 | 646 | __inline 647 | BOOLEAN 648 | DmaSafeAtapiCommand ( 649 | __in UCHAR CdbCommand 650 | ) 651 | { 652 | ULONG i; 653 | BOOLEAN useDma; 654 | static const UCHAR dmaCommandList[] = 655 | {SCSIOP_READ6, 656 | SCSIOP_READ, 657 | SCSIOP_READ_CD, 658 | SCSIOP_READ_CD_MSF, 659 | SCSIOP_READ12, 660 | SCSIOP_WRITE6, 661 | SCSIOP_WRITE, 662 | SCSIOP_WRITE12, 663 | SCSIOP_WRITE_VERIFY, 664 | SCSIOP_WRITE_VERIFY12, 665 | 0}; 666 | 667 | useDma = FALSE; 668 | i = 0; 669 | 670 | while (dmaCommandList[i]) { 671 | if (CdbCommand == dmaCommandList[i]) { 672 | useDma = TRUE; 673 | break; 674 | } 675 | 676 | i++; 677 | } 678 | 679 | return useDma; 680 | } 681 | 682 | __inline 683 | BOOLEAN 684 | IsSupportedReadCdb ( 685 | __in PCDB Cdb 686 | ) 687 | { 688 | return ((Cdb->CDB10.OperationCode == SCSIOP_READ) || (Cdb->CDB10.OperationCode == SCSIOP_READ16)); 689 | } 690 | 691 | __inline 692 | BOOLEAN 693 | IsSupportedWriteCdb ( 694 | __in PCDB Cdb 695 | ) 696 | { 697 | return ((Cdb->CDB10.OperationCode == SCSIOP_WRITE) || (Cdb->CDB10.OperationCode == SCSIOP_WRITE16)); 698 | } 699 | 700 | 701 | struct AHCI_CHANNEL_EXTENSION; 702 | typedef struct _AHCI_CHANNEL_EXTENSION 703 | AHCI_CHANNEL_EXTENSION, 704 | *PAHCI_CHANNEL_EXTENSION; 705 | 706 | ULONG 707 | SCSItoATA( 708 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 709 | __in PSCSI_REQUEST_BLOCK_EX Srb 710 | ); 711 | 712 | ULONG 713 | SrbConvertToATAPICommand( 714 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 715 | __in PSCSI_REQUEST_BLOCK_EX Srb, 716 | __in PCDB Cdb 717 | ); 718 | 719 | ULONG 720 | AtapiCommonRequest ( 721 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 722 | __in PSCSI_REQUEST_BLOCK_EX Srb, 723 | __in PCDB Cdb 724 | ); 725 | 726 | ULONG 727 | AtapiInquiryRequest ( 728 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 729 | __in PSCSI_REQUEST_BLOCK_EX Srb 730 | ); 731 | 732 | ULONG 733 | AtapiModeSenseRequest ( 734 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 735 | __in PSCSI_REQUEST_BLOCK_EX Srb, 736 | __in PCDB Cdb 737 | ); 738 | 739 | ULONG 740 | AtapiModeSelectRequest ( 741 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 742 | __in PSCSI_REQUEST_BLOCK_EX Srb, 743 | __in PCDB Cdb 744 | ); 745 | 746 | ULONG 747 | SrbConvertToATACommand( 748 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 749 | __in PSCSI_REQUEST_BLOCK_EX Srb, 750 | __in PCDB Cdb, 751 | __in ULONG CdbLength 752 | ); 753 | 754 | ULONG 755 | AtaReadWriteRequest ( 756 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 757 | __in PSCSI_REQUEST_BLOCK_EX Srb, 758 | __in PCDB Cdb//, 759 | //__in ULONG CdbLength 760 | ); 761 | 762 | ULONG 763 | AtaVerifyRequest( 764 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 765 | __in PSCSI_REQUEST_BLOCK_EX Srb, 766 | __in PCDB Cdb, 767 | __in ULONG CdbLength 768 | ); 769 | 770 | ULONG 771 | AtaModeSenseRequest ( 772 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 773 | __in PSCSI_REQUEST_BLOCK_EX Srb, 774 | __in PCDB Cdb 775 | ); 776 | 777 | ULONG 778 | AtaModeSelectRequest ( 779 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 780 | __in PSCSI_REQUEST_BLOCK_EX Srb, 781 | __in PCDB Cdb 782 | ); 783 | 784 | ULONG 785 | AtaReadCapacityRequest ( 786 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 787 | __in PSCSI_REQUEST_BLOCK_EX Srb, 788 | __in PCDB Cdb, 789 | __in ULONG CdbLength 790 | ); 791 | 792 | ULONG 793 | InquiryComplete( 794 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 795 | __in PSCSI_REQUEST_BLOCK_EX Srb 796 | ); 797 | 798 | ULONG 799 | AtaInquiryRequest( 800 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 801 | __in PSCSI_REQUEST_BLOCK_EX Srb, 802 | __in PCDB Cdb 803 | ); 804 | 805 | ULONG 806 | AtaStartStopUnitRequest ( 807 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 808 | __in PSCSI_REQUEST_BLOCK_EX Srb, 809 | __in PCDB Cdb 810 | ); 811 | 812 | ULONG 813 | AtaTestUnitReadyRequest ( 814 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 815 | __in PSCSI_REQUEST_BLOCK_EX Srb 816 | ); 817 | 818 | ULONG 819 | AtaMediumRemovalRequest ( 820 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 821 | __in PSCSI_REQUEST_BLOCK_EX Srb, 822 | __in PCDB Cdb 823 | ); 824 | 825 | ULONG 826 | AtaFlushCommandRequest ( 827 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 828 | __in PSCSI_REQUEST_BLOCK_EX Srb 829 | ); 830 | 831 | ULONG 832 | AtaPassThroughRequest ( 833 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 834 | __in PSCSI_REQUEST_BLOCK_EX Srb, 835 | __in PCDB Cdb 836 | ); 837 | 838 | ULONG 839 | AtaUnmapRequest ( 840 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 841 | __in PSCSI_REQUEST_BLOCK_EX Srb 842 | ); 843 | 844 | ULONG 845 | AtaSecurityProtocolRequest ( 846 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 847 | __in PSCSI_REQUEST_BLOCK_EX Srb, 848 | __in PCDB Cdb 849 | ); 850 | 851 | ULONG 852 | AtaReportLunsCommand( 853 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 854 | __in PVOID Context 855 | ); 856 | 857 | UCHAR 858 | AtaMapError( 859 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 860 | __in PSCSI_REQUEST_BLOCK_EX Srb, 861 | __in BOOLEAN FUAcommand 862 | ); 863 | 864 | VOID 865 | UpdateDeviceParameters( 866 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 867 | ); 868 | 869 | VOID 870 | DeviceInitAtapiIds( 871 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 872 | __in PINQUIRYDATA InquiryData 873 | ); 874 | 875 | VOID 876 | AhciPortIdentifyDevice( 877 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 878 | __in PSCSI_REQUEST_BLOCK_EX Srb 879 | ); 880 | 881 | ULONG 882 | IOCTLtoATA( 883 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 884 | __in PSCSI_REQUEST_BLOCK_EX Srb 885 | ); 886 | 887 | ULONG 888 | SmartVersion( 889 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 890 | __in PSCSI_REQUEST_BLOCK_EX Srb 891 | ); 892 | 893 | BOOLEAN 894 | FillClippedSGL( 895 | __in PSTOR_SCATTER_GATHER_LIST SourceSgl, 896 | __inout PSTOR_SCATTER_GATHER_LIST LocalSgl, 897 | __in ULONG BytesLeft, 898 | __in ULONG BytesNeeded 899 | ); 900 | 901 | ULONG 902 | SmartIdentifyData( 903 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 904 | __in PSCSI_REQUEST_BLOCK_EX Srb 905 | ); 906 | 907 | ULONG 908 | SmartGeneric( 909 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 910 | __in PSCSI_REQUEST_BLOCK_EX Srb 911 | ); 912 | 913 | ULONG 914 | NVCacheGeneric( 915 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 916 | __in PSCSI_REQUEST_BLOCK_EX Srb 917 | ); 918 | 919 | 920 | ULONG 921 | HybridIoctlProcess( 922 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 923 | __in PSCSI_REQUEST_BLOCK_EX Srb 924 | ); 925 | 926 | ULONG 927 | DsmGeneralIoctlProcess( 928 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 929 | __in PSCSI_REQUEST_BLOCK_EX Srb 930 | ); 931 | 932 | ULONG 933 | DatasetManagementIoctl( 934 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 935 | __in PSCSI_REQUEST_BLOCK_EX Srb 936 | ); 937 | 938 | 939 | #if _MSC_VER >= 1200 940 | #pragma warning(pop) 941 | #else 942 | #pragma warning(default:4214) 943 | #pragma warning(default:4201) 944 | #endif 945 | 946 | -------------------------------------------------------------------------------- /entrypts.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeorgeK1ng/GenAHCI/b936a0d8bdf410928aefa9e0f373fb1d6c7c8240/entrypts.c -------------------------------------------------------------------------------- /entrypts.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (C) Microsoft Corporation, 2009 4 | 5 | Module Name: 6 | 7 | entrypts.h 8 | 9 | Abstract: 10 | 11 | This header contains the declaration of functions that will be called by Storport driver. 12 | 13 | Authors: 14 | 15 | Michael Xing (xiaoxing), December 2009 16 | 17 | --*/ 18 | 19 | #pragma once 20 | 21 | #if _MSC_VER >= 1200 22 | #pragma warning(push) 23 | #endif 24 | 25 | #pragma warning(disable:4214) // bit field types other than int 26 | #pragma warning(disable:4201) // nameless struct/union 27 | 28 | 29 | #define AHCI_POOL_TAG 'ichA' // "Ahci" - StorAHCI miniport driver 30 | 31 | #define NUM_ACCESS_RANGES 6 32 | 33 | #define AHCI_MAX_PORT_COUNT 32 34 | #define AHCI_MAX_DEVICE 1 //not support Port Multiplier 35 | #define AHCI_MAX_LUN 8 //ATAport supports this much in old implementation. 36 | #define AHCI_MAX_NCQ_REQUEST_COUNT 32 37 | 38 | #define KB (1024) 39 | #define AHCI_MAX_TRANSFER_LENGTH (128 * KB) 40 | #define MAX_SETTINGS_PRESERVED 32 41 | #define MAX_CRB_LOG_INDEX 64 42 | 43 | #define INQUIRYDATABUFFERSIZE 36 44 | 45 | // timeout values and counters for channel start 46 | // some big HDDs (e.g. 2TB) takes ~ 20 seconds to spin up. We hit timeout during S3 resume for now, 47 | // we reset after 1/3 * AHCI_PORT_START_TIMEOUT_IN_SECONDS Busy, and give up after AHCI_PORT_START_TIMEOUT_IN_SECONDS seconds 48 | 49 | #define AHCI_PORT_START_TIMEOUT_IN_SECONDS 60 // 60 sec. 50 | 51 | #define AHCI_PORT_WAIT_ON_DET_COUNT 3 // in unit of 10ms, default 30ms. 52 | 53 | 54 | // port start states 55 | #define WaitOnDET 0x11 56 | #define WaitWhileDET1 0x12 57 | #define WaitOnDET3 0x13 58 | #define WaitOnFRE 0x14 59 | #define WaitOnBSYDRQ 0x15 60 | #define StartComplete 0x16 61 | #define Stopped 0x20 62 | #define StartFailed 0xff 63 | 64 | // 65 | // Bit field definitions for PortProperties field in CHANNEL_EXTENSION 66 | // 67 | 68 | // Clear: Internal port 69 | // Set: External port 70 | #define PORT_PROPERTIES_EXTERNAL_PORT ( 1 << 0 ) 71 | 72 | // registry flags apply to port or device 73 | typedef struct _CHANNEL_REGISTRY_FLAGS { 74 | 75 | 76 | ULONG Reserved : 20; 77 | 78 | 79 | } CHANNEL_REGISTRY_FLAGS, *PCHANNEL_REGISTRY_FLAGS; 80 | 81 | // registry flags apply to the whole adapter 82 | typedef struct _ADAPTER_REGISTRY_FLAGS { 83 | 84 | ULONG Reserved2 : 16; 85 | 86 | 87 | } ADAPTER_REGISTRY_FLAGS, *PADAPTER_REGISTRY_FLAGS; 88 | 89 | typedef struct _CHANNEL_STATE_FLAGS { 90 | 91 | ULONG Initialized : 1; 92 | ULONG NoMoreIO : 1; 93 | ULONG QueuePaused : 1; 94 | ULONG ReservedSlotInUse : 1; //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 3) is used there. 95 | 96 | ULONG NCQ_Activated : 1; 97 | ULONG NCQ_Succeeded : 1; 98 | ULONG RestorePreservedSettingsActiveReferenced : 1; // this bit will be set if active reference is acquired for RestorePreservedSettings process 99 | ULONG HybridInfoEnabledOnHiberFile : 1; // this bit indicates if priority level should be put for NCQ Write by StorAHCI when writes a hiber file. 100 | 101 | ULONG CallAhciReset : 1; 102 | ULONG CallAhciNonQueuedErrorRecovery : 1; 103 | ULONG CallAhciReportBusChange : 1; 104 | ULONG IgnoreHotplugInterrupt : 1; 105 | 106 | ULONG PowerDown : 1; //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 12) is used there. 107 | ULONG PoFxEnabled : 1; 108 | ULONG PoFxActive : 1; 109 | ULONG D3ColdEnabled : 1; 110 | 111 | ULONG Reserved1; 112 | } CHANNEL_STATE_FLAGS, *PCHANNEL_STATE_FLAGS; 113 | 114 | typedef struct _ATA_IO_RECORD { 115 | 116 | ULONG SuccessCount; 117 | 118 | ULONG CrcErrorCount; 119 | ULONG MediaErrorCount; 120 | ULONG EndofMediaCount; 121 | ULONG IllegalCommandCount; 122 | ULONG AbortedCommandCount; 123 | 124 | ULONG OtherErrorCount; 125 | 126 | ULONG PortDriverResetCount; 127 | ULONG TotalResetCount; 128 | 129 | } ATA_IO_RECORD, *PATA_IO_RECORD; 130 | 131 | // 132 | // Data structure to retrieve a Log Page 133 | // 134 | typedef struct _ATA_GPL_PAGE { 135 | BOOLEAN Query; 136 | UCHAR LogAddress; 137 | USHORT PageNumber; 138 | USHORT BlockCount; 139 | USHORT FeatureField; 140 | } ATA_GPL_PAGE, *PATA_GPL_PAGE; 141 | 142 | #define ATA_GPL_PAGES_QUERY_COUNT 0x10 143 | #define ATA_GPL_PAGES_INVALID_INDEX 0xFFFF 144 | 145 | typedef struct _ATA_GPL_PAGES_TO_QUERY { 146 | USHORT TotalPageCount; 147 | USHORT CurrentPageIndex; 148 | 149 | ATA_GPL_PAGE LogPage[ATA_GPL_PAGES_QUERY_COUNT]; 150 | } ATA_GPL_PAGES_TO_QUERY, *PATA_GPL_PAGES_TO_QUERY; 151 | 152 | // 153 | // This data structure defines supportive information of Log Address and Log Page 154 | // If a Log Address contains more than one different Log Pages, there normally is Log Page 0x00 to get supported log pages. 155 | // 156 | typedef struct _ATA_SUPPORTED_GPL_PAGES { 157 | 158 | struct { 159 | ULONG LogAddressSupported : 1; // Log Address 0x04 160 | ULONG GeneralStatistics : 1; // Log Page 0x01 161 | ULONG Reserved : 30; 162 | } DeviceStatistics; 163 | 164 | struct { 165 | ULONG LogAddressSupported : 1; // Log Address 0x30 166 | ULONG SATA : 1; // Log Page 0x08 167 | ULONG Reserved : 30; 168 | } IdentifyDeviceData; 169 | 170 | struct { 171 | ULONG NcqCommandError : 1; // Log Address 0x10 172 | ULONG NcqNonData : 1; // Log Address 0x12 173 | ULONG NcqSendReceive : 1; // Log Address 0x13 174 | ULONG HybridInfo : 1; // Log Address 0x14 175 | ULONG CurrentDeviceInternalStatusData : 1; // Log Address 0x24 176 | ULONG SavedDeviceInternalStatusData : 1; // Log Address 0x25 177 | 178 | ULONG Reserved : 26; 179 | } SinglePage; 180 | 181 | } ATA_SUPPORTED_GPL_PAGES, *PATA_SUPPORTED_GPL_PAGES; 182 | 183 | typedef struct _ATA_COMMAND_SUPPORTED { 184 | 185 | ULONG HybridDemoteBySize : 1; 186 | ULONG HybridChangeByLbaRange : 1; 187 | ULONG HybridControl : 1; 188 | ULONG HybridEvict : 1; 189 | 190 | ULONG SetDateAndTime : 1; 191 | 192 | ULONG Reserved : 27; 193 | 194 | } ATA_COMMAND_SUPPORTED, *PATA_COMMAND_SUPPORTED; 195 | 196 | 197 | typedef struct _AHCI_DEVICE_EXTENSION { 198 | STOR_ADDR_BTL8 DeviceAddress; 199 | ATA_DEVICE_PARAMETERS DeviceParameters; 200 | ATA_IO_RECORD IoRecord; //IO counts completed by device, the count only change if an IO reaches hardware 201 | 202 | union { 203 | PIDENTIFY_DEVICE_DATA IdentifyDeviceData; 204 | PIDENTIFY_PACKET_DATA IdentifyPacketData; 205 | }; 206 | STOR_PHYSICAL_ADDRESS IdentifyDataPhysicalAddress; 207 | 208 | PUCHAR InquiryData; //for ATAPI device, size:INQUIRYDATABUFFERSIZE 209 | STOR_PHYSICAL_ADDRESS InquiryDataPhysicalAddress; 210 | 211 | ATA_GPL_PAGES_TO_QUERY QueryLogPages; 212 | 213 | ATA_SUPPORTED_GPL_PAGES SupportedGPLPages; 214 | ATA_COMMAND_SUPPORTED SupportedCommands; 215 | GP_LOG_HYBRID_INFORMATION_HEADER HybridInfo; 216 | LONG HybridCachingMediumEnableRefs; 217 | 218 | PUSHORT ReadLogExtPageData; 219 | STOR_PHYSICAL_ADDRESS ReadLogExtPageDataPhysicalAddress; 220 | 221 | } AHCI_DEVICE_EXTENSION, *PAHCI_DEVICE_EXTENSION; 222 | 223 | typedef struct _COMMAND_HISTORY { 224 | union { //0x10 bytes 225 | ATA_TASK_FILE InitialTaskFile; 226 | UCHAR Cdb[16]; 227 | }; 228 | ULONG InitialPx[0x10]; //0x40 bytes 229 | ULONG CompletionPx[0x10]; 230 | 231 | AHCI_D2H_REGISTER_FIS CompletionFIS; //0x14 bytes 232 | ULONG Tag; 233 | ULONG Function; 234 | ULONG SrbStatus; 235 | } COMMAND_HISTORY, *PCOMMAND_HISTORY; 236 | 237 | typedef struct _SLOT_MANAGER { 238 | ULONG HighPriorityAttribute; 239 | 240 | ULONG NCQueueSlice; 241 | ULONG NormalQueueSlice; 242 | ULONG SingleIoSlice; 243 | 244 | ULONG CommandsIssued; 245 | ULONG CommandsToComplete; 246 | } SLOT_MANAGER, *PSLOT_MANAGER; 247 | 248 | typedef struct _EXECUTION_HISTORY { 249 | ULONG Function; 250 | ULONG IS; 251 | SLOT_MANAGER SlotManager; //SLOT_MANAGER from _AHCI_CHANNEL_EXTENSION 252 | ULONG Px[0x10]; //Px registers value, end to AHCI_SNOTIFICATION -- SNTF 253 | } EXECUTION_HISTORY, *PEXECUTION_HISTORY; 254 | 255 | typedef struct _SLOT_STATE_FLAGS { 256 | UCHAR FUA :1; 257 | UCHAR Reserved :7; 258 | } SLOT_STATE_FLAGS, *PSLOT_STATE_FLAGS; 259 | 260 | 261 | typedef struct _SLOT_CONTENT { 262 | UCHAR CommandHistoryIndex; 263 | SLOT_STATE_FLAGS StateFlags; 264 | UCHAR Reserved0[2]; 265 | PSCSI_REQUEST_BLOCK_EX Srb; 266 | PAHCI_COMMAND_HEADER CmdHeader; 267 | PVOID Reserved; 268 | } SLOT_CONTENT, *PSLOT_CONTENT; 269 | 270 | #pragma pack(1) 271 | typedef struct _ACPI_GTF_IDE_REGISTERS { 272 | UCHAR FeaturesReg; 273 | UCHAR SectorCountReg; 274 | UCHAR SectorNumberReg; 275 | UCHAR CylLowReg; 276 | UCHAR CylHighReg; 277 | UCHAR DriveHeadReg; 278 | UCHAR CommandReg; 279 | } ACPI_GTF_IDE_REGISTERS, *PACPI_GTF_IDE_REGISTERS; 280 | #pragma pack() 281 | 282 | typedef struct _AHCI_DEVICE_INIT_COMMANDS { 283 | UCHAR CommandCount; // count of total commands, mainly used to allocate memory for CommandTaskFile 284 | UCHAR ValidCommandCount; // count of valid commands 285 | UCHAR CommandToSend; // command index indicating which command is to be sent 286 | PATA_TASK_FILE CommandTaskFile; // commands 287 | } AHCI_DEVICE_INIT_COMMANDS, *PAHCI_DEVICE_INIT_COMMANDS; 288 | 289 | 290 | typedef struct _SET_FEATURE_PARAMS { 291 | UCHAR Features; 292 | UCHAR SectorCount; 293 | } SET_FEATURE_PARAMS, *PSET_FEATURE_PARAMS; 294 | 295 | typedef struct _PERSISTENT_SETTINGS { 296 | ULONG Slots; 297 | ULONG SlotsToSend; 298 | SET_FEATURE_PARAMS CommandParams[MAX_SETTINGS_PRESERVED]; 299 | } PERSISTENT_SETTINGS, *PPERSISTENT_SETTINGS; 300 | 301 | typedef struct _CHANNEL_START_STATE { 302 | UCHAR ChannelNextStartState; 303 | UCHAR ChannelStateDETCount; 304 | UCHAR ChannelStateDET1Count; 305 | UCHAR ChannelStateDET3Count; 306 | UCHAR ChannelStateFRECount; 307 | UCHAR AtDIRQL : 1; 308 | UCHAR DirectStartInProcess : 1; 309 | UCHAR Reserved : 6; 310 | USHORT ChannelStateBSYDRQCount; 311 | } CHANNEL_START_STATE, *PCHANNEL_START_STATE; 312 | 313 | typedef VOID 314 | (*PSRB_COMPLETION_ROUTINE) ( 315 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 316 | __in_opt PSCSI_REQUEST_BLOCK_EX Srb 317 | ); 318 | 319 | typedef struct _LOCAL_SCATTER_GATHER_LIST { 320 | ULONG NumberOfElements; 321 | ULONG_PTR Reserved; 322 | __field_ecount(NumberOfElements) 323 | STOR_SCATTER_GATHER_ELEMENT List[33]; 324 | } LOCAL_SCATTER_GATHER_LIST, *PLOCAL_SCATTER_GATHER_LIST; 325 | 326 | typedef struct _AHCI_SRB_EXTENSION { 327 | AHCI_COMMAND_TABLE CommandTable; // this field MUST to be the first one as it's asked to be 128 aligned 328 | USHORT AtaFunction; // if this field is 0, it means the command does not need to be sent to device 329 | UCHAR AtaStatus; 330 | UCHAR AtaError; 331 | ULONG Flags; 332 | union { 333 | ATA_TASK_FILE TaskFile; // for ATA device 334 | CDB Cdb; // for ATAPI device 335 | AHCI_H2D_REGISTER_FIS Cfis; // info related to Host to Device FIS (0x27) 336 | }; 337 | PVOID DataBuffer; // go with Cdb field when needed. 338 | ULONG DataTransferLength; // go with Cdb field when needed. 339 | PLOCAL_SCATTER_GATHER_LIST Sgl; // pointer to the local or port provided SGL 340 | LOCAL_SCATTER_GATHER_LIST LocalSgl; // local SGL 341 | PSRB_COMPLETION_ROUTINE CompletionRoutine; // go with Cdb field when needed. 342 | PVOID CompletionContext; // context information for completionRoutine 343 | UCHAR QueueTag; // for AHCI controller slots 344 | UCHAR RetryCount; // how many times the command has been retired 345 | ULONGLONG StartTime; 346 | 347 | PVOID ResultBuffer; // for requests marked with ATA_FLAGS_RETURN_RESULTS 348 | ULONG ResultBufferLength; 349 | } AHCI_SRB_EXTENSION, *PAHCI_SRB_EXTENSION; 350 | 351 | typedef struct _LOCAL_COMMAND { 352 | SCSI_REQUEST_BLOCK_EX Srb; 353 | PAHCI_SRB_EXTENSION SrbExtension; 354 | STOR_PHYSICAL_ADDRESS SrbExtensionPhysicalAddress; 355 | } LOCAL_COMMAND, *PLOCAL_COMMAND; 356 | 357 | typedef enum { 358 | CallbackTypeNone = 0, //not used 359 | CallbackTypeStartPort, 360 | CallbackTypeLPM, 361 | CallbackTypeMax //count 362 | } TIMER_CALLBACK_TYPE; 363 | 364 | typedef 365 | BOOLEAN 366 | (*PAHCI_TIMER_CALLBACK) ( 367 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 368 | __in PVOID Context 369 | ); 370 | 371 | typedef struct _STORAHCI_QUEUE { 372 | PVOID Head; 373 | PVOID Tail; 374 | ULONG CurrentDepth; 375 | ULONG DeepestDepth; 376 | ULONG DepthHistoryIndex; 377 | ULONG DepthHistory[100]; 378 | } STORAHCI_QUEUE, *PSTORAHCI_QUEUE; 379 | 380 | typedef struct _AHCI_ADAPTER_EXTENSION AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION; 381 | 382 | typedef struct _AHCI_CHANNEL_EXTENSION { 383 | //Adapter Characteristics 384 | PAHCI_ADAPTER_EXTENSION AdapterExtension; 385 | 386 | //Device Characteristics 387 | AHCI_DEVICE_EXTENSION DeviceExtension[1]; 388 | 389 | //Channel Characteristics 390 | ULONG PortNumber; 391 | ULONG PortProperties; // See PORT_PROPERTIES_XYZ definitions above in this file. 392 | 393 | //Channel State 394 | CHANNEL_START_STATE StartState; 395 | CHANNEL_STATE_FLAGS StateFlags; 396 | CHANNEL_REGISTRY_FLAGS RegistryFlags; 397 | 398 | UCHAR MaxPortQueueDepth; 399 | UCHAR CurrentCommandSlot; // miniport driver use to remember which slot to put command in. 400 | UCHAR LastActiveSlot; 401 | UCHAR LastUserLpmPowerSetting; // bit 0: HIPM; bit 1: DIPM 402 | 403 | ULONG AutoPartialToSlumberInterval; // in milliSeconds, max: 300,000 (5 minutes) 404 | 405 | AHCI_TASK_FILE_DATA TaskFileData; 406 | 407 | // Port runtime power management 408 | PSTOR_POFX_DEVICE PoFxDevice; 409 | UCHAR PoFxState; //Current F-State of the unit 410 | STOR_DEVICE_POWER_STATE DevicePowerState; // Current D-State of the unit. 411 | 412 | // 413 | // AutoPartialToSlumber statistics to aid in debugging. 414 | // 415 | struct { 416 | ULONG InterfaceNotReady; // Number of times the interface was no ready (CMD.ICC != 0) 417 | ULONG InterfaceReady; // Number of times the interface was ready (CMD.ICC == 0) 418 | ULONG ActiveFailCount; // Number of times we failed to go to Active 419 | ULONG ActiveSuccessCount; // Number of times we succeeded in going to Active 420 | ULONG SlumberFailCount; // Number of times we failed to go to Slumber 421 | ULONG SlumberSuccessCount; // Number of times we succeeded in going to Slumber 422 | } AutoPartialToSlumberDbgStats; 423 | 424 | 425 | struct { 426 | ULONG RestorePreservedSettings :1; //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 0) is used there. 427 | ULONG BusChange :1; //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 1) is used there. 428 | 429 | ULONG Reserved: 30; 430 | } PoFxPendingWork; 431 | 432 | //IO 433 | SLOT_MANAGER SlotManager; 434 | SLOT_CONTENT Slot[AHCI_MAX_NCQ_REQUEST_COUNT]; 435 | 436 | //Port IO Queue 437 | STORAHCI_QUEUE SrbQueue; 438 | 439 | //IO Completion Queue and DPC 440 | STORAHCI_QUEUE CompletionQueue; 441 | STOR_DPC CompletionDpc; 442 | 443 | //DPC to handle hotplug notification 444 | STOR_DPC BusChangeDpc; 445 | 446 | //AHCI defined register interface structures 447 | PAHCI_PORT Px; 448 | PAHCI_COMMAND_HEADER CommandList; 449 | PAHCI_RECEIVED_FIS ReceivedFIS; 450 | STOR_PHYSICAL_ADDRESS CommandListPhysicalAddress; 451 | STOR_PHYSICAL_ADDRESS ReceivedFisPhysicalAddress; 452 | 453 | //Local Command Structures 454 | LOCAL_COMMAND Local; 455 | LOCAL_COMMAND Sense; // used to retrieve Sense Data from device 456 | 457 | AHCI_DEVICE_INIT_COMMANDS DeviceInitCommands; 458 | PERSISTENT_SETTINGS PersistentSettings; 459 | 460 | //Timer 461 | PVOID StartPortTimer; // used for the Port Starting process 462 | PVOID WorkerTimer; // used for LPM management for now 463 | 464 | //Logging 465 | UCHAR CommandHistoryNextAvailableIndex; 466 | COMMAND_HISTORY CommandHistory[64]; 467 | UCHAR ExecutionHistoryNextAvailableIndex; 468 | EXECUTION_HISTORY ExecutionHistory[100]; 469 | 470 | } AHCI_CHANNEL_EXTENSION, *PAHCI_CHANNEL_EXTENSION; 471 | 472 | typedef struct _ADAPTER_STATE_FLAGS { 473 | 474 | ULONG StoppedState : 1; 475 | ULONG PowerDown : 1; 476 | ULONG PoFxEnabled : 1; 477 | ULONG PoFxActive : 1; 478 | 479 | 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. 480 | ULONG Removed : 1; 481 | 482 | ULONG Reserved : 25; 483 | 484 | } ADAPTER_STATE_FLAGS, *PADAPTER_STATE_FLAGS; 485 | 486 | typedef union _ADAPTER_LOG_FLAGS { 487 | 488 | struct { 489 | ULONG ExecutionDetail :1; 490 | ULONG CommandHistory :1; 491 | 492 | ULONG Reserved: 30; 493 | }; 494 | 495 | ULONG AsUlong; 496 | 497 | } ADAPTER_LOG_FLAGS, *PADAPTER_LOG_FLAGS; 498 | 499 | #define LogCommand(flags) (flags.CommandHistory != 0) 500 | #define LogExecuteFullDetail(flags) (flags.ExecutionDetail != 0) 501 | 502 | 503 | typedef struct _AHCI_ADAPTER_EXTENSION { 504 | ULONG AdapterNumber; 505 | ULONG SystemIoBusNumber; 506 | ULONG SlotNumber; 507 | ULONG AhciBaseAddress; // AHCI Base Address from bus. for example: BAR5 value on PCI bus 508 | 509 | USHORT VendorID; 510 | USHORT DeviceID; 511 | UCHAR RevisionID; 512 | 513 | // Adapter runtime power management 514 | PSTOR_POFX_DEVICE_V2 PoFxDevice; 515 | RAID_SYSTEM_POWER SystemPowerHintState; 516 | ULONG SystemPowerResumeLatencyMSec; 517 | 518 | struct { 519 | ULONG AdapterStop :1; //NOTE: this field is accessed in InterlockedBitTestAndReset, bit position (currently: 0) is used there. 520 | 521 | ULONG Reserved: 31; 522 | } PoFxPendingWork; 523 | 524 | //Flags 525 | ADAPTER_STATE_FLAGS StateFlags; 526 | ULONG ErrorFlags; // save adapter errors 527 | ADAPTER_LOG_FLAGS LogFlags; // internal log levels 528 | ADAPTER_REGISTRY_FLAGS RegistryFlags; 529 | 530 | //adapter attributes 531 | ULONG PortImplemented; 532 | ULONG HighestPort; 533 | ULONG LastInterruptedPort; 534 | 535 | UCHAR DumpMode; 536 | BOOLEAN InRunningPortsProcess; //in process of starting every implemented ports 537 | BOOLEAN TracingEnabled; 538 | 539 | //Memory structures 540 | PAHCI_MEMORY_REGISTERS ABAR_Address; //mapped AHCI Base Address. StorAHCI uses this field to control the adapter and ports. 541 | AHCI_VERSION Version; 542 | 543 | PULONG IS; 544 | AHCI_HBA_CAPABILITIES CAP; 545 | AHCI_HBA_CAPABILITIES2 CAP2; 546 | 547 | //Channel Extensions 548 | PAHCI_CHANNEL_EXTENSION PortExtension[AHCI_MAX_PORT_COUNT]; 549 | 550 | //nonCacheExtension 551 | PVOID NonCachedExtension; 552 | 553 | } AHCI_ADAPTER_EXTENSION, *PAHCI_ADAPTER_EXTENSION; 554 | 555 | // information that will be transferred to dump/hibernate environment 556 | typedef struct _AHCI_DUMP_CONTEXT { 557 | // adapter information 558 | USHORT VendorID; 559 | USHORT DeviceID; 560 | UCHAR RevisionID; 561 | UCHAR Reserved[3]; 562 | 563 | ULONG AhciBaseAddress; 564 | 565 | ADAPTER_LOG_FLAGS LogFlags; // internal log levels 566 | ADAPTER_REGISTRY_FLAGS AdapterRegistryFlags; 567 | 568 | // port information 569 | ULONG DumpPortNumber; 570 | CHANNEL_REGISTRY_FLAGS PortRegistryFlags; 571 | 572 | // 573 | // Device telemetry descriptors for the boot device 574 | // 575 | ULONG PublicGPLogTableAddresses[TC_PUBLIC_DEVICEDUMP_CONTENT_GPLOG_MAX]; 576 | ULONG PrivateGPLogPageAddress; 577 | 578 | // 579 | // Hybrid Disk Information Log 580 | // 581 | GP_LOG_HYBRID_INFORMATION_HEADER HybridInfo; 582 | 583 | } AHCI_DUMP_CONTEXT, *PAHCI_DUMP_CONTEXT; 584 | 585 | 586 | // Storport miniport driver entry routines, with prefix: "AhciHw" 587 | sp_DRIVER_INITIALIZE DriverEntry; 588 | 589 | HW_FIND_ADAPTER_EX AhciHwFindAdapter; 590 | 591 | HW_INITIALIZE AhciHwInitialize; 592 | 593 | HW_PASSIVE_INITIALIZE_ROUTINE AhciHwPassiveInitialize; 594 | 595 | HW_STARTIO_EX AhciHwStartIo; 596 | 597 | HW_BUILDIO_EX AhciHwBuildIo; 598 | 599 | HW_INTERRUPT AhciHwInterrupt; 600 | 601 | HW_RESET_BUS AhciHwResetBus; 602 | 603 | HW_ADAPTER_CONTROL AhciHwAdapterControl; 604 | 605 | HW_TRACING_ENABLED AhciHwTracingEnabled; 606 | 607 | HW_UNIT_CONTROL AhciHwUnitControl; 608 | 609 | 610 | VOID 611 | AhciGetNextIos ( 612 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 613 | __in BOOLEAN AtDIRQL 614 | ); 615 | 616 | VOID 617 | AhciDeviceStart ( 618 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 619 | ); 620 | 621 | // 622 | // References to globals 623 | // 624 | // 625 | // Device telemetry descriptors for the boot device 626 | // 627 | extern ULONG AhciPublicGPLogTableAddresses[TC_PUBLIC_DEVICEDUMP_CONTENT_GPLOG_MAX]; 628 | extern ULONG AhciGPLogPageIntoPrivate; 629 | 630 | 631 | 632 | #if _MSC_VER >= 1200 633 | #pragma warning(pop) 634 | #else 635 | #pragma warning(default:4214) 636 | #pragma warning(default:4201) 637 | #endif 638 | 639 | 640 | -------------------------------------------------------------------------------- /genahci.inf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeorgeK1ng/GenAHCI/b936a0d8bdf410928aefa9e0f373fb1d6c7c8240/genahci.inf -------------------------------------------------------------------------------- /genahci.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeorgeK1ng/GenAHCI/b936a0d8bdf410928aefa9e0f373fb1d6c7c8240/genahci.rc -------------------------------------------------------------------------------- /generic.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (C) Microsoft Corporation, 2009 4 | 5 | Module Name: 6 | 7 | generic.h 8 | 9 | Abstract: 10 | 11 | holder of header files 12 | 13 | Notes: 14 | 15 | Revision History: 16 | 17 | Michael Xing (xiaoxing), December 2009 18 | --*/ 19 | 20 | 21 | // common header files 22 | #include "ntddk.h" 23 | #include ".\inc\ddk\storport.h" 24 | #include ".\inc\ddk\ata.h" 25 | 26 | #include ".\inc\api\ntddscsi.h" 27 | #define DEVICE_TYPE ULONG 28 | #include ".\inc\api\ntddstor.h" 29 | 30 | 31 | 32 | // storahci header files 33 | #include "stor_helper.h" 34 | #include "srb_helper.h" 35 | #include "StorPortPatch.h" 36 | #include "common.h" 37 | #include "ahci.h" 38 | #include "entrypts.h" 39 | #include "pnppower.h" 40 | #include "hbastat.h" 41 | #include "io.h" 42 | #include "util.h" 43 | 44 | // 45 | // Data structures for SMART drive fault prediction. 46 | // 47 | // GETVERSIONINPARAMS contains the data returned from the 48 | // Get Driver Version function. 49 | // 50 | 51 | #include 52 | typedef struct _GETVERSIONINPARAMS { 53 | UCHAR bVersion; // Binary driver version. 54 | UCHAR bRevision; // Binary driver revision. 55 | UCHAR bReserved; // Not used. 56 | UCHAR bIDEDeviceMap; // Bit map of IDE devices. 57 | ULONG fCapabilities; // Bit mask of driver capabilities. 58 | ULONG dwReserved[4]; // For future use. 59 | } GETVERSIONINPARAMS, *PGETVERSIONINPARAMS, *LPGETVERSIONINPARAMS; 60 | #include 61 | 62 | // 63 | // Valid values for the bCommandReg member of IDEREGS. 64 | // 65 | 66 | #define ATAPI_ID_CMD 0xA1 // Returns ID sector for ATAPI. 67 | #define ID_CMD 0xEC // Returns ID sector for ATA. 68 | #define SMART_CMD 0xB0 // Performs SMART cmd. 69 | // Requires valid bFeaturesReg, 70 | // bCylLowReg, and bCylHighReg 71 | 72 | // 73 | // Cylinder register defines for SMART command 74 | // 75 | 76 | #define SMART_CYL_LOW 0x4F 77 | #define SMART_CYL_HI 0xC2 78 | 79 | // 80 | // Bits returned in the fCapabilities member of GETVERSIONINPARAMS 81 | // 82 | 83 | #define CAP_ATA_ID_CMD 1 // ATA ID command supported 84 | #define CAP_ATAPI_ID_CMD 2 // ATAPI ID command supported 85 | #define CAP_SMART_CMD 4 // SMART commannds supported 86 | 87 | // 88 | // SENDCMDINPARAMS contains the input parameters for the 89 | // Send Command to Drive function. 90 | // 91 | 92 | #include 93 | typedef struct _SENDCMDINPARAMS { 94 | ULONG cBufferSize; // Buffer size in bytes 95 | ATAREGISTERS irDriveRegs; // Structure with drive register values. 96 | UCHAR bDriveNumber; // Physical drive number to send command to. 97 | UCHAR bReserved[3]; // Reserved for future expansion. 98 | ULONG dwReserved[4]; // For future use. 99 | UCHAR bBuffer[1]; // Input buffer. 100 | } SENDCMDINPARAMS, *PSENDCMDINPARAMS, *LPSENDCMDINPARAMS; 101 | #include 102 | 103 | // 104 | // Status returned from driver 105 | // 106 | 107 | #include 108 | typedef struct _DRIVERSTATUS { 109 | UCHAR bDriverError; // Error code from driver, 110 | // or 0 if no error. 111 | UCHAR bIDEError; // Contents of IDE Error register. 112 | // Only valid when bDriverError 113 | // is SMART_IDE_ERROR. 114 | UCHAR bReserved[2]; // Reserved for future expansion. 115 | ULONG dwReserved[2]; // Reserved for future expansion. 116 | } DRIVERSTATUS, *PDRIVERSTATUS, *LPDRIVERSTATUS; 117 | #include 118 | 119 | // 120 | // bDriverError values 121 | // 122 | 123 | #define SMART_NO_ERROR 0 // No error 124 | #define SMART_IDE_ERROR 1 // Error from IDE controller 125 | #define SMART_INVALID_FLAG 2 // Invalid command flag 126 | #define SMART_INVALID_COMMAND 3 // Invalid command byte 127 | #define SMART_INVALID_BUFFER 4 // Bad buffer (null, invalid addr..) 128 | #define SMART_INVALID_DRIVE 5 // Drive number not valid 129 | #define SMART_INVALID_IOCTL 6 // Invalid IOCTL 130 | #define SMART_ERROR_NO_MEM 7 // Could not lock user's buffer 131 | #define SMART_INVALID_REGISTER 8 // Some IDE Register not valid 132 | #define SMART_NOT_SUPPORTED 9 // Invalid cmd flag set 133 | #define SMART_NO_IDE_DEVICE 10 // Cmd issued to device not present 134 | // although drive number is valid 135 | // 136 | // SMART sub commands for execute offline diags 137 | // 138 | #define SMART_OFFLINE_ROUTINE_OFFLINE 0 139 | #define SMART_SHORT_SELFTEST_OFFLINE 1 140 | #define SMART_EXTENDED_SELFTEST_OFFLINE 2 141 | #define SMART_ABORT_OFFLINE_SELFTEST 127 142 | #define SMART_SHORT_SELFTEST_CAPTIVE 129 143 | #define SMART_EXTENDED_SELFTEST_CAPTIVE 130 144 | 145 | #include 146 | typedef struct _SENDCMDOUTPARAMS { 147 | ULONG cBufferSize; // Size of bBuffer in bytes 148 | DRIVERSTATUS DriverStatus; // Driver status structure. 149 | UCHAR bBuffer[1]; // Buffer of arbitrary length in which to store the data read from the // drive. 150 | } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS, *LPSENDCMDOUTPARAMS; 151 | #include 152 | 153 | 154 | #define READ_ATTRIBUTE_BUFFER_SIZE 512 155 | #define IDENTIFY_BUFFER_SIZE 512 156 | #define READ_THRESHOLD_BUFFER_SIZE 512 157 | #define SMART_LOG_SECTOR_SIZE 512 158 | 159 | // 160 | // Feature register defines for SMART "sub commands" 161 | // 162 | 163 | #define READ_ATTRIBUTES 0xD0 164 | #define READ_THRESHOLDS 0xD1 165 | #define ENABLE_DISABLE_AUTOSAVE 0xD2 166 | #define SAVE_ATTRIBUTE_VALUES 0xD3 167 | #define EXECUTE_OFFLINE_DIAGS 0xD4 168 | #define SMART_READ_LOG 0xD5 169 | #define SMART_WRITE_LOG 0xd6 170 | #define ENABLE_SMART 0xD8 171 | #define DISABLE_SMART 0xD9 172 | #define RETURN_SMART_STATUS 0xDA 173 | #define ENABLE_DISABLE_AUTO_OFFLINE 0xDB 174 | 175 | -------------------------------------------------------------------------------- /gpl.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /hbastat.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeorgeK1ng/GenAHCI/b936a0d8bdf410928aefa9e0f373fb1d6c7c8240/hbastat.c -------------------------------------------------------------------------------- /hbastat.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (C) Microsoft Corporation, 2009 4 | 5 | Module Name: 6 | 7 | hbastat.h 8 | 9 | Abstract: 10 | 11 | 12 | 13 | Notes: 14 | 15 | Revision History: 16 | 17 | Nathan Obr (natobr), February 2005 18 | Michael Xing (xiaoxing), December 2009 19 | --*/ 20 | 21 | #pragma once 22 | 23 | BOOLEAN 24 | AhciAdapterReset( 25 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 26 | ); 27 | 28 | VOID 29 | AhciCOMRESET( 30 | PAHCI_CHANNEL_EXTENSION ChannelExtension, 31 | PAHCI_PORT Px 32 | ); 33 | 34 | BOOLEAN 35 | P_NotRunning( 36 | PAHCI_CHANNEL_EXTENSION ChannelExtension, 37 | PAHCI_PORT Px 38 | ); 39 | 40 | VOID 41 | AhciAdapterRunAllPorts( 42 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 43 | ); 44 | 45 | VOID 46 | RunNextPort( 47 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 48 | __in BOOLEAN AtDIRQL 49 | ); 50 | 51 | VOID 52 | P_Running_StartAttempt( 53 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 54 | __in BOOLEAN AtDIRQL 55 | ); 56 | 57 | BOOLEAN 58 | P_Running( 59 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 60 | __in BOOLEAN TimerCallbackProcess 61 | ); 62 | 63 | HW_TIMER_EX P_Running_Callback; 64 | 65 | VOID 66 | P_Running_WaitOnDET( 67 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 68 | __in BOOLEAN TimerCallbackProcess 69 | ); 70 | 71 | VOID 72 | P_Running_WaitWhileDET1( 73 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 74 | __in BOOLEAN TimerCallbackProcess 75 | ); 76 | 77 | VOID 78 | P_Running_WaitOnDET3( 79 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 80 | __in BOOLEAN TimerCallbackProcess 81 | ); 82 | 83 | VOID 84 | P_Running_WaitOnFRE( 85 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 86 | __in BOOLEAN TimerCallbackProcess 87 | ); 88 | 89 | VOID 90 | P_Running_WaitOnBSYDRQ( 91 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 92 | __in BOOLEAN TimerCallbackProcess 93 | ); 94 | 95 | VOID 96 | P_Running_StartFailed( 97 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 98 | __in BOOLEAN TimerCallbackProcess 99 | ); 100 | 101 | BOOLEAN 102 | AhciPortReset ( 103 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 104 | __in BOOLEAN CompleteAllRequests 105 | ); 106 | 107 | VOID 108 | AhciPortErrorRecovery( 109 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 110 | ); 111 | 112 | 113 | -------------------------------------------------------------------------------- /io.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (C) Microsoft Corporation, 2009 4 | 5 | Module Name: 6 | 7 | io.h 8 | 9 | Abstract: 10 | 11 | 12 | 13 | Notes: 14 | 15 | Revision History: 16 | 17 | Nathan Obr (natobr), February 2005 18 | Michael Xing (xiaoxing), December 2009 19 | --*/ 20 | 21 | #pragma once 22 | 23 | ULONG 24 | GetSlotToActivate( 25 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 26 | __in ULONG TargetSlots 27 | ); 28 | 29 | UCHAR 30 | GetSingleIo( 31 | PAHCI_CHANNEL_EXTENSION ChannelExtension 32 | ); 33 | 34 | BOOLEAN 35 | ActivateQueue( 36 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 37 | __in BOOLEAN AtDIRQL 38 | ); 39 | 40 | VOID 41 | AddQueue ( 42 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 43 | __inout PSTORAHCI_QUEUE Queue, 44 | __in PSCSI_REQUEST_BLOCK_EX Srb, 45 | __in ULONG Signature, 46 | __in UCHAR Tag 47 | ); 48 | 49 | PSCSI_REQUEST_BLOCK_EX 50 | RemoveQueue ( 51 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 52 | __inout PSTORAHCI_QUEUE Queue, 53 | __in ULONG Signature, 54 | __in UCHAR Tag 55 | ); 56 | 57 | VOID 58 | AhciCompleteIssuedSRBs( 59 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 60 | __in UCHAR SrbStatus, 61 | __in BOOLEAN AtDIRQL 62 | ); 63 | 64 | VOID 65 | SRBtoATA_CFIS( 66 | PAHCI_CHANNEL_EXTENSION ChannelExtension, 67 | PSLOT_CONTENT SlotContent 68 | ); 69 | 70 | VOID 71 | SRBtoATAPI_CFIS( 72 | PAHCI_CHANNEL_EXTENSION ChannelExtension, 73 | PSLOT_CONTENT SlotContent 74 | ); 75 | 76 | VOID 77 | CfistoATA_CFIS( 78 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 79 | __in PSLOT_CONTENT SlotContent 80 | ); 81 | 82 | ULONG 83 | SRBtoPRDT( 84 | __in PVOID ChannelExtension, 85 | __in PSLOT_CONTENT SlotContent 86 | ); 87 | 88 | VOID 89 | SRBtoCmdHeader( 90 | __in PVOID ChannelExtension, 91 | __in PSLOT_CONTENT SlotContent, 92 | __in ULONG Length, 93 | __in BOOLEAN Reset 94 | ); 95 | 96 | BOOLEAN 97 | AhciProcessIo( 98 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 99 | __in PSCSI_REQUEST_BLOCK_EX Srb, 100 | __in BOOLEAN AtDIRQL 101 | ); 102 | 103 | BOOLEAN 104 | AhciFormIo( 105 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 106 | __in PSCSI_REQUEST_BLOCK_EX Srb, 107 | __in BOOLEAN AtDIRQL 108 | ); 109 | 110 | PSCSI_REQUEST_BLOCK_EX 111 | BuildRequestSenseSrb( 112 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 113 | __in PSCSI_REQUEST_BLOCK_EX FailingSrb 114 | ); 115 | 116 | VOID 117 | AhciPortFailAllIos( 118 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 119 | __in UCHAR SrbStatus, 120 | __in BOOLEAN AtDIRQL 121 | ); 122 | 123 | HW_DPC_ROUTINE AhciPortSrbCompletionDpcRoutine; 124 | 125 | HW_DPC_ROUTINE AhciPortBusChangeDpcRoutine; 126 | 127 | 128 | -------------------------------------------------------------------------------- /make_chk.cmd: -------------------------------------------------------------------------------- 1 | REM set target path 2 | set TARGETPATH=.\bin 3 | 4 | REM set DDK path 5 | set DDKDIR=C:\WinDDK\7600.16385.1 6 | 7 | REM remove and recreate target path 8 | rmdir %TARGETPATH% /S /Q 9 | mkdir %TARGETPATH% 10 | mkdir %TARGETPATH%\x86 11 | mkdir %TARGETPATH%\x64 12 | 13 | REM build x86 driver 14 | setlocal 15 | call %DDKDIR%\bin\setenv.bat %DDKDIR% chk x86 WNET 16 | cd /d %~dp0 17 | if not exist obj%BUILD_ALT_DIR% mkdir obj%BUILD_ALT_DIR% 18 | build -cewgZ /jpath obj%BUILD_ALT_DIR% 19 | endlocal 20 | if errorlevel 1 goto :error 21 | 22 | REM build x64 driver 23 | setlocal 24 | call %DDKDIR%\bin\setenv.bat %DDKDIR% chk x64 WNET 25 | cd /d %~dp0 26 | if not exist obj%BUILD_ALT_DIR% mkdir obj%BUILD_ALT_DIR% 27 | build -cewgZ /jpath obj%BUILD_ALT_DIR% 28 | endlocal 29 | if errorlevel 1 goto :error 30 | 31 | REM copy driver files to bin directory 32 | copy gpl.txt %TARGETPATH%\ 33 | copy objchk_wnet_x86\i386\storahci.sys %TARGETPATH%\x86\ 34 | copy objchk_wnet_AMD64\amd64\storahci.sys %TARGETPATH%\x64\ 35 | copy storahci.inf %TARGETPATH%\x86\ 36 | copy storahci.inf %TARGETPATH%\x64\ 37 | copy txtsetup.oem %TARGETPATH%\ 38 | 39 | REM sign driver files 40 | setlocal 41 | PATH=%PATH%;%DDKDIR%\bin\selfsign;%DDKDIR%\bin\x86 42 | inf2cat /driver:%TARGETPATH%\x86 /os:Server2003_X86,Server2003_X64 /verbose 43 | inf2cat /driver:%TARGETPATH%\x64 /os:Server2003_X86,Server2003_X64 /verbose 44 | makecert -$ individual -r -pe -ss MY -n CN="StorAhci" %TARGETPATH%\StorAhci.cer 45 | signtool.exe sign /v /s MY /n "StorAhci" %TARGETPATH%\x86\*.sys %TARGETPATH%\x86\*.cat 46 | signtool.exe sign /v /s MY /n "StorAhci" %TARGETPATH%\x64\*.sys %TARGETPATH%\x64\*.cat 47 | certmgr -del -c -n "StorAhci" -s -r currentUser MY 48 | endlocal 49 | if errorlevel 1 goto :error 50 | 51 | REM cleanup 52 | REM do not delete the checked object folders, because we need the PDB file for debugging 53 | REM rmdir "objchk_wnet_x86" /S /Q 54 | REM rmdir "objchk_wnet_amd64" /S /Q 55 | del %TARGETPATH%\StorAhci.cer 56 | goto :end 57 | 58 | REM show error message 59 | :error 60 | echo Build errors occurred 61 | pause 62 | exit 63 | 64 | :end 65 | echo Build succeeded 66 | pause -------------------------------------------------------------------------------- /make_fre.cmd: -------------------------------------------------------------------------------- 1 | REM set target path 2 | set TARGETPATH=.\bin 3 | 4 | REM set DDK path 5 | set DDKDIR=%SYSTEMDRIVE%\WinDDK\7600.16385.1 6 | 7 | REM remove and recreate target path 8 | rmdir %TARGETPATH% /S /Q 9 | mkdir %TARGETPATH% 10 | mkdir %TARGETPATH%\x86 11 | mkdir %TARGETPATH%\x64 12 | 13 | REM build x86 driver 14 | setlocal 15 | call %DDKDIR%\bin\setenv.bat %DDKDIR% fre x86 WNET 16 | cd /d %~dp0 17 | if not exist obj%BUILD_ALT_DIR% mkdir obj%BUILD_ALT_DIR% 18 | build -cewgZ /jpath obj%BUILD_ALT_DIR% 19 | endlocal 20 | if errorlevel 1 goto :error 21 | 22 | REM build x64 driver 23 | setlocal 24 | call %DDKDIR%\bin\setenv.bat %DDKDIR% fre x64 WNET 25 | cd /d %~dp0 26 | if not exist obj%BUILD_ALT_DIR% mkdir obj%BUILD_ALT_DIR% 27 | build -cewgZ /jpath obj%BUILD_ALT_DIR% 28 | endlocal 29 | if errorlevel 1 goto :error 30 | 31 | REM copy driver files to bin directory 32 | copy gpl.txt %TARGETPATH%\ 33 | copy objfre_wnet_x86\i386\genahci.sys %TARGETPATH%\x86\ 34 | copy objfre_wnet_AMD64\amd64\genahci.sys %TARGETPATH%\x64\ 35 | copy genahci.inf %TARGETPATH%\x86\ 36 | copy genahci.inf %TARGETPATH%\x64\ 37 | copy txtsetup.oem %TARGETPATH%\ 38 | 39 | REM sign driver files 40 | setlocal 41 | PATH=%PATH%;%DDKDIR%\bin\selfsign;%DDKDIR%\bin\x86 42 | inf2cat /driver:%TARGETPATH%\x86 /os:Server2003_X86,Server2003_X64 /verbose 43 | inf2cat /driver:%TARGETPATH%\x64 /os:Server2003_X86,Server2003_X64 /verbose 44 | makecert -$ individual -r -pe -ss MY -n CN="genahci" %TARGETPATH%\genahci.cer 45 | signtool.exe sign /v /s MY /n "genahci" %TARGETPATH%\x86\*.sys %TARGETPATH%\x86\*.cat 46 | signtool.exe sign /v /s MY /n "genahci" %TARGETPATH%\x64\*.sys %TARGETPATH%\x64\*.cat 47 | certmgr -del -c -n "genahci" -s -r currentUser MY 48 | endlocal 49 | if errorlevel 1 goto :error 50 | 51 | REM cleanup 52 | rmdir "objfre_wnet_x86" /S /Q 53 | rmdir "objfre_wnet_amd64" /S /Q 54 | del %TARGETPATH%\genahci.cer 55 | goto :end 56 | 57 | REM show error message 58 | :error 59 | echo Build errors occurred 60 | pause 61 | exit 62 | 63 | :end 64 | echo Build succeeded 65 | pause -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | !INCLUDE $(NTMAKEENV)\makefile.def -------------------------------------------------------------------------------- /pnppower.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeorgeK1ng/GenAHCI/b936a0d8bdf410928aefa9e0f373fb1d6c7c8240/pnppower.c -------------------------------------------------------------------------------- /pnppower.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (C) Microsoft Corporation, 2009 4 | 5 | Module Name: 6 | 7 | pnppower.h 8 | 9 | Abstract: 10 | 11 | 12 | 13 | Notes: 14 | 15 | Revision History: 16 | 17 | Nathan Obr (natobr), February 2005 18 | Michael Xing (xiaoxing), December 2009 19 | --*/ 20 | 21 | #pragma once 22 | 23 | #if _MSC_VER >= 1200 24 | #pragma warning(push) 25 | #endif 26 | 27 | #pragma warning(disable:4214) // bit field types other than int 28 | #pragma warning(disable:4201) // nameless struct/union 29 | 30 | // ACPI methods 31 | #define ACPI_METHOD_GTF ((ULONG) 'FTG_') // _GTF 32 | #define ACPI_METHOD_SDD ((ULONG) 'DDS_') // _SDD 33 | #define ACPI_METHOD_PR3 ((ULONG) '3RP_') // _PR3 34 | #define ACPI_METHOD_DSM ((ULONG) 'MSD_') // _DSM 35 | 36 | // ACPI _DSM method related definition 37 | #define ACPI_METHOD_DSM_LINKPOWER_REVISION 0x01 38 | 39 | #define ACPI_METHOD_DSM_LINKPOWER_FUNCTION_SUPPORT 0x00 40 | #define ACPI_METHOD_DSM_LINKPOWER_FUNCTION_QUERY 0x01 41 | #define ACPI_METHOD_DSM_LINKPOWER_FUNCTION_CONTROL 0x02 42 | 43 | #define ACPI_METHOD_DSM_LINKPOWER_REMOVE_POWER 0x00 44 | #define ACPI_METHOD_DSM_LINKPOWER_APPLY_POWER 0x01 45 | 46 | // 47 | // When waiting for the link to change power states, don't wait more 48 | // than 100 microseconds. 49 | // 50 | #define AHCI_LINK_POWER_STATE_CHANGE_TIMEOUT_US 100 51 | 52 | typedef union _AHCI_LPM_POWER_SETTINGS { 53 | struct { 54 | //LSB 55 | ULONG HipmEnabled: 1; 56 | ULONG DipmEnabled: 1; 57 | ULONG Reserved: 30; 58 | //MSB 59 | }; 60 | 61 | ULONG AsUlong; 62 | 63 | } AHCI_LPM_POWER_SETTINGS, *PAHCI_LPM_POWER_SETTINGS; 64 | 65 | BOOLEAN 66 | AhciPortInitialize( 67 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 68 | ); 69 | 70 | BOOLEAN 71 | AhciAdapterPowerUp( 72 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 73 | ); 74 | 75 | BOOLEAN 76 | AhciAdapterPowerSettingNotification( 77 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension, 78 | __in PSTOR_POWER_SETTING_INFO PowerSettingInfo 79 | ); 80 | 81 | BOOLEAN 82 | AhciAdapterPowerDown( 83 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 84 | ); 85 | 86 | VOID 87 | AhciPortPowerUp( 88 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 89 | ); 90 | 91 | VOID 92 | AhciPortPowerDown( 93 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 94 | ); 95 | 96 | VOID 97 | AhciPortStop( 98 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 99 | ); 100 | 101 | VOID 102 | AhciPortSmartCompletion( 103 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 104 | __in PSCSI_REQUEST_BLOCK_EX Srb 105 | ); 106 | 107 | VOID 108 | AhciPortNVCacheCompletion( 109 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 110 | __in PSCSI_REQUEST_BLOCK_EX Srb 111 | ); 112 | 113 | VOID 114 | AhciPortGetInitCommands( 115 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 116 | ); 117 | 118 | VOID 119 | AhciPortEvaluateSDDMethod( 120 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 121 | ); 122 | 123 | VOID 124 | AhciAdapterEvaluateDSMMethod( 125 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 126 | ); 127 | 128 | VOID 129 | AhciPortAcpiDSMControl( 130 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension, 131 | __in ULONG PortNumber, 132 | __in BOOLEAN Sleep 133 | ); 134 | 135 | 136 | VOID 137 | IssuePreservedSettingCommands( 138 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 139 | __in_opt PSCSI_REQUEST_BLOCK_EX Srb 140 | ); 141 | 142 | VOID 143 | IssueInitCommands( 144 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 145 | __in_opt PSCSI_REQUEST_BLOCK_EX Srb 146 | ); 147 | 148 | VOID 149 | IssueSetDateAndTimeCommand( 150 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 151 | __inout PSCSI_REQUEST_BLOCK_EX Srb, 152 | __in BOOLEAN SendStandBy 153 | ); 154 | 155 | VOID 156 | IssueReadLogExtCommand( 157 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 158 | __in PSCSI_REQUEST_BLOCK_EX Srb, 159 | __in UCHAR LogAddress, 160 | __in USHORT PageNumber, 161 | __in USHORT BlockCount, 162 | __in USHORT FeatureField, 163 | __in PSTOR_PHYSICAL_ADDRESS PhysicalAddress, 164 | __in PVOID DataBuffer, 165 | __in_opt PSRB_COMPLETION_ROUTINE CompletionRoutine 166 | ); 167 | 168 | HW_TIMER_EX AhciAutoPartialToSlumber; 169 | 170 | BOOLEAN 171 | AhciLpmSettingsModes( 172 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 173 | __in AHCI_LPM_POWER_SETTINGS LpmMode 174 | ); 175 | 176 | 177 | #if _MSC_VER >= 1200 178 | #pragma warning(pop) 179 | #else 180 | #pragma warning(default:4214) 181 | #pragma warning(default:4201) 182 | #endif 183 | 184 | -------------------------------------------------------------------------------- /sources: -------------------------------------------------------------------------------- 1 | TARGETNAME = genahci 2 | TARGETTYPE = MINIPORT 3 | TARGETPATH = obj 4 | MSC_WARNING_LEVEL = /W4 /WX 5 | TARGETLIBS = $(DDK_LIB_PATH)\storport.lib $(DDK_LIB_PATH)\ntoskrnl.lib 6 | SOURCES = common.c entrypts.c hbastat.c io.c pnppower.c StorPortPatch.c util.c genahci.rc -------------------------------------------------------------------------------- /srb_helper.h: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * File: srb_helper.h 4 | */ 5 | 6 | #ifndef __SRB_HELPER_H__ 7 | #define __SRB_HELPER_H__ 8 | 9 | #define IOCTL_SCSI_MINIPORT_DSM_GENERAL ((FILE_DEVICE_SCSI << 16) + 0x0721) 10 | #define IOCTL_SCSI_MINIPORT_HYBRID ((FILE_DEVICE_SCSI << 16) + 0x0620) 11 | 12 | FORCEINLINE PVOID 13 | SrbGetDataBuffer( 14 | __in PVOID Srb 15 | ) 16 | { 17 | PSCSI_REQUEST_BLOCK_EX srb = Srb; 18 | PVOID DataBuffer; 19 | 20 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 21 | { 22 | DataBuffer = srb->DataBuffer; 23 | } 24 | else 25 | { 26 | DataBuffer = ((PSCSI_REQUEST_BLOCK_EX)srb)->DataBuffer; 27 | } 28 | return DataBuffer; 29 | } 30 | 31 | FORCEINLINE VOID 32 | SrbSetSrbFlags( 33 | __in PVOID Srb, 34 | __in ULONG Flags 35 | ) 36 | { 37 | PSCSI_REQUEST_BLOCK_EX srb = Srb; 38 | 39 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 40 | { 41 | srb->SrbFlags |= Flags; 42 | } 43 | else 44 | { 45 | ((PSCSI_REQUEST_BLOCK_EX)srb)->SrbFlags |= Flags; 46 | } 47 | } 48 | 49 | 50 | FORCEINLINE PVOID 51 | SrbGetOriginalRequest( 52 | __in PVOID Srb 53 | ) 54 | { 55 | PSCSI_REQUEST_BLOCK_EX srb = Srb; 56 | 57 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 58 | { 59 | return srb->OriginalRequest; 60 | } 61 | else 62 | { 63 | return ((PSCSI_REQUEST_BLOCK_EX)srb)->OriginalRequest; 64 | } 65 | } 66 | 67 | 68 | // 69 | // If you do not wish to use NT_ASSERT, put "#define SRBHELPER_ASSERT ASSERT" 70 | // before including this file. 71 | // 72 | #if !defined(SRBHELPER_ASSERT) 73 | #define SRBHELPER_ASSERT NT_ASSERT 74 | #endif 75 | 76 | FORCEINLINE PCDB 77 | SrbGetScsiData( 78 | __in PSTORAGE_REQUEST_BLOCK SrbEx, 79 | __in_opt PUCHAR CdbLength8, 80 | __in_opt PULONG CdbLength32, 81 | __in_opt PUCHAR ScsiStatus, 82 | __in_opt PVOID *SenseInfoBuffer, 83 | __in_opt PUCHAR SenseInfoBufferLength 84 | ) 85 | /*++ 86 | 87 | Routine Description: 88 | 89 | Helper function to retrieve SCSI related fields from an extended SRB. If SRB is 90 | not a SRB_FUNCTION_EXECUTE_SCSI or not an extended SRB, default values will be returned. 91 | 92 | Arguments: 93 | 94 | SrbEx - Pointer to extended SRB. 95 | 96 | CdbLength8 - Pointer to buffer to hold CdbLength field value for 97 | SRBEX_DATA_SCSI_CDB16 or SRBEX_DATA_SCSI_CDB32 98 | 99 | CdbLength32 - Pointer to buffer to hold CdbLength field value for 100 | SRBEX_DATA_SCSI_CDB_VAR 101 | 102 | ScsiStatus - Pointer to buffer to hold ScsiStatus field value. 103 | 104 | SenseInfoBuffer - Pointer to buffer to hold SenseInfoBuffer value. 105 | 106 | SenseInfoBufferLength - Pointer to buffer to hold SenseInfoBufferLength value. 107 | 108 | Return Value: 109 | 110 | Pointer to Cdb field or NULL if SRB is not a SRB_FUNCTION_EXECUTE_SCSI. 111 | 112 | --*/ 113 | { 114 | PCDB Cdb = NULL; 115 | ULONG i; 116 | PSRBEX_DATA SrbExData = NULL; 117 | BOOLEAN FoundEntry = FALSE; 118 | 119 | if ((SrbEx->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) && 120 | (SrbEx->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI)) { 121 | SRBHELPER_ASSERT(SrbEx->NumSrbExData > 0); 122 | 123 | for (i = 0; i < SrbEx->NumSrbExData; i++) { 124 | 125 | // Skip any invalid offsets 126 | if ((SrbEx->SrbExDataOffset[i] < sizeof(STORAGE_REQUEST_BLOCK)) || 127 | (SrbEx->SrbExDataOffset[i] >= SrbEx->SrbLength)){ 128 | // Catch any invalid offsets 129 | SRBHELPER_ASSERT(FALSE); 130 | continue; 131 | } 132 | 133 | SrbExData = (PSRBEX_DATA)((PUCHAR)SrbEx + SrbEx->SrbExDataOffset[i]); 134 | 135 | switch (SrbExData->Type) { 136 | 137 | case SrbExDataTypeScsiCdb16: 138 | if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB16) <= SrbEx->SrbLength) { 139 | FoundEntry = TRUE; 140 | if (CdbLength8) { 141 | *CdbLength8 = ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->CdbLength; 142 | } 143 | 144 | if (((PSRBEX_DATA_SCSI_CDB16) SrbExData)->CdbLength > 0) { 145 | Cdb = (PCDB)((PSRBEX_DATA_SCSI_CDB16) SrbExData)->Cdb; 146 | } 147 | 148 | if (ScsiStatus) { 149 | *ScsiStatus = 150 | ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->ScsiStatus; 151 | } 152 | 153 | if (SenseInfoBuffer) { 154 | *SenseInfoBuffer = 155 | ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->SenseInfoBuffer; 156 | } 157 | 158 | if (SenseInfoBufferLength) { 159 | *SenseInfoBufferLength = 160 | ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->SenseInfoBufferLength; 161 | } 162 | 163 | } else { 164 | // Catch invalid offset 165 | SRBHELPER_ASSERT(FALSE); 166 | } 167 | break; 168 | 169 | case SrbExDataTypeScsiCdb32: 170 | if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB32) <= SrbEx->SrbLength) { 171 | FoundEntry = TRUE; 172 | if (CdbLength8) { 173 | *CdbLength8 = ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->CdbLength; 174 | } 175 | 176 | if (((PSRBEX_DATA_SCSI_CDB32) SrbExData)->CdbLength > 0) { 177 | Cdb = (PCDB)((PSRBEX_DATA_SCSI_CDB32) SrbExData)->Cdb; 178 | } 179 | 180 | if (ScsiStatus) { 181 | *ScsiStatus = 182 | ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->ScsiStatus; 183 | } 184 | 185 | if (SenseInfoBuffer) { 186 | *SenseInfoBuffer = 187 | ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->SenseInfoBuffer; 188 | } 189 | 190 | if (SenseInfoBufferLength) { 191 | *SenseInfoBufferLength = 192 | ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->SenseInfoBufferLength; 193 | } 194 | 195 | } else { 196 | // Catch invalid offset 197 | SRBHELPER_ASSERT(FALSE); 198 | } 199 | break; 200 | 201 | case SrbExDataTypeScsiCdbVar: 202 | if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB_VAR) <= SrbEx->SrbLength) { 203 | FoundEntry = TRUE; 204 | if (CdbLength32) { 205 | *CdbLength32 = ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->CdbLength; 206 | } 207 | 208 | if (((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->CdbLength > 0) { 209 | Cdb = (PCDB)((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->Cdb; 210 | } 211 | 212 | if (ScsiStatus) { 213 | *ScsiStatus = 214 | ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->ScsiStatus; 215 | } 216 | 217 | if (SenseInfoBuffer) { 218 | *SenseInfoBuffer = 219 | ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->SenseInfoBuffer; 220 | } 221 | 222 | if (SenseInfoBufferLength) { 223 | *SenseInfoBufferLength = 224 | ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->SenseInfoBufferLength; 225 | } 226 | 227 | } else { 228 | // Catch invalid offset 229 | SRBHELPER_ASSERT(FALSE); 230 | } 231 | break; 232 | } 233 | 234 | if (FoundEntry) { 235 | break; 236 | } 237 | } 238 | 239 | } else { 240 | 241 | if (CdbLength8) { 242 | *CdbLength8 = 0; 243 | } 244 | 245 | if (CdbLength32) { 246 | *CdbLength32 = 0; 247 | } 248 | 249 | if (ScsiStatus) { 250 | *ScsiStatus = SCSISTAT_GOOD; 251 | } 252 | 253 | if (SenseInfoBuffer) { 254 | *SenseInfoBuffer = NULL; 255 | } 256 | 257 | if (SenseInfoBufferLength) { 258 | *SenseInfoBufferLength = 0; 259 | } 260 | } 261 | 262 | return Cdb; 263 | } 264 | 265 | FORCEINLINE PCDB 266 | SrbGetCdb( 267 | __in PVOID Srb 268 | ) 269 | { 270 | PSTORAGE_REQUEST_BLOCK srb = Srb; 271 | PCDB pCdb = NULL; 272 | 273 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 274 | { 275 | return SrbGetScsiData(srb, 276 | NULL, // CdbLength8 277 | NULL, // CdbLength32 278 | NULL, // ScsiStatus 279 | NULL, // SenseInfoBuffer 280 | NULL); // SenseInfoBufferLength 281 | } 282 | else 283 | { 284 | pCdb = (PCDB)((PSCSI_REQUEST_BLOCK_EX)srb)->Cdb; 285 | } 286 | 287 | return pCdb; 288 | } 289 | 290 | FORCEINLINE VOID 291 | SrbSetScsiData( 292 | __in PSTORAGE_REQUEST_BLOCK SrbEx, 293 | __in_opt PUCHAR CdbLength8, 294 | __in_opt PULONG CdbLength32, 295 | __in_opt PUCHAR ScsiStatus, 296 | __in_opt PVOID *SenseInfoBuffer, 297 | __in_opt PUCHAR SenseInfoBufferLength 298 | ) 299 | /*++ 300 | 301 | Routine Description: 302 | 303 | Helper function to set SCSI related fields in an extended SRB. If SRB is 304 | not a SRB_FUNCTION_EXECUTE_SCSI or not an extended SRB, nothing will happen. 305 | 306 | Only the arguments specified will be set in the extended SRB. 307 | 308 | Arguments: 309 | 310 | SrbEx - Pointer to extended SRB. 311 | 312 | CdbLength8 - Pointer to buffer that holds the CdbLength field value for 313 | SRBEX_DATA_SCSI_CDB16 or SRBEX_DATA_SCSI_CDB32 314 | 315 | CdbLength32 - Pointer to buffer that holds the CdbLength field value for 316 | SRBEX_DATA_SCSI_CDB_VAR 317 | 318 | ScsiStatus - Pointer to buffer that holds the ScsiStatus field value. 319 | 320 | SenseInfoBuffer - Pointer to a SenseInfoBuffer pointer. 321 | 322 | SenseInfoBufferLength - Pointer to buffer that holds the SenseInfoBufferLength value. 323 | 324 | --*/ 325 | { 326 | ULONG i; 327 | PSRBEX_DATA SrbExData = NULL; 328 | BOOLEAN FoundEntry = FALSE; 329 | 330 | if ((SrbEx->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) && 331 | (SrbEx->SrbFunction == SRB_FUNCTION_EXECUTE_SCSI)) { 332 | SRBHELPER_ASSERT(SrbEx->NumSrbExData > 0); 333 | 334 | for (i = 0; i < SrbEx->NumSrbExData; i++) { 335 | 336 | // Skip any invalid offsets 337 | if ((SrbEx->SrbExDataOffset[i] < sizeof(PSTORAGE_REQUEST_BLOCK)) || 338 | (SrbEx->SrbExDataOffset[i] >= SrbEx->SrbLength)){ 339 | // Catch any invalid offsets 340 | SRBHELPER_ASSERT(FALSE); 341 | continue; 342 | } 343 | 344 | SrbExData = (PSRBEX_DATA)((PUCHAR)SrbEx + SrbEx->SrbExDataOffset[i]); 345 | 346 | switch (SrbExData->Type) { 347 | 348 | case SrbExDataTypeScsiCdb16: 349 | if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB16) <= SrbEx->SrbLength) { 350 | FoundEntry = TRUE; 351 | if (CdbLength8) { 352 | ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->CdbLength = *CdbLength8; 353 | } 354 | 355 | if (ScsiStatus) { 356 | ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->ScsiStatus = *ScsiStatus; 357 | } 358 | 359 | if (SenseInfoBuffer) { 360 | ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->SenseInfoBuffer = *SenseInfoBuffer; 361 | } 362 | 363 | if (SenseInfoBufferLength) { 364 | ((PSRBEX_DATA_SCSI_CDB16) SrbExData)->SenseInfoBufferLength = *SenseInfoBufferLength; 365 | } 366 | 367 | } else { 368 | // Catch invalid offset 369 | SRBHELPER_ASSERT(FALSE); 370 | } 371 | break; 372 | 373 | case SrbExDataTypeScsiCdb32: 374 | if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB32) <= SrbEx->SrbLength) { 375 | FoundEntry = TRUE; 376 | if (CdbLength8) { 377 | ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->CdbLength = *CdbLength8; 378 | } 379 | 380 | if (ScsiStatus) { 381 | ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->ScsiStatus = *ScsiStatus; 382 | } 383 | 384 | if (SenseInfoBuffer) { 385 | ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->SenseInfoBuffer = *SenseInfoBuffer; 386 | } 387 | 388 | if (SenseInfoBufferLength) { 389 | ((PSRBEX_DATA_SCSI_CDB32) SrbExData)->SenseInfoBufferLength = *SenseInfoBufferLength; 390 | } 391 | 392 | } else { 393 | // Catch invalid offset 394 | SRBHELPER_ASSERT(FALSE); 395 | } 396 | break; 397 | 398 | case SrbExDataTypeScsiCdbVar: 399 | if (SrbEx->SrbExDataOffset[i] + sizeof(SRBEX_DATA_SCSI_CDB_VAR) <= SrbEx->SrbLength) { 400 | FoundEntry = TRUE; 401 | if (CdbLength32) { 402 | ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->CdbLength = *CdbLength32; 403 | } 404 | 405 | if (ScsiStatus) { 406 | ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->ScsiStatus = *ScsiStatus; 407 | } 408 | 409 | if (SenseInfoBuffer) { 410 | ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->SenseInfoBuffer = *SenseInfoBuffer; 411 | } 412 | 413 | if (SenseInfoBufferLength) { 414 | ((PSRBEX_DATA_SCSI_CDB_VAR) SrbExData)->SenseInfoBufferLength = *SenseInfoBufferLength; 415 | } 416 | 417 | } else { 418 | // Catch invalid offset 419 | SRBHELPER_ASSERT(FALSE); 420 | } 421 | break; 422 | } 423 | 424 | if (FoundEntry) { 425 | break; 426 | } 427 | } 428 | } 429 | } 430 | 431 | FORCEINLINE VOID 432 | SrbSetScsiStatus( 433 | __in PVOID Srb, 434 | __in UCHAR ScsiStatus 435 | ) 436 | { 437 | PSTORAGE_REQUEST_BLOCK srb = Srb; 438 | 439 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 440 | { 441 | SrbSetScsiData(srb, 442 | NULL, // CdbLength8 443 | NULL, // CdbLength32 444 | &ScsiStatus, // ScsiStatus 445 | NULL, // SenseInfoBuffer 446 | NULL); // SenseInfoBufferLength 447 | } 448 | else 449 | { 450 | ((PSCSI_REQUEST_BLOCK_EX)srb)->ScsiStatus = ScsiStatus; 451 | } 452 | } 453 | 454 | 455 | FORCEINLINE ULONG 456 | SrbGetDataTransferLength( 457 | __in PVOID Srb 458 | ) 459 | { 460 | PSCSI_REQUEST_BLOCK_EX srb = Srb; 461 | ULONG DataTransferLength; 462 | 463 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 464 | { 465 | DataTransferLength = srb->DataTransferLength; 466 | } 467 | else 468 | { 469 | DataTransferLength = ((PSCSI_REQUEST_BLOCK_EX)srb)->DataTransferLength; 470 | } 471 | return DataTransferLength; 472 | 473 | } 474 | 475 | FORCEINLINE VOID 476 | SrbSetDataTransferLength( 477 | __in PVOID Srb, 478 | __in ULONG DataTransferLength 479 | ) 480 | { 481 | PSCSI_REQUEST_BLOCK_EX srb = Srb; 482 | 483 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 484 | { 485 | srb->DataTransferLength = DataTransferLength; 486 | } 487 | else 488 | { 489 | ((PSCSI_REQUEST_BLOCK_EX)srb)->DataTransferLength = DataTransferLength; 490 | } 491 | } 492 | 493 | FORCEINLINE UCHAR 494 | SrbGetCdbLength( 495 | __in PVOID Srb 496 | ) 497 | { 498 | PSTORAGE_REQUEST_BLOCK srb = Srb; 499 | UCHAR CdbLength = 0; 500 | 501 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 502 | { 503 | SrbGetScsiData(srb, 504 | &CdbLength, // CdbLength8 505 | NULL, // CdbLength32 506 | NULL, // ScsiStatus 507 | NULL, // SenseInfoBuffer 508 | NULL); // SenseInfoBufferLength 509 | } 510 | else 511 | { 512 | CdbLength = ((PSCSI_REQUEST_BLOCK_EX)srb)->CdbLength; 513 | } 514 | return CdbLength; 515 | } 516 | 517 | 518 | FORCEINLINE PVOID 519 | SrbGetNextSrb( 520 | __in PVOID Srb 521 | ) 522 | { 523 | PSCSI_REQUEST_BLOCK_EX srb = Srb; 524 | 525 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 526 | { 527 | return (PVOID)srb->NextSrb; 528 | } 529 | else 530 | { 531 | return (PVOID)((PSCSI_REQUEST_BLOCK_EX)srb)->NextSrb; 532 | } 533 | } 534 | 535 | FORCEINLINE VOID 536 | SrbSetNextSrb( 537 | __in PVOID Srb, 538 | __in_opt PVOID NextSrb 539 | ) 540 | { 541 | PSCSI_REQUEST_BLOCK_EX srb = Srb; 542 | 543 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 544 | { 545 | srb->NextSrb = (PSCSI_REQUEST_BLOCK_EX)NextSrb; 546 | } 547 | else 548 | { 549 | ((PSCSI_REQUEST_BLOCK_EX)srb)->NextSrb = (PSCSI_REQUEST_BLOCK_EX)NextSrb; 550 | } 551 | } 552 | 553 | FORCEINLINE ULONG 554 | SrbGetSrbFunction( 555 | __in PVOID Srb 556 | ) 557 | { 558 | PSTORAGE_REQUEST_BLOCK srb = Srb; 559 | 560 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 561 | { 562 | return srb->SrbFunction; 563 | } 564 | else 565 | { 566 | return (ULONG)((PSTORAGE_REQUEST_BLOCK)srb)->Function; 567 | } 568 | } 569 | 570 | 571 | // 572 | // If you do not wish to use NT_ASSERT, put "#define SRBHELPER_ASSERT ASSERT" 573 | // before including this file. 574 | // 575 | #if !defined(SRBHELPER_ASSERT) 576 | #define SRBHELPER_ASSERT NT_ASSERT 577 | #endif 578 | 579 | FORCEINLINE PSTOR_ADDRESS 580 | SrbGetAddress( 581 | __in PSTORAGE_REQUEST_BLOCK Srb 582 | ) 583 | { 584 | PSTOR_ADDRESS storAddr = NULL; 585 | 586 | if (Srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 587 | { 588 | SRBHELPER_ASSERT(Srb->AddressOffset); 589 | 590 | if (Srb->AddressOffset) 591 | { 592 | storAddr = (PSTOR_ADDRESS)((PUCHAR)Srb + Srb->AddressOffset); 593 | 594 | // 595 | // We currently only support BTL8, so assert if the type is something 596 | // different. 597 | // 598 | SRBHELPER_ASSERT(storAddr->Type == STOR_ADDRESS_TYPE_BTL8); 599 | } 600 | } 601 | 602 | return storAddr; 603 | } 604 | 605 | FORCEINLINE VOID 606 | SrbGetPathTargetLun( 607 | __in PVOID Srb, 608 | __in_opt PUCHAR PathId, 609 | __in_opt PUCHAR TargetId, 610 | __in_opt PUCHAR Lun 611 | ) 612 | { 613 | PSTORAGE_REQUEST_BLOCK srb = Srb; 614 | PSTOR_ADDRESS storAddr = NULL; 615 | 616 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 617 | { 618 | storAddr = (PSTOR_ADDRESS)SrbGetAddress(srb); 619 | if (storAddr) 620 | { 621 | switch (storAddr->Type) 622 | { 623 | case STOR_ADDRESS_TYPE_BTL8: 624 | if (PathId != NULL) { 625 | *PathId = ((PSTOR_ADDR_BTL8)storAddr)->Path; 626 | } 627 | 628 | if (TargetId != NULL) { 629 | *TargetId = ((PSTOR_ADDR_BTL8)storAddr)->Target; 630 | } 631 | 632 | if (Lun != NULL) { 633 | *Lun = ((PSTOR_ADDR_BTL8)storAddr)->Lun; 634 | } 635 | 636 | break; 637 | 638 | default: 639 | SRBHELPER_ASSERT(FALSE); 640 | break; 641 | } 642 | } 643 | } 644 | else 645 | { 646 | if (PathId != NULL) { 647 | *PathId = ((PSCSI_REQUEST_BLOCK_EX)srb)->PathId; 648 | } 649 | 650 | if (TargetId != NULL) { 651 | *TargetId = ((PSCSI_REQUEST_BLOCK_EX)srb)->TargetId; 652 | } 653 | 654 | if (Lun != NULL) { 655 | *Lun = ((PSCSI_REQUEST_BLOCK_EX)srb)->Lun; 656 | } 657 | } 658 | 659 | return; 660 | } 661 | 662 | FORCEINLINE UCHAR 663 | SrbGetLun( 664 | __in PVOID Srb 665 | ) 666 | { 667 | PSTORAGE_REQUEST_BLOCK srb = Srb; 668 | UCHAR Lun = 0; 669 | PSTOR_ADDRESS storAddr = NULL; 670 | 671 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 672 | { 673 | storAddr = (PSTOR_ADDRESS)SrbGetAddress(srb); 674 | if (storAddr) 675 | { 676 | switch (storAddr->Type) 677 | { 678 | case STOR_ADDRESS_TYPE_BTL8: 679 | Lun = ((PSTOR_ADDR_BTL8)storAddr)->Lun; 680 | break; 681 | 682 | default: 683 | SRBHELPER_ASSERT(FALSE); 684 | break; 685 | } 686 | } 687 | } 688 | else 689 | { 690 | Lun = ((PSCSI_REQUEST_BLOCK_EX)srb)->Lun; 691 | } 692 | return Lun; 693 | } 694 | 695 | 696 | 697 | 698 | FORCEINLINE ULONG 699 | SrbGetSrbFlags( 700 | __in PVOID Srb 701 | ) 702 | { 703 | PSCSI_REQUEST_BLOCK_EX srb = Srb; 704 | ULONG srbFlags; 705 | 706 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 707 | { 708 | srbFlags = srb->SrbFlags; 709 | } 710 | else 711 | { 712 | srbFlags = ((PSCSI_REQUEST_BLOCK_EX)srb)->SrbFlags; 713 | } 714 | return srbFlags; 715 | } 716 | 717 | 718 | FORCEINLINE PSRBEX_DATA 719 | SrbGetSrbExDataByType( 720 | __in PSTORAGE_REQUEST_BLOCK Srb, 721 | __in SRBEXDATATYPE Type 722 | ) 723 | { 724 | if ((Srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) && 725 | (Srb->NumSrbExData > 0)) 726 | { 727 | PSRBEX_DATA srbExData = NULL; 728 | UCHAR i = 0; 729 | 730 | for (i = 0; i < Srb->NumSrbExData; i++) 731 | { 732 | if (Srb->SrbExDataOffset[i] >= sizeof(PSCSI_REQUEST_BLOCK_EX) && 733 | Srb->SrbExDataOffset[i] < Srb->SrbLength) 734 | { 735 | srbExData = (PSRBEX_DATA)((PUCHAR)Srb + Srb->SrbExDataOffset[i]); 736 | if (srbExData->Type == Type) 737 | { 738 | return srbExData; 739 | } 740 | } 741 | } 742 | } 743 | 744 | return NULL; 745 | } 746 | 747 | 748 | FORCEINLINE UCHAR 749 | SrbGetPathId( 750 | __in PVOID Srb 751 | ) 752 | { 753 | PSTORAGE_REQUEST_BLOCK srb = Srb; 754 | UCHAR PathId = 0; 755 | PSTOR_ADDRESS storAddr = NULL; 756 | 757 | if (srb->Function == SRB_FUNCTION_STORAGE_REQUEST_BLOCK) 758 | { 759 | storAddr = (PSTOR_ADDRESS)SrbGetAddress(srb); 760 | if (storAddr) 761 | { 762 | switch (storAddr->Type) 763 | { 764 | case STOR_ADDRESS_TYPE_BTL8: 765 | PathId = ((PSTOR_ADDR_BTL8)storAddr)->Path; 766 | break; 767 | 768 | default: 769 | SRBHELPER_ASSERT(FALSE); 770 | break; 771 | } 772 | } 773 | } 774 | else 775 | { 776 | PathId = ((PSCSI_REQUEST_BLOCK_EX)srb)->PathId; 777 | } 778 | return PathId; 779 | 780 | } 781 | 782 | #endif /* __SRB_HELPER_H__ */ 783 | 784 | -------------------------------------------------------------------------------- /txtsetup.oem: -------------------------------------------------------------------------------- 1 | [Disks] 2 | disk1 = "StorAhci SATA AHCI Controller Driver Diskette x86", \x86\storahci.inf, \x86 3 | disk2 = "StorAhci SATA AHCI Controller Driver Diskette x64", \x64\storahci.inf, \x64 4 | 5 | [Defaults] 6 | SCSI = storahci_x86 7 | 8 | [SCSI] 9 | storahci_x86 = "StorAhci SATA AHCI Controller x86" 10 | storahci_x64 = "StorAhci SATA AHCI Controller x64" 11 | 12 | [Files.SCSI.storahci_x86] 13 | driver = disk1, storahci.sys, storahci 14 | inf = disk1, storahci.inf 15 | catalog = disk1, storahci.cat 16 | 17 | [Files.SCSI.storahci_x64] 18 | driver = disk2, storahci.sys, storahci 19 | inf = disk2, storahci.inf 20 | catalog = disk2, storahci.cat 21 | 22 | [HardwareIds.SCSI.storahci_x86] 23 | id = "PCI\CC_010601", "storahci" ; Standard SATA AHCI Controller 24 | 25 | [HardwareIds.SCSI.storahci_x64] 26 | id = "PCI\CC_010601", "storahci" ; Standard SATA AHCI Controller 27 | 28 | [Config.storahci] 29 | value = "Parameters\PnpInterface", "5", REG_DWORD, 00000001 30 | value = "Parameters", "BusType", REG_DWORD, 0000000B -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GeorgeK1ng/GenAHCI/b936a0d8bdf410928aefa9e0f373fb1d6c7c8240/util.c -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | /*++ 2 | 3 | Copyright (C) Microsoft Corporation, 2009 4 | 5 | Module Name: 6 | 7 | util.h 8 | 9 | Abstract: 10 | 11 | Internal support routines used in STORAHCI 12 | 13 | Notes: 14 | 15 | Revision History: 16 | 17 | Nathan Obr (natobr), February 2005 18 | Michael Xing (xiaoxing), December 2009 19 | --*/ 20 | 21 | 22 | #pragma once 23 | 24 | //_At_buffer_(Buffer, _I_, BufferSize, _Post_equal_to_(0)) 25 | __inline 26 | VOID 27 | AhciZeroMemory( 28 | __out __field_bcount(BufferSize) PCHAR Buffer, 29 | __in ULONG BufferSize 30 | ) 31 | { 32 | ULONG i; 33 | 34 | for (i = 0; i < BufferSize; i++) { 35 | Buffer[i] = 0; 36 | } 37 | } 38 | 39 | //_At_buffer_(Buffer, _I_, BufferSize, _Post_equal_to_(Fill)) 40 | __inline 41 | VOID 42 | AhciFillMemory( 43 | __out __field_bcount(BufferSize) PCHAR Buffer, 44 | __in ULONG BufferSize, 45 | __in CHAR Fill 46 | ) 47 | { 48 | ULONG i; 49 | 50 | for (i = 0; i < BufferSize; i++) { 51 | Buffer[i] = Fill; 52 | } 53 | } 54 | 55 | __inline 56 | BOOLEAN 57 | IsPortValid( 58 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension, 59 | __in ULONG PathId 60 | ) 61 | { 62 | return ( (PathId <= AdapterExtension->HighestPort) && (AdapterExtension->PortExtension[PathId] != NULL) ); 63 | } 64 | 65 | __inline 66 | BOOLEAN 67 | IsPortStartCapable( 68 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 69 | ) 70 | /* 71 | Indicates if a port can be started or port can process IO 72 | */ 73 | { 74 | return ( (ChannelExtension != NULL) && 75 | (ChannelExtension->AdapterExtension->StateFlags.StoppedState == 0) && 76 | (ChannelExtension->AdapterExtension->StateFlags.PowerDown == 0) && 77 | (ChannelExtension->StateFlags.Initialized == 1) ); 78 | } 79 | 80 | 81 | __inline 82 | PAHCI_SRB_EXTENSION 83 | GetSrbExtension ( 84 | __in PSCSI_REQUEST_BLOCK_EX Srb 85 | ) 86 | { 87 | PCHAR tempBuffer; 88 | ULONG_PTR leftBytes; 89 | 90 | tempBuffer = (PCHAR)((PSCSI_REQUEST_BLOCK_EX)Srb)->SrbExtension; 91 | 92 | // 93 | // Use lower 32bit is good enough for this calculation. 94 | // 95 | leftBytes = ((ULONG_PTR)tempBuffer) % 128; 96 | 97 | if (leftBytes == 0) { 98 | // 99 | // the buffer is already aligned. 100 | // 101 | return (PAHCI_SRB_EXTENSION)tempBuffer; 102 | } else { 103 | // 104 | // need to align to 128 bytes. 105 | // 106 | return (PAHCI_SRB_EXTENSION)(tempBuffer + 128 - leftBytes); 107 | } 108 | } 109 | 110 | __inline 111 | VOID 112 | MarkSrbToBeCompleted( 113 | __in PSCSI_REQUEST_BLOCK_EX Srb 114 | ) 115 | { 116 | PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb); 117 | SETMASK(srbExtension->Flags, ATA_FLAGS_COMPLETE_SRB); 118 | } 119 | 120 | __inline 121 | BOOLEAN 122 | IsDataTransferNeeded( 123 | __in PSCSI_REQUEST_BLOCK_EX Srb 124 | ) 125 | { 126 | PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb); 127 | return ( (srbExtension->Flags & (ATA_FLAGS_DATA_IN | ATA_FLAGS_DATA_OUT)) || (srbExtension->DataBuffer != NULL) ); 128 | } 129 | 130 | 131 | __inline 132 | BOOLEAN 133 | IsDumpMode( 134 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 135 | ) 136 | /* 137 | Return Value: 138 | TRUE: miniport works in crashdump, hibernate etc. 139 | FALSE: miniport works in normal mode. 140 | */ 141 | { 142 | return (AdapterExtension->DumpMode > 0); 143 | } 144 | 145 | __inline 146 | BOOLEAN 147 | IsDumpCrashMode( 148 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 149 | ) 150 | { 151 | return (AdapterExtension->DumpMode == DUMP_MODE_CRASH); 152 | } 153 | 154 | __inline 155 | BOOLEAN 156 | IsDumpHiberMode( 157 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 158 | ) 159 | { 160 | return (AdapterExtension->DumpMode == DUMP_MODE_HIBER); 161 | } 162 | 163 | __inline 164 | BOOLEAN 165 | IsDumpMarkMemoryMode( 166 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 167 | ) 168 | { 169 | return (AdapterExtension->DumpMode == DUMP_MODE_MARK_MEMORY); 170 | } 171 | 172 | __inline 173 | BOOLEAN 174 | IsDumpResumeMode( 175 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 176 | ) 177 | { 178 | return (AdapterExtension->DumpMode == DUMP_MODE_RESUME); 179 | } 180 | 181 | 182 | __inline 183 | BOOLEAN 184 | IsMsnEnabled( 185 | __in PAHCI_DEVICE_EXTENSION DeviceExtension 186 | ) 187 | { 188 | return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) && 189 | (DeviceExtension->IdentifyDeviceData->MsnSupport == 1) ); 190 | } 191 | 192 | __inline 193 | BOOLEAN 194 | IsRmfEnabled( 195 | __in PAHCI_DEVICE_EXTENSION DeviceExtension 196 | ) 197 | { 198 | return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) && 199 | (DeviceExtension->IdentifyDeviceData->CommandSetSupport.RemovableMediaFeature == 1) && 200 | (DeviceExtension->IdentifyDeviceData->GeneralConfiguration.RemovableMedia == 1) ); 201 | } 202 | 203 | __inline 204 | BOOLEAN 205 | NoFlushDevice( 206 | __in PAHCI_DEVICE_EXTENSION DeviceExtension 207 | ) 208 | { 209 | return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAta) && 210 | (DeviceExtension->IdentifyDeviceData->CommandSetSupport.WriteCache == 0) && 211 | (DeviceExtension->IdentifyDeviceData->CommandSetSupport.FlushCache == 0) && 212 | (DeviceExtension->IdentifyDeviceData->CommandSetSupport.FlushCacheExt == 0) ); 213 | } 214 | 215 | __inline 216 | BOOLEAN 217 | IsTapeDevice( 218 | __in PAHCI_DEVICE_EXTENSION DeviceExtension 219 | ) 220 | { 221 | return ( (DeviceExtension->DeviceParameters.AtaDeviceType == DeviceIsAtapi) && 222 | (DeviceExtension->IdentifyPacketData->GeneralConfiguration.CommandPacketType == 1) ); 223 | } 224 | 225 | 226 | __inline 227 | BOOLEAN 228 | IsNCQCommand ( 229 | __in PAHCI_SRB_EXTENSION SrbExtension 230 | ) 231 | /*++ 232 | Determine if a command is NCQ command. 233 | 234 | Return Value: 235 | TRUE if CommandRegister is 0x60, 0x61, 0x63, 0x64 or 0x65 236 | --*/ 237 | { 238 | UCHAR command = IDE_COMMAND_NOT_VALID; 239 | 240 | // NvCachePassCommand needs to be checked first as it's also ATA command 241 | if ( IsAtaCfisPayload(SrbExtension->AtaFunction) ) { 242 | command = SrbExtension->Cfis.Command; 243 | } else if ( IsAtaCommand(SrbExtension->AtaFunction) ) { 244 | command = SrbExtension->TaskFile.Current.bCommandReg; 245 | } 246 | 247 | if ( (command == IDE_COMMAND_READ_FPDMA_QUEUED) || 248 | (command == IDE_COMMAND_WRITE_FPDMA_QUEUED) || 249 | (command == IDE_COMMAND_NCQ_NON_DATA) || 250 | (command == IDE_COMMAND_SEND_FPDMA_QUEUED) || 251 | (command == IDE_COMMAND_RECEIVE_FPDMA_QUEUED) ) { 252 | return TRUE; 253 | } else { 254 | return FALSE; 255 | } 256 | } 257 | 258 | __inline 259 | BOOLEAN 260 | IsNcqReadWriteCommand ( 261 | __in PAHCI_SRB_EXTENSION SrbExtension 262 | ) 263 | /*++ 264 | Determine if a command is NCQ R/W command. 265 | 266 | Return Value: 267 | TRUE if CommandRegister is 0x60, 0x61 268 | --*/ 269 | { 270 | UCHAR command = IDE_COMMAND_NOT_VALID; 271 | 272 | if ( IsAtaCfisPayload(SrbExtension->AtaFunction) ) { 273 | command = SrbExtension->Cfis.Command; 274 | } else if ( IsAtaCommand(SrbExtension->AtaFunction) ) { 275 | command = SrbExtension->TaskFile.Current.bCommandReg; 276 | } 277 | 278 | if ((command == IDE_COMMAND_READ_FPDMA_QUEUED) || (command == IDE_COMMAND_WRITE_FPDMA_QUEUED)) { 279 | return TRUE; 280 | } else { 281 | return FALSE; 282 | } 283 | } 284 | 285 | __inline 286 | BOOLEAN 287 | IsNCQWriteCommand ( 288 | __in PAHCI_SRB_EXTENSION SrbExtension 289 | ) 290 | /*++ 291 | Determine if a command is NCQ Write command. 292 | 293 | Return Value: 294 | TRUE if CommandRegister is 0x60, 0x61, 0x63, 0x64 or 0x65 295 | --*/ 296 | { 297 | UCHAR command = IDE_COMMAND_NOT_VALID; 298 | 299 | // NvCachePassCommand needs to be checked first as it's also ATA command 300 | if ( IsAtaCfisPayload(SrbExtension->AtaFunction) ) { 301 | command = SrbExtension->Cfis.Command; 302 | } else if ( IsAtaCommand(SrbExtension->AtaFunction) ) { 303 | command = SrbExtension->TaskFile.Current.bCommandReg; 304 | } 305 | 306 | if (command == IDE_COMMAND_WRITE_FPDMA_QUEUED) { 307 | return TRUE; 308 | } else { 309 | return FALSE; 310 | } 311 | } 312 | 313 | __inline 314 | BOOLEAN 315 | IsNormalCommand ( 316 | __in PSCSI_REQUEST_BLOCK_EX Srb 317 | ) 318 | { 319 | /*++ 320 | This could be a macro 321 | 322 | Return Value: 323 | TRUE if any Command Register is any non NCQ IO command 324 | --*/ 325 | PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb); 326 | 327 | if ((srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_READ) || 328 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE) || 329 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_READ_EXT) || 330 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_EXT) || 331 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_READ_DMA) || 332 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_DMA) || 333 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_READ_DMA_EXT) || 334 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_DMA_EXT) || 335 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_DMA_FUA_EXT) || 336 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_READ_DMA_QUEUED_EXT) || 337 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_DMA_QUEUED_EXT) || 338 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_DMA_QUEUED_FUA_EXT) || 339 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_READ_MULTIPLE) || 340 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_MULTIPLE) || 341 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_READ_MULTIPLE_EXT) || 342 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_MULTIPLE_EXT) || 343 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_MULTIPLE_FUA_EXT) || 344 | (srbExtension->TaskFile.Current.bCommandReg == IDE_COMMAND_WRITE_DMA_QUEUED) || 345 | (srbExtension->AtaFunction == ATA_FUNCTION_ATAPI_COMMAND) ) { 346 | return TRUE; 347 | } else { 348 | return FALSE; 349 | } 350 | } 351 | 352 | __inline 353 | BOOLEAN 354 | IsReadWriteCommand( 355 | __in PSCSI_REQUEST_BLOCK_EX Srb 356 | ) 357 | { 358 | /*++ 359 | Return Value: 360 | TRUE if the command is a read or a write command. This includes 361 | NCQ and non-NCQ commands. 362 | --*/ 363 | PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb); 364 | UCHAR command = IDE_COMMAND_NOT_VALID; 365 | 366 | if ( IsAtaCfisPayload(srbExtension->AtaFunction) ) { 367 | command = srbExtension->Cfis.Command; 368 | } else if ( IsAtaCommand(srbExtension->AtaFunction) ) { 369 | command = srbExtension->TaskFile.Current.bCommandReg; 370 | } 371 | 372 | if ((command == IDE_COMMAND_READ_FPDMA_QUEUED) || 373 | (command == IDE_COMMAND_WRITE_FPDMA_QUEUED) || 374 | (command == IDE_COMMAND_READ) || 375 | (command == IDE_COMMAND_WRITE) || 376 | (command == IDE_COMMAND_READ_EXT) || 377 | (command == IDE_COMMAND_WRITE_EXT) || 378 | (command == IDE_COMMAND_READ_DMA) || 379 | (command == IDE_COMMAND_WRITE_DMA) || 380 | (command == IDE_COMMAND_READ_DMA_EXT) || 381 | (command == IDE_COMMAND_WRITE_DMA_EXT) || 382 | (command == IDE_COMMAND_WRITE_DMA_FUA_EXT) || 383 | (command == IDE_COMMAND_READ_DMA_QUEUED_EXT) || 384 | (command == IDE_COMMAND_WRITE_DMA_QUEUED_EXT) || 385 | (command == IDE_COMMAND_WRITE_DMA_QUEUED_FUA_EXT) || 386 | (command == IDE_COMMAND_READ_MULTIPLE) || 387 | (command == IDE_COMMAND_WRITE_MULTIPLE) || 388 | (command == IDE_COMMAND_READ_MULTIPLE_EXT) || 389 | (command == IDE_COMMAND_WRITE_MULTIPLE_EXT) || 390 | (command == IDE_COMMAND_WRITE_MULTIPLE_FUA_EXT) || 391 | (command == IDE_COMMAND_WRITE_DMA_QUEUED) ) { 392 | return TRUE; 393 | } else { 394 | return FALSE; 395 | } 396 | } 397 | 398 | __inline 399 | BOOLEAN 400 | NeedRequestSense ( 401 | __in PSCSI_REQUEST_BLOCK_EX Srb 402 | ) 403 | { 404 | PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb); 405 | PVOID srbSenseBuffer = NULL; 406 | UCHAR srbSenseBufferLength = 0; 407 | 408 | RequestGetSrbScsiData(Srb, NULL, NULL, &srbSenseBuffer, &srbSenseBufferLength); 409 | 410 | return ( IsAtapiCommand(srbExtension->AtaFunction) && 411 | !IsRequestSenseSrb(srbExtension->AtaFunction) && 412 | (Srb->SrbStatus == SRB_STATUS_ERROR) && 413 | (srbSenseBuffer != NULL) && 414 | (srbSenseBufferLength > 0) ); 415 | } 416 | 417 | BOOLEAN 418 | __inline 419 | IsDeviceSupportsTrim ( 420 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 421 | ) 422 | { 423 | // word 169: bit 0 -- Trim function is supported. 424 | return (ChannelExtension->DeviceExtension[0].IdentifyDeviceData->DataSetManagementFeature.SupportsTrim == 1); 425 | } 426 | 427 | 428 | __inline 429 | BOOLEAN 430 | IsDeviceSupportsAN( 431 | __in PIDENTIFY_PACKET_DATA IdentifyPacketData 432 | ) 433 | { 434 | // This bit is actually from IDENTIFY_PACKET_DATA structure for ATAPI devices. 435 | return (IdentifyPacketData->SerialAtaFeaturesSupported.AsynchronousNotification == TRUE); 436 | } 437 | 438 | __inline 439 | BOOLEAN 440 | IsDeviceEnabledAN( 441 | __in PIDENTIFY_PACKET_DATA IdentifyPacketData 442 | ) 443 | { 444 | // This bit is actually from IDENTIFY_PACKET_DATA structure for ATAPI devices. 445 | return (IdentifyPacketData->SerialAtaFeaturesEnabled.AsynchronousNotification == TRUE); 446 | } 447 | 448 | __inline 449 | BOOLEAN 450 | IsExternalPort( 451 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 452 | ) 453 | { 454 | if ( (ChannelExtension->Px->CMD.HPCP) || 455 | ((ChannelExtension->AdapterExtension->CAP.SXS) && (ChannelExtension->Px->CMD.ESP)) || 456 | ((ChannelExtension->AdapterExtension->CAP.SMPS) && (ChannelExtension->Px->CMD.MPSP)) ) { 457 | //1. Px->CMD.HPCP indicates that the port is hot-pluggable. (both signal and power cable) 458 | //2. CAP.SXS && Px->CMD.ESP indicates that it's an ESATA port. (only signal cable) 459 | //3. CAP.SMPS && Px->CMD.MPSP indicates that Mechanical Switch is implemented on the port. 460 | return TRUE; 461 | } 462 | 463 | return FALSE; 464 | } 465 | 466 | __inline 467 | BOOLEAN 468 | IsLPMCapablePort( 469 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 470 | ) 471 | { 472 | // if a port is marked eSATA port but not having mechanical switch nor supporting Cold Presence Detection, don't turn on LPM on it. 473 | if ( (ChannelExtension->Px->CMD.HPCP) || 474 | ((ChannelExtension->AdapterExtension->CAP.SXS) && (ChannelExtension->Px->CMD.ESP)) ) { 475 | 476 | if ( ((ChannelExtension->AdapterExtension->CAP.SMPS == 0) || (ChannelExtension->Px->CMD.MPSP == 0)) && 477 | (ChannelExtension->Px->CMD.CPD == 0) ) { 478 | return FALSE; 479 | } 480 | } 481 | 482 | return TRUE; 483 | } 484 | 485 | __inline 486 | BOOLEAN 487 | IsDeviceHybridInfoSupported( 488 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 489 | ) 490 | { 491 | if ( (ChannelExtension->DeviceExtension[0].DeviceParameters.AtaDeviceType == DeviceIsAta) && 492 | (ChannelExtension->DeviceExtension[0].IdentifyDeviceData->SerialAtaFeaturesSupported.HybridInformation == 1) ) { 493 | 494 | return TRUE; 495 | } 496 | 497 | return FALSE; 498 | } 499 | 500 | __inline 501 | BOOLEAN 502 | IsDeviceHybridInfoEnabled( 503 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 504 | ) 505 | { 506 | if ( IsDeviceHybridInfoSupported(ChannelExtension) && 507 | (ChannelExtension->DeviceExtension[0].IdentifyDeviceData->SerialAtaFeaturesEnabled.HybridInformation == 1) ) { 508 | 509 | return TRUE; 510 | } 511 | 512 | return FALSE; 513 | } 514 | 515 | __inline 516 | BOOLEAN 517 | IsDeviceGeneralPurposeLoggingSupported( 518 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 519 | ) 520 | { 521 | if (IsAtaDevice(&ChannelExtension->DeviceExtension->DeviceParameters) && 522 | (ChannelExtension->DeviceExtension->IdentifyDeviceData->CommandSetSupport.GpLogging == 1) && 523 | (ChannelExtension->DeviceExtension->IdentifyDeviceData->CommandSetSupport.BigLba == 1) ) { 524 | 525 | return TRUE; 526 | } 527 | 528 | return FALSE; 529 | } 530 | 531 | __inline 532 | BOOLEAN 533 | IsD3ColdAllowed( 534 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 535 | ) 536 | { 537 | BOOLEAN allowed = TRUE; 538 | 539 | UNREFERENCED_PARAMETER(AdapterExtension); 540 | 541 | 542 | return allowed; 543 | } 544 | 545 | __inline 546 | BOOLEAN 547 | IsPortD3ColdEnabled( 548 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 549 | ) 550 | { 551 | // if device is D3Cold capable, return TRUE. 552 | if (ChannelExtension->StateFlags.D3ColdEnabled == 1) { 553 | return TRUE; 554 | } 555 | 556 | return FALSE; 557 | } 558 | 559 | __inline 560 | BOOLEAN 561 | IsReceivingSystemPowerHints( 562 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 563 | ) 564 | { 565 | return (AdapterExtension->SystemPowerHintState != RaidSystemPowerUnknown); 566 | } 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | __inline 576 | BOOLEAN 577 | AdapterPoFxEnabled ( 578 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 579 | ) 580 | { 581 | return (AdapterExtension->StateFlags.PoFxEnabled == 1); 582 | } 583 | 584 | __inline 585 | BOOLEAN 586 | PortPoFxEnabled ( 587 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 588 | ) 589 | { 590 | return (ChannelExtension->StateFlags.PoFxEnabled == 1); 591 | } 592 | 593 | __inline 594 | BOOLEAN 595 | AdapterAcquireActiveReference ( 596 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension, 597 | __inout_opt PBOOLEAN InIdle 598 | ) 599 | { 600 | BOOLEAN idle = FALSE; 601 | BOOLEAN referenceAcquired = FALSE; 602 | 603 | if (AdapterPoFxEnabled(AdapterExtension)) { 604 | ULONG status; 605 | status = StorPortPoFxActivateComponent(AdapterExtension, 606 | NULL, 607 | NULL, 608 | 0, 609 | 0); 610 | // STOR_STATUS_BUSY indicates that ActivateComponent is not completed yet. 611 | idle = (status == STOR_STATUS_BUSY); 612 | 613 | if ( (status == STOR_STATUS_SUCCESS) || (status == STOR_STATUS_BUSY) ) { 614 | referenceAcquired = TRUE; 615 | } 616 | } 617 | 618 | if (InIdle != NULL) { 619 | *InIdle = idle; 620 | } 621 | 622 | return referenceAcquired; 623 | } 624 | 625 | __inline 626 | VOID 627 | AdapterReleaseActiveReference ( 628 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 629 | ) 630 | { 631 | if (AdapterPoFxEnabled(AdapterExtension)) { 632 | StorPortPoFxIdleComponent(AdapterExtension, 633 | NULL, 634 | NULL, 635 | 0, 636 | 0); 637 | } 638 | } 639 | 640 | __inline 641 | BOOLEAN 642 | PortAcquireActiveReference ( 643 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 644 | __in_opt PSCSI_REQUEST_BLOCK_EX Srb, 645 | __inout_opt PBOOLEAN InIdle 646 | ) 647 | { 648 | BOOLEAN idle = FALSE; 649 | BOOLEAN referenceAcquired = FALSE; 650 | 651 | if (PortPoFxEnabled(ChannelExtension)) { 652 | ULONG status; 653 | 654 | status = StorPortPoFxActivateComponentEx(ChannelExtension->AdapterExtension, 655 | (PSTOR_ADDRESS)&ChannelExtension->DeviceExtension[0].DeviceAddress, 656 | Srb, 657 | 0, 658 | 0); 659 | // STOR_STATUS_BUSY indicates that ActivateComponent is not completed yet. 660 | idle = (status == STOR_STATUS_BUSY); 661 | 662 | if ( (status == STOR_STATUS_SUCCESS) || (status == STOR_STATUS_BUSY) ) { 663 | if (Srb != NULL) { 664 | PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb); 665 | SETMASK(srbExtension->Flags, ATA_FLAGS_ACTIVE_REFERENCE); 666 | } 667 | 668 | referenceAcquired = TRUE; 669 | } 670 | 671 | } else { 672 | UNREFERENCED_PARAMETER(Srb); 673 | } 674 | 675 | if (InIdle != NULL) { 676 | *InIdle = idle; 677 | } 678 | 679 | return referenceAcquired; 680 | } 681 | 682 | __inline 683 | VOID 684 | PortReleaseActiveReference ( 685 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 686 | __in_opt PSCSI_REQUEST_BLOCK_EX Srb 687 | ) 688 | { 689 | if (PortPoFxEnabled(ChannelExtension)) { 690 | if (Srb != NULL) { 691 | PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb); 692 | CLRMASK(srbExtension->Flags, ATA_FLAGS_ACTIVE_REFERENCE); 693 | } 694 | 695 | StorPortPoFxIdleComponentEx(ChannelExtension->AdapterExtension, 696 | (PSTOR_ADDRESS)&ChannelExtension->DeviceExtension[0].DeviceAddress, 697 | Srb, 698 | 0, 699 | 0); 700 | } else { 701 | UNREFERENCED_PARAMETER(Srb); 702 | } 703 | } 704 | 705 | __inline 706 | BOOLEAN 707 | DeviceIdentificationComplete( 708 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 709 | ) 710 | { 711 | ULONG i; 712 | 713 | for (i = 0; i <= AdapterExtension->HighestPort; i++) { 714 | if ( (AdapterExtension->PortExtension[i] != NULL) && 715 | (AdapterExtension->PortExtension[i]->DeviceExtension->DeviceParameters.AtaDeviceType == DeviceUnknown) ) { 716 | return FALSE; 717 | } 718 | } 719 | 720 | return TRUE; 721 | } 722 | 723 | __inline 724 | ULONG 725 | RequestGetDataTransferLength ( 726 | __in PSCSI_REQUEST_BLOCK_EX Srb 727 | ) 728 | { 729 | PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb); 730 | 731 | if (srbExtension->DataTransferLength > 0) { 732 | return srbExtension->DataTransferLength; 733 | } else { 734 | return SrbGetDataTransferLength(Srb); 735 | } 736 | } 737 | 738 | __inline 739 | VOID 740 | RequestSetDataTransferLength ( 741 | __in PSCSI_REQUEST_BLOCK_EX Srb, 742 | __in ULONG Length 743 | ) 744 | { 745 | PAHCI_SRB_EXTENSION srbExtension = GetSrbExtension(Srb); 746 | 747 | if (srbExtension->DataTransferLength > 0) { 748 | srbExtension->DataTransferLength = Length; 749 | } else { 750 | SrbSetDataTransferLength(Srb, Length); 751 | } 752 | 753 | return; 754 | } 755 | 756 | __inline 757 | UCHAR 758 | NumberOfSetBits ( 759 | __in ULONG Value 760 | ) 761 | /*++ 762 | This routine emulates the __popcnt intrinsic function. 763 | 764 | Return Value: 765 | Count of '1's in the ULONG value 766 | --*/ 767 | { 768 | // 769 | // Partition into groups of bit pairs. Compute population count for each 770 | // bit pair. 771 | // 772 | Value -= (Value >> 1) & 0x55555555; 773 | 774 | // 775 | // Sum population count of adjacent pairs into quads. 776 | // 777 | Value = (Value & 0x33333333) + ((Value >> 2) & 0x33333333); 778 | 779 | // 780 | // Sum population count of adjacent quads into octets. Lower quad in each 781 | // octet has desired sum and upper quad is garbage. 782 | // 783 | Value = (Value + (Value >> 4)) & 0x0F0F0F0F; 784 | 785 | // 786 | // The lower quads in each octet must now be accumulated by multiplying with 787 | // a magic multiplier: 788 | // 789 | // 0p0q0r0s * 0x01010101 = :0p0q0r0s 790 | // 0p:0q0r0s 791 | // 0p0q:0r0s 792 | // 0p0q0r:0s 793 | // 000pxxww:vvuutt0s 794 | // 795 | // The octet vv contains the final interesting result. 796 | // 797 | Value *= 0x01010101; 798 | 799 | return (UCHAR)(Value >> 24); 800 | } 801 | 802 | VOID 803 | RecordExecutionHistory( 804 | PAHCI_CHANNEL_EXTENSION ChannelExtension, 805 | ULONG Function 806 | ); 807 | 808 | VOID 809 | RecordInterruptHistory( 810 | PAHCI_CHANNEL_EXTENSION ChannelExtension, 811 | ULONG PxIS, 812 | ULONG PxSSTS, 813 | ULONG PxSERR, 814 | ULONG PxCI, 815 | ULONG PxSACT, 816 | ULONG Function 817 | ); 818 | 819 | VOID 820 | Set_PxIE( 821 | PAHCI_CHANNEL_EXTENSION ChannelExtension, 822 | PAHCI_INTERRUPT_ENABLE IE 823 | ); 824 | 825 | 826 | __inline 827 | BOOLEAN 828 | IsFuaSupported( 829 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 830 | ) 831 | { 832 | return (ChannelExtension->DeviceExtension->DeviceParameters.StateFlags.FuaSupported == 1); 833 | } 834 | 835 | __inline 836 | BOOLEAN 837 | IsDeviceSupportsHIPM( 838 | __in PIDENTIFY_DEVICE_DATA IdentifyDeviceData 839 | ) 840 | { 841 | return (IdentifyDeviceData->SerialAtaCapabilities.HIPM == TRUE); 842 | } 843 | 844 | __inline 845 | BOOLEAN 846 | IsDeviceSupportsDIPM( 847 | __in PIDENTIFY_DEVICE_DATA IdentifyDeviceData 848 | ) 849 | { 850 | return (IdentifyDeviceData->SerialAtaFeaturesSupported.DIPM == TRUE); 851 | } 852 | 853 | __inline 854 | BOOLEAN 855 | NoLpmSupport( 856 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 857 | ) 858 | { 859 | if (ChannelExtension->AdapterExtension->StateFlags.StoppedState == 1) { 860 | // adapter is stopped, Px registers are not accessible. 861 | return TRUE; 862 | } 863 | 864 | if (ChannelExtension->AdapterExtension->CAP.PSC == 0) { 865 | // adapter doesn't support Partial state 866 | return TRUE; 867 | } 868 | 869 | // return TRUE if HIPM and DIPM are not supported. 870 | return ( (ChannelExtension->AdapterExtension->CAP.SALP == 0) && 871 | (!IsDeviceSupportsDIPM(ChannelExtension->DeviceExtension[0].IdentifyDeviceData)) ); 872 | } 873 | 874 | 875 | __inline 876 | BOOLEAN 877 | NeedToSetTransferMode( 878 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 879 | ) 880 | { 881 | UNREFERENCED_PARAMETER(ChannelExtension); // make WDK sample build clean 882 | return FALSE; 883 | } 884 | 885 | __inline 886 | BOOLEAN 887 | IsSingleIoDevice( 888 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 889 | ) 890 | { 891 | UNREFERENCED_PARAMETER(AdapterExtension); // make WDK sample build clean 892 | return FALSE; 893 | } 894 | 895 | __inline 896 | BOOLEAN 897 | AdapterResetInInit( 898 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 899 | ) 900 | { 901 | UNREFERENCED_PARAMETER(AdapterExtension); // make WDK sample build clean 902 | return FALSE; 903 | } 904 | 905 | __inline 906 | BOOLEAN 907 | IgnoreHotPlug( 908 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 909 | ) 910 | { 911 | return (ChannelExtension->StateFlags.IgnoreHotplugInterrupt == 1); 912 | } 913 | 914 | __inline 915 | BOOLEAN 916 | AdapterNoNonQueuedErrorRecovery( 917 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 918 | ) 919 | { 920 | UNREFERENCED_PARAMETER(AdapterExtension); // make WDK sample build clean 921 | return FALSE; 922 | } 923 | 924 | __inline 925 | BOOLEAN 926 | CloResetEnabled( 927 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension 928 | ) 929 | { 930 | UNREFERENCED_PARAMETER(AdapterExtension); // make WDK sample build clean 931 | return (AdapterExtension->CAP.SCLO == 1); 932 | } 933 | 934 | __inline 935 | BOOLEAN 936 | IsNCQSupported( 937 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 938 | ) 939 | { 940 | if ( IsAtaDevice(&ChannelExtension->DeviceExtension->DeviceParameters) && 941 | (ChannelExtension->AdapterExtension->CAP.SNCQ == 1) && 942 | (ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaCapabilities.NCQ == 1) && 943 | (ChannelExtension->DeviceExtension->IdentifyDeviceData->QueueDepth > 1) ) { 944 | //Queue Depth is a 0 based value (i.e. 0x0 == 1). StorAHCI reserves slot 0 for internal use. 945 | return TRUE; 946 | } 947 | return FALSE; 948 | } 949 | 950 | __inline 951 | ULONG 952 | GetOccupiedSlots ( 953 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 954 | ) 955 | { 956 | return ( ChannelExtension->SlotManager.CommandsIssued | 957 | ChannelExtension->SlotManager.NCQueueSlice | 958 | ChannelExtension->SlotManager.NormalQueueSlice | 959 | ChannelExtension->SlotManager.SingleIoSlice | 960 | ChannelExtension->SlotManager.CommandsToComplete ); 961 | } 962 | 963 | __inline 964 | BOOLEAN 965 | ErrorRecoveryIsPending ( 966 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 967 | ) 968 | { 969 | return ( (ChannelExtension->StateFlags.CallAhciReset == 1) || 970 | (ChannelExtension->StateFlags.CallAhciReportBusChange == 1) || 971 | (ChannelExtension->StateFlags.CallAhciNonQueuedErrorRecovery == 1) ); 972 | } 973 | 974 | __inline 975 | BOOLEAN 976 | IsMiniportInternalSrb ( 977 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 978 | __in PSCSI_REQUEST_BLOCK_EX Srb 979 | ) 980 | { 981 | return ( (Srb == &ChannelExtension->Local.Srb) || 982 | (Srb == &ChannelExtension->Sense.Srb) ); 983 | } 984 | 985 | __inline 986 | VOID 987 | PortClearPendingInterrupt ( 988 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 989 | ) 990 | { 991 | StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->SERR.AsUlong, (ULONG)~0); 992 | StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, &ChannelExtension->Px->IS.AsUlong, (ULONG)~0); 993 | StorPortWriteRegisterUlong(ChannelExtension->AdapterExtension, ChannelExtension->AdapterExtension->IS, (1 << ChannelExtension->PortNumber)); 994 | } 995 | 996 | __inline 997 | BOOLEAN 998 | PartialToSlumberTransitionIsAllowed ( 999 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 1000 | __in AHCI_COMMAND CMD, 1001 | __in ULONG CI, 1002 | __in ULONG SACT 1003 | ) 1004 | { 1005 | if ( (CI != 0) || (SACT != 0) ) { 1006 | //device still has request pending 1007 | return FALSE; 1008 | } 1009 | 1010 | if ((ChannelExtension->LastUserLpmPowerSetting & 0x3) == 0) { 1011 | //Neither HIPM nor DIPM is allowed. e.g. LastUserLpmPowerSetting --- bit 0: HIPM; bit 1: DIPM 1012 | return FALSE; 1013 | } 1014 | 1015 | if ((ChannelExtension->AutoPartialToSlumberInterval == 0)) { 1016 | //Software auto Partial to Slumber is not enabled yet. 1017 | return FALSE; 1018 | } 1019 | 1020 | if (ChannelExtension->StartState.ChannelNextStartState != StartComplete) { 1021 | //port is not started yet 1022 | return FALSE; 1023 | } 1024 | 1025 | if ( NoLpmSupport(ChannelExtension) || !IsLPMCapablePort(ChannelExtension) ) { 1026 | //link power management is not supported 1027 | return FALSE; 1028 | } 1029 | 1030 | if (!IsDeviceSupportsHIPM(ChannelExtension->DeviceExtension[0].IdentifyDeviceData)) { 1031 | // HIPM is not supported. 1032 | return FALSE; 1033 | } 1034 | 1035 | 1036 | if ( ( (ChannelExtension->AdapterExtension->CAP.SALP == 0) || (CMD.ALPE == 0) ) && 1037 | (!IsDeviceSupportsDIPM(ChannelExtension->DeviceExtension[0].IdentifyDeviceData)) ) { 1038 | //Neither HIPM nor DIPM is enabled. 1039 | return FALSE; 1040 | } 1041 | 1042 | if ( ((ChannelExtension->LastUserLpmPowerSetting & 0x2) != 0) && 1043 | (ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaCapabilities.DeviceAutoPS == 1) && 1044 | (ChannelExtension->DeviceExtension->IdentifyDeviceData->SerialAtaFeaturesEnabled.DeviceAutoPS == 1) ) { 1045 | //DIPM is enabled; device supports and enabled Device auto Partial to Slumber. 1046 | //note that IdentifyDeviceData applies to both ATA and ATAPI devices. 1047 | return FALSE; 1048 | } 1049 | 1050 | if ( (ChannelExtension->AdapterExtension->CAP.SALP == 1) && 1051 | (CMD.ALPE != 0) && 1052 | ( (CMD.ASP == 1) || 1053 | ( (ChannelExtension->AdapterExtension->CAP2.APST != 0) && (CMD.APSTE != 0) ) ) ) { 1054 | // HIPM is enabled. AND 1055 | // either Host initiates Slumber automatically, OR 1056 | // Host supports and enabled auto Partial to Slumber. 1057 | return FALSE; 1058 | } 1059 | 1060 | return TRUE; 1061 | } 1062 | 1063 | __inline 1064 | ULONG 1065 | GetHybridMaxLbaRangeCountForChangeLba ( 1066 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 1067 | ) 1068 | { 1069 | // 1070 | // If CacheBehavior is supported, disk doesn't move data from primary medium to caching medium when 1071 | // executes HybridChangeByLba command. Use 64 as default MaxLbaRangeCountForChangeLba value. 1072 | // Otherwise, use 8 as default value. 1073 | // 1074 | if (ChannelExtension->DeviceExtension->HybridInfo.SupportedOptions.SupportCacheBehavior == 1) { 1075 | return 64; 1076 | } else { 1077 | return 8; 1078 | } 1079 | } 1080 | 1081 | VOID 1082 | PortBusChangeProcess ( 1083 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension 1084 | ); 1085 | 1086 | PAHCI_MEMORY_REGISTERS 1087 | GetABARAddress( 1088 | __in PAHCI_ADAPTER_EXTENSION AdapterExtension, 1089 | __in PPORT_CONFIGURATION_INFORMATION_EX ConfigInfo 1090 | ); 1091 | 1092 | VOID 1093 | AhciCompleteJustSlottedRequest( 1094 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 1095 | __in PSCSI_REQUEST_BLOCK_EX Srb, 1096 | __in BOOLEAN AtDIRQL 1097 | ); 1098 | 1099 | VOID 1100 | AhciCompleteRequest( 1101 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 1102 | __in PSCSI_REQUEST_BLOCK_EX Srb, 1103 | __in BOOLEAN AtDIRQL 1104 | ); 1105 | 1106 | BOOLEAN 1107 | UpdateSetFeatureCommands( 1108 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 1109 | __in UCHAR OldFeatures, 1110 | __in UCHAR NewFeatures, 1111 | __in UCHAR OldSectorCount, 1112 | __in UCHAR NewSectorCount 1113 | ); 1114 | 1115 | VOID 1116 | GetAvailableSlot( 1117 | PAHCI_CHANNEL_EXTENSION ChannelExtension, 1118 | PSCSI_REQUEST_BLOCK_EX Srb 1119 | ); 1120 | 1121 | VOID 1122 | ReleaseSlottedCommand( 1123 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 1124 | __in UCHAR SlotNumber, 1125 | __in BOOLEAN AtDIRQL 1126 | ); 1127 | 1128 | VOID 1129 | RestorePreservedSettings( 1130 | __in PAHCI_CHANNEL_EXTENSION ChannelExtension, 1131 | __in BOOLEAN AtDIRQL 1132 | ); 1133 | 1134 | VOID 1135 | AhciPortIssueInitCommands( 1136 | PAHCI_CHANNEL_EXTENSION ChannelExtension 1137 | ); 1138 | 1139 | __success(return != FALSE) 1140 | BOOLEAN 1141 | CompareId ( 1142 | __in_opt PSTR DeviceId, 1143 | __in ULONG DeviceIdLength, 1144 | __in_opt PZZSTR TargetId, 1145 | __in ULONG TargetIdLength, 1146 | __inout_opt PULONG Value 1147 | ); 1148 | 1149 | ULONG 1150 | GetStringLength ( 1151 | __in PSTR String, 1152 | __in ULONG MaxLength 1153 | ); 1154 | 1155 | __inline 1156 | VOID 1157 | AhciUlongIncrement( 1158 | __inout PULONG Value 1159 | ) 1160 | { 1161 | if (Value != NULL && 1162 | *Value != MAXULONG) { 1163 | (*Value)++; 1164 | } 1165 | } 1166 | 1167 | --------------------------------------------------------------------------------