|
|
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: * IOATAPICDDrive.h - Generic ATAPI CD-ROM driver.
26: *
27: * HISTORY
28: * Sep 2, 1999 jliu - Ported from AppleATAPIDrive.
29: */
30:
31: #include <IOKit/assert.h>
32: #include <IOKit/storage/ata/IOATAPICDDrive.h>
33: #include <IOKit/storage/ata/IOATAPICDDriveNub.h>
34:
35: #define super IOATAPIHDDrive
36: OSDefineMetaClassAndStructors( IOATAPICDDrive, IOATAPIHDDrive )
37:
38: // --------------------------------------------------------------------------
39: // Looks for an ATAPI device which is a CD-ROM device.
40:
41: bool
42: IOATAPICDDrive::matchATAPIDeviceType(UInt8 type)
43: {
44: if (type == kIOATAPIDeviceTypeCDROM)
45: return true;
46: return false;
47: }
48:
49: // --------------------------------------------------------------------------
50: // Instantiate an ATAPI specific subclass of IOCDDriveNub.
51:
52: IOService *
53: IOATAPICDDrive::instantiateNub()
54: {
55: IOService * nub = new IOATAPICDDriveNub;
56: return nub;
57: }
58:
59: // --------------------------------------------------------------------------
60: // Report whether media is write-protected.
61:
62: IOReturn
63: IOATAPICDDrive::reportWriteProtection(bool * isWriteProtected)
64: {
65: *isWriteProtected = true;
66: return kIOReturnSuccess;
67: }
68:
69: // --------------------------------------------------------------------------
70: // Returns the device type.
71:
72: const char *
73: IOATAPICDDrive::getDeviceTypeName()
74: {
75: return kDeviceTypeCDROM;
76: }
77:
78: // --------------------------------------------------------------------------
79: // Read the Table of Contents.
80:
81: IOReturn
82: IOATAPICDDrive::readTOC(struct rawToc * buffer,
83: UInt32 length,
84: tocFormat format)
85: {
86: IOReturn ret;
87: IOATACommand * cmd;
88: IOMemoryDescriptor * tocDesc;
89:
90: assert(buffer);
91:
92: tocDesc = IOMemoryDescriptor::withAddress(buffer,
93: length,
94: kIODirectionIn);
95: if (!tocDesc)
96: return kIOReturnNoMemory;
97:
98: cmd = atapiCommandReadTOC(tocDesc, format, 0);
99: if (!cmd)
100: return kIOReturnNoMemory;
101:
102: // Execute the Read TOC command.
103: //
104: ret = getIOReturn(syncExecute(cmd));
105:
106: // Release the memory descriptor.
107: //
108: tocDesc->release();
109:
110: cmd->release();
111:
112: return ret;
113: }
114:
115: // --------------------------------------------------------------------------
116: // Start analog audio play
117:
118: IOReturn
119: IOATAPICDDrive::setAudioStopAddress (positioningType addressType,
120: cdAddress address)
121: {
122: if (addressType == kAbsoluteTime)
123: fMSFStopAddress = (UInt32)address;
124: if (addressType == kBlockAddress)
125: fLBAStopAddress = (UInt32)address;
126: return 0;
127: }
128:
129: IOReturn
130: IOATAPICDDrive::audioPlay(positioningType addressType,
131: cdAddress address,
132: audioPlayMode mode)
133: {
134: if (addressType == kBlockAddress) {
135: return playAudio((UInt32)address,0xfff);
136: }
137: if (addressType == kAbsoluteTime) {
138: return playAudioMSF((UInt32)address,(UInt32)fMSFStopAddress);
139: }
140: return 0;
141: }
142:
143: IOReturn
144: IOATAPICDDrive::playAudioMSF (UInt32 start_msf,
145: UInt32 end_msf)
146: {
147: IOATACommand * cmd;
148: IOReturn ret;
149:
150: // IOLog("IOATAPICDDrive::playAudioMSF %x %x\n",start_msf,end_msf);
151: cmd = atapiCommandPlayAudioMSF(start_msf, end_msf);
152: if (!cmd)
153: return kIOReturnNoMemory;
154:
155: // Execute the audio play command.
156: //
157: ret = getIOReturn(syncExecute(cmd));
158:
159: cmd->release();
160:
161: return ret;
162: }
163:
164: IOReturn
165: IOATAPICDDrive::playAudio (UInt32 start_lba,
166: UInt32 len_lba)
167: {
168: IOATACommand * cmd;
169: IOReturn ret;
170:
171: // IOLog("IOATAPICDDrive::playAudio\n");
172: cmd = atapiCommandPlayAudio(start_lba, len_lba);
173: if (!cmd)
174: return kIOReturnNoMemory;
175:
176: // Execute the audio play command.
177: //
178: ret = getIOReturn(syncExecute(cmd));
179:
180: cmd->release();
181:
182: return ret;
183: }
184:
185: IOReturn
186: IOATAPICDDrive::audioPause(bool pause)
187: {
188: IOATACommand * cmd;
189: IOReturn ret;
190:
191: // IOLog("IOATAPICDDrive::audioPause\n");
192: cmd = atapiCommandPauseResume(!pause);
193: if (!cmd)
194: return kIOReturnNoMemory;
195:
196: // Execute the audio pause/resume command.
197: //
198: ret = getIOReturn(syncExecute(cmd));
199:
200: cmd->release();
201:
202: return ret;
203: }
204:
205: IOReturn
206: IOATAPICDDrive::readAudioVolume(UInt8 * leftVolume, UInt8 * rightVolume)
207: {
208: UInt8 *audio_control;
209: IOReturn status = -1;
210:
211: audio_control = (UInt8 *)IOMalloc(144);
212: if (!audio_control) return kIOReturnNoMemory;
213:
214: status = readModeSense(audio_control,(UInt32)144,(UInt32)0xe);
215: *leftVolume = audio_control[21] & 0xff;
216: *rightVolume = audio_control[17] & 0xff;
217:
218: // IOLog("IOATAPICDDrive::readAudioVolume left0=%d right0=%d left1=%d right1=%d\n", *leftVolume,*rightVolume, audio_control[23],audio_control[19]);
219:
220: // IOLog("IOATAPICDDrive::readAudioVolume p0=%d p1=%d p2=%d p3=%d\n", audio_control[8],audio_control[10], audio_control[12],audio_control[14]);
221:
222: IOFree(audio_control,144);
223: return status;
224: }
225:
226: IOReturn
227: IOATAPICDDrive::setVolume(UInt8 leftVolume, UInt8 rightVolume)
228: {
229: UInt8 *audio_control;
230: IOReturn status = -1;
231: UInt32 len;
232:
233: // IOLog("IOATAPICDDrive::setVolume %d %d\n",leftVolume,rightVolume);
234:
235: // init
236: audio_control = (UInt8 *)IOMalloc(144);
237: if (!audio_control) return kIOReturnNoMemory;
238:
239: // get current values
240: status = readModeSense(audio_control,(UInt32)144,(UInt32)0xe);
241: len = (UInt32)audio_control[1] + 2;
242:
243: // set new values
244: // audio_control[ 9] = audio_control[11] = 0xff;
245: // audio_control[23] = audio_control[21] = leftVolume & 0xff;
246: audio_control[19] = audio_control[17] = rightVolume & 0xff;
247:
248: // get current values
249: status = writeModeSelect(audio_control,(UInt32)len,(UInt32)0xe);
250:
251: // cleanup and exit
252: IOFree(audio_control,144);
253: return status;
254: }
255:
256: IOReturn
257: IOATAPICDDrive::readModeSense(UInt8 * buffer, UInt32 length, UInt32 pageCode)
258: {
259: IOReturn ret;
260: IOATACommand * cmd;
261: IOMemoryDescriptor * senseDesc;
262:
263: assert(buffer);
264:
265: // IOLog("IOATAPICDDrive::readModeSense len=%d page=%d\n",length,pageCode);
266:
267: senseDesc = IOMemoryDescriptor::withAddress(buffer,
268: length,
269: kIODirectionIn);
270: if (!senseDesc)
271: return kIOReturnNoMemory;
272:
273: cmd = atapiCommandModeSense(senseDesc, pageCode);
274: if (!cmd)
275: return kIOReturnNoMemory;
276:
277: // Execute the Mode Sense command.
278: //
279: ret = getIOReturn(syncExecute(cmd));
280:
281: // Release the memory descriptor.
282: //
283: senseDesc->release();
284:
285: cmd->release();
286:
287: return ret;
288: }
289:
290: IOReturn
291: IOATAPICDDrive::writeModeSelect(UInt8 * buffer, UInt32 length, UInt32 pageCode)
292: {
293: IOReturn ret;
294: IOATACommand * cmd;
295: IOMemoryDescriptor * selectDesc;
296:
297: // IOLog("IOATAPICDDrive::writeModeSelect %d %d\n",length,pageCode);
298: assert(buffer);
299:
300: selectDesc = IOMemoryDescriptor::withAddress(buffer,
301: length,
302: kIODirectionOut);
303: if (!selectDesc)
304: return kIOReturnNoMemory;
305:
306: cmd = atapiCommandModeSelect(selectDesc, pageCode);
307: if (!cmd)
308: return kIOReturnNoMemory;
309:
310: // Execute the Mode Select command.
311: //
312: ret = getIOReturn(syncExecute(cmd));
313:
314: // Release the memory descriptor.
315: //
316: selectDesc->release();
317:
318: cmd->release();
319:
320: return ret;
321: }
322:
323: IOReturn
324: IOATAPICDDrive::readTheQSubcode(struct qSubcode *buffer)
325: {
326: UInt8 * channel_data;
327: UInt32 address;
328: IOReturn ret;
329:
330: // init
331: channel_data = (UInt8 *)IOMalloc(16);
332: if (!channel_data) return kIOReturnNoMemory;
333:
334: // get audio status
335: ret = readSubChannel(channel_data,16,0x01,0x00,true);
336:
337: // get current absolute address
338: address = ((channel_data[ 8] & 0xff) << 24) |
339: ((channel_data[ 9] & 0xff) << 16) |
340: ((channel_data[10] & 0xff) << 8) |
341: ((channel_data[11] & 0xff));
342: buffer->absAddress = (cdAddress)address;
343:
344: // get current track relative address
345: address = ((channel_data[12] & 0xff) << 24) |
346: ((channel_data[13] & 0xff) << 16) |
347: ((channel_data[14] & 0xff) << 8) |
348: ((channel_data[15] & 0xff));
349: buffer->relAddress = (cdAddress)address;
350:
351: // get type, track, index
352: buffer->type = channel_data[5] & 0x0f;
353: buffer->track = channel_data[6] & 0x0f;
354: buffer->index = channel_data[7] & 0x0f;
355:
356: // IOLog("IOATAPICDDrive::readTheQSubcode absAddr=0x%x relAddr=0x%xx\n", buffer->absAddress, buffer->relAddress);
357:
358: // cleanup
359: IOFree(channel_data,16);
360: return ret;
361: }
362:
363: IOReturn
364: IOATAPICDDrive::getAudioStatus(struct audioStatus *status)
365: {
366: UInt8 * channel_data;
367: UInt32 address;
368: IOReturn ret;
369:
370: // init
371: channel_data = (UInt8 *)IOMalloc(16);
372: if (!channel_data) return kIOReturnNoMemory;
373:
374: // get audio status
375: ret = readSubChannel(channel_data,16,0x01,0x00,true);
376:
377: // get current absolute address
378: address = ((channel_data[ 8] & 0xff) << 24) |
379: ((channel_data[ 9] & 0xff) << 16) |
380: ((channel_data[10] & 0xff) << 8) |
381: ((channel_data[11] & 0xff));
382: status->address = (cdAddress)address;
383:
384: // get current status
385: if ((channel_data[1] & 0xff) == 0x00) status->status = kUnknown;
386: if ((channel_data[1] & 0xff) == 0x11) status->status = kAudioPlayInProgress;
387: if ((channel_data[1] & 0xff) == 0x12) status->status = kHoldTrackMode;
388: if ((channel_data[1] & 0xff) == 0x13) status->status = kAudioPlayCompleted;
389: if ((channel_data[1] & 0xff) == 0x14) status->status = kError;
390: if ((channel_data[1] & 0xff) == 0x15) status->status = fStatus;
391: fStatus = status->status;
392:
393: // get current track type
394: status->type = channel_data[5] & 0x0f;
395:
396: // IOLog("IOATAPICDDrive::getAudioStatus addr=0x%x status=0x%x type=0x%x\n", status->address, status->status, status->type);
397:
398: // cleanup
399: IOFree(channel_data,16);
400: return ret;
401: }
402:
403: IOReturn
404: IOATAPICDDrive::readMCN(UInt8 * buffer, bool * found)
405: {
406: UInt8 * channel_data;
407: UInt32 address;
408: IOReturn ret;
409:
410: // init
411: channel_data = (UInt8 *)IOMalloc(24);
412: if (!channel_data) return kIOReturnNoMemory;
413:
414: // get audio status
415: ret = readSubChannel(channel_data,24,0x02,0x00,true);
416:
417: // check if found
418: *found = (channel_data[8] & 0x80 == 0x80);
419:
420: // copy the data
421: if (*found) {
422: bcopy(&channel_data[9],buffer,15);
423: }
424:
425: // IOLog("IOATAPICDDrive::readMCN found=%d\n",*found);
426:
427: // cleanup
428: IOFree(channel_data,24);
429: return ret;
430: }
431:
432: IOReturn
433: IOATAPICDDrive::readISRC(UInt32 track, UInt8 * buffer, bool * found)
434: {
435: UInt8 * channel_data;
436: UInt32 address;
437: IOReturn ret;
438:
439: // init
440: channel_data = (UInt8 *)IOMalloc(24);
441: if (!channel_data) return kIOReturnNoMemory;
442:
443: // get audio status
444: ret = readSubChannel(channel_data,24,0x03,track,true);
445:
446: // check if found
447: *found = (channel_data[8] & 0x80 == 0x80);
448:
449: // copy the data
450: if (*found) {
451: bcopy(&channel_data[9],buffer,15);
452: }
453:
454: // IOLog("IOATAPICDDrive::readISRC found=%d\n",*found);
455:
456: // cleanup
457: IOFree(channel_data,24);
458: return ret;
459: }
460:
461: IOReturn
462: IOATAPICDDrive::readHeader(UInt32 blockAddress,struct headerInfo *buffer)
463: {
464: UInt8 * header_data;
465: IOReturn ret;
466: IOATACommand * cmd;
467: IOMemoryDescriptor * readDesc;
468:
469: // init
470: header_data = (UInt8 *)IOMalloc(8);
471: if (!header_data) return kIOReturnNoMemory;
472:
473: // IOLog("IOATAPICDDrive::readHeader addr=0x%x\n",blockAddress);
474:
475: readDesc = IOMemoryDescriptor::withAddress(header_data,
476: 8,
477: kIODirectionIn);
478: if (!readDesc)
479: return kIOReturnNoMemory;
480:
481: cmd = atapiCommandReadHeader(readDesc, blockAddress);
482: if (!cmd)
483: return kIOReturnNoMemory;
484:
485: // Execute the Read Header command.
486: //
487: ret = getIOReturn(syncExecute(cmd));
488:
489: // Release the memory descriptor.
490: //
491: readDesc->release();
492: cmd->release();
493:
494: // save the data
495: buffer->address = ((header_data[4] & 0xff) << 24) |
496: ((header_data[5] & 0xff) << 16) |
497: ((header_data[6] & 0xff) << 8) |
498: ((header_data[7] & 0xff));
499: buffer->mode = header_data[0] & 0xff;
500:
501: IOFree(header_data,8);
502:
503: return ret;
504: }
505:
506: IOReturn
507: IOATAPICDDrive::readSubChannel(UInt8 * buffer,
508: UInt32 length,
509: UInt8 dataFormat,
510: UInt8 trackNumber,
511: bool subQ)
512: {
513: IOReturn ret;
514: IOATACommand * cmd;
515: IOMemoryDescriptor * readDesc;
516:
517: assert(buffer);
518:
519: // IOLog("IOATAPICDDrive::readSubChannel len=%d\n",length);
520:
521: readDesc = IOMemoryDescriptor::withAddress(buffer,
522: length,
523: kIODirectionIn);
524: if (!readDesc)
525: return kIOReturnNoMemory;
526:
527: cmd = atapiCommandReadSubChannel(readDesc, dataFormat, trackNumber, subQ);
528: if (!cmd)
529: return kIOReturnNoMemory;
530:
531: // Execute the Mode Sense command.
532: //
533: ret = getIOReturn(syncExecute(cmd));
534:
535: // Release the memory descriptor.
536: //
537: readDesc->release();
538:
539: cmd->release();
540:
541: return ret;
542: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.