Annotation of XNU/iokit/Drivers/platform/drvAppleCuda/AppleCuda.cpp, revision 1.1.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.