2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
24 * IOATAStandardCommand.cpp
28 #include <IOKit/IOSyncer.h>
30 #include <IOKit/ata/IOATAStandardInterface.h>
31 #include <libkern/OSAtomic.h>
34 #define super IOATACommand
36 OSDefineMetaClassAndStructors( IOATAStandardCommand
, IOATACommand
)
37 OSDefineMetaClassAndAbstractStructors( IOATACommand
, IOCDBCommand
)
39 IOATADevice
*IOATAStandardCommand::getDevice(IOATADevice
*)
41 return (IOATADevice
*)device
;
44 IOATAStandardDevice
*IOATAStandardCommand::getDevice(IOATAStandardDevice
*)
49 void *IOATAStandardCommand::getClientData()
54 void *IOATAStandardCommand::getCommandData()
56 return commandPrivateData
;
59 UInt32
IOATAStandardCommand::getCmdType()
64 IOATAStandardCommand
*IOATAStandardCommand::getOriginalCmd()
69 UInt32
IOATAStandardCommand::getSequenceNumber()
71 return sequenceNumber
;
74 ATAUnit
IOATAStandardCommand::getUnit()
79 void IOATAStandardCommand::setTaskfile( ATATaskfile
*srcTaskfile
)
81 taskfile
= *srcTaskfile
;
84 void IOATAStandardCommand::getTaskfile( ATATaskfile
*dstTaskfile
)
86 *dstTaskfile
= taskfile
;
89 UInt32
IOATAStandardCommand::getFlags()
91 return taskfile
.flags
;
94 ATAProtocol
IOATAStandardCommand::getProtocol()
96 return taskfile
.protocol
;
99 UInt32
IOATAStandardCommand::getResultMask()
101 return taskfile
.resultmask
;
105 void IOATAStandardCommand::setTimeout( UInt32 timeoutMS
)
110 UInt32
IOATAStandardCommand::getTimeout()
116 void IOATAStandardCommand::setResults( ATAResults
*srcResults
)
118 results
= *srcResults
;
120 if ( getCmdType() == kATACommandExecute
)
122 if ( results
.bytesTransferred
< xferCount
)
124 if ( results
.returnCode
== kIOReturnSuccess
)
126 results
.returnCode
= kIOReturnUnderrun
;
132 IOReturn
IOATAStandardCommand::getResults( ATAResults
*dstResults
)
134 if ( dstResults
!= 0 )
136 *dstResults
= results
;
139 return results
.returnCode
;
142 void IOATAStandardCommand::setQueueInfo( UInt32 forQueueType
, UInt32 forQueuePosition
)
144 queueType
= forQueueType
;
145 queuePosition
= forQueuePosition
;
148 void IOATAStandardCommand::getQueueInfo( UInt32
*forQueueType
, UInt32
*forQueuePosition
= 0 )
150 if ( forQueueType
!= 0 ) *forQueueType
= queueType
;
151 if ( forQueuePosition
!= 0 ) *forQueuePosition
= queuePosition
;
154 void IOATAStandardCommand::setPointers( IOMemoryDescriptor
*clientDesc
, UInt32 transferCount
, bool isWrite
, bool isSense
= false )
156 if ( isSense
== false )
158 xferDesc
= clientDesc
;
159 xferCount
= transferCount
;
160 xferDirection
= isWrite
;
164 senseData
= clientDesc
;
165 senseLength
= transferCount
;
169 void IOATAStandardCommand::getPointers( IOMemoryDescriptor
**clientDesc
, UInt32
*transferCount
, bool *isWrite
, bool isSense
= false )
171 if ( clientDesc
!= NULL
)
173 *clientDesc
= (isSense
== false) ? xferDesc
: senseData
;
176 if ( transferCount
!= NULL
)
178 *transferCount
= (isSense
== false) ? xferCount
: senseLength
;
181 if ( isWrite
!= NULL
)
183 *isWrite
= (isSense
== false) ? xferDirection
: false;
187 void IOATAStandardCommand::setCDB( ATACDBInfo
*clientATACmd
)
189 ataCmd
= *clientATACmd
;
192 void IOATAStandardCommand::getCDB( ATACDBInfo
*clientATACmd
)
194 *clientATACmd
= ataCmd
;
197 void IOATAStandardCommand::setCallback( void *clientTarget
, CallbackFn clientATADoneFn
, void *clientRefcon
)
199 completionInfo
.async
.target
= clientTarget
;
200 completionInfo
.async
.callback
= clientATADoneFn
;
201 completionInfo
.async
.refcon
= clientRefcon
;
204 bool IOATAStandardCommand::execute( UInt32
*cmdSequenceNumber
)
210 sequenceNumber
= OSIncrementAtomic( (SInt32
*)&controller
->sequenceNumber
);
212 while ( sequenceNumber
== 0 );
214 if ( cmdSequenceNumber
!= 0 )
216 *cmdSequenceNumber
= sequenceNumber
;
219 list
= (queue_head_t
*)device
->deviceGate
;
221 isSync
= (completionInfo
.async
.callback
== 0);
225 completionInfo
.sync
.lock
= IOSyncer::create();
228 device
->submitCommand( kATACommandExecute
, this );
232 completionInfo
.sync
.lock
->wait();
239 void IOATAStandardCommand::abort( UInt32 sequenceNumber
)
241 device
->submitCommand( kATACommandAbort
, this, sequenceNumber
);
244 void IOATAStandardCommand::complete()
248 device
->completeCommand( this );
252 controller
->completeCommand( this );
256 /*------------------- Generic CDB Interface -----------------------------------------------*/
258 void IOATAStandardCommand::getCDB( CDBInfo
*cdbInfo
)
260 ATACDBInfo ataCDBInfo
;
262 bzero( cdbInfo
, sizeof(CDBInfo
) );
264 getCDB( &ataCDBInfo
);
265 cdbInfo
->cdb
= ataCDBInfo
.cdb
;
266 cdbInfo
->cdbLength
= ataCDBInfo
.cdbLength
;
269 void IOATAStandardCommand::setCDB( CDBInfo
*cdbInfo
)
271 IOATAStandardDevice
*ataDevice
;
272 ATATimingProtocol ataTimingProtocol
;
273 ATACDBInfo ataCDBInfo
;
274 ATATaskfile ataTaskfile
;
276 ataDevice
= getDevice(kIOATAStandardDevice
);
278 if ( ataDevice
->getDeviceType() != kATADeviceATAPI
)
283 bzero( &ataTaskfile
, sizeof(ataTaskfile
) );
285 ataDevice
->getTimingSelected( &ataTimingProtocol
);
287 ataTaskfile
.regmask
= ATARegtoMask(kATARegATAPIDeviceSelect
)
288 | ATARegtoMask(kATARegATAPICommand
)
289 | ATARegtoMask(kATARegATAPIByteCountLow
)
290 | ATARegtoMask(kATARegATAPIByteCountHigh
)
291 | ATARegtoMask(kATARegATAPIFeatures
);
293 ataTaskfile
.ataRegs
[kATARegATAPICommand
] = kATACommandATAPIPacket
;
294 ataTaskfile
.ataRegs
[kATARegATAPIDeviceSelect
] = kATAModeLBA
| (getUnit() << 4);
296 if ( ataTimingProtocol
& ~kATATimingPIO
)
298 ataTaskfile
.protocol
= kATAProtocolATAPIDMA
;
299 ataTaskfile
.ataRegs
[kATARegATAPIFeatures
] = 0x01;
303 ataTaskfile
.protocol
= kATAProtocolATAPIPIO
;
304 ataTaskfile
.ataRegs
[kATARegATAPIByteCountLow
] = 0xfe;
305 ataTaskfile
.ataRegs
[kATARegATAPIByteCountHigh
] = 0xff;
308 setTaskfile( &ataTaskfile
);
310 bzero( &ataCDBInfo
, sizeof(ATACDBInfo
) );
312 ataCDBInfo
.cdbLength
= cdbInfo
->cdbLength
;
313 ataCDBInfo
.cdb
= cdbInfo
->cdb
;
314 setCDB( &ataCDBInfo
);
319 IOReturn
IOATAStandardCommand::getResults( CDBResults
*cdbResults
)
321 ATAResults ataResults
;
324 rc
= getResults( &ataResults
);
326 if ( cdbResults
!= 0 )
328 bzero( cdbResults
, sizeof(CDBResults
) );
330 cdbResults
->returnCode
= ataResults
.returnCode
;
331 cdbResults
->bytesTransferred
= ataResults
.bytesTransferred
;
332 cdbResults
->requestSenseDone
= ataResults
.returnCode
;
333 cdbResults
->requestSenseLength
= ataResults
.requestSenseLength
;
340 IOCDBDevice
*IOATAStandardCommand::getDevice( IOCDBDevice
* )
342 return (IOCDBDevice
*)device
;