]> git.saurik.com Git - apple/xnu.git/blame - iokit/Families/IOATAPIHDDrive/IOATAPIHDCommand.cpp
xnu-124.13.tar.gz
[apple/xnu.git] / iokit / Families / IOATAPIHDDrive / IOATAPIHDCommand.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 * 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
42bool
43IOATAPIHDDrive::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
58void
59IOATAPIHDDrive::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
87IOATACommand *
88IOATAPIHDDrive::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
129IOATACommand *
130IOATAPIHDDrive::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
171IOATACommand *
172IOATAPIHDDrive::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
199IOATACommand *
200IOATAPIHDDrive::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
227IOATACommand *
228IOATAPIHDDrive::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
245IOATACommand *
246IOATAPIHDDrive::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
264IOATACommand *
265IOATAPIHDDrive::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
286IOATACommand *
287IOATAPIHDDrive::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
309IOATACommand *
310IOATAPIHDDrive::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}