diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp new file mode 100644 index 0000000000..59f9d95db3 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.cpp @@ -0,0 +1,134 @@ +/* + * Copyright 2008, Marcus Overhagen. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "sata_request.h" +#include + +sata_request::sata_request() + : fCcb(NULL) + , fCompletionSem(create_sem(0, "sata completion")) + , fCompletionStatus(0) + , fData(NULL) + , fDataSize(0) +{ +} + + +sata_request::sata_request(scsi_ccb *ccb) + : fCcb(ccb) + , fCompletionSem(-1) + , fCompletionStatus(0) + , fData(NULL) + , fDataSize(0) +{ +} + + +sata_request::~sata_request() +{ + if (fCompletionSem >= 0) + delete_sem(fCompletionSem); +} + + +void +sata_request::set_data(void *data, size_t dataSize) +{ + if (fCcb) panic("wrong usage"); + fData = data; + fDataSize = dataSize; +} + + +void +sata_request::set_ata_cmd(uint8 command) +{ + memset(fFis, 0, sizeof(fFis)); + fFis[0] = 0x27; + fFis[1] = 0x80; + fFis[2] = command; +} + + +void +sata_request::set_ata28_cmd(uint8 command, uint32 lba, uint8 sectorCount) +{ + set_ata_cmd(command); + fFis[4] = lba & 0xff; + fFis[5] = (lba >> 8) & 0xff; + fFis[6] = (lba >> 16) & 0xff; + fFis[7] = 0x40 | ((lba >> 24) & 0x0f); + fFis[12] = sectorCount & 0xff; +} + + +void +sata_request::set_ata48_cmd(uint8 command, uint64 lba, uint16 sectorCount) +{ + set_ata_cmd(command); + fFis[4] = lba & 0xff; + fFis[5] = (lba >> 8) & 0xff; + fFis[6] = (lba >> 16) & 0xff; + fFis[7] = 0x40; + fFis[8] = (lba >> 24) & 0xff; + fFis[9] = (lba >> 32) & 0xff; + fFis[10] = (lba >> 40) & 0xff; + fFis[12] = sectorCount & 0xff; + fFis[13] = (sectorCount >> 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 (fCcb) { + fCcb->data_resid = fCcb->data_length - bytesTransfered; + fCcb->subsys_status = (tfd & ATA_ERR) ? SCSI_REQ_CMP_ERR : SCSI_REQ_CMP; + gSCSI->finished(fCcb, 1); + delete this; + } else { + fCompletionStatus = tfd; + release_sem(fCompletionSem); + } +} + + +void +sata_request::abort() +{ + dprintf("ahci: sata_request::abort called for command 0x%02x\n", fFis[2]); + if (fCcb) { + fCcb->subsys_status = SCSI_REQ_ABORTED; + gSCSI->finished(fCcb, 1); + delete this; + } else { + fCompletionStatus = -1; + release_sem(fCompletionSem); + } +} + + +void +sata_request::wait_for_completition() +{ + if (fCcb) panic("wrong usage"); + acquire_sem(fCompletionSem); +} + + +int +sata_request::completition_status() +{ + if (fCcb) panic("wrong usage"); + return fCompletionStatus; +} + + + + + + diff --git a/src/add-ons/kernel/busses/scsi/ahci/sata_request.h b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h new file mode 100644 index 0000000000..3b05001907 --- /dev/null +++ b/src/add-ons/kernel/busses/scsi/ahci/sata_request.h @@ -0,0 +1,71 @@ +/* + * Copyright 2008, Marcus Overhagen. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _SATA_REQUEST_H +#define _SATA_REQUEST_H + +#include "ahci_defs.h" + +class sata_request +{ +public: + sata_request(); + sata_request(scsi_ccb *ccb); + ~sata_request(); + + void set_data(void *data, size_t dataSize); + + void set_ata_cmd(uint8 command); + void set_ata28_cmd(uint8 command, uint32 lba, uint8 sectorCount); + void set_ata48_cmd(uint8 command, uint64 lba, uint16 sectorCount); + + scsi_ccb * ccb(); + const void * fis(); + void * data(); + int size(); + void finish(int tfd, size_t bytesTransfered); + void abort(); + + void wait_for_completition(); + int completition_status(); + +private: + scsi_ccb * fCcb; + uint8 fFis[20]; + sem_id fCompletionSem; + int fCompletionStatus; + void * fData; + size_t fDataSize; +}; + + +inline scsi_ccb * +sata_request::ccb() +{ + return fCcb; +} + + +inline const void * +sata_request::fis() +{ + return fFis; +} + + +inline void * +sata_request::data() +{ + return fData; +} + + +inline int +sata_request::size() +{ + return fDataSize; +} + + +#endif