Annotation of XNU/iokit/Drivers/platform/drvAppleCuda/AppleCuda.cpp, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright 1996 1995 by Open Software Foundation, Inc. 1997 1996 1995 1994 1993 1992 1991  
        !            24:  *              All Rights Reserved 
        !            25:  *  
        !            26:  * Permission to use, copy, modify, and distribute this software and 
        !            27:  * its documentation for any purpose and without fee is hereby granted, 
        !            28:  * provided that the above copyright notice appears in all copies and 
        !            29:  * that both the copyright notice and this permission notice appear in 
        !            30:  * supporting documentation. 
        !            31:  *  
        !            32:  * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 
        !            33:  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
        !            34:  * FOR A PARTICULAR PURPOSE. 
        !            35:  *  
        !            36:  * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 
        !            37:  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
        !            38:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 
        !            39:  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
        !            40:  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
        !            41:  * 
        !            42:  */
        !            43: /*
        !            44:  * Copyright 1996 1995 by Apple Computer, Inc. 1997 1996 1995 1994 1993 1992 1991  
        !            45:  *              All Rights Reserved 
        !            46:  *  
        !            47:  * Permission to use, copy, modify, and distribute this software and 
        !            48:  * its documentation for any purpose and without fee is hereby granted, 
        !            49:  * provided that the above copyright notice appears in all copies and 
        !            50:  * that both the copyright notice and this permission notice appear in 
        !            51:  * supporting documentation. 
        !            52:  *  
        !            53:  * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 
        !            54:  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
        !            55:  * FOR A PARTICULAR PURPOSE. 
        !            56:  *  
        !            57:  * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 
        !            58:  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 
        !            59:  * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 
        !            60:  * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 
        !            61:  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
        !            62:  */
        !            63: /*
        !            64:  * MKLINUX-1.0DR2
        !            65:  */
        !            66: 
        !            67: /* 1 April 1997 Simon Douglas:
        !            68:  * Stolen wholesale from MkLinux.
        !            69:  * Added nonblocking adb poll from interrupt level for the debugger.
        !            70:  * Acknowledge before response so polled mode can work from inside the adb handler.
        !            71:  *
        !            72:  * 18 June 1998 sdouglas
        !            73:  * Start IOKit version. Fix errors from kCudaSRQAssertMask. Use ool cmd & reply buffers,
        !            74:  * not fixed len in packet. Does queueing here.
        !            75:  *
        !            76:  * 20 Nov 1998 suurballe
        !            77:  * Port to C++
        !            78:  */
        !            79: 
        !            80: 
        !            81: #include "AppleCuda.h"
        !            82: #include "IOCudaADBController.h"
        !            83: #include <IOKit/IOLib.h>
        !            84: #include <IOKit/IOSyncer.h>
        !            85: #include <IOKit/IOWorkLoop.h>
        !            86: #include <IOKit/IOInterruptEventSource.h>
        !            87: #include <IOKit/IODeviceMemory.h>
        !            88: #include <IOKit/IOPlatformExpert.h>
        !            89: 
        !            90: #include <IOKit/assert.h>
        !            91: 
        !            92: #define super IOService
        !            93: OSDefineMetaClassAndStructors(AppleCuda,IOService)
        !            94: 
        !            95: static  void   cuda_interrupt ( AppleCuda * self );
        !            96: 
        !            97: static  void    cuda_process_response(AppleCuda * self);
        !            98: static  void    cuda_transmit_data(AppleCuda * self);
        !            99: static  void    cuda_expected_attention(AppleCuda * self);
        !           100: static  void    cuda_unexpected_attention(AppleCuda * self);
        !           101: static  void    cuda_receive_data(AppleCuda * self);
        !           102: static  void    cuda_receive_last_byte(AppleCuda * self);
        !           103: static  void    cuda_collision(AppleCuda * self);
        !           104: static  void    cuda_idle(AppleCuda * self);
        !           105: 
        !           106: static  void    cuda_poll(AppleCuda * self);
        !           107: static  void    cuda_error(AppleCuda * self);
        !           108: static  void    cuda_send_request(AppleCuda * self);
        !           109: static IOReturn cuda_do_sync_request( AppleCuda * self,
        !           110:                cuda_request_t * request, bool polled);
        !           111: static void    cuda_do_state_transition_delay(AppleCuda * self);
        !           112: 
        !           113: static int Cuda_PE_poll_input(unsigned int options, char * c);
        !           114: static int Cuda_PE_read_write_time_of_day(unsigned int options, long * secs);
        !           115: static int Cuda_PE_halt_restart(unsigned int type);
        !           116: static int Cuda_PE_write_IIC(unsigned char addr, unsigned char reg,
        !           117:                                unsigned char data);
        !           118: 
        !           119: static void
        !           120: autopollArrived ( OSObject *inCuda, IOInterruptEventSource *, int );
        !           121: 
        !           122: 
        !           123: //
        !           124: // inline functions
        !           125: //
        !           126: 
        !           127: static __inline__ unsigned char cuda_read_data(AppleCuda * self)
        !           128: {
        !           129:     volatile unsigned char val;
        !           130: 
        !           131:     val = *self->cuda_via_regs.shift; eieio();
        !           132:     return val;
        !           133: }
        !           134: 
        !           135: static __inline__ int cuda_get_result(cuda_request_t *request)
        !           136: {
        !           137:     int status = ADB_RET_OK;
        !           138:     int theStatus = request->a_reply.a_header[1];
        !           139:     
        !           140:     if ( theStatus & kCudaTimeOutMask ) {
        !           141:         status = ADB_RET_TIMEOUT;
        !           142: #if 0
        !           143:     // these are expected before autopoll mask is set
        !           144:     } else if ( theStatus & kCudaSRQAssertMask ) {
        !           145:         status = ADB_RET_UNEXPECTED_RESULT;
        !           146: #endif
        !           147:     } else if ( theStatus & kCudaSRQErrorMask ) {
        !           148:         status = ADB_RET_REQUEST_ERROR;
        !           149:     } else if ( theStatus & kCudaBusErrorMask ) {
        !           150:         status = ADB_RET_BUS_ERROR;
        !           151:     }
        !           152: 
        !           153:     return status;
        !           154: }
        !           155: 
        !           156: static __inline__ void cuda_lock(AppleCuda * self)
        !           157: {
        !           158:     if( !self->cuda_polled_mode)
        !           159:         IOSimpleLockLock(self->cuda_request_lock);
        !           160: }
        !           161: 
        !           162: static __inline__ void cuda_unlock(AppleCuda * self)
        !           163: {
        !           164:     if( !self->cuda_polled_mode)
        !           165:         IOSimpleLockUnlock(self->cuda_request_lock);
        !           166: }
        !           167: 
        !           168: //
        !           169: // 
        !           170: //
        !           171: 
        !           172: 
        !           173: static AppleCuda * gCuda;
        !           174: // **********************************************************************************
        !           175: // init
        !           176: //
        !           177: // **********************************************************************************
        !           178: bool AppleCuda::init ( OSDictionary * properties = 0 )
        !           179: {
        !           180: return super::init(properties);
        !           181: }
        !           182: 
        !           183: 
        !           184: // **********************************************************************************
        !           185: // start
        !           186: //
        !           187: // **********************************************************************************
        !           188: bool AppleCuda::start ( IOService * nub )
        !           189: {
        !           190: int i;
        !           191: IOMemoryMap * viaMap;
        !           192: unsigned char * cuda_base;
        !           193: 
        !           194: if( !super::start(nub))
        !           195:     return false;
        !           196: 
        !           197: gCuda = this;
        !           198: 
        !           199: workLoop = NULL;
        !           200: eventSrc = NULL;
        !           201: ourADBinterface = NULL;
        !           202: 
        !           203: workLoop = IOWorkLoop::workLoop();
        !           204: if ( !workLoop ) {
        !           205:         kprintf("Start is bailing\n");
        !           206:        return false;
        !           207: }
        !           208: 
        !           209: eventSrc = IOInterruptEventSource::interruptEventSource(this, autopollArrived);
        !           210: if (!eventSrc || 
        !           211:        kIOReturnSuccess != workLoop->addEventSource(eventSrc) ) {
        !           212:         kprintf("Start is bailing\n");
        !           213:        return false;
        !           214: }
        !           215: 
        !           216: if( 0 == (viaMap = nub->mapDeviceMemoryWithIndex( 0 )) ) {
        !           217:        IOLog("%s: no via memory\n", getName());
        !           218:         kprintf("Start is bailing\n");
        !           219:        return false;
        !           220: }
        !           221: cuda_base = (unsigned char *)viaMap->getVirtualAddress();
        !           222: 
        !           223: kprintf("VIA base = %08x\n", (UInt32)cuda_base);
        !           224: ourADBinterface = new IOCudaADBController;
        !           225: if ( !ourADBinterface ) {
        !           226:         kprintf("Start is bailing\n");
        !           227:        return false;
        !           228: }
        !           229: if ( !ourADBinterface->init(0,this) ) {
        !           230:         kprintf("Start is bailing\n");
        !           231:         return false;
        !           232: }
        !           233: 
        !           234: if ( !ourADBinterface->attach( this) ) {
        !           235:         kprintf("Start is bailing\n");
        !           236:         return false;
        !           237: }
        !           238: 
        !           239: cuda_request_lock = IOSimpleLockAlloc();
        !           240: IOSimpleLockInit(cuda_request_lock);
        !           241: 
        !           242: cuda_via_regs.dataB                = cuda_base;
        !           243: cuda_via_regs.handshakeDataA        = cuda_base+0x0200;
        !           244: cuda_via_regs.dataDirectionB        = cuda_base+0x0400;
        !           245: cuda_via_regs.dataDirectionA        = cuda_base+0x0600;
        !           246: cuda_via_regs.timer1CounterLow      = cuda_base+0x0800;
        !           247: cuda_via_regs.timer1CounterHigh     = cuda_base+0x0A00;
        !           248: cuda_via_regs.timer1LatchLow        = cuda_base+0x0C00;
        !           249: cuda_via_regs.timer1LatchHigh       = cuda_base+0x0E00;
        !           250: cuda_via_regs.timer2CounterLow      = cuda_base+0x1000;
        !           251: cuda_via_regs.timer2CounterHigh     = cuda_base+0x1200;
        !           252: cuda_via_regs.shift                = cuda_base+0x1400;
        !           253: cuda_via_regs.auxillaryControl      = cuda_base+0x1600;
        !           254: cuda_via_regs.peripheralControl     = cuda_base+0x1800;
        !           255: cuda_via_regs.interruptFlag                = cuda_base+0x1A00;
        !           256: cuda_via_regs.interruptEnable       = cuda_base+0x1C00;
        !           257: cuda_via_regs.dataA                = cuda_base+0x1E00;
        !           258: 
        !           259: // we require delays of this duration between certain state transitions
        !           260: clock_interval_to_absolutetime_interval(200, 1, &cuda_state_transition_delay);
        !           261: 
        !           262: // Set the direction of the cuda signals.  ByteACk and TIP are output and
        !           263: // TREQ is an input
        !           264: 
        !           265: *cuda_via_regs.dataDirectionB |= (kCudaByteAcknowledgeMask | kCudaTransferInProgressMask);
        !           266: *cuda_via_regs.dataDirectionB &= ~kCudaTransferRequestMask;
        !           267: 
        !           268: // Set the clock control.  Set to shift data in by external clock CB1.
        !           269: 
        !           270: *cuda_via_regs.auxillaryControl = (*cuda_via_regs.auxillaryControl | kCudaTransferMode) &
        !           271:                                                                kCudaSystemRecieve;
        !           272: 
        !           273: // Clear any posible cuda interupt.
        !           274: 
        !           275: if ( *cuda_via_regs.shift );
        !           276: 
        !           277: // Initialize the internal data.
        !           278: 
        !           279: cuda_interrupt_state    = CUDA_STATE_IDLE;
        !           280: cuda_transaction_state  = CUDA_TS_NO_REQUEST;
        !           281: cuda_is_header_transfer = false;
        !           282: cuda_is_packet_type    = false;
        !           283: cuda_transfer_count    = 0;
        !           284: cuda_current_response   = NULL;
        !           285: for( i = 0; i < NUM_AP_BUFFERS; i++ ) {
        !           286:        cuda_unsolicited[ i ].a_buffer = cuda_autopoll_buffers[ i ];
        !           287: }
        !           288: 
        !           289: // Terminate transaction and set idle state
        !           290: 
        !           291: cuda_neg_tip_and_byteack(this);
        !           292: 
        !           293: // we want to delay 4 mS for ADB reset to complete
        !           294: 
        !           295: IOSleep( 4 );
        !           296: 
        !           297: // Clear pending interrupt if any...
        !           298: 
        !           299: (void)cuda_read_data(this);
        !           300: 
        !           301: // Issue a Sync Transaction, ByteAck asserted while TIP is negated.
        !           302: 
        !           303: cuda_assert_byte_ack(this);
        !           304: 
        !           305: // Wait for the Sync acknowledgement, cuda to assert TREQ
        !           306: 
        !           307: cuda_wait_for_transfer_request_assert(this);
        !           308: 
        !           309: // Wait for the Sync acknowledgement interrupt.
        !           310: 
        !           311: cuda_wait_for_interrupt(this);
        !           312: 
        !           313: // Clear pending interrupt
        !           314: 
        !           315: (void)cuda_read_data(this);
        !           316: 
        !           317: // Terminate the sync cycle by Negating ByteAck
        !           318: 
        !           319: cuda_neg_byte_ack(this);
        !           320: 
        !           321: // Wait for the Sync termination acknowledgement, cuda negates TREQ.
        !           322: 
        !           323: cuda_wait_for_transfer_request_neg(this);
        !           324: 
        !           325: // Wait for the Sync termination acknowledgement interrupt.
        !           326: 
        !           327: cuda_wait_for_interrupt(this);
        !           328: 
        !           329: // Terminate transaction and set idle state, TIP negate and ByteAck negate.
        !           330: cuda_neg_transfer_in_progress(this);
        !           331: 
        !           332: // Clear pending interrupt, if there is one...
        !           333: (void)cuda_read_data(this);
        !           334: 
        !           335: #if 0
        !           336:         cuda_polled_mode = true;
        !           337: #else
        !           338: #define        VIA_DEV_CUDA            2
        !           339: nub->registerInterrupt(VIA_DEV_CUDA,
        !           340:                        this, (IOInterruptAction) cuda_interrupt);
        !           341: nub->enableInterrupt(VIA_DEV_CUDA);
        !           342: #endif
        !           343: 
        !           344: PE_poll_input = Cuda_PE_poll_input;
        !           345: PE_read_write_time_of_day = Cuda_PE_read_write_time_of_day;
        !           346: PE_halt_restart = Cuda_PE_halt_restart;
        !           347: PE_write_IIC = Cuda_PE_write_IIC;
        !           348: publishResource( "IOiic0", this );
        !           349: publishResource( "IORTC", this );
        !           350: 
        !           351: ourADBinterface->start( this );
        !           352: 
        !           353: return true;
        !           354: }
        !           355: 
        !           356: 
        !           357: // *****************************************************************************
        !           358: // getWorkLoop
        !           359: //
        !           360: // Return the cuda's workloop.
        !           361: //
        !           362: // *****************************************************************************
        !           363: IOWorkLoop *AppleCuda::getWorkLoop() const
        !           364: {
        !           365:     return workLoop;
        !           366: }
        !           367: 
        !           368: // *****************************************************************************
        !           369: // free
        !           370: //
        !           371: // Release everything we may have allocated.
        !           372: //
        !           373: // *****************************************************************************
        !           374: void AppleCuda::free ( void )
        !           375: {
        !           376: if ( workLoop ) {
        !           377:        workLoop->release();
        !           378: }
        !           379: if ( eventSrc ) {
        !           380:        eventSrc->release();
        !           381: }
        !           382: if ( ourADBinterface ) {
        !           383:        ourADBinterface->release();
        !           384: }
        !           385: super::free();
        !           386: }
        !           387: 
        !           388: 
        !           389: // **********************************************************************************
        !           390: // registerForADBInterrupts
        !           391: //
        !           392: // Some driver is calling to say it is prepared to receive "unsolicited" adb
        !           393: // interrupts (e.g. autopoll keyboard and trackpad data).  The parameters identify
        !           394: // who to call when we get one.
        !           395: // **********************************************************************************
        !           396: void AppleCuda::registerForADBInterrupts ( ADB_callback_func handler, IOService * caller )
        !           397: {
        !           398: autopoll_handler = handler;
        !           399: ADBid = caller;
        !           400: }
        !           401: 
        !           402: 
        !           403: // **********************************************************************************
        !           404: // autopollArrived
        !           405: //
        !           406: // **********************************************************************************
        !           407: static void autopollArrived ( OSObject * CudaDriver, IOInterruptEventSource *, int )
        !           408: {
        !           409: ((AppleCuda *)CudaDriver)->serviceAutopolls();
        !           410: }
        !           411: 
        !           412: 
        !           413: // **********************************************************************************
        !           414: // serviceAutopolls
        !           415: //
        !           416: // **********************************************************************************
        !           417: void AppleCuda::serviceAutopolls ( void )
        !           418: {
        !           419: cuda_packet_t *        response;
        !           420: 
        !           421: while( inIndex != outIndex ) {
        !           422: 
        !           423:         response = &cuda_unsolicited[ outIndex ];
        !           424: 
        !           425:         if ( ADBid != NULL ) {
        !           426:            (*autopoll_handler)(ADBid,response->a_header[2],response->a_bcount,response->a_buffer);
        !           427:         }
        !           428: 
        !           429:         outIndex = (outIndex + 1) & (NUM_AP_BUFFERS - 1);
        !           430: }
        !           431: }
        !           432: 
        !           433: 
        !           434: // **********************************************************************************
        !           435: // doSyncRequest
        !           436: //
        !           437: // **********************************************************************************
        !           438: IOReturn AppleCuda::doSyncRequest ( cuda_request_t * request )
        !           439: {
        !           440: return(cuda_do_sync_request(this, request, false));
        !           441: }
        !           442: 
        !           443: 
        !           444: // **********************************************************************************
        !           445: // cuda_do_sync_request
        !           446: //
        !           447: // **********************************************************************************
        !           448: IOReturn cuda_do_sync_request ( AppleCuda * self, cuda_request_t * request, bool polled )
        !           449: {
        !           450:     bool               wasPolled = false;
        !           451:     IOInterruptState   ints;
        !           452: 
        !           453:     if( !polled ) {
        !           454:         request->sync = IOSyncer::create();
        !           455:        request->needWake = true;
        !           456:     }
        !           457: 
        !           458:     ints = IOSimpleLockLockDisableInterrupt(self->cuda_request_lock);
        !           459: 
        !           460:     if( polled ) {
        !           461:         wasPolled = self->cuda_polled_mode;
        !           462:         self->cuda_polled_mode = polled;
        !           463:     }
        !           464: 
        !           465:     if( self->cuda_last_request )
        !           466:        self->cuda_last_request->a_next = request;
        !           467:     else
        !           468:        self->cuda_request = request;
        !           469: 
        !           470:     self->cuda_last_request = request;
        !           471: 
        !           472:     if( self->cuda_interrupt_state == CUDA_STATE_IDLE )
        !           473:        cuda_send_request(self);
        !           474: 
        !           475:     if( polled ) {
        !           476:         cuda_poll(self);
        !           477:         self->cuda_polled_mode = wasPolled;
        !           478:         assert( 0 == self->cuda_request );
        !           479:         assert( 0 == self->cuda_last_request );
        !           480:     }
        !           481: 
        !           482:     IOSimpleLockUnlockEnableInterrupt(self->cuda_request_lock, ints);
        !           483: 
        !           484:     if( !polled)
        !           485:        request->sync->wait();
        !           486: 
        !           487:     return cuda_get_result(request);
        !           488: }
        !           489: 
        !           490: 
        !           491: // **********************************************************************************
        !           492: // Cuda_PE_read_write_time_of_day
        !           493: //
        !           494: // **********************************************************************************
        !           495: static int Cuda_PE_read_write_time_of_day ( unsigned int options, long * secs )
        !           496: {
        !           497: cuda_request_t cmd;
        !           498: 
        !           499: adb_init_request(&cmd);
        !           500: 
        !           501: cmd.a_cmd.a_hcount = 2;
        !           502: cmd.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
        !           503: 
        !           504: switch( options ) {
        !           505: 
        !           506:        case kPEReadTOD:
        !           507:             cmd.a_cmd.a_header[1] = ADB_PSEUDOCMD_GET_REAL_TIME;
        !           508:             cmd.a_reply.a_buffer = (UInt8 *)secs;
        !           509:             cmd.a_reply.a_bcount = sizeof(*secs);
        !           510:            break;
        !           511: 
        !           512:        case kPEWriteTOD:
        !           513:             cmd.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_REAL_TIME;
        !           514:             cmd.a_cmd.a_buffer = (UInt8 *)secs;
        !           515:             cmd.a_cmd.a_bcount = sizeof(*secs);
        !           516:            break;
        !           517: 
        !           518:        default:
        !           519:            return 1;
        !           520: }
        !           521: 
        !           522: return cuda_do_sync_request(gCuda, &cmd, true);
        !           523: }
        !           524: 
        !           525: 
        !           526: // **********************************************************************************
        !           527: // Cuda_PE_halt_restart
        !           528: //
        !           529: // **********************************************************************************
        !           530: static int Cuda_PE_halt_restart ( unsigned int type )
        !           531: {
        !           532: cuda_request_t cmd;
        !           533: 
        !           534: adb_init_request(&cmd);
        !           535: 
        !           536: cmd.a_cmd.a_hcount = 2;
        !           537: cmd.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
        !           538: 
        !           539: switch( type ) {
        !           540: 
        !           541:        case kPERestartCPU:
        !           542:             cmd.a_cmd.a_header[1] = ADB_PSEUDOCMD_RESTART_SYSTEM;
        !           543:            break;
        !           544: 
        !           545:        case kPEHaltCPU:
        !           546:             cmd.a_cmd.a_header[1] = ADB_PSEUDOCMD_POWER_DOWN;
        !           547:            break;
        !           548: 
        !           549:        default:
        !           550:            return 1;
        !           551:     }
        !           552: 
        !           553: return cuda_do_sync_request(gCuda, &cmd, true);
        !           554: }
        !           555: 
        !           556: 
        !           557: // **********************************************************************************
        !           558: // Cuda_PE_write_IIC
        !           559: //
        !           560: // **********************************************************************************
        !           561: static int Cuda_PE_write_IIC ( unsigned char addr, unsigned char reg, unsigned char data )
        !           562: {
        !           563: cuda_request_t cmd;
        !           564: 
        !           565: adb_init_request(&cmd);
        !           566: 
        !           567: cmd.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
        !           568: cmd.a_cmd.a_header[1] = ADB_PSEUDOCMD_GET_SET_IIC;
        !           569: cmd.a_cmd.a_header[2] = addr;
        !           570: cmd.a_cmd.a_header[3] = reg;
        !           571: cmd.a_cmd.a_header[4] = data;
        !           572: cmd.a_cmd.a_hcount = 5;
        !           573: 
        !           574: return cuda_do_sync_request(gCuda, &cmd, true);
        !           575: }
        !           576: 
        !           577: 
        !           578: // **********************************************************************************
        !           579: // Cuda_PE_poll_input
        !           580: //
        !           581: // **********************************************************************************
        !           582: static int Cuda_PE_poll_input ( unsigned int, char * c )
        !           583: {
        !           584: AppleCuda *    self = gCuda;
        !           585: int            interruptflag;
        !           586: UInt8          code;
        !           587: cuda_packet_t *        response;         //0123456789abcdef
        !           588: static char    keycodes2ascii[] = "asdfhgzxcv_bqwer"   //00
        !           589:                                "yt123465=97-80]o"      //10
        !           590:                                "u[ip\nlj'k;_,/nm."     //20
        !           591:                                "\t_";                  //30
        !           592: 
        !           593: *c = 0xff;
        !           594: 
        !           595: if( !self ) {
        !           596:        return 1;
        !           597: }
        !           598: 
        !           599: self->cuda_polled_mode = true;
        !           600: interruptflag = *self->cuda_via_regs.interruptFlag & kCudaInterruptMask;
        !           601: eieio();
        !           602: if( interruptflag ) {
        !           603:        cuda_interrupt(self);
        !           604: }
        !           605: 
        !           606: if( self->inIndex != self->outIndex ) {
        !           607:        response = &self->cuda_unsolicited[ self->outIndex ];
        !           608:        if( ((response->a_header[2] >> 4) == 2)
        !           609:                &&  (response->a_bcount > 1) ) {
        !           610:                code = response->a_buffer[0];
        !           611:                if( code < sizeof(keycodes2ascii) ) {
        !           612:                        *c = keycodes2ascii[ code ];
        !           613:                }
        !           614:        }
        !           615:         self->outIndex = self->inIndex;
        !           616: }
        !           617: 
        !           618: self->cuda_polled_mode = false;
        !           619: return 0;
        !           620: }
        !           621: 
        !           622: 
        !           623: //
        !           624: // internal
        !           625: //
        !           626: 
        !           627: 
        !           628: // **********************************************************************************
        !           629: // cuda_send_request
        !           630: //
        !           631: // **********************************************************************************
        !           632: static void cuda_send_request ( AppleCuda * self )
        !           633: {
        !           634: 
        !           635:     // The data register must written with the data byte 25uS
        !           636:     // after examining TREQ or we run the risk of getting out of sync
        !           637:     // with Cuda. So call with disabled interrupts and spinlock held.
        !           638: 
        !           639:     // Check if we can commence with the packet transmission.  First, check if
        !           640:     // Cuda can service our request now.  Second, check if Cuda wants to send
        !           641:     // a response packet now.
        !           642: 
        !           643: if( !cuda_is_transfer_in_progress(self) ) {
        !           644:     // Set the shift register direction to output to Cuda by setting
        !           645:     // the direction bit.
        !           646: 
        !           647:         cuda_set_data_direction_to_output(self);
        !           648: 
        !           649:         // Write the first byte to the shift register
        !           650:         cuda_write_data(self, self->cuda_request->a_cmd.a_header[0]);
        !           651: 
        !           652:         // Set up the transfer state info here.
        !           653: 
        !           654:         self->cuda_is_header_transfer = true;
        !           655:         self->cuda_transfer_count = 1;
        !           656: 
        !           657:         // Make sure we're in idle state before transaction, and then
        !           658:         // assert TIP to tell Cuda we're starting command
        !           659:         cuda_neg_byte_ack(self);
        !           660:         cuda_assert_transfer_in_progress(self);
        !           661: 
        !           662:         // The next state is going to be a transmit state, if there is
        !           663:         // no collision.  This is a requested response but call it sync.
        !           664: 
        !           665:         self->cuda_interrupt_state = CUDA_STATE_TRANSMIT_EXPECTED;
        !           666:         self->cuda_transaction_state = CUDA_TS_SYNC_RESPONSE;
        !           667: } 
        !           668: 
        !           669: #if 0
        !           670: else {
        !           671:        IOLog("Req = %x, state = %x, TIP = %x\n", self->cuda_request,
        !           672:         self->cuda_interrupt_state, cuda_is_transfer_in_progress(self));
        !           673: }
        !           674: #endif
        !           675: }
        !           676: 
        !           677: 
        !           678: // **********************************************************************************
        !           679: // cuda_poll
        !           680: //
        !           681: // **********************************************************************************
        !           682: static void cuda_poll( AppleCuda * self )
        !           683: {
        !           684:     do {
        !           685:         cuda_wait_for_interrupt(self);
        !           686:        cuda_interrupt(self);
        !           687:     } while( self->cuda_interrupt_state != CUDA_STATE_IDLE );
        !           688: }
        !           689: 
        !           690: //
        !           691: //  cuda_process_response
        !           692: //  Execute at secondary interrupt.
        !           693: //
        !           694: 
        !           695: 
        !           696: // **********************************************************************************
        !           697: // cuda_process_response
        !           698: //
        !           699: // **********************************************************************************
        !           700: static void cuda_process_response ( AppleCuda * self )
        !           701: {
        !           702: volatile cuda_request_t *      request;
        !           703: unsigned int                   newIndex;
        !           704: 
        !           705:     // Almost ready for the next state, which should be a Idle state.
        !           706:     // Just need to notifiy the client.
        !           707: 
        !           708: if ( self->cuda_transaction_state == CUDA_TS_SYNC_RESPONSE ) {
        !           709: 
        !           710:         // dequeue reqeuest
        !           711:         cuda_lock(self);
        !           712:         request = self->cuda_request;
        !           713:         if( NULL == (self->cuda_request = request->a_next) ) {
        !           714:             self->cuda_last_request = NULL;
        !           715:        }
        !           716:         cuda_unlock(self);
        !           717: 
        !           718:         // wake the sync request thread
        !           719:         if ( ((cuda_request_t *)request)->needWake ) {
        !           720:             ((cuda_request_t *)request)->sync->signal();
        !           721:        }
        !           722: 
        !           723: }
        !           724: else {
        !           725:        if ( self->cuda_transaction_state == CUDA_TS_ASYNC_RESPONSE ) {
        !           726:                newIndex = (self->inIndex + 1) & (NUM_AP_BUFFERS - 1);
        !           727:                if( newIndex != self->outIndex ) {
        !           728:                                self->inIndex = newIndex;
        !           729:                }
        !           730:                else {
        !           731:                        // drop this packet, and reuse the buffer
        !           732:                }
        !           733:                if ( !self->cuda_polled_mode ) {
        !           734:                        // wake thread to service autopolls
        !           735:                        self->eventSrc->interruptOccurred(0, 0, 0);
        !           736:                }
        !           737:         }
        !           738: }
        !           739: return;
        !           740: }
        !           741: 
        !           742: 
        !           743: // **********************************************************************************
        !           744: // cuda_interrupt
        !           745: //
        !           746: // **********************************************************************************
        !           747: static void cuda_interrupt ( AppleCuda * self )
        !           748: {
        !           749: unsigned char interruptState;
        !           750: 
        !           751:     // Get the relevant signal in determining the cause of the interrupt:
        !           752:     // the shift direction, the transfer request line and the transfer
        !           753:     // request line.
        !           754: 
        !           755: interruptState = cuda_get_interrupt_state(self);
        !           756: 
        !           757: //kprintf("%02x",interruptState);
        !           758: 
        !           759: switch ( interruptState ) {
        !           760:     case kCudaReceiveByte:
        !           761:         cuda_receive_data(self);
        !           762:         break;
        !           763: 
        !           764:     case kCudaReceiveLastByte:
        !           765:         cuda_receive_last_byte(self);
        !           766:         break;
        !           767: 
        !           768:     case kCudaTransmitByte:
        !           769:         cuda_transmit_data(self);
        !           770:         break;
        !           771: 
        !           772:     case kCudaUnexpectedAttention:
        !           773:         cuda_unexpected_attention(self);
        !           774:         break;
        !           775: 
        !           776:     case kCudaExpectedAttention:
        !           777:         cuda_expected_attention(self);
        !           778:         break;
        !           779: 
        !           780:     case kCudaIdleState:
        !           781:         cuda_idle(self);
        !           782:         break;
        !           783: 
        !           784:     case kCudaCollision:
        !           785:         cuda_collision(self);
        !           786:         break;
        !           787: 
        !           788:     // Unknown interrupt, clear it and leave.
        !           789:     default:
        !           790:         cuda_error(self);
        !           791:         break;
        !           792: }
        !           793: }
        !           794: 
        !           795: //
        !           796: //  TransmitCudaData
        !           797: //  Executes at hardware interrupt level.
        !           798: //
        !           799: 
        !           800: // **********************************************************************************
        !           801: // cuda_transmit_data
        !           802: //
        !           803: // **********************************************************************************
        !           804: static void cuda_transmit_data ( AppleCuda * self )
        !           805: {
        !           806:     // Clear the pending interrupt by reading the shift register.
        !           807: 
        !           808: if ( self->cuda_is_header_transfer ) {
        !           809:         // There are more header bytes, write one out.
        !           810:         cuda_write_data(self, self->cuda_request->a_cmd.a_header[self->cuda_transfer_count++]);
        !           811: 
        !           812:         // Toggle the handshake line.
        !           813:         if ( self->cuda_transfer_count >= self->cuda_request->a_cmd.a_hcount ) {
        !           814:             self->cuda_is_header_transfer = FALSE;
        !           815:             self->cuda_transfer_count = 0;
        !           816:         }
        !           817: 
        !           818:         cuda_toggle_byte_ack( self);
        !           819: }
        !           820: else {
        !           821:        if ( self->cuda_transfer_count < self->cuda_request->a_cmd.a_bcount ) {
        !           822:                // There are more command bytes, write one out and update the pointer
        !           823:                cuda_write_data( self,
        !           824:                        *(self->cuda_request->a_cmd.a_buffer + self->cuda_transfer_count++));
        !           825:                // Toggle the handshake line.
        !           826:                cuda_toggle_byte_ack(self);
        !           827:        }
        !           828:        else {
        !           829:                (void)cuda_read_data(self);
        !           830:                // There is no more command bytes, terminate the send transaction.
        !           831:                // Cuda should send a expected attention interrupt soon.
        !           832: 
        !           833:                        cuda_neg_tip_and_byteack(self);
        !           834: 
        !           835:                // The next interrupt should be a expected attention interrupt.
        !           836: 
        !           837:                self->cuda_interrupt_state = CUDA_STATE_ATTN_EXPECTED;
        !           838:        }
        !           839: }
        !           840: }
        !           841: 
        !           842: //
        !           843: //  cuda_expected_attention
        !           844: //  Executes at hardware interrupt level.
        !           845: //
        !           846: 
        !           847: 
        !           848: // **********************************************************************************
        !           849: // cuda_expected_attention
        !           850: //
        !           851: // **********************************************************************************
        !           852: static void cuda_expected_attention ( AppleCuda * self )
        !           853: {
        !           854:     // Clear the pending interrupt by reading the shift register.
        !           855: 
        !           856: (void)cuda_read_data(self);
        !           857: 
        !           858:     // Allow the VIA to settle directions.. else the possibility of
        !           859:     // data corruption.
        !           860: cuda_do_state_transition_delay(self);
        !           861: 
        !           862: if ( self->cuda_transaction_state ==  CUDA_TS_SYNC_RESPONSE ) {
        !           863:         self->cuda_current_response = (cuda_packet_t*)&self->cuda_request->a_reply;
        !           864: }
        !           865: else {
        !           866:         self->cuda_current_response = &self->cuda_unsolicited[ self->inIndex ];
        !           867:         self->cuda_current_response->a_hcount = 0;
        !           868:         self->cuda_current_response->a_bcount = MAX_AP_RESPONSE;
        !           869: }
        !           870: 
        !           871: self->cuda_is_header_transfer = true;
        !           872: self->cuda_is_packet_type = true;
        !           873: self->cuda_transfer_count = 0;
        !           874: 
        !           875:     // Set the shift register direction to input.
        !           876: cuda_set_data_direction_to_input(self);
        !           877: 
        !           878:     // Start the response packet transaction.
        !           879: cuda_assert_transfer_in_progress(self);
        !           880: 
        !           881:     // The next interrupt should be a receive data interrupt.
        !           882: self->cuda_interrupt_state = CUDA_STATE_RECEIVE_EXPECTED;
        !           883: }
        !           884: 
        !           885: //
        !           886: //  cuda_unexpected_attention
        !           887: //  Executes at hardware interrupt level.
        !           888: //
        !           889: 
        !           890: 
        !           891: // **********************************************************************************
        !           892: // cuda_expected_attention
        !           893: //
        !           894: // **********************************************************************************
        !           895: static void cuda_unexpected_attention ( AppleCuda * self )
        !           896: {
        !           897:     // Clear the pending interrupt by reading the shift register.
        !           898: (void)cuda_read_data(self);
        !           899: 
        !           900:     // Get ready for a unsolicited response.
        !           901: self->cuda_current_response = &self->cuda_unsolicited[ self->inIndex ];
        !           902: self->cuda_current_response->a_hcount = 0;
        !           903: self->cuda_current_response->a_bcount = MAX_AP_RESPONSE;
        !           904: 
        !           905: self->cuda_is_header_transfer = TRUE;
        !           906: self->cuda_is_packet_type = TRUE;
        !           907: self->cuda_transfer_count = 0;
        !           908: 
        !           909:     // Start the response packet transaction, Transaction In Progress
        !           910: cuda_assert_transfer_in_progress(self);
        !           911: 
        !           912:     // The next interrupt should be a receive data interrupt and the next
        !           913:     // response should be an async response.
        !           914: 
        !           915: self->cuda_interrupt_state = CUDA_STATE_RECEIVE_EXPECTED;
        !           916: 
        !           917: self->cuda_transaction_state = CUDA_TS_ASYNC_RESPONSE;
        !           918: }
        !           919: 
        !           920: //
        !           921: //  cuda_receive_data
        !           922: //  Executes at hardware interrupt level.
        !           923: //
        !           924: 
        !           925: 
        !           926: // **********************************************************************************
        !           927: // cuda_receive_data
        !           928: //
        !           929: // **********************************************************************************
        !           930: static void cuda_receive_data ( AppleCuda * self )
        !           931: {
        !           932: if ( self->cuda_is_packet_type ) {
        !           933:         unsigned char packetType;
        !           934: 
        !           935:         packetType = cuda_read_data( self);
        !           936:         self->cuda_current_response->a_header[self->cuda_transfer_count++] = packetType;
        !           937: 
        !           938:         if ( packetType == ADB_PACKET_ERROR) {
        !           939:             self->cuda_current_response->a_hcount = 4;
        !           940:         }
        !           941:        else {
        !           942:             self->cuda_current_response->a_hcount = 3;
        !           943:         }
        !           944: 
        !           945:         self->cuda_is_packet_type = false;
        !           946: 
        !           947:         cuda_toggle_byte_ack(self);
        !           948: 
        !           949: }
        !           950: else {
        !           951:        if ( self->cuda_is_header_transfer ) {
        !           952: 
        !           953:                self->cuda_current_response->a_header[self->cuda_transfer_count++] =
        !           954:                        cuda_read_data(self);
        !           955: 
        !           956:                if (self->cuda_transfer_count >= self->cuda_current_response->a_hcount) {
        !           957:                        self->cuda_is_header_transfer = FALSE;
        !           958:                        self->cuda_transfer_count = 0;
        !           959:                }
        !           960: 
        !           961:                cuda_toggle_byte_ack(self);
        !           962:        }
        !           963:        else {
        !           964:                if ( self->cuda_transfer_count < self->cuda_current_response->a_bcount ) {
        !           965:                        // Still room for more bytes. Get the byte and tell Cuda to continue.
        !           966:                        // Toggle the handshake line, ByteAck, to acknowledge receive.
        !           967: 
        !           968:                        *(self->cuda_current_response->a_buffer + self->cuda_transfer_count++) =
        !           969:                                cuda_read_data(self);
        !           970: 
        !           971:                        cuda_toggle_byte_ack(self);
        !           972: 
        !           973:                }
        !           974:                else {
        !           975:                        // Cuda is still sending data but the buffer is full.
        !           976:                        // Normally should not get here.  The only exceptions are open ended
        !           977:                        // request such as  PRAM read...  In any event time to exit.
        !           978: 
        !           979:                        self->cuda_current_response->a_bcount = self->cuda_transfer_count;
        !           980: 
        !           981:                        cuda_read_data(self);
        !           982: 
        !           983:                        cuda_process_response(self);
        !           984:                        cuda_neg_tip_and_byteack(self);
        !           985:                }
        !           986:        }
        !           987: }
        !           988: }
        !           989: 
        !           990: 
        !           991: //
        !           992: //  cuda_receive_last_byte
        !           993: //  Executes at hardware interrupt level.
        !           994: //
        !           995: 
        !           996: 
        !           997: // **********************************************************************************
        !           998: // cuda_receive_last_byte
        !           999: //
        !          1000: // **********************************************************************************
        !          1001: static void cuda_receive_last_byte ( AppleCuda * self )
        !          1002: {
        !          1003: if ( self->cuda_is_header_transfer ) {
        !          1004:         self->cuda_current_response->a_header[self->cuda_transfer_count++]  =
        !          1005:             cuda_read_data(self);
        !          1006: 
        !          1007:         self->cuda_transfer_count = 0;
        !          1008:     }
        !          1009: else {
        !          1010:        if ( self->cuda_transfer_count < self->cuda_current_response->a_bcount ) {
        !          1011:                *(self->cuda_current_response->a_buffer + self->cuda_transfer_count++) =
        !          1012:                cuda_read_data(self);
        !          1013:        }
        !          1014:        else {
        !          1015:                /* Overrun -- ignore data */
        !          1016:                (void) cuda_read_data(self);
        !          1017:        }
        !          1018: }
        !          1019: self->cuda_current_response->a_bcount = self->cuda_transfer_count;
        !          1020: 
        !          1021:     // acknowledge before response so polled mode can work
        !          1022:     // from inside the handler
        !          1023: cuda_neg_tip_and_byteack(self);
        !          1024: cuda_process_response(self);
        !          1025: }
        !          1026: 
        !          1027: 
        !          1028: //
        !          1029: //  cuda_collision
        !          1030: //  Executes at hardware interrupt level.
        !          1031: //
        !          1032: 
        !          1033: 
        !          1034: // **********************************************************************************
        !          1035: // cuda_collision
        !          1036: //
        !          1037: // **********************************************************************************
        !          1038: static void cuda_collision ( AppleCuda * self )
        !          1039: {
        !          1040: // Clear the pending interrupt by reading the shift register.
        !          1041: (void)cuda_read_data(self);
        !          1042: 
        !          1043: // Negate TIP to abort the send.  Cuda should send a second attention
        !          1044: // interrupt to acknowledge the abort cycle.
        !          1045: cuda_neg_transfer_in_progress(self);
        !          1046: 
        !          1047: // The next interrupt should be an expected attention and the next
        !          1048: // response packet should be an async response.
        !          1049: 
        !          1050: self->cuda_interrupt_state = CUDA_STATE_ATTN_EXPECTED;
        !          1051: self->cuda_transaction_state = CUDA_TS_ASYNC_RESPONSE;
        !          1052: 
        !          1053: /* queue the request */
        !          1054: self->cuda_is_header_transfer = false;
        !          1055: self->cuda_transfer_count = 0;
        !          1056: }
        !          1057: 
        !          1058: 
        !          1059: //
        !          1060: //  
        !          1061: //  Executes at hardware interrupt level.
        !          1062: //
        !          1063: 
        !          1064: 
        !          1065: // **********************************************************************************
        !          1066: // cuda_idle
        !          1067: //
        !          1068: // **********************************************************************************
        !          1069: static void cuda_idle ( AppleCuda * self )
        !          1070: {
        !          1071: 
        !          1072: // Clear the pending interrupt by reading the shift register.
        !          1073: (void)cuda_read_data(self);
        !          1074: 
        !          1075: cuda_lock(self);
        !          1076:     // Set to the idle state.
        !          1077: self->cuda_interrupt_state = CUDA_STATE_IDLE;
        !          1078:     // See if there are any pending requests.
        !          1079: if( self->cuda_request ) {
        !          1080:         cuda_send_request(self);
        !          1081: }
        !          1082: cuda_unlock(self);
        !          1083: }
        !          1084: 
        !          1085: 
        !          1086: // **********************************************************************************
        !          1087: // cuda_error
        !          1088: //
        !          1089: // **********************************************************************************
        !          1090: static void cuda_error ( AppleCuda * self )
        !          1091: {
        !          1092: //printf("{Error %d}", self->cuda_transaction_state);
        !          1093: 
        !          1094: // Was looking at cuda_transaction_state - doesn't seem right
        !          1095: 
        !          1096: switch ( self->cuda_interrupt_state ) {
        !          1097:     case CUDA_STATE_IDLE:
        !          1098:         cuda_neg_tip_and_byteack(self);
        !          1099:         break;
        !          1100: 
        !          1101:     case CUDA_STATE_TRANSMIT_EXPECTED:
        !          1102:         if ( self->cuda_is_header_transfer && self->cuda_transfer_count <= 1 ) {
        !          1103:             cuda_do_state_transition_delay(self);
        !          1104:             cuda_neg_transfer_in_progress(self);
        !          1105:             cuda_set_data_direction_to_input(self);
        !          1106:             panic ("CUDA - TODO FORCE COMMAND BACK UP!\n");
        !          1107:         }
        !          1108:        else {
        !          1109:             self->cuda_interrupt_state = CUDA_STATE_ATTN_EXPECTED;
        !          1110:             cuda_neg_tip_and_byteack(self);
        !          1111:         }
        !          1112:         break;
        !          1113: 
        !          1114:     case CUDA_STATE_ATTN_EXPECTED:
        !          1115:         cuda_assert_transfer_in_progress(self);
        !          1116: 
        !          1117:         cuda_do_state_transition_delay(self);
        !          1118:         cuda_set_data_direction_to_input(self);
        !          1119:         cuda_neg_transfer_in_progress(self);
        !          1120:         panic("CUDA - TODO CHECK FOR TRANSACTION TYPE AND ERROR");
        !          1121:         break;
        !          1122: 
        !          1123:     case CUDA_STATE_RECEIVE_EXPECTED:
        !          1124:         cuda_neg_tip_and_byteack(self);
        !          1125:         panic("Cuda - todo check for transaction type and error");
        !          1126:         break;
        !          1127: 
        !          1128:     default:
        !          1129:         cuda_set_data_direction_to_input(self);
        !          1130:         cuda_neg_tip_and_byteack(self);
        !          1131:         break;
        !          1132: }
        !          1133: }
        !          1134: 
        !          1135: static void cuda_do_state_transition_delay( AppleCuda * self )
        !          1136: {
        !          1137:        AbsoluteTime    deadline;
        !          1138: 
        !          1139:        clock_absolutetime_interval_to_deadline(
        !          1140:                                                        self->cuda_state_transition_delay, &deadline);
        !          1141:        clock_delay_until(deadline);
        !          1142: }

unix.superglobalmegacorp.com

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