AHCI: Begin simulating SCSI Inquiry with VPD data
* Needed for SCSI level access to trim maximum block sizes.
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -5,8 +5,12 @@
|
||||
#ifndef _AHCI_PORT_H
|
||||
#define _AHCI_PORT_H
|
||||
|
||||
|
||||
#include <ATAInfoBlock.h>
|
||||
|
||||
#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);
|
||||
|
||||
Reference in New Issue
Block a user