Source to bsd/dev/ppc/adb.m
/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @[email protected]
*
* "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
* Reserved. This file contains Original Code and/or Modifications of
* Original Code as defined in and that are subject to the Apple Public
* Source License Version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. Please obtain a copy of the
* License at http://www.apple.com/publicsource and read it before using
* this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
* License for the specific language governing rights and limitations
* under the License."
*
* @[email protected]
*/
/*
* Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both the copyright notice and this permission notice appear in
* supporting documentation.
*
* OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
* NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
/*
* Copyright 1996 1995 by Apple Computer, Inc. 1997 1996 1995 1994 1993 1992 1991
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both the copyright notice and this permission notice appear in
* supporting documentation.
*
* APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
* NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* MKLINUX-1.0DR2
*/
/*
* ADB Driver - used internally by ADB device drivers
*
* Currently this is heavily tied to the design of
* the CUDA hardware and MACH driver
*/
#include <mach_kdb.h>
#include <mach/mach_types.h>
#include <machdep/ppc/powermac.h> //for HasPMU() definition
#include <sys/tty.h>
#include <sys/conf.h>
#include "busses.h"
#include "adb.h"
#include "adb_io.h"
#include "drvPMU/pmu.h"
void waitForCallback(void);
void ADBcallback(id, UInt32, UInt32, UInt8 *);
void ADBReadCallback(id, UInt32, UInt32, UInt8 *);
void ADBReadCallback2(id, UInt32, UInt32, UInt8 *);
void inputHandler(id, UInt32, UInt32, UInt32, UInt8*);
id PMUdriver = NULL;
UInt8 read_buffer[8];
int read_length;
boolean_t adb_initted = FALSE;
int adb_count = 0;
adb_request_t *adb_queue_root = NULL, *adb_queue_end = NULL;
#define ADB_POOL_COUNT 16
adb_device_t adb_devices[ADB_DEVICE_COUNT];
adb_request_t adb_async_requests[ADB_POOL_COUNT], *adb_async_pool;
boolean_t adb_hardware = FALSE;
void adbattach( struct bus_device *device);
int adbprobe(caddr_t addr, void *ui);
struct bus_device *adb_info[NADB];
void
InitializeADB(void)
{
if (adb_hardware == FALSE) {
[PMUdriver registerForADBAutopoll:inputHandler:(id)NULL];
adb_hardware = TRUE;
adbprobe(0, 0);
}
}
static int
adb_is_dev_present(unsigned short addr)
{
struct adb_device *devp = &adb_devices[addr];
unsigned short value;
int retval;
//kprintf("adb_is_dev_present: addr = %08x, devp = %08x\n", addr, devp);
retval = adb_readreg(addr, 3, &value);
//kprintf("adb_is_dev_present: retval = %08x, ADB_RET_TIMEOUT = %08x\n",
// retval, ADB_RET_TIMEOUT);
#if notdef_next // DEBUG
if (retval != ADB_RET_TIMEOUT)
printf("adb_is_dev_present(%2d) returned %d\n", addr, retval);
#endif /* DEBUG */
if (retval != ADB_RET_TIMEOUT) {
//kprintf("adb_is_dev_present: value = %08x\n", value);
devp->a_dev_addr = (value >> 8) & 0xf;
devp->a_dev_orighandler = devp->a_dev_handler = (value & 0xff);
devp->a_flags |= ADB_FLAGS_PRESENT;
return TRUE;
}
return FALSE;
}
int
adb_set_handler(struct adb_device *devp, int handler)
{
unsigned long retval;
unsigned short value;
retval = adb_readreg(devp->a_addr, 3, &value);
if (retval != ADB_RET_OK)
return( retval);
value = (value & 0xF000) | handler;
retval = adb_writereg(devp->a_addr, 3, value);
if (retval != ADB_RET_OK)
return( retval);
retval = adb_readreg(devp->a_addr, 3, &value);
if (retval != ADB_RET_OK)
return( retval);
if( (value & 0xFF) != handler)
retval = ADB_RET_UNEXPECTED_RESULT;
/* Update to new handler/id */
devp->a_dev_handler = (value & 0xff);
return( retval);
}
static void
adb_move_dev(unsigned short from, unsigned short to)
{
int addr;
adb_writereg(from, 3, ((to << 8) | 0xfe));
addr = adb_devices[to].a_addr;
adb_devices[to] = adb_devices[from];
adb_devices[to].a_addr = addr;
adb_devices[from].a_flags = 0;
return;
}
static boolean_t
adb_find_unresolved_dev(unsigned short *devnum)
{
int i;
struct adb_device *devp;
devp = &adb_devices[1];
for (i = 1; i < ADB_DEVICE_COUNT; i++, devp++) {
if (devp->a_flags & ADB_FLAGS_UNRESOLVED) {
*devnum = i;
return TRUE;
}
}
return FALSE;
}
static int
adb_find_freedev(void)
{
struct adb_device *devp;
int i;
for (i = ADB_DEVICE_COUNT-1; i >= 1; i--) {
devp = &adb_devices[i];
if ((devp->a_flags & ADB_FLAGS_PRESENT) == 0)
return i;
}
panic("ADB: Cannot find a free ADB slot for reassignment!");
return -1;
}
int
adbprobe(caddr_t addr, void *ui)
{
unsigned short devnum, freenum, devlist;
struct adb_device *devp;
int i;
spl_t s;
//kprintf("adbprobe: Begining\n");
if (adb_initted)
return 1;
//kprintf("adbprobe: Not initted\n");
for (i = 0; i < ADB_POOL_COUNT; i++) {
adb_async_requests[i].a_next = adb_async_pool;
adb_async_pool = &adb_async_requests[i];
}
s = spltty();
/* Kill the auto poll until a new dev id's have been setup */
if ( [PMUdriver ADBPollDisable:(UInt32)current_thread():0:ADBcallback] == kPMUNoError ) {
waitForCallback();
}
/*
* Send a ADB bus reset - reply is sent after bus has reset,
* so there is no need to wait for the reset to complete.
*/
if ( [PMUdriver ADBReset:(UInt32)current_thread():0:ADBcallback] == kPMUNoError ) {
waitForCallback();
}
/*
* Okay, now attempt reassign the
* bus
*/
//kprintf("adbprobe: probing\n");
/* Skip 0 -- its special! */
for (i = 1; i < ADB_DEVICE_COUNT; i++) {
adb_devices[i].a_addr = i;
//kprintf("adbprobe: probing %x\n", i);
if (adb_is_dev_present(i)) {
//kprintf("adbprobe: adb_is_dev_present\n");
adb_devices[i].a_dev_type = i;
adb_devices[i].a_flags |= ADB_FLAGS_UNRESOLVED;
}
}
/* Now attempt to reassign the addresses */
while (adb_find_unresolved_dev(&devnum)) {
freenum = adb_find_freedev();
adb_move_dev(devnum, freenum);
if (!adb_is_dev_present(freenum)) {
/* It didn't move.. damn! */
adb_devices[devnum].a_flags &= ~ADB_FLAGS_UNRESOLVED;
printf("WARNING : ADB DEVICE %d having problems "
"probing!\n", devnum);
continue;
}
if (!adb_is_dev_present(devnum)) {
/* no more at this address, good !*/
/* Move it back.. */
adb_move_dev(freenum, devnum);
/* Check the device to talk again.. */
(void) adb_is_dev_present(devnum);
adb_devices[devnum].a_flags &= ~ADB_FLAGS_UNRESOLVED;
} else {
/* Found another device at the address, leave
* the first device moved to one side and set up
* newly found device for probing
*/
/* device_present already called on freenum above */
adb_devices[freenum].a_flags &= ~ADB_FLAGS_UNRESOLVED;
/* device_present already called on devnum above */
adb_devices[devnum].a_dev_type = devnum;
adb_devices[devnum].a_flags |= ADB_FLAGS_UNRESOLVED;
#if 0
printf("Found hidden device at %d, previous device "
"moved to %d\n", devnum, freenum);
#endif /* DEBUG */
}
}
/*
* Now build up a dev list bitmap and total device count
*/
devp = adb_devices;
devlist = 0;
for (i = 0; i < ADB_DEVICE_COUNT; i++, devp++) {
if ((devp->a_flags & ADB_FLAGS_PRESENT) == 0)
continue;
devlist |= (1<<i);
adb_count++;
}
// ADBSetPollList calls the callback before it returns when
// autopolling is off.
if (HasPMU())
{
[PMUdriver ADBSetPollList:devlist:0:0:NULL];
//PG&E doesn't perform this hardware operation immediately
// so it's OK not to wait for callback
}
else
if ( [PMUdriver ADBSetPollList:devlist:(UInt32)current_thread():0:ADBcallback] == kPMUNoError)
{
waitForCallback();
}
if ( [PMUdriver ADBSetPollRate:11:(UInt32)current_thread():0:ADBcallback] == kPMUNoError ) {
waitForCallback();
}
if ( [PMUdriver ADBPollEnable:(UInt32)current_thread():0:ADBcallback] == kPMUNoError ) {
waitForCallback();
}
if ( [PMUdriver ADBSetFileServerMode:(UInt32)current_thread():0:ADBcallback] == kPMUNoError ) {
waitForCallback();
}
adb_initted = TRUE;
splx(s);
return 1;
}
void
adbattach( struct bus_device *device)
{
int i;
adb_device_t *devp = &adb_devices[0];
printf("\nadb0: %d devices on bus.\n", adb_count);
for (i = 0; i < ADB_DEVICE_COUNT; i++, devp++) {
if (devp->a_flags & ADB_FLAGS_PRESENT) {
printf(" %d: ", i);
switch (devp->a_dev_type) {
case ADB_DEV_PROTECT:
printf("security device");
break;
case ADB_DEV_KEYBOARD:
printf("keyboard");
break;
case ADB_DEV_MOUSE:
printf("mouse");
break;
case ADB_DEV_TABLET:
printf("tablet");
break;
case ADB_DEV_MODEM:
printf("modem");
break;
case ADB_DEV_APPL:
printf("application device");
break;
default:
printf("unknown device id=%d", i);
}
printf("\n");
}
}
}
/*
* adbopen
*
*/
io_return_t
adbopen(dev_t dev, dev_mode_t flag, io_req_t ior)
{
return D_SUCCESS;
}
void
adbclose(dev_t dev)
{
return;
}
io_return_t
adbread(dev_t dev, io_req_t ior)
{
return D_INVALID_OPERATION;
}
io_return_t
adbwrite(dev_t dev, io_req_t ior)
{
return D_INVALID_OPERATION;
}
boolean_t
adbportdeath(dev_t dev, ipc_port_t port)
{
return FALSE;
}
#if 0
io_return_t
adbgetstatus(dev_t dev, dev_flavor_t flavor, dev_status_t data,
mach_msg_type_number_t *status_count)
{
/* DS1
struct adb_info *info = (struct adb_info *) data;
struct adb_device *devp;
int i;
switch (flavor) {
case ADB_GET_INFO:
devp = adb_devices;
for (i = 0; i < ADB_DEVICE_COUNT; i++, devp++) {
if ((devp->a_flags & ADB_FLAGS_PRESENT) == 0)
continue;
info->a_addr = devp->a_addr;
info->a_type = devp->a_dev_type;
info->a_handler = devp->a_dev_handler;
info->a_orighandler = devp->a_dev_orighandler;
info++;
}
*status_count = (sizeof(struct adb_info)*adb_count)/sizeof(int);
break;
case ADB_GET_COUNT:
*((unsigned int *) data) = adb_count;
*status_count = 1;
break;
case ADB_READ_DATA: {
struct adb_regdata *reg = (struct adb_regdata *) data;
reg->a_count = adb_reg_data.a_reply.a_bcount;
bcopy((char *) adb_reg_data.a_reply.a_buffer,
(char *) reg->a_buffer, adb_reg_data.a_reply.a_bcount);
*status_count = (sizeof(struct adb_regdata))/sizeof(int);
}
break;
default:
return D_INVALID_OPERATION;
}
DS1 */
return D_SUCCESS;
}
io_return_t
adbsetstatus(dev_t dev, dev_flavor_t flavor, dev_status_t data,
mach_msg_type_number_t status_count)
{
/* DS1
struct adb_info *info = (struct adb_info *) data;
struct adb_device *devp;
switch (flavor) {
case ADB_SET_HANDLER:
if (info->a_addr < 1 || info->a_addr >= ADB_DEVICE_COUNT)
return D_NO_SUCH_DEVICE;
devp = &adb_devices[info->a_addr];
adb_set_handler(devp, info->a_handler);
if (devp->a_dev_handler != info->a_handler)
return D_READ_ONLY;
break;
case ADB_READ_REG: {
struct adb_regdata *reg = (struct adb_regdata *) data;
adb_init_request(&adb_reg_data);
ADB_BUILD_CMD2(&adb_reg_data, ADB_PACKET_ADB,
(ADB_ADBCMD_READ_ADB|(reg->a_addr<<4)|reg->a_reg));
adb_send(&adb_reg_data, TRUE);
if (adb_reg_data.a_result != ADB_RET_OK)
return D_IO_ERROR;
}
break;
case ADB_WRITE_REG: {
struct adb_regdata *reg = (struct adb_regdata *) data;
adb_init_request(&adb_reg_data);
ADB_BUILD_CMD2_BUFFER(&adb_reg_data, ADB_PACKET_ADB,
(ADB_ADBCMD_WRITE_ADB|(reg->a_addr<<4)|reg->a_reg),
reg->a_count, ®->a_buffer);
adb_send(&adb_reg_data, TRUE);
if (adb_reg_data.a_result != ADB_RET_OK)
return D_IO_ERROR;
}
break;
default:
return D_INVALID_OPERATION;
}
DS1 */
return D_SUCCESS;
}
#endif
/*
* Register a routine which is to send events from all
* devices matching a given type.
*/
void
adb_register_handler(int type,
void (*handler)(int number, unsigned char *packet, int count, void * ssp))
{
int dev;
adb_device_t *devp;
//kprintf("adb_register_handler: type = %08x, handler = %08x\n",
// type, handler);
for (dev = 0; dev < ADB_DEVICE_COUNT; dev++) {
devp = &adb_devices[dev];
//kprintf("adb_register_handler: dev = %08x, devp = %08x, devp->a_dev_type = %08x\n", dev, devp, devp->a_dev_type);
if (devp->a_dev_type != type)
continue;
devp->a_flags |= ADB_FLAGS_REGISTERED;
devp->a_handler = handler;
}
}
/*
* Register a routine to handle a dev at a specific address
*/
void
adb_register_dev(int devnum, void (*handler)(int number, unsigned char *packet, int count, void * ssp))
{
adb_device_t *devp;
if (devnum < 0 || devnum > ADB_DEVICE_COUNT)
panic("adb_register: addr is out of range.");
devp = &adb_devices[devnum];
devp->a_flags |= ADB_FLAGS_REGISTERED;
devp->a_handler = handler;
}
static void (*oldHandlers[ ADB_DEVICE_COUNT ])(int number, unsigned char *buffer, int bytes, void * ssp);
void
borrow_adb( void (*handler)(int number, unsigned char *packet, int count, void * ssp))
{
int dev;
adb_device_t *devp;
for (dev = 1; dev < ADB_DEVICE_COUNT; dev++) {
devp = &adb_devices[dev];
if( devp->a_flags & ADB_FLAGS_REGISTERED)
oldHandlers[ dev] = devp->a_handler;
else
oldHandlers[ dev] = 0;
devp->a_flags |= ADB_FLAGS_REGISTERED;
devp->a_handler = handler;
}
}
void
return_adb( void )
{
int dev;
adb_device_t *devp;
for (dev = 1; dev < ADB_DEVICE_COUNT; dev++) {
devp = &adb_devices[dev];
if( oldHandlers[ dev] ) {
devp->a_flags |= ADB_FLAGS_REGISTERED;
devp->a_handler = oldHandlers[ dev];
} else
devp->a_flags &= ~ADB_FLAGS_REGISTERED;
}
}
#if 0
/* DS2...
void
adb_done(adb_request_t *req)
{
adb_packet_t *pack = &req->a_reply;
DS2 */
/* Note, adb_busy is not reset because the CUDA chip
* needs time to settle back into an idle state.
* adb_busy will be reset in adb_next_request() when
* the CUDA driver is ready for the next one.
*/
/* DS2
if (req->a_flags & ADB_IS_ASYNC) {
req->a_next = adb_async_pool;
adb_async_pool = req;
return;
}
req->a_flags |= ADB_DONE;
if (!adb_polling) {
if (req->a_done)
req->a_done(req);
else thread_wakeup((event_t) req);
}
}
void
adb_unsolicited_done(adb_packet_t *pack, void * ssp)
{
adb_device_t *devp;
int devnum;
DS2 */
/* adb_next_request() will reset this when CUDA
* asks for the next request.. until then the bus
* has to become idle
*/
/* DS2
adb_busy = TRUE;
devnum = pack->a_header[2] >> 4;
devp = &adb_devices[devnum];
if (devp->a_flags & ADB_FLAGS_REGISTERED)
devp->a_handler(devnum, pack->a_buffer, pack->a_bcount, ssp);
}
...DS2 */
#endif
int
adb_readreg(int number, int reg, unsigned short *value)
{
if ([PMUdriver ADBRead:number :reg :(UInt32)current_thread() :0 :ADBReadCallback] != kPMUNoError) {
return ADB_RET_UNEXPECTED_RESULT;
}
waitForCallback();
if ( read_length ) {
*value = (read_buffer[0] << 8) | read_buffer[1];
return ADB_RET_OK;
}
else {
return ADB_RET_TIMEOUT;
}
}
int
adb_readreg2(int number, int reg, unsigned char *buffer, int *length)
{
if ([PMUdriver ADBRead:number :reg :(UInt32)current_thread() :0 :ADBReadCallback2] != kPMUNoError) {
return ADB_RET_UNEXPECTED_RESULT;
}
waitForCallback();
*length = read_length;
if ( read_length ) {
int i;
for ( i = 0; i < read_length; i++ ) {
buffer[i] = read_buffer[i];
}
if ( reg == 3 ) { // snoop on reads from reg 3
adb_devices[number].a_dev_handler = read_buffer[1];
}
return ADB_RET_OK;
}
else {
return ADB_RET_TIMEOUT;
}
}
int
adb_flush(int number)
{
if ([PMUdriver ADBFlush: number :(UInt32)current_thread() :0 :ADBReadCallback] != kPMUNoError) {
return ADB_RET_UNEXPECTED_RESULT;
}
waitForCallback();
return ADB_RET_OK;
}
int
adb_writereg(int number, int reg, unsigned short value)
{
UInt8 buffer[2];
buffer[0] = value >> 8;
buffer[1] = value & 0xff;
if ([PMUdriver ADBWrite:number :reg :2 :buffer :(UInt32)current_thread() :0 :ADBcallback] != kPMUNoError) {
return ADB_RET_UNEXPECTED_RESULT;
}
waitForCallback();
return ADB_RET_OK;
}
int
adb_writereg2(int number, int reg, unsigned char *buffer, int length)
{
if ([PMUdriver ADBWrite:number :reg :length :buffer :(UInt32)current_thread() :0 :ADBcallback] != kPMUNoError) {
return ADB_RET_UNEXPECTED_RESULT;
}
waitForCallback();
return ADB_RET_OK;
}
void
adb_writereg_async(int number, int reg, unsigned short value)
{
UInt8 buffer[2];
buffer[0] = value >> 8;
buffer[1] = value & 0xff;
if ([PMUdriver ADBWrite:number :reg :2 :buffer :0 :0:NULL] != kPMUNoError) {
return;
}
return;
}
#if 0
/* DS1
void
adb_send(adb_request_t *adb, boolean_t wait)
{
spl_t s;
if (!adb_polling)
s = spltty();
adb->a_reply.a_bsize = sizeof(adb->a_reply.a_buffer);
if (wait)
adb->a_done = NULL;
adb->a_flags &= ~ADB_DONE;
adb->a_next = NULL;
if (adb_busy) {
if (adb_queue_root == NULL)
adb_queue_root = adb_queue_end = adb;
else {
adb_queue_end->a_next = adb;
adb_queue_end = adb;
}
if (adb_polling) {
adb_hardware->ao_poll();
if ((adb->a_flags & ADB_DONE) == 0)
panic("adb_send: request did not complete?!?");
}
} else {
adb_busy = TRUE;
adb_hardware->ao_send(adb);
}
if (wait && !adb_polling) {
simple_lock(&adb->a_lock);
// simon: was thread_sleep_simple_lock
thread_sleep((event_t) adb, simple_lock_addr(adb->a_lock), TRUE);
}
if (!adb_polling)
splx(s);
}
adb_request_t *
adb_next_request()
{
adb_request_t *adb;
adb = adb_queue_root;
if (adb) {
adb_queue_root = adb_queue_root->a_next;
if (adb_queue_root == NULL)
adb_queue_end = NULL;
adb_busy = TRUE;
} else adb_busy = FALSE;
return adb;
}
void
adb_poll(void)
{
boolean_t save_poll = adb_polling;
adb_polling = TRUE;
adb_hardware->ao_poll();
adb_polling = save_poll;
}
DS1 */
#endif
// The PMU driver is finished sending the last command.
// Wake up the thread that is waiting.
void ADBcallback(id unused, UInt32 refnum, UInt32 length, UInt8* buffer)
{
clear_wait(refnum,0,FALSE);
}
// The PMU driver has received data from the PMU that is the result of our
// previous read. Copy the data and wake up the thread.
void ADBReadCallback(id unused, UInt32 refnum, UInt32 length, UInt8* buffer)
{
if (buffer != NULL) {
read_buffer[0] = *buffer;
read_buffer[1] = *(buffer+1);
}
read_length = length;
clear_wait(refnum,0,FALSE);
}
// The PMU driver has received data from the PMU that is the result of our
// previous read. Copy the data and wake up the thread.
void ADBReadCallback2(id unused, UInt32 refnum, UInt32 length, UInt8* buffer)
{
int i;
for ( i = 0; i < length; i++ ) {
read_buffer[i] = buffer[i];
}
read_length = length;
clear_wait(refnum,0,FALSE);
}
// We have sent a command to the PMU driver with current_thread as the refnum.
// Sleep until it has sent the command to the PMU.
void waitForCallback(void)
{
assert_wait(current_thread(), FALSE);
thread_block();
}
// Called by the keyboard driver. Interrupts are off. Call PMU/Cuda
// to let it service any interrupts.
void CheckADBPoll(void)
{
[PMUdriver poll_device];
}
// Autopoll data has arrived from the PMU.
void inputHandler(id unused, UInt32 refnum, UInt32 devnum, UInt32 length, UInt8* buffer)
{
adb_device_t *devp;
//kprintf("inputHandler: refnum: %08x, devnum = %08x, length = %08x, buffer = %08x\n", refnum, devnum, length, buffer);
//kprintf("buffer[0] = %02x, buffer[1] = %02x\n", buffer[0], buffer[1]);
devp = &adb_devices[devnum];
//kprintf("devp = %08x, devp->a_handler = %08x\n", devp, devp->a_handler);
if (devp->a_flags & ADB_FLAGS_REGISTERED) {
devp->a_handler(devnum, buffer, length, 0);
}
}