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 12283b52f4..5bebd3d639 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -565,6 +565,11 @@ 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); @@ -586,6 +591,24 @@ 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) { @@ -604,9 +627,18 @@ AHCIPort::ExecuteSataRequest(sata_request *request, bool isWrite) FLOW("prdEntrys %d\n", prdEntrys); - memcpy((char *)fCommandTable->cfis, request->fis(), 20); fCommandList->prdtl_flags_cfl = 0; - fCommandList->cfl = 5; // length is 20 bytes, in DWORDS + fCommandList->cfl = request->fis_length() / 4; // length in DWORDS + + if (request->fis_length() == 20) { + // command fis is always 20 byte + memcpy((char *)fCommandTable->cfis, request->fis(), 20); + } else { + // ATAPI PACKET is a 12 or 16 byte SCSI command + memcpy((char *)fCommandTable->acmd, request->fis(), request->fis_length()); + fCommandList->a = 1; + } + if (isWrite) fCommandList->w = 1; fCommandList->prdtl = prdEntrys; 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 d640b4c933..176d0b5631 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.h @@ -33,6 +33,7 @@ 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); diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp index 59f9d95db3..8b17d67a1e 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp @@ -8,6 +8,7 @@ sata_request::sata_request() : fCcb(NULL) + , fFisLength(20) , fCompletionSem(create_sem(0, "sata completion")) , fCompletionStatus(0) , fData(NULL) @@ -18,6 +19,7 @@ sata_request::sata_request() sata_request::sata_request(scsi_ccb *ccb) : fCcb(ccb) + , fFisLength(20) , fCompletionSem(-1) , fCompletionStatus(0) , fData(NULL) @@ -80,6 +82,40 @@ sata_request::set_ata48_cmd(uint8 command, uint64 lba, uint16 sectorCount) } +void +sata_request::set_atapi6_cmd(const void *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; +} + + void sata_request::finish(int tfd, size_t bytesTransfered) { diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h index 3b05001907..3a21846da6 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h +++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h @@ -20,8 +20,14 @@ 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); + scsi_ccb * ccb(); const void * fis(); + int fis_length(); void * data(); int size(); void finish(int tfd, size_t bytesTransfered); @@ -33,6 +39,7 @@ public: private: scsi_ccb * fCcb; uint8 fFis[20]; + int fFisLength; sem_id fCompletionSem; int fCompletionStatus; void * fData; @@ -54,6 +61,13 @@ sata_request::fis() } +inline int +sata_request::fis_length() +{ + return fFisLength; +} + + inline void * sata_request::data() {