1 /* 2 * Copyright 2008, Marcus Overhagen. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include "sata_request.h" 7 #include <string.h> 8 9 sata_request::sata_request() 10 : fCcb(NULL) 11 , fCompletionSem(create_sem(0, "sata completion")) 12 , fCompletionStatus(0) 13 , fData(NULL) 14 , fDataSize(0) 15 { 16 } 17 18 19 sata_request::sata_request(scsi_ccb *ccb) 20 : fCcb(ccb) 21 , fCompletionSem(-1) 22 , fCompletionStatus(0) 23 , fData(NULL) 24 , fDataSize(0) 25 { 26 } 27 28 29 sata_request::~sata_request() 30 { 31 if (fCompletionSem >= 0) 32 delete_sem(fCompletionSem); 33 } 34 35 36 void 37 sata_request::set_data(void *data, size_t dataSize) 38 { 39 if (fCcb) panic("wrong usage"); 40 fData = data; 41 fDataSize = dataSize; 42 } 43 44 45 void 46 sata_request::set_ata_cmd(uint8 command) 47 { 48 memset(fFis, 0, sizeof(fFis)); 49 fFis[0] = 0x27; 50 fFis[1] = 0x80; 51 fFis[2] = command; 52 } 53 54 55 void 56 sata_request::set_ata28_cmd(uint8 command, uint32 lba, uint8 sectorCount) 57 { 58 set_ata_cmd(command); 59 fFis[4] = lba & 0xff; 60 fFis[5] = (lba >> 8) & 0xff; 61 fFis[6] = (lba >> 16) & 0xff; 62 fFis[7] = 0x40 | ((lba >> 24) & 0x0f); 63 fFis[12] = sectorCount & 0xff; 64 } 65 66 67 void 68 sata_request::set_ata48_cmd(uint8 command, uint64 lba, uint16 sectorCount) 69 { 70 set_ata_cmd(command); 71 fFis[4] = lba & 0xff; 72 fFis[5] = (lba >> 8) & 0xff; 73 fFis[6] = (lba >> 16) & 0xff; 74 fFis[7] = 0x40; 75 fFis[8] = (lba >> 24) & 0xff; 76 fFis[9] = (lba >> 32) & 0xff; 77 fFis[10] = (lba >> 40) & 0xff; 78 fFis[12] = sectorCount & 0xff; 79 fFis[13] = (sectorCount >> 8) & 0xff; 80 } 81 82 83 void 84 sata_request::finish(int tfd, size_t bytesTransfered) 85 { 86 if (tfd & ATA_ERR) 87 dprintf("ahci: sata_request::finish ATA_ERR set for command 0x%02x\n", fFis[2]); 88 if (fCcb) { 89 fCcb->data_resid = fCcb->data_length - bytesTransfered; 90 fCcb->subsys_status = (tfd & ATA_ERR) ? SCSI_REQ_CMP_ERR : SCSI_REQ_CMP; 91 gSCSI->finished(fCcb, 1); 92 delete this; 93 } else { 94 fCompletionStatus = tfd; 95 release_sem(fCompletionSem); 96 } 97 } 98 99 100 void 101 sata_request::abort() 102 { 103 dprintf("ahci: sata_request::abort called for command 0x%02x\n", fFis[2]); 104 if (fCcb) { 105 fCcb->subsys_status = SCSI_REQ_ABORTED; 106 gSCSI->finished(fCcb, 1); 107 delete this; 108 } else { 109 fCompletionStatus = -1; 110 release_sem(fCompletionSem); 111 } 112 } 113 114 115 void 116 sata_request::wait_for_completition() 117 { 118 if (fCcb) panic("wrong usage"); 119 acquire_sem(fCompletionSem); 120 } 121 122 123 int 124 sata_request::completition_status() 125 { 126 if (fCcb) panic("wrong usage"); 127 return fCompletionStatus; 128 } 129 130 131 132 133 134 135