]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOATAPIHDDrive/IOATAPIHDCommand.cpp
xnu-124.13.tar.gz
[apple/xnu.git] / iokit / Families / IOATAPIHDDrive / IOATAPIHDCommand.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 * 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 }