1 /*++ 2 3 Copyright (c) 2008-2016 Alexandr A. Telyatnikov (Alter) 4 5 Module Name: 6 id_probe.cpp 7 8 Abstract: 9 This module handles SATA- and AHCI-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 SATA support 33 AHCI support 34 35 Licence: 36 GPLv2 37 38 --*/ 39 40 #include "stdafx.h" 41 42 UCHAR 43 NTAPI 44 UniataSataConnect( 45 IN PVOID HwDeviceExtension, 46 IN ULONG lChannel, // logical channel 47 IN ULONG pm_port /* for port multipliers */ 48 ) 49 { 50 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 51 //ULONG Channel = deviceExtension->Channel + lChannel; 52 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 53 SATA_SSTATUS_REG SStatus; 54 ULONG i; 55 /* 56 UCHAR signatureLow, 57 signatureHigh; 58 */ 59 UCHAR Status; 60 61 KdPrint2((PRINT_PREFIX "UniataSataConnect:\n")); 62 63 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 64 KdPrint2((PRINT_PREFIX " no I/O range\n")); 65 return IDE_STATUS_IDLE; 66 } 67 68 /* clear SATA error register, some controllers need this */ 69 UniataSataWritePort4(chan, IDX_SATA_SError, 70 UniataSataReadPort4(chan, IDX_SATA_SError, pm_port), pm_port); 71 /* wait up to 1 second for "connect well" */ 72 for(i=0; i<100; i++) { 73 SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, pm_port); 74 if(SStatus.SPD == SStatus_SPD_Gen1 || 75 SStatus.SPD == SStatus_SPD_Gen2 || 76 SStatus.SPD == SStatus_SPD_Gen3) { 77 // SATA sets actual transfer rate in LunExt on init. 78 // There is no run-time SATA rate adjustment yet. 79 // On the other hand, we may turn SATA device in PIO mode 80 // TODO: make separate states for interface speed and transfer mode (DMA vs PIO) 81 chan->lun[0]->LimitedTransferMode = 82 chan->lun[0]->PhyTransferMode = 83 chan->lun[0]->TransferMode = ATA_SA150 + (UCHAR)(SStatus.SPD - 1); 84 85 KdPrint2((PRINT_PREFIX "SATA TransferMode %#x\n", chan->lun[0]->TransferMode)); 86 if(chan->MaxTransferMode < chan->lun[0]->TransferMode) { 87 KdPrint2((PRINT_PREFIX "SATA upd chan TransferMode\n")); 88 chan->MaxTransferMode = chan->lun[0]->TransferMode; 89 } 90 if(deviceExtension->MaxTransferMode < chan->lun[0]->TransferMode) { 91 KdPrint2((PRINT_PREFIX "SATA upd controller TransferMode\n")); 92 deviceExtension->MaxTransferMode = chan->lun[0]->TransferMode; 93 } 94 95 break; 96 } 97 AtapiStallExecution(10000); 98 } 99 if(i >= 100) { 100 KdPrint2((PRINT_PREFIX "UniataSataConnect: SStatus %8.8x\n", SStatus.Reg)); 101 return IDE_STATUS_WRONG; 102 } 103 /* clear SATA error register */ 104 UniataSataWritePort4(chan, IDX_SATA_SError, 105 UniataSataReadPort4(chan, IDX_SATA_SError, pm_port), pm_port); 106 107 Status = WaitOnBaseBusyLong(chan); 108 if(Status & IDE_STATUS_BUSY) { 109 return Status; 110 } 111 /* 112 signatureLow = AtapiReadPort1(chan, &deviceExtension->BaseIoAddress1[lChannel].i.CylinderLow); 113 signatureHigh = AtapiReadPort1(chan, &deviceExtension->baseIoAddress1[lChannel].i.CylinderHigh); 114 115 if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) { 116 } 117 */ 118 KdPrint2((PRINT_PREFIX "UniataSataConnect: OK, ATA status %#x\n", Status)); 119 return IDE_STATUS_IDLE; 120 } // end UniataSataConnect() 121 122 UCHAR 123 NTAPI 124 UniataSataPhyEnable( 125 IN PVOID HwDeviceExtension, 126 IN ULONG lChannel, // logical channel 127 IN ULONG pm_port, /* for port multipliers */ 128 IN BOOLEAN doReset 129 ) 130 { 131 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 132 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 133 SATA_SCONTROL_REG SControl; 134 int loop, retry; 135 136 KdPrint2((PRINT_PREFIX "UniataSataPhyEnable:\n")); 137 138 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 139 KdPrint2((PRINT_PREFIX " no I/O range\n")); 140 return IDE_STATUS_IDLE; 141 } 142 143 SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port); 144 KdPrint2((PRINT_PREFIX "SControl %#x\n", SControl.Reg)); 145 if(SControl.DET == SControl_DET_Idle) { 146 if(!doReset) { 147 return UniataSataConnect(HwDeviceExtension, lChannel, pm_port); 148 } 149 } 150 151 for (retry = 0; retry < 10; retry++) { 152 KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: retry init %d\n", retry)); 153 for (loop = 0; loop < 10; loop++) { 154 SControl.Reg = 0; 155 SControl.DET = SControl_DET_Init; 156 UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, pm_port); 157 AtapiStallExecution(100); 158 SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port); 159 KdPrint2((PRINT_PREFIX " SControl %8.8x\n", SControl.Reg)); 160 if(SControl.DET == SControl_DET_Init) { 161 break; 162 } 163 } 164 AtapiStallExecution(5000); 165 KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: retry idle %d\n", retry)); 166 for (loop = 0; loop < 10; loop++) { 167 SControl.Reg = 0; 168 SControl.DET = SControl_DET_DoNothing; 169 SControl.IPM = SControl_IPM_NoPartialSlumber; 170 UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, pm_port); 171 AtapiStallExecution(100); 172 SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port); 173 KdPrint2((PRINT_PREFIX " SControl %8.8x\n", SControl.Reg)); 174 if(SControl.DET == SControl_DET_Idle) { 175 return UniataSataConnect(HwDeviceExtension, lChannel, pm_port); 176 } 177 } 178 } 179 180 KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: failed\n")); 181 return IDE_STATUS_WRONG; 182 } // end UniataSataPhyEnable() 183 184 BOOLEAN 185 NTAPI 186 UniataSataClearErr( 187 IN PVOID HwDeviceExtension, 188 IN ULONG lChannel, // logical channel 189 IN BOOLEAN do_connect, 190 IN ULONG pm_port /* for port multipliers */ 191 ) 192 { 193 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 194 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 195 //ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK; 196 SATA_SSTATUS_REG SStatus; 197 SATA_SERROR_REG SError; 198 199 if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 200 //if(ChipFlags & UNIATA_SATA) { 201 202 SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, pm_port); 203 SError.Reg = UniataSataReadPort4(chan, IDX_SATA_SError, pm_port); 204 205 if(SStatus.Reg) { 206 KdPrint2((PRINT_PREFIX " SStatus %#x\n", SStatus.Reg)); 207 } 208 if(SError.Reg) { 209 KdPrint2((PRINT_PREFIX " SError %#x\n", SError.Reg)); 210 /* clear error bits/interrupt */ 211 UniataSataWritePort4(chan, IDX_SATA_SError, SError.Reg, pm_port); 212 213 if(do_connect) { 214 /* if we have a connection event deal with it */ 215 if(SError.DIAG.N) { 216 KdPrint2((PRINT_PREFIX " catch SATA connect/disconnect\n")); 217 if(SStatus.SPD >= SStatus_SPD_Gen1) { 218 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, pm_port); 219 } else { 220 UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, pm_port); 221 } 222 return TRUE; 223 } 224 } 225 //return TRUE; 226 } 227 } 228 return FALSE; 229 } // end UniataSataClearErr() 230 231 BOOLEAN 232 NTAPI 233 UniataSataEvent( 234 IN PVOID HwDeviceExtension, 235 IN ULONG lChannel, // logical channel 236 IN ULONG Action, 237 IN ULONG pm_port /* for port multipliers */ 238 ) 239 { 240 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 241 UCHAR Status; 242 ULONG DeviceNumber = (pm_port ? 1 : 0); 243 244 if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) { 245 return FALSE; 246 } 247 248 switch(Action) { 249 case UNIATA_SATA_EVENT_ATTACH: 250 KdPrint2((PRINT_PREFIX " CONNECTED\n")); 251 Status = UniataSataConnect(HwDeviceExtension, lChannel, pm_port); 252 KdPrint2((PRINT_PREFIX " Status %#x\n", Status)); 253 if(Status != IDE_STATUS_IDLE) { 254 return FALSE; 255 } 256 CheckDevice(HwDeviceExtension, lChannel, DeviceNumber /*dev*/, FALSE); 257 return TRUE; 258 break; 259 case UNIATA_SATA_EVENT_DETACH: 260 KdPrint2((PRINT_PREFIX " DISCONNECTED\n")); 261 UniataForgetDevice(deviceExtension->chan[lChannel].lun[DeviceNumber]); 262 return TRUE; 263 break; 264 } 265 return FALSE; 266 } // end UniataSataEvent() 267 268 ULONG 269 NTAPI 270 UniataSataReadPort4( 271 IN PHW_CHANNEL chan, 272 IN ULONG io_port_ndx, 273 IN ULONG pm_port /* for port multipliers */ 274 ) 275 { 276 if(chan && (io_port_ndx < IDX_MAX_REG) && 277 chan->RegTranslation[io_port_ndx].Proc) { 278 279 KdPrint3((PRINT_PREFIX " UniataSataReadPort4 %#x[%d]\n", io_port_ndx, pm_port)); 280 281 PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension; 282 PVOID HwDeviceExtension = (PVOID)deviceExtension; 283 ULONG slotNumber = deviceExtension->slotNumber; 284 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; 285 ULONG VendorID = deviceExtension->DevID & 0xffff; 286 ULONG offs; 287 ULONG p; 288 289 switch(VendorID) { 290 case ATA_INTEL_ID: { 291 p = pm_port ? 1 : 0; 292 if(deviceExtension->HwFlags & ICH5) { 293 offs = 0x50+chan->lun[p]->SATA_lun_map*0x10; 294 KdPrint3((PRINT_PREFIX " ICH5 way, offs %#x\n", offs)); 295 switch(io_port_ndx) { 296 case IDX_SATA_SStatus: 297 offs += 0; 298 break; 299 case IDX_SATA_SError: 300 offs += 1*4; 301 break; 302 case IDX_SATA_SControl: 303 offs += 2*4; 304 break; 305 default: 306 return -1; 307 } 308 SetPciConfig4(0xa0, offs); 309 GetPciConfig4(0xa4, offs); 310 return offs; 311 } else 312 if(deviceExtension->HwFlags & ICH7) { 313 offs = 0x100+chan->lun[p]->SATA_lun_map*0x80; 314 KdPrint3((PRINT_PREFIX " ICH7 way, offs %#x\n", offs)); 315 switch(io_port_ndx) { 316 case IDX_SATA_SStatus: 317 offs += IDX_AHCI_P_SStatus; 318 break; 319 case IDX_SATA_SError: 320 offs += IDX_AHCI_P_SError; 321 break; 322 case IDX_SATA_SControl: 323 offs += IDX_AHCI_P_SControl; 324 break; 325 default: 326 return -1; 327 } 328 return AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), offs); 329 } else { 330 offs = ((deviceExtension->Channel+chan->lChannel)*2+p) * 0x100; 331 KdPrint3((PRINT_PREFIX " def way, offs %#x\n", offs)); 332 switch(io_port_ndx) { 333 case IDX_SATA_SStatus: 334 offs += 0; 335 break; 336 case IDX_SATA_SControl: 337 offs += 1; 338 break; 339 case IDX_SATA_SError: 340 offs += 2; 341 break; 342 default: 343 return -1; 344 } 345 AtapiWritePort4(chan, IDX_INDEXED_ADDR, offs); 346 return AtapiReadPort4(chan, IDX_INDEXED_DATA); 347 } 348 } // ATA_INTEL_ID 349 } // end switch(VendorID) 350 return -1; 351 } 352 return AtapiReadPort4(chan, io_port_ndx); 353 } // end UniataSataReadPort4() 354 355 VOID 356 NTAPI 357 UniataSataWritePort4( 358 IN PHW_CHANNEL chan, 359 IN ULONG io_port_ndx, 360 IN ULONG data, 361 IN ULONG pm_port /* for port multipliers */ 362 ) 363 { 364 if(chan && (io_port_ndx < IDX_MAX_REG) && 365 chan->RegTranslation[io_port_ndx].Proc) { 366 367 KdPrint3((PRINT_PREFIX " UniataSataWritePort4 %#x[%d]\n", io_port_ndx, pm_port)); 368 369 PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension; 370 PVOID HwDeviceExtension = (PVOID)deviceExtension; 371 ULONG slotNumber = deviceExtension->slotNumber; 372 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; 373 ULONG VendorID = deviceExtension->DevID & 0xffff; 374 ULONG offs; 375 ULONG p; 376 377 switch(VendorID) { 378 case ATA_INTEL_ID: { 379 p = pm_port ? 1 : 0; 380 if(deviceExtension->HwFlags & ICH5) { 381 offs = 0x50+chan->lun[p]->SATA_lun_map*0x10; 382 KdPrint3((PRINT_PREFIX " ICH5 way, offs %#x\n", offs)); 383 switch(io_port_ndx) { 384 case IDX_SATA_SStatus: 385 offs += 0; 386 break; 387 case IDX_SATA_SError: 388 offs += 1*4; 389 break; 390 case IDX_SATA_SControl: 391 offs += 2*4; 392 break; 393 default: 394 return; 395 } 396 SetPciConfig4(0xa0, offs); 397 SetPciConfig4(0xa4, data); 398 return; 399 } else 400 if(deviceExtension->HwFlags & ICH7) { 401 offs = 0x100+chan->lun[p]->SATA_lun_map*0x80; 402 KdPrint3((PRINT_PREFIX " ICH7 way, offs %#x\n", offs)); 403 switch(io_port_ndx) { 404 case IDX_SATA_SStatus: 405 offs += IDX_AHCI_P_SStatus; 406 break; 407 case IDX_SATA_SError: 408 offs += IDX_AHCI_P_SError; 409 break; 410 case IDX_SATA_SControl: 411 offs += IDX_AHCI_P_SControl; 412 break; 413 default: 414 return; 415 } 416 AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0), offs, data); 417 return; 418 } else { 419 offs = ((deviceExtension->Channel+chan->lChannel)*2+p) * 0x100; 420 KdPrint3((PRINT_PREFIX " def way, offs %#x\n", offs)); 421 switch(io_port_ndx) { 422 case IDX_SATA_SStatus: 423 offs += 0; 424 break; 425 case IDX_SATA_SControl: 426 offs += 1; 427 break; 428 case IDX_SATA_SError: 429 offs += 2; 430 break; 431 default: 432 return; 433 } 434 AtapiWritePort4(chan, IDX_INDEXED_ADDR, offs); 435 AtapiWritePort4(chan, IDX_INDEXED_DATA, data); 436 } 437 } // ATA_INTEL_ID 438 } // end switch(VendorID) 439 return; 440 } 441 AtapiWritePort4(chan, io_port_ndx, data); 442 } // end UniataSataWritePort4() 443 444 BOOLEAN 445 NTAPI 446 UniataSataReadPM( 447 IN PHW_CHANNEL chan, 448 IN ULONG DeviceNumber, 449 IN ULONG Reg, 450 OUT PULONG result 451 ) 452 { 453 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { 454 return UniataAhciReadPM(chan, DeviceNumber, Reg, result); 455 } 456 return FALSE; 457 } // end UniataSataReadPM() 458 459 UCHAR 460 NTAPI 461 UniataSataWritePM( 462 IN PHW_CHANNEL chan, 463 IN ULONG DeviceNumber, 464 IN ULONG Reg, 465 IN ULONG value 466 ) 467 { 468 if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) { 469 return UniataAhciWritePM(chan, DeviceNumber, Reg, value); 470 } 471 return IDE_STATUS_WRONG; 472 } // end UniataSataWritePM() 473 474 ULONG 475 NTAPI 476 UniataSataSoftReset( 477 IN PVOID HwDeviceExtension, 478 IN ULONG lChannel, 479 IN ULONG DeviceNumber 480 ) 481 { 482 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 483 484 if(deviceExtension->HwFlags & UNIATA_AHCI) { 485 return UniataAhciSoftReset(HwDeviceExtension, lChannel, DeviceNumber); 486 } 487 return 0xffffffff; 488 } // end UniataSataSoftReset() 489 490 VOID 491 UniataSataIdentifyPM( 492 IN PHW_CHANNEL chan 493 ) 494 { 495 ULONG PM_DeviceId; 496 ULONG PM_RevId; 497 ULONG PM_Ports; 498 UCHAR i; 499 ULONG signature; 500 PHW_LU_EXTENSION LunExt; 501 502 KdPrint((PRINT_PREFIX "UniataSataIdentifyPM:\n")); 503 504 chan->PmLunMap = 0; 505 506 /* get PM vendor & product data */ 507 if(!UniataSataReadPM(chan, AHCI_DEV_SEL_PM, 0, &PM_DeviceId)) { 508 KdPrint2((PRINT_PREFIX " error getting PM vendor data\n")); 509 return; 510 } 511 /* get PM revision data */ 512 if(!UniataSataReadPM(chan, AHCI_DEV_SEL_PM, 1, &PM_RevId)) { 513 KdPrint2((PRINT_PREFIX " error getting PM revison data\n")); 514 return; 515 } 516 /* get number of HW ports on the PM */ 517 if(!UniataSataReadPM(chan, AHCI_DEV_SEL_PM, 2, &PM_Ports)) { 518 KdPrint2((PRINT_PREFIX " error getting PM port info\n")); 519 return; 520 } 521 522 PM_Ports &= 0x0000000f; 523 524 switch(PM_DeviceId) { 525 case 0x37261095: 526 /* This PM declares 6 ports, while only 5 of them are real. 527 * Port 5 is enclosure management bridge port, which has implementation 528 * problems, causing probe faults. Hide it for now. */ 529 KdPrint2((PRINT_PREFIX " SiI 3726 (rev=%#x) Port Multiplier with %d (5) ports\n", 530 PM_RevId, PM_Ports)); 531 PM_Ports = 5; 532 break; 533 case 0x47261095: 534 /* This PM declares 7 ports, while only 5 of them are real. 535 * Port 5 is some fake "Config Disk" with 640 sectors size, 536 * port 6 is enclosure management bridge port. 537 * Both fake ports has implementation problems, causing 538 * probe faults. Hide them for now. */ 539 KdPrint2((PRINT_PREFIX " SiI 4726 (rev=%#x) Port Multiplier with %d (5) ports\n", 540 PM_RevId, PM_Ports)); 541 PM_Ports = 5; 542 break; 543 default: 544 KdPrint2((PRINT_PREFIX " Port Multiplier (id=%08x rev=%#x) with %d ports\n", 545 PM_DeviceId, PM_RevId, PM_Ports)); 546 break; 547 } 548 549 // reset 550 for(i=0; i<PM_Ports; i++) { 551 552 LunExt = chan->lun[i]; 553 554 KdPrint2((PRINT_PREFIX " Port %d\n", i)); 555 if(UniataSataPhyEnable(chan->DeviceExtension, chan->lChannel, i, UNIATA_SATA_RESET_ENABLE) != IDE_STATUS_IDLE) { 556 LunExt->DeviceFlags &= ~DFLAGS_DEVICE_PRESENT; 557 continue; 558 } 559 /* 560 * XXX: I have no idea how to properly wait for PMP port hardreset 561 * completion. Without this delay soft reset does not completes 562 * successfully. 563 */ 564 AtapiStallExecution(1000000); 565 566 signature = UniataSataSoftReset(chan->DeviceExtension, chan->lChannel, i); 567 KdPrint2((PRINT_PREFIX " signature %#x\n", signature)); 568 569 LunExt->DeviceFlags |= DFLAGS_DEVICE_PRESENT; 570 chan->PmLunMap |= (1 << i); 571 /* figure out whats there */ 572 switch (signature >> 16) { 573 case 0x0000: 574 LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE; 575 continue; 576 case 0xeb14: 577 LunExt->DeviceFlags |= DFLAGS_ATAPI_DEVICE; 578 continue; 579 } 580 581 } 582 583 } // end UniataSataIdentifyPM() 584 585 #ifdef _DEBUG 586 VOID 587 NTAPI 588 UniataDumpAhciRegs( 589 IN PHW_DEVICE_EXTENSION deviceExtension 590 ) 591 { 592 ULONG j; 593 ULONG xReg; 594 595 KdPrint2((PRINT_PREFIX 596 " AHCI Base: %#x MemIo %d Proc %d\n", 597 deviceExtension->BaseIoAHCI_0.Addr, 598 deviceExtension->BaseIoAHCI_0.MemIo, 599 deviceExtension->BaseIoAHCI_0.Proc)); 600 601 for(j=0; j<=IDX_AHCI_VS; j+=sizeof(ULONG)) { 602 xReg = AtapiReadPortEx4(NULL, (ULONGIO_PTR)&deviceExtension->BaseIoAHCI_0, j); 603 KdPrint2((PRINT_PREFIX 604 " AHCI_%#x (%#x) = %#x\n", 605 j, 606 (deviceExtension->BaseIoAHCI_0.Addr+j), 607 xReg)); 608 } 609 return; 610 } // end UniataDumpAhciRegs() 611 612 613 VOID 614 NTAPI 615 UniataDumpAhciPortRegs( 616 IN PHW_CHANNEL chan 617 ) 618 { 619 ULONG j; 620 ULONG xReg; 621 622 KdPrint2((PRINT_PREFIX 623 " AHCI port %d Base: %#x MemIo %d Proc %d\n", 624 chan->lChannel, 625 chan->BaseIoAHCI_Port.Addr, 626 chan->BaseIoAHCI_Port.MemIo, 627 chan->BaseIoAHCI_Port.Proc)); 628 629 for(j=0; j<=IDX_AHCI_P_SNTF; j+=sizeof(ULONG)) { 630 xReg = AtapiReadPortEx4(NULL, (ULONGIO_PTR)&chan->BaseIoAHCI_Port, j); 631 KdPrint2((PRINT_PREFIX 632 " AHCI%d_%#x (%#x) = %#x\n", 633 chan->lChannel, 634 j, 635 (chan->BaseIoAHCI_Port.Addr+j), 636 xReg)); 637 } 638 return; 639 } // end UniataDumpAhciPortRegs() 640 #endif //_DEBUG 641 642 643 BOOLEAN 644 NTAPI 645 UniataAhciInit( 646 IN PVOID HwDeviceExtension 647 ) 648 { 649 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 650 ULONG c, i; 651 PHW_CHANNEL chan; 652 ULONG offs; 653 ULONG BaseMemAddress; 654 ULONG PI; 655 ULONG CAP; 656 ULONG CAP2; 657 ULONG BOHC; 658 ULONG GHC; 659 BOOLEAN MemIo = FALSE; 660 661 KdPrint2((PRINT_PREFIX " UniataAhciInit:\n")); 662 663 #ifdef _DEBUG 664 UniataDumpAhciRegs(deviceExtension); 665 #endif //_DEBUG 666 667 CAP2 = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP2); 668 if(CAP2 & AHCI_CAP2_BOH) { 669 BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC); 670 KdPrint2((PRINT_PREFIX " stage 1 BOHC %#x\n", BOHC)); 671 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_BOHC, 672 BOHC | AHCI_BOHC_OOS); 673 for(i=0; i<50; i++) { 674 AtapiStallExecution(500); 675 BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC); 676 KdPrint2((PRINT_PREFIX " BOHC %#x\n", BOHC)); 677 if(BOHC & AHCI_BOHC_BB) { 678 break; 679 } 680 if(!(BOHC & AHCI_BOHC_BOS)) { 681 break; 682 } 683 } 684 KdPrint2((PRINT_PREFIX " stage 2 BOHC %#x\n", BOHC)); 685 if(BOHC & AHCI_BOHC_BB) { 686 for(i=0; i<2000; i++) { 687 AtapiStallExecution(1000); 688 BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC); 689 KdPrint2((PRINT_PREFIX " BOHC %#x\n", BOHC)); 690 if(!(BOHC & AHCI_BOHC_BOS)) { 691 break; 692 } 693 } 694 } 695 KdPrint2((PRINT_PREFIX " final BOHC %#x\n", BOHC)); 696 } 697 698 /* disable AHCI interrupts, for MSI compatibility issue 699 see http://www.intel.com/Assets/PDF/specupdate/307014.pdf 700 26. AHCI Reset and MSI Request 701 */ 702 703 KdPrint2((PRINT_PREFIX " get GHC\n")); 704 /* enable AHCI mode */ 705 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 706 if(!(GHC & AHCI_GHC_AE)) { 707 KdPrint2((PRINT_PREFIX " enable AHCI mode, disable intr, GHC %#x\n", GHC)); 708 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, 709 (GHC | AHCI_GHC_AE) & ~AHCI_GHC_IE); 710 } else { 711 KdPrint2((PRINT_PREFIX " disable intr, GHC %#x\n", GHC)); 712 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, 713 GHC & ~AHCI_GHC_IE); 714 } 715 AtapiStallExecution(100); 716 717 /* read GHC again and reset AHCI controller */ 718 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 719 KdPrint2((PRINT_PREFIX " reset AHCI controller, GHC %#x\n", GHC)); 720 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, 721 GHC | AHCI_GHC_HR); 722 723 for(i=0; i<1000; i++) { 724 AtapiStallExecution(1000); 725 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 726 KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC)); 727 if(!(GHC & AHCI_GHC_HR)) { 728 break; 729 } 730 } 731 if(GHC & AHCI_GHC_HR) { 732 KdPrint2((PRINT_PREFIX " AHCI reset failed\n")); 733 return FALSE; 734 } 735 736 /* re-enable AHCI mode */ 737 /* Linux: Some controllers need AHCI_EN to be written multiple times. 738 * Try a few times before giving up. 739 */ 740 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 741 for(i=0; i<5; i++) { 742 if(!(GHC & AHCI_GHC_AE)) { 743 KdPrint2((PRINT_PREFIX " re-enable AHCI mode, GHC %#x\n", GHC)); 744 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, 745 GHC | AHCI_GHC_AE); 746 AtapiStallExecution(1000); 747 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 748 } else { 749 break; 750 } 751 } 752 KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC)); 753 if(!(GHC & AHCI_GHC_AE)) { 754 KdPrint2((PRINT_PREFIX " Can't enable AHCI mode\n")); 755 return FALSE; 756 } 757 758 deviceExtension->AHCI_CAP = 759 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); 760 KdPrint2((PRINT_PREFIX " AHCI CAP %#x\n", CAP)); 761 if(CAP & AHCI_CAP_S64A) { 762 KdPrint2((PRINT_PREFIX " AHCI 64bit\n")); 763 deviceExtension->Host64 = TRUE; 764 } 765 KdPrint2((PRINT_PREFIX " AHCI %d CMD slots\n", (CAP & AHCI_CAP_NCS_MASK) >> 8 )); 766 if(CAP & AHCI_CAP_PMD) { 767 KdPrint2((PRINT_PREFIX " AHCI multi-block PIO\n")); 768 } 769 if(CAP & AHCI_CAP_SAM) { 770 KdPrint2((PRINT_PREFIX " AHCI legasy SATA\n")); 771 } 772 773 /* get the number of HW channels */ 774 PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); 775 deviceExtension->AHCI_PI = PI; 776 KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI)); 777 KdPrint2((PRINT_PREFIX " AHCI PI mask %#x\n", deviceExtension->AHCI_PI_mask)); 778 deviceExtension->AHCI_PI = PI = PI & deviceExtension->AHCI_PI_mask; 779 KdPrint2((PRINT_PREFIX " masked AHCI PI %#x\n", PI)); 780 781 CAP2 = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP2); 782 if(CAP2 & AHCI_CAP2_BOH) { 783 KdPrint2((PRINT_PREFIX " retry BOHC\n")); 784 BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC); 785 KdPrint2((PRINT_PREFIX " BOHC %#x\n", BOHC)); 786 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_BOHC, 787 BOHC | AHCI_BOHC_OOS); 788 } 789 /* clear interrupts */ 790 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS, 791 UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS)); 792 793 /* enable AHCI interrupts */ 794 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, 795 UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC) | AHCI_GHC_IE); 796 797 BaseMemAddress = deviceExtension->BaseIoAHCI_0.Addr; 798 MemIo = deviceExtension->BaseIoAHCI_0.MemIo; 799 800 deviceExtension->MaxTransferMode = ATA_SA150+(((CAP & AHCI_CAP_ISS_MASK) >> 20)-1); 801 KdPrint2((PRINT_PREFIX " SATA Gen %d\n", ((CAP & AHCI_CAP_ISS_MASK) >> 20) )); 802 803 for(c=0; c<deviceExtension->NumberChannels; c++) { 804 chan = &deviceExtension->chan[c]; 805 offs = sizeof(IDE_AHCI_REGISTERS) + c*sizeof(IDE_AHCI_PORT_REGISTERS); 806 807 KdPrint2((PRINT_PREFIX " chan %d, offs %#x\n", c, offs)); 808 809 chan->MaxTransferMode = deviceExtension->MaxTransferMode; 810 811 AtapiSetupLunPtrs(chan, deviceExtension, c); 812 813 chan->BaseIoAHCI_Port = deviceExtension->BaseIoAHCI_0; 814 chan->BaseIoAHCI_Port.Addr = BaseMemAddress + offs; 815 816 chan->RegTranslation[IDX_IO1_i_Status ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD.STS); 817 chan->RegTranslation[IDX_IO1_i_Status ].MemIo = MemIo; 818 chan->RegTranslation[IDX_IO2_AltStatus] = chan->RegTranslation[IDX_IO1_i_Status]; 819 chan->RegTranslation[IDX_IO1_i_Error ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD.ERR); 820 chan->RegTranslation[IDX_IO1_i_Error ].MemIo = MemIo; 821 chan->RegTranslation[IDX_IO1_i_CylinderLow ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.LbaLow); 822 chan->RegTranslation[IDX_IO1_i_CylinderLow ].MemIo = MemIo; 823 chan->RegTranslation[IDX_IO1_i_CylinderHigh].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.LbaHigh); 824 chan->RegTranslation[IDX_IO1_i_CylinderHigh].MemIo = MemIo; 825 chan->RegTranslation[IDX_IO1_i_BlockCount ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.SectorCount); 826 chan->RegTranslation[IDX_IO1_i_BlockCount ].MemIo = MemIo; 827 828 UniataInitSyncBaseIO(chan); 829 830 chan->RegTranslation[IDX_SATA_SStatus].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SSTS); 831 chan->RegTranslation[IDX_SATA_SStatus].MemIo = MemIo; 832 chan->RegTranslation[IDX_SATA_SError].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SERR); 833 chan->RegTranslation[IDX_SATA_SError].MemIo = MemIo; 834 chan->RegTranslation[IDX_SATA_SControl].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SCTL); 835 chan->RegTranslation[IDX_SATA_SControl].MemIo = MemIo; 836 chan->RegTranslation[IDX_SATA_SActive].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SACT); 837 chan->RegTranslation[IDX_SATA_SActive].MemIo = MemIo; 838 839 AtapiDmaAlloc(HwDeviceExtension, NULL, c); 840 841 if(!UniataAhciChanImplemented(deviceExtension, c)) { 842 KdPrint2((PRINT_PREFIX " chan %d not implemented\n", c)); 843 continue; 844 } 845 846 UniataAhciResume(chan); 847 848 chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE; 849 } 850 851 return TRUE; 852 } // end UniataAhciInit() 853 854 BOOLEAN 855 NTAPI 856 UniAtaAhciValidateVersion( 857 IN PHW_DEVICE_EXTENSION deviceExtension, 858 IN ULONG version, 859 IN BOOLEAN Strict 860 ) 861 { 862 switch(version) { 863 case 0x00000000: 864 case 0xffffffff: 865 KdPrint((" wrong AHCI revision %#x\n", version)); 866 return FALSE; 867 case 0x00000905: 868 case 0x00010000: 869 case 0x00010100: 870 case 0x00010200: 871 case 0x00010300: 872 break; 873 default: 874 KdPrint2((PRINT_PREFIX " Unknown AHCI revision\n")); 875 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"CheckAhciRevision", Strict)) { 876 KdPrint((" AHCI revision excluded\n")); 877 return FALSE; 878 } 879 } 880 return TRUE; 881 } // end UniAtaAhciValidateVersion() 882 883 BOOLEAN 884 NTAPI 885 UniataAhciDetect( 886 IN PVOID HwDeviceExtension, 887 IN PPCI_COMMON_CONFIG pciData, // optional 888 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo 889 ) 890 { 891 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 892 //ULONG slotNumber = deviceExtension->slotNumber; 893 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; 894 ULONG version; 895 ULONG i, n; 896 ULONG PI; 897 ULONG CAP; 898 ULONG CAP2; 899 ULONG GHC, GHC0; 900 #ifdef _DEBUG 901 ULONG BOHC; 902 ULONG v_Mn, v_Mj; 903 #endif //_DEBUG 904 ULONG NumberChannels; 905 #ifdef __REACTOS__ 906 ULONG_PTR BaseMemAddress; 907 #else 908 ULONG BaseMemAddress; 909 #endif 910 BOOLEAN MemIo = FALSE; 911 BOOLEAN found = FALSE; 912 913 KdPrint2((PRINT_PREFIX " UniataAhciDetect:\n")); 914 915 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhci", 0)) { 916 KdPrint((" AHCI excluded\n")); 917 return FALSE; 918 } 919 BaseMemAddress = AtapiGetIoRange(HwDeviceExtension, ConfigInfo, pciData, SystemIoBusNumber, 920 5, 0, 0x10); 921 if(!BaseMemAddress) { 922 KdPrint2((PRINT_PREFIX " AHCI init failed - no IoRange\n")); 923 return FALSE; 924 } 925 if((*ConfigInfo->AccessRanges)[5].RangeInMemory) { 926 KdPrint2((PRINT_PREFIX "MemIo\n")); 927 MemIo = TRUE; 928 } 929 deviceExtension->BaseIoAHCI_0.Addr = BaseMemAddress; 930 deviceExtension->BaseIoAHCI_0.MemIo = MemIo; 931 932 #ifdef _DEBUG 933 UniataDumpAhciRegs(deviceExtension); 934 #endif //_DEBUG 935 936 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 937 if(GHC & AHCI_GHC_HR) { 938 KdPrint2((PRINT_PREFIX " AHCI in reset state\n")); 939 return FALSE; 940 } 941 942 /* check AHCI mode. Save state and try enable */ 943 GHC0 = 944 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 945 KdPrint2((PRINT_PREFIX " check AHCI mode, GHC %#x\n", GHC)); 946 947 version = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_VS); 948 949 if(!(GHC & AHCI_GHC_AE)) { 950 KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE), check revision %#x\n", version)); 951 if(!UniAtaAhciValidateVersion(deviceExtension, version, FALSE)) { 952 KdPrint2((PRINT_PREFIX " Non-AHCI\n")); 953 goto exit_detect; 954 } 955 KdPrint2((PRINT_PREFIX " try enable\n")); 956 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, 957 (GHC | AHCI_GHC_AE) & ~AHCI_GHC_IE); 958 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 959 960 KdPrint2((PRINT_PREFIX " re-check AHCI mode, GHC %#x\n", GHC)); 961 if(!(GHC & AHCI_GHC_AE)) { 962 KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE)\n")); 963 goto exit_detect; 964 } 965 } 966 967 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); 968 CAP2 = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP2); 969 KdPrint2((PRINT_PREFIX " AHCI CAP %#x, CAP2 %#x\n", CAP, CAP2)); 970 if(CAP & AHCI_CAP_S64A) { 971 KdPrint2((PRINT_PREFIX " 64bit")); 972 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything 973 } 974 #ifdef _DEBUG 975 if(CAP2 & AHCI_CAP2_BOH) { 976 BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC); 977 KdPrint2((PRINT_PREFIX " BOHC %#x", BOHC)); 978 } 979 #endif //_DEBUG 980 if(CAP & AHCI_CAP_NCQ) { 981 KdPrint2((PRINT_PREFIX " NCQ")); 982 } 983 if(CAP & AHCI_CAP_SNTF) { 984 KdPrint2((PRINT_PREFIX " SNTF")); 985 } 986 if(CAP & AHCI_CAP_CCC) { 987 KdPrint2((PRINT_PREFIX " CCC")); 988 } 989 KdPrint2((PRINT_PREFIX "\n")); 990 991 /* get the number of HW channels */ 992 993 /* CAP.NOP sometimes indicate the index of the last enabled 994 * port, at other times, that of the last possible port, so 995 * determining the maximum port number requires looking at 996 * both CAP.NOP and PI. 997 */ 998 PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); 999 deviceExtension->AHCI_PI = deviceExtension->AHCI_PI_mask = PI; 1000 KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI)); 1001 1002 for(i=PI, n=0; i; n++, i=i>>1) { 1003 if(AtapiRegCheckDevValue(deviceExtension, n, DEVNUM_NOT_SPECIFIED, L"Exclude", 0)) { 1004 KdPrint2((PRINT_PREFIX "Channel %d excluded\n", n)); 1005 deviceExtension->AHCI_PI &= ~((ULONG)1 << n); 1006 deviceExtension->AHCI_PI_mask &= ~((ULONG)1 << n); 1007 } 1008 } 1009 deviceExtension->AHCI_PI_mask = 1010 AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PortMask", deviceExtension->AHCI_PI_mask); 1011 KdPrint2((PRINT_PREFIX "Force PortMask %#x\n", deviceExtension->AHCI_PI_mask)); 1012 1013 for(i=PI, n=0; i; n++, i=i>>1); 1014 NumberChannels = 1015 max((CAP & AHCI_CAP_NOP_MASK)+1, n); 1016 1017 KdPrint2((PRINT_PREFIX " CommandSlots %d\n", (CAP & AHCI_CAP_NCS_MASK)>>8 )); 1018 KdPrint2((PRINT_PREFIX " Detected Channels %d / %d\n", NumberChannels, n)); 1019 1020 switch(deviceExtension->DevID) { 1021 case ATA_M88SE6111: 1022 KdPrint2((PRINT_PREFIX " Marvell M88SE6111 -> 1\n")); 1023 NumberChannels = 1; 1024 break; 1025 case ATA_M88SE6121: 1026 KdPrint2((PRINT_PREFIX " Marvell M88SE6121 -> 2\n")); 1027 NumberChannels = min(NumberChannels, 2); 1028 break; 1029 case ATA_M88SE6141: 1030 case ATA_M88SE6145: 1031 case ATA_M88SE9123: 1032 KdPrint2((PRINT_PREFIX " Marvell M88SE614x/9123 -> 4\n")); 1033 NumberChannels = min(NumberChannels, 4); 1034 break; 1035 } // switch() 1036 1037 if(!NumberChannels) { 1038 KdPrint2((PRINT_PREFIX " Non-AHCI - NumberChannels=0\n")); 1039 found = FALSE; 1040 goto exit_detect; 1041 } 1042 KdPrint2((PRINT_PREFIX " Adjusted Channels %d\n", NumberChannels)); 1043 1044 #ifdef _DEBUG 1045 v_Mj = ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f); 1046 v_Mn = ((version >> 4) & 0xf0) + (version & 0x0f); 1047 1048 KdPrint2((PRINT_PREFIX " AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n", 1049 v_Mj, v_Mn, 1050 NumberChannels, PI)); 1051 KdPrint((" AHCI SATA Gen %d\n", (((CAP & AHCI_CAP_ISS_MASK) >> 20)) )); 1052 #endif //_DEBUG 1053 1054 if(CAP & AHCI_CAP_SPM) { 1055 KdPrint2((PRINT_PREFIX " PM supported\n")); 1056 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhciPM", 1 /* DEBUG */)) { 1057 KdPrint2((PRINT_PREFIX "SATA/AHCI w/o PM, max luns 1\n")); 1058 deviceExtension->NumberLuns = 1; 1059 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE; 1060 } else { 1061 KdPrint2((PRINT_PREFIX "SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS)); 1062 deviceExtension->NumberLuns = SATA_MAX_PM_UNITS; 1063 //deviceExtension->NumberLuns = 1; 1064 } 1065 } else { 1066 KdPrint2((PRINT_PREFIX " PM not supported -> 1 lun/chan\n")); 1067 deviceExtension->NumberLuns = 1; 1068 } 1069 1070 if(!UniAtaAhciValidateVersion(deviceExtension, version, TRUE)) { 1071 goto exit_detect; 1072 } 1073 1074 deviceExtension->HwFlags |= UNIATA_SATA | UNIATA_AHCI; 1075 if(deviceExtension->NumberChannels < NumberChannels) { 1076 deviceExtension->NumberChannels = NumberChannels; 1077 } 1078 deviceExtension->DmaSegmentLength = 0x3fffff+1; // 4MB 1079 deviceExtension->DmaSegmentAlignmentMask = -1; // no restrictions 1080 1081 deviceExtension->BusMaster = DMA_MODE_AHCI; 1082 deviceExtension->MaxTransferMode = max(deviceExtension->MaxTransferMode, ATA_SA150+(((CAP & AHCI_CAP_ISS_MASK) >> 20)-1) ); 1083 1084 found = TRUE; 1085 1086 exit_detect: 1087 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, GHC0); 1088 KdPrint((" AHCI detect status %d\n", found)); 1089 1090 return found; 1091 } // end UniataAhciDetect() 1092 1093 UCHAR 1094 NTAPI 1095 UniataAhciStatus( 1096 IN PVOID HwDeviceExtension, 1097 IN ULONG lChannel, 1098 IN ULONG DeviceNumber 1099 ) 1100 { 1101 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1102 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1103 ULONG Channel = deviceExtension->Channel + lChannel; 1104 ULONG hIS; 1105 ULONG CI, ACT; 1106 AHCI_IS_REG IS; 1107 SATA_SSTATUS_REG SStatus; 1108 SATA_SERROR_REG SError; 1109 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); 1110 ULONG tag=0; 1111 1112 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel, Channel)); 1113 1114 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS); 1115 KdPrint((" hIS %#x\n", hIS)); 1116 hIS &= (1 << Channel); 1117 if(!hIS) { 1118 return INTERRUPT_REASON_IGNORE; 1119 } 1120 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); 1121 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); 1122 ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT); 1123 SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus); 1124 SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); 1125 1126 /* clear interrupt(s) */ 1127 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS, hIS); 1128 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg); 1129 AtapiWritePort4(chan, IDX_SATA_SError, SError.Reg); 1130 1131 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n", 1132 IS.Reg, SStatus.Reg, SError.Reg, CI, ACT)); 1133 1134 /* do we have cold connect surprise */ 1135 if(IS.CPDS) { 1136 } 1137 1138 /* check for and handle connect events */ 1139 if(IS.PCS) { 1140 UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH); 1141 } 1142 if(IS.PRCS) { 1143 UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH); 1144 } 1145 chan->AhciCompleteCI = (chan->AhciPrevCI ^ CI) & chan->AhciPrevCI; // only 1->0 states 1146 chan->AhciPrevCI = CI; 1147 chan->AhciLastSError = SError.Reg; 1148 KdPrint((" AHCI: complete mask %#x\n", chan->AhciCompleteCI)); 1149 chan->AhciLastIS = IS.Reg; 1150 if(CI & (1 << tag)) { 1151 #ifdef _DEBUG 1152 UniataDumpAhciPortRegs(chan); 1153 #endif //_DEBUG 1154 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts 1155 if(IS.Reg & 1156 (ATA_AHCI_P_IX_OF | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF | 1157 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_HBF | ATA_AHCI_P_IX_TFE)) { 1158 KdPrint((" AHCI: unexpected, error\n")); 1159 } else { 1160 KdPrint((" AHCI: unexpected, incomplete command or error ?\n")); 1161 /* 1162 ULONG TFD; 1163 1164 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1165 KdPrint2((" TFD %#x\n", TFD)); 1166 if(TFD & IDE_STATUS_BUSY) { 1167 KdPrint2((" Seems to be interrupt on error\n")); 1168 return INTERRUPT_REASON_OUR; 1169 } 1170 */ 1171 return INTERRUPT_REASON_UNEXPECTED; 1172 } 1173 } 1174 return INTERRUPT_REASON_OUR; 1175 1176 } // end UniataAhciStatus() 1177 1178 VOID 1179 NTAPI 1180 UniataAhciSnapAtaRegs( 1181 IN PHW_CHANNEL chan, 1182 IN ULONG DeviceNumber, 1183 IN OUT PIDEREGS_EX regs 1184 ) 1185 { 1186 ULONG TFD, SIG; 1187 1188 regs->bDriveHeadReg = IDE_DRIVE_SELECT_1; 1189 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1190 regs->bCommandReg = (UCHAR)(TFD & 0xff); 1191 regs->bFeaturesReg = (UCHAR)((TFD >> 8) & 0xff); 1192 1193 SIG = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG); 1194 regs->bSectorCountReg = (UCHAR)(SIG & 0xff); 1195 regs->bSectorNumberReg = (UCHAR)((SIG >> 8) & 0xff); 1196 regs->bCylLowReg = (UCHAR)((SIG >> 16) & 0xff); 1197 regs->bCylHighReg = (UCHAR)((SIG >> 24) & 0xff); 1198 regs->bOpFlags = 0; 1199 1200 return; 1201 } // end UniataAhciSnapAtaRegs() 1202 1203 ULONG 1204 NTAPI 1205 UniataAhciSetupFIS_H2D( 1206 IN PHW_DEVICE_EXTENSION deviceExtension, 1207 IN ULONG DeviceNumber, 1208 IN ULONG lChannel, 1209 OUT PUCHAR fis, 1210 IN UCHAR command, 1211 IN ULONGLONG lba, 1212 IN USHORT count, 1213 IN USHORT feature 1214 ) 1215 { 1216 //ULONG i; 1217 PUCHAR plba; 1218 BOOLEAN need48; 1219 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1220 1221 KdPrint2((PRINT_PREFIX " AHCI setup FIS %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber)); 1222 //i = 0; 1223 plba = (PUCHAR)&lba; 1224 1225 RtlZeroMemory(fis, 20); 1226 1227 fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */ 1228 fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */ 1229 fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 | 1230 ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0); 1231 fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT; 1232 1233 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command, 1234 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET 1235 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) && 1236 */ 1237 command == IDE_COMMAND_ATAPI_PACKET) { 1238 fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET; 1239 if(feature & ATA_F_DMA) { 1240 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff); 1241 } else { 1242 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff); 1243 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff; 1244 } 1245 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT; 1246 } else { 1247 1248 if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) && 1249 CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) { 1250 KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count)); 1251 return 0; 1252 } 1253 1254 need48 = UniAta_need_lba48(command, lba, count, 1255 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48); 1256 1257 /* translate command into 48bit version */ 1258 if(need48) { 1259 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { 1260 command = AtaCommands48[command]; 1261 } else { 1262 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n")); 1263 return 0; 1264 } 1265 } 1266 1267 fis[IDX_AHCI_o_Command] = command; 1268 fis[IDX_AHCI_o_Feature] = (UCHAR)feature; 1269 1270 fis[IDX_AHCI_o_BlockNumber] = plba[0]; 1271 fis[IDX_AHCI_o_CylinderLow] = plba[1]; 1272 fis[IDX_AHCI_o_CylinderHigh] = plba[2]; 1273 1274 fis[IDX_AHCI_o_BlockCount] = (UCHAR)count & 0xff; 1275 1276 if(need48) { 1277 //i++; 1278 fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB; 1279 1280 fis[IDX_AHCI_o_BlockNumberExp] = plba[3]; 1281 fis[IDX_AHCI_o_CylinderLowExp] = plba[4]; 1282 fis[IDX_AHCI_o_CylinderHighExp] = plba[5]; 1283 1284 fis[IDX_AHCI_o_BlockCountExp] = (UCHAR)(count>>8) & 0xff; 1285 1286 fis[IDX_AHCI_o_FeatureExp] = (UCHAR)(feature>>8) & 0xff; 1287 1288 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48; 1289 } else { 1290 fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f); 1291 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48; 1292 } 1293 1294 //fis[14] = 0x00; 1295 1296 } 1297 1298 //KdDump(fis, 20); 1299 1300 return 20; 1301 } // end UniataAhciSetupFIS_H2D() 1302 1303 ULONG 1304 NTAPI 1305 UniataAhciSetupFIS_H2D_Direct( 1306 IN PHW_DEVICE_EXTENSION deviceExtension, 1307 IN ULONG DeviceNumber, 1308 IN ULONG lChannel, 1309 OUT PUCHAR fis, 1310 IN PIDEREGS_EX regs 1311 ) 1312 { 1313 //ULONG i; 1314 //PUCHAR plba; 1315 BOOLEAN need48; 1316 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1317 UCHAR command; 1318 1319 command = regs->bCommandReg; 1320 1321 KdPrint2((PRINT_PREFIX " AHCI setup FIS Direct %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber)); 1322 //i = 0; 1323 //plba = (PUCHAR)&lba; 1324 1325 RtlZeroMemory(fis, 20); 1326 1327 fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */ 1328 fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */ 1329 fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 | 1330 ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0); 1331 fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT; 1332 1333 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command, 1334 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET 1335 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) && 1336 */ 1337 command == IDE_COMMAND_ATAPI_PACKET) { 1338 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET; 1339 if(feature & ATA_F_DMA) { 1340 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff); 1341 } else { 1342 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff); 1343 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff; 1344 }*/ 1345 return 0; 1346 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT; 1347 } else { 1348 1349 need48 = (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) && 1350 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48; 1351 1352 /* translate command into 48bit version */ 1353 if(need48) { 1354 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { 1355 command = AtaCommands48[command]; 1356 } else { 1357 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n")); 1358 return 0; 1359 } 1360 } 1361 1362 fis[IDX_AHCI_o_Command] = command; 1363 fis[IDX_AHCI_o_Feature] = regs->bFeaturesReg; 1364 1365 fis[IDX_AHCI_o_BlockNumber] = regs->bSectorNumberReg; 1366 fis[IDX_AHCI_o_CylinderLow] = regs->bCylLowReg; 1367 fis[IDX_AHCI_o_CylinderHigh] = regs->bCylHighReg; 1368 1369 fis[IDX_AHCI_o_BlockCount] = regs->bSectorCountReg; 1370 1371 if(need48) { 1372 //i++; 1373 fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB; 1374 1375 fis[IDX_AHCI_o_BlockNumberExp] = regs->bSectorNumberRegH; 1376 fis[IDX_AHCI_o_CylinderLowExp] = regs->bCylLowRegH; 1377 fis[IDX_AHCI_o_CylinderHighExp] = regs->bCylHighRegH; 1378 1379 fis[IDX_AHCI_o_BlockCountExp] = regs->bSectorCountRegH; 1380 1381 fis[IDX_AHCI_o_FeatureExp] = regs->bFeaturesRegH; 1382 1383 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48; 1384 } else { 1385 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f); 1386 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48; 1387 } 1388 fis[IDX_AHCI_o_DriveSelect] |= regs->bDriveHeadReg & 0x0f; 1389 } 1390 1391 KdDump(fis, 20); 1392 1393 return 20; 1394 } // end UniataAhciSetupFIS_H2D_Direct() 1395 1396 UCHAR 1397 NTAPI 1398 UniataAhciWaitCommandReady( 1399 IN PHW_CHANNEL chan, 1400 IN ULONG timeout 1401 ) 1402 { 1403 AHCI_IS_REG IS; 1404 //ULONG ACT; 1405 ULONG CI=0; 1406 ULONG i; 1407 ULONG SError; 1408 ULONG tag=0; 1409 1410 timeout *= 5; 1411 1412 for (i=0; i<timeout; i++) { 1413 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); 1414 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT); 1415 if (!(( CI >> tag) & 0x01)) { 1416 break; 1417 } 1418 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); 1419 //KdPrint((" IS %#x\n", IS.Reg)); 1420 if(IS.Reg) { 1421 break; 1422 } 1423 SError = AtapiReadPort4(chan, IDX_SATA_SError); 1424 if(SError) { 1425 KdPrint((" AHCI: error %#x\n", SError)); 1426 i = timeout; 1427 break; 1428 } 1429 AtapiStallExecution(200); 1430 } 1431 KdPrint((" CI %#x\n", CI)); 1432 1433 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus); 1434 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); 1435 1436 /* clear interrupt(s) */ 1437 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); 1438 KdPrint((" IS %#x\n", IS.Reg)); 1439 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg); 1440 1441 if (timeout && (i >= timeout)) { 1442 #ifdef _DEBUG 1443 ULONG TFD; 1444 1445 SError = AtapiReadPort4(chan, IDX_SATA_SError); 1446 KdPrint((" AHCI: timeout, SError %#x\n", SError)); 1447 1448 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1449 KdPrint2((" TFD %#x\n", TFD)); 1450 #endif //_DEBUG 1451 1452 return IDE_STATUS_WRONG; 1453 } 1454 1455 return IDE_STATUS_IDLE; 1456 } // end UniataAhciWaitCommandReady() 1457 1458 UCHAR 1459 NTAPI 1460 UniataAhciSendCommand( 1461 IN PVOID HwDeviceExtension, 1462 IN ULONG lChannel, 1463 IN ULONG DeviceNumber, 1464 IN USHORT ahci_flags, 1465 IN ULONG timeout 1466 ) 1467 { 1468 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1469 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1470 //ULONG Channel = deviceExtension->Channel + lChannel; 1471 //ULONG hIS; 1472 //ULONG SError; 1473 //SATA_SSTATUS_REG SStatus; 1474 //SATA_SERROR_REG SError; 1475 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); 1476 //ULONGIO_PTR base; 1477 ULONG tag=0; 1478 1479 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 1480 1481 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan->lChannel)); 1482 1483 AHCI_CL->prd_length = 0; 1484 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12); 1485 AHCI_CL->cmd_flags = UniAtaAhciAdjustIoFlags(0, ahci_flags, 20, DeviceNumber); 1486 1487 AHCI_CL->bytecount = 0; 1488 AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd); 1489 if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) { 1490 KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK)); 1491 } 1492 1493 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag); 1494 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 1 << tag); 1495 1496 return UniataAhciWaitCommandReady(chan, timeout); 1497 1498 } // end UniataAhciSendCommand() 1499 1500 UCHAR 1501 NTAPI 1502 UniataAhciSendPIOCommand( 1503 IN PVOID HwDeviceExtension, 1504 IN ULONG lChannel, 1505 IN ULONG DeviceNumber, 1506 IN PSCSI_REQUEST_BLOCK Srb, 1507 IN PUCHAR data, 1508 IN ULONG length, /* bytes */ 1509 IN UCHAR command, 1510 IN ULONGLONG lba, 1511 IN USHORT bcount, /* block count, just ATA register */ 1512 IN USHORT feature, 1513 IN USHORT ahci_flags, 1514 IN ULONG wait_flags, 1515 IN ULONG timeout 1516 ) 1517 { 1518 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1519 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1520 UCHAR statusByte; 1521 PATA_REQ AtaReq; 1522 ULONG fis_size; 1523 //ULONG tag=0; 1524 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 1525 PIDE_AHCI_CMD AHCI_CMD = NULL; 1526 1527 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 1528 1529 KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n", 1530 deviceExtension->DevIndex, lChannel, DeviceNumber, command, lba, bcount, feature, data, length, wait_flags )); 1531 1532 if(length/DEV_BSIZE != bcount) { 1533 KdPrint((" length/DEV_BSIZE != bcount\n")); 1534 } 1535 1536 #ifdef _DEBUG 1537 //UniataDumpAhciPortRegs(chan); 1538 #endif // _DEBUG 1539 1540 if(!Srb) { 1541 Srb = BuildAhciInternalSrb(HwDeviceExtension, DeviceNumber, lChannel, data, length); 1542 if(!Srb) { 1543 KdPrint((" !Srb\n")); 1544 return IDE_STATUS_WRONG; 1545 } 1546 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup 1547 //should be already called on init 1548 } 1549 AtaReq = (PATA_REQ)(Srb->SrbExtension); 1550 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq)); 1551 1552 AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr; 1553 1554 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, 1555 &(AHCI_CMD->cfis[0]), 1556 command, 1557 lba, 1558 bcount, 1559 feature 1560 ); 1561 1562 if(!fis_size) { 1563 KdPrint2(("!fis_size\n")); 1564 return IDE_STATUS_WRONG; 1565 } 1566 1567 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n")); 1568 ahci_flags = UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber); 1569 KdPrint2(("ahci_flags %#x\n", ahci_flags)); 1570 1571 if(data) { 1572 if(ahci_flags & ATA_AHCI_CMD_WRITE) { 1573 AtaReq->Flags &= ~REQ_FLAG_READ; 1574 Srb->SrbFlags |= SRB_FLAGS_DATA_OUT; 1575 KdPrint((" assume OUT\n")); 1576 } else { 1577 AtaReq->Flags |= REQ_FLAG_READ; 1578 Srb->SrbFlags |= SRB_FLAGS_DATA_IN; 1579 KdPrint((" assume IN\n")); 1580 } 1581 if(!AtapiDmaSetup(HwDeviceExtension, 1582 DeviceNumber, 1583 lChannel, // logical channel, 1584 Srb, 1585 data, 1586 length)) { 1587 KdPrint2((" can't setup buffer\n")); 1588 return IDE_STATUS_WRONG; 1589 } 1590 } 1591 1592 AtaReq->ahci.io_cmd_flags = ahci_flags; 1593 1594 #ifdef _DEBUG 1595 //UniataDumpAhciPortRegs(chan); 1596 #endif // _DEBUG 1597 1598 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 1599 1600 #ifdef _DEBUG 1601 //UniataDumpAhciPortRegs(chan); 1602 #endif // _DEBUG 1603 1604 if(wait_flags == ATA_IMMEDIATE) { 1605 statusByte = 0; 1606 KdPrint2((" return imemdiately\n")); 1607 } else { 1608 statusByte = UniataAhciWaitCommandReady(chan, timeout); 1609 UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber); 1610 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 1611 } 1612 1613 return statusByte; 1614 1615 } // end UniataAhciSendPIOCommand() 1616 1617 UCHAR 1618 NTAPI 1619 UniataAhciSendPIOCommandDirect( 1620 IN PVOID HwDeviceExtension, 1621 IN ULONG lChannel, 1622 IN ULONG DeviceNumber, 1623 IN PSCSI_REQUEST_BLOCK Srb, 1624 IN PIDEREGS_EX regs, 1625 IN ULONG wait_flags, 1626 IN ULONG timeout 1627 ) 1628 { 1629 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1630 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1631 UCHAR statusByte; 1632 PATA_REQ AtaReq; 1633 ULONG fis_size; 1634 //ULONG tag=0; 1635 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 1636 PIDE_AHCI_CMD AHCI_CMD = NULL; 1637 USHORT ahci_flags=0; 1638 // USHORT bcount=0; 1639 1640 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 1641 1642 KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n", 1643 deviceExtension->DevIndex, lChannel, DeviceNumber, Srb->DataBuffer, Srb->DataTransferLength, wait_flags )); 1644 1645 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) { 1646 // KdPrint((" length/DEV_BSIZE != bcount\n")); 1647 // } 1648 1649 #ifdef _DEBUG 1650 //UniataDumpAhciPortRegs(chan); 1651 #endif // _DEBUG 1652 1653 if(!Srb) { 1654 KdPrint((" !Srb\n")); 1655 return IDE_STATUS_WRONG; 1656 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup 1657 //should be already called on init 1658 } 1659 AtaReq = (PATA_REQ)(Srb->SrbExtension); 1660 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq)); 1661 1662 AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr; 1663 if(!AHCI_CMD) { 1664 KdPrint((" !AHCI_CMD\n")); 1665 return IDE_STATUS_WRONG; 1666 } 1667 1668 if(Srb->DataTransferLength) { 1669 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 1670 ahci_flags |= ATA_AHCI_CMD_WRITE; 1671 AtaReq->Flags &= ~REQ_FLAG_READ; 1672 } else { 1673 AtaReq->Flags |= REQ_FLAG_READ; 1674 } 1675 } 1676 1677 fis_size = UniataAhciSetupFIS_H2D_Direct(deviceExtension, DeviceNumber, lChannel, 1678 &(AHCI_CMD->cfis[0]), 1679 regs); 1680 1681 if(!fis_size) { 1682 KdPrint2(("!fis_size\n")); 1683 return IDE_STATUS_WRONG; 1684 } 1685 1686 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n")); 1687 ahci_flags = UniAtaAhciAdjustIoFlags(regs->bCommandReg, ahci_flags, fis_size, DeviceNumber); 1688 KdPrint2(("ahci_flags %#x\n", ahci_flags)); 1689 1690 if(Srb->DataTransferLength) { 1691 if(!AtapiDmaSetup(HwDeviceExtension, 1692 DeviceNumber, 1693 lChannel, // logical channel, 1694 Srb, 1695 (PUCHAR)(Srb->DataBuffer), 1696 Srb->DataTransferLength)) { 1697 KdPrint2((" can't setup buffer\n")); 1698 return IDE_STATUS_WRONG; 1699 } 1700 } 1701 1702 AtaReq->ahci.io_cmd_flags = ahci_flags; 1703 1704 #ifdef _DEBUG 1705 //UniataDumpAhciPortRegs(chan); 1706 #endif // _DEBUG 1707 1708 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 1709 1710 #ifdef _DEBUG 1711 //UniataDumpAhciPortRegs(chan); 1712 #endif // _DEBUG 1713 1714 if(wait_flags == ATA_IMMEDIATE) { 1715 statusByte = 0; 1716 KdPrint2((" return imemdiately\n")); 1717 } else { 1718 statusByte = UniataAhciWaitCommandReady(chan, timeout); 1719 UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber); 1720 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 1721 } 1722 1723 return statusByte; 1724 1725 } // end UniataAhciSendPIOCommandDirect() 1726 1727 BOOLEAN 1728 NTAPI 1729 UniataAhciAbortOperation( 1730 IN PHW_CHANNEL chan 1731 ) 1732 { 1733 /* kick controller into sane state */ 1734 if(!UniataAhciStop(chan)) { 1735 return FALSE; 1736 } 1737 if(!UniataAhciStopFR(chan)) { 1738 return FALSE; 1739 } 1740 if(!UniataAhciCLO(chan)) { 1741 return FALSE; 1742 } 1743 UniataAhciStartFR(chan); 1744 UniataAhciStart(chan); 1745 1746 return TRUE; 1747 } // end UniataAhciAbortOperation() 1748 1749 ULONG 1750 NTAPI 1751 UniataAhciSoftReset( 1752 IN PVOID HwDeviceExtension, 1753 IN ULONG lChannel, 1754 IN ULONG DeviceNumber 1755 ) 1756 { 1757 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1758 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1759 //ULONG Channel = deviceExtension->Channel + lChannel; 1760 //ULONG hIS; 1761 //ULONG CI; 1762 //AHCI_IS_REG IS; 1763 //ULONG tag=0; 1764 1765 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan->lChannel)); 1766 1767 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 1768 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); 1769 1770 /* kick controller into sane state */ 1771 if(!UniataAhciAbortOperation(chan)) { 1772 KdPrint2((" abort failed\n")); 1773 return (ULONG)(-1); 1774 } 1775 1776 /* pull reset active */ 1777 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); 1778 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; 1779 AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f; 1780 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT; 1781 AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT | IDE_DC_RESET_CONTROLLER); 1782 1783 if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY, 100) == IDE_STATUS_WRONG) { 1784 KdPrint2((" timeout\n")); 1785 return (ULONG)(-1); 1786 } 1787 AtapiStallExecution(50); 1788 1789 /* pull reset inactive */ 1790 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); 1791 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; 1792 AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f; 1793 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT; 1794 AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT); 1795 if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, 0, 3000) == IDE_STATUS_WRONG) { 1796 KdPrint2((" timeout (2)\n")); 1797 return (ULONG)(-1); 1798 } 1799 1800 UniataAhciWaitReady(chan, 1); 1801 1802 KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis)); 1803 1804 return UniataAhciUlongFromRFIS(RCV_FIS); 1805 1806 } // end UniataAhciSoftReset() 1807 1808 ULONG 1809 NTAPI 1810 UniataAhciWaitReady( 1811 IN PHW_CHANNEL chan, 1812 IN ULONG timeout 1813 ) 1814 { 1815 ULONG TFD; 1816 ULONG i; 1817 1818 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan->lChannel)); 1819 1820 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs); 1821 1822 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1823 for(i=0; i<timeout && (TFD & 1824 (IDE_STATUS_DRQ | IDE_STATUS_BUSY)); i++) { 1825 AtapiStallExecution(1000); 1826 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1827 } 1828 1829 KdPrint2((" TFD %#x\n", TFD)); 1830 1831 return TFD; 1832 1833 } // end UniataAhciWaitReady() 1834 1835 ULONG 1836 NTAPI 1837 UniataAhciHardReset( 1838 IN PVOID HwDeviceExtension, 1839 IN ULONG lChannel, 1840 OUT PULONG signature 1841 ) 1842 { 1843 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1844 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1845 //ULONG Channel = deviceExtension->Channel + lChannel; 1846 ULONG TFD; 1847 1848 1849 KdPrint(("UniataAhciHardReset: lChan %d\n", chan->lChannel)); 1850 1851 (*signature) = 0xffffffff; 1852 1853 UniataAhciStop(chan); 1854 if(UniataSataPhyEnable(HwDeviceExtension, lChannel, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE) == IDE_STATUS_WRONG) { 1855 KdPrint((" no PHY\n")); 1856 return IDE_STATUS_WRONG; 1857 } 1858 1859 /* Wait for clearing busy status. */ 1860 TFD = UniataAhciWaitReady(chan, 15000); 1861 if(TFD & (IDE_STATUS_DRQ | IDE_STATUS_BUSY)) { 1862 KdPrint((" busy: TFD %#x\n", TFD)); 1863 return TFD; 1864 } 1865 KdPrint((" TFD %#x\n", TFD)); 1866 1867 #ifdef _DEBUG 1868 UniataDumpAhciPortRegs(chan); 1869 #endif // _DEBUG 1870 1871 (*signature) = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG); 1872 KdPrint((" sig: %#x\n", *signature)); 1873 1874 UniataAhciStart(chan); 1875 1876 return 0; 1877 1878 } // end UniataAhciHardReset() 1879 1880 VOID 1881 NTAPI 1882 UniataAhciReset( 1883 IN PVOID HwDeviceExtension, 1884 IN ULONG lChannel 1885 ) 1886 { 1887 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1888 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1889 //ULONG Channel = deviceExtension->Channel + lChannel; 1890 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); 1891 ULONG CAP; 1892 //ULONGIO_PTR base; 1893 ULONG signature; 1894 ULONG i; 1895 ULONG VendorID = deviceExtension->DevID & 0xffff; 1896 1897 KdPrint(("UniataAhciReset: lChan %d\n", chan->lChannel)); 1898 1899 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs); 1900 1901 /* Disable port interrupts */ 1902 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); 1903 1904 if(UniataAhciHardReset(HwDeviceExtension, lChannel, &signature)) { 1905 1906 KdPrint((" No devices in all LUNs\n")); 1907 for (i=0; i<deviceExtension->NumberLuns; i++) { 1908 // Zero device fields to ensure that if earlier devices were found, 1909 // but not claimed, the fields are cleared. 1910 UniataForgetDevice(chan->lun[i]); 1911 } 1912 1913 /* enable wanted port interrupts */ 1914 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 1915 ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC); 1916 return; 1917 } 1918 1919 /* enable wanted port interrupts */ 1920 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 1921 (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | 1922 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | 1923 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC) : 0) | 1924 ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | 1925 ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR) ); 1926 1927 /* 1928 * Only probe for PortMultiplier if HW has support. 1929 * Ignore Marvell, which is not working, 1930 */ 1931 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); 1932 if ((CAP & AHCI_CAP_SPM) && 1933 (VendorID != ATA_MARVELL_ID)) { 1934 KdPrint((" check PM\n")); 1935 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, AHCI_DEV_SEL_PM); 1936 /* Workaround for some ATI chips, failing to soft-reset 1937 * when port multiplicator supported, but absent. 1938 * XXX: We can also check PxIS.IPMS==1 here to be sure. */ 1939 if (signature == 0xffffffff) { 1940 KdPrint((" re-check PM\n")); 1941 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0); 1942 } 1943 } else { 1944 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0); 1945 } 1946 1947 KdPrint((" signature %#x\n", signature)); 1948 chan->lun[0]->DeviceFlags &= ~(DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT | CTRFLAGS_AHCI_PM); 1949 switch (signature >> 16) { 1950 case 0x0000: 1951 KdPrint((" ATA dev\n")); 1952 chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT; 1953 chan->PmLunMap = 0; 1954 break; 1955 case 0x9669: 1956 KdPrint((" PM\n")); 1957 if(deviceExtension->NumberLuns > 1) { 1958 chan->ChannelCtrlFlags |= CTRFLAGS_AHCI_PM; 1959 UniataSataIdentifyPM(chan); 1960 } else { 1961 KdPrint((" no PM supported (1 lun/chan)\n")); 1962 } 1963 break; 1964 case 0xeb14: 1965 KdPrint((" ATAPI dev\n")); 1966 chan->lun[0]->DeviceFlags |= (DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT); 1967 chan->PmLunMap = 0; 1968 break; 1969 default: /* SOS XXX */ 1970 KdPrint((" default to ATA ???\n")); 1971 chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT; 1972 chan->PmLunMap = 0; 1973 } 1974 1975 return; 1976 1977 } // end UniataAhciReset() 1978 1979 VOID 1980 NTAPI 1981 UniataAhciStartFR( 1982 IN PHW_CHANNEL chan 1983 ) 1984 { 1985 ULONG CMD; 1986 1987 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan->lChannel)); 1988 1989 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 1990 KdPrint2((" CMD %#x\n", CMD)); 1991 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD | ATA_AHCI_P_CMD_FRE); 1992 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 1993 1994 return; 1995 } // end UniataAhciStartFR() 1996 1997 BOOLEAN 1998 NTAPI 1999 UniataAhciStopFR( 2000 IN PHW_CHANNEL chan 2001 ) 2002 { 2003 ULONG CMD; 2004 ULONG i; 2005 2006 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan->lChannel)); 2007 2008 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2009 KdPrint2((" CMD %#x\n", CMD)); 2010 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD & ~ATA_AHCI_P_CMD_FRE); 2011 2012 for(i=0; i<1000; i++) { 2013 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2014 if(!(CMD & ATA_AHCI_P_CMD_FR)) { 2015 KdPrint2((" final CMD %#x\n", CMD)); 2016 return TRUE; 2017 } 2018 AtapiStallExecution(1000); 2019 } 2020 KdPrint2((" CMD %#x\n", CMD)); 2021 KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError))); 2022 KdPrint2(("UniataAhciStopFR: timeout\n")); 2023 return FALSE; 2024 } // end UniataAhciStopFR() 2025 2026 VOID 2027 NTAPI 2028 UniataAhciStart( 2029 IN PHW_CHANNEL chan 2030 ) 2031 { 2032 ULONG IS, CMD; 2033 SATA_SERROR_REG SError; 2034 2035 KdPrint2(("UniataAhciStart: lChan %d\n", chan->lChannel)); 2036 2037 /* clear SATA error register */ 2038 SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); 2039 2040 /* clear any interrupts pending on this channel */ 2041 IS = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); 2042 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS); 2043 2044 KdPrint2((" SError %#x, IS %#x\n", SError.Reg, IS)); 2045 2046 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2047 KdPrint2((" CMD %#x\n", CMD)); 2048 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 2049 CMD | 2050 ATA_AHCI_P_CMD_ST | 2051 ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0)); 2052 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2053 2054 return; 2055 } // end UniataAhciStart() 2056 2057 BOOLEAN 2058 NTAPI 2059 UniataAhciCLO( 2060 IN PHW_CHANNEL chan 2061 ) 2062 { 2063 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2064 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 2065 ULONG CAP, CMD; 2066 //SATA_SERROR_REG SError; 2067 ULONG i; 2068 2069 KdPrint2(("UniataAhciCLO: lChan %d\n", chan->lChannel)); 2070 2071 /* issue Command List Override if supported */ 2072 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); 2073 CAP = chan->DeviceExtension->AHCI_CAP; 2074 if(!(CAP & AHCI_CAP_SCLO)) { 2075 return TRUE; 2076 } 2077 KdPrint2((" send CLO\n")); 2078 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2079 CMD |= ATA_AHCI_P_CMD_CLO; 2080 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); 2081 2082 for(i=0; i<1000; i++) { 2083 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2084 if(!(CMD & ATA_AHCI_P_CMD_CLO)) { 2085 KdPrint2((" final CMD %#x\n", CMD)); 2086 return TRUE; 2087 } 2088 AtapiStallExecution(1000); 2089 } 2090 KdPrint2((" CMD %#x\n", CMD)); 2091 KdPrint2(("UniataAhciCLO: timeout\n")); 2092 return FALSE; 2093 } // end UniataAhciCLO() 2094 2095 BOOLEAN 2096 NTAPI 2097 UniataAhciStop( 2098 IN PHW_CHANNEL chan 2099 ) 2100 { 2101 ULONG CMD; 2102 //SATA_SERROR_REG SError; 2103 ULONG i; 2104 2105 KdPrint2(("UniataAhciStop: lChan %d\n", chan->lChannel)); 2106 2107 /* issue Command List Override if supported */ 2108 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2109 CMD &= ~ATA_AHCI_P_CMD_ST; 2110 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); 2111 2112 for(i=0; i<1000; i++) { 2113 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2114 if(!(CMD & ATA_AHCI_P_CMD_CR)) { 2115 KdPrint2((" final CMD %#x\n", CMD)); 2116 return TRUE; 2117 } 2118 AtapiStallExecution(1000); 2119 } 2120 KdPrint2((" CMD %#x\n", CMD)); 2121 KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError))); 2122 KdPrint2(("UniataAhciStop: timeout\n")); 2123 return FALSE; 2124 } // end UniataAhciStop() 2125 2126 UCHAR 2127 NTAPI 2128 UniataAhciBeginTransaction( 2129 IN PVOID HwDeviceExtension, 2130 IN ULONG lChannel, 2131 IN ULONG DeviceNumber, 2132 IN PSCSI_REQUEST_BLOCK Srb 2133 ) 2134 { 2135 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2136 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 2137 //ULONG Channel = deviceExtension->Channel + lChannel; 2138 //ULONG hIS; 2139 ULONG CMD, CMD0; 2140 //AHCI_IS_REG IS; 2141 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 2142 //SATA_SSTATUS_REG SStatus; 2143 //SATA_SERROR_REG SError; 2144 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); 2145 //ULONGIO_PTR base; 2146 ULONG tag=0; 2147 //ULONG i; 2148 2149 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 2150 2151 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan->lChannel, AtaReq)); 2152 2153 if(Srb->DataTransferLength && (!AtaReq->dma_entries || AtaReq->dma_entries >= (USHORT)0xffff)) { 2154 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq->dma_entries)); 2155 return 0; 2156 } 2157 2158 AHCI_CL->prd_length = (USHORT)(AtaReq->dma_entries); 2159 AHCI_CL->cmd_flags = AtaReq->ahci.io_cmd_flags; 2160 AHCI_CL->bytecount = 0; 2161 if(AtaReq->ahci.ahci_base64) { 2162 KdPrint2((PRINT_PREFIX " AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64))); 2163 AHCI_CL->cmd_table_phys = AtaReq->ahci.ahci_base64; 2164 } else 2165 if(AtaReq->ahci.ahci_cmd_ptr) { 2166 KdPrint2((PRINT_PREFIX " AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n", 2167 AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64), 2168 &(chan->AhciCtlBlock->cmd), chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd) )); 2169 RtlCopyMemory(&(chan->AhciCtlBlock->cmd), AtaReq->ahci.ahci_cmd_ptr, 2170 FIELD_OFFSET(IDE_AHCI_CMD, prd_tab)+AHCI_CL->prd_length*sizeof(IDE_AHCI_PRD_ENTRY)); 2171 AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd); 2172 } else { 2173 KdPrint2((PRINT_PREFIX " no AHCI CMD\n")); 2174 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd); 2175 return 0; 2176 } 2177 if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) { 2178 KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK)); 2179 return 0; 2180 } 2181 2182 #ifdef _DEBUG 2183 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL->prd_length, AHCI_CL->cmd_flags, 2184 AHCI_CL->cmd_table_phys)); 2185 #endif // _DEBUG 2186 2187 CMD0 = CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2188 KdPrint2((" CMD %#x\n", CMD)); 2189 // switch controller to ATAPI mode for ATA_PACKET commands only 2190 if(ATAPI_DEVICE(chan, DeviceNumber) && 2191 AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_PACKET) { 2192 KdPrint2((" ATAPI\n")); 2193 CMD |= ATA_AHCI_P_CMD_ATAPI; 2194 KdDump(&(AtaReq->ahci.ahci_cmd_ptr->acmd), 16); 2195 } else { 2196 CMD &= ~ATA_AHCI_P_CMD_ATAPI; 2197 } 2198 if(CMD0 != CMD) { 2199 KdPrint2((" send CMD %#x, entries %#x\n", CMD, AHCI_CL->prd_length)); 2200 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); 2201 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2202 } 2203 2204 /* issue command to controller */ 2205 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag); 2206 KdPrint2((" Set CI\n")); 2207 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 0x01 << tag); 2208 chan->AhciPrevCI |= 0x01 << tag; 2209 2210 CMD0 = CMD; 2211 CMD |= ATA_AHCI_P_CMD_ST | 2212 ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0); 2213 if(CMD != CMD0) { 2214 KdPrint2((" Send CMD START\n")); 2215 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); 2216 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2217 } else { 2218 KdPrint2((" No CMD START, already active\n")); 2219 } 2220 2221 if(!ATAPI_DEVICE(chan, DeviceNumber)) { 2222 // TODO: check if we send ATAPI_RESET and wait for ready of so. 2223 if(AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_RESET) { 2224 ULONG TFD; 2225 ULONG i; 2226 2227 for(i=0; i<1000000; i++) { 2228 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 2229 if(!(TFD & IDE_STATUS_BUSY)) { 2230 break; 2231 } 2232 } 2233 if(TFD & IDE_STATUS_BUSY) { 2234 KdPrint2((" timeout\n")); 2235 } 2236 if(TFD & IDE_STATUS_ERROR) { 2237 KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8))); 2238 } 2239 AtaReq->ahci.in_status = TFD; 2240 2241 return IDE_STATUS_SUCCESS; 2242 } 2243 } 2244 2245 return IDE_STATUS_IDLE; 2246 2247 } // end UniataAhciBeginTransaction() 2248 2249 UCHAR 2250 NTAPI 2251 UniataAhciEndTransaction( 2252 IN PVOID HwDeviceExtension, 2253 IN ULONG lChannel, 2254 IN ULONG DeviceNumber, 2255 IN PSCSI_REQUEST_BLOCK Srb 2256 ) 2257 { 2258 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2259 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 2260 //ULONG Channel = deviceExtension->Channel + lChannel; 2261 //ULONG hIS; 2262 ULONG CI, ACT; 2263 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 2264 ULONG TFD; 2265 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); 2266 ULONG tag=0; 2267 //ULONG i; 2268 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 2269 //PHW_LU_EXTENSION LunExt; 2270 2271 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan->lChannel)); 2272 2273 //LunExt = chan->lun[DeviceNumber]; 2274 2275 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 2276 KdPrint2((" TFD %#x\n", TFD)); 2277 2278 if(TFD & IDE_STATUS_ERROR) { 2279 AtaReq->ahci.in_error = (UCHAR)(TFD >> 8); 2280 KdPrint2((" ERROR %#x\n", AtaReq->ahci.in_error)); 2281 } else { 2282 AtaReq->ahci.in_error = 0; 2283 } 2284 AtaReq->ahci.in_status = TFD; 2285 2286 //if (request->flags & ATA_R_CONTROL) { 2287 2288 AtaReq->ahci.in_bcount = (ULONG)(RCV_FIS[12]) | ((ULONG)(RCV_FIS[13]) << 8); 2289 AtaReq->ahci.in_lba = (ULONG)(RCV_FIS[4]) | ((ULONGLONG)(RCV_FIS[5]) << 8) | 2290 ((ULONGLONG)(RCV_FIS[6]) << 16); 2291 if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) { 2292 AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) | 2293 ((ULONGLONG)(RCV_FIS[9]) << 32) | 2294 ((ULONGLONG)(RCV_FIS[10]) << 40); 2295 } else { 2296 AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) | 2297 ((ULONGLONG)(RCV_FIS[9]) << 32) | 2298 ((ULONGLONG)(RCV_FIS[7] & 0x0f) << 24); 2299 } 2300 AtaReq->WordsTransfered = AHCI_CL->bytecount/2; 2301 /* 2302 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { 2303 KdPrint2(("RCV:\n")); 2304 KdDump(RCV_FIS, 24); 2305 KdPrint2(("PIO:\n")); 2306 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24); 2307 2308 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) )); 2309 if(!AHCI_CL->bytecount) { 2310 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2; 2311 } 2312 } 2313 */ 2314 ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT); 2315 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); 2316 if(CI & (1 << tag)) { 2317 // clear CI 2318 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI, ACT)); 2319 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS[2], RCV_FIS[3])); 2320 2321 #ifdef _DEBUG 2322 UniataDumpAhciPortRegs(chan); 2323 #endif 2324 if(!UniataAhciAbortOperation(chan)) { 2325 KdPrint2((" Abort failed, need RESET\n")); 2326 } 2327 #ifdef _DEBUG 2328 UniataDumpAhciPortRegs(chan); 2329 #endif 2330 chan->AhciPrevCI = CI & ~((ULONG)1 << tag); 2331 if(chan->AhciPrevCI) { 2332 KdPrint2((" Need command list restart, CI %#x\n", chan->AhciPrevCI)); 2333 } 2334 } else { 2335 chan->AhciPrevCI &= ~((ULONG)1 << tag); 2336 RtlZeroMemory(AHCI_CL, sizeof(IDE_AHCI_CMD_LIST)); 2337 } 2338 //} 2339 2340 return 0; 2341 2342 } // end UniataAhciEndTransaction() 2343 2344 VOID 2345 NTAPI 2346 UniataAhciResume( 2347 IN PHW_CHANNEL chan 2348 ) 2349 { 2350 ULONGLONG base; 2351 2352 KdPrint2(("UniataAhciResume: lChan %d\n", chan->lChannel)); 2353 2354 #ifdef _DEBUG 2355 //UniataDumpAhciPortRegs(chan); 2356 #endif // _DEBUG 2357 2358 /* Disable port interrupts */ 2359 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); 2360 2361 /* setup work areas */ 2362 base = chan->AHCI_CTL_PhAddr; 2363 if(!base) { 2364 KdPrint2((PRINT_PREFIX " AHCI buffer allocation failed\n")); 2365 return; 2366 } 2367 KdPrint2((PRINT_PREFIX " AHCI CLB setup\n")); 2368 if(base & AHCI_CLB_ALIGNEMENT_MASK) { 2369 KdPrint2((PRINT_PREFIX " AHCI CLB address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK)); 2370 } 2371 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB, 2372 (ULONG)(base & 0xffffffff)); 2373 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB + 4, 2374 (ULONG)((base >> 32) & 0xffffffff)); 2375 2376 KdPrint2((PRINT_PREFIX " AHCI RCV FIS setup\n")); 2377 base = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, rcv_fis); 2378 if(base & AHCI_FIS_ALIGNEMENT_MASK) { 2379 KdPrint2((PRINT_PREFIX " AHCI FIS address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK)); 2380 } 2381 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB, 2382 (ULONG)(base & 0xffffffff)); 2383 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB + 4, 2384 (ULONG)((base >> 32) & 0xffffffff)); 2385 2386 /* activate the channel and power/spin up device */ 2387 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 2388 (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | 2389 (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM)) ? ATA_AHCI_P_CMD_ALPE : 0) | 2390 (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM2)) ? ATA_AHCI_P_CMD_ASP : 0 )) 2391 ); 2392 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2393 2394 #ifdef _DEBUG 2395 //UniataDumpAhciPortRegs(chan); 2396 #endif // _DEBUG 2397 2398 UniataAhciStartFR(chan); 2399 UniataAhciStart(chan); 2400 2401 #ifdef _DEBUG 2402 UniataDumpAhciPortRegs(chan); 2403 #endif // _DEBUG 2404 2405 return; 2406 } // end UniataAhciResume() 2407 2408 #if 0 2409 VOID 2410 NTAPI 2411 UniataAhciSuspend( 2412 IN PHW_CHANNEL chan 2413 ) 2414 { 2415 ULONGLONG base; 2416 SATA_SCONTROL_REG SControl; 2417 2418 KdPrint2(("UniataAhciSuspend:\n")); 2419 2420 /* Disable port interrupts */ 2421 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); 2422 2423 /* Reset command register. */ 2424 UniataAhciStop(chan); 2425 UniataAhciStopFR(chan); 2426 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 0); 2427 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2428 2429 /* Allow everything including partial and slumber modes. */ 2430 UniataSataWritePort4(chan, IDX_SATA_SControl, 0, 0); 2431 2432 /* Request slumber mode transition and give some time to get there. */ 2433 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, ATA_AHCI_P_CMD_SLUMBER); 2434 AtapiStallExecution(100); 2435 2436 /* Disable PHY. */ 2437 SControl.Reg = 0; 2438 SControl.DET = SStatus_DET_Offline; 2439 UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, 0); 2440 2441 return; 2442 } // end UniataAhciSuspend() 2443 #endif 2444 2445 BOOLEAN 2446 NTAPI 2447 UniataAhciReadPM( 2448 IN PHW_CHANNEL chan, 2449 IN ULONG DeviceNumber, 2450 IN ULONG Reg, 2451 OUT PULONG result 2452 ) 2453 { 2454 //ULONG Channel = deviceExtension->Channel + lChannel; 2455 //ULONG hIS; 2456 //ULONG CI; 2457 //AHCI_IS_REG IS; 2458 //ULONG tag=0; 2459 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 2460 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); 2461 2462 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan->lChannel, DeviceNumber)); 2463 2464 if(DeviceNumber == DEVNUM_NOT_SPECIFIED) { 2465 (*result) = UniataSataReadPort4(chan, Reg, 0); 2466 return TRUE; 2467 } 2468 if(DeviceNumber < AHCI_DEV_SEL_PM) { 2469 switch(Reg) { 2470 case IDX_SATA_SStatus: 2471 Reg = 0; break; 2472 case IDX_SATA_SError: 2473 Reg = 1; break; 2474 case IDX_SATA_SControl: 2475 Reg = 2; break; 2476 default: 2477 return FALSE; 2478 } 2479 } 2480 2481 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); 2482 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; 2483 AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM; 2484 AHCI_CMD->cfis[2] = IDE_COMMAND_READ_PM; 2485 AHCI_CMD->cfis[3] = (UCHAR)Reg; 2486 AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber); 2487 AHCI_CMD->cfis[15] = IDE_DC_A_4BIT; 2488 2489 if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 10) == IDE_STATUS_WRONG) { 2490 KdPrint2((" PM read failed\n")); 2491 return FALSE; 2492 } 2493 2494 KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis)); 2495 2496 (*result) = UniataAhciUlongFromRFIS(RCV_FIS); 2497 return TRUE; 2498 2499 } // end UniataAhciReadPM() 2500 2501 UCHAR 2502 NTAPI 2503 UniataAhciWritePM( 2504 IN PHW_CHANNEL chan, 2505 IN ULONG DeviceNumber, 2506 IN ULONG Reg, 2507 IN ULONG value 2508 ) 2509 { 2510 //ULONG Channel = deviceExtension->Channel + lChannel; 2511 //ULONG hIS; 2512 //ULONG CI; 2513 //AHCI_IS_REG IS; 2514 //ULONG tag=0; 2515 ULONG TFD; 2516 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 2517 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); 2518 2519 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan->lChannel, DeviceNumber, value)); 2520 2521 if(DeviceNumber == DEVNUM_NOT_SPECIFIED) { 2522 UniataSataWritePort4(chan, Reg, value, 0); 2523 return 0; 2524 } 2525 if(DeviceNumber < AHCI_DEV_SEL_PM) { 2526 switch(Reg) { 2527 case IDX_SATA_SStatus: 2528 Reg = 0; break; 2529 case IDX_SATA_SError: 2530 Reg = 1; break; 2531 case IDX_SATA_SControl: 2532 Reg = 2; break; 2533 default: 2534 return IDE_STATUS_WRONG; 2535 } 2536 } 2537 2538 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); 2539 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; 2540 AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM; 2541 AHCI_CMD->cfis[2] = IDE_COMMAND_WRITE_PM; 2542 AHCI_CMD->cfis[3] = (UCHAR)Reg; 2543 AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber); 2544 2545 AHCI_CMD->cfis[12] = (UCHAR)(value & 0xff); 2546 AHCI_CMD->cfis[4] = (UCHAR)((value >> 8) & 0xff); 2547 AHCI_CMD->cfis[5] = (UCHAR)((value >> 16) & 0xff); 2548 AHCI_CMD->cfis[6] = (UCHAR)((value >> 24) & 0xff); 2549 2550 AHCI_CMD->cfis[15] = IDE_DC_A_4BIT; 2551 2552 if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 100) == IDE_STATUS_WRONG) { 2553 KdPrint2((" PM write failed\n")); 2554 return IDE_STATUS_WRONG; 2555 } 2556 2557 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 2558 2559 if(TFD & IDE_STATUS_ERROR) { 2560 KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8))); 2561 } 2562 return (UCHAR)(TFD >> 8); 2563 2564 } // end UniataAhciWritePM() 2565 2566 VOID 2567 UniataAhciSetupCmdPtr( 2568 IN OUT PATA_REQ AtaReq 2569 ) 2570 { 2571 union { 2572 PUCHAR prd_base; 2573 ULONGLONG prd_base64; 2574 }; 2575 union { 2576 PUCHAR prd_base0; 2577 ULONGLONG prd_base64_0; 2578 }; 2579 #ifdef _DEBUG 2580 ULONG d; 2581 #endif // _DEBUG 2582 2583 prd_base64_0 = prd_base64 = 0; 2584 prd_base = (PUCHAR)(&AtaReq->ahci_cmd0); 2585 prd_base0 = prd_base; 2586 2587 prd_base64 = (prd_base64 + max(FIELD_OFFSET(ATA_REQ, ahci_cmd0), AHCI_CMD_ALIGNEMENT_MASK+1)) & ~AHCI_CMD_ALIGNEMENT_MASK; 2588 2589 #ifdef _DEBUG 2590 d = (ULONG)(prd_base64 - prd_base64_0); 2591 KdPrint2((PRINT_PREFIX " AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq, prd_base64, d)); 2592 #endif // _DEBUG 2593 2594 AtaReq->ahci.ahci_cmd_ptr = (PIDE_AHCI_CMD)prd_base64; 2595 KdPrint2((PRINT_PREFIX " ahci_cmd_ptr %#x\n", AtaReq->ahci.ahci_cmd_ptr)); 2596 } // end UniataAhciSetupCmdPtr() 2597 2598 PSCSI_REQUEST_BLOCK 2599 NTAPI 2600 BuildAhciInternalSrb ( 2601 IN PVOID HwDeviceExtension, 2602 IN ULONG DeviceNumber, 2603 IN ULONG lChannel, 2604 IN PUCHAR Buffer, 2605 IN ULONG Length 2606 ) 2607 { 2608 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2609 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 2610 PSCSI_REQUEST_BLOCK srb; 2611 // PCDB cdb; 2612 PATA_REQ AtaReq = chan->AhciInternalAtaReq; 2613 2614 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel, DeviceNumber)); 2615 2616 if(!AtaReq) { 2617 KdPrint2((PRINT_PREFIX " !chan->AhciInternalAtaReq\n")); 2618 return NULL; 2619 } 2620 2621 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ)); 2622 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci)); 2623 UniAtaClearAtaReq(AtaReq); 2624 2625 srb = chan->AhciInternalSrb; 2626 2627 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK)); 2628 2629 srb->PathId = (UCHAR)lChannel; 2630 srb->TargetId = (UCHAR)DeviceNumber; 2631 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 2632 srb->Length = sizeof(SCSI_REQUEST_BLOCK); 2633 2634 // Set flags to disable synchronous negociation. 2635 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 2636 2637 // Set timeout to 4 seconds. 2638 srb->TimeOutValue = 4; 2639 2640 srb->CdbLength = 6; 2641 srb->DataBuffer = Buffer; 2642 srb->DataTransferLength = Length; 2643 srb->SrbExtension = AtaReq; 2644 2645 AtaReq->Srb = srb; 2646 AtaReq->DataBuffer = (PUSHORT)Buffer; 2647 AtaReq->TransferLength = Length; 2648 2649 //if(!AtaReq->ahci.ahci_cmd_ptr) { 2650 //UniataAhciSetupCmdPtr(AtaReq); 2651 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd); 2652 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd); 2653 //} 2654 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0); 2655 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place 2656 2657 KdPrint2((PRINT_PREFIX " Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb, AtaReq, 2658 AtaReq->ahci.ahci_cmd_ptr, AtaReq->ahci.ahci_base64)); 2659 2660 /* // Set CDB operation code. 2661 cdb = (PCDB)srb->Cdb; 2662 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE; 2663 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA); 2664 */ 2665 return srb; 2666 } // end BuildAhciInternalSrb() 2667 2668