1 /* 2 * Copyright 2008-2014 Haiku, Inc. All rights reserved. 3 * Copyright 2007-2009, Marcus Overhagen. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "ahci_port.h" 9 10 #include <new> 11 #include <stdio.h> 12 #include <string.h> 13 14 #include <ByteOrder.h> 15 #include <KernelExport.h> 16 17 #include <ATACommands.h> 18 #include <ATAInfoBlock.h> 19 #include <AutoDeleter.h> 20 21 #include "ahci_controller.h" 22 #include "ahci_tracing.h" 23 #include "sata_request.h" 24 #include "scsi_cmds.h" 25 #include "util.h" 26 27 28 #define TRACE_AHCI 29 #ifdef TRACE_AHCI 30 # define TRACE(a...) dprintf("ahci: " a) 31 #else 32 # define TRACE(a...) 33 #endif 34 //#define FLOW(a...) dprintf("ahci: " a) 35 //#define RWTRACE(a...) dprintf("ahci: " a) 36 #define FLOW(a...) 37 #define RWTRACE(a...) 38 39 40 AHCIPort::AHCIPort(AHCIController* controller, int index) 41 : 42 fController(controller), 43 fIndex(index), 44 fRegs(&controller->fRegs->port[index]), 45 fArea(-1), 46 fCommandsActive(0), 47 fRequestSem(-1), 48 fResponseSem(-1), 49 fDevicePresent(false), 50 fUse48BitCommands(false), 51 fSectorSize(0), 52 fSectorCount(0), 53 fIsATAPI(false), 54 fTestUnitReadyActive(false), 55 fResetPort(false), 56 fError(false), 57 fTrimSupported(false) 58 { 59 B_INITIALIZE_SPINLOCK(&fSpinlock); 60 fRequestSem = create_sem(1, "ahci request"); 61 fResponseSem = create_sem(0, "ahci response"); 62 } 63 64 65 AHCIPort::~AHCIPort() 66 { 67 delete_sem(fRequestSem); 68 delete_sem(fResponseSem); 69 } 70 71 72 status_t 73 AHCIPort::Init1() 74 { 75 TRACE("AHCIPort::Init1 port %d\n", fIndex); 76 77 size_t size = sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT 78 + sizeof(fis) + sizeof(command_table) 79 + sizeof(prd) * PRD_TABLE_ENTRY_COUNT; 80 81 char* virtAddr; 82 phys_addr_t physAddr; 83 char name[32]; 84 snprintf(name, sizeof(name), "AHCI port %d", fIndex); 85 86 fArea = alloc_mem((void**)&virtAddr, &physAddr, size, 0, name); 87 if (fArea < B_OK) { 88 TRACE("failed allocating memory for port %d\n", fIndex); 89 return fArea; 90 } 91 memset(virtAddr, 0, size); 92 93 fCommandList = (command_list_entry*)virtAddr; 94 virtAddr += sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT; 95 fFIS = (fis*)virtAddr; 96 virtAddr += sizeof(fis); 97 fCommandTable = (command_table*)virtAddr; 98 virtAddr += sizeof(command_table); 99 fPRDTable = (prd*)virtAddr; 100 TRACE("PRD table is at %p\n", fPRDTable); 101 102 fRegs->clb = LO32(physAddr); 103 fRegs->clbu = HI32(physAddr); 104 physAddr += sizeof(command_list_entry) * COMMAND_LIST_ENTRY_COUNT; 105 fRegs->fb = LO32(physAddr); 106 fRegs->fbu = HI32(physAddr); 107 physAddr += sizeof(fis); 108 fCommandList[0].ctba = LO32(physAddr); 109 fCommandList[0].ctbau = HI32(physAddr); 110 // prdt follows after command table 111 112 // disable transitions to partial or slumber state 113 fRegs->sctl |= 0x300; 114 115 // clear IRQ status bits 116 fRegs->is = fRegs->is; 117 118 // clear error bits 119 fRegs->serr = fRegs->serr; 120 121 // power up device 122 fRegs->cmd |= PORT_CMD_POD; 123 124 // spin up device 125 fRegs->cmd |= PORT_CMD_SUD; 126 127 // activate link 128 fRegs->cmd = (fRegs->cmd & ~PORT_CMD_ICC_MASK) | PORT_CMD_ICC_ACTIVE; 129 130 // enable FIS receive 131 fRegs->cmd |= PORT_CMD_FER; 132 133 FlushPostedWrites(); 134 135 return B_OK; 136 } 137 138 139 // called with global interrupts enabled 140 status_t 141 AHCIPort::Init2() 142 { 143 TRACE("AHCIPort::Init2 port %d\n", fIndex); 144 145 // start DMA engine 146 fRegs->cmd |= PORT_CMD_ST; 147 148 // enable interrupts 149 fRegs->ie = PORT_INT_MASK; 150 151 FlushPostedWrites(); 152 153 ResetPort(true); 154 155 TRACE("ie 0x%08" B_PRIx32 "\n", fRegs->ie); 156 TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is); 157 TRACE("cmd 0x%08" B_PRIx32 "\n", fRegs->cmd); 158 TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); 159 TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl); 160 TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); 161 TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); 162 TRACE("tfd 0x%08" B_PRIx32 "\n", fRegs->tfd); 163 164 fDevicePresent = (fRegs->ssts & 0xf) == 0x3; 165 166 return B_OK; 167 } 168 169 170 void 171 AHCIPort::Uninit() 172 { 173 TRACE("AHCIPort::Uninit port %d\n", fIndex); 174 175 // disable FIS receive 176 fRegs->cmd &= ~PORT_CMD_FER; 177 178 // wait for receive completion, up to 500ms 179 if (wait_until_clear(&fRegs->cmd, PORT_CMD_FR, 500000) < B_OK) { 180 TRACE("AHCIPort::Uninit port %d error FIS rx still running\n", fIndex); 181 } 182 183 // stop DMA engine 184 fRegs->cmd &= ~PORT_CMD_ST; 185 186 // wait for DMA completion 187 if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) { 188 TRACE("AHCIPort::Uninit port %d error DMA engine still running\n", 189 fIndex); 190 } 191 192 // disable interrupts 193 fRegs->ie = 0; 194 195 // clear pending interrupts 196 fRegs->is = fRegs->is; 197 198 // invalidate DMA addresses 199 fRegs->clb = 0; 200 fRegs->clbu = 0; 201 fRegs->fb = 0; 202 fRegs->fbu = 0; 203 204 delete_area(fArea); 205 } 206 207 208 void 209 AHCIPort::ResetDevice() 210 { 211 if (fRegs->cmd & PORT_CMD_ST) 212 TRACE("AHCIPort::ResetDevice PORT_CMD_ST set, behaviour undefined\n"); 213 214 // perform a hard reset 215 fRegs->sctl = (fRegs->sctl & ~0xf) | 1; 216 FlushPostedWrites(); 217 spin(1100); 218 fRegs->sctl &= ~0xf; 219 FlushPostedWrites(); 220 221 if (wait_until_set(&fRegs->ssts, 0x1, 100000) < B_OK) { 222 TRACE("AHCIPort::ResetDevice port %d no device detected\n", fIndex); 223 } 224 225 // clear error bits 226 fRegs->serr = fRegs->serr; 227 FlushPostedWrites(); 228 229 if (fRegs->ssts & 1) { 230 if (wait_until_set(&fRegs->ssts, 0x3, 500000) < B_OK) { 231 TRACE("AHCIPort::ResetDevice port %d device present but no phy " 232 "communication\n", fIndex); 233 } 234 } 235 236 // clear error bits 237 fRegs->serr = fRegs->serr; 238 FlushPostedWrites(); 239 } 240 241 242 status_t 243 AHCIPort::ResetPort(bool forceDeviceReset) 244 { 245 if (!fTestUnitReadyActive) 246 TRACE("AHCIPort::ResetPort port %d\n", fIndex); 247 248 // stop DMA engine 249 fRegs->cmd &= ~PORT_CMD_ST; 250 FlushPostedWrites(); 251 252 if (wait_until_clear(&fRegs->cmd, PORT_CMD_CR, 500000) < B_OK) { 253 TRACE("AHCIPort::ResetPort port %d error DMA engine doesn't stop\n", 254 fIndex); 255 } 256 257 bool deviceBusy = fRegs->tfd & (ATA_BSY | ATA_DRQ); 258 259 if (!fTestUnitReadyActive) { 260 TRACE("AHCIPort::ResetPort port %d, deviceBusy %d, " 261 "forceDeviceReset %d\n", fIndex, deviceBusy, forceDeviceReset); 262 } 263 264 if (deviceBusy || forceDeviceReset) 265 ResetDevice(); 266 267 // start DMA engine 268 fRegs->cmd |= PORT_CMD_ST; 269 FlushPostedWrites(); 270 271 return PostReset(); 272 } 273 274 275 status_t 276 AHCIPort::PostReset() 277 { 278 if (!fTestUnitReadyActive) 279 TRACE("AHCIPort::PostReset port %d\n", fIndex); 280 281 if ((fRegs->ssts & 0xf) != 0x3 || (fRegs->tfd & 0xff) == 0x7f) { 282 TRACE("AHCIPort::PostReset port %d: no device\n", fIndex); 283 return B_OK; 284 } 285 286 if ((fRegs->tfd & 0xff) == 0xff) 287 snooze(200000); 288 289 if ((fRegs->tfd & 0xff) == 0xff) { 290 TRACE("AHCIPort::PostReset port %d: invalid task file status 0xff\n", 291 fIndex); 292 return B_ERROR; 293 } 294 295 wait_until_clear(&fRegs->tfd, ATA_BSY, 31000000); 296 297 fIsATAPI = fRegs->sig == 0xeb140101; 298 299 if (fIsATAPI) 300 fRegs->cmd |= PORT_CMD_ATAPI; 301 else 302 fRegs->cmd &= ~PORT_CMD_ATAPI; 303 FlushPostedWrites(); 304 305 if (!fTestUnitReadyActive) { 306 TRACE("device signature 0x%08" B_PRIx32 " (%s)\n", fRegs->sig, 307 fRegs->sig == 0xeb140101 ? "ATAPI" : fRegs->sig == 0x00000101 308 ? "ATA" : "unknown"); 309 } 310 311 return B_OK; 312 } 313 314 315 void 316 AHCIPort::DumpD2HFis() 317 { 318 TRACE("D2H FIS:\n"); 319 TRACE(" DW0 %02x %02x %02x %02x\n", fFIS->rfis[3], fFIS->rfis[2], 320 fFIS->rfis[1], fFIS->rfis[0]); 321 TRACE(" DW1 %02x %02x %02x %02x\n", fFIS->rfis[7], fFIS->rfis[6], 322 fFIS->rfis[5], fFIS->rfis[4]); 323 TRACE(" DW2 %02x %02x %02x %02x\n", fFIS->rfis[11], fFIS->rfis[10], 324 fFIS->rfis[9], fFIS->rfis[8]); 325 TRACE(" DW3 %02x %02x %02x %02x\n", fFIS->rfis[15], fFIS->rfis[14], 326 fFIS->rfis[13], fFIS->rfis[12]); 327 TRACE(" DW4 %02x %02x %02x %02x\n", fFIS->rfis[19], fFIS->rfis[18], 328 fFIS->rfis[17], fFIS->rfis[16]); 329 } 330 331 332 void 333 AHCIPort::Interrupt() 334 { 335 uint32 is = fRegs->is; 336 fRegs->is = is; // clear interrupts 337 338 if (is & PORT_INT_ERROR) { 339 InterruptErrorHandler(is); 340 return; 341 } 342 343 uint32 ci = fRegs->ci; 344 345 RWTRACE("[%lld] %ld AHCIPort::Interrupt port %d, fCommandsActive 0x%08" 346 B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", 347 system_time(), find_thread(NULL), fIndex, fCommandsActive, is, ci); 348 349 acquire_spinlock(&fSpinlock); 350 if ((fCommandsActive & 1) && !(ci & 1)) { 351 fCommandsActive &= ~1; 352 release_sem_etc(fResponseSem, 1, B_DO_NOT_RESCHEDULE); 353 } 354 release_spinlock(&fSpinlock); 355 } 356 357 358 void 359 AHCIPort::InterruptErrorHandler(uint32 is) 360 { 361 uint32 ci = fRegs->ci; 362 363 if (!fTestUnitReadyActive) { 364 TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 0x%08" 365 B_PRIx32 ", is 0x%08" B_PRIx32 ", ci 0x%08" B_PRIx32 "\n", fIndex, 366 fCommandsActive, is, ci); 367 368 TRACE("ssts 0x%08" B_PRIx32 ", sctl 0x%08" B_PRIx32 ", serr 0x%08" 369 B_PRIx32 ", sact 0x%08" B_PRIx32 "\n", 370 fRegs->ssts, fRegs->sctl, fRegs->serr, fRegs->sact); 371 } 372 373 // read and clear SError 374 uint32 serr = fRegs->serr; 375 fRegs->serr = serr; 376 377 if (is & PORT_INT_TFE) { 378 if (!fTestUnitReadyActive) 379 TRACE("Task File Error\n"); 380 381 fResetPort = true; 382 fError = true; 383 } 384 if (is & PORT_INT_HBF) { 385 TRACE("Host Bus Fatal Error\n"); 386 fResetPort = true; 387 fError = true; 388 } 389 if (is & PORT_INT_HBD) { 390 TRACE("Host Bus Data Error\n"); 391 fResetPort = true; 392 fError = true; 393 } 394 if (is & PORT_INT_IF) { 395 TRACE("Interface Fatal Error\n"); 396 fResetPort = true; 397 fError = true; 398 } 399 if (is & PORT_INT_INF) { 400 TRACE("Interface Non Fatal Error\n"); 401 } 402 if (is & PORT_INT_OF) { 403 TRACE("Overflow\n"); 404 fResetPort = true; 405 fError = true; 406 } 407 if (is & PORT_INT_IPM) { 408 TRACE("Incorrect Port Multiplier Status\n"); 409 } 410 if (is & PORT_INT_PRC) { 411 TRACE("PhyReady Change\n"); 412 // fResetPort = true; 413 } 414 if (is & PORT_INT_PC) { 415 TRACE("Port Connect Change\n"); 416 // fResetPort = true; 417 } 418 if (is & PORT_INT_UF) { 419 TRACE("Unknown FIS\n"); 420 fResetPort = true; 421 } 422 423 if (fError) { 424 acquire_spinlock(&fSpinlock); 425 if ((fCommandsActive & 1)) { 426 fCommandsActive &= ~1; 427 release_sem_etc(fResponseSem, 1, B_DO_NOT_RESCHEDULE); 428 } 429 release_spinlock(&fSpinlock); 430 } 431 } 432 433 434 status_t 435 AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax, 436 const void* data, size_t dataSize) 437 { 438 int maxEntries = prdMax + 1; 439 physical_entry entries[maxEntries]; 440 uint32 entriesUsed = maxEntries; 441 442 status_t status = get_memory_map_etc(B_CURRENT_TEAM, data, dataSize, 443 entries, &entriesUsed); 444 if (status != B_OK) { 445 TRACE("AHCIPort::FillPrdTable get_memory_map() failed: %s\n", 446 strerror(status)); 447 return B_ERROR; 448 } 449 450 return FillPrdTable(prdTable, prdCount, prdMax, entries, entriesUsed, 451 dataSize); 452 } 453 454 455 status_t 456 AHCIPort::FillPrdTable(volatile prd* prdTable, int* prdCount, int prdMax, 457 const physical_entry* sgTable, int sgCount, size_t dataSize) 458 { 459 *prdCount = 0; 460 while (sgCount > 0 && dataSize > 0) { 461 size_t size = min_c(sgTable->size, dataSize); 462 phys_addr_t address = sgTable->address; 463 T_PORT(AHCIPortPrdTable(fController, fIndex, address, size)); 464 FLOW("FillPrdTable: sg-entry addr %#" B_PRIxPHYSADDR ", size %lu\n", 465 address, size); 466 if (address & 1) { 467 TRACE("AHCIPort::FillPrdTable: data alignment error\n"); 468 return B_ERROR; 469 } 470 dataSize -= size; 471 while (size > 0) { 472 size_t bytes = min_c(size, PRD_MAX_DATA_LENGTH); 473 if (*prdCount == prdMax) { 474 TRACE("AHCIPort::FillPrdTable: prd table exhausted\n"); 475 return B_ERROR; 476 } 477 FLOW("FillPrdTable: prd-entry %u, addr %p, size %lu\n", 478 *prdCount, address, bytes); 479 480 prdTable->dba = LO32(address); 481 prdTable->dbau = HI32(address); 482 prdTable->res = 0; 483 prdTable->dbc = bytes - 1; 484 *prdCount += 1; 485 prdTable++; 486 address = address + bytes; 487 size -= bytes; 488 } 489 sgTable++; 490 sgCount--; 491 } 492 if (*prdCount == 0) { 493 TRACE("AHCIPort::FillPrdTable: count is 0\n"); 494 return B_ERROR; 495 } 496 if (dataSize > 0) { 497 TRACE("AHCIPort::FillPrdTable: sg table %ld bytes too small\n", 498 dataSize); 499 return B_ERROR; 500 } 501 return B_OK; 502 } 503 504 505 void 506 AHCIPort::StartTransfer() 507 { 508 acquire_sem(fRequestSem); 509 } 510 511 512 status_t 513 AHCIPort::WaitForTransfer(int* tfd, bigtime_t timeout) 514 { 515 status_t result = acquire_sem_etc(fResponseSem, 1, B_RELATIVE_TIMEOUT, 516 timeout); 517 if (result < B_OK) { 518 cpu_status cpu = disable_interrupts(); 519 acquire_spinlock(&fSpinlock); 520 fCommandsActive &= ~1; 521 release_spinlock(&fSpinlock); 522 restore_interrupts(cpu); 523 524 result = B_TIMED_OUT; 525 } else if (fError) { 526 *tfd = fRegs->tfd; 527 result = B_ERROR; 528 fError = false; 529 } else { 530 *tfd = fRegs->tfd; 531 } 532 return result; 533 } 534 535 536 void 537 AHCIPort::FinishTransfer() 538 { 539 release_sem(fRequestSem); 540 } 541 542 543 void 544 AHCIPort::ScsiTestUnitReady(scsi_ccb* request) 545 { 546 TRACE("AHCIPort::ScsiTestUnitReady port %d\n", fIndex); 547 request->subsys_status = SCSI_REQ_CMP; 548 gSCSI->finished(request, 1); 549 } 550 551 552 void 553 AHCIPort::ScsiInquiry(scsi_ccb* request) 554 { 555 TRACE("AHCIPort::ScsiInquiry port %d\n", fIndex); 556 557 const scsi_cmd_inquiry* cmd = (const scsi_cmd_inquiry*)request->cdb; 558 scsi_res_inquiry scsiData; 559 ata_device_infoblock ataData; 560 561 ASSERT(sizeof(ataData) == 512); 562 563 if (cmd->evpd || cmd->page_code 564 || request->data_length < sizeof(scsiData)) { 565 TRACE("invalid request\n"); 566 request->subsys_status = SCSI_REQ_ABORTED; 567 gSCSI->finished(request, 1); 568 return; 569 } 570 571 sata_request sreq; 572 sreq.SetData(&ataData, sizeof(ataData)); 573 sreq.SetATACommand(fIsATAPI 574 ? ATA_COMMAND_IDENTIFY_PACKET_DEVICE : ATA_COMMAND_IDENTIFY_DEVICE); 575 ExecuteSataRequest(&sreq); 576 sreq.WaitForCompletion(); 577 578 if ((sreq.CompletionStatus() & ATA_ERR) != 0) { 579 TRACE("identify device failed\n"); 580 request->subsys_status = SCSI_REQ_CMP_ERR; 581 gSCSI->finished(request, 1); 582 return; 583 } 584 585 /* 586 uint8* data = (uint8*)&ataData; 587 for (int i = 0; i < 512; i += 8) { 588 TRACE(" %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1], 589 data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]); 590 } 591 */ 592 593 scsiData.device_type = fIsATAPI 594 ? ataData.word_0.atapi.command_packet_set : scsi_dev_direct_access; 595 scsiData.device_qualifier = scsi_periph_qual_connected; 596 scsiData.device_type_modifier = 0; 597 scsiData.removable_medium = ataData.word_0.ata.removable_media_device; 598 scsiData.ansi_version = 2; 599 scsiData.ecma_version = 0; 600 scsiData.iso_version = 0; 601 scsiData.response_data_format = 2; 602 scsiData.term_iop = false; 603 scsiData.additional_length = sizeof(scsi_res_inquiry) - 4; 604 scsiData.soft_reset = false; 605 scsiData.cmd_queue = false; 606 scsiData.linked = false; 607 scsiData.sync = false; 608 scsiData.write_bus16 = true; 609 scsiData.write_bus32 = false; 610 scsiData.relative_address = false; 611 612 if (!fIsATAPI) { 613 fSectorCount = ataData.SectorCount(fUse48BitCommands, true); 614 fSectorSize = ataData.SectorSize(); 615 fTrimSupported = ataData.data_set_management_support; 616 fMaxTrimRangeBlocks = B_LENDIAN_TO_HOST_INT16( 617 ataData.max_data_set_management_lba_range_blocks); 618 TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %" B_PRIu32 619 ", sectors48 %" B_PRIu64 ", size %" B_PRIu64 "\n", 620 ataData.dma_supported != 0, ataData.lba48_supported != 0, 621 fUse48BitCommands, ataData.lba_sector_count, 622 ataData.lba48_sector_count, fSectorCount * fSectorSize); 623 if (fTrimSupported) { 624 if (fMaxTrimRangeBlocks == 0) 625 fMaxTrimRangeBlocks = 1; 626 627 bool deterministic = ataData.supports_deterministic_read_after_trim; 628 TRACE("trim supported, %" B_PRIu32 " ranges blocks, reads are " 629 "%sdeterministic%s.\n", fMaxTrimRangeBlocks, 630 deterministic ? "" : "non-", deterministic 631 ? (ataData.supports_read_zero_after_trim 632 ? ", zero" : ", random") : ""); 633 } 634 } 635 636 #if 0 637 if (fSectorCount < 0x0fffffff) { 638 TRACE("disabling 48 bit commands\n"); 639 fUse48BitCommands = 0; 640 } 641 #endif 642 643 char modelNumber[sizeof(ataData.model_number) + 1]; 644 char serialNumber[sizeof(ataData.serial_number) + 1]; 645 char firmwareRev[sizeof(ataData.firmware_revision) + 1]; 646 647 strlcpy(modelNumber, ataData.model_number, sizeof(modelNumber)); 648 strlcpy(serialNumber, ataData.serial_number, sizeof(serialNumber)); 649 strlcpy(firmwareRev, ataData.firmware_revision, sizeof(firmwareRev)); 650 651 swap_words(modelNumber, sizeof(modelNumber) - 1); 652 swap_words(serialNumber, sizeof(serialNumber) - 1); 653 swap_words(firmwareRev, sizeof(firmwareRev) - 1); 654 655 TRACE("model number: %s\n", modelNumber); 656 TRACE("serial number: %s\n", serialNumber); 657 TRACE("firmware rev.: %s\n", firmwareRev); 658 659 // There's not enough space to fit all of the data in. ATA has 40 bytes for 660 // the model number, 20 for the serial number and another 8 for the 661 // firmware revision. SCSI has room for 8 for vendor ident, 16 for product 662 // ident and another 4 for product revision. We just try and fit in as much 663 // as possible of the model number into the vendor and product ident fields 664 // and put a little of the serial number into the product revision field. 665 memcpy(scsiData.vendor_ident, modelNumber, sizeof(scsiData.vendor_ident)); 666 memcpy(scsiData.product_ident, modelNumber + 8, 667 sizeof(scsiData.product_ident)); 668 memcpy(scsiData.product_rev, serialNumber, sizeof(scsiData.product_rev)); 669 670 if (sg_memcpy(request->sg_list, request->sg_count, &scsiData, 671 sizeof(scsiData)) < B_OK) { 672 request->subsys_status = SCSI_DATA_RUN_ERR; 673 } else { 674 request->subsys_status = SCSI_REQ_CMP; 675 request->data_resid = request->data_length - sizeof(scsiData); 676 } 677 gSCSI->finished(request, 1); 678 } 679 680 681 void 682 AHCIPort::ScsiSynchronizeCache(scsi_ccb* request) 683 { 684 //TRACE("AHCIPort::ScsiSynchronizeCache port %d\n", fIndex); 685 686 sata_request* sreq = new(std::nothrow) sata_request(request); 687 if (sreq == NULL) { 688 TRACE("out of memory when allocating sync request\n"); 689 request->subsys_status = SCSI_REQ_ABORTED; 690 gSCSI->finished(request, 1); 691 return; 692 } 693 694 sreq->SetATACommand(fUse48BitCommands 695 ? ATA_COMMAND_FLUSH_CACHE_EXT : ATA_COMMAND_FLUSH_CACHE); 696 ExecuteSataRequest(sreq); 697 } 698 699 700 void 701 AHCIPort::ScsiReadCapacity(scsi_ccb* request) 702 { 703 TRACE("AHCIPort::ScsiReadCapacity port %d\n", fIndex); 704 705 const scsi_cmd_read_capacity* cmd 706 = (const scsi_cmd_read_capacity*)request->cdb; 707 scsi_res_read_capacity scsiData; 708 709 if (cmd->pmi || cmd->lba || request->data_length < sizeof(scsiData)) { 710 TRACE("invalid request\n"); 711 request->subsys_status = SCSI_REQ_ABORTED; 712 gSCSI->finished(request, 1); 713 return; 714 } 715 716 TRACE("SectorSize %" B_PRIu32 ", SectorCount 0x%" B_PRIx64 "\n", 717 fSectorSize, fSectorCount); 718 719 scsiData.block_size = B_HOST_TO_BENDIAN_INT32(fSectorSize); 720 721 if (fSectorCount <= 0xffffffff) 722 scsiData.lba = B_HOST_TO_BENDIAN_INT32(fSectorCount - 1); 723 else 724 scsiData.lba = 0xffffffff; 725 726 if (sg_memcpy(request->sg_list, request->sg_count, &scsiData, 727 sizeof(scsiData)) < B_OK) { 728 request->subsys_status = SCSI_DATA_RUN_ERR; 729 } else { 730 request->subsys_status = SCSI_REQ_CMP; 731 request->data_resid = request->data_length - sizeof(scsiData); 732 } 733 gSCSI->finished(request, 1); 734 } 735 736 737 void 738 AHCIPort::ScsiReadCapacity16(scsi_ccb* request) 739 { 740 TRACE("AHCIPort::ScsiReadCapacity16 port %d\n", fIndex); 741 742 scsi_res_read_capacity_long scsiData; 743 744 TRACE("SectorSize %" B_PRIu32 ", SectorCount 0x%" B_PRIx64 "\n", 745 fSectorSize, fSectorCount); 746 747 scsiData.block_size = B_HOST_TO_BENDIAN_INT32(fSectorSize); 748 scsiData.lba = B_HOST_TO_BENDIAN_INT64(fSectorCount - 1); 749 750 if (sg_memcpy(request->sg_list, request->sg_count, &scsiData, 751 sizeof(scsiData)) < B_OK) { 752 request->subsys_status = SCSI_DATA_RUN_ERR; 753 } else { 754 request->subsys_status = SCSI_REQ_CMP; 755 request->data_resid = request->data_length - sizeof(scsiData); 756 } 757 gSCSI->finished(request, 1); 758 } 759 760 761 void 762 AHCIPort::ScsiReadWrite(scsi_ccb* request, uint64 lba, size_t sectorCount, 763 bool isWrite) 764 { 765 RWTRACE("[%lld] %ld ScsiReadWrite: position %llu, size %lu, isWrite %d\n", 766 system_time(), find_thread(NULL), lba * 512, sectorCount * 512, 767 isWrite); 768 769 #if 0 770 if (isWrite) { 771 TRACE("write request ignored\n"); 772 request->subsys_status = SCSI_REQ_CMP; 773 request->data_resid = 0; 774 gSCSI->finished(request, 1); 775 return; 776 } 777 #endif 778 779 ASSERT(request->data_length == sectorCount * 512); 780 sata_request* sreq = new(std::nothrow) sata_request(request); 781 if (sreq == NULL) { 782 TRACE("out of memory when allocating read/write request\n"); 783 request->subsys_status = SCSI_REQ_ABORTED; 784 gSCSI->finished(request, 1); 785 return; 786 } 787 788 if (fUse48BitCommands) { 789 if (sectorCount > 65536) { 790 panic("ahci: ScsiReadWrite length too large, %lu sectors", 791 sectorCount); 792 } 793 if (lba > MAX_SECTOR_LBA_48) 794 panic("achi: ScsiReadWrite position too large for 48-bit LBA\n"); 795 sreq->SetATA48Command( 796 isWrite ? ATA_COMMAND_WRITE_DMA_EXT : ATA_COMMAND_READ_DMA_EXT, 797 lba, sectorCount); 798 } else { 799 if (sectorCount > 256) { 800 panic("ahci: ScsiReadWrite length too large, %lu sectors", 801 sectorCount); 802 } 803 if (lba > MAX_SECTOR_LBA_28) 804 panic("achi: ScsiReadWrite position too large for normal LBA\n"); 805 sreq->SetATA28Command(isWrite 806 ? ATA_COMMAND_WRITE_DMA : ATA_COMMAND_READ_DMA, lba, sectorCount); 807 } 808 809 ExecuteSataRequest(sreq, isWrite); 810 } 811 812 813 void 814 AHCIPort::ScsiUnmap(scsi_ccb* request, scsi_unmap_parameter_list* unmapBlocks) 815 { 816 // Determine how many blocks are supposed to be trimmed in total 817 uint32 scsiRangeCount = B_BENDIAN_TO_HOST_INT16( 818 unmapBlocks->block_data_length) / sizeof(scsi_unmap_block_descriptor); 819 820 dprintf("TRIM SCSI:\n"); 821 for (uint32 i = 0; i < scsiRangeCount; i++) { 822 dprintf("[%3" B_PRIu32 "] %" B_PRIu64 " : %" B_PRIu32 "\n", i, 823 (uint64)B_BENDIAN_TO_HOST_INT64(unmapBlocks->blocks[i].lba), 824 (uint32)B_BENDIAN_TO_HOST_INT32(unmapBlocks->blocks[i].block_count)); 825 } 826 827 uint32 scsiIndex = 0; 828 uint32 scsiLastBlocks = 0; 829 uint32 maxLBARangeCount = fMaxTrimRangeBlocks * 512 / 8; 830 // 512 bytes per range block, 8 bytes per range 831 832 // Split the SCSI ranges into ATA ranges as large as allowed. 833 // We assume that the SCSI unmap ranges cannot be merged together 834 835 while (scsiIndex < scsiRangeCount) { 836 // Determine how many LBA ranges we need for the next chunk 837 uint32 lbaRangeCount = 0; 838 for (uint32 i = scsiIndex; i < scsiRangeCount; i++) { 839 uint32 scsiBlocks = B_BENDIAN_TO_HOST_INT32( 840 unmapBlocks->blocks[i].block_count); 841 if (scsiBlocks == 0) 842 break; 843 if (i == scsiIndex) 844 scsiBlocks -= scsiLastBlocks; 845 846 lbaRangeCount += (scsiBlocks + 65534) / 65535; 847 if (lbaRangeCount >= maxLBARangeCount) { 848 lbaRangeCount = maxLBARangeCount; 849 break; 850 } 851 } 852 if (lbaRangeCount == 0) 853 break; 854 855 uint32 lbaRangesSize = lbaRangeCount * sizeof(uint64); 856 uint64* lbaRanges = (uint64*)malloc(lbaRangesSize); 857 if (lbaRanges == NULL) { 858 TRACE("out of memory when allocating %" B_PRIu32 " unmap ranges\n", 859 lbaRangeCount); 860 request->subsys_status = SCSI_REQ_ABORTED; 861 gSCSI->finished(request, 1); 862 return; 863 } 864 865 MemoryDeleter deleter(lbaRanges); 866 867 for (uint32 lbaIndex = 0; 868 scsiIndex < scsiRangeCount && lbaIndex < lbaRangeCount;) { 869 uint64 scsiOffset = B_BENDIAN_TO_HOST_INT64( 870 unmapBlocks->blocks[scsiIndex].lba) + scsiLastBlocks; 871 uint32 scsiBlocksLeft = B_BENDIAN_TO_HOST_INT32( 872 unmapBlocks->blocks[scsiIndex].block_count) - scsiLastBlocks; 873 874 if (scsiBlocksLeft == 0) { 875 // Ignore the rest of the ranges (they are empty) 876 scsiIndex = scsiRangeCount; 877 break; 878 } 879 880 while (scsiBlocksLeft > 0 && lbaIndex < lbaRangeCount) { 881 uint16 blocks = scsiBlocksLeft > 65535 882 ? 65535 : (uint16)scsiBlocksLeft; 883 lbaRanges[lbaIndex++] = B_HOST_TO_LENDIAN_INT64( 884 ((uint64)blocks << 48) | scsiOffset); 885 886 scsiOffset += blocks; 887 scsiLastBlocks += blocks; 888 scsiBlocksLeft -= blocks; 889 } 890 891 if (scsiBlocksLeft == 0) { 892 scsiLastBlocks = 0; 893 scsiIndex++; 894 } 895 } 896 897 dprintf("TRIM AHCI:\n"); 898 for (uint32 i = 0; i < lbaRangeCount; i++) { 899 uint64 value = B_HOST_TO_LENDIAN_INT64(lbaRanges[i]); 900 dprintf("[%3" B_PRIu32 "] %" B_PRIu64 " : %" B_PRIu64 "\n", i, 901 value & (((uint64)1 << 48) - 1), value >> 48); 902 } 903 904 sata_request sreq; 905 sreq.SetATA48Command(ATA_COMMAND_DATA_SET_MANAGEMENT, 0, 906 (lbaRangesSize + 511) / 512); 907 sreq.SetFeature(1); 908 sreq.SetData(lbaRanges, lbaRangesSize); 909 910 ExecuteSataRequest(&sreq); 911 sreq.WaitForCompletion(); 912 913 if ((sreq.CompletionStatus() & ATA_ERR) != 0) { 914 TRACE("trim failed (%" B_PRIu32 " ranges)!\n", lbaRangeCount); 915 request->subsys_status = SCSI_REQ_CMP_ERR; 916 } else 917 request->subsys_status = SCSI_REQ_CMP; 918 } 919 920 request->data_resid = 0; 921 request->device_status = SCSI_STATUS_GOOD; 922 gSCSI->finished(request, 1); 923 } 924 925 926 void 927 AHCIPort::ExecuteSataRequest(sata_request* request, bool isWrite) 928 { 929 FLOW("ExecuteAtaRequest port %d\n", fIndex); 930 931 StartTransfer(); 932 933 int prdEntrys; 934 935 if (request->CCB() && request->CCB()->data_length) { 936 FillPrdTable(fPRDTable, &prdEntrys, PRD_TABLE_ENTRY_COUNT, 937 request->CCB()->sg_list, request->CCB()->sg_count, 938 request->CCB()->data_length); 939 } else if (request->Data() && request->Size()) { 940 FillPrdTable(fPRDTable, &prdEntrys, PRD_TABLE_ENTRY_COUNT, 941 request->Data(), request->Size()); 942 } else 943 prdEntrys = 0; 944 945 FLOW("prdEntrys %d\n", prdEntrys); 946 947 fCommandList->prdtl_flags_cfl = 0; 948 fCommandList->cfl = 5; // 20 bytes, length in DWORDS 949 memcpy((char*)fCommandTable->cfis, request->FIS(), 20); 950 951 fTestUnitReadyActive = request->IsTestUnitReady(); 952 if (request->IsATAPI()) { 953 // ATAPI PACKET is a 12 or 16 byte SCSI command 954 memset((char*)fCommandTable->acmd, 0, 32); 955 memcpy((char*)fCommandTable->acmd, request->CCB()->cdb, 956 request->CCB()->cdb_length); 957 fCommandList->a = 1; 958 } 959 960 if (isWrite) 961 fCommandList->w = 1; 962 fCommandList->prdtl = prdEntrys; 963 fCommandList->prdbc = 0; 964 965 if (wait_until_clear(&fRegs->tfd, ATA_BSY | ATA_DRQ, 1000000) < B_OK) { 966 TRACE("ExecuteAtaRequest port %d: device is busy\n", fIndex); 967 ResetPort(); 968 FinishTransfer(); 969 request->Abort(); 970 return; 971 } 972 973 cpu_status cpu = disable_interrupts(); 974 acquire_spinlock(&fSpinlock); 975 fCommandsActive |= 1; 976 fRegs->ci = 1; 977 FlushPostedWrites(); 978 release_spinlock(&fSpinlock); 979 restore_interrupts(cpu); 980 981 int tfd; 982 status_t status = WaitForTransfer(&tfd, 20000000); 983 984 FLOW("tfd %#x\n", tfd); 985 FLOW("prdbc %ld\n", fCommandList->prdbc); 986 FLOW("ci 0x%08" B_PRIx32 "\n", fRegs->ci); 987 FLOW("is 0x%08" B_PRIx32 "\n", fRegs->is); 988 FLOW("serr 0x%08" B_PRIx32 "\n", fRegs->serr); 989 990 /* 991 TRACE("ci 0x%08" B_PRIx32 "\n", fRegs->ci); 992 TRACE("ie 0x%08" B_PRIx32 "\n", fRegs->ie); 993 TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is); 994 TRACE("cmd 0x%08" B_PRIx32 "\n", fRegs->cmd); 995 TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts); 996 TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl); 997 TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr); 998 TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact); 999 TRACE("tfd 0x%08" B_PRIx32 "\n", fRegs->tfd); 1000 */ 1001 1002 if (fResetPort || status == B_TIMED_OUT) { 1003 fResetPort = false; 1004 ResetPort(); 1005 } 1006 1007 size_t bytesTransfered = fCommandList->prdbc; 1008 1009 FinishTransfer(); 1010 1011 if (status == B_TIMED_OUT) { 1012 TRACE("ExecuteAtaRequest port %d: device timeout\n", fIndex); 1013 request->Abort(); 1014 return; 1015 } 1016 1017 request->Finish(tfd, bytesTransfered); 1018 } 1019 1020 1021 void 1022 AHCIPort::ScsiExecuteRequest(scsi_ccb* request) 1023 { 1024 // TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length); 1025 1026 if (fIsATAPI) { 1027 bool isWrite = false; 1028 switch (request->flags & SCSI_DIR_MASK) { 1029 case SCSI_DIR_NONE: 1030 ASSERT(request->data_length == 0); 1031 break; 1032 case SCSI_DIR_IN: 1033 ASSERT(request->data_length > 0); 1034 break; 1035 case SCSI_DIR_OUT: 1036 isWrite = true; 1037 ASSERT(request->data_length > 0); 1038 break; 1039 default: 1040 panic("CDB has invalid direction mask"); 1041 } 1042 1043 // TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length); 1044 1045 sata_request* sreq = new(std::nothrow) sata_request(request); 1046 if (sreq == NULL) { 1047 TRACE("out of memory when allocating atapi request\n"); 1048 request->subsys_status = SCSI_REQ_ABORTED; 1049 gSCSI->finished(request, 1); 1050 return; 1051 } 1052 1053 sreq->SetATAPICommand(request->data_length); 1054 // uint8* data = (uint8*) sreq->ccb()->cdb; 1055 // for (int i = 0; i < 16; i += 8) { 1056 // TRACE(" %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1], data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]); 1057 // } 1058 ExecuteSataRequest(sreq, isWrite); 1059 return; 1060 } 1061 1062 if (request->cdb[0] == SCSI_OP_REQUEST_SENSE) { 1063 panic("ahci: SCSI_OP_REQUEST_SENSE not yet supported\n"); 1064 return; 1065 } 1066 1067 if (!fDevicePresent) { 1068 TRACE("no device present on port %d\n", fIndex); 1069 request->subsys_status = SCSI_DEV_NOT_THERE; 1070 gSCSI->finished(request, 1); 1071 return; 1072 } 1073 1074 request->subsys_status = SCSI_REQ_CMP; 1075 1076 switch (request->cdb[0]) { 1077 case SCSI_OP_TEST_UNIT_READY: 1078 ScsiTestUnitReady(request); 1079 break; 1080 case SCSI_OP_INQUIRY: 1081 ScsiInquiry(request); 1082 break; 1083 case SCSI_OP_READ_CAPACITY: 1084 ScsiReadCapacity(request); 1085 break; 1086 case SCSI_OP_SERVICE_ACTION_IN: 1087 if ((request->cdb[1] & 0x1f) == SCSI_SAI_READ_CAPACITY_16) 1088 ScsiReadCapacity16(request); 1089 else { 1090 request->subsys_status = SCSI_REQ_INVALID; 1091 gSCSI->finished(request, 1); 1092 } 1093 break; 1094 case SCSI_OP_SYNCHRONIZE_CACHE: 1095 ScsiSynchronizeCache(request); 1096 break; 1097 case SCSI_OP_READ_6: 1098 case SCSI_OP_WRITE_6: 1099 { 1100 const scsi_cmd_rw_6* cmd = (const scsi_cmd_rw_6*)request->cdb; 1101 uint32 position = ((uint32)cmd->high_lba << 16) 1102 | ((uint32)cmd->mid_lba << 8) | (uint32)cmd->low_lba; 1103 size_t length = cmd->length != 0 ? cmd->length : 256; 1104 bool isWrite = request->cdb[0] == SCSI_OP_WRITE_6; 1105 ScsiReadWrite(request, position, length, isWrite); 1106 break; 1107 } 1108 case SCSI_OP_READ_10: 1109 case SCSI_OP_WRITE_10: 1110 { 1111 const scsi_cmd_rw_10* cmd = (const scsi_cmd_rw_10*)request->cdb; 1112 uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba); 1113 size_t length = B_BENDIAN_TO_HOST_INT16(cmd->length); 1114 bool isWrite = request->cdb[0] == SCSI_OP_WRITE_10; 1115 if (length) { 1116 ScsiReadWrite(request, position, length, isWrite); 1117 } else { 1118 TRACE("AHCIPort::ScsiExecuteRequest error: transfer without " 1119 "data!\n"); 1120 request->subsys_status = SCSI_REQ_INVALID; 1121 gSCSI->finished(request, 1); 1122 } 1123 break; 1124 } 1125 case SCSI_OP_READ_12: 1126 case SCSI_OP_WRITE_12: 1127 { 1128 const scsi_cmd_rw_12* cmd = (const scsi_cmd_rw_12*)request->cdb; 1129 uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba); 1130 size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length); 1131 bool isWrite = request->cdb[0] == SCSI_OP_WRITE_12; 1132 if (length) { 1133 ScsiReadWrite(request, position, length, isWrite); 1134 } else { 1135 TRACE("AHCIPort::ScsiExecuteRequest error: transfer without " 1136 "data!\n"); 1137 request->subsys_status = SCSI_REQ_INVALID; 1138 gSCSI->finished(request, 1); 1139 } 1140 break; 1141 } 1142 case SCSI_OP_READ_16: 1143 case SCSI_OP_WRITE_16: 1144 { 1145 const scsi_cmd_rw_16* cmd = (const scsi_cmd_rw_16*)request->cdb; 1146 uint64 position = B_BENDIAN_TO_HOST_INT64(cmd->lba); 1147 size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length); 1148 bool isWrite = request->cdb[0] == SCSI_OP_WRITE_16; 1149 if (length) { 1150 ScsiReadWrite(request, position, length, isWrite); 1151 } else { 1152 TRACE("AHCIPort::ScsiExecuteRequest error: transfer without " 1153 "data!\n"); 1154 request->subsys_status = SCSI_REQ_INVALID; 1155 gSCSI->finished(request, 1); 1156 } 1157 break; 1158 } 1159 case SCSI_OP_UNMAP: 1160 { 1161 const scsi_cmd_unmap* cmd = (const scsi_cmd_unmap*)request->cdb; 1162 1163 if (!fTrimSupported) { 1164 TRACE("%s port %d: unsupported request opcode 0x%02x\n", 1165 __func__, fIndex, request->cdb[0]); 1166 request->subsys_status = SCSI_REQ_ABORTED; 1167 gSCSI->finished(request, 1); 1168 break; 1169 } 1170 1171 scsi_unmap_parameter_list* unmapBlocks 1172 = (scsi_unmap_parameter_list*)request->data; 1173 if (unmapBlocks == NULL 1174 || B_BENDIAN_TO_HOST_INT16(cmd->length) != request->data_length 1175 || B_BENDIAN_TO_HOST_INT16(unmapBlocks->data_length) 1176 != request->data_length - 1) { 1177 TRACE("%s port %d: invalid unmap parameter data length\n", 1178 __func__, fIndex); 1179 request->subsys_status = SCSI_REQ_ABORTED; 1180 gSCSI->finished(request, 1); 1181 } else { 1182 ScsiUnmap(request, unmapBlocks); 1183 } 1184 break; 1185 } 1186 default: 1187 TRACE("AHCIPort::ScsiExecuteRequest port %d unsupported request " 1188 "opcode 0x%02x\n", fIndex, request->cdb[0]); 1189 request->subsys_status = SCSI_REQ_ABORTED; 1190 gSCSI->finished(request, 1); 1191 } 1192 } 1193 1194 1195 uchar 1196 AHCIPort::ScsiAbortRequest(scsi_ccb* request) 1197 { 1198 return SCSI_REQ_CMP; 1199 } 1200 1201 1202 uchar 1203 AHCIPort::ScsiTerminateRequest(scsi_ccb* request) 1204 { 1205 return SCSI_REQ_CMP; 1206 } 1207 1208 1209 uchar 1210 AHCIPort::ScsiResetDevice() 1211 { 1212 return SCSI_REQ_CMP; 1213 } 1214 1215 1216 void 1217 AHCIPort::ScsiGetRestrictions(bool* isATAPI, bool* noAutoSense, 1218 uint32* maxBlocks) 1219 { 1220 *isATAPI = fIsATAPI; 1221 *noAutoSense = fIsATAPI; // emulated auto sense for ATA, but not ATAPI 1222 *maxBlocks = fUse48BitCommands ? 65536 : 256; 1223 TRACE("AHCIPort::ScsiGetRestrictions port %d: isATAPI %d, noAutoSense %d, " 1224 "maxBlocks %" B_PRIu32 "\n", fIndex, *isATAPI, *noAutoSense, 1225 *maxBlocks); 1226 } 1227