]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOATAStandard/IOATAStandardDriverPio.cpp
d1b4c4c30609414c5d3da650fd1b097e2659803a
[apple/xnu.git] / iokit / Families / IOATAStandard / IOATAStandardDriverPio.cpp
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 /*
23 *
24 * IOATAStandardDriverPio.cpp
25 *
26 */
27 #include <IOKit/ata/IOATAStandardInterface.h>
28
29 /*----------------------------------- ATA SetRegs Protocol ------------------------------*/
30
31 /*
32 *
33 *
34 */
35 void IOATAStandardDriver::doProtocolSetRegs( IOATAStandardCommand *ataCmd )
36 {
37 ATATaskfile taskfile;
38 UInt32 regmask;
39 UInt32 i;
40
41 setCommandLimit( currentDevice, 1 );
42
43 ataCmd->getTaskfile( &taskfile );
44
45 regmask = taskfile.regmask;
46
47 if ( regmask & ATARegtoMask(kATARegDriveHead) )
48 {
49 regmask &= ~ATARegtoMask(kATARegDriveHead);
50 if ( selectDrive( taskfile.ataRegs[kATARegDriveHead] ) == false )
51 {
52 completeCmd( ataCmd, kATAReturnBusyError );
53 return;
54 }
55 }
56
57 for ( i = 0; regmask; i++ )
58 {
59 if ( regmask & 1 )
60 {
61 writeATAReg( i, taskfile.ataRegs[i] );
62 }
63 regmask >>= 1;
64 }
65
66 IODelay( 100 );
67
68 completeCmd( ataCmd, kATAReturnSuccess );
69 }
70
71 /*----------------------------------- ATA PIO Protocol ------------------------------*/
72
73 /*
74 *
75 *
76 */
77 void IOATAStandardDriver::doATAProtocolPio( IOATAStandardCommand *ataCmd )
78 {
79 ATATaskfile taskfile;
80 ATAReturnCode rc;
81 UInt32 regmask;
82 UInt32 i;
83
84 setCommandLimit( currentDevice, 1 );
85
86 ataCmd->getTaskfile( &taskfile );
87
88 regmask = taskfile.regmask;
89
90 if ( regmask & ATARegtoMask(kATARegDriveHead) )
91 {
92 regmask &= ~ATARegtoMask(kATARegDriveHead);
93 if ( selectDrive( taskfile.ataRegs[kATARegDriveHead] ) == false )
94 {
95 completeCmd( ataCmd, kATAReturnBusyError );
96 return;
97 }
98 }
99
100 xferCount = 0;
101 ataCmd->getPointers( &xferDesc, &xferRemaining, &xferIsWrite );
102
103 for ( i = 0; regmask; i++ )
104 {
105 if ( regmask & 1 )
106 {
107 writeATAReg( i, taskfile.ataRegs[i] );
108 }
109 regmask >>= 1;
110 }
111
112 if ( xferIsWrite )
113 {
114 rc = waitForDRQ( kATADRQTimeoutmS );
115 if ( rc != kATAReturnSuccess )
116 {
117 completeCmd( ataCmd, rc );
118 return;
119 }
120 interruptOccurred();
121 }
122 }
123
124
125 /*
126 *
127 *
128 */
129 void IOATAStandardDriver::processATAPioInt()
130 {
131 IOATAStandardCommand *ataCmd;
132 UInt16 tmpBuffer[256];
133 UInt32 status;
134 UInt32 i;
135 ATAReturnCode rc = kATAReturnSuccess;
136
137 ataCmd = findCommandWithNexus( currentDevice, (UInt32) -1 );
138 if ( ataCmd == 0 )
139 {
140 IOLog( "IOATAStandardDriver::processATAPioInt() - ATA Command not found\n\r" );
141 return;
142 }
143
144 if ( waitForStatus( 0, kATAStatusBSY, kATABusyTimeoutmS ) == false )
145 {
146 completeCmd( ataCmd, kATAReturnBusyError, xferCount );
147 return;
148 }
149
150 status = readATAReg( kATARegStatus );
151
152 if ( (status & kATAStatusDRQ) && (xferRemaining != 0) )
153 {
154 if ( xferIsWrite == true )
155 {
156 xferDesc->readBytes( xferCount, tmpBuffer, 512 );
157
158 for ( i=0; i < 256; i++ )
159 {
160 writeATAReg( kATARegData, tmpBuffer[i] );
161 }
162 }
163 else
164 {
165 for ( i=0; i < 256; i++ )
166 {
167 tmpBuffer[i] = readATAReg( kATARegData );
168 }
169 xferDesc->writeBytes( xferCount, tmpBuffer, 512 );
170 }
171
172 xferCount += 512;
173 xferRemaining -= 512;
174 }
175
176 if ( status & kATAStatusERR )
177 {
178 completeCmd( ataCmd, kATAReturnStatusError, xferCount );
179 }
180 else if ( !xferRemaining )
181 {
182 completeCmd( ataCmd, rc, xferCount );
183 }
184 }
185 /*----------------------------------- ATA Reset Protocol ------------------------------*/
186
187 /*
188 *
189 *
190 *
191 */
192 void IOATAStandardDriver::doATAReset( IOATAStandardCommand *ataCmd )
193 {
194
195 if ( resetCmd != 0 )
196 {
197 completeCmd( ataCmd, kATAReturnNoResource );
198 return;
199 }
200
201 if ( resetPollEvent == 0 )
202 {
203 resetPollEvent = IOTimerEventSource::timerEventSource( this,
204 (IOTimerEventSource::Action) &IOATAStandardDriver::checkATAResetComplete);
205
206 if ( (resetPollEvent == 0) || (getWorkLoop()->addEventSource( resetPollEvent ) != kIOReturnSuccess) )
207 {
208 completeCmd( ataCmd, kATAReturnNoResource );
209 return;
210 }
211 }
212
213 resetCmd = ataCmd;
214
215 clock_interval_to_deadline( resetCmd->getTimeout(), 1000000, &resetTimeout );
216
217 writeATAReg( kATARegDeviceControl, kATADevControlnIEN | kATADevControlSRST );
218 IODelay( 25 );
219 writeATAReg( kATARegDeviceControl, 0 );
220
221 IOSleep(5);
222
223 checkATAResetComplete();
224
225 return;
226 }
227
228 /*
229 *
230 *
231 *
232 */
233 void IOATAStandardDriver::checkATAResetComplete()
234 {
235 UInt32 status;
236 IOATAStandardCommand *ataCmd;
237 AbsoluteTime currentTime;
238 ATAReturnCode rc = kATAReturnSuccess;
239
240 do
241 {
242 status = readATAReg( kATARegStatus );
243
244 if ( (status & kATAStatusBSY) == 0 )
245 {
246 break;
247 }
248
249 clock_get_uptime( &currentTime );
250 if ( CMP_ABSOLUTETIME( &currentTime, &resetTimeout ) > 0 )
251 {
252 rc = kATAReturnBusyError;
253 break;
254 }
255
256 resetPollEvent->setTimeoutMS(kATAResetPollIntervalmS);
257 return;
258
259 } while ( 0 );
260
261 ataCmd = resetCmd;
262 resetCmd = 0;
263
264 if ( ataCmd->getCmdType() != kATACommandBusReset )
265 {
266 resetOccurred();
267 }
268
269 completeCmd( ataCmd, rc );
270 }
271
272
273 /*----------------------------------- ATAPI PIO Protocols ------------------------------*/
274
275 /*
276 *
277 *
278 *
279 */
280 void IOATAStandardDriver::doATAPIProtocolPio( IOATAStandardCommand *ataCmd )
281 {
282 ATATaskfile taskfile;
283 ATACDBInfo atapiCmd;
284 ATAReturnCode rc;
285 UInt32 regmask;
286 UInt32 i;
287
288 setCommandLimit( currentDevice, 1 );
289
290 xferCount = 0;
291
292 ataCmd->getTaskfile( &taskfile );
293 ataCmd->getCDB( &atapiCmd );
294
295 regmask = taskfile.regmask;
296
297 if ( regmask & ATARegtoMask(kATARegDriveHead) )
298 {
299 regmask &= ~ATARegtoMask(kATARegDriveHead);
300 if ( selectDrive( taskfile.ataRegs[kATARegDriveHead] ) == false )
301 {
302 completeCmd( ataCmd, kATAReturnBusyError );
303 return;
304 }
305 }
306
307 for ( i = 0; regmask; i++ )
308 {
309 if ( regmask & 1 )
310 {
311 writeATAReg( i, taskfile.ataRegs[i] );
312 }
313 regmask >>= 1;
314 }
315
316 xferCount = 0;
317 ataCmd->getPointers( &xferDesc, &xferRemaining, &xferIsWrite );
318
319 if ( ataCmd->getDevice(kIOATAStandardDevice)->getATAPIPktInt() == false )
320 {
321 rc = sendATAPIPacket( ataCmd );
322
323 if ( rc != kATAReturnSuccess )
324 {
325 completeCmd( ataCmd, rc );
326 return;
327 }
328 }
329 }
330
331 /*
332 *
333 *
334 */
335 void IOATAStandardDriver::processATAPIPioInt()
336 {
337 IOATAStandardCommand *ataCmd;
338 ATAReturnCode rc = kATAReturnProtocolError;
339 UInt32 status;
340 UInt32 intReason;
341 UInt32 n;
342
343 ataCmd = findCommandWithNexus( currentDevice, (UInt32) -1 );
344 if ( ataCmd == 0 )
345 {
346 IOLog( "IOATAStandardDriver::processATAPIPioInt() - ATA Command not found\n\r" );
347 return;
348 }
349
350 if ( waitForStatus( 0, kATAStatusBSY, kATABusyTimeoutmS ) == false )
351 {
352 completeCmd( ataCmd, kATAReturnBusyError, xferCount );
353 return;
354 }
355
356 status = readATAReg( kATARegATAPIStatus );
357 intReason = readATAReg( kATARegATAPIIntReason );
358
359 if ( status & kATAPIStatusDRQ )
360 {
361 if ( intReason & kATAPIIntReasonCD )
362 {
363 if ( !(intReason & kATAPIIntReasonIO) )
364 {
365 rc = sendATAPIPacket( ataCmd );
366 }
367 }
368 else
369 {
370 n = readATAReg( kATARegATAPIByteCountLow ) | (readATAReg( kATARegATAPIByteCountHigh ) << 8);
371 n = (n+1) & ~0x01;
372
373 if ( !(intReason & kATAPIIntReasonIO) && (xferIsWrite == true) )
374 {
375 rc = writeATAPIDevice( n );
376 }
377 else if ( (intReason & kATAPIIntReasonIO) && (xferIsWrite == false) )
378 {
379 rc = readATAPIDevice( n );
380 }
381 }
382 }
383 else if ( (intReason & kATAPIIntReasonCD) && (intReason & kATAPIIntReasonIO) )
384 {
385 rc = (status & kATAPIStatusCHK) ? kATAReturnStatusError : kATAReturnSuccess;
386 completeCmd( ataCmd, rc, xferCount );
387 }
388 }
389
390 /*
391 *
392 *
393 */
394 ATAReturnCode IOATAStandardDriver::sendATAPIPacket( IOATAStandardCommand *ataCmd )
395 {
396 UInt32 i;
397 ATACDBInfo atapiCmd;
398 UInt16 *pCDB;
399 ATAReturnCode rc;
400
401 ataCmd->getCDB( &atapiCmd );
402
403 rc = waitForDRQ( kATADRQTimeoutmS );
404 if ( rc != kATAReturnSuccess ) return rc;
405
406 pCDB = (UInt16 *)atapiCmd.cdb;
407 for ( i=0; i < atapiCmd.cdbLength >> 1; i++ )
408 {
409 writeATAReg( kATARegData, *pCDB++ );
410 }
411
412 return rc;
413 }
414
415
416 /*
417 *
418 *
419 */
420 ATAReturnCode IOATAStandardDriver::readATAPIDevice( UInt32 n )
421 {
422 UInt16 tmpBuffer[256];
423 UInt32 i,j,k;
424
425 while ( n )
426 {
427 j = (n < 512) ? n : 512;
428
429 j >>= 1;
430 for ( i=0; i < j; i++ )
431 {
432 tmpBuffer[i] = readATAReg( kATARegData );
433 }
434 j <<= 1;
435 n -= j;
436
437 k = (j > xferRemaining ) ? xferRemaining : j;
438
439 xferDesc->writeBytes( xferCount, tmpBuffer, k );
440
441 xferCount += k;
442 xferRemaining -= k;
443 }
444
445 return kATAReturnSuccess;
446 }
447
448 /*
449 *
450 *
451 */
452 ATAReturnCode IOATAStandardDriver::writeATAPIDevice( UInt32 n )
453 {
454 UInt16 tmpBuffer[256];
455 UInt32 i,j,k;
456
457
458 while ( n )
459 {
460 j = (n < 512) ? n : 512;
461
462 k = (j > xferRemaining ) ? xferRemaining : j;
463
464 xferDesc->readBytes( xferCount, tmpBuffer, k );
465
466 j >>= 1;
467 for ( i=0; i < j; i++ )
468 {
469 writeATAReg( kATARegData, tmpBuffer[i] );
470 }
471 j <<= 1;
472 n -= j;
473
474 xferCount += k;
475 xferRemaining -= k;
476 }
477
478 return kATAReturnSuccess;
479 }
480
481
482 /*
483 *
484 *
485 */
486 bool IOATAStandardDriver::selectDrive( UInt32 driveHeadReg )
487 {
488 if ( waitForAltStatus( 0, kATAStatusBSY, kATABusyTimeoutmS ) == false )
489 {
490 return false;
491 }
492
493 writeATAReg( kATARegDriveHead, driveHeadReg );
494
495 if ( waitForAltStatus( 0, kATAStatusBSY, kATABusyTimeoutmS ) == false )
496 {
497 return false;
498 }
499
500 return true;
501 }