|
|
1.1 ! root 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: * IOSCSIParallelController.cpp ! 24: * ! 25: */ ! 26: ! 27: #include <IOKit/scsi/IOSCSIParallelInterface.h> ! 28: #include <IOKit/IOSyncer.h> ! 29: ! 30: #undef super ! 31: #define super IOService ! 32: ! 33: OSDefineMetaClass( IOSCSIParallelController, IOService ) ! 34: OSDefineAbstractStructors( IOSCSIParallelController, IOService ); ! 35: ! 36: #define round(x,y) (((int)(x) + (y) - 1) & ~((y)-1)) ! 37: ! 38: /* ! 39: * ! 40: * ! 41: */ ! 42: bool IOSCSIParallelController::start( IOService *forProvider ) ! 43: { ! 44: provider = forProvider; ! 45: ! 46: if ( provider->open( this ) != true ) ! 47: { ! 48: return false; ! 49: } ! 50: ! 51: if ( createWorkLoop() != true ) ! 52: { ! 53: return false; ! 54: } ! 55: ! 56: if ( configureController() == false ) ! 57: { ! 58: provider->close( this ); ! 59: return false; ! 60: } ! 61: ! 62: initQueues(); ! 63: ! 64: if ( scanSCSIBus() == false ) ! 65: { ! 66: provider->close( this ); ! 67: return false; ! 68: } ! 69: ! 70: return true; ! 71: } ! 72: ! 73: /* ! 74: * ! 75: * ! 76: * ! 77: */ ! 78: bool IOSCSIParallelController::scanSCSIBus() ! 79: { ! 80: SCSITargetLun targetLun; ! 81: UInt32 i; ! 82: ! 83: targetLun.lun = 0; ! 84: ! 85: for ( i=0; i < controllerInfo.maxTargetsSupported; i++ ) ! 86: { ! 87: targetLun.target = i; ! 88: probeTarget( targetLun ); ! 89: } ! 90: ! 91: return true; ! 92: } ! 93: ! 94: /* ! 95: * ! 96: * ! 97: * ! 98: */ ! 99: bool IOSCSIParallelController::probeTarget( SCSITargetLun targetLun ) ! 100: { ! 101: IOSCSIParallelDevice *device; ! 102: UInt32 i; ! 103: ! 104: if ( targetLun.target == controllerInfo.initiatorId ) ! 105: { ! 106: return false; ! 107: } ! 108: ! 109: if ( workLoopRequest( kWorkLoopInitTarget, *(UInt32 *)&targetLun ) == false ) ! 110: { ! 111: releaseTarget( targetLun ); ! 112: return false; ! 113: } ! 114: ! 115: for ( i=0; i < controllerInfo.maxLunsSupported; i++ ) ! 116: { ! 117: targetLun.lun = i; ! 118: ! 119: device = createDevice(); ! 120: if ( device == 0 ) ! 121: { ! 122: break; ! 123: } ! 124: ! 125: if ( device->init( this, targetLun ) == false ) ! 126: { ! 127: releaseDevice( device ); ! 128: break; ! 129: } ! 130: ! 131: if ( workLoopRequest( kWorkLoopInitDevice, (UInt32)device ) == false ) ! 132: { ! 133: releaseDevice( device ); ! 134: } ! 135: ! 136: // IOLog("Target %d Lun %d - created\n\r", targetLun.target, targetLun.lun ); ! 137: ! 138: if ( device->probeTargetLun() != kIOReturnSuccess ) ! 139: { ! 140: // IOLog("Target %d Lun %d - no response\n\r", targetLun.target, targetLun.lun ); ! 141: ! 142: releaseDevice( device ); ! 143: ! 144: if ( i == 0 ) break; ! 145: } ! 146: } ! 147: ! 148: if ( i == 0 ) ! 149: { ! 150: releaseTarget( targetLun ); ! 151: return false; ! 152: } ! 153: ! 154: queue_iterate( &targets[targetLun.target].deviceList, device, IOSCSIParallelDevice *, nextDevice ) ! 155: { ! 156: device->setupTarget(); ! 157: device->attach( this ); ! 158: device->registerService(); ! 159: } ! 160: ! 161: return true; ! 162: } ! 163: ! 164: /* ! 165: * ! 166: * ! 167: * ! 168: */ ! 169: bool IOSCSIParallelController::initTarget( SCSITargetLun targetLun ) ! 170: { ! 171: SCSITarget *target; ! 172: ! 173: target = &targets[targetLun.target]; ! 174: ! 175: assert ( target->clientSem == 0 ); ! 176: assert ( target->targetSem == 0 ); ! 177: ! 178: bzero( target, sizeof(SCSITarget) ); ! 179: ! 180: queue_init( &targets[targetLun.target].deviceList ); ! 181: ! 182: target->clientSem = IORWLockAlloc(); ! 183: target->targetSem = IORWLockAlloc(); ! 184: if( (target->targetSem == 0) || (target->clientSem == 0)) ! 185: { ! 186: return false; ! 187: } ! 188: target->commandLimitSave = target->commandLimit = 1; ! 189: ! 190: target->targetParmsCurrent.transferWidth = 1; ! 191: ! 192: if ( controllerInfo.targetPrivateDataSize != 0 ) ! 193: { ! 194: target->targetPrivateData = IOMallocContiguous( controllerInfo.targetPrivateDataSize, 16, 0 ); ! 195: if ( target->targetPrivateData == 0 ) ! 196: { ! 197: return false; ! 198: } ! 199: } ! 200: ! 201: if ( controllerInfo.tagAllocationMethod == kTagAllocationPerTarget ) ! 202: { ! 203: target->tagArray = (UInt32 *)IOMalloc( tagArraySize ); ! 204: if ( target->tagArray == 0 ) ! 205: { ! 206: return false; ! 207: } ! 208: bzero( target->tagArray, tagArraySize ); ! 209: } ! 210: ! 211: return true; ! 212: } ! 213: ! 214: /* ! 215: * ! 216: * ! 217: * ! 218: */ ! 219: void IOSCSIParallelController::releaseTarget( SCSITargetLun targetLun ) ! 220: { ! 221: SCSITarget *target; ! 222: ! 223: workLoopRequest( kWorkLoopReleaseTarget, *(UInt32 *)&targetLun ); ! 224: ! 225: target = &targets[targetLun.target]; ! 226: if ( target->tagArray != 0 ) ! 227: { ! 228: IOFree( target->tagArray, tagArraySize ); ! 229: target->tagArray = 0; ! 230: } ! 231: ! 232: if ( target->targetPrivateData != 0 ) ! 233: { ! 234: IOFreeContiguous( target->targetPrivateData, controllerInfo.targetPrivateDataSize ); ! 235: target->targetPrivateData = 0; ! 236: } ! 237: ! 238: if ( target->clientSem != 0 ) ! 239: { ! 240: IORWLockFree( target->clientSem ); ! 241: } ! 242: if ( target->targetSem != 0 ) ! 243: { ! 244: IORWLockFree( target->targetSem ); ! 245: } ! 246: } ! 247: ! 248: /* ! 249: * ! 250: * ! 251: * ! 252: */ ! 253: void IOSCSIParallelController::releaseDevice( IOSCSIParallelDevice *device ) ! 254: { ! 255: workLoopRequest( kWorkLoopReleaseDevice, (UInt32) device ); ! 256: ! 257: device->release(); ! 258: } ! 259: ! 260: /* ! 261: * ! 262: * ! 263: * ! 264: */ ! 265: bool IOSCSIParallelController::workLoopRequest( WorkLoopReqType type, UInt32 p1, UInt32 p2, UInt32 p3 ) ! 266: { ! 267: WorkLoopRequest workLoopReq; ! 268: ! 269: bzero( &workLoopReq, sizeof(WorkLoopRequest) ); ! 270: workLoopReq.type = type; ! 271: workLoopReq.sync = IOSyncer::create(); ! 272: ! 273: workLoopReqGate->runCommand( &workLoopReq, (void *)p1, (void *)p2, (void *)p3 ); ! 274: ! 275: workLoopReq.sync->wait(); ! 276: ! 277: return( workLoopReq.rc ); ! 278: } ! 279: ! 280: ! 281: /* ! 282: * ! 283: * ! 284: * ! 285: */ ! 286: void IOSCSIParallelController::workLoopProcessRequest( WorkLoopRequest *workLoopReq, void *p1, void *p2, void *p3 ) ! 287: { ! 288: bool rc = true; ! 289: IOSCSIParallelDevice *device; ! 290: SCSITargetLun targetLun; ! 291: ! 292: switch ( workLoopReq->type ) ! 293: { ! 294: case kWorkLoopInitTarget: ! 295: targetLun = *(SCSITargetLun *)&p1; ! 296: rc = initTarget( targetLun ); ! 297: if ( rc == false ) ! 298: { ! 299: break; ! 300: } ! 301: rc = allocateTarget( targetLun ); ! 302: break; ! 303: ! 304: case kWorkLoopReleaseTarget: ! 305: targetLun = *(SCSITargetLun *) &p1; ! 306: if ( queue_empty( &targets[targetLun.target].deviceList ) != true ) ! 307: { ! 308: IOLog("IOSCSIParallelController()::Target %d deleted with lun(s) active!\n\r", ! 309: targetLun.target ); ! 310: } ! 311: deallocateTarget( targetLun ); ! 312: break; ! 313: ! 314: case kWorkLoopInitDevice: ! 315: device = (IOSCSIParallelDevice *) p1; ! 316: addDevice( device ); ! 317: rc = allocateLun( device->targetLun ); ! 318: break; ! 319: ! 320: case kWorkLoopReleaseDevice: ! 321: device = (IOSCSIParallelDevice *) p1; ! 322: deleteDevice( device ); ! 323: deallocateLun( device->targetLun ); ! 324: break; ! 325: } ! 326: ! 327: workLoopReq->rc = rc; ! 328: workLoopReq->sync->signal(); ! 329: } ! 330: ! 331: /* ! 332: * ! 333: * ! 334: * ! 335: */ ! 336: void IOSCSIParallelController::addDevice( IOSCSIParallelDevice *forDevice ) ! 337: { ! 338: UInt32 targetID; ! 339: ! 340: targetID = forDevice->targetLun.target; ! 341: ! 342: forDevice->target = &targets[targetID]; ! 343: queue_enter( &targets[targetID].deviceList, forDevice, IOSCSIParallelDevice *, nextDevice ); ! 344: } ! 345: ! 346: /* ! 347: * ! 348: * ! 349: * ! 350: */ ! 351: void IOSCSIParallelController::deleteDevice( IOSCSIParallelDevice *forDevice ) ! 352: { ! 353: queue_head_t *deviceList; ! 354: IOSCSIParallelDevice *device; ! 355: UInt32 targetID; ! 356: ! 357: targetID = forDevice->targetLun.target; ! 358: ! 359: deviceList = &targets[targetID].deviceList; ! 360: ! 361: queue_iterate( deviceList, device, IOSCSIParallelDevice *, nextDevice ) ! 362: { ! 363: if ( device == forDevice ) ! 364: { ! 365: queue_remove( &targets[targetID].deviceList, device, IOSCSIParallelDevice *, nextDevice ); ! 366: break; ! 367: } ! 368: } ! 369: } ! 370: ! 371: /* ! 372: * ! 373: * ! 374: * ! 375: */ ! 376: bool IOSCSIParallelController::allocateTarget( SCSITargetLun targetLun ) ! 377: { ! 378: return true; ! 379: } ! 380: ! 381: /* ! 382: * ! 383: * ! 384: * ! 385: */ ! 386: void IOSCSIParallelController::deallocateTarget( SCSITargetLun targetLun ) ! 387: { ! 388: } ! 389: ! 390: /* ! 391: * ! 392: * ! 393: * ! 394: */ ! 395: bool IOSCSIParallelController::allocateLun( SCSITargetLun targetLun ) ! 396: { ! 397: return true; ! 398: } ! 399: ! 400: /* ! 401: * ! 402: * ! 403: * ! 404: */ ! 405: void IOSCSIParallelController::deallocateLun( SCSITargetLun targetLun ) ! 406: { ! 407: } ! 408: ! 409: ! 410: /* ! 411: * ! 412: * ! 413: * ! 414: */ ! 415: void *IOSCSIParallelController::getTargetData( SCSITargetLun targetLun ) ! 416: { ! 417: return targets[targetLun.target].targetPrivateData; ! 418: } ! 419: ! 420: /* ! 421: * ! 422: * ! 423: * ! 424: */ ! 425: void *IOSCSIParallelController::getLunData( SCSITargetLun targetLun ) ! 426: { ! 427: queue_head_t *deviceList; ! 428: IOSCSIParallelDevice *device; ! 429: ! 430: deviceList = &targets[targetLun.target].deviceList; ! 431: ! 432: queue_iterate( deviceList, device, IOSCSIParallelDevice *, nextDevice ) ! 433: { ! 434: if ( device->targetLun.lun == targetLun.lun ) ! 435: { ! 436: return device->devicePrivateData; ! 437: } ! 438: } ! 439: return 0; ! 440: } ! 441: ! 442: ! 443: ! 444: /* ! 445: * ! 446: * ! 447: * ! 448: */ ! 449: IOSCSIParallelDevice *IOSCSIParallelController::createDevice() ! 450: { ! 451: return new IOSCSIParallelDevice; ! 452: } ! 453: ! 454: ! 455: /* ! 456: * ! 457: * ! 458: * ! 459: */ ! 460: void IOSCSIParallelController::initQueues() ! 461: { ! 462: UInt32 i; ! 463: ! 464: for ( i=0; i < controllerInfo.maxTargetsSupported; i++ ) ! 465: { ! 466: queue_init( &targets[i].deviceList ); ! 467: } ! 468: ! 469: resetCmd = allocCommand( 0 ); ! 470: resetCmd->cmdType = kSCSICommandBusReset; ! 471: ! 472: timer( timerEvent ); ! 473: } ! 474: ! 475: /* ! 476: * ! 477: * ! 478: * ! 479: */ ! 480: void IOSCSIParallelController::reset() ! 481: { ! 482: IOSCSIParallelDevice *device; ! 483: UInt32 i; ! 484: ! 485: if ( busResetState != kStateIssue ) ! 486: { ! 487: return; ! 488: } ! 489: ! 490: busResetState = kStateActive; ! 491: ! 492: for (i=0; i < controllerInfo.maxTargetsSupported; i++ ) ! 493: { ! 494: queue_iterate( &targets[i].deviceList, device, IOSCSIParallelDevice *, nextDevice ) ! 495: { ! 496: if ( device->client != 0 ) ! 497: { ! 498: device->client->message( kSCSIClientMsgBusReset, device ); ! 499: } ! 500: } ! 501: } ! 502: ! 503: resetCommand( resetCmd ); ! 504: } ! 505: ! 506: /* ! 507: * ! 508: * ! 509: * ! 510: */ ! 511: bool IOSCSIParallelController::checkBusReset() ! 512: { ! 513: if ( busResetState == kStateIdle ) ! 514: { ! 515: return false; ! 516: } ! 517: if ( busResetState == kStateIssue ) ! 518: { ! 519: reset(); ! 520: } ! 521: return true; ! 522: } ! 523: ! 524: ! 525: /* ! 526: * ! 527: * ! 528: * ! 529: */ ! 530: void IOSCSIParallelController::resetOccurred() ! 531: { ! 532: UInt32 i; ! 533: IOSCSIParallelDevice *device; ! 534: SCSITarget *target; ! 535: SCSIClientMessage clientMsg; ! 536: ! 537: for (i=0; i < controllerInfo.maxTargetsSupported; i++ ) ! 538: { ! 539: target = &targets[i]; ! 540: ! 541: target->commandLimit = target->commandLimitSave; ! 542: target->reqSenseCount = 0; ! 543: target->reqSenseState = kStateIdle; ! 544: target->negotiateState = kStateIssue; ! 545: ! 546: target->targetParmsCurrent.transferPeriodpS = 0; ! 547: target->targetParmsCurrent.transferOffset = 0; ! 548: target->targetParmsCurrent.transferWidth = 1; ! 549: ! 550: noDisconnectCmd = 0; ! 551: ! 552: clientMsg = ( busResetState != kStateActive ) ? kSCSIClientMsgBusReset : kSCSIClientMsgNone; ! 553: ! 554: queue_iterate( &target->deviceList, device, IOSCSIParallelDevice *, nextDevice ) ! 555: { ! 556: device->resetOccurred( clientMsg ); ! 557: } ! 558: } ! 559: ! 560: resetTimer = (kSCSIResetIntervalmS / kSCSITimerIntervalmS + 1); ! 561: } ! 562: ! 563: ! 564: /* ! 565: * ! 566: * ! 567: */ ! 568: void IOSCSIParallelController::timer( IOTimerEventSource * /* timer */ ) ! 569: { ! 570: UInt32 i; ! 571: IOSCSIParallelDevice *device; ! 572: ! 573: ! 574: if ( disableTimer ) ! 575: { ! 576: if ( !--disableTimer ) ! 577: { ! 578: disableTimeoutOccurred(); ! 579: } ! 580: } ! 581: ! 582: if ( resetTimer ) ! 583: { ! 584: if ( !--resetTimer ) ! 585: { ! 586: for (i=0; i < controllerInfo.maxTargetsSupported; i++ ) ! 587: { ! 588: queue_iterate( &targets[i].deviceList, device, IOSCSIParallelDevice *, nextDevice ) ! 589: { ! 590: device->resetComplete(); ! 591: } ! 592: } ! 593: ! 594: } ! 595: } ! 596: else ! 597: { ! 598: for (i=0; i < controllerInfo.maxTargetsSupported; i++ ) ! 599: { ! 600: queue_iterate( &targets[i].deviceList, device, IOSCSIParallelDevice *, nextDevice ) ! 601: { ! 602: device->timer(); ! 603: } ! 604: } ! 605: } ! 606: ! 607: timerEvent->setTimeoutMS(kSCSITimerIntervalmS); ! 608: } ! 609: ! 610: ! 611: /* ! 612: * ! 613: * ! 614: * ! 615: */ ! 616: void IOSCSIParallelController::completeCommand( IOSCSIParallelCommand *scsiCmd ) ! 617: { ! 618: switch ( scsiCmd->cmdType ) ! 619: { ! 620: case kSCSICommandBusReset: ! 621: resetOccurred(); ! 622: busResetState = kStateIdle; ! 623: break; ! 624: default: ! 625: ; ! 626: } ! 627: } ! 628: ! 629: ! 630: /* ! 631: * ! 632: * ! 633: * ! 634: */ ! 635: bool IOSCSIParallelController::createWorkLoop() ! 636: { ! 637: workLoop = new IOWorkLoop; ! 638: if ( workLoop == NULL ) ! 639: { ! 640: return false; ! 641: } ! 642: ! 643: if ( workLoop->init() != true ) ! 644: { ! 645: return false; ! 646: } ! 647: ! 648: timerEvent = IOTimerEventSource::timerEventSource( this, (IOTimerEventSource::Action) &IOSCSIParallelController::timer ); ! 649: if ( timerEvent == NULL ) ! 650: { ! 651: return false; ! 652: } ! 653: ! 654: if ( workLoop->addEventSource( timerEvent ) != kIOReturnSuccess ) ! 655: { ! 656: return false; ! 657: } ! 658: ! 659: ! 660: dispatchEvent = IOInterruptEventSource::interruptEventSource( this, ! 661: (IOInterruptEventAction) &IOSCSIParallelController::dispatch, ! 662: 0 ); ! 663: if ( dispatchEvent == 0 ) ! 664: { ! 665: return false; ! 666: } ! 667: ! 668: if ( workLoop->addEventSource( dispatchEvent ) != kIOReturnSuccess ) ! 669: { ! 670: return false; ! 671: } ! 672: ! 673: workLoopReqGate = IOCommandGate::commandGate( this, (IOCommandGate::Action) &IOSCSIParallelController::workLoopProcessRequest ); ! 674: if ( workLoopReqGate == NULL ) ! 675: { ! 676: return false; ! 677: } ! 678: ! 679: if ( workLoop->addEventSource( workLoopReqGate ) != kIOReturnSuccess ) ! 680: { ! 681: return false; ! 682: } ! 683: ! 684: ! 685: return true; ! 686: } ! 687: ! 688: /* ! 689: * ! 690: * ! 691: * ! 692: */ ! 693: IOSCSIParallelCommand *IOSCSIParallelController::findCommandWithNexus( SCSITargetLun targetLun, UInt32 tagValue = (UInt32)-1 ) ! 694: { ! 695: IOSCSIParallelDevice *device; ! 696: ! 697: device = findDeviceWithTargetLun( targetLun ); ! 698: if ( device == 0 ) ! 699: { ! 700: return NULL; ! 701: } ! 702: ! 703: return device->findCommandWithNexus( tagValue ); ! 704: } ! 705: ! 706: ! 707: /* ! 708: * ! 709: * ! 710: * ! 711: */ ! 712: IOSCSIParallelDevice *IOSCSIParallelController::findDeviceWithTargetLun( SCSITargetLun targetLun ) ! 713: { ! 714: IOSCSIParallelDevice *device; ! 715: ! 716: if ( targetLun.target > controllerInfo.maxTargetsSupported || targetLun.lun > controllerInfo.maxLunsSupported ) ! 717: { ! 718: return 0; ! 719: } ! 720: ! 721: queue_iterate( &targets[targetLun.target].deviceList, device, IOSCSIParallelDevice *, nextDevice ) ! 722: { ! 723: if ( device->targetLun.lun == targetLun.lun ) ! 724: { ! 725: return device; ! 726: } ! 727: } ! 728: return 0; ! 729: } ! 730: ! 731: ! 732: /* ! 733: * ! 734: * ! 735: * ! 736: */ ! 737: bool IOSCSIParallelController::configureController() ! 738: { ! 739: UInt32 targetsSize; ! 740: ! 741: if ( configure( provider, &controllerInfo ) == false ) ! 742: { ! 743: return false; ! 744: } ! 745: ! 746: controllerInfo.commandPrivateDataSize = round( controllerInfo.commandPrivateDataSize, 16 ); ! 747: ! 748: if ( controllerInfo.maxCommandsPerController == 0 ) controllerInfo.maxCommandsPerController = (UInt32) -1; ! 749: if ( controllerInfo.maxCommandsPerTarget == 0 ) controllerInfo.maxCommandsPerTarget = (UInt32) -1; ! 750: if ( controllerInfo.maxCommandsPerLun == 0 ) controllerInfo.maxCommandsPerLun = (UInt32) -1; ! 751: ! 752: targetsSize = controllerInfo.maxTargetsSupported * sizeof(SCSITarget); ! 753: targets = (SCSITarget *)IOMalloc( targetsSize ); ! 754: bzero( targets, targetsSize ); ! 755: ! 756: commandLimit = commandLimitSave = controllerInfo.maxCommandsPerController; ! 757: ! 758: tagArraySize = (controllerInfo.maxTags / 32 + ((controllerInfo.maxTags % 32) ? 1 : 0)) * sizeof(UInt32); ! 759: ! 760: if ( controllerInfo.tagAllocationMethod == kTagAllocationPerController ) ! 761: { ! 762: tagArray = (UInt32 *)IOMalloc( tagArraySize ); ! 763: bzero( tagArray, tagArraySize ); ! 764: } ! 765: ! 766: return true; ! 767: } ! 768: ! 769: /* ! 770: * ! 771: * ! 772: * ! 773: */ ! 774: void IOSCSIParallelController::setCommandLimit( UInt32 newCommandLimit ) ! 775: { ! 776: if ( newCommandLimit == 0 ) controllerInfo.maxCommandsPerController = (UInt32) -1; ! 777: ! 778: commandLimit = commandLimitSave = controllerInfo.maxCommandsPerController; ! 779: } ! 780: ! 781: /* ! 782: * ! 783: * ! 784: * ! 785: */ ! 786: IOWorkLoop *IOSCSIParallelController::getWorkLoop() const ! 787: { ! 788: return workLoop; ! 789: } ! 790: ! 791: /* ! 792: * ! 793: * ! 794: * ! 795: */ ! 796: void IOSCSIParallelController::disableCommands( UInt32 disableTimeoutmS ) ! 797: { ! 798: commandDisable = true; ! 799: ! 800: disableTimer = ( disableTimeoutmS != 0 ) ? (disableTimeoutmS / kSCSITimerIntervalmS + 1) : 0; ! 801: } ! 802: ! 803: ! 804: /* ! 805: * ! 806: * ! 807: * ! 808: */ ! 809: void IOSCSIParallelController::disableCommands() ! 810: { ! 811: UInt32 disableTimeout; ! 812: ! 813: commandDisable = true; ! 814: ! 815: disableTimeout = kSCSIDisableTimeoutmS; ! 816: ! 817: if ( noDisconnectCmd != 0 ) ! 818: { ! 819: disableTimeout = noDisconnectCmd->getTimeout(); ! 820: if ( disableTimeout != 0 ) disableTimeout += kSCSIDisableTimeoutmS; ! 821: } ! 822: ! 823: disableTimer = ( disableTimeout != 0 ) ? (disableTimeout / kSCSITimerIntervalmS + 1) : 0; ! 824: } ! 825: ! 826: /* ! 827: * ! 828: * ! 829: * ! 830: */ ! 831: void IOSCSIParallelController::disableTimeoutOccurred() ! 832: { ! 833: busResetState = kStateIssue; ! 834: dispatchRequest(); ! 835: } ! 836: ! 837: ! 838: /* ! 839: * ! 840: * ! 841: * ! 842: */ ! 843: void IOSCSIParallelController::rescheduleCommand( IOSCSICommand *forSCSICmd ) ! 844: { ! 845: IOSCSIParallelCommand *scsiCmd = (IOSCSIParallelCommand *)forSCSICmd; ! 846: IOSCSIParallelDevice *device = (IOSCSIParallelDevice *) scsiCmd->getDevice(kIOSCSIDevice); ! 847: ! 848: device->rescheduleCommand( scsiCmd ); ! 849: } ! 850: ! 851: /* ! 852: * ! 853: * ! 854: * ! 855: */ ! 856: void IOSCSIParallelController::enableCommands() ! 857: { ! 858: commandDisable = false; ! 859: ! 860: disableTimer = 0; ! 861: ! 862: dispatchRequest(); ! 863: } ! 864: ! 865: /* ! 866: * ! 867: * ! 868: * ! 869: */ ! 870: void IOSCSIParallelController::dispatchRequest() ! 871: { ! 872: dispatchEvent->interruptOccurred(0, 0, 0); ! 873: } ! 874: ! 875: ! 876: /* ! 877: * ! 878: * ! 879: * ! 880: */ ! 881: void IOSCSIParallelController::dispatch() ! 882: { ! 883: SCSITarget *target; ! 884: IOSCSIParallelDevice *device; ! 885: UInt32 dispatchAction; ! 886: UInt32 lunsActive = 0; ! 887: UInt32 i; ! 888: ! 889: if ( checkBusReset() == true ) ! 890: { ! 891: goto dispatch_Exit; ! 892: } ! 893: ! 894: for ( i = 0; i < controllerInfo.maxTargetsSupported; i++ ) ! 895: { ! 896: target = &targets[i]; ! 897: ! 898: if ( target->state == kStateActive ) ! 899: { ! 900: lunsActive = 0; ! 901: ! 902: queue_iterate( &target->deviceList, device, IOSCSIParallelDevice *, nextDevice ) ! 903: { ! 904: if ( device->dispatch( &dispatchAction ) == true ) ! 905: { ! 906: lunsActive++; ! 907: } ! 908: ! 909: switch ( dispatchAction ) ! 910: { ! 911: case kDispatchNextLun: ! 912: ; ! 913: case kDispatchNextTarget: ! 914: break; ! 915: case kDispatchStop: ! 916: goto dispatch_Exit; ! 917: } ! 918: } ! 919: if ( lunsActive == 0 ) ! 920: { ! 921: target->state = kStateIdle; ! 922: } ! 923: } ! 924: } ! 925: ! 926: dispatch_Exit: ! 927: ; ! 928: } ! 929: ! 930: /* ! 931: * ! 932: * ! 933: * ! 934: */ ! 935: IOSCSIParallelCommand *IOSCSIParallelController::allocCommand(UInt32 clientDataSize ) ! 936: { ! 937: IOSCSIParallelCommand *cmd; ! 938: UInt32 size; ! 939: ! 940: size = controllerInfo.commandPrivateDataSize + round(clientDataSize, 16); ! 941: ! 942: cmd = new IOSCSIParallelCommand; ! 943: if ( !cmd ) ! 944: { ! 945: return 0; ! 946: } ! 947: cmd->init(); ! 948: ! 949: if ( size ) ! 950: { ! 951: cmd->dataArea = (void *)IOMallocContiguous( (vm_size_t)size, 16, 0 ); ! 952: if ( !cmd->dataArea ) ! 953: { ! 954: cmd->release(); ! 955: return 0; ! 956: } ! 957: ! 958: bzero( cmd->dataArea, size ); ! 959: ! 960: cmd->dataSize = size; ! 961: ! 962: if ( controllerInfo.commandPrivateDataSize ) ! 963: { ! 964: cmd->commandPrivateData = cmd->dataArea; ! 965: } ! 966: if ( clientDataSize ) ! 967: { ! 968: cmd->clientData = (void *)((UInt8 *)cmd->dataArea + controllerInfo.commandPrivateDataSize); ! 969: } ! 970: } ! 971: ! 972: cmd->controller = this; ! 973: ! 974: return cmd; ! 975: } ! 976: ! 977: /* ! 978: * ! 979: * ! 980: * ! 981: */ ! 982: void IOSCSIParallelController::free() ! 983: { ! 984: UInt32 targetsSize; ! 985: UInt32 i; ! 986: ! 987: if ( timerEvent != 0 ) timerEvent->release(); ! 988: ! 989: if ( workLoopReqGate != 0 ) workLoopReqGate->release(); ! 990: ! 991: if ( dispatchEvent != 0 ) dispatchEvent->release(); ! 992: ! 993: if ( resetCmd != 0 ) resetCmd->release(); ! 994: ! 995: if ( workLoop != 0 ) workLoop->release(); ! 996: ! 997: if ( targets != 0 ) ! 998: { ! 999: for ( i=0; i < controllerInfo.maxTargetsSupported; i++ ) ! 1000: { ! 1001: if ( targets[i].targetPrivateData != 0 ) ! 1002: { ! 1003: IOFreeContiguous( targets[i].targetPrivateData, controllerInfo.targetPrivateDataSize ); ! 1004: } ! 1005: } ! 1006: ! 1007: targetsSize = controllerInfo.maxTargetsSupported * sizeof(SCSITarget); ! 1008: IOFree( targets, targetsSize ); ! 1009: } ! 1010: ! 1011: if ( tagArray != 0 ) IOFree( tagArray, tagArraySize ); ! 1012: ! 1013: super::free(); ! 1014: } ! 1015: ! 1016: /* ! 1017: * ! 1018: * ! 1019: * ! 1020: */ ! 1021: void IOSCSIParallelCommand::free() ! 1022: { ! 1023: if ( dataArea ) ! 1024: { ! 1025: IOFreeContiguous( dataArea, dataSize ); ! 1026: } ! 1027: ! 1028: OSObject::free(); ! 1029: } ! 1030:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.