1/*
2 * Copyright (c) 2006-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
24#include <IOKit/storage/IOBDBlockStorageDriver.h>
25#include <IOKit/storage/IOBDMedia.h>
26
27#define super IODVDBlockStorageDriver
28OSDefineMetaClassAndStructors(IOBDBlockStorageDriver, IODVDBlockStorageDriver)
29
30OSCompileAssert(sizeof(BDDiscInfo) == sizeof(CDDiscInfo));
31OSCompileAssert(sizeof(BDTrackInfo) == sizeof(CDTrackInfo));
32
33#define reportDiscInfo(x)    reportDiscInfo((CDDiscInfo *)(x))
34#define reportTrackInfo(y,x) reportTrackInfo((y),(CDTrackInfo *)(x))
35
36IOBDBlockStorageDevice *
37IOBDBlockStorageDriver::getProvider() const
38{
39    return (IOBDBlockStorageDevice *) IOService::getProvider();
40}
41
42/* Accept a new piece of media, doing whatever's necessary to make it
43 * show up properly to the system.
44 */
45IOReturn
46IOBDBlockStorageDriver::acceptNewMedia(void)
47{
48    if (getMediaType() < kBDMediaTypeMin || getMediaType() > kBDMediaTypeMax) {
49        return super::acceptNewMedia();
50    }
51
52    /* Obtain disc status: */
53
54    switch (getMediaType()) {
55        case kBDMediaTypeR: {
56            BDDiscInfo discInfo;
57            BDTrackInfo trackInfo;
58            IOReturn result;
59
60            result = reportDiscInfo(&discInfo);
61            if (result != kIOReturnSuccess) {
62                break;
63            }
64
65            /* Obtain track status: */
66
67            if (discInfo.discStatus == 0x01) { /* is disc incomplete? */
68                UInt16 trackLast = (discInfo.lastTrackNumberInLastSessionMSB << 8) |
69                                    discInfo.lastTrackNumberInLastSessionLSB;
70
71                _writeProtected = false;
72
73                result = reportTrackInfo(trackLast,&trackInfo);
74                if (result != kIOReturnSuccess) {
75                    break;
76                }
77
78                _maxBlockNumber = max( _maxBlockNumber,
79                                       max( OSSwapBigToHostInt32(trackInfo.trackStartAddress) +
80                                            OSSwapBigToHostInt32(trackInfo.trackSize), 1 ) - 1 );
81            } else if (discInfo.discStatus == 0x03) { /* is disc random recordable? */
82                _writeProtected = false;
83            }
84
85            break;
86        }
87    }
88
89    return IOBlockStorageDriver::acceptNewMedia();
90}
91
92const char *
93IOBDBlockStorageDriver::getDeviceTypeName(void)
94{
95    return(kIOBlockStorageDeviceTypeBD);
96}
97
98IOMedia *
99IOBDBlockStorageDriver::instantiateDesiredMediaObject(void)
100{
101    if (getMediaType() < kBDMediaTypeMin || getMediaType() > kBDMediaTypeMax) {
102        return super::instantiateDesiredMediaObject();
103    }
104
105    return(new IOBDMedia);
106}
107
108IOMedia *
109IOBDBlockStorageDriver::instantiateMediaObject(UInt64 base,UInt64 byteSize,
110                                        UInt32 blockSize,char *mediaName)
111{
112    IOMedia *media = NULL;
113
114    if (getMediaType() < kBDMediaTypeMin || getMediaType() > kBDMediaTypeMax) {
115        return super::instantiateMediaObject(base,byteSize,blockSize,mediaName);
116    }
117
118    media = IOBlockStorageDriver::instantiateMediaObject(
119                                             base,byteSize,blockSize,mediaName);
120
121    if (media) {
122        const char *description = NULL;
123        const char *picture = NULL;
124
125        switch (getMediaType()) {
126            case kBDMediaTypeROM:
127                description = kIOBDMediaTypeROM;
128                picture = "BD.icns";
129                break;
130            case kBDMediaTypeR:
131                description = kIOBDMediaTypeR;
132                picture = "BD-R.icns";
133                break;
134            case kBDMediaTypeRE:
135                description = kIOBDMediaTypeRE;
136                picture = "BD-RE.icns";
137                break;
138        }
139
140        if (description) {
141            media->setProperty(kIOBDMediaTypeKey, description);
142        }
143
144        if (picture) {
145            OSDictionary *dictionary = OSDictionary::withCapacity(2);
146            OSString *identifier = OSString::withCString("com.apple.iokit.IOBDStorageFamily");
147            OSString *resourceFile = OSString::withCString(picture);
148
149            if (dictionary && identifier && resourceFile) {
150                dictionary->setObject("CFBundleIdentifier", identifier);
151                dictionary->setObject("IOBundleResourceFile", resourceFile);
152            }
153
154            media->setProperty(kIOMediaIconKey, dictionary);
155
156            if (resourceFile) {
157                resourceFile->release();
158            }
159            if (identifier) {
160                identifier->release();
161            }
162            if (dictionary) {
163                dictionary->release();
164            }
165        }
166    }
167
168    return media;
169}
170
171IOReturn
172IOBDBlockStorageDriver::readStructure(IOMemoryDescriptor *buffer,const DVDStructureFormat format,
173                                        const UInt32 address,const UInt8 layer,const UInt8 agid)
174{
175    if (getMediaType() < kBDMediaTypeMin || getMediaType() > kBDMediaTypeMax) {
176        return super::readStructure(buffer,format,address,layer,agid);
177    }
178
179    return(getProvider()->readDiscStructure(buffer,format,address,layer,agid,1));
180}
181
182IOReturn
183IOBDBlockStorageDriver::splitTrack(UInt32 address)
184{
185    return(getProvider()->splitTrack(address));
186}
187
188OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  0);
189OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  1);
190OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  2);
191OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  3);
192OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  4);
193OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  5);
194OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  6);
195OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  7);
196OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  8);
197OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver,  9);
198OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver, 10);
199OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver, 11);
200OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver, 12);
201OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver, 13);
202OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver, 14);
203OSMetaClassDefineReservedUnused(IOBDBlockStorageDriver, 15);
204