|
|
1.1 root 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: * AppleATAPio.cpp
25: *
26: */
27: #include "AppleATA.h"
28:
29: /*----------------------------------- ATA SetRegs Protocol ------------------------------*/
30:
31: /*
32: *
33: *
34: */
35: void AppleATA::doProtocolSetRegs( IOATACommand *cmd )
36: {
37: ATATaskfile taskfile;
38: UInt32 regmask;
39: UInt32 i;
40:
41: cmd->getTaskfile( &taskfile );
42:
43: regmask = taskfile.regmask;
44:
45: if ( regmask & ATARegtoMask(ataRegDriveHead) )
46: {
47: regmask &= ~ATARegtoMask(ataRegDriveHead);
48: if ( selectDrive( taskfile.ataRegs[ataRegDriveHead] ) == false )
49: {
50: completeCmd( cmd, ataReturnErrorBusy );
51: return;
52: }
53: }
54:
55: for ( i = 0; regmask; i++ )
56: {
57: if ( regmask & 1 )
58: {
59: writeATAReg( i, taskfile.ataRegs[i] );
60: }
61: regmask >>= 1;
62: }
63:
64: IODelay( 100 );
65:
66: completeCmd( cmd, ataReturnNoError );
67: }
68:
69: /*----------------------------------- ATA PIO Protocol ------------------------------*/
70:
71: /*
72: *
73: *
74: */
75: void AppleATA::doATAProtocolPio( IOATACommand *cmd )
76: {
77: ATATaskfile taskfile;
78: UInt32 regmask;
79: UInt32 i;
80: UInt32 status = 0;
81:
82: cmd->getTaskfile( &taskfile );
83:
84: regmask = taskfile.regmask;
85:
86: if ( regmask & ATARegtoMask(ataRegDriveHead) )
87: {
88: regmask &= ~ATARegtoMask(ataRegDriveHead);
89: if ( selectDrive( taskfile.ataRegs[ataRegDriveHead] ) == false )
90: {
91: completeCmd( cmd, ataReturnErrorBusy );
92: return;
93: }
94: }
95:
96: xferCount = 0;
97: cmd->getPointers( &xferDesc, &xferRemaining, &xferIsWrite );
98:
99: xferInts = ( xferRemaining ) ? xferRemaining / 512 : 1;
100:
101: if ( cmd->getTimeout() != 0 )
102: {
103: xferCmdTimer = cmd->getTimeout() / ATATimerIntervalmS + 1;
104: }
105:
106: for ( i = 0; regmask; i++ )
107: {
108: if ( regmask & 1 )
109: {
110: writeATAReg( i, taskfile.ataRegs[i] );
111: }
112: regmask >>= 1;
113: }
114:
115: if ( xferIsWrite )
116: {
117: do
118: {
119: status = readATAReg( ataRegStatus );
120: }
121: while ( !(status & ataStatusDRQ) );
122:
123: xferInts++;
124: interruptOccurred();
125: }
126: }
127:
128:
129: /*
130: *
131: *
132: */
133: void AppleATA::processATAPioInt()
134: {
135: UInt16 tmpBuffer[256];
136: UInt32 status;
137: UInt32 i;
138: ATAReturnCode rc = ataReturnNoError;
139: UInt32 reqCount;
140:
141: if ( waitForStatus( 0, ataStatusBSY, ataBusyTimeoutmS ) == false )
142: {
143: completeCmd( xferCmd, ataReturnErrorBusy, xferCount );
144: return;
145: }
146:
147: status = readATAReg( ataRegStatus );
148:
149: if ( status & ataStatusDRQ )
150: {
151: if ( xferIsWrite == true )
152: {
153: xferDesc->readBytes( xferCount, tmpBuffer, 512 );
154:
155: for ( i=0; i < 256; i++ )
156: {
157: writeATAReg( ataRegData, tmpBuffer[i] );
158: }
159: }
160: else
161: {
162: for ( i=0; i < 256; i++ )
163: {
164: tmpBuffer[i] = readATAReg( ataRegData );
165: }
166: xferDesc->writeBytes( xferCount, tmpBuffer, 512 );
167: }
168:
169: xferCount += 512;
170: xferRemaining -= 512;
171: }
172:
173: if ( status & ataStatusERR )
174: {
175: completeCmd( xferCmd, ataReturnErrorStatus, xferCount );
176: }
177: else if ( !--xferInts )
178: {
179: xferCmd->getPointers( 0, &reqCount, 0 );
180: if ( xferCount != reqCount )
181: {
182: rc = ataReturnErrorProtocol;
183: }
184:
185: completeCmd( xferCmd, rc, xferCount );
186: }
187: }
188:
189: /*----------------------------------- ATAPI PIO Protocols ------------------------------*/
190:
191: /*
192: *
193: *
194: *
195: */
196: void AppleATA::doATAPIProtocolPio( IOATACommand *cmd )
197: {
198: ATATaskfile taskfile;
199: ATAPICmd atapiCmd;
200: UInt16 *pCDB = NULL;
201: UInt32 regmask;
202: UInt32 status;
203: UInt32 i;
204:
205: xferCount = 0;
206:
207: cmd->getTaskfile( &taskfile );
208: cmd->getATAPICmd( &atapiCmd );
209:
210:
211: regmask = taskfile.regmask;
212:
213: if ( regmask & ATARegtoMask(ataRegDriveHead) )
214: {
215: regmask &= ~ATARegtoMask(ataRegDriveHead);
216: if ( selectDrive( taskfile.ataRegs[ataRegDriveHead] ) == false )
217: {
218: completeCmd( cmd, ataReturnErrorBusy );
219: return;
220: }
221: }
222:
223: xferInts = 1;
224:
225: if ( cmd->getTimeout() != 0 )
226: {
227: xferCmdTimer = cmd->getTimeout() / ATATimerIntervalmS + 1;
228: }
229:
230: for ( i = 0; regmask; i++ )
231: {
232: if ( regmask & 1 )
233: {
234: writeATAReg( i, taskfile.ataRegs[i] );
235: }
236: regmask >>= 1;
237: }
238:
239: xferCount = 0;
240: cmd->getPointers( &xferDesc, &xferRemaining, &xferIsWrite );
241:
242: if ( cmd->getDevice()->getATAPIPktInt() == false )
243: {
244: do
245: {
246: status = readATAReg( ataRegStatus );
247: }
248: while ( (status & atapiStatusBSY) || !(status & atapiStatusDRQ) );
249:
250: pCDB = (UInt16 *)atapiCmd.cdb;
251: for ( i = 0; i < atapiCmd.cdbLength >> 1; i++ )
252: {
253: writeATAReg( ataRegData, *pCDB++ );
254: }
255: }
256: }
257:
258: /*
259: *
260: *
261: */
262: void AppleATA::processATAPIPioInt()
263: {
264: ATAReturnCode rc = ataReturnErrorProtocol;
265: UInt32 status;
266: UInt32 intReason;
267: UInt32 n;
268:
269: if ( waitForStatus( 0, ataStatusBSY, ataBusyTimeoutmS ) == false )
270: {
271: completeCmd( xferCmd, ataReturnErrorBusy, xferCount );
272: return;
273: }
274:
275: status = readATAReg( atapiRegStatus );
276: intReason = readATAReg( atapiRegIntReason );
277:
278: if ( !xferInts ) return;
279:
280: if ( status & atapiStatusDRQ )
281: {
282: if ( intReason & atapiIntReasonCD )
283: {
284: if ( !(intReason & atapiIntReasonIO) )
285: {
286: rc = sendATAPIPacket();
287: }
288: }
289: else
290: {
291: n = readATAReg( atapiRegByteCountLow ) | (readATAReg( atapiRegByteCountHigh ) << 8);
292: n = (n+1) & ~0x01;
293:
294: if ( !(intReason & atapiIntReasonIO) && (xferIsWrite == true) )
295: {
296: rc = writeATAPIDevice( n );
297: }
298: else if ( (intReason & atapiIntReasonIO) && (xferIsWrite == false) )
299: {
300: rc = readATAPIDevice( n );
301: }
302: }
303: }
304: else if ( (intReason & atapiIntReasonCD) && (intReason & atapiIntReasonIO) )
305: {
306: xferInts = 0;
307: rc = (status & atapiStatusCHK) ? ataReturnErrorStatus : ataReturnNoError;
308:
309: if ( rc == ataReturnErrorStatus )
310: {
311: updateCmdStatus( xferCmd, rc, xferCount );
312:
313: if ( doRequestSense( xferCmd ) == false )
314: {
315: completeCmd( xferCmd );
316: }
317: }
318: else
319: {
320: completeCmd( xferCmd, rc, xferCount );
321: }
322: }
323: }
324:
325: /*
326: *
327: *
328: */
329: ATAReturnCode AppleATA::sendATAPIPacket()
330: {
331: UInt32 i;
332: ATAPICmd atapiCmd;
333: UInt16 *pCDB;
334:
335: xferCmd->getATAPICmd( &atapiCmd );
336:
337: pCDB = (UInt16 *)atapiCmd.cdb;
338: for ( i=0; i < atapiCmd.cdbLength >> 1; i++ )
339: {
340: writeATAReg( ataRegData, *pCDB++ );
341: }
342: return ataReturnNoError;
343: }
344:
345:
346: /*
347: *
348: *
349: */
350: ATAReturnCode AppleATA::readATAPIDevice( UInt32 n )
351: {
352: UInt16 tmpBuffer[256];
353: UInt32 i,j,k;
354:
355: while ( n )
356: {
357: j = (n < 512) ? n : 512;
358:
359: j >>= 1;
360: for ( i=0; i < j; i++ )
361: {
362: tmpBuffer[i] = readATAReg( ataRegData );
363: }
364: j <<= 1;
365: n -= j;
366:
367: k = (j > xferRemaining ) ? xferRemaining : j;
368:
369: xferDesc->writeBytes( xferCount, tmpBuffer, k );
370:
371: xferCount += k;
372: xferRemaining -= k;
373: }
374:
375: return ataReturnNoError;
376: }
377:
378: /*
379: *
380: *
381: */
382: ATAReturnCode AppleATA::writeATAPIDevice( UInt32 n )
383: {
384: UInt16 tmpBuffer[256];
385: UInt32 i,j,k;
386:
387:
388: while ( n )
389: {
390: j = (n < 512) ? n : 512;
391:
392: k = (j > xferRemaining ) ? xferRemaining : j;
393:
394: xferDesc->readBytes( xferCount, tmpBuffer, k );
395:
396: j >>= 1;
397: for ( i=0; i < j; i++ )
398: {
399: writeATAReg( ataRegData, tmpBuffer[i] );
400: }
401: j <<= 1;
402: n -= j;
403:
404: xferCount += k;
405: xferRemaining -= k;
406: }
407:
408: return ataReturnNoError;
409: }
410:
411:
412: /*
413: *
414: *
415: */
416: bool AppleATA::selectDrive( UInt32 driveHeadReg )
417: {
418: bool isBusy = true;
419: UInt32 i;
420: UInt32 status;
421:
422: writeATAReg( ataRegDriveHead, driveHeadReg );
423:
424: for ( i=0; i < 10; i++ )
425: {
426: status = readATAReg( ataRegStatus );
427: isBusy = ((status & ataStatusBSY) != 0);
428: if ( isBusy == false )
429: {
430: break;
431: }
432: IODelay( 10 );
433: }
434:
435: return !isBusy;
436: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.