|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
25: *
26: * IODiskPartition.m - implementation of NeXT-style logical disk.
27: *
28: * HISTORY
29: * 22-Jan-98 radar 1669467 - ISO 9660 CD support - jwc
30: * 15-Dec-92 Sam Streeper (sam) at NeXT
31: * Added support for a NeXT disk on a MS-DOS partition
32: * 01-May-91 Doug Mitchell at NeXT
33: * Created.
34: */
35:
36: #define DRIVER_PRIVATE 1
37:
38: #import <driverkit/return.h>
39: #import <driverkit/IODiskPartition.h>
40: #import <driverkit/generalFuncs.h>
41: #import <bsd/dev/disk_label.h>
42: #import <bsd/sys/disktab.h>
43: #ifdef KERNEL
44: #import <kernserv/prototypes.h>
45: #import <driverkit/kernelDiskMethods.h>
46: #import <driverkit/kernelDiskMethodsPrivate.h>
47: #import <driverkit/kernelDriver.h>
48: #import <machkit/NXLock.h>
49: #else KERNEL
50: #import <bsd/libc.h>
51: #endif KERNEL
52: #import <kern/time_stamp.h>
53: #import <driverkit/Device_ddm.h>
54: #import <mach/vm_param.h>
55: #import <driverkit/disk_label.h>
56: #import <driverkit/diskstruct.h>
57: #ifdef i386
58: #import <bsd/dev/i386/disk.h>
59: #endif i386
60: #import <architecture/byte_order.h>
61: #import "label_subr.h"
62: #import <driverkit/IODeviceDescription.h>
63: #import <bsd/dev/voldev.h>
64: #ifdef ppc
65: #import <bsd/dev/ppc/disk.h>
66: #endif
67:
68: /* Define GROK_DOS if scsi driver is to understand MS-DOS partitions.
69: * It only finds the partition with the NeXT name. Live partition is
70: * not affected. -sam
71: *
72: * define GROK_APPLE if we want to look to a Rhapsody partition on a
73: * Apple Partitioned disk
74: */
75: #ifdef i386
76: #define GROK_DOS
77: #endif
78:
79: #ifdef ppc
80: #define GROK_APPLE 1
81: #endif
82:
83: // seconds to wait for disk ready at probe time
84: #define DELAY_AT_PROBE 0
85:
86: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
87:
88: #define HFS_PART_TYPE "Apple_HFS"
89:
90: #endif //bknight - 12/3/97 - Radar #2004660
91:
92:
93: @interface IODiskPartition(Private)
94:
95: /*
96: * Private methods.
97: */
98: /*
99: * Examine a known good label, initialize LogicalDisk parameters for the
100: * raw device (on which this method is invoked) and create block devices
101: * as appropriate.
102: *
103: * Invoked by LogicalDisk +probe, upon disk insertion, and when a new label
104: * is written.
105: */
106: - (void) _probeLabel : (disk_label_t *)labelp;
107:
108: /*
109: * Assign logical disk parameters for a partition instance.
110: */
111: - (void)_initPartition : (int)partNum
112: physicalPartition : (int)physNum
113: disktab : (struct disktab *)dtp;
114:
115: /*
116: * Free all partition instances other than partition 0.
117: */
118: - (IOReturn)_freePartitions;
119:
120: /*
121: * Determine if any block devices in the logicalDisk chain are open.
122: */
123: - (BOOL)isAnyBlockDevOpen;
124:
125: /*
126: * Verify that it's safe to do an operation which will result in a call
127: * to _freePartitions.
128: */
129: - (IOReturn)checkSafeConfig : (const char *)op;
130:
131: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
132:
133: /*
134: * IODiskPartition knows how to
135: * Create HFS Devices From Apple Partition Map.
136: */
137: + (void)CreateHFSDevicesFromApplePartitionMap : (id)physicalDisk;
138:
139: /*
140: * Assign logical disk parameters for a partition instance.
141: */
142:
143: - (void) _initHFSPartition : (int) partitionNum
144: physicalPartNum : (int) physNum
145: diskSize : (int) diskSize
146: partitionBase : (int) partitionBase;
147:
148: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
149:
150: @end
151:
152:
153: @implementation IODiskPartition
154:
155: + (IODeviceStyle)deviceStyle
156: {
157: return IO_IndirectDevice;
158: }
159:
160: /*
161: * The protocol we need as an indirect device.
162: */
163: static Protocol *protocols[] = {
164: @protocol(IOPhysicalDiskMethods),
165: @protocol(IODiskReadingAndWriting),
166: nil
167: };
168:
169: + (Protocol **)requiredProtocols
170: {
171: return protocols;
172: }
173:
174: /*
175: * Attempt to read label of physical device. If valid label, create an
176: * instance of LogicalDisk for each valid partition as well as for the
177: * Unix raw device. Returns YES if any instances were created.
178: */
179: + (BOOL)probe : deviceDescription
180: {
181: id physDisk = [deviceDescription directDevice];
182: int try;
183: IODiskReadyState ready;
184: IOReturn rtn;
185: disk_label_t *labelp = NULL;
186: IODiskPartition *part0p;
187: BOOL frtn = YES; // when would this be NO?
188: char name[30];
189: id ld;
190: const char *physName = [physDisk name];
191: unsigned physBlockSize = 0;
192: unsigned physDiskSize = 0;
193: unsigned formattedFlag;
194: BOOL logParams = NO;
195: BOOL logLabel = NO;
196: IODiskReadyState oldReady;
197:
198: xpr_disk("IODiskPartition probe\n", 1,2,3,4,5);
199: /*
200: * First of all, we're only interested in physical disks.
201: * (Shouldn't this be covered by our requiredProtocols values?)
202: */
203: if(![physDisk isPhysical]) {
204: return NO;
205: }
206:
207: /*
208: * Create a partition 0 instance if there isn't already one; attach
209: * it to physDisk. There will already be a partition 0 instance if
210: * this probe is in response to a disk insertion as opposed to
211: * initial device configuration.
212: */
213: ld = [physDisk nextLogicalDisk];
214: if(ld != nil) {
215: part0p = (IODiskPartition *)ld;
216:
217: /*
218: * Update physical parameters.
219: */
220: [part0p connectToPhysicalDisk:physDisk];
221: part0p->_labelValid = 0;
222: part0p->_physicalPartition = 0;
223:
224: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
225: part0p->_hfsValid = 0;
226: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
227: part0p->_blockDeviceOpen = 0;
228: part0p->_rawDeviceOpen = 0;
229: IOLog("\n");
230: }
231: else {
232: part0p = [IODiskPartition new];
233: sprintf(name, "%sa", physName);
234: [part0p setName:name];
235: [part0p setDeviceKind:"IODiskPartition"];
236: [part0p setDriveName:"IODiskPartition Partition"];
237: [part0p setLocation:NULL];
238: part0p->_partitionWaitLock = [[NXConditionLock alloc] init];
239: IOGetTimestamp( &part0p->_probeTime);
240: [part0p init];
241: [part0p connectToPhysicalDisk:physDisk];
242: [part0p setDeviceDescription:deviceDescription];
243: [physDisk setLogicalDisk:part0p];
244: part0p->_labelValid = 0;
245: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
246: part0p->_hfsValid = 0;
247: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
248: part0p->_blockDeviceOpen = 0;
249: part0p->_rawDeviceOpen = 0;
250:
251: #ifdef KERNEL
252: /*
253: * Register both physDisk and partition 0 with Unix
254: * level owner.
255: */
256: [physDisk registerUnixDisk:0];
257: [part0p registerUnixDisk:0];
258: #endif KERNEL
259: }
260:
261: /*
262: * Give the drive a chance to spin up.
263: */
264: oldReady = [physDisk lastReadyState];
265:
266: #if DELAY_AT_PROBE
267: if( (physName[0] == 'f') && (physName[1] == 'd'))
268: ready = [physDisk updateReadyState];
269: else {
270: for(try = 0; try < DELAY_AT_PROBE; try++) {
271: ready = [physDisk updateReadyState];
272: switch(ready) {
273: case IO_Ready:
274: goto goOn; /* go for it */
275: case IO_NotReady:
276: break; /* try again */
277: case IO_NoDisk:
278: if (try > 0)
279: IOLog("\n");
280: goto done; /* forget it */
281: case IO_Ejecting:
282: break; /* try again */
283: }
284: if(try == 0)
285: IOLog("%s: Waiting for drive to come ready", physName);
286: else
287: IOLog(".");
288: IOSleep(1000);
289: }
290: goOn:
291: if (try > 0)
292: IOLog("\n");
293: }
294: #else
295: ready = [physDisk updateReadyState];
296: #endif
297: [physDisk setLastReadyState:ready];
298: if(ready != IO_Ready) {
299: IOLog("%s: Disk Not Ready\n", physName);
300: xpr_disk("IODiskPartition probe: Disk Not Ready\n", 1,2,3,4,5);
301: goto done;
302: }
303:
304: /*
305: * If the disk just came ready, have driver update its physical
306: * parameters.
307: */
308: if(oldReady != IO_Ready) {
309: [physDisk updatePhysicalParameters];
310: }
311:
312: /*
313: * If disk is not formatted, forget the rest of this.
314: */
315: formattedFlag = [physDisk isFormatted];
316: if(!formattedFlag) {
317: IOLog("%s: Disk Unformatted\n", physName);
318: xpr_disk("IODiskPartitionProbe: physDisk %s not formatted\n",
319: physName, 2,3,4,5);
320: goto done;
321: }
322:
323: physDiskSize = [physDisk diskSize];
324: physBlockSize = [physDisk blockSize];
325:
326: [part0p setPhysicalBlockSize:physBlockSize];
327:
328: logParams = YES;
329:
330: /*
331: * Try to read a label.
332: */
333: labelp = IOMalloc(sizeof(disk_label_t));
334: rtn = [part0p readLabel:labelp];
335: if(rtn) {
336: xpr_disk("IODiskPartition probe: No Label\n", 1,2,3,4,5);
337: IOLog("%s: No Valid Disk Label\n", physName);
338:
339: /*
340: * Set up blockSize and diskSize of partition A
341: * to be the same as our physicalDisk's for now.
342: */
343: [part0p setBlockSize:physBlockSize];
344: [part0p setDiskSize:[physDisk diskSize]];
345:
346: /* Remember to reset the partition base to zero,
347: * since we don't yet have any recognizable
348: * partitioning information.
349: */
350: [part0p setPartitionBase:0];
351: }
352: else {
353: logLabel = YES;
354:
355: /*
356: * Initialize remaining device parameters and create
357: * additional partition instances as appropriate.
358: */
359: [part0p _probeLabel:labelp];
360: }
361:
362: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
363:
364: [self CreateHFSDevicesFromApplePartitionMap:deviceDescription];
365:
366: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
367:
368: if( part0p->_partitionWaitLock) {
369: [part0p->_partitionWaitLock lock];
370: [part0p->_partitionWaitLock unlockWith:YES];
371: }
372: done:
373: if(logParams) {
374: unsigned kbytes;
375:
376: IOLog("%s: Device Block Size: %u bytes\n",
377: physName, physBlockSize);
378: kbytes = (physDiskSize / 1024) * physBlockSize;
379: if(kbytes > (10 * 1024)) {
380: IOLog("%s: Device Capacity: %u MB\n",
381: physName, kbytes / 1024);
382: }
383: else {
384: IOLog("%s: Device Capacity: %u KB\n",
385: physName, physDiskSize * physBlockSize /
386: 1024);
387: }
388: }
389: if(logLabel) {
390: IOLog("%s: Disk Label: %s\n",
391: physName, labelp->dl_label);
392: }
393: if(labelp != NULL) {
394: IOFree(labelp, sizeof(disk_label_t));
395: }
396:
397: if(ld == nil)
398: [part0p registerDevice];
399:
400: return(frtn);
401: }
402:
403: #ifdef GROK_DOS
404: /* returns the offset to the NeXT partition of an MSDOS partitioned
405: * hard disk (0 if it isn't a DOS disk), or a (negative) IOReturn.
406: */
407: - (int) NeXTpartitionOffset
408: {
409: IOReturn frtn = 0;
410: IOReturn rtn;
411: unsigned bytesXfr;
412: id physDisk = [self physicalDisk];
413: /*
414: * Force page alignment...
415: */
416: unsigned char *blk= IOMalloc(PAGE_SIZE);
417: struct disk_blk0 *blk0;
418: struct fdisk_part *fd;
419: int n;
420: BOOL validPart = NO;
421:
422: if ([self physicalBlockSize] != DISK_BLK0SZ) {
423: frtn = 0;
424: goto out;
425: }
426: // fixme - can I really transfer to unwired, unaligned buffer?
427: rtn = [[super class] commonReadWrite
428: : physDisk
429: : YES /* read */
430: : (unsigned long long)DISK_BLK0 * [physDisk blockSize]
431: : DISK_BLK0SZ /* bytes */
432: : blk
433: : IOVmTaskSelf()
434: : (void *)NULL
435: : &bytesXfr];
436:
437: if (rtn) {
438: frtn = IO_R_NO_BLOCK_ZERO;
439: goto out;
440: }
441:
442: // Check for a valid DOS boot block.
443: blk0 = (struct disk_blk0 *)blk;
444: if (blk0->signature != DISK_SIGNATURE) {
445: goto out;
446: }
447:
448: // Check to see if the disk has been partitioned with FDISK
449: // to allow DOS and ufs filesystems to exist on the same disk
450: fd = (struct fdisk_part *)blk0->parts;
451: for (n = 0; n < FDISK_NPART; n++, fd++) {
452: switch(fd->systid) {
453: case 0:
454: /*
455: * Not valid partition, meaningless.
456: */
457: break;
458: case FDISK_NEXTNAME:
459: /*
460: * Valid NeXT partition.
461: */
462: frtn = fd->relsect;
463: _physicalPartition = n;
464: goto out;
465: default:
466: /*
467: * Not what we're looking for, but this means that
468: * we can't use partition 0.
469: */
470: validPart = YES;
471: break;
472: }
473: }
474: if(validPart) {
475: frtn = IO_R_NO_NEXT_PART;
476: }
477: else {
478: /*
479: * No valid partitions; treat same as "no valid block 0".
480: */
481: }
482: out:
483: IOFree(blk, PAGE_SIZE);
484: return frtn;
485: }
486: #endif GROK_DOS
487:
488: #ifdef GROK_APPLE
489: /*
490: * Check for an apple partition:
491: *
492: */
493: #define BLOCKSIZE_512_BYTES 512
494:
495: - (int) NeXTpartitionOffset
496: {
497: unsigned char * blk;
498: Block0 * blk0;
499: unsigned long blocksize = [self physicalBlockSize];
500: unsigned bytesXfr;
501: IOReturn frtn = 0;
502: id physDisk = [self physicalDisk];
503: IOReturn rtn;
504:
505: blk = IOMalloc(PAGE_SIZE); /* force page alignment */
506: blk0 = (Block0 *)blk;
507:
508: /* check block 0 for valid Apple partition signature */
509:
510: rtn = [[super class] commonReadWrite
511: : physDisk
512: : YES /* read */
513: : (unsigned long long)0 /* byte offset */
514: : PAGE_SIZE /* bytes */
515: : blk
516: : IOVmTaskSelf()
517: : (void *)NULL
518: : &bytesXfr];
519:
520: /* scan for the rhapsody apple ufs partition */
521: if (rtn)
522: frtn = IO_R_NO_BLOCK_ZERO;
523: else {
524: unsigned int block = 1;
525: unsigned int entry_within_block = 0;
526: int n;
527: unsigned int nentries_per_block = 1;
528: unsigned int numPartBlocks;
529: DPME * partEntry;
530: int physNum;
531:
532: /* check if there is a valid map at 512 offset */
533: partEntry = (DPME *)(blk + BLOCKSIZE_512_BYTES);
534: if (blocksize > BLOCKSIZE_512_BYTES) {
535: if (NXSwapBigShortToHost(partEntry->dpme_signature)
536: == DPME_SIGNATURE) {
537: /* there is a valid map, and the device blocksize
538: * is > 512, which means we probably have a CDROM
539: * using 2K, but having valid 512 map
540: */
541: block = 0;
542: nentries_per_block = blocksize / BLOCKSIZE_512_BYTES;
543: entry_within_block = 1;
544: }
545: else
546: partEntry = (DPME *)(blk + blocksize);
547: }
548: if (NXSwapBigShortToHost(partEntry->dpme_signature) == DPME_SIGNATURE) {
549: numPartBlocks = NXSwapBigLongToHost(partEntry->dpme_map_entries);
550: #ifdef PRINT_APT
551: IOLog("Apple Partition table (%d entries)...\n", numPartBlocks);
552: #endif PRINT_APT
553:
554: physNum = 1;
555: for (n = 0; n < numPartBlocks; n++) {
556: int ufs_partition_set = 0;
557:
558: if (NXSwapBigShortToHost(partEntry->dpme_signature)
559: != DPME_SIGNATURE) {
560: break;
561: }
562: if (strcmp(partEntry->dpme_type, RHAPSODY_PART_TYPE) == 0
563: && ufs_partition_set == 0) {
564: unsigned long part_offset;
565:
566: part_offset
567: = NXSwapBigLongToHost(partEntry->dpme_pblock_start);
568: if ((part_offset / nentries_per_block * nentries_per_block)
569: != part_offset) {
570: IOLog("IODiskPartition: " RHAPSODY_PART_TYPE
571: " partition base (%ld x 512) is not"
572: " a multiple of the devblksize %ld\n",
573: part_offset, blocksize);
574: frtn = IO_R_NO_NEXT_PART;
575: break;
576: }
577:
578: part_offset = part_offset / nentries_per_block;
579: #ifdef PRINT_APT
580: IOLog("%s: UFS partition at offset %ld\n",
581: [physDisk name], part_offset);
582: #endif PRINT_APT
583: frtn = (IOReturn)part_offset;
584: ufs_partition_set = 1;
585: _physicalPartition = physNum;
586: }
587: #ifdef PRINT_APT
588: IOLog("Apple Partition entry %d:\n", n + 1);
589: IOLog(" Name: %s, Type %s, size: %d\n",
590: partEntry->dpme_name, partEntry->dpme_type,
591: partEntry->dpme_pblocks);
592: IOLog("block %d entry %d (of %d) blocksize %d\n",
593: block, entry_within_block + 1,
594: nentries_per_block, blocksize);
595: #endif PRINT_APT
596: partEntry++;
597: physNum++;
598: if (++entry_within_block == nentries_per_block) {
599: block++;
600: entry_within_block = 0;
601: partEntry = (DPME *)blk;
602:
603: rtn = [[super class] commonReadWrite
604: : physDisk
605: : YES /* read */
606: : (unsigned long long)block * blocksize /* byte offset */
607: : blocksize /* bytes */
608: : blk
609: : IOVmTaskSelf()
610: : (void *)NULL
611: : &bytesXfr];
612:
613: if (rtn) {
614: frtn = IO_R_NO_NEXT_PART;
615: break;
616: }
617: }
618: }
619: } /* DPME signature validation */
620: } /* scan for Apple rhapsody ufs partitions */
621: IOFree(blk, PAGE_SIZE);
622: return frtn;
623: }
624:
625: - getDevicePath:(char *)path maxLength:(int)maxLen useAlias:(BOOL)doAlias
626: {
627: if( [[self physicalDisk]
628: getDevicePath:path maxLength:maxLen useAlias:doAlias]) {
629:
630: char partStr[ 12 ];
631:
632: sprintf( partStr, ":%x", _physicalPartition);
633: strcat( path, partStr);
634: return( self);
635: }
636: return( nil);
637: }
638:
639: #endif GROK_APPLE
640:
641: /*
642: * Read disk label. label_p must does not have to be aligned; we do a
643: * page-aligned read to satisfy any possible DMA requirements.
644: *
645: * This is only invoked on the raw device. This can be invoked on a
646: * drive with no disk present; we'll do a 'isDiskReady:YES" to get a
647: * disk if necessary.
648: *
649: * This reads labels as raw m68k disk_label_t's. On successful return,
650: * *label_p contains a label which is valid for the current architecture;
651: * the transformation is performed per the API in <driverkit/disk_label.h>.
652: */
653:
654: - (IOReturn) readLabel : (disk_label_t *)label_p
655: {
656: int label_num;
657: IOReturn rtn;
658: int found = 0;
659: int blocksInLabel;
660: int bytesInLabel;
661: unsigned bytesXfr;
662: char *raw_label;
663: int labelBufSize;
664: id physDisk = [self physicalDisk];
665: unsigned physBlockSize = [self physicalBlockSize];
666: unsigned physFormatted;
667: unsigned blocksize;
668: const char *disk_name = [self name];
669: /* offset of NeXT disk on dos or Apple partition */
670: int part_offset = 0;
671:
672: xpr_disk("IODiskPartition readLabel\n", 1,2,3,4,5);
673:
674: /*
675: * Note we have to 'fault in' a possible non-present disk in
676: * order to get its physical parameters...
677: */
678: rtn = [physDisk isDiskReady:YES];
679: switch(rtn) {
680: case IO_R_SUCCESS:
681: break;
682: case IO_R_NO_DISK:
683: xpr_err("%s readLabel: disk not present\n", disk_name,
684: 2,3,4,5);
685: return(rtn);
686: default:
687: IOLog("%s readLabel: bogus return from isDiskReady (%s)\n",
688: disk_name, [self stringFromReturn:rtn]);
689: return(rtn);
690: }
691:
692: physFormatted = [physDisk isFormatted];
693: if((physBlockSize == 0) || !physFormatted) {
694: xpr_err("%s readLabel: physDisk UNFORMATTED\n",
695: disk_name, 2,3,4,5);
696: return(IO_R_UNFORMATTED);
697: }
698:
699: #if defined(GROK_DOS) || defined(GROK_APPLE)
700: part_offset = [self NeXTpartitionOffset];
701: if (part_offset < 0) {
702: return part_offset;
703: }
704: #ifdef DEBUG
705: if (part_offset > 0) {
706: printf("found NeXT disk partition at offset"
707: ", offset = %d sectors\n", part_offset);
708: }
709: #endif DEBUG
710: #endif defined(GROK_DOS) || defined(GROK_APPLE)
711:
712: /*
713: * Careful, we're reading in an m68k-style label...
714: */
715: blocksInLabel = howmany(SIZEOF_DISK_LABEL_T, physBlockSize);
716: bytesInLabel = blocksInLabel * physBlockSize;
717: labelBufSize = round_page(bytesInLabel);
718:
719: /*
720: * This assumes that the memory allocator used by IOMalloc will
721: * return one physically contiguous page if we ask it for one
722: * page...should be OK, right?
723: * This used to be vm_allocate(), but can't DMA to IOTask's
724: * virtual memory.
725: */
726: raw_label = IOMalloc(labelBufSize);
727: for(label_num=0; label_num<NLABELS; label_num++) {
728:
729: /* To read a disk label, we *should* use the blocksize of the
730: * enclosing partition, but we don't know what that is.
731: *
732: * As a workaround, we can use the *physical* blocksize. By
733: * doing so, we will always compute the proper offset for
734: * fixed disks using Mac, FDISK, or *no* partitioning scheme,
735: * since all these schemes assume a 512 byte blocksize.
736: * (It is possible for a Mac partition map to imply a non-512
737: * blocksize, but in practice this is rare).
738: *
739: * Using the physical blocksize would not iterate properly
740: * through all four labels on a Mac-partitioned CD-ROM, because
741: * we'd be using 2K blocks instead of the Mac partition's 512.
742: * This, however, *still* luckily works because the first label
743: * is at offset zero: offset zero is always the same no matter
744: * what you're multiplying by to get that zero!
745: *
746: * Once we find a valid label (often the one at offset zero),
747: * we immediately reset our logical blocksize, so after that
748: * point things work normally.
749: */
750:
751: blocksize = [physDisk blockSize];
752:
753: rtn = [[super class] commonReadWrite
754: : physDisk
755: : YES /* read */
756: : ((unsigned long long)part_offset +
757: (label_num * blocksInLabel))
758: * blocksize /* byte offset */
759: : bytesInLabel /* bytes */
760: : raw_label
761: : IOVmTaskSelf()
762: : (void *)NULL
763: : &bytesXfr];
764: if((rtn == IO_R_SUCCESS) &&
765: (bytesXfr == bytesInLabel)) {
766:
767: /*
768: * Is it a valid disk label?
769: */
770: const char *rtn;
771:
772: rtn = check_label(raw_label,
773: part_offset + (label_num*blocksInLabel));
774: if(rtn == NULL) {
775: found++;
776: break;
777: }
778: #ifdef DEBUG
779: else {
780: IOLog("%s\n", rtn);
781: }
782: #endif DEBUG
783: }
784:
785: /*
786: * there is one fatal error here - disk not present.
787: */
788: if(rtn == IO_R_NO_DISK)
789: break;
790: }
791:
792: if(found) {
793: /*
794: * Success.
795: */
796: xpr_disk("readLabel: Valid Label\n", 1,2,3,4,5);
797: _labelValid = 1;
798: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
799: _hfsValid = 0; // bek - 12/14/97 - Is this redundant?
800: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
801: get_disk_label(raw_label, label_p);
802: rtn = IO_R_SUCCESS;
803: }
804: else {
805: xpr_disk("readLabel: NO LABEL\n", 1,2,3,4,5);
806: if(rtn != IO_R_NO_DISK)
807: rtn = IO_R_NO_LABEL;
808: }
809: IOFree(raw_label, labelBufSize);
810: return(rtn);
811: }
812:
813: /*
814: * Write disk label. Label is passed in as an actual native label per
815: * current architecture and is written as an m68k-style label.
816: */
817:
818: static inline void put_short(unsigned short s, void *dest)
819: {
820: *((unsigned short *)dest) = NXSwapHostShortToBig(s);
821: }
822:
823: - (IOReturn) writeLabel : (disk_label_t *)label_p
824: {
825: unsigned size;
826: unsigned short *cksum_p;
827: unsigned short cksum;
828: ns_time_t timestamp;
829: int label_num;
830: unsigned bytesXfr;
831: int goodLabel = 0;
832: IOReturn rtn;
833: int blocksInLabel;
834: int bytesInLabel;
835: id physDisk = [self physicalDisk];
836: unsigned physBlockSize = [self physicalBlockSize];
837: char *raw_label = NULL;
838: int labelBufSize = 0; /* compiler quirk */
839: unsigned formattedFlag = 0;
840: const char *lrtn;
841: int cksum_offset;
842: /* offset of NeXT disk on dos or Apple partition */
843: int part_offset = 0;
844: #ifdef i386
845: /*
846: * Avoid writing first label over block 0.
847: */
848: int firstLabel = 1;
849: #else i386
850: int firstLabel = 0;
851: #endif i386
852:
853: xpr_disk("IODiskPartition writeLabel\n", 1,2,3,4,5);
854:
855: /*
856: * We can't do this if any block devices, or any other logical disk,
857: * are currently open. Also, we can only do this on partition 0
858: * because we're going to blow away all IODiskPartitions other than the
859: * one for partition 0 before we're thru.
860: */
861: rtn = [self checkSafeConfig:"writeLabel"];
862: if(rtn) {
863: return rtn;
864: }
865:
866: /*
867: * Lock out similar destructive actions...
868: */
869: [physDisk lockLogicalDisks];
870:
871: formattedFlag = [physDisk isFormatted];
872: if(!formattedFlag) {
873: xpr_disk("IODiskPartition writeLabel: UNFORMATTED DISK\n",
874: 1,2,3,4,5);
875: rtn = IO_R_IO;
876: goto done;
877: }
878:
879: /*
880: * OK, here we go. All other partitions are now invalid. Let's
881: * get rid of them.
882: */
883: [self _freePartitions];
884: _labelValid = 0; // until we're thru
885: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
886: _hfsValid = 0; // until we're thru
887: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
888:
889: if(label_p->dl_version == DL_V1 || label_p->dl_version == DL_V2) {
890: size = SIZEOF_DISK_LABEL_T;
891: cksum_p = &label_p->dl_checksum;
892: cksum_offset = DISK_LABEL_DL_CHECKSUM;
893: } else if(label_p->dl_version == DL_V3) {
894: size = SIZEOF_DISK_LABEL_T - SIZEOF_DL_UN_T;
895: cksum_p = &label_p->dl_v3_checksum;
896: cksum_offset = DISK_LABEL_DL_UN;
897: }
898: else {
899: IOLog("%s writeLabel: BAD LABEL\n", [self name]);
900: rtn = IO_R_INVALID_ARG;
901: goto done;
902: }
903:
904: /*
905: * tag label with time.
906: */
907: IOGetTimestamp(×tamp);
908: label_p->dl_tag = (unsigned)timestamp;
909:
910: /*
911: * prepare to validate (before converting to m68k-style label).
912: */
913: label_p->dl_label_blkno = 0;
914: *cksum_p = 0;
915:
916: /*
917: * Get an m68k-style label for validation (and which we'll eventually
918: * write to disk). We do page alignment here to satisfy the most
919: * stringent DMA requirements downstream.
920: */
921: blocksInLabel = howmany(SIZEOF_DISK_LABEL_T, physBlockSize);
922: bytesInLabel = blocksInLabel * physBlockSize;
923: labelBufSize = round_page(bytesInLabel);
924: raw_label = IOMalloc(labelBufSize);
925: put_disk_label(label_p, raw_label);
926:
927: /*
928: * Get checksum and validate. Careful, put the checksum in the
929: * raw m68k-style label in a machine-independent manner...
930: */
931: cksum = checksum16((unsigned short *)raw_label, size >> 1);
932: put_short(cksum, raw_label + cksum_offset);
933: if(lrtn = check_label(raw_label, 0)) {
934: IOLog("%s writeLabel: BAD LABEL : %s\n",
935: [self name], lrtn);
936: rtn = IO_R_INVALID_ARG;
937: goto done;
938: }
939:
940: #if defined(GROK_DOS) || defined(GROK_APPLE)
941: part_offset = [self NeXTpartitionOffset];
942: if (part_offset < 0) {
943: rtn = part_offset;
944: goto done;
945: }
946: #endif defined(GROK_DOS) || defined(GROK_APPLE)
947:
948: /*
949: * OK, the caller gave us a good label. Write NLABEL copies.
950: */
951: for(label_num=firstLabel; label_num<NLABELS; label_num++) {
952: *(int *)(raw_label + DISK_LABEL_DL_LABEL_BLKNO ) =
953: NXSwapHostIntToBig(part_offset +
954: (label_num * blocksInLabel));
955:
956: rtn = [[super class] commonReadWrite
957: : physDisk
958: : NO /* write */
959: : ((unsigned long long)part_offset +
960: (label_num * blocksInLabel))
961: * physBlockSize /* byte offset */
962: : bytesInLabel /* bytes */
963: : raw_label
964: : IOVmTaskSelf()
965: : (void *)NULL
966: : &bytesXfr];
967:
968: if((rtn == IO_R_SUCCESS) && (bytesXfr == bytesInLabel)) {
969: goodLabel++;
970: }
971: /*
972: * there is one fatal error here - disk not present.
973: */
974: if(rtn == IO_R_NO_DISK)
975: break;
976: }
977: if(goodLabel) {
978: _labelValid = 1;
979: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
980: _hfsValid = 0; // bek - 12/14/97 - Is this redundant?
981: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
982: rtn = IO_R_SUCCESS;
983: }
984: else {
985: xpr_disk("IODiskPartition writeLabel: Couldn\'t write label\n",
986: 1,2,3,4,5);
987: if(rtn != IO_R_NO_DISK)
988: rtn = IO_R_IO;
989: goto done;
990: }
991:
992: /*
993: * One more thing - update our own parameters and see if we
994: * need to create any block devices.
995: */
996: [self _probeLabel: label_p];
997: done:
998: [physDisk unlockLogicalDisks];
999: if(raw_label) {
1000: IOFree(raw_label, labelBufSize);
1001: }
1002: return(rtn);
1003: }
1004:
1005:
1006: /*
1007: * Before we die, tell owner about this. LogicalDisk takes care of freeing
1008: * chained logicalDisks.
1009: */
1010: - free
1011: {
1012: #ifdef KERNEL
1013: [self unregisterUnixDisk: _partition];
1014: #endif KERNEL
1015:
1016: if( _partitionWaitLock) {
1017: [_partitionWaitLock free];
1018: _partitionWaitLock = nil;
1019: }
1020: return([super free]);
1021: }
1022:
1023: /*
1024: * Handle Disk Eject request. Overrides IODisk's method of same name.
1025: * Invoked upon the partition 0 instance by DiskObject's eject. This
1026: * will be rejected at the DiskObject level if any block devices are open.
1027: * We require this to be done only on partition 0 since we're going to blow
1028: * away all of the other partitions.
1029: */
1030: - (IOReturn)eject
1031: {
1032: IOReturn rtn;
1033: id phys = [self physicalDisk];
1034:
1035: xpr_disk("IODiskPartition eject\n", 1,2,3,4,5);
1036:
1037: /*
1038: * We can't do this if any block devices, or any other logical disk,
1039: * are currently open. Also, we can only do this on partition 0
1040: * because we're going to blow away all IODiskPartitions other than the
1041: * one for partition 0 before we're thru.
1042: */
1043: rtn = [self checkSafeConfig:"eject"];
1044: if(rtn) {
1045: return rtn;
1046: }
1047:
1048: /*
1049: * Kill all other partitions. Have IODisk clear our
1050: * "formatted" flag.
1051: */
1052: [self _freePartitions];
1053: _labelValid = 0;
1054: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1055: _hfsValid = 0;
1056: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1057: [super setFormattedInternal:0];
1058:
1059: /*
1060: * Cancel possible outstanding "manual poll" request. This covers
1061: * the case in which the open() performed immediately preceeding
1062: * this eject command did an implied vol_check_set_poll() in the
1063: * driver's open() routine.
1064: */
1065: if([phys needsManualPolling]) {
1066: vol_check_manual_poll();
1067: }
1068:
1069: /*
1070: * Pass this down to physDisk using the internal versions to avoid
1071: * getting callbacks.
1072: */
1073: return([phys ejectPhysical]);
1074: }
1075:
1076: - (IOReturn) requestRelease
1077: {
1078: IOReturn rtn;
1079:
1080: /*
1081: * We can't do this if any block devices, or any other logical disk,
1082: * are currently open. Also, we can only do this on partition 0
1083: * because we're going to blow away all IODiskPartitions other than the
1084: * one for partition 0 before we're thru.
1085: */
1086:
1087: rtn = [self checkSafeConfig:"disown"];
1088: if(rtn) {
1089: return rtn;
1090: }
1091:
1092: /*
1093: * Kill all other partitions. Have IODisk clear our
1094: * "formatted" flag.
1095: */
1096: [self _freePartitions];
1097: _labelValid = 0;
1098: #ifdef GROK_APPLE
1099: _hfsValid = 0;
1100: #endif GROK_APPLE
1101: [super setFormattedInternal:0];
1102:
1103: return(rtn);
1104: }
1105:
1106: /*
1107: * read/write methods. These are illegal if _labelValid is false, otherwise
1108: * they're just passed up to LogicalDisk.
1109: */
1110: #ifdef KERNEL
1111: - (IOReturn) readAt : (unsigned)offset
1112: length : (unsigned)length
1113: buffer : (unsigned char *)buffer
1114: actualLength : (out unsigned *)actualLength
1115: client : (vm_task_t)client
1116: {
1117: xpr_disk("IODiskPartition read\n", 1,2,3,4,5);
1118:
1119: #if 0 // radar 1669467 - ISO 9660 CD support
1120: // Read is NOT illegal if _labelValid is false - ISO 9660 CDs do not have
1121: // standard disk label. In order to get read-only ISO 9660 CDROM support
1122: // working, we have disabled the check for a valid label on the read path
1123: // only. However, the ISO 9660 file system will not attempt to write to
1124: // the device and no other client should be able to open the device for
1125: // writing while the file system has it open, so the above scenario should
1126: // not occur. bknight.
1127: //
1128: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1129: if( ! ( _labelValid || _hfsValid ) ) {
1130: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1131: if( ! _labelValid ) {
1132: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1133: IOLog("%s: Read attempt with no valid label\n",
1134: [self name]);
1135: return(IO_R_INVALID_ARG);
1136: }
1137: #endif // radar 1669467 - ISO 9660 CD support
1138:
1139: return([super readAt : offset
1140: length : length
1141: buffer : buffer
1142: actualLength : actualLength
1143: client : client]);
1144: }
1145:
1146: - (IOReturn) readAsyncAt : (unsigned)offset
1147: length : (unsigned)length
1148: buffer : (unsigned char *)buffer
1149: pending : (void *)pending
1150: client : (vm_task_t)client
1151: {
1152: xpr_disk("IODiskPartition readAsync\n", 1,2,3,4,5);
1153: #if 0 // radar 1669467 - ISO 9660 CD support
1154: // Read is NOT illegal if _labelValid is false - ISO 9660 CDs do not have
1155: // standard disk label. In order to get read-only ISO 9660 CDROM support
1156: // working, we have disabled the check for a valid label on the read path
1157: // only. However, the ISO 9660 file system will not attempt to write to
1158: // the device and no other client should be able to open the device for
1159: // writing while the file system has it open, so the above scenario should
1160: // not occur. bknight.
1161: //
1162: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1163: if( ! ( _labelValid || _hfsValid ) ) {
1164: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1165: if( ! _labelValid ) {
1166: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1167: IOLog("%s: Read attempt with no valid label\n",
1168: [self name]);
1169: return(IO_R_INVALID_ARG);
1170: }
1171: #endif // radar 1669467 - ISO 9660 CD support
1172:
1173: return([super readAsyncAt : offset
1174: length : length
1175: buffer : buffer
1176: pending: pending
1177: client : client]);
1178: }
1179:
1180: - (IOReturn) writeAt : (unsigned)offset
1181: length : (unsigned)length
1182: buffer : (unsigned char *)buffer
1183: actualLength : (out unsigned *)actualLength
1184: client : (vm_task_t)client
1185: {
1186: xpr_disk("IODiskPartition writeAt\n", 1,2,3,4,5);
1187: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1188: if( ! ( _labelValid || _hfsValid ) ) {
1189: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1190: if( ! _labelValid ) {
1191: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1192: IOLog("%s: Write attempt with no valid label\n",
1193: [self name]);
1194: return(IO_R_INVALID_ARG);
1195: }
1196: return([super writeAt : offset
1197: length : length
1198: buffer : buffer
1199: actualLength : actualLength
1200: client : client]);
1201: }
1202:
1203: - (IOReturn) writeAsyncAt : (unsigned)offset
1204: length : (unsigned)length
1205: buffer : (unsigned char *)buffer
1206: pending : (void *)pending
1207: client : (vm_task_t)client
1208: {
1209: xpr_disk("IODiskPartition writeAsync\n", 1,2,3,4,5);
1210: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1211: if( ! ( _labelValid || _hfsValid ) ) {
1212: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1213: if( ! _labelValid ) {
1214: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1215: IOLog("%s: Write attempt with no valid label\n",
1216: [self name]);
1217: return(IO_R_INVALID_ARG);
1218: }
1219: return([super writeAsyncAt : offset
1220: length : length
1221: buffer : buffer
1222: pending: pending
1223: client : client]);
1224: }
1225:
1226: #else KERNEL
1227:
1228: - (IOReturn) readAt : (unsigned)offset
1229: length : (unsigned)length
1230: buffer : (unsigned char *)buffer
1231: actualLength : (out unsigned *)actualLength
1232: {
1233: xpr_disk("IODiskPartition read\n", 1,2,3,4,5);
1234: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1235: if( ! ( _labelValid || _hfsValid ) ) {
1236: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1237: if( ! _labelValid ) {
1238: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1239: IOLog("%s: Read attempt with no valid label\n",
1240: [self name]);
1241: return(IO_R_INVALID_ARG);
1242: }
1243: return([super readAt : offset
1244: length : length
1245: buffer : buffer
1246: actualLength : actualLength]);
1247: }
1248:
1249: - (IOReturn) readAsyncAt : (unsigned)offset
1250: length : (unsigned)length
1251: buffer : (unsigned char *)buffer
1252: pending : (void *)pending
1253: {
1254: xpr_disk("IODiskPartition readAsync\n", 1,2,3,4,5);
1255: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1256: if( ! ( _labelValid || _hfsValid ) ) {
1257: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1258: if( ! _labelValid ) {
1259: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1260: IOLog("%s: Read attempt with no valid label\n",
1261: [self name]);
1262: return(IO_R_INVALID_ARG);
1263: }
1264: return([super readAsyncAt : offset
1265: length : length
1266: buffer : buffer
1267: pending: pending]);
1268: }
1269:
1270: - (IOReturn) writeAt : (unsigned)offset
1271: length : (unsigned)length
1272: buffer : (unsigned char *)buffer
1273: actualLength : (unsigned *)actualLength
1274: {
1275: xpr_disk("IODiskPartition writeAt\n", 1,2,3,4,5);
1276: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1277: if( ! ( _labelValid || _hfsValid ) ) {
1278: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1279: if( ! _labelValid ) {
1280: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1281: IOLog("%s: Write attempt with no valid label\n",
1282: [self name]);
1283: return(IO_R_INVALID_ARG);
1284: }
1285: return([super writeAt : offset
1286: length : length
1287: buffer : buffer
1288: actualLength : actualLength]);
1289: }
1290:
1291: - (IOReturn) writeAsyncAt : (unsigned)offset
1292: length : (unsigned)length
1293: buffer : (unsigned char *)buffer
1294: pending : (void *)pending
1295: {
1296: xpr_disk("IODiskPartition writeAsync\n", 1,2,3,4,5);
1297: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1298: if( ! ( _labelValid || _hfsValid ) ) {
1299: #else GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1300: if( ! _labelValid ) {
1301: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1302: IOLog("%s: Write attempt with no valid label\n",
1303: [self name]);
1304: return(IO_R_INVALID_ARG);
1305: }
1306: return([super writeAsyncAt : offset
1307: length : length
1308: buffer : buffer
1309: pending: pending]);
1310: }
1311: #endif KERNEL
1312:
1313: /*
1314: * Public setFormatted, overrides the same method in IODisk.
1315: * This is the normal way a setFormatted operation is done in a
1316: * Unix environment.
1317: */
1318: - (IOReturn)setFormatted : (BOOL)formattedFlag
1319: {
1320: id physDisk;
1321: IOReturn rtn;
1322:
1323: /*
1324: * We can't do this if any block devices, or any other logical disk,
1325: * are currently open. Also, we can only do this on partition 0
1326: * because we're going to blow away all IODiskPartitions other than the
1327: * one for partition 0 before we're thru.
1328: */
1329: rtn = [self checkSafeConfig:"setFormatted"];
1330: if(rtn) {
1331: return rtn;
1332: }
1333:
1334: /*
1335: * Pass this down to physDisk using the internal versions to avoid
1336: * getting callbacks.
1337: */
1338: physDisk = [self physicalDisk];
1339: [physDisk setFormattedInternal:formattedFlag];
1340: if(formattedFlag) {
1341: /*
1342: * Going to a newly formatted state; have physical
1343: * device update block size and so forth.
1344: */
1345: [physDisk updatePhysicalParameters];
1346: }
1347:
1348: /*
1349: * Strange, but we'll set the internal formatted flag again in case
1350: * physical device driver disagrees with what our caller is saying.
1351: * The caller wins in this case.
1352: */
1353: [physDisk setFormattedInternal:formattedFlag];
1354: [self setFormattedInternal:formattedFlag];
1355: return IO_R_SUCCESS;
1356: }
1357:
1358: /*
1359: * internal setFormatted - avoids logical disk interaction. Called by
1360: * the exported setFormatted method both here (for normal Unix use) and
1361: * from physicalDisk.
1362: */
1363: - (void)setFormattedInternal:(BOOL)formattedFlag
1364: {
1365: xpr_disk("%s: setFormattedInternal %d\n", [self name],
1366: formattedFlag, 3,4,5);
1367: [self _freePartitions];
1368: _labelValid = 0;
1369:
1370: /*
1371: * Finally, the low-impact "just set the flag" method in
1372: * IODisk...
1373: */
1374: [super setFormattedInternal:formattedFlag];
1375: }
1376:
1377:
1378: /*
1379: * Get/set "device open" flags.
1380: */
1381: - (BOOL)isBlockDeviceOpen
1382: {
1383: return _blockDeviceOpen;
1384: }
1385:
1386: - (void)setBlockDeviceOpen : (BOOL)openFlag
1387: {
1388: _blockDeviceOpen = openFlag ? YES : NO;
1389: [self setInstanceOpen: (_blockDeviceOpen || _rawDeviceOpen)];
1390: }
1391:
1392: - (BOOL)isRawDeviceOpen
1393: {
1394: return _rawDeviceOpen;
1395: }
1396:
1397: - (void)setRawDeviceOpen : (BOOL)openFlag
1398: {
1399: _rawDeviceOpen = openFlag ? YES : NO;
1400: [self setInstanceOpen: (_blockDeviceOpen || _rawDeviceOpen)];
1401: }
1402:
1403: - waitForProbe:(int) seconds
1404: {
1405: int attempts;
1406: BOOL ready;
1407: ns_time_t now;
1408:
1409: if( nil == _partitionWaitLock)
1410: return( nil);
1411:
1412: [_partitionWaitLock lock];
1413: ready = [_partitionWaitLock condition];
1414: [_partitionWaitLock unlock];
1415:
1416: if( NO == ready) do {
1417: IOGetTimestamp( &now);
1418: attempts = seconds - (int)((now - _probeTime) / 1000 / 1000 / 1000);
1419: if( attempts <= 0)
1420: continue;
1421:
1422: IOLog( "%s: Waiting for drive to come ready", [self name]);
1423: for( ; (NO == ready) && attempts; attempts--) {
1424: IOLog( ".");
1425: IOSleep( 1000);
1426: [_partitionWaitLock lock];
1427: ready = [_partitionWaitLock condition];
1428: [_partitionWaitLock unlock];
1429: }
1430: IOLog( "\n");
1431: if( NO == ready)
1432: IOLog( "%s: Disk Not Ready\n", [self name]);
1433:
1434: } while( NO);
1435:
1436: return( ready ? self : nil);
1437: }
1438:
1439: @end
1440:
1441: @implementation IODiskPartition(Private)
1442:
1443:
1444: /*
1445: * Examine a known good label, initialize LogicalDisk parameters for the
1446: * partition '0' instance (on which this method is invoked) and create
1447: * additional partition instances as appropriate.
1448: *
1449: * Invoked by LogicalDisk +probe, upon disk insertion, and when a new label
1450: * is written.
1451: */
1452: - (void) _probeLabel : (disk_label_t *)labelp
1453: {
1454: IODiskPartition *partInst;
1455: int part;
1456: struct partition *partition_p;
1457: id physDisk = [self physicalDisk];
1458: id lastIODiskPartition = self;
1459:
1460: xpr_disk("IODiskPartition _probeLabel\n", 1,2,3,4,5);
1461:
1462: if(_partition != 0) {
1463: IOLog("%s: _probeLabel on partition != 0\n",
1464: [self name]);
1465: return;
1466: }
1467:
1468: /*
1469: * Update internal state for partition 0.
1470: */
1471: [self _initPartition:0
1472: physicalPartition:_physicalPartition
1473: disktab:&labelp->dl_dt];
1474:
1475: /*
1476: * Create & init an additional IODiskPartition instance per valid
1477: * partition. Partition NPART-1 is never used by convention (it's
1478: * the live partition).
1479: */
1480: for(part=1; part<NPART-1; part++) {
1481: partition_p = &labelp->dl_dt.d_partitions[part];
1482: if(partition_p->p_size > 0) {
1483:
1484: /*
1485: * A valid logical disk partition.
1486: */
1487: partInst = [IODiskPartition new];
1488: [partInst connectToPhysicalDisk:physDisk];
1489: [partInst _initPartition : part
1490: physicalPartition: _physicalPartition
1491: disktab : &labelp->dl_dt];
1492: [partInst init];
1493: [partInst registerDevice];
1494:
1495: /*
1496: * Link to logical disk chain, and notify
1497: * physDisk as well.
1498: */
1499: [lastIODiskPartition setLogicalDisk:partInst];
1500: [[self physicalDisk] setLogicalDisk:partInst];
1501: lastIODiskPartition = partInst;
1502: }
1503: }
1504: return;
1505: }
1506:
1507: /*
1508: * Assign logical disk parameters for an IODiskPartition instance based on
1509: * specified partition number on disktab. Caller must have already
1510: * done a connectToPhysicalDisk on this instance, and specified partition
1511: * is known to be valid.
1512: */
1513: - (void)_initPartition : (int)partNum
1514: physicalPartition : (int)physNum
1515: disktab : (struct disktab *)dtp;
1516: {
1517: struct partition *pp = &dtp->d_partitions[partNum];
1518: int partBase;
1519: char name[30];
1520: id physDisk = [self physicalDisk];
1521:
1522: /*
1523: * Set IODevice-class instance variables.
1524: */
1525: sprintf(name, "%s%c", [physDisk name], 'a' + partNum);
1526: [self setName:name];
1527: [self setDriveName:"IODiskPartition Partition"];
1528: [self setLocation:NULL];
1529: xpr_disk("%s: _initPartition\n", IOCopyString(name), 2,3,4,5);
1530: [self setDiskSize:pp->p_size];
1531: [self setBlockSize:dtp->d_secsize];
1532: [self setUnit:[physDisk unit]]; // probably unnecessary
1533:
1534: // Ensure partition 0 always has the correct value
1535: // for this instance variable, since connectToPhysicalDisk
1536: // is only called once for that partition.
1537: [self setWriteProtected:[physDisk isWriteProtected]];
1538:
1539: /*
1540: * LogicalDisk instance variables are taken care of in
1541: * connectToPhysicalDisk.
1542: * Set up local instance variables.
1543: *
1544: * Careful, partitionBase is not necessarily in physical blocksize;
1545: * for old disks, it's in d_secsize (usually DEV_BSIZE) from
1546: * disktab...
1547: */
1548: partBase = pp->p_base + dtp->d_front;
1549: partBase *= dtp->d_secsize / [self physicalBlockSize];
1550: [self setPartitionBase:partBase];
1551: _partition = partNum;
1552: _physicalPartition = physNum;
1553:
1554: /*
1555: * The low-impact "just set the flag" method in IODisk...Our
1556: * override of this method frees partitions.
1557: */
1558: [super setFormattedInternal:1];
1559: _labelValid = 1;
1560: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1561: _hfsValid = 0; // bek - 12/14/97 - Is this redundant?
1562: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1563:
1564: #ifdef KERNEL
1565: /*
1566: * Let Unix layer know about us.
1567: */
1568: [self registerUnixDisk : partNum];
1569: #endif KERNEL
1570: return;
1571: }
1572:
1573: /*
1574: * Free all partition instances other than partition 0. The others must
1575: * not be open, and this must be invoked on partition 0.
1576: */
1577: - (IOReturn)_freePartitions;
1578: {
1579: id nextPart = [self nextLogicalDisk];
1580:
1581: if(_partition != 0) {
1582: IOLog("%s: _freePartitions on partition != 0\n",
1583: [self name]);
1584: return IO_R_BUSY;
1585: }
1586: if(nextPart == nil)
1587: return IO_R_SUCCESS;
1588: if([nextPart isOpen]) {
1589: /*
1590: * this shouldn't happen - this was already checked
1591: * in checkSafeConfig.
1592: */
1593: IOLog("%s: _freePartitions with open partitions\n",
1594: [self name]);
1595: return IO_R_BUSY;
1596: }
1597: [nextPart free];
1598: [self setLogicalDisk:nil];
1599: return IO_R_SUCCESS;
1600: }
1601:
1602: /*
1603: * Determine if any block devices in the logicalDisk chain are open.
1604: */
1605: - (BOOL)isAnyBlockDevOpen
1606: {
1607: id logDisk = [[self physicalDisk] nextLogicalDisk];
1608:
1609: while(logDisk) {
1610: if([logDisk isBlockDeviceOpen]) {
1611: return YES;
1612: }
1613: logDisk = [logDisk nextLogicalDisk];
1614: }
1615: return NO;
1616: }
1617:
1618:
1619: /*
1620: * Verify that it's safe to do an operation which will result in a call
1621: * to _freePartitions.
1622: */
1623: - (IOReturn)checkSafeConfig : (const char *)op
1624: {
1625: if(_partition != 0) {
1626: return IO_R_BUSY;
1627: }
1628: if([self isAnyBlockDevOpen]) {
1629: return IO_R_BUSY;
1630: }
1631: if([self isAnyOtherOpen]) {
1632: return IO_R_BUSY;
1633: }
1634: return IO_R_SUCCESS;
1635: }
1636:
1637:
1638: #ifdef GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1639:
1640: /*
1641: * Check for an apple partition:
1642: *
1643: */
1644: #define BLOCKSIZE_512_BYTES 512
1645:
1646: + (void)CreateHFSDevicesFromApplePartitionMap: (id) devDesc
1647: {
1648: id physicalDisk = [devDesc directDevice];
1649: unsigned char * blk;
1650: Block0 * blk0;
1651: unsigned long blocksize;
1652: unsigned bytesXfr;
1653: IOReturn rtn;
1654:
1655: unsigned int block = 1;
1656: unsigned int entry_within_block = 0;
1657: int n;
1658: unsigned int nentries_per_block = 1;
1659: unsigned int numPartBlocks;
1660: DPME * partEntry;
1661: int physNum;
1662:
1663: IODiskPartition * partitionInstance;
1664: IODiskPartition * lastIODiskPartition = nil; // mandatory initialization
1665: unsigned part = 0;
1666:
1667: blocksize = 512;
1668:
1669: blk = IOMalloc(PAGE_SIZE); /* force page alignment */
1670: blk0 = (Block0 *)blk;
1671:
1672: /* check block 0 for valid Apple partition signature */
1673:
1674: rtn = [[super class] commonReadWrite
1675: : physicalDisk
1676: : YES /* read */
1677: : (unsigned long long)0 /* byte offset */
1678: : PAGE_SIZE /* bytes */
1679: : blk
1680: : IOVmTaskSelf()
1681: : (void *)NULL
1682: : &bytesXfr];
1683:
1684: if (rtn)
1685: {
1686: goto Return;
1687: }
1688:
1689: /* scan for apple hfs partitions */
1690:
1691: /* check if there is a valid map at 512 offset */
1692:
1693: partEntry = (DPME *)(blk + BLOCKSIZE_512_BYTES);
1694:
1695: if (blocksize > BLOCKSIZE_512_BYTES)
1696: {
1697: if (NXSwapBigShortToHost(partEntry->dpme_signature) == DPME_SIGNATURE)
1698: {
1699: /* there is a valid map, and the device blocksize
1700: * is > 512, which means we probably have a CDROM
1701: * using 2K, but having valid 512 map
1702: */
1703: block = 0;
1704: nentries_per_block = blocksize / BLOCKSIZE_512_BYTES;
1705: entry_within_block = 1;
1706: }
1707: else
1708: {
1709: partEntry = (DPME *)(blk + blocksize);
1710: }
1711: }
1712:
1713: if (NXSwapBigShortToHost(partEntry->dpme_signature) != DPME_SIGNATURE)
1714: {
1715: #if 1 // bknight - 7/2/98 - Radar #2240631
1716: /* Make a single giant "_hfs_a" partition to support floppies, DOS disks, ISO9660 CDs. */
1717:
1718: partitionInstance = [IODiskPartition new];
1719: [partitionInstance connectToPhysicalDisk: physicalDisk];
1720: [partitionInstance setDeviceDescription: devDesc];
1721: [partitionInstance _initHFSPartition: 0
1722: physicalPartNum: 0 // bknight - intentionally illegal phys part num
1723: diskSize: ( [physicalDisk diskSize] * ([physicalDisk blockSize] / BLOCKSIZE_512_BYTES) )
1724: partitionBase: 0];
1725: [partitionInstance init]; //bknight - [super init] all the way up to Object
1726: [partitionInstance registerDevice]; //bknight - doesn't do anything since (!_isPhysical)
1727:
1728: /* No need to link onto the end of nonexistent chain of logical partitions.
1729: Just notify the physical disk. */
1730:
1731: [physicalDisk setLogicalDisk: partitionInstance]; //bknight - doesn't override if already set
1732: #endif // bknight - 7/2/98 - Radar #2240631
1733: goto Return;
1734: }
1735:
1736: numPartBlocks = NXSwapBigLongToHost(partEntry->dpme_map_entries);
1737: physNum = 1;
1738: for (n = 0; n < numPartBlocks; n++)
1739: {
1740: if (NXSwapBigShortToHost(partEntry->dpme_signature) != DPME_SIGNATURE)
1741: {
1742: break;
1743: }
1744:
1745: if ( strcmp(partEntry->dpme_type, HFS_PART_TYPE) == 0 )
1746: {
1747: /*
1748: * Mount HFS volume only if this isn't "MOSX_OF3_Booter" partition.
1749: */
1750: if ( strcmp(partEntry->dpme_name, "MOSX_OF3_Booter") != 0 )
1751: {
1752: unsigned long part_offset;
1753:
1754: part_offset = NXSwapBigLongToHost(partEntry->dpme_pblock_start);
1755: if ((part_offset / nentries_per_block * nentries_per_block) != part_offset)
1756: {
1757: IOLog("IODiskPartition: " HFS_PART_TYPE
1758: " partition base (%ld x 512) is not"
1759: " a multiple of the devblksize %ld\n",
1760: part_offset, blocksize);
1761: break;
1762: }
1763:
1764: part_offset = part_offset / nentries_per_block;
1765:
1766: /* A valid logical disk partition. */
1767:
1768: partitionInstance = [IODiskPartition new];
1769: [partitionInstance connectToPhysicalDisk: physicalDisk];
1770: [partitionInstance setDeviceDescription:devDesc];
1771: [partitionInstance
1772: _initHFSPartition: part
1773: physicalPartNum: physNum
1774: diskSize: partEntry->dpme_pblocks
1775: partitionBase: partEntry->dpme_pblock_start];
1776: [partitionInstance init]; //bknight - [super init] all the way up to Object
1777: [partitionInstance registerDevice]; //bknight - doesn't do anything since (!_isPhysical)
1778:
1779: /* Link to logical disk chain, and notify the physicalDisk. */
1780:
1781: if ( lastIODiskPartition != nil )
1782: {
1783: [lastIODiskPartition setLogicalDisk: partitionInstance];
1784: }
1785: lastIODiskPartition = partitionInstance;
1786: [physicalDisk setLogicalDisk: partitionInstance]; //bknight - doesn't override if already set
1787:
1788: /* Increment our partition counter. */
1789:
1790: part++;
1791: } // if not "MOSX_OF3_Booter" partition flag set
1792: } // if HFS_PART_TYPE
1793:
1794: physNum++;
1795: partEntry++;
1796: if (++entry_within_block == nentries_per_block)
1797: {
1798: block++;
1799: entry_within_block = 0;
1800: partEntry = (DPME *)blk;
1801: rtn = [[super class] commonReadWrite
1802: : physicalDisk
1803: : YES /* read */
1804: : (unsigned long long)block * blocksize /* byte offset */
1805: : blocksize /* bytes */
1806: : blk
1807: : IOVmTaskSelf()
1808: : (void *)NULL
1809: : &bytesXfr];
1810: if (rtn)
1811: {
1812: break;
1813: }
1814:
1815: } // if
1816:
1817: } // for
1818:
1819: Return:
1820:
1821: IOFree(blk, PAGE_SIZE);
1822: return;
1823:
1824: } // CreateHFSDevicesFromApplePartitionMap
1825:
1826: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1827:
1828: #if GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1829:
1830: /*
1831: * Assign logical disk parameters for an IODiskPartition instance based on
1832: * specified partition number on disktab. Caller must have already
1833: * done a connectToPhysicalDisk on this instance, and specified partition
1834: * is known to be valid.
1835: */
1836: - (void) _initHFSPartition : (int) partitionNum
1837: physicalPartNum : (int) physNum
1838: diskSize : (int) diskSize
1839: partitionBase : (int) partitionBase;
1840: {
1841: int hfsPartitionNum = partitionNum + NPART;
1842: char name[30]; //bknight - hardcoded
1843: id physicalDisk = [self physicalDisk];
1844:
1845: /* IODevice initialization */
1846:
1847: sprintf(name, "%s_hfs_%c", [physicalDisk name], 'a' + partitionNum);
1848: [self setUnit: [physicalDisk unit]]; // IODevice //bknight - probably unnecessary ???
1849: [self setName: name];
1850: [self setLocation: NULL];
1851:
1852: /* IODisk initialization */
1853:
1854: [self setDriveName: "IODiskPartition Partition"];
1855:
1856: // always measured in 512-byte blocks, regardless of the device block size
1857:
1858: [self setDiskSize: diskSize]; //bknight - in 512-byte blocks
1859:
1860: // hardcoded per Radar #2211264
1861:
1862: [self setBlockSize: 512];
1863:
1864: /* bknight - WHAT DOES THIS COMMENT / LINE MEAN ??? */
1865:
1866: // Ensure partition 0 always has the correct value
1867: // for this instance variable, since connectToPhysicalDisk
1868: // is only called once for that partition.
1869: [self setWriteProtected:[physicalDisk isWriteProtected]];
1870:
1871: /*
1872: * IOLogicalDisk instance variables are taken care of in connectToPhysicalDisk.
1873: * Set up IODiskPartition instance variables.
1874: *
1875: */
1876: [self setPartitionBase: partitionBase];
1877: _partition = hfsPartitionNum;
1878: _physicalPartition = physNum;
1879:
1880: /*
1881: * The low-impact "just set the flag" method in IODisk...Our
1882: * override of this method frees partitions.
1883: */
1884: [super setFormattedInternal:1];
1885: _hfsValid = 1;
1886: _labelValid = 0;
1887:
1888: #ifdef KERNEL
1889: /*
1890: * Let Unix layer know about us.
1891: */
1892: [self registerUnixDisk: hfsPartitionNum];
1893: #endif KERNEL
1894:
1895: Return:
1896:
1897: return;
1898:
1899: } // _initHFSPartition
1900:
1901: #endif GROK_APPLE //bknight - 12/3/97 - Radar #2004660
1902:
1903: - property_IODeviceType:(char *)types length:(unsigned int *)maxLen
1904: {
1905: #if GROK_APPLE
1906: if( _hfsValid)
1907: strcat( types, " "IOTypeHFS);
1908: else
1909: #endif GROK_APPLE
1910: strcat( types, " "IOTypeUFS);
1911: return( self);
1912: }
1913:
1914: - property_IODeviceClass:(char *)classes length:(unsigned int *)maxLen
1915: {
1916: [super property_IODeviceClass:classes length:maxLen];
1917: strcat( classes, " "IOClassDiskPartition);
1918: return( self);
1919: }
1920:
1921: - property_IOPartitionNumber:(char *)result length:(unsigned int *)maxLen
1922: {
1923: sprintf( result, "0x%x", _physicalPartition);
1924: return( self);
1925: }
1926:
1927: - registerLoudly
1928: {
1929: return( nil);
1930: }
1931:
1932: @end
1933:
1934: #ifndef KERNEL
1935: /*
1936: * Ripped off from kernel's next/checksum16.c
1937: */
1938: #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
1939: #define REDUCE { \
1940: l_util.l = sum; \
1941: sum = l_util.s[0] + l_util.s[1]; \
1942: ADDCARRY(sum); \
1943: }
1944:
1945: u_short checksum_16(u_short *wp, int num_shorts)
1946: {
1947: int sum = 0;
1948: union {
1949: u_short s[2];
1950: long l;
1951: } l_util;
1952:
1953: while (num_shorts--)
1954: sum += *wp++;
1955: REDUCE;
1956: return (sum);
1957: }
1958: #endif KERNEL
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.