]>
Commit | Line | Data |
---|---|---|
1c79356b A |
1 | /* |
2 | * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
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. | |
11 | * | |
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 | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | ||
23 | #include <IOKit/storage/IOPartitionScheme.h> | |
24 | ||
25 | #define super IOStorage | |
26 | OSDefineMetaClassAndStructors(IOPartitionScheme, IOStorage) | |
27 | ||
28 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
29 | ||
30 | IOMedia * IOPartitionScheme::getProvider() const | |
31 | { | |
32 | // | |
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. | |
36 | // | |
37 | ||
38 | return (IOMedia *) IOService::getProvider(); | |
39 | } | |
40 | ||
41 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
42 | ||
43 | bool IOPartitionScheme::init(OSDictionary * properties = 0) | |
44 | { | |
45 | // | |
46 | // Initialize this object's minimal state. | |
47 | // | |
48 | ||
49 | if (super::init(properties) == false) return false; | |
50 | ||
51 | _openLevel = kIOStorageAccessNone; | |
52 | _openReaders = OSSet::withCapacity(16); | |
53 | _openReaderWriters = OSSet::withCapacity(16); | |
54 | ||
55 | if (_openReaders == 0 || _openReaderWriters == 0) return false; | |
56 | ||
57 | return true; | |
58 | } | |
59 | ||
60 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
61 | ||
62 | void IOPartitionScheme::free() | |
63 | { | |
64 | // | |
65 | // Free all of this object's outstanding resources. | |
66 | // | |
67 | ||
68 | if (_openReaders) _openReaders->release(); | |
69 | if (_openReaderWriters) _openReaderWriters->release(); | |
70 | ||
71 | super::free(); | |
72 | } | |
73 | ||
74 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
75 | ||
76 | bool IOPartitionScheme::handleOpen(IOService * client, | |
77 | IOOptionBits options, | |
78 | void * argument) | |
79 | { | |
80 | // | |
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. | |
84 | // | |
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. | |
91 | // | |
92 | // This implementation replaces the IOService definition of handleOpen(). | |
93 | // | |
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. | |
96 | // | |
97 | ||
98 | IOStorageAccess access = (IOStorageAccess) argument; | |
99 | IOStorageAccess level; | |
100 | ||
101 | assert(client); | |
102 | assert( access == kIOStorageAccessReader || | |
103 | access == kIOStorageAccessReaderWriter ); | |
104 | ||
105 | // | |
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 | |
108 | // access. | |
109 | // | |
110 | ||
111 | unsigned writers = _openReaderWriters->getCount(); | |
112 | ||
113 | if (_openReaderWriters->containsObject(client)) writers--; | |
114 | if (access == kIOStorageAccessReaderWriter) writers++; | |
115 | ||
116 | level = (writers) ? kIOStorageAccessReaderWriter : kIOStorageAccessReader; | |
117 | ||
118 | // | |
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). | |
121 | // | |
122 | ||
123 | if (_openLevel != level) // (has open level changed?) | |
124 | { | |
125 | IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); | |
126 | ||
127 | if (provider && provider->open(this, options, level) == false) | |
128 | return false; | |
129 | } | |
130 | ||
131 | // | |
132 | // Process the open. | |
133 | // | |
134 | ||
135 | if (access == kIOStorageAccessReader) | |
136 | { | |
137 | _openReaders->setObject(client); | |
138 | ||
139 | _openReaderWriters->removeObject(client); // (for a downgrade) | |
140 | } | |
141 | else // (access == kIOStorageAccessReaderWriter) | |
142 | { | |
143 | _openReaderWriters->setObject(client); | |
144 | ||
145 | _openReaders->removeObject(client); // (for an upgrade) | |
146 | } | |
147 | ||
148 | _openLevel = level; | |
149 | ||
150 | return true; | |
151 | } | |
152 | ||
153 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
154 | ||
155 | bool IOPartitionScheme::handleIsOpen(const IOService * client) const | |
156 | { | |
157 | // | |
158 | // The handleIsOpen method determines whether the specified client, or any | |
159 | // client if none is specificed, presently has an open on this object. | |
160 | // | |
161 | // This implementation replaces the IOService definition of handleIsOpen(). | |
162 | // | |
163 | // We are guaranteed that no other opens or closes will be processed until | |
164 | // we return from this method. | |
165 | // | |
166 | ||
167 | if (client == 0) return (_openLevel != kIOStorageAccessNone); | |
168 | ||
169 | return ( _openReaderWriters->containsObject(client) || | |
170 | _openReaders->containsObject(client) ); | |
171 | } | |
172 | ||
173 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
174 | ||
175 | void IOPartitionScheme::handleClose(IOService * client, IOOptionBits options) | |
176 | { | |
177 | // | |
178 | // The handleClose method closes the client's access to this object. | |
179 | // | |
180 | // This implementation replaces the IOService definition of handleClose(). | |
181 | // | |
182 | // We are guaranteed that no other opens or closes will be processed until | |
183 | // we change our state and return from this method. | |
184 | // | |
185 | ||
186 | assert(client); | |
187 | ||
188 | // | |
189 | // Process the close. | |
190 | // | |
191 | ||
192 | if (_openReaderWriters->containsObject(client)) // (is it a reader-writer?) | |
193 | { | |
194 | _openReaderWriters->removeObject(client); | |
195 | } | |
196 | else if (_openReaders->containsObject(client)) // (is the client a reader?) | |
197 | { | |
198 | _openReaders->removeObject(client); | |
199 | } | |
200 | else // (is the client is an imposter?) | |
201 | { | |
202 | assert(0); | |
203 | return; | |
204 | } | |
205 | ||
206 | // | |
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. | |
209 | // | |
210 | ||
211 | IOStorageAccess level; | |
212 | ||
213 | if (_openReaderWriters->getCount()) level = kIOStorageAccessReaderWriter; | |
214 | else if (_openReaders->getCount()) level = kIOStorageAccessReader; | |
215 | else level = kIOStorageAccessNone; | |
216 | ||
217 | if (_openLevel != level) // (has open level changed?) | |
218 | { | |
219 | IOStorage * provider = OSDynamicCast(IOStorage, getProvider()); | |
220 | ||
221 | assert(level != kIOStorageAccessReaderWriter); | |
222 | ||
223 | if (provider) | |
224 | { | |
225 | if (level == kIOStorageAccessNone) // (is a close in order?) | |
226 | { | |
227 | provider->close(this, options); | |
228 | } | |
229 | else // (is a downgrade in order?) | |
230 | { | |
231 | bool success; | |
232 | success = provider->open(this, 0, level); | |
233 | assert(success); // (should never fail, unless avoided deadlock) | |
234 | } | |
235 | } | |
236 | ||
237 | _openLevel = level; // (set new open level) | |
238 | } | |
239 | } | |
240 | ||
241 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
242 | ||
243 | void IOPartitionScheme::read(IOService * /* client */, | |
244 | UInt64 byteStart, | |
245 | IOMemoryDescriptor * buffer, | |
246 | IOStorageCompletion completion) | |
247 | { | |
248 | // | |
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. | |
252 | // | |
253 | // The buffer will be retained for the duration of the read. | |
254 | // | |
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. | |
258 | // | |
259 | ||
260 | getProvider()->read(this, byteStart, buffer, completion); | |
261 | } | |
262 | ||
263 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
264 | ||
265 | void IOPartitionScheme::write(IOService * /* client */, | |
266 | UInt64 byteStart, | |
267 | IOMemoryDescriptor * buffer, | |
268 | IOStorageCompletion completion) | |
269 | { | |
270 | // | |
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. | |
274 | // | |
275 | // The buffer will be retained for the duration of the write. | |
276 | // | |
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. | |
280 | // | |
281 | ||
282 | getProvider()->write(this, byteStart, buffer, completion); | |
283 | } | |
284 | ||
285 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
286 | ||
287 | IOReturn IOPartitionScheme::synchronizeCache(IOService * client) | |
288 | { | |
289 | return getProvider()->synchronizeCache(this); | |
290 | } | |
291 | ||
292 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
293 | ||
294 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 0); | |
295 | ||
296 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
297 | ||
298 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 1); | |
299 | ||
300 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
301 | ||
302 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 2); | |
303 | ||
304 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
305 | ||
306 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 3); | |
307 | ||
308 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
309 | ||
310 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 4); | |
311 | ||
312 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
313 | ||
314 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 5); | |
315 | ||
316 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
317 | ||
318 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 6); | |
319 | ||
320 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
321 | ||
322 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 7); | |
323 | ||
324 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
325 | ||
326 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 8); | |
327 | ||
328 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
329 | ||
330 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 9); | |
331 | ||
332 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
333 | ||
334 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 10); | |
335 | ||
336 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
337 | ||
338 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 11); | |
339 | ||
340 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
341 | ||
342 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 12); | |
343 | ||
344 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
345 | ||
346 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 13); | |
347 | ||
348 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
349 | ||
350 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 14); | |
351 | ||
352 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
353 | ||
354 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 15); | |
355 | ||
356 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
357 | ||
358 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 16); | |
359 | ||
360 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
361 | ||
362 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 17); | |
363 | ||
364 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
365 | ||
366 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 18); | |
367 | ||
368 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
369 | ||
370 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 19); | |
371 | ||
372 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
373 | ||
374 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 20); | |
375 | ||
376 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
377 | ||
378 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 21); | |
379 | ||
380 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
381 | ||
382 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 22); | |
383 | ||
384 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
385 | ||
386 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 23); | |
387 | ||
388 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
389 | ||
390 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 24); | |
391 | ||
392 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
393 | ||
394 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 25); | |
395 | ||
396 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
397 | ||
398 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 26); | |
399 | ||
400 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
401 | ||
402 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 27); | |
403 | ||
404 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
405 | ||
406 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 28); | |
407 | ||
408 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
409 | ||
410 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 29); | |
411 | ||
412 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
413 | ||
414 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 30); | |
415 | ||
416 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
417 | ||
418 | OSMetaClassDefineReservedUnused(IOPartitionScheme, 31); |