16bb01f71SMichael Lotz /* 26bb01f71SMichael Lotz * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. 36bb01f71SMichael Lotz * Distributed under the terms of the MIT License. 46bb01f71SMichael Lotz */ 56bb01f71SMichael Lotz 6bf9a3835SMichael Lotz #include "ATAPrivate.h" 7bf9a3835SMichael Lotz 8da4c9900SMichael Lotz ATARequest::ATARequest(bool hasLock) 9da4c9900SMichael Lotz : fHasLock(hasLock), 10da4c9900SMichael Lotz fDevice(NULL), 11bf9a3835SMichael Lotz fTimeout(0), 1233d80ba2SMichael Lotz fBytesLeft(0), 13bf9a3835SMichael Lotz fIsWrite(false), 14bf9a3835SMichael Lotz fUseDMA(false), 15bf9a3835SMichael Lotz fCCB(NULL) 16bf9a3835SMichael Lotz { 17da4c9900SMichael Lotz if (hasLock) 18da4c9900SMichael Lotz mutex_init(&fLock, "ata request"); 19da4c9900SMichael Lotz 20bf9a3835SMichael Lotz ClearSense(); 21bf9a3835SMichael Lotz } 22bf9a3835SMichael Lotz 23bf9a3835SMichael Lotz 24da4c9900SMichael Lotz ATARequest::~ATARequest() 25da4c9900SMichael Lotz { 26da4c9900SMichael Lotz if (fHasLock) 27da4c9900SMichael Lotz mutex_destroy(&fLock); 28da4c9900SMichael Lotz } 29da4c9900SMichael Lotz 30da4c9900SMichael Lotz 31bf9a3835SMichael Lotz void 32bf9a3835SMichael Lotz ATARequest::SetStatus(uint8 status) 33bf9a3835SMichael Lotz { 34bf9a3835SMichael Lotz fStatus = status; 35bf9a3835SMichael Lotz } 36bf9a3835SMichael Lotz 37bf9a3835SMichael Lotz 38bf9a3835SMichael Lotz void 39bf9a3835SMichael Lotz ATARequest::SetSense(uint8 key, uint16 codeQualifier) 40bf9a3835SMichael Lotz { 41bf9a3835SMichael Lotz fSenseKey = key; 42bf9a3835SMichael Lotz fSenseCode = (uint8)(codeQualifier >> 8); 43bf9a3835SMichael Lotz fSenseQualifier = (uint8)(codeQualifier & 0xff); 44bf9a3835SMichael Lotz } 45bf9a3835SMichael Lotz 46bf9a3835SMichael Lotz 47bf9a3835SMichael Lotz void 48bf9a3835SMichael Lotz ATARequest::ClearSense() 49bf9a3835SMichael Lotz { 50bf9a3835SMichael Lotz fSenseKey = fSenseCode = fSenseQualifier = 0; 51bf9a3835SMichael Lotz } 52bf9a3835SMichael Lotz 53bf9a3835SMichael Lotz 54bf9a3835SMichael Lotz void 55bf9a3835SMichael Lotz ATARequest::SetDevice(ATADevice *device) 56bf9a3835SMichael Lotz { 57bf9a3835SMichael Lotz fDevice = device; 58bf9a3835SMichael Lotz } 59bf9a3835SMichael Lotz 60bf9a3835SMichael Lotz 61bf9a3835SMichael Lotz void 62bf9a3835SMichael Lotz ATARequest::SetTimeout(bigtime_t timeout) 63bf9a3835SMichael Lotz { 64bf9a3835SMichael Lotz fTimeout = timeout; 65bf9a3835SMichael Lotz } 66bf9a3835SMichael Lotz 67bf9a3835SMichael Lotz 68bf9a3835SMichael Lotz void 69bf9a3835SMichael Lotz ATARequest::SetIsWrite(bool isWrite) 70bf9a3835SMichael Lotz { 71bf9a3835SMichael Lotz fIsWrite = isWrite; 72bf9a3835SMichael Lotz } 73bf9a3835SMichael Lotz 74bf9a3835SMichael Lotz 75bf9a3835SMichael Lotz void 76bf9a3835SMichael Lotz ATARequest::SetUseDMA(bool useDMA) 77bf9a3835SMichael Lotz { 78bf9a3835SMichael Lotz fUseDMA = useDMA; 79bf9a3835SMichael Lotz } 80bf9a3835SMichael Lotz 81bf9a3835SMichael Lotz 82bf9a3835SMichael Lotz void 8333d80ba2SMichael Lotz ATARequest::SetBytesLeft(uint32 bytesLeft) 84bf9a3835SMichael Lotz { 8533d80ba2SMichael Lotz fBytesLeft = bytesLeft; 86bf9a3835SMichael Lotz } 87bf9a3835SMichael Lotz 88bf9a3835SMichael Lotz 89bf9a3835SMichael Lotz status_t 90da4c9900SMichael Lotz ATARequest::Start(scsi_ccb *ccb) 91da4c9900SMichael Lotz { 92da4c9900SMichael Lotz if (mutex_trylock(&fLock) != B_OK) 93da4c9900SMichael Lotz return B_BUSY; 94da4c9900SMichael Lotz 95da4c9900SMichael Lotz fCCB = ccb; 96da4c9900SMichael Lotz fStatus = SCSI_REQ_CMP; 97*d102012dSMichael Lotz fCCB->device_status = SCSI_STATUS_GOOD; 9833d80ba2SMichael Lotz fIsWrite = false; 99da4c9900SMichael Lotz return B_OK; 100da4c9900SMichael Lotz } 101da4c9900SMichael Lotz 102da4c9900SMichael Lotz 103da4c9900SMichael Lotz status_t 104da4c9900SMichael Lotz ATARequest::Finish(bool resubmit) 105bf9a3835SMichael Lotz { 106bf9a3835SMichael Lotz // when the request completed and has set sense 107bf9a3835SMichael Lotz // data, report this to the scsi stack by setting 108bf9a3835SMichael Lotz // CHECK CONDITION status 109bf9a3835SMichael Lotz if (fStatus == SCSI_REQ_CMP && fSenseKey != 0) { 110bf9a3835SMichael Lotz TRACE("setting check condition\n"); 111bf9a3835SMichael Lotz 112bf9a3835SMichael Lotz fCCB->subsys_status = SCSI_REQ_CMP_ERR; 113bf9a3835SMichael Lotz fCCB->device_status = SCSI_STATUS_CHECK_CONDITION; 114bf9a3835SMichael Lotz 115bf9a3835SMichael Lotz // copy sense data if caller requested it 116bf9a3835SMichael Lotz if ((fCCB->flags & SCSI_DIS_AUTOSENSE) == 0) { 117bf9a3835SMichael Lotz // we cannot copy sense directly as sense buffer may be too small 118bf9a3835SMichael Lotz scsi_sense sense; 119bf9a3835SMichael Lotz _FillSense(&sense); 120bf9a3835SMichael Lotz 121bf9a3835SMichael Lotz size_t senseLength = MIN(sizeof(fCCB->sense), sizeof(sense)); 122bf9a3835SMichael Lotz memcpy(fCCB->sense, &sense, senseLength); 123bf9a3835SMichael Lotz fCCB->sense_resid = SCSI_MAX_SENSE_SIZE - senseLength; 124bf9a3835SMichael Lotz fCCB->subsys_status |= SCSI_AUTOSNS_VALID; 125bf9a3835SMichael Lotz ClearSense(); 126bf9a3835SMichael Lotz } 127bf9a3835SMichael Lotz } else 128bf9a3835SMichael Lotz fCCB->subsys_status = fStatus; 129bf9a3835SMichael Lotz 130da4c9900SMichael Lotz mutex_unlock(&fLock); 131118bb4e7SMichael Lotz 132bf9a3835SMichael Lotz if (resubmit) 133bf9a3835SMichael Lotz gSCSIModule->resubmit(fCCB); 134bf9a3835SMichael Lotz else 135bf9a3835SMichael Lotz gSCSIModule->finished(fCCB, 1); 136bf9a3835SMichael Lotz 137bf9a3835SMichael Lotz return B_OK; 138bf9a3835SMichael Lotz } 139bf9a3835SMichael Lotz 140bf9a3835SMichael Lotz 141bf9a3835SMichael Lotz void 142bf9a3835SMichael Lotz ATARequest::RequestSense() 143bf9a3835SMichael Lotz { 144bf9a3835SMichael Lotz // Copy sense data from last request into data buffer of current request. 145bf9a3835SMichael Lotz // The sense data of last request is still present in the current request, 146bf9a3835SMichael Lotz // as it isn't cleared on SCSI_OP_REQUEST_SENSE. 147bf9a3835SMichael Lotz scsi_sense sense; 148bf9a3835SMichael Lotz if (fSenseKey != 0) 149bf9a3835SMichael Lotz _FillSense(&sense); 150bf9a3835SMichael Lotz else 151bf9a3835SMichael Lotz memset(&sense, 0, sizeof(sense)); 152bf9a3835SMichael Lotz 153bf9a3835SMichael Lotz scsi_cmd_request_sense *command = (scsi_cmd_request_sense *)fCCB->cdb; 154bf9a3835SMichael Lotz copy_sg_data(fCCB, 0, command->allocation_length, &sense, sizeof(sense), 155bf9a3835SMichael Lotz false); 156bf9a3835SMichael Lotz 157bf9a3835SMichael Lotz fCCB->data_resid = fCCB->data_length - MIN(MIN(sizeof(sense), 158bf9a3835SMichael Lotz command->allocation_length), fCCB->data_length); 159bf9a3835SMichael Lotz ClearSense(); 160bf9a3835SMichael Lotz } 161bf9a3835SMichael Lotz 162bf9a3835SMichael Lotz 163bf9a3835SMichael Lotz void 164bf9a3835SMichael Lotz ATARequest::PrepareSGInfo() 165bf9a3835SMichael Lotz { 166bf9a3835SMichael Lotz fSGElementsLeft = fCCB->sg_count; 167bf9a3835SMichael Lotz fCurrentSGElement = fCCB->sg_list; 168bf9a3835SMichael Lotz fCurrentSGOffset = 0; 169bf9a3835SMichael Lotz fHasOddByte = false; 170bf9a3835SMichael Lotz fCCB->data_resid = fCCB->data_length; 171bf9a3835SMichael Lotz } 172bf9a3835SMichael Lotz 173bf9a3835SMichael Lotz 174bf9a3835SMichael Lotz void 175bf9a3835SMichael Lotz ATARequest::AdvanceSG(uint32 bytes) 176bf9a3835SMichael Lotz { 177bf9a3835SMichael Lotz uint32 bytesLeft = fCurrentSGElement->size - fCurrentSGOffset; 178bf9a3835SMichael Lotz if (bytesLeft <= bytes) { 179bf9a3835SMichael Lotz fCurrentSGOffset = 0; 180bf9a3835SMichael Lotz fCurrentSGElement++; 181bf9a3835SMichael Lotz fSGElementsLeft--; 182bf9a3835SMichael Lotz } else 183bf9a3835SMichael Lotz fCurrentSGOffset += bytes; 184bf9a3835SMichael Lotz } 185bf9a3835SMichael Lotz 186bf9a3835SMichael Lotz 187bf9a3835SMichael Lotz void 188bf9a3835SMichael Lotz ATARequest::SetOddByte(uint8 byte) 189bf9a3835SMichael Lotz { 190bf9a3835SMichael Lotz fOddByte = byte; 191bf9a3835SMichael Lotz fHasOddByte = true; 192bf9a3835SMichael Lotz } 193bf9a3835SMichael Lotz 194bf9a3835SMichael Lotz 195bf9a3835SMichael Lotz bool 196bf9a3835SMichael Lotz ATARequest::GetOddByte(uint8 *byte) 197bf9a3835SMichael Lotz { 198bf9a3835SMichael Lotz if (!fHasOddByte) 199bf9a3835SMichael Lotz return false; 200bf9a3835SMichael Lotz 201bf9a3835SMichael Lotz if (byte != NULL) 202bf9a3835SMichael Lotz *byte = fOddByte; 203bf9a3835SMichael Lotz 204bf9a3835SMichael Lotz fHasOddByte = false; 205bf9a3835SMichael Lotz return true; 206bf9a3835SMichael Lotz } 207bf9a3835SMichael Lotz 208bf9a3835SMichael Lotz 209bf9a3835SMichael Lotz void 210bf9a3835SMichael Lotz ATARequest::_FillSense(scsi_sense *sense) 211bf9a3835SMichael Lotz { 212bf9a3835SMichael Lotz memset(sense, 0, sizeof(*sense)); 213bf9a3835SMichael Lotz sense->error_code = SCSIS_CURR_ERROR; 214bf9a3835SMichael Lotz sense->sense_key = fSenseKey; 215bf9a3835SMichael Lotz sense->add_sense_length = sizeof(*sense) - 7; 216bf9a3835SMichael Lotz sense->asc = fSenseCode; 217bf9a3835SMichael Lotz sense->ascq = fSenseQualifier; 218bf9a3835SMichael Lotz sense->sense_key_spec.raw.SKSV = 0; // no additional info 219bf9a3835SMichael Lotz } 220