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