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
|
void
|
||||||
AHCIPort::ScsiInquiry(scsi_ccb* request)
|
AHCIPort::ScsiInquiry(scsi_ccb* request)
|
||||||
{
|
{
|
||||||
@@ -568,11 +631,17 @@ AHCIPort::ScsiInquiry(scsi_ccb* request)
|
|||||||
|
|
||||||
ASSERT(sizeof(ataData) == 512);
|
ASSERT(sizeof(ataData) == 512);
|
||||||
|
|
||||||
if (cmd->evpd)
|
if (cmd->evpd) {
|
||||||
TRACE("VPD inquiry page %d\n", cmd->page_code);
|
TRACE("VPD inquiry page 0x%X\n", cmd->page_code);
|
||||||
else if (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
|
// 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->subsys_status = SCSI_REQ_ABORTED;
|
||||||
request->device_status = SCSI_STATUS_CHECK_CONDITION;
|
request->device_status = SCSI_STATUS_CHECK_CONDITION;
|
||||||
// TODO: Sense ILLEGAL REQUEST + INVALID FIELD IN CDB?
|
// TODO: Sense ILLEGAL REQUEST + INVALID FIELD IN CDB?
|
||||||
@@ -599,6 +668,13 @@ AHCIPort::ScsiInquiry(scsi_ccb* request)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd->evpd) {
|
||||||
|
// Simulate SCSI VPD data.
|
||||||
|
ScsiVPDInquiry(request, &ataData);
|
||||||
|
gSCSI->finished(request, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
uint8* data = (uint8*)&ataData;
|
uint8* data = (uint8*)&ataData;
|
||||||
for (int i = 0; i < 512; i += 8) {
|
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 0
|
||||||
if (fSectorCount < 0x0fffffff) {
|
if (fSectorCount < 0x0fffffff) {
|
||||||
TRACE("disabling 48 bit commands\n");
|
TRACE("disabling 48 bit commands\n");
|
||||||
|
|||||||
@@ -5,8 +5,12 @@
|
|||||||
#ifndef _AHCI_PORT_H
|
#ifndef _AHCI_PORT_H
|
||||||
#define _AHCI_PORT_H
|
#define _AHCI_PORT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <ATAInfoBlock.h>
|
||||||
|
|
||||||
#include "ahci_defs.h"
|
#include "ahci_defs.h"
|
||||||
|
|
||||||
|
|
||||||
class AHCIController;
|
class AHCIController;
|
||||||
class sata_request;
|
class sata_request;
|
||||||
|
|
||||||
@@ -32,6 +36,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
void ScsiTestUnitReady(scsi_ccb *request);
|
void ScsiTestUnitReady(scsi_ccb *request);
|
||||||
void ScsiInquiry(scsi_ccb *request);
|
void ScsiInquiry(scsi_ccb *request);
|
||||||
|
void ScsiVPDInquiry(scsi_ccb* request, ata_device_infoblock* ataData);
|
||||||
|
|
||||||
void ScsiReadCapacity(scsi_ccb *request);
|
void ScsiReadCapacity(scsi_ccb *request);
|
||||||
void ScsiReadCapacity16(scsi_ccb *request);
|
void ScsiReadCapacity16(scsi_ccb *request);
|
||||||
void ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t sectorCount, bool isWrite);
|
void ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t sectorCount, bool isWrite);
|
||||||
|
|||||||
Reference in New Issue
Block a user