Annotation of kernel/bsd/dev/ppc/drvCuda/cuda.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: 
        !            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

unix.superglobalmegacorp.com

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