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 #include <IOKit/storage/IOPartitionScheme.h>
25 #define super IOStorage
26 OSDefineMetaClassAndStructors(IOPartitionScheme
, IOStorage
)
28 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
30 IOMedia
* IOPartitionScheme::getProvider() const
33 // Obtain this object's provider. We override the superclass's method
34 // to return a more specific subclass of OSObject -- an IOMedia. This
35 // method serves simply as a convenience to subclass developers.
38 return (IOMedia
*) IOService::getProvider();
41 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
43 bool IOPartitionScheme::init(OSDictionary
* properties
= 0)
46 // Initialize this object's minimal state.
49 if (super::init(properties
) == false) return false;
51 _openLevel
= kIOStorageAccessNone
;
52 _openReaders
= OSSet::withCapacity(16);
53 _openReaderWriters
= OSSet::withCapacity(16);
55 if (_openReaders
== 0 || _openReaderWriters
== 0) return false;
60 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
62 void IOPartitionScheme::free()
65 // Free all of this object's outstanding resources.
68 if (_openReaders
) _openReaders
->release();
69 if (_openReaderWriters
) _openReaderWriters
->release();
74 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
76 bool IOPartitionScheme::handleOpen(IOService
* client
,
81 // The handleOpen method grants or denies permission to access this object
82 // to an interested client. The argument is an IOStorageAccess value that
83 // specifies the level of access desired -- reader or reader-writer.
85 // This method can be invoked to upgrade or downgrade the access level for
86 // an existing client as well. The previous access level will prevail for
87 // upgrades that fail, of course. A downgrade should never fail. If the
88 // new access level should be the same as the old for a given client, this
89 // method will do nothing and return success. In all cases, one, singular
90 // close-per-client is expected for all opens-per-client received.
92 // This implementation replaces the IOService definition of handleOpen().
94 // We are guaranteed that no other opens or closes will be processed until
95 // we make our decision, change our state, and return from this method.
98 IOStorageAccess access
= (IOStorageAccess
) argument
;
99 IOStorageAccess level
;
102 assert( access
== kIOStorageAccessReader
||
103 access
== kIOStorageAccessReaderWriter
);
106 // A partition scheme multiplexes the opens it receives from several clients
107 // and sends one open to the level below that satisfies the highest level of
111 unsigned writers
= _openReaderWriters
->getCount();
113 if (_openReaderWriters
->containsObject(client
)) writers
--;
114 if (access
== kIOStorageAccessReaderWriter
) writers
++;
116 level
= (writers
) ? kIOStorageAccessReaderWriter
: kIOStorageAccessReader
;
119 // Determine whether the levels below us accept this open or not (we avoid
120 // the open if the required access is the access we already hold).
123 if (_openLevel
!= level
) // (has open level changed?)
125 IOStorage
* provider
= OSDynamicCast(IOStorage
, getProvider());
127 if (provider
&& provider
->open(this, options
, level
) == false)
135 if (access
== kIOStorageAccessReader
)
137 _openReaders
->setObject(client
);
139 _openReaderWriters
->removeObject(client
); // (for a downgrade)
141 else // (access == kIOStorageAccessReaderWriter)
143 _openReaderWriters
->setObject(client
);
145 _openReaders
->removeObject(client
); // (for an upgrade)
153 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
155 bool IOPartitionScheme::handleIsOpen(const IOService
* client
) const
158 // The handleIsOpen method determines whether the specified client, or any
159 // client if none is specificed, presently has an open on this object.
161 // This implementation replaces the IOService definition of handleIsOpen().
163 // We are guaranteed that no other opens or closes will be processed until
164 // we return from this method.
167 if (client
== 0) return (_openLevel
!= kIOStorageAccessNone
);
169 return ( _openReaderWriters
->containsObject(client
) ||
170 _openReaders
->containsObject(client
) );
173 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
175 void IOPartitionScheme::handleClose(IOService
* client
, IOOptionBits options
)
178 // The handleClose method closes the client's access to this object.
180 // This implementation replaces the IOService definition of handleClose().
182 // We are guaranteed that no other opens or closes will be processed until
183 // we change our state and return from this method.
189 // Process the close.
192 if (_openReaderWriters
->containsObject(client
)) // (is it a reader-writer?)
194 _openReaderWriters
->removeObject(client
);
196 else if (_openReaders
->containsObject(client
)) // (is the client a reader?)
198 _openReaders
->removeObject(client
);
200 else // (is the client is an imposter?)
207 // Reevaluate the open we have on the level below us. If no opens remain,
208 // we close, or if no reader-writer remains, but readers do, we downgrade.
211 IOStorageAccess level
;
213 if (_openReaderWriters
->getCount()) level
= kIOStorageAccessReaderWriter
;
214 else if (_openReaders
->getCount()) level
= kIOStorageAccessReader
;
215 else level
= kIOStorageAccessNone
;
217 if (_openLevel
!= level
) // (has open level changed?)
219 IOStorage
* provider
= OSDynamicCast(IOStorage
, getProvider());
221 assert(level
!= kIOStorageAccessReaderWriter
);
225 if (level
== kIOStorageAccessNone
) // (is a close in order?)
227 provider
->close(this, options
);
229 else // (is a downgrade in order?)
232 success
= provider
->open(this, 0, level
);
233 assert(success
); // (should never fail, unless avoided deadlock)
237 _openLevel
= level
; // (set new open level)
241 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
243 void IOPartitionScheme::read(IOService
* /* client */,
245 IOMemoryDescriptor
* buffer
,
246 IOStorageCompletion completion
)
249 // Read data from the storage object at the specified byte offset into the
250 // specified buffer, asynchronously. When the read completes, the caller
251 // will be notified via the specified completion action.
253 // The buffer will be retained for the duration of the read.
255 // For simple partition schemes, the default behavior is to simply pass the
256 // read through to the provider media. More complex partition schemes such
257 // as RAID will need to do extra processing here.
260 getProvider()->read(this, byteStart
, buffer
, completion
);
263 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
265 void IOPartitionScheme::write(IOService
* /* client */,
267 IOMemoryDescriptor
* buffer
,
268 IOStorageCompletion completion
)
271 // Write data into the storage object at the specified byte offset from the
272 // specified buffer, asynchronously. When the write completes, the caller
273 // will be notified via the specified completion action.
275 // The buffer will be retained for the duration of the write.
277 // For simple partition schemes, the default behavior is to simply pass the
278 // write through to the provider media. More complex partition schemes such
279 // as RAID will need to do extra processing here.
282 getProvider()->write(this, byteStart
, buffer
, completion
);
285 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
287 IOReturn
IOPartitionScheme::synchronizeCache(IOService
* client
)
289 return getProvider()->synchronizeCache(this);
292 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
294 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 0);
296 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
298 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 1);
300 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
302 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 2);
304 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
306 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 3);
308 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
310 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 4);
312 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
314 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 5);
316 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
318 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 6);
320 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
322 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 7);
324 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
326 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 8);
328 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
330 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 9);
332 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
334 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 10);
336 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
338 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 11);
340 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
342 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 12);
344 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
346 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 13);
348 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
350 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 14);
352 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
354 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 15);
356 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
358 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 16);
360 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
362 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 17);
364 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
366 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 18);
368 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
370 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 19);
372 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
374 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 20);
376 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
378 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 21);
380 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
382 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 22);
384 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
386 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 23);
388 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
390 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 24);
392 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
394 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 25);
396 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
398 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 26);
400 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
402 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 27);
404 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
406 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 28);
408 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
410 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 29);
412 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
414 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 30);
416 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
418 OSMetaClassDefineReservedUnused(IOPartitionScheme
, 31);