The AHCI controller doesn't natively support ATAPI commands.
Instead, one needs to execute the ATA command 0xa0 (PACKET) using a normal ATA PIO FIS and in addition fill the SCSI CDB into the ACMD space to transfer the ATAPI PACKET command. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25597 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -286,8 +286,13 @@ AHCIPort::Interrupt()
|
||||
|
||||
RWTRACE("AHCIPort::Interrupt port %d, fCommandsActive 0x%08lx, is 0x%08lx, ci 0x%08lx\n", fIndex, fCommandsActive, is, ci);
|
||||
|
||||
if (is & PORT_INT_ERROR)
|
||||
if (is & PORT_INT_ERROR) {
|
||||
TRACE("AHCIPort::Interrupt port %d, fCommandsActive 0x%08lx, is 0x%08lx, ci 0x%08lx\n", fIndex, fCommandsActive, is, ci);
|
||||
TRACE("ssts 0x%08lx\n", fRegs->ssts);
|
||||
TRACE("sctl 0x%08lx\n", fRegs->sctl);
|
||||
TRACE("serr 0x%08lx\n", fRegs->serr);
|
||||
TRACE("sact 0x%08lx\n", fRegs->sact);
|
||||
}
|
||||
|
||||
if (is & PORT_INT_FATAL)
|
||||
panic("ahci fatal error, is 0x%08lx", is);
|
||||
@@ -565,11 +570,6 @@ AHCIPort::ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t sectorCount, bool
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fIsATAPI) {
|
||||
ScsiReadWriteATAPI(request, lba, sectorCount, isWrite);
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(request->data_length == sectorCount * 512);
|
||||
sata_request *sreq = new(std::nothrow) sata_request(request);
|
||||
|
||||
@@ -591,24 +591,6 @@ AHCIPort::ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t sectorCount, bool
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AHCIPort::ScsiReadWriteATAPI(scsi_ccb *request, uint64 lba, size_t sectorCount, bool isWrite)
|
||||
{
|
||||
TRACE("ScsiReadWriteATAPI lba %lld, sectorCount %ld, isWrite %d\n", lba, sectorCount, isWrite);
|
||||
|
||||
sata_request *sreq = new(std::nothrow) sata_request(request);
|
||||
|
||||
sreq->set_atapi12_cmd(request->cdb);
|
||||
|
||||
uint8 *data = (uint8*) sreq->fis();
|
||||
for (int i = 0; i < 16; i += 8) {
|
||||
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]);
|
||||
}
|
||||
|
||||
ExecuteSataRequest(sreq, isWrite);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
|
||||
{
|
||||
@@ -628,14 +610,13 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite)
|
||||
FLOW("prdEntrys %d\n", prdEntrys);
|
||||
|
||||
fCommandList->prdtl_flags_cfl = 0;
|
||||
fCommandList->cfl = request->fis_length() / 4; // length in DWORDS
|
||||
fCommandList->cfl = 5; // 20 bytes, length in DWORDS
|
||||
memcpy((char *)fCommandTable->cfis, request->fis(), 20);
|
||||
|
||||
if (request->fis_length() == 20) {
|
||||
// command fis is always 20 byte
|
||||
memcpy((char *)fCommandTable->cfis, request->fis(), 20);
|
||||
} else {
|
||||
if (request->is_atapi()) {
|
||||
// ATAPI PACKET is a 12 or 16 byte SCSI command
|
||||
memcpy((char *)fCommandTable->acmd, request->fis(), request->fis_length());
|
||||
memset((char *)fCommandTable->acmd, 0, 32);
|
||||
memcpy((char *)fCommandTable->acmd, request->ccb()->cdb, request->ccb()->cdb_length);
|
||||
fCommandList->a = 1;
|
||||
}
|
||||
|
||||
@@ -698,6 +679,30 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request)
|
||||
|
||||
// TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);
|
||||
|
||||
if (fIsATAPI && request->cdb[0] != SCSI_OP_INQUIRY) {
|
||||
bool isWrite;
|
||||
switch (request->cdb[0]) {
|
||||
case SCSI_OP_WRITE_6:
|
||||
case SCSI_OP_WRITE_10:
|
||||
case SCSI_OP_WRITE_12:
|
||||
isWrite = true;
|
||||
break;
|
||||
default:
|
||||
isWrite = false;
|
||||
}
|
||||
|
||||
TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length);
|
||||
|
||||
sata_request *sreq = new(std::nothrow) sata_request(request);
|
||||
sreq->set_atapi_cmd();
|
||||
uint8 *data = (uint8*) sreq->ccb()->cdb;
|
||||
for (int i = 0; i < 16; i += 8) {
|
||||
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]);
|
||||
}
|
||||
ExecuteSataRequest(sreq, isWrite);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request->cdb[0] == SCSI_OP_REQUEST_SENSE) {
|
||||
panic("ahci: SCSI_OP_REQUEST_SENSE not yet supported\n");
|
||||
return;
|
||||
|
||||
@@ -33,7 +33,6 @@ private:
|
||||
void ScsiInquiry(scsi_ccb *request);
|
||||
void ScsiReadCapacity(scsi_ccb *request);
|
||||
void ScsiReadWrite(scsi_ccb *request, uint64 lba, size_t sectorCount, bool isWrite);
|
||||
void ScsiReadWriteATAPI(scsi_ccb *request, uint64 lba, size_t sectorCount, bool isWrite);
|
||||
void ScsiSynchronizeCache(scsi_ccb *request);
|
||||
|
||||
void ExecuteSataRequest(sata_request *request, bool isWrite = false);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
sata_request::sata_request()
|
||||
: fCcb(NULL)
|
||||
, fFisLength(20)
|
||||
, fIsATAPI(false)
|
||||
, fCompletionSem(create_sem(0, "sata completion"))
|
||||
, fCompletionStatus(0)
|
||||
, fData(NULL)
|
||||
@@ -19,7 +19,7 @@ sata_request::sata_request()
|
||||
|
||||
sata_request::sata_request(scsi_ccb *ccb)
|
||||
: fCcb(ccb)
|
||||
, fFisLength(20)
|
||||
, fIsATAPI(false)
|
||||
, fCompletionSem(-1)
|
||||
, fCompletionStatus(0)
|
||||
, fData(NULL)
|
||||
@@ -83,36 +83,12 @@ sata_request::set_ata48_cmd(uint8 command, uint64 lba, uint16 sectorCount)
|
||||
|
||||
|
||||
void
|
||||
sata_request::set_atapi6_cmd(const void *cmd)
|
||||
sata_request::set_atapi_cmd()
|
||||
{
|
||||
memcpy(fFis, cmd, 6);
|
||||
memset(fFis + 6, 0, 6);
|
||||
fFisLength = 12;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sata_request::set_atapi10_cmd(const void *cmd)
|
||||
{
|
||||
memcpy(fFis, cmd, 10);
|
||||
memset(fFis + 10, 0, 2);
|
||||
fFisLength = 12;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sata_request::set_atapi12_cmd(const void *cmd)
|
||||
{
|
||||
memcpy(fFis, cmd, 12);
|
||||
fFisLength = 12;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sata_request::set_atapi16_cmd(const void *cmd)
|
||||
{
|
||||
memcpy(fFis, cmd, 16);
|
||||
fFisLength = 16;
|
||||
fIsATAPI = true;
|
||||
set_ata_cmd(0xa0);
|
||||
fFis[5] = 0xfe;
|
||||
fFis[6] = 0xff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,14 +20,11 @@ public:
|
||||
void set_ata28_cmd(uint8 command, uint32 lba, uint8 sectorCount);
|
||||
void set_ata48_cmd(uint8 command, uint64 lba, uint16 sectorCount);
|
||||
|
||||
void set_atapi6_cmd(const void *cmd);
|
||||
void set_atapi10_cmd(const void *cmd);
|
||||
void set_atapi12_cmd(const void *cmd);
|
||||
void set_atapi16_cmd(const void *cmd);
|
||||
void set_atapi_cmd();
|
||||
bool is_atapi();
|
||||
|
||||
scsi_ccb * ccb();
|
||||
const void * fis();
|
||||
int fis_length();
|
||||
void * data();
|
||||
int size();
|
||||
void finish(int tfd, size_t bytesTransfered);
|
||||
@@ -39,7 +36,7 @@ public:
|
||||
private:
|
||||
scsi_ccb * fCcb;
|
||||
uint8 fFis[20];
|
||||
int fFisLength;
|
||||
bool fIsATAPI;
|
||||
sem_id fCompletionSem;
|
||||
int fCompletionStatus;
|
||||
void * fData;
|
||||
@@ -61,10 +58,10 @@ sata_request::fis()
|
||||
}
|
||||
|
||||
|
||||
inline int
|
||||
sata_request::fis_length()
|
||||
inline bool
|
||||
sata_request::is_atapi()
|
||||
{
|
||||
return fFisLength;
|
||||
return fIsATAPI;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user