]> git.saurik.com Git - apple/xnu.git/blame - iokit/Families/IOATAStandard/IOATAStandardDriverDma.cpp
xnu-124.7.tar.gz
[apple/xnu.git] / iokit / Families / IOATAStandard / IOATAStandardDriverDma.cpp
CommitLineData
1c79356b
A
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 * IOATAStandardDriverDma.cpp
25 *
26 */
27#include <IOKit/ata/IOATAStandardInterface.h>
28
29/*----------------------------------- ATA DMA Protocol ------------------------------*/
30
31/*
32 *
33 *
34 */
35void IOATAStandardDriver::doATAProtocolDma( IOATAStandardCommand *cmd )
36{
37 ATATaskfile taskfile;
38 UInt32 regmask;
39 UInt32 i;
40
41 setCommandLimit( currentDevice, 1 );
42
43 cmd->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( cmd, kATAReturnBusyError );
53 return;
54 }
55 }
56
57 programDma( cmd );
58
59 for ( i = 0; regmask; i++ )
60 {
61 if ( regmask & 1 )
62 {
63 writeATAReg( i, taskfile.ataRegs[i] );
64 }
65 regmask >>= 1;
66 }
67
68 startDma( cmd );
69}
70
71/*
72 *
73 *
74 */
75void IOATAStandardDriver::processATADmaInt()
76{
77 UInt32 status;
78 UInt32 reqCount;
79 ATAReturnCode rc = kATAReturnSuccess;
80 IOATAStandardCommand *ataCmd;
81 UInt32 xferCount;
82
83 ataCmd = findCommandWithNexus( currentDevice, (UInt32) -1 );
84 if ( ataCmd == 0 )
85 {
86 IOLog( "IOATAStandardDriver::processATADmaInt() - ATA Command not found\n\r" );
87 return;
88 }
89
90 if ( waitForStatus( 0, kATAStatusBSY, kATABusyTimeoutmS ) == false )
91 {
92 stopDma( ataCmd, &xferCount );
93 completeCmd( ataCmd, kATAReturnBusyError, xferCount );
94 return;
95 }
96
97 status = readATAReg( kATARegStatus );
98
99 ataCmd->getPointers( 0, &reqCount, 0 );
100
101 if ( stopDma( ataCmd, &xferCount ) != true )
102 {
103 rc = kATAReturnDMAError;
104 }
105
106 else if ( status & kATAStatusDRQ )
107 {
108 rc = kATAReturnDMAError;
109 }
110
111 else if ( status & kATAStatusERR )
112 {
113 rc = kATAReturnStatusError;
114 }
115
116 else if ( reqCount != xferCount )
117 {
118 rc = kATAReturnProtocolError;
119 }
120
121 completeCmd( ataCmd, rc, xferCount );
122}
123
124/*----------------------------------- ATA DMA Queued Protocol ------------------------------*/
125
126/*
127 *
128 *
129 */
130void IOATAStandardDriver::doATAProtocolDmaQueued( IOATAStandardCommand *ataCmd )
131{
132 ATATaskfile taskfile;
133 UInt32 regmask;
134 UInt32 i;
135
136 if ( dmaActive == true )
137 {
138 setCommandLimit( currentDevice, 0 );
139 rescheduleCommand( ataCmd );
140 return;
141 }
142
143 setCommandLimit( currentDevice, 31 );
144
145 ataCmd->getTaskfile( &taskfile );
146
147 regmask = taskfile.regmask;
148
149 regmask &= ~(ATARegtoMask(kATARegDriveHead) | ATARegtoMask(kATARegCommand));
150
151 if ( selectDrive( taskfile.ataRegs[kATARegDriveHead] ) == false )
152 {
153 completeCmd( ataCmd, kATAReturnBusyError );
154 return;
155 }
156
157 programDma( ataCmd );
158 dmaActive = true;
159 startDma( ataCmd );
160
161 taskfile.ataRegs[kATARegSectorCount] = taskfile.tag << 3;
162
163 for ( i = 0; regmask; i++ )
164 {
165 if ( regmask & 1 )
166 {
167 writeATAReg( i, taskfile.ataRegs[i] );
168 }
169 regmask >>= 1;
170 }
171
172 writeATAReg( kATARegCommand, taskfile.ataRegs[kATARegCommand] );
173
174#if 1
175 IODelay( 1 );
176 waitForAltStatus( 0, kATAStatusBSY, kATABusyTimeoutmS );
177#endif
178}
179
180/*
181 *
182 *
183 */
184void IOATAStandardDriver::processATADmaQueuedInt()
185{
186 UInt32 status;
187 UInt32 intReason;
188 UInt32 tag;
189 UInt32 xferCount;
190 IOATAStandardCommand *ataCmd;
191 ATAReturnCode rc = kATAReturnSuccess;
192
193 while ( 1 )
194 {
195 status = readATAReg( kATARegStatus );
196 intReason = readATAReg( kATARegSectorCount );
197 tag = intReason / kATATagBit;
198
199 ataCmd = findCommandWithNexus( currentDevice, tag );
200
201 if ( (intReason & kATAPIIntReasonCD) && (intReason & kATAPIIntReasonIO) && (dmaActive == true) )
202 {
203 if ( ataCmd == 0 )
204 {
205 IOLog( "IOATAStandardDriver::processATADmaQueuedInt() - ATA Command not found\n\r" );
206 return;
207 }
208
209 dmaActive = false;
210
211 if ( stopDma( ataCmd, &xferCount ) != true )
212 {
213 rc = kATAReturnDMAError;
214 }
215
216 else if ( status & kATAStatusERR )
217 {
218 rc = kATAReturnStatusError;
219 }
220
221 completeCmd( ataCmd, rc, xferCount );
222 }
223
224 if ( (status & kATAStatusDRQ) != 0 )
225 {
226 if ( ataCmd == 0 )
227 {
228 IOLog( "IOATAStandardDriver::processATADmaQueuedInt() - ATA Command not found\n\r" );
229 return;
230 }
231
232 programDma( ataCmd );
233 dmaActive = true;
234 startDma( ataCmd );
235 break;
236 }
237
238 if ( status & kATAStatusSERV )
239 {
240 resetDma();
241
242 writeATAReg( kATARegCommand, kATACommandService );
243
244 if ( waitForAltStatus( 0, kATAStatusBSY, 500 ) == false )
245 {
246 return;
247 }
248 continue;
249 }
250
251 if ( dmaActive == false )
252 {
253 setCommandLimit( currentDevice, 31 );
254 }
255 break;
256 }
257
258}
259
260/*----------------------------------- ATAPI DMA Protocols ------------------------------*/
261
262/*
263 *
264 *
265 *
266 */
267void IOATAStandardDriver::doATAPIProtocolDma( IOATAStandardCommand *ataCmd )
268{
269 ATATaskfile taskfile;
270 ATACDBInfo atapiCmd;
271 ATAReturnCode rc;
272 UInt32 regmask;
273 UInt32 i;
274
275 setCommandLimit( currentDevice, 1 );
276
277 ataCmd->getTaskfile( &taskfile );
278 ataCmd->getCDB( &atapiCmd );
279
280 regmask = taskfile.regmask;
281
282 if ( regmask & ATARegtoMask(kATARegDriveHead) )
283 {
284 regmask &= ~ATARegtoMask(kATARegDriveHead);
285 if ( selectDrive( taskfile.ataRegs[kATARegDriveHead] ) == false )
286 {
287 completeCmd( ataCmd, kATAReturnBusyError);
288 return;
289 }
290 }
291
292 for ( i = 0; regmask; i++ )
293 {
294 if ( regmask & 1 )
295 {
296 writeATAReg( i, taskfile.ataRegs[i] );
297 }
298 regmask >>= 1;
299 }
300
301 programDma( ataCmd );
302
303 if ( ataCmd->getDevice(kIOATAStandardDevice)->getATAPIPktInt() == false )
304 {
305 rc = sendATAPIPacket( ataCmd );
306
307 if ( rc != kATAReturnSuccess )
308 {
309 completeCmd( ataCmd, rc );
310 return;
311 }
312
313 startDma( ataCmd );
314 }
315}
316
317
318/*
319 *
320 *
321 */
322void IOATAStandardDriver::processATAPIDmaInt()
323{
324 IOATAStandardCommand *ataCmd;
325 ATAReturnCode rc = kATAReturnProtocolError;
326 UInt32 status;
327 UInt32 intReason;
328 UInt32 xferCount;
329
330 ataCmd = findCommandWithNexus( currentDevice, (UInt32) -1 );
331 if ( ataCmd == 0 )
332 {
333 IOLog( "IOATAStandardDriver::processATAPIDmaInt() - ATA Command not found\n\r" );
334 return;
335 }
336
337 if ( waitForStatus( 0, kATAStatusBSY, kATABusyTimeoutmS ) == false )
338 {
339 completeCmd( ataCmd, kATAReturnBusyError, 0 );
340 return;
341 }
342
343 status = readATAReg( kATARegATAPIStatus );
344 intReason = readATAReg( kATARegATAPIIntReason );
345
346 if ( (status & kATAPIStatusDRQ) && (intReason & kATAPIIntReasonCD) && !(intReason & kATAPIIntReasonIO) )
347 {
348 rc = sendATAPIPacket( ataCmd );
349 if ( rc != kATAReturnSuccess )
350 {
351 completeCmd( ataCmd, rc );
352 }
353
354 else if ( startDma( ataCmd ) != true )
355 {
356 rc = kATAReturnDMAError;
357 completeCmd( ataCmd, rc );
358 }
359 }
360
361 else if ( !(status & kATAPIStatusDRQ) && (intReason & kATAPIIntReasonCD) && (intReason & kATAPIIntReasonIO) )
362 {
363 if ( stopDma( ataCmd, &xferCount ) != true )
364 {
365 rc = kATAReturnDMAError;
366 xferCount = 0;
367 }
368 else
369 {
370 rc = (status & kATAPIStatusCHK) ? kATAReturnStatusError : kATAReturnSuccess;
371 }
372
373 completeCmd( ataCmd, rc, xferCount );
374 }
375 else
376 {
377 stopDma( ataCmd, &xferCount );
378 completeCmd( ataCmd, rc, 0 );
379 }
380}
381