|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25:
26: /*********
27:
28: cuda.m
29:
30: This file is a combination of the old cuda.c and the new pmu.m for PGE.
31: Cuda is based on a Motorola MC68HC05E1.
32:
33: NOTES:
34:
35: "WARNING" look for this string during integration.
36: cuda interrupts are cleared by reading the shift register.
37: cuda has a TIP (transaction in progress) signal which the PGE seems to lack.
38: PGE seems to require a "length" byte in command packets while cuda does not.
39: Signals:
40: TIP is asserted when 0. System asserts this when transaction is in progress.
41: BYTEACK is asserted when 0. When data is passed from the system to Cuda,
42: a toggle indicates to Cuda that the VIA data register is full. When
43: data is passed from Cuda to the system, a toggle indicates that the
44: system has read the data from the VIA and the VIA data register
45: is now empty. When no transaction in progress (note TIP), this
46: line is deasserted.
47: TREQ is asserted when 0. When asserted by Cuda, this indicates to the system
48: that Cuda is making a Transaction REQUEST. During a transaction which
49: is initiated by Cuda (as opposed to one initiated by system), this line
50: is negated prior to generating a VIA interrupt for the last byte
51: of data transacted. When no transaction is in progress (note TIP),
52: this line is negated.
53:
54:
55: *********/
56:
57:
58: #include <sys/param.h> //for sysctl
59: #include <sys/proc.h> //for sysctl also (but not documented)
60:
61: #import <kern/clock.h>
62: #import <kernserv/prototypes.h>
63: #import <kernserv/clock_timer.h>
64: #import <kernserv/ns_timer.h>
65: #import <sys/time.h>
66: #import <sys/callout.h>
67: #import <machdep/ppc/proc_reg.h>
68: #import <driverkit/generalFuncs.h>
69: #import <driverkit/kernelDriver.h>
70: #import <driverkit/interruptMsg.h>
71:
72: #import <bsd/dev/ppc/drvPMU/pmu.h>
73: #import <bsd/dev/ppc/drvPMU/pmupriv.h>
74: #import <bsd/dev/ppc/drvPMU/pmumisc.h>
75: #include <sys/sysctl.h> //for debug2, debug3, debug4 in sysctl
76: #import "via6522.h"
77: #import "cuda_hdw.h"
78: #import "cuda.h" //must come after pmu definitions
79:
80: //typedefs from cuda.c:
81: //
82: // CudaInterruptState - internal
83: //
84: //#define kNS_TIMEOUT_AUTOPOLL 9000000000ULL
85: #define kNS_TIMEOUT_AUTOPOLL 4000000000ULL
86:
87: enum CudaInterruptState
88: {
89: CUDA_STATE_INTERRUPT_LIMBO = -1, //
90: CUDA_STATE_IDLE = 0, //
91: CUDA_STATE_ATTN_EXPECTED = 1, //
92: CUDA_STATE_TRANSMIT_EXPECTED = 2, //
93: CUDA_STATE_RECEIVE_EXPECTED = 3 //
94: };
95:
96: typedef enum CudaInterruptState CudaInterruptState;
97:
98:
99: //
100: // CudaTransactionFlag - internal to cuda2.m, used to be in cuda.c
101: //
102:
103: enum CudaTransactionFlag
104: {
105: CUDA_TS_NO_REQUEST = 0x0000,
106: CUDA_TS_SYNC_RESPONSE = 0x0001,
107: CUDA_TS_ASYNC_RESPONSE = 0x0002
108: };
109:
110: typedef enum CudaTransactionFlag CudaTransactionFlag;
111:
112:
113: void gotInterruptCause(id, UInt32, UInt32, UInt8 *);
114: void cuda_timer_autopoll(port_t mach_port);
115: void timer_expired(port_t mach_port); //WARNING... not needed by Cuda? Was not in cuda.c
116:
117: extern id ApplePMUId; //in adb.m (remove this when adb becomes an indirect driver)(q8q)
118:
119: extern void kprintf(const char *, ...);
120: extern void bcopy(void *, void *, int);
121: // extern to let us fix up the boot time.
122: extern void set_boot_time(void);
123: extern msg_send_from_kernel(msg_header_t *, int, int);
124:
125: // Variables copied from cuda.c:
126: static long cuda_state_transition_delay_ticks;
127: volatile CudaInterruptState cuda_interrupt_state;
128: volatile CudaTransactionFlag cuda_transaction_state;
129: static port_t glob_port;
130:
131: //WARNING Hack to make pmutables.h work
132: extern SInt8 *cmdLengthTable;
133: extern SInt8 *rspLengthTable;
134:
135:
136: CudaRequest *cuda_request = NULL, *cuda_collided = NULL;
137: adb_packet_t cuda_unsolicited;
138: adb_packet_t *cuda_current_response = NULL;
139:
140: int cuda_transfer_count = 0;
141: boolean_t cuda_is_header_transfer = FALSE;
142: boolean_t cuda_is_packet_type = FALSE;
143: boolean_t cuda_initted = FALSE;
144: boolean_t debugging = FALSE;
145: boolean_t adb_reading = FALSE;
146:
147: static UInt8 *return_buff_pointer = NULL;
148: static boolean_t bImmediate_buff_needed = FALSE;
149:
150: // for Debug
151: pmADBinput_func cuda_debug_client; // Input handler in ADB client
152: static VIAAddress stat_aux_control;
153: static boolean_t p = FALSE;
154: int que_cuda_count;
155: int cuda_glob_dbug_freeze; //Can only be asserted through debugging tool
156: int cuda_glob_data1;
157: int cuda_glob_data2;
158: int cuda_freeze_counter; //This will become "static" after debugging phase
159: int cuda_freeze_prevcount;
160:
161: //sysctl debugging tool
162: struct ctldebug debug2 = { "cuda_glob_dbug_freeze", &cuda_glob_dbug_freeze };
163: //struct ctldebug debug3 = { "cuda_glob_data1", &cuda_glob_data1 };
164: //struct ctldebug debug4 = { "cuda_glob_data2", &cuda_glob_data2 };
165:
166:
167: @implementation AppleCuda
168:
169: // **********************************************************************************
170: // probe
171: //
172: //
173: //
174: // **********************************************************************************
175: + (Boolean) probe : deviceDescription
176: {
177: id dev;
178:
179: if (cuda_initted)
180: return 1;
181:
182: cuda_initted = TRUE;
183: que_cuda_count = 0;
184: cuda_glob_dbug_freeze = 0; // 0. Only external debugger can change it now.
185: cuda_freeze_counter = 1; //2 vars needed to recover from BYTEACK hang
186: cuda_freeze_prevcount = 0;
187:
188: if ( (dev = [ self alloc ]) == nil ) {
189: return NO;
190: }
191:
192: if ([dev initFromDeviceDescription:deviceDescription] == nil) {
193: return NO;
194: }
195:
196: // tell ADB about us. This is a global variable accessible in adb.m
197: ApplePMUId = dev;
198:
199: set_boot_time();
200:
201: return YES;
202: }
203:
204:
205: // **********************************************************************************
206: // initFromDeviceDescription
207: //
208: //
209: //
210: // **********************************************************************************
211: - initFromDeviceDescription:(IODeviceDescription *)deviceDescription
212: {
213: volatile unsigned char valcuda;
214: VIAAddress physicalAddress;
215: IORange * ioRange;
216: unsigned char *cuda_temp_reg;
217:
218: struct timeval x = {0,1000000}; // one second timeout on adb reads
219:
220: auto_power_on = 1; //default is to enable auto power on feature (after electrical power failure)
221:
222: if ( [super initFromDeviceDescription:deviceDescription] == nil ) {
223: [self free];
224: return nil;
225: }
226:
227: [self setDeviceKind:"Cuda Subsystem"];
228: [self setLocation:NULL];
229: [self setName:"Cuda"];
230:
231:
232: ioRange = [deviceDescription memoryRangeList];
233:
234: physicalAddress = (VIAAddress)ioRange->start;
235: stat_aux_control = physicalAddress;
236:
237: //above works perfectly physicalAddress = (unsigned char*)POWERMAC_IO(PCI_VIA_BASE_PHYS);
238:
239:
240: //CUDA_REPLACE
241:
242:
243: VIA1_shift = physicalAddress + 0x1400; // initialize VIA addresses
244: VIA1_auxillaryControl = physicalAddress + 0x1600;
245:
246: VIA1_interruptFlag = physicalAddress + 0x1A00;
247: VIA1_interruptEnable = physicalAddress + 0x1C00;
248: VIA2_dataB = physicalAddress + 0x0000; // Hooper uses VIA 1 instead
249:
250:
251: PMack = kCudaAssertByteAcknowledge; //in cuda_hdw.h is 0x10
252:
253:
254:
255: cuda_state_transition_delay_ticks = nsec_to_processor_clock_ticks(200);
256: //This is just 2 ticks
257: // Set the direction of the cuda signals. ByteACk and TIP are output and
258: // TREQ is an input
259:
260: cuda_temp_reg = physicalAddress + 0x0400; //dataDirectionB
261: *cuda_temp_reg |= (kCudaByteAcknowledgeMask | kCudaTransferInProgressMask);
262: *cuda_temp_reg &= ~kCudaTransferRequestMask;
263:
264: *VIA1_auxillaryControl = ( *VIA1_auxillaryControl | kCudaTransferMode) &
265: kCudaSystemRecieve;
266:
267: // Clear any posible cuda interupt.
268: if ( *VIA1_shift );
269:
270: // Initialize the internal data.
271:
272: cuda_interrupt_state = CUDA_STATE_IDLE;
273: cuda_transaction_state = CUDA_TS_NO_REQUEST;
274: cuda_is_header_transfer = FALSE;
275: cuda_is_packet_type = FALSE;
276: cuda_transfer_count = 0;
277: cuda_current_response = NULL;
278:
279: // Terminate transaction and set idle state
280: // cuda_neg_tip_and_byteack();
281: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress;
282: eieio();
283:
284: // we want to delay 4 mS for ADB reset to complete
285:
286: delay(4000);
287:
288: // Clear pending interrupt if any...
289: //(void)cuda_read_data();
290: valcuda = *VIA1_shift; eieio();
291:
292: // Issue a Sync Transaction, ByteAck asserted while TIP is negated.
293: // cuda_assert_byte_ack();
294: *VIA2_dataB &= kCudaAssertByteAcknowledge; eieio();
295:
296:
297: // Wait for the Sync acknowledgement, cuda to assert TREQ
298: // cuda_wait_for_transfer_request_assert();
299: while ( (*VIA2_dataB & kCudaTransferRequestMask) != 0 )
300: {
301: eieio();
302: }
303: eieio();
304:
305: // Wait for the Sync acknowledgement interrupt.
306: // cuda_wait_for_interrupt();
307: while ( (*VIA1_interruptFlag & kCudaInterruptMask) == 0 )
308: {
309: eieio();
310: }
311: eieio();
312:
313:
314: // Clear pending interrupt
315: //(void)cuda_read_data();
316: valcuda = *VIA1_shift; eieio();
317:
318: // Terminate the sync cycle by Negating ByteAck
319: // cuda_neg_byte_ack();
320: *VIA2_dataB |= kCudaNegateByteAcknowledge; eieio();
321:
322: // Wait for the Sync termination acknowledgement, cuda negates TREQ.
323: // cuda_wait_for_transfer_request_neg();
324: while ( (*VIA2_dataB & kCudaTransferRequestMask) == 0 )
325: {
326: eieio();
327: }
328: eieio();
329:
330:
331: // Wait for the Sync termination acknowledgement interrupt.
332: // cuda_wait_for_interrupt();
333: while ( (*VIA1_interruptFlag & kCudaInterruptMask) == 0 )
334: {
335: eieio();
336: }
337: eieio();
338:
339:
340: // Terminate transaction and set idle state, TIP negate and ByteAck negate.
341: // cuda_neg_transfer_in_progress();
342: *VIA2_dataB |= kCudaNegateTransferInProgress; eieio();
343:
344: // Clear pending interrupt, if there is one...
345: //(void)cuda_read_data();
346: valcuda = *VIA1_shift; eieio();
347:
348:
349:
350:
351:
352: ADBclient = NULL;
353: RTCclient = NULL;
354: debugging = FALSE;
355: queueHead = NULL;
356: queueTail = NULL;
357: adb_reading = FALSE;
358: adb_read_timeout = timeval_to_ns_time(&x);
359:
360: //CUDA_REPLACE
361: // A.W. This call seems to have no counterpart in Cuda
362: // Pending interrupts are cleared with cuda_read_data()
363: *VIA1_interruptEnable = kCudaInterruptDisable;eieio(); // turn off any pending interrupt
364: valcuda = *VIA1_shift; eieio();
365:
366: [self EnableCudaInterrupt]; // enable PGE interrupts. CUDA_REPLACE already
367:
368: [self enableAllInterrupts];
369:
370: //WARNING... this was moved here in new pmu.m
371: if ([self startIOThread] != IO_R_SUCCESS) {
372: [self free];
373: return nil;
374: }
375: port = IOConvertPort([self interruptPort],IO_KernelIOTask,IO_Kernel);
376: glob_port = port; //needed for non-ObjC functions
377: [self registerDevice];
378:
379:
380: //A.W. I don't think Cuda needs to exclude any interrupts
381: //I need to set up a 5-second timer which will make sure that the Auto Poll
382: // feature of Cuda is never accidentally disabled by anybody
383: ns_timeout((func)cuda_timer_autopoll,(void *)port, kNS_TIMEOUT_AUTOPOLL ,CALLOUT_PRI_SOFTINT0); // start timer
384:
385:
386: return self;
387: }
388:
389:
390: // **********************************************************************************
391: // free
392: //
393: //
394: //
395: // **********************************************************************************
396: - free
397: {
398: return [ super free ];
399: }
400:
401:
402: // **********************************************************************************
403: // receiveMsg
404: //
405: //
406: //
407: // **********************************************************************************
408:
409:
410: - (void)receiveMsg
411: {
412: CudaMachMessage * toQueue;
413: IOReturn result;
414: spl_t intstate;
415: //unsigned char interruptState;
416:
417: //interruptState = (*VIA2_dataB & kCudaInterruptStateMask) | (*VIA1_auxillaryControl & kCudaDirectionMask) ;
418: //if ( (interruptState == kCudaIdleState) && !adb_reading )
419:
420: if (cuda_interrupt_state == CUDA_STATE_IDLE)
421: {
422:
423: if (p) kprintf("cuda2.m::receiveMsg will Xmit now... \n");
424: //localMachMessage is class variable in cuda.h
425: localMachMessage.msgHeader.msg_size = sizeof(CudaMachMessage);
426: localMachMessage.msgHeader.msg_local_port = [self interruptPort];
427: result = msg_receive(&localMachMessage.msgHeader, (msg_option_t)RCV_TIMEOUT, 0);
428:
429: #ifdef OMIT
430: if ( localMachMessage.msgBody.pmCallback == NULL )
431: {
432: kprintf("ADAM: receiveMsg no callback\n");
433: }
434: #endif
435:
436: if ( result == RCV_SUCCESS ) {
437: //Try Simon's suggestion
438: intstate = spltty();
439: [self StartCudaTransmission:&localMachMessage.msgBody];
440: splx(intstate);
441: }
442: }
443: else
444: {
445: if (p) kprintf("cuda2.m::receiveMsg will enqueue instead \n");
446:
447: #ifdef DEBUG
448: if (cuda_glob_dbug_freeze == 1)
449: {
450: kprintf("cuda: Queued\n");
451: }
452: #endif
453:
454: toQueue = (CudaMachMessage*)kalloc(sizeof(CudaMachMessage));
455: toQueue->msgHeader.msg_size = sizeof(CudaMachMessage);
456: toQueue->msgHeader.msg_local_port = [self interruptPort];
457: result = msg_receive(&toQueue->msgHeader, (msg_option_t)RCV_TIMEOUT, 0);
458: if ( result == RCV_SUCCESS ) {
459: toQueue->msgBody.prev = queueTail;
460: toQueue->msgBody.next = NULL;
461: if ( queueTail != NULL ) {
462: queueTail->msgBody.next = toQueue;
463: }
464: else
465: {
466: queueHead = toQueue;
467: }
468: queueTail = toQueue;
469: }
470: }
471: }
472:
473:
474:
475:
476:
477:
478:
479: // **********************************************************************************
480: // timeoutOccurred
481: //
482: // Our adb-read timer has expired after sending an adb-read command to the PMU.
483: // This means there is no such addressed device on the ADB bus.
484: // We call back to the ADB driver with a zero-characters-received response and
485: // dequeue our command queue and carry on.
486: // **********************************************************************************
487: - (void)timeoutOccurred
488: {
489: adb_reading = FALSE;
490: if ( clientRequest->pmCallback != NULL ) { // Make the client callback
491: clientRequest->pmCallback(clientRequest->pmId, clientRequest->pmRefNum, 0, NULL);
492: } // with zero received-length
493: [self CheckRequestQueue];
494: }
495:
496:
497: // ****************************************************************************
498: // CheckRequestQueue
499: // Called at interrupt time when current request is complete. We may start
500: // another request here if one is in queue, or we may re-enable PMU interrupts
501: // (they were turned off in PMUStartIO) and return.
502: // ****************************************************************************
503:
504: - (void)CheckRequestQueue
505: {
506: CudaMachMessage * nextRequest;
507:
508: if ( queueHead == NULL ) { // is queue empty?
509: if (p) kprintf("cuda2.m::CheckRequestQueue empty \n");
510: [self EnableCudaInterrupt]; // yes, enable interrupt and return
511: }
512: else
513: {
514: que_cuda_count--;
515: if (p) kprintf("cuda2.m::CheckRequestQueue will dequeue \n");
516: nextRequest = queueHead; // no, dequeue first command
517: queueHead = nextRequest->msgBody.next;
518: if ( queueHead == NULL ) {
519: queueTail = NULL;
520: }
521: bcopy (&nextRequest->msgBody, &localMachMessage.msgBody, sizeof(CudaRequest)); // copy it
522: kfree(nextRequest, sizeof(CudaMachMessage)); // free its memory
523: [self StartCudaTransmission:&localMachMessage.msgBody]; // and send it to the Cuda
524: }
525: }
526:
527:
528:
529:
530: // **********************************************************************************
531: // registerForADBAutopoll
532: //
533: // The ADB driver is calling to tell us that it is prepared to receive
534: // "unsolicited" ADB autopoll data. The parameter tells who to call
535: // when we get some.
536: //
537: // **********************************************************************************
538: - (void)registerForADBAutopoll :(pmCallback_func)InputHandler
539: :(id)caller
540: {
541: if (p) kprintf("registerForADBAutopoll: %08x caller: %08x\n", InputHandler, caller);
542: ADBclient = InputHandler;
543: cuda_debug_client = ADBclient; // Debug use only
544: ADBid = caller;
545: }
546:
547:
548: // **********************************************************************************
549: // ADBWrite
550: //
551: // **********************************************************************************
552: - (PMUStatus)ADBWrite :(UInt32)DevAddr
553: :(UInt32)DevReg
554: :(UInt32)ByteCount
555: :(UInt8*)Buffer
556: :(UInt32)RefNum
557: :(id)Id
558: :(pmCallback_func)Callback
559: {
560: CudaMachMessage request;
561: msg_return_t return_code;
562:
563: if (p) kprintf("ADBWrite\n");
564:
565: if (ByteCount > 7)
566: {
567: kprintf("bsd-dev-ppc-drvCuda-cuda.m: ADBWrite may fail\n");
568: }
569:
570: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_ADB;
571: request.msgBody.a_cmd.a_header[1] = ADB_ADBCMD_WRITE_ADB | DevAddr << 4 | DevReg;
572: request.msgBody.a_cmd.a_header[2] = Buffer[0];
573: request.msgBody.a_cmd.a_header[3] = Buffer[1];
574: request.msgBody.a_cmd.a_header[4] = Buffer[2]; //necessary?
575: request.msgBody.a_cmd.a_header[5] = Buffer[3];
576: request.msgBody.a_cmd.a_header[6] = Buffer[4];
577: request.msgBody.a_cmd.a_header[7] = Buffer[5];
578: request.msgBody.a_cmd.a_header[8] = Buffer[6];
579:
580: //request.msgBody.a_cmd.a_hcount = 4;
581: request.msgBody.a_cmd.a_hcount = ByteCount + 2;
582: //Dave added unlimited-length adb_writereg()
583:
584: request.msgBody.a_cmd.a_bcount = 0;
585: request.msgBody.pmCallback = Callback;
586:
587: #ifdef OMIT
588: if (Callback == NULL)
589: {
590: kprintf("Cuda: ADBWrite callback is NULL\n");
591: }
592: #endif
593:
594: request.msgBody.pmId = Id;
595: request.msgBody.pmRefNum = RefNum;
596:
597: request.msgHeader.msg_simple = TRUE;
598: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
599: request.msgHeader.msg_remote_port = port;
600: request.msgHeader.msg_local_port = PORT_NULL;
601: request.msgHeader.msg_size = sizeof(CudaMachMessage);
602: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
603:
604: if ( return_code == SEND_SUCCESS ) {
605: return kPMUNoError;
606: }
607: else {
608: return kPMUIOError;
609: }
610: }
611:
612:
613: // **********************************************************************************
614: // ADBRead
615: //
616: // **********************************************************************************
617: - (PMUStatus)ADBRead :(UInt32)DevAddr
618: :(UInt32)DevReg
619: :(UInt32)RefNum
620: :(id)Id
621: :(pmCallback_func)Callback
622: {
623: CudaMachMessage request;
624: msg_return_t return_code;
625:
626: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_ADB;
627: request.msgBody.a_cmd.a_header[1] = ADB_ADBCMD_READ_ADB | DevAddr << 4 | DevReg;
628: request.msgBody.a_cmd.a_hcount = 2;
629: //request.msgBody.a_cmd.a_bsize = sizeof(request.msgBody.a_cmd.a_buffer);
630: request.msgBody.a_reply.a_bsize = 8; //It's 8 in adb.h
631: //WARNING... try out line above 3/4/98 TitanL kernel
632:
633: request.msgBody.a_cmd.a_bcount = 0;
634: request.msgBody.pmCallback = Callback;
635:
636: #ifdef OMIT
637: if (Callback == NULL)
638: {
639: kprintf("Cuda: ADBRead callback is NULL\n");
640: }
641: #endif
642:
643: request.msgBody.pmId = Id;
644: request.msgBody.pmRefNum = RefNum;
645:
646: request.msgHeader.msg_simple = TRUE;
647: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
648: request.msgHeader.msg_remote_port = port;
649: request.msgHeader.msg_local_port = PORT_NULL;
650: request.msgHeader.msg_size = sizeof(CudaMachMessage);
651: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
652:
653: if ( return_code == SEND_SUCCESS ) {
654: return kPMUNoError;
655: }
656: else {
657: return kPMUIOError;
658: }
659: }
660:
661:
662: // **********************************************************************************
663: // ADBReset
664: //
665: // **********************************************************************************
666: - (PMUStatus)ADBReset :(UInt32)RefNum
667: :(id)Id
668: :(pmCallback_func)Callback
669: {
670: CudaMachMessage request;
671: msg_return_t return_code;
672:
673: kprintf("CUDA: ADBReset\n");
674: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_ADB;
675: request.msgBody.a_cmd.a_header[1] = ADB_ADBCMD_RESET_BUS;
676: request.msgBody.a_cmd.a_hcount = 2;
677: request.msgBody.a_cmd.a_bcount = 0;
678: request.msgBody.pmCallback = Callback;
679: request.msgBody.pmId = Id;
680: request.msgBody.pmRefNum = RefNum;
681:
682: request.msgHeader.msg_simple = TRUE;
683: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
684: request.msgHeader.msg_remote_port = port;
685: request.msgHeader.msg_local_port = PORT_NULL;
686: request.msgHeader.msg_size = sizeof(CudaMachMessage);
687: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
688:
689: if ( return_code == SEND_SUCCESS ) {
690: return kPMUNoError;
691: }
692: else {
693: return kPMUIOError;
694: }
695: }
696:
697:
698: // **********************************************************************************
699: // ADBFlush
700: //
701: // **********************************************************************************
702: - (PMUStatus)ADBFlush :(UInt32)DevAddr
703: :(UInt32)RefNum
704: :(id)Id
705: :(pmCallback_func)Callback
706: {
707: CudaMachMessage request;
708: msg_return_t return_code;
709:
710: if (p) kprintf("ADBFlush\n");
711: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_ADB;
712: request.msgBody.a_cmd.a_header[1] = ADB_ADBCMD_FLUSH_ADB | (DevAddr << 4);
713: request.msgBody.a_cmd.a_hcount = 2;
714: request.msgBody.a_cmd.a_bcount = 0;
715: request.msgBody.pmId = Id;
716: request.msgBody.pmRefNum = RefNum;
717: request.msgBody.pmCallback = Callback;
718:
719: request.msgHeader.msg_simple = TRUE;
720: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
721: request.msgHeader.msg_remote_port = port;
722: request.msgHeader.msg_local_port = PORT_NULL;
723: request.msgHeader.msg_size = sizeof(CudaMachMessage);
724: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
725:
726: if ( return_code == SEND_SUCCESS ) {
727: return kPMUNoError;
728: }
729: else {
730: return kPMUIOError;
731: }
732: }
733:
734:
735: // **********************************************************************************
736: // ADBSetPollList
737: //
738: //
739: // **********************************************************************************
740: - (PMUStatus)ADBSetPollList :(UInt32)PollBitField
741: :(UInt32)RefNum
742: :(id)Id
743: :(pmCallback_func)Callback
744: {
745: CudaMachMessage request;
746: msg_return_t return_code;
747:
748: if (p) kprintf("ADBSetPollList\n");
749: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
750: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_DEVICE_LIST;
751: request.msgBody.a_cmd.a_header[2] = (PollBitField >> 8) & 0xFF;
752: request.msgBody.a_cmd.a_header[3] = PollBitField & 0xFF;
753: request.msgBody.a_cmd.a_hcount = 4;
754: request.msgBody.a_cmd.a_bcount = 0;
755: request.msgBody.pmRefNum = RefNum;
756: request.msgBody.pmId = Id;
757: request.msgBody.pmCallback = Callback;
758:
759: #ifdef OMIT
760: if (Callback == NULL)
761: {
762: kprintf("Cuda: ADBSetPollList callback is NULL\n");
763: }
764: #endif
765:
766:
767: request.msgHeader.msg_simple = TRUE;
768: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
769: request.msgHeader.msg_remote_port = port;
770: request.msgHeader.msg_local_port = PORT_NULL;
771: request.msgHeader.msg_size = sizeof(CudaMachMessage);
772: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
773:
774: if ( return_code == SEND_SUCCESS ) {
775: return kPMUNoError;
776: }
777: else {
778: return kPMUIOError;
779: }
780: }
781:
782:
783:
784:
785: // **********************************************************************************
786: // ADBSetFileServerMode()
787: //
788: // **********************************************************************************
789: - (PMUStatus)ADBSetFileServerMode :(UInt32)RefNum
790: :(id)Id
791: :(pmCallback_func)Callback
792:
793: {
794: CudaMachMessage request;
795: msg_return_t return_code;
796:
797: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
798: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_FILE_SERVER_FLAG;
799: request.msgBody.a_cmd.a_header[2] = TRUE;
800: request.msgBody.a_cmd.a_hcount = 3;
801: request.msgBody.a_cmd.a_bcount = 0;
802: request.msgBody.pmRefNum = RefNum;
803: request.msgBody.pmId = Id;
804: request.msgBody.pmCallback = Callback;
805:
806: request.msgHeader.msg_simple = TRUE;
807: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
808: request.msgHeader.msg_remote_port = port;
809: request.msgHeader.msg_local_port = PORT_NULL;
810: request.msgHeader.msg_size = sizeof(CudaMachMessage);
811: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
812:
813: if ( return_code == SEND_SUCCESS ) {
814: return kPMUNoError;
815: }
816: else {
817: return kPMUIOError;
818: }
819: }
820:
821:
822: // **********************************************************************************
823: // ADBPollEnable
824: //
825: // **********************************************************************************
826: - (PMUStatus)ADBPollEnable :(UInt32)RefNum
827: :(id)Id
828: :(pmCallback_func)Callback
829:
830: {
831: CudaMachMessage request;
832: msg_return_t return_code;
833:
834: if (p) kprintf("ADBPollEnable\n");
835: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
836: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_START_STOP_AUTO_POLL;
837: request.msgBody.a_cmd.a_header[2] = TRUE;
838: request.msgBody.a_cmd.a_hcount = 3;
839: request.msgBody.a_cmd.a_bcount = 0;
840: request.msgBody.pmRefNum = RefNum;
841: request.msgBody.pmId = Id;
842: request.msgBody.pmCallback = Callback;
843:
844: request.msgHeader.msg_simple = TRUE;
845: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
846: request.msgHeader.msg_remote_port = port;
847: request.msgHeader.msg_local_port = PORT_NULL;
848: request.msgHeader.msg_size = sizeof(CudaMachMessage);
849: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
850:
851: if ( return_code == SEND_SUCCESS ) {
852: return kPMUNoError;
853: }
854: else {
855: return kPMUIOError;
856: }
857: }
858:
859:
860: // **********************************************************************************
861: // ADBPollDisable
862: //
863: // **********************************************************************************
864: - (PMUStatus)ADBPollDisable :(UInt32)RefNum
865: :(id)Id
866: :(pmCallback_func)Callback
867: {
868: CudaMachMessage request;
869: msg_return_t return_code;
870:
871: if (p) kprintf("ADBPollDisable\n");
872: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
873: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_START_STOP_AUTO_POLL;
874: request.msgBody.a_cmd.a_header[2] = FALSE;
875: request.msgBody.a_cmd.a_hcount = 3;
876: request.msgBody.a_cmd.a_bcount = 0;
877: request.msgBody.pmRefNum = RefNum;
878: request.msgBody.pmId = Id;
879: request.msgBody.pmCallback = Callback;
880:
881: request.msgHeader.msg_simple = TRUE;
882: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
883: request.msgHeader.msg_remote_port = port;
884: request.msgHeader.msg_local_port = PORT_NULL;
885: request.msgHeader.msg_size = sizeof(CudaMachMessage);
886: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
887:
888: if ( return_code == SEND_SUCCESS ) {
889: return kPMUNoError;
890: }
891: else {
892: return kPMUIOError;
893: }
894: }
895:
896:
897: // **********************************************************************************
898: // ADBSetPollRate
899: //
900: // **********************************************************************************
901: - (PMUStatus)ADBSetPollRate :(UInt32)NewRate
902: :(UInt32)RefNum
903: :(id)Id
904: :(pmCallback_func)Callback
905: {
906: CudaMachMessage request;
907: msg_return_t return_code;
908:
909: if (p) kprintf("ADBSetPollRate\n");
910: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
911: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_AUTO_RATE;
912: request.msgBody.a_cmd.a_header[2] = NewRate;
913: request.msgBody.a_cmd.a_hcount = 3;
914: request.msgBody.a_cmd.a_bcount = 0;
915: request.msgBody.pmRefNum = RefNum;
916: request.msgBody.pmId = Id;
917: request.msgBody.pmCallback = Callback;
918:
919: request.msgHeader.msg_simple = TRUE;
920: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
921: request.msgHeader.msg_remote_port = port;
922: request.msgHeader.msg_local_port = PORT_NULL;
923: request.msgHeader.msg_size = sizeof(CudaMachMessage);
924: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
925:
926: if ( return_code == SEND_SUCCESS ) {
927: return kPMUNoError;
928: }
929: else {
930: return kPMUIOError;
931: }
932: }
933:
934:
935: // **********************************************************************************
936: // ADBGetPollRate
937: //
938: // **********************************************************************************
939: - (PMUStatus)ADBGetPollRate :(UInt32 *)CurrentRate
940: :(UInt32)RefNum
941: :(id)Id
942: :(pmCallback_func)Callback
943: {
944: return kPMUNotSupported;
945: }
946:
947:
948: // **********************************************************************************
949: // ADBSetAlternateKeyboard
950: //
951: // **********************************************************************************
952: - (PMUStatus)ADBSetAlternateKeyboard :(UInt32)DevAddr
953: :(UInt32)RefNum
954: :(id)Id
955: :(pmCallback_func)Callback
956: {
957: return kPMUNotSupported;
958: }
959:
960:
961: // **********************************************************************************
962: // ADBinput
963: //
964: // The PGE has interrupted with ADB data. We package this up and send
965: // it to our ADB client, if there is one, either as the result to its previous
966: // read command, or as autopoll data.
967: //
968: // Removed since cuda_process_response() does the same thing
969: // **********************************************************************************
970:
971:
972: // **********************************************************************************
973: // registerForClockTicks
974: //
975: // The RTC driver is calling to tell us that it is prepared to receive clock
976: // ticks every second. The parameter block tells who to call when we get one.
977: //
978: // **********************************************************************************
979: - (void)registerForClockTicks :(pmCallback_func)TickHandler
980: :(id)caller
981: {
982: RTCclient = TickHandler;
983: RTCid = caller;
984: }
985:
986:
987: // **********************************************************************************
988: // setRealTimeClock
989: //
990: // The RTC driver is calling to set the real time clock. We translate this into
991: // a PMU command and enqueue it to our command queue.
992: //
993: // **********************************************************************************
994: - (PMUStatus)setRealTimeClock :(UInt8 *)newTime
995: :(UInt32)RefNum
996: :(id)Id
997: :(pmCallback_func)Callback
998: {
999: CudaMachMessage request;
1000: msg_return_t return_code;
1001:
1002: if (p) kprintf("ADBSetRealTimeClock\n");
1003: if ( newTime == NULL ) {
1004: return kPMUParameterError;
1005: }
1006:
1007: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
1008: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_REAL_TIME;
1009: request.msgBody.a_cmd.a_hcount = 2;
1010: request.msgBody.a_cmd.a_buffer[0] = newTime[0];
1011: request.msgBody.a_cmd.a_buffer[1] = newTime[1];
1012: request.msgBody.a_cmd.a_buffer[2] = newTime[2];
1013: request.msgBody.a_cmd.a_buffer[3] = newTime[3];
1014: request.msgBody.a_cmd.a_bcount = 4;
1015: request.msgBody.pmRefNum = RefNum;
1016: request.msgBody.pmId = Id;
1017: request.msgBody.pmCallback = Callback;
1018:
1019: request.msgHeader.msg_simple = TRUE;
1020: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
1021: request.msgHeader.msg_remote_port = port;
1022: request.msgHeader.msg_local_port = PORT_NULL;
1023: request.msgHeader.msg_size = sizeof(CudaMachMessage);
1024: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
1025:
1026: if ( return_code == SEND_SUCCESS ) {
1027: return kPMUNoError;
1028: }
1029: else {
1030: return kPMUIOError;
1031: }
1032: }
1033:
1034:
1035: // **********************************************************************************
1036: // getRealTimeClock
1037: //
1038: // The RTC driver is calling to read the real time clock. We translate this into
1039: // a PMU command and enqueue it to our command queue.
1040: // Called from PowerSurgeMB.m
1041: //
1042: // **********************************************************************************
1043: - (PMUStatus)getRealTimeClock :(UInt8 *)currentTime
1044: :(UInt32)RefNum
1045: :(id)Id
1046: :(pmCallback_func)Callback
1047: {
1048: CudaMachMessage request;
1049: msg_return_t return_code;
1050:
1051: if (p) kprintf("ADBGetRealTimeClock\n");
1052:
1053: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
1054: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_GET_REAL_TIME;
1055: request.msgBody.a_cmd.a_hcount = 2;
1056: request.msgBody.a_cmd.a_bcount = 0; //A.W. added 2/27. Is it enough? Response Specs:
1057: // Attention Byte
1058: // Response Type = PSEUDO
1059: // Response Flag
1060: // Command (was)
1061: // Data (Real Time Clock MSB)
1062: // Data
1063: // Data
1064: // Data (RTC LSB)
1065: // Idle Byte
1066:
1067: //The a_cmd.a_buffer is filled in by cuda_transmit_data()... but I need receive_data
1068: //Called from PowerSurgeMB.m
1069: /*** following commented out because it doesn't look right
1070: request.msgBody.a_cmd.a_buffer[0] = currentTime[0];
1071: request.msgBody.a_cmd.a_buffer[1] = currentTime[1];
1072: request.msgBody.a_cmd.a_buffer[2] = currentTime[2];
1073: request.msgBody.a_cmd.a_buffer[3] = currentTime[3];
1074: ******/
1075: bImmediate_buff_needed = TRUE;
1076: return_buff_pointer = currentTime;
1077: request.msgBody.a_reply.a_bsize = 8; //It's 8 in adb.h
1078:
1079: request.msgBody.pmRefNum = RefNum;
1080: request.msgBody.pmId = Id;
1081: request.msgBody.pmCallback = Callback;
1082:
1083: request.msgHeader.msg_simple = TRUE;
1084: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
1085: request.msgHeader.msg_remote_port = port;
1086: request.msgHeader.msg_local_port = PORT_NULL;
1087: request.msgHeader.msg_size = sizeof(CudaMachMessage);
1088: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
1089:
1090: if ( return_code == SEND_SUCCESS ) {
1091: return kPMUNoError;
1092: }
1093: else {
1094: return kPMUIOError;
1095: }
1096: }
1097:
1098:
1099:
1100: // **********************************************************************************
1101: // setPowerupTime
1102: // This sets the future time (in seconds) when Cuda will power-up the system again
1103: // If the power is already on then nothing happens. TRICKLE SENSE must be asserted.
1104: //
1105: // **********************************************************************************
1106: - (PMUStatus)setPowerupTime :(UInt8 *)newTime
1107: :(UInt32)RefNum
1108: :(id)Id
1109: :(pmCallback_func)Callback
1110: {
1111: CudaMachMessage request;
1112: msg_return_t return_code;
1113:
1114: if ( newTime == NULL ) {
1115: return kPMUParameterError;
1116: }
1117:
1118: if ( auto_power_on == 0) {
1119: return kPMUNoError;
1120: }
1121:
1122: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
1123: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_SET_POWER_UPTIME;
1124: request.msgBody.a_cmd.a_hcount = 2;
1125: request.msgBody.a_cmd.a_buffer[0] = newTime[0];
1126: request.msgBody.a_cmd.a_buffer[1] = newTime[1];
1127: request.msgBody.a_cmd.a_buffer[2] = newTime[2];
1128: request.msgBody.a_cmd.a_buffer[3] = newTime[3];
1129: request.msgBody.a_cmd.a_bcount = 4;
1130: request.msgBody.pmRefNum = RefNum;
1131: request.msgBody.pmId = Id;
1132: request.msgBody.pmCallback = Callback;
1133:
1134: request.msgHeader.msg_simple = TRUE;
1135: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
1136: request.msgHeader.msg_remote_port = port;
1137: request.msgHeader.msg_local_port = PORT_NULL;
1138: request.msgHeader.msg_size = sizeof(CudaMachMessage);
1139: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
1140:
1141: if ( return_code == SEND_SUCCESS ) {
1142: return kPMUNoError;
1143: }
1144: else {
1145: return kPMUIOError;
1146: }
1147: }
1148:
1149:
1150: // **********************************************************************************
1151: // CudaMisc
1152: //
1153: //
1154: // **********************************************************************************
1155: - (PMUStatus)CudaMisc :(UInt8 *)output
1156: :(UInt32)length
1157: :(UInt32)RefNum
1158: :(id)Id
1159: :(pmCallback_func)Callback
1160: {
1161: CudaMachMessage request;
1162: msg_return_t return_code;
1163: int i;
1164:
1165: for ( i = 0; i < length; i++ ) {
1166: //I should check for length < 8 but I trust callers in adb.m and PowerSurgeMB.m
1167: request.msgBody.a_cmd.a_header[i] = output[i];
1168: }
1169:
1170: request.msgBody.a_cmd.a_hcount = length;
1171: request.msgBody.a_cmd.a_bcount = 0;
1172: //Don't need to worry about how big the caller's buffer is because
1173: // cuda's adb_packet_t buffer is 8 bytes, and it's the caller who
1174: // must copy the bytes in its callback function
1175: request.msgBody.a_reply.a_bsize = 8; //It's 8 in adb.h for adb_packet_type
1176: request.msgBody.pmRefNum = RefNum;
1177: request.msgBody.pmId = Id;
1178: request.msgBody.pmCallback = Callback;
1179:
1180: request.msgHeader.msg_simple = TRUE;
1181: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
1182: request.msgHeader.msg_remote_port = port;
1183: request.msgHeader.msg_local_port = PORT_NULL;
1184: request.msgHeader.msg_size = sizeof(CudaMachMessage);
1185: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
1186:
1187: if ( return_code == SEND_SUCCESS ) {
1188: return kPMUNoError;
1189: }
1190: else {
1191: return kPMUIOError;
1192: }
1193:
1194: }
1195:
1196:
1197:
1198: //This function calls back the ADB client (such as Mouse driver).
1199: -(void) cuda_process_response
1200: {
1201:
1202: if ( cuda_transaction_state == CUDA_TS_SYNC_RESPONSE )
1203: {
1204: if ( cuda_request->pmCallback != NULL ) { // make the client callback
1205:
1206: if (p) kprintf("cuda_process_response: pmId = %08x, a_bcount = %08x, a_buffer = %08x\n",
1207: cuda_request->pmId, cuda_request->a_reply.a_bcount, cuda_request->a_reply.a_buffer);
1208:
1209:
1210: cuda_request->pmCallback ( cuda_request->pmId,
1211: cuda_request->pmRefNum,
1212: cuda_request->a_reply.a_bcount,
1213: cuda_request->a_reply.a_buffer );
1214: }
1215: else
1216: {
1217: //It's OK to not have a callback since some callers don't care
1218: // about synchronous completion
1219: //kprintf("WARNING: Cuda process_response() has no callback\n");
1220: }
1221: return_buff_pointer = NULL; //for getRealTimeClock only. a_buffer[]
1222: //above is ignored by PowerSurgeMB.m
1223: bImmediate_buff_needed = FALSE;
1224: //kprintf("cuda.m: cuda_process_response end \n");
1225: }
1226:
1227: else
1228: {
1229: if ( cuda_transaction_state == CUDA_TS_ASYNC_RESPONSE )
1230: {
1231: if ( ADBclient != NULL )
1232: { // call the client input handler
1233: cuda_freeze_counter++;
1234:
1235: if (p) {
1236: kprintf("cuda2.m::cuda_process_response ASYNC \n");
1237: kprintf("cuda2.m::ASYNC count is %d\n", cuda_current_response->a_bcount);
1238: kprintf("cuda2.m::ASYNC buffer 0 is %x\n", cuda_current_response->a_buffer[0]);
1239: kprintf("cuda2.m::ASYNC buffer 1 is %x\n", cuda_current_response->a_buffer[1]);
1240: kprintf("cuda2.m::ASYNC buffer 2 is %x\n", cuda_current_response->a_buffer[2]);
1241: kprintf("cuda2.m::ASYNC buffer 3 is %x\n", cuda_current_response->a_buffer[3]);
1242: kprintf("cuda2.m::ASYNC buffer 4 is %x\n", cuda_current_response->a_buffer[4]);
1243: kprintf("cuda2.m::ASYNC buffer 5 is %x\n", cuda_current_response->a_buffer[5]);
1244: kprintf("cuda2.m::ASYNC header 0 is %x\n", cuda_current_response->a_header[0]);
1245: kprintf("cuda2.m::ASYNC header 1 is %x\n", cuda_current_response->a_header[1]);
1246: kprintf("cuda2.m::ASYNC header 2 is %x\n", cuda_current_response->a_header[2]);
1247: }
1248:
1249: if (p) kprintf("cuda_process_response: ADBclient = %08x, ADBid = %08x\n", ADBclient, ADBid);
1250:
1251: #ifdef DEBUG
1252: cuda_glob_data1 = cuda_current_response->a_buffer[0];
1253: cuda_glob_data2 = cuda_current_response->a_buffer[1];
1254: if (cuda_glob_dbug_freeze == 1)
1255: {
1256: //kprintf("%x %x \n", cuda_glob_data1, cuda_glob_data2);
1257: }
1258: #endif
1259: //ADBClient is the global variable that clients registered with
1260: ADBclient(ADBid,
1261: 0,
1262: (cuda_current_response->a_header[2] >> 4) & 0xf,
1263: cuda_current_response->a_bcount,
1264: &cuda_current_response->a_buffer[0]);
1265: }
1266: }
1267: }
1268: }
1269:
1270:
1271: // **********************************************************************************
1272: // readNVRAM
1273: //
1274: // The NVRAM driver is calling to read part of the NVRAM. We translate this into
1275: // a PMU command and enqueue it to our command queue.
1276: //
1277: // **********************************************************************************
1278: - (PMUStatus) readNVRAM :(UInt32)Offset
1279: :(UInt32)Length
1280: :(UInt8 *)Buffer
1281: :(UInt32)RefNum
1282: :(id)Id
1283: :(pmCallback_func)Callback
1284: {
1285: return kPMUNotSupported;
1286: }
1287:
1288:
1289: // **********************************************************************************
1290: // writeNVRAM
1291: //
1292: // The NVRAM driver is calling to write part of the NVRAM. We translate this into
1293: // a PMU command and enqueue it to our command queue.
1294: //
1295: // **********************************************************************************
1296: - (PMUStatus) writeNVRAM:(UInt32)Offset
1297: :(UInt32)Length
1298: :(UInt8 *)Buffer
1299: :(UInt32)RefNum
1300: :(id)Id
1301: :(pmCallback_func)Callback
1302: {
1303: return kPMUNotSupported;
1304: }
1305:
1306:
1307: // **********************************************************************************
1308: // registerForPowerInterrupts
1309: //
1310: // Some driver is calling to say it is prepared to receive "unsolicited" power-system
1311: // interrups (e.g. battery low). The parameter block says who to call when we get one.
1312: //
1313: // **********************************************************************************
1314: - (void)registerForPowerInterrupts :(pmCallback_func)buttonHandler
1315: :(id)caller
1316: {
1317: PWRclient = buttonHandler;
1318: PWRid = caller;
1319: }
1320:
1321:
1322: // **********************************************************************************
1323: // sendMiscCommand
1324: //
1325: // Some driver is calling to send some miscellaneous command. We copy this into a
1326: // PMU command and enqueue it to our command queue.
1327: // A.W. Not completed yet for Cuda commands!!
1328: // **********************************************************************************
1329: - (PMUStatus)sendMiscCommand :(UInt32)Command
1330: :(UInt32)SLength
1331: :(UInt8 *)SBuffer
1332: :(UInt8 *)RBuffer
1333: :(UInt32)RefNum
1334: :(id)Id
1335: :(pmCallback_func)Callback
1336: {
1337: CudaMachMessage request;
1338: msg_return_t return_code;
1339: spl_t interruptState;
1340:
1341:
1342: if (Command == kPMUPmgrPWRoff)
1343: {
1344: //kprintf("\nCuda received power-down message\n");
1345: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_POWER_DOWN;
1346: auto_power_on = 0; //console operator really wants to shut off power
1347: }
1348: else if (Command == kPMUresetCPU)
1349: {
1350: request.msgBody.a_cmd.a_header[1] = ADB_PSEUDOCMD_RESTART_SYSTEM;
1351: //kprintf("\nCuda received reset message\n");
1352: }
1353: else
1354: {
1355: return kPMUParameterError;
1356: }
1357:
1358: //A.W. 3/17/98 I found out that reboots cannot happen from within
1359: // the mini-monitor because interrupts are turned off, which means
1360: // Cuda cannot get the subsequent command packet bytes to reboot
1361: // However, Simon says that next 2 lines are not necessary
1362: // WARNING The current file is checked out from trunk, don't check in
1363: interruptState = spltty();
1364: splx(interruptState);
1365: //request.msgBody.a_reply.a_bsize = 0; //we don't expect any replies for two commands above
1366: request.msgBody.a_reply.a_bsize = 8; //reset fails WARNING
1367: request.msgBody.a_cmd.a_header[0] = ADB_PACKET_PSEUDO;
1368: request.msgBody.a_cmd.a_hcount = 2;
1369: request.msgBody.a_cmd.a_bcount = 0;
1370: request.msgBody.pmRefNum = RefNum;
1371: request.msgBody.pmId = Id;
1372: request.msgBody.pmCallback = Callback;
1373:
1374: request.msgHeader.msg_simple = TRUE;
1375: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
1376: request.msgHeader.msg_remote_port = port;
1377: request.msgHeader.msg_local_port = PORT_NULL;
1378: request.msgHeader.msg_size = sizeof(CudaMachMessage);
1379: return_code = msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
1380:
1381: if ( return_code == SEND_SUCCESS ) {
1382: return kPMUNoError;
1383: }
1384: else {
1385: return kPMUIOError;
1386: }
1387: }
1388:
1389:
1390: // **********************************************************************************
1391: // StartCudaTransmission
1392: //
1393: // Called with PMU interrupts disabled. q8q
1394: // Transmission of the command byte is started. The transaction will be
1395: // completed by the Shift Register Interrupt Service Routine.
1396: // **********************************************************************************
1397: - (void)StartCudaTransmission:(CudaRequest *)plugInMessage;
1398: {
1399:
1400:
1401: if (( *VIA2_dataB & kCudaTransferRequestMask) == 0)
1402: {
1403: //Simon says there's a collision here
1404: cuda_interrupt_state = CUDA_STATE_ATTN_EXPECTED;
1405: cuda_transaction_state = CUDA_TS_ASYNC_RESPONSE;
1406: [self cuda_queue: plugInMessage];
1407: return;
1408: }
1409:
1410: //MAJOR CHANGE 8/6/98... 2 lines were at beginning, IDLE didn't make sense there
1411: if ( cuda_interrupt_state == CUDA_STATE_IDLE)
1412: {
1413: clientRequest = plugInMessage;
1414: firstChar = plugInMessage->a_cmd.a_header[0]; //Should be ADB_PACKET or PSEUDO
1415: charCountS1 = plugInMessage->a_cmd.a_hcount;
1416:
1417: dataPointer1 = &plugInMessage->a_cmd.a_header[0];
1418:
1419: cuda_request = plugInMessage;
1420: cuda_request->a_reply.a_bcount = 0;
1421:
1422:
1423: // cuda_set_data_direction_to_output(); //On cuda value is 0x10;
1424: *VIA1_auxillaryControl |= kCudaSystemSend; eieio();
1425:
1426: // ADBPollDisable is handled how?
1427: *VIA1_shift = firstChar; // give it the byte (this clears any pending SR interrupt)
1428:
1429: // Set up the transfer state info here.
1430:
1431: cuda_is_header_transfer = TRUE;
1432: cuda_transfer_count = 1;
1433:
1434:
1435:
1436: // *VIA2_dataB &= ~kCudaNegateTransferRequest; // yes, assert /REQ
1437: //I think I actually need to assert TIP here, not REQ.
1438: //eieio();
1439:
1440:
1441: // cuda_neg_byte_ack();
1442: *VIA2_dataB |= kCudaNegateByteAcknowledge; eieio();
1443:
1444: // cuda_assert_transfer_in_progress();
1445: *VIA2_dataB &= kCudaAssertTransferInProgress; eieio();
1446:
1447: // The next state is going to be a transmit state, if there is
1448: // no collision. This is a requested response but call it sync.
1449:
1450: cuda_interrupt_state = CUDA_STATE_TRANSMIT_EXPECTED;
1451:
1452: //INVESTIGATE: we get here even if there was a collision and the
1453: // collision packet was put onto the queue. In that case it means
1454: // the transaction was ASYNC?
1455: // This entire function is protected by splt so no interrupts should
1456: // be happening at all.
1457: cuda_transaction_state = CUDA_TS_SYNC_RESPONSE;
1458:
1459: return;
1460:
1461: }
1462: }
1463:
1464:
1465:
1466: //This ISR is copied from cuda.c. The nice thing about Cuda is that at any
1467: // time we can determine state of hardware by examining 3 bits.
1468: - (void)interruptOccurred
1469: {
1470:
1471: unsigned char interruptState;
1472:
1473: *VIA2_dataB |= kCudaNegateTransferRequest; // deassert /REQ
1474:
1475: // Get the relevant signal in determining the cause of the interrupt:
1476: // the shift direction, the transfer request line and the transfer
1477: // request line.
1478:
1479: //interruptState = cuda_get_interrupt_state();
1480: interruptState = (*VIA2_dataB & kCudaInterruptStateMask) | (*VIA1_auxillaryControl & kCudaDirectionMask) ;
1481:
1482: #ifdef DEBUG
1483: if ( cuda_glob_dbug_freeze == 1)
1484: {
1485: printf(" %d: ", interruptState);
1486: }
1487: #endif
1488:
1489: //no use DELAY(12); //12 microsecond delay in Ray Montagne's Cuda Manager for MacOS
1490:
1491: switch ( interruptState ) {
1492:
1493: case kCudaReceiveByte:
1494: if (p) kprintf("CUDA ** INTERRUPT ** RECEIVE *** \n");
1495: [self cuda_receive_data];
1496: break;
1497:
1498: case kCudaReceiveLastByte:
1499: if (p) kprintf("CUDA ** INTERRUPT ** RECEIVE LAST BYTE *** \n");
1500: [self cuda_receive_last_byte];
1501: break;
1502:
1503: case kCudaTransmitByte:
1504: if (p) kprintf("CUDA ** INTERRUPT ** TRANSMIT *** \n");
1505: [self cuda_transmit_data];
1506: break;
1507:
1508: case kCudaUnexpectedAttention:
1509: if (p) kprintf("CUDA ** INTERRUPT ** Unexpected Attention *** \n");
1510: [self cuda_unexpected_attention];
1511: break;
1512:
1513: case kCudaExpectedAttention:
1514: if (p) kprintf("CUDA ** INTERRUPT ** EXPECTED ATTENTION *** \n");
1515: [self cuda_expected_attention];
1516: break;
1517:
1518: case kCudaIdleState:
1519: if (p) kprintf("CUDA ** INTERRUPT ** IDLE *** \n");
1520: [self cuda_idle];
1521: break;
1522:
1523: case kCudaCollision:
1524: if (p) kprintf("Cuda *** INTERRUPT *** ADB collision\n");
1525: [self cuda_collision];
1526: break;
1527:
1528: // Unknown interrupt, clear it and leave
1529: default:
1530: if (p) kprintf("Cuda *** INTERRUPT *** ERROR\n");
1531: [self cuda_error];
1532: break;
1533: }
1534: }
1535:
1536:
1537: // ****************************************************************************
1538: // interruptOccurredAt
1539: // PGE has interrupted. Send the ReadInt command to find out why.
1540: // When the command byte is sent, the Shift Register will interrupt.
1541: // If we are mid-transaction when we find out about the interrupt,
1542: // set a flag and find out why later.
1543: //
1544: // A.W. Removed 2/11/98 because cuda only has 1 interrupt
1545: //
1546: // ****************************************************************************
1547:
1548:
1549:
1550: // ****************************************************************************
1551: // gotInterruptCause
1552: //
1553: // Called by the debug-mode PMU interrupt handler as the Callback function
1554: // after sending the kPMUreadInt command and receiving its response
1555: // A.W. only called by interruptOccurredAt above, so remove as well
1556: // ****************************************************************************
1557:
1558:
1559: // ****************************************************************************
1560: // EnableCudaInterrupt used to be EnablePMUInterrupt
1561: // ****************************************************************************
1562: - (void)EnableCudaInterrupt
1563: {
1564:
1565: // cuda_enable_interrupt(); // from cuda_hdw.h
1566: *VIA1_interruptEnable = kCudaInterruptEnable;
1567: eieio();
1568:
1569: }
1570:
1571:
1572: #ifdef OMIT
1573: // ****************************************************************************
1574: // timer_expired
1575: //
1576: // Our adb-read timer has expired, so we have to notify our i/o thread by
1577: // enqueuing a Timeout message to its interrupt port.
1578: // This was only called by ADBinput() in pmu.m, but cuda doesn't have ADBinput()
1579: // so this method is useless for now.
1580: // ****************************************************************************
1581: void timer_expired(port_t mach_port)
1582: {
1583: PMUmachMessage request;
1584:
1585: request.msgHeader.msg_simple = TRUE;
1586: request.msgHeader.msg_type = MSG_TYPE_NORMAL;
1587: request.msgHeader.msg_id = IO_TIMEOUT_MSG;
1588: request.msgHeader.msg_remote_port = mach_port;
1589: request.msgHeader.msg_local_port = PORT_NULL;
1590: request.msgHeader.msg_size = sizeof(msg_header_t);
1591: msg_send_from_kernel(&request.msgHeader, MSG_OPTION_NONE, 0);
1592:
1593: }
1594:
1595: #endif
1596:
1597:
1598:
1599: // ****************************************************************************
1600: // cuda_timer_autopoll
1601: //
1602: // Automatic scheduling of command to make sure auto-polling is always available
1603: // In worst case, I may want to reset Cuda here.
1604: // ****************************************************************************
1605: void cuda_timer_autopoll(port_t mach_port)
1606: {
1607: CudaMachMessage request;
1608: extern int kdp_flag;
1609: static int old_kdp_flag;
1610: static int cuda_TREQ_history;
1611: VIAAddress temp_register, dataB;
1612: unsigned char interruptState;
1613: //unsigned int newTime;
1614:
1615: #ifdef DEBUG
1616: //[ApplePMUId ADBPollEnable :0:0: NULL]; //stress this one
1617: //newTime = 0;
1618: //[ApplePMUId getRealTimeClock :(UInt8 *)&newTime : 0: 0: NULL];
1619:
1620: //*stat_aux_control &= kCudaSystemRecieve; eieio();
1621: ns_timeout((func)cuda_timer_autopoll,(void *)glob_port, kNS_TIMEOUT_AUTOPOLL,CALLOUT_PRI_SOFTINT0); // start timer again for another 4 seconds
1622: //Can only be set through debugging tool
1623: switch (cuda_glob_dbug_freeze )
1624: {
1625: case 0:
1626: old_kdp_flag = kdp_flag;
1627: break;
1628: case 1:
1629: kdp_flag |= 0x02;
1630: temp_register = stat_aux_control + 0x1600; //auxillary
1631: dataB = stat_aux_control ;
1632: interruptState = (*dataB & kCudaInterruptStateMask) | (*temp_register & kCudaDirectionMask) ;
1633: printf("CUDA: 4-second periodic, interruptState is %x\n", interruptState);
1634: kprintf("CUDA: 4-second periodic, interruptState is %x\n", interruptState);
1635:
1636: #ifdef OMIT_CUDA_DBUG
1637: //kprintf("istate = %x ", interruptState);
1638: //temp_register = stat_aux_control + 0x1A00;
1639: //kprintf("ir flag = %x ", *temp_register);
1640: //eieio();
1641: temp_register = stat_aux_control + 0x1600; //auxillary
1642: kprintf("aux= %x ", *temp_register);
1643: eieio();
1644: temp_register = stat_aux_control;//dataB
1645: kprintf("dataB= %x ", *temp_register);
1646: eieio();
1647: temp_register = stat_aux_control + 0x1400; // SHIFT
1648: kprintf("shift= %x ", *temp_register);
1649: eieio();
1650: temp_register = stat_aux_control + 0x1c00; // Interrupt Enable
1651: kprintf("IE= %x \n", *temp_register);
1652: eieio();
1653: #endif
1654:
1655: //put printf here so it doesn't interfere with other debugging sessions
1656: break;
1657: case 2:
1658: //May disabling Cuda debugging kprintf, but preserve "4" for debugging
1659: kdp_flag = old_kdp_flag;
1660: break;
1661: case 3:
1662: cuda_glob_dbug_freeze = 1;
1663: cuda_interrupt_state = CUDA_STATE_IDLE; //Force state change
1664: [ApplePMUId EnableCudaInterrupt];
1665: [ApplePMUId enableAllInterrupts];
1666: [ApplePMUId ADBReset :0:0: NULL];
1667: //mouse will be in low-res mode
1668: break;
1669: case 4:
1670: cuda_glob_dbug_freeze = 1;
1671: [ApplePMUId ADBPollEnable :0:0: NULL];
1672: //No side effects seen for now, but gets queued when cuda freezes
1673: break;
1674: case 5:
1675: cuda_glob_dbug_freeze = 1;
1676: [ApplePMUId ADBFlush :2:0:0: NULL]; //keyboard is 2
1677: //No side effects seen for now, but gets queued when cuda freezes
1678: break;
1679: case 6:
1680: cuda_glob_dbug_freeze = 1;
1681: //change data direction to input
1682: temp_register = stat_aux_control + 0x1600;
1683: *temp_register &= kCudaSystemRecieve; eieio();
1684: break;
1685: case 7:
1686: cuda_glob_dbug_freeze = 1;
1687: temp_register = stat_aux_control + 0x1400; // SHIFT
1688: interruptState = *temp_register; eieio(); //dummy read
1689: //Simon suggests toggling the byteack too
1690: temp_register = stat_aux_control;//dataB
1691: *temp_register ^= kCudaByteAcknowledgeMask; eieio();
1692: break;
1693: case 8:
1694: cuda_interrupt_state = CUDA_STATE_IDLE; //Force state change
1695: temp_register = stat_aux_control;//dataB
1696: *temp_register &= kCudaAssertTransferInProgress;
1697: *temp_register |= kCudaNegateByteAcknowledge ;
1698: eieio();
1699: cuda_glob_dbug_freeze = 1;
1700: break;
1701: case 9:
1702: cuda_glob_dbug_freeze = 1;
1703: cuda_current_response->a_buffer[0] = 0;
1704: cuda_current_response->a_buffer[1] = 0xff;
1705: cuda_debug_client(0, 0, 2, 2, &cuda_current_response->a_buffer[0]);
1706: break;
1707: case 10:
1708: cuda_glob_dbug_freeze = 1;
1709: call_kdp();
1710: break;
1711: case 11:
1712: cuda_glob_dbug_freeze = 1;
1713: cuda_interrupt_state = CUDA_STATE_IDLE; //Force state change
1714: [ApplePMUId EnableCudaInterrupt];
1715: [ApplePMUId enableAllInterrupts];
1716: [ApplePMUId ADBPollEnable :0 :0: NULL];
1717: break;
1718: case 12:
1719: cuda_glob_dbug_freeze = 1;
1720: temp_register = stat_aux_control + 0x1400; // SHIFT
1721: interruptState = *temp_register; eieio(); //dummy read
1722: break;
1723: case 20: //Negate ByteAcknowledge
1724: temp_register = stat_aux_control;//dataB
1725: *temp_register |= kCudaNegateByteAcknowledge; eieio();
1726: eieio();
1727: cuda_glob_dbug_freeze = 1;
1728: break;
1729: case 21:
1730: //Set ByteAcknowledge
1731: temp_register = stat_aux_control;//dataB
1732: *temp_register &= kCudaAssertByteAcknowledge; eieio();
1733: eieio();
1734: cuda_glob_dbug_freeze = 1;
1735: break;
1736: case 22:
1737: //Set TIP
1738: temp_register = stat_aux_control; //dataB
1739: *temp_register &= kCudaTransferInProgressMask;
1740: eieio();
1741: cuda_glob_dbug_freeze = 1;
1742: break;
1743: case 23:
1744: //Negate TIP
1745: temp_register = stat_aux_control; //dataB
1746: *temp_register |= kCudaNegateTransferInProgress;
1747: eieio();
1748: cuda_glob_dbug_freeze = 1;
1749: break;
1750: case 24:
1751: //data direction to input
1752: temp_register = stat_aux_control + 0x1600; //auxillary
1753: *temp_register &= kCudaSystemRecieve;
1754: eieio();
1755: cuda_glob_dbug_freeze = 1;
1756: break;
1757: case 25:
1758: //data direction to output
1759: temp_register = stat_aux_control + 0x1600; //auxillary
1760: *temp_register |= kCudaSystemSend;
1761: eieio();
1762: cuda_glob_dbug_freeze = 1;
1763: break;
1764: case 30: //general reset
1765: {
1766: temp_register = stat_aux_control + 0x0400; //dataDirectionB
1767: *temp_register |= (kCudaByteAcknowledgeMask | kCudaTransferInProgressMask);
1768: *temp_register &= ~kCudaTransferRequestMask;
1769:
1770: temp_register = stat_aux_control + 0x1600; //auxillary
1771: *temp_register = ( *temp_register | kCudaTransferMode) & kCudaSystemRecieve;
1772:
1773: // Clear any posible cuda interupt.
1774: temp_register = stat_aux_control + 0x1400; //shift
1775: if ( *temp_register );
1776: eieio();
1777:
1778: // Initialize the internal data.
1779:
1780: cuda_interrupt_state = CUDA_STATE_IDLE;
1781: cuda_transaction_state = CUDA_TS_NO_REQUEST;
1782: cuda_is_header_transfer = FALSE;
1783: cuda_is_packet_type = FALSE;
1784: cuda_transfer_count = 0;
1785: cuda_current_response = NULL;
1786:
1787: // Terminate transaction and set idle state
1788: // cuda_neg_tip_and_byteack();
1789: temp_register = stat_aux_control; //dataB
1790: *temp_register |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress;
1791: eieio();
1792:
1793: // we want to delay 4 mS for ADB reset to complete
1794:
1795: delay(4000);
1796:
1797: // Clear pending interrupt if any...
1798: //(void)cuda_read_data();
1799: temp_register = stat_aux_control + 0x1400; //Shift
1800: if ( *temp_register ); eieio();
1801:
1802: // Issue a Sync Transaction, ByteAck asserted while TIP is negated.
1803: // cuda_assert_byte_ack();
1804: temp_register = stat_aux_control; //dataB
1805: *temp_register &= kCudaAssertByteAcknowledge; eieio();
1806:
1807:
1808: // Wait for the Sync acknowledgement, cuda to assert TREQ
1809: // cuda_wait_for_transfer_request_assert();
1810: while ( (*temp_register & kCudaTransferRequestMask) != 0 )
1811: {
1812: eieio();
1813: }
1814: eieio();
1815:
1816: // Wait for the Sync acknowledgement interrupt.
1817: // cuda_wait_for_interrupt();
1818: temp_register = stat_aux_control + 0x1A00; //VIA interrupt flag
1819: while ( (*temp_register & kCudaInterruptMask) == 0 )
1820: {
1821: eieio();
1822: }
1823: eieio();
1824:
1825:
1826: // Clear pending interrupt
1827: //(void)cuda_read_data();
1828: temp_register = stat_aux_control + 0x1400; //shift
1829: if ( *temp_register );
1830: eieio();
1831:
1832: // Terminate the sync cycle by Negating ByteAck
1833: // cuda_neg_byte_ack();
1834: temp_register = stat_aux_control; //dataB
1835: *temp_register |= kCudaNegateByteAcknowledge; eieio();
1836:
1837: // Wait for the Sync termination acknowledgement, cuda negates TREQ.
1838: // cuda_wait_for_transfer_request_neg();
1839: while ( (*temp_register & kCudaTransferRequestMask) == 0 )
1840: {
1841: eieio();
1842: }
1843: eieio();
1844:
1845:
1846: // Wait for the Sync termination acknowledgement interrupt.
1847: // cuda_wait_for_interrupt();
1848: temp_register = stat_aux_control + 0x1A00; //VIA interrupt flag
1849: while ( (*temp_register & kCudaInterruptMask) == 0 )
1850: {
1851: eieio();
1852: }
1853: eieio();
1854:
1855:
1856: // Terminate transaction and set idle state, TIP negate and ByteAck negate.
1857: // cuda_neg_transfer_in_progress();
1858: temp_register = stat_aux_control; //dataB
1859: *temp_register |= kCudaNegateTransferInProgress; eieio();
1860:
1861: // Clear pending interrupt, if there is one...
1862: //(void)cuda_read_data();
1863: temp_register = stat_aux_control + 0x1400; //shift
1864: if ( *temp_register );
1865: eieio();
1866:
1867:
1868:
1869:
1870: debugging = FALSE;
1871: adb_reading = FALSE;
1872:
1873: //CUDA_REPLACE
1874: // A.W. This call seems to have no counterpart in Cuda
1875: // Pending interrupts are cleared with cuda_read_data()
1876: temp_register = stat_aux_control + 0x1A00; //VIA interrupt flag
1877: *temp_register = kCudaInterruptDisable;eieio(); // turn off any pending interrupt
1878:
1879: temp_register = stat_aux_control + 0x1400; //shift
1880: if ( *temp_register );
1881: eieio();
1882:
1883: [ApplePMUId EnableCudaInterrupt];
1884:
1885: [ApplePMUId enableAllInterrupts];
1886:
1887: }
1888: break;
1889:
1890: case 40:
1891: //try AIX stuff
1892: temp_register = stat_aux_control; //dataB
1893: *temp_register |= kCudaNegateTransferInProgress | kCudaNegateByteAcknowledge;
1894: eieio();
1895: [ApplePMUId EnableCudaInterrupt];
1896: //[ApplePMUId enableAllInterrupts];
1897: [ApplePMUId ADBPollEnable :0 :0: NULL];
1898: cuda_glob_dbug_freeze = 1;
1899: break;
1900:
1901: default:
1902: }
1903:
1904: // Sept 11, 1998 Add new code to fix ADB hang problem
1905: if ( cuda_freeze_counter == cuda_freeze_prevcount)
1906: //Even if user never touches keyboard, this test is FALSE first time
1907: {
1908: //if here then that means either user has not moved ADB device for
1909: // a long time or the system is hung
1910: //kprintf("HH: No ADB movement so far\n");
1911: //Now check TREQ (if in middle of transaction)
1912: temp_register = stat_aux_control; //dataB
1913: if ((*temp_register & kCudaTransferRequestMask) == 0 )
1914: {
1915: //kprintf("HH: TREQ is 0 (asserted), incrementing flag now\n");
1916: cuda_TREQ_history++;
1917: }
1918: else
1919: {
1920: cuda_TREQ_history = 0;
1921: }
1922: if ( cuda_TREQ_history == 2) // 2 cycles already
1923: {
1924: //Executing this code at any time has proven to be safe and does
1925: // not affect the operation of the high-resolution pointing devices
1926: //kprintf("HH: In recovery code now \n");
1927: printf("\nCuda: recover from transaction hang\n");
1928: temp_register = stat_aux_control; //dataB
1929: *temp_register |= kCudaNegateTransferInProgress | kCudaNegateByteAcknowledge;
1930: eieio();
1931: [ApplePMUId EnableCudaInterrupt];
1932: [ApplePMUId ADBPollEnable :0 :0: NULL];
1933: cuda_TREQ_history = 0;
1934: }
1935: }
1936: else
1937: {
1938: cuda_TREQ_history = 0;
1939: }
1940:
1941: cuda_freeze_prevcount = cuda_freeze_counter ; //Get ready for next 4-sec timer
1942: #endif //DEBUG
1943:
1944:
1945: }
1946:
1947:
1948: // Cuda functions needed to help -interruptOccured:
1949:
1950:
1951:
1952:
1953: //
1954: // TransmitCudaData
1955: // Executes at hardware interrupt level.
1956: //
1957:
1958: -(void) cuda_transmit_data
1959: {
1960: volatile unsigned char valcuda; //dummy, unused
1961: // Clear the pending interrupt by reading the shift register.
1962:
1963:
1964: if ( cuda_is_header_transfer ) {
1965: // There are more header bytes, write one out.
1966: // Initially cuda_transfer_count is 1, so for most Cuda commands
1967: // that means the ADB command itself, which contains Talk, Listen, etc.
1968: // cuda_write_data(cuda_request->a_cmd.a_header[cuda_transfer_count++]);
1969: *VIA1_shift = cuda_request->a_cmd.a_header[cuda_transfer_count++];
1970:
1971: // Toggle the handshake line.
1972: // a_hcount is number of bytes in command packet
1973: if ( cuda_transfer_count >= cuda_request->a_cmd.a_hcount ) {
1974: cuda_is_header_transfer = FALSE;
1975: cuda_transfer_count = 0;
1976: }
1977:
1978: // cuda_toggle_byte_ack();
1979: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio();
1980:
1981:
1982: } else if ( cuda_transfer_count < cuda_request->a_cmd.a_bcount ) {
1983: //WARNING... find out why a_bcount above is examined during Cuda Transmit?
1984:
1985:
1986: // There are more command bytes, write one out and update the pointer
1987: // cuda_write_data(cuda_request->a_cmd.a_buffer[cuda_transfer_count++]);
1988: *VIA1_shift = cuda_request->a_cmd.a_buffer[cuda_transfer_count++];
1989:
1990: // Toggle the handshake line.
1991: // cuda_toggle_byte_ack();
1992: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio();
1993: } else {
1994: //(void)cuda_read_data();
1995: valcuda = *VIA1_shift; eieio();
1996: // There is no more command bytes, terminate the send transaction.
1997: // Cuda should send a expected attention interrupt soon.
1998:
1999: // cuda_neg_tip_and_byteack();
2000: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress;
2001: eieio();
2002:
2003: // The next interrupt should be a expected attention interrupt.
2004:
2005: cuda_interrupt_state = CUDA_STATE_ATTN_EXPECTED;
2006:
2007: /**** moved to cuda_idle() portion
2008: // call back the ADB layer if entire transmission packet is complete.
2009: if ( clientRequest->pmCallback != NULL ) {
2010: clientRequest->pmCallback(clientRequest->pmId, clientRequest->pmRefNum, 0, NULL);
2011:
2012: }
2013: *****/
2014:
2015: }
2016: }
2017:
2018: //
2019: // cuda_expected_attention
2020: // Executes at hardware interrupt level.
2021: //
2022:
2023: - (void)cuda_expected_attention
2024: {
2025: volatile unsigned char valcuda; //dummy, unused
2026:
2027:
2028: // Clear the pending interrupt by reading the shift register.
2029: // This first byte is the "attention" byte and contains no
2030: // useful data, so ignore it. Next byte should be response
2031: // packet TYPE.
2032: //(void)cuda_read_data();
2033: valcuda = *VIA1_shift; eieio();
2034:
2035: // Allow the VIA to settle directions.. else the possibility of
2036: // data corruption.
2037: tick_delay(cuda_state_transition_delay_ticks);
2038:
2039: if ( cuda_transaction_state == CUDA_TS_SYNC_RESPONSE) {
2040: cuda_current_response = (adb_packet_t*)&cuda_request->a_reply;
2041: } else {
2042: cuda_unsolicited.a_hcount = 0;
2043: cuda_unsolicited.a_bcount = 0;
2044: cuda_unsolicited.a_bsize = sizeof(cuda_unsolicited.a_buffer);
2045: cuda_current_response = &cuda_unsolicited;
2046: }
2047:
2048: cuda_is_header_transfer = TRUE;
2049: cuda_is_packet_type = TRUE;
2050: cuda_transfer_count = 0;
2051:
2052: // Set the shift register direction to input.
2053: // cuda_set_data_direction_to_input();
2054: *VIA1_auxillaryControl &= kCudaSystemRecieve; eieio();
2055:
2056: // Start the response packet transaction.
2057: // cuda_assert_transfer_in_progress();
2058: *VIA2_dataB &= kCudaAssertTransferInProgress; eieio();
2059:
2060: // The next interrupt should be a receive data interrupt.
2061: cuda_interrupt_state = CUDA_STATE_RECEIVE_EXPECTED;
2062: }
2063:
2064: //
2065: // cuda_unexpected_attention
2066: // Executes at hardware interrupt level.
2067: //
2068:
2069: -(void) cuda_unexpected_attention
2070: {
2071: volatile unsigned char valcuda; //dummy, unused
2072:
2073: // Clear the pending interrupt by reading the shift register.
2074: // This first byte is the "attention" byte and contains no
2075: // useful data, so ignore it. Next byte should be response
2076: // packet TYPE.
2077: //(void)cuda_read_data();
2078: valcuda = *VIA1_shift; eieio();
2079:
2080: // Get ready for a unsolicited response.
2081:
2082: cuda_unsolicited.a_hcount = 0;
2083: cuda_unsolicited.a_bcount = 0;
2084: cuda_unsolicited.a_bsize = sizeof(cuda_unsolicited.a_buffer);
2085: //Try to fix jumping bug
2086: bzero( cuda_unsolicited.a_buffer, cuda_unsolicited.a_bsize);
2087:
2088:
2089: cuda_current_response = &cuda_unsolicited;
2090:
2091: cuda_is_header_transfer = TRUE;
2092: cuda_is_packet_type = TRUE;
2093: cuda_transfer_count = 0;
2094:
2095:
2096: // Start the response packet transaction, Transaction In Progress
2097: // cuda_assert_transfer_in_progress();
2098: *VIA2_dataB &= kCudaAssertTransferInProgress; eieio();
2099:
2100: // The next interrupt should be a receive data interrupt and the next
2101: // response should be an async response.
2102:
2103: cuda_interrupt_state = CUDA_STATE_RECEIVE_EXPECTED;
2104:
2105: cuda_transaction_state = CUDA_TS_ASYNC_RESPONSE;
2106: }
2107:
2108: //
2109: // cuda_receive_data
2110: // Executes at hardware interrupt level.
2111: //
2112:
2113: -(void) cuda_receive_data
2114: {
2115:
2116: // cuda_is_packet_type is set to TRUE when cuda_(+un)expected_attention() is called
2117: // The first part will be called just to read the packet type
2118: if ( cuda_is_packet_type ) {
2119: unsigned char packetType;
2120:
2121: //packetType = cuda_read_data();
2122: packetType = *VIA1_shift; eieio();
2123: cuda_current_response->a_header[cuda_transfer_count++] = packetType;
2124:
2125: if ( packetType == ADB_PACKET_ERROR) {
2126: cuda_current_response->a_hcount = 4;
2127: } else {
2128: cuda_current_response->a_hcount = 3;
2129: }
2130:
2131: cuda_is_packet_type = FALSE;
2132:
2133: // cuda_toggle_byte_ack();
2134: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio();
2135:
2136: } else if ( cuda_is_header_transfer ) { //set TRUE by cuda_(+un)expected_attention
2137:
2138: //This should be the Response Packet ADB Status byte (2nd byte)
2139: cuda_current_response->a_header[cuda_transfer_count++] =
2140: *VIA1_shift; eieio();
2141: // cuda_read_data();
2142:
2143: if (cuda_transfer_count >= cuda_current_response->a_hcount) {
2144: cuda_is_header_transfer = FALSE;
2145: cuda_transfer_count = 0;
2146: }
2147:
2148: // cuda_toggle_byte_ack();
2149: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio();
2150:
2151: } else if ( cuda_transfer_count < cuda_current_response->a_bsize ) {
2152: // Still room for more bytes. Get the byte and tell Cuda to continue.
2153: // Toggle the handshake line, ByteAck, to acknowledge receive.
2154:
2155: // a_buffer[] is the actual buffer going back to ADB.M Callback
2156: cuda_current_response->a_buffer[cuda_transfer_count] =
2157: *VIA1_shift; eieio();
2158: // cuda_read_data();
2159:
2160: if (bImmediate_buff_needed) //just for getRealTimeClock
2161: {
2162: if ( return_buff_pointer)
2163: {
2164: *(return_buff_pointer + cuda_transfer_count) =
2165: cuda_current_response->a_buffer[cuda_transfer_count];
2166:
2167: //kprintf("%x ", cuda_current_response->a_buffer[cuda_transfer_count]);
2168: }
2169: }
2170:
2171: cuda_transfer_count++;
2172:
2173: // cuda_toggle_byte_ack();
2174: *VIA2_dataB ^= kCudaByteAcknowledgeMask; eieio();
2175: } else {
2176: // Cuda is still sending data but the buffer is full.
2177: // Normally should not get here. The only exceptions are open ended
2178: // request such as PRAM read... In any event time to exit.
2179:
2180: // a_bcount is the actual count going back to ADB.M Callback
2181: cuda_current_response->a_bcount = cuda_transfer_count;
2182:
2183: // cuda_read_data();
2184: if (*VIA1_shift); eieio();
2185:
2186: //So far no hits here on kernel bootup 3/20/98
2187:
2188: [self cuda_process_response]; //Rewritten by D.S.
2189: // cuda_neg_tip_and_byteack();
2190: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress;
2191: eieio();
2192: }
2193: }
2194:
2195: //
2196: // cuda_receive_last_byte
2197: // Executes at hardware interrupt level.
2198: //
2199:
2200: -(void) cuda_receive_last_byte
2201: {
2202: volatile unsigned char valcuda; //dummy, unused
2203:
2204:
2205: if ( cuda_is_header_transfer ) {
2206: cuda_current_response->a_header[cuda_transfer_count++] =
2207: *VIA1_shift; eieio();
2208: // cuda_read_data();
2209:
2210: cuda_transfer_count = 0;
2211: } else if ( cuda_transfer_count < cuda_current_response->a_bsize ) {
2212:
2213: cuda_current_response->a_buffer[cuda_transfer_count] =
2214: *VIA1_shift; eieio();
2215:
2216: //Added 1/13/98 A.W.
2217: if (bImmediate_buff_needed) //just for getRealTimeClock
2218: {
2219: if ( return_buff_pointer)
2220: {
2221: *(return_buff_pointer + cuda_transfer_count) =
2222: cuda_current_response->a_buffer[cuda_transfer_count];
2223: }
2224: }
2225: cuda_transfer_count++;
2226:
2227: // cuda_read_data();
2228: } else {
2229: /* Overrun -- ignore data */
2230: //(void) cuda_read_data();
2231: valcuda = *VIA1_shift; eieio();
2232: }
2233:
2234: cuda_current_response->a_bcount = cuda_transfer_count;
2235:
2236: //SD: acknowledge before response so polled mode can work from inside the adb handler
2237:
2238: // cuda_neg_tip_and_byteack();
2239: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress;
2240: eieio();
2241: if (p) kprintf("cuda.m: process response in LAST BYTE, count is %d\n", cuda_transfer_count);
2242: [self cuda_process_response]; //Rewritten by D.S.
2243: }
2244:
2245: /* 3/19/98 A.W. added to fix collision problems */
2246: - (void) cuda_queue:(CudaRequest *)cuda_req
2247: {
2248: CudaMachMessage * toQueue;
2249: IOReturn result;
2250:
2251: que_cuda_count++; //for debugging only
2252: //For collisions, queue up the incoming request from Rhapsody system
2253: // and handle Cuda's urgent request first.
2254: toQueue = (CudaMachMessage*)kalloc(sizeof(CudaMachMessage));
2255: toQueue->msgHeader.msg_size = sizeof(CudaMachMessage);
2256: toQueue->msgHeader.msg_local_port = [self interruptPort];
2257: bcopy (cuda_req, &toQueue->msgBody, sizeof(CudaRequest)); // copy it
2258: toQueue->msgBody.prev = queueTail;
2259: toQueue->msgBody.next = NULL;
2260: if ( queueTail != NULL ) {
2261: queueTail->msgBody.next = toQueue;
2262: }
2263: else
2264: {
2265: queueHead = toQueue;
2266: }
2267: queueTail = toQueue;
2268: }
2269:
2270: //
2271: // cuda_collision
2272: // Executes at hardware interrupt level.
2273: //
2274:
2275: -(void) cuda_collision
2276: {
2277: volatile unsigned char valcuda; //dummy, unused
2278:
2279:
2280: // Clear the pending interrupt by reading the shift register.
2281: //(void)cuda_read_data();
2282: valcuda = *VIA1_shift; eieio();
2283:
2284: // Negate TIP to abort the send. Cuda should send a second attention
2285: // interrupt to acknowledge the abort cycle.
2286: // cuda_neg_transfer_in_progress();
2287: *VIA2_dataB |= kCudaNegateTransferInProgress; eieio();
2288:
2289: // The next interrupt should be an expected attention and the next
2290: // response packet should be an async response.
2291:
2292: cuda_interrupt_state = CUDA_STATE_ATTN_EXPECTED;
2293: cuda_transaction_state = CUDA_TS_ASYNC_RESPONSE;
2294:
2295: /* queue the request */
2296: cuda_collided = cuda_request; //WARNING... unused now, don't use this variable
2297: #ifdef OMIT
2298: cuda_request = NULL;
2299: #endif
2300: cuda_is_header_transfer = FALSE;
2301: cuda_transfer_count = 0;
2302:
2303: [self cuda_queue: cuda_request];
2304: }
2305:
2306: //
2307: // cuda_idle
2308: // Executes at hardware interrupt level.
2309: // A.W. WARNING... what if this state is reached without a client callback available?
2310: // what happens with unsolicited cuda events? Should they go to the ADBRegisterAutopoll
2311: // function?
2312: //
2313:
2314: -(void) cuda_idle
2315: {
2316: volatile unsigned char valcuda; //dummy, unused
2317:
2318: // Clear the pending interrupt by reading the shift register.
2319: //(void)cuda_read_data();
2320: valcuda = *VIA1_shift; eieio();
2321:
2322: // Set to the idle state.
2323: cuda_interrupt_state = CUDA_STATE_IDLE;
2324:
2325: // See if there are any pending requests. There may be a pending request
2326: // if a collision has occured. If so do the resend.
2327:
2328: //if (adb_polling)
2329: //return; /* Prevent recursion */
2330:
2331: //if collision then that has already been queued above, so all we do
2332: // now is check for it.
2333:
2334: [self CheckRequestQueue];
2335:
2336: }
2337:
2338:
2339:
2340: -(void) cuda_error
2341: {
2342: unsigned char valcuda;
2343:
2344: kprintf("\nCUDA:{Error %d}\n", cuda_transaction_state);
2345:
2346: switch (cuda_transaction_state) {
2347: case CUDA_STATE_IDLE:
2348: // cuda_neg_tip_and_byteack();
2349: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress;
2350: eieio();
2351: break;
2352:
2353: case CUDA_STATE_TRANSMIT_EXPECTED:
2354: if (cuda_is_header_transfer && cuda_transfer_count <= 1) {
2355: tick_delay(cuda_state_transition_delay_ticks);
2356: // cuda_neg_transfer_in_progress();
2357: *VIA2_dataB |= kCudaNegateTransferInProgress; eieio();
2358: // cuda_set_data_direction_to_input();
2359: *VIA1_auxillaryControl &= kCudaSystemRecieve; eieio();
2360: //panic ("CUDA - TODO FORCE COMMAND BACK UP!\n");
2361: } else {
2362: cuda_transaction_state = CUDA_STATE_ATTN_EXPECTED;
2363: // cuda_neg_tip_and_byteack();
2364: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress;
2365: eieio();
2366: }
2367: break;
2368:
2369: case CUDA_STATE_ATTN_EXPECTED:
2370: // cuda_assert_transfer_in_progress();
2371: *VIA2_dataB &= kCudaAssertTransferInProgress; eieio();
2372:
2373: tick_delay(cuda_state_transition_delay_ticks);
2374: // cuda_set_data_direction_to_input();
2375: *VIA1_auxillaryControl &= kCudaSystemRecieve; eieio();
2376: // cuda_neg_transfer_in_progress();
2377: *VIA2_dataB |= kCudaNegateTransferInProgress; eieio();
2378: //panic("CUDA - TODO CHECK FOR TRANSACTION TYPE AND ERROR");
2379: break;
2380:
2381: case CUDA_STATE_RECEIVE_EXPECTED:
2382: // cuda_neg_tip_and_byteack();
2383: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress;
2384: eieio();
2385: //panic("Cuda - todo check for transaction type and error");
2386: break;
2387:
2388: default:
2389: // cuda_set_data_direction_to_input();
2390: *VIA1_auxillaryControl &= kCudaSystemRecieve; eieio();
2391: valcuda = *VIA1_shift; eieio(); //Ray Montagne .a indicates this may be useful
2392: // cuda_neg_tip_and_byteack();
2393: *VIA2_dataB |= kCudaNegateByteAcknowledge | kCudaNegateTransferInProgress;
2394: eieio();
2395: break;
2396: }
2397: }
2398:
2399: -(void) poll_device
2400: {
2401: CudaRequest *next;
2402: int interruptflag = *VIA1_interruptFlag & kCudaInterruptMask;
2403: eieio();
2404:
2405: if(interruptflag) {
2406: [self interruptOccurred];
2407: if( cuda_interrupt_state == CUDA_STATE_IDLE) {
2408: [self CheckRequestQueue];
2409: }
2410: }
2411: }
2412:
2413:
2414: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.