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#include <IOKit/IOLib.h> 24#include <IOKit/IOUserClient.h> 25#include <IOKit/IOLocks.h> 26#include <IOKit/pwr_mgt/RootDomain.h> 27#include <IOKit/ndrvsupport/IONDRVFramebuffer.h> 28#include <IOKit/assert.h> 29#include <libkern/c++/OSContainers.h> 30 31#include <IOKit/i2c/IOI2CInterfacePrivate.h> 32 33/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 34 35#undef super 36#define super IOService 37 38OSDefineMetaClassAndAbstractStructors(IOI2CInterface, IOService) 39 40/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 41 42bool IOI2CInterface::registerI2C( UInt64 id ) 43{ 44 bool result = true; 45 46 fID = id; 47 48 setProperty(kIOI2CInterfaceIDKey, id, 64); 49 50 registerService(); 51 52 return (result); 53} 54 55IOReturn IOI2CInterface::newUserClient( task_t owningTask, 56 void * security_id, 57 UInt32 type, 58 IOUserClient ** handler ) 59 60{ 61 IOReturn err = kIOReturnSuccess; 62 IOUserClient * newConnect = 0; 63 64 if (type) 65 return (kIOReturnBadArgument); 66 67 newConnect = IOI2CInterfaceUserClient::withTask(owningTask); 68 69 if (newConnect) 70 { 71 if (!newConnect->attach(this) 72 || !newConnect->start(this)) 73 { 74 newConnect->detach( this ); 75 newConnect->release(); 76 newConnect = 0; 77 } 78 } 79 80 *handler = newConnect; 81 82 return (err); 83} 84 85/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 86 87#undef super 88#define super IOUserClient 89 90OSDefineMetaClassAndStructors(IOI2CInterfaceUserClient, IOUserClient) 91 92/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 93 94IOI2CInterfaceUserClient * IOI2CInterfaceUserClient::withTask( task_t owningTask ) 95{ 96 IOI2CInterfaceUserClient * inst; 97 98 inst = new IOI2CInterfaceUserClient; 99 if (inst && !inst->init()) 100 { 101 inst->release(); 102 inst = 0; 103 } 104 if (inst) 105 inst->fTask = owningTask; 106 107 return (inst); 108} 109 110bool IOI2CInterfaceUserClient::start( IOService * provider ) 111{ 112 if (!super::start(provider)) 113 return (false); 114 115 return (true); 116} 117 118IOReturn IOI2CInterfaceUserClient::clientClose( void ) 119{ 120 terminate(); 121 return (kIOReturnSuccess); 122} 123 124IOService * IOI2CInterfaceUserClient::getService( void ) 125{ 126 return (getProvider()); 127} 128 129IOExternalMethod * IOI2CInterfaceUserClient::getTargetAndMethodForIndex( 130 IOService ** targetP, UInt32 index ) 131{ 132 static const IOExternalMethod methodTemplate[] = { 133 /* 0 */ { NULL, (IOMethod) &IOI2CInterfaceUserClient::extAcquireBus, 134 kIOUCScalarIScalarO, 0, 0 }, 135 /* 1 */ { NULL, (IOMethod) &IOI2CInterfaceUserClient::extReleaseBus, 136 kIOUCScalarIScalarO, 0, 0 }, 137 /* 3 */ { NULL, (IOMethod) &IOI2CInterfaceUserClient::extIO, 138 kIOUCStructIStructO, 0xffffffff, 0xffffffff }, 139 }; 140 141 if (index > (sizeof(methodTemplate) / sizeof(methodTemplate[0]))) 142 return (NULL); 143 144 *targetP = this; 145 return ((IOExternalMethod *)(methodTemplate + index)); 146} 147 148IOReturn IOI2CInterfaceUserClient::setProperties( OSObject * properties ) 149{ 150 return (kIOReturnUnsupported); 151} 152 153IOReturn IOI2CInterfaceUserClient::extAcquireBus( void ) 154{ 155 IOReturn ret = kIOReturnNotReady; 156 IOI2CInterface * provider; 157 158 if ((provider = (IOI2CInterface *) copyParentEntry(gIOServicePlane))) 159 { 160 ret = provider->open( this ) ? kIOReturnSuccess : kIOReturnBusy; 161 provider->release(); 162 } 163 164 return (ret); 165} 166 167IOReturn IOI2CInterfaceUserClient::extReleaseBus( void ) 168{ 169 IOReturn ret = kIOReturnNotReady; 170 IOI2CInterface * provider; 171 172 if ((provider = (IOI2CInterface *) copyParentEntry(gIOServicePlane))) 173 { 174 provider->close( this ); 175 provider->release(); 176 ret = kIOReturnSuccess; 177 } 178 179 return (ret); 180} 181 182IOReturn IOI2CInterfaceUserClient::extIO( 183 void * inStruct, void * outStruct, 184 IOByteCount inSize, IOByteCount * outSize ) 185{ 186 IOReturn err = kIOReturnNotReady; 187 IOI2CInterface * provider; 188 IOI2CBuffer * buffer; 189 190 IOI2CRequest * request; 191 IOI2CRequest_10_5_0 * requestV1 = NULL; 192 IOI2CRequest requestV2; 193 194 if (inSize < sizeof(IOI2CBuffer)) 195 return (kIOReturnNoSpace); 196 if (*outSize < inSize) 197 return (kIOReturnNoSpace); 198 199 buffer = (IOI2CBuffer *) inStruct; 200 request = &buffer->request; 201 202 if (!request->sendTransactionType && !request->replyTransactionType) 203 { 204 requestV1 = (typeof (requestV1)) &buffer->request; 205 bzero(&requestV2, sizeof(requestV2)); 206 request = &requestV2; 207 208 request->sendTransactionType = requestV1->sendTransactionType; 209 request->replyTransactionType = requestV1->replyTransactionType; 210 request->sendAddress = requestV1->sendAddress; 211 request->replyAddress = requestV1->replyAddress; 212 request->sendBytes = requestV1->sendBytes; 213 request->replyBytes = requestV1->replyBytes; 214 request->sendSubAddress = requestV1->sendSubAddress; 215 request->replySubAddress = requestV1->replySubAddress; 216 request->commFlags = requestV1->commFlags; 217 request->minReplyDelay = requestV1->minReplyDelay; 218 } 219 220 if ((provider = (IOI2CInterface *) copyParentEntry(gIOServicePlane))) 221 do 222 { 223 if (!provider->isOpen(this)) 224 { 225 err = kIOReturnNotOpen; 226 continue; 227 } 228 229 if (request->sendBytes) 230 { 231 if (!request->sendBuffer) 232 request->sendBuffer = (vm_address_t) &buffer->inlineBuffer[0]; 233 else 234 { 235 err = kIOReturnMessageTooLarge; 236 continue; 237 } 238 } 239 if (request->replyBytes) 240 { 241 if (!request->replyBuffer) 242 request->replyBuffer = (vm_address_t) &buffer->inlineBuffer[0]; 243 else 244 { 245 err = kIOReturnMessageTooLarge; 246 continue; 247 } 248 } 249 250 err = provider->startIO( request ); 251 252 if (requestV1) 253 requestV1->result = request->result; 254 } 255 while (false); 256 257 if (provider) 258 provider->release(); 259 260 if (kIOReturnSuccess == err) 261 { 262 *outSize = inSize; 263 bcopy(inStruct, outStruct, inSize); 264 } 265 else 266 *outSize = 0; 267 268 return (err); 269} 270 271/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 272 273 274