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