1/* 2 * Copyright (c) 2008 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#include <IOKit/firewire/IOFireWireController.h> 24#include <IOKit/firewire/IOFireWireMultiIsochReceive.h> 25/////////////////////////////////////////////////////////////////////////////////// 26// 27// Definition of objects used by the Multi-Isoch Receiver 28// 29/////////////////////////////////////////////////////////////////////////////////// 30OSDefineMetaClassAndStructors(IOFireWireMultiIsochReceiveListener, OSObject) 31OSDefineMetaClassAndStructors(IOFireWireMultiIsochReceivePacket, OSObject) 32 33/////////////////////////////////////////////////////////////////////////////////// 34// IOFireWireMultiIsochReceiveListener::init 35/////////////////////////////////////////////////////////////////////////////////// 36bool IOFireWireMultiIsochReceiveListener::init(IOFireWireController *fwController, 37 UInt32 receiveChannel, 38 FWMultiIsochReceiveListenerCallback callback, 39 void *pCallbackRefCon, 40 FWMultiIsochReceiveListenerParams *pListenerParams) 41{ 42 bool success = true; 43 44 //IOLog( "IOFireWireMultiIsochReceiveListener::init (0x%08X)\n",(int) this); 45 46 // init super 47 if( !OSObject::init() ) 48 success = false; 49 50 if( success ) 51 { 52 // Initialize this object 53 fControl = fwController; 54 fChannel = receiveChannel; 55 fClientCallback = callback; 56 fClientCallbackRefCon = pCallbackRefCon; 57 fActivated = false; 58 59 if (pListenerParams) 60 { 61 fListenerParams = new FWMultiIsochReceiveListenerParams; 62 if (fListenerParams) 63 { 64 // copy over the parameters specified by the client. 65 fListenerParams->maxLatencyInFireWireCycles = pListenerParams->maxLatencyInFireWireCycles; 66 fListenerParams->expectedStreamBitRate = pListenerParams->expectedStreamBitRate; 67 fListenerParams->clientPacketReturnLatencyInFireWireCycles = pListenerParams->clientPacketReturnLatencyInFireWireCycles; 68 } 69 } 70 else 71 fListenerParams = NULL; 72 } 73 74 return success; 75} 76 77/////////////////////////////////////////////////////////////////////////////////// 78// IOFireWireMultiIsochReceiveListener::free 79/////////////////////////////////////////////////////////////////////////////////// 80void IOFireWireMultiIsochReceiveListener::free() 81{ 82 if (fListenerParams) 83 { 84 delete fListenerParams; 85 fListenerParams = NULL; 86 } 87 88 OSObject::free(); 89} 90 91/////////////////////////////////////////////////////////////////////////////////// 92// IOFireWireMultiIsochReceiveListener::create 93/////////////////////////////////////////////////////////////////////////////////// 94IOFireWireMultiIsochReceiveListener * IOFireWireMultiIsochReceiveListener::create(IOFireWireController *fwController, 95 UInt32 channel, 96 FWMultiIsochReceiveListenerCallback callback, 97 void *pCallbackRefCon, 98 FWMultiIsochReceiveListenerParams *pListenerParams) 99{ 100 IOFireWireMultiIsochReceiveListener * listener; 101 102 listener = OSTypeAlloc( IOFireWireMultiIsochReceiveListener ); 103 104 if( listener != NULL && !listener->init(fwController, 105 channel, 106 callback, 107 pCallbackRefCon, 108 pListenerParams)) 109 { 110 listener->release(); 111 listener = NULL; 112 } 113 114 return listener; 115} 116 117/////////////////////////////////////////////////////////////////////////////////// 118// IOFireWireMultiIsochReceiveListener::Activate 119/////////////////////////////////////////////////////////////////////////////////// 120IOReturn IOFireWireMultiIsochReceiveListener::Activate() 121{ 122 return fControl->activateMultiIsochReceiveListener(this); 123} 124 125/////////////////////////////////////////////////////////////////////////////////// 126// IOFireWireMultiIsochReceiveListener::Deactivate 127/////////////////////////////////////////////////////////////////////////////////// 128IOReturn IOFireWireMultiIsochReceiveListener::Deactivate() 129{ 130 return fControl->deactivateMultiIsochReceiveListener(this); 131} 132 133/////////////////////////////////////////////////////////////////////////////////// 134// IOFireWireMultiIsochReceiveListener::SetCallback 135/////////////////////////////////////////////////////////////////////////////////// 136IOReturn IOFireWireMultiIsochReceiveListener::SetCallback(FWMultiIsochReceiveListenerCallback callback, 137 void *pCallbackRefCon) 138{ 139 if (!fActivated) 140 { 141 fClientCallback = callback; 142 fClientCallbackRefCon = pCallbackRefCon; 143 return kIOReturnSuccess; 144 } 145 else 146 return kIOReturnNotPermitted; 147} 148 149/////////////////////////////////////////////////////////////////////////////////// 150// IOFireWireMultiIsochReceivePacket::init 151/////////////////////////////////////////////////////////////////////////////////// 152bool IOFireWireMultiIsochReceivePacket::init(IOFireWireController *fwController) 153{ 154 bool success = true; 155 156 //IOLog( "IOFireWireMultiIsochReceivePacket::init (0x%08X)\n",(int) this); 157 158 // init super 159 if( !OSObject::init() ) 160 success = false; 161 162 if( success ) 163 { 164 // Initialize this object 165 fControl = fwController; 166 numRanges = 0; 167 numClientReferences = 0; 168 } 169 170 return success; 171} 172 173/////////////////////////////////////////////////////////////////////////////////// 174// IOFireWireMultiIsochReceivePacket::free 175/////////////////////////////////////////////////////////////////////////////////// 176void IOFireWireMultiIsochReceivePacket::free() 177{ 178 OSObject::free(); 179} 180 181/////////////////////////////////////////////////////////////////////////////////// 182// IOFireWireMultiIsochReceivePacket::create 183/////////////////////////////////////////////////////////////////////////////////// 184IOFireWireMultiIsochReceivePacket * IOFireWireMultiIsochReceivePacket::create( IOFireWireController *fwController ) 185{ 186 IOFireWireMultiIsochReceivePacket * packet; 187 188 packet = OSTypeAlloc( IOFireWireMultiIsochReceivePacket ); 189 190 if( packet != NULL && !packet->init(fwController)) 191 { 192 packet->release(); 193 packet = NULL; 194 } 195 196 return packet; 197} 198 199/////////////////////////////////////////////////////////////////////////////////// 200// IOFireWireMultiIsochReceivePacket::clientDone 201/////////////////////////////////////////////////////////////////////////////////// 202void IOFireWireMultiIsochReceivePacket::clientDone( void ) 203{ 204 fControl->clientDoneWithMultiIsochReceivePacket(this); 205} 206 207/////////////////////////////////////////////////////////////////////////////////// 208// IOFireWireMultiIsochReceivePacket::isochChannel 209/////////////////////////////////////////////////////////////////////////////////// 210UInt32 211IOFireWireMultiIsochReceivePacket::isochChannel(void) 212{ 213 // The isoch channel number is in the first quad, 214 // which is guarranted to be in the first range. 215 216 UInt32 *pIsochPacketHeader = (UInt32*) ranges[0].address; 217 UInt32 isochPacketHeader = OSSwapLittleToHostInt32(*pIsochPacketHeader); 218 return ((isochPacketHeader & 0x00003F00) >> 8); 219} 220 221/////////////////////////////////////////////////////////////////////////////////// 222// IOFireWireMultiIsochReceivePacket::isochPayloadSize 223/////////////////////////////////////////////////////////////////////////////////// 224UInt32 225IOFireWireMultiIsochReceivePacket::isochPayloadSize(void) 226{ 227 // The isoch payload size is in the first quad, 228 // which is guarranted to be in the first range. 229 230 UInt32 *pIsochPacketHeader = (UInt32*) ranges[0].address; 231 UInt32 isochPacketHeader = OSSwapLittleToHostInt32(*pIsochPacketHeader); 232 return ((isochPacketHeader & 0xFFFF0000) >> 16); 233} 234 235/////////////////////////////////////////////////////////////////////////////////// 236// IOFireWireMultiIsochReceivePacket::packetReceiveTime 237/////////////////////////////////////////////////////////////////////////////////// 238UInt32 239IOFireWireMultiIsochReceivePacket::packetReceiveTime(void) 240{ 241 // The isoch timestamp is in the last quad, 242 // which is guarranted to be in the last range. 243 244 UInt32 *pIsochPacketTrailer = (UInt32*) ranges[numRanges-1].address; 245 pIsochPacketTrailer += ((ranges[numRanges-1].length/4)-1); // Bump to the last quadlet in the range 246 UInt32 isochPacketTrailer = OSSwapLittleToHostInt32(*pIsochPacketTrailer); 247 248 // We shift the 16-bit time-stamp into the normal 7:13:12 FireWire cycle-time format! 249 return ((isochPacketTrailer & 0x0000FFFF) << 12); 250} 251 252/////////////////////////////////////////////////////////////////////////////////// 253// IOFireWireMultiIsochReceivePacket::createMemoryDescriptorForRanges 254/////////////////////////////////////////////////////////////////////////////////// 255IOMemoryDescriptor* 256IOFireWireMultiIsochReceivePacket::createMemoryDescriptorForRanges(void) 257{ 258 IOMemoryDescriptor * bufferDesc = NULL ; 259 IOReturn error; 260 261 bufferDesc = IOMemoryDescriptor::withAddressRanges (ranges, numRanges, kIODirectionOut, kernel_task) ; 262 if ( ! bufferDesc ) 263 { 264 error = kIOReturnNoMemory ; 265 } 266 else 267 { 268 error = bufferDesc->prepare() ; 269 if (error != kIOReturnSuccess) 270 { 271 bufferDesc->release(); 272 bufferDesc = NULL; 273 } 274 } 275 276 return bufferDesc; 277} 278