Annotation of kernel/bsd/dev/ppc/drvPMU/pmu.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: #import "pmu.h"
                     26: #import "pmupriv.h"
                     27: #import "pmumisc.h"
                     28: #import "pmutables.h"
                     29: #import <kern/clock.h>
                     30: #import <kernserv/prototypes.h>
                     31: #import <kernserv/clock_timer.h>
                     32: #import <kernserv/ns_timer.h>
                     33: #import <bsd/sys/time.h>
                     34: #import <sys/callout.h>
                     35: #import <machdep/ppc/proc_reg.h>
                     36: #import <driverkit/generalFuncs.h>
                     37: #import <driverkit/kernelDriver.h>
                     38: #import <driverkit/interruptMsg.h>
                     39: 
                     40: // extern to let us fix up the boot time.
                     41: extern void set_boot_time(void);
                     42: 
                     43: void gotInterruptCause(id, UInt32, UInt32, UInt8 *);
                     44: void timer_expired(port_t mach_port);
                     45: 
                     46: extern void kprintf(const char *, ...);
                     47: extern void bcopy(void *, void *, int);
                     48: extern msg_send_from_kernel(msg_header_t *, int, int);
                     49: 
                     50: extern id ApplePMUId;
                     51: 
                     52: @implementation ApplePMU
                     53: 
                     54: // **********************************************************************************
                     55: // probe
                     56: //
                     57: // 
                     58: //
                     59: // **********************************************************************************
                     60: + (Boolean) probe : deviceDescription
                     61: {
                     62:   id dev;
                     63: kprintf("PMU probe\n");
                     64:   if ( (dev = [ self alloc ]) == nil ) {
                     65:     return NO;
                     66:   }
                     67:   
                     68:   if ([dev initFromDeviceDescription:deviceDescription] == nil) {
                     69:     return NO;
                     70:   }
                     71:   
                     72:   ApplePMUId = dev;
                     73:   
                     74:   set_boot_time();
                     75: 
                     76:   return YES;
                     77: }
                     78: 
                     79: 
                     80: 
                     81: 
                     82: // **********************************************************************************
                     83: // initFromDeviceDescription
                     84: //
                     85: // 
                     86: //
                     87: // **********************************************************************************
                     88: - initFromDeviceDescription:(IODeviceDescription *)deviceDescription
                     89: {
                     90:   VIAAddress     physicalAddress;
                     91:   IORange         *ioRange;
                     92:   PMUmachMessage  theRequest;
                     93:   unsigned int    *oldIRQs, newIRQs[2], tmpIRQ;
                     94:   
                     95:   
                     96:   if ( [super initFromDeviceDescription:deviceDescription] == nil ) {
                     97:     [self free];
                     98:     return nil;
                     99:   }
                    100:   
                    101:   [self setDeviceKind:"PM Subsystem"];
                    102:   [self setLocation:NULL];
                    103:   [self setName:"PMU"];
                    104:   
                    105:   ioRange = [deviceDescription memoryRangeList];
                    106:   physicalAddress = (VIAAddress)ioRange->start;
                    107:   
                    108:   VIA1_shift           = physicalAddress + 0x1400; // initialize VIA addresses
                    109:   VIA1_auxillaryControl = physicalAddress + 0x1600;
                    110:   VIA1_interruptFlag   = physicalAddress + 0x1A00;
                    111:   VIA1_interruptEnable = physicalAddress + 0x1C00;
                    112: // VIA2_dataB          = physicalAddress + 0x2000;             // 5300
                    113: // PMreq               = 1 << M2Req;
                    114: // PMack               = 1 << M2Ack;
                    115:   VIA2_dataB           = physicalAddress + 0x0000; // Hooper uses VIA 1 instead
                    116:   PMreq                        = 1 << HooperReq;           // and different bits in it as well
                    117:   PMack                        = 1 << HooperAck;
                    118:   // initialize other variables
                    119:   ADBclient = NULL;
                    120:   RTCclient = NULL;
                    121:   debugging = FALSE;
                    122:   queueHead = NULL;
                    123:   queueTail = NULL;
                    124:   PGE_ISR_state = kPMUidle;
                    125:   pollList = 0;
                    126:   autopollOn = FALSE;
                    127:   adb_reading = FALSE;
                    128:   PMU_int_pending = FALSE;
                    129: 
                    130:   adb_read_timeout = 100000000;
                    131: 
                    132:   [self AcknowledgePMUInterrupt];                              // turn off any pending PGE interrupt
                    133:   [self EnablePMUInterrupt];                                   // enable PGE interrupts
                    134: 
                    135:   // This is a still sleazy hack...
                    136:   oldIRQs = [deviceDescription interruptList];
                    137: 
                    138:   // This is another sleazy hack. The second irq is two lower in the via table.
                    139:   tmpIRQ = ((*oldIRQs ^ 0x18) + 2) ^ 0x18;
                    140: 
                    141:   newIRQs[0] = *oldIRQs;
                    142:   newIRQs[1] = tmpIRQ;
                    143: 
                    144:   [deviceDescription setInterruptList:newIRQs num:2];
                    145: 
                    146:   [self enableAllInterrupts];
                    147: 
                    148:   if ([self startIOThread] != IO_R_SUCCESS) {
                    149:     [self free];
                    150:     return nil;
                    151:   }
                    152: 
                    153:   port = IOConvertPort([self interruptPort],IO_KernelIOTask,IO_Kernel);
                    154:   
                    155:   theRequest.msgBody.pmCommand = kPMUSetModem1SecInt;             // tell PGE why it may interrupt
                    156:   theRequest.msgBody.pmFlag = FALSE;
                    157:   theRequest.msgBody.pmSLength1 = 1;
                    158:   theRequest.msgBody.pmSBuffer1[0] = kPMUMD2Int | kPMUbrightnessInt | kPMUADBint;
                    159:   theRequest.msgBody.pmSLength2 = 0;
                    160:   theRequest.msgBody.pmCallback = NULL;
                    161:   
                    162:   theRequest.msgHeader.msg_simple = TRUE;
                    163:   theRequest.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    164:   theRequest.msgHeader.msg_remote_port = port;
                    165:   theRequest.msgHeader.msg_local_port = PORT_NULL;
                    166:   theRequest.msgHeader.msg_size = sizeof(PMUmachMessage);
                    167:   msg_send_from_kernel(&theRequest.msgHeader, MSG_OPTION_NONE, 0);
                    168:   
                    169:   theRequest.msgBody.pmCommand = kPMUreadINT;                     // read any pending interrupt from PGE
                    170:   theRequest.msgBody.pmFlag = FALSE;
                    171:   theRequest.msgBody.pmSLength1 = 0;                              // just to clear it
                    172:   theRequest.msgBody.pmSLength2 = 0;
                    173:   theRequest.msgBody.pmRBuffer = &interruptState[0];
                    174:   theRequest.msgBody.pmCallback = NULL;
                    175:   
                    176:   theRequest.msgHeader.msg_simple = TRUE;
                    177:   theRequest.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    178:   theRequest.msgHeader.msg_remote_port = port;
                    179:   theRequest.msgHeader.msg_local_port = PORT_NULL;
                    180:   theRequest.msgHeader.msg_size = sizeof(PMUmachMessage);
                    181:   msg_send_from_kernel(&theRequest.msgHeader, MSG_OPTION_NONE, 0);
                    182: 
                    183:   [self registerDevice];
                    184: 
                    185:   return self;
                    186: }
                    187: 
                    188: 
                    189: // **********************************************************************************
                    190: // free
                    191: //
                    192: // 
                    193: //
                    194: // **********************************************************************************
                    195: - free
                    196: {
                    197: return [ super free ];
                    198: }
                    199: 
                    200: 
                    201: 
                    202: 
                    203: 
                    204: // **********************************************************************************
                    205: // poll_device
                    206: //
                    207: // System interrupts are disabled, but we are still operating the PMU for mini-
                    208: // monitor keyboard input.  We are called here in a loop to service the PMU.
                    209: //
                    210: // **********************************************************************************
                    211: - (void)poll_device
                    212: {
                    213:   if ( *VIA1_interruptFlag & 0x04 ) {   // is shift register done? ( ifSR )
                    214:     [self interruptOccurred];          // yes, handle it
                    215:     return;
                    216:   }
                    217:   if ( *VIA1_interruptFlag & 0x10 ) {  // is PMU requesting service? ( ifCB1 )
                    218:     *VIA1_interruptFlag = 0x10;        // yes, clear interrupt ( ifCB1 )
                    219:     PGE_ISR_state = kPMUidle;          // and handle it
                    220:     [self interruptOccurredAt:1];
                    221:   }
                    222: }
                    223: 
                    224: 
                    225: // **********************************************************************************
                    226: // receiveMsg
                    227: //
                    228: // 
                    229: //
                    230: // **********************************************************************************
                    231: - (void)receiveMsg
                    232: {
                    233: PMUmachMessage * toQueue;
                    234: IOReturn result;
                    235: if ( (PGE_ISR_state == kPMUidle) && !adb_reading ) {
                    236:        localMachMessage.msgHeader.msg_size = sizeof(PMUmachMessage);
                    237:         localMachMessage.msgHeader.msg_local_port = [self interruptPort];
                    238:        result = msg_receive(&localMachMessage.msgHeader, (msg_option_t)RCV_TIMEOUT, 0);
                    239:        if ( result == RCV_SUCCESS ) {
                    240:                [self StartPMUTransmission:&localMachMessage.msgBody];
                    241:                }
                    242:        }
                    243: else {
                    244:        toQueue = (PMUmachMessage*)kalloc(sizeof(PMUmachMessage));
                    245:         toQueue->msgHeader.msg_size = sizeof(PMUmachMessage);
                    246:         toQueue->msgHeader.msg_local_port = [self interruptPort];
                    247:         result = msg_receive(&toQueue->msgHeader, (msg_option_t)RCV_TIMEOUT, 0);
                    248:         if ( result == RCV_SUCCESS ) {
                    249:                toQueue->msgBody.prev = queueTail;
                    250:                toQueue->msgBody.next = NULL;
                    251:                if ( queueTail != NULL ) {
                    252:                        queueTail->msgBody.next = toQueue;
                    253:                        }
                    254:                else {
                    255:                        queueHead = toQueue;
                    256:                        }
                    257:                queueTail = toQueue;
                    258:                }
                    259:        }
                    260: }
                    261: 
                    262: 
                    263: // **********************************************************************************
                    264: // timeoutOccurred
                    265: //
                    266: // Our adb-read timer has expired after sending an adb-read command to the PMU.
                    267: // This means there is no such addressed device on the ADB bus.
                    268: // We call back to the ADB driver with a zero-characters-received response and
                    269: // dequeue our command queue and carry on.
                    270: // **********************************************************************************
                    271: - (void)timeoutOccurred
                    272: {
                    273: adb_reading = FALSE;
                    274: if ( clientRequest->pmCallback != NULL ) {             // Make the client callback
                    275:        clientRequest->pmCallback(clientRequest->pmId, clientRequest->pmRefNum, 0, NULL);
                    276:        }                                               // with zero received-length
                    277: [self CheckRequestQueue];
                    278: }
                    279: 
                    280: 
                    281: // ****************************************************************************
                    282: //      CheckRequestQueue
                    283: //      Called at interrupt time when current request is complete.  We may start
                    284: //      another request here if one is in queue, or we may re-enable PMU interrupts
                    285: //      (they were turned off in PMUStartIO) and return.
                    286: // ****************************************************************************
                    287: - (void)CheckRequestQueue
                    288: {
                    289: PMUmachMessage * nextRequest;
                    290: 
                    291: if ( queueHead == NULL ) {                             // is queue empty?
                    292:         [self EnablePMUInterrupt];                      // yes, enable interrupt and return
                    293:         }
                    294: else {
                    295:         nextRequest = queueHead;                        // no, dequeue first command
                    296:         queueHead = nextRequest->msgBody.next;
                    297:        if ( queueHead == NULL ) {
                    298:                queueTail = NULL;
                    299:                }
                    300:        bcopy (&nextRequest->msgBody, &localMachMessage.msgBody, sizeof(PMURequest));   // copy it
                    301:         kfree(nextRequest, sizeof(PMUmachMessage));                                    // free its memory
                    302:         [self StartPMUTransmission:&localMachMessage.msgBody];                         // and send it to the PMU
                    303:         }
                    304: }
                    305: 
                    306: 
                    307: // **********************************************************************************
                    308: // registerForADBAutopoll
                    309: //
                    310: // The ADB driver is calling to tell us that it is prepared to receive
                    311: // "unsolicited" ADB autopoll data.  The parameter tells who to call
                    312: // when we get some.
                    313: //
                    314: // **********************************************************************************
                    315: - (void)registerForADBAutopoll :(pmADBinput_func)InputHandler
                    316:                                :(id)caller
                    317: {
                    318: ADBclient = InputHandler;
                    319: ADBid = caller;
                    320: }
                    321: 
                    322: 
                    323: // **********************************************************************************
                    324: // ADBWrite
                    325: //
                    326: // **********************************************************************************
                    327: - (PMUStatus)ADBWrite  :(UInt32)DevAddr
                    328:                        :(UInt32)DevReg
                    329:                        :(UInt32)ByteCount
                    330:                        :(UInt8*)Buffer
                    331:                        :(UInt32)RefNum
                    332:                        :(id)Id
                    333:                        :(pmCallback_func)Callback
                    334: {
                    335: PMUmachMessage request;
                    336: msg_return_t   return_code;
                    337: 
                    338: if (   (ByteCount == 0) ||
                    339:        (Buffer == NULL) ||
                    340:        (ByteCount > (MISC_LENGTH-3) ) ) {
                    341:                return kPMUParameterError;
                    342:                }
                    343: 
                    344: request.msgBody.pmCommand = kPMUpMgrADB;
                    345: request.msgBody.pmFlag = TRUE;                 // this op solicits input from PGE
                    346: request.msgBody.pmSLength1 = 3;
                    347: request.msgBody.pmSBuffer2 = Buffer;
                    348: request.msgBody.pmSLength2 = ByteCount;
                    349: request.msgBody.pmRBuffer = NULL;
                    350: request.msgBody.pmCallback = Callback;
                    351: request.msgBody.pmId = Id;
                    352: request.msgBody.pmRefNum = RefNum;
                    353: request.msgBody.pmSBuffer1[0] = kPMUWriteADB | (DevAddr << kPMUADBAddressField) | (DevReg);
                    354: if ( autopollOn ) {
                    355:        request.msgBody.pmSBuffer1[1] = 2;
                    356:        }
                    357: else {
                    358:        request.msgBody.pmSBuffer1[1] = 0;
                    359:        }
                    360: request.msgBody.pmSBuffer1[2] = ByteCount;
                    361: 
                    362: request.msgHeader.msg_simple = TRUE;
                    363: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    364: request.msgHeader.msg_remote_port = port;
                    365: request.msgHeader.msg_local_port = PORT_NULL;
                    366: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    367: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    368: 
                    369: if ( return_code == SEND_SUCCESS ) {
                    370:        return kPMUNoError;
                    371:        }
                    372: else {
                    373:        return kPMUIOError;
                    374:        }
                    375: }
                    376: 
                    377: 
                    378: // **********************************************************************************
                    379: // ADBRead
                    380: //
                    381: // **********************************************************************************
                    382: - (PMUStatus)ADBRead   :(UInt32)DevAddr
                    383:                        :(UInt32)DevReg
                    384:                        :(UInt32)RefNum
                    385:                         :(id)Id
                    386:                        :(pmCallback_func)Callback
                    387: {
                    388: PMUmachMessage request;
                    389: msg_return_t   return_code;
                    390: 
                    391: request.msgBody.pmCommand = kPMUpMgrADB;
                    392: request.msgBody.pmFlag = TRUE;                 // this op solicits input from PGE
                    393: request.msgBody.pmSLength1 = 3;
                    394: request.msgBody.pmSBuffer2 = NULL;
                    395: request.msgBody.pmSLength2 = 0;
                    396: request.msgBody.pmRBuffer = NULL;
                    397: request.msgBody.pmCallback = Callback;
                    398: request.msgBody.pmId = Id;
                    399: request.msgBody.pmRefNum = RefNum;
                    400: request.msgBody.pmSBuffer1[0] = kPMUReadADB | (DevAddr << kPMUADBAddressField) | (DevReg);
                    401: if ( autopollOn ) {
                    402:        request.msgBody.pmSBuffer1[1] = 2;
                    403:        }
                    404: else {
                    405:        request.msgBody.pmSBuffer1[1] = 0;
                    406:        }
                    407: request.msgBody.pmSBuffer1[2] = 0;
                    408: 
                    409: request.msgHeader.msg_simple = TRUE;
                    410: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    411: request.msgHeader.msg_remote_port = port;
                    412: request.msgHeader.msg_local_port = PORT_NULL;
                    413: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    414: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    415: 
                    416: if ( return_code == SEND_SUCCESS ) {
                    417:        return kPMUNoError;
                    418:        }
                    419: else {
                    420:        return kPMUIOError;
                    421:        }
                    422: }
                    423: 
                    424: 
                    425: // **********************************************************************************
                    426: // ADBReset
                    427: //
                    428: // **********************************************************************************
                    429: - (PMUStatus)ADBReset  :(UInt32)RefNum
                    430:                         :(id)Id
                    431:                        :(pmCallback_func)Callback
                    432: {
                    433: PMUmachMessage request;
                    434: msg_return_t   return_code;
                    435: 
                    436: request.msgBody.pmCommand = kPMUpMgrADB;
                    437: request.msgBody.pmFlag = TRUE;         // this op solicits input from PGE
                    438: request.msgBody.pmSLength1 = 3;
                    439: request.msgBody.pmSBuffer2 = NULL;
                    440: request.msgBody.pmSLength2 = 0;
                    441: request.msgBody.pmRBuffer = NULL;
                    442: request.msgBody.pmCallback = Callback;
                    443: request.msgBody.pmId = Id;
                    444: request.msgBody.pmRefNum = RefNum;
                    445: request.msgBody.pmSBuffer1[0] = kPMUResetADBBus;
                    446: request.msgBody.pmSBuffer1[1] = 0;
                    447: request.msgBody.pmSBuffer1[2] = 0;
                    448: 
                    449: request.msgHeader.msg_simple = TRUE;
                    450: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    451: request.msgHeader.msg_remote_port = port;
                    452: request.msgHeader.msg_local_port = PORT_NULL;
                    453: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    454: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    455: 
                    456: if ( return_code == SEND_SUCCESS ) {
                    457:        return kPMUNoError;
                    458:        }
                    459: else {
                    460:        return kPMUIOError;
                    461:        }
                    462: }
                    463: 
                    464: 
                    465: // **********************************************************************************
                    466: // ADBFlush
                    467: //
                    468: // **********************************************************************************
                    469: - (PMUStatus)ADBFlush  :(UInt32)DevAddr
                    470:                        :(UInt32)RefNum
                    471:                         :(id)Id
                    472:                        :(pmCallback_func)Callback
                    473: {
                    474: PMUmachMessage request;
                    475: msg_return_t   return_code;
                    476: 
                    477: request.msgBody.pmCommand = kPMUpMgrADB;
                    478: request.msgBody.pmFlag = TRUE;
                    479: request.msgBody.pmSLength1 = 3;
                    480: request.msgBody.pmSBuffer2 = NULL;
                    481: request.msgBody.pmSLength2 = 0;
                    482: request.msgBody.pmRBuffer = NULL;
                    483: request.msgBody.pmId = Id;
                    484: request.msgBody.pmRefNum = RefNum;
                    485: request.msgBody.pmCallback = Callback;
                    486: request.msgBody.pmSBuffer1[0] = kPMUFlushADB | (DevAddr << kPMUADBAddressField);
                    487: if ( autopollOn ) {
                    488:        request.msgBody.pmSBuffer1[1] = 2;
                    489:        }
                    490: else {
                    491:        request.msgBody.pmSBuffer1[1] = 0;
                    492:        }
                    493: request.msgBody.pmSBuffer1[2] = 0;
                    494:                
                    495: request.msgHeader.msg_simple = TRUE;
                    496: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    497: request.msgHeader.msg_remote_port = port;
                    498: request.msgHeader.msg_local_port = PORT_NULL;
                    499: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    500: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    501: 
                    502: if ( return_code == SEND_SUCCESS ) {
                    503:        return kPMUNoError;
                    504:        }
                    505: else {
                    506:        return kPMUIOError;
                    507:        }
                    508: }
                    509: 
                    510: 
                    511: // **********************************************************************************
                    512: // ADBSetPollList
                    513: //
                    514: // **********************************************************************************
                    515: - (PMUStatus)ADBSetPollList    :(UInt32)PollBitField
                    516:                                :(UInt32)RefNum
                    517:                                :(id)Id
                    518:                                :(pmCallback_func)Callback
                    519: {
                    520: PMUmachMessage request;
                    521: msg_return_t   return_code;
                    522: 
                    523: pollList = PollBitField;                               // remember the new poll list
                    524: 
                    525: if ( autopollOn ) {                                    // if PMU is currently autopolling,
                    526:        request.msgBody.pmCommand = kPMUpMgrADB;        // give it the new list
                    527:        request.msgBody.pmFlag = FALSE;
                    528:        request.msgBody.pmSLength1 = 4;
                    529:        request.msgBody.pmSBuffer2 = NULL;
                    530:        request.msgBody.pmSLength2 = 0;
                    531:        request.msgBody.pmRBuffer = NULL;
                    532:        request.msgBody.pmRefNum = RefNum;
                    533:        request.msgBody.pmId = Id;
                    534:        request.msgBody.pmCallback = Callback;
                    535:        request.msgBody.pmSBuffer1[0] = 0;
                    536:        request.msgBody.pmSBuffer1[1] = 0x86;
                    537:        request.msgBody.pmSBuffer1[2] = (UInt8)(PollBitField >> 8);
                    538:        request.msgBody.pmSBuffer1[3] = (UInt8)(PollBitField & 0xff);
                    539: 
                    540:        request.msgHeader.msg_simple = TRUE;
                    541:        request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    542:        request.msgHeader.msg_remote_port = port;
                    543:        request.msgHeader.msg_local_port = PORT_NULL;
                    544:        request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    545:        return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    546: 
                    547:        if ( return_code == SEND_SUCCESS ) {
                    548:                return kPMUNoError;
                    549:                }
                    550:        else {
                    551:                return kPMUIOError;
                    552:                }
                    553:        }
                    554: else {                                                 // we'll do it later
                    555:        if ( Callback != NULL ) {                       // but make the client callback now
                    556:                Callback(Id, RefNum, 0, NULL);
                    557:                }
                    558:        }
                    559: return kPMUNoError;
                    560: }
                    561: 
                    562: 
                    563: // **********************************************************************************
                    564: // ADBSetFileServerMode()
                    565: //
                    566: // **********************************************************************************
                    567: - (PMUStatus)ADBSetFileServerMode       :(UInt32)RefNum
                    568:                                                :(id)Id
                    569:                                                :(pmCallback_func)Callback
                    570: 
                    571: {
                    572: return kPMUNotSupported;
                    573: }
                    574: 
                    575: 
                    576: // **********************************************************************************
                    577: // ADBPollEnable
                    578: //
                    579: // **********************************************************************************
                    580: - (PMUStatus)ADBPollEnable      :(UInt32)RefNum
                    581:                                 :(id)Id
                    582:                                 :(pmCallback_func)Callback
                    583: 
                    584: {
                    585: PMUmachMessage  request;
                    586: msg_return_t    return_code;
                    587: 
                    588: 
                    589: request.msgBody.pmCommand = kPMUpMgrADB;        // give it the list we have
                    590: request.msgBody.pmFlag = FALSE;
                    591: request.msgBody.pmSLength1 = 4;
                    592: request.msgBody.pmSBuffer2 = NULL;
                    593: request.msgBody.pmSLength2 = 0;
                    594: request.msgBody.pmRBuffer = NULL;
                    595: request.msgBody.pmRefNum = RefNum;
                    596: request.msgBody.pmId = Id;
                    597: request.msgBody.pmCallback = Callback;
                    598: request.msgBody.pmSBuffer1[0] = 0;
                    599: request.msgBody.pmSBuffer1[1] = 0x86;
                    600: request.msgBody.pmSBuffer1[2] = (UInt8)(pollList >> 8);
                    601: request.msgBody.pmSBuffer1[3] = (UInt8)(pollList & 0xff);
                    602: 
                    603: request.msgHeader.msg_simple = TRUE;
                    604: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    605: request.msgHeader.msg_remote_port = port;
                    606: request.msgHeader.msg_local_port = PORT_NULL;
                    607: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    608: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    609: 
                    610: if ( return_code == SEND_SUCCESS ) {
                    611:        autopollOn = TRUE;
                    612:         return kPMUNoError;
                    613:         }
                    614: else {
                    615:         return kPMUIOError;
                    616:         }
                    617: }
                    618: 
                    619: 
                    620: // **********************************************************************************
                    621: // ADBPollDisable
                    622: //
                    623: // **********************************************************************************
                    624: - (PMUStatus)ADBPollDisable    :(UInt32)RefNum
                    625:                                :(id)Id
                    626:                                :(pmCallback_func)Callback
                    627: {
                    628: PMUmachMessage request;
                    629: msg_return_t   return_code;
                    630: 
                    631: request.msgBody.pmCommand = kPMUpMgrADBoff;
                    632: request.msgBody.pmFlag = FALSE;
                    633: request.msgBody.pmFlag = TRUE;
                    634: request.msgBody.pmSLength1 = 0;
                    635: request.msgBody.pmSBuffer2 = NULL;
                    636: request.msgBody.pmSLength2 = 0;
                    637: request.msgBody.pmRBuffer = NULL;
                    638: request.msgBody.pmRefNum = RefNum;
                    639: request.msgBody.pmId = Id;
                    640: request.msgBody.pmCallback = Callback;
                    641: 
                    642: request.msgHeader.msg_simple = TRUE;
                    643: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    644: request.msgHeader.msg_remote_port = port;
                    645: request.msgHeader.msg_local_port = PORT_NULL;
                    646: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    647: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    648: 
                    649: if ( return_code == SEND_SUCCESS ) {
                    650:        autopollOn = FALSE;
                    651:        return kPMUNoError;
                    652:        }
                    653: else {
                    654:        return kPMUIOError;
                    655:        }
                    656: }
                    657: 
                    658: 
                    659: // **********************************************************************************
                    660: // ADBSetPollRate
                    661: //
                    662: // **********************************************************************************
                    663: - (PMUStatus)ADBSetPollRate     :(UInt32)NewRate
                    664:                                :(UInt32)RefNum
                    665:                                 :(id)Id
                    666:                                 :(pmCallback_func)Callback
                    667: {
                    668: return kPMUNotSupported;
                    669: }
                    670: 
                    671: 
                    672: // **********************************************************************************
                    673: // ADBGetPollRate
                    674: //
                    675: // **********************************************************************************
                    676: - (PMUStatus)ADBGetPollRate     :(UInt32 *)CurrentRate
                    677:                                 :(UInt32)RefNum
                    678:                                 :(id)Id
                    679:                                 :(pmCallback_func)Callback
                    680: {
                    681: return kPMUNotSupported;
                    682: }
                    683: 
                    684: 
                    685: // **********************************************************************************
                    686: // ADBSetAlternateKeyboard
                    687: //
                    688: // **********************************************************************************
                    689: - (PMUStatus)ADBSetAlternateKeyboard   :(UInt32)DevAddr
                    690:                                        :(UInt32)RefNum
                    691:                                        :(id)Id
                    692:                                        :(pmCallback_func)Callback
                    693: {
                    694: return kPMUNotSupported;
                    695: }
                    696: 
                    697: 
                    698: // **********************************************************************************
                    699: // ADBinput
                    700: //
                    701: // The PGE has interrupted with ADB data.  We package this up and send
                    702: // it to our ADB client, if there is one, either as the result to its previous
                    703: // read command, or as autopoll data.
                    704: //
                    705: // **********************************************************************************
                    706: - (void)ADBinput:(UInt32)theLength:(UInt8 *)theInput
                    707: {
                    708: if ( theInput[0] & kPMUautopoll ) {                            // autopoll data?
                    709:        if ( ADBclient != NULL ) {
                    710:          ADBclient(ADBid, 0, (theInput[1]>>4)&0x0F, theLength-2, theInput+2);
                    711:          // yes, call adb input handler
                    712:        }
                    713:        return;
                    714:        }
                    715: if ( adb_reading ) {                                           // no, expecting adb input?
                    716:        if ( clientRequest->pmSBuffer1[0] == theInput[1] ) {    // yes, is it our input?
                    717:                ns_untimeout((func)timer_expired,(void *)port); // yes, turn off our timer
                    718:                if ( clientRequest->pmCallback != NULL ) {      // Make the client callback
                    719:                        clientRequest->pmCallback(clientRequest->pmId, clientRequest->pmRefNum, theLength-2, theInput+2);
                    720:                        }
                    721:                adb_reading = FALSE;
                    722:                return;
                    723:                }
                    724:        }
                    725: kprintf("unexpected adb input: %02d %02x %02x %02x %02x\n", theLength, interruptState[0], interruptState[1], interruptState[2], interruptState[3]);
                    726: }
                    727: 
                    728: 
                    729: // **********************************************************************************
                    730: // registerForClockTicks
                    731: //
                    732: // The RTC driver is calling to tell us that it is prepared to receive clock
                    733: // ticks every second.  The parameter block tells who to call when we get one.
                    734: //
                    735: // **********************************************************************************
                    736: - (void)registerForClockTicks  :(pmCallback_func)TickHandler
                    737:                                :(id)caller
                    738: {
                    739: RTCclient = TickHandler;
                    740: RTCid = caller;
                    741: }
                    742: 
                    743: 
                    744: // **********************************************************************************
                    745: // setRealTimeClock
                    746: //
                    747: // The RTC driver is calling to set the real time clock.  We translate this into
                    748: // a PMU command and enqueue it to our command queue.
                    749: //
                    750: // **********************************************************************************
                    751: - (PMUStatus)setRealTimeClock  :(UInt8 *)newTime
                    752:                                :(UInt32)RefNum
                    753:                                :(id)Id
                    754:                                 :(pmCallback_func)Callback
                    755: {
                    756: PMUmachMessage  request;
                    757: msg_return_t    return_code;
                    758: 
                    759: if ( newTime == NULL ) {
                    760:        return kPMUParameterError;
                    761:        }
                    762: 
                    763: request.msgBody.pmCommand = kPMUtimeWrite;
                    764: request.msgBody.pmFlag = FALSE;
                    765: request.msgBody.pmSLength1 = 0;
                    766: request.msgBody.pmSBuffer2 = newTime;
                    767: request.msgBody.pmSLength2 = 4;
                    768: request.msgBody.pmRBuffer = NULL;
                    769: request.msgBody.pmRefNum = RefNum;
                    770: request.msgBody.pmId = Id;
                    771: request.msgBody.pmCallback = Callback;
                    772: 
                    773: request.msgHeader.msg_simple = TRUE;
                    774: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    775: request.msgHeader.msg_remote_port = port;
                    776: request.msgHeader.msg_local_port = PORT_NULL;
                    777: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    778: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    779: 
                    780: if ( return_code == SEND_SUCCESS ) {
                    781:         return kPMUNoError;
                    782:         }
                    783: else {
                    784:         return kPMUIOError;
                    785:         }
                    786: }
                    787: 
                    788: 
                    789: // **********************************************************************************
                    790: // getRealTimeClock
                    791: //
                    792: // The RTC driver is calling to read the real time clock.  We translate this into
                    793: // a PMU command and enqueue it to our command queue.
                    794: //
                    795: // **********************************************************************************
                    796: - (PMUStatus)getRealTimeClock  :(UInt8 *)currentTime
                    797:                                 :(UInt32)RefNum
                    798:                                :(id)Id
                    799:                                 :(pmCallback_func)Callback
                    800: {
                    801: PMUmachMessage  request;
                    802: msg_return_t    return_code;
                    803: 
                    804: if ( currentTime == NULL ) {
                    805:         return kPMUParameterError;
                    806:         }
                    807: 
                    808: request.msgBody.pmCommand = kPMUtimeRead;
                    809: request.msgBody.pmFlag = FALSE;
                    810: request.msgBody.pmSLength1 = 0;
                    811: request.msgBody.pmSBuffer2 = NULL;
                    812: request.msgBody.pmSLength2 = 0;
                    813: request.msgBody.pmRBuffer = currentTime;
                    814: request.msgBody.pmRefNum = RefNum;
                    815: request.msgBody.pmId = Id;
                    816: request.msgBody.pmCallback = Callback;
                    817: 
                    818: request.msgHeader.msg_simple = TRUE;
                    819: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    820: request.msgHeader.msg_remote_port = port;
                    821: request.msgHeader.msg_local_port = PORT_NULL;
                    822: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    823: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    824: 
                    825: if ( return_code == SEND_SUCCESS ) {
                    826:         return kPMUNoError;
                    827:         }
                    828: else {
                    829:         return kPMUIOError;
                    830:         }
                    831: }
                    832: 
                    833: 
                    834: // **********************************************************************************
                    835: // readNVRAM
                    836: //
                    837: // The NVRAM driver is calling to read part of the NVRAM.  We translate this into
                    838: // single-byte PMU commands and enqueue them to our command queue.
                    839: //
                    840: // **********************************************************************************
                    841: - (PMUStatus) readNVRAM :(UInt32)Offset
                    842:                         :(UInt32)Length
                    843:                        :(UInt8 *)Buffer
                    844:                         :(UInt32)RefNum
                    845:                         :(id)Id
                    846:                         :(pmCallback_func)Callback
                    847: {
                    848: PMUmachMessage  request;
                    849: msg_return_t    return_code;
                    850: int            i;
                    851: UInt8 *                client_buffer = Buffer;
                    852: UInt32         our_offset = Offset;
                    853: 
                    854: if ( (Buffer == NULL) ||
                    855:        (Length == 0) ||
                    856:        (Length > 8192) ||
                    857:        (Offset > 8192) ||
                    858:        ((Length + Offset) > 8192) ) {
                    859:         return kPMUParameterError;
                    860:         }
                    861: 
                    862: for ( i = 0; i < (Length - 1); i++ ) {                 // read all but the last byte
                    863:        request.msgBody.pmCommand = kPMUNVRAMRead;
                    864:        request.msgBody.pmFlag = FALSE;
                    865:        request.msgBody.pmSLength1 = 2;
                    866:        request.msgBody.pmSBuffer2 = NULL;
                    867:        request.msgBody.pmSLength2 = 0;
                    868:        request.msgBody.pmRBuffer = client_buffer++;
                    869:        request.msgBody.pmCallback = NULL;
                    870:        request.msgBody.pmSBuffer1[0] = our_offset >> 8;
                    871:        request.msgBody.pmSBuffer1[1] = our_offset++;
                    872: 
                    873:        request.msgHeader.msg_simple = TRUE;
                    874:        request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    875:        request.msgHeader.msg_remote_port = port;
                    876:        request.msgHeader.msg_local_port = PORT_NULL;
                    877:        request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    878:        return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    879: 
                    880:        if ( return_code != SEND_SUCCESS ) {
                    881:                return kPMUIOError;
                    882:                }
                    883:        }
                    884: 
                    885: request.msgBody.pmCommand = kPMUNVRAMRead;                     // now read last byte
                    886: request.msgBody.pmFlag = FALSE;
                    887: request.msgBody.pmSLength1 = 2;
                    888: request.msgBody.pmSBuffer2 = NULL;
                    889: request.msgBody.pmSLength2 = 0;
                    890: request.msgBody.pmRBuffer = client_buffer;
                    891: request.msgBody.pmRefNum = RefNum;
                    892: request.msgBody.pmId = Id;
                    893: request.msgBody.pmCallback = Callback;
                    894: request.msgBody.pmSBuffer1[0] = our_offset >> 8;
                    895: request.msgBody.pmSBuffer1[1] = our_offset;
                    896: 
                    897: request.msgHeader.msg_simple = TRUE;
                    898: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    899: request.msgHeader.msg_remote_port = port;
                    900: request.msgHeader.msg_local_port = PORT_NULL;
                    901: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    902: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    903: 
                    904: if ( return_code == SEND_SUCCESS ) {
                    905:        return kPMUNoError;
                    906:        }
                    907: else {
                    908:         return kPMUIOError;
                    909:         }
                    910: }
                    911: 
                    912: 
                    913: // **********************************************************************************
                    914: // writeNVRAM
                    915: //
                    916: // The NVRAM driver is calling to write part of the NVRAM.  We translate this into
                    917: // single-byte PMU commands and enqueue them to our command queue.
                    918: //
                    919: // **********************************************************************************
                    920: - (PMUStatus) writeNVRAM:(UInt32)Offset
                    921:                         :(UInt32)Length
                    922:                        :(UInt8 *)Buffer
                    923:                         :(UInt32)RefNum
                    924:                         :(id)Id
                    925:                         :(pmCallback_func)Callback
                    926: {
                    927: PMUmachMessage  request;
                    928: msg_return_t    return_code;
                    929: int            i;
                    930: UInt32         our_offset = Offset;
                    931: UInt8 *                client_buffer = Buffer;
                    932: 
                    933: if ( (Buffer == NULL) ||
                    934:         (Length == 0) ||
                    935:         (Length > 8192) ||
                    936:         (Offset > 8192) ||
                    937:         ((Length + Offset) > 8192) ) {
                    938:         return kPMUParameterError;
                    939:         }
                    940: 
                    941: for ( i = 0; i < (Length - 1); i++ ) {                 // write all but the last byte
                    942:         request.msgBody.pmCommand = kPMUNVRAMWrite;
                    943:        request.msgBody.pmFlag = FALSE;
                    944:         request.msgBody.pmSLength1 = 3;
                    945:         request.msgBody.pmSBuffer2 = NULL;
                    946:         request.msgBody.pmSLength2 = 0;
                    947:         request.msgBody.pmRBuffer = NULL;
                    948:         request.msgBody.pmCallback = NULL;
                    949:        request.msgBody.pmSBuffer1[0] = our_offset >> 8;
                    950:        request.msgBody.pmSBuffer1[1] = our_offset++;
                    951:        request.msgBody.pmSBuffer1[2] = *client_buffer++;
                    952: 
                    953:        request.msgHeader.msg_simple = TRUE;
                    954:        request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    955:        request.msgHeader.msg_remote_port = port;
                    956:        request.msgHeader.msg_local_port = PORT_NULL;
                    957:        request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    958:        return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    959: 
                    960:         if ( return_code != SEND_SUCCESS ) {
                    961:                 return kPMUIOError;
                    962:                 }
                    963:        }
                    964: 
                    965: request.msgBody.pmCommand = kPMUNVRAMWrite;            // write the last byte
                    966: request.msgBody.pmFlag = FALSE;
                    967: request.msgBody.pmSLength1 = 3;
                    968: request.msgBody.pmSBuffer2 = NULL;
                    969: request.msgBody.pmSLength2 = 0;
                    970: request.msgBody.pmRBuffer = NULL;
                    971: request.msgBody.pmRefNum = RefNum;
                    972: request.msgBody.pmId = Id;
                    973: request.msgBody.pmCallback = Callback;
                    974: request.msgBody.pmSBuffer1[0] = our_offset >> 8;
                    975: request.msgBody.pmSBuffer1[1] = our_offset;
                    976: request.msgBody.pmSBuffer1[2] = *client_buffer;
                    977: 
                    978: request.msgHeader.msg_simple = TRUE;
                    979: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                    980: request.msgHeader.msg_remote_port = port;
                    981: request.msgHeader.msg_local_port = PORT_NULL;
                    982: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                    983: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                    984: 
                    985: if ( return_code == SEND_SUCCESS ) {
                    986:         return kPMUNoError;
                    987:         }
                    988: else {
                    989:         return kPMUIOError;
                    990:         }
                    991: }
                    992: 
                    993: 
                    994: // **********************************************************************************
                    995: // registerForPowerInterrupts
                    996: //
                    997: // Some driver is calling to say it is prepared to receive "unsolicited" power-system
                    998: // interrups (e.g. battery low).  The parameter block says who to call when we get one.
                    999: //
                   1000: // **********************************************************************************
                   1001: - (void)registerForPowerInterrupts     :(pmCallback_func)buttonHandler
                   1002:                                        :(id)caller
                   1003: {
                   1004: PWRclient = buttonHandler;
                   1005: PWRid = caller;
                   1006: }
                   1007: 
                   1008: 
                   1009: // **********************************************************************************
                   1010: // sendMiscCommand
                   1011: //
                   1012: // Some driver is calling to send some miscellaneous command.  We copy this into a
                   1013: // PMU command and enqueue it to our command queue.
                   1014: //
                   1015: // **********************************************************************************
                   1016: - (PMUStatus)sendMiscCommand   :(UInt32)Command
                   1017:                                :(UInt32)SLength
                   1018:                                :(UInt8 *)SBuffer
                   1019:                                :(UInt8 *)RBuffer
                   1020:                                :(UInt32)RefNum
                   1021:                                :(id)Id
                   1022:                                :(pmCallback_func)Callback
                   1023: {
                   1024: PMUmachMessage  request;
                   1025: msg_return_t    return_code;
                   1026: SInt32         rsp_length;
                   1027: SInt32         send_length;
                   1028: 
                   1029: rsp_length = rspLengthTable[Command];                          // get cmd and response lengths from table
                   1030: send_length = cmdLengthTable[Command];
                   1031: 
                   1032: if ( ((SLength != 0) && (SBuffer == NULL)) ||                          // validate pointers
                   1033:        ((rsp_length != 0) && (RBuffer == NULL)) ) {
                   1034:                return kPMUParameterError;
                   1035:                }
                   1036: if ( (Command != kPMUdownloadFlash) &&
                   1037:        ((send_length != -1) && (send_length != SLength)) ) {
                   1038:                 return kPMUParameterError;
                   1039:                 }
                   1040: 
                   1041: if ( send_length > MISC_LENGTH ) {
                   1042:        return kPMUParameterError;
                   1043:        }
                   1044: 
                   1045: request.msgBody.pmCommand = Command;
                   1046: request.msgBody.pmFlag = FALSE;
                   1047: request.msgBody.pmSLength1 = 0;
                   1048: request.msgBody.pmSBuffer2 = SBuffer;
                   1049: request.msgBody.pmSLength2 = SLength;
                   1050: request.msgBody.pmRBuffer = RBuffer;
                   1051: request.msgBody.pmRefNum = RefNum;
                   1052: request.msgBody.pmId = Id;
                   1053: request.msgBody.pmCallback = Callback;
                   1054: 
                   1055: request.msgHeader.msg_simple = TRUE;
                   1056: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                   1057: request.msgHeader.msg_remote_port = port;
                   1058: request.msgHeader.msg_local_port = PORT_NULL;
                   1059: request.msgHeader.msg_size = sizeof(PMUmachMessage);
                   1060: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                   1061: 
                   1062: if ( return_code == SEND_SUCCESS ) {
                   1063:         return kPMUNoError;
                   1064:         }
                   1065: else {
                   1066:         return kPMUIOError;
                   1067:         }
                   1068: }
                   1069: 
                   1070: 
                   1071: // **********************************************************************************
                   1072: // StartPMUTransmission
                   1073: //
                   1074: // Transmission of the command byte is started.  The transaction will be
                   1075: // completed by the Shift Register Interrupt Service Routine.
                   1076: // **********************************************************************************
                   1077: - (void)StartPMUTransmission:(PMURequest *)plugInMessage
                   1078: {
                   1079: if ( !debugging ) {
                   1080:        clientRequest = plugInMessage;
                   1081:        firstChar = plugInMessage->pmCommand;           // get command byte
                   1082:        charCountS1 = plugInMessage->pmSLength1;        // get caller's length counters
                   1083:        charCountS2 = plugInMessage->pmSLength2;
                   1084:        dataPointer1 = plugInMessage->pmSBuffer1;       // and transmit data pointers
                   1085:        dataPointer2 = plugInMessage->pmSBuffer2;
                   1086:        dataPointer = plugInMessage->pmRBuffer;         // set up read pointer for data bytes
                   1087:        charCountR = rspLengthTable[firstChar];         // get response length from table
                   1088:        charCountR2 = charCountR;
                   1089: 
                   1090:                                // figure out what happens after command byte transmission
                   1091:        if ( cmdLengthTable[firstChar] < 0 ) {  // will we be sending a length byte next?
                   1092:                PGE_ISR_state = kPMUxmtLen;     // yes
                   1093:                }
                   1094:        else {                                  // no, will we be sending data next?
                   1095:                if ( cmdLengthTable[firstChar] > 0 ) {
                   1096:                        PGE_ISR_state = kPMUxmtData;                    // yes
                   1097:                        }
                   1098:                else {                                                  // no, will we be receiving a length byte next?
                   1099:                        if ( charCountR < 0 ) {
                   1100:                                PGE_ISR_state = kPMUreadLen_cmd;        // yes
                   1101:                                }
                   1102:                        else {                                          // no, will we be receiving data next?
                   1103:                                if ( charCountR > 0 ) {
                   1104:                                        PGE_ISR_state = kPMUreadData;   // yes
                   1105:                                        }
                   1106:                                else {
                   1107:                                        PGE_ISR_state = kPMUdone;       // no, this is a single-byte transaction
                   1108:                                        }
                   1109:                                }
                   1110:                        }
                   1111:                }
                   1112:                                                                // ready to start the command byte
                   1113:        *VIA1_auxillaryControl |= 0x1C;                         // set shift register to output
                   1114:        *VIA1_shift = firstChar;                                // give it the byte (this clears any pending SR interrupt)
                   1115: //     *VIA1_interruptEnable = 0x84;                           // enable SR interrupt
                   1116:        *VIA2_dataB &= ~PMreq;                                  // assert /REQ
                   1117:        return;
                   1118:        
                   1119:        }
                   1120: else {
                   1121:        UInt32          i;
                   1122:        
                   1123:        *VIA1_interruptEnable = 0x04;                                                   // disable SR interrupt
                   1124: 
                   1125:        firstChar = plugInMessage->pmCommand;                                           // get command byte
                   1126:        charCountS1 = plugInMessage->pmSLength1;                                        // get caller's length counters
                   1127:        charCountS2 = plugInMessage->pmSLength2;
                   1128:        dataPointer1 = plugInMessage->pmSBuffer1;                                       // and transmit data pointers
                   1129:        dataPointer2 = plugInMessage->pmSBuffer2;
                   1130:        
                   1131:        charCountR = rspLengthTable[firstChar];                                         // get response length from table
                   1132:        charCountR2 = charCountR;
                   1133:        
                   1134:        [self SendPMUByte:firstChar];                                                   // send command byte
                   1135: 
                   1136:        if ( cmdLengthTable[firstChar] < 0 ) {                                          // should we send a length byte?
                   1137:                [self SendPMUByte:(UInt8)(charCountS1 + charCountS2)];                  // yes, do it
                   1138:                }
                   1139: 
                   1140:        for ( i = 0; i < charCountS1; i++ ) {                                           // send data bytes
                   1141:                [self SendPMUByte:*dataPointer1++];
                   1142:                }
                   1143: 
                   1144:        for ( i = 0; i < charCountS2; i++ ) {                                           // send more data bytes
                   1145:                [self SendPMUByte:*dataPointer2++];
                   1146:                }
                   1147: /* charCountR ==       0:      no reply at all
                   1148:                                1:      only a reply byte will be sent by the PGE
                   1149:                                <0: a length byte and a reply will be sent
                   1150:                                >1: a reply will be sent, but no length byte
                   1151:                                         (length is charCount - 1)
                   1152: */
                   1153:        if ( charCountR ) {                                                             // receive the reply byte
                   1154:                if ( charCountR == 1 ) {                
                   1155:                        [self ReadPMUByte:plugInMessage->pmRBuffer];
                   1156:                        }
                   1157:                else {
                   1158:                        if ( charCountR < 0 ) {                                         // receive the length byte
                   1159:                                [self ReadPMUByte:&receivedByte];
                   1160:                                charCountR = receivedByte;
                   1161:                                }
                   1162:                        else {
                   1163:                                charCountR--;
                   1164:                                }
                   1165:                        dataPointer = plugInMessage->pmRBuffer;
                   1166:                        for ( i = 0; i < charCountR; i++ ) {
                   1167:                                [self ReadPMUByte:dataPointer++];                       // receive the rest of the reply
                   1168:                                }
                   1169:                        }
                   1170:                }
                   1171: 
                   1172:        if ( plugInMessage->pmCallback != NULL ) {                              // Make the client callback
                   1173:                plugInMessage->pmCallback(plugInMessage->pmId, plugInMessage->pmRefNum, charCountR, plugInMessage->pmRBuffer);
                   1174:                }
                   1175:        return;
                   1176:        }
                   1177: }
                   1178: 
                   1179: 
                   1180: 
                   1181: // ****************************************************************************
                   1182: //     interruptOccurred
                   1183: //     The shift register has finished shifting in a byte from PG&E or finished
                   1184: //     shifting out a byte to PG&E.  Here we continue the transaction by starting
                   1185: //     the i/o of the next byte, or we finish the transaction by calling the
                   1186: //     client's callback function.
                   1187: //     Both the VIA interrupt flag register and the interrupt enable registers
                   1188: //     have been cleared by the ohare ISR.
                   1189: // ****************************************************************************
                   1190: 
                   1191: - (void)interruptOccurred
                   1192: {
                   1193: *VIA2_dataB |= PMreq;                                  // deassert /REQ line
                   1194:                                                        // what state are we in?
                   1195: switch ( PGE_ISR_state ) {
                   1196:                                                        // We are processing a PMU interrupt.  We are reading the response
                   1197:                                                        // to the kPMUreadINT command, and a byte has arrived.
                   1198:        case kPMUrcvData_int:
                   1199:                *dataPointer++ = *VIA1_shift;           // read the data byte
                   1200:                charCountR2--;
                   1201:                if ( charCountR2 > 0 ) {                                // is there more to read?
                   1202:                        while ( !(*VIA2_dataB & PMack) ) {
                   1203:                                }
                   1204:                        *VIA2_dataB &= ~PMreq;                          // yes, assert /REQ
                   1205: //                     *VIA1_interruptEnable = 0x84;                   // enable SR interrupt
                   1206:                        return;                                         // next interrupt will be next data byte
                   1207:                        }
                   1208:                if ( interruptState[0] & kPMUADBint ) {                                 // no, what kind of interrupt was it?
                   1209:                        [self ADBinput: (UInt32)charCountR: &interruptState[0]];        // ADB
                   1210:                        }
                   1211:                else {
                   1212:                        if ( interruptState[0] & kPMUbattInt ) {
                   1213:                                kprintf("battery PGE interrupt\n");
                   1214:                                }
                   1215:                        else {
                   1216:                                if ( interruptState[0] & kPMUoneSecInt ) {
                   1217: //                                     kprintf("one-second PGE interrupt\n");
                   1218:                                        if ( RTCclient != NULL ) {                      // one-second interrupt
                   1219:                                                RTCclient(RTCid,0,0,0);
                   1220:                                                }
                   1221:                                        }
                   1222:                                else {
                   1223:                                        if ( interruptState[0] & kPMUenvironmentInt ) {
                   1224:                                                kprintf("environment interrupt\n");
                   1225:                                                }
                   1226:                                        else {
                   1227:                                                if ( interruptState[0] & kPMUbrightnessInt ) {
                   1228:                                                        kprintf("brightness button PGE interrupt\n");
                   1229:                                                        }
                   1230:                                                else {
                   1231:                                                        kprintf("machine-dependent PGE interrupt\n");
                   1232:                                                        }
                   1233:                                                }
                   1234:                                        }
                   1235:                                }
                   1236:                        }
                   1237:                PGE_ISR_state = kPMUidle;                                       // set the state
                   1238:                if ( !PMU_int_pending ) {                                       // is PMU requesting service again?
                   1239: //             if ( !(*VIA1_interruptFlag & 0x10) ) {                          // is PMU requesting service again? ( ifCB1 )
                   1240: //                     if ( queueHead == (PMUmachMessage*)0 ) {                // no, queue empty?
                   1241: //                             *VIA1_interruptEnable = 0x90;                   // yes, enable PMU interrupts ( ifCB1 )
                   1242: //                             return;                                         // and we are completely idle
                   1243: //                             }
                   1244:                        [self CheckRequestQueue];                               // no, start next queued transaction
                   1245:                        }
                   1246:                else {
                   1247: //                     *VIA1_interruptFlag = 0x10;             // PMU wants service, acknowledge VIA interrupt ( ifCB1 )       
                   1248:                        PMU_int_pending = FALSE;
                   1249:                        *VIA1_auxillaryControl |= 0x1C;                         // set shift register to output
                   1250:                        *VIA1_shift = kPMUreadINT;                              // give it the command byte
                   1251:                        *VIA2_dataB &= ~PMreq;                                  // assert /REQ
                   1252: //                     *VIA1_interruptEnable = 0x84;                           // enable SR interrupt
                   1253:                        PGE_ISR_state = kPMUreadLen_int;                        // set the state
                   1254:                        dataPointer = &interruptState[0];                       // set up read pointer for data bytes
                   1255:                        return;                                 // next interrupt is command byte transmission complete
                   1256:                        }
                   1257:                return;
                   1258:                
                   1259:                                                        // We are processing a PMU interrupt.
                   1260:                                                        // We have finished transmitting the kPMUreadINT command byte, and
                   1261:                                                        // according to our table, we will be getting a response and a
                   1262:                                                        // length byte for it.  Finish the transmit handshake and set up
                   1263:        case kPMUreadLen_int:                           // a receive for the length byte.
                   1264:                receivedByte = *VIA1_shift;                                     // read shift reg to turn off SR int
                   1265:                PGE_ISR_state = kPMUrcvLen_int;
                   1266:                *VIA1_auxillaryControl &= 0xEF;                                 // set shift register to input
                   1267:                while ( !(*VIA2_dataB & PMack) ) {
                   1268:                        }
                   1269:                *VIA2_dataB &= ~PMreq;                                          // assert /REQ
                   1270: //             *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1271:                return;                                                         // next interrupt will be the length byte
                   1272: 
                   1273:                                                        // We are processing a PMU interrupt.
                   1274:        case kPMUrcvLen_int:                            // The length byte has arrived.  Read it and start data read
                   1275:                charCountR = *VIA1_shift;               // read it
                   1276: 
                   1277:                charCountR2 = charCountR;
                   1278:                PGE_ISR_state = kPMUrcvData_int;
                   1279:                while ( !(*VIA2_dataB & PMack) ) {
                   1280:                        }
                   1281:                *VIA2_dataB &= ~PMreq;                                          // assert /REQ
                   1282: //             *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1283:                return;                                                         // next interrupt will be the first data byte
                   1284:                        
                   1285:                                                        // We are doing a command transaction.  The command byte transmission
                   1286:        case kPMUxmtLen:                                // has completed.  Start length byte transmission
                   1287:                PGE_ISR_state = kPMUxmtData;
                   1288:                while ( !(*VIA2_dataB & PMack) ) {
                   1289:                        }
                   1290:                *VIA1_shift = (UInt8)(charCountS1 + charCountS2);               // give it the length byte
                   1291:                *VIA2_dataB &= ~PMreq;                                          // assert /REQ
                   1292: //             *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1293:                return;                                                         // next interrupt start sending data
                   1294:                
                   1295:                                                        // We are doing a command transaction.  A byte transmission has completed.
                   1296:        case kPMUxmtData:                               // Continue data byte transmission
                   1297:                while ( !(*VIA2_dataB & PMack) ) {
                   1298:                        }
                   1299:                if ( charCountS1 ) {
                   1300:                        *VIA1_shift = *dataPointer1++;                          // give it the next data byte from buffer 1
                   1301:                        *VIA2_dataB &= ~PMreq;                                  // assert /REQ 
                   1302:                        if ( --charCountS1 + charCountS2 ) {
                   1303: //                             *VIA1_interruptEnable = 0x84;                   // enable SR interrupt
                   1304:                                return;                                         // next interrupt do another byte
                   1305:                                }
                   1306:                        }
                   1307:                else {
                   1308:                        if ( charCountS2 ) {
                   1309:                                *VIA1_shift = *dataPointer2++;          // buffer 1 empty, give it the next byte from buffer 2
                   1310:                                *VIA2_dataB &= ~PMreq;                  // assert /REQ
                   1311:                                if ( --charCountS2 ) {
                   1312: //                                     *VIA1_interruptEnable = 0x84;   // enable SR interrupt
                   1313:                                        return;                         // next interrupt do another byte
                   1314:                                        }
                   1315:                                }
                   1316:                        }
                   1317:                                                                                // sending last byte, what's next?
                   1318:                if ( charCountR < 0 ) {
                   1319:                        PGE_ISR_state = kPMUreadLen_cmd;                        // we will receive a length byte
                   1320:                        }
                   1321:                else {
                   1322:                        if ( charCountR > 0 ) {
                   1323:                                PGE_ISR_state = kPMUreadData;                   // we will receive constant-length data
                   1324:                                }
                   1325:                        else {
                   1326:                                PGE_ISR_state = kPMUdone;                       // nothing, we're done
                   1327:                                }
                   1328:                        }
                   1329: //             *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1330:                return;
                   1331:                
                   1332:                                                        // We have finished the transmission part of a command transaction, and
                   1333:                                                        // according to our table, we will be getting a response and a
                   1334:                                                        // length byte for it.  Finish the transmit handshake and set up
                   1335:        case kPMUreadLen_cmd:                           // a receive for the length byte.
                   1336:                receivedByte = *VIA1_shift;                                     // read shift reg to turn off SR int
                   1337:                PGE_ISR_state = kPMUrcvLen_cmd;
                   1338:                *VIA1_auxillaryControl &= 0xEF;                                 // set shift register to input
                   1339:                while ( !(*VIA2_dataB & PMack) ) {
                   1340:                        }
                   1341:                *VIA2_dataB &= ~PMreq;                                          // assert /REQ
                   1342: //             *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1343:                return;                                                         // next interrupt will be the length byte
                   1344: 
                   1345:        case kPMUrcvLen_cmd:                            // the length byte has arrived, read it and start data read
                   1346:                charCountR = *VIA1_shift;                               // read it
                   1347:                charCountR2 = charCountR;
                   1348:                PGE_ISR_state = kPMUrcvData_cmd;
                   1349:                if ( !(*VIA2_dataB & PMack) )
                   1350:                        if ( ![self WaitForAckHi] ) {
                   1351:                                return;                                         // make sure ACK is high
                   1352:                                }
                   1353:                *VIA2_dataB &= ~PMreq;                                          // assert /REQ
                   1354: //             *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1355:                return;                                                         // next interrupt will be the first data byte
                   1356:        
                   1357:                
                   1358:                                                        // We have finished the transmission part of a command transaction, and
                   1359:                                                        // according to our table, we will be getting a response but not a
                   1360:                                                        // length byte for it.  Finish the transmit handshake and set up
                   1361:        case kPMUreadData:                              // a receive for the first data byte.
                   1362:                if ( charCountR > 1 ) {
                   1363:                        charCountR2--;                                          // make constant (byte count + 1) into byte count
                   1364:                        charCountR--;
                   1365:                        }
                   1366: //             receivedByte = *VIA1_shift;                                     // read shift reg to turn off SR int
                   1367:                PGE_ISR_state = kPMUrcvData_cmd;
                   1368:                *VIA1_auxillaryControl &= 0xEF;                                 // set shift register to input
                   1369:                if ( !(*VIA2_dataB & PMack) )
                   1370:                        if ( ![self WaitForAckHi] ) {
                   1371:                                return;                                         // make sure ACK is high
                   1372:                                }
                   1373:                *VIA2_dataB &= ~PMreq;                                          // assert /REQ
                   1374: //             *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1375:                return;                                                         // next interrupt will be the first data character
                   1376:                
                   1377:                                                                // We are reading the response in a command transaction, and
                   1378:        case kPMUrcvData_cmd:                                   // a data byte has arrived
                   1379:                *dataPointer++ = *VIA1_shift;                                   // read the data byte
                   1380:                charCountR2--;
                   1381:                if ( charCountR2 > 0 ) {                                        // is there more to read?
                   1382:                        if ( !(*VIA2_dataB & PMack) )
                   1383:                                if ( ![self WaitForAckHi] ) {
                   1384:                                        return;                                 // yes, make sure ACK is high
                   1385:                                        }
                   1386:                        *VIA2_dataB &= ~PMreq;                                  // assert /REQ
                   1387:                        return;                                                 // next interrupt will be next data byte
                   1388:                        }
                   1389:                if ( clientRequest->pmCallback != NULL ) {                      // no, make the client callback
                   1390:                        clientRequest->pmCallback(clientRequest->pmId, clientRequest->pmRefNum, charCountR, clientRequest->pmRBuffer);
                   1391:                        }
                   1392:                PGE_ISR_state = kPMUidle;                                               // set the state
                   1393:                if ( !PMU_int_pending ) {                                               // is PMU now requesting service?
                   1394: //             if ( !(*VIA1_interruptFlag & 0x10) ) {                                  // is PMU now requesting service? (ifCB1)
                   1395: //                     if ( queueHead == (PMUmachMessage*)0 ) {                        // no, queue empty?
                   1396: //                             *VIA1_interruptEnable = 0x90;                           // yes, enable PMU interrupts ( ifCB1 )
                   1397: //                             return;                                                 // and we are completely idle
                   1398: //                             }
                   1399:                        [self CheckRequestQueue];                                       // no, start next queued transaction
                   1400:                        }
                   1401:                else {
                   1402: //                     *VIA1_interruptFlag = 0x10;             // PMU wants service, acknowledge VIA interrupt ( ifCB1 )       
                   1403:                        PMU_int_pending = FALSE;
                   1404:                        *VIA1_auxillaryControl |= 0x1C;                                 // set shift register to output
                   1405:                        *VIA1_shift = kPMUreadINT;                                      // give it the command byte
                   1406:                        *VIA2_dataB &= ~PMreq;                                          // assert /REQ
                   1407: //                     *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1408:                        PGE_ISR_state = kPMUreadLen_int;                                // set the state
                   1409:                        dataPointer = &interruptState[0];                               // set up read pointer for data bytes
                   1410:                        return;                                 // next interrupt is command byte transmission complete
                   1411:                        }
                   1412:                return;
                   1413: 
                   1414:        case kPMUdone:                                          // this was the last xmt SR interrupt of a command transaction
                   1415: //             receivedByte = *VIA1_shift;                                     // read shift reg to turn off SR int
                   1416: 
                   1417:                if ( clientRequest->pmFlag ) {                                  // does this command cause input?
                   1418:                                PGE_ISR_state = kPMUidle;                               // yes, set the state
                   1419:                        adb_reading = TRUE;                                     // don't do callback now
                   1420: //                     who_to_call = clientRequest->pmCallback;                // do it after the read completes
                   1421: //                     theirId = clientRequest->pmId;
                   1422: //                     theirRefNum = clientRequest->pmRefNum;
                   1423:                        ns_timeout((func)timer_expired,(void *)port,adb_read_timeout,CALLOUT_PRI_SOFTINT0);     // start timer
                   1424:                        if ( !PMU_int_pending ) {                                       // is PMU now requesting service?
                   1425: //                     if ( !(*VIA1_interruptFlag & 0x10) ) {                          // is PMU now requesting service? (ifCB1)
                   1426: //                             *VIA1_interruptEnable = 0x90;                           // yes, enable PMU interrupts ( ifCB1 )
                   1427:                                return;                                                 // and we are completely idle
                   1428:                                }
                   1429:                        else {
                   1430: //                             *VIA1_interruptFlag = 0x10;             // PMU wants service, acknowledge VIA interrupt ( ifCB1 )       
                   1431:                                PMU_int_pending = FALSE;
                   1432:                                *VIA1_auxillaryControl |= 0x1C;                                 // set shift register to output
                   1433:                                *VIA1_shift = kPMUreadINT;                                      // give it the command byte
                   1434:                                *VIA2_dataB &= ~PMreq;                                          // assert /REQ
                   1435: //                             *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1436:                                PGE_ISR_state = kPMUreadLen_int;                                // set the state
                   1437:                                dataPointer = &interruptState[0];                               // set up read pointer for data bytes
                   1438:                                return;                                 // next interrupt is command byte transmission complete
                   1439:                                }
                   1440:                        }
                   1441:                                                                                // not an adb read
                   1442:                if ( clientRequest->pmCallback != NULL ) {                              // Make the client callback
                   1443:                        clientRequest->pmCallback(clientRequest->pmId, clientRequest->pmRefNum, 0, NULL);
                   1444:                        }
                   1445:                if ( !PMU_int_pending ) {                                               // is PMU now requesting service?
                   1446: //             if ( !(*VIA1_interruptFlag & 0x10) ) {                                  // is PMU now requesting service? (ifCB1)
                   1447: //                     if ( queueHead == (PMUmachMessage*)0  ) {                       // no, queue empty?
                   1448:                                PGE_ISR_state = kPMUidle;
                   1449: //                             *VIA1_interruptEnable = 0x90;                           // yes, enable PMU interrupts ( ifCB1 )
                   1450: //                             return;                                                 // and we are completely idle
                   1451: //                             }
                   1452:                        [self CheckRequestQueue];                                       // no, start next queued transaction
                   1453:                        }
                   1454:                else {
                   1455:                        *VIA1_interruptFlag = 0x10;             // PMU wants service, acknowledge VIA interrupt ( ifCB1 )       
                   1456:                        PMU_int_pending = FALSE;
                   1457:                        *VIA1_auxillaryControl |= 0x1C;                                 // set shift register to output
                   1458:                        *VIA1_shift = kPMUreadINT;                                      // give it the command byte
                   1459:                        *VIA2_dataB &= ~PMreq;                                          // assert /REQ
                   1460: //                     *VIA1_interruptEnable = 0x84;                                   // enable SR interrupt
                   1461:                        PGE_ISR_state = kPMUreadLen_int;                                // set the state
                   1462:                        dataPointer = &interruptState[0];                               // set up read pointer for data bytes
                   1463:                        return;                                 // next interrupt is command byte transmission complete
                   1464:                        }
                   1465:                return;
                   1466:        }
                   1467: return;
                   1468: }
                   1469: 
                   1470: // ****************************************************************************
                   1471: //     interruptOccurredAt
                   1472: //     PGE has interrupted.  Send the ReadInt command to find out why.
                   1473: //     When the command byte is sent, the Shift Register will interrupt.
                   1474: //     If we are mid-transaction when we find out about the interrupt,
                   1475: //     set a flag and find out why later.
                   1476: //
                   1477: // ****************************************************************************
                   1478: 
                   1479: - (void)interruptOccurredAt:(int)localInterrupt
                   1480: {
                   1481: if ( PGE_ISR_state != kPMUidle ) {
                   1482:        PMU_int_pending = TRUE;
                   1483:        return;
                   1484:        }
                   1485: if ( !debugging ) {
                   1486:                                                                // make sure ACK is high
                   1487: //     *VIA1_interruptFlag = 0x10;                             // acknowledge VIA interrupt ( ifCB1 )
                   1488: //     *VIA1_interruptEnable = 0x10;                           // and disable it entirely ( ifCB1 )
                   1489:        while ( !(*VIA2_dataB & PMack) ) {
                   1490:                }
                   1491:        *VIA1_auxillaryControl |= 0x1C;                         // set shift register to output
                   1492:        *VIA1_shift = kPMUreadINT;                              // give it the command byte
                   1493:        *VIA2_dataB &= ~PMreq;                                  // assert /REQ
                   1494: //     *VIA1_interruptEnable = 0x84;                           // enable SR interrupt
                   1495:        PGE_ISR_state = kPMUreadLen_int;                        // set the state
                   1496:        dataPointer = &interruptState[0];                       // set up read pointer for data bytes
                   1497:        return;                                                 // return till character transmission completes
                   1498:        }
                   1499: else {
                   1500:        PMURequest      getInterruptState;                      // debug mode PMU interrupt handler
                   1501: 
                   1502: //     [self AcknowledgePMUInterrupt];                         // turn off VIA interrupt
                   1503:        *VIA1_interruptEnable = 0x04;                           // disable SR interrupt
                   1504:        
                   1505:        getInterruptState.pmCommand = kPMUreadINT;              // find out cause of interrupt from PGE
                   1506:        getInterruptState.pmFlag = FALSE;
                   1507:        getInterruptState.pmSLength1 = 0;
                   1508:        getInterruptState.pmSLength2 = 0;
                   1509:        getInterruptState.pmRBuffer = &interruptState[0];
                   1510:        getInterruptState.pmCallback = gotInterruptCause;
                   1511:        getInterruptState.pmId = self;
                   1512:        
                   1513:        [self StartPMUTransmission:&getInterruptState];
                   1514:        }
                   1515: }
                   1516: 
                   1517:        
                   1518: // ****************************************************************************
                   1519: // gotInterruptCause
                   1520: // 
                   1521: // Called by the debug-mode PMU interrupt handler as the Callback function
                   1522: // after sending the kPMUreadInt command and receiving its response
                   1523: // ****************************************************************************
                   1524: void gotInterruptCause(id PMUdriver, UInt32 unused, UInt32 length, UInt8 * data)
                   1525: {
                   1526: UInt8 interruptSource;
                   1527: 
                   1528: interruptSource = *data;
                   1529:        
                   1530: if ( interruptSource & kPMUADBint ) {
                   1531:        [PMUdriver ADBinput: length: data];
                   1532:        }
                   1533: else {
                   1534:        if ( interruptSource & kPMUbattInt ) {
                   1535:                IOLog("battery PGE interrupt");
                   1536:                }
                   1537:        else {
                   1538:                if ( interruptSource & kPMUoneSecInt ) {
                   1539:                        IOLog("one-second PGE interrupt");
                   1540:                        }
                   1541:                else {
                   1542:                        if ( interruptSource & kPMUenvironmentInt ) {
                   1543:                                IOLog("environment interrupt");
                   1544:                                }
                   1545:                        else {
                   1546:                                if ( interruptSource & kPMUbrightnessInt ) {
                   1547:                                        IOLog("brightness button PGE interrupt");
                   1548:                                        }
                   1549:                                else {
                   1550:                                        IOLog("machine-dependent PGE interrupt");
                   1551:                                        }
                   1552:                                }
                   1553:                        }
                   1554:                }
                   1555:        }
                   1556: }
                   1557: 
                   1558: 
                   1559: // ****************************************************************************
                   1560: // SendPMUByte
                   1561: // ****************************************************************************
                   1562: - (void)SendPMUByte:(UInt8)theByte
                   1563: {
                   1564: *VIA1_auxillaryControl |= 0x1C;         // set shift register to output
                   1565: eieio();
                   1566: *VIA1_shift = theByte;                  // give it the byte
                   1567: eieio();
                   1568: *VIA2_dataB &= ~PMreq;                 // assert /REQ
                   1569: eieio();
                   1570: if ( [self WaitForAckLo] ) {            // ack now low
                   1571:         *VIA2_dataB |= PMreq;          // deassert /REQ line
                   1572:         eieio();
                   1573:         if ( ! [self WaitForAckHi] ) {
                   1574:                 return;
                   1575:                 }
                   1576:         }
                   1577: else {
                   1578:         *VIA2_dataB |= PMreq;          // deassert /REQ line
                   1579:         eieio();
                   1580:         return;
                   1581:         }
                   1582: return;
                   1583: }
                   1584: 
                   1585: 
                   1586: // ****************************************************************************
                   1587: // ReadPMUByte
                   1588: // ****************************************************************************
                   1589: - (void)ReadPMUByte:(UInt8 *)theByte
                   1590: {
                   1591: *VIA1_auxillaryControl |= 0x0C;                 // set shift register to input
                   1592: *VIA1_auxillaryControl &= ~0x10;
                   1593: *theByte = *VIA1_shift;                         // read a byte to reset shift reg
                   1594: eieio();
                   1595: *VIA2_dataB &= ~PMreq;                         // assert /REQ
                   1596: eieio();
                   1597: if ( [self WaitForAckLo] ) {                    // ack now low
                   1598:         *VIA2_dataB |= PMreq;                  // deassert /REQ line
                   1599:         eieio();
                   1600:         if ( [self WaitForAckHi] ) {            // wait for /ACK high
                   1601:                 *theByte = *VIA1_shift;         // got it, read the byte
                   1602:                 eieio();
                   1603:                 }
                   1604:         else {
                   1605:                 return;
                   1606:                 }
                   1607:         }
                   1608: else {
                   1609:         *VIA2_dataB |= PMreq;                  // deassert /REQ line
                   1610:         eieio();
                   1611:         return;
                   1612:         }
                   1613: return;
                   1614: }
                   1615: 
                   1616: 
                   1617: // ****************************************************************************
                   1618: // WaitForAckLo
                   1619: // ****************************************************************************
                   1620: - (Boolean)WaitForAckLo
                   1621: {
                   1622: struct timeval startTime;
                   1623: struct timeval currentTime;
                   1624: ns_time_t x;
                   1625: 
                   1626: // wait up to 32 milliseconds for Ack signal from PG&E to go low
                   1627: 
                   1628: IOGetTimestamp(&x);
                   1629: ns_time_to_timeval(x, &startTime);                                     // get current time
                   1630: 
                   1631: while ( TRUE ) {
                   1632:         if ( !(*VIA2_dataB & PMack) ) {
                   1633:                 return ( TRUE );                                       // ack is low, return
                   1634:                 }
                   1635:        IOGetTimestamp(&x);
                   1636:         ns_time_to_timeval(x, &currentTime);
                   1637:        if ( startTime.tv_usec > currentTime.tv_usec ) {
                   1638:                currentTime.tv_usec += 1000000;                         // clock has wrapped, adjust it
                   1639:                }
                   1640:        if ( currentTime.tv_usec > (startTime.tv_usec + 32000) ) {      // has 32 ms elapsed?
                   1641:                 return ( FALSE );                                      // yes, return
                   1642:                 }
                   1643:         }
                   1644: }
                   1645: 
                   1646: 
                   1647: // ****************************************************************************
                   1648: // WaitForAckHi
                   1649: // ****************************************************************************
                   1650: - (Boolean)WaitForAckHi
                   1651: {
                   1652: struct timeval startTime;
                   1653: struct timeval currentTime;
                   1654: ns_time_t x;
                   1655: 
                   1656: // wait up to 32 milliseconds for Ack signal from PG&E to go high
                   1657: 
                   1658: IOGetTimestamp(&x);
                   1659: ns_time_to_timeval(x, &startTime);                                     // get current time
                   1660: 
                   1661: while ( TRUE ) {
                   1662:        if ( *VIA2_dataB & PMack ) {
                   1663:                return ( TRUE );                                        // ack is high, return
                   1664:                }
                   1665:        IOGetTimestamp(&x);
                   1666:         ns_time_to_timeval(x, &currentTime);
                   1667:         if ( startTime.tv_usec > currentTime.tv_usec ) {
                   1668:                 currentTime.tv_usec += 1000000;                         // clock has wrapped, adjust it
                   1669:                 }
                   1670:         if ( currentTime.tv_usec > (startTime.tv_usec + 32000) ) {      // has 32 ms elapsed?
                   1671:                 return ( FALSE );                                       // yes, return
                   1672:                 }
                   1673:         }
                   1674: }
                   1675: 
                   1676: 
                   1677: // ****************************************************************************
                   1678: // GetPMUInterruptState
                   1679: // ****************************************************************************
                   1680: - (UInt8)GetPMUInterruptState
                   1681: {                              // return current state of CB1 int enable
                   1682: return (*VIA1_interruptEnable & (1<<ifCB1));
                   1683: }
                   1684: 
                   1685: 
                   1686: // ****************************************************************************
                   1687: // RestorePMUInterrupt
                   1688: // ****************************************************************************
                   1689: - (void)RestorePMUInterrupt:(UInt8)savedValue
                   1690: {
                   1691: if ( savedValue ) {            // restore VIA interrupt state
                   1692:        *VIA1_interruptEnable = savedValue | 0x80;
                   1693:        }
                   1694: eieio();
                   1695: }
                   1696: 
                   1697: 
                   1698: // ****************************************************************************
                   1699: // DisablePMUInterrupt
                   1700: // ****************************************************************************
                   1701: - (void)DisablePMUInterrupt
                   1702: {
                   1703: *VIA1_interruptEnable = 1<<ifCB1;
                   1704: eieio();
                   1705: }
                   1706: 
                   1707: 
                   1708: // ****************************************************************************
                   1709: // EnablePMUInterrupt
                   1710: // ****************************************************************************
                   1711: - (void)EnablePMUInterrupt
                   1712: {
                   1713: *VIA1_interruptEnable = (1<<ifCB1) | 0x80;
                   1714: eieio();
                   1715: }
                   1716: 
                   1717: 
                   1718: // ****************************************************************************
                   1719: // AcknowledgePMUInterrupt
                   1720: // ****************************************************************************
                   1721: - (void)AcknowledgePMUInterrupt
                   1722: {
                   1723: *VIA1_interruptFlag = 1<<ifCB1;
                   1724: eieio();
                   1725: }
                   1726: 
                   1727: 
                   1728: // ****************************************************************************
                   1729: // GetSRInterruptState
                   1730: // ****************************************************************************
                   1731: - (UInt8)GetSRInterruptState
                   1732: {                                      // return current state of SR int enable
                   1733: return (*VIA1_interruptEnable & (1<<ifSR));
                   1734: }
                   1735: 
                   1736: 
                   1737: // ****************************************************************************
                   1738: // RestoreSRInterrupt
                   1739: // ****************************************************************************
                   1740: - (void)RestoreSRInterrupt:(UInt8)savedValue
                   1741: {
                   1742: if ( savedValue ) {                    // restore SR interrupt state
                   1743:        *VIA1_interruptEnable = savedValue | 0x80;
                   1744:        eieio();
                   1745:        }
                   1746: }
                   1747: 
                   1748: 
                   1749: // ****************************************************************************
                   1750: // DisableSRInterrupt
                   1751: // ****************************************************************************
                   1752: - (void)DisableSRInterrupt
                   1753: {
                   1754: *VIA1_interruptEnable = 1<<ifSR;
                   1755: }
                   1756: 
                   1757: 
                   1758: // ****************************************************************************
                   1759: // EnableSRInterrupt
                   1760: // ****************************************************************************
                   1761: - (void)EnableSRInterrupt
                   1762: {
                   1763: *VIA1_interruptEnable = (1<<ifSR) | 0x80;
                   1764: }
                   1765: 
                   1766: 
                   1767: 
                   1768: // ****************************************************************************
                   1769: // timer_expired
                   1770: //
                   1771: // Our adb-read timer has expired, so we have to notify our i/o thread by
                   1772: // enqueuing a Timeout message to its interrupt port.
                   1773: // ****************************************************************************
                   1774: void timer_expired(port_t mach_port)
                   1775: {
                   1776: PMUmachMessage request;
                   1777: 
                   1778: request.msgHeader.msg_simple = TRUE;
                   1779: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
                   1780: request.msgHeader.msg_id = IO_TIMEOUT_MSG;
                   1781: request.msgHeader.msg_remote_port = mach_port;
                   1782: request.msgHeader.msg_local_port = PORT_NULL;
                   1783: request.msgHeader.msg_size = sizeof(msg_header_t);
                   1784: msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
                   1785: 
                   1786: }
                   1787: 
                   1788: 
                   1789: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.