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
24#include <IOKit/storage/IOFilterScheme.h>
25
26#define super IOStorage
27OSDefineMetaClassAndStructors(IOFilterScheme, IOStorage)
28
29#ifndef __LP64__
30extern IOStorageAttributes gIOStorageAttributesUnsupported;
31#endif /* !__LP64__ */
32
33IOMedia * IOFilterScheme::getProvider() const
34{
35    //
36    // Obtain this object's provider.  We override the superclass's method
37    // to return a more specific subclass of OSObject -- an IOMedia.  This
38    // method serves simply as a convenience to subclass developers.
39    //
40
41    return (IOMedia *) IOService::getProvider();
42}
43
44bool IOFilterScheme::handleOpen(IOService *  client,
45                                IOOptionBits options,
46                                void *       argument)
47{
48    //
49    // The handleOpen method grants or denies permission to access this object
50    // to an interested client.  The argument is an IOStorageAccess value that
51    // specifies the level of access desired -- reader or reader-writer.
52    //
53    // This method can be invoked to upgrade or downgrade the access level for
54    // an existing client as well.  The previous access level will prevail for
55    // upgrades that fail, of course.   A downgrade should never fail.  If the
56    // new access level should be the same as the old for a given client, this
57    // method will do nothing and return success.  In all cases, one, singular
58    // close-per-client is expected for all opens-per-client received.
59    //
60    // This implementation replaces the IOService definition of handleOpen().
61    //
62    // We are guaranteed that no other opens or closes will be processed until
63    // we make our decision, change our state, and return from this method.
64    //
65
66    return getProvider()->open(this, options, (uintptr_t) argument);
67}
68
69bool IOFilterScheme::handleIsOpen(const IOService * client) const
70{
71    //
72    // The handleIsOpen method determines whether the specified client, or any
73    // client if none is specificed, presently has an open on this object.
74    //
75    // This implementation replaces the IOService definition of handleIsOpen().
76    //
77    // We are guaranteed that no other opens or closes will be processed until
78    // we return from this method.
79    //
80
81    return getProvider()->isOpen(this);
82}
83
84void IOFilterScheme::handleClose(IOService * client, IOOptionBits options)
85{
86    //
87    // The handleClose method closes the client's access to this object.
88    //
89    // This implementation replaces the IOService definition of handleClose().
90    //
91    // We are guaranteed that no other opens or closes will be processed until
92    // we change our state and return from this method.
93    //
94
95    getProvider()->close(this, options);
96}
97
98void IOFilterScheme::read(IOService *           client,
99                          UInt64                byteStart,
100                          IOMemoryDescriptor *  buffer,
101                          IOStorageAttributes * attributes,
102                          IOStorageCompletion * completion)
103{
104    //
105    // Read data from the storage object at the specified byte offset into the
106    // specified buffer, asynchronously.   When the read completes, the caller
107    // will be notified via the specified completion action.
108    //
109    // The buffer will be retained for the duration of the read.
110    //
111    // For simple filter schemes, the default behavior is to simply pass the
112    // read through to the provider media.  More complex filter schemes such
113    // as RAID will need to do extra processing here.
114    //
115
116#ifndef __LP64__
117    if ( IOStorage::_expansionData )
118    {
119        if ( attributes == &gIOStorageAttributesUnsupported )
120        {
121            attributes = NULL;
122        }
123        else
124        {
125            IOStorage::read( client, byteStart, buffer, attributes, completion );
126
127            return;
128        }
129    }
130#endif /* !__LP64__ */
131
132    getProvider( )->read( this, byteStart, buffer, attributes, completion );
133}
134
135void IOFilterScheme::write(IOService *           client,
136                           UInt64                byteStart,
137                           IOMemoryDescriptor *  buffer,
138                           IOStorageAttributes * attributes,
139                           IOStorageCompletion * completion)
140{
141    //
142    // Write data into the storage object at the specified byte offset from the
143    // specified buffer, asynchronously.   When the write completes, the caller
144    // will be notified via the specified completion action.
145    //
146    // The buffer will be retained for the duration of the write.
147    //
148    // For simple filter schemes, the default behavior is to simply pass the
149    // write through to the provider media. More complex filter schemes such
150    // as RAID will need to do extra processing here.
151    //
152
153#ifndef __LP64__
154    if ( IOStorage::_expansionData )
155    {
156        if ( attributes == &gIOStorageAttributesUnsupported )
157        {
158            attributes = NULL;
159        }
160        else
161        {
162            IOStorage::write( client, byteStart, buffer, attributes, completion );
163
164            return;
165        }
166    }
167#endif /* !__LP64__ */
168
169    getProvider( )->write( this, byteStart, buffer, attributes, completion );
170}
171
172IOReturn IOFilterScheme::synchronizeCache(IOService * client)
173{
174    //
175    // Flush the cached data in the storage object, if any, synchronously.
176    //
177
178    return getProvider()->synchronizeCache(this);
179}
180
181IOReturn IOFilterScheme::unmap(IOService *       client,
182                               IOStorageExtent * extents,
183                               UInt32            extentsCount,
184                               UInt32            options)
185{
186    //
187    // Delete unused data from the storage object at the specified byte offsets,
188    // synchronously.
189    //
190
191    return getProvider( )->unmap( this, extents, extentsCount, options );
192}
193
194bool IOFilterScheme::lockPhysicalExtents(IOService * client)
195{
196    //
197    // Lock the contents of the storage object against relocation temporarily,
198    // for the purpose of getting physical extents.
199    //
200
201    return getProvider( )->lockPhysicalExtents( this );
202}
203
204IOStorage * IOFilterScheme::copyPhysicalExtent(IOService * client,
205                                               UInt64 *    byteStart,
206                                               UInt64 *    byteCount)
207{
208    //
209    // Convert the specified byte offset into a physical byte offset, relative
210    // to a physical storage object.  This call should only be made within the
211    // context of lockPhysicalExtents().
212    //
213
214    return getProvider( )->copyPhysicalExtent( this, byteStart, byteCount );
215}
216
217void IOFilterScheme::unlockPhysicalExtents(IOService * client)
218{
219    //
220    // Unlock the contents of the storage object for relocation again.  This
221    // call must balance a successful call to lockPhysicalExtents().
222    //
223
224    getProvider( )->unlockPhysicalExtents( this );
225}
226
227IOReturn IOFilterScheme::setPriority(IOService *       client,
228                                     IOStorageExtent * extents,
229                                     UInt32            extentsCount,
230                                     IOStoragePriority priority)
231{
232    //
233    // Reprioritize read or write requests at the specified byte offsets.
234    //
235
236    return getProvider( )->setPriority( this, extents, extentsCount, priority );
237}
238
239OSMetaClassDefineReservedUnused(IOFilterScheme,  0);
240OSMetaClassDefineReservedUnused(IOFilterScheme,  1);
241OSMetaClassDefineReservedUnused(IOFilterScheme,  2);
242OSMetaClassDefineReservedUnused(IOFilterScheme,  3);
243OSMetaClassDefineReservedUnused(IOFilterScheme,  4);
244OSMetaClassDefineReservedUnused(IOFilterScheme,  5);
245OSMetaClassDefineReservedUnused(IOFilterScheme,  6);
246OSMetaClassDefineReservedUnused(IOFilterScheme,  7);
247OSMetaClassDefineReservedUnused(IOFilterScheme,  8);
248OSMetaClassDefineReservedUnused(IOFilterScheme,  9);
249OSMetaClassDefineReservedUnused(IOFilterScheme, 10);
250OSMetaClassDefineReservedUnused(IOFilterScheme, 11);
251OSMetaClassDefineReservedUnused(IOFilterScheme, 12);
252OSMetaClassDefineReservedUnused(IOFilterScheme, 13);
253OSMetaClassDefineReservedUnused(IOFilterScheme, 14);
254OSMetaClassDefineReservedUnused(IOFilterScheme, 15);
255OSMetaClassDefineReservedUnused(IOFilterScheme, 16);
256OSMetaClassDefineReservedUnused(IOFilterScheme, 17);
257OSMetaClassDefineReservedUnused(IOFilterScheme, 18);
258OSMetaClassDefineReservedUnused(IOFilterScheme, 19);
259OSMetaClassDefineReservedUnused(IOFilterScheme, 20);
260OSMetaClassDefineReservedUnused(IOFilterScheme, 21);
261OSMetaClassDefineReservedUnused(IOFilterScheme, 22);
262OSMetaClassDefineReservedUnused(IOFilterScheme, 23);
263OSMetaClassDefineReservedUnused(IOFilterScheme, 24);
264OSMetaClassDefineReservedUnused(IOFilterScheme, 25);
265OSMetaClassDefineReservedUnused(IOFilterScheme, 26);
266OSMetaClassDefineReservedUnused(IOFilterScheme, 27);
267OSMetaClassDefineReservedUnused(IOFilterScheme, 28);
268OSMetaClassDefineReservedUnused(IOFilterScheme, 29);
269OSMetaClassDefineReservedUnused(IOFilterScheme, 30);
270OSMetaClassDefineReservedUnused(IOFilterScheme, 31);
271
272#ifndef __LP64__
273extern "C" void _ZN14IOFilterScheme4readEP9IOServiceyP18IOMemoryDescriptor19IOStorageCompletion( IOFilterScheme * scheme, IOService * client, UInt64 byteStart, IOMemoryDescriptor * buffer, IOStorageCompletion completion )
274{
275    scheme->read( client, byteStart, buffer, NULL, &completion );
276}
277
278extern "C" void _ZN14IOFilterScheme5writeEP9IOServiceyP18IOMemoryDescriptor19IOStorageCompletion( IOFilterScheme * scheme, IOService * client, UInt64 byteStart, IOMemoryDescriptor * buffer, IOStorageCompletion completion )
279{
280    scheme->write( client, byteStart, buffer, NULL, &completion );
281}
282#endif /* !__LP64__ */
283