|
|
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, ¤tTime); ! 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 }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.