|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.