]> git.saurik.com Git - apple/xnu.git/blob - iokit/Families/IOStorage/IOMedia.cpp
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / Families / IOStorage / IOMedia.cpp
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 <machine/limits.h> // (ULONG_MAX, ...)
24 #include <IOKit/IODeviceTreeSupport.h> // (gIODTPlane, ...)
25 #include <IOKit/storage/IOMedia.h>
26
27 #define super IOStorage
28 OSDefineMetaClassAndStructors(IOMedia, IOStorage)
29
30 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
31
32 IOStorage * IOMedia::getProvider() const
33 {
34 //
35 // Obtain this object's provider. We override the superclass's method to
36 // return a more specific subclass of OSObject -- IOStorage. This method
37 // serves simply as a convenience to subclass developers.
38 //
39
40 return (IOStorage *) IOService::getProvider();
41 }
42
43 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
44
45 bool IOMedia::init(UInt64 base,
46 UInt64 size,
47 UInt64 preferredBlockSize,
48 bool isEjectable,
49 bool isWhole,
50 bool isWritable,
51 const char * contentHint = 0,
52 OSDictionary * properties = 0)
53 {
54 //
55 // Initialize this object's minimal state.
56 //
57
58 if (super::init(properties) == false) return false;
59
60 _mediaBase = base;
61 _mediaSize = size;
62 _isEjectable = isEjectable;
63 _isWhole = isWhole;
64 _isWritable = isWritable;
65 _openLevel = kIOStorageAccessNone;
66 _openReaders = OSSet::withCapacity(1);
67 _openReaderWriter = 0;
68 _preferredBlockSize = preferredBlockSize;
69
70 if (_openReaders == 0) return false;
71
72 //
73 // Create the standard media registry properties.
74 //
75
76 setProperty(kIOMediaContentKey, contentHint ? contentHint : "");
77 setProperty(kIOMediaContentHintKey, contentHint ? contentHint : "");
78 setProperty(kIOMediaEjectableKey, isEjectable);
79 setProperty(kIOMediaLeafKey, true);
80 setProperty(kIOMediaPreferredBlockSizeKey, preferredBlockSize, 64);
81 setProperty(kIOMediaSizeKey, size, 64);
82 setProperty(kIOMediaWholeKey, isWhole);
83 setProperty(kIOMediaWritableKey, isWritable);
84
85 return true;
86 }
87
88 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
89
90 void IOMedia::free(void)
91 {
92 //
93 // Free all of this object's outstanding resources.
94 //
95
96 if (_openReaders) _openReaders->release();
97
98 super::free();
99 }
100
101 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
102
103 bool IOMedia::attachToChild(IORegistryEntry * client,
104 const IORegistryPlane * plane)
105 {
106 //
107 // This method is called for each client interested in the services we
108 // provide. The superclass links us as a parent to this client in the
109 // I/O Kit registry on success.
110 //
111
112 OSString * s;
113
114 // Ask our superclass' opinion.
115
116 if (super::attachToChild(client, plane) == false) return false;
117
118 //
119 // Determine whether the client is a storage object, which we consider
120 // to be a consumer of this storage object's content and a producer of
121 // new content. A storage object need not be an IOStorage subclass, so
122 // long as it identifies itself with a match category of "IOStorage".
123 //
124 // If the client is indeed a storage object, we reset the media's Leaf
125 // property to false and replace the media's Content property with the
126 // client's Content Mask property, if any.
127 //
128
129 s = OSDynamicCast(OSString, client->getProperty(gIOMatchCategoryKey));
130
131 if (s && !strcmp(s->getCStringNoCopy(), kIOStorageCategory))
132 {
133 setProperty(kIOMediaLeafKey, false);
134
135 s = OSDynamicCast(OSString,client->getProperty(kIOMediaContentMaskKey));
136 if (s) setProperty(kIOMediaContentKey, s->getCStringNoCopy());
137 }
138
139 return true;
140 }
141
142 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
143
144 void IOMedia::detachFromChild(IORegistryEntry * client,
145 const IORegistryPlane * plane)
146 {
147 //
148 // This method is called for each client that loses interest in the
149 // services we provide. The superclass unlinks us from this client
150 // in the I/O Kit registry on success.
151 //
152 // Note that this method is called at a nondeterministic time after
153 // our client is terminated, which means another client may already
154 // have arrived and attached in the meantime. This is not an issue
155 // should the termination be issued synchrnously, however, which we
156 // take advantage of when this media needs to eliminate one of its
157 // clients. If the termination was issued on this media or farther
158 // below in the hierarchy, we don't really care that the properties
159 // would not be consistent since this media object is going to die
160 // anyway.
161 //
162
163 OSString * s;
164
165 //
166 // Determine whether the client is a storage object, which we consider
167 // to be a consumer of this storage object's content and a producer of
168 // new content. A storage object need not be an IOStorage subclass, so
169 // long as it identifies itself with a match category of "IOStorage".
170 //
171 // If the client is indeed a storage object, we reset the media's Leaf
172 // property to true and reset the media's Content property to the hint
173 // we obtained when this media was initialized.
174 //
175
176 s = OSDynamicCast(OSString, client->getProperty(gIOMatchCategoryKey));
177
178 if (s && !strcmp(s->getCStringNoCopy(), kIOStorageCategory))
179 {
180 setProperty(kIOMediaContentKey, getContentHint());
181 setProperty(kIOMediaLeafKey, true);
182 }
183
184 // Pass the call onto our superclass.
185
186 super::detachFromChild(client, plane);
187 }
188
189 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
190
191 bool IOMedia::handleOpen(IOService * client,
192 IOOptionBits options,
193 void * argument)
194 {
195 //
196 // The handleOpen method grants or denies permission to access this object
197 // to an interested client. The argument is an IOStorageAccess value that
198 // specifies the level of access desired -- reader or reader-writer.
199 //
200 // This method can be invoked to upgrade or downgrade the access level for
201 // an existing client as well. The previous access level will prevail for
202 // upgrades that fail, of course. A downgrade should never fail. If the
203 // new access level should be the same as the old for a given client, this
204 // method will do nothing and return success. In all cases, one, singular
205 // close-per-client is expected for all opens-per-client received.
206 //
207 // This method will work even when the media is in the terminated state.
208 //
209 // We are guaranteed that no other opens or closes will be processed until
210 // we make our decision, change our state, and return from this method.
211 //
212
213 IOStorageAccess access = (IOStorageAccess) argument;
214 IOStorageAccess level;
215
216 assert(client);
217
218 //
219 // Chart our course of action.
220 //
221
222 switch (access)
223 {
224 case kIOStorageAccessReader:
225 {
226 if (_openReaders->containsObject(client)) // (access: no change)
227 return true;
228 else if (_openReaderWriter == client) // (access: downgrade)
229 level = kIOStorageAccessReader;
230 else // (access: new reader)
231 level = _openReaderWriter ? kIOStorageAccessReaderWriter
232 : kIOStorageAccessReader;
233 break;
234 }
235 case kIOStorageAccessReaderWriter:
236 {
237 if (_openReaders->containsObject(client)) // (access: upgrade)
238 level = kIOStorageAccessReaderWriter;
239 else if (_openReaderWriter == client) // (access: no change)
240 return true;
241 else // (access: new writer)
242 level = kIOStorageAccessReaderWriter;
243
244 if (_isWritable == false) // (is this media object writable?)
245 return false;
246
247 if (_openReaderWriter) // (does a reader-writer already exist?)
248 return false;
249
250 break;
251 }
252 default:
253 {
254 assert(0);
255 return false;
256 }
257 }
258
259 //
260 // If we are in the terminated state, we only accept downgrades.
261 //
262
263 if (isInactive() && _openReaderWriter != client) // (dead? not a downgrade?)
264 return false;
265
266 //
267 // Determine whether the storage objects above us can be torn down, should
268 // this be a new reader-writer open or an upgrade into a reader-writer (if
269 // the client issuing the open is not a storage object itself, of course).
270 //
271
272 if (access == kIOStorageAccessReaderWriter) // (new reader-writer/upgrade?)
273 {
274 const OSSymbol * category = OSSymbol::withCString(kIOStorageCategory);
275
276 if (category)
277 {
278 IOService * storageObject = getClientWithCategory(category);
279 category->release();
280
281 if (storageObject && storageObject != client)
282 {
283 if (storageObject->terminate(kIOServiceSynchronous) == false)
284 return false;
285 }
286 }
287 }
288
289 //
290 // Determine whether the storage objects below us accept this open at this
291 // multiplexed level of access -- new opens, upgrades, and downgrades (and
292 // no changes in access) all enter through the same open api.
293 //
294
295 if (_openLevel != level) // (has open level changed?)
296 {
297 IOStorage * provider = OSDynamicCast(IOStorage, getProvider());
298
299 if (provider && provider->open(this, options, level) == false)
300 {
301 //
302 // We were unable to open the storage objects below us. We must
303 // recover from the terminate we issued above before bailing out,
304 // if applicable, by re-registering the media object for matching.
305 //
306
307 if (access == kIOStorageAccessReaderWriter)
308 registerService(kIOServiceSynchronous); // (re-register media)
309
310 return false;
311 }
312 }
313
314 //
315 // Process the open.
316 //
317 // We make sure our open state is consistent before calling registerService
318 // (if applicable) since this method can be called again on the same thread
319 // (the lock protecting handleOpen is recursive, so access would be given).
320 //
321
322 _openLevel = level;
323
324 if (access == kIOStorageAccessReader)
325 {
326 _openReaders->setObject(client);
327
328 if (_openReaderWriter == client) // (for a downgrade)
329 {
330 _openReaderWriter = 0;
331 registerService(kIOServiceSynchronous); // (re-register media)
332 }
333 }
334 else // (access == kIOStorageAccessReaderWriter)
335 {
336 _openReaderWriter = client;
337
338 _openReaders->removeObject(client); // (for an upgrade)
339 }
340
341 return true;
342 }
343
344 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
345
346 bool IOMedia::handleIsOpen(const IOService * client) const
347 {
348 //
349 // The handleIsOpen method determines whether the specified client, or any
350 // client if none is specificed, presently has an open on this object.
351 //
352 // This method will work even when the media is in the terminated state.
353 //
354 // We are guaranteed that no other opens or closes will be processed until
355 // we return from this method.
356 //
357
358 if (client == 0) return (_openLevel != kIOStorageAccessNone);
359
360 return ( _openReaderWriter == client ||
361 _openReaders->containsObject(client) );
362 }
363
364 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
365
366 void IOMedia::handleClose(IOService * client, IOOptionBits options)
367 {
368 //
369 // A client is informing us that it is giving up access to our contents.
370 //
371 // This method will work even when the media is in the terminated state.
372 //
373 // We are guaranteed that no other opens or closes will be processed until
374 // we change our state and return from this method.
375 //
376
377 assert(client);
378
379 //
380 // Process the close.
381 //
382
383 bool reregister = (_openReaderWriter == client) && (isInactive() == false);
384
385 if (_openReaderWriter == client) // (is the client a reader-writer?)
386 {
387 _openReaderWriter = 0;
388 }
389 else if (_openReaders->containsObject(client)) // (is the client a reader?)
390 {
391 _openReaders->removeObject(client);
392 }
393 else // (is the client is an imposter?)
394 {
395 assert(0);
396 return;
397 }
398
399 //
400 // Reevaluate the open we have on the level below us. If no opens remain,
401 // we close, or if no reader-writer remains, but readers do, we downgrade.
402 //
403
404 IOStorageAccess level;
405
406 if (_openReaderWriter) level = kIOStorageAccessReaderWriter;
407 else if (_openReaders->getCount()) level = kIOStorageAccessReader;
408 else level = kIOStorageAccessNone;
409
410 if (_openLevel != level) // (has open level changed?)
411 {
412 IOStorage * provider = OSDynamicCast(IOStorage, getProvider());
413
414 assert(level != kIOStorageAccessReaderWriter);
415
416 if (provider)
417 {
418 if (level == kIOStorageAccessNone) // (is a close in order?)
419 {
420 provider->close(this, options);
421 }
422 else // (is a downgrade in order?)
423 {
424 bool success;
425 success = provider->open(this, 0, level);
426 assert(success); // (should never fail, unless avoided deadlock)
427 }
428 }
429
430 _openLevel = level; // (set new open level)
431 }
432
433 //
434 // If the reader-writer just closeed, re-register the media so that I/O Kit
435 // will attempt to match storage objects that may now be interested in this
436 // media.
437 //
438 // We make sure our open state is consistent before calling registerService
439 // (if applicable) since this method can be called again on the same thread
440 // (the lock protecting handleClose is recursive, so access would be given).
441 //
442
443 if (reregister)
444 registerService(kIOServiceSynchronous); // (re-register media)
445 }
446
447 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
448
449 void IOMedia::read(IOService * /* client */,
450 UInt64 byteStart,
451 IOMemoryDescriptor * buffer,
452 IOStorageCompletion completion)
453 {
454 //
455 // Read data from the storage object at the specified byte offset into the
456 // specified buffer, asynchronously. When the read completes, the caller
457 // will be notified via the specified completion action.
458 //
459 // The buffer will be retained for the duration of the read.
460 //
461 // This method will work even when the media is in the terminated state.
462 //
463
464 if (isInactive())
465 {
466 complete(completion, kIOReturnNoMedia);
467 return;
468 }
469
470 if (_openLevel == kIOStorageAccessNone) // (instantaneous value, no lock)
471 {
472 complete(completion, kIOReturnNotOpen);
473 return;
474 }
475
476 if (_mediaSize == 0 || _preferredBlockSize == 0)
477 {
478 complete(completion, kIOReturnUnformattedMedia);
479 return;
480 }
481
482 if (_mediaSize < byteStart + buffer->getLength())
483 {
484 complete(completion, kIOReturnBadArgument);
485 return;
486 }
487
488 byteStart += _mediaBase;
489 getProvider()->read(this, byteStart, buffer, completion);
490 }
491
492 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
493
494 void IOMedia::write(IOService * client,
495 UInt64 byteStart,
496 IOMemoryDescriptor * buffer,
497 IOStorageCompletion completion)
498 {
499 //
500 // Write data into the storage object at the specified byte offset from the
501 // specified buffer, asynchronously. When the write completes, the caller
502 // will be notified via the specified completion action.
503 //
504 // The buffer will be retained for the duration of the write.
505 //
506 // This method will work even when the media is in the terminated state.
507 //
508
509 if (isInactive())
510 {
511 complete(completion, kIOReturnNoMedia);
512 return;
513 }
514
515 if (_openLevel == kIOStorageAccessNone) // (instantaneous value, no lock)
516 {
517 complete(completion, kIOReturnNotOpen);
518 return;
519 }
520
521 if (_openReaderWriter != client) // (instantaneous value, no lock)
522 {
523 ///m:2425148:workaround:commented:start
524 // complete(completion, kIOReturnNotPrivileged);
525 // return;
526 ///m:2425148:workaround:commented:stop
527 }
528
529 if (_isWritable == 0)
530 {
531 complete(completion, kIOReturnLockedWrite);
532 return;
533 }
534
535 if (_mediaSize == 0 || _preferredBlockSize == 0)
536 {
537 complete(completion, kIOReturnUnformattedMedia);
538 return;
539 }
540
541 if (_mediaSize < byteStart + buffer->getLength())
542 {
543 complete(completion, kIOReturnBadArgument);
544 return;
545 }
546
547 byteStart += _mediaBase;
548 getProvider()->write(this, byteStart, buffer, completion);
549 }
550
551 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
552
553 IOReturn IOMedia::synchronizeCache(IOService * client)
554 {
555 if (isInactive())
556 {
557 return kIOReturnNoMedia;
558 }
559
560 if (_openLevel == kIOStorageAccessNone) // (instantaneous value, no lock)
561 {
562 return kIOReturnNotOpen;
563 }
564
565 if (_openReaderWriter != client) // (instantaneous value, no lock)
566 {
567 return kIOReturnNotPrivileged;
568 }
569
570 if (_isWritable == 0)
571 {
572 return kIOReturnLockedWrite;
573 }
574
575 if (_mediaSize == 0 || _preferredBlockSize == 0)
576 {
577 return kIOReturnUnformattedMedia;
578 }
579
580 return getProvider()->synchronizeCache(this);
581 }
582
583 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
584
585 UInt64 IOMedia::getPreferredBlockSize() const
586 {
587 //
588 // Ask the media object for its natural block size. This information
589 // is useful to clients that want to optimize access to the media.
590 //
591
592 return _preferredBlockSize;
593 }
594
595 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
596
597 UInt64 IOMedia::getSize() const
598 {
599 //
600 // Ask the media object for its total length in bytes.
601 //
602
603 return _mediaSize;
604 }
605
606 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
607
608 UInt64 IOMedia::getBase() const
609 {
610 //
611 // Ask the media object for its byte offset relative to its provider media
612 // object below it in the storage hierarchy.
613 //
614
615 return _mediaBase;
616 }
617
618 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
619
620 bool IOMedia::isEjectable() const
621 {
622 //
623 // Ask the media object whether it is ejectable.
624 //
625
626 return _isEjectable;
627 }
628
629 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
630
631 bool IOMedia::isFormatted() const
632 {
633 //
634 // Ask the media object whether it is formatted.
635 //
636
637 return (_mediaSize && _preferredBlockSize);
638 }
639
640 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
641
642 bool IOMedia::isWritable() const
643 {
644 //
645 // Ask the media object whether it is writable.
646 //
647
648 return _isWritable;
649 }
650
651 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
652
653 bool IOMedia::isWhole() const
654 {
655 //
656 // Ask the media object whether it represents the whole disk.
657 //
658
659 return _isWhole;
660 }
661
662 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
663
664 const char * IOMedia::getContent() const
665 {
666 //
667 // Ask the media object for a description of its contents. The description
668 // is the same as the hint at the time of the object's creation, but it is
669 // possible that the description be overrided by a client (which has probed
670 // the media and identified the content correctly) of the media object. It
671 // is more accurate than the hint for this reason. The string is formed in
672 // the likeness of Apple's "Apple_HFS" strings.
673 //
674 // The content description can be overrided by any client that matches onto
675 // this media object with a match category of kIOStorageCategory. The media
676 // object checks for a kIOMediaContentMaskKey property in the client, and if
677 // it finds one, it copies it into kIOMediaContentKey property.
678 //
679
680 OSString * string;
681
682 string = OSDynamicCast(OSString, getProperty(kIOMediaContentKey));
683 if (string == 0) return "";
684 return string->getCStringNoCopy();
685 }
686
687 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
688
689 const char * IOMedia::getContentHint() const
690 {
691 //
692 // Ask the media object for a hint of its contents. The hint is set at the
693 // time of the object's creation, should the creator have a clue as to what
694 // it may contain. The hint string does not change for the lifetime of the
695 // object and is also formed in the likeness of Apple's "Apple_HFS" strings.
696 //
697
698 OSString * string;
699
700 string = OSDynamicCast(OSString, getProperty(kIOMediaContentHintKey));
701 if (string == 0) return "";
702 return string->getCStringNoCopy();
703 }
704
705 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
706
707 bool IOMedia::matchPropertyTable(OSDictionary * table, SInt32 * score)
708 {
709 //
710 // Compare the properties in the supplied table to this object's properties.
711 //
712
713 // Ask our superclass' opinion.
714
715 if (super::matchPropertyTable(table, score) == false) return false;
716
717 // We return success if the following expression is true -- individual
718 // comparisions evaluate to truth if the named property is not present
719 // in the supplied table.
720
721 return compareProperty(table, kIOMediaContentKey) &&
722 compareProperty(table, kIOMediaContentHintKey) &&
723 compareProperty(table, kIOMediaEjectableKey) &&
724 compareProperty(table, kIOMediaLeafKey) &&
725 compareProperty(table, kIOMediaSizeKey) &&
726 compareProperty(table, kIOMediaWholeKey) &&
727 compareProperty(table, kIOMediaWritableKey) ;
728 }
729
730 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
731
732 OSMetaClassDefineReservedUnused(IOMedia, 0);
733
734 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
735
736 OSMetaClassDefineReservedUnused(IOMedia, 1);
737
738 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
739
740 OSMetaClassDefineReservedUnused(IOMedia, 2);
741
742 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
743
744 OSMetaClassDefineReservedUnused(IOMedia, 3);
745
746 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
747
748 OSMetaClassDefineReservedUnused(IOMedia, 4);
749
750 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
751
752 OSMetaClassDefineReservedUnused(IOMedia, 5);
753
754 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
755
756 OSMetaClassDefineReservedUnused(IOMedia, 6);
757
758 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
759
760 OSMetaClassDefineReservedUnused(IOMedia, 7);
761
762 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
763
764 OSMetaClassDefineReservedUnused(IOMedia, 8);
765
766 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
767
768 OSMetaClassDefineReservedUnused(IOMedia, 9);
769
770 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
771
772 OSMetaClassDefineReservedUnused(IOMedia, 10);
773
774 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
775
776 OSMetaClassDefineReservedUnused(IOMedia, 11);
777
778 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
779
780 OSMetaClassDefineReservedUnused(IOMedia, 12);
781
782 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
783
784 OSMetaClassDefineReservedUnused(IOMedia, 13);
785
786 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
787
788 OSMetaClassDefineReservedUnused(IOMedia, 14);
789
790 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
791
792 OSMetaClassDefineReservedUnused(IOMedia, 15);