|
|
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: ! 26: /********* ! 27: ! 28: cuda.m ! 29: ! 30: This file is a combination of the old cuda.c and the new pmu.m for PGE. ! 31: Cuda is based on a Motorola MC68HC05E1. ! 32: ! 33: NOTES: ! 34: ! 35: "WARNING" look for this string during integration. ! 36: cuda interrupts are cleared by reading the shift register. ! 37: cuda has a TIP (transaction in progress) signal which the PGE seems to lack. ! 38: PGE seems to require a "length" byte in command packets while cuda does not. ! 39: Signals: ! 40: TIP is asserted when 0. System asserts this when transaction is in progress. ! 41: BYTEACK is asserted when 0. When data is passed from the system to Cuda, ! 42: a toggle indicates to Cuda that the VIA data register is full. When ! 43: data is passed from Cuda to the system, a toggle indicates that the ! 44: system has read the data from the VIA and the VIA data register ! 45: is now empty. When no transaction in progress (note TIP), this ! 46: line is deasserted. ! 47: TREQ is asserted when 0. When asserted by Cuda, this indicates to the system ! 48: that Cuda is making a Transaction REQUEST. During a transaction which ! 49: is initiated by Cuda (as opposed to one initiated by system), this line ! 50: is negated prior to generating a VIA interrupt for the last byte ! 51: of data transacted. When no transaction is in progress (note TIP), ! 52: this line is negated. ! 53: ! 54: ! 55: *********/ ! 56: ! 57: ! 58: #include <sys/param.h> //for sysctl ! 59: #include <sys/proc.h> //for sysctl also (but not documented) ! 60: ! 61: #import <kern/clock.h> ! 62: #import <kernserv/prototypes.h> ! 63: #import <kernserv/clock_timer.h> ! 64: #import <kernserv/ns_timer.h> ! 65: #import <sys/time.h> ! 66: #import <sys/callout.h> ! 67: #import <machdep/ppc/proc_reg.h> ! 68: #import <driverkit/generalFuncs.h> ! 69: #import <driverkit/kernelDriver.h> ! 70: #import <driverkit/interruptMsg.h> ! 71: ! 72: #import <bsd/dev/ppc/drvPMU/pmu.h> ! 73: #import <bsd/dev/ppc/drvPMU/pmupriv.h> ! 74: #import <bsd/dev/ppc/drvPMU/pmumisc.h> ! 75: #include <sys/sysctl.h> //for debug2, debug3, debug4 in sysctl ! 76: #import "via6522.h" ! 77: #import "cuda_hdw.h" ! 78: #import "cuda.h" //must come after pmu definitions ! 79: ! 80: //typedefs from cuda.c: ! 81: // ! 82: // CudaInterruptState - internal ! 83: // ! 84: //#define kNS_TIMEOUT_AUTOPOLL 9000000000ULL ! 85: #define kNS_TIMEOUT_AUTOPOLL 4000000000ULL ! 86: ! 87: enum CudaInterruptState ! 88: { ! 89: CUDA_STATE_INTERRUPT_LIMBO = -1, // ! 90: CUDA_STATE_IDLE = 0, // ! 91: CUDA_STATE_ATTN_EXPECTED = 1, // ! 92: CUDA_STATE_TRANSMIT_EXPECTED = 2, // ! 93: CUDA_STATE_RECEIVE_EXPECTED = 3 // ! 94: }; ! 95: ! 96: typedef enum CudaInterruptState CudaInterruptState; ! 97: ! 98: ! 99: // ! 100: // CudaTransactionFlag - internal to cuda2.m, used to be in cuda.c ! 101: // ! 102: ! 103: enum CudaTransactionFlag ! 104: { ! 105: CUDA_TS_NO_REQUEST = 0x0000, ! 106: CUDA_TS_SYNC_RESPONSE = 0x0001, ! 107: CUDA_TS_ASYNC_RESPONSE = 0x0002 ! 108: }; ! 109: ! 110: typedef enum CudaTransactionFlag CudaTransactionFlag; ! 111: ! 112: ! 113: void gotInterruptCause(id, UInt32, UInt32, UInt8 *); ! 114: void cuda_timer_autopoll(port_t mach_port); ! 115: void timer_expired(port_t mach_port); //WARNING... not needed by Cuda? Was not in cuda.c ! 116: ! 117: extern id ApplePMUId; //in adb.m (remove this when adb becomes an indirect driver)(q8q) ! 118: ! 119: extern void kprintf(const char *, ...); ! 120: extern void bcopy(void *, void *, int); ! 121: // extern to let us fix up the boot time. ! 122: extern void set_boot_time(void); ! 123: extern msg_send_from_kernel(msg_header_t *, int, int); ! 124: ! 125: // Variables copied from cuda.c: ! 126: static long cuda_state_transition_delay_ticks; ! 127: volatile CudaInterruptState cuda_interrupt_state; ! 128: volatile CudaTransactionFlag cuda_transaction_state; ! 129: static port_t glob_port; ! 130: ! 131: //WARNING Hack to make pmutables.h work ! 132: extern SInt8 *cmdLengthTable; ! 133: extern SInt8 *rspLengthTable; ! 134: ! 135: ! 136: CudaRequest *cuda_request = NULL, *cuda_collided = NULL; ! 137: adb_packet_t cuda_unsolicited; ! 138: adb_packet_t *cuda_current_response = NULL; ! 139: ! 140: int cuda_transfer_count = 0; ! 141: boolean_t cuda_is_header_transfer = FALSE; ! 142: boolean_t cuda_is_packet_type = FALSE; ! 143: boolean_t cuda_initted = FALSE; ! 144: boolean_t debugging = FALSE; ! 145: boolean_t adb_reading = FALSE; ! 146: ! 147: static UInt8 *return_buff_pointer = NULL; ! 148: static boolean_t bImmediate_buff_needed = FALSE; ! 149: ! 150: // for Debug ! 151: pmADBinput_func cuda_debug_client; // Input handler in ADB client ! 152: static VIAAddress stat_aux_control; ! 153: static boolean_t p = FALSE; ! 154: int que_cuda_count; ! 155: int cuda_glob_dbug_freeze; //Can only be asserted through debugging tool ! 156: int cuda_glob_data1; ! 157: int cuda_glob_data2; ! 158: int cuda_freeze_counter; //This will become "static" after debugging phase ! 159: int cuda_freeze_prevcount; ! 160: ! 161: //sysctl debugging tool ! 162: struct ctldebug debug2 = { "cuda_glob_dbug_freeze", &cuda_glob_dbug_freeze }; ! 163: //struct ctldebug debug3 = { "cuda_glob_data1", &cuda_glob_data1 }; ! 164: //struct ctldebug debug4 = { "cuda_glob_data2", &cuda_glob_data2 }; ! 165: ! 166: ! 167: @implementation AppleCuda ! 168: ! 169: // ********************************************************************************** ! 170: // probe ! 171: // ! 172: // ! 173: // ! 174: // ********************************************************************************** ! 175: + (Boolean) probe : deviceDescription ! 176: { ! 177: id dev; ! 178: ! 179: if (cuda_initted) ! 180: return 1; ! 181: ! 182: cuda_initted = TRUE; ! 183: que_cuda_count = 0; ! 184: cuda_glob_dbug_freeze = 0; // 0. Only external debugger can change it now. ! 185: cuda_freeze_counter = 1; //2 vars needed to recover from BYTEACK hang ! 186: cuda_freeze_prevcount = 0; ! 187: ! 188: if ( (dev = [ self alloc ]) == nil ) { ! 189: return NO; ! 190: } ! 191: ! 192: if ([dev initFromDeviceDescription:deviceDescription] == nil) { ! 193: return NO; ! 194: } ! 195: ! 196: // tell ADB about us. This is a global variable accessible in adb.m ! 197: ApplePMUId = dev; ! 198: ! 199: set_boot_time(); ! 200: ! 201: return YES; ! 202: } ! 203: ! 204: ! 205: // ********************************************************************************** ! 206: // initFromDeviceDescription ! 207: // ! 208: // ! 209: // ! 210: // ********************************************************************************** ! 211: - initFromDeviceDescription:(IODeviceDescription *)deviceDescription ! 212: { ! 213: volatile unsigned char valcuda; ! 214: VIAAddress physicalAddress; ! 215: IORange * ioRange; ! 216: unsigned char *cuda_temp_reg; ! 217: ! 218: struct timeval x = {0,1000000}; // one second timeout on adb reads ! 219: ! 220: auto_power_on = 1; //default is to enable auto power on feature (after electrical power failure) ! 221: ! 222: if ( [super initFromDeviceDescription:deviceDescription] == nil ) { ! 223: [self free]; ! 224: return nil; ! 225: } ! 226: ! 227: [self setDeviceKind:"Cuda Subsystem"]; ! 228: [self setLocation:NULL]; ! 229: [self setName:"Cuda"]; ! 230: ! 231: ! 232: ioRange = [deviceDescription memoryRangeList]; ! 233: ! 234: physicalAddress = (VIAAddress)ioRange->start; ! 235: stat_aux_control = physicalAddress; ! 236: ! 237: //above works perfectly physicalAddress = (unsigned char*)POWERMAC_IO(PCI_VIA_BASE_PHYS); ! 238: ! 239: ! 240: //CUDA_REPLACE ! 241: ! 242: ! 243: VIA1_shift = physicalAddress + 0x1400; // initialize VIA addresses ! 244: VIA1_auxillaryControl = physicalAddress + 0x1600; ! 245: ! 246: VIA1_interruptFlag = physicalAddress + 0x1A00; ! 247: VIA1_interruptEnable = physicalAddress + 0x1C00; ! 248: VIA2_dataB = physicalAddress + 0x0000; // Hooper uses VIA 1 instead ! 249: ! 250: ! 251: PMack = kCudaAssertByteAcknowledge; //in cuda_hdw.h is 0x10 ! 252: ! 253: ! 254: ! 255: cuda_state_transition_delay_ticks = nsec_to_processor_clock_ticks(200); ! 256: //This is just 2 ticks ! 257: // Set the direction of the cuda signals. ByteACk and TIP are output and ! 258: // TREQ is an input ! 259: ! 260: cuda_temp_reg = physicalAddress + 0x0400; //dataDirectionB ! 261: *cuda_temp_reg |= (kCudaByteAcknowledgeMask | kCudaTransferInProgressMask); ! 262: *cuda_temp_reg &= ~kCudaTransferRequestMask; ! 263: ! 264: *VIA1_auxillaryControl = ( *VIA1_auxillaryControl | kCudaTransferMode) & ! 265: kCudaSystemRecieve; ! 266: ! 267: // Clear any posible cuda interupt. ! 268: if ( *VIA1_shift ); ! 269: ! 270: // Initialize the internal data. ! 271: ! 272: cuda_interrupt_state = CUDA_STATE_IDLE; ! 273: cuda_transaction_state = CUDA_TS_NO_REQUEST; ! 274: cuda_is_header_transfer = FALSE; ! 275: cuda_is_packet_type = FALSE; ! 276: cuda_transfer_count = 0; ! 277: cuda_current_response = NULL; ! 278: ! 279: // Terminate transaction and set idle state ! 280: // cuda_neg_tip_and_byteack(); ! 281: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress; ! 282: eieio(); ! 283: ! 284: // we want to delay 4 mS for ADB reset to complete ! 285: ! 286: delay(4000); ! 287: ! 288: // Clear pending interrupt if any... ! 289: //(void)cuda_read_data(); ! 290: valcuda = *VIA1_shift; eieio(); ! 291: ! 292: // Issue a Sync Transaction, ByteAck asserted while TIP is negated. ! 293: // cuda_assert_byte_ack(); ! 294: *VIA2_dataB &= kCudaAssertByteAcknowledge; eieio(); ! 295: ! 296: ! 297: // Wait for the Sync acknowledgement, cuda to assert TREQ ! 298: // cuda_wait_for_transfer_request_assert(); ! 299: while ( (*VIA2_dataB & kCudaTransferRequestMask) != 0 ) ! 300: { ! 301: eieio(); ! 302: } ! 303: eieio(); ! 304: ! 305: // Wait for the Sync acknowledgement interrupt. ! 306: // cuda_wait_for_interrupt(); ! 307: while ( (*VIA1_interruptFlag & kCudaInterruptMask) == 0 ) ! 308: { ! 309: eieio(); ! 310: } ! 311: eieio(); ! 312: ! 313: ! 314: // Clear pending interrupt ! 315: //(void)cuda_read_data(); ! 316: valcuda = *VIA1_shift; eieio(); ! 317: ! 318: // Terminate the sync cycle by Negating ByteAck ! 319: // cuda_neg_byte_ack(); ! 320: *VIA2_dataB |= kCudaNegateByteAcknowledge; eieio(); ! 321: ! 322: // Wait for the Sync termination acknowledgement, cuda negates TREQ. ! 323: // cuda_wait_for_transfer_request_neg(); ! 324: while ( (*VIA2_dataB & kCudaTransferRequestMask) == 0 ) ! 325: { ! 326: eieio(); ! 327: } ! 328: eieio(); ! 329: ! 330: ! 331: // Wait for the Sync termination acknowledgement interrupt. ! 332: // cuda_wait_for_interrupt(); ! 333: while ( (*VIA1_interruptFlag & kCudaInterruptMask) == 0 ) ! 334: { ! 335: eieio(); ! 336: } ! 337: eieio(); ! 338: ! 339: ! 340: // Terminate transaction and set idle state, TIP negate and ByteAck negate. ! 341: // cuda_neg_transfer_in_progress(); ! 342: *VIA2_dataB |= kCudaNegateTransferInProgress; eieio(); ! 343: ! 344: // Clear pending interrupt, if there is one... ! 345: //(void)cuda_read_data(); ! 346: valcuda = *VIA1_shift; eieio(); ! 347: ! 348: ! 349: ! 350: ! 351: ! 352: ADBclient = NULL; ! 353: RTCclient = NULL; ! 354: debugging = FALSE; ! 355: queueHead = NULL; ! 356: queueTail = NULL; ! 357: adb_reading = FALSE; ! 358: adb_read_timeout = timeval_to_ns_time(&x); ! 359: ! 360: //CUDA_REPLACE ! 361: // A.W. This call seems to have no counterpart in Cuda ! 362: // Pending interrupts are cleared with cuda_read_data() ! 363: *VIA1_interruptEnable = kCudaInterruptDisable;eieio(); // turn off any pending interrupt ! 364: valcuda = *VIA1_shift; eieio(); ! 365: ! 366: [self EnableCudaInterrupt]; // enable PGE interrupts. CUDA_REPLACE already ! 367: ! 368: [self enableAllInterrupts]; ! 369: ! 370: //WARNING... this was moved here in new pmu.m ! 371: if ([self startIOThread] != IO_R_SUCCESS) { ! 372: [self free]; ! 373: return nil; ! 374: } ! 375: port = IOConvertPort([self interruptPort],IO_KernelIOTask,IO_Kernel); ! 376: glob_port = port; //needed for non-ObjC functions ! 377: [self registerDevice]; ! 378: ! 379: ! 380: //A.W. I don't think Cuda needs to exclude any interrupts ! 381: //I need to set up a 5-second timer which will make sure that the Auto Poll ! 382: // feature of Cuda is never accidentally disabled by anybody ! 383: ns_timeout((func)cuda_timer_autopoll,(void *)port, kNS_TIMEOUT_AUTOPOLL ,CALLOUT_PRI_SOFTINT0); // start timer ! 384: ! 385: ! 386: return self; ! 387: } ! 388: ! 389: ! 390: // ********************************************************************************** ! 391: // free ! 392: // ! 393: // ! 394: // ! 395: // ********************************************************************************** ! 396: - free ! 397: { ! 398: return [ super free ]; ! 399: } ! 400: ! 401: ! 402: // ********************************************************************************** ! 403: // receiveMsg ! 404: // ! 405: // ! 406: // ! 407: // ********************************************************************************** ! 408: ! 409: ! 410: - (void)receiveMsg ! 411: { ! 412: CudaMachMessage * toQueue; ! 413: IOReturn result; ! 414: spl_t intstate; ! 415: //unsigned char interruptState; ! 416: ! 417: //interruptState = (*VIA2_dataB & kCudaInterruptStateMask) | (*VIA1_auxillaryControl & kCudaDirectionMask) ; ! 418: //if ( (interruptState == kCudaIdleState) && !adb_reading ) ! 419: ! 420: if (cuda_interrupt_state == CUDA_STATE_IDLE) ! 421: { ! 422: ! 423: if (p) kprintf("cuda2.m::receiveMsg will Xmit now... \n"); ! 424: //localMachMessage is class variable in cuda.h ! 425: localMachMessage.msgHeader.msg_size = sizeof(CudaMachMessage); ! 426: localMachMessage.msgHeader.msg_local_port = [self interruptPort]; ! 427: result = msg_receive(&localMachMessage.msgHeader, (msg_option_t)RCV_TIMEOUT, 0); ! 428: ! 429: #ifdef OMIT ! 430: if ( localMachMessage.msgBody.pmCallback == NULL ) ! 431: { ! 432: kprintf("ADAM: receiveMsg no callback\n"); ! 433: } ! 434: #endif ! 435: ! 436: if ( result == RCV_SUCCESS ) { ! 437: //Try Simon's suggestion ! 438: intstate = spltty(); ! 439: [self StartCudaTransmission:&localMachMessage.msgBody]; ! 440: splx(intstate); ! 441: } ! 442: } ! 443: else ! 444: { ! 445: if (p) kprintf("cuda2.m::receiveMsg will enqueue instead \n"); ! 446: ! 447: #ifdef DEBUG ! 448: if (cuda_glob_dbug_freeze == 1) ! 449: { ! 450: kprintf("cuda: Queued\n"); ! 451: } ! 452: #endif ! 453: ! 454: toQueue = (CudaMachMessage*)kalloc(sizeof(CudaMachMessage)); ! 455: toQueue->msgHeader.msg_size = sizeof(CudaMachMessage); ! 456: toQueue->msgHeader.msg_local_port = [self interruptPort]; ! 457: result = msg_receive(&toQueue->msgHeader, (msg_option_t)RCV_TIMEOUT, 0); ! 458: if ( result == RCV_SUCCESS ) { ! 459: toQueue->msgBody.prev = queueTail; ! 460: toQueue->msgBody.next = NULL; ! 461: if ( queueTail != NULL ) { ! 462: queueTail->msgBody.next = toQueue; ! 463: } ! 464: else ! 465: { ! 466: queueHead = toQueue; ! 467: } ! 468: queueTail = toQueue; ! 469: } ! 470: } ! 471: } ! 472: ! 473: ! 474: ! 475: ! 476: ! 477: ! 478: ! 479: // ********************************************************************************** ! 480: // timeoutOccurred ! 481: // ! 482: // Our adb-read timer has expired after sending an adb-read command to the PMU. ! 483: // This means there is no such addressed device on the ADB bus. ! 484: // We call back to the ADB driver with a zero-characters-received response and ! 485: // dequeue our command queue and carry on. ! 486: // ********************************************************************************** ! 487: - (void)timeoutOccurred ! 488: { ! 489: adb_reading = FALSE; ! 490: if ( clientRequest->pmCallback != NULL ) { // Make the client callback ! 491: clientRequest->pmCallback(clientRequest->pmId, clientRequest->pmRefNum, 0, NULL); ! 492: } // with zero received-length ! 493: [self CheckRequestQueue]; ! 494: } ! 495: ! 496: ! 497: // **************************************************************************** ! 498: // CheckRequestQueue ! 499: // Called at interrupt time when current request is complete. We may start ! 500: // another request here if one is in queue, or we may re-enable PMU interrupts ! 501: // (they were turned off in PMUStartIO) and return. ! 502: // **************************************************************************** ! 503: ! 504: - (void)CheckRequestQueue ! 505: { ! 506: CudaMachMessage * nextRequest; ! 507: ! 508: if ( queueHead == NULL ) { // is queue empty? ! 509: if (p) kprintf("cuda2.m::CheckRequestQueue empty \n"); ! 510: [self EnableCudaInterrupt]; // yes, enable interrupt and return ! 511: } ! 512: else ! 513: { ! 514: que_cuda_count--; ! 515: if (p) kprintf("cuda2.m::CheckRequestQueue will dequeue \n"); ! 516: nextRequest = queueHead; // no, dequeue first command ! 517: queueHead = nextRequest->msgBody.next; ! 518: if ( queueHead == NULL ) { ! 519: queueTail = NULL; ! 520: } ! 521: bcopy (&nextRequest->msgBody, &localMachMessage.msgBody, sizeof(CudaRequest)); // copy it ! 522: kfree(nextRequest, sizeof(CudaMachMessage)); // free its memory ! 523: [self StartCudaTransmission:&localMachMessage.msgBody]; // and send it to the Cuda ! 524: } ! 525: } ! 526: ! 527: ! 528: ! 529: ! 530: // ********************************************************************************** ! 531: // registerForADBAutopoll ! 532: // ! 533: // The ADB driver is calling to tell us that it is prepared to receive ! 534: // "unsolicited" ADB autopoll data. The parameter tells who to call ! 535: // when we get some. ! 536: // ! 537: // ********************************************************************************** ! 538: - (void)registerForADBAutopoll :(pmCallback_func)InputHandler ! 539: :(id)caller ! 540: { ! 541: if (p) kprintf("registerForADBAutopoll: %08x caller: %08x\n", InputHandler, caller); ! 542: ADBclient = InputHandler; ! 543: cuda_debug_client = ADBclient; // Debug use only ! 544: ADBid = caller; ! 545: } ! 546: ! 547: ! 548: // ********************************************************************************** ! 549: // ADBWrite ! 550: // ! 551: // ********************************************************************************** ! 552: - (PMUStatus)ADBWrite :(UInt32)DevAddr ! 553: :(UInt32)DevReg ! 554: :(UInt32)ByteCount ! 555: :(UInt8*)Buffer ! 556: :(UInt32)RefNum ! 557: :(id)Id ! 558: :(pmCallback_func)Callback ! 559: { ! 560: CudaMachMessage request; ! 561: msg_return_t return_code; ! 562: ! 563: if (p) kprintf("ADBWrite\n"); ! 564: ! 565: if (ByteCount > 7) ! 566: { ! 567: kprintf("bsd-dev-ppc-drvCuda-cuda.m: ADBWrite may fail\n"); ! 568: } ! 569: ! 570: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_ADB; ! 571: request.msgBody.a_cmd.a_header[1] = ADB_ADBCMD_WRITE_ADB | DevAddr << 4 | DevReg; ! 572: request.msgBody.a_cmd.a_header[2] = Buffer[0]; ! 573: request.msgBody.a_cmd.a_header[3] = Buffer[1]; ! 574: request.msgBody.a_cmd.a_header[4] = Buffer[2]; //necessary? ! 575: request.msgBody.a_cmd.a_header[5] = Buffer[3]; ! 576: request.msgBody.a_cmd.a_header[6] = Buffer[4]; ! 577: request.msgBody.a_cmd.a_header[7] = Buffer[5]; ! 578: request.msgBody.a_cmd.a_header[8] = Buffer[6]; ! 579: ! 580: //request.msgBody.a_cmd.a_hcount = 4; ! 581: request.msgBody.a_cmd.a_hcount = ByteCount + 2; ! 582: //Dave added unlimited-length adb_writereg() ! 583: ! 584: request.msgBody.a_cmd.a_bcount = 0; ! 585: request.msgBody.pmCallback = Callback; ! 586: ! 587: #ifdef OMIT ! 588: if (Callback == NULL) ! 589: { ! 590: kprintf("Cuda: ADBWrite callback is NULL\n"); ! 591: } ! 592: #endif ! 593: ! 594: request.msgBody.pmId = Id; ! 595: request.msgBody.pmRefNum = RefNum; ! 596: ! 597: request.msgHeader.msg_simple = TRUE; ! 598: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 599: request.msgHeader.msg_remote_port = port; ! 600: request.msgHeader.msg_local_port = PORT_NULL; ! 601: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 602: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 603: ! 604: if ( return_code == SEND_SUCCESS ) { ! 605: return kPMUNoError; ! 606: } ! 607: else { ! 608: return kPMUIOError; ! 609: } ! 610: } ! 611: ! 612: ! 613: // ********************************************************************************** ! 614: // ADBRead ! 615: // ! 616: // ********************************************************************************** ! 617: - (PMUStatus)ADBRead :(UInt32)DevAddr ! 618: :(UInt32)DevReg ! 619: :(UInt32)RefNum ! 620: :(id)Id ! 621: :(pmCallback_func)Callback ! 622: { ! 623: CudaMachMessage request; ! 624: msg_return_t return_code; ! 625: ! 626: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_ADB; ! 627: request.msgBody.a_cmd.a_header[1] = ADB_ADBCMD_READ_ADB | DevAddr << 4 | DevReg; ! 628: request.msgBody.a_cmd.a_hcount = 2; ! 629: //request.msgBody.a_cmd.a_bsize = sizeof(request.msgBody.a_cmd.a_buffer); ! 630: request.msgBody.a_reply.a_bsize = 8; //It's 8 in adb.h ! 631: //WARNING... try out line above 3/4/98 TitanL kernel ! 632: ! 633: request.msgBody.a_cmd.a_bcount = 0; ! 634: request.msgBody.pmCallback = Callback; ! 635: ! 636: #ifdef OMIT ! 637: if (Callback == NULL) ! 638: { ! 639: kprintf("Cuda: ADBRead callback is NULL\n"); ! 640: } ! 641: #endif ! 642: ! 643: request.msgBody.pmId = Id; ! 644: request.msgBody.pmRefNum = RefNum; ! 645: ! 646: request.msgHeader.msg_simple = TRUE; ! 647: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 648: request.msgHeader.msg_remote_port = port; ! 649: request.msgHeader.msg_local_port = PORT_NULL; ! 650: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 651: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 652: ! 653: if ( return_code == SEND_SUCCESS ) { ! 654: return kPMUNoError; ! 655: } ! 656: else { ! 657: return kPMUIOError; ! 658: } ! 659: } ! 660: ! 661: ! 662: // ********************************************************************************** ! 663: // ADBReset ! 664: // ! 665: // ********************************************************************************** ! 666: - (PMUStatus)ADBReset :(UInt32)RefNum ! 667: :(id)Id ! 668: :(pmCallback_func)Callback ! 669: { ! 670: CudaMachMessage request; ! 671: msg_return_t return_code; ! 672: ! 673: kprintf("CUDA: ADBReset\n"); ! 674: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_ADB; ! 675: request.msgBody.a_cmd.a_header[1] = ADB_ADBCMD_RESET_BUS; ! 676: request.msgBody.a_cmd.a_hcount = 2; ! 677: request.msgBody.a_cmd.a_bcount = 0; ! 678: request.msgBody.pmCallback = Callback; ! 679: request.msgBody.pmId = Id; ! 680: request.msgBody.pmRefNum = RefNum; ! 681: ! 682: request.msgHeader.msg_simple = TRUE; ! 683: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 684: request.msgHeader.msg_remote_port = port; ! 685: request.msgHeader.msg_local_port = PORT_NULL; ! 686: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 687: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 688: ! 689: if ( return_code == SEND_SUCCESS ) { ! 690: return kPMUNoError; ! 691: } ! 692: else { ! 693: return kPMUIOError; ! 694: } ! 695: } ! 696: ! 697: ! 698: // ********************************************************************************** ! 699: // ADBFlush ! 700: // ! 701: // ********************************************************************************** ! 702: - (PMUStatus)ADBFlush :(UInt32)DevAddr ! 703: :(UInt32)RefNum ! 704: :(id)Id ! 705: :(pmCallback_func)Callback ! 706: { ! 707: CudaMachMessage request; ! 708: msg_return_t return_code; ! 709: ! 710: if (p) kprintf("ADBFlush\n"); ! 711: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_ADB; ! 712: request.msgBody.a_cmd.a_header[1] = ADB_ADBCMD_FLUSH_ADB | (DevAddr << 4); ! 713: request.msgBody.a_cmd.a_hcount = 2; ! 714: request.msgBody.a_cmd.a_bcount = 0; ! 715: request.msgBody.pmId = Id; ! 716: request.msgBody.pmRefNum = RefNum; ! 717: request.msgBody.pmCallback = Callback; ! 718: ! 719: request.msgHeader.msg_simple = TRUE; ! 720: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 721: request.msgHeader.msg_remote_port = port; ! 722: request.msgHeader.msg_local_port = PORT_NULL; ! 723: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 724: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 725: ! 726: if ( return_code == SEND_SUCCESS ) { ! 727: return kPMUNoError; ! 728: } ! 729: else { ! 730: return kPMUIOError; ! 731: } ! 732: } ! 733: ! 734: ! 735: // ********************************************************************************** ! 736: // ADBSetPollList ! 737: // ! 738: // ! 739: // ********************************************************************************** ! 740: - (PMUStatus)ADBSetPollList :(UInt32)PollBitField ! 741: :(UInt32)RefNum ! 742: :(id)Id ! 743: :(pmCallback_func)Callback ! 744: { ! 745: CudaMachMessage request; ! 746: msg_return_t return_code; ! 747: ! 748: if (p) kprintf("ADBSetPollList\n"); ! 749: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; ! 750: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_DEVICE_LIST; ! 751: request.msgBody.a_cmd.a_header[2] = (PollBitField >> 8) & 0xFF; ! 752: request.msgBody.a_cmd.a_header[3] = PollBitField & 0xFF; ! 753: request.msgBody.a_cmd.a_hcount = 4; ! 754: request.msgBody.a_cmd.a_bcount = 0; ! 755: request.msgBody.pmRefNum = RefNum; ! 756: request.msgBody.pmId = Id; ! 757: request.msgBody.pmCallback = Callback; ! 758: ! 759: #ifdef OMIT ! 760: if (Callback == NULL) ! 761: { ! 762: kprintf("Cuda: ADBSetPollList callback is NULL\n"); ! 763: } ! 764: #endif ! 765: ! 766: ! 767: request.msgHeader.msg_simple = TRUE; ! 768: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 769: request.msgHeader.msg_remote_port = port; ! 770: request.msgHeader.msg_local_port = PORT_NULL; ! 771: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 772: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 773: ! 774: if ( return_code == SEND_SUCCESS ) { ! 775: return kPMUNoError; ! 776: } ! 777: else { ! 778: return kPMUIOError; ! 779: } ! 780: } ! 781: ! 782: ! 783: ! 784: ! 785: // ********************************************************************************** ! 786: // ADBSetFileServerMode() ! 787: // ! 788: // ********************************************************************************** ! 789: - (PMUStatus)ADBSetFileServerMode :(UInt32)RefNum ! 790: :(id)Id ! 791: :(pmCallback_func)Callback ! 792: ! 793: { ! 794: CudaMachMessage request; ! 795: msg_return_t return_code; ! 796: ! 797: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; ! 798: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_FILE_SERVER_FLAG; ! 799: request.msgBody.a_cmd.a_header[2] = TRUE; ! 800: request.msgBody.a_cmd.a_hcount = 3; ! 801: request.msgBody.a_cmd.a_bcount = 0; ! 802: request.msgBody.pmRefNum = RefNum; ! 803: request.msgBody.pmId = Id; ! 804: request.msgBody.pmCallback = Callback; ! 805: ! 806: request.msgHeader.msg_simple = TRUE; ! 807: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 808: request.msgHeader.msg_remote_port = port; ! 809: request.msgHeader.msg_local_port = PORT_NULL; ! 810: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 811: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 812: ! 813: if ( return_code == SEND_SUCCESS ) { ! 814: return kPMUNoError; ! 815: } ! 816: else { ! 817: return kPMUIOError; ! 818: } ! 819: } ! 820: ! 821: ! 822: // ********************************************************************************** ! 823: // ADBPollEnable ! 824: // ! 825: // ********************************************************************************** ! 826: - (PMUStatus)ADBPollEnable :(UInt32)RefNum ! 827: :(id)Id ! 828: :(pmCallback_func)Callback ! 829: ! 830: { ! 831: CudaMachMessage request; ! 832: msg_return_t return_code; ! 833: ! 834: if (p) kprintf("ADBPollEnable\n"); ! 835: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; ! 836: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_START_STOP_AUTO_POLL; ! 837: request.msgBody.a_cmd.a_header[2] = TRUE; ! 838: request.msgBody.a_cmd.a_hcount = 3; ! 839: request.msgBody.a_cmd.a_bcount = 0; ! 840: request.msgBody.pmRefNum = RefNum; ! 841: request.msgBody.pmId = Id; ! 842: request.msgBody.pmCallback = Callback; ! 843: ! 844: request.msgHeader.msg_simple = TRUE; ! 845: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 846: request.msgHeader.msg_remote_port = port; ! 847: request.msgHeader.msg_local_port = PORT_NULL; ! 848: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 849: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 850: ! 851: if ( return_code == SEND_SUCCESS ) { ! 852: return kPMUNoError; ! 853: } ! 854: else { ! 855: return kPMUIOError; ! 856: } ! 857: } ! 858: ! 859: ! 860: // ********************************************************************************** ! 861: // ADBPollDisable ! 862: // ! 863: // ********************************************************************************** ! 864: - (PMUStatus)ADBPollDisable :(UInt32)RefNum ! 865: :(id)Id ! 866: :(pmCallback_func)Callback ! 867: { ! 868: CudaMachMessage request; ! 869: msg_return_t return_code; ! 870: ! 871: if (p) kprintf("ADBPollDisable\n"); ! 872: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; ! 873: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_START_STOP_AUTO_POLL; ! 874: request.msgBody.a_cmd.a_header[2] = FALSE; ! 875: request.msgBody.a_cmd.a_hcount = 3; ! 876: request.msgBody.a_cmd.a_bcount = 0; ! 877: request.msgBody.pmRefNum = RefNum; ! 878: request.msgBody.pmId = Id; ! 879: request.msgBody.pmCallback = Callback; ! 880: ! 881: request.msgHeader.msg_simple = TRUE; ! 882: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 883: request.msgHeader.msg_remote_port = port; ! 884: request.msgHeader.msg_local_port = PORT_NULL; ! 885: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 886: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 887: ! 888: if ( return_code == SEND_SUCCESS ) { ! 889: return kPMUNoError; ! 890: } ! 891: else { ! 892: return kPMUIOError; ! 893: } ! 894: } ! 895: ! 896: ! 897: // ********************************************************************************** ! 898: // ADBSetPollRate ! 899: // ! 900: // ********************************************************************************** ! 901: - (PMUStatus)ADBSetPollRate :(UInt32)NewRate ! 902: :(UInt32)RefNum ! 903: :(id)Id ! 904: :(pmCallback_func)Callback ! 905: { ! 906: CudaMachMessage request; ! 907: msg_return_t return_code; ! 908: ! 909: if (p) kprintf("ADBSetPollRate\n"); ! 910: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; ! 911: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_AUTO_RATE; ! 912: request.msgBody.a_cmd.a_header[2] = NewRate; ! 913: request.msgBody.a_cmd.a_hcount = 3; ! 914: request.msgBody.a_cmd.a_bcount = 0; ! 915: request.msgBody.pmRefNum = RefNum; ! 916: request.msgBody.pmId = Id; ! 917: request.msgBody.pmCallback = Callback; ! 918: ! 919: request.msgHeader.msg_simple = TRUE; ! 920: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 921: request.msgHeader.msg_remote_port = port; ! 922: request.msgHeader.msg_local_port = PORT_NULL; ! 923: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 924: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 925: ! 926: if ( return_code == SEND_SUCCESS ) { ! 927: return kPMUNoError; ! 928: } ! 929: else { ! 930: return kPMUIOError; ! 931: } ! 932: } ! 933: ! 934: ! 935: // ********************************************************************************** ! 936: // ADBGetPollRate ! 937: // ! 938: // ********************************************************************************** ! 939: - (PMUStatus)ADBGetPollRate :(UInt32 *)CurrentRate ! 940: :(UInt32)RefNum ! 941: :(id)Id ! 942: :(pmCallback_func)Callback ! 943: { ! 944: return kPMUNotSupported; ! 945: } ! 946: ! 947: ! 948: // ********************************************************************************** ! 949: // ADBSetAlternateKeyboard ! 950: // ! 951: // ********************************************************************************** ! 952: - (PMUStatus)ADBSetAlternateKeyboard :(UInt32)DevAddr ! 953: :(UInt32)RefNum ! 954: :(id)Id ! 955: :(pmCallback_func)Callback ! 956: { ! 957: return kPMUNotSupported; ! 958: } ! 959: ! 960: ! 961: // ********************************************************************************** ! 962: // ADBinput ! 963: // ! 964: // The PGE has interrupted with ADB data. We package this up and send ! 965: // it to our ADB client, if there is one, either as the result to its previous ! 966: // read command, or as autopoll data. ! 967: // ! 968: // Removed since cuda_process_response() does the same thing ! 969: // ********************************************************************************** ! 970: ! 971: ! 972: // ********************************************************************************** ! 973: // registerForClockTicks ! 974: // ! 975: // The RTC driver is calling to tell us that it is prepared to receive clock ! 976: // ticks every second. The parameter block tells who to call when we get one. ! 977: // ! 978: // ********************************************************************************** ! 979: - (void)registerForClockTicks :(pmCallback_func)TickHandler ! 980: :(id)caller ! 981: { ! 982: RTCclient = TickHandler; ! 983: RTCid = caller; ! 984: } ! 985: ! 986: ! 987: // ********************************************************************************** ! 988: // setRealTimeClock ! 989: // ! 990: // The RTC driver is calling to set the real time clock. We translate this into ! 991: // a PMU command and enqueue it to our command queue. ! 992: // ! 993: // ********************************************************************************** ! 994: - (PMUStatus)setRealTimeClock :(UInt8 *)newTime ! 995: :(UInt32)RefNum ! 996: :(id)Id ! 997: :(pmCallback_func)Callback ! 998: { ! 999: CudaMachMessage request; ! 1000: msg_return_t return_code; ! 1001: ! 1002: if (p) kprintf("ADBSetRealTimeClock\n"); ! 1003: if ( newTime == NULL ) { ! 1004: return kPMUParameterError; ! 1005: } ! 1006: ! 1007: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; ! 1008: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_REAL_TIME; ! 1009: request.msgBody.a_cmd.a_hcount = 2; ! 1010: request.msgBody.a_cmd.a_buffer[0] = newTime[0]; ! 1011: request.msgBody.a_cmd.a_buffer[1] = newTime[1]; ! 1012: request.msgBody.a_cmd.a_buffer[2] = newTime[2]; ! 1013: request.msgBody.a_cmd.a_buffer[3] = newTime[3]; ! 1014: request.msgBody.a_cmd.a_bcount = 4; ! 1015: request.msgBody.pmRefNum = RefNum; ! 1016: request.msgBody.pmId = Id; ! 1017: request.msgBody.pmCallback = Callback; ! 1018: ! 1019: request.msgHeader.msg_simple = TRUE; ! 1020: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 1021: request.msgHeader.msg_remote_port = port; ! 1022: request.msgHeader.msg_local_port = PORT_NULL; ! 1023: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 1024: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 1025: ! 1026: if ( return_code == SEND_SUCCESS ) { ! 1027: return kPMUNoError; ! 1028: } ! 1029: else { ! 1030: return kPMUIOError; ! 1031: } ! 1032: } ! 1033: ! 1034: ! 1035: // ********************************************************************************** ! 1036: // getRealTimeClock ! 1037: // ! 1038: // The RTC driver is calling to read the real time clock. We translate this into ! 1039: // a PMU command and enqueue it to our command queue. ! 1040: // Called from PowerSurgeMB.m ! 1041: // ! 1042: // ********************************************************************************** ! 1043: - (PMUStatus)getRealTimeClock :(UInt8 *)currentTime ! 1044: :(UInt32)RefNum ! 1045: :(id)Id ! 1046: :(pmCallback_func)Callback ! 1047: { ! 1048: CudaMachMessage request; ! 1049: msg_return_t return_code; ! 1050: ! 1051: if (p) kprintf("ADBGetRealTimeClock\n"); ! 1052: ! 1053: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; ! 1054: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_GET_REAL_TIME; ! 1055: request.msgBody.a_cmd.a_hcount = 2; ! 1056: request.msgBody.a_cmd.a_bcount = 0; //A.W. added 2/27. Is it enough? Response Specs: ! 1057: // Attention Byte ! 1058: // Response Type = PSEUDO ! 1059: // Response Flag ! 1060: // Command (was) ! 1061: // Data (Real Time Clock MSB) ! 1062: // Data ! 1063: // Data ! 1064: // Data (RTC LSB) ! 1065: // Idle Byte ! 1066: ! 1067: //The a_cmd.a_buffer is filled in by cuda_transmit_data()... but I need receive_data ! 1068: //Called from PowerSurgeMB.m ! 1069: /*** following commented out because it doesn't look right ! 1070: request.msgBody.a_cmd.a_buffer[0] = currentTime[0]; ! 1071: request.msgBody.a_cmd.a_buffer[1] = currentTime[1]; ! 1072: request.msgBody.a_cmd.a_buffer[2] = currentTime[2]; ! 1073: request.msgBody.a_cmd.a_buffer[3] = currentTime[3]; ! 1074: ******/ ! 1075: bImmediate_buff_needed = TRUE; ! 1076: return_buff_pointer = currentTime; ! 1077: request.msgBody.a_reply.a_bsize = 8; //It's 8 in adb.h ! 1078: ! 1079: request.msgBody.pmRefNum = RefNum; ! 1080: request.msgBody.pmId = Id; ! 1081: request.msgBody.pmCallback = Callback; ! 1082: ! 1083: request.msgHeader.msg_simple = TRUE; ! 1084: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 1085: request.msgHeader.msg_remote_port = port; ! 1086: request.msgHeader.msg_local_port = PORT_NULL; ! 1087: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 1088: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 1089: ! 1090: if ( return_code == SEND_SUCCESS ) { ! 1091: return kPMUNoError; ! 1092: } ! 1093: else { ! 1094: return kPMUIOError; ! 1095: } ! 1096: } ! 1097: ! 1098: ! 1099: ! 1100: // ********************************************************************************** ! 1101: // setPowerupTime ! 1102: // This sets the future time (in seconds) when Cuda will power-up the system again ! 1103: // If the power is already on then nothing happens. TRICKLE SENSE must be asserted. ! 1104: // ! 1105: // ********************************************************************************** ! 1106: - (PMUStatus)setPowerupTime :(UInt8 *)newTime ! 1107: :(UInt32)RefNum ! 1108: :(id)Id ! 1109: :(pmCallback_func)Callback ! 1110: { ! 1111: CudaMachMessage request; ! 1112: msg_return_t return_code; ! 1113: ! 1114: if ( newTime == NULL ) { ! 1115: return kPMUParameterError; ! 1116: } ! 1117: ! 1118: if ( auto_power_on == 0) { ! 1119: return kPMUNoError; ! 1120: } ! 1121: ! 1122: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; ! 1123: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_POWER_UPTIME; ! 1124: request.msgBody.a_cmd.a_hcount = 2; ! 1125: request.msgBody.a_cmd.a_buffer[0] = newTime[0]; ! 1126: request.msgBody.a_cmd.a_buffer[1] = newTime[1]; ! 1127: request.msgBody.a_cmd.a_buffer[2] = newTime[2]; ! 1128: request.msgBody.a_cmd.a_buffer[3] = newTime[3]; ! 1129: request.msgBody.a_cmd.a_bcount = 4; ! 1130: request.msgBody.pmRefNum = RefNum; ! 1131: request.msgBody.pmId = Id; ! 1132: request.msgBody.pmCallback = Callback; ! 1133: ! 1134: request.msgHeader.msg_simple = TRUE; ! 1135: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 1136: request.msgHeader.msg_remote_port = port; ! 1137: request.msgHeader.msg_local_port = PORT_NULL; ! 1138: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 1139: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 1140: ! 1141: if ( return_code == SEND_SUCCESS ) { ! 1142: return kPMUNoError; ! 1143: } ! 1144: else { ! 1145: return kPMUIOError; ! 1146: } ! 1147: } ! 1148: ! 1149: ! 1150: // ********************************************************************************** ! 1151: // CudaMisc ! 1152: // ! 1153: // ! 1154: // ********************************************************************************** ! 1155: - (PMUStatus)CudaMisc :(UInt8 *)output ! 1156: :(UInt32)length ! 1157: :(UInt32)RefNum ! 1158: :(id)Id ! 1159: :(pmCallback_func)Callback ! 1160: { ! 1161: CudaMachMessage request; ! 1162: msg_return_t return_code; ! 1163: int i; ! 1164: ! 1165: for ( i = 0; i < length; i++ ) { ! 1166: //I should check for length < 8 but I trust callers in adb.m and PowerSurgeMB.m ! 1167: request.msgBody.a_cmd.a_header[i] = output[i]; ! 1168: } ! 1169: ! 1170: request.msgBody.a_cmd.a_hcount = length; ! 1171: request.msgBody.a_cmd.a_bcount = 0; ! 1172: //Don't need to worry about how big the caller's buffer is because ! 1173: // cuda's adb_packet_t buffer is 8 bytes, and it's the caller who ! 1174: // must copy the bytes in its callback function ! 1175: request.msgBody.a_reply.a_bsize = 8; //It's 8 in adb.h for adb_packet_type ! 1176: request.msgBody.pmRefNum = RefNum; ! 1177: request.msgBody.pmId = Id; ! 1178: request.msgBody.pmCallback = Callback; ! 1179: ! 1180: request.msgHeader.msg_simple = TRUE; ! 1181: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 1182: request.msgHeader.msg_remote_port = port; ! 1183: request.msgHeader.msg_local_port = PORT_NULL; ! 1184: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 1185: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 1186: ! 1187: if ( return_code == SEND_SUCCESS ) { ! 1188: return kPMUNoError; ! 1189: } ! 1190: else { ! 1191: return kPMUIOError; ! 1192: } ! 1193: ! 1194: } ! 1195: ! 1196: ! 1197: ! 1198: //This function calls back the ADB client (such as Mouse driver). ! 1199: -(void) cuda_process_response ! 1200: { ! 1201: ! 1202: if ( cuda_transaction_state == CUDA_TS_SYNC_RESPONSE ) ! 1203: { ! 1204: if ( cuda_request->pmCallback != NULL ) { // make the client callback ! 1205: ! 1206: if (p) kprintf("cuda_process_response: pmId = %08x, a_bcount = %08x, a_buffer = %08x\n", ! 1207: cuda_request->pmId, cuda_request->a_reply.a_bcount, cuda_request->a_reply.a_buffer); ! 1208: ! 1209: ! 1210: cuda_request->pmCallback ( cuda_request->pmId, ! 1211: cuda_request->pmRefNum, ! 1212: cuda_request->a_reply.a_bcount, ! 1213: cuda_request->a_reply.a_buffer ); ! 1214: } ! 1215: else ! 1216: { ! 1217: //It's OK to not have a callback since some callers don't care ! 1218: // about synchronous completion ! 1219: //kprintf("WARNING: Cuda process_response() has no callback\n"); ! 1220: } ! 1221: return_buff_pointer = NULL; //for getRealTimeClock only. a_buffer[] ! 1222: //above is ignored by PowerSurgeMB.m ! 1223: bImmediate_buff_needed = FALSE; ! 1224: //kprintf("cuda.m: cuda_process_response end \n"); ! 1225: } ! 1226: ! 1227: else ! 1228: { ! 1229: if ( cuda_transaction_state == CUDA_TS_ASYNC_RESPONSE ) ! 1230: { ! 1231: if ( ADBclient != NULL ) ! 1232: { // call the client input handler ! 1233: cuda_freeze_counter++; ! 1234: ! 1235: if (p) { ! 1236: kprintf("cuda2.m::cuda_process_response ASYNC \n"); ! 1237: kprintf("cuda2.m::ASYNC count is %d\n", cuda_current_response->a_bcount); ! 1238: kprintf("cuda2.m::ASYNC buffer 0 is %x\n", cuda_current_response->a_buffer[0]); ! 1239: kprintf("cuda2.m::ASYNC buffer 1 is %x\n", cuda_current_response->a_buffer[1]); ! 1240: kprintf("cuda2.m::ASYNC buffer 2 is %x\n", cuda_current_response->a_buffer[2]); ! 1241: kprintf("cuda2.m::ASYNC buffer 3 is %x\n", cuda_current_response->a_buffer[3]); ! 1242: kprintf("cuda2.m::ASYNC buffer 4 is %x\n", cuda_current_response->a_buffer[4]); ! 1243: kprintf("cuda2.m::ASYNC buffer 5 is %x\n", cuda_current_response->a_buffer[5]); ! 1244: kprintf("cuda2.m::ASYNC header 0 is %x\n", cuda_current_response->a_header[0]); ! 1245: kprintf("cuda2.m::ASYNC header 1 is %x\n", cuda_current_response->a_header[1]); ! 1246: kprintf("cuda2.m::ASYNC header 2 is %x\n", cuda_current_response->a_header[2]); ! 1247: } ! 1248: ! 1249: if (p) kprintf("cuda_process_response: ADBclient = %08x, ADBid = %08x\n", ADBclient, ADBid); ! 1250: ! 1251: #ifdef DEBUG ! 1252: cuda_glob_data1 = cuda_current_response->a_buffer[0]; ! 1253: cuda_glob_data2 = cuda_current_response->a_buffer[1]; ! 1254: if (cuda_glob_dbug_freeze == 1) ! 1255: { ! 1256: //kprintf("%x %x \n", cuda_glob_data1, cuda_glob_data2); ! 1257: } ! 1258: #endif ! 1259: //ADBClient is the global variable that clients registered with ! 1260: ADBclient(ADBid, ! 1261: 0, ! 1262: (cuda_current_response->a_header[2] >> 4) & 0xf, ! 1263: cuda_current_response->a_bcount, ! 1264: &cuda_current_response->a_buffer[0]); ! 1265: } ! 1266: } ! 1267: } ! 1268: } ! 1269: ! 1270: ! 1271: // ********************************************************************************** ! 1272: // readNVRAM ! 1273: // ! 1274: // The NVRAM driver is calling to read part of the NVRAM. We translate this into ! 1275: // a PMU command and enqueue it to our command queue. ! 1276: // ! 1277: // ********************************************************************************** ! 1278: - (PMUStatus) readNVRAM :(UInt32)Offset ! 1279: :(UInt32)Length ! 1280: :(UInt8 *)Buffer ! 1281: :(UInt32)RefNum ! 1282: :(id)Id ! 1283: :(pmCallback_func)Callback ! 1284: { ! 1285: return kPMUNotSupported; ! 1286: } ! 1287: ! 1288: ! 1289: // ********************************************************************************** ! 1290: // writeNVRAM ! 1291: // ! 1292: // The NVRAM driver is calling to write part of the NVRAM. We translate this into ! 1293: // a PMU command and enqueue it to our command queue. ! 1294: // ! 1295: // ********************************************************************************** ! 1296: - (PMUStatus) writeNVRAM:(UInt32)Offset ! 1297: :(UInt32)Length ! 1298: :(UInt8 *)Buffer ! 1299: :(UInt32)RefNum ! 1300: :(id)Id ! 1301: :(pmCallback_func)Callback ! 1302: { ! 1303: return kPMUNotSupported; ! 1304: } ! 1305: ! 1306: ! 1307: // ********************************************************************************** ! 1308: // registerForPowerInterrupts ! 1309: // ! 1310: // Some driver is calling to say it is prepared to receive "unsolicited" power-system ! 1311: // interrups (e.g. battery low). The parameter block says who to call when we get one. ! 1312: // ! 1313: // ********************************************************************************** ! 1314: - (void)registerForPowerInterrupts :(pmCallback_func)buttonHandler ! 1315: :(id)caller ! 1316: { ! 1317: PWRclient = buttonHandler; ! 1318: PWRid = caller; ! 1319: } ! 1320: ! 1321: ! 1322: // ********************************************************************************** ! 1323: // sendMiscCommand ! 1324: // ! 1325: // Some driver is calling to send some miscellaneous command. We copy this into a ! 1326: // PMU command and enqueue it to our command queue. ! 1327: // A.W. Not completed yet for Cuda commands!! ! 1328: // ********************************************************************************** ! 1329: - (PMUStatus)sendMiscCommand :(UInt32)Command ! 1330: :(UInt32)SLength ! 1331: :(UInt8 *)SBuffer ! 1332: :(UInt8 *)RBuffer ! 1333: :(UInt32)RefNum ! 1334: :(id)Id ! 1335: :(pmCallback_func)Callback ! 1336: { ! 1337: CudaMachMessage request; ! 1338: msg_return_t return_code; ! 1339: spl_t interruptState; ! 1340: ! 1341: ! 1342: if (Command == kPMUPmgrPWRoff) ! 1343: { ! 1344: //kprintf("\nCuda received power-down message\n"); ! 1345: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_POWER_DOWN; ! 1346: auto_power_on = 0; //console operator really wants to shut off power ! 1347: } ! 1348: else if (Command == kPMUresetCPU) ! 1349: { ! 1350: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_RESTART_SYSTEM; ! 1351: //kprintf("\nCuda received reset message\n"); ! 1352: } ! 1353: else ! 1354: { ! 1355: return kPMUParameterError; ! 1356: } ! 1357: ! 1358: //A.W. 3/17/98 I found out that reboots cannot happen from within ! 1359: // the mini-monitor because interrupts are turned off, which means ! 1360: // Cuda cannot get the subsequent command packet bytes to reboot ! 1361: // However, Simon says that next 2 lines are not necessary ! 1362: // WARNING The current file is checked out from trunk, don't check in ! 1363: interruptState = spltty(); ! 1364: splx(interruptState); ! 1365: //request.msgBody.a_reply.a_bsize = 0; //we don't expect any replies for two commands above ! 1366: request.msgBody.a_reply.a_bsize = 8; //reset fails WARNING ! 1367: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO; ! 1368: request.msgBody.a_cmd.a_hcount = 2; ! 1369: request.msgBody.a_cmd.a_bcount = 0; ! 1370: request.msgBody.pmRefNum = RefNum; ! 1371: request.msgBody.pmId = Id; ! 1372: request.msgBody.pmCallback = Callback; ! 1373: ! 1374: request.msgHeader.msg_simple = TRUE; ! 1375: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 1376: request.msgHeader.msg_remote_port = port; ! 1377: request.msgHeader.msg_local_port = PORT_NULL; ! 1378: request.msgHeader.msg_size = sizeof(CudaMachMessage); ! 1379: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 1380: ! 1381: if ( return_code == SEND_SUCCESS ) { ! 1382: return kPMUNoError; ! 1383: } ! 1384: else { ! 1385: return kPMUIOError; ! 1386: } ! 1387: } ! 1388: ! 1389: ! 1390: // ********************************************************************************** ! 1391: // StartCudaTransmission ! 1392: // ! 1393: // Called with PMU interrupts disabled. q8q ! 1394: // Transmission of the command byte is started. The transaction will be ! 1395: // completed by the Shift Register Interrupt Service Routine. ! 1396: // ********************************************************************************** ! 1397: - (void)StartCudaTransmission:(CudaRequest *)plugInMessage; ! 1398: { ! 1399: ! 1400: ! 1401: if (( *VIA2_dataB & kCudaTransferRequestMask) == 0) ! 1402: { ! 1403: //Simon says there's a collision here ! 1404: cuda_interrupt_state = CUDA_STATE_ATTN_EXPECTED; ! 1405: cuda_transaction_state = CUDA_TS_ASYNC_RESPONSE; ! 1406: [self cuda_queue: plugInMessage]; ! 1407: return; ! 1408: } ! 1409: ! 1410: //MAJOR CHANGE 8/6/98... 2 lines were at beginning, IDLE didn't make sense there ! 1411: if ( cuda_interrupt_state == CUDA_STATE_IDLE) ! 1412: { ! 1413: clientRequest = plugInMessage; ! 1414: firstChar = plugInMessage->a_cmd.a_header[0]; //Should be ADB_PACKET or PSEUDO ! 1415: charCountS1 = plugInMessage->a_cmd.a_hcount; ! 1416: ! 1417: dataPointer1 = &plugInMessage->a_cmd.a_header[0]; ! 1418: ! 1419: cuda_request = plugInMessage; ! 1420: cuda_request->a_reply.a_bcount = 0; ! 1421: ! 1422: ! 1423: // cuda_set_data_direction_to_output(); //On cuda value is 0x10; ! 1424: *VIA1_auxillaryControl |= kCudaSystemSend; eieio(); ! 1425: ! 1426: // ADBPollDisable is handled how? ! 1427: *VIA1_shift = firstChar; // give it the byte (this clears any pending SR interrupt) ! 1428: ! 1429: // Set up the transfer state info here. ! 1430: ! 1431: cuda_is_header_transfer = TRUE; ! 1432: cuda_transfer_count = 1; ! 1433: ! 1434: ! 1435: ! 1436: // *VIA2_dataB &= ~kCudaNegateTransferRequest; // yes, assert /REQ ! 1437: //I think I actually need to assert TIP here, not REQ. ! 1438: //eieio(); ! 1439: ! 1440: ! 1441: // cuda_neg_byte_ack(); ! 1442: *VIA2_dataB |= kCudaNegateByteAcknowledge; eieio(); ! 1443: ! 1444: // cuda_assert_transfer_in_progress(); ! 1445: *VIA2_dataB &= kCudaAssertTransferInProgress; eieio(); ! 1446: ! 1447: // The next state is going to be a transmit state, if there is ! 1448: // no collision. This is a requested response but call it sync. ! 1449: ! 1450: cuda_interrupt_state = CUDA_STATE_TRANSMIT_EXPECTED; ! 1451: ! 1452: //INVESTIGATE: we get here even if there was a collision and the ! 1453: // collision packet was put onto the queue. In that case it means ! 1454: // the transaction was ASYNC? ! 1455: // This entire function is protected by splt so no interrupts should ! 1456: // be happening at all. ! 1457: cuda_transaction_state = CUDA_TS_SYNC_RESPONSE; ! 1458: ! 1459: return; ! 1460: ! 1461: } ! 1462: } ! 1463: ! 1464: ! 1465: ! 1466: //This ISR is copied from cuda.c. The nice thing about Cuda is that at any ! 1467: // time we can determine state of hardware by examining 3 bits. ! 1468: - (void)interruptOccurred ! 1469: { ! 1470: ! 1471: unsigned char interruptState; ! 1472: ! 1473: *VIA2_dataB |= kCudaNegateTransferRequest; // deassert /REQ ! 1474: ! 1475: // Get the relevant signal in determining the cause of the interrupt: ! 1476: // the shift direction, the transfer request line and the transfer ! 1477: // request line. ! 1478: ! 1479: //interruptState = cuda_get_interrupt_state(); ! 1480: interruptState = (*VIA2_dataB & kCudaInterruptStateMask) | (*VIA1_auxillaryControl & kCudaDirectionMask) ; ! 1481: ! 1482: #ifdef DEBUG ! 1483: if ( cuda_glob_dbug_freeze == 1) ! 1484: { ! 1485: printf(" %d: ", interruptState); ! 1486: } ! 1487: #endif ! 1488: ! 1489: //no use DELAY(12); //12 microsecond delay in Ray Montagne's Cuda Manager for MacOS ! 1490: ! 1491: switch ( interruptState ) { ! 1492: ! 1493: case kCudaReceiveByte: ! 1494: if (p) kprintf("CUDA ** INTERRUPT ** RECEIVE *** \n"); ! 1495: [self cuda_receive_data]; ! 1496: break; ! 1497: ! 1498: case kCudaReceiveLastByte: ! 1499: if (p) kprintf("CUDA ** INTERRUPT ** RECEIVE LAST BYTE *** \n"); ! 1500: [self cuda_receive_last_byte]; ! 1501: break; ! 1502: ! 1503: case kCudaTransmitByte: ! 1504: if (p) kprintf("CUDA ** INTERRUPT ** TRANSMIT *** \n"); ! 1505: [self cuda_transmit_data]; ! 1506: break; ! 1507: ! 1508: case kCudaUnexpectedAttention: ! 1509: if (p) kprintf("CUDA ** INTERRUPT ** Unexpected Attention *** \n"); ! 1510: [self cuda_unexpected_attention]; ! 1511: break; ! 1512: ! 1513: case kCudaExpectedAttention: ! 1514: if (p) kprintf("CUDA ** INTERRUPT ** EXPECTED ATTENTION *** \n"); ! 1515: [self cuda_expected_attention]; ! 1516: break; ! 1517: ! 1518: case kCudaIdleState: ! 1519: if (p) kprintf("CUDA ** INTERRUPT ** IDLE *** \n"); ! 1520: [self cuda_idle]; ! 1521: break; ! 1522: ! 1523: case kCudaCollision: ! 1524: if (p) kprintf("Cuda *** INTERRUPT *** ADB collision\n"); ! 1525: [self cuda_collision]; ! 1526: break; ! 1527: ! 1528: // Unknown interrupt, clear it and leave ! 1529: default: ! 1530: if (p) kprintf("Cuda *** INTERRUPT *** ERROR\n"); ! 1531: [self cuda_error]; ! 1532: break; ! 1533: } ! 1534: } ! 1535: ! 1536: ! 1537: // **************************************************************************** ! 1538: // interruptOccurredAt ! 1539: // PGE has interrupted. Send the ReadInt command to find out why. ! 1540: // When the command byte is sent, the Shift Register will interrupt. ! 1541: // If we are mid-transaction when we find out about the interrupt, ! 1542: // set a flag and find out why later. ! 1543: // ! 1544: // A.W. Removed 2/11/98 because cuda only has 1 interrupt ! 1545: // ! 1546: // **************************************************************************** ! 1547: ! 1548: ! 1549: ! 1550: // **************************************************************************** ! 1551: // gotInterruptCause ! 1552: // ! 1553: // Called by the debug-mode PMU interrupt handler as the Callback function ! 1554: // after sending the kPMUreadInt command and receiving its response ! 1555: // A.W. only called by interruptOccurredAt above, so remove as well ! 1556: // **************************************************************************** ! 1557: ! 1558: ! 1559: // **************************************************************************** ! 1560: // EnableCudaInterrupt used to be EnablePMUInterrupt ! 1561: // **************************************************************************** ! 1562: - (void)EnableCudaInterrupt ! 1563: { ! 1564: ! 1565: // cuda_enable_interrupt(); // from cuda_hdw.h ! 1566: *VIA1_interruptEnable = kCudaInterruptEnable; ! 1567: eieio(); ! 1568: ! 1569: } ! 1570: ! 1571: ! 1572: #ifdef OMIT ! 1573: // **************************************************************************** ! 1574: // timer_expired ! 1575: // ! 1576: // Our adb-read timer has expired, so we have to notify our i/o thread by ! 1577: // enqueuing a Timeout message to its interrupt port. ! 1578: // This was only called by ADBinput() in pmu.m, but cuda doesn't have ADBinput() ! 1579: // so this method is useless for now. ! 1580: // **************************************************************************** ! 1581: void timer_expired(port_t mach_port) ! 1582: { ! 1583: PMUmachMessage request; ! 1584: ! 1585: request.msgHeader.msg_simple = TRUE; ! 1586: request.msgHeader.msg_type = MSG_TYPE_NORMAL; ! 1587: request.msgHeader.msg_id = IO_TIMEOUT_MSG; ! 1588: request.msgHeader.msg_remote_port = mach_port; ! 1589: request.msgHeader.msg_local_port = PORT_NULL; ! 1590: request.msgHeader.msg_size = sizeof(msg_header_t); ! 1591: msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0); ! 1592: ! 1593: } ! 1594: ! 1595: #endif ! 1596: ! 1597: ! 1598: ! 1599: // **************************************************************************** ! 1600: // cuda_timer_autopoll ! 1601: // ! 1602: // Automatic scheduling of command to make sure auto-polling is always available ! 1603: // In worst case, I may want to reset Cuda here. ! 1604: // **************************************************************************** ! 1605: void cuda_timer_autopoll(port_t mach_port) ! 1606: { ! 1607: CudaMachMessage request; ! 1608: extern int kdp_flag; ! 1609: static int old_kdp_flag; ! 1610: static int cuda_TREQ_history; ! 1611: VIAAddress temp_register, dataB; ! 1612: unsigned char interruptState; ! 1613: //unsigned int newTime; ! 1614: ! 1615: #ifdef DEBUG ! 1616: //[ApplePMUId ADBPollEnable :0:0: NULL]; //stress this one ! 1617: //newTime = 0; ! 1618: //[ApplePMUId getRealTimeClock :(UInt8 *)&newTime : 0: 0: NULL]; ! 1619: ! 1620: //*stat_aux_control &= kCudaSystemRecieve; eieio(); ! 1621: ns_timeout((func)cuda_timer_autopoll,(void *)glob_port, kNS_TIMEOUT_AUTOPOLL,CALLOUT_PRI_SOFTINT0); // start timer again for another 4 seconds ! 1622: //Can only be set through debugging tool ! 1623: switch (cuda_glob_dbug_freeze ) ! 1624: { ! 1625: case 0: ! 1626: old_kdp_flag = kdp_flag; ! 1627: break; ! 1628: case 1: ! 1629: kdp_flag |= 0x02; ! 1630: temp_register = stat_aux_control + 0x1600; //auxillary ! 1631: dataB = stat_aux_control ; ! 1632: interruptState = (*dataB & kCudaInterruptStateMask) | (*temp_register & kCudaDirectionMask) ; ! 1633: printf("CUDA: 4-second periodic, interruptState is %x\n", interruptState); ! 1634: kprintf("CUDA: 4-second periodic, interruptState is %x\n", interruptState); ! 1635: ! 1636: #ifdef OMIT_CUDA_DBUG ! 1637: //kprintf("istate = %x ", interruptState); ! 1638: //temp_register = stat_aux_control + 0x1A00; ! 1639: //kprintf("ir flag = %x ", *temp_register); ! 1640: //eieio(); ! 1641: temp_register = stat_aux_control + 0x1600; //auxillary ! 1642: kprintf("aux= %x ", *temp_register); ! 1643: eieio(); ! 1644: temp_register = stat_aux_control;//dataB ! 1645: kprintf("dataB= %x ", *temp_register); ! 1646: eieio(); ! 1647: temp_register = stat_aux_control + 0x1400; // SHIFT ! 1648: kprintf("shift= %x ", *temp_register); ! 1649: eieio(); ! 1650: temp_register = stat_aux_control + 0x1c00; // Interrupt Enable ! 1651: kprintf("IE= %x \n", *temp_register); ! 1652: eieio(); ! 1653: #endif ! 1654: ! 1655: //put printf here so it doesn't interfere with other debugging sessions ! 1656: break; ! 1657: case 2: ! 1658: //May disabling Cuda debugging kprintf, but preserve "4" for debugging ! 1659: kdp_flag = old_kdp_flag; ! 1660: break; ! 1661: case 3: ! 1662: cuda_glob_dbug_freeze = 1; ! 1663: cuda_interrupt_state = CUDA_STATE_IDLE; //Force state change ! 1664: [ApplePMUId EnableCudaInterrupt]; ! 1665: [ApplePMUId enableAllInterrupts]; ! 1666: [ApplePMUId ADBReset :0:0: NULL]; ! 1667: //mouse will be in low-res mode ! 1668: break; ! 1669: case 4: ! 1670: cuda_glob_dbug_freeze = 1; ! 1671: [ApplePMUId ADBPollEnable :0:0: NULL]; ! 1672: //No side effects seen for now, but gets queued when cuda freezes ! 1673: break; ! 1674: case 5: ! 1675: cuda_glob_dbug_freeze = 1; ! 1676: [ApplePMUId ADBFlush :2:0:0: NULL]; //keyboard is 2 ! 1677: //No side effects seen for now, but gets queued when cuda freezes ! 1678: break; ! 1679: case 6: ! 1680: cuda_glob_dbug_freeze = 1; ! 1681: //change data direction to input ! 1682: temp_register = stat_aux_control + 0x1600; ! 1683: *temp_register &= kCudaSystemRecieve; eieio(); ! 1684: break; ! 1685: case 7: ! 1686: cuda_glob_dbug_freeze = 1; ! 1687: temp_register = stat_aux_control + 0x1400; // SHIFT ! 1688: interruptState = *temp_register; eieio(); //dummy read ! 1689: //Simon suggests toggling the byteack too ! 1690: temp_register = stat_aux_control;//dataB ! 1691: *temp_register ^= kCudaByteAcknowledgeMask; eieio(); ! 1692: break; ! 1693: case 8: ! 1694: cuda_interrupt_state = CUDA_STATE_IDLE; //Force state change ! 1695: temp_register = stat_aux_control;//dataB ! 1696: *temp_register &= kCudaAssertTransferInProgress; ! 1697: *temp_register |= kCudaNegateByteAcknowledge ; ! 1698: eieio(); ! 1699: cuda_glob_dbug_freeze = 1; ! 1700: break; ! 1701: case 9: ! 1702: cuda_glob_dbug_freeze = 1; ! 1703: cuda_current_response->a_buffer[0] = 0; ! 1704: cuda_current_response->a_buffer[1] = 0xff; ! 1705: cuda_debug_client(0, 0, 2, 2, &cuda_current_response->a_buffer[0]); ! 1706: break; ! 1707: case 10: ! 1708: cuda_glob_dbug_freeze = 1; ! 1709: call_kdp(); ! 1710: break; ! 1711: case 11: ! 1712: cuda_glob_dbug_freeze = 1; ! 1713: cuda_interrupt_state = CUDA_STATE_IDLE; //Force state change ! 1714: [ApplePMUId EnableCudaInterrupt]; ! 1715: [ApplePMUId enableAllInterrupts]; ! 1716: [ApplePMUId ADBPollEnable :0 :0: NULL]; ! 1717: break; ! 1718: case 12: ! 1719: cuda_glob_dbug_freeze = 1; ! 1720: temp_register = stat_aux_control + 0x1400; // SHIFT ! 1721: interruptState = *temp_register; eieio(); //dummy read ! 1722: break; ! 1723: case 20: //Negate ByteAcknowledge ! 1724: temp_register = stat_aux_control;//dataB ! 1725: *temp_register |= kCudaNegateByteAcknowledge; eieio(); ! 1726: eieio(); ! 1727: cuda_glob_dbug_freeze = 1; ! 1728: break; ! 1729: case 21: ! 1730: //Set ByteAcknowledge ! 1731: temp_register = stat_aux_control;//dataB ! 1732: *temp_register &= kCudaAssertByteAcknowledge; eieio(); ! 1733: eieio(); ! 1734: cuda_glob_dbug_freeze = 1; ! 1735: break; ! 1736: case 22: ! 1737: //Set TIP ! 1738: temp_register = stat_aux_control; //dataB ! 1739: *temp_register &= kCudaTransferInProgressMask; ! 1740: eieio(); ! 1741: cuda_glob_dbug_freeze = 1; ! 1742: break; ! 1743: case 23: ! 1744: //Negate TIP ! 1745: temp_register = stat_aux_control; //dataB ! 1746: *temp_register |= kCudaNegateTransferInProgress; ! 1747: eieio(); ! 1748: cuda_glob_dbug_freeze = 1; ! 1749: break; ! 1750: case 24: ! 1751: //data direction to input ! 1752: temp_register = stat_aux_control + 0x1600; //auxillary ! 1753: *temp_register &= kCudaSystemRecieve; ! 1754: eieio(); ! 1755: cuda_glob_dbug_freeze = 1; ! 1756: break; ! 1757: case 25: ! 1758: //data direction to output ! 1759: temp_register = stat_aux_control + 0x1600; //auxillary ! 1760: *temp_register |= kCudaSystemSend; ! 1761: eieio(); ! 1762: cuda_glob_dbug_freeze = 1; ! 1763: break; ! 1764: case 30: //general reset ! 1765: { ! 1766: temp_register = stat_aux_control + 0x0400; //dataDirectionB ! 1767: *temp_register |= (kCudaByteAcknowledgeMask | kCudaTransferInProgressMask); ! 1768: *temp_register &= ~kCudaTransferRequestMask; ! 1769: ! 1770: temp_register = stat_aux_control + 0x1600; //auxillary ! 1771: *temp_register = ( *temp_register | kCudaTransferMode) & kCudaSystemRecieve; ! 1772: ! 1773: // Clear any posible cuda interupt. ! 1774: temp_register = stat_aux_control + 0x1400; //shift ! 1775: if ( *temp_register ); ! 1776: eieio(); ! 1777: ! 1778: // Initialize the internal data. ! 1779: ! 1780: cuda_interrupt_state = CUDA_STATE_IDLE; ! 1781: cuda_transaction_state = CUDA_TS_NO_REQUEST; ! 1782: cuda_is_header_transfer = FALSE; ! 1783: cuda_is_packet_type = FALSE; ! 1784: cuda_transfer_count = 0; ! 1785: cuda_current_response = NULL; ! 1786: ! 1787: // Terminate transaction and set idle state ! 1788: // cuda_neg_tip_and_byteack(); ! 1789: temp_register = stat_aux_control; //dataB ! 1790: *temp_register |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress; ! 1791: eieio(); ! 1792: ! 1793: // we want to delay 4 mS for ADB reset to complete ! 1794: ! 1795: delay(4000); ! 1796: ! 1797: // Clear pending interrupt if any... ! 1798: //(void)cuda_read_data(); ! 1799: temp_register = stat_aux_control + 0x1400; //Shift ! 1800: if ( *temp_register ); eieio(); ! 1801: ! 1802: // Issue a Sync Transaction, ByteAck asserted while TIP is negated. ! 1803: // cuda_assert_byte_ack(); ! 1804: temp_register = stat_aux_control; //dataB ! 1805: *temp_register &= kCudaAssertByteAcknowledge; eieio(); ! 1806: ! 1807: ! 1808: // Wait for the Sync acknowledgement, cuda to assert TREQ ! 1809: // cuda_wait_for_transfer_request_assert(); ! 1810: while ( (*temp_register & kCudaTransferRequestMask) != 0 ) ! 1811: { ! 1812: eieio(); ! 1813: } ! 1814: eieio(); ! 1815: ! 1816: // Wait for the Sync acknowledgement interrupt. ! 1817: // cuda_wait_for_interrupt(); ! 1818: temp_register = stat_aux_control + 0x1A00; //VIA interrupt flag ! 1819: while ( (*temp_register & kCudaInterruptMask) == 0 ) ! 1820: { ! 1821: eieio(); ! 1822: } ! 1823: eieio(); ! 1824: ! 1825: ! 1826: // Clear pending interrupt ! 1827: //(void)cuda_read_data(); ! 1828: temp_register = stat_aux_control + 0x1400; //shift ! 1829: if ( *temp_register ); ! 1830: eieio(); ! 1831: ! 1832: // Terminate the sync cycle by Negating ByteAck ! 1833: // cuda_neg_byte_ack(); ! 1834: temp_register = stat_aux_control; //dataB ! 1835: *temp_register |= kCudaNegateByteAcknowledge; eieio(); ! 1836: ! 1837: // Wait for the Sync termination acknowledgement, cuda negates TREQ. ! 1838: // cuda_wait_for_transfer_request_neg(); ! 1839: while ( (*temp_register & kCudaTransferRequestMask) == 0 ) ! 1840: { ! 1841: eieio(); ! 1842: } ! 1843: eieio(); ! 1844: ! 1845: ! 1846: // Wait for the Sync termination acknowledgement interrupt. ! 1847: // cuda_wait_for_interrupt(); ! 1848: temp_register = stat_aux_control + 0x1A00; //VIA interrupt flag ! 1849: while ( (*temp_register & kCudaInterruptMask) == 0 ) ! 1850: { ! 1851: eieio(); ! 1852: } ! 1853: eieio(); ! 1854: ! 1855: ! 1856: // Terminate transaction and set idle state, TIP negate and ByteAck negate. ! 1857: // cuda_neg_transfer_in_progress(); ! 1858: temp_register = stat_aux_control; //dataB ! 1859: *temp_register |= kCudaNegateTransferInProgress; eieio(); ! 1860: ! 1861: // Clear pending interrupt, if there is one... ! 1862: //(void)cuda_read_data(); ! 1863: temp_register = stat_aux_control + 0x1400; //shift ! 1864: if ( *temp_register ); ! 1865: eieio(); ! 1866: ! 1867: ! 1868: ! 1869: ! 1870: debugging = FALSE; ! 1871: adb_reading = FALSE; ! 1872: ! 1873: //CUDA_REPLACE ! 1874: // A.W. This call seems to have no counterpart in Cuda ! 1875: // Pending interrupts are cleared with cuda_read_data() ! 1876: temp_register = stat_aux_control + 0x1A00; //VIA interrupt flag ! 1877: *temp_register = kCudaInterruptDisable;eieio(); // turn off any pending interrupt ! 1878: ! 1879: temp_register = stat_aux_control + 0x1400; //shift ! 1880: if ( *temp_register ); ! 1881: eieio(); ! 1882: ! 1883: [ApplePMUId EnableCudaInterrupt]; ! 1884: ! 1885: [ApplePMUId enableAllInterrupts]; ! 1886: ! 1887: } ! 1888: break; ! 1889: ! 1890: case 40: ! 1891: //try AIX stuff ! 1892: temp_register = stat_aux_control; //dataB ! 1893: *temp_register |= kCudaNegateTransferInProgress | kCudaNegateByteAcknowledge; ! 1894: eieio(); ! 1895: [ApplePMUId EnableCudaInterrupt]; ! 1896: //[ApplePMUId enableAllInterrupts]; ! 1897: [ApplePMUId ADBPollEnable :0 :0: NULL]; ! 1898: cuda_glob_dbug_freeze = 1; ! 1899: break; ! 1900: ! 1901: default: ! 1902: } ! 1903: ! 1904: // Sept 11, 1998 Add new code to fix ADB hang problem ! 1905: if ( cuda_freeze_counter == cuda_freeze_prevcount) ! 1906: //Even if user never touches keyboard, this test is FALSE first time ! 1907: { ! 1908: //if here then that means either user has not moved ADB device for ! 1909: // a long time or the system is hung ! 1910: //kprintf("HH: No ADB movement so far\n"); ! 1911: //Now check TREQ (if in middle of transaction) ! 1912: temp_register = stat_aux_control; //dataB ! 1913: if ((*temp_register & kCudaTransferRequestMask) == 0 ) ! 1914: { ! 1915: //kprintf("HH: TREQ is 0 (asserted), incrementing flag now\n"); ! 1916: cuda_TREQ_history++; ! 1917: } ! 1918: else ! 1919: { ! 1920: cuda_TREQ_history = 0; ! 1921: } ! 1922: if ( cuda_TREQ_history == 2) // 2 cycles already ! 1923: { ! 1924: //Executing this code at any time has proven to be safe and does ! 1925: // not affect the operation of the high-resolution pointing devices ! 1926: //kprintf("HH: In recovery code now \n"); ! 1927: printf("\nCuda: recover from transaction hang\n"); ! 1928: temp_register = stat_aux_control; //dataB ! 1929: *temp_register |= kCudaNegateTransferInProgress | kCudaNegateByteAcknowledge; ! 1930: eieio(); ! 1931: [ApplePMUId EnableCudaInterrupt]; ! 1932: [ApplePMUId ADBPollEnable :0 :0: NULL]; ! 1933: cuda_TREQ_history = 0; ! 1934: } ! 1935: } ! 1936: else ! 1937: { ! 1938: cuda_TREQ_history = 0; ! 1939: } ! 1940: ! 1941: cuda_freeze_prevcount = cuda_freeze_counter ; //Get ready for next 4-sec timer ! 1942: #endif //DEBUG ! 1943: ! 1944: ! 1945: } ! 1946: ! 1947: ! 1948: // Cuda functions needed to help -interruptOccured: ! 1949: ! 1950: ! 1951: ! 1952: ! 1953: // ! 1954: // TransmitCudaData ! 1955: // Executes at hardware interrupt level. ! 1956: // ! 1957: ! 1958: -(void) cuda_transmit_data ! 1959: { ! 1960: volatile unsigned char valcuda; //dummy, unused ! 1961: // Clear the pending interrupt by reading the shift register. ! 1962: ! 1963: ! 1964: if ( cuda_is_header_transfer ) { ! 1965: // There are more header bytes, write one out. ! 1966: // Initially cuda_transfer_count is 1, so for most Cuda commands ! 1967: // that means the ADB command itself, which contains Talk, Listen, etc. ! 1968: // cuda_write_data(cuda_request->a_cmd.a_header[cuda_transfer_count++]); ! 1969: *VIA1_shift = cuda_request->a_cmd.a_header[cuda_transfer_count++]; ! 1970: ! 1971: // Toggle the handshake line. ! 1972: // a_hcount is number of bytes in command packet ! 1973: if ( cuda_transfer_count >= cuda_request->a_cmd.a_hcount ) { ! 1974: cuda_is_header_transfer = FALSE; ! 1975: cuda_transfer_count = 0; ! 1976: } ! 1977: ! 1978: // cuda_toggle_byte_ack(); ! 1979: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio(); ! 1980: ! 1981: ! 1982: } else if ( cuda_transfer_count < cuda_request->a_cmd.a_bcount ) { ! 1983: //WARNING... find out why a_bcount above is examined during Cuda Transmit? ! 1984: ! 1985: ! 1986: // There are more command bytes, write one out and update the pointer ! 1987: // cuda_write_data(cuda_request->a_cmd.a_buffer[cuda_transfer_count++]); ! 1988: *VIA1_shift = cuda_request->a_cmd.a_buffer[cuda_transfer_count++]; ! 1989: ! 1990: // Toggle the handshake line. ! 1991: // cuda_toggle_byte_ack(); ! 1992: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio(); ! 1993: } else { ! 1994: //(void)cuda_read_data(); ! 1995: valcuda = *VIA1_shift; eieio(); ! 1996: // There is no more command bytes, terminate the send transaction. ! 1997: // Cuda should send a expected attention interrupt soon. ! 1998: ! 1999: // cuda_neg_tip_and_byteack(); ! 2000: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress; ! 2001: eieio(); ! 2002: ! 2003: // The next interrupt should be a expected attention interrupt. ! 2004: ! 2005: cuda_interrupt_state = CUDA_STATE_ATTN_EXPECTED; ! 2006: ! 2007: /**** moved to cuda_idle() portion ! 2008: // call back the ADB layer if entire transmission packet is complete. ! 2009: if ( clientRequest->pmCallback != NULL ) { ! 2010: clientRequest->pmCallback(clientRequest->pmId, clientRequest->pmRefNum, 0, NULL); ! 2011: ! 2012: } ! 2013: *****/ ! 2014: ! 2015: } ! 2016: } ! 2017: ! 2018: // ! 2019: // cuda_expected_attention ! 2020: // Executes at hardware interrupt level. ! 2021: // ! 2022: ! 2023: - (void)cuda_expected_attention ! 2024: { ! 2025: volatile unsigned char valcuda; //dummy, unused ! 2026: ! 2027: ! 2028: // Clear the pending interrupt by reading the shift register. ! 2029: // This first byte is the "attention" byte and contains no ! 2030: // useful data, so ignore it. Next byte should be response ! 2031: // packet TYPE. ! 2032: //(void)cuda_read_data(); ! 2033: valcuda = *VIA1_shift; eieio(); ! 2034: ! 2035: // Allow the VIA to settle directions.. else the possibility of ! 2036: // data corruption. ! 2037: tick_delay(cuda_state_transition_delay_ticks); ! 2038: ! 2039: if ( cuda_transaction_state == CUDA_TS_SYNC_RESPONSE) { ! 2040: cuda_current_response = (adb_packet_t*)&cuda_request->a_reply; ! 2041: } else { ! 2042: cuda_unsolicited.a_hcount = 0; ! 2043: cuda_unsolicited.a_bcount = 0; ! 2044: cuda_unsolicited.a_bsize = sizeof(cuda_unsolicited.a_buffer); ! 2045: cuda_current_response = &cuda_unsolicited; ! 2046: } ! 2047: ! 2048: cuda_is_header_transfer = TRUE; ! 2049: cuda_is_packet_type = TRUE; ! 2050: cuda_transfer_count = 0; ! 2051: ! 2052: // Set the shift register direction to input. ! 2053: // cuda_set_data_direction_to_input(); ! 2054: *VIA1_auxillaryControl &= kCudaSystemRecieve; eieio(); ! 2055: ! 2056: // Start the response packet transaction. ! 2057: // cuda_assert_transfer_in_progress(); ! 2058: *VIA2_dataB &= kCudaAssertTransferInProgress; eieio(); ! 2059: ! 2060: // The next interrupt should be a receive data interrupt. ! 2061: cuda_interrupt_state = CUDA_STATE_RECEIVE_EXPECTED; ! 2062: } ! 2063: ! 2064: // ! 2065: // cuda_unexpected_attention ! 2066: // Executes at hardware interrupt level. ! 2067: // ! 2068: ! 2069: -(void) cuda_unexpected_attention ! 2070: { ! 2071: volatile unsigned char valcuda; //dummy, unused ! 2072: ! 2073: // Clear the pending interrupt by reading the shift register. ! 2074: // This first byte is the "attention" byte and contains no ! 2075: // useful data, so ignore it. Next byte should be response ! 2076: // packet TYPE. ! 2077: //(void)cuda_read_data(); ! 2078: valcuda = *VIA1_shift; eieio(); ! 2079: ! 2080: // Get ready for a unsolicited response. ! 2081: ! 2082: cuda_unsolicited.a_hcount = 0; ! 2083: cuda_unsolicited.a_bcount = 0; ! 2084: cuda_unsolicited.a_bsize = sizeof(cuda_unsolicited.a_buffer); ! 2085: //Try to fix jumping bug ! 2086: bzero( cuda_unsolicited.a_buffer, cuda_unsolicited.a_bsize); ! 2087: ! 2088: ! 2089: cuda_current_response = &cuda_unsolicited; ! 2090: ! 2091: cuda_is_header_transfer = TRUE; ! 2092: cuda_is_packet_type = TRUE; ! 2093: cuda_transfer_count = 0; ! 2094: ! 2095: ! 2096: // Start the response packet transaction, Transaction In Progress ! 2097: // cuda_assert_transfer_in_progress(); ! 2098: *VIA2_dataB &= kCudaAssertTransferInProgress; eieio(); ! 2099: ! 2100: // The next interrupt should be a receive data interrupt and the next ! 2101: // response should be an async response. ! 2102: ! 2103: cuda_interrupt_state = CUDA_STATE_RECEIVE_EXPECTED; ! 2104: ! 2105: cuda_transaction_state = CUDA_TS_ASYNC_RESPONSE; ! 2106: } ! 2107: ! 2108: // ! 2109: // cuda_receive_data ! 2110: // Executes at hardware interrupt level. ! 2111: // ! 2112: ! 2113: -(void) cuda_receive_data ! 2114: { ! 2115: ! 2116: // cuda_is_packet_type is set to TRUE when cuda_(+un)expected_attention() is called ! 2117: // The first part will be called just to read the packet type ! 2118: if ( cuda_is_packet_type ) { ! 2119: unsigned char packetType; ! 2120: ! 2121: //packetType = cuda_read_data(); ! 2122: packetType = *VIA1_shift; eieio(); ! 2123: cuda_current_response->a_header[cuda_transfer_count++] = packetType; ! 2124: ! 2125: if ( packetType == ADB_PACKET_ERROR) { ! 2126: cuda_current_response->a_hcount = 4; ! 2127: } else { ! 2128: cuda_current_response->a_hcount = 3; ! 2129: } ! 2130: ! 2131: cuda_is_packet_type = FALSE; ! 2132: ! 2133: // cuda_toggle_byte_ack(); ! 2134: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio(); ! 2135: ! 2136: } else if ( cuda_is_header_transfer ) { //set TRUE by cuda_(+un)expected_attention ! 2137: ! 2138: //This should be the Response Packet ADB Status byte (2nd byte) ! 2139: cuda_current_response->a_header[cuda_transfer_count++] = ! 2140: *VIA1_shift; eieio(); ! 2141: // cuda_read_data(); ! 2142: ! 2143: if (cuda_transfer_count >= cuda_current_response->a_hcount) { ! 2144: cuda_is_header_transfer = FALSE; ! 2145: cuda_transfer_count = 0; ! 2146: } ! 2147: ! 2148: // cuda_toggle_byte_ack(); ! 2149: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio(); ! 2150: ! 2151: } else if ( cuda_transfer_count < cuda_current_response->a_bsize ) { ! 2152: // Still room for more bytes. Get the byte and tell Cuda to continue. ! 2153: // Toggle the handshake line, ByteAck, to acknowledge receive. ! 2154: ! 2155: // a_buffer[] is the actual buffer going back to ADB.M Callback ! 2156: cuda_current_response->a_buffer[cuda_transfer_count] = ! 2157: *VIA1_shift; eieio(); ! 2158: // cuda_read_data(); ! 2159: ! 2160: if (bImmediate_buff_needed) //just for getRealTimeClock ! 2161: { ! 2162: if ( return_buff_pointer) ! 2163: { ! 2164: *(return_buff_pointer + cuda_transfer_count) = ! 2165: cuda_current_response->a_buffer[cuda_transfer_count]; ! 2166: ! 2167: //kprintf("%x ", cuda_current_response->a_buffer[cuda_transfer_count]); ! 2168: } ! 2169: } ! 2170: ! 2171: cuda_transfer_count++; ! 2172: ! 2173: // cuda_toggle_byte_ack(); ! 2174: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio(); ! 2175: } else { ! 2176: // Cuda is still sending data but the buffer is full. ! 2177: // Normally should not get here. The only exceptions are open ended ! 2178: // request such as PRAM read... In any event time to exit. ! 2179: ! 2180: // a_bcount is the actual count going back to ADB.M Callback ! 2181: cuda_current_response->a_bcount = cuda_transfer_count; ! 2182: ! 2183: // cuda_read_data(); ! 2184: if (*VIA1_shift); eieio(); ! 2185: ! 2186: //So far no hits here on kernel bootup 3/20/98 ! 2187: ! 2188: [self cuda_process_response]; //Rewritten by D.S. ! 2189: // cuda_neg_tip_and_byteack(); ! 2190: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress; ! 2191: eieio(); ! 2192: } ! 2193: } ! 2194: ! 2195: // ! 2196: // cuda_receive_last_byte ! 2197: // Executes at hardware interrupt level. ! 2198: // ! 2199: ! 2200: -(void) cuda_receive_last_byte ! 2201: { ! 2202: volatile unsigned char valcuda; //dummy, unused ! 2203: ! 2204: ! 2205: if ( cuda_is_header_transfer ) { ! 2206: cuda_current_response->a_header[cuda_transfer_count++] = ! 2207: *VIA1_shift; eieio(); ! 2208: // cuda_read_data(); ! 2209: ! 2210: cuda_transfer_count = 0; ! 2211: } else if ( cuda_transfer_count < cuda_current_response->a_bsize ) { ! 2212: ! 2213: cuda_current_response->a_buffer[cuda_transfer_count] = ! 2214: *VIA1_shift; eieio(); ! 2215: ! 2216: //Added 1/13/98 A.W. ! 2217: if (bImmediate_buff_needed) //just for getRealTimeClock ! 2218: { ! 2219: if ( return_buff_pointer) ! 2220: { ! 2221: *(return_buff_pointer + cuda_transfer_count) = ! 2222: cuda_current_response->a_buffer[cuda_transfer_count]; ! 2223: } ! 2224: } ! 2225: cuda_transfer_count++; ! 2226: ! 2227: // cuda_read_data(); ! 2228: } else { ! 2229: /* Overrun -- ignore data */ ! 2230: //(void) cuda_read_data(); ! 2231: valcuda = *VIA1_shift; eieio(); ! 2232: } ! 2233: ! 2234: cuda_current_response->a_bcount = cuda_transfer_count; ! 2235: ! 2236: //SD: acknowledge before response so polled mode can work from inside the adb handler ! 2237: ! 2238: // cuda_neg_tip_and_byteack(); ! 2239: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress; ! 2240: eieio(); ! 2241: if (p) kprintf("cuda.m: process response in LAST BYTE, count is %d\n", cuda_transfer_count); ! 2242: [self cuda_process_response]; //Rewritten by D.S. ! 2243: } ! 2244: ! 2245: /* 3/19/98 A.W. added to fix collision problems */ ! 2246: - (void) cuda_queue:(CudaRequest *)cuda_req ! 2247: { ! 2248: CudaMachMessage * toQueue; ! 2249: IOReturn result; ! 2250: ! 2251: que_cuda_count++; //for debugging only ! 2252: //For collisions, queue up the incoming request from Rhapsody system ! 2253: // and handle Cuda's urgent request first. ! 2254: toQueue = (CudaMachMessage*)kalloc(sizeof(CudaMachMessage)); ! 2255: toQueue->msgHeader.msg_size = sizeof(CudaMachMessage); ! 2256: toQueue->msgHeader.msg_local_port = [self interruptPort]; ! 2257: bcopy (cuda_req, &toQueue->msgBody, sizeof(CudaRequest)); // copy it ! 2258: toQueue->msgBody.prev = queueTail; ! 2259: toQueue->msgBody.next = NULL; ! 2260: if ( queueTail != NULL ) { ! 2261: queueTail->msgBody.next = toQueue; ! 2262: } ! 2263: else ! 2264: { ! 2265: queueHead = toQueue; ! 2266: } ! 2267: queueTail = toQueue; ! 2268: } ! 2269: ! 2270: // ! 2271: // cuda_collision ! 2272: // Executes at hardware interrupt level. ! 2273: // ! 2274: ! 2275: -(void) cuda_collision ! 2276: { ! 2277: volatile unsigned char valcuda; //dummy, unused ! 2278: ! 2279: ! 2280: // Clear the pending interrupt by reading the shift register. ! 2281: //(void)cuda_read_data(); ! 2282: valcuda = *VIA1_shift; eieio(); ! 2283: ! 2284: // Negate TIP to abort the send. Cuda should send a second attention ! 2285: // interrupt to acknowledge the abort cycle. ! 2286: // cuda_neg_transfer_in_progress(); ! 2287: *VIA2_dataB |= kCudaNegateTransferInProgress; eieio(); ! 2288: ! 2289: // The next interrupt should be an expected attention and the next ! 2290: // response packet should be an async response. ! 2291: ! 2292: cuda_interrupt_state = CUDA_STATE_ATTN_EXPECTED; ! 2293: cuda_transaction_state = CUDA_TS_ASYNC_RESPONSE; ! 2294: ! 2295: /* queue the request */ ! 2296: cuda_collided = cuda_request; //WARNING... unused now, don't use this variable ! 2297: #ifdef OMIT ! 2298: cuda_request = NULL; ! 2299: #endif ! 2300: cuda_is_header_transfer = FALSE; ! 2301: cuda_transfer_count = 0; ! 2302: ! 2303: [self cuda_queue: cuda_request]; ! 2304: } ! 2305: ! 2306: // ! 2307: // cuda_idle ! 2308: // Executes at hardware interrupt level. ! 2309: // A.W. WARNING... what if this state is reached without a client callback available? ! 2310: // what happens with unsolicited cuda events? Should they go to the ADBRegisterAutopoll ! 2311: // function? ! 2312: // ! 2313: ! 2314: -(void) cuda_idle ! 2315: { ! 2316: volatile unsigned char valcuda; //dummy, unused ! 2317: ! 2318: // Clear the pending interrupt by reading the shift register. ! 2319: //(void)cuda_read_data(); ! 2320: valcuda = *VIA1_shift; eieio(); ! 2321: ! 2322: // Set to the idle state. ! 2323: cuda_interrupt_state = CUDA_STATE_IDLE; ! 2324: ! 2325: // See if there are any pending requests. There may be a pending request ! 2326: // if a collision has occured. If so do the resend. ! 2327: ! 2328: //if (adb_polling) ! 2329: //return; /* Prevent recursion */ ! 2330: ! 2331: //if collision then that has already been queued above, so all we do ! 2332: // now is check for it. ! 2333: ! 2334: [self CheckRequestQueue]; ! 2335: ! 2336: } ! 2337: ! 2338: ! 2339: ! 2340: -(void) cuda_error ! 2341: { ! 2342: unsigned char valcuda; ! 2343: ! 2344: kprintf("\nCUDA:{Error %d}\n", cuda_transaction_state); ! 2345: ! 2346: switch (cuda_transaction_state) { ! 2347: case CUDA_STATE_IDLE: ! 2348: // cuda_neg_tip_and_byteack(); ! 2349: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress; ! 2350: eieio(); ! 2351: break; ! 2352: ! 2353: case CUDA_STATE_TRANSMIT_EXPECTED: ! 2354: if (cuda_is_header_transfer && cuda_transfer_count <= 1) { ! 2355: tick_delay(cuda_state_transition_delay_ticks); ! 2356: // cuda_neg_transfer_in_progress(); ! 2357: *VIA2_dataB |= kCudaNegateTransferInProgress; eieio(); ! 2358: // cuda_set_data_direction_to_input(); ! 2359: *VIA1_auxillaryControl &= kCudaSystemRecieve; eieio(); ! 2360: //panic ("CUDA - TODO FORCE COMMAND BACK UP!\n"); ! 2361: } else { ! 2362: cuda_transaction_state = CUDA_STATE_ATTN_EXPECTED; ! 2363: // cuda_neg_tip_and_byteack(); ! 2364: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress; ! 2365: eieio(); ! 2366: } ! 2367: break; ! 2368: ! 2369: case CUDA_STATE_ATTN_EXPECTED: ! 2370: // cuda_assert_transfer_in_progress(); ! 2371: *VIA2_dataB &= kCudaAssertTransferInProgress; eieio(); ! 2372: ! 2373: tick_delay(cuda_state_transition_delay_ticks); ! 2374: // cuda_set_data_direction_to_input(); ! 2375: *VIA1_auxillaryControl &= kCudaSystemRecieve; eieio(); ! 2376: // cuda_neg_transfer_in_progress(); ! 2377: *VIA2_dataB |= kCudaNegateTransferInProgress; eieio(); ! 2378: //panic("CUDA - TODO CHECK FOR TRANSACTION TYPE AND ERROR"); ! 2379: break; ! 2380: ! 2381: case CUDA_STATE_RECEIVE_EXPECTED: ! 2382: // cuda_neg_tip_and_byteack(); ! 2383: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress; ! 2384: eieio(); ! 2385: //panic("Cuda - todo check for transaction type and error"); ! 2386: break; ! 2387: ! 2388: default: ! 2389: // cuda_set_data_direction_to_input(); ! 2390: *VIA1_auxillaryControl &= kCudaSystemRecieve; eieio(); ! 2391: valcuda = *VIA1_shift; eieio(); //Ray Montagne .a indicates this may be useful ! 2392: // cuda_neg_tip_and_byteack(); ! 2393: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress; ! 2394: eieio(); ! 2395: break; ! 2396: } ! 2397: } ! 2398: ! 2399: -(void) poll_device ! 2400: { ! 2401: CudaRequest *next; ! 2402: int interruptflag = *VIA1_interruptFlag & kCudaInterruptMask; ! 2403: eieio(); ! 2404: ! 2405: if(interruptflag) { ! 2406: [self interruptOccurred]; ! 2407: if( cuda_interrupt_state == CUDA_STATE_IDLE) { ! 2408: [self CheckRequestQueue]; ! 2409: } ! 2410: } ! 2411: } ! 2412: ! 2413: ! 2414: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.