2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
25 * IOATAPICDDrive.h - Generic ATAPI CD-ROM driver.
28 * Sep 2, 1999 jliu - Ported from AppleATAPIDrive.
31 #include <IOKit/assert.h>
32 #include <IOKit/IOBufferMemoryDescriptor.h>
33 #include <IOKit/storage/ata/IOATAPICDDrive.h>
34 #include <IOKit/storage/ata/IOATAPICDDriveNub.h>
36 #define super IOATAPIHDDrive
37 OSDefineMetaClassAndStructors( IOATAPICDDrive
, IOATAPIHDDrive
)
39 //---------------------------------------------------------------------------
40 // Looks for an ATAPI device which is a CD-ROM device.
43 IOATAPICDDrive::matchATAPIDeviceType(UInt8 type
, SInt32
* score
)
45 if (type
== kIOATAPIDeviceTypeCDROM
)
51 //---------------------------------------------------------------------------
52 // Instantiate an ATAPI specific subclass of IOCDBlockStorageDevice.
55 IOATAPICDDrive::instantiateNub()
57 IOService
* nub
= new IOATAPICDDriveNub
;
61 //---------------------------------------------------------------------------
62 // Report whether media is write-protected.
65 IOATAPICDDrive::reportWriteProtection(bool * isWriteProtected
)
67 *isWriteProtected
= true;
68 return kIOReturnSuccess
;
71 //---------------------------------------------------------------------------
72 // Returns the device type.
75 IOATAPICDDrive::getDeviceTypeName()
77 return kIOBlockStorageDeviceTypeCDROM
;
80 //---------------------------------------------------------------------------
81 // Read the Table of Contents.
83 // The LG DVD-ROM DRN8080B LAB8 drive returns a TOC Data Length field which
84 // describes the number of bytes *returned* in the transfer, not the number
85 // bytes available to be transferred like it should. There is a workaround
86 // that addresses this problem here, however the workaround should be moved
87 // into a separate drive-specific subclass in the future.
89 #define LG_DVD_ROM_DRN8080B_SUPPORT
92 IOATAPICDDrive::readTOC(IOMemoryDescriptor
* buffer
)
99 #ifdef LG_DVD_ROM_DRN8080B_SUPPORT
100 IOMemoryDescriptor
* bufferOrig
= buffer
;
101 bool isLG_DVD_ROM_DRN8080B
=
102 ( getVendorString() &&
103 getProductString() &&
104 !strcmp(getVendorString(), "LG") &&
105 !strcmp(getProductString(), "DVD-ROM DRN8080B") );
107 if (isLG_DVD_ROM_DRN8080B
) {
108 buffer
= IOBufferMemoryDescriptor::withCapacity(
109 max(4096, (bufferOrig
->getLength()+1) & (~1)),
112 return kIOReturnNoMemory
;
114 #endif LG_DVD_ROM_DRN8080B_SUPPORT
116 cmd
= atapiCommandReadTOC(buffer
, true, 2, 0);
118 return kIOReturnNoMemory
;
120 // Execute the Read TOC command.
122 ret
= syncExecute(cmd
);
124 #ifdef LG_DVD_ROM_DRN8080B_SUPPORT
125 if (isLG_DVD_ROM_DRN8080B
) {
130 cmd
->getResults(&results
);
131 toc
= ((IOBufferMemoryDescriptor
*)buffer
)->getBytesNoCopy();
132 tocSize
= min(results
.bytesTransferred
, bufferOrig
->getLength());
134 if (bufferOrig
->writeBytes(0, toc
, tocSize
) < bufferOrig
->getLength())
135 ret
= (ret
== kIOReturnSuccess
) ? kIOReturnUnderrun
: ret
;
137 ret
= (ret
== kIOReturnUnderrun
) ? kIOReturnSuccess
: ret
;
141 #endif LG_DVD_ROM_DRN8080B_SUPPORT
148 //---------------------------------------------------------------------------
149 // Start analog audio play
152 IOATAPICDDrive::audioPlay(CDMSF timeStart
,CDMSF timeStop
)
157 // IOLog("IOATAPICDDrive::audioPlay %x %x\n",timeStart,timeStop);
158 cmd
= atapiCommandPlayAudioMSF(timeStart
, timeStop
);
160 return kIOReturnNoMemory
;
162 // Execute the audio play command.
164 ret
= syncExecute(cmd
);
172 IOATAPICDDrive::audioPause(bool pause
)
177 // IOLog("IOATAPICDDrive::audioPause\n");
178 cmd
= atapiCommandPauseResume(!pause
);
180 return kIOReturnNoMemory
;
182 // Execute the audio pause/resume command.
184 ret
= syncExecute(cmd
);
192 IOATAPICDDrive::audioScan(CDMSF timeStart
, bool reverse
)
197 cmd
= atapiCommandScan(timeStart
, reverse
);
199 return kIOReturnNoMemory
;
201 // Execute the audio scan command.
203 ret
= syncExecute(cmd
);
211 IOATAPICDDrive::audioStop()
216 cmd
= atapiCommandStopPlay();
218 return kIOReturnNoMemory
;
220 // Execute the audio stop play command.
222 ret
= syncExecute(cmd
);
230 IOATAPICDDrive::getAudioVolume(UInt8
* leftVolume
, UInt8
* rightVolume
)
232 UInt8 audio_control
[24];
235 status
= readModeSense(audio_control
,sizeof(audio_control
),(UInt32
)0xe);
237 if (status
== kIOReturnSuccess
) {
238 assert((audio_control
[0] ) == 0x00);
239 assert((audio_control
[1] ) == sizeof(audio_control
) - 2);
240 assert((audio_control
[8] & 0x3f) == 0x0e);
241 assert((audio_control
[9] ) == 0x0e);
243 *leftVolume
= audio_control
[17];
244 *rightVolume
= audio_control
[19];
251 IOATAPICDDrive::setAudioVolume(UInt8 leftVolume
, UInt8 rightVolume
)
253 UInt8 audio_control
[24];
256 // get current values
257 status
= readModeSense(audio_control
,sizeof(audio_control
),(UInt32
)0xe);
259 if (status
== kIOReturnSuccess
) {
260 assert((audio_control
[0] ) == 0x00);
261 assert((audio_control
[1] ) == sizeof(audio_control
) - 2);
262 assert((audio_control
[8] & 0x3f) == 0x0e);
263 assert((audio_control
[9] ) == 0x0e);
266 audio_control
[17] = audio_control
[21] = leftVolume
;
267 audio_control
[19] = audio_control
[23] = rightVolume
;
269 status
= writeModeSelect(audio_control
,sizeof(audio_control
));
276 IOATAPICDDrive::readModeSense(UInt8
* buffer
,
279 UInt8 pageControl
= 0)
283 IOMemoryDescriptor
* senseDesc
;
287 // IOLog("IOATAPICDDrive::readModeSense len=%d page=%d\n",length,pageCode);
289 senseDesc
= IOMemoryDescriptor::withAddress(buffer
,
293 return kIOReturnNoMemory
;
295 cmd
= atapiCommandModeSense(senseDesc
, pageCode
, pageControl
);
297 return kIOReturnNoMemory
;
299 // Execute the Mode Sense command.
301 ret
= syncExecute(cmd
);
303 // Release the memory descriptor.
305 senseDesc
->release();
313 IOATAPICDDrive::writeModeSelect(UInt8
* buffer
, UInt32 length
)
317 IOMemoryDescriptor
* selectDesc
;
319 // IOLog("IOATAPICDDrive::writeModeSelect %d %d\n",length);
322 selectDesc
= IOMemoryDescriptor::withAddress(buffer
,
326 return kIOReturnNoMemory
;
328 cmd
= atapiCommandModeSelect(selectDesc
);
330 return kIOReturnNoMemory
;
332 // Execute the Mode Select command.
334 ret
= syncExecute(cmd
);
336 // Release the memory descriptor.
338 selectDesc
->release();
346 IOATAPICDDrive::getAudioStatus(CDAudioStatus
* status
)
348 UInt8
* channel_data
;
352 channel_data
= (UInt8
*)IOMalloc(16);
353 if (!channel_data
) return kIOReturnNoMemory
;
356 ret
= readSubChannel(channel_data
,16,0x01,0x00);
358 if (ret
== kIOReturnSuccess
) {
359 // state our assumptions
360 assert(channel_data
[2] == 0);
361 assert(channel_data
[3] == 12);
362 assert(channel_data
[4] == 1);
364 // get current status
365 status
->status
= channel_data
[ 1];
367 // get current track and track index
368 status
->position
.track
.number
= channel_data
[ 6];
369 status
->position
.track
.index
= channel_data
[ 7];
371 // get current absolute address
372 status
->position
.time
.minute
= channel_data
[ 9];
373 status
->position
.time
.second
= channel_data
[10];
374 status
->position
.time
.frame
= channel_data
[11];
376 // get current relative address
377 status
->position
.track
.time
.minute
= channel_data
[13];
378 status
->position
.track
.time
.second
= channel_data
[14];
379 status
->position
.track
.time
.frame
= channel_data
[15];
383 IOFree(channel_data
,16);
388 IOATAPICDDrive::readMCN(CDMCN mcn
)
390 UInt8
* channel_data
;
394 channel_data
= (UInt8
*)IOMalloc(24);
395 if (!channel_data
) return kIOReturnNoMemory
;
398 ret
= readSubChannel(channel_data
,24,0x02,0x00);
400 if (ret
== kIOReturnSuccess
) {
401 // state our assumptions
402 assert(channel_data
[2] == 0);
403 assert(channel_data
[3] == 20);
404 assert(channel_data
[4] == 2);
407 if ((channel_data
[8] & 0x80)) {
409 bcopy(&channel_data
[9],mcn
,kCDMCNMaxLength
);
410 mcn
[kCDMCNMaxLength
] = '\0';
412 ret
= kIOReturnNotFound
;
417 IOFree(channel_data
,24);
422 IOATAPICDDrive::readISRC(UInt8 track
, CDISRC isrc
)
424 UInt8
* channel_data
;
428 channel_data
= (UInt8
*)IOMalloc(24);
429 if (!channel_data
) return kIOReturnNoMemory
;
432 ret
= readSubChannel(channel_data
,24,0x03,track
);
434 if (ret
== kIOReturnSuccess
) {
435 // state our assumptions
436 assert(channel_data
[2] == 0);
437 assert(channel_data
[3] == 20);
438 assert(channel_data
[4] == 3);
441 if ((channel_data
[8] & 0x80)) {
443 bcopy(&channel_data
[9],isrc
,kCDISRCMaxLength
);
444 isrc
[kCDISRCMaxLength
] = '\0';
446 ret
= kIOReturnNotFound
;
451 IOFree(channel_data
,24);
456 IOATAPICDDrive::readSubChannel(UInt8
* buffer
,
463 IOMemoryDescriptor
* readDesc
;
467 // IOLog("IOATAPICDDrive::readSubChannel len=%d\n",length);
469 readDesc
= IOMemoryDescriptor::withAddress(buffer
,
473 return kIOReturnNoMemory
;
475 cmd
= atapiCommandReadSubChannel(readDesc
, dataFormat
, trackNumber
);
477 return kIOReturnNoMemory
;
479 // Execute the Mode Sense command.
481 ret
= syncExecute(cmd
);
483 // Release the memory descriptor.
493 IOATAPICDDrive::doAsyncReadCD(IOMemoryDescriptor
* buffer
,
496 CDSectorArea sectorArea
,
497 CDSectorType sectorType
,
498 IOStorageCompletion completion
)
503 cmd
= atapiCommandReadCD(buffer
,block
,nblks
,sectorArea
,sectorType
);
506 return kIOReturnNoMemory
;
508 ret
= asyncExecute(cmd
, completion
);