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

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

unix.superglobalmegacorp.com

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