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 36OSDefineMetaClassAndStructors(IOFWWriteCommand, IOFWAsyncCommand) 37OSMetaClassDefineReservedUnused(IOFWWriteCommand, 0); 38OSMetaClassDefineReservedUnused(IOFWWriteCommand, 1); 39 40#pragma mark - 41 42// initWithController 43// 44// 45 46bool IOFWWriteCommand::initWithController(IOFireWireController *control) 47{ 48 bool success = true; 49 50 fWrite = true; 51 52 success = IOFWAsyncCommand::initWithController(control); 53 54 // create member variables 55 56 if( success ) 57 { 58 success = createMemberVariables(); 59 } 60 61 return success; 62} 63 64// initAll 65// 66// 67 68bool IOFWWriteCommand::initAll( IOFireWireNub * device, 69 FWAddress devAddress, 70 IOMemoryDescriptor * hostMem, 71 FWDeviceCallback completion, 72 void * refcon, 73 bool failOnReset ) 74{ 75 bool success = true; 76 77 fWrite = true; 78 79 success = IOFWAsyncCommand::initAll( device, devAddress, hostMem, 80 completion, refcon, failOnReset); 81 82 // create member variables 83 84 if( success ) 85 { 86 success = createMemberVariables(); 87 } 88 89 return success; 90} 91 92// initAll 93// 94// 95 96bool IOFWWriteCommand::initAll( IOFireWireController * control, 97 UInt32 generation, 98 FWAddress devAddress, 99 IOMemoryDescriptor * hostMem, 100 FWDeviceCallback completion, 101 void * refcon ) 102{ 103 bool success = true; 104 105 fWrite = true; 106 107 success = IOFWAsyncCommand::initAll(control, generation, devAddress, 108 hostMem, completion, refcon); 109 110 // create member variables 111 112 if( success ) 113 { 114 success = createMemberVariables(); 115 } 116 117 return success; 118} 119 120// createMemberVariables 121// 122// 123 124bool IOFWWriteCommand::createMemberVariables( void ) 125{ 126 bool success = true; 127 128 if( fMembers == NULL ) 129 { 130 success = IOFWAsyncCommand::createMemberVariables(); 131 } 132 133 if( fMembers ) 134 { 135 if( success ) 136 { 137 fMembers->fSubclassMembers = IOMalloc( sizeof(MemberVariables) ); 138 if( fMembers->fSubclassMembers == NULL ) 139 success = false; 140 } 141 142 // zero member variables 143 144 if( success ) 145 { 146 bzero( fMembers->fSubclassMembers, sizeof(MemberVariables) ); 147 } 148 149 // clean up on failure 150 151 if( !success ) 152 { 153 destroyMemberVariables(); 154 } 155 } 156 157 return success; 158} 159 160// destroyMemberVariables 161// 162// 163 164void IOFWWriteCommand::destroyMemberVariables( void ) 165{ 166 if( fMembers->fSubclassMembers != NULL ) 167 { 168 // free member variables 169 170 IOFree( fMembers->fSubclassMembers, sizeof(MemberVariables) ); 171 fMembers->fSubclassMembers = NULL; 172 } 173} 174 175// free 176// 177// 178 179void IOFWWriteCommand::free() 180{ 181 destroyMemberVariables(); 182 183 IOFWAsyncCommand::free(); 184} 185 186// reinit 187// 188// 189 190IOReturn IOFWWriteCommand::reinit( FWAddress devAddress, 191 IOMemoryDescriptor * hostMem, 192 FWDeviceCallback completion, 193 void * refcon, 194 bool failOnReset ) 195{ 196 return IOFWAsyncCommand::reinit( devAddress, 197 hostMem, 198 completion, 199 refcon, 200 failOnReset ); 201} 202 203// reinit 204// 205// 206 207IOReturn IOFWWriteCommand::reinit( UInt32 generation, 208 FWAddress devAddress, 209 IOMemoryDescriptor * hostMem, 210 FWDeviceCallback completion, 211 void * refcon ) 212{ 213 return IOFWAsyncCommand::reinit( generation, 214 devAddress, 215 hostMem, 216 completion, 217 refcon ); 218} 219 220// execute 221// 222// 223 224IOReturn IOFWWriteCommand::execute() 225{ 226 IOReturn result; 227 fStatus = kIOReturnBusy; 228 229 if( !fFailOnReset ) 230 { 231 // Update nodeID and generation 232 fDevice->getNodeIDGeneration( fGeneration, fNodeID ); 233 fSpeed = fControl->FWSpeed( fNodeID ); 234 if( fMembers->fMaxSpeed < fSpeed ) 235 { 236 fSpeed = fMembers->fMaxSpeed; 237 } 238 } 239 240 fPackSize = fSize; 241 if( fPackSize > fMaxPack ) 242 { 243 fPackSize = fMaxPack; 244 } 245 246 int maxPack = (1 << fControl->maxPackLog(fWrite, fNodeID)); 247 if( maxPack < fPackSize ) 248 { 249 fPackSize = maxPack; 250 } 251 252 // Do this when we're in execute, not before, 253 // so that Reset handling knows which commands are waiting a response. 254 fTrans = fControl->allocTrans( this ); 255 if( fTrans ) 256 { 257 UInt32 flags = kIOFWWriteFlagsNone; 258 259 if( fMembers && fMembers->fSubclassMembers ) 260 { 261 if( ((MemberVariables*)fMembers->fSubclassMembers)->fDeferredNotify ) 262 { 263 flags |= kIOFWWriteFlagsDeferredNotify; 264 } 265 266 if( ((MemberVariables*)fMembers->fSubclassMembers)->fFastRetryOnBusy ) 267 { 268 flags |= kIOFWWriteFastRetryOnBusy; 269 } 270 271 if( ((IOFWAsyncCommand::MemberVariables*)fMembers)->fForceBlockRequests ) 272 { 273 flags |= kIOFWWriteBlockRequest; 274 } 275 } 276 277 result = fControl->asyncWrite( fGeneration, 278 fNodeID, 279 fAddressHi, 280 fAddressLo, 281 fSpeed, 282 fTrans->fTCode, 283 fMemDesc, 284 fBytesTransferred, 285 fPackSize, 286 this, 287 (IOFWWriteFlags)flags ); 288 } 289 else 290 { 291 //IOLog("IOFWWriteCommand::execute: Out of tLabels?\n"); 292 result = kIOFireWireOutOfTLabels; 293 } 294 295 // complete could release us so protect fStatus with retain and release 296 IOReturn status = fStatus; 297 if( result != kIOReturnSuccess ) 298 { 299 retain(); 300 complete( result ); 301 status = fStatus; 302 release(); 303 } 304 305 return status; 306} 307 308// gotPacket 309// 310// 311 312void IOFWWriteCommand::gotPacket( int rcode, const void* data, int size ) 313{ 314 setResponseCode( rcode ); 315 316 if( rcode != kFWResponseComplete ) 317 { 318 complete( kIOFireWireResponseBase+rcode ); 319 return; 320 } 321 else 322 { 323 fBytesTransferred += fPackSize; 324 fSize -= fPackSize; 325 } 326 327 if( fSize > 0 ) 328 { 329 fAddressLo += fPackSize; 330 331 updateTimer(); 332 fCurRetries = fMaxRetries; 333 fControl->freeTrans( fTrans ); // Free old tcode 334 execute(); 335 } 336 else 337 { 338 complete( kIOReturnSuccess ); 339 } 340} 341