1 /*++ 2 3 Copyright (c) 2008-2019 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 case 0x00010301: 873 break; 874 default: 875 KdPrint2((PRINT_PREFIX " Unknown AHCI revision\n")); 876 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"CheckAhciRevision", Strict)) { 877 KdPrint((" AHCI revision excluded %#x\n", version)); 878 return FALSE; 879 } 880 } 881 return TRUE; 882 } // end UniAtaAhciValidateVersion() 883 884 BOOLEAN 885 NTAPI 886 UniataAhciDetect( 887 IN PVOID HwDeviceExtension, 888 IN PPCI_COMMON_CONFIG pciData, // optional 889 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo 890 ) 891 { 892 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 893 //ULONG slotNumber = deviceExtension->slotNumber; 894 ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; 895 ULONG version; 896 ULONG i, n; 897 ULONG PI; 898 //ULONG PI_ex_mask=0; 899 ULONG CAP; 900 ULONG CAP2; 901 ULONG GHC, GHC0; 902 #ifdef _DEBUG 903 ULONG BOHC; 904 ULONG v_Mn, v_Mj; 905 #endif //_DEBUG 906 ULONG NumberChannels; 907 ULONG_PTR BaseMemAddress; 908 BOOLEAN MemIo = FALSE; 909 BOOLEAN found = FALSE; 910 ULONG BarId=5; 911 912 KdPrint2((PRINT_PREFIX " UniataAhciDetect:\n")); 913 914 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhci", 0)) { 915 KdPrint((" AHCI excluded\n")); 916 return FALSE; 917 } 918 switch(deviceExtension->DevID) { 919 case 0xa01c0031: 920 KdPrint2((PRINT_PREFIX " Cavium uses BAR(0)\n")); 921 BarId = 0; 922 break; 923 } 924 BaseMemAddress = AtapiGetIoRange(HwDeviceExtension, ConfigInfo, pciData, SystemIoBusNumber, 925 BarId, 0, 0x10); 926 if(!BaseMemAddress) { 927 KdPrint2((PRINT_PREFIX " AHCI init failed - no IoRange\n")); 928 return FALSE; 929 } 930 if((*ConfigInfo->AccessRanges)[BarId].RangeInMemory) { 931 KdPrint2((PRINT_PREFIX "MemIo\n")); 932 MemIo = TRUE; 933 } 934 deviceExtension->BaseIoAHCI_0.Addr = BaseMemAddress; 935 deviceExtension->BaseIoAHCI_0.MemIo = MemIo; 936 937 #ifdef _DEBUG 938 UniataDumpAhciRegs(deviceExtension); 939 #endif //_DEBUG 940 941 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 942 if(GHC & AHCI_GHC_HR) { 943 KdPrint2((PRINT_PREFIX " AHCI in reset state\n")); 944 return FALSE; 945 } 946 947 /* check AHCI mode. Save state and try enable */ 948 GHC0 = 949 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 950 KdPrint2((PRINT_PREFIX " check AHCI mode, GHC %#x\n", GHC)); 951 952 version = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_VS); 953 954 if(!(GHC & AHCI_GHC_AE)) { 955 KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE), check revision %#x\n", version)); 956 if(!UniAtaAhciValidateVersion(deviceExtension, version, FALSE)) { 957 KdPrint2((PRINT_PREFIX " Non-AHCI\n")); 958 goto exit_detect; 959 } 960 KdPrint2((PRINT_PREFIX " try enable\n")); 961 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, 962 (GHC | AHCI_GHC_AE) & ~AHCI_GHC_IE); 963 GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC); 964 965 KdPrint2((PRINT_PREFIX " re-check AHCI mode, GHC %#x\n", GHC)); 966 if(!(GHC & AHCI_GHC_AE)) { 967 KdPrint2((PRINT_PREFIX " Non-AHCI GHC (!AE)\n")); 968 goto exit_detect; 969 } 970 } 971 972 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); 973 CAP2 = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP2); 974 KdPrint2((PRINT_PREFIX " AHCI CAP %#x, CAP2 %#x, ver %#x\n", CAP, CAP2, version)); 975 if(CAP & AHCI_CAP_S64A) { 976 KdPrint2((PRINT_PREFIX " 64bit")); 977 //deviceExtension->Host64 = TRUE; // this is just DETECT, do not update anything 978 } 979 #ifdef _DEBUG 980 if(CAP2 & AHCI_CAP2_BOH) { 981 BOHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_BOHC); 982 KdPrint2((PRINT_PREFIX " BOHC %#x", BOHC)); 983 } 984 #endif //_DEBUG 985 if(CAP & AHCI_CAP_NCQ) { 986 KdPrint2((PRINT_PREFIX " NCQ")); 987 } 988 if(CAP & AHCI_CAP_SNTF) { 989 KdPrint2((PRINT_PREFIX " SNTF")); 990 } 991 if(CAP & AHCI_CAP_CCC) { 992 KdPrint2((PRINT_PREFIX " CCC")); 993 } 994 KdPrint2((PRINT_PREFIX "\n")); 995 996 /* get the number of HW channels */ 997 998 /* CAP.NOP sometimes indicate the index of the last enabled 999 * port, at other times, that of the last possible port, so 1000 * determining the maximum port number requires looking at 1001 * both CAP.NOP and PI. 1002 */ 1003 PI = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_PI); 1004 deviceExtension->AHCI_PI = deviceExtension->AHCI_PI_mask = PI; 1005 KdPrint2((PRINT_PREFIX " AHCI PI %#x\n", PI)); 1006 1007 for(i=PI, n=0; i; n++, i=i>>1) { 1008 if(AtapiRegCheckDevValue(deviceExtension, n, DEVNUM_NOT_SPECIFIED, L"Exclude", 0)) { 1009 KdPrint2((PRINT_PREFIX "Channel %d excluded\n", n)); 1010 deviceExtension->AHCI_PI &= ~((ULONG)1 << n); 1011 deviceExtension->AHCI_PI_mask &= ~((ULONG)1 << n); 1012 //PI_ex_mask |= ((ULONG)1 << n); 1013 } 1014 } 1015 deviceExtension->AHCI_PI_mask = 1016 AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PortMask", deviceExtension->AHCI_PI_mask); 1017 KdPrint2((PRINT_PREFIX "Force PortMask %#x\n", deviceExtension->AHCI_PI_mask)); 1018 1019 for(i=PI, n=0; i; n++, i=i>>1); 1020 NumberChannels = 1021 max((CAP & AHCI_CAP_NOP_MASK)+1, n); 1022 1023 if(!PI && ((CAP & AHCI_CAP_NOP_MASK)+1)) { 1024 /* Enable ports. 1025 * The spec says that BIOS sets up bits corresponding to 1026 * available ports. On platforms where this information 1027 * is missing, the driver can define available ports on its own. 1028 */ 1029 KdPrint2((PRINT_PREFIX "PI=0 -> Enable ports (mask) %#x\n", deviceExtension->AHCI_PI_mask)); 1030 n = NumberChannels; 1031 deviceExtension->AHCI_PI = ((ULONG)1 << n)-1; 1032 1033 if(deviceExtension->AHCI_PI_mask) { 1034 // we have some forced port mask 1035 PI = deviceExtension->AHCI_PI_mask; 1036 } else { 1037 // construct mask 1038 PI = deviceExtension->AHCI_PI = (((ULONG)1 << n)-1); 1039 deviceExtension->AHCI_PI_mask = (((ULONG)1 << n)-1); 1040 } 1041 KdPrint2((PRINT_PREFIX "Enable ports final PI %#x\n", PI)); 1042 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_PI, PI); 1043 } 1044 1045 KdPrint2((PRINT_PREFIX " CommandSlots %d\n", (CAP & AHCI_CAP_NCS_MASK)>>8 )); 1046 KdPrint2((PRINT_PREFIX " Detected Channels %d / %d\n", NumberChannels, n)); 1047 1048 switch(deviceExtension->DevID) { 1049 case 0x2361197b: 1050 KdPrint2((PRINT_PREFIX " JMicron JMB361 -> 1\n")); 1051 NumberChannels = 1; 1052 break; 1053 case ATA_M88SE6111: 1054 KdPrint2((PRINT_PREFIX " Marvell M88SE6111 -> 1\n")); 1055 NumberChannels = 1; 1056 break; 1057 case ATA_M88SE6121: 1058 KdPrint2((PRINT_PREFIX " Marvell M88SE6121 -> 2\n")); 1059 NumberChannels = min(NumberChannels, 2); 1060 break; 1061 case ATA_M88SE6141: 1062 case ATA_M88SE6145: 1063 case ATA_M88SE9123: 1064 KdPrint2((PRINT_PREFIX " Marvell M88SE614x/9123 -> 4\n")); 1065 NumberChannels = min(NumberChannels, 4); 1066 break; 1067 } // switch() 1068 1069 if(!NumberChannels) { 1070 KdPrint2((PRINT_PREFIX " Non-AHCI - NumberChannels=0\n")); 1071 found = FALSE; 1072 goto exit_detect; 1073 } 1074 KdPrint2((PRINT_PREFIX " Adjusted Channels %d\n", NumberChannels)); 1075 1076 #ifdef _DEBUG 1077 v_Mj = ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f); 1078 v_Mn = ((version >> 4) & 0xf0) + (version & 0x0f); 1079 1080 KdPrint2((PRINT_PREFIX " AHCI version %#x.%02x controller with %d ports (mask %#x) detected\n", 1081 v_Mj, v_Mn, 1082 NumberChannels, PI)); 1083 KdPrint((" AHCI SATA Gen %d\n", (((CAP & AHCI_CAP_ISS_MASK) >> 20)) )); 1084 #endif //_DEBUG 1085 1086 if(CAP & AHCI_CAP_SPM) { 1087 KdPrint2((PRINT_PREFIX " PM supported\n")); 1088 if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"IgnoreAhciPM", 1 /* DEBUG */)) { 1089 KdPrint2((PRINT_PREFIX "SATA/AHCI w/o PM, max luns 1\n")); 1090 deviceExtension->NumberLuns = 1; 1091 //chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE; 1092 } else { 1093 KdPrint2((PRINT_PREFIX "SATA/AHCI -> possible PM, max luns %d\n", SATA_MAX_PM_UNITS)); 1094 deviceExtension->NumberLuns = SATA_MAX_PM_UNITS; 1095 //deviceExtension->NumberLuns = 1; 1096 } 1097 } else { 1098 KdPrint2((PRINT_PREFIX " PM not supported -> 1 lun/chan\n")); 1099 deviceExtension->NumberLuns = 1; 1100 } 1101 1102 if(!UniAtaAhciValidateVersion(deviceExtension, version, TRUE)) { 1103 goto exit_detect; 1104 } 1105 1106 deviceExtension->HwFlags |= UNIATA_SATA | UNIATA_AHCI; 1107 if(deviceExtension->NumberChannels < NumberChannels) { 1108 deviceExtension->NumberChannels = NumberChannels; 1109 } 1110 deviceExtension->DmaSegmentLength = 0x3fffff+1; // 4MB 1111 deviceExtension->DmaSegmentAlignmentMask = -1; // no restrictions 1112 1113 deviceExtension->BusMaster = DMA_MODE_AHCI; 1114 deviceExtension->MaxTransferMode = max(deviceExtension->MaxTransferMode, ATA_SA150+(((CAP & AHCI_CAP_ISS_MASK) >> 20)-1) ); 1115 1116 found = TRUE; 1117 1118 exit_detect: 1119 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC, GHC0); 1120 KdPrint((" AHCI detect status %d\n", found)); 1121 1122 return found; 1123 } // end UniataAhciDetect() 1124 1125 UCHAR 1126 NTAPI 1127 UniataAhciStatus( 1128 IN PVOID HwDeviceExtension, 1129 IN ULONG lChannel, 1130 IN ULONG DeviceNumber 1131 ) 1132 { 1133 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1134 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1135 ULONG Channel = deviceExtension->Channel + lChannel; 1136 ULONG hIS; 1137 ULONG CI, ACT; 1138 AHCI_IS_REG IS; 1139 SATA_SSTATUS_REG SStatus; 1140 SATA_SERROR_REG SError; 1141 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); 1142 ULONG tag=0; 1143 1144 KdPrint(("UniataAhciStatus(%d-%d):\n", lChannel, Channel)); 1145 1146 hIS = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_IS); 1147 KdPrint((" hIS %#x\n", hIS)); 1148 hIS &= (1 << Channel); 1149 if(!hIS) { 1150 return INTERRUPT_REASON_IGNORE; 1151 } 1152 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); 1153 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); 1154 ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT); 1155 SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus); 1156 SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); 1157 1158 /* clear interrupt(s) */ 1159 UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_IS, hIS); 1160 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg); 1161 AtapiWritePort4(chan, IDX_SATA_SError, SError.Reg); 1162 1163 KdPrint((" AHCI: is=%08x ss=%08x serror=%08x CI=%08x, ACT=%08x\n", 1164 IS.Reg, SStatus.Reg, SError.Reg, CI, ACT)); 1165 1166 /* do we have cold connect surprise */ 1167 if(IS.CPDS) { 1168 } 1169 1170 /* check for and handle connect events */ 1171 if(IS.PCS) { 1172 UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH); 1173 } 1174 if(IS.PRCS) { 1175 UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH); 1176 } 1177 chan->AhciCompleteCI = (chan->AhciPrevCI ^ CI) & chan->AhciPrevCI; // only 1->0 states 1178 chan->AhciPrevCI = CI; 1179 chan->AhciLastSError = SError.Reg; 1180 KdPrint((" AHCI: complete mask %#x\n", chan->AhciCompleteCI)); 1181 chan->AhciLastIS = IS.Reg; 1182 if(CI & (1 << tag)) { 1183 #ifdef _DEBUG 1184 UniataDumpAhciPortRegs(chan); 1185 #endif //_DEBUG 1186 //deviceExtension->ExpectingInterrupt++; // will be updated in ISR on ReturnEnableInterrupts 1187 if(IS.Reg & 1188 (ATA_AHCI_P_IX_OF | ATA_AHCI_P_IX_INF | ATA_AHCI_P_IX_IF | 1189 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_HBF | ATA_AHCI_P_IX_TFE)) { 1190 KdPrint((" AHCI: unexpected, error\n")); 1191 } else { 1192 KdPrint((" AHCI: unexpected, incomplete command or error ?\n")); 1193 /* 1194 ULONG TFD; 1195 1196 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1197 KdPrint2((" TFD %#x\n", TFD)); 1198 if(TFD & IDE_STATUS_BUSY) { 1199 KdPrint2((" Seems to be interrupt on error\n")); 1200 return INTERRUPT_REASON_OUR; 1201 } 1202 */ 1203 return INTERRUPT_REASON_UNEXPECTED; 1204 } 1205 } 1206 return INTERRUPT_REASON_OUR; 1207 1208 } // end UniataAhciStatus() 1209 1210 VOID 1211 NTAPI 1212 UniataAhciSnapAtaRegs( 1213 IN PHW_CHANNEL chan, 1214 IN ULONG DeviceNumber, 1215 IN OUT PIDEREGS_EX regs 1216 ) 1217 { 1218 ULONG TFD, SIG; 1219 1220 regs->bDriveHeadReg = IDE_DRIVE_SELECT_1; 1221 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1222 regs->bCommandReg = (UCHAR)(TFD & 0xff); 1223 regs->bFeaturesReg = (UCHAR)((TFD >> 8) & 0xff); 1224 1225 SIG = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG); 1226 regs->bSectorCountReg = (UCHAR)(SIG & 0xff); 1227 regs->bSectorNumberReg = (UCHAR)((SIG >> 8) & 0xff); 1228 regs->bCylLowReg = (UCHAR)((SIG >> 16) & 0xff); 1229 regs->bCylHighReg = (UCHAR)((SIG >> 24) & 0xff); 1230 regs->bOpFlags = 0; 1231 1232 return; 1233 } // end UniataAhciSnapAtaRegs() 1234 1235 ULONG 1236 NTAPI 1237 UniataAhciSetupFIS_H2D( 1238 IN PHW_DEVICE_EXTENSION deviceExtension, 1239 IN ULONG DeviceNumber, 1240 IN ULONG lChannel, 1241 OUT PUCHAR fis, 1242 IN UCHAR command, 1243 IN ULONGLONG lba, 1244 IN USHORT count, 1245 IN USHORT feature 1246 ) 1247 { 1248 //ULONG i; 1249 PUCHAR plba; 1250 BOOLEAN need48; 1251 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1252 1253 KdPrint2((PRINT_PREFIX " AHCI setup FIS %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber)); 1254 //i = 0; 1255 plba = (PUCHAR)&lba; 1256 1257 RtlZeroMemory(fis, 20); 1258 1259 fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */ 1260 fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */ 1261 fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 | 1262 ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0); 1263 fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT; 1264 1265 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command, 1266 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET 1267 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) && 1268 */ 1269 command == IDE_COMMAND_ATAPI_PACKET) { 1270 fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET; 1271 if(feature & ATA_F_DMA) { 1272 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff); 1273 } else { 1274 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff); 1275 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff; 1276 } 1277 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT; 1278 } else { 1279 1280 if(((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp|ATA_CMD_FLAG_FUA)) == ATA_CMD_FLAG_LBAIOsupp) && 1281 CheckIfBadBlock(chan->lun[DeviceNumber], lba, count)) { 1282 KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count)); 1283 return 0; 1284 } 1285 1286 need48 = UniAta_need_lba48(command, lba, count, 1287 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48); 1288 1289 /* translate command into 48bit version */ 1290 if(need48) { 1291 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { 1292 command = AtaCommands48[command]; 1293 } else { 1294 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n")); 1295 return 0; 1296 } 1297 } 1298 1299 fis[IDX_AHCI_o_Command] = command; 1300 fis[IDX_AHCI_o_Feature] = (UCHAR)feature; 1301 1302 fis[IDX_AHCI_o_BlockNumber] = plba[0]; 1303 fis[IDX_AHCI_o_CylinderLow] = plba[1]; 1304 fis[IDX_AHCI_o_CylinderHigh] = plba[2]; 1305 1306 fis[IDX_AHCI_o_BlockCount] = (UCHAR)count & 0xff; 1307 1308 if(need48) { 1309 //i++; 1310 fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB; 1311 1312 fis[IDX_AHCI_o_BlockNumberExp] = plba[3]; 1313 fis[IDX_AHCI_o_CylinderLowExp] = plba[4]; 1314 fis[IDX_AHCI_o_CylinderHighExp] = plba[5]; 1315 1316 fis[IDX_AHCI_o_BlockCountExp] = (UCHAR)(count>>8) & 0xff; 1317 1318 fis[IDX_AHCI_o_FeatureExp] = (UCHAR)(feature>>8) & 0xff; 1319 1320 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48; 1321 } else { 1322 fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f); 1323 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48; 1324 } 1325 1326 //fis[14] = 0x00; 1327 1328 } 1329 1330 //KdDump(fis, 20); 1331 1332 return 20; 1333 } // end UniataAhciSetupFIS_H2D() 1334 1335 ULONG 1336 NTAPI 1337 UniataAhciSetupFIS_H2D_Direct( 1338 IN PHW_DEVICE_EXTENSION deviceExtension, 1339 IN ULONG DeviceNumber, 1340 IN ULONG lChannel, 1341 OUT PUCHAR fis, 1342 IN PIDEREGS_EX regs 1343 ) 1344 { 1345 //ULONG i; 1346 //PUCHAR plba; 1347 BOOLEAN need48; 1348 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1349 UCHAR command; 1350 1351 command = regs->bCommandReg; 1352 1353 KdPrint2((PRINT_PREFIX " AHCI setup FIS Direct %x, ch %d, dev %d\n", fis, lChannel, DeviceNumber)); 1354 //i = 0; 1355 //plba = (PUCHAR)&lba; 1356 1357 RtlZeroMemory(fis, 20); 1358 1359 fis[0] = AHCI_FIS_TYPE_ATA_H2D; /* host to device */ 1360 fis[1] = 0x80 | ((UCHAR)DeviceNumber & 0x0f); /* command FIS (note PM goes here) */ 1361 fis[IDX_AHCI_o_DriveSelect] = IDE_DRIVE_SELECT_1 | 1362 ((AtaCommandFlags[command] & (ATA_CMD_FLAG_LBAIOsupp | ATA_CMD_FLAG_48)) ? IDE_USE_LBA : 0); 1363 fis[IDX_AHCI_o_Control] = IDE_DC_A_4BIT; 1364 1365 // IDE_COMMAND_ATAPI_IDENTIFY should be processed as regular ATA command, 1366 // the rest of ATAPI requests are processed via IDE_COMMAND_ATAPI_PACKET 1367 if(/*(chan->lun[DeviceNumber]->DeviceFlags & DFLAGS_ATAPI_DEVICE) && 1368 */ 1369 command == IDE_COMMAND_ATAPI_PACKET) { 1370 /* fis[IDX_AHCI_o_Command] = IDE_COMMAND_ATAPI_PACKET; 1371 if(feature & ATA_F_DMA) { 1372 fis[IDX_AHCI_o_Feature] = (UCHAR)(feature & 0xff); 1373 } else { 1374 fis[IDX_AHCI_o_CylinderLow] = (UCHAR)(count & 0xff); 1375 fis[IDX_AHCI_o_CylinderHigh] = (UCHAR)(count>>8) & 0xff; 1376 }*/ 1377 return 0; 1378 //fis[IDX_AHCI_o_Control] |= IDE_DC_A_4BIT; 1379 } else { 1380 1381 need48 = (regs->bOpFlags & ATA_FLAGS_48BIT_COMMAND) && 1382 chan->lun[DeviceNumber]->IdentifyData.FeaturesSupport.Address48; 1383 1384 /* translate command into 48bit version */ 1385 if(need48) { 1386 if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { 1387 command = AtaCommands48[command]; 1388 } else { 1389 KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n")); 1390 return 0; 1391 } 1392 } 1393 1394 fis[IDX_AHCI_o_Command] = command; 1395 fis[IDX_AHCI_o_Feature] = regs->bFeaturesReg; 1396 1397 fis[IDX_AHCI_o_BlockNumber] = regs->bSectorNumberReg; 1398 fis[IDX_AHCI_o_CylinderLow] = regs->bCylLowReg; 1399 fis[IDX_AHCI_o_CylinderHigh] = regs->bCylHighReg; 1400 1401 fis[IDX_AHCI_o_BlockCount] = regs->bSectorCountReg; 1402 1403 if(need48) { 1404 //i++; 1405 fis[IDX_AHCI_o_Control] |= IDE_DC_USE_HOB; 1406 1407 fis[IDX_AHCI_o_BlockNumberExp] = regs->bSectorNumberRegH; 1408 fis[IDX_AHCI_o_CylinderLowExp] = regs->bCylLowRegH; 1409 fis[IDX_AHCI_o_CylinderHighExp] = regs->bCylHighRegH; 1410 1411 fis[IDX_AHCI_o_BlockCountExp] = regs->bSectorCountRegH; 1412 1413 fis[IDX_AHCI_o_FeatureExp] = regs->bFeaturesRegH; 1414 1415 chan->ChannelCtrlFlags |= CTRFLAGS_LBA48; 1416 } else { 1417 //fis[IDX_AHCI_o_DriveSelect] |= /*IDE_DRIVE_1 |*/ (plba[3] & 0x0f); 1418 chan->ChannelCtrlFlags &= ~CTRFLAGS_LBA48; 1419 } 1420 fis[IDX_AHCI_o_DriveSelect] |= regs->bDriveHeadReg & 0x0f; 1421 } 1422 1423 KdDump(fis, 20); 1424 1425 return 20; 1426 } // end UniataAhciSetupFIS_H2D_Direct() 1427 1428 UCHAR 1429 NTAPI 1430 UniataAhciWaitCommandReady( 1431 IN PHW_CHANNEL chan, 1432 IN ULONG timeout 1433 ) 1434 { 1435 AHCI_IS_REG IS; 1436 //ULONG ACT; 1437 ULONG CI=0; 1438 ULONG i; 1439 ULONG SError; 1440 ULONG tag=0; 1441 1442 timeout *= 5; 1443 1444 for (i=0; i<timeout; i++) { 1445 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); 1446 //ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT); 1447 if (!(( CI >> tag) & 0x01)) { 1448 break; 1449 } 1450 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); 1451 //KdPrint((" IS %#x\n", IS.Reg)); 1452 if(IS.Reg) { 1453 break; 1454 } 1455 SError = AtapiReadPort4(chan, IDX_SATA_SError); 1456 if(SError) { 1457 KdPrint((" AHCI: error %#x\n", SError)); 1458 i = timeout; 1459 break; 1460 } 1461 AtapiStallExecution(200); 1462 } 1463 KdPrint((" CI %#x\n", CI)); 1464 1465 //SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus); 1466 //SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); 1467 1468 /* clear interrupt(s) */ 1469 IS.Reg = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); 1470 KdPrint((" IS %#x\n", IS.Reg)); 1471 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS.Reg); 1472 1473 if (timeout && (i >= timeout)) { 1474 #ifdef _DEBUG 1475 ULONG TFD; 1476 1477 SError = AtapiReadPort4(chan, IDX_SATA_SError); 1478 KdPrint((" AHCI: timeout, SError %#x\n", SError)); 1479 1480 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1481 KdPrint2((" TFD %#x\n", TFD)); 1482 #endif //_DEBUG 1483 1484 return IDE_STATUS_WRONG; 1485 } 1486 1487 return IDE_STATUS_IDLE; 1488 } // end UniataAhciWaitCommandReady() 1489 1490 UCHAR 1491 NTAPI 1492 UniataAhciSendCommand( 1493 IN PVOID HwDeviceExtension, 1494 IN ULONG lChannel, 1495 IN ULONG DeviceNumber, 1496 IN USHORT ahci_flags, 1497 IN ULONG timeout 1498 ) 1499 { 1500 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1501 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1502 //ULONG Channel = deviceExtension->Channel + lChannel; 1503 //ULONG hIS; 1504 //ULONG SError; 1505 //SATA_SSTATUS_REG SStatus; 1506 //SATA_SERROR_REG SError; 1507 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); 1508 //ULONGIO_PTR base; 1509 ULONG tag=0; 1510 1511 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 1512 1513 KdPrint(("UniataAhciSendCommand: lChan %d\n", chan->lChannel)); 1514 1515 AHCI_CL->prd_length = 0; 1516 //AHCI_CL->cmd_flags = (20 / sizeof(ULONG)) | ahci_flags | (DeviceNumber << 12); 1517 AHCI_CL->cmd_flags = UniAtaAhciAdjustIoFlags(0, ahci_flags, 20, DeviceNumber); 1518 1519 AHCI_CL->bytecount = 0; 1520 AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd); 1521 if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) { 1522 KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK)); 1523 } 1524 1525 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag); 1526 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 1 << tag); 1527 1528 return UniataAhciWaitCommandReady(chan, timeout); 1529 1530 } // end UniataAhciSendCommand() 1531 1532 UCHAR 1533 NTAPI 1534 UniataAhciSendPIOCommand( 1535 IN PVOID HwDeviceExtension, 1536 IN ULONG lChannel, 1537 IN ULONG DeviceNumber, 1538 IN PSCSI_REQUEST_BLOCK Srb, 1539 IN PUCHAR data, 1540 IN ULONG length, /* bytes */ 1541 IN UCHAR command, 1542 IN ULONGLONG lba, 1543 IN USHORT bcount, /* block count, just ATA register */ 1544 IN USHORT feature, 1545 IN USHORT ahci_flags, 1546 IN ULONG wait_flags, 1547 IN ULONG timeout 1548 ) 1549 { 1550 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1551 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1552 UCHAR statusByte; 1553 PATA_REQ AtaReq; 1554 ULONG fis_size; 1555 //ULONG tag=0; 1556 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 1557 PIDE_AHCI_CMD AHCI_CMD = NULL; 1558 1559 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 1560 1561 KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, cmd %#x, lba %#I64x bcount %#x feature %#x, buff %#x, len %#x, WF %#x \n", 1562 deviceExtension->DevIndex, lChannel, DeviceNumber, command, lba, bcount, feature, data, length, wait_flags )); 1563 1564 if(length/DEV_BSIZE != bcount) { 1565 KdPrint((" length/DEV_BSIZE != bcount\n")); 1566 } 1567 1568 #ifdef _DEBUG 1569 //UniataDumpAhciPortRegs(chan); 1570 #endif // _DEBUG 1571 1572 if(!Srb) { 1573 Srb = BuildAhciInternalSrb(HwDeviceExtension, DeviceNumber, lChannel, data, length); 1574 if(!Srb) { 1575 KdPrint((" !Srb\n")); 1576 return IDE_STATUS_WRONG; 1577 } 1578 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup 1579 //should be already called on init 1580 } 1581 AtaReq = (PATA_REQ)(Srb->SrbExtension); 1582 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq)); 1583 1584 AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr; 1585 1586 fis_size = UniataAhciSetupFIS_H2D(deviceExtension, DeviceNumber, lChannel, 1587 &(AHCI_CMD->cfis[0]), 1588 command, 1589 lba, 1590 bcount, 1591 feature 1592 ); 1593 1594 if(!fis_size) { 1595 KdPrint2(("!fis_size\n")); 1596 return IDE_STATUS_WRONG; 1597 } 1598 1599 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n")); 1600 ahci_flags = UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber); 1601 KdPrint2(("ahci_flags %#x\n", ahci_flags)); 1602 1603 if(data) { 1604 if(ahci_flags & ATA_AHCI_CMD_WRITE) { 1605 AtaReq->Flags &= ~REQ_FLAG_READ; 1606 Srb->SrbFlags |= SRB_FLAGS_DATA_OUT; 1607 KdPrint((" assume OUT\n")); 1608 } else { 1609 AtaReq->Flags |= REQ_FLAG_READ; 1610 Srb->SrbFlags |= SRB_FLAGS_DATA_IN; 1611 KdPrint((" assume IN\n")); 1612 } 1613 if(!AtapiDmaSetup(HwDeviceExtension, 1614 DeviceNumber, 1615 lChannel, // logical channel, 1616 Srb, 1617 data, 1618 length)) { 1619 KdPrint2((" can't setup buffer\n")); 1620 return IDE_STATUS_WRONG; 1621 } 1622 } 1623 1624 AtaReq->ahci.io_cmd_flags = ahci_flags; 1625 1626 #ifdef _DEBUG 1627 //UniataDumpAhciPortRegs(chan); 1628 #endif // _DEBUG 1629 1630 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 1631 1632 #ifdef _DEBUG 1633 //UniataDumpAhciPortRegs(chan); 1634 #endif // _DEBUG 1635 1636 if(wait_flags == ATA_IMMEDIATE) { 1637 statusByte = 0; 1638 KdPrint2((" return imemdiately\n")); 1639 } else { 1640 statusByte = UniataAhciWaitCommandReady(chan, timeout); 1641 UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber); 1642 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 1643 } 1644 1645 return statusByte; 1646 1647 } // end UniataAhciSendPIOCommand() 1648 1649 UCHAR 1650 NTAPI 1651 UniataAhciSendPIOCommandDirect( 1652 IN PVOID HwDeviceExtension, 1653 IN ULONG lChannel, 1654 IN ULONG DeviceNumber, 1655 IN PSCSI_REQUEST_BLOCK Srb, 1656 IN PIDEREGS_EX regs, 1657 IN ULONG wait_flags, 1658 IN ULONG timeout 1659 ) 1660 { 1661 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1662 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1663 UCHAR statusByte; 1664 PATA_REQ AtaReq; 1665 ULONG fis_size; 1666 //ULONG tag=0; 1667 //PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 1668 PIDE_AHCI_CMD AHCI_CMD = NULL; 1669 USHORT ahci_flags=0; 1670 // USHORT bcount=0; 1671 1672 //PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 1673 1674 KdPrint2((PRINT_PREFIX "UniataAhciSendPIOCommand: cntrlr %#x:%#x dev %#x, buff %#x, len %#x, WF %#x \n", 1675 deviceExtension->DevIndex, lChannel, DeviceNumber, Srb->DataBuffer, Srb->DataTransferLength, wait_flags )); 1676 1677 // if(Srb->DataTransferLength/DEV_BSIZE != bcount) { 1678 // KdPrint((" length/DEV_BSIZE != bcount\n")); 1679 // } 1680 1681 #ifdef _DEBUG 1682 //UniataDumpAhciPortRegs(chan); 1683 #endif // _DEBUG 1684 1685 if(!Srb) { 1686 KdPrint((" !Srb\n")); 1687 return IDE_STATUS_WRONG; 1688 //UniataAhciSetupCmdPtr(AtaReq); // must be called before DMA setup 1689 //should be already called on init 1690 } 1691 AtaReq = (PATA_REQ)(Srb->SrbExtension); 1692 //KdPrint((" Srb %#x, AtaReq %#x\n", Srb, AtaReq)); 1693 1694 AHCI_CMD = AtaReq->ahci.ahci_cmd_ptr; 1695 if(!AHCI_CMD) { 1696 KdPrint((" !AHCI_CMD\n")); 1697 return IDE_STATUS_WRONG; 1698 } 1699 1700 if(Srb->DataTransferLength) { 1701 if(Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { 1702 ahci_flags |= ATA_AHCI_CMD_WRITE; 1703 AtaReq->Flags &= ~REQ_FLAG_READ; 1704 } else { 1705 AtaReq->Flags |= REQ_FLAG_READ; 1706 } 1707 } 1708 1709 fis_size = UniataAhciSetupFIS_H2D_Direct(deviceExtension, DeviceNumber, lChannel, 1710 &(AHCI_CMD->cfis[0]), 1711 regs); 1712 1713 if(!fis_size) { 1714 KdPrint2(("!fis_size\n")); 1715 return IDE_STATUS_WRONG; 1716 } 1717 1718 //KdPrint2(("UniAtaAhciAdjustIoFlags(command, ahci_flags, fis_size, DeviceNumber)\n")); 1719 ahci_flags = UniAtaAhciAdjustIoFlags(regs->bCommandReg, ahci_flags, fis_size, DeviceNumber); 1720 KdPrint2(("ahci_flags %#x\n", ahci_flags)); 1721 1722 if(Srb->DataTransferLength) { 1723 if(!AtapiDmaSetup(HwDeviceExtension, 1724 DeviceNumber, 1725 lChannel, // logical channel, 1726 Srb, 1727 (PUCHAR)(Srb->DataBuffer), 1728 Srb->DataTransferLength)) { 1729 KdPrint2((" can't setup buffer\n")); 1730 return IDE_STATUS_WRONG; 1731 } 1732 } 1733 1734 AtaReq->ahci.io_cmd_flags = ahci_flags; 1735 1736 #ifdef _DEBUG 1737 //UniataDumpAhciPortRegs(chan); 1738 #endif // _DEBUG 1739 1740 UniataAhciBeginTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 1741 1742 #ifdef _DEBUG 1743 //UniataDumpAhciPortRegs(chan); 1744 #endif // _DEBUG 1745 1746 if(wait_flags == ATA_IMMEDIATE) { 1747 statusByte = 0; 1748 KdPrint2((" return imemdiately\n")); 1749 } else { 1750 statusByte = UniataAhciWaitCommandReady(chan, timeout); 1751 UniataAhciStatus(HwDeviceExtension, lChannel, DeviceNumber); 1752 UniataAhciEndTransaction(HwDeviceExtension, lChannel, DeviceNumber, Srb); 1753 } 1754 1755 return statusByte; 1756 1757 } // end UniataAhciSendPIOCommandDirect() 1758 1759 BOOLEAN 1760 NTAPI 1761 UniataAhciAbortOperation( 1762 IN PHW_CHANNEL chan 1763 ) 1764 { 1765 /* kick controller into sane state */ 1766 if(!UniataAhciStop(chan)) { 1767 return FALSE; 1768 } 1769 if(!UniataAhciStopFR(chan)) { 1770 return FALSE; 1771 } 1772 if(!UniataAhciCLO(chan)) { 1773 return FALSE; 1774 } 1775 UniataAhciStartFR(chan); 1776 UniataAhciStart(chan); 1777 1778 return TRUE; 1779 } // end UniataAhciAbortOperation() 1780 1781 ULONG 1782 NTAPI 1783 UniataAhciSoftReset( 1784 IN PVOID HwDeviceExtension, 1785 IN ULONG lChannel, 1786 IN ULONG DeviceNumber 1787 ) 1788 { 1789 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1790 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1791 //ULONG Channel = deviceExtension->Channel + lChannel; 1792 //ULONG hIS; 1793 //ULONG CI; 1794 //AHCI_IS_REG IS; 1795 //ULONG tag=0; 1796 1797 KdPrint(("UniataAhciSoftReset: lChan %d\n", chan->lChannel)); 1798 1799 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 1800 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); 1801 1802 /* kick controller into sane state */ 1803 if(!UniataAhciAbortOperation(chan)) { 1804 KdPrint2((" abort failed\n")); 1805 return (ULONG)(-1); 1806 } 1807 1808 /* pull reset active */ 1809 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); 1810 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; 1811 AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f; 1812 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT; 1813 AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT | IDE_DC_RESET_CONTROLLER); 1814 1815 if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, ATA_AHCI_CMD_RESET | ATA_AHCI_CMD_CLR_BUSY, 100) == IDE_STATUS_WRONG) { 1816 KdPrint2((" timeout\n")); 1817 return (ULONG)(-1); 1818 } 1819 AtapiStallExecution(50); 1820 1821 /* pull reset inactive */ 1822 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); 1823 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; 1824 AHCI_CMD->cfis[1] = (UCHAR)DeviceNumber & 0x0f; 1825 //AHCI_CMD->cfis[7] = IDE_USE_LBA | IDE_DRIVE_SELECT; 1826 AHCI_CMD->cfis[15] = (IDE_DC_A_4BIT); 1827 if(UniataAhciSendCommand(HwDeviceExtension, lChannel, DeviceNumber, 0, 3000) == IDE_STATUS_WRONG) { 1828 KdPrint2((" timeout (2)\n")); 1829 return (ULONG)(-1); 1830 } 1831 1832 UniataAhciWaitReady(chan, 1); 1833 1834 KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis)); 1835 1836 if(deviceExtension->HwFlags & UNIATA_AHCI_ALT_SIG) { 1837 ULONG signature; 1838 signature = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG); 1839 KdPrint((" alt sig: %#x\n", signature)); 1840 return signature; 1841 } 1842 1843 return UniataAhciUlongFromRFIS(RCV_FIS); 1844 1845 } // end UniataAhciSoftReset() 1846 1847 ULONG 1848 NTAPI 1849 UniataAhciWaitReady( 1850 IN PHW_CHANNEL chan, 1851 IN ULONG timeout 1852 ) 1853 { 1854 ULONG TFD; 1855 ULONG i; 1856 1857 KdPrint2(("UniataAhciWaitReady: lChan %d\n", chan->lChannel)); 1858 1859 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs); 1860 1861 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1862 for(i=0; i<timeout && (TFD & 1863 (IDE_STATUS_DRQ | IDE_STATUS_BUSY)); i++) { 1864 AtapiStallExecution(1000); 1865 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 1866 } 1867 1868 KdPrint2((" TFD %#x\n", TFD)); 1869 1870 return TFD; 1871 1872 } // end UniataAhciWaitReady() 1873 1874 ULONG 1875 NTAPI 1876 UniataAhciHardReset( 1877 IN PVOID HwDeviceExtension, 1878 IN ULONG lChannel, 1879 OUT PULONG signature 1880 ) 1881 { 1882 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1883 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1884 //ULONG Channel = deviceExtension->Channel + lChannel; 1885 ULONG TFD; 1886 1887 1888 KdPrint(("UniataAhciHardReset: lChan %d\n", chan->lChannel)); 1889 1890 (*signature) = 0xffffffff; 1891 1892 UniataAhciStop(chan); 1893 if(UniataSataPhyEnable(HwDeviceExtension, lChannel, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE) == IDE_STATUS_WRONG) { 1894 KdPrint((" no PHY\n")); 1895 return IDE_STATUS_WRONG; 1896 } 1897 1898 /* Wait for clearing busy status. */ 1899 TFD = UniataAhciWaitReady(chan, 15000); 1900 if(TFD & (IDE_STATUS_DRQ | IDE_STATUS_BUSY)) { 1901 KdPrint((" busy: TFD %#x\n", TFD)); 1902 return TFD; 1903 } 1904 KdPrint((" TFD %#x\n", TFD)); 1905 1906 #ifdef _DEBUG 1907 UniataDumpAhciPortRegs(chan); 1908 #endif // _DEBUG 1909 1910 (*signature) = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG); 1911 KdPrint((" sig: %#x\n", *signature)); 1912 1913 UniataAhciStart(chan); 1914 1915 return 0; 1916 1917 } // end UniataAhciHardReset() 1918 1919 VOID 1920 NTAPI 1921 UniataAhciReset( 1922 IN PVOID HwDeviceExtension, 1923 IN ULONG lChannel 1924 ) 1925 { 1926 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 1927 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 1928 //ULONG Channel = deviceExtension->Channel + lChannel; 1929 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); 1930 ULONG CAP; 1931 //ULONGIO_PTR base; 1932 ULONG signature; 1933 ULONG i; 1934 ULONG VendorID = deviceExtension->DevID & 0xffff; 1935 1936 KdPrint(("UniataAhciReset: lChan %d\n", chan->lChannel)); 1937 1938 //base = (ULONGIO_PTR)(&deviceExtension->BaseIoAHCI_0 + offs); 1939 1940 /* Disable port interrupts */ 1941 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); 1942 1943 if(UniataAhciHardReset(HwDeviceExtension, lChannel, &signature)) { 1944 1945 KdPrint((" No devices in all LUNs\n")); 1946 for (i=0; i<deviceExtension->NumberLuns; i++) { 1947 // Zero device fields to ensure that if earlier devices were found, 1948 // but not claimed, the fields are cleared. 1949 UniataForgetDevice(chan->lun[i]); 1950 } 1951 1952 /* enable wanted port interrupts */ 1953 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 1954 ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC); 1955 return; 1956 } 1957 1958 /* enable wanted port interrupts */ 1959 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 1960 (ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF | 1961 ATA_AHCI_P_IX_HBD | ATA_AHCI_P_IX_IF | ATA_AHCI_P_IX_OF | 1962 ((/*ch->pm_level == */0) ? (ATA_AHCI_P_IX_PRC | ATA_AHCI_P_IX_PC) : 0) | 1963 ATA_AHCI_P_IX_DP | ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | 1964 ATA_AHCI_P_IX_DS | ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR) ); 1965 1966 /* 1967 * Only probe for PortMultiplier if HW has support. 1968 * Ignore Marvell, which is not working, 1969 */ 1970 CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); 1971 if ((CAP & AHCI_CAP_SPM) && 1972 (VendorID != ATA_MARVELL_ID)) { 1973 KdPrint((" check PM\n")); 1974 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, AHCI_DEV_SEL_PM); 1975 /* Workaround for some ATI chips, failing to soft-reset 1976 * when port multiplicator supported, but absent. 1977 * XXX: We can also check PxIS.IPMS==1 here to be sure. */ 1978 if (signature == 0xffffffff) { 1979 KdPrint((" re-check PM\n")); 1980 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0); 1981 } 1982 } else { 1983 signature = UniataAhciSoftReset(HwDeviceExtension, lChannel, 0); 1984 } 1985 1986 KdPrint((" signature %#x\n", signature)); 1987 chan->lun[0]->DeviceFlags &= ~(DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT | CTRFLAGS_AHCI_PM); 1988 switch (signature >> 16) { 1989 case 0x0000: 1990 KdPrint((" ATA dev\n")); 1991 chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT; 1992 chan->PmLunMap = 0; 1993 break; 1994 case 0x9669: 1995 KdPrint((" PM\n")); 1996 if(deviceExtension->NumberLuns > 1) { 1997 chan->ChannelCtrlFlags |= CTRFLAGS_AHCI_PM; 1998 UniataSataIdentifyPM(chan); 1999 } else { 2000 KdPrint((" no PM supported (1 lun/chan)\n")); 2001 } 2002 break; 2003 case 0xeb14: 2004 KdPrint((" ATAPI dev\n")); 2005 chan->lun[0]->DeviceFlags |= (DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT); 2006 chan->PmLunMap = 0; 2007 break; 2008 default: /* SOS XXX */ 2009 KdPrint((" default to ATA ???\n")); 2010 chan->lun[0]->DeviceFlags |= DFLAGS_DEVICE_PRESENT; 2011 chan->PmLunMap = 0; 2012 } 2013 2014 return; 2015 2016 } // end UniataAhciReset() 2017 2018 VOID 2019 NTAPI 2020 UniataAhciStartFR( 2021 IN PHW_CHANNEL chan 2022 ) 2023 { 2024 ULONG CMD; 2025 2026 KdPrint2(("UniataAhciStartFR: lChan %d\n", chan->lChannel)); 2027 2028 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2029 KdPrint2((" CMD %#x\n", CMD)); 2030 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD | ATA_AHCI_P_CMD_FRE); 2031 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2032 2033 return; 2034 } // end UniataAhciStartFR() 2035 2036 BOOLEAN 2037 NTAPI 2038 UniataAhciStopFR( 2039 IN PHW_CHANNEL chan 2040 ) 2041 { 2042 ULONG CMD; 2043 ULONG i; 2044 2045 KdPrint2(("UniataAhciStopFR: lChan %d\n", chan->lChannel)); 2046 2047 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2048 KdPrint2((" CMD %#x\n", CMD)); 2049 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD & ~ATA_AHCI_P_CMD_FRE); 2050 2051 for(i=0; i<1000; i++) { 2052 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2053 if(!(CMD & ATA_AHCI_P_CMD_FR)) { 2054 KdPrint2((" final CMD %#x\n", CMD)); 2055 return TRUE; 2056 } 2057 AtapiStallExecution(1000); 2058 } 2059 KdPrint2((" CMD %#x\n", CMD)); 2060 KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError))); 2061 KdPrint2(("UniataAhciStopFR: timeout\n")); 2062 return FALSE; 2063 } // end UniataAhciStopFR() 2064 2065 VOID 2066 NTAPI 2067 UniataAhciStart( 2068 IN PHW_CHANNEL chan 2069 ) 2070 { 2071 ULONG IS, CMD; 2072 SATA_SERROR_REG SError; 2073 2074 KdPrint2(("UniataAhciStart: lChan %d\n", chan->lChannel)); 2075 2076 /* clear SATA error register */ 2077 SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); 2078 2079 /* clear any interrupts pending on this channel */ 2080 IS = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_IS); 2081 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IS, IS); 2082 2083 KdPrint2((" SError %#x, IS %#x\n", SError.Reg, IS)); 2084 2085 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2086 KdPrint2((" CMD %#x\n", CMD)); 2087 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 2088 CMD | 2089 ATA_AHCI_P_CMD_ST | 2090 ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0)); 2091 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2092 2093 return; 2094 } // end UniataAhciStart() 2095 2096 BOOLEAN 2097 NTAPI 2098 UniataAhciCLO( 2099 IN PHW_CHANNEL chan 2100 ) 2101 { 2102 //PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2103 //PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 2104 ULONG CAP, CMD; 2105 //SATA_SERROR_REG SError; 2106 ULONG i; 2107 2108 KdPrint2(("UniataAhciCLO: lChan %d\n", chan->lChannel)); 2109 2110 /* issue Command List Override if supported */ 2111 //CAP = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_CAP); 2112 CAP = chan->DeviceExtension->AHCI_CAP; 2113 if(!(CAP & AHCI_CAP_SCLO)) { 2114 return TRUE; 2115 } 2116 KdPrint2((" send CLO\n")); 2117 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2118 CMD |= ATA_AHCI_P_CMD_CLO; 2119 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); 2120 2121 for(i=0; i<1000; i++) { 2122 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2123 if(!(CMD & ATA_AHCI_P_CMD_CLO)) { 2124 KdPrint2((" final CMD %#x\n", CMD)); 2125 return TRUE; 2126 } 2127 AtapiStallExecution(1000); 2128 } 2129 KdPrint2((" CMD %#x\n", CMD)); 2130 KdPrint2(("UniataAhciCLO: timeout\n")); 2131 return FALSE; 2132 } // end UniataAhciCLO() 2133 2134 BOOLEAN 2135 NTAPI 2136 UniataAhciStop( 2137 IN PHW_CHANNEL chan 2138 ) 2139 { 2140 ULONG CMD; 2141 //SATA_SERROR_REG SError; 2142 ULONG i; 2143 2144 KdPrint2(("UniataAhciStop: lChan %d\n", chan->lChannel)); 2145 2146 /* issue Command List Override if supported */ 2147 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2148 CMD &= ~ATA_AHCI_P_CMD_ST; 2149 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); 2150 2151 for(i=0; i<1000; i++) { 2152 CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2153 if(!(CMD & ATA_AHCI_P_CMD_CR)) { 2154 KdPrint2((" final CMD %#x\n", CMD)); 2155 return TRUE; 2156 } 2157 AtapiStallExecution(1000); 2158 } 2159 KdPrint2((" CMD %#x\n", CMD)); 2160 KdPrint((" SError %#x\n", AtapiReadPort4(chan, IDX_SATA_SError))); 2161 KdPrint2(("UniataAhciStop: timeout\n")); 2162 return FALSE; 2163 } // end UniataAhciStop() 2164 2165 UCHAR 2166 NTAPI 2167 UniataAhciBeginTransaction( 2168 IN PVOID HwDeviceExtension, 2169 IN ULONG lChannel, 2170 IN ULONG DeviceNumber, 2171 IN PSCSI_REQUEST_BLOCK Srb 2172 ) 2173 { 2174 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2175 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 2176 //ULONG Channel = deviceExtension->Channel + lChannel; 2177 //ULONG hIS; 2178 ULONG CMD, CMD0; 2179 //AHCI_IS_REG IS; 2180 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 2181 //SATA_SSTATUS_REG SStatus; 2182 //SATA_SERROR_REG SError; 2183 //ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); 2184 //ULONGIO_PTR base; 2185 ULONG tag=0; 2186 //ULONG i; 2187 2188 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 2189 2190 KdPrint2(("UniataAhciBeginTransaction: lChan %d, AtaReq %#x\n", chan->lChannel, AtaReq)); 2191 2192 if(Srb->DataTransferLength && (!AtaReq->dma_entries || AtaReq->dma_entries >= (USHORT)0xffff)) { 2193 KdPrint2(("UniataAhciBeginTransaction wrong DMA tab len %x\n", AtaReq->dma_entries)); 2194 return 0; 2195 } 2196 2197 AHCI_CL->prd_length = (USHORT)(AtaReq->dma_entries); 2198 AHCI_CL->cmd_flags = AtaReq->ahci.io_cmd_flags; 2199 AHCI_CL->bytecount = 0; 2200 if(AtaReq->ahci.ahci_base64) { 2201 KdPrint2((PRINT_PREFIX " AHCI AtaReq CMD %#x (ph %#x)\n", AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64))); 2202 AHCI_CL->cmd_table_phys = AtaReq->ahci.ahci_base64; 2203 } else 2204 if(AtaReq->ahci.ahci_cmd_ptr) { 2205 KdPrint2((PRINT_PREFIX " AHCI AtaReq->Chan CMD %#x (ph %#x) -> %#x (ph %#x)\n", 2206 AtaReq->ahci.ahci_cmd_ptr, (ULONG)(AtaReq->ahci.ahci_base64), 2207 &(chan->AhciCtlBlock->cmd), chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd) )); 2208 RtlCopyMemory(&(chan->AhciCtlBlock->cmd), AtaReq->ahci.ahci_cmd_ptr, 2209 FIELD_OFFSET(IDE_AHCI_CMD, prd_tab)+AHCI_CL->prd_length*sizeof(IDE_AHCI_PRD_ENTRY)); 2210 AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd); 2211 } else { 2212 KdPrint2((PRINT_PREFIX " no AHCI CMD\n")); 2213 //AHCI_CL->cmd_table_phys = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd); 2214 return 0; 2215 } 2216 if(AHCI_CL->cmd_table_phys & AHCI_CMD_ALIGNEMENT_MASK) { 2217 KdPrint2((PRINT_PREFIX " AHCI CMD address is not aligned (mask %#x)\n", (ULONG)AHCI_CMD_ALIGNEMENT_MASK)); 2218 return 0; 2219 } 2220 2221 #ifdef _DEBUG 2222 KdPrint2((" prd_length %#x, flags %#x, base %I64x\n", AHCI_CL->prd_length, AHCI_CL->cmd_flags, 2223 AHCI_CL->cmd_table_phys)); 2224 #endif // _DEBUG 2225 2226 CMD0 = CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); 2227 KdPrint2((" CMD %#x\n", CMD)); 2228 // switch controller to ATAPI mode for ATA_PACKET commands only 2229 if(ATAPI_DEVICE(chan, DeviceNumber) && 2230 AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_PACKET) { 2231 KdPrint2((" ATAPI\n")); 2232 CMD |= ATA_AHCI_P_CMD_ATAPI; 2233 KdDump(&(AtaReq->ahci.ahci_cmd_ptr->acmd), 16); 2234 } else { 2235 CMD &= ~ATA_AHCI_P_CMD_ATAPI; 2236 } 2237 if(CMD0 != CMD) { 2238 KdPrint2((" send CMD %#x, entries %#x\n", CMD, AHCI_CL->prd_length)); 2239 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); 2240 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2241 } 2242 2243 /* issue command to controller */ 2244 //UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag); 2245 KdPrint2((" Set CI\n")); 2246 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 0x01 << tag); 2247 chan->AhciPrevCI |= 0x01 << tag; 2248 2249 CMD0 = CMD; 2250 CMD |= ATA_AHCI_P_CMD_ST | 2251 ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0); 2252 if(CMD != CMD0) { 2253 KdPrint2((" Send CMD START\n")); 2254 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD); 2255 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2256 } else { 2257 KdPrint2((" No CMD START, already active\n")); 2258 } 2259 2260 if(!ATAPI_DEVICE(chan, DeviceNumber)) { 2261 // TODO: check if we send ATAPI_RESET and wait for ready of so. 2262 if(AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_RESET) { 2263 ULONG TFD; 2264 ULONG i; 2265 2266 for(i=0; i<1000000; i++) { 2267 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 2268 if(!(TFD & IDE_STATUS_BUSY)) { 2269 break; 2270 } 2271 } 2272 if(TFD & IDE_STATUS_BUSY) { 2273 KdPrint2((" timeout\n")); 2274 } 2275 if(TFD & IDE_STATUS_ERROR) { 2276 KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8))); 2277 } 2278 AtaReq->ahci.in_status = TFD; 2279 2280 return IDE_STATUS_SUCCESS; 2281 } 2282 } 2283 2284 return IDE_STATUS_IDLE; 2285 2286 } // end UniataAhciBeginTransaction() 2287 2288 UCHAR 2289 NTAPI 2290 UniataAhciEndTransaction( 2291 IN PVOID HwDeviceExtension, 2292 IN ULONG lChannel, 2293 IN ULONG DeviceNumber, 2294 IN PSCSI_REQUEST_BLOCK Srb 2295 ) 2296 { 2297 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2298 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 2299 //ULONG Channel = deviceExtension->Channel + lChannel; 2300 //ULONG hIS; 2301 ULONG CI, ACT; 2302 PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension); 2303 ULONG TFD; 2304 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); 2305 ULONG tag=0; 2306 //ULONG i; 2307 PIDE_AHCI_CMD_LIST AHCI_CL = &(chan->AhciCtlBlock->cmd_list[tag]); 2308 //PHW_LU_EXTENSION LunExt; 2309 2310 KdPrint2(("UniataAhciEndTransaction: lChan %d\n", chan->lChannel)); 2311 2312 //LunExt = chan->lun[DeviceNumber]; 2313 2314 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 2315 KdPrint2((" TFD %#x\n", TFD)); 2316 2317 if(TFD & IDE_STATUS_ERROR) { 2318 AtaReq->ahci.in_error = (UCHAR)(TFD >> 8); 2319 KdPrint2((" ERROR %#x\n", AtaReq->ahci.in_error)); 2320 } else { 2321 AtaReq->ahci.in_error = 0; 2322 } 2323 AtaReq->ahci.in_status = TFD; 2324 2325 //if (request->flags & ATA_R_CONTROL) { 2326 2327 AtaReq->ahci.in_bcount = (ULONG)(RCV_FIS[12]) | ((ULONG)(RCV_FIS[13]) << 8); 2328 AtaReq->ahci.in_lba = (ULONG)(RCV_FIS[4]) | ((ULONGLONG)(RCV_FIS[5]) << 8) | 2329 ((ULONGLONG)(RCV_FIS[6]) << 16); 2330 if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) { 2331 AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) | 2332 ((ULONGLONG)(RCV_FIS[9]) << 32) | 2333 ((ULONGLONG)(RCV_FIS[10]) << 40); 2334 } else { 2335 AtaReq->ahci.in_lba |= ((ULONGLONG)(RCV_FIS[8]) << 24) | 2336 ((ULONGLONG)(RCV_FIS[9]) << 32) | 2337 ((ULONGLONG)(RCV_FIS[7] & 0x0f) << 24); 2338 } 2339 AtaReq->WordsTransfered = AHCI_CL->bytecount/2; 2340 2341 /* 2342 if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { 2343 KdPrint2(("RCV:\n")); 2344 KdDump(RCV_FIS, 24); 2345 KdPrint2(("PIO:\n")); 2346 KdDump(&(chan->AhciCtlBlock->rcv_fis.psfis[0]), 24); 2347 2348 KdPrint2(("len: %d vs %d\n", AHCI_CL->bytecount, (ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8) )); 2349 if(!AHCI_CL->bytecount) { 2350 AtaReq->WordsTransfered = ((ULONG)RCV_FIS[5] | ((ULONG)RCV_FIS[6] << 8)) / 2; 2351 } 2352 } 2353 */ 2354 ACT = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_ACT); 2355 CI = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CI); 2356 if(CI & (1 << tag)) { 2357 // clear CI 2358 KdPrint2((" Incomplete command, CI %#x, ACT %#x\n", CI, ACT)); 2359 KdPrint2((" FIS status %#x, error %#x\n", RCV_FIS[2], RCV_FIS[3])); 2360 2361 #ifdef _DEBUG 2362 UniataDumpAhciPortRegs(chan); 2363 #endif 2364 if(!UniataAhciAbortOperation(chan)) { 2365 KdPrint2((" Abort failed, need RESET\n")); 2366 } 2367 #ifdef _DEBUG 2368 UniataDumpAhciPortRegs(chan); 2369 #endif 2370 chan->AhciPrevCI = CI & ~((ULONG)1 << tag); 2371 if(chan->AhciPrevCI) { 2372 KdPrint2((" Need command list restart, CI %#x\n", chan->AhciPrevCI)); 2373 } 2374 } else { 2375 chan->AhciPrevCI &= ~((ULONG)1 << tag); 2376 RtlZeroMemory(AHCI_CL, sizeof(IDE_AHCI_CMD_LIST)); 2377 } 2378 //} 2379 2380 return 0; 2381 2382 } // end UniataAhciEndTransaction() 2383 2384 VOID 2385 NTAPI 2386 UniataAhciResume( 2387 IN PHW_CHANNEL chan 2388 ) 2389 { 2390 ULONGLONG base; 2391 2392 KdPrint2(("UniataAhciResume: lChan %d\n", chan->lChannel)); 2393 2394 #ifdef _DEBUG 2395 //UniataDumpAhciPortRegs(chan); 2396 #endif // _DEBUG 2397 2398 /* Disable port interrupts */ 2399 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); 2400 2401 /* setup work areas */ 2402 base = chan->AHCI_CTL_PhAddr; 2403 if(!base) { 2404 KdPrint2((PRINT_PREFIX " AHCI buffer allocation failed\n")); 2405 return; 2406 } 2407 KdPrint2((PRINT_PREFIX " AHCI CLB setup\n")); 2408 if(base & AHCI_CLB_ALIGNEMENT_MASK) { 2409 KdPrint2((PRINT_PREFIX " AHCI CLB address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK)); 2410 } 2411 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB, 2412 (ULONG)(base & 0xffffffff)); 2413 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CLB + 4, 2414 (ULONG)((base >> 32) & 0xffffffff)); 2415 2416 KdPrint2((PRINT_PREFIX " AHCI RCV FIS setup\n")); 2417 base = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, rcv_fis); 2418 if(base & AHCI_FIS_ALIGNEMENT_MASK) { 2419 KdPrint2((PRINT_PREFIX " AHCI FIS address is not aligned (mask %#x)\n", (ULONG)AHCI_FIS_ALIGNEMENT_MASK)); 2420 } 2421 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB, 2422 (ULONG)(base & 0xffffffff)); 2423 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_FB + 4, 2424 (ULONG)((base >> 32) & 0xffffffff)); 2425 2426 /* activate the channel and power/spin up device */ 2427 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 2428 (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD | 2429 (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM)) ? ATA_AHCI_P_CMD_ALPE : 0) | 2430 (((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM2)) ? ATA_AHCI_P_CMD_ASP : 0 )) 2431 ); 2432 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2433 2434 #ifdef _DEBUG 2435 //UniataDumpAhciPortRegs(chan); 2436 #endif // _DEBUG 2437 2438 UniataAhciStartFR(chan); 2439 UniataAhciStart(chan); 2440 2441 #ifdef _DEBUG 2442 UniataDumpAhciPortRegs(chan); 2443 #endif // _DEBUG 2444 2445 return; 2446 } // end UniataAhciResume() 2447 2448 #if 0 2449 VOID 2450 NTAPI 2451 UniataAhciSuspend( 2452 IN PHW_CHANNEL chan 2453 ) 2454 { 2455 ULONGLONG base; 2456 SATA_SCONTROL_REG SControl; 2457 2458 KdPrint2(("UniataAhciSuspend:\n")); 2459 2460 /* Disable port interrupts */ 2461 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_IE, 0); 2462 2463 /* Reset command register. */ 2464 UniataAhciStop(chan); 2465 UniataAhciStopFR(chan); 2466 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 0); 2467 UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */ 2468 2469 /* Allow everything including partial and slumber modes. */ 2470 UniataSataWritePort4(chan, IDX_SATA_SControl, 0, 0); 2471 2472 /* Request slumber mode transition and give some time to get there. */ 2473 UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, ATA_AHCI_P_CMD_SLUMBER); 2474 AtapiStallExecution(100); 2475 2476 /* Disable PHY. */ 2477 SControl.Reg = 0; 2478 SControl.DET = SStatus_DET_Offline; 2479 UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, 0); 2480 2481 return; 2482 } // end UniataAhciSuspend() 2483 #endif 2484 2485 BOOLEAN 2486 NTAPI 2487 UniataAhciReadPM( 2488 IN PHW_CHANNEL chan, 2489 IN ULONG DeviceNumber, 2490 IN ULONG Reg, 2491 OUT PULONG result 2492 ) 2493 { 2494 //ULONG Channel = deviceExtension->Channel + lChannel; 2495 //ULONG hIS; 2496 //ULONG CI; 2497 //AHCI_IS_REG IS; 2498 //ULONG tag=0; 2499 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 2500 PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); 2501 2502 KdPrint(("UniataAhciReadPM: lChan %d [%#x]\n", chan->lChannel, DeviceNumber)); 2503 2504 if(DeviceNumber == DEVNUM_NOT_SPECIFIED) { 2505 (*result) = UniataSataReadPort4(chan, Reg, 0); 2506 return TRUE; 2507 } 2508 if(DeviceNumber < AHCI_DEV_SEL_PM) { 2509 switch(Reg) { 2510 case IDX_SATA_SStatus: 2511 Reg = 0; break; 2512 case IDX_SATA_SError: 2513 Reg = 1; break; 2514 case IDX_SATA_SControl: 2515 Reg = 2; break; 2516 default: 2517 return FALSE; 2518 } 2519 } 2520 2521 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); 2522 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; 2523 AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM; 2524 AHCI_CMD->cfis[2] = IDE_COMMAND_READ_PM; 2525 AHCI_CMD->cfis[3] = (UCHAR)Reg; 2526 AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber); 2527 AHCI_CMD->cfis[15] = IDE_DC_A_4BIT; 2528 2529 if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 10) == IDE_STATUS_WRONG) { 2530 KdPrint2((" PM read failed\n")); 2531 return FALSE; 2532 } 2533 2534 KdDump(RCV_FIS, sizeof(chan->AhciCtlBlock->rcv_fis.rfis)); 2535 2536 (*result) = UniataAhciUlongFromRFIS(RCV_FIS); 2537 return TRUE; 2538 2539 } // end UniataAhciReadPM() 2540 2541 UCHAR 2542 NTAPI 2543 UniataAhciWritePM( 2544 IN PHW_CHANNEL chan, 2545 IN ULONG DeviceNumber, 2546 IN ULONG Reg, 2547 IN ULONG value 2548 ) 2549 { 2550 //ULONG Channel = deviceExtension->Channel + lChannel; 2551 //ULONG hIS; 2552 //ULONG CI; 2553 //AHCI_IS_REG IS; 2554 //ULONG tag=0; 2555 ULONG TFD; 2556 PIDE_AHCI_CMD AHCI_CMD = &(chan->AhciCtlBlock->cmd); 2557 //PUCHAR RCV_FIS = &(chan->AhciCtlBlock->rcv_fis.rfis[0]); 2558 2559 KdPrint(("UniataAhciWritePM: lChan %d [%#x] %#x\n", chan->lChannel, DeviceNumber, value)); 2560 2561 if(DeviceNumber == DEVNUM_NOT_SPECIFIED) { 2562 UniataSataWritePort4(chan, Reg, value, 0); 2563 return 0; 2564 } 2565 if(DeviceNumber < AHCI_DEV_SEL_PM) { 2566 switch(Reg) { 2567 case IDX_SATA_SStatus: 2568 Reg = 0; break; 2569 case IDX_SATA_SError: 2570 Reg = 1; break; 2571 case IDX_SATA_SControl: 2572 Reg = 2; break; 2573 default: 2574 return IDE_STATUS_WRONG; 2575 } 2576 } 2577 2578 RtlZeroMemory(AHCI_CMD->cfis, sizeof(AHCI_CMD->cfis)); 2579 AHCI_CMD->cfis[0] = AHCI_FIS_TYPE_ATA_H2D; 2580 AHCI_CMD->cfis[1] = AHCI_FIS_COMM_PM; 2581 AHCI_CMD->cfis[2] = IDE_COMMAND_WRITE_PM; 2582 AHCI_CMD->cfis[3] = (UCHAR)Reg; 2583 AHCI_CMD->cfis[7] = (UCHAR)(IDE_USE_LBA | DeviceNumber); 2584 2585 AHCI_CMD->cfis[12] = (UCHAR)(value & 0xff); 2586 AHCI_CMD->cfis[4] = (UCHAR)((value >> 8) & 0xff); 2587 AHCI_CMD->cfis[5] = (UCHAR)((value >> 16) & 0xff); 2588 AHCI_CMD->cfis[6] = (UCHAR)((value >> 24) & 0xff); 2589 2590 AHCI_CMD->cfis[15] = IDE_DC_A_4BIT; 2591 2592 if(UniataAhciSendCommand(chan->DeviceExtension, chan->lChannel, DeviceNumber, 0, 100) == IDE_STATUS_WRONG) { 2593 KdPrint2((" PM write failed\n")); 2594 return IDE_STATUS_WRONG; 2595 } 2596 2597 TFD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_TFD); 2598 2599 if(TFD & IDE_STATUS_ERROR) { 2600 KdPrint2((" ERROR %#x\n", (UCHAR)(TFD >> 8))); 2601 } 2602 return (UCHAR)(TFD >> 8); 2603 2604 } // end UniataAhciWritePM() 2605 2606 VOID 2607 UniataAhciSetupCmdPtr( 2608 IN OUT PATA_REQ AtaReq 2609 ) 2610 { 2611 union { 2612 PUCHAR prd_base; 2613 ULONGLONG prd_base64; 2614 }; 2615 union { 2616 PUCHAR prd_base0; 2617 ULONGLONG prd_base64_0; 2618 }; 2619 #ifdef _DEBUG 2620 ULONG d; 2621 #endif // _DEBUG 2622 2623 prd_base64_0 = prd_base64 = 0; 2624 prd_base = (PUCHAR)(&AtaReq->ahci_cmd0); 2625 prd_base0 = prd_base; 2626 2627 prd_base64 = (prd_base64 + max(FIELD_OFFSET(ATA_REQ, ahci_cmd0), AHCI_CMD_ALIGNEMENT_MASK+1)) & ~AHCI_CMD_ALIGNEMENT_MASK; 2628 2629 #ifdef _DEBUG 2630 d = (ULONG)(prd_base64 - prd_base64_0); 2631 KdPrint2((PRINT_PREFIX " AtaReq %#x: cmd aligned %I64x, d=%x\n", AtaReq, prd_base64, d)); 2632 #endif // _DEBUG 2633 2634 AtaReq->ahci.ahci_cmd_ptr = (PIDE_AHCI_CMD)prd_base64; 2635 KdPrint2((PRINT_PREFIX " ahci_cmd_ptr %#x\n", AtaReq->ahci.ahci_cmd_ptr)); 2636 } // end UniataAhciSetupCmdPtr() 2637 2638 PSCSI_REQUEST_BLOCK 2639 NTAPI 2640 BuildAhciInternalSrb ( 2641 IN PVOID HwDeviceExtension, 2642 IN ULONG DeviceNumber, 2643 IN ULONG lChannel, 2644 IN PUCHAR Buffer, 2645 IN ULONG Length 2646 ) 2647 { 2648 PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; 2649 PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; 2650 PSCSI_REQUEST_BLOCK srb; 2651 // PCDB cdb; 2652 PATA_REQ AtaReq = chan->AhciInternalAtaReq; 2653 2654 KdPrint(("BuildAhciInternalSrb: lChan %d [%#x]\n", lChannel, DeviceNumber)); 2655 2656 if(!AtaReq) { 2657 KdPrint2((PRINT_PREFIX " !chan->AhciInternalAtaReq\n")); 2658 return NULL; 2659 } 2660 2661 //RtlZeroMemory((PCHAR) AtaReq, sizeof(ATA_REQ)); 2662 //RtlZeroMemory((PCHAR) AtaReq, FIELD_OFFSET(ATA_REQ, ahci)); 2663 UniAtaClearAtaReq(AtaReq); 2664 2665 srb = chan->AhciInternalSrb; 2666 2667 RtlZeroMemory((PCHAR) srb, sizeof(SCSI_REQUEST_BLOCK)); 2668 2669 srb->PathId = (UCHAR)lChannel; 2670 srb->TargetId = (UCHAR)DeviceNumber; 2671 srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 2672 srb->Length = sizeof(SCSI_REQUEST_BLOCK); 2673 2674 // Set flags to disable synchronous negociation. 2675 //srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER; 2676 2677 // Set timeout to 4 seconds. 2678 srb->TimeOutValue = 4; 2679 2680 srb->CdbLength = 6; 2681 srb->DataBuffer = Buffer; 2682 srb->DataTransferLength = Length; 2683 srb->SrbExtension = AtaReq; 2684 2685 AtaReq->Srb = srb; 2686 AtaReq->DataBuffer = (PUSHORT)Buffer; 2687 AtaReq->TransferLength = Length; 2688 2689 //if(!AtaReq->ahci.ahci_cmd_ptr) { 2690 //UniataAhciSetupCmdPtr(AtaReq); 2691 //AtaReq->ahci.ahci_cmd_ptr = &(chan->AhciCtlBlock->cmd); 2692 //AtaReq->ahci.ahci_base64 = chan->AHCI_CTL_PhAddr + FIELD_OFFSET(IDE_AHCI_CHANNEL_CTL_BLOCK, cmd); 2693 //} 2694 //AtaReq->ahci.ahci_cmd_ptr = &(AtaReq->ahci_cmd0); 2695 //AtaReq->ahci.ahci_base64 = NULL; // indicate that we should copy command to proper place 2696 2697 KdPrint2((PRINT_PREFIX " Srb %#x, AtaReq %#x, CMD %#x ph %I64x\n", srb, AtaReq, 2698 AtaReq->ahci.ahci_cmd_ptr, AtaReq->ahci.ahci_base64)); 2699 2700 /* // Set CDB operation code. 2701 cdb = (PCDB)srb->Cdb; 2702 cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE; 2703 cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA); 2704 */ 2705 return srb; 2706 } // end BuildAhciInternalSrb() 2707 2708