1/*
2 * Copyright (c) 1998-2014 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/IOLib.h>
24#include <IOKit/IOUserClient.h>
25#include <IOKit/storage/IOBlockStorageDevice.h>
26
27#define	super	IOService
28OSDefineMetaClassAndAbstractStructors(IOBlockStorageDevice,IOService)
29
30bool
31IOBlockStorageDevice::init(OSDictionary * properties)
32{
33    bool result;
34
35    result = super::init(properties);
36    if (result) {
37        result = setProperty(kIOBlockStorageDeviceTypeKey,
38                             kIOBlockStorageDeviceTypeGeneric);
39    }
40
41    return(result);
42}
43
44/* Route a user-client getter request.  We should make a full-
45 * fledged user-client for IOBlockStorageDevice at some point.
46 */
47OSObject *
48IOBlockStorageDevice::getProperty(const OSSymbol * key) const
49{
50    OSObject *obj = NULL;
51
52    if (key->isEqualTo(kIOBlockStorageDeviceWriteCacheStateKey)) {
53        bool enabled;
54        IOReturn result;
55
56        result = ((IOBlockStorageDevice *)this)->getWriteCacheState(&enabled);
57        if (result == kIOReturnSuccess) {
58            obj = (enabled) ? kOSBooleanTrue : kOSBooleanFalse;
59        }
60/*  } else if (key->isEqualTo(...)) {
61 *      obj = ...;
62 */
63    } else {
64        obj = super::getProperty(key);
65    }
66
67    return(obj);
68}
69
70/* Route a user-client setter request.  We should make a full-
71 * fledged user-client for IOBlockStorageDevice at some point.
72 */
73IOReturn
74IOBlockStorageDevice::setProperties(OSObject * properties)
75{
76    OSDictionary *dict;
77    OSObject *obj;
78    IOReturn result;
79
80    result = super::setProperties(properties);
81    if (result != kIOReturnUnsupported) {
82        return(result);
83    }
84
85    result = IOUserClient::clientHasPrivilege(current_task(),kIOClientPrivilegeAdministrator);
86    if (result != kIOReturnSuccess) {
87        return(result);
88    }
89
90    dict = OSDynamicCast(OSDictionary,properties);
91    if (!dict) {
92        return(kIOReturnBadArgument);
93    }
94
95    obj = dict->getObject(kIOBlockStorageDeviceWriteCacheStateKey);
96    if (obj) {
97        if (OSDynamicCast(OSBoolean,obj)) {
98            result = setWriteCacheState((obj == kOSBooleanTrue));
99        } else {
100            result = kIOReturnBadArgument;
101        }
102        return(result);
103    }
104
105/*  obj = dict->getObject(...);
106 *  if (obj) {
107 *      result = ...;
108 *      return(result);
109 *  }
110 */
111
112    return(kIOReturnUnsupported);
113}
114
115#ifndef __LP64__
116IOReturn
117IOBlockStorageDevice::reportMaxReadTransfer(UInt64 blockSize,UInt64 *max)
118{
119    return(kIOReturnUnsupported);
120}
121
122IOReturn
123IOBlockStorageDevice::reportMaxWriteTransfer(UInt64 blockSize,UInt64 *max)
124{
125    return(kIOReturnUnsupported);
126}
127
128IOReturn
129IOBlockStorageDevice::doSyncReadWrite(IOMemoryDescriptor *buffer,
130                                      UInt32 block,UInt32 nblks)
131{
132    return(kIOReturnUnsupported);
133}
134
135IOReturn
136IOBlockStorageDevice::doAsyncReadWrite(IOMemoryDescriptor *buffer,
137                                       UInt32 block, UInt32 nblks,
138                                       IOStorageCompletion completion)
139{
140    return(kIOReturnUnsupported);
141}
142
143IOReturn
144IOBlockStorageDevice::doAsyncReadWrite(IOMemoryDescriptor *buffer,
145                                       UInt64 block,UInt64 nblks,
146                                       IOStorageCompletion completion)
147{
148    if ((block >> 32) || (nblks >> 32)) {
149        return(kIOReturnUnsupported);
150    } else {
151        return(doAsyncReadWrite(buffer,(UInt32)block,(UInt32)nblks,completion));
152    }
153}
154
155IOReturn
156IOBlockStorageDevice::getWriteCacheState(bool *enabled)
157{
158    return(kIOReturnUnsupported);
159}
160
161IOReturn
162IOBlockStorageDevice::setWriteCacheState(bool enabled)
163{
164    return(kIOReturnUnsupported);
165}
166
167IOReturn
168IOBlockStorageDevice::doAsyncReadWrite(IOMemoryDescriptor *buffer,
169                                       UInt64 block,UInt64 nblks,
170                                       IOStorageAttributes *attributes,
171                                       IOStorageCompletion *completion)
172{
173    if (attributes && attributes->options) {
174        return(kIOReturnUnsupported);
175    } else {
176        return(doAsyncReadWrite(buffer,block,nblks,completion ? *completion : (IOStorageCompletion) { 0 }));
177    }
178}
179#endif /* !__LP64__ */
180
181IOReturn
182IOBlockStorageDevice::doLockUnlockMedia(bool doLock)
183{
184    return(kIOReturnUnsupported);
185}
186
187IOReturn
188IOBlockStorageDevice::reportLockability(bool *isLockable)
189{
190    return(kIOReturnUnsupported);
191}
192
193IOReturn
194IOBlockStorageDevice::reportPollRequirements(bool *pollRequired,
195                                             bool *pollIsExpensive)
196{
197    return(kIOReturnUnsupported);
198}
199
200IOReturn
201IOBlockStorageDevice::requestIdle(void)
202{
203    return(kIOReturnUnsupported);
204}
205
206IOReturn
207IOBlockStorageDevice::doDiscard(UInt64 block, UInt64 nblks)
208{
209    return(kIOReturnUnsupported);
210}
211
212IOReturn
213IOBlockStorageDevice::doUnmap(IOBlockStorageDeviceExtent * extents,
214                              UInt32                       extentsCount,
215                              UInt32                       options)
216{
217    if (options) {
218        return(kIOReturnUnsupported);
219    } else {
220        UInt32 i;
221
222        for (i = 0; i < extentsCount; i++) {
223            IOReturn result;
224
225            result = doDiscard(extents[i].blockStart, extents[i].blockCount);
226            if (result != kIOReturnSuccess) {
227                return(result);
228            }
229        }
230    }
231
232    return(kIOReturnSuccess);
233}
234
235IOReturn
236IOBlockStorageDevice::doSetPriority(IOBlockStorageDeviceExtent * extents,
237                                    UInt32                       extentsCount,
238                                    IOStoragePriority            priority)
239{
240    return(kIOReturnUnsupported);
241}
242
243OSMetaClassDefineReservedUsed(IOBlockStorageDevice,  0);
244OSMetaClassDefineReservedUsed(IOBlockStorageDevice,  1);
245#ifdef __LP64__
246OSMetaClassDefineReservedUnused(IOBlockStorageDevice,  2);
247OSMetaClassDefineReservedUnused(IOBlockStorageDevice,  3);
248OSMetaClassDefineReservedUnused(IOBlockStorageDevice,  4);
249OSMetaClassDefineReservedUnused(IOBlockStorageDevice,  5);
250OSMetaClassDefineReservedUnused(IOBlockStorageDevice,  6);
251OSMetaClassDefineReservedUnused(IOBlockStorageDevice,  7);
252#else /* !__LP64__ */
253OSMetaClassDefineReservedUsed(IOBlockStorageDevice,  2);
254OSMetaClassDefineReservedUsed(IOBlockStorageDevice,  3);
255OSMetaClassDefineReservedUsed(IOBlockStorageDevice,  4);
256OSMetaClassDefineReservedUsed(IOBlockStorageDevice,  5);
257OSMetaClassDefineReservedUsed(IOBlockStorageDevice,  6);
258OSMetaClassDefineReservedUsed(IOBlockStorageDevice,  7);
259#endif /* !__LP64__ */
260OSMetaClassDefineReservedUnused(IOBlockStorageDevice,  8);
261OSMetaClassDefineReservedUnused(IOBlockStorageDevice,  9);
262OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 10);
263OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 11);
264OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 12);
265OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 13);
266OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 14);
267OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 15);
268OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 16);
269OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 17);
270OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 18);
271OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 19);
272OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 20);
273OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 21);
274OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 22);
275OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 23);
276OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 24);
277OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 25);
278OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 26);
279OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 27);
280OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 28);
281OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 29);
282OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 30);
283OSMetaClassDefineReservedUnused(IOBlockStorageDevice, 31);
284