/* * Copyright (c) 1998-2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ //#define IOASSERT 1 // Set to 1 to activate assert() // public #include #include #include #include // system #include #include #include #include OSDefineMetaClassAndStructors(IOFWCompareAndSwapCommand, IOFWAsyncCommand) OSMetaClassDefineReservedUnused(IOFWCompareAndSwapCommand, 0); OSMetaClassDefineReservedUnused(IOFWCompareAndSwapCommand, 1); OSMetaClassDefineReservedUnused(IOFWCompareAndSwapCommand, 2); OSMetaClassDefineReservedUnused(IOFWCompareAndSwapCommand, 3); #pragma mark - // initWithController // // bool IOFWCompareAndSwapCommand::initWithController(IOFireWireController *control) { bool result = true; result = IOFWAsyncCommand::initWithController(control); // create member variables if( result ) { result = createMemberVariables(); } if( result ) { result = createMemoryDescriptor(); } return result; } // initAll // // bool IOFWCompareAndSwapCommand::initAll( IOFireWireNub * device, FWAddress devAddress, const UInt32 * cmpVal, const UInt32 * newVal, int size, FWDeviceCallback completion, void * refcon, bool failOnReset ) { bool result = true; result = IOFWAsyncCommand::initAll( device, devAddress, NULL, completion, refcon, failOnReset ); // create member variables if( result ) { result = createMemberVariables(); } if( result ) { setInputVals( cmpVal, newVal, size ); } if( result ) { result = createMemoryDescriptor(); } return result; } // initAll // // bool IOFWCompareAndSwapCommand::initAll( IOFireWireController * control, UInt32 generation, FWAddress devAddress, const UInt32 * cmpVal, const UInt32 * newVal, int size, FWDeviceCallback completion, void * refcon ) { bool result = true; result = IOFWAsyncCommand::initAll( control, generation, devAddress, NULL, completion, refcon ); // create member variables if( result ) { result = createMemberVariables(); } if( result ) { setInputVals( cmpVal, newVal, size ); } if( result ) { result = createMemoryDescriptor(); } return result; } // createMemberVariables // // bool IOFWCompareAndSwapCommand::createMemberVariables( void ) { bool success = true; if( fMembers == NULL ) { // create member variables if( success ) { fMembers = (MemberVariables*)IOMalloc( sizeof(MemberVariables) ); if( fMembers == NULL ) success = false; } // zero member variables if( success ) { bzero( fMembers, sizeof(MemberVariables) ); } // clean up on failure if( !success ) { destroyMemberVariables(); } } return success; } // destroyMemberVariables // // void IOFWCompareAndSwapCommand::destroyMemberVariables( void ) { if( fMembers != NULL ) { IOFree( fMembers, sizeof(MemberVariables) ); fMembers = NULL; } } // createMemoryDescriptor // // bool IOFWCompareAndSwapCommand::createMemoryDescriptor() { bool result = true; bool prepared = false; if( result ) { fMembers->fMemory = IOMemoryDescriptor::withAddress( fInputVals, 4 * sizeof(UInt32), kIODirectionOutIn ); if( fMembers->fMemory == NULL ) result = false; } if( result ) { IOReturn status = fMembers->fMemory->prepare( kIODirectionOutIn ); if( status == kIOReturnSuccess ) { prepared = true; } else { result = false; } } if( !result ) { if( fMembers->fMemory != NULL ) { if( prepared ) { fMembers->fMemory->complete( kIODirectionOutIn ); } fMembers->fMemory->release(); fMembers->fMemory = NULL; } } return result; } // destroyMemoryDescriptor // // void IOFWCompareAndSwapCommand::destroyMemoryDescriptor() { if( fMembers->fMemory != NULL ) { fMembers->fMemory->complete( kIODirectionOutIn ); fMembers->fMemory->release(); fMembers->fMemory = NULL; } } // free // // void IOFWCompareAndSwapCommand::free() { destroyMemoryDescriptor(); destroyMemberVariables(); IOFWAsyncCommand::free(); } // reinit // // IOReturn IOFWCompareAndSwapCommand::reinit( FWAddress devAddress, const UInt32 * cmpVal, const UInt32 * newVal, int size, FWDeviceCallback completion, void * refcon, bool failOnReset ) { IOReturn status = kIOReturnSuccess; status = IOFWAsyncCommand::reinit( devAddress, NULL, completion, refcon, failOnReset ); if( status == kIOReturnSuccess ) { setInputVals( cmpVal, newVal, size ); } return status; } // reinit // // IOReturn IOFWCompareAndSwapCommand::reinit( UInt32 generation, FWAddress devAddress, const UInt32 * cmpVal, const UInt32 * newVal, int size, FWDeviceCallback completion, void * refcon ) { IOReturn status = kIOReturnSuccess; status = IOFWAsyncCommand::reinit( generation, devAddress, NULL, completion, refcon ); if( status == kIOReturnSuccess ) { setInputVals( cmpVal, newVal, size ); } return status; } // setInputVals // // void IOFWCompareAndSwapCommand::setInputVals( const UInt32 * cmpVal, const UInt32 * newVal, int size ) { int i; for( i = 0; i < size; i++ ) { fInputVals[i] = cmpVal[i]; fInputVals[size+i] = newVal[i]; } fSize = 8 * size; } // execute // // IOReturn IOFWCompareAndSwapCommand::execute() { IOReturn result; fStatus = kIOReturnBusy; if( !fFailOnReset ) { // Update nodeID and generation fDevice->getNodeIDGeneration(fGeneration, fNodeID); fSpeed = fControl->FWSpeed( fNodeID ); if( IOFWAsyncCommand::fMembers->fMaxSpeed < fSpeed ) { fSpeed = IOFWAsyncCommand::fMembers->fMaxSpeed; } } // Do this when we're in execute, not before, // so that Reset handling knows which commands are waiting a response. fTrans = fControl->allocTrans(this); if( fTrans ) { result = fControl->asyncLock( fGeneration, fNodeID, fAddressHi, fAddressLo, fSpeed, fTrans->fTCode, kFWExtendedTCodeCompareSwap, fMembers->fMemory, 0, fSize, this ); } else { // IOLog("IOFWCompareAndSwapCommand::execute: Out of tLabels?\n"); result = kIOFireWireOutOfTLabels; } // complete could release us so protect fStatus with retain and release IOReturn status = fStatus; if( result != kIOReturnSuccess ) { retain(); complete(result); status = fStatus; release(); } else { fBytesTransferred = fSize ; } return status; } // locked // // bool IOFWCompareAndSwapCommand::locked( UInt32 * oldVal ) { int i; bool result = true; for( i = 0; i < fSize / 8; i++ ) { result = result && (fInputVals[i] == fOldVal[i]); oldVal[i] = fOldVal[i]; } return result; } // gotPacket // // void IOFWCompareAndSwapCommand::gotPacket( int rcode, const void* data, int size ) { setResponseCode( rcode ); int i; if( rcode != kFWResponseComplete ) { //IOLog("Received rcode %d for lock command %p, nodeID %x\n", rcode, this, fNodeID); complete( kIOFireWireResponseBase + rcode ); return; } for( i = 0; i < size / 4; i++ ) { fOldVal[i] = ((UInt32 *)data)[i]; } complete( kIOReturnSuccess ); }