1/*
2 * Copyright (c) 1998-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23#include <IOKit/IOBufferMemoryDescriptor.h>
24#include <IOKit/IOKitKeys.h>
25#include <IOKit/IOLib.h>
26#include <IOKit/storage/IODVDBlockStorageDevice.h>
27#include <IOKit/storage/IODVDBlockStorageDriver.h>
28#include <IOKit/storage/IODVDMedia.h>
29
30#define	super	IOCDBlockStorageDriver
31OSDefineMetaClassAndStructors(IODVDBlockStorageDriver,IOCDBlockStorageDriver)
32
33OSCompileAssert(sizeof(DVDDiscInfo) == sizeof(CDDiscInfo));
34OSCompileAssert(sizeof(DVDRZoneInfo) == sizeof(CDTrackInfo));
35
36#define reportDiscInfo(x)    reportDiscInfo((CDDiscInfo *)(x))
37#define reportRZoneInfo(y,x) reportTrackInfo((y),(CDTrackInfo *)(x))
38
39IODVDBlockStorageDevice *
40IODVDBlockStorageDriver::getProvider() const
41{
42    return (IODVDBlockStorageDevice *) IOService::getProvider();
43}
44
45/* Accept a new piece of media, doing whatever's necessary to make it
46 * show up properly to the system.
47 */
48IOReturn
49IODVDBlockStorageDriver::acceptNewMedia(void)
50{
51    IOReturn result;
52
53    if (getMediaType() < kDVDMediaTypeMin || getMediaType() > kDVDMediaTypeMax) {
54        return super::acceptNewMedia();
55    }
56
57    /* Obtain disc status: */
58
59    switch (getMediaType()) {
60        case kDVDMediaTypeR:
61        case kDVDMediaTypeRW: {
62            bool checkIsWritable = false;
63            DVDDiscInfo discInfo;
64            DVDRZoneInfo rzoneInfo;
65
66            result = reportDiscInfo(&discInfo);
67            if (result != kIOReturnSuccess) {
68                break;
69            }
70
71            switch (discInfo.discStatus) {
72                case 0x01: /* is disc incomplete? */
73                    checkIsWritable = true;
74                    break;
75                case 0x02: /* is disc complete? */
76                    checkIsWritable = discInfo.erasable ? true : false;
77                    break;
78            }
79
80            /* Obtain rzone status: */
81
82            if (checkIsWritable) {
83                UInt16 rzoneLast = (discInfo.lastRZoneNumberInLastBorderMSB << 8) |
84                                    discInfo.lastRZoneNumberInLastBorderLSB;
85
86                result = reportRZoneInfo(rzoneLast,&rzoneInfo);
87                if (result != kIOReturnSuccess) {
88                    break;
89                }
90
91                if (discInfo.discStatus == 0x01) { /* is disc incomplete? */
92                    _maxBlockNumber = max( _maxBlockNumber,
93                                           max( OSSwapBigToHostInt32(rzoneInfo.rzoneStartAddress) +
94                                                OSSwapBigToHostInt32(rzoneInfo.rzoneSize), 1 ) - 1 );
95                }
96
97                if (rzoneInfo.incremental) { /* is rzone incremental? */
98                    _writeProtected = false;
99                    break;
100                }
101
102                if (discInfo.discStatus == 0x01) { /* is disc incomplete? */
103                    if (rzoneInfo.blank) { /* is rzone invisible? */
104                        UInt16 rzoneFirst = (discInfo.firstRZoneNumberInLastBorderMSB << 8) |
105                                             discInfo.firstRZoneNumberInLastBorderLSB;
106
107                        if (rzoneFirst < rzoneLast) {
108                            result = reportRZoneInfo(rzoneLast - 1,&rzoneInfo);
109                            if (result != kIOReturnSuccess) {
110                                break;
111                            }
112
113                            if (rzoneInfo.incremental) { /* is rzone incremental? */
114                                _writeProtected = false;
115                                break;
116                            }
117                        }
118                    }
119                }
120            }
121
122            break;
123        }
124        case kDVDMediaTypePlusR:
125        case kDVDMediaTypeHDR: {
126            DVDDiscInfo discInfo;
127            DVDRZoneInfo rzoneInfo;
128            IOReturn result;
129
130            result = reportDiscInfo(&discInfo);
131            if (result != kIOReturnSuccess) {
132                break;
133            }
134
135            /* Obtain rzone status: */
136
137            if (discInfo.discStatus == 0x01) { /* is disc incomplete? */
138                UInt16 rzoneLast = (discInfo.lastRZoneNumberInLastBorderMSB << 8) |
139                                    discInfo.lastRZoneNumberInLastBorderLSB;
140
141                _writeProtected = false;
142
143                result = reportRZoneInfo(rzoneLast,&rzoneInfo);
144                if (result != kIOReturnSuccess) {
145                    break;
146                }
147
148                _maxBlockNumber = max( _maxBlockNumber,
149                                       max( OSSwapBigToHostInt32(rzoneInfo.rzoneStartAddress) +
150                                            OSSwapBigToHostInt32(rzoneInfo.rzoneSize), 1 ) - 1 );
151            }
152
153            break;
154        }
155    }
156
157    return IOBlockStorageDriver::acceptNewMedia();
158}
159
160const char *
161IODVDBlockStorageDriver::getDeviceTypeName(void)
162{
163    return(kIOBlockStorageDeviceTypeDVD);
164}
165
166IOMedia *
167IODVDBlockStorageDriver::instantiateDesiredMediaObject(void)
168{
169    if (getMediaType() < kDVDMediaTypeMin || getMediaType() > kDVDMediaTypeMax) {
170        return super::instantiateDesiredMediaObject();
171    }
172
173    return(new IODVDMedia);
174}
175
176IOMedia *
177IODVDBlockStorageDriver::instantiateMediaObject(UInt64 base,UInt64 byteSize,
178                                        UInt32 blockSize,char *mediaName)
179{
180    IOMedia *media = NULL;
181
182    if (getMediaType() < kDVDMediaTypeMin || getMediaType() > kDVDMediaTypeMax) {
183        return super::instantiateMediaObject(base,byteSize,blockSize,mediaName);
184    }
185
186    media = IOBlockStorageDriver::instantiateMediaObject(
187                                             base,byteSize,blockSize,mediaName);
188
189    if (media) {
190        const char *description = NULL;
191        const char *picture = NULL;
192
193        switch (getMediaType()) {
194            case kDVDMediaTypeROM:
195                description = kIODVDMediaTypeROM;
196                picture = "DVD.icns";
197                break;
198            case kDVDMediaTypeRAM:
199                description = kIODVDMediaTypeRAM;
200                picture = "DVD-RAM.icns";
201                break;
202            case kDVDMediaTypeR:
203                description = kIODVDMediaTypeR;
204                picture = "DVD-R.icns";
205                break;
206            case kDVDMediaTypeRW:
207                description = kIODVDMediaTypeRW;
208                picture = "DVD-RW.icns";
209                break;
210            case kDVDMediaTypePlusR:
211                description = kIODVDMediaTypePlusR;
212                picture = "DVD+R.icns";
213                break;
214            case kDVDMediaTypePlusRW:
215                description = kIODVDMediaTypePlusRW;
216                picture = "DVD+RW.icns";
217                break;
218            case kDVDMediaTypeHDROM:
219                description = kIODVDMediaTypeHDROM;
220                picture = "DVD.icns";
221                break;
222            case kDVDMediaTypeHDRAM:
223                description = kIODVDMediaTypeHDRAM;
224                picture = "DVD-RAM.icns";
225                break;
226            case kDVDMediaTypeHDR:
227                description = kIODVDMediaTypeHDR;
228                picture = "DVD-R.icns";
229                break;
230            case kDVDMediaTypeHDRW:
231                description = kIODVDMediaTypeHDRW;
232                picture = "DVD-RW.icns";
233                break;
234        }
235
236        if (description) {
237            media->setProperty(kIODVDMediaTypeKey, description);
238        }
239
240        if (picture) {
241            OSDictionary *dictionary = OSDictionary::withCapacity(2);
242            OSString *identifier = OSString::withCString("com.apple.iokit.IODVDStorageFamily");
243            OSString *resourceFile = OSString::withCString(picture);
244
245            if (dictionary && identifier && resourceFile) {
246                dictionary->setObject("CFBundleIdentifier", identifier);
247                dictionary->setObject("IOBundleResourceFile", resourceFile);
248            }
249
250            media->setProperty(kIOMediaIconKey, dictionary);
251
252            if (resourceFile) {
253                resourceFile->release();
254            }
255            if (identifier) {
256                identifier->release();
257            }
258            if (dictionary) {
259                dictionary->release();
260            }
261        }
262    }
263
264    return media;
265}
266
267IOReturn
268IODVDBlockStorageDriver::reportKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass,
269                                        const UInt32 lba,const UInt8 agid,const DVDKeyFormat keyFormat)
270{
271    return(getProvider()->reportKey(buffer,keyClass,lba,agid,keyFormat));
272}
273
274IOReturn
275IODVDBlockStorageDriver::sendKey(IOMemoryDescriptor *buffer,const DVDKeyClass keyClass,
276                                        const UInt8 agid,const DVDKeyFormat keyFormat)
277{
278    return(getProvider()->sendKey(buffer,keyClass,agid,keyFormat));
279}
280
281IOReturn
282IODVDBlockStorageDriver::readStructure(IOMemoryDescriptor *buffer,const DVDStructureFormat format,
283                                        const UInt32 address,const UInt8 layer,const UInt8 agid)
284{
285    return(getProvider()->readDVDStructure(buffer,format,address,layer,agid));
286}
287
288#ifdef __LP64__
289OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  0);
290#else /* !__LP64__ */
291OSMetaClassDefineReservedUsed(IODVDBlockStorageDriver,  0);
292#endif /* !__LP64__ */
293OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  1);
294OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  2);
295OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  3);
296OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  4);
297OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  5);
298OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  6);
299OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  7);
300OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  8);
301OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver,  9);
302OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 10);
303OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 11);
304OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 12);
305OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 13);
306OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 14);
307OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 15);
308OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 16);
309OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 17);
310OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 18);
311OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 19);
312OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 20);
313OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 21);
314OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 22);
315OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 23);
316OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 24);
317OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 25);
318OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 26);
319OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 27);
320OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 28);
321OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 29);
322OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 30);
323OSMetaClassDefineReservedUnused(IODVDBlockStorageDriver, 31);
324