|
|
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.