|
|
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: * volCheck.m - common volume check logic for all DiskObjects. ! 27: * ! 28: * This only does useful work in the kernel, since it relies heavily ! 29: * on the vol driver functionality. Someday we'll have to come up ! 30: * with a new interface bewteen WS and a user-level version of this. ! 31: * ! 32: * HISTORY ! 33: * 07-May-91 Doug Mitchell at NeXT ! 34: * Created. ! 35: */ ! 36: #import <driverkit/IODisk.h> ! 37: #import <driverkit/IODiskPartition.h> ! 38: #import <machkit/NXLock.h> ! 39: #import <kernserv/queue.h> ! 40: #import <driverkit/generalFuncs.h> ! 41: #import <driverkit/Device_ddm.h> ! 42: #import <driverkit/IODeviceDescription.h> ! 43: #import <bsd/dev/disk.h> ! 44: ! 45: #undef DRIVER_PRIVATE ! 46: #define DRIVER_PRIVATE ! 47: ! 48: #ifdef KERNEL ! 49: #import <kernserv/prototypes.h> ! 50: #import <bsd/dev/voldev.h> ! 51: #else KERNEL ! 52: #import <bsd/libc.h> ! 53: #import "volDriver.h" ! 54: #endif KERNEL ! 55: ! 56: #import <driverkit/volCheck.h> ! 57: #import "volCheckPrivate.h" ! 58: ! 59: /* ! 60: * Static data. ! 61: */ ! 62: /* ! 63: * Queue of volCheckEntry_t's. One per removable disk drive. It's not ! 64: * protected with a lock; all accesses to this queue are by the ! 65: * volCheckThread. ! 66: */ ! 67: static queue_head_t volCheckEntryQ; ! 68: ! 69: /* ! 70: * Input queue. Commands are queued here by public routines to ensure ! 71: * single-threaded response to change in device state. ! 72: */ ! 73: static queue_head_t volCheckCmdQ; ! 74: static id volCheckCmdLock; ! 75: ! 76: /* ! 77: * Prototypes of static functions. ! 78: */ ! 79: static void volCheckThread(void *foo); ! 80: static void volCheckResponse(void *param, ! 81: int tag, ! 82: int response_value); ! 83: static volCheckEntry_t *getVCEntry(id diskObj); ! 84: static void vcEnqueueCmd(volCheckOp_t op, ! 85: id diskObj, ! 86: int diskType, ! 87: dev_t blockDev, ! 88: dev_t rawDev); ! 89: static void volCheckCmdHandler(); ! 90: static void volDriverNotify(id diskObj, ! 91: dev_t blockDev, ! 92: dev_t rawDev); ! 93: ! 94: /* ! 95: * Public functions. ! 96: */ ! 97: ! 98: /* ! 99: * One-time only initialization. ! 100: */ ! 101: void volCheckInit() ! 102: { ! 103: volCheckCmdLock = [NXSpinLock new]; ! 104: queue_init(&volCheckEntryQ); ! 105: queue_init(&volCheckCmdQ); ! 106: ! 107: /* ! 108: * FIXME - only start up a thread when we get the first ! 109: * volCheckRegister(). ! 110: */ ! 111: IOForkThread((IOThreadFunc)volCheckThread, NULL); ! 112: #ifndef KERNEL ! 113: volDriverInit(); ! 114: #endif KERNEL ! 115: } ! 116: ! 117: /* ! 118: * These public routines queue up a command on volCheckCmdQ to ensure ! 119: * single-threaded handling of lastReadyState transitions. ! 120: */ ! 121: /* ! 122: * Register a removable media drive. This should be called once for the ! 123: * physical disk object, not for any LogicalDisks which sit on top of it. ! 124: */ ! 125: void volCheckRegister(id diskObj, ! 126: dev_t blockDev, ! 127: dev_t rawDev) ! 128: { ! 129: xpr_vc("volCheckRegister: disk %s\n", [diskObj name], 2,3,4,5); ! 130: if(![diskObj isPhysical]) { ! 131: IOLog("volCheckRegister: %s is not a physical device\n", ! 132: [diskObj name]); ! 133: return; ! 134: } ! 135: vcEnqueueCmd(VC_REGISTER, ! 136: diskObj, ! 137: 0, ! 138: blockDev, ! 139: rawDev); ! 140: } ! 141: ! 142: /* ! 143: * Unregister a removable media drive. This probably should never happen, ! 144: * at least not in the kernel... ! 145: */ ! 146: void volCheckUnregister(id diskObj) ! 147: { ! 148: xpr_vc("volCheckUnregister: disk %s\n", ! 149: [diskObj name], 2,3,4,5); ! 150: vcEnqueueCmd(VC_UNREGISTER, ! 151: diskObj, ! 152: 0, ! 153: 0, ! 154: 0); ! 155: } ! 156: ! 157: /* ! 158: * Request a "please insert disk" panel. Called by physDevice DiskObject. ! 159: * ! 160: * For now, we don't have a connection with WS unless we're in the ! 161: * kernel. ! 162: */ ! 163: void volCheckRequest(id diskObj, // requestor ! 164: int diskType) // PR_DRIVE_FLOPPY, etc. ! 165: { ! 166: xpr_vc("volCheckRequest: disk %s\n", ! 167: [diskObj name], 2,3,4,5); ! 168: vcEnqueueCmd(VC_REQUEST, ! 169: diskObj, ! 170: diskType, ! 171: 0, ! 172: 0); ! 173: } ! 174: ! 175: /* ! 176: * Notify volCheck that specified device is in a "disk ejecting" state. ! 177: * Called by physDevice DiskObject in ejectPhysical:. Only necessary ! 178: * for drives which may not respond to autoeject. Thus floppy drivers shouldn't ! 179: * have to call this. ! 180: * ! 181: * NOTE: we force the low-level driver to pass in diskType in this call ! 182: * and in volCheckRequest() to avoid having DiskObject know this ! 183: * detail at registerDisk: time... ! 184: */ ! 185: void volCheckEjecting(id diskObj, ! 186: int diskType) // PR_DRIVE_FLOPPY, etc. ! 187: { ! 188: xpr_vc("volCheckEjecting: disk %s\n", [diskObj name], 2,3,4,5); ! 189: ! 190: vcEnqueueCmd(VC_EJECTING, ! 191: diskObj, ! 192: diskType, ! 193: 0, ! 194: 0); ! 195: } ! 196: ! 197: /* ! 198: * Notify volCheck that disk has gone not ready. Typically called on ! 199: * gross error detection. ! 200: */ ! 201: void volCheckNotReady(id diskObj) ! 202: { ! 203: xpr_vc("volCheckNotReady: disk %s\n", [diskObj name], 2,3,4,5); ! 204: vcEnqueueCmd(VC_NOTREADY, ! 205: diskObj, ! 206: 0, ! 207: 0, ! 208: 0); ! 209: } ! 210: ! 211: /* ! 212: * Private functions. ! 213: */ ! 214: /* ! 215: * Get the volCheckEntry_t for specified DiskObject id. ! 216: */ ! 217: static volCheckEntry_t *getVCEntry(id diskObj) ! 218: { ! 219: volCheckEntry_t *vcEntry; ! 220: ! 221: vcEntry = (volCheckEntry_t *)queue_first(&volCheckEntryQ); ! 222: while(!queue_end(&volCheckEntryQ, (queue_t)vcEntry)) { ! 223: if(vcEntry->diskObj == diskObj) ! 224: return(vcEntry); ! 225: vcEntry = (volCheckEntry_t *)vcEntry->link.next; ! 226: } ! 227: xpr_err("getVCEntry: ENTRY NOT FOUND\n", 1,2,3,4,5); ! 228: return(NULL); ! 229: } ! 230: ! 231: /* ! 232: * Enqueue a command on volCheckCmdQ. Called by public routines. ! 233: */ ! 234: static void vcEnqueueCmd(volCheckOp_t op, ! 235: id diskObj, ! 236: int diskType, ! 237: dev_t blockDev, ! 238: dev_t rawDev) ! 239: { ! 240: volCheckCmd_t *vcCmd; ! 241: ! 242: vcCmd = IOMalloc(sizeof(*vcCmd)); ! 243: vcCmd->op = op; ! 244: vcCmd->diskObj = diskObj; ! 245: vcCmd->diskType = diskType; ! 246: vcCmd->blockDev = blockDev; ! 247: vcCmd->rawDev = rawDev; ! 248: [volCheckCmdLock lock]; ! 249: queue_enter(&volCheckCmdQ, ! 250: vcCmd, ! 251: volCheckCmd_t *, ! 252: link); ! 253: [volCheckCmdLock unlock]; ! 254: } ! 255: ! 256: /* ! 257: * Called by vol driver upon reception of panel response. The only ! 258: * response we know about is an abort...do we need others? All we do ! 259: * is forward this notification to the appropriate DiskObject. ! 260: */ ! 261: static void volCheckResponse(void *param, ! 262: int tag, ! 263: int response_value) ! 264: { ! 265: id diskObj = (id)param; ! 266: ! 267: xpr_vc("volCheckResponse disk %s\n", [diskObj name], 2,3,4,5); ! 268: vcEnqueueCmd(VC_RESPONSE, ! 269: diskObj, ! 270: 0, ! 271: 0, ! 272: 0); ! 273: } ! 274: ! 275: /* ! 276: * volCheck thread function. Max of two per system (one in the kernel, ! 277: * one in user space). ! 278: */ ! 279: static void volCheckThread(void *foo) ! 280: { ! 281: ! 282: volCheckEntry_t *vcEntry; ! 283: IODiskReadyState lastReadyState; ! 284: IODiskReadyState newReadyState = IO_NotReady; // damned compiler! ! 285: const char *devname; ! 286: id diskObj; ! 287: int manualPoll; ! 288: ! 289: while(1) { ! 290: ! 291: /* ! 292: * First handle any queued commands. ! 293: */ ! 294: volCheckCmdHandler(); ! 295: ! 296: /* ! 297: * Process each registered disk. ! 298: */ ! 299: vcEntry = (volCheckEntry_t *)queue_first(&volCheckEntryQ); ! 300: manualPoll = vol_check_manual_poll(); ! 301: while(!queue_end(&volCheckEntryQ, (queue_t)vcEntry)) { ! 302: ! 303: devname = [vcEntry->diskObj name]; ! 304: diskObj = vcEntry->diskObj; ! 305: lastReadyState = [diskObj lastReadyState]; ! 306: if(lastReadyState != IO_Ready) { ! 307: /* ! 308: * Poll for transition if: ! 309: * -- this is a normal once-per-second polling ! 310: * drive, or ! 311: * -- vol driver tells us it's time to poll, or ! 312: * -- ready state is Ejecting ! 313: */ ! 314: if(![vcEntry->diskObj needsManualPolling] || ! 315: manualPoll || ! 316: (lastReadyState == IO_Ejecting)) { ! 317: newReadyState = [diskObj updateReadyState]; ! 318: } ! 319: else { ! 320: /* ! 321: * Don't poll; assume state unchanged. ! 322: */ ! 323: newReadyState = lastReadyState; ! 324: } ! 325: } ! 326: switch(lastReadyState) { ! 327: case IO_Ready: ! 328: break; // nothing to do here ! 329: ! 330: case IO_Ejecting: ! 331: /* ! 332: * We hope to see a transition to not ready or ! 333: * no disk...when we see "ready" enough times, ! 334: * we'll ask the WS to put up a "please eject disk" ! 335: * panel. ! 336: */ ! 337: if(newReadyState == IO_Ready) { ! 338: if(--vcEntry->ejectCounter == 0) { ! 339: xpr_vc("volCheck: requesting disk eject" ! 340: " panel for disk %s\n", devname, ! 341: 2,3,4,5); ! 342: vol_panel_request(NULL, // no callback ! 343: PR_RT_EJECT_REQ, ! 344: PR_RT_CANCEL, // leave up 'til ! 345: // we take it ! 346: // down ! 347: 0, // p1, not used ! 348: vcEntry->diskType, // p2 ! 349: [diskObj unit], // p3 ! 350: 0, // p4, not used ! 351: "", // string1 ! 352: "", // string2 ! 353: NULL, // no callback ! 354: &vcEntry->tag); ! 355: vcEntry->ejectRequestPending = YES; ! 356: ! 357: } /* counter 0 */ ! 358: } /* still ready */ ! 359: else { ! 360: ! 361: /* ! 362: * Allright! It went not ready. Remove ! 363: * eject request panel if present. ! 364: */ ! 365: xpr_vc("volCheck: %s: Eject Complete\n", ! 366: devname, 2,3,4,5); ! 367: [diskObj setLastReadyState:IO_NoDisk]; ! 368: if(vcEntry->ejectRequestPending) { ! 369: vcEntry->ejectRequestPending = NO; ! 370: vol_panel_remove(vcEntry->tag); ! 371: } ! 372: } /* not ready/not present */ ! 373: break; /* from case IO_Ejecting */ ! 374: ! 375: case IO_NotReady: ! 376: case IO_NoDisk: ! 377: /* ! 378: * The drive wasn't ready the last time we checked. ! 379: * We're interested in transitions to a ready state, ! 380: * indicating disk insertion. ! 381: */ ! 382: if(newReadyState == IO_Ready) { ! 383: ! 384: id descr; ! 385: ! 386: [diskObj setLastReadyState:IO_Ready]; ! 387: if(vcEntry->diskRequestPending) { ! 388: /* ! 389: * Cancel the panel. ! 390: */ ! 391: xpr_vc("volCheck: cancelling request panel" ! 392: " for %s\n", devname, 2,3,4,5); ! 393: vol_panel_remove(vcEntry->tag); ! 394: } ! 395: ! 396: /* ! 397: * Have the driver get other physical parameters. ! 398: */ ! 399: [diskObj updatePhysicalParameters]; ! 400: ! 401: /* ! 402: * Notify driver whether or not we think it ! 403: * is waiting for this disk to cover race ! 404: * conditions between panels and insertions. ! 405: * Then take care of layering some ! 406: * IODiskPartitions on top of this new disk. ! 407: * We have to do this before a possible ! 408: * vol_notify_dev(). ! 409: */ ! 410: [diskObj diskBecameReady]; ! 411: descr = [IODeviceDescription new]; ! 412: [descr setDirectDevice:diskObj]; ! 413: if(![IODiskPartition probe:descr]) { ! 414: [descr free]; ! 415: } ! 416: ! 417: if(vcEntry->diskRequestPending) { ! 418: vcEntry->diskRequestPending = NO; ! 419: } ! 420: else { ! 421: /* ! 422: * Unexpected disk insertion. Notify WS. ! 423: * We are the one to determine whether it has ! 424: * a valid label. We also have to gather ! 425: * other cruft like write protect for use by ! 426: * WS. ! 427: */ ! 428: volDriverNotify(diskObj, vcEntry->blockDev, ! 429: vcEntry->rawDev); ! 430: ! 431: } /* new disk insertion */ ! 432: } /* new state == ready */ ! 433: /* else no action (wasn't ready, still ! 434: * isn't) */ ! 435: break; /* from case not ready/no disk */ ! 436: } /* switch lastReadyState */ ! 437: ! 438: /* ! 439: * Next disk. ! 440: */ ! 441: vcEntry = (volCheckEntry_t *)vcEntry->link.next; ! 442: } ! 443: ! 444: /* ! 445: * OK, sleep a while. ! 446: */ ! 447: IOSleep(1000); ! 448: ! 449: } /* while 1 */ ! 450: ! 451: /* NOT REACHED */ ! 452: ! 453: } ! 454: ! 455: /* ! 456: * Handle queued commands. ! 457: */ ! 458: static void volCheckCmdHandler() ! 459: { ! 460: volCheckCmd_t *vcCmd; ! 461: volCheckEntry_t *vcEntry = NULL; ! 462: id diskObj; ! 463: IODiskReadyState readyState; ! 464: ! 465: [volCheckCmdLock lock]; ! 466: while(!queue_empty(&volCheckCmdQ)) { ! 467: vcCmd = (volCheckCmd_t *)queue_first(&volCheckCmdQ); ! 468: queue_remove(&volCheckCmdQ, ! 469: vcCmd, ! 470: volCheckCmd_t *, ! 471: link); ! 472: [volCheckCmdLock unlock]; ! 473: diskObj = vcCmd->diskObj; ! 474: if(vcCmd->op != VC_REGISTER) { ! 475: vcEntry = getVCEntry(diskObj); ! 476: if(vcEntry == NULL) { ! 477: IOLog("volCheck: disk %s not " ! 478: "registered, cmd = %d\n", ! 479: [diskObj name], vcCmd->op); ! 480: goto freeCmd; ! 481: } ! 482: ! 483: } ! 484: switch(vcCmd->op) { ! 485: case VC_REGISTER: ! 486: xpr_vc("volCheck: registering disk %s\n", ! 487: [diskObj name], 2,3,4,5); ! 488: #if 1 ! 489: /* ! 490: * We should use the current state since that ! 491: * indicates whether or the disk has been probed ! 492: * at registration. It may have come ready after ! 493: * probe, but before we get here. ! 494: */ ! 495: readyState = [diskObj lastReadyState]; ! 496: #else ! 497: readyState = [diskObj updateReadyState]; ! 498: /* ! 499: * IODiskPartition does this too, but we have to do ! 500: * it here as well in case we run before ! 501: * IODiskPartition does this. ! 502: */ ! 503: [diskObj setLastReadyState:readyState]; ! 504: #endif ! 505: ! 506: /* ! 507: * If ready now, go ahead and notify vol driver. ! 508: */ ! 509: if(readyState == IO_Ready) { ! 510: /* ! 511: * If this disk is not removable and ! 512: * it's currently ready, we have no ! 513: * reason to do anything other than ! 514: * the initial notify. ! 515: */ ! 516: volDriverNotify(diskObj, vcCmd->blockDev, ! 517: vcCmd->rawDev); ! 518: ! 519: ! 520: if(![diskObj isRemovable]) { ! 521: /* ! 522: * If ready now, go ahead and ! 523: * notify vol driver. ! 524: */ ! 525: break; ! 526: }; ! 527: } ! 528: ! 529: vcEntry = IOMalloc(sizeof(*vcEntry)); ! 530: vcEntry->diskObj = diskObj; ! 531: vcEntry->blockDev = vcCmd->blockDev; ! 532: vcEntry->rawDev = vcCmd->rawDev; ! 533: vcEntry->ejectCounter = 0; ! 534: vcEntry->ejectRequestPending = NO; ! 535: vcEntry->diskRequestPending = NO; ! 536: vcEntry->diskType = vcCmd->diskType; ! 537: queue_enter(&volCheckEntryQ, ! 538: vcEntry, ! 539: volCheckEntry_t *, ! 540: link); ! 541: break; ! 542: ! 543: case VC_UNREGISTER: ! 544: xpr_vc("volCheck: unregistering disk %s\n", ! 545: [vcCmd->diskObj name], 2,3,4,5); ! 546: queue_remove(&volCheckEntryQ, ! 547: vcEntry, ! 548: volCheckEntry_t *, ! 549: link); ! 550: IOFree(vcEntry, sizeof(*vcEntry)); ! 551: break; ! 552: ! 553: case VC_REQUEST: ! 554: /* ! 555: * Panel request. ! 556: */ ! 557: { ! 558: kern_return_t krtn; ! 559: int unit = [diskObj unit]; ! 560: ! 561: xpr_vc("volCheck VC_REQUEST: disk %s\n", ! 562: [diskObj name], 2,3,4,5); ! 563: ! 564: /* ! 565: * If there is already a panel up for this drive, ! 566: * this is a nop. ! 567: */ ! 568: if(vcEntry->diskRequestPending) { ! 569: xpr_vc("volCheckRequest: Panel already " ! 570: "pending\n", 1,2,3,4,5); ! 571: break; ! 572: } ! 573: if([diskObj lastReadyState] == IO_Ready) { ! 574: /* ! 575: * This can be the result of a call to ! 576: * volCheckRequest() follwed by immediate ! 577: * insertion of the desired disk. ! 578: * No error. No panel. ! 579: */ ! 580: xpr_vc("volCheckRequest: Panel Not " ! 581: "Necessary\n", 1,2,3,4,5); ! 582: break; ! 583: } ! 584: krtn = vol_panel_disk_num(volCheckResponse, ! 585: 0, // volume number ! 586: vcCmd->diskType, ! 587: unit, // drive number ! 588: diskObj, // param for callback ! 589: NO, // wrong disk ! 590: &vcEntry->tag); ! 591: /* ! 592: * Record this request in *vcEntry. ! 593: */ ! 594: vcEntry->diskRequestPending = YES; ! 595: break; ! 596: } ! 597: ! 598: case VC_EJECTING: ! 599: xpr_vc("volCheck VC_EJECTING: disk %s\n", ! 600: [diskObj name], 2,3,4,5); ! 601: [diskObj setLastReadyState:IO_Ejecting]; ! 602: #if i386 ! 603: /* ! 604: * FIXME - this should only be done for ! 605: * i386 *floppy* drives! ! 606: */ ! 607: vcEntry->ejectCounter = 1; ! 608: #else ! 609: vcEntry->ejectCounter = VC_EJECT_DELAY; ! 610: #endif ! 611: vcEntry->ejectRequestPending = NO; ! 612: vcEntry->diskType = vcCmd->diskType; ! 613: break; ! 614: ! 615: case VC_NOTREADY: ! 616: xpr_vc("volCheck VC_NOTREADY: disk %s\n", ! 617: [diskObj name], 2,3,4,5); ! 618: [diskObj setLastReadyState:IO_NotReady]; ! 619: break; ! 620: ! 621: case VC_RESPONSE: ! 622: /* ! 623: * This comes from the vol driver - it's a panel ! 624: * response, which can only mean "disk not available". ! 625: */ ! 626: xpr_vc("volCheck VC_RESPONSE: disk %s\n", ! 627: [diskObj name], 2,3,4,5); ! 628: if(!vcEntry->diskRequestPending) { ! 629: /* ! 630: * This can happen if the disk is inserted ! 631: * at around the same time as the user hit ! 632: * "cancel". ! 633: */ ! 634: break; ! 635: } ! 636: vcEntry->diskRequestPending = NO; ! 637: [diskObj abortRequest]; ! 638: break; ! 639: ! 640: } /* switch op */ ! 641: ! 642: freeCmd: ! 643: IOFree(vcCmd, sizeof(*vcCmd)); ! 644: ! 645: /* ! 646: * We need to hold this lock at the top of the loop, and ! 647: * we'll hold it when we drop out. ! 648: */ ! 649: [volCheckCmdLock lock]; ! 650: } /* for each cmd */ ! 651: ! 652: [volCheckCmdLock unlock]; ! 653: xpr_vc("volCheckCmdHandler: done\n", 1,2,3,4,5); ! 654: } ! 655: ! 656: /* ! 657: * Common means by which vol driver is notified of presence of disk, either ! 658: * at disk insertion time or at volCheckRegister() time. ! 659: */ ! 660: static void volDriverNotify(id diskObj, ! 661: dev_t blockDev, ! 662: dev_t rawDev) ! 663: { ! 664: struct disk_label *label = IOMalloc(sizeof(struct disk_label)); ! 665: int vol_state; ! 666: int flags; ! 667: id logicalDisk; ! 668: IOReturn rtn; ! 669: ! 670: xpr_vc("volDriverNotify: dev=%s\n", [diskObj name], 2,3,4,5); ! 671: if([diskObj isRemovable]) { ! 672: flags = IND_FLAGS_REMOVABLE; ! 673: } ! 674: else { ! 675: flags = IND_FLAGS_FIXED; ! 676: } ! 677: logicalDisk = [diskObj nextLogicalDisk]; ! 678: if(logicalDisk != nil) { ! 679: rtn = [logicalDisk readLabel:label]; ! 680: } ! 681: else { ! 682: /* ! 683: * This is pretty weird. IODiskPartitionProbe: ! 684: * should have created an IODiskPartition object as partition ! 685: * 0's raw device... ! 686: */ ! 687: IOLog("volCheck: physDev with no logicalDisk!!\n"); ! 688: rtn = IO_R_NO_LABEL; ! 689: } ! 690: if(rtn == IO_R_SUCCESS) { ! 691: vol_state = IND_VS_LABEL; ! 692: } ! 693: else { ! 694: if([diskObj isFormatted]) { ! 695: vol_state = IND_VS_FORMATTED; ! 696: } ! 697: else { ! 698: vol_state = IND_VS_UNFORMATTED; ! 699: } ! 700: } ! 701: if([diskObj isWriteProtected]) { ! 702: flags |= IND_FLAGS_WP; ! 703: } ! 704: vol_notify_dev(blockDev, ! 705: rawDev, ! 706: "", // form_type - what was this for ! 707: // again??? ! 708: vol_state, ! 709: [diskObj name], // "sd0", etc. ! 710: flags); // WP, removable ! 711: ! 712: IOFree(label, sizeof(struct disk_label)); ! 713: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.