1 /*++ 2 3 Copyright (c) 2008-2012 Alexandr A. Telyatnikov (Alter) 4 5 Module Name: 6 id_probe.cpp 7 8 Abstract: 9 This module handles SATA-related staff 10 11 Author: 12 Alexander A. Telyatnikov (Alter) 13 14 Environment: 15 kernel mode only 16 17 Notes: 18 19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 Revision History: 31 32 Licence: 33 GPLv2 34 35 --*/ 36 37 #ifndef __UNIATA_SATA__H__ 38 #define __UNIATA_SATA__H__ 39 40 UCHAR 41 NTAPI 42 UniataSataConnect( 43 IN PVOID HwDeviceExtension, 44 IN ULONG lChannel, // logical channel 45 IN ULONG pm_port = 0 /* for port multipliers */ 46 ); 47 48 #define UNIATA_SATA_RESET_ENABLE TRUE 49 #define UNIATA_SATA_FAST_ENABLE FALSE 50 51 UCHAR 52 NTAPI 53 UniataSataPhyEnable( 54 IN PVOID HwDeviceExtension, 55 IN ULONG lChannel, // logical channel 56 IN ULONG pm_port = 0, /* for port multipliers */ 57 IN BOOLEAN doReset = UNIATA_SATA_FAST_ENABLE 58 ); 59 60 #define UNIATA_SATA_DO_CONNECT TRUE 61 #define UNIATA_SATA_IGNORE_CONNECT FALSE 62 63 BOOLEAN 64 NTAPI 65 UniataSataClearErr( 66 IN PVOID HwDeviceExtension, 67 IN ULONG lChannel, // logical channel 68 IN BOOLEAN do_connect, 69 IN ULONG pm_port = 0 /* for port multipliers */ 70 ); 71 72 #define UNIATA_SATA_EVENT_ATTACH 0x01 73 #define UNIATA_SATA_EVENT_DETACH 0x02 74 75 BOOLEAN 76 NTAPI 77 UniataSataEvent( 78 IN PVOID HwDeviceExtension, 79 IN ULONG lChannel, // logical channel 80 IN ULONG Action, 81 IN ULONG pm_port = 0 /* for port multipliers */ 82 ); 83 /* 84 #define UniataIsSATARangeAvailable(deviceExtension, lChannel) \ 85 ((deviceExtension->BaseIoAddressSATA_0.Addr || \ 86 deviceExtension->BaseIoAHCI_0.Addr) && \ 87 (deviceExtension->chan[lChannel].RegTranslation[IDX_SATA_SStatus].Addr)) 88 */ 89 __inline 90 BOOLEAN 91 UniataIsSATARangeAvailable( 92 IN PHW_DEVICE_EXTENSION deviceExtension, 93 IN ULONG lChannel 94 ) 95 { 96 // seems, check for deviceExtension->BaseIoAddressSATA_0.Addr and 97 // deviceExtension->BaseIoAHCI_0.Addr is not necessary now 98 if(deviceExtension->chan[lChannel].RegTranslation[IDX_SATA_SStatus].Addr || 99 deviceExtension->chan[lChannel].RegTranslation[IDX_SATA_SStatus].Proc) { 100 return TRUE; 101 } 102 return FALSE; 103 } // end UniataIsSATARangeAvailable() 104 105 106 ULONG 107 NTAPI 108 UniataSataReadPort4( 109 IN PHW_CHANNEL chan, 110 IN ULONG io_port_ndx, 111 IN ULONG pm_port=0 /* for port multipliers */ 112 ); 113 114 VOID 115 NTAPI 116 UniataSataWritePort4( 117 IN PHW_CHANNEL chan, 118 IN ULONG io_port_ndx, 119 IN ULONG data, 120 IN ULONG pm_port=0 /* for port multipliers */ 121 ); 122 123 BOOLEAN 124 NTAPI 125 UniataAhciInit( 126 IN PVOID HwDeviceExtension 127 ); 128 129 #ifdef _DEBUG 130 VOID 131 NTAPI 132 UniataDumpAhciPortRegs( 133 IN PHW_CHANNEL chan 134 ); 135 #endif 136 137 BOOLEAN 138 NTAPI 139 UniataAhciDetect( 140 IN PVOID HwDeviceExtension, 141 IN PPCI_COMMON_CONFIG pciData, // optional 142 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo 143 ); 144 145 UCHAR 146 NTAPI 147 UniataAhciStatus( 148 IN PVOID HwDeviceExtension, 149 IN ULONG lChannel, 150 IN ULONG DeviceNumber 151 ); 152 153 VOID 154 NTAPI 155 UniataAhciSnapAtaRegs( 156 IN PHW_CHANNEL chan, 157 IN ULONG DeviceNumber, 158 IN OUT PIDEREGS_EX regs 159 ); 160 161 ULONG 162 NTAPI 163 UniataAhciSetupFIS_H2D( 164 IN PHW_DEVICE_EXTENSION deviceExtension, 165 IN ULONG DeviceNumber, 166 IN ULONG lChannel, 167 OUT PUCHAR fis, 168 IN UCHAR command, 169 IN ULONGLONG lba, 170 IN USHORT count, 171 IN USHORT feature 172 ); 173 174 UCHAR 175 NTAPI 176 UniataAhciWaitCommandReady( 177 IN PHW_CHANNEL chan, 178 IN ULONG timeout 179 ); 180 181 UCHAR 182 NTAPI 183 UniataAhciSendCommand( 184 IN PVOID HwDeviceExtension, 185 IN ULONG lChannel, 186 IN ULONG DeviceNumber, 187 IN USHORT ahci_flags, 188 IN ULONG timeout 189 ); 190 191 UCHAR 192 NTAPI 193 UniataAhciSendPIOCommand( 194 IN PVOID HwDeviceExtension, 195 IN ULONG lChannel, 196 IN ULONG DeviceNumber, 197 IN PSCSI_REQUEST_BLOCK Srb, 198 IN PUCHAR data, 199 IN ULONG length, 200 IN UCHAR command, 201 IN ULONGLONG lba, 202 IN USHORT count, 203 IN USHORT feature, 204 IN USHORT ahci_flags, 205 IN ULONG flags, 206 IN ULONG timeout 207 ); 208 209 UCHAR 210 NTAPI 211 UniataAhciSendPIOCommandDirect( 212 IN PVOID HwDeviceExtension, 213 IN ULONG lChannel, 214 IN ULONG DeviceNumber, 215 IN PSCSI_REQUEST_BLOCK Srb, 216 IN PIDEREGS_EX regs, 217 IN ULONG wait_flags, 218 IN ULONG timeout 219 ); 220 221 BOOLEAN 222 NTAPI 223 UniataAhciAbortOperation( 224 IN PHW_CHANNEL chan 225 ); 226 227 ULONG 228 NTAPI 229 UniataAhciSoftReset( 230 IN PVOID HwDeviceExtension, 231 IN ULONG lChannel, 232 IN ULONG DeviceNumber 233 ); 234 235 ULONG 236 NTAPI 237 UniataAhciWaitReady( 238 IN PHW_CHANNEL chan, 239 IN ULONG timeout 240 ); 241 242 ULONG 243 NTAPI 244 UniataAhciHardReset( 245 IN PVOID HwDeviceExtension, 246 IN ULONG lChannel, 247 OUT PULONG signature 248 ); 249 250 VOID 251 NTAPI 252 UniataAhciReset( 253 IN PVOID HwDeviceExtension, 254 IN ULONG lChannel 255 ); 256 257 VOID 258 NTAPI 259 UniataAhciStartFR( 260 IN PHW_CHANNEL chan 261 ); 262 263 BOOLEAN 264 NTAPI 265 UniataAhciStopFR( 266 IN PHW_CHANNEL chan 267 ); 268 269 VOID 270 NTAPI 271 UniataAhciStart( 272 IN PHW_CHANNEL chan 273 ); 274 275 BOOLEAN 276 NTAPI 277 UniataAhciCLO( 278 IN PHW_CHANNEL chan 279 ); 280 281 BOOLEAN 282 NTAPI 283 UniataAhciStop( 284 IN PHW_CHANNEL chan 285 ); 286 287 288 __inline 289 ULONG 290 UniataAhciReadChannelPort4( 291 IN PHW_CHANNEL chan, 292 IN ULONG io_port_ndx 293 ) 294 { 295 volatile ULONG v = AtapiReadPortEx4(NULL, (ULONGIO_PTR)&((chan)->BaseIoAHCI_Port), io_port_ndx); 296 KdPrint3((PRINT_PREFIX "ReadChannelPort4 ch%d[%x] = %x\n", chan->lChannel, io_port_ndx, v)); 297 return v; 298 } // end UniataAhciReadChannelPort4() 299 300 __inline 301 VOID 302 UniataAhciWriteChannelPort4( 303 IN PHW_CHANNEL chan, 304 IN ULONG io_port_ndx, 305 IN ULONG data 306 ) 307 { 308 KdPrint3((PRINT_PREFIX "WriteChannelPort4 %x => ch%d[%x]\n", data, chan->lChannel, io_port_ndx)); 309 AtapiWritePortEx4(NULL, (ULONGIO_PTR)&((chan)->BaseIoAHCI_Port), io_port_ndx, data); 310 } // end UniataAhciWriteChannelPort4() 311 312 313 #define UniataAhciReadHostPort4(deviceExtension, io_port_ndx) \ 314 AtapiReadPortEx4(NULL, (ULONGIO_PTR)&((deviceExtension)->BaseIoAHCI_0), io_port_ndx) 315 316 #define UniataAhciWriteHostPort4(deviceExtension, io_port_ndx, data) \ 317 AtapiWritePortEx4(NULL, (ULONGIO_PTR)&((deviceExtension)->BaseIoAHCI_0), io_port_ndx, data) 318 319 UCHAR 320 NTAPI 321 UniataAhciBeginTransaction( 322 IN PVOID HwDeviceExtension, 323 IN ULONG lChannel, 324 IN ULONG DeviceNumber, 325 IN PSCSI_REQUEST_BLOCK Srb 326 ); 327 328 UCHAR 329 NTAPI 330 UniataAhciEndTransaction( 331 IN PVOID HwDeviceExtension, 332 IN ULONG lChannel, 333 IN ULONG DeviceNumber, 334 IN PSCSI_REQUEST_BLOCK Srb 335 ); 336 337 VOID 338 NTAPI 339 UniataAhciResume( 340 IN PHW_CHANNEL chan 341 ); 342 343 __inline 344 ULONG 345 UniataAhciUlongFromRFIS( 346 PUCHAR RCV_FIS 347 ) 348 { 349 return ( (((ULONG)(RCV_FIS[6])) << 24) | 350 (((ULONG)(RCV_FIS[5])) << 16) | 351 (((ULONG)(RCV_FIS[4])) << 8) | 352 ((ULONG)(RCV_FIS[12])) ); 353 } // end UniataAhciUlongFromRFIS() 354 355 __inline 356 USHORT 357 UniAtaAhciAdjustIoFlags( 358 IN UCHAR command, 359 IN USHORT ahci_flags, 360 IN ULONG fis_size, 361 IN ULONG DeviceNumber 362 ) 363 { 364 ahci_flags |= (fis_size / sizeof(ULONG)) | (DeviceNumber << 12); 365 if(!command) { 366 return ahci_flags; 367 } 368 369 if(AtaCommandFlags[command] & ATA_CMD_FLAG_Out) { 370 ahci_flags |= ATA_AHCI_CMD_WRITE; 371 } 372 /* 373 if(AtaCommandFlags[command] & ATA_CMD_FLAG_In) { 374 ahci_flags |= ATA_AHCI_CMD_READ; 375 } 376 */ 377 return ahci_flags; 378 } // end UniAtaAhciAdjustIoFlags() 379 380 BOOLEAN 381 NTAPI 382 UniataAhciReadPM( 383 IN PHW_CHANNEL chan, 384 IN ULONG DeviceNumber, 385 IN ULONG Reg, 386 OUT PULONG result 387 ); 388 389 UCHAR 390 NTAPI 391 UniataAhciWritePM( 392 IN PHW_CHANNEL chan, 393 IN ULONG DeviceNumber, 394 IN ULONG Reg, 395 IN ULONG value 396 ); 397 398 VOID 399 UniataAhciSetupCmdPtr( 400 IN OUT PATA_REQ AtaReq 401 ); 402 403 PSCSI_REQUEST_BLOCK 404 NTAPI 405 BuildAhciInternalSrb ( 406 IN PVOID HwDeviceExtension, 407 IN ULONG DeviceNumber, 408 IN ULONG lChannel, 409 IN PUCHAR Buffer = NULL, 410 IN ULONG Length = 0 411 ); 412 413 __inline 414 BOOLEAN 415 UniataAhciChanImplemented( 416 IN PHW_DEVICE_EXTENSION deviceExtension, 417 IN ULONG c 418 ) 419 { 420 #ifdef _DEBUG 421 KdPrint2((PRINT_PREFIX "imp: %#x & %#x\n", (deviceExtension)->AHCI_PI, (1<<c) )); 422 #endif 423 return (((deviceExtension)->AHCI_PI) & ((ULONG)1 << c)) ? TRUE : FALSE; 424 } // end UniataAhciChanImplemented() 425 426 427 #endif //__UNIATA_SATA__H__ 428