]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOATAStandard/IOATAStandardDriverDma.cpp
xnu-201.tar.gz
[apple/xnu.git] / iokit / Families / IOATAStandard / IOATAStandardDriverDma.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 * IOATAStandardDriverDma.cpp
25 *
26 */
27 #include <IOKit/ata/IOATAStandardInterface.h>
28
29 /*----------------------------------- ATA DMA Protocol ------------------------------*/
30
31 /*
32 *
33 *
34 */
35 void 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 */
75 void 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 */
130 void 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 */
184 void 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 */
267 void 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 // Wait for BSY = 0 and DRQ = 0 before issuing a packet command.
293
294 waitForStatus( 0, kATAStatusBSY | kATAStatusDRQ, kATABusyTimeoutmS );
295
296 for ( i = 0; regmask; i++ )
297 {
298 if ( regmask & 1 )
299 {
300 writeATAReg( i, taskfile.ataRegs[i] );
301 }
302 regmask >>= 1;
303 }
304
305 programDma( ataCmd );
306
307 if ( ataCmd->getDevice(kIOATAStandardDevice)->getATAPIPktInt() == false )
308 {
309 rc = sendATAPIPacket( ataCmd );
310
311 if ( rc != kATAReturnSuccess )
312 {
313 completeCmd( ataCmd, rc );
314 return;
315 }
316
317 startDma( ataCmd );
318 }
319 }
320
321
322 /*
323 *
324 *
325 */
326 void IOATAStandardDriver::processATAPIDmaInt()
327 {
328 IOATAStandardCommand *ataCmd;
329 ATAReturnCode rc = kATAReturnProtocolError;
330 UInt32 status;
331 UInt32 intReason;
332 UInt32 xferCount;
333
334 ataCmd = findCommandWithNexus( currentDevice, (UInt32) -1 );
335 if ( ataCmd == 0 )
336 {
337 IOLog( "IOATAStandardDriver::processATAPIDmaInt() - ATA Command not found\n\r" );
338 return;
339 }
340
341 if ( waitForStatus( 0, kATAStatusBSY, kATABusyTimeoutmS ) == false )
342 {
343 completeCmd( ataCmd, kATAReturnBusyError, 0 );
344 return;
345 }
346
347 status = readATAReg( kATARegATAPIStatus );
348 intReason = readATAReg( kATARegATAPIIntReason );
349
350 if ( (status & kATAPIStatusDRQ) && (intReason & kATAPIIntReasonCD) && !(intReason & kATAPIIntReasonIO) )
351 {
352 rc = sendATAPIPacket( ataCmd );
353 if ( rc != kATAReturnSuccess )
354 {
355 completeCmd( ataCmd, rc );
356 }
357
358 else if ( startDma( ataCmd ) != true )
359 {
360 rc = kATAReturnDMAError;
361 completeCmd( ataCmd, rc );
362 }
363 }
364
365 else if ( !(status & kATAPIStatusDRQ) && (intReason & kATAPIIntReasonCD) && (intReason & kATAPIIntReasonIO) )
366 {
367 if ( stopDma( ataCmd, &xferCount ) != true )
368 {
369 rc = kATAReturnDMAError;
370 xferCount = 0;
371 }
372 else
373 {
374 rc = (status & kATAPIStatusCHK) ? kATAReturnStatusError : kATAReturnSuccess;
375 }
376
377 completeCmd( ataCmd, rc, xferCount );
378 }
379 else
380 {
381 stopDma( ataCmd, &xferCount );
382 completeCmd( ataCmd, rc, 0 );
383 }
384 }
385