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