|
|
1.1 root 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: void
43: IOATAPIHDDrive::selectCommandProtocol(bool useDMA)
44: {
45: super::selectCommandProtocol(useDMA);
46:
47: if (useDMA)
48: _atapiProtocol = atapiProtocolDMA;
49: else
50: _atapiProtocol = atapiProtocolPIO;
51: }
52:
53: // --------------------------------------------------------------------------
54: // Setup a ATATaskFile for an ATAPI packet command from the parameters given.
55:
56: void
57: IOATAPIHDDrive::setupPacketTaskFile(ATATaskfile * taskfile,
58: ATAProtocol protocol,
59: UInt16 byteCount)
60: {
61: taskfile->protocol = protocol;
62:
63: taskfile->regmask = ATARegtoMask(atapiRegDeviceSelect)
64: | ATARegtoMask(atapiRegCommand)
65: | ATARegtoMask(atapiRegByteCountLow)
66: | ATARegtoMask(atapiRegByteCountHigh)
67: | ATARegtoMask(atapiRegFeatures);
68:
69: taskfile->resultmask = ATARegtoMask(atapiRegError);
70:
71: taskfile->ataRegs[atapiRegDeviceSelect] = ataModeLBA | (_unit << 4);
72: taskfile->ataRegs[atapiRegCommand] = atapiCommandPacket;
73: taskfile->ataRegs[atapiRegByteCountLow] = byteCount & 0xff;
74: taskfile->ataRegs[atapiRegByteCountHigh] = (byteCount >> 8) & 0xff;
75: taskfile->ataRegs[atapiRegFeatures] = (protocol == atapiProtocolPIO) ?
76: 0 : kIOATAPIFeaturesDMA;
77: }
78:
79: // --------------------------------------------------------------------------
80: // Create a generic ATAPI command object.
81:
82: IOATACommand *
83: IOATAPIHDDrive::atapiCommand(ATAPICmd * packetCommand,
84: IOMemoryDescriptor * transferBuffer = 0,
85: IOMemoryDescriptor * senseData = 0)
86: {
87: ATATaskfile taskfile;
88: bool isWrite;
89: UInt32 transferLength;
90:
91: IOATACommand * cmd = allocateCommand();
92: if (!cmd) return 0; // error, command allocation failed.
93:
94: // Create ATA packet command.
95: //
96: setupPacketTaskFile(&taskfile, _atapiProtocol, kIOATAPIMaxTransfer);
97:
98: // Get a pointer to the client data buffer, and record parameters
99: // which shall be later used by the completion routine.
100: //
101: IOATAClientData * clientData = ATA_CLIENT_DATA(cmd);
102: assert(clientData);
103:
104: clientData->buffer = transferBuffer;
105:
106: cmd->setTaskfile(&taskfile);
107: cmd->setATAPICmd(packetCommand, senseData,
108: senseData ? senseData->getLength() : 0);
109:
110: if (transferBuffer) {
111: isWrite = (transferBuffer->getDirection() == kIODirectionOut);
112: transferLength = transferBuffer->getLength();
113: }
114: else {
115: isWrite = false;
116: transferLength = 0;
117: }
118: cmd->setPointers(transferBuffer, transferLength, isWrite);
119:
120: return cmd;
121: }
122:
123: // --------------------------------------------------------------------------
124: // Allocates and return an IOATACommand to perform a read/write operation.
125:
126: IOATACommand *
127: IOATAPIHDDrive::atapiCommandReadWrite(IOMemoryDescriptor * buffer,
128: UInt32 block,
129: UInt32 nblks)
130: {
131: ATAPICmd atapiCmd;
132:
133: assert(buffer);
134:
135: #ifdef DEBUG_LOG
136: IOLog("%s: atapiCommandReadWrite %08x (%d) %s %d %d\n",
137: getName(),
138: buffer,
139: buffer->getLength(),
140: (buffer->getDirection() == kIODirectionOut) ? "WR" :
141: "RD",
142: block,
143: nblks);
144: #endif
145:
146: // Create the ATAPI packet (bytes 1, 10, 11 are reserved).
147: //
148: bzero(&atapiCmd, sizeof(atapiCmd));
149:
150: atapiCmd.cdbLength = 12;
151: atapiCmd.cdb[0] = (buffer->getDirection() == kIODirectionOut) ?
152: kIOATAPICommandWrite : kIOATAPICommandRead;
153: atapiCmd.cdb[2] = (block >> 24) & 0xff;
154: atapiCmd.cdb[3] = (block >> 16) & 0xff;
155: atapiCmd.cdb[4] = (block >> 8) & 0xff;
156: atapiCmd.cdb[5] = (block & 0xff);
157: atapiCmd.cdb[6] = (nblks >> 24) & 0xff;
158: atapiCmd.cdb[7] = (nblks >> 16) & 0xff;
159: atapiCmd.cdb[8] = (nblks >> 8) & 0xff;
160: atapiCmd.cdb[9] = (nblks & 0xff);
161:
162: return atapiCommand(&atapiCmd, buffer);
163: }
164:
165: // --------------------------------------------------------------------------
166: // ATAPI Start/Stop Unit command (1B).
167:
168: IOATACommand *
169: IOATAPIHDDrive::atapiCommandStartStopUnit(IOMemoryDescriptor * senseData,
170: bool doStart,
171: bool doLoadEject,
172: bool immediate)
173: {
174: ATAPICmd atapiCmd;
175:
176: #ifdef DEBUG_LOG
177: IOLog("%s: atapiCommandStartStopUnit: %s\n", getName(),
178: doStart ? "start" : "stop");
179: #endif
180:
181: // Create the ATAPI packet.
182: //
183: bzero(&atapiCmd, sizeof(atapiCmd));
184:
185: atapiCmd.cdbLength = 12;
186: atapiCmd.cdb[0] = kIOATAPICommandStartStopUnit;
187: atapiCmd.cdb[1] = immediate ? 0x01 : 0x00;
188: atapiCmd.cdb[4] = (doStart ? 0x01 : 0) |
189: (doLoadEject ? 0x02 : 0);
190:
191: return atapiCommand(&atapiCmd, 0, senseData);
192: }
193:
194: // --------------------------------------------------------------------------
195: // ATAPI Prevent/Allow medium removal command (1E).
196:
197: IOATACommand *
198: IOATAPIHDDrive::atapiCommandPreventAllowRemoval(bool doLock)
199: {
200: ATAPICmd atapiCmd;
201:
202: // Create the ATAPI packet.
203: //
204: bzero(&atapiCmd, sizeof(atapiCmd));
205:
206: atapiCmd.cdbLength = 12;
207: atapiCmd.cdb[0] = kIOATAPICommandPreventAllow;
208: atapiCmd.cdb[4] = doLock ? 0x01 : 0;
209:
210: return atapiCommand(&atapiCmd);
211: }
212:
213: // --------------------------------------------------------------------------
214: // ATAPI Test Unit Ready command (00).
215:
216: IOATACommand *
217: IOATAPIHDDrive::atapiCommandTestUnitReady(IOMemoryDescriptor * senseData)
218: {
219: ATAPICmd atapiCmd;
220:
221: #ifdef DEBUG_LOG
222: IOLog("%s: atapiCommandTestUnitReady\n", getName());
223: #endif
224:
225: // Create the ATAPI packet.
226: //
227: bzero(&atapiCmd, sizeof(atapiCmd));
228:
229: atapiCmd.cdbLength = 12;
230: atapiCmd.cdb[0] = kIOATAPICommandTestUnitReady;
231:
232: return atapiCommand(&atapiCmd, 0, senseData);
233: }
234:
235: // --------------------------------------------------------------------------
236: // ATAPI Read TOC command (43).
237:
238: IOATACommand *
239: IOATAPIHDDrive::atapiCommandReadTOC(IOMemoryDescriptor * buffer,
240: tocFormat format,
241: UInt8 startTrackSession)
242: {
243: ATAPICmd atapiCmd;
244:
245: assert(buffer);
246:
247: // Create the ATAPI packet.
248: //
249: bzero(&atapiCmd, sizeof(atapiCmd));
250:
251: atapiCmd.cdbLength = 12;
252: atapiCmd.cdb[0] = kIOATAPICommandReadTOC;
253: atapiCmd.cdb[1] = (format == ktocSCSI2MSF) ? 0x02 : 0x00;
254: atapiCmd.cdb[6] = startTrackSession;
255: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff;
256: atapiCmd.cdb[8] = buffer->getLength() & 0xff;
257:
258: switch (format) {
259: case ktocSCSI2MSF:
260: case ktocSCSI2LBA:
261: atapiCmd.cdb[9] = 0x00;
262: break;
263:
264: case ktocSessionInfo:
265: atapiCmd.cdb[9] = 0x40;
266: break;
267:
268: case ktocQLeadin:
269: atapiCmd.cdb[9] = 0x80;
270: break;
271: }
272:
273: return atapiCommand(&atapiCmd, buffer);
274: }
275:
276: IOATACommand *
277: IOATAPIHDDrive::atapiCommandPlayAudioMSF(UInt32 starting_msf,
278: UInt32 ending_msf)
279: {
280: ATAPICmd atapiCmd;
281:
282: // IOLog("IOATAPIHDDrive::atapiCommandPlayAudioMSF %x %x\n",starting_msf,ending_msf);
283:
284: bzero(&atapiCmd, sizeof(atapiCmd));
285: atapiCmd.cdbLength = 12;
286:
287: atapiCmd.cdb[0] = kIOATAPICommandPlayAudioMSF;
288:
289: // starting MSF address
290: atapiCmd.cdb[3] = (starting_msf >> 16) & 0xff;
291: atapiCmd.cdb[4] = (starting_msf >> 8) & 0xff;
292: atapiCmd.cdb[5] = (starting_msf & 0xff);
293:
294: // ending MSF address
295: atapiCmd.cdb[6] = (ending_msf >> 16) & 0xff;
296: atapiCmd.cdb[7] = (ending_msf >> 8) & 0xff;
297: atapiCmd.cdb[8] = (ending_msf & 0xff);
298:
299: return atapiCommand(&atapiCmd);
300: }
301:
302: IOATACommand *
303: IOATAPIHDDrive::atapiCommandPlayAudio(UInt32 starting_lba,
304: UInt32 length_lba)
305: {
306: ATAPICmd atapiCmd;
307:
308: // IOLog("IOATAPIHDDrive::atapiCommandPlayAudio\n");
309:
310: bzero(&atapiCmd, sizeof(atapiCmd));
311: atapiCmd.cdbLength = 12;
312:
313: atapiCmd.cdb[0] = kIOATAPICommandPlayAudio;
314:
315: // starting LBA address
316: atapiCmd.cdb[2] = (starting_lba >> 24) & 0xff;
317: atapiCmd.cdb[3] = (starting_lba >> 16) & 0xff;
318: atapiCmd.cdb[4] = (starting_lba >> 8) & 0xff;
319: atapiCmd.cdb[5] = (starting_lba & 0xff);
320:
321: // length in blocks
322: atapiCmd.cdb[7] = (length_lba >> 8) & 0xff;
323: atapiCmd.cdb[8] = (length_lba & 0xff);
324:
325: return atapiCommand(&atapiCmd);
326: }
327:
328: IOATACommand *
329: IOATAPIHDDrive::atapiCommandPauseResume(bool resume)
330: {
331: ATAPICmd atapiCmd;
332:
333: // IOLog("IOATAPIHDDrive::atapiCommandPauseResume\n");
334:
335: bzero(&atapiCmd, sizeof(atapiCmd));
336: atapiCmd.cdbLength = 12;
337:
338: atapiCmd.cdb[0] = kIOATAPICommandPauseResume;
339:
340: // set resume bit
341: if (resume) atapiCmd.cdb[8] = 0x01;
342:
343: return atapiCommand(&atapiCmd);
344: }
345:
346: IOATACommand *
347: IOATAPIHDDrive::atapiCommandModeSense(IOMemoryDescriptor * buffer,
348: UInt8 pageCode)
349: {
350: ATAPICmd atapiCmd;
351:
352: assert(buffer);
353:
354: bzero(&atapiCmd, sizeof(atapiCmd));
355:
356: atapiCmd.cdbLength = 12;
357: atapiCmd.cdb[0] = kIOATAPICommandModeSense;
358: atapiCmd.cdb[2] = pageCode;
359: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff;
360: atapiCmd.cdb[8] = buffer->getLength() & 0xff;
361:
362: return atapiCommand(&atapiCmd, buffer);
363: }
364:
365: IOATACommand *
366: IOATAPIHDDrive::atapiCommandModeSelect(IOMemoryDescriptor * buffer,
367: UInt8 pageCode)
368: {
369: ATAPICmd atapiCmd;
370:
371: assert(buffer);
372:
373: bzero(&atapiCmd, sizeof(atapiCmd));
374:
375: atapiCmd.cdbLength = 12;
376: atapiCmd.cdb[0] = kIOATAPICommandModeSelect;
377: atapiCmd.cdb[1] = 0x10;
378: atapiCmd.cdb[2] = pageCode;
379: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff;
380: atapiCmd.cdb[8] = buffer->getLength() & 0xff;
381:
382: return atapiCommand(&atapiCmd, buffer);
383: }
384:
385: IOATACommand *
386: IOATAPIHDDrive::atapiCommandReadSubChannel(IOMemoryDescriptor * buffer,
387: UInt8 dataFormat,
388: UInt8 trackNumber,
389: bool subQ)
390: {
391: ATAPICmd atapiCmd;
392:
393: assert(buffer);
394:
395: bzero(&atapiCmd, sizeof(atapiCmd));
396:
397: atapiCmd.cdbLength = 12;
398: atapiCmd.cdb[0] = kIOATAPICommandReadSubChannel;
399: atapiCmd.cdb[1] = 0x02;
400: if (subQ) atapiCmd.cdb[2] = 0x40;
401: atapiCmd.cdb[3] = dataFormat;
402: atapiCmd.cdb[6] = trackNumber;
403: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff;
404: atapiCmd.cdb[8] = buffer->getLength() & 0xff;
405:
406: return atapiCommand(&atapiCmd, buffer);
407: }
408:
409: IOATACommand *
410: IOATAPIHDDrive::atapiCommandReadHeader(IOMemoryDescriptor * buffer,
411: UInt32 address)
412: {
413: ATAPICmd atapiCmd;
414:
415: assert(buffer);
416:
417: bzero(&atapiCmd, sizeof(atapiCmd));
418:
419: atapiCmd.cdbLength = 12;
420: atapiCmd.cdb[0] = kIOATAPICommandReadHeader;
421: atapiCmd.cdb[1] = 0x02; // MSF
422:
423: // starting LBA address
424: atapiCmd.cdb[2] = (address >> 24) & 0xff;
425: atapiCmd.cdb[3] = (address >> 16) & 0xff;
426: atapiCmd.cdb[4] = (address >> 8) & 0xff;
427: atapiCmd.cdb[5] = (address & 0xff);
428:
429: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff;
430: atapiCmd.cdb[8] = buffer->getLength() & 0xff;
431:
432: return atapiCommand(&atapiCmd, buffer);
433: }
434:
435: IOATACommand *
436: IOATAPIHDDrive::atapiCommandReadCD(IOMemoryDescriptor * buffer,
437: UInt32 address,
438: UInt32 length,
439: UInt8 sector,
440: UInt8 header,
441: UInt8 error,
442: UInt8 data)
443: {
444:
445: ATAPICmd atapiCmd;
446:
447: assert(buffer);
448:
449: bzero(&atapiCmd, sizeof(atapiCmd));
450:
451: atapiCmd.cdbLength = 12;
452: atapiCmd.cdb[0] = kIOATAPICommandReadCD;
453:
454: // expected sector type
455: atapiCmd.cdb[1] = (sector << 2) & 0xff;
456:
457: // starting LBA address
458: atapiCmd.cdb[2] = (address >> 24) & 0xff;
459: atapiCmd.cdb[3] = (address >> 16) & 0xff;
460: atapiCmd.cdb[4] = (address >> 8) & 0xff;
461: atapiCmd.cdb[5] = (address & 0xff);
462:
463: // transfer length
464: atapiCmd.cdb[6] = (buffer->getLength() >> 16) & 0xff;
465: atapiCmd.cdb[7] = (buffer->getLength() >> 8) & 0xff;
466: atapiCmd.cdb[8] = buffer->getLength() & 0xff;
467:
468: // flag bits
469: atapiCmd.cdb[9] = ((header << 5) | (error << 1)) & 0xff;
470:
471: // sub-channel data selection
472: atapiCmd.cdb[10] = (data) & 0xff;
473:
474: return atapiCommand(&atapiCmd, buffer);
475: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.