Annotation of XNU/iokit/Drivers/platform/drvApplePMU/pmu.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: #include <IOKit/IOPlatformExpert.h>
                     23: #include <IOKit/IODeviceTreeSupport.h>
                     24: extern "C" {
                     25: #include <machine/machine_routines.h>
                     26: #include <kern/clock.h>
                     27: }
                     28: #include <IOKit/assert.h>
                     29: #include <IOKit/IOSyncer.h>
                     30: 
                     31: #include "pmupriv.h"
                     32: #include "pmutables.h"
                     33: #include "IOPMUADBController.h"
                     34: #include "IOPMUNVRAMController.h"
                     35: #include "IOPMURTCController.h"
                     36: //#include "IOPMUPwrController.h"
                     37: 
                     38: //extern void kprintf(const char *, ...);
                     39: 
                     40: void receiveMsg ( OSObject * unused, void * newRequest, void * unused1,
                     41:                                                void * unused2, void * unused3 );
                     42: //void shiftRegisterInt ( OSObject * PMUdriver, IOInterruptEventSource * unused, int alsoUnused );
                     43: void commandDoneInt ( OSObject * PMUdriver, IOInterruptEventSource * unused, int alsoUnused );
                     44: void unsolicitedInt ( OSObject * PMUdriver, IOInterruptEventSource * unused, int alsoUnused );
                     45: 
                     46: void PMUint ( OSObject * PMUdriver, IOInterruptEventSource * unused, int alsoUnused );
                     47: void serviceShiftRegister ( ApplePMU * );
                     48: 
                     49: static int PMU_PE_poll_input ( unsigned int, char *  );
                     50: static int PMU_PE_halt_restart ( unsigned int type );
                     51: static int PMU_PE_write_IIC ( unsigned char, unsigned char, unsigned char );
                     52: static int PMU_PE_read_write_time_of_day ( unsigned int, long * );
                     53: 
                     54: // Interrupt Vectors
                     55: #define VIA_DEV_VIA0   2
                     56: #define VIA_DEV_VIA2   4
                     57: 
                     58: #define super IOService
                     59: OSDefineMetaClassAndStructors(ApplePMU,IOService)
                     60: 
                     61: static ApplePMU * gOurself;
                     62: 
                     63: // **********************************************************************************
                     64: // init
                     65: //
                     66: // **********************************************************************************
                     67: bool ApplePMU::init ( OSDictionary * properties = 0 )
                     68: {
                     69: return super::init(properties);
                     70: }
                     71: 
                     72: 
                     73: // **********************************************************************************
                     74: // start
                     75: //
                     76: // **********************************************************************************
                     77: bool ApplePMU::start ( IOService * nub )
                     78: {
                     79: IOMemoryMap *  viaMap;
                     80: unsigned char *        physicalAddress;
                     81: PMUrequest     theRequest;
                     82: 
                     83: workLoop = NULL;
                     84: commandQueue = NULL;
                     85: //SRintEventSrc = NULL;
                     86: cmdDoneEventSrc = NULL;
                     87: unsolicitedEventSrc = NULL;
                     88: PMUintEventSrc = NULL;
                     89: ourADBinterface = NULL;
                     90: ourRTCinterface = NULL;
                     91: /*
                     92: ourNVRAMinterface = NULL;
                     93: ourPwrinterface = NULL;
                     94: */
                     95: ADBclient = NULL;
                     96: RTCclient = NULL;
                     97: queueHead = NULL;
                     98: queueTail = NULL;
                     99: PGE_ISR_state = kPMUidle;
                    100: adb_reading = false;
                    101: PMU_int_pending = false;
                    102: 
                    103: adb_read_timeout.tv_sec = 0;
                    104: adb_read_timeout.tv_nsec = 100000000;
                    105: 
                    106: gOurself = this;
                    107: 
                    108: if( 0 == (viaMap = nub->mapDeviceMemoryWithIndex( 0 )) ) {
                    109:         IOLog("%s: no via memory\n", getName());
                    110:         return false;
                    111: }
                    112: physicalAddress = (unsigned char *)viaMap->getVirtualAddress();
                    113: 
                    114: //kprintf("VIA base = %08x\n", (UInt32)physicalAddress);
                    115: 
                    116: VIA1_shift             = physicalAddress + 0x1400;     // initialize VIA addresses
                    117: VIA1_auxillaryControl  = physicalAddress + 0x1600;
                    118: VIA1_interruptFlag     = physicalAddress + 0x1A00;
                    119: VIA1_interruptEnable   = physicalAddress + 0x1C00;
                    120: VIA2_dataB             = physicalAddress + 0x0000;
                    121:     
                    122: PMreq  = 1 << HooperReq;
                    123: PMack  = 1 << HooperAck;
                    124: 
                    125: // max to wait for ack low after SR interrupt, 100us
                    126: clock_interval_to_absolutetime_interval(100, 1000, &SR_to_ack_transition_delay);
                    127: 
                    128: workLoop = IOWorkLoop::workLoop();     // make the workloop
                    129: if ( !workLoop ) {
                    130:         kprintf("can't create workloop\n");
                    131:        return false;
                    132: }
                    133:                                                // make the command queue
                    134: commandQueue = IOCommandQueue::commandQueue(this, receiveMsg);
                    135: if (!commandQueue ||
                    136:        (workLoop->addEventSource(commandQueue) != kIOReturnSuccess) ) {        // add it to the workloop
                    137:         kprintf("can't create or add commandQueue\n");
                    138:        return false;
                    139: }
                    140: #if 0
                    141: // make the shift register interrupt source
                    142: SRintEventSrc = IOInterruptEventSource::
                    143: interruptEventSource(this, shiftRegisterInt, nub, VIA_DEV_VIA0);
                    144: if ( !SRintEventSrc ||
                    145: (workLoop->addEventSource(SRintEventSrc) != kIOReturnSuccess) ) {      // add it to the workloop
                    146: kprintf("can't create or add SRintEventSrc\n");
                    147: return false;
                    148: }
                    149: #endif
                    150: 
                    151: nub->registerInterrupt(VIA_DEV_VIA0,this,(IOInterruptAction) serviceShiftRegister);
                    152: nub->enableInterrupt(VIA_DEV_VIA0);
                    153: 
                    154: // make the command-done interrupt source
                    155: cmdDoneEventSrc = IOInterruptEventSource::interruptEventSource(this, commandDoneInt);
                    156: if ( !cmdDoneEventSrc ||                                               // add it to the workloop
                    157:      (workLoop->addEventSource(cmdDoneEventSrc) != kIOReturnSuccess) ) { 
                    158:     kprintf("can't create or add cmdDoneEventSrc\n");
                    159: return false;
                    160: }
                    161: 
                    162: // make the unsolicited interrupt source
                    163: unsolicitedEventSrc = IOInterruptEventSource::interruptEventSource(this, unsolicitedInt);
                    164: if ( !unsolicitedEventSrc ||                                           // add it to the workloop
                    165:      (workLoop->addEventSource(unsolicitedEventSrc) != kIOReturnSuccess) ) {
                    166:     kprintf("can't create or add unsolicitedEventSrc\n");
                    167: return false;
                    168: }
                    169:                                                // make the PMU interrupt source
                    170: PMUintEventSrc = IOInterruptEventSource::
                    171:     interruptEventSource(this, PMUint, nub, VIA_DEV_VIA2);
                    172: if ( !PMUintEventSrc ||
                    173:        (workLoop->addEventSource(PMUintEventSrc) != kIOReturnSuccess) ) {      // add it to the workloop
                    174:         kprintf("can't create or add PMUintEventSrc\n");
                    175:        return false;
                    176: }
                    177: 
                    178: AcknowledgePMUInterrupt();                             // turn off any pending PGE interrupt
                    179: workLoop->enableAllInterrupts();                       // enable interrupt delivery
                    180: EnablePMUInterrupt();                                          // enable PGE interrupts
                    181: EnableSRInterrupt();
                    182: 
                    183: theRequest.sync = IOSyncer::create();
                    184: theRequest.pmCommand = kPMUSetModem1SecInt;            // tell PGE why it may interrupt
                    185: theRequest.pmFlag = false;
                    186: theRequest.pmSLength1 = 1;
                    187: //theRequest.pmSBuffer1[0] = kPMUMD2Int | kPMUbrightnessInt | kPMUADBint;
                    188: theRequest.pmSBuffer1[0] = kPMUMD2Int | kPMUbrightnessInt | kPMUADBint | kPMUoneSecInt;
                    189: theRequest.pmSLength2 = 0;
                    190: commandQueue->enqueueCommand(true, &theRequest);
                    191: theRequest.sync->wait();                       // wait till done
                    192: 
                    193: theRequest.sync = IOSyncer::create();
                    194: theRequest.pmCommand = kPMUreadINT;                    // read any pending interrupt from PGE
                    195: theRequest.pmFlag = false;
                    196: theRequest.pmSLength1 = 0;                                     // just to clear it
                    197: theRequest.pmSLength2 = 0;
                    198: theRequest.pmRBuffer = &interruptState[0];
                    199: commandQueue->enqueueCommand(true, &theRequest);
                    200: theRequest.sync->wait();                       // wait till done
                    201: 
                    202:                                                        // initialize our interfaces
                    203: 
                    204:  // Do not create the IOPMUADBController if the no-adb property is set.
                    205:  if (!nub->getProperty("no-adb")) {
                    206:    ourADBinterface = new IOPMUADBController;
                    207:    if ( !ourADBinterface ) {
                    208:      return false;
                    209:    }
                    210:    if ( !ourADBinterface->init(0,this) ) {
                    211:      return false;
                    212:    }
                    213:    if ( !ourADBinterface->attach( this) ) {
                    214:      return false;
                    215:    }
                    216:  }
                    217:  
                    218:  // Do not create the IOPMUNVRAMController if the no-nvram property is set.
                    219:  if (!nub->getProperty("no-nvram")) { 
                    220:    ourNVRAMinterface = new IOPMUNVRAMController;
                    221:    if ( !ourNVRAMinterface ) {
                    222:      return false;
                    223:    }
                    224:    if ( !ourNVRAMinterface->init(0,this) ) {
                    225:      return false;
                    226:    }
                    227:    if ( !ourNVRAMinterface->attach( this) ) {
                    228:      return false;
                    229:    }
                    230:  }
                    231:  
                    232: 
                    233: ourRTCinterface = new IOPMURTCController;
                    234: if ( !ourRTCinterface ) {
                    235:        return false;
                    236: }
                    237: if ( !ourRTCinterface->init(0,this) ) {
                    238:        return false;
                    239: }
                    240: 
                    241: /*
                    242: ourPwrinterface = new IOPMUPwrController;
                    243: if ( !ourPwrinterface ) {
                    244:        return false;
                    245: }
                    246: if ( !ourPwrinterface->init(ourRegEntry,this) ) {
                    247:        return false;
                    248: }
                    249: */
                    250: 
                    251:     if (ourADBinterface) ourADBinterface->start( this );
                    252:     if (ourNVRAMinterface) ourNVRAMinterface->start( this );
                    253:     if (ourRTCinterface) ourRTCinterface->start( this );
                    254:     if (ourRTCinterface) {
                    255:             PE_read_write_time_of_day = PMU_PE_read_write_time_of_day;
                    256:     }
                    257: 
                    258:     PE_poll_input =PMU_PE_poll_input;
                    259:     PE_halt_restart =PMU_PE_halt_restart;
                    260:     PE_write_IIC = PMU_PE_write_IIC;
                    261: 
                    262:     /* are these even implemented? */
                    263:     publishResource( "IOiic0", this );
                    264:     publishResource( "IORTC", this );
                    265: 
                    266:     OSSerializer * infoSerializer = OSSerializer::forTarget(
                    267:                 (void *) this, &serializeBatteryInfo );
                    268:     if( infoSerializer) {
                    269:         IORegistryEntry * entry;
                    270:         if( (entry = IORegistryEntry::fromPath("mac-io/battery",
                    271:                                             gIODTPlane))) {
                    272:             entry->setProperty( kIOBatteryInfoKey, infoSerializer );
                    273:             entry->release();
                    274:         }
                    275:         infoSerializer->release();
                    276:     }
                    277: 
                    278:     publishResource(kPMUname, this);
                    279: 
                    280:     return true;
                    281: }
                    282: 
                    283: 
                    284: // *****************************************************************************
                    285: // getWorkLoop
                    286: //
                    287: // Return the PMU's workloop.
                    288: //
                    289: // *****************************************************************************
                    290: IOWorkLoop *ApplePMU::getWorkLoop() const
                    291: {
                    292:     return workLoop;
                    293: }
                    294: 
                    295: // *****************************************************************************
                    296: // free
                    297: //
                    298: // Release everything we may have allocated.
                    299: //
                    300: // *****************************************************************************
                    301: void ApplePMU::free ( void )
                    302: {
                    303: if ( workLoop ) {
                    304:        workLoop->release();
                    305: }
                    306: if ( commandQueue ) {
                    307:        commandQueue->release();
                    308: }
                    309: #if 0
                    310: if ( SRintEventSrc ) {
                    311:        SRintEventSrc->release();
                    312: }
                    313: #endif
                    314: if ( cmdDoneEventSrc ) {
                    315:     cmdDoneEventSrc->release();
                    316: }
                    317: if ( unsolicitedEventSrc ) {
                    318:     unsolicitedEventSrc->release();
                    319: }
                    320: if ( PMUintEventSrc ) {
                    321:        PMUintEventSrc->release();
                    322: }
                    323: if ( ourADBinterface ) {
                    324:        ourADBinterface->release();
                    325: }
                    326: if ( ourNVRAMinterface ) {
                    327:     ourNVRAMinterface->release();
                    328: }
                    329: 
                    330: if ( ourRTCinterface ) {
                    331:        ourRTCinterface->release();
                    332: }
                    333: /*
                    334: if ( ourPwrinterface ) {
                    335:        ourPwrinterface->release();
                    336: }
                    337: */
                    338: super::free();
                    339: }
                    340: 
                    341: 
                    342: // **********************************************************************************
                    343: // PMU_PE_halt_restart
                    344: //
                    345: // **********************************************************************************
                    346: static int PMU_PE_halt_restart ( unsigned int type )
                    347: {
                    348: PMUrequest     theRequest;
                    349: UInt8          reply_byte;
                    350: 
                    351: switch( type ) {
                    352: 
                    353:     case kPERestartCPU:
                    354:         theRequest.sync = IOSyncer::create();
                    355:         theRequest.pmCommand = kPMUresetCPU;
                    356:         theRequest.pmFlag = false;
                    357:         theRequest.pmSLength1 = 0;
                    358:         theRequest.pmSLength2 = 0;
                    359:         theRequest.pmRBuffer = &reply_byte;
                    360:         gOurself->enqueueCommand(&theRequest);
                    361:         theRequest.sync->wait();                       // wait till done
                    362:         break;
                    363: 
                    364:     case kPEHaltCPU:
                    365:         theRequest.sync = IOSyncer::create();
                    366:         theRequest.pmCommand = kPMUPmgrPWRoff;
                    367:         theRequest.pmFlag = false;
                    368:         theRequest.pmSLength1 = 4;
                    369:         theRequest.pmSBuffer1[0] = 'M';
                    370:         theRequest.pmSBuffer1[1] = 'A';
                    371:         theRequest.pmSBuffer1[2] = 'T';
                    372:         theRequest.pmSBuffer1[3] = 'T';
                    373:         theRequest.pmSLength2 = 0;
                    374:         theRequest.pmRBuffer = &reply_byte;
                    375:         gOurself->enqueueCommand(&theRequest);
                    376:         theRequest.sync->wait();                       // wait till done
                    377:         break;
                    378: 
                    379:     default:
                    380:         return 1;
                    381: }
                    382: 
                    383: // workaround 2377033; avoid memory accesses after this point
                    384: ml_set_interrupts_enabled(false);
                    385: while(true) {}
                    386: 
                    387: return 1;
                    388: }
                    389: 
                    390: 
                    391: // **********************************************************************************
                    392: // PMU_PE_read_write_time_of_day
                    393: //
                    394: // **********************************************************************************
                    395: static int PMU_PE_read_write_time_of_day ( unsigned int options, long * secs )
                    396: {
                    397:     UInt8      currentTime[8];
                    398:     IOByteCount        length,i;
                    399:     long       longTime = 0;
                    400: 
                    401:     if( (options == kPEReadTOD) && (gOurself->ourRTCinterface != NULL) )
                    402:     {
                    403:         gOurself->ourRTCinterface->getRealTimeClock(currentTime,&length);
                    404:         
                    405:         for ( i = 0; i < length; i++ )
                    406:         {
                    407:             longTime |= currentTime[i] << ((length-i-1)*8);
                    408:         }
                    409:         *secs = longTime;
                    410:     }
                    411: 
                    412:     if( (options == kPEWriteTOD) && (gOurself->ourRTCinterface != NULL) )
                    413:     {
                    414:         gOurself->ourRTCinterface->setRealTimeClock((UInt8 *)secs);
                    415:     }    
                    416: 
                    417:     return 0;
                    418: }
                    419: 
                    420: 
                    421: // **********************************************************************************
                    422: // PMU_PE_write_IIC
                    423: //
                    424: // **********************************************************************************
                    425: static int PMU_PE_write_IIC ( unsigned char, unsigned char, unsigned char )
                    426: {
                    427:     kprintf ("PMU_PE_write_IIC - ");
                    428: 
                    429:     return 1;
                    430: }
                    431: 
                    432: 
                    433: // **********************************************************************************
                    434: // PMU_PE_poll_input
                    435: //
                    436: // System interrupts are disabled, but we are still operating the PMU for mini-
                    437: // monitor keyboard input.  We are called here in a loop to service the PMU.
                    438: //
                    439: // **********************************************************************************
                    440: static int PMU_PE_poll_input ( unsigned int, char *  )
                    441: {
                    442:     return 1;  // XXX -- svail: what is the correct value???
                    443: }
                    444: 
                    445: #if 0
                    446: // **********************************************************************************
                    447: // poll_device
                    448: //
                    449: // System interrupts are disabled, but we are still operating the PMU for mini-
                    450: // monitor keyboard input.  We are called here in a loop to service the PMU.
                    451: //
                    452: // **********************************************************************************
                    453: void ApplePMU::poll_device( void )
                    454: {
                    455: if ( *VIA1_interruptFlag & 0x04 ) {            // is shift register done? ( ifSR )
                    456:        serviceShiftRegister();                 // yes, handle it
                    457:        return;
                    458: }
                    459: if ( *VIA1_interruptFlag & 0x10 ) {            // is PMU requesting service? ( ifCB1 )
                    460:        *VIA1_interruptFlag = 0x10;             // yes, clear interrupt ( ifCB1 )
                    461:        PGE_ISR_state = kPMUidle;               // and handle it
                    462:        servicePMU();
                    463: }
                    464: }
                    465: #endif
                    466: 
                    467: // **********************************************************************************
                    468: // receiveMsg
                    469: //
                    470: // 
                    471: //
                    472: // **********************************************************************************
                    473: void receiveMsg ( OSObject * theDriver, void * newRequest, void *, void *, void * )
                    474: {
                    475: ApplePMU * PMUdriver = (ApplePMU *) theDriver;
                    476: 
                    477: if ( (PMUdriver->PGE_ISR_state == kPMUidle) && !PMUdriver->adb_reading ) {
                    478:        PMUdriver->StartPMUTransmission((PMUrequest *)newRequest);
                    479: }
                    480: else {
                    481:        ((PMUrequest *) newRequest)->prev = PMUdriver->queueTail;
                    482:         ((PMUrequest *) newRequest)->next = NULL;
                    483:         if ( PMUdriver->queueTail != NULL ) {
                    484:             PMUdriver->queueTail->next = (PMUrequest *) newRequest;
                    485:         }
                    486:         else {
                    487:             PMUdriver->queueHead = (PMUrequest *)newRequest;
                    488:         }
                    489:         PMUdriver->queueTail =  (PMUrequest *)newRequest;
                    490: }
                    491: }
                    492: 
                    493: 
                    494: // **********************************************************************************
                    495: // timeoutOccurred
                    496: //
                    497: // Our adb-read timer has expired after sending an adb-read command to the PMU.
                    498: // This means there is no such addressed device on the ADB bus.
                    499: // We call back to the ADB driver with a zero-characters-received response and
                    500: // dequeue our command queue and carry on.
                    501: // **********************************************************************************
                    502: void ApplePMU::timeoutOccurred ( void )
                    503: {
                    504: adb_reading = false;
                    505: clientRequest->pmRLength = 0;                          // nothing was read
                    506: clientRequest->sync->signal();                 // unblock the caller
                    507: clientRequest = 0;
                    508: CheckRequestQueue();
                    509: }
                    510: 
                    511: 
                    512: // ****************************************************************************
                    513: // CheckRequestQueue
                    514: // Called at interrupt time when current request is complete.  We start
                    515: // another request here if one is in queue.
                    516: // ****************************************************************************
                    517: void ApplePMU::CheckRequestQueue ( void )
                    518: {
                    519: PMUrequest * nextRequest;
                    520: 
                    521: if ( queueHead != NULL ) {                     // is queue empty?
                    522:         nextRequest = queueHead;               // no, dequeue first command
                    523:         queueHead = nextRequest->next;
                    524:         if ( queueHead == NULL ) {
                    525:             queueTail = NULL;
                    526:         }
                    527:         StartPMUTransmission(nextRequest);     // and send it to the PMU
                    528: }
                    529: }
                    530: 
                    531: 
                    532: // **********************************************************************************
                    533: // enqueueCommand
                    534: //
                    535: // **********************************************************************************
                    536: void ApplePMU::enqueueCommand ( PMUrequest * request )
                    537: {
                    538: commandQueue->enqueueCommand(true,request);
                    539: }
                    540: 
                    541: 
                    542: // **********************************************************************************
                    543: // ADBinput
                    544: //
                    545: // The PGE has interrupted with ADB data.  We package this up and send
                    546: // it to our ADB client, if there is one, either as the result to its previous
                    547: // read command, or as autopoll data.
                    548: //
                    549: // **********************************************************************************
                    550: void ApplePMU::ADBinput(UInt32 theLength, UInt8 * theInput)
                    551: {
                    552: if ( theInput[0] & kPMUautopoll ) {                                    // autopoll data?
                    553:         if ( ADBclient != NULL ) {
                    554: //            kprintf("autopoll: %d %02x %02x %02x %02x\n", theLength, theInput[0], theInput[1], theInput[2], theInput[3]);
                    555: 
                    556:             (* ADBclient)(ADBid, theInput[1], theLength-2, theInput+2 );// yes, call adb input handler
                    557:         }
                    558:         return;
                    559: }
                    560: if ( adb_reading ) {                                                   // no, expecting adb input?
                    561:         if ( clientRequest->pmSBuffer1[0] == theInput[1] ) {           // yes, is it our input?
                    562:            // q8q                                                      // yes, turn off our timer
                    563:             clientRequest->pmRLength = theLength-2;                    // this much was read
                    564:             clientRequest->pmRBuffer = theInput+2;                     // to here
                    565:             clientRequest->sync->signal();                             // unblock the caller
                    566:            clientRequest = 0;
                    567:             adb_reading = false;
                    568:             return;
                    569:             }
                    570:         }
                    571: kprintf("unexpected adb input: %02d %02x %02x %02x %02x %02x\n", theLength, theInput[0], theInput[1], theInput[2], theInput[3], clientRequest->pmSBuffer1[0]);
                    572: }
                    573: 
                    574: 
                    575: // **********************************************************************************
                    576: // registerForADBInterrupts
                    577: //
                    578: // Some driver is calling to say it is prepared to receive "unsolicited" adb
                    579: // interrupts (e.g. autopoll keyboard and trackpad data).  The parameters identify
                    580: // who to call when we get one.
                    581: // **********************************************************************************
                    582: void ApplePMU::registerForADBInterrupts ( ADB_callback_func client, IOService * caller )
                    583: {
                    584: ADBclient = client;
                    585: ADBid = caller;
                    586: }
                    587: 
                    588: 
                    589: // **********************************************************************************
                    590: // registerForPowerInterrupts
                    591: //
                    592: // Some driver is calling to say it is prepared to receive "unsolicited" power-system
                    593: // interrupts (e.g. battery low).  The parameters identify who to call when we get one.
                    594: // **********************************************************************************
                    595: void ApplePMU::registerForPowerInterrupts ( pmCallback_func buttonHandler, IOService * caller )
                    596: {
                    597: PWRclient = buttonHandler;
                    598: PWRid = caller;
                    599: }
                    600: 
                    601: 
                    602: // **********************************************************************************
                    603: // registerForClockInterrupts
                    604: //
                    605: // Some driver is calling to say it is prepared to receive "unsolicited" real-time clock
                    606: // interrupts (e.g. one-second tick).  The parameters identify who to call when we get one.
                    607: // **********************************************************************************
                    608: void ApplePMU::registerForClockInterrupts ( pmCallback_func tickHandler, IOService * caller )
                    609: {
                    610: RTCclient = tickHandler;
                    611: RTCid = caller;
                    612: }
                    613: 
                    614: 
                    615: // **********************************************************************************
                    616: // buttonInput
                    617: //
                    618: // The PGE has interrupted with Brightness/Contrast data.  We package this up and send
                    619: // it to our Display client, if there is one.
                    620: //
                    621: // **********************************************************************************
                    622: void ApplePMU::buttonInput ( UInt32 theLength, UInt8 * theInput )
                    623: {
                    624: if ( PWRclient != NULL ) {
                    625:        (* PWRclient)(PWRid, theLength-1, theInput+1);
                    626: }
                    627: }
                    628: 
                    629: // **********************************************************************************
                    630: 
                    631: bool ApplePMU::serializeBatteryInfo( void * target, void * ref, OSSerialize * s )
                    632: {
                    633:     UInt32             flags, current, capacity;
                    634:     OSArray *          array;
                    635:     OSDictionary *     dict;
                    636:     OSNumber   *       num;
                    637:     UInt32             battery;
                    638:     UInt8              data[16];
                    639:     IOByteCount                readLen;
                    640:     IOReturn           err;
                    641:     bool               ok = true;
                    642: 
                    643:     array = OSArray::withCapacity(2);
                    644:     if( !array)
                    645:         return( false );
                    646:     
                    647:     for( battery = 1; battery <= 2; battery++) {
                    648:         data[0] = battery;
                    649:         err = ((ApplePMU *) target)->sendMiscCommand( kPMUGetSOB,
                    650:                                         1, data, &readLen, data );
                    651:         if( kIOReturnSuccess == err) {
                    652:             switch( data[0] ) {
                    653:                 case 3:
                    654:                 case 4:
                    655:                     current = data[2];
                    656:                     capacity = data[3];
                    657:                     break;
                    658:                 case 5:
                    659:                     current = (data[2] << 8) | data[3];
                    660:                     capacity = (data[4] << 8) | data[5];
                    661:                     break;
                    662:                 default:
                    663:                     continue;
                    664:             }
                    665:             flags = data[1];
                    666:             dict = OSDictionary::withCapacity(2);
                    667:             if( !dict)
                    668:                 continue;
                    669:             num = OSNumber::withNumber(flags, 32);
                    670:             if( num) {
                    671:                 dict->setObject(kIOBatteryFlagsKey, num);
                    672:                 num->release();
                    673:             }
                    674:             num = OSNumber::withNumber(current, 32);
                    675:             if( num) {
                    676:                 dict->setObject(kIOBatteryCurrentChargeKey, num);
                    677:                 num->release();
                    678:             }
                    679:             num = OSNumber::withNumber(capacity, 32);
                    680:             if( num) {
                    681:                 dict->setObject(kIOBatteryCapacityKey, num);
                    682:                 num->release();
                    683:             }
                    684:             array->setObject( dict );
                    685:             dict->release();
                    686:         }
                    687:     }
                    688: 
                    689:     ok = array->serialize(s);
                    690:     array->release();
                    691:     
                    692:     return( ok );
                    693: }
                    694: 
                    695: 
                    696: // **********************************************************************************
                    697: // sendMiscCommand
                    698: //
                    699: // Some driver is calling to send some miscellaneous command.  We copy this into a
                    700: // PMU command and enqueue it to our command queue.
                    701: //
                    702: // The read-length parameter is ignored on entry.  On exit it is set to the number
                    703: // of bytes read in response to transmission of the command.
                    704: // **********************************************************************************
                    705: IOReturn ApplePMU::sendMiscCommand ( UInt32 Command, IOByteCount  SLength,
                    706:                        UInt8 * SBuffer, IOByteCount * RLength, UInt8 * RBuffer )
                    707: {
                    708: PMUrequest     request;
                    709: SInt32         rsp_length;
                    710: SInt32         send_length;
                    711: 
                    712: rsp_length = rspLengthTable[Command];                  // get cmd and response lengths from table
                    713: send_length = cmdLengthTable[Command];
                    714: 
                    715: if ( ((SLength != 0) && (SBuffer == NULL)) ||                  // validate pointers
                    716:      ((rsp_length != 0) && (RBuffer == NULL)) ||
                    717:      (RLength == NULL) ) {
                    718:     return kPMUParameterError;
                    719: }
                    720: if ( (Command != kPMUdownloadFlash) &&
                    721:      ((send_length != -1) && ((IOByteCount )send_length != SLength)) ) {
                    722:     return kPMUParameterError;
                    723: }
                    724: 
                    725: if ( send_length > MISC_LENGTH ) {
                    726:     return kPMUParameterError;
                    727: }
                    728: 
                    729: request.sync = IOSyncer::create();
                    730: request.pmCommand = Command;
                    731: request.pmFlag = false;                // this is usually correct, but the API needs to be enhanced
                    732: request.pmSLength1 = 0;
                    733: request.pmSBuffer2 = SBuffer;
                    734: request.pmSLength2 = SLength;
                    735: request.pmRBuffer = RBuffer;
                    736: 
                    737: commandQueue->enqueueCommand(true, &request);
                    738: request.sync->wait();                  // wait till done
                    739: 
                    740: *RLength = request.pmRLength;                          // set user's receive byte count
                    741:     
                    742: return kPMUNoError;
                    743: }
                    744: 
                    745: 
                    746: // **********************************************************************************
                    747: // StartPMUTransmission
                    748: //
                    749: // Transmission of the command byte is started.  The transaction will be
                    750: // completed by the Shift Register Interrupt Service Routine.
                    751: // **********************************************************************************
                    752: void ApplePMU::StartPMUTransmission ( PMUrequest * plugInMessage )
                    753: {
                    754: clientRequest = plugInMessage;
                    755: firstChar = plugInMessage->pmCommand;          // get command byte
                    756: charCountS1 = plugInMessage->pmSLength1;       // get caller's length counters
                    757: charCountS2 = plugInMessage->pmSLength2;
                    758: dataPointer1 = plugInMessage->pmSBuffer1;      // and transmit data pointers
                    759: dataPointer2 = plugInMessage->pmSBuffer2;
                    760: dataPointer = plugInMessage->pmRBuffer;                // set up read pointer for data bytes
                    761: charCountR = rspLengthTable[firstChar];                // get response length from table
                    762: charCountR2 = charCountR;
                    763:                                        // figure out what happens after command byte transmission
                    764: if ( cmdLengthTable[firstChar] < 0 ) {         // will we be sending a length byte next?
                    765:         PGE_ISR_state = kPMUxmtLen;            // yes
                    766: }
                    767: else {                                         // no, will we be sending data next?
                    768:         if ( cmdLengthTable[firstChar] > 0 ) {
                    769:             PGE_ISR_state = kPMUxmtData;       // yes
                    770:         }
                    771:         else {                                 // no, will we be receiving a length byte next?
                    772:             if ( charCountR < 0 ) {
                    773:                 PGE_ISR_state = kPMUreadLen_cmd;       // yes
                    774:             }
                    775:             else {                                     // no, will we be receiving data next?
                    776:                 if ( charCountR > 0 ) {
                    777:                     PGE_ISR_state = kPMUreadData;      // yes
                    778:                 }
                    779:                 else {
                    780:                     PGE_ISR_state = kPMUdone;          // no, this is a single-byte transaction
                    781:                 }
                    782:             }
                    783:         }
                    784: }
                    785:                                        // ready to start the command byte
                    786: *VIA1_auxillaryControl |= 0x1C;                // set shift register to output
                    787: *VIA1_shift = firstChar;               // give it the byte (this clears any pending SR interrupt)
                    788: // *VIA1_interruptEnable = 0x84;       // enable SR interrupt
                    789: *VIA2_dataB &= ~PMreq;                 // assert /REQ
                    790: return;
                    791: }
                    792: 
                    793: #if 0
                    794: // ****************************************************************************
                    795: //     shiftRegisterInt
                    796: //
                    797: // ****************************************************************************
                    798: 
                    799: void shiftRegisterInt ( OSObject * PMUdriver, IOInterruptEventSource *, int )
                    800: {
                    801: ((ApplePMU *)PMUdriver)->serviceShiftRegister();
                    802: }
                    803: #endif
                    804: 
                    805: 
                    806: // ****************************************************************************
                    807: //     commandDoneInt
                    808: //
                    809: // ****************************************************************************
                    810: 
                    811: void commandDoneInt ( OSObject * PMUdriver, IOInterruptEventSource *, int )
                    812: {
                    813:     ApplePMU * pmu = (ApplePMU *)PMUdriver;
                    814:     pmu->PGE_ISR_state = kPMUidle;                     // set the state
                    815:     if ( pmu->clientRequest->pmFlag ) {                        // does this command cause input?
                    816:         if ( ! pmu->adb_reading ) {                    // yes, is this the input completion?
                    817:             pmu->adb_reading = true;                   // no, don't unblock caller now
                    818: //q8q                                                  // start timer
                    819:             if ( pmu->PMU_int_pending ) {                      // is PMU now requesting service?
                    820:                 pmu->PMU_int_pending = false;
                    821:                 *(pmu->VIA1_auxillaryControl) |= 0x1C;         // set shift register to output
                    822:                 *(pmu->VIA1_shift) = kPMUreadINT;              // give it this command byte
                    823:                 *(pmu->VIA2_dataB) &= ~(pmu->PMreq);           // assert /REQ
                    824: //             *VIA1_interruptEnable = 0x84;                   // enable SR interrupt
                    825:                 pmu->PGE_ISR_state = kPMUreadLen_int;          // next int is cmd byte xmt done
                    826:                 pmu->dataPointer = &(pmu->interruptState[0]);  // set up read ptr for data bytes
                    827:             }
                    828:             return;
                    829:         }
                    830:     }
                    831: 
                    832:     pmu->clientRequest->sync->signal();                // unblock the caller
                    833:     pmu->clientRequest = 0;
                    834:     if ( !(pmu->PMU_int_pending) ) {                   // is PMU now requesting service?
                    835:         pmu->CheckRequestQueue();                      // no, start next queued transaction
                    836:     }
                    837:     else {
                    838:         pmu->PMU_int_pending = false;
                    839:         *(pmu->VIA1_auxillaryControl) |= 0x1C;         // set shift register to output
                    840:         *(pmu->VIA1_shift) = kPMUreadINT;              // give it this command byte
                    841:         *(pmu->VIA2_dataB) &= ~(pmu->PMreq);           // assert /REQ
                    842: //     *VIA1_interruptEnable = 0x84;                   // enable SR interrupt
                    843:         pmu->PGE_ISR_state = kPMUreadLen_int;          // next int is cmd byte xmt done
                    844:         pmu->dataPointer = &(pmu->interruptState[0]);  // set up read ptr for data bytes
                    845:     }
                    846: }
                    847: 
                    848: 
                    849: // ****************************************************************************
                    850: //     unsolicitedInt
                    851: //
                    852: // ****************************************************************************
                    853: 
                    854: void unsolicitedInt ( OSObject * PMUdriver, IOInterruptEventSource *, int )
                    855: {
                    856:     ApplePMU * pmu = (ApplePMU *)PMUdriver;
                    857:     if ( pmu->interruptState[0] & kPMUADBint ) {       // what kind of int was it?
                    858:         pmu->ADBinput((UInt32)(pmu->charCountR), &(pmu->interruptState[0]));   // ADB
                    859:     }
                    860:     else {
                    861:         if ( pmu->interruptState[0] & kPMUbattInt ) {
                    862: //            kprintf("battery PGE interrupt\n");
                    863:         }
                    864:         else {
                    865:             if ( pmu->interruptState[0] & kPMUoneSecInt ) {
                    866: //             kprintf("one-second PGE interrupt\n");
                    867:                 if ( pmu->RTCclient != NULL ) {                // one-second interrupt
                    868: //                  (* RTCclient)(RTCid,0,0,0);
                    869:                 }
                    870:             }
                    871:             else {
                    872:                 if ( pmu->interruptState[0] & kPMUenvironmentInt ) {
                    873: //                    kprintf("environment interrupt\n");
                    874:                 }
                    875:                 else {
                    876:                     if ( pmu->interruptState[0] & kPMUbrightnessInt ) {
                    877: //                        kprintf("brightness button PGE interrupt\n");
                    878:                         pmu->buttonInput((UInt32)(pmu->charCountR),&(pmu->interruptState[0]));
                    879:                     }
                    880:                     else {
                    881: //                        kprintf("machine-dependent PGE interrupt\n");
                    882:                     }
                    883:                 }
                    884:             }
                    885:         }
                    886:     }
                    887:     pmu->PGE_ISR_state = kPMUidle;                     // set the state
                    888: 
                    889:     if ( !(pmu->PMU_int_pending) ) {                   // is PMU requesting service again?
                    890:       if (0 == pmu->clientRequest)
                    891:         pmu->CheckRequestQueue();                      // no, start next queued command
                    892:     }
                    893:     else {
                    894:         pmu->PMU_int_pending = false;
                    895:         *(pmu->VIA1_auxillaryControl) |= 0x1C;         // set shift register to output
                    896:         *(pmu->VIA1_shift) = kPMUreadINT;              // give it this command byte
                    897:         *(pmu->VIA2_dataB) &= ~(pmu->PMreq);           // assert /REQ
                    898: //     *VIA1_interruptEnable = 0x84;                   // enable SR interrupt
                    899:         pmu->PGE_ISR_state = kPMUreadLen_int;          // next int is cmd byte xmt done
                    900:         pmu->dataPointer = &(pmu->interruptState[0]);  // set up read ptr for data bytes
                    901:     }
                    902: }
                    903: 
                    904: bool ApplePMU::WaitForAckLo ( void )
                    905: {
                    906:     AbsoluteTime       deadline, now;
                    907:     bool               ok = true;
                    908: 
                    909:     clock_absolutetime_interval_to_deadline(
                    910:             SR_to_ack_transition_delay, &deadline);
                    911: 
                    912:     while( ok && ((*VIA2_dataB) & PMack) ) {
                    913:         clock_get_uptime( &now );
                    914:        ok = (CMP_ABSOLUTETIME( &now, &deadline ) < 0);
                    915:     }
                    916:     eieio();
                    917: 
                    918:     return( ok );
                    919: }
                    920: 
                    921: // ****************************************************************************
                    922: //     serviceShiftRegister
                    923: //     The shift register has finished shifting in a byte from PG&E or finished
                    924: //     shifting out a byte to PG&E.  Here we continue the transaction by starting
                    925: //     the i/o of the next byte, or we finish the transaction by indicating an
                    926: //     interrupt on either the command-done interrupt source or the autopoll
                    927: //     interrupt source on the workloop.
                    928: //     Both the VIA interrupt flag register and the interrupt enable registers
                    929: //     have been cleared by the ohare ISR.
                    930: // ****************************************************************************
                    931: 
                    932: void serviceShiftRegister ( ApplePMU * pmu )
                    933: {
                    934: 
                    935:     if( (*(pmu->VIA2_dataB) & pmu->PMack) )
                    936:        pmu->WaitForAckLo();
                    937: 
                    938:     *(pmu->VIA2_dataB) |= pmu->PMreq;                  // deassert /REQ line
                    939:                                                        // what state are we in?
                    940:     switch ( pmu->PGE_ISR_state ) {
                    941:         // We are processing a PMU interrupt.  We are reading the response
                    942:         // to the kPMUreadINT command, and a byte has arrived.
                    943:         case kPMUrcvData_int:
                    944:             *(pmu->dataPointer)++ = *(pmu->VIA1_shift);                // read the data byte
                    945:             (pmu->charCountR2)--;
                    946:             if ( pmu->charCountR2 > 0 ) {                      // is there more to read?
                    947:                 while ( !(*(pmu->VIA2_dataB) & pmu->PMack) ) {
                    948:                 }
                    949:                 *(pmu->VIA2_dataB) &= ~(pmu->PMreq);           // yes, assert /REQ
                    950: //             *VIA1_interruptEnable = 0x84;                   // enable SR interrupt
                    951:                 return;                                                // next int is next data byte
                    952:             }
                    953:             pmu->unsolicitedEventSrc->interruptOccurred(0,0,0);        // no, inform workloop
                    954:             return;
                    955:             
                    956:                                // We are processing a PMU interrupt.
                    957:                                // We have finished transmitting the kPMUreadINT command byte,
                    958:                                // and according to our table, we will be getting a response and
                    959:                                // a length byte for it.  Finish the transmit handshake and set
                    960:         case kPMUreadLen_int:  // up a receive for the length byte.
                    961:             pmu->receivedByte = *(pmu->VIA1_shift);    // read shift reg to turn off SR int
                    962:             pmu->PGE_ISR_state = kPMUrcvLen_int;
                    963:             *(pmu->VIA1_auxillaryControl) &= 0xEF;     // set shift register to input
                    964:             while ( !(*(pmu->VIA2_dataB) & pmu->PMack) ) {
                    965:             }
                    966:             *(pmu->VIA2_dataB) &= ~(pmu->PMreq);       // assert /REQ
                    967: //         *VIA1_interruptEnable = 0x84;               // enable SR interrupt
                    968:             return;                                    // next interrupt will be the length byte
                    969: 
                    970:                                // We are processing a PMU interrupt.
                    971:         case kPMUrcvLen_int:   // The length byte has arrived.  Read it and start data read
                    972:             pmu->charCountR = *(pmu->VIA1_shift);      // read it
                    973: 
                    974:             pmu->charCountR2 = pmu->charCountR;
                    975:             pmu->PGE_ISR_state = kPMUrcvData_int;
                    976:             while ( !(*(pmu->VIA2_dataB) & pmu->PMack) ) {
                    977:             }
                    978:             *(pmu->VIA2_dataB) &= ~(pmu->PMreq);       // assert /REQ
                    979: //         *VIA1_interruptEnable = 0x84;               // enable SR interrupt
                    980:             return;                                    // next int will be the first data byte
                    981: 
                    982:                                // We are doing a command transaction.  The command byte
                    983:         case kPMUxmtLen:       // transmission  has completed.  Start length byte transmission
                    984:             pmu->PGE_ISR_state = kPMUxmtData;
                    985:             while ( !(*(pmu->VIA2_dataB) & pmu->PMack) ) {
                    986:             }
                    987:             *(pmu->VIA1_shift) = (UInt8)(pmu->charCountS1 + pmu->charCountS2); // give it the length byte
                    988:             *(pmu->VIA2_dataB) &= ~(pmu->PMreq);               // assert /REQ
                    989: //         *VIA1_interruptEnable = 0x84;                       // enable SR interrupt
                    990:             return;                                            // next int start sending data
                    991: 
                    992:                                // We are doing a command transaction.  A byte transmission has
                    993:         case kPMUxmtData:      // completed .  Continue data byte transmission
                    994:             while ( !(*(pmu->VIA2_dataB) & pmu->PMack) ) {
                    995:             }
                    996:             if ( pmu->charCountS1 ) {
                    997:                 *(pmu->VIA1_shift) = *(pmu->dataPointer1)++;   // give it the next data byte from buffer 1
                    998:                 *(pmu->VIA2_dataB) &= ~(pmu->PMreq);           // assert /REQ
                    999:                 if ( --(pmu->charCountS1) + pmu->charCountS2 ) {
                   1000: //             *VIA1_interruptEnable = 0x84;           // enable SR interrupt
                   1001:                 return;                                        // next interrupt do another byte
                   1002:                 }
                   1003:             }
                   1004:             else {
                   1005:                 if ( pmu->charCountS2 ) {                              // buffer 1 empty,
                   1006:                     *(pmu->VIA1_shift) = *(pmu->dataPointer2)++;       // give it the next byte from buffer 2
                   1007:                     *(pmu->VIA2_dataB) &= ~(pmu->PMreq);               // assert /REQ
                   1008:                     if ( --(pmu->charCountS2) ) {
                   1009: //                     *VIA1_interruptEnable = 0x84;   // enable SR interrupt
                   1010:                         return;                                // next interrupt do another byte
                   1011:                     }
                   1012:                 }
                   1013:             }
                   1014:                                                        // sending last byte, what's next?
                   1015:             if ( pmu->charCountR < 0 ) {
                   1016:                 pmu->PGE_ISR_state = kPMUreadLen_cmd;  // we will receive a length byte
                   1017:             }
                   1018:             else {
                   1019:                 if ( pmu->charCountR > 0 ) {
                   1020:                     pmu->PGE_ISR_state = kPMUreadData; // we will receive constant-length data
                   1021:                 }
                   1022:                 else {
                   1023:                     pmu->PGE_ISR_state = kPMUdone;     // nothing, we're done
                   1024:                 }
                   1025:             }
                   1026: //         *VIA1_interruptEnable = 0x84;               // enable SR interrupt
                   1027:             return;
                   1028: 
                   1029:                        // We have finished the transmission part of a command transaction, and
                   1030:                        // according to our table, we will be getting a response and a
                   1031:                        // length byte for it.  Finish the transmit handshake and set up
                   1032:         case kPMUreadLen_cmd:                          // a receive for the length byte.
                   1033:             pmu->receivedByte = *(pmu->VIA1_shift);    // read shift reg to turn off SR int
                   1034:             pmu->PGE_ISR_state = kPMUrcvLen_cmd;
                   1035:             *(pmu->VIA1_auxillaryControl) &= 0xEF;     // set shift register to input
                   1036:             while ( !(*(pmu->VIA2_dataB) & pmu->PMack) ) {
                   1037:             }
                   1038:             *(pmu->VIA2_dataB) &= ~(pmu->PMreq);       // assert /REQ
                   1039: //         *VIA1_interruptEnable = 0x84;               // enable SR interrupt
                   1040:             return;                                    // next interrupt will be the length byte
                   1041: 
                   1042:         case kPMUrcvLen_cmd:           // the length byte has arrived, read it and start data read
                   1043:             pmu->charCountR = *(pmu->VIA1_shift);      // read it
                   1044:             pmu->charCountR2 = pmu->charCountR;
                   1045:             pmu->PGE_ISR_state = kPMUrcvData_cmd;
                   1046:             if ( pmu->charCountR2 > 0 ) {              // is there anything to read?
                   1047:                 if ( !(*(pmu->VIA2_dataB) & pmu->PMack) ) {
                   1048:                     if ( !(pmu->WaitForAckHi()) ) {
                   1049:                         return;                                // yes, make sure ACK is high
                   1050:                     }
                   1051:                 }
                   1052:                 *(pmu->VIA2_dataB) &= ~(pmu->PMreq);   // assert /REQ
                   1053:                 return;                                        // next interrupt will be first data byte
                   1054:             }
                   1055:             pmu->clientRequest->pmRLength = pmu->charCountR;   // no, this much was read
                   1056:             pmu->cmdDoneEventSrc->interruptOccurred(0,0,0);    // inform workloop
                   1057:             return;
                   1058:                        // We have finished the transmission part of a command transaction, and
                   1059:                        // according to our table, we will be getting a response but not a
                   1060:                        // length byte for it.  Finish the transmit handshake and set up
                   1061:         case kPMUreadData:                     // a receive for the first data byte.
                   1062:             if ( pmu->charCountR > 1 ) {
                   1063:                 pmu->charCountR2--;            // make constant (byte count + 1) into byte count
                   1064:                 pmu->charCountR--;
                   1065:             }
                   1066: //         receivedByte = *VIA1_shift;                 // read shift reg to turn off SR int
                   1067:             pmu->PGE_ISR_state = kPMUrcvData_cmd;
                   1068:             *(pmu->VIA1_auxillaryControl) &= 0xEF;     // set shift register to input
                   1069:             if ( !(*(pmu->VIA2_dataB) & pmu->PMack) ) {
                   1070:                 if ( !(pmu->WaitForAckHi()) ) {
                   1071:                     return;                            // make sure ACK is high
                   1072:                 }
                   1073:             }
                   1074:             *(pmu->VIA2_dataB) &= ~(pmu->PMreq);// assert /REQ
                   1075: //         *VIA1_interruptEnable = 0x84;       // enable SR interrupt
                   1076:             return;                            // next interrupt will be the first data character
                   1077: 
                   1078:                                // We are reading the response in a command transaction, and
                   1079:         case kPMUrcvData_cmd:  // a data byte has arrived
                   1080:             *(pmu->dataPointer)++ = *(pmu->VIA1_shift);        // read the data byte
                   1081:             pmu->charCountR2--;
                   1082:             if ( pmu->charCountR2 > 0 ) {              // is there more to read?
                   1083:                 if ( !(*(pmu->VIA2_dataB) & pmu->PMack) ) {
                   1084:                     if ( !(pmu->WaitForAckHi()) ) {
                   1085:                         return;                                // yes, make sure ACK is high
                   1086:                     }
                   1087:                 }
                   1088:                 *(pmu->VIA2_dataB) &= ~(pmu->PMreq);   // assert /REQ
                   1089:                 return;                                        // next interrupt will be next data byte
                   1090:             }
                   1091:             pmu->clientRequest->pmRLength = pmu->charCountR;   // no, this much was read
                   1092:             pmu->cmdDoneEventSrc->interruptOccurred(0,0,0);    // inform workloop
                   1093:             return;
                   1094:             
                   1095:         case kPMUdone:         // this was the last xmt SR interrupt of a command transaction
                   1096: //         receivedByte = *VIA1_shift;                 // read shift reg to turn off SR int
                   1097:             pmu->clientRequest->pmRLength = 0;                 // nothing was read
                   1098:             pmu->cmdDoneEventSrc->interruptOccurred(0,0,0);    // inform workloop
                   1099:             return;
                   1100:     }
                   1101:     return;
                   1102: }
                   1103: 
                   1104: 
                   1105: // ****************************************************************************
                   1106: //     PMUint
                   1107: //
                   1108: // ****************************************************************************
                   1109: 
                   1110: void PMUint ( OSObject * PMUdriver, IOInterruptEventSource *, int )
                   1111: {
                   1112: ((ApplePMU *)PMUdriver)->servicePMU();
                   1113: }
                   1114: 
                   1115: 
                   1116: // ****************************************************************************
                   1117: //     servicePMU
                   1118: //     PGE has interrupted.  Send the ReadInt command to find out why.
                   1119: //     When the command byte is sent, the Shift Register will interrupt.
                   1120: //     If we are mid-transaction when we find out about the interrupt,
                   1121: //     set a flag and find out why later.
                   1122: //
                   1123: // ****************************************************************************
                   1124: 
                   1125: void ApplePMU::servicePMU ( void )
                   1126: {
                   1127: if ( PGE_ISR_state != kPMUidle ) {
                   1128:         PMU_int_pending = true;
                   1129:         return;
                   1130: }
                   1131: 
                   1132: // *VIA1_interruptFlag = 0x10;                 // acknowledge VIA interrupt ( ifCB1 )
                   1133: // *VIA1_interruptEnable = 0x10;               // and disable it entirely ( ifCB1 )
                   1134: while ( !(*VIA2_dataB & PMack) ) {             // make sure ACK is high
                   1135: }
                   1136: *VIA1_auxillaryControl |= 0x1C;                        // set shift register to output
                   1137: *VIA1_shift = kPMUreadINT;                     // give it this command byte
                   1138: *VIA2_dataB &= ~PMreq;                         // assert /REQ
                   1139: // *VIA1_interruptEnable = 0x84;               // enable SR interrupt
                   1140: PGE_ISR_state = kPMUreadLen_int;               // set the state
                   1141: dataPointer = &interruptState[0];              // set up read pointer for data bytes
                   1142: return;                                                // return till character transmission completes
                   1143: }
                   1144: 
                   1145:        
                   1146: // ****************************************************************************
                   1147: // WaitForAckHi
                   1148: // ****************************************************************************
                   1149: bool ApplePMU::WaitForAckHi ( void )
                   1150: {
                   1151: // q8q struct timeval startTime;
                   1152: // q8q struct timeval currentTime;
                   1153: // q8q ns_time_t x;
                   1154: 
                   1155: // wait up to 32 milliseconds for Ack signal from PG&E to go high
                   1156: 
                   1157: // q8q IOGetTimestamp(&x);
                   1158: // q8q ns_time_to_timeval(x, &startTime);                      // get current time
                   1159: 
                   1160: while ( true ) {
                   1161:         if ( *VIA2_dataB & PMack ) {
                   1162:             return ( true );                                   // ack is high, return
                   1163:         }
                   1164: // q8q  IOGetTimestamp(&x);
                   1165: // q8q  ns_time_to_timeval(x, &currentTime);
                   1166: // q8q  if ( startTime.tv_usec > currentTime.tv_usec ) {
                   1167: // q8q      currentTime.tv_usec += 1000000;                    // clock has wrapped, adjust it
                   1168: // q8q  }
                   1169: // q8q  if ( currentTime.tv_usec > (startTime.tv_usec + 32000) ) {     // has 32 ms elapsed?
                   1170: // q8q      return ( false );                                          // yes, return
                   1171: // q8q  }
                   1172: }
                   1173: }
                   1174: 
                   1175: 
                   1176: // ****************************************************************************
                   1177: // DisablePMUInterrupt
                   1178: // ****************************************************************************
                   1179: void ApplePMU::DisablePMUInterrupt ( void )
                   1180: {
                   1181: *VIA1_interruptEnable = 1<<ifCB1;
                   1182: eieio();
                   1183: }
                   1184: 
                   1185: 
                   1186: // ****************************************************************************
                   1187: // EnablePMUInterrupt
                   1188: // ****************************************************************************
                   1189: void ApplePMU::EnablePMUInterrupt ( void )
                   1190: {
                   1191: *VIA1_interruptEnable = (1<<ifCB1) | 0x80;
                   1192: eieio();
                   1193: }
                   1194: 
                   1195: 
                   1196: // ****************************************************************************
                   1197: // AcknowledgePMUInterrupt
                   1198: // ****************************************************************************
                   1199: void ApplePMU::AcknowledgePMUInterrupt ( void )
                   1200: {
                   1201: *VIA1_interruptFlag = 1<<ifCB1;
                   1202: eieio();
                   1203: }
                   1204: 
                   1205: 
                   1206: // ****************************************************************************
                   1207: // DisableSRInterrupt
                   1208: // ****************************************************************************
                   1209: void ApplePMU::DisableSRInterrupt ( void )
                   1210: {
                   1211:     *VIA1_interruptEnable = 1<<ifSR;
                   1212: }
                   1213: 
                   1214: 
                   1215: // ****************************************************************************
                   1216: // EnableSRInterrupt
                   1217: // ****************************************************************************
                   1218: void ApplePMU::EnableSRInterrupt ( void )
                   1219: {
                   1220:     *VIA1_interruptEnable = (1<<ifSR) | 0x80;
                   1221: }
                   1222: 
                   1223: 
                   1224: 
                   1225: // ****************************************************************************
                   1226: // timer_expired
                   1227: //
                   1228: // Our adb-read timer has expired, so we have to notify our i/o thread by
                   1229: // enqueuing a Timeout message to its interrupt port.
                   1230: // ****************************************************************************
                   1231: // q8q void timer_expired(port_t mach_port)
                   1232: // q8q {
                   1233: 
                   1234: // q8q }

unix.superglobalmegacorp.com

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