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(IOFWReadCommand, IOFWAsyncCommand)
37OSMetaClassDefineReservedUnused(IOFWReadCommand, 0);
38OSMetaClassDefineReservedUnused(IOFWReadCommand, 1);
39
40#pragma mark -
41
42// gotPacket
43//
44//
45
46void IOFWReadCommand::gotPacket(int rcode, const void* data, int size)
47{
48	setResponseCode( rcode );
49
50    if(rcode != kFWResponseComplete) {
51        //kprintf("Received rcode %d for read command 0x%x, nodeID %x\n", rcode, this, fNodeID);
52        if(rcode == kFWResponseTypeError && 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        fMemDesc->writeBytes(fBytesTransferred, data, size);
64        fSize -= size;
65	fBytesTransferred += size;
66    }
67
68    if(fSize > 0) {
69        fAddressLo += size;
70        fControl->freeTrans(fTrans);  // Free old tcode
71        updateTimer();
72        fCurRetries = fMaxRetries;
73        execute();
74    }
75    else {
76        complete(kIOReturnSuccess);
77    }
78}
79
80// initAll
81//
82//
83
84bool IOFWReadCommand::initAll(IOFireWireNub *device, FWAddress devAddress,
85	IOMemoryDescriptor *hostMem, FWDeviceCallback completion,
86	void *refcon, bool failOnReset)
87{
88    return IOFWAsyncCommand::initAll(device, devAddress,
89                          hostMem, completion, refcon, failOnReset);
90}
91
92// initAll
93//
94//
95
96bool IOFWReadCommand::initAll(IOFireWireController *control,
97                              UInt32 generation, FWAddress devAddress,
98        IOMemoryDescriptor *hostMem, FWDeviceCallback completion,
99        void *refcon)
100{
101    return IOFWAsyncCommand::initAll(control, generation, devAddress,
102                          hostMem, completion, refcon);
103}
104
105// reinit
106//
107//
108
109IOReturn IOFWReadCommand::reinit(FWAddress devAddress,
110	IOMemoryDescriptor *hostMem,
111	FWDeviceCallback completion, void *refcon, bool failOnReset)
112{
113    return IOFWAsyncCommand::reinit(devAddress,
114	hostMem, completion, refcon, failOnReset);
115}
116
117IOReturn IOFWReadCommand::reinit(UInt32 generation, FWAddress devAddress,
118        IOMemoryDescriptor *hostMem,
119        FWDeviceCallback completion, void *refcon)
120{
121    return IOFWAsyncCommand::reinit(generation, devAddress,
122        hostMem, completion, refcon);
123}
124
125// execute
126//
127//
128
129IOReturn IOFWReadCommand::execute()
130{
131    IOReturn result;
132    int transfer;
133
134    fStatus = kIOReturnBusy;
135
136    if(!fFailOnReset) {
137        // Update nodeID and generation
138        fDevice->getNodeIDGeneration(fGeneration, fNodeID);
139		fSpeed = fControl->FWSpeed( fNodeID );
140		if( fMembers->fMaxSpeed < fSpeed )
141		{
142			fSpeed = fMembers->fMaxSpeed;
143		}
144    }
145
146    transfer = fSize;
147    if(transfer > fMaxPack)
148	{
149		transfer = fMaxPack;
150	}
151
152	int maxPack = (1 << fControl->maxPackLog(fWrite, fNodeID));
153	if( maxPack < transfer )
154	{
155		transfer = maxPack;
156	}
157
158	UInt32 flags = kIOFWReadFlagsNone;
159
160	if( fMembers )
161	{
162		if( ((IOFWAsyncCommand::MemberVariables*)fMembers)->fForceBlockRequests )
163		{
164			flags |= kIOFWWriteBlockRequest;
165		}
166	}
167
168    fTrans = fControl->allocTrans(this);
169    if(fTrans) {
170        result = fControl->asyncRead(fGeneration, fNodeID, fAddressHi,
171                        fAddressLo, fSpeed, fTrans->fTCode, transfer, this, (IOFWReadFlags)flags );
172    }
173    else {
174    //    IOLog("IOFWReadCommand::execute: Out of tLabels?\n");
175        result = kIOFireWireOutOfTLabels;
176    }
177
178	// complete could release us so protect fStatus with retain and release
179	IOReturn status = fStatus;
180    if(result != kIOReturnSuccess)
181	{
182		retain();
183        complete(result);
184		status = fStatus;
185		release();
186	}
187
188	return status;
189}
190