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

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

unix.superglobalmegacorp.com

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