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