2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * 12 Nov 1998 suurballe Created.
26 #include <IOKit/IOSyncer.h>
27 #include "IOPMUADBController.h"
29 #define super IOADBController
30 OSDefineMetaClassAndStructors(IOPMUADBController
, IOADBController
)
32 // **********************************************************************************
35 // **********************************************************************************
36 IOService
* IOPMUADBController::probe( IOService
* provider
, SInt32
* score
)
38 if (super::probe(provider
, score
) == NULL
)
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'"))
47 // If it is a different machine the compatible property will tell us if it is a pmu-driven
49 OSData
*kl
= OSDynamicCast(OSData
, provider
->getProperty("compatible"));
50 if ((kl
!= NULL
) && kl
->isEqualTo("pmu", 3))
53 // In all the other cases we do not handle it:
57 // **********************************************************************************
60 // **********************************************************************************
61 bool IOPMUADBController::start ( IOService
* nub
)
63 // Wait for the PMU to show up:
64 PMUdriver
= waitForService(serviceMatching("ApplePMU"));
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
;
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
80 // Creates the mutex lock to protect the clients list:
81 requestMutexLock
= NULL
;
82 requestMutexLock
= IOLockAlloc();
83 if (!requestMutexLock
)
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
))
94 // **********************************************************************************
97 // **********************************************************************************
98 void IOPMUADBController::free ( )
100 // Releases the mutex lock used to protect the clients lists:
101 if (requestMutexLock
!= NULL
) {
102 IOLockFree (requestMutexLock
);
103 requestMutexLock
= NULL
;
106 // And removes the interrupt handler:
107 if (PMUdriver
!= NULL
)
108 PMUdriver
->callPlatformFunction("deRegisterClient", true, (void*)this, (void*)kPMUADBint
, NULL
, NULL
);
111 // **********************************************************************************
112 // localSendMiscCommand
114 // **********************************************************************************
115 IOReturn
IOPMUADBController::localSendMiscCommand(int command
, IOByteCount sLength
, UInt8
*sBuffer
, IOByteCount
*rLength
, UInt8
*rBuffer
)
117 IOReturn returnValue
= kIOReturnError
;
119 // The poupose of this method is to free us from the pain to create a parameter block each time
120 // we wish to talk to the pmu:
121 SendMiscCommandParameterBlock prmBlock
= {command
, sLength
, sBuffer
, rLength
, rBuffer
};
123 #ifdef VERBOSE_LOGS_ON
124 IOLog("ApplePMUInterface::localSendMiscCommand 0x%02x %d 0x%08lx 0x%08lx 0x%08lx\n",
125 command
, sLength
, sBuffer
, rLength
, rBuffer
);
128 if (PMUdriver
!= NULL
) {
129 #ifdef VERBOSE_LOGS_ON
130 IOLog("IOPMUADBController::localSendMiscCommand calling PMUdriver->callPlatformFunction\n");
132 returnValue
= PMUdriver
->callPlatformFunction("sendMiscCommand", true, (void*)&prmBlock
, NULL
, NULL
, NULL
);
135 // If we are here we do not have a dreive to talk to:
136 #ifdef VERBOSE_LOGS_ON
137 IOLog("IOPMUADBController::localSendMiscCommand end 0x%08lx\n", returnValue
);
143 // **********************************************************************************
144 // this is the interrupt handler for all ADB interrupts:
146 // **********************************************************************************
149 IOPMUADBController::handleADBInterrupt(IOService
*client
, UInt8 interruptMask
, UInt32 length
, UInt8
*buffer
)
151 if (interruptMask
& kPMUautopoll
)
152 autopollHandler(client
, buffer
[0], length
- 1, buffer
+ 1); // yes, call adb input handler
154 IOPMUADBController
*myThis
= OSDynamicCast(IOPMUADBController
, client
);
156 if ((myThis
!= NULL
) && (myThis
->waitingForData
!= NULL
)) {
157 // Complets the adb transaction
158 myThis
->dataLen
= length
- 1;
159 bcopy(buffer
+ 1, myThis
->dataBuffer
, myThis
->dataLen
);
160 myThis
->waitingForData
->signal();
165 // **********************************************************************************
168 // **********************************************************************************
169 IOReturn
IOPMUADBController::setAutoPollPeriod ( int )
171 return kPMUNotSupported
;
175 // **********************************************************************************
178 // **********************************************************************************
179 IOReturn
IOPMUADBController::getAutoPollPeriod ( int * )
181 return kPMUNotSupported
;
185 // **********************************************************************************
188 // **********************************************************************************
189 IOReturn
IOPMUADBController::setAutoPollList ( UInt16 PollBitField
)
191 pollList
= PollBitField
; // remember the new poll list
196 oBuffer
[0] = 0; // Byte count in the resto of the command
197 oBuffer
[1] = 0x86; // adb Command op.
198 oBuffer
[2] = (UInt8
)(PollBitField
>> 8); // ??
199 oBuffer
[3] = (UInt8
)(PollBitField
& 0xff); // ??
201 localSendMiscCommand (kPMUpMgrADB
, 4, oBuffer
, NULL
, NULL
);
207 // **********************************************************************************
210 // **********************************************************************************
211 IOReturn
IOPMUADBController::getAutoPollList ( UInt16
* activeAddressMask
)
213 *activeAddressMask
= pollList
;
218 // **********************************************************************************
221 // **********************************************************************************
222 IOReturn
IOPMUADBController::setAutoPollEnable ( bool enable
)
226 if ( enable
) { // enabling autopoll
229 oBuffer
[2] = (UInt8
)(pollList
>> 8);
230 oBuffer
[3] = (UInt8
)(pollList
& 0xff);
232 localSendMiscCommand (kPMUpMgrADB
, 4, oBuffer
, NULL
,NULL
);
235 else { // disabling autopoll;
236 localSendMiscCommand (kPMUpMgrADBoff
, 0, NULL
, NULL
, NULL
);
243 // **********************************************************************************
246 // **********************************************************************************
247 IOReturn
IOPMUADBController::resetBus ( void )
249 if (requestMutexLock
!= NULL
)
250 IOLockLock(requestMutexLock
);
254 oBuffer
[0] = kPMUResetADBBus
;
258 // Reset bus needs to wait for the interrupt to terminate the transaction:
259 waitingForData
= IOSyncer::create();
260 localSendMiscCommand (kPMUpMgrADB
, 3, oBuffer
, NULL
, NULL
);
261 waitingForData
->wait(); // wait till done
264 if (requestMutexLock
!= NULL
)
265 IOLockUnlock(requestMutexLock
);
271 // **********************************************************************************
274 // **********************************************************************************
275 IOReturn
IOPMUADBController::flushDevice ( IOADBAddress address
)
277 if (requestMutexLock
!= NULL
)
278 IOLockLock(requestMutexLock
);
282 oBuffer
[0] = kPMUFlushADB
| (address
<< kPMUADBAddressField
);
283 oBuffer
[1] = ( autopollOn
? 2 : 0 );
286 // flush device needs to wait for the interrupt to terminate the transaction
287 waitingForData
= IOSyncer::create();
288 localSendMiscCommand (kPMUpMgrADB
, 3, oBuffer
, NULL
, NULL
);
289 waitingForData
->wait(); // wait till done
292 if (requestMutexLock
!= NULL
)
293 IOLockUnlock(requestMutexLock
);
299 // **********************************************************************************
302 // The length parameter is ignored on entry. It is set on exit to reflect
303 // the number of bytes read from the device.
304 // **********************************************************************************
305 IOReturn
IOPMUADBController::readFromDevice ( IOADBAddress address
, IOADBRegister adbRegister
,
306 UInt8
* data
, IOByteCount
* length
)
308 if ( (length
== NULL
) || (data
== NULL
) ) {
309 return kPMUParameterError
;
312 if (requestMutexLock
!= NULL
)
313 IOLockLock(requestMutexLock
);
317 oBuffer
[0] = kPMUReadADB
| (address
<< kPMUADBAddressField
) | (adbRegister
);
318 oBuffer
[1] = ( autopollOn
? 2 : 0 );
321 // read from device needs to wait for the interrupt to terminate the transaction
322 // and to obtain the data from the device.
323 waitingForData
= IOSyncer::create();
324 localSendMiscCommand (kPMUpMgrADB
, 3, oBuffer
, NULL
, NULL
);
325 waitingForData
->wait(); // wait till done
328 // set caller's length
329 *length
= (dataLen
< *length
? dataLen
: *length
);
330 bcopy(dataBuffer
, data
, *length
);
332 if (requestMutexLock
!= NULL
)
333 IOLockUnlock(requestMutexLock
);
335 if (dataLen
== 0 ) { // nothing read; device isn't there
336 return ADB_RET_NOTPRESENT
;
343 // **********************************************************************************
346 // **********************************************************************************
347 IOReturn
IOPMUADBController::writeToDevice ( IOADBAddress address
, IOADBRegister adbRegister
,
348 UInt8
* data
, IOByteCount
* length
)
350 // Last check on * length > (252): since the pmu registers are 8 bit
351 // and the buffer has the first 3 bytes used for the standard paramters
352 // the max lenght can not be more than 252 bytes.
353 if ( (* length
== 0) || (data
== NULL
) || (* length
> 252) )
355 return kPMUParameterError
;
359 return kPMUNoError
; // for now let's ignore these ...
361 if (requestMutexLock
!= NULL
)
362 IOLockLock(requestMutexLock
);
366 oBuffer
[0] = kPMUWriteADB
| (address
<< kPMUADBAddressField
) | (adbRegister
);
367 oBuffer
[1] = ( autopollOn
? 2 : 0 );
368 oBuffer
[2] = *length
;
369 bcopy(data
, &oBuffer
[3], *length
);
371 // write to the device needs to wait for the interrupt to terminate the transaction
372 waitingForData
= IOSyncer::create();
373 localSendMiscCommand (kPMUpMgrADB
, 3 + *length
, oBuffer
, NULL
, NULL
);
374 waitingForData
->wait();
377 if (requestMutexLock
!= NULL
)
378 IOLockUnlock(requestMutexLock
);