From d7c321236fb72c4044f75bbad7144ecc37cc0a1a Mon Sep 17 00:00:00 2001 From: Marcus Overhagen Date: Tue, 1 Jul 2008 22:04:33 +0000 Subject: [PATCH] Set transfer length when doing ATAPI transfers. Dump ATAPI command packet on error. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26205 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/busses/scsi/ahci/ahci_port.cpp | 2 +- .../kernel/busses/scsi/ahci/sata_request.cpp | 64 ++++++++++++------- .../kernel/busses/scsi/ahci/sata_request.h | 2 +- 3 files changed, 42 insertions(+), 26 deletions(-) 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 5e2211f968..e8e44b4875 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/ahci_port.cpp @@ -790,7 +790,7 @@ AHCIPort::ScsiExecuteRequest(scsi_ccb *request) // 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(); + sreq->set_atapi_cmd(request->data_length); // 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]); 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 25b0216779..8106fab670 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp +++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp @@ -84,47 +84,63 @@ sata_request::set_ata48_cmd(uint8 command, uint64 lba, uint16 sectorCount) void -sata_request::set_atapi_cmd() +sata_request::set_atapi_cmd(size_t transferLength) { fIsATAPI = true; set_ata_cmd(0xa0); - fFis[5] = 0xfe; - fFis[6] = 0xff; + if (1 /* isPIO */) { + if (transferLength == 0) + transferLength = 2; + else if (transferLength > 0xfffe) + transferLength = 0xfffe; + fFis[5] = transferLength & 0xff; + fFis[6] = (transferLength >> 8) & 0xff; + } } void sata_request::finish(int tfd, size_t bytesTransfered) { - if (tfd & ATA_ERR) - dprintf("ahci: sata_request::finish ATA_ERR set for command 0x%02x\n", fFis[2]); + if (tfd & (ATA_ERR | ATA_DF)) { + uint8 status = tfd & 0xff; + uint8 error = (tfd >> 8) & 0xff; + dprintf("ahci: sata_request::finish ATA command 0x%02x failed\n", fFis[2]); + dprintf("ahci: sata_request::finish status 0x%02x, error 0x%02x\n", status, error); + } + if (fCcb) { fCcb->data_resid = fCcb->data_length - bytesTransfered; fCcb->subsys_status = SCSI_REQ_CMP; if (tfd & (ATA_ERR | ATA_DF)) { - uint8 error = (tfd >> 8) & 0xff; - dprintf("ahci: sata_request::finish status 0x%02x, error 0x%02x\n", tfd & 0xff, error); + fCcb->subsys_status = SCSI_REQ_CMP_ERR; if (fIsATAPI) { - fCcb->subsys_status = SCSI_REQ_CMP_ERR; + dprintf("ahci: sata_request::finish ATAPI packet %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x (len %d)\n", + fCcb->cdb[0], fCcb->cdb[1], fCcb->cdb[2], fCcb->cdb[3], + fCcb->cdb[4], fCcb->cdb[5], fCcb->cdb[6], fCcb->cdb[7], + fCcb->cdb[8], fCcb->cdb[9], fCcb->cdb[10], fCcb->cdb[11], + fCcb->cdb[12], fCcb->cdb[13], fCcb->cdb[14], fCcb->cdb[15], + fCcb->cdb_length); fCcb->device_status = SCSI_STATUS_CHECK_CONDITION; } else { - fCcb->subsys_status = SCSI_REQ_CMP_ERR; - // TODO error handling goes here - } + // TODO ATA error handling goes here /* - if (error & 0x04) { // ABRT - fCcb->subsys_status = SCSI_REQ_ABORTED; - } else { - fCcb->device_status = SCSI_STATUS_CHECK_CONDITION; - fCcb->subsys_status |= SCSI_AUTOSNS_VALID; - fCcb->sense_resid = 0; //FIXME - scsi_sense *sense = (scsi_sense *)fCcb->sense; - sense->error_code = SCSIS_CURR_ERROR; - sense->sense_key = error >> 4; - sense->asc = 0; - sense->ascq = 0; - } + // TODO check ABORT bit if this is useful + if ((tfd >> 8) & 0x04) { // ABRT + fCcb->subsys_status = SCSI_REQ_ABORTED; + } else { + fCcb->device_status = SCSI_STATUS_CHECK_CONDITION; + fCcb->subsys_status |= SCSI_AUTOSNS_VALID; + fCcb->sense_resid = 0; //FIXME + scsi_sense *sense = (scsi_sense *)fCcb->sense; + sense->error_code = SCSIS_CURR_ERROR; + sense->sense_key = error >> 4; + sense->asc = 0; + sense->ascq = 0; + } */ + } } gSCSI->finished(fCcb, 1); delete this; @@ -144,7 +160,7 @@ sata_request::abort() gSCSI->finished(fCcb, 1); delete this; } else { - fCompletionStatus = -1; + fCompletionStatus = ATA_ERR; release_sem(fCompletionSem); } } 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 9873fa8579..71532ab9ad 100644 --- a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h +++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h @@ -20,7 +20,7 @@ public: void set_ata28_cmd(uint8 command, uint32 lba, uint8 sectorCount); void set_ata48_cmd(uint8 command, uint64 lba, uint16 sectorCount); - void set_atapi_cmd(); + void set_atapi_cmd(size_t transferLength); bool is_atapi(); scsi_ccb * ccb();