]> git.saurik.com Git - apple/xnu.git/blame - iokit/Drivers/platform/drvApplePMU/IOPMUADBController.cpp
xnu-201.tar.gz
[apple/xnu.git] / iokit / Drivers / platform / drvApplePMU / IOPMUADBController.cpp
CommitLineData
1c79356b
A
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 * 12 Nov 1998 suurballe Created.
24 */
25
26#include <IOKit/IOSyncer.h>
27#include "IOPMUADBController.h"
28
29#define super IOADBController
30OSDefineMetaClassAndStructors(IOPMUADBController, IOADBController)
31
32// **********************************************************************************
33// start
34//
35// **********************************************************************************
36IOService * IOPMUADBController::probe( IOService * provider, SInt32 * score )
37{
38 if (super::probe(provider, score) == NULL)
39 return NULL;
40
41 // this adb controller must interface with the pmu, so let's check if it is of the right type:
42 // so in any case if this is a powerbook G3 1998 or 1999 it has a pmu so:
43 if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'AAPL,PowerBook1998'") ||
44 IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'"))
45 return this;
46
47 // If it is a different machine the compatible property will tell us if it is a pmu-driven
48 // adb device:
49 OSData *kl = OSDynamicCast(OSData, provider->getProperty("compatible"));
50 if ((kl != NULL) && kl->isEqualTo("pmu", 3))
51 return this;
52
53 // In all the other cases we do not handle it:
54 return NULL;
55}
56
57// **********************************************************************************
58// start
59//
60// **********************************************************************************
61bool IOPMUADBController::start ( IOService * nub )
62{
63 // Wait for the PMU to show up:
64 PMUdriver = waitForService(serviceMatching("ApplePMU"));
65
66 // All the commands in this file will generate an interrupt.
67 // since the interrupt is the logical conclusion of those commands
68 // we need a syncer to sincronize the begin/end of these functions:
69 waitingForData = NULL;
70
71 // Registers for the two interrupts that needs to handle:
72 if (PMUdriver->callPlatformFunction("registerForPMUInterrupts", true, (void*)kPMUADBint, (void*)handleADBInterrupt, (void*)this, NULL) != kIOReturnSuccess) {
73#ifdef VERBOSE_LOGS_ON
74 IOLog("IOPMUADBController::start registerForPMUInterrupts kPMUADBint fails\n");
75#endif // VERBOSE_LOGS_ON
76
77 return false;
78 }
79
80 // Creates the mutex lock to protect the clients list:
81 requestMutexLock = NULL;
82 requestMutexLock = IOLockAlloc();
83 if (!requestMutexLock)
84 return false;
85
86 // This happens last (while the most common place is the begin) because
87 // trhe superclass may need the services of the functions above.
88 if( !super::start(nub))
89 return false;
90
91 return true;
92}
93
94// **********************************************************************************
95// free
96//
97// **********************************************************************************
98void IOPMUADBController::free ( )
99{
100 // Releases the mutex lock used to protect the clients lists:
101 if (requestMutexLock != NULL) {
102 IOLockFree (requestMutexLock);
103 requestMutexLock = NULL;
104 }
105
106 // And removes the interrupt handler:
107 if (PMUdriver != NULL)
108 PMUdriver->callPlatformFunction("deRegisterClient", true, (void*)this, (void*)kPMUADBint, NULL, NULL);
109}
110
111// **********************************************************************************
112// localSendMiscCommand
113//
114// **********************************************************************************
0b4e3aa0 115IOReturn IOPMUADBController::localSendMiscCommand(int command, IOByteCount sLength, UInt8 *sBuffer)
1c79356b
A
116{
117 IOReturn returnValue = kIOReturnError;
0b4e3aa0
A
118 IOByteCount rLength = 1;
119 UInt8 rBuffer;
120
1c79356b
A
121 // The poupose of this method is to free us from the pain to create a parameter block each time
122 // we wish to talk to the pmu:
0b4e3aa0 123 SendMiscCommandParameterBlock prmBlock = {command, sLength, sBuffer, &rLength, &rBuffer};
1c79356b
A
124
125#ifdef VERBOSE_LOGS_ON
126 IOLog("ApplePMUInterface::localSendMiscCommand 0x%02x %d 0x%08lx 0x%08lx 0x%08lx\n",
127 command, sLength, sBuffer, rLength, rBuffer);
128#endif
129
130 if (PMUdriver != NULL) {
131#ifdef VERBOSE_LOGS_ON
132 IOLog("IOPMUADBController::localSendMiscCommand calling PMUdriver->callPlatformFunction\n");
133#endif
134 returnValue = PMUdriver->callPlatformFunction("sendMiscCommand", true, (void*)&prmBlock, NULL, NULL, NULL);
135 }
136
137 // If we are here we do not have a dreive to talk to:
138#ifdef VERBOSE_LOGS_ON
139 IOLog("IOPMUADBController::localSendMiscCommand end 0x%08lx\n", returnValue);
140#endif
141
142 return returnValue;
143}
144
145// **********************************************************************************
146// this is the interrupt handler for all ADB interrupts:
147//
148// **********************************************************************************
149
150/* static */ void
151IOPMUADBController::handleADBInterrupt(IOService *client, UInt8 interruptMask, UInt32 length, UInt8 *buffer)
152{
0b4e3aa0
A
153 IOPMUADBController *myThis = OSDynamicCast(IOPMUADBController, client);
154
155 // Check if we are the right client for this interrupt:
156 if (myThis == NULL)
157 return;
158
159 if ((interruptMask & kPMUautopoll) && (myThis->autopollOn))
1c79356b
A
160 autopollHandler(client, buffer[0], length - 1, buffer + 1); // yes, call adb input handler
161 else {
0b4e3aa0 162 if (myThis->waitingForData != NULL) {
1c79356b
A
163 // Complets the adb transaction
164 myThis->dataLen = length - 1;
165 bcopy(buffer + 1, myThis->dataBuffer, myThis->dataLen);
166 myThis->waitingForData->signal();
167 }
168 }
169}
170
0b4e3aa0
A
171
172// **********************************************************************************
173// cancelAllIO
174//
175// **********************************************************************************
176IOReturn IOPMUADBController::cancelAllIO ( void )
177{
178 if (waitingForData != NULL) {
179 dataLen = 0; // read fails with error, write fails quietly
180 waitingForData->signal();
181 }
182 return kPMUNoError;
183}
184
185
1c79356b
A
186// **********************************************************************************
187// setAutoPollPeriod
188//
189// **********************************************************************************
190IOReturn IOPMUADBController::setAutoPollPeriod ( int )
191{
192 return kPMUNotSupported;
193}
194
195
196// **********************************************************************************
197// getAutoPollPeriod
198//
199// **********************************************************************************
200IOReturn IOPMUADBController::getAutoPollPeriod ( int * )
201{
202 return kPMUNotSupported;
203}
204
205
206// **********************************************************************************
207// setAutoPollList
208//
209// **********************************************************************************
210IOReturn IOPMUADBController::setAutoPollList ( UInt16 PollBitField )
211{
212 pollList = PollBitField; // remember the new poll list
213
214 if ( autopollOn ) {
215 UInt8 oBuffer[4];
216
217 oBuffer[0] = 0; // Byte count in the resto of the command
218 oBuffer[1] = 0x86; // adb Command op.
219 oBuffer[2] = (UInt8)(PollBitField >> 8); // ??
220 oBuffer[3] = (UInt8)(PollBitField & 0xff); // ??
0b4e3aa0
A
221
222 localSendMiscCommand (kPMUpMgrADB, 4, oBuffer);
1c79356b
A
223 }
224 return kPMUNoError;
225}
226
227
228// **********************************************************************************
229// getAutoPollList
230//
231// **********************************************************************************
232IOReturn IOPMUADBController::getAutoPollList ( UInt16 * activeAddressMask )
233{
234 *activeAddressMask = pollList;
235 return kPMUNoError;
236}
237
238
239// **********************************************************************************
240// setAutoPollEnable
241//
242// **********************************************************************************
243IOReturn IOPMUADBController::setAutoPollEnable ( bool enable )
244{
245 UInt8 oBuffer[4];
246
0b4e3aa0
A
247 autopollOn = enable;
248
1c79356b
A
249 if ( enable ) { // enabling autopoll
250 oBuffer[0] = 0;
251 oBuffer[1] = 0x86;
252 oBuffer[2] = (UInt8)(pollList >> 8);
253 oBuffer[3] = (UInt8)(pollList & 0xff);
254
0b4e3aa0 255 localSendMiscCommand (kPMUpMgrADB, 4, oBuffer);
1c79356b
A
256 }
257 else { // disabling autopoll;
0b4e3aa0
A
258 /* Waits one second for the trackpads to be up (this is needed only in old machines)
259 This is placed here because this is the fist call at wake. */
260 if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'") ||
261 IODTMatchNubWithKeys(getPlatform()->getProvider(), "'AAPL,PowerBook1998'"))
262 IOSleep(1500);
263
264 localSendMiscCommand (kPMUpMgrADBoff, 0, NULL);
1c79356b
A
265 }
266
267 return kPMUNoError;
268}
269
270
271// **********************************************************************************
272// resetBus
273//
274// **********************************************************************************
275IOReturn IOPMUADBController::resetBus ( void )
276{
277 if (requestMutexLock != NULL)
278 IOLockLock(requestMutexLock);
279
280 UInt8 oBuffer[4];
0b4e3aa0 281
1c79356b
A
282 oBuffer[0] = kPMUResetADBBus;
283 oBuffer[1] = 0;
284 oBuffer[2] = 0;
285
286 // Reset bus needs to wait for the interrupt to terminate the transaction:
287 waitingForData = IOSyncer::create();
0b4e3aa0 288 localSendMiscCommand (kPMUpMgrADB, 3, oBuffer);
1c79356b
A
289 waitingForData->wait(); // wait till done
290 waitingForData = 0;
291
292 if (requestMutexLock != NULL)
293 IOLockUnlock(requestMutexLock);
0b4e3aa0
A
294
295 /* Waits one second for the trackpads to be up (this is needed only in old machines) */
296 if (IODTMatchNubWithKeys(getPlatform()->getProvider(), "'PowerBook1,1'") ||
297 IODTMatchNubWithKeys(getPlatform()->getProvider(), "'AAPL,PowerBook1998'"))
298 IOSleep(1500);
299
1c79356b
A
300 return kPMUNoError;
301}
302
303
304// **********************************************************************************
305// flushDevice
306//
307// **********************************************************************************
308IOReturn IOPMUADBController::flushDevice ( IOADBAddress address )
309{
310 if (requestMutexLock != NULL)
311 IOLockLock(requestMutexLock);
312
313 UInt8 oBuffer[4];
314
315 oBuffer[0] = kPMUFlushADB | (address << kPMUADBAddressField);
316 oBuffer[1] = ( autopollOn ? 2 : 0 );
317 oBuffer[2] = 0;
318
319 // flush device needs to wait for the interrupt to terminate the transaction
320 waitingForData = IOSyncer::create();
0b4e3aa0 321 localSendMiscCommand (kPMUpMgrADB, 3, oBuffer);
1c79356b
A
322 waitingForData->wait(); // wait till done
323 waitingForData = 0;
324
325 if (requestMutexLock != NULL)
326 IOLockUnlock(requestMutexLock);
327
328 return kPMUNoError;
329}
330
331
332// **********************************************************************************
333// readFromDevice
334//
335// The length parameter is ignored on entry. It is set on exit to reflect
336// the number of bytes read from the device.
337// **********************************************************************************
338IOReturn IOPMUADBController::readFromDevice ( IOADBAddress address, IOADBRegister adbRegister,
339 UInt8 * data, IOByteCount * length )
340{
341 if ( (length == NULL) || (data == NULL) ) {
342 return kPMUParameterError;
343 }
344
345 if (requestMutexLock != NULL)
346 IOLockLock(requestMutexLock);
347
348 UInt8 oBuffer[4];
349
350 oBuffer[0] = kPMUReadADB | (address << kPMUADBAddressField) | (adbRegister);
351 oBuffer[1] = ( autopollOn ? 2 : 0 );
352 oBuffer[2] = 0;
353
354 // read from device needs to wait for the interrupt to terminate the transaction
355 // and to obtain the data from the device.
356 waitingForData = IOSyncer::create();
0b4e3aa0 357 localSendMiscCommand (kPMUpMgrADB, 3, oBuffer);
1c79356b
A
358 waitingForData->wait(); // wait till done
359 waitingForData = 0;
360
361 // set caller's length
362 *length = (dataLen < *length ? dataLen : *length);
363 bcopy(dataBuffer, data, *length);
364
365 if (requestMutexLock != NULL)
366 IOLockUnlock(requestMutexLock);
367
368 if (dataLen == 0 ) { // nothing read; device isn't there
369 return ADB_RET_NOTPRESENT;
370 }
371
372 return ADB_RET_OK;
373}
374
375
376// **********************************************************************************
377// writeToDevice
378//
379// **********************************************************************************
380IOReturn IOPMUADBController::writeToDevice ( IOADBAddress address, IOADBRegister adbRegister,
381 UInt8 * data, IOByteCount * length )
382{
383 // Last check on * length > (252): since the pmu registers are 8 bit
384 // and the buffer has the first 3 bytes used for the standard paramters
385 // the max lenght can not be more than 252 bytes.
386 if ( (* length == 0) || (data == NULL) || (* length > 252) )
387 {
388 return kPMUParameterError;
389 }
390
391 if (address == 0)
392 return kPMUNoError; // for now let's ignore these ...
393
394 if (requestMutexLock != NULL)
395 IOLockLock(requestMutexLock);
396
397 UInt8 oBuffer[256];
398
399 oBuffer[0] = kPMUWriteADB | (address << kPMUADBAddressField) | (adbRegister);
400 oBuffer[1] = ( autopollOn ? 2 : 0 );
401 oBuffer[2] = *length;
402 bcopy(data, &oBuffer[3], *length);
403
404 // write to the device needs to wait for the interrupt to terminate the transaction
405 waitingForData = IOSyncer::create();
0b4e3aa0 406 localSendMiscCommand (kPMUpMgrADB, 3 + *length, oBuffer);
1c79356b
A
407 waitingForData->wait();
408 waitingForData = 0;
409
410 if (requestMutexLock != NULL)
411 IOLockUnlock(requestMutexLock);
412
413 return kPMUNoError;
414}
415
416