diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp index caef6ac8e8..82efc5b8d8 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -557,6 +557,69 @@ AHCIPort::ScsiTestUnitReady(scsi_ccb* request) } +void +AHCIPort::ScsiVPDInquiry(scsi_ccb* request, ata_device_infoblock* ataData) +{ + TRACE("AHCIPort::ScsiVPDInquiry port %d\n", fIndex); + + const scsi_cmd_inquiry* cmd = (const scsi_cmd_inquiry*)request->cdb; + + size_t vpdDataLength = 0; + status_t transactionResult = B_ERROR; + + switch (cmd->page_code) { + case SCSI_PAGE_SUPPORTED_VPD: + { + scsi_page_list vpdPageData; + vpdDataLength = sizeof(vpdPageData); + + vpdPageData.page_code = cmd->page_code; + // Our supported pages + vpdPageData.page_length = 1; + vpdPageData.pages[0] = SCSI_PAGE_BLOCK_LIMITS; + + transactionResult = sg_memcpy(request->sg_list, request->sg_count, + &vpdPageData, vpdDataLength); + break; + } + case SCSI_PAGE_BLOCK_LIMITS: + { + scsi_page_block_limits vpdPageData; + vpdDataLength = sizeof(vpdPageData); + + vpdPageData.page_code = cmd->page_code; + vpdPageData.max_unmap_lba_count + = ataData->max_data_set_management_lba_range_blocks; + + transactionResult = sg_memcpy(request->sg_list, request->sg_count, + &vpdPageData, vpdDataLength); + break; + } + case SCSI_PAGE_USN: + case SCSI_PAGE_BLOCK_DEVICE_CHARS: + case SCSI_PAGE_LB_PROVISIONING: + case SCSI_PAGE_REFERRALS: + ERROR("VPD AHCI page %d not yet implemented!\n", + cmd->page_code); + //request->subsys_status = SCSI_REQ_CMP; + request->subsys_status = SCSI_REQ_ABORTED; + return; + default: + ERROR("unknown VPD page code!\n"); + request->subsys_status = SCSI_REQ_ABORTED; + return; + } + + if (transactionResult < B_OK) { + request->subsys_status = SCSI_DATA_RUN_ERR; + } else { + request->subsys_status = SCSI_REQ_CMP; + request->data_resid = request->data_length + - vpdDataLength; + } +} + + void AHCIPort::ScsiInquiry(scsi_ccb* request) { @@ -568,11 +631,17 @@ AHCIPort::ScsiInquiry(scsi_ccb* request) ASSERT(sizeof(ataData) == 512); - if (cmd->evpd) - TRACE("VPD inquiry page %d\n", cmd->page_code); - else if (cmd->page_code) { + if (cmd->evpd) { + TRACE("VPD inquiry page 0x%X\n", cmd->page_code); + if (!request->data || request->data_length == 0) { + ERROR("invalid VPD request\n"); + request->subsys_status = SCSI_REQ_ABORTED; + gSCSI->finished(request, 1); + return; + } + } else if (cmd->page_code) { // page_code without evpd is invalid per SCSI spec - ERROR("page code %d on non-VPD request\n", cmd->page_code); + ERROR("page code 0x%X on non-VPD request\n", cmd->page_code); request->subsys_status = SCSI_REQ_ABORTED; request->device_status = SCSI_STATUS_CHECK_CONDITION; // TODO: Sense ILLEGAL REQUEST + INVALID FIELD IN CDB? @@ -599,6 +668,13 @@ AHCIPort::ScsiInquiry(scsi_ccb* request) return; } + if (cmd->evpd) { + // Simulate SCSI VPD data. + ScsiVPDInquiry(request, &ataData); + gSCSI->finished(request, 1); + return; + } + /* uint8* data = (uint8*)&ataData; for (int i = 0; i < 512; i += 8) { @@ -650,31 +726,6 @@ AHCIPort::ScsiInquiry(scsi_ccb* request) } } - if (cmd->evpd) { - switch (cmd->page_code) { - case SCSI_PAGE_SUPPORTED_VPD: - case SCSI_PAGE_USN: - case SCSI_PAGE_BLOCK_LIMITS: - //max_unmap_lba_count - // = ataData.max_data_set_management_lba_range_blocks; - //max_unmap_blk_count = - // = ataData.max_data_set_management_lba_range_blocks; - case SCSI_PAGE_BLOCK_DEVICE_CHARS: - case SCSI_PAGE_LB_PROVISIONING: - case SCSI_PAGE_REFERRALS: - ERROR("VPD AHCI page %d not yet implemented!\n", - cmd->page_code); - //request->subsys_status = SCSI_REQ_CMP; - request->subsys_status = SCSI_REQ_ABORTED; - gSCSI->finished(request, 1); - return; - } - ERROR("unknown VPD page code!\n"); - request->subsys_status = SCSI_REQ_ABORTED; - gSCSI->finished(request, 1); - return; - } - #if 0 if (fSectorCount < 0x0fffffff) { TRACE("disabling 48 bit commands\n"); diff --git a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h index 7ebb1fcc49..34cee69f80 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h @@ -5,8 +5,12 @@ #ifndef _AHCI_PORT_H #define _AHCI_PORT_H + +#include + #include "ahci_defs.h" + class AHCIController; class sata_request; @@ -32,6 +36,8 @@ public: private: void ScsiTestUnitReady(scsi_ccb *request); void ScsiInquiry(scsi_ccb *request); + void ScsiVPDInquiry(scsi_ccb* request, ata_device_infoblock* ataData); + void ScsiReadCapacity(scsi_ccb *request); void ScsiReadCapacity16(scsi_ccb *request); void ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t sectorCount, bool isWrite);