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