xref: /haiku/src/add-ons/kernel/bus_managers/ata/ATARequest.cpp (revision 8c8c904aca6e88d54c583b0c2742c56373f443b0)
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