1/* 2 * Copyright (c) 1998-2002 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//#define IOASSERT 1 // Set to 1 to activate assert() 24 25// public 26#include <IOKit/firewire/IOFWCommand.h> 27#include <IOKit/firewire/IOFireWireController.h> 28#include <IOKit/firewire/IOFireWireNub.h> 29#include <IOKit/firewire/IOLocalConfigDirectory.h> 30 31// system 32#include <IOKit/assert.h> 33#include <IOKit/IOWorkLoop.h> 34#include <IOKit/IOCommand.h> 35 36#pragma mark - 37 38OSDefineMetaClassAndStructors(IOFWAsyncStreamCommand, IOFWCommand) 39OSMetaClassDefineReservedUnused(IOFWAsyncStreamCommand, 0); 40OSMetaClassDefineReservedUnused(IOFWAsyncStreamCommand, 1); 41 42#pragma mark - 43 44// initAll 45// 46// 47 48bool IOFWAsyncStreamCommand::initAll( 49 IOFireWireController * control, 50 UInt32 generation, 51 UInt32 channel, 52 UInt32 sync, 53 UInt32 tag, 54 IOMemoryDescriptor * hostMem, 55 UInt32 size, 56 int speed, 57 FWAsyncStreamCallback completion, 58 void * refcon) 59{ 60 return initAll( control, generation, channel, sync, tag, hostMem, size, speed, completion, refcon, false); 61} 62 63bool IOFWAsyncStreamCommand::initAll( 64 IOFireWireController * control, 65 UInt32 generation, 66 UInt32 channel, 67 UInt32 sync, 68 UInt32 tag, 69 IOMemoryDescriptor * hostMem, 70 UInt32 size, 71 int speed, 72 FWAsyncStreamCallback completion, 73 void * refcon, 74 bool failOnReset) 75{ 76 bool success = true; 77 78 success = IOFWCommand::initWithController(control); 79 80 if( success ) 81 { 82 fMaxRetries = kFWCmdDefaultRetries; 83 fCurRetries = fMaxRetries; 84 fMemDesc = hostMem; 85 fComplete = completion; 86 fSync = completion == NULL; 87 fRefCon = refcon; 88 fTimeout = 1000*125; // 1000 frames, 125mSec 89 if(hostMem) 90 fSize = hostMem->getLength(); 91 92 fGeneration = generation; 93 fChannel = channel; 94 fSyncBits = sync; 95 fTag = tag; 96 fSpeed = speed; 97 fSize = size; 98 fFailOnReset = failOnReset; 99 } 100 101 return success; 102} 103 104 105// free 106// 107// 108 109void IOFWAsyncStreamCommand::free() 110{ 111 IOFWCommand::free(); 112} 113 114 115// reinit 116// 117// 118 119IOReturn IOFWAsyncStreamCommand::reinit( 120 UInt32 generation, 121 UInt32 channel, 122 UInt32 sync, 123 UInt32 tag, 124 IOMemoryDescriptor * hostMem, 125 UInt32 size, 126 int speed, 127 FWAsyncStreamCallback completion, 128 void * refcon) 129{ 130 if(fStatus == kIOReturnBusy || fStatus == kIOFireWirePending) 131 return fStatus; 132 133 fComplete = completion; 134 fRefCon = refcon; 135 fMemDesc=hostMem; 136 if(fMemDesc) 137 fSize=fMemDesc->getLength(); 138 fSync = completion == NULL; 139 fCurRetries = fMaxRetries; 140 141 fGeneration = generation; 142 fChannel = channel; 143 fSyncBits = sync; 144 fTag = tag; 145 fSpeed = speed; 146 fSize = size; 147 return fStatus = kIOReturnSuccess; 148} 149 150IOReturn IOFWAsyncStreamCommand::reinit( 151 UInt32 generation, 152 UInt32 channel, 153 UInt32 sync, 154 UInt32 tag, 155 IOMemoryDescriptor * hostMem, 156 UInt32 size, 157 int speed, 158 FWAsyncStreamCallback completion, 159 void * refcon, 160 bool failOnReset) 161{ 162 if(fStatus == kIOReturnBusy || fStatus == kIOFireWirePending) 163 return fStatus; 164 165 fFailOnReset = failOnReset; 166 167 return reinit( generation, channel, sync, tag, hostMem, size, speed, completion, refcon ); 168} 169 170// complete 171// 172// 173 174IOReturn IOFWAsyncStreamCommand::complete(IOReturn status) 175{ 176 // latch the most recent completion status 177 IOFWCommand::fMembers->fCompletionStatus = status; 178 179 if( fStatus == kIOFireWireCompleting ) 180 { 181 // prevent double completion 182 return kIOReturnSuccess; 183 } 184 185 // tell the fwim we're completing 186 // this could cause this routine to be reentered, hence the protection above 187 188 fStatus = kIOFireWireCompleting; 189 fControl->handleAsyncCompletion( this, status ); 190 191 // we're back - actually complete the command 192 IOReturn completion_status = IOFWCommand::fMembers->fCompletionStatus; 193 194 removeFromQ(); // Remove from current queue 195 196 // If we're in the middle of processing a bus reset and 197 // the command should be retried after a bus reset, put it on the 198 // 'after reset queue' 199 // If we aren't still scanning the bus, and we're supposed to retry after bus resets, turn it into device offline 200 if( (completion_status == kIOFireWireBusReset) && !fFailOnReset) 201 { 202 if(fControl->scanningBus()) 203 { 204 setHead(fControl->getAfterResetHandledQ()); 205 return fStatus = kIOFireWirePending; // On a queue waiting to execute 206 } 207 } 208 fStatus = completion_status; 209 if(fSync) 210 fSyncWakeup->signal(completion_status); 211 else if(fComplete) 212 (*fComplete)(fRefCon, completion_status, fControl, this); 213 214 return completion_status; 215} 216 217// gotAck 218// 219// 220 221void IOFWAsyncStreamCommand::gotAck(int ackCode) 222{ 223 if (ackCode == kFWAckComplete ) 224 complete( kIOReturnSuccess ); 225 else 226 complete( kIOReturnTimeout ); 227} 228 229// execute 230// 231// 232 233IOReturn IOFWAsyncStreamCommand::execute() 234{ 235 IOReturn result = kIOReturnBadArgument; 236 237 fStatus = kIOReturnBusy; 238 239 if( !fFailOnReset ) 240 { 241 // Update generation 242 fGeneration = fControl->getGeneration(); 243 } 244 245 fSpeed = min((int)fControl->getBroadcastSpeed(), fSpeed) ; 246 247 if( fSize < ( 1 << 9+fControl->getBroadcastSpeed() ) and ( fChannel >= 0 and fChannel < 64) ) 248 { 249 result = fControl->asyncStreamWrite(fGeneration, 250 fSpeed, fTag, fSyncBits, fChannel,fMemDesc,0,fSize, this); 251 } 252 253 // complete could release us so protect fStatus with retain and release 254 IOReturn status = fStatus; 255 if(result != kIOReturnSuccess) 256 { 257 retain(); 258 complete(result); 259 status = fStatus; 260 release(); 261 } 262 return status; 263} 264