1/* 2 * Copyright (c) 1998-2000 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 * IOFireWireLibPhysicalAddressSpace.cpp 24 * IOFireWireLib 25 * 26 * Created by NWG on Tue Dec 12 2000. 27 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. 28 * 29 */ 30 31#import "IOFireWireLibPhysicalAddressSpace.h" 32#import "IOFireWireLibDevice.h" 33#import <exception> 34 35#import <System/libkern/OSCrossEndian.h> 36 37namespace IOFireWireLib { 38 39 // COM 40 41 PhysicalAddressSpace::Interface PhysicalAddressSpace::sInterface = 42 { 43 INTERFACEIMP_INTERFACE, 44 1, 0, //vers, rev 45 & PhysicalAddressSpace::SGetPhysicalSegments, 46 & PhysicalAddressSpace::SGetPhysicalSegment, 47 & PhysicalAddressSpace::SGetPhysicalAddress, 48 49 SGetFWAddress, 50 SGetBuffer, 51 SGetBufferSize 52 } ; 53 54 HRESULT 55 PhysicalAddressSpace::QueryInterface(REFIID iid, void **ppv) 56 { 57 HRESULT result = S_OK ; 58 *ppv = nil ; 59 60 CFUUIDRef interfaceID = CFUUIDCreateFromUUIDBytes(kCFAllocatorDefault, iid) ; 61 62 if ( CFEqual(interfaceID, IUnknownUUID) || CFEqual(interfaceID, kIOFireWirePhysicalAddressSpaceInterfaceID) ) 63 { 64 *ppv = & GetInterface() ; 65 AddRef() ; 66 } 67 else 68 { 69 *ppv = nil ; 70 result = E_NOINTERFACE ; 71 } 72 73 CFRelease(interfaceID) ; 74 return result ; 75 } 76 77 IUnknownVTbl** 78 PhysicalAddressSpace::Alloc( 79 Device& inUserClient, 80 UserObjectHandle inAddrSpaceRef, 81 UInt32 inSize, 82 void* inBackingStore, 83 UInt32 inFlags) 84 { 85 PhysicalAddressSpace* me = nil ; 86 try { 87 me = new PhysicalAddressSpace(inUserClient, inAddrSpaceRef, inSize, inBackingStore, inFlags) ; 88 } catch (...) { 89 } 90 91 return ( nil == me ) ? nil : reinterpret_cast<IUnknownVTbl**>(& me->GetInterface()) ; 92 } 93 94#pragma mark - 95 void 96 PhysicalAddressSpace::SGetPhysicalSegments( 97 IOFireWireLibPhysicalAddressSpaceRef self, 98 UInt32* ioSegmentCount, 99 IOByteCount outSegments[], 100 IOPhysicalAddress outAddresses[]) 101 { 102 IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->GetPhysicalSegments(ioSegmentCount, outSegments, outAddresses) ; 103 } 104 105 IOPhysicalAddress 106 PhysicalAddressSpace::SGetPhysicalSegment( 107 IOFireWireLibPhysicalAddressSpaceRef self, 108 IOByteCount offset, 109 IOByteCount* length) 110 { 111 return IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->GetPhysicalSegment(offset, length) ; 112 } 113 114 IOPhysicalAddress 115 PhysicalAddressSpace::SGetPhysicalAddress( 116 IOFireWireLibPhysicalAddressSpaceRef self) 117 { 118 return IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->mSegments[0].location ; 119 } 120 121 void 122 PhysicalAddressSpace::SGetFWAddress(IOFireWireLibPhysicalAddressSpaceRef self, FWAddress* outAddr ) 123 { 124 bcopy(& IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->mFWAddress, outAddr, sizeof(*outAddr)) ; 125 } 126 127 void* 128 PhysicalAddressSpace::SGetBuffer(IOFireWireLibPhysicalAddressSpaceRef self) 129 { 130 return IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->mBackingStore ; 131 } 132 133 const UInt32 134 PhysicalAddressSpace::SGetBufferSize(IOFireWireLibPhysicalAddressSpaceRef self) 135 { 136 return IOFireWireIUnknown::InterfaceMap<PhysicalAddressSpace>::GetThis(self)->mSize ; 137 } 138 139#pragma mark - 140 PhysicalAddressSpace::PhysicalAddressSpace( Device& inUserClient, UserObjectHandle inKernPhysicalAddrSpaceRef, 141 UInt32 inSize, void* inBackingStore, UInt32 inFlags) 142 : IOFireWireIUnknown( reinterpret_cast<const IUnknownVTbl &>( sInterface ) ), 143 mUserClient(inUserClient), 144 mKernPhysicalAddrSpaceRef(inKernPhysicalAddrSpaceRef), 145 mSize(inSize), 146 mBackingStore(inBackingStore), 147 mSegments( NULL ), 148 mSegmentCount(0) 149 { 150 inUserClient.AddRef() ; 151 152 if (!mKernPhysicalAddrSpaceRef) 153 throw kIOReturnNoMemory ; 154 155 uint32_t outputCnt = 1; 156 uint64_t outputVal = 0; 157 IOReturn error = IOConnectCallScalarMethod( mUserClient.GetUserClientConnection(), 158 mUserClient.MakeSelectorWithObject( kPhysicalAddrSpace_GetSegmentCount_d, mKernPhysicalAddrSpaceRef ), 159 NULL,0, 160 &outputVal,&outputCnt); 161 mSegmentCount = outputVal & 0xFFFFFFFF; 162 163 if ( error || mSegmentCount == 0) 164 throw error ; 165 166 mSegments = new FWPhysicalSegment32[mSegmentCount] ; 167 if (!mSegments) 168 { 169 throw kIOReturnNoMemory ; 170 } 171 172 outputCnt = 1; 173 outputVal = 0; 174 const uint64_t inputs[3] = {(const uint64_t)mKernPhysicalAddrSpaceRef, mSegmentCount, (const uint64_t)mSegments}; 175 error = IOConnectCallScalarMethod( mUserClient.GetUserClientConnection(), 176 kPhysicalAddrSpace_GetSegments, 177 inputs,3, 178 &outputVal,&outputCnt); 179 mSegmentCount = outputVal & 0xFFFFFFFF; 180 181 if (error) 182 { 183 throw error ; 184 } 185 186#ifndef __LP64__ 187 ROSETTA_ONLY( 188 { 189 UInt32 i; 190 for( i = 0; i < mSegmentCount; i++ ) 191 { 192 mSegments[i].location = OSSwapInt32( mSegments[i].location ); 193 mSegments[i].length = OSSwapInt32( mSegments[i].length ); 194 } 195 } 196 ); 197#endif 198 199 mFWAddress = FWAddress(0, mSegments[0].location, 0) ; 200 } 201 202 PhysicalAddressSpace::~PhysicalAddressSpace() 203 { 204 // call user client to delete our addr space ref here (if not yet released) 205 uint32_t outputCnt = 0; 206 const uint64_t inputs[1]={(const uint64_t)mKernPhysicalAddrSpaceRef}; 207 208 IOConnectCallScalarMethod(mUserClient.GetUserClientConnection(), 209 kReleaseUserObject, 210 inputs,1, 211 NULL,&outputCnt); 212 213 delete[] mSegments ; 214 215 mUserClient.Release() ; 216 } 217 218 void 219 PhysicalAddressSpace::GetPhysicalSegments( 220 UInt32* ioSegmentCount, 221 IOByteCount outSegmentLengths[], 222 IOPhysicalAddress outSegments[]) 223 { 224 if ( !outSegments || !outSegmentLengths ) 225 { 226 *ioSegmentCount = mSegmentCount ; 227 return ; 228 } 229 230 *ioSegmentCount = MIN( *ioSegmentCount, mSegmentCount ) ; 231 232 for( unsigned index=0; index < *ioSegmentCount; ++index ) 233 { 234 outSegments[ index ] = mSegments[ index ].location ; 235 outSegmentLengths[ index ] = mSegments[ index ].length ; 236 } 237 } 238 239 IOPhysicalAddress 240 PhysicalAddressSpace::GetPhysicalSegment( 241 IOByteCount offset, 242 IOByteCount* length) 243 { 244 IOPhysicalAddress result = 0 ; 245 246 if (mSegmentCount > 0) 247 { 248 IOByteCount traversed = mSegments[0].length ; 249 UInt32 currentSegment = 0 ; 250 251 while((traversed <= offset) && (currentSegment < mSegmentCount)) 252 { 253 traversed += mSegments[ currentSegment ].length ; 254 ++currentSegment ; 255 } 256 257 if ( currentSegment <= mSegmentCount ) 258 { 259 *length = mSegments[ currentSegment ].length ; 260 result = mSegments[ currentSegment ].location ; 261 } 262 } 263 264 return result ; 265 } 266 267} 268