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.
7 * Axel Dörfler, axeld@pinc-software.de
8 * Michael Lotz, mmlr@mlotz.ch
9 * Alexander von Gluck IV, kallisti5@unixzen.com
13 #include "ahci_port.h"
19 #include <ByteOrder.h>
20 #include <KernelExport.h>
22 #include <ATACommands.h>
23 #include <ATAInfoBlock.h>
24 #include <AutoDeleter.h>
26 #include "ahci_controller.h"
27 #include "ahci_tracing.h"
28 #include "sata_request.h"
29 #include "scsi_cmds.h"
35 # define TRACE(a...) dprintf("ahci: " a)
40 #define ERROR(a...) dprintf("ahci: " a)
41 //#define FLOW(a...) dprintf("ahci: " a)
42 //#define RWTRACE(a...) dprintf("ahci: " a)
47 AHCIPort::AHCIPort(AHCIController
* controller
, int index
)
49 fController(controller
),
51 fRegs(&controller
->fRegs
->port
[index
]),
56 fDevicePresent(false),
57 fUse48BitCommands(false),
61 fTestUnitReadyActive(false),
66 B_INITIALIZE_SPINLOCK(&fSpinlock
);
67 fRequestSem
= create_sem(1, "ahci request");
68 fResponseSem
= create_sem(0, "ahci response");
74 delete_sem(fRequestSem
);
75 delete_sem(fResponseSem
);
82 TRACE("AHCIPort::Init1 port %d\n", fIndex
);
84 size_t size
= sizeof(command_list_entry
) * COMMAND_LIST_ENTRY_COUNT
85 + sizeof(fis
) + sizeof(command_table
)
86 + sizeof(prd
) * PRD_TABLE_ENTRY_COUNT
;
91 snprintf(name
, sizeof(name
), "AHCI port %d", fIndex
);
93 fArea
= alloc_mem((void**)&virtAddr
, &physAddr
, size
, 0, name
);
95 TRACE("failed allocating memory for port %d\n", fIndex
);
98 memset(virtAddr
, 0, size
);
100 fCommandList
= (command_list_entry
*)virtAddr
;
101 virtAddr
+= sizeof(command_list_entry
) * COMMAND_LIST_ENTRY_COUNT
;
102 fFIS
= (fis
*)virtAddr
;
103 virtAddr
+= sizeof(fis
);
104 fCommandTable
= (command_table
*)virtAddr
;
105 virtAddr
+= sizeof(command_table
);
106 fPRDTable
= (prd
*)virtAddr
;
107 TRACE("PRD table is at %p\n", fPRDTable
);
109 fRegs
->clb
= LO32(physAddr
);
110 fRegs
->clbu
= HI32(physAddr
);
111 physAddr
+= sizeof(command_list_entry
) * COMMAND_LIST_ENTRY_COUNT
;
112 fRegs
->fb
= LO32(physAddr
);
113 fRegs
->fbu
= HI32(physAddr
);
114 physAddr
+= sizeof(fis
);
115 fCommandList
[0].ctba
= LO32(physAddr
);
116 fCommandList
[0].ctbau
= HI32(physAddr
);
117 // prdt follows after command table
119 // disable transitions to partial or slumber state
120 fRegs
->sctl
|= (SCTL_PORT_IPM_NOPART
| SCTL_PORT_IPM_NOSLUM
);
122 // clear IRQ status bits
123 fRegs
->is
= fRegs
->is
;
126 _ClearErrorRegister();
129 fRegs
->cmd
|= PORT_CMD_POD
;
132 fRegs
->cmd
|= PORT_CMD_SUD
;
135 fRegs
->cmd
= (fRegs
->cmd
& ~PORT_CMD_ICC_MASK
) | PORT_CMD_ICC_ACTIVE
;
137 // enable FIS receive (enabled when fb set, only to be disabled when unset)
138 fRegs
->cmd
|= PORT_CMD_FRE
;
146 // called with global interrupts enabled
150 TRACE("AHCIPort::Init2 port %d\n", fIndex
);
156 fRegs
->ie
= PORT_INT_MASK
;
160 // reset port and probe info
165 TRACE("%s: port %d, device %s\n", __func__
, fIndex
,
166 fDevicePresent
? "present" : "absent");
175 TRACE("AHCIPort::Uninit port %d\n", fIndex
);
177 // Spec v1.3.1, §10.3.2 - Shut down port before unsetting FRE
181 ERROR("%s: port %d error, unable to shutdown before FRE clear!\n",
186 // Clear FRE and wait for completion
187 fRegs
->cmd
&= ~PORT_CMD_FRE
;
188 if (wait_until_clear(&fRegs
->cmd
, PORT_CMD_FR
, 500000) < B_OK
)
189 ERROR("%s: port %d error FIS rx still running\n", __func__
, fIndex
);
191 // disable interrupts
194 // clear pending interrupts
195 fRegs
->is
= fRegs
->is
;
197 // invalidate DMA addresses
208 AHCIPort::ResetDevice()
210 // perform a hard reset
211 if (PortReset() != B_OK
) {
212 ERROR("%s: port %d unable to hard reset device\n", __func__
, fIndex
);
216 if (wait_until_set(&fRegs
->ssts
, SSTS_PORT_DET_NODEV
, 100000) < B_OK
)
217 TRACE("AHCIPort::ResetDevice port %d no device detected\n", fIndex
);
219 _ClearErrorRegister();
221 if (fRegs
->ssts
& SSTS_PORT_DET_NOPHY
) {
222 if (wait_until_set(&fRegs
->ssts
, 0x3, 500000) < B_OK
) {
223 TRACE("AHCIPort::ResetDevice port %d device present but no phy "
224 "communication\n", fIndex
);
228 _ClearErrorRegister();
233 AHCIPort::PortReset()
235 TRACE("AHCIPort::PortReset port %d\n", fIndex
);
238 ERROR("%s: port %d unable to shutdown!\n", __func__
, fIndex
);
242 _ClearErrorRegister();
244 // Wait for BSY and DRQ to clear (idle port)
245 if (wait_until_clear(&fRegs
->tfd
, ATA_STATUS_BUSY
| ATA_STATUS_DATA_REQUEST
,
247 // If we can't clear busy, do a full comreset
249 // Spec v1.3.1, §10.4.2 Port Reset
250 // Physical comm between HBA and port disabled. More Intrusive
251 ERROR("%s: port %d undergoing COMRESET\n", __func__
, fIndex
);
253 // Notice we're throwing out all other control flags.
254 fRegs
->sctl
= (SSTS_PORT_IPM_ACTIVE
| SSTS_PORT_IPM_PARTIAL
255 | SCTL_PORT_DET_INIT
);
258 // You must wait 1ms at minimum
259 fRegs
->sctl
= (fRegs
->sctl
& ~HBA_PORT_DET_MASK
) | SCTL_PORT_DET_NOINIT
;
265 if (wait_until_set(&fRegs
->ssts
, SSTS_PORT_DET_PRESENT
, 500000) < B_OK
) {
266 TRACE("%s: port %d: no device detected\n", __func__
, fIndex
);
267 fDevicePresent
= false;
278 if ((fRegs
->tfd
& 0xff) == 0xff)
281 if ((fRegs
->tfd
& 0xff) == 0xff) {
282 TRACE("%s: port %d: invalid task file status 0xff\n", __func__
,
287 if (!fTestUnitReadyActive
) {
288 switch (fRegs
->ssts
& HBA_PORT_SPD_MASK
) {
290 ERROR("%s: port %d link speed 1.5Gb/s\n", __func__
, fIndex
);
293 ERROR("%s: port %d link speed 3.0Gb/s\n", __func__
, fIndex
);
296 ERROR("%s: port %d link speed 6.0Gb/s\n", __func__
, fIndex
);
299 ERROR("%s: port %d link speed unrestricted\n", __func__
, fIndex
);
304 wait_until_clear(&fRegs
->tfd
, ATA_STATUS_BUSY
, 31000000);
306 fDevicePresent
= (fRegs
->ssts
& HBA_PORT_DET_MASK
) == SSTS_PORT_DET_PRESENT
;
307 fIsATAPI
= fRegs
->sig
== SATA_SIG_ATAPI
;
310 fRegs
->cmd
|= PORT_CMD_ATAPI
;
312 fRegs
->cmd
&= ~PORT_CMD_ATAPI
;
315 TRACE("device signature 0x%08" B_PRIx32
" (%s)\n", fRegs
->sig
,
316 fRegs
->sig
== SATA_SIG_ATAPI
? "ATAPI" : fRegs
->sig
== SATA_SIG_ATA
317 ? "ATA" : "unknown");
324 AHCIPort::DumpD2HFis()
327 TRACE(" DW0 %02x %02x %02x %02x\n", fFIS
->rfis
[3], fFIS
->rfis
[2],
328 fFIS
->rfis
[1], fFIS
->rfis
[0]);
329 TRACE(" DW1 %02x %02x %02x %02x\n", fFIS
->rfis
[7], fFIS
->rfis
[6],
330 fFIS
->rfis
[5], fFIS
->rfis
[4]);
331 TRACE(" DW2 %02x %02x %02x %02x\n", fFIS
->rfis
[11], fFIS
->rfis
[10],
332 fFIS
->rfis
[9], fFIS
->rfis
[8]);
333 TRACE(" DW3 %02x %02x %02x %02x\n", fFIS
->rfis
[15], fFIS
->rfis
[14],
334 fFIS
->rfis
[13], fFIS
->rfis
[12]);
335 TRACE(" DW4 %02x %02x %02x %02x\n", fFIS
->rfis
[19], fFIS
->rfis
[18],
336 fFIS
->rfis
[17], fFIS
->rfis
[16]);
341 AHCIPort::DumpHBAState()
343 TRACE("Port %d state:\n", fIndex
);
344 TRACE(" ie 0x%08" B_PRIx32
"\n", fRegs
->ie
);
345 TRACE(" is 0x%08" B_PRIx32
"\n", fRegs
->is
);
346 TRACE(" cmd 0x%08" B_PRIx32
"\n", fRegs
->cmd
);
347 TRACE(" ssts 0x%08" B_PRIx32
"\n", fRegs
->ssts
);
348 TRACE(" sctl 0x%08" B_PRIx32
"\n", fRegs
->sctl
);
349 TRACE(" serr 0x%08" B_PRIx32
"\n", fRegs
->serr
);
350 TRACE(" sact 0x%08" B_PRIx32
"\n", fRegs
->sact
);
351 TRACE(" tfd 0x%08" B_PRIx32
"\n", fRegs
->tfd
);
356 AHCIPort::Interrupt()
358 uint32 is
= fRegs
->is
;
359 fRegs
->is
= is
; // clear interrupts
361 if (is
& PORT_INT_ERROR
) {
362 InterruptErrorHandler(is
);
366 uint32 ci
= fRegs
->ci
;
368 RWTRACE("[%lld] %ld AHCIPort::Interrupt port %d, fCommandsActive 0x%08"
369 B_PRIx32
", is 0x%08" B_PRIx32
", ci 0x%08" B_PRIx32
"\n",
370 system_time(), find_thread(NULL
), fIndex
, fCommandsActive
, is
, ci
);
372 acquire_spinlock(&fSpinlock
);
373 if ((fCommandsActive
& 1) && !(ci
& 1)) {
374 fCommandsActive
&= ~1;
375 release_sem_etc(fResponseSem
, 1, B_DO_NOT_RESCHEDULE
);
377 release_spinlock(&fSpinlock
);
382 AHCIPort::InterruptErrorHandler(uint32 is
)
384 TRACE("AHCIPort::InterruptErrorHandler port %d, fCommandsActive 0x%08"
385 B_PRIx32
", is 0x%08" B_PRIx32
", ci 0x%08" B_PRIx32
"\n", fIndex
,
386 fCommandsActive
, is
, fRegs
->ci
);
387 TRACE("ssts 0x%08" B_PRIx32
"\n", fRegs
->ssts
);
388 TRACE("sctl 0x%08" B_PRIx32
"\n", fRegs
->sctl
);
389 TRACE("serr 0x%08" B_PRIx32
"\n", fRegs
->serr
);
390 TRACE("sact 0x%08" B_PRIx32
"\n", fRegs
->sact
);
392 // read and clear SError
393 _ClearErrorRegister();
395 if (is
& PORT_INT_TFE
) {
396 TRACE("Task File Error\n");
401 if (is
& PORT_INT_HBF
) {
402 ERROR("Host Bus Fatal Error\n");
406 if (is
& PORT_INT_HBD
) {
407 ERROR("Host Bus Data Error\n");
411 if (is
& PORT_INT_IF
) {
412 ERROR("Interface Fatal Error\n");
416 if (is
& PORT_INT_INF
) {
417 TRACE("Interface Non Fatal Error\n");
419 if (is
& PORT_INT_OF
) {
424 if (is
& PORT_INT_IPM
) {
425 TRACE("Incorrect Port Multiplier Status\n");
427 if (is
& PORT_INT_PRC
) {
428 TRACE("PhyReady Change\n");
431 if (is
& PORT_INT_PC
) {
432 TRACE("Port Connect Change\n");
433 // Unsolicited when we had a port connect change without us requesting
434 // Spec v1.3, §6.2.2.3 Recovery of Unsolicited COMINIT
436 // XXX: This shouldn't be needed here... but we can loop without it
437 //_ClearErrorRegister();
439 if (is
& PORT_INT_UF
) {
440 TRACE("Unknown FIS\n");
445 acquire_spinlock(&fSpinlock
);
446 if ((fCommandsActive
& 1)) {
447 fCommandsActive
&= ~1;
448 release_sem_etc(fResponseSem
, 1, B_DO_NOT_RESCHEDULE
);
450 release_spinlock(&fSpinlock
);
456 AHCIPort::FillPrdTable(volatile prd
* prdTable
, int* prdCount
, int prdMax
,
457 const void* data
, size_t dataSize
)
459 int maxEntries
= prdMax
+ 1;
460 physical_entry entries
[maxEntries
];
461 uint32 entriesUsed
= maxEntries
;
463 status_t status
= get_memory_map_etc(B_CURRENT_TEAM
, data
, dataSize
,
464 entries
, &entriesUsed
);
465 if (status
!= B_OK
) {
466 ERROR("%s: get_memory_map() failed: %s\n", __func__
, strerror(status
));
470 return FillPrdTable(prdTable
, prdCount
, prdMax
, entries
, entriesUsed
,
476 AHCIPort::FillPrdTable(volatile prd
* prdTable
, int* prdCount
, int prdMax
,
477 const physical_entry
* sgTable
, int sgCount
, size_t dataSize
)
480 while (sgCount
> 0 && dataSize
> 0) {
481 size_t size
= min_c(sgTable
->size
, dataSize
);
482 phys_addr_t address
= sgTable
->address
;
483 T_PORT(AHCIPortPrdTable(fController
, fIndex
, address
, size
));
484 FLOW("FillPrdTable: sg-entry addr %#" B_PRIxPHYSADDR
", size %lu\n",
487 ERROR("AHCIPort::FillPrdTable: data alignment error\n");
492 size_t bytes
= min_c(size
, PRD_MAX_DATA_LENGTH
);
493 if (*prdCount
== prdMax
) {
494 ERROR("AHCIPort::FillPrdTable: prd table exhausted\n");
497 FLOW("FillPrdTable: prd-entry %u, addr %p, size %lu\n",
498 *prdCount
, address
, bytes
);
500 prdTable
->dba
= LO32(address
);
501 prdTable
->dbau
= HI32(address
);
503 prdTable
->dbc
= bytes
- 1;
506 address
= address
+ bytes
;
512 if (*prdCount
== 0) {
513 ERROR("%s: count is 0\n", __func__
);
517 ERROR("AHCIPort::FillPrdTable: sg table %ld bytes too small\n",
526 AHCIPort::StartTransfer()
528 acquire_sem(fRequestSem
);
533 AHCIPort::WaitForTransfer(int* tfd
, bigtime_t timeout
)
535 status_t result
= acquire_sem_etc(fResponseSem
, 1, B_RELATIVE_TIMEOUT
,
538 cpu_status cpu
= disable_interrupts();
539 acquire_spinlock(&fSpinlock
);
540 fCommandsActive
&= ~1;
541 release_spinlock(&fSpinlock
);
542 restore_interrupts(cpu
);
544 result
= B_TIMED_OUT
;
557 AHCIPort::FinishTransfer()
559 release_sem(fRequestSem
);
564 AHCIPort::ScsiTestUnitReady(scsi_ccb
* request
)
566 TRACE("AHCIPort::ScsiTestUnitReady port %d\n", fIndex
);
567 request
->subsys_status
= SCSI_REQ_CMP
;
568 gSCSI
->finished(request
, 1);
573 AHCIPort::ScsiVPDInquiry(scsi_ccb
* request
, ata_device_infoblock
* ataData
)
575 TRACE("AHCIPort::ScsiVPDInquiry port %d\n", fIndex
);
577 const scsi_cmd_inquiry
* cmd
= (const scsi_cmd_inquiry
*)request
->cdb
;
579 size_t vpdDataLength
= 0;
580 status_t transactionResult
= B_ERROR
;
582 switch (cmd
->page_code
) {
583 case SCSI_PAGE_SUPPORTED_VPD
:
585 scsi_page_list vpdPageData
;
586 vpdDataLength
= sizeof(vpdPageData
);
588 vpdPageData
.page_code
= cmd
->page_code
;
589 // Our supported pages
590 vpdPageData
.page_length
= 1;
591 vpdPageData
.pages
[0] = SCSI_PAGE_BLOCK_LIMITS
;
593 transactionResult
= sg_memcpy(request
->sg_list
, request
->sg_count
,
594 &vpdPageData
, vpdDataLength
);
597 case SCSI_PAGE_BLOCK_LIMITS
:
599 scsi_page_block_limits vpdPageData
;
600 vpdDataLength
= sizeof(vpdPageData
);
602 vpdPageData
.page_code
= cmd
->page_code
;
603 vpdPageData
.max_unmap_lba_count
604 = ataData
->max_data_set_management_lba_range_blocks
;
606 transactionResult
= sg_memcpy(request
->sg_list
, request
->sg_count
,
607 &vpdPageData
, vpdDataLength
);
611 case SCSI_PAGE_BLOCK_DEVICE_CHARS
:
612 case SCSI_PAGE_LB_PROVISIONING
:
613 case SCSI_PAGE_REFERRALS
:
614 ERROR("VPD AHCI page %d not yet implemented!\n",
616 //request->subsys_status = SCSI_REQ_CMP;
617 request
->subsys_status
= SCSI_REQ_ABORTED
;
620 ERROR("unknown VPD page code!\n");
621 request
->subsys_status
= SCSI_REQ_ABORTED
;
625 if (transactionResult
< B_OK
) {
626 request
->subsys_status
= SCSI_DATA_RUN_ERR
;
628 request
->subsys_status
= SCSI_REQ_CMP
;
629 request
->data_resid
= request
->data_length
636 AHCIPort::ScsiInquiry(scsi_ccb
* request
)
638 TRACE("AHCIPort::ScsiInquiry port %d\n", fIndex
);
640 const scsi_cmd_inquiry
* cmd
= (const scsi_cmd_inquiry
*)request
->cdb
;
641 scsi_res_inquiry scsiData
;
642 ata_device_infoblock ataData
;
644 ASSERT(sizeof(ataData
) == 512);
647 TRACE("VPD inquiry page 0x%X\n", cmd
->page_code
);
648 if (!request
->data
|| request
->data_length
== 0) {
649 ERROR("invalid VPD request\n");
650 request
->subsys_status
= SCSI_REQ_ABORTED
;
651 gSCSI
->finished(request
, 1);
654 } else if (cmd
->page_code
) {
655 // page_code without evpd is invalid per SCSI spec
656 ERROR("page code 0x%X on non-VPD request\n", cmd
->page_code
);
657 request
->subsys_status
= SCSI_REQ_ABORTED
;
658 request
->device_status
= SCSI_STATUS_CHECK_CONDITION
;
659 // TODO: Sense ILLEGAL REQUEST + INVALID FIELD IN CDB?
660 gSCSI
->finished(request
, 1);
662 } else if (request
->data_length
< sizeof(scsiData
)) {
663 ERROR("invalid request\n");
664 request
->subsys_status
= SCSI_REQ_ABORTED
;
665 gSCSI
->finished(request
, 1);
670 sreq
.SetData(&ataData
, sizeof(ataData
));
671 sreq
.SetATACommand(fIsATAPI
672 ? ATA_COMMAND_IDENTIFY_PACKET_DEVICE
: ATA_COMMAND_IDENTIFY_DEVICE
);
673 ExecuteSataRequest(&sreq
);
674 sreq
.WaitForCompletion();
676 if ((sreq
.CompletionStatus() & ATA_STATUS_ERROR
) != 0) {
677 ERROR("identify device failed\n");
678 request
->subsys_status
= SCSI_REQ_CMP_ERR
;
679 gSCSI
->finished(request
, 1);
684 // Simulate SCSI VPD data.
685 ScsiVPDInquiry(request
, &ataData
);
686 gSCSI
->finished(request
, 1);
691 uint8* data = (uint8*)&ataData;
692 for (int i = 0; i < 512; i += 8) {
693 TRACE(" %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1],
694 data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]);
698 scsiData
.device_type
= fIsATAPI
699 ? ataData
.word_0
.atapi
.command_packet_set
: scsi_dev_direct_access
;
700 scsiData
.device_qualifier
= scsi_periph_qual_connected
;
701 scsiData
.device_type_modifier
= 0;
702 scsiData
.removable_medium
= ataData
.word_0
.ata
.removable_media_device
;
703 scsiData
.ansi_version
= 2;
704 scsiData
.ecma_version
= 0;
705 scsiData
.iso_version
= 0;
706 scsiData
.response_data_format
= 2;
707 scsiData
.term_iop
= false;
708 scsiData
.additional_length
= sizeof(scsi_res_inquiry
) - 4;
709 scsiData
.soft_reset
= false;
710 scsiData
.cmd_queue
= false;
711 scsiData
.linked
= false;
712 scsiData
.sync
= false;
713 scsiData
.write_bus16
= true;
714 scsiData
.write_bus32
= false;
715 scsiData
.relative_address
= false;
718 fSectorCount
= ataData
.SectorCount(fUse48BitCommands
, true);
719 fSectorSize
= ataData
.SectorSize();
720 fTrimSupported
= ataData
.data_set_management_support
;
721 fMaxTrimRangeBlocks
= B_LENDIAN_TO_HOST_INT16(
722 ataData
.max_data_set_management_lba_range_blocks
);
723 TRACE("lba %d, lba48 %d, fUse48BitCommands %d, sectors %" B_PRIu32
724 ", sectors48 %" B_PRIu64
", size %" B_PRIu64
"\n",
725 ataData
.dma_supported
!= 0, ataData
.lba48_supported
!= 0,
726 fUse48BitCommands
, ataData
.lba_sector_count
,
727 ataData
.lba48_sector_count
, fSectorCount
* fSectorSize
);
728 if (fTrimSupported
) {
729 if (fMaxTrimRangeBlocks
== 0)
730 fMaxTrimRangeBlocks
= 1;
733 bool deterministic
= ataData
.supports_deterministic_read_after_trim
;
734 TRACE("trim supported, %" B_PRIu32
" ranges blocks, reads are "
735 "%sdeterministic%s.\n", fMaxTrimRangeBlocks
,
736 deterministic
? "" : "non-", deterministic
737 ? (ataData
.supports_read_zero_after_trim
738 ? ", zero" : ", random") : "");
744 if (fSectorCount
< 0x0fffffff) {
745 TRACE("disabling 48 bit commands\n");
746 fUse48BitCommands
= 0;
750 char modelNumber
[sizeof(ataData
.model_number
) + 1];
751 char serialNumber
[sizeof(ataData
.serial_number
) + 1];
752 char firmwareRev
[sizeof(ataData
.firmware_revision
) + 1];
754 strlcpy(modelNumber
, ataData
.model_number
, sizeof(modelNumber
));
755 strlcpy(serialNumber
, ataData
.serial_number
, sizeof(serialNumber
));
756 strlcpy(firmwareRev
, ataData
.firmware_revision
, sizeof(firmwareRev
));
758 swap_words(modelNumber
, sizeof(modelNumber
) - 1);
759 swap_words(serialNumber
, sizeof(serialNumber
) - 1);
760 swap_words(firmwareRev
, sizeof(firmwareRev
) - 1);
762 TRACE("model number: %s\n", modelNumber
);
763 TRACE("serial number: %s\n", serialNumber
);
764 TRACE("firmware rev.: %s\n", firmwareRev
);
766 // There's not enough space to fit all of the data in. ATA has 40 bytes for
767 // the model number, 20 for the serial number and another 8 for the
768 // firmware revision. SCSI has room for 8 for vendor ident, 16 for product
769 // ident and another 4 for product revision.
770 size_t vendorLen
= strcspn(modelNumber
, " ");
771 if (vendorLen
>= sizeof(scsiData
.vendor_ident
))
772 vendorLen
= strcspn(modelNumber
, "-");
773 if (vendorLen
< sizeof(scsiData
.vendor_ident
)) {
774 // First we try to break things apart smartly.
775 snprintf(scsiData
.vendor_ident
, vendorLen
+ 1, "%s", modelNumber
);
776 size_t modelRemain
= (sizeof(modelNumber
) - vendorLen
);
777 if (modelRemain
> sizeof(scsiData
.product_ident
))
778 modelRemain
= sizeof(scsiData
.product_ident
);
779 memcpy(scsiData
.product_ident
, modelNumber
+ (vendorLen
+ 1),
782 // If we're unable to smartly break apart the vendor and model, just
783 // dumbly squeeze as much in as possible.
784 memcpy(scsiData
.vendor_ident
, modelNumber
, sizeof(scsiData
.vendor_ident
));
785 memcpy(scsiData
.product_ident
, modelNumber
+ 8,
786 sizeof(scsiData
.product_ident
));
788 // Take the last 4 digits of the serial number as product rev
789 size_t serialLen
= sizeof(scsiData
.product_rev
);
790 size_t serialOff
= sizeof(serialNumber
) - serialLen
;
791 memcpy(scsiData
.product_rev
, serialNumber
+ serialOff
, serialLen
);
793 if (sg_memcpy(request
->sg_list
, request
->sg_count
, &scsiData
,
794 sizeof(scsiData
)) < B_OK
) {
795 request
->subsys_status
= SCSI_DATA_RUN_ERR
;
797 request
->subsys_status
= SCSI_REQ_CMP
;
798 request
->data_resid
= request
->data_length
- sizeof(scsiData
);
800 gSCSI
->finished(request
, 1);
805 AHCIPort::ScsiSynchronizeCache(scsi_ccb
* request
)
807 //TRACE("AHCIPort::ScsiSynchronizeCache port %d\n", fIndex);
809 sata_request
* sreq
= new(std::nothrow
) sata_request(request
);
811 ERROR("out of memory when allocating sync request\n");
812 request
->subsys_status
= SCSI_REQ_ABORTED
;
813 gSCSI
->finished(request
, 1);
817 sreq
->SetATACommand(fUse48BitCommands
818 ? ATA_COMMAND_FLUSH_CACHE_EXT
: ATA_COMMAND_FLUSH_CACHE
);
819 ExecuteSataRequest(sreq
);
824 AHCIPort::ScsiReadCapacity(scsi_ccb
* request
)
826 TRACE("AHCIPort::ScsiReadCapacity port %d\n", fIndex
);
828 const scsi_cmd_read_capacity
* cmd
829 = (const scsi_cmd_read_capacity
*)request
->cdb
;
830 scsi_res_read_capacity scsiData
;
832 if (cmd
->pmi
|| cmd
->lba
|| request
->data_length
< sizeof(scsiData
)) {
833 TRACE("invalid request\n");
834 request
->subsys_status
= SCSI_REQ_ABORTED
;
835 gSCSI
->finished(request
, 1);
839 TRACE("SectorSize %" B_PRIu32
", SectorCount 0x%" B_PRIx64
"\n",
840 fSectorSize
, fSectorCount
);
842 scsiData
.block_size
= B_HOST_TO_BENDIAN_INT32(fSectorSize
);
844 if (fSectorCount
<= 0xffffffff)
845 scsiData
.lba
= B_HOST_TO_BENDIAN_INT32(fSectorCount
- 1);
847 scsiData
.lba
= 0xffffffff;
849 if (sg_memcpy(request
->sg_list
, request
->sg_count
, &scsiData
,
850 sizeof(scsiData
)) < B_OK
) {
851 request
->subsys_status
= SCSI_DATA_RUN_ERR
;
853 request
->subsys_status
= SCSI_REQ_CMP
;
854 request
->data_resid
= request
->data_length
- sizeof(scsiData
);
856 gSCSI
->finished(request
, 1);
861 AHCIPort::ScsiReadCapacity16(scsi_ccb
* request
)
863 TRACE("AHCIPort::ScsiReadCapacity16 port %d\n", fIndex
);
865 scsi_res_read_capacity_long scsiData
;
867 TRACE("SectorSize %" B_PRIu32
", SectorCount 0x%" B_PRIx64
"\n",
868 fSectorSize
, fSectorCount
);
870 scsiData
.block_size
= B_HOST_TO_BENDIAN_INT32(fSectorSize
);
871 scsiData
.lba
= B_HOST_TO_BENDIAN_INT64(fSectorCount
- 1);
873 if (sg_memcpy(request
->sg_list
, request
->sg_count
, &scsiData
,
874 sizeof(scsiData
)) < B_OK
) {
875 request
->subsys_status
= SCSI_DATA_RUN_ERR
;
877 request
->subsys_status
= SCSI_REQ_CMP
;
878 request
->data_resid
= request
->data_length
- sizeof(scsiData
);
880 gSCSI
->finished(request
, 1);
885 AHCIPort::ScsiReadWrite(scsi_ccb
* request
, uint64 lba
, size_t sectorCount
,
888 RWTRACE("[%lld] %ld ScsiReadWrite: position %llu, size %lu, isWrite %d\n",
889 system_time(), find_thread(NULL
), lba
* 512, sectorCount
* 512,
894 TRACE("write request ignored\n");
895 request
->subsys_status
= SCSI_REQ_CMP
;
896 request
->data_resid
= 0;
897 gSCSI
->finished(request
, 1);
902 ASSERT(request
->data_length
== sectorCount
* 512);
903 sata_request
* sreq
= new(std::nothrow
) sata_request(request
);
905 TRACE("out of memory when allocating read/write request\n");
906 request
->subsys_status
= SCSI_REQ_ABORTED
;
907 gSCSI
->finished(request
, 1);
911 if (fUse48BitCommands
) {
912 if (sectorCount
> 65536) {
913 panic("ahci: ScsiReadWrite length too large, %lu sectors",
916 if (lba
> MAX_SECTOR_LBA_48
)
917 panic("achi: ScsiReadWrite position too large for 48-bit LBA\n");
918 sreq
->SetATA48Command(
919 isWrite
? ATA_COMMAND_WRITE_DMA_EXT
: ATA_COMMAND_READ_DMA_EXT
,
922 if (sectorCount
> 256) {
923 panic("ahci: ScsiReadWrite length too large, %lu sectors",
926 if (lba
> MAX_SECTOR_LBA_28
)
927 panic("achi: ScsiReadWrite position too large for normal LBA\n");
928 sreq
->SetATA28Command(isWrite
929 ? ATA_COMMAND_WRITE_DMA
: ATA_COMMAND_READ_DMA
, lba
, sectorCount
);
932 ExecuteSataRequest(sreq
, isWrite
);
937 AHCIPort::ScsiUnmap(scsi_ccb
* request
, scsi_unmap_parameter_list
* unmapBlocks
)
939 // Determine how many blocks are supposed to be trimmed in total
940 uint32 scsiRangeCount
= B_BENDIAN_TO_HOST_INT16(
941 unmapBlocks
->block_data_length
) / sizeof(scsi_unmap_block_descriptor
);
943 dprintf("TRIM SCSI:\n");
944 for (uint32 i
= 0; i
< scsiRangeCount
; i
++) {
945 dprintf("[%3" B_PRIu32
"] %" B_PRIu64
" : %" B_PRIu32
"\n", i
,
946 (uint64
)B_BENDIAN_TO_HOST_INT64(unmapBlocks
->blocks
[i
].lba
),
947 (uint32
)B_BENDIAN_TO_HOST_INT32(unmapBlocks
->blocks
[i
].block_count
));
950 uint32 scsiIndex
= 0;
951 uint32 scsiLastBlocks
= 0;
952 uint32 maxLBARangeCount
= fMaxTrimRangeBlocks
* 512 / 8;
953 // 512 bytes per range block, 8 bytes per range
955 // Split the SCSI ranges into ATA ranges as large as allowed.
956 // We assume that the SCSI unmap ranges cannot be merged together
958 while (scsiIndex
< scsiRangeCount
) {
959 // Determine how many LBA ranges we need for the next chunk
960 uint32 lbaRangeCount
= 0;
961 for (uint32 i
= scsiIndex
; i
< scsiRangeCount
; i
++) {
962 uint32 scsiBlocks
= B_BENDIAN_TO_HOST_INT32(
963 unmapBlocks
->blocks
[i
].block_count
);
967 scsiBlocks
-= scsiLastBlocks
;
969 lbaRangeCount
+= (scsiBlocks
+ 65534) / 65535;
970 if (lbaRangeCount
>= maxLBARangeCount
) {
971 lbaRangeCount
= maxLBARangeCount
;
975 if (lbaRangeCount
== 0)
978 uint32 lbaRangesSize
= lbaRangeCount
* sizeof(uint64
);
979 uint64
* lbaRanges
= (uint64
*)malloc(lbaRangesSize
);
980 if (lbaRanges
== NULL
) {
981 ERROR("out of memory when allocating %" B_PRIu32
" unmap ranges\n",
983 request
->subsys_status
= SCSI_REQ_ABORTED
;
984 gSCSI
->finished(request
, 1);
988 MemoryDeleter
deleter(lbaRanges
);
990 for (uint32 lbaIndex
= 0;
991 scsiIndex
< scsiRangeCount
&& lbaIndex
< lbaRangeCount
;) {
992 uint64 scsiOffset
= B_BENDIAN_TO_HOST_INT64(
993 unmapBlocks
->blocks
[scsiIndex
].lba
) + scsiLastBlocks
;
994 uint32 scsiBlocksLeft
= B_BENDIAN_TO_HOST_INT32(
995 unmapBlocks
->blocks
[scsiIndex
].block_count
) - scsiLastBlocks
;
997 if (scsiBlocksLeft
== 0) {
998 // Ignore the rest of the ranges (they are empty)
999 scsiIndex
= scsiRangeCount
;
1003 while (scsiBlocksLeft
> 0 && lbaIndex
< lbaRangeCount
) {
1004 uint16 blocks
= scsiBlocksLeft
> 65535
1005 ? 65535 : (uint16
)scsiBlocksLeft
;
1006 lbaRanges
[lbaIndex
++] = B_HOST_TO_LENDIAN_INT64(
1007 ((uint64
)blocks
<< 48) | scsiOffset
);
1009 scsiOffset
+= blocks
;
1010 scsiLastBlocks
+= blocks
;
1011 scsiBlocksLeft
-= blocks
;
1014 if (scsiBlocksLeft
== 0) {
1020 dprintf("TRIM AHCI:\n");
1021 for (uint32 i
= 0; i
< lbaRangeCount
; i
++) {
1022 uint64 value
= B_HOST_TO_LENDIAN_INT64(lbaRanges
[i
]);
1023 dprintf("[%3" B_PRIu32
"] %" B_PRIu64
" : %" B_PRIu64
"\n", i
,
1024 value
& (((uint64
)1 << 48) - 1), value
>> 48);
1028 sreq
.SetATA48Command(ATA_COMMAND_DATA_SET_MANAGEMENT
, 0,
1029 (lbaRangesSize
+ 511) / 512);
1031 sreq
.SetData(lbaRanges
, lbaRangesSize
);
1033 ExecuteSataRequest(&sreq
);
1034 sreq
.WaitForCompletion();
1036 if ((sreq
.CompletionStatus() & ATA_STATUS_ERROR
) != 0) {
1037 ERROR("trim failed (%" B_PRIu32
" ranges)!\n", lbaRangeCount
);
1038 request
->subsys_status
= SCSI_REQ_CMP_ERR
;
1040 request
->subsys_status
= SCSI_REQ_CMP
;
1043 request
->data_resid
= 0;
1044 request
->device_status
= SCSI_STATUS_GOOD
;
1045 gSCSI
->finished(request
, 1);
1050 AHCIPort::ExecuteSataRequest(sata_request
* request
, bool isWrite
)
1052 FLOW("ExecuteAtaRequest port %d\n", fIndex
);
1058 if (request
->CCB() && request
->CCB()->data_length
) {
1059 FillPrdTable(fPRDTable
, &prdEntrys
, PRD_TABLE_ENTRY_COUNT
,
1060 request
->CCB()->sg_list
, request
->CCB()->sg_count
,
1061 request
->CCB()->data_length
);
1062 } else if (request
->Data() && request
->Size()) {
1063 FillPrdTable(fPRDTable
, &prdEntrys
, PRD_TABLE_ENTRY_COUNT
,
1064 request
->Data(), request
->Size());
1068 FLOW("prdEntrys %d\n", prdEntrys
);
1070 fCommandList
->prdtl_flags_cfl
= 0;
1071 fCommandList
->cfl
= 5; // 20 bytes, length in DWORDS
1072 memcpy((char*)fCommandTable
->cfis
, request
->FIS(), 20);
1074 // We some hide messages when the test unit ready active is clear
1075 // as empty removeable media resets constantly.
1076 fTestUnitReadyActive
= request
->IsTestUnitReady();
1078 if (request
->IsATAPI()) {
1079 // ATAPI PACKET is a 12 or 16 byte SCSI command
1080 memset((char*)fCommandTable
->acmd
, 0, 32);
1081 memcpy((char*)fCommandTable
->acmd
, request
->CCB()->cdb
,
1082 request
->CCB()->cdb_length
);
1083 fCommandList
->a
= 1;
1087 fCommandList
->w
= 1;
1088 fCommandList
->prdtl
= prdEntrys
;
1089 fCommandList
->prdbc
= 0;
1091 if (wait_until_clear(&fRegs
->tfd
, ATA_STATUS_BUSY
| ATA_STATUS_DATA_REQUEST
,
1093 ERROR("ExecuteAtaRequest port %d: device is busy\n", fIndex
);
1100 cpu_status cpu
= disable_interrupts();
1101 acquire_spinlock(&fSpinlock
);
1102 fCommandsActive
|= 1;
1104 FlushPostedWrites();
1105 release_spinlock(&fSpinlock
);
1106 restore_interrupts(cpu
);
1109 status_t status
= WaitForTransfer(&tfd
, 20000000);
1111 FLOW("Port %d sata request flow:\n", fIndex
);
1112 FLOW(" tfd %#x\n", tfd
);
1113 FLOW(" prdbc %ld\n", fCommandList
->prdbc
);
1114 FLOW(" ci 0x%08" B_PRIx32
"\n", fRegs
->ci
);
1115 FLOW(" is 0x%08" B_PRIx32
"\n", fRegs
->is
);
1116 FLOW(" serr 0x%08" B_PRIx32
"\n", fRegs
->serr
);
1119 TRACE("ci 0x%08" B_PRIx32 "\n", fRegs->ci);
1120 TRACE("ie 0x%08" B_PRIx32 "\n", fRegs->ie);
1121 TRACE("is 0x%08" B_PRIx32 "\n", fRegs->is);
1122 TRACE("cmd 0x%08" B_PRIx32 "\n", fRegs->cmd);
1123 TRACE("ssts 0x%08" B_PRIx32 "\n", fRegs->ssts);
1124 TRACE("sctl 0x%08" B_PRIx32 "\n", fRegs->sctl);
1125 TRACE("serr 0x%08" B_PRIx32 "\n", fRegs->serr);
1126 TRACE("sact 0x%08" B_PRIx32 "\n", fRegs->sact);
1127 TRACE("tfd 0x%08" B_PRIx32 "\n", fRegs->tfd);
1130 if (fPortReset
|| status
== B_TIMED_OUT
) {
1135 size_t bytesTransfered
= fCommandList
->prdbc
;
1139 if (status
== B_TIMED_OUT
) {
1140 ERROR("ExecuteAtaRequest port %d: device timeout\n", fIndex
);
1145 request
->Finish(tfd
, bytesTransfered
);
1150 AHCIPort::ScsiExecuteRequest(scsi_ccb
* request
)
1152 // TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);
1155 bool isWrite
= false;
1156 switch (request
->flags
& SCSI_DIR_MASK
) {
1158 ASSERT(request
->data_length
== 0);
1161 ASSERT(request
->data_length
> 0);
1165 ASSERT(request
->data_length
> 0);
1168 panic("CDB has invalid direction mask");
1171 // TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);
1173 sata_request
* sreq
= new(std::nothrow
) sata_request(request
);
1175 ERROR("out of memory when allocating atapi request\n");
1176 request
->subsys_status
= SCSI_REQ_ABORTED
;
1177 gSCSI
->finished(request
, 1);
1181 sreq
->SetATAPICommand(request
->data_length
);
1182 // uint8* data = (uint8*) sreq->ccb()->cdb;
1183 // for (int i = 0; i < 16; i += 8) {
1184 // 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]);
1186 ExecuteSataRequest(sreq
, isWrite
);
1190 if (request
->cdb
[0] == SCSI_OP_REQUEST_SENSE
) {
1191 panic("ahci: SCSI_OP_REQUEST_SENSE not yet supported\n");
1195 if (!fDevicePresent
) {
1196 TRACE("no device present on port %d\n", fIndex
);
1197 request
->subsys_status
= SCSI_DEV_NOT_THERE
;
1198 gSCSI
->finished(request
, 1);
1202 request
->subsys_status
= SCSI_REQ_CMP
;
1204 switch (request
->cdb
[0]) {
1205 case SCSI_OP_TEST_UNIT_READY
:
1206 ScsiTestUnitReady(request
);
1208 case SCSI_OP_INQUIRY
:
1209 ScsiInquiry(request
);
1211 case SCSI_OP_READ_CAPACITY
:
1212 ScsiReadCapacity(request
);
1214 case SCSI_OP_SERVICE_ACTION_IN
:
1215 if ((request
->cdb
[1] & 0x1f) == SCSI_SAI_READ_CAPACITY_16
)
1216 ScsiReadCapacity16(request
);
1218 request
->subsys_status
= SCSI_REQ_INVALID
;
1219 gSCSI
->finished(request
, 1);
1222 case SCSI_OP_SYNCHRONIZE_CACHE
:
1223 ScsiSynchronizeCache(request
);
1225 case SCSI_OP_READ_6
:
1226 case SCSI_OP_WRITE_6
:
1228 const scsi_cmd_rw_6
* cmd
= (const scsi_cmd_rw_6
*)request
->cdb
;
1229 uint32 position
= ((uint32
)cmd
->high_lba
<< 16)
1230 | ((uint32
)cmd
->mid_lba
<< 8) | (uint32
)cmd
->low_lba
;
1231 size_t length
= cmd
->length
!= 0 ? cmd
->length
: 256;
1232 bool isWrite
= request
->cdb
[0] == SCSI_OP_WRITE_6
;
1233 ScsiReadWrite(request
, position
, length
, isWrite
);
1236 case SCSI_OP_READ_10
:
1237 case SCSI_OP_WRITE_10
:
1239 const scsi_cmd_rw_10
* cmd
= (const scsi_cmd_rw_10
*)request
->cdb
;
1240 uint32 position
= B_BENDIAN_TO_HOST_INT32(cmd
->lba
);
1241 size_t length
= B_BENDIAN_TO_HOST_INT16(cmd
->length
);
1242 bool isWrite
= request
->cdb
[0] == SCSI_OP_WRITE_10
;
1244 ScsiReadWrite(request
, position
, length
, isWrite
);
1246 ERROR("AHCIPort::ScsiExecuteRequest error: transfer without "
1248 request
->subsys_status
= SCSI_REQ_INVALID
;
1249 gSCSI
->finished(request
, 1);
1253 case SCSI_OP_READ_12
:
1254 case SCSI_OP_WRITE_12
:
1256 const scsi_cmd_rw_12
* cmd
= (const scsi_cmd_rw_12
*)request
->cdb
;
1257 uint32 position
= B_BENDIAN_TO_HOST_INT32(cmd
->lba
);
1258 size_t length
= B_BENDIAN_TO_HOST_INT32(cmd
->length
);
1259 bool isWrite
= request
->cdb
[0] == SCSI_OP_WRITE_12
;
1261 ScsiReadWrite(request
, position
, length
, isWrite
);
1263 ERROR("AHCIPort::ScsiExecuteRequest error: transfer without "
1265 request
->subsys_status
= SCSI_REQ_INVALID
;
1266 gSCSI
->finished(request
, 1);
1270 case SCSI_OP_READ_16
:
1271 case SCSI_OP_WRITE_16
:
1273 const scsi_cmd_rw_16
* cmd
= (const scsi_cmd_rw_16
*)request
->cdb
;
1274 uint64 position
= B_BENDIAN_TO_HOST_INT64(cmd
->lba
);
1275 size_t length
= B_BENDIAN_TO_HOST_INT32(cmd
->length
);
1276 bool isWrite
= request
->cdb
[0] == SCSI_OP_WRITE_16
;
1278 ScsiReadWrite(request
, position
, length
, isWrite
);
1280 ERROR("AHCIPort::ScsiExecuteRequest error: transfer without "
1282 request
->subsys_status
= SCSI_REQ_INVALID
;
1283 gSCSI
->finished(request
, 1);
1289 const scsi_cmd_unmap
* cmd
= (const scsi_cmd_unmap
*)request
->cdb
;
1291 if (!fTrimSupported
) {
1292 ERROR("%s port %d: unsupported request opcode 0x%02x\n",
1293 __func__
, fIndex
, request
->cdb
[0]);
1294 request
->subsys_status
= SCSI_REQ_ABORTED
;
1295 gSCSI
->finished(request
, 1);
1299 scsi_unmap_parameter_list
* unmapBlocks
1300 = (scsi_unmap_parameter_list
*)request
->data
;
1301 if (unmapBlocks
== NULL
1302 || B_BENDIAN_TO_HOST_INT16(cmd
->length
) != request
->data_length
1303 || B_BENDIAN_TO_HOST_INT16(unmapBlocks
->data_length
)
1304 != request
->data_length
- 1) {
1305 ERROR("%s port %d: invalid unmap parameter data length\n",
1307 request
->subsys_status
= SCSI_REQ_ABORTED
;
1308 gSCSI
->finished(request
, 1);
1310 ScsiUnmap(request
, unmapBlocks
);
1315 ERROR("AHCIPort::ScsiExecuteRequest port %d unsupported request "
1316 "opcode 0x%02x\n", fIndex
, request
->cdb
[0]);
1317 request
->subsys_status
= SCSI_REQ_ABORTED
;
1318 gSCSI
->finished(request
, 1);
1324 AHCIPort::ScsiAbortRequest(scsi_ccb
* request
)
1326 return SCSI_REQ_CMP
;
1331 AHCIPort::ScsiTerminateRequest(scsi_ccb
* request
)
1333 return SCSI_REQ_CMP
;
1338 AHCIPort::ScsiResetDevice()
1340 return SCSI_REQ_CMP
;
1345 AHCIPort::ScsiGetRestrictions(bool* isATAPI
, bool* noAutoSense
,
1348 *isATAPI
= fIsATAPI
;
1349 *noAutoSense
= fIsATAPI
; // emulated auto sense for ATA, but not ATAPI
1350 *maxBlocks
= fUse48BitCommands
? 65536 : 256;
1351 TRACE("AHCIPort::ScsiGetRestrictions port %d: isATAPI %d, noAutoSense %d, "
1352 "maxBlocks %" B_PRIu32
"\n", fIndex
, *isATAPI
, *noAutoSense
,
1360 // Spec v1.3.1, §10.3.1 Start (PxCMD.ST)
1361 TRACE("%s: port %d\n", __func__
, fIndex
);
1363 if ((fRegs
->cmd
& PORT_CMD_ST
) != 0) {
1364 ERROR("%s: Starting port already running!\n", __func__
);
1368 if ((fRegs
->cmd
& PORT_CMD_FRE
) == 0) {
1369 ERROR("%s: Unable to start port without FRE enabled!\n", __func__
);
1373 // Clear DMA engine and wait for completion
1374 if (wait_until_clear(&fRegs
->cmd
, PORT_CMD_CR
, 500000) < B_OK
) {
1375 ERROR("%s: port %d error DMA engine still running\n", __func__
,
1380 fRegs
->cmd
|= PORT_CMD_ST
;
1381 FlushPostedWrites();
1389 TRACE("%s: port %d\n", __func__
, fIndex
);
1391 if ((fRegs
->cmd
& PORT_CMD_ST
) == 0) {
1392 // Port already disabled, carry on.
1393 TRACE("%s: port %d attempting to disable stopped port.\n",
1397 fRegs
->cmd
&= ~PORT_CMD_ST
;
1398 FlushPostedWrites();
1401 // Spec v1.3.1, §10.4.2 Port Reset - assume hung after 500 mil.
1402 // Clear DMA engine and wait for completion
1403 if (wait_until_clear(&fRegs
->cmd
, PORT_CMD_CR
, 500000) < B_OK
) {
1404 ERROR("%s: port %d error DMA engine still running\n", __func__
,
1414 AHCIPort::_ClearErrorRegister()
1417 fRegs
->serr
= fRegs
->serr
;
1418 FlushPostedWrites();