]>
Commit | Line | Data |
---|---|---|
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 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
24 | * | |
25 | * IOATAPIHDCommand.cpp - Performs ATAPI command processing. | |
26 | * | |
27 | * HISTORY | |
28 | * Sep 2, 1999 jliu - Ported from AppleATAPIDrive. | |
29 | */ | |
30 | ||
31 | #include <IOKit/assert.h> | |
32 | #include <IOKit/storage/ata/IOATAPIHDDrive.h> | |
33 | ||
34 | #define super IOATAHDDrive | |
35 | ||
36 | // Enable this define to generate debugging messages. | |
37 | // #define DEBUG_LOG 1 | |
38 | ||
39 | //--------------------------------------------------------------------------- | |
40 | // Returns the Command protocol to use (e.g. ataProtocolPIO, ataProtocolDMA). | |
41 | ||
42 | bool | |
43 | IOATAPIHDDrive::selectCommandProtocol(bool isDMA) | |
44 | { | |
45 | super::selectCommandProtocol(isDMA); | |
46 | ||
47 | if (isDMA) | |
48 | _atapiProtocol = kATAProtocolATAPIDMA; | |
49 | else | |
50 | _atapiProtocol = kATAProtocolATAPIPIO; | |
51 | ||
52 | return true; | |
53 | } | |
54 | ||
55 | //--------------------------------------------------------------------------- | |
56 | // Setup a ATATaskFile for an ATAPI packet command from the parameters given. | |
57 | ||
58 | void | |
59 | IOATAPIHDDrive::setupPacketTaskFile(ATATaskfile * taskfile, | |
60 | ATAProtocol protocol, | |
61 | UInt16 byteCount) | |
62 | { | |
63 | bzero( taskfile, sizeof(ATATaskfile) ); | |
64 | ||
65 | taskfile->protocol = protocol; | |
66 | ||
67 | taskfile->regmask = ATARegtoMask(kATARegATAPIDeviceSelect) | |
68 | | ATARegtoMask(kATARegATAPICommand) | |
69 | | ATARegtoMask(kATARegATAPIByteCountLow) | |
70 | | ATARegtoMask(kATARegATAPIByteCountHigh) | |
71 | | ATARegtoMask(kATARegATAPIFeatures); | |
72 | ||
73 | taskfile->resultmask = ATARegtoMask(kATARegATAPIError); | |
74 | ||
75 | taskfile->ataRegs[kATARegATAPIDeviceSelect] = kATAModeLBA | (_unit << 4); | |
76 | taskfile->ataRegs[kATARegATAPICommand] = kATACommandATAPIPacket; | |
77 | taskfile->ataRegs[kATARegATAPIByteCountLow] = byteCount & 0xff; | |
78 | taskfile->ataRegs[kATARegATAPIByteCountHigh] = (byteCount >> 8) & 0xff; | |
79 | taskfile->ataRegs[kATARegATAPIFeatures] = (protocol == | |
80 | kATAProtocolATAPIPIO) ? | |
81 | 0 : kIOATAPIFeaturesDMA; | |
82 | } | |
83 | ||
84 | //--------------------------------------------------------------------------- | |
85 | // Create a generic ATAPI command object. | |
86 | ||
87 | IOATACommand * | |
88 | IOATAPIHDDrive::atapiCommand(ATACDBInfo * packetCommand, | |
89 | IOMemoryDescriptor * transferBuffer = 0) | |
90 | { | |
91 | ATATaskfile taskfile; | |
92 | bool isWrite; | |
93 | UInt32 transferLength; | |
94 | IOATACommand * cmd = allocateCommand(); | |
95 | ||
96 | if (!cmd) return 0; // error, command allocation failed. | |
97 | ||
98 | // Create ATA packet command. | |
99 | // | |
100 | setupPacketTaskFile(&taskfile, _atapiProtocol, kIOATAPIMaxTransfer); | |
101 | ||
102 | // Get a pointer to the client data buffer, and record parameters | |
103 | // which shall be later used by the completion routine. | |
104 | // | |
105 | IOATAClientData * clientData = ATA_CLIENT_DATA(cmd); | |
106 | assert(clientData); | |
107 | ||
108 | clientData->buffer = transferBuffer; | |
109 | ||
110 | cmd->setTaskfile(&taskfile); | |
111 | cmd->setCDB(packetCommand); | |
112 | ||
113 | if (transferBuffer) { | |
114 | isWrite = (transferBuffer->getDirection() == kIODirectionOut); | |
115 | transferLength = transferBuffer->getLength(); | |
116 | } | |
117 | else { | |
118 | isWrite = false; | |
119 | transferLength = 0; | |
120 | } | |
121 | cmd->setPointers(transferBuffer, transferLength, isWrite); | |
122 | ||
123 | return cmd; | |
124 | } | |
125 | ||
126 | //--------------------------------------------------------------------------- | |
127 | // Allocates and return an IOATACommand to perform a read/write operation. | |
128 | ||
129 | IOATACommand * | |
130 | IOATAPIHDDrive::atapiCommandReadWrite(IOMemoryDescriptor * buffer, | |
131 | UInt32 block, | |
132 | UInt32 nblks) | |
133 | { | |
134 | ATACDBInfo atapiCmd; | |
135 | ||
136 | assert(buffer); | |
137 | ||
138 | #ifdef DEBUG_LOG | |
139 | IOLog("%s: atapiCommandReadWrite %08x (%d) %s %d %d\n", | |
140 | getName(), | |
141 | buffer, | |
142 | buffer->getLength(), | |
143 | (buffer->getDirection() == kIODirectionOut) ? "WR" : | |
144 | "RD", | |
145 | block, | |
146 | nblks); | |
147 | #endif | |
148 | ||
149 | // Create the ATAPI packet (bytes 1, 10, 11 are reserved). | |
150 | // | |
151 | bzero(&atapiCmd, sizeof(atapiCmd)); | |
152 | ||
153 | atapiCmd.cdbLength = 12; | |
154 | atapiCmd.cdb[0] = (buffer->getDirection() == kIODirectionOut) ? | |
155 | kIOATAPICommandWrite : kIOATAPICommandRead; | |
156 | atapiCmd.cdb[2] = (UInt8)(block >> 24); | |
157 | atapiCmd.cdb[3] = (UInt8)(block >> 16); | |
158 | atapiCmd.cdb[4] = (UInt8)(block >> 8); | |
159 | atapiCmd.cdb[5] = (UInt8)(block); | |
160 | atapiCmd.cdb[6] = (UInt8)(nblks >> 24); | |
161 | atapiCmd.cdb[7] = (UInt8)(nblks >> 16); | |
162 | atapiCmd.cdb[8] = (UInt8)(nblks >> 8); | |
163 | atapiCmd.cdb[9] = (UInt8)(nblks); | |
164 | ||
165 | return atapiCommand(&atapiCmd, buffer); | |
166 | } | |
167 | ||
168 | //--------------------------------------------------------------------------- | |
169 | // ATAPI Start/Stop Unit command (1B). | |
170 | ||
171 | IOATACommand * | |
172 | IOATAPIHDDrive::atapiCommandStartStopUnit(bool doStart, | |
173 | bool doLoadEject, | |
174 | bool immediate) | |
175 | { | |
176 | ATACDBInfo atapiCmd; | |
177 | ||
178 | #ifdef DEBUG_LOG | |
179 | IOLog("%s: atapiCommandStartStopUnit: %s\n", getName(), | |
180 | doStart ? "start" : "stop"); | |
181 | #endif | |
182 | ||
183 | // Create the ATAPI packet. | |
184 | // | |
185 | bzero(&atapiCmd, sizeof(atapiCmd)); | |
186 | ||
187 | atapiCmd.cdbLength = 12; | |
188 | atapiCmd.cdb[0] = kIOATAPICommandStartStopUnit; | |
189 | atapiCmd.cdb[1] = immediate ? 0x01 : 0x00; | |
190 | atapiCmd.cdb[4] = (doStart ? 0x01 : 0) | | |
191 | (doLoadEject ? 0x02 : 0); | |
192 | ||
193 | return atapiCommand(&atapiCmd); | |
194 | } | |
195 | ||
196 | //--------------------------------------------------------------------------- | |
197 | // ATAPI Format Unit command (04). | |
198 | ||
199 | IOATACommand * | |
200 | IOATAPIHDDrive::atapiCommandFormatUnit(UInt16 interleave, | |
201 | UInt8 flagBits, | |
202 | UInt8 vendorBits, | |
203 | IOMemoryDescriptor * formatData) | |
204 | { | |
205 | ATACDBInfo atapiCmd; | |
206 | ||
207 | // Create the ATAPI packet. | |
208 | // | |
209 | bzero(&atapiCmd, sizeof(atapiCmd)); | |
210 | ||
211 | atapiCmd.cdbLength = 12; | |
212 | atapiCmd.cdb[0] = kIOATAPICommandFormatUnit; | |
213 | atapiCmd.cdb[1] = flagBits; | |
214 | atapiCmd.cdb[3] = (UInt8)(interleave >> 8); | |
215 | atapiCmd.cdb[4] = (UInt8)(interleave); | |
216 | atapiCmd.cdb[5] = vendorBits; | |
217 | ||
218 | if (formatData) | |
219 | atapiCmd.cdb[1] |= 0x10; | |
220 | ||
221 | return atapiCommand(&atapiCmd, formatData); | |
222 | } | |
223 | ||
224 | //--------------------------------------------------------------------------- | |
225 | // ATAPI Synchronize Cache command (35). | |
226 | ||
227 | IOATACommand * | |
228 | IOATAPIHDDrive::atapiCommandSynchronizeCache() | |
229 | { | |
230 | ATACDBInfo atapiCmd; | |
231 | ||
232 | // Create the ATAPI packet. | |
233 | // | |
234 | bzero(&atapiCmd, sizeof(atapiCmd)); | |
235 | ||
236 | atapiCmd.cdbLength = 12; | |
237 | atapiCmd.cdb[0] = kIOATAPICommandSynchronizeCache; | |
238 | ||
239 | return atapiCommand(&atapiCmd); | |
240 | } | |
241 | ||
242 | //--------------------------------------------------------------------------- | |
243 | // ATAPI Prevent/Allow medium removal command (1E). | |
244 | ||
245 | IOATACommand * | |
246 | IOATAPIHDDrive::atapiCommandPreventAllowRemoval(bool doLock) | |
247 | { | |
248 | ATACDBInfo atapiCmd; | |
249 | ||
250 | // Create the ATAPI packet. | |
251 | // | |
252 | bzero(&atapiCmd, sizeof(atapiCmd)); | |
253 | ||
254 | atapiCmd.cdbLength = 12; | |
255 | atapiCmd.cdb[0] = kIOATAPICommandPreventAllow; | |
256 | atapiCmd.cdb[4] = doLock ? 0x01 : 0; | |
257 | ||
258 | return atapiCommand(&atapiCmd); | |
259 | } | |
260 | ||
261 | //--------------------------------------------------------------------------- | |
262 | // ATAPI Test Unit Ready command (00). | |
263 | ||
264 | IOATACommand * | |
265 | IOATAPIHDDrive::atapiCommandTestUnitReady() | |
266 | { | |
267 | ATACDBInfo atapiCmd; | |
268 | ||
269 | #ifdef DEBUG_LOG | |
270 | IOLog("%s: atapiCommandTestUnitReady\n", getName()); | |
271 | #endif | |
272 | ||
273 | // Create the ATAPI packet. | |
274 | // | |
275 | bzero(&atapiCmd, sizeof(atapiCmd)); | |
276 | ||
277 | atapiCmd.cdbLength = 12; | |
278 | atapiCmd.cdb[0] = kIOATAPICommandTestUnitReady; | |
279 | ||
280 | return atapiCommand(&atapiCmd); | |
281 | } | |
282 | ||
283 | //--------------------------------------------------------------------------- | |
284 | // atapiCommandModeSense | |
285 | ||
286 | IOATACommand * | |
287 | IOATAPIHDDrive::atapiCommandModeSense(IOMemoryDescriptor * buffer, | |
288 | UInt8 pageCode, | |
289 | UInt8 pageControl) | |
290 | { | |
291 | ATACDBInfo atapiCmd; | |
292 | ||
293 | assert(buffer); | |
294 | ||
295 | bzero(&atapiCmd, sizeof(atapiCmd)); | |
296 | ||
297 | atapiCmd.cdbLength = 12; | |
298 | atapiCmd.cdb[0] = kIOATAPICommandModeSense; | |
299 | atapiCmd.cdb[2] = (pageCode & 0x3f) | ((pageControl & 0x3) << 6); | |
300 | atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; | |
301 | atapiCmd.cdb[8] = buffer->getLength() & 0xff; | |
302 | ||
303 | return atapiCommand(&atapiCmd, buffer); | |
304 | } | |
305 | ||
306 | //--------------------------------------------------------------------------- | |
307 | // atapiCommandModeSelect | |
308 | ||
309 | IOATACommand * | |
310 | IOATAPIHDDrive::atapiCommandModeSelect(IOMemoryDescriptor * buffer) | |
311 | { | |
312 | ATACDBInfo atapiCmd; | |
313 | ||
314 | assert(buffer); | |
315 | ||
316 | bzero(&atapiCmd, sizeof(atapiCmd)); | |
317 | ||
318 | atapiCmd.cdbLength = 12; | |
319 | atapiCmd.cdb[0] = kIOATAPICommandModeSelect; | |
320 | atapiCmd.cdb[1] = 0x10; | |
321 | atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff; | |
322 | atapiCmd.cdb[8] = buffer->getLength() & 0xff; | |
323 | ||
324 | return atapiCommand(&atapiCmd, buffer); | |
325 | } |