/* * Copyright (c) 1998-2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This 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 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(IOFWWriteQuadCommand, IOFWAsyncCommand) OSMetaClassDefineReservedUnused(IOFWWriteQuadCommand, 0); OSMetaClassDefineReservedUnused(IOFWWriteQuadCommand, 1); #pragma mark - // initWithController // // bool IOFWWriteQuadCommand::initWithController(IOFireWireController *control) { bool success = true; fWrite = true; success = IOFWAsyncCommand::initWithController(control); // create member variables if( success ) { success = createMemberVariables(); } if( success ) { success = createMemoryDescriptor(); } return success; } // initAll // // bool IOFWWriteQuadCommand::initAll( IOFireWireNub * device, FWAddress devAddress, UInt32 * quads, int numQuads, FWDeviceCallback completion, void * refcon, bool failOnReset ) { bool result = true; if( numQuads > kMaxWriteQuads ) { result = false; } if( result ) { fWrite = true; result = IOFWAsyncCommand::initAll( device, devAddress, NULL, completion, refcon, failOnReset); } // create member variables if( result ) { result = createMemberVariables(); } if( result ) { ((MemberVariables*)fMembers->fSubclassMembers)->fDeferredNotify = false; setQuads( quads, numQuads ); } if( result ) { result = createMemoryDescriptor(); } return result; } // initAll // // bool IOFWWriteQuadCommand::initAll( IOFireWireController * control, UInt32 generation, FWAddress devAddress, UInt32 * quads, int numQuads, FWDeviceCallback completion, void * refcon ) { bool result = true; if( numQuads > kMaxWriteQuads ) { result = false; } if( result ) { fWrite = true; result = IOFWAsyncCommand::initAll( control, generation, devAddress, NULL, completion, refcon ); } // create member variables if( result ) { result = createMemberVariables(); } if( result ) { ((MemberVariables*)fMembers->fSubclassMembers)->fDeferredNotify = false; setQuads( quads, numQuads ); } if( result ) { result = createMemoryDescriptor(); } return result; } // createMemberVariables // // bool IOFWWriteQuadCommand::createMemberVariables( void ) { bool success = true; if( fMembers == NULL ) { success = IOFWAsyncCommand::createMemberVariables(); } if( fMembers && fMembers->fSubclassMembers == NULL ) { if( success ) { fMembers->fSubclassMembers = IOMalloc( sizeof(MemberVariables) ); if( fMembers->fSubclassMembers == NULL ) success = false; } // zero member variables if( success ) { bzero( fMembers->fSubclassMembers, sizeof(MemberVariables) ); } // clean up on failure if( !success ) { destroyMemberVariables(); } } return success; } // destroyMemberVariables // // void IOFWWriteQuadCommand::destroyMemberVariables( void ) { if( fMembers->fSubclassMembers != NULL ) { // free member variables IOFree( fMembers->fSubclassMembers, sizeof(MemberVariables) ); fMembers->fSubclassMembers = NULL; } } // createMemoryDescriptor // // bool IOFWWriteQuadCommand::createMemoryDescriptor( void ) { bool result = true; bool prepared = false; if( result ) { ((MemberVariables*)fMembers->fSubclassMembers)->fMemory = IOMemoryDescriptor::withAddress( fQuads, kMaxWriteQuads * sizeof(UInt32), kIODirectionOutIn ); if( ((MemberVariables*)fMembers->fSubclassMembers)->fMemory == NULL ) result = false; } if( result ) { IOReturn status = ((MemberVariables*)fMembers->fSubclassMembers)->fMemory->prepare( kIODirectionOutIn ); if( status == kIOReturnSuccess ) { prepared = true; } else { result = false; } } if( !result ) { if( ((MemberVariables*)fMembers->fSubclassMembers)->fMemory != NULL ) { if( prepared ) { ((MemberVariables*)fMembers->fSubclassMembers)->fMemory->complete( kIODirectionOutIn ); } ((MemberVariables*)fMembers->fSubclassMembers)->fMemory->release(); ((MemberVariables*)fMembers->fSubclassMembers)->fMemory = NULL; } } return result; } // destroyMemoryDescriptor // // void IOFWWriteQuadCommand::destroyMemoryDescriptor() { if( ((MemberVariables*)fMembers->fSubclassMembers)->fMemory != NULL ) { ((MemberVariables*)fMembers->fSubclassMembers)->fMemory->complete( kIODirectionOutIn ); ((MemberVariables*)fMembers->fSubclassMembers)->fMemory->release(); ((MemberVariables*)fMembers->fSubclassMembers)->fMemory = NULL; } } // free // // void IOFWWriteQuadCommand::free() { destroyMemoryDescriptor(); destroyMemberVariables(); IOFWAsyncCommand::free(); } // reinit // // IOReturn IOFWWriteQuadCommand::reinit( FWAddress devAddress, UInt32 * quads, int numQuads, FWDeviceCallback completion, void * refcon, bool failOnReset ) { IOReturn status = kIOReturnSuccess; if(numQuads > kMaxWriteQuads) { status = kIOReturnUnsupported; } if( status == kIOReturnSuccess ) { status = IOFWAsyncCommand::reinit( devAddress, NULL, completion, refcon, failOnReset ); } if( status == kIOReturnSuccess ) { setQuads( quads, numQuads ); } return status; } // reinit // // IOReturn IOFWWriteQuadCommand::reinit( UInt32 generation, FWAddress devAddress, UInt32 * quads, int numQuads, FWDeviceCallback completion, void * refcon ) { IOReturn status = kIOReturnSuccess; if( numQuads > kMaxWriteQuads ) { status = kIOReturnUnsupported; } if( status == kIOReturnSuccess ) { status = IOFWAsyncCommand::reinit( generation, devAddress, NULL, completion, refcon ); } if( status == kIOReturnSuccess ) { setQuads( quads, numQuads ); } return status; } // setQuads // // void IOFWWriteQuadCommand::setQuads( UInt32 * quads, int numQuads ) { int i; fSize = 4 * numQuads; for( i = 0; i < numQuads; i++ ) { fQuads[i] = *quads++; } fQPtr = fQuads; } // execute // // IOReturn IOFWWriteQuadCommand::execute() { IOReturn result; // IOLog( "IOFWWriteQuadCommand::execute\n" ); fStatus = kIOReturnBusy; if( !fFailOnReset ) { // Update nodeID and generation fDevice->getNodeIDGeneration( fGeneration, fNodeID ); fSpeed = fControl->FWSpeed( fNodeID ); if( fMembers->fMaxSpeed < fSpeed ) { fSpeed = fMembers->fMaxSpeed; } } fPackSize = fSize; if( fPackSize > fMaxPack ) { fPackSize = fMaxPack; } int maxPack = (1 << fControl->maxPackLog(fWrite, fNodeID)); if( maxPack < fPackSize ) { fPackSize = maxPack; } // 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 ) { IOFWWriteFlags flags = kIOFWWriteFlagsNone; if( fMembers && fMembers->fSubclassMembers && ((MemberVariables*)fMembers->fSubclassMembers)->fDeferredNotify ) { flags = kIOFWWriteFlagsDeferredNotify; } // IOLog( "IOFWWriteQuadCommand::execute - fControl->asyncWrite()\n" ); result = fControl->asyncWrite( fGeneration, fNodeID, fAddressHi, fAddressLo, fSpeed, fTrans->fTCode, ((MemberVariables*)fMembers->fSubclassMembers)->fMemory, 0, fPackSize, this, flags ); } else { // IOLog("IOFWReadCommand::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(); } return status; } // gotPacket // // void IOFWWriteQuadCommand::gotPacket( int rcode, const void* data, int size ) { setResponseCode( rcode ); if( rcode != kFWResponseComplete ) { //kprintf("Received rcode %d for command 0x%x\n", rcode, this); complete( kIOFireWireResponseBase+rcode ); return; } else { fQPtr += fPackSize / 4; fSize -= fPackSize; fBytesTransferred += fPackSize ; } if( fSize > 0 ) { fAddressLo += fPackSize; updateTimer(); fCurRetries = fMaxRetries; fControl->freeTrans( fTrans ); // Free old tcode execute(); } else { complete( kIOReturnSuccess ); } }