Update ACPICA to 20150818.
[haiku.git] / src / add-ons / kernel / bus_managers / ata / ATARequest.cpp
blobe8e5f189fb59c61011c7ceb95aa4aa1312020bf2
1 /*
2 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch.
3 * Distributed under the terms of the MIT License.
4 */
6 #include "ATAPrivate.h"
9 ATARequest::ATARequest(bool hasLock)
11 fHasLock(hasLock),
12 fDevice(NULL),
13 fTimeout(0),
14 fBytesLeft(0),
15 fIsWrite(false),
16 fUseDMA(false),
17 fCCB(NULL)
19 if (hasLock)
20 mutex_init(&fLock, "ata request");
22 ClearSense();
26 ATARequest::~ATARequest()
28 if (fHasLock)
29 mutex_destroy(&fLock);
33 void
34 ATARequest::SetStatus(uint8 status)
36 fStatus = status;
40 void
41 ATARequest::SetSense(uint8 key, uint16 codeQualifier)
43 fSenseKey = key;
44 fSenseCode = (uint8)(codeQualifier >> 8);
45 fSenseQualifier = (uint8)(codeQualifier & 0xff);
49 void
50 ATARequest::ClearSense()
52 fSenseKey = fSenseCode = fSenseQualifier = 0;
56 void
57 ATARequest::SetDevice(ATADevice *device)
59 fDevice = device;
63 void
64 ATARequest::SetTimeout(bigtime_t timeout)
66 fTimeout = timeout;
70 void
71 ATARequest::SetIsWrite(bool isWrite)
73 fIsWrite = isWrite;
77 void
78 ATARequest::SetUseDMA(bool useDMA)
80 fUseDMA = useDMA;
84 void
85 ATARequest::SetBytesLeft(uint32 bytesLeft)
87 fBytesLeft = bytesLeft;
91 status_t
92 ATARequest::Start(scsi_ccb *ccb)
94 if (mutex_trylock(&fLock) != B_OK)
95 return B_BUSY;
97 fCCB = ccb;
98 fStatus = SCSI_REQ_CMP;
99 fCCB->device_status = SCSI_STATUS_GOOD;
100 fIsWrite = false;
101 return B_OK;
105 status_t
106 ATARequest::Finish(bool resubmit)
108 // when the request completed and has set sense
109 // data, report this to the scsi stack by setting
110 // CHECK CONDITION status
111 if (fStatus == SCSI_REQ_CMP && fSenseKey != 0) {
112 TRACE("setting check condition\n");
114 fCCB->subsys_status = SCSI_REQ_CMP_ERR;
115 fCCB->device_status = SCSI_STATUS_CHECK_CONDITION;
117 // copy sense data if caller requested it
118 if ((fCCB->flags & SCSI_DIS_AUTOSENSE) == 0) {
119 // we cannot copy sense directly as sense buffer may be too small
120 scsi_sense sense;
121 _FillSense(&sense);
123 size_t senseLength = MIN(sizeof(fCCB->sense), sizeof(sense));
124 memcpy(fCCB->sense, &sense, senseLength);
125 fCCB->sense_resid = SCSI_MAX_SENSE_SIZE - senseLength;
126 fCCB->subsys_status |= SCSI_AUTOSNS_VALID;
127 ClearSense();
129 } else
130 fCCB->subsys_status = fStatus;
132 mutex_unlock(&fLock);
134 if (resubmit)
135 gSCSIModule->resubmit(fCCB);
136 else
137 gSCSIModule->finished(fCCB, 1);
139 return B_OK;
143 void
144 ATARequest::RequestSense()
146 // Copy sense data from last request into data buffer of current request.
147 // The sense data of last request is still present in the current request,
148 // as it isn't cleared on SCSI_OP_REQUEST_SENSE.
149 scsi_sense sense;
150 if (fSenseKey != 0)
151 _FillSense(&sense);
152 else
153 memset(&sense, 0, sizeof(sense));
155 scsi_cmd_request_sense *command = (scsi_cmd_request_sense *)fCCB->cdb;
156 copy_sg_data(fCCB, 0, command->allocation_length, &sense, sizeof(sense),
157 false);
159 fCCB->data_resid = fCCB->data_length - MIN(MIN(sizeof(sense),
160 command->allocation_length), fCCB->data_length);
161 ClearSense();
165 void
166 ATARequest::PrepareSGInfo()
168 fSGElementsLeft = fCCB->sg_count;
169 fCurrentSGElement = fCCB->sg_list;
170 fCurrentSGOffset = 0;
171 fHasOddByte = false;
172 fCCB->data_resid = fCCB->data_length;
176 void
177 ATARequest::AdvanceSG(uint32 bytes)
179 uint32 bytesLeft = fCurrentSGElement->size - fCurrentSGOffset;
180 if (bytesLeft <= bytes) {
181 fCurrentSGOffset = 0;
182 fCurrentSGElement++;
183 fSGElementsLeft--;
184 } else
185 fCurrentSGOffset += bytes;
189 void
190 ATARequest::SetOddByte(uint8 byte)
192 fOddByte = byte;
193 fHasOddByte = true;
197 bool
198 ATARequest::GetOddByte(uint8 *byte)
200 if (!fHasOddByte)
201 return false;
203 if (byte != NULL)
204 *byte = fOddByte;
206 fHasOddByte = false;
207 return true;
211 void
212 ATARequest::_FillSense(scsi_sense *sense)
214 memset(sense, 0, sizeof(*sense));
215 sense->error_code = SCSIS_CURR_ERROR;
216 sense->sense_key = fSenseKey;
217 sense->add_sense_length = sizeof(*sense) - 7;
218 sense->asc = fSenseCode;
219 sense->ascq = fSenseQualifier;
220 sense->sense_key_spec.raw.SKSV = 0; // no additional info