/[pearpc]/src/io/cuda/cuda.cc
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /src/io/cuda/cuda.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (hide annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 8 months ago) by dpavlin
File size: 26006 byte(s)
import upstream CVS
1 dpavlin 1 /*
2     * PearPC
3     * cuda.cc
4     *
5     * Copyright (C) 2003-2004 Sebastian Biallas (sb@biallas.net)
6     * Copyright (C) 2004 Stefan Weyergraf
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License version 2 as
10     * published by the Free Software Foundation.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20     *
21     * From Linux 2.6.4:
22     * The VIA (versatile interface adapter) interfaces to the CUDA,
23     * a 6805 microprocessor core which controls the ADB (Apple Desktop
24     * Bus) which connects to the keyboard and mouse. The CUDA also
25     * controls system power and the RTC (real time clock) chip.
26     *
27     * See also:
28     * http://www.howell1964.freeserve.co.uk/parts/6522_VIA.htm
29     *
30     * References:
31     * [1] http://bbc.nvg.org/doc/datasheets/R6522_r9.zip
32     */
33    
34     #include <cstdlib>
35     #include <cstring>
36     #include <cstdarg>
37     #include <ctime>
38    
39     #include "cpu/cpu.h"
40     #include "tools/snprintf.h"
41     #include "debug/tracers.h"
42     #include "io/pic/pic.h"
43     #include "system/keyboard.h"
44     #include "system/mouse.h"
45     #include "system/sys.h"
46     #include "system/sysclk.h"
47     #include "system/systhread.h"
48    
49     #include "cuda.h"
50    
51     //#define IO_CUDA_TRACE2(str...) ht_printf(str)
52     #define IO_CUDA_TRACE2(str...)
53    
54     //#define IO_CUDA_TRACE3(str...) ht_printf(str)
55     #define IO_CUDA_TRACE3(str...)
56    
57     #define RS (0x200)
58     #define B 0 /* B-side data */
59     #define A RS /* A-side data */
60     #define DIRB (2*RS) /* B-side direction (1=output) */
61     #define DIRA (3*RS) /* A-side direction (1=output) */
62     #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */
63     #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */
64     #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */
65     #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */
66     #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */
67     #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */
68     #define SR (10*RS) /* Shift register */
69     #define ACR (11*RS) /* Auxiliary control register */
70     #define PCR (12*RS) /* Peripheral control register */
71     #define IFR (13*RS) /* Interrupt flag register */
72     #define IER (14*RS) /* Interrupt enable register */
73     #define ANH (15*RS) /* A-side data, no handshake */
74    
75     /* Bits in B data register: all active low */
76     #define TREQ 0x08 /* Transfer request (input) */
77     #define TACK 0x10 /* Transfer acknowledge (output) */
78     #define TIP 0x20 /* Transfer in progress (output) */
79    
80     /* Bits in ACR */
81     #define SR_CTRL 0x1c /* Shift register control bits */
82     #define SR_EXT 0x0c /* Shift on external clock */
83     #define SR_OUT 0x10 /* Shift out if 1 */
84    
85     /* Bits in IFR and IER */
86     #define IER_SET 0x80 /* set bits in IER */
87     #define IER_CLR 0 /* clear bits in IER */
88     #define SR_INT 0x04 /* Shift register full/empty */
89    
90     /* Bits in ACR */
91     #define T1MODE 0xc0 /* Timer 1 mode */
92     #define T1MODE_CONT 0x40 /* continuous interrupts */
93    
94     /* Bits in IFR and IER */
95     #define T1_INT 0x40 /* Timer 1 interrupt */
96    
97     /* commands (1st byte) */
98     #define ADB_PACKET 0
99     #define CUDA_PACKET 1
100     #define ERROR_PACKET 2
101     #define TIMER_PACKET 3
102     #define POWER_PACKET 4
103     #define MACIIC_PACKET 5
104     #define PMU_PACKET 6
105    
106     /* CUDA commands (2nd byte) */
107     #define CUDA_WARM_START 0x0
108     #define CUDA_AUTOPOLL 0x1
109     #define CUDA_GET_6805_ADDR 0x2
110     #define CUDA_GET_TIME 0x3
111     #define CUDA_GET_PRAM 0x7
112     #define CUDA_SET_6805_ADDR 0x8
113     #define CUDA_SET_TIME 0x9
114     #define CUDA_POWERDOWN 0xa
115     #define CUDA_POWERUP_TIME 0xb
116     #define CUDA_SET_PRAM 0xc
117     #define CUDA_MS_RESET 0xd
118     #define CUDA_SEND_DFAC 0xe
119     #define CUDA_BATTERY_SWAP_SENSE 0x10
120     #define CUDA_RESET_SYSTEM 0x11
121     #define CUDA_SET_IPL 0x12
122     #define CUDA_FILE_SERVER_FLAG 0x13
123     #define CUDA_SET_AUTO_RATE 0x14
124     #define CUDA_GET_AUTO_RATE 0x16
125     #define CUDA_SET_DEVICE_LIST 0x19
126     #define CUDA_GET_DEVICE_LIST 0x1a
127     #define CUDA_SET_ONE_SECOND_MODE 0x1b
128     #define CUDA_SET_POWER_MESSAGES 0x21
129     #define CUDA_GET_SET_IIC 0x22
130     #define CUDA_WAKEUP 0x23
131     #define CUDA_TIMER_TICKLE 0x24
132     #define CUDA_COMBINED_FORMAT_IIC 0x25
133    
134    
135     /* ADB commands */
136     #define ADB_BUSRESET 0x00
137     #define ADB_FLUSH 0x01
138     #define ADB_WRITEREG 0x08
139     #define ADB_READREG 0x0c
140    
141     /* ADB device commands */
142     #define ADB_CMD_SELF_TEST 0xff
143     #define ADB_CMD_CHANGE_ID 0xfe
144     #define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
145     #define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
146    
147     /* ADB default device IDs (upper 4 bits of ADB command byte) */
148     #define ADB_DONGLE 1
149     #define ADB_KEYBOARD 2
150     #define ADB_MOUSE 3
151     #define ADB_TABLET 4
152     #define ADB_MODEM 5
153     #define ADB_MISC 7
154    
155     #define ADB_RET_OK 0
156     #define ADB_RET_INUSE 1
157     #define ADB_RET_NOTPRESENT 2
158     #define ADB_RET_TIMEOUT 3
159     #define ADB_RET_UNEXPECTED_RESULT 4
160     #define ADB_RET_REQUEST_ERROR 5
161     #define ADB_RET_BUS_ERROR 6
162    
163     #define ADB_PACKET 0
164     #define CUDA_PACKET 1
165     #define ERROR_PACKET 2
166     #define TIMER_PACKET 3
167     #define POWER_PACKET 4
168     #define MACIIC_PACKET 5
169     #define PMU_PACKET 6
170    
171     // VIA timer runs at a frequency of 1/1.27655us
172     // or 783361.40378364 ticks/second
173     #define VIA_TIMER_FREQ_DIV_HZ_TIMES_1000 (783361404ULL)
174    
175     enum cuda_state {
176     cuda_idle,
177     cuda_writing,
178     cuda_reading,
179     };
180    
181     struct cuda_control {
182     byte rA;
183     byte rB;
184     byte rDIRB;
185     byte rDIRA;
186     byte rT1CL;
187     byte rT1CH;
188     byte rT1LL;
189     byte rT1LH;
190     byte rT2CL;
191     byte rT2CH;
192     byte rSR;
193     byte rACR;
194     byte rPCR;
195     byte rIFR;
196     byte rIER;
197     byte rANH;
198    
199     // private
200     uint64 T1_end; // in cpu ticks
201     bool autopoll;
202     cuda_state state;
203     int left;
204     int pos;
205     uint8 data[100];
206    
207     int keybaddr;
208     int keybhandler;
209     int mouseaddr;
210     int mousehandler;
211    
212     sys_semaphore idle_sem;
213     };
214    
215     static cuda_control gCUDA;
216     static sys_mutex gCUDAMutex;
217    
218     static void cuda_send_packet(uint8 type, int nb, ...)
219     {
220     gCUDA.data[0] = type;
221     va_list va;
222     va_start(va, nb);
223     for (int i=0; i<nb; i++) {
224     uint8 b = va_arg(va, int);
225     gCUDA.data[i+1] = b;
226     }
227     IO_CUDA_TRACE3("send: ");
228     for (int i=0; i<nb+1; i++) {
229     IO_CUDA_TRACE3("%02x ", gCUDA.data[i]);
230     }
231     IO_CUDA_TRACE3("\n");
232     va_end(va);
233     gCUDA.pos = 0;
234     gCUDA.left = nb+1;
235     gCUDA.rIFR |= SR_INT;
236     gCUDA.rB &= ~TREQ;
237     gCUDA.rB |= TIP;
238     pic_raise_interrupt(IO_PIC_IRQ_CUDA);
239     }
240    
241     static void cuda_receive_adb_packet()
242     {
243     IO_CUDA_TRACE3("===========================================\n");
244     IO_CUDA_TRACE3("ADB_PACKET ");// %02x %02x %02x %02x %02x\n", gCUDA.data[1], gCUDA.data[2], gCUDA.data[3], gCUDA.data[4], gCUDA.data[5]);
245     for (int i=1; i<gCUDA.pos; i++) {
246     IO_CUDA_TRACE3("%02x ", gCUDA.data[i]);
247     }
248     IO_CUDA_TRACE3("\n");
249     // gSinglestep = true;
250     IO_CUDA_TRACE2("ADB_PACKET ");
251     if (gCUDA.data[1] == ADB_BUSRESET) {
252     IO_CUDA_TRACE2("ADB_BUSRESET %02x\n", gCUDA.data[2]);
253     cuda_send_packet(ADB_PACKET, 2, 0, 0);
254     return;
255     }
256     int devaddr = gCUDA.data[1] >> 4;
257     int cmd = gCUDA.data[1] & 0xf;
258     if (cmd == ADB_FLUSH) {
259     // FIXME: ok?
260     cuda_send_packet(ADB_PACKET, 2, 0, 0);
261     return;
262     }
263     int reg = cmd & 3;
264     cmd &= 0xc;
265     IO_CUDA_TRACE3("devaddr %x reg %x cmd %s\n", devaddr, reg, (cmd==ADB_WRITEREG)?"write":"read");
266     switch (cmd) {
267     case ADB_WRITEREG:
268     switch (reg) {
269     case 2:
270     if (devaddr == gCUDA.keybaddr) {
271     // LED stat
272     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
273     } else if (devaddr == gCUDA.mouseaddr) {
274     // gSinglestep = true;
275     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
276     } else {
277     cuda_send_packet(ADB_PACKET, 1, ADB_RET_NOTPRESENT);
278     }
279     break;
280     case 3:
281     if (devaddr == gCUDA.keybaddr) {
282     switch (gCUDA.data[3]) {
283     case ADB_CMD_SELF_TEST:
284     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
285     break;
286     case ADB_CMD_CHANGE_ID:
287     case ADB_CMD_CHANGE_ID_AND_ACT:
288     case ADB_CMD_CHANGE_ID_AND_ENABLE:
289     gCUDA.keybaddr = gCUDA.data[2] & 0xf;
290     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
291     break;
292     default:
293     gCUDA.keybaddr = gCUDA.data[2] & 0xf;
294     gCUDA.keybhandler = gCUDA.data[3];
295     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
296     break;
297     }
298     } else if (devaddr == gCUDA.mouseaddr) {
299     switch (gCUDA.data[3]) {
300     case ADB_CMD_SELF_TEST:
301     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
302     break;
303     case ADB_CMD_CHANGE_ID:
304     case ADB_CMD_CHANGE_ID_AND_ACT:
305     case ADB_CMD_CHANGE_ID_AND_ENABLE:
306     gCUDA.mouseaddr = gCUDA.data[2] & 0xf;
307     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
308     break;
309     default:
310     gCUDA.mouseaddr = gCUDA.data[2] & 0xf;
311     gCUDA.mousehandler = gCUDA.data[3];
312     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
313     break;
314     }
315     } else {
316     cuda_send_packet(ADB_PACKET, 1, ADB_RET_NOTPRESENT);
317     }
318     break;
319     default:
320     IO_CUDA_ERR("unknown reg %02x for device %02x\n", reg, devaddr);
321     }
322     break;
323     case ADB_READREG: {
324     switch (reg) {
325     case 1:
326     if (devaddr == gCUDA.keybaddr) {
327     IO_CUDA_WARN("keyb reg1\n");
328     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
329     } else if (devaddr == gCUDA.mouseaddr) {
330     // gSinglestep = true;
331     IO_CUDA_WARN("read reg 1 of mouse unsupported.\n");
332     cuda_send_packet(ADB_PACKET, 1, ADB_RET_OK);
333     } else {
334     cuda_send_packet(ADB_PACKET, 1, ADB_RET_NOTPRESENT);
335     }
336     break;
337     case 2:
338     if (devaddr == gCUDA.keybaddr) {
339     // LED stat
340     // 111b == all off
341     int ledstat = gKeyboard->getKeybLEDs();
342     int keyb = 0xff;
343     if (!(ledstat & KEYB_LED_NUM)) keyb &= ~0x80;
344     if (!(ledstat & KEYB_LED_SCROLL)) keyb &= ~0x40;
345     if (!(ledstat & KEYB_LED_CAPS)) keyb &= ~0x20;
346     cuda_send_packet(ADB_PACKET, 3, ADB_RET_OK, 0xff, keyb);
347     } else if (devaddr == gCUDA.mouseaddr) {
348     // gSinglestep = true;
349     IO_CUDA_WARN("read reg 2 of mouse unsupported.\n");
350     } else {
351     cuda_send_packet(ADB_PACKET, 1, ADB_RET_NOTPRESENT);
352     }
353     break;
354     case 3:
355     if (devaddr == gCUDA.keybaddr) {
356     // cuda_send_packet(ADB_PACKET, 3, ADB_RET_OK, gCUDA.keybaddr, gCUDA.keybhandler);
357     cuda_send_packet(ADB_PACKET, 3, ADB_RET_OK, gCUDA.keybhandler, gCUDA.keybaddr);
358     } else if (devaddr == gCUDA.mouseaddr) {
359     // cuda_send_packet(ADB_PACKET, 3, ADB_RET_OK, gCUDA.mouseaddr, gCUDA.mousehandler);
360     cuda_send_packet(ADB_PACKET, 3, ADB_RET_OK, gCUDA.mousehandler, gCUDA.mouseaddr);
361     } else {
362     cuda_send_packet(ADB_PACKET, 1, ADB_RET_NOTPRESENT);
363     }
364     break;
365     default:
366     IO_CUDA_ERR("unknown reg %02x for device %02x\n", reg, devaddr);
367     }
368     break;
369     }
370     default:
371     IO_CUDA_ERR("unknown adb command\n");
372     }
373     /*
374     default:
375     switch (gCUDA.data[1] & 0xf0) {
376     case (ADB_KEYBOARD << 4):
377     switch (gCUDA.data[1] & 0xf) {
378     case 0xf:
379     IO_CUDA_TRACE2("KEYBOARD: GET DEVICE INFO %02x\n", gCUDA.data[1]);
380     cuda_send_packet(ADB_PACKET, 4, 0, 0, 0, 1);
381     return;
382     }
383     IO_CUDA_TRACE2("KEYBOARD: unknown %02x\n", gCUDA.data[1]);
384     cuda_send_packet(ADB_PACKET, 1, 0x2);
385     return;
386     }
387     IO_CUDA_TRACE2("unknown adb (%02x)!\n", gCUDA.data[1]);
388     // IO_CUDA_ERR("!\n");
389     cuda_send_packet(ADB_PACKET, 1, 0x2);
390     }
391     */
392     }
393    
394     static void cuda_receive_cuda_packet()
395     {
396     IO_CUDA_TRACE2("CUDA_PACKET ");
397     switch (gCUDA.data[1]) {
398     case CUDA_AUTOPOLL: {
399     IO_CUDA_TRACE2("CUDA_AUTOPOLL=%02x\n", gCUDA.data[2]);
400     if (gCUDA.data[2]) {
401     gCUDA.autopoll = true;
402     } else {
403     gCUDA.autopoll = false;
404     }
405     cuda_send_packet(CUDA_PACKET, 1, gCUDA.data[2]);
406     break;
407     }
408     case CUDA_GET_TIME: {
409     IO_CUDA_TRACE2("CUDA_GET_TIME %02x\n", gCUDA.data[2]);
410     time_t tt;
411     time(&tt);
412     uint32 t = (uint32)tt+ 2082844800;
413     cuda_send_packet(CUDA_PACKET, 6, 0, 0, t>>24, t>>16, t>>8, t);
414     break;
415     }
416     case CUDA_SET_TIME: {
417     IO_CUDA_TRACE2("CUDA_SET_TIME %02x\n", gCUDA.data[2]);
418     cuda_send_packet(CUDA_PACKET, 1, 0);
419     break;
420     }
421     case CUDA_RESET_SYSTEM: {
422     IO_CUDA_WARN("reset!\n");
423     ppc_cpu_stop();
424     break;
425     }
426     case CUDA_FILE_SERVER_FLAG: {
427     IO_CUDA_TRACE2("FILE_SERVER_FLAG %02x\n", gCUDA.data[2]);
428     cuda_send_packet(CUDA_PACKET, 1, 0);
429     break;
430     }
431     case CUDA_SET_DEVICE_LIST: {
432     IO_CUDA_TRACE2("SET_DEVICE_LIST %02x %02x %02x\n", gCUDA.data[2], gCUDA.data[3], gCUDA.data[4]);
433     cuda_send_packet(CUDA_PACKET, 1, 0);
434     break;
435     }
436     case CUDA_SET_AUTO_RATE: {
437     IO_CUDA_TRACE2("SET_AUTO_RATE %02x\n", gCUDA.data[2]);
438     cuda_send_packet(CUDA_PACKET, 1, 0);
439     break;
440     }
441     case CUDA_SET_POWER_MESSAGES: {
442     IO_CUDA_TRACE2("CUDA_SET_POWER_MESSAGES %02x\n", gCUDA.data[2]);
443     cuda_send_packet(CUDA_PACKET, 1, 0);
444     break;
445     }
446     case CUDA_POWERDOWN: {
447     IO_CUDA_WARN("power down!\n");
448     ppc_cpu_stop();
449     break;
450     }
451     default:
452     IO_CUDA_ERR("unknown cuda (%02x)!\n", gCUDA.data[1]);
453     }
454     }
455    
456     static void cuda_receive_packet()
457     {
458     IO_CUDA_TRACE2("cuda received packet: (%d) ", gCUDA.pos);
459     switch (gCUDA.data[0]) {
460     case ADB_PACKET:
461     cuda_receive_adb_packet();
462     break;
463     case CUDA_PACKET:
464     cuda_receive_cuda_packet();
465     break;
466     case ERROR_PACKET:
467     IO_CUDA_TRACE2("ERROR_PACKET %02x %02x\n", gCUDA.data[1], gCUDA.data[2]);
468     IO_CUDA_ERR("error packet\n");
469     break;
470     case TIMER_PACKET:
471     IO_CUDA_TRACE2("TIMER_PACKET %02x %02x\n", gCUDA.data[1], gCUDA.data[2]);
472     IO_CUDA_ERR("timer packet\n");
473     break;
474     case POWER_PACKET:
475     IO_CUDA_TRACE2("POWER_PACKET %02x %02x\n", gCUDA.data[1], gCUDA.data[2]);
476     IO_CUDA_ERR("power packet\n");
477     break;
478     case MACIIC_PACKET:
479     IO_CUDA_TRACE2("MACIIC_PACKET %02x %02x\n", gCUDA.data[1], gCUDA.data[2]);
480     IO_CUDA_ERR("maciic packet\n");
481     break;
482     case PMU_PACKET:
483     IO_CUDA_TRACE2("PMU_PACKET %02x %02x\n", gCUDA.data[1], gCUDA.data[2]);
484     IO_CUDA_ERR("pmu packet\n");
485     break;
486     default:
487     IO_CUDA_TRACE2("unknown generic (%02x)!\n", gCUDA.data[0]);
488     IO_CUDA_ERR("unknown packet\n", gCUDA.data[0]);
489     break;
490     }
491     }
492    
493     static void cuda_update_T1()
494     {
495     uint64 clk = sys_get_hiresclk_ticks();
496     if (clk < gCUDA.T1_end) {
497     uint64 ticks_per_sec = 1000ULL * sys_get_hiresclk_ticks_per_second();
498     uint64 T1 = (gCUDA.T1_end - clk) * VIA_TIMER_FREQ_DIV_HZ_TIMES_1000 / ticks_per_sec;
499     gCUDA.rT1CL = T1;
500     gCUDA.rT1CH = T1 >> 8;
501     gCUDA.rIFR &= ~T1_INT;
502     //
503     // uint64 tmp = gCUDA.T1_end - clk;
504     // IO_CUDA_WARN("T1 running, T1 now %04x, T1_end-clk=%08qx\n", (uint32)T1, tmp);
505     } else {
506     uint64 ticks_per_sec = 1000ULL * sys_get_hiresclk_ticks_per_second();
507     uint64 T1_latch = (gCUDA.rT1LH << 8) | gCUDA.rT1LL;
508     uint64 full_T1_interval_ticks = (T1_latch+1) * ticks_per_sec / VIA_TIMER_FREQ_DIV_HZ_TIMES_1000;
509     uint64 T1_end = clk + full_T1_interval_ticks - (clk - gCUDA.T1_end) % full_T1_interval_ticks;
510     gCUDA.T1_end = T1_end;
511     uint64 T1 = (gCUDA.T1_end - clk) * VIA_TIMER_FREQ_DIV_HZ_TIMES_1000 / ticks_per_sec;
512     gCUDA.rT1CL = T1;
513     gCUDA.rT1CH = T1 >> 8;
514     gCUDA.rIFR |= T1_INT;
515     //
516     // uint64 tmp = gCUDA.T1_end - clk;
517     // IO_CUDA_WARN("T1 overflowed, setting interrupt flag, T1 set to %04x, T1_end-clk=%08qx, T1_latch = %04x\n", (uint32)T1, tmp, T1_latch);
518     }
519     }
520    
521     static void cuda_start_T1()
522     {
523     uint64 clk = sys_get_hiresclk_ticks();
524     uint64 ticks_per_sec = 1000ULL * sys_get_hiresclk_ticks_per_second();
525     uint32 T1 = (gCUDA.rT1CH << 8) | gCUDA.rT1CL;
526     /* uint64 tmp = static_cast<uint64>(T1) * ticks_per_sec / VIA_TIMER_FREQ_DIV_HZ_TIMES_1000;
527     printf("T1 for %lld ticks (%g seconds vs. %g)\n",
528     tmp, static_cast<double>(tmp)/static_cast<double>(ticks_per_sec / 1000),
529     static_cast<double>(T1) * 1.27655 / 1000000.0);*/
530     gCUDA.T1_end = clk + T1 * ticks_per_sec / VIA_TIMER_FREQ_DIV_HZ_TIMES_1000;
531     gCUDA.rIFR &= ~T1_INT;
532     IO_CUDA_TRACE("T1 restarted, T1 = %08x\n", T1);
533     }
534    
535     void cuda_write(uint32 addr, uint32 data, int size)
536     {
537     sys_lock_mutex(gCUDAMutex);
538    
539     IO_CUDA_TRACE("%d write word @%08x: %08x\n", gCUDA.state, addr, data);
540     addr -= IO_CUDA_PA_START;
541     switch (addr) {
542     case A:
543     IO_CUDA_TRACE("->A\n");
544     gCUDA.rA = data;
545     break;
546     case B: {
547     bool ack = false;
548     if (gCUDA.rB & TACK) {
549     if (!(data & TACK)) {
550     gCUDA.rIFR |= SR_INT;
551     if (gCUDA.state == cuda_idle) {
552     data &= ~TREQ;
553     }
554     ack = true;
555     }
556     } else {
557     if ((data & TACK)) {
558     gCUDA.rIFR |= SR_INT;
559     if (gCUDA.state == cuda_idle) {
560     if (data & TIP) {
561     data |= TREQ;
562     } else {
563     data &= ~TREQ;
564     }
565     }
566     ack = true;
567     }
568     }
569     if ((gCUDA.state == cuda_reading) && ack && (gCUDA.rACR & SR_OUT)
570     && !(!(gCUDA.rB & TIP) && (data & TIP))) {
571     // don't ask...
572     gCUDA.data[gCUDA.pos] = gCUDA.rSR;
573     IO_CUDA_TRACE2(";; %d:%x\n", gCUDA.pos, gCUDA.rSR);
574     gCUDA.pos++;
575     if (gCUDA.pos > 10) {
576     gCUDA.pos = 0;
577     IO_CUDA_ERR("cuda overflow!\n");
578     }
579     }
580     if ((gCUDA.state == cuda_writing) && ack) {
581     if (gCUDA.left <= 1) {
582     data |= TREQ;
583     }
584     // gCUDA.rB = data;
585     // break;
586     }
587     if ((gCUDA.rB & TIP) && !(data & TIP)) {
588     gCUDA.rIFR |= SR_INT;
589     // IO_CUDA_TRACE2("^ from: %08x %02x\n", gCPU.pc, gCUDA.rIFR);
590     if (gCUDA.rACR & SR_OUT) {
591     gCUDA.state = cuda_reading;
592     IO_CUDA_TRACE2("CUDA CHANGE STATE %d: to %d\n", __LINE__, gCUDA.state);
593     gCUDA.pos = 1;
594     data |= TREQ;
595     gCUDA.data[0] = gCUDA.rSR;
596     IO_CUDA_TRACE2(";; %d:%x\n", gCUDA.pos, gCUDA.rSR);
597     } else {
598     if (gCUDA.left) {
599     gCUDA.state = cuda_writing;
600     IO_CUDA_TRACE2("CUDA CHANGE STATE %d: to %d\n", __LINE__, gCUDA.state);
601     } else {
602     // data &= ~TIP;
603     }
604     data &= ~TREQ;
605     }
606     }
607     pic_raise_interrupt(IO_PIC_IRQ_CUDA);
608     if (!(gCUDA.rB & TIP) && (data & TIP)) {
609     gCUDA.rIFR |= SR_INT;
610     // IO_CUDA_TRACE2("v from: %08x %d\n", gCPU.pc, gCUDA.state);
611     data |= TREQ | TIP;
612     gCUDA.rB = data;
613     if (gCUDA.state == cuda_reading) {
614     cuda_receive_packet();
615     if (!gCUDA.left) {
616     // pic_cancel_interrupt(IO_PIC_IRQ_CUDA);
617     gCUDA.rIFR &= ~SR_INT;
618     }
619     } else if (gCUDA.state == cuda_writing) {
620     IO_CUDA_TRACE2("cuda sent packet (%d)\n", gCUDA.pos);
621     gCUDA.left = 0;
622     gCUDA.pos = 0;
623     }
624     gCUDA.state = cuda_idle;
625     sys_signal_semaphore(gCUDA.idle_sem);
626     IO_CUDA_TRACE2("CUDA CHANGE STATE %d: to %d\n", __LINE__, gCUDA.state);
627     } else {
628     gCUDA.rB = data;
629     }
630     IO_CUDA_TRACE("->B(%02x)\n", gCUDA.rB);
631     break;
632     }
633     case DIRB:
634     IO_CUDA_TRACE("->DIRB\n");
635     gCUDA.rDIRB = data;
636     break;
637     case DIRA:
638     IO_CUDA_TRACE("->DIRA\n");
639     gCUDA.rDIRA = data;
640     break;
641     case T1CL:
642     IO_CUDA_TRACE("->T1CL\n");
643     // same as writing to T1LL
644     gCUDA.rT1CL = data;
645     gCUDA.rT1LL = data;
646     break;
647     case T1CH:
648     IO_CUDA_TRACE("->T1CH\n");
649     /* from [1]: "[T1C-L] is loaded automatically from the low-order\
650     * latch (T1L-L) when the processor writes into the high-order counter\
651     * (T1C-H)"
652     * and: "8 bits loaded into high-order latches. also at this time both \
653     * high- and low-order latches transferred into T1 counter"
654     */
655     gCUDA.rT1LH = data;
656     gCUDA.rT1CH = gCUDA.rT1LH;
657     gCUDA.rT1CL = gCUDA.rT1LL;
658     cuda_start_T1();
659     break;
660     case T1LL:
661     IO_CUDA_TRACE("->T1LL\n");
662     /* from [1]: "this operation is no different than a write into reg 4"
663     * reg4 is T1CL
664     */
665     gCUDA.rT1CL = data;
666     gCUDA.rT1LL = data;
667     break;
668     case T1LH:
669     IO_CUDA_TRACE("->T1LH\n");
670     gCUDA.rT1LH = data;
671     break;
672     case T2CL:
673     IO_CUDA_ERR("->T2CL\n");
674     gCUDA.rT2CL = data;
675     break;
676     case T2CH:
677     IO_CUDA_ERR("->T2CH\n");
678     gCUDA.rT2CH = data;
679     break;
680     case ACR:
681     IO_CUDA_TRACE("->ACR\n");
682     gCUDA.rACR = data;
683     break;
684     case SR:
685     IO_CUDA_TRACE("->SR\n");
686     gCUDA.rSR = data;
687     break;
688     case PCR:
689     IO_CUDA_TRACE("->PCR\n");
690     gCUDA.rPCR = data;
691     break;
692     case IFR:
693     IO_CUDA_TRACE("->IFR\n");
694     gCUDA.rIFR = data;
695     break;
696     case IER:
697     IO_CUDA_TRACE("->IER\n");
698     gCUDA.rIER = data;
699     break;
700     case ANH:
701     IO_CUDA_TRACE("->ANH\n");
702     gCUDA.rANH = data;
703     break;
704     default:
705     IO_CUDA_ERR("unknown service\n");
706     }
707    
708     sys_unlock_mutex(gCUDAMutex);
709     }
710    
711     void cuda_read(uint32 addr, uint32 &data, int size)
712     {
713     sys_lock_mutex(gCUDAMutex);
714    
715     IO_CUDA_TRACE("%d read word @%08x\n", gCUDA.state, addr);
716     addr -= IO_CUDA_PA_START;
717     switch (addr) {
718     case A:
719     IO_CUDA_TRACE("A(%02x)->\n", gCUDA.rA);
720     data = gCUDA.rA;
721     break;
722     case B:
723     IO_CUDA_TRACE("B(%02x)->\n", gCUDA.rB);
724     data = gCUDA.rB;
725     break;
726     case DIRB:
727     IO_CUDA_TRACE("DIRB(%02x)->\n", gCUDA.rDIRB);
728     data = gCUDA.rDIRB;
729     break;
730     case DIRA:
731     IO_CUDA_TRACE("DIRA->\n");
732     data = gCUDA.rDIRA;
733     break;
734     case T1CL:
735     IO_CUDA_TRACE("T1CL->\n");
736     cuda_update_T1();
737     data = gCUDA.rT1CL;
738     break;
739     case T1CH: {
740     IO_CUDA_TRACE("T1CH->\n");
741     cuda_update_T1();
742     // uint64 clk = sys_get_cpu_ticks();
743     // IO_CUDA_WARN("read %08x: T1 = %04x clk = %08qx, T1_end = %08qx\n",
744     // gCPU.current_code_base + gCPU.pc_ofs,
745     // (gCUDA.rT1CH<<8) | gCUDA.rT1CL,
746     // clk, gCUDA.T1_end);
747     data = gCUDA.rT1CH;
748     break;
749     }
750     case T1LL:
751     IO_CUDA_WARN("T1LL->\n");
752     data = gCUDA.rT1LL;
753     break;
754     case T1LH:
755     IO_CUDA_WARN("T1LH->\n");
756     data = gCUDA.rT1LH;
757     break;
758     case T2CL:
759     IO_CUDA_ERR("T2CL->\n");
760     data = gCUDA.rT2CL;
761     break;
762     case T2CH:
763     IO_CUDA_ERR("T2CH->\n");
764     data = gCUDA.rT2CH;
765     break;
766     case ACR:
767     IO_CUDA_TRACE("ACR->\n");
768     data = gCUDA.rACR;
769     break;
770     case SR:
771     IO_CUDA_TRACE("SR->\n");
772     data = gCUDA.rSR;
773     if (gCUDA.state == cuda_writing) {
774     if (gCUDA.left) {
775     data = gCUDA.data[gCUDA.pos];
776     IO_CUDA_TRACE2("::%d:%02x\n", gCUDA.pos, data);
777     gCUDA.pos++;
778     gCUDA.left--;
779     }
780     if (gCUDA.left <= 0) {
781     IO_CUDA_TRACE2("stop\n");
782     gCUDA.rB |= TREQ;
783     gCUDA.rB &= ~TIP;
784     }
785     gCUDA.rIFR &= ~SR_INT;
786     } else if (gCUDA.state == cuda_reading) {
787     gCUDA.rB &= ~TREQ;
788     gCUDA.rIFR &= ~SR_INT;
789     } else {
790     gCUDA.rB |= TREQ;
791     gCUDA.rIFR &= ~SR_INT;
792     }
793     break;
794     case PCR:
795     IO_CUDA_TRACE("PCR->\n");
796     data = gCUDA.rPCR;
797     break;
798     case IFR:
799     data = gCUDA.rIFR;
800     if (gCUDA.state == cuda_idle) {
801     if (!gCUDA.left /*&& !(gCUDA.rIER & SR_INT)*/) {
802     if (cuda_interrupt()) {
803     data |= SR_INT;
804     // if (gCUDA.autopoll) pic_raise_interrupt(IO_PIC_IRQ_CUDA);
805     }
806     }
807     // ht_printf("is idle!\n");
808     } else {
809     // ht_printf("state not idle bla !\n");
810     // data |= SR_INT;
811     }
812     cuda_update_T1();
813     IO_CUDA_TRACE("%d IFR->(%02x/%02x)\n", gCUDA.state, gCUDA.rIFR, data);
814     break;
815     case IER:
816     IO_CUDA_TRACE("IER->\n");
817     data = gCUDA.rIER;
818     break;
819     case ANH:
820     IO_CUDA_TRACE("ANH->\n");
821     data = gCUDA.rANH;
822     break;
823     default:
824     IO_CUDA_ERR("unknown service\n");
825     }
826    
827     sys_unlock_mutex(gCUDAMutex);
828     }
829    
830     bool cuda_interrupt()
831     {
832     return false;
833     }
834    
835     static sys_semaphore gCUDAEventSem;
836     static Queue gCUDAEvents(true);
837    
838     static bool cudaEventHandler(const SystemEvent &ev)
839     {
840     sys_lock_semaphore(gCUDAEventSem);
841     // ht_printf("queue %d\n", ev.key.pressed);
842     gCUDAEvents.enQueue(new SystemEventObject(ev));
843     sys_unlock_semaphore(gCUDAEventSem);
844     sys_signal_semaphore(gCUDAEventSem);
845     return true;
846     }
847    
848     static bool doProcessCudaEvent(const SystemEvent &ev)
849     {
850     switch (ev.type) {
851     case sysevKey: {
852     uint8 k = ev.key.keycode;
853     if (!ev.key.pressed) {
854     k |= 0x80;
855     }
856     cuda_send_packet(ADB_PACKET, 4, 0x40, 0x2c, k, 0xff);
857     return true;
858     }
859     case sysevMouse: {
860     int dx = ev.mouse.relx; //* 256 / gDisplay->mClientChar.width;
861     int dy = ev.mouse.rely; //* 256 / gDisplay->mClientChar.height;
862     if (dx < 0) {
863     if (dx < -63) {
864     dx = 127;
865     } else {
866     dx += 128;
867     }
868     } else if (dx > 63) {
869     dx = 63;
870     }
871     if (dy < 0) {
872     if (dy < -63) {
873     dy = 127;
874     } else {
875     dy += 128;
876     }
877     } else if (dy > 63) {
878     dy = 63;
879     }
880     if (!ev.mouse.button2) dx |= 0x80;
881     if (!ev.mouse.button1) dy |= 0x80;
882     // ht_printf("adb mouse: cur: %d, %d d: %d, %d\n", ev.mouseEvent.x, ev.mouseEvent.y, dx, dy);
883     cuda_send_packet(ADB_PACKET, 4, 0x40, 0x3c, dy, dx);
884     return true;
885     }
886     default:
887     return false;
888     }
889     }
890    
891     static bool tryProcessCudaEvent(const SystemEvent &ev)
892     {
893     uint timeout_msec = 200;
894     uint64 time_end = sys_get_hiresclk_ticks() + sys_get_hiresclk_ticks_per_second()
895     * timeout_msec / 1000;
896     // ht_printf("process %d\n", ev.key.pressed);
897     while (sys_get_hiresclk_ticks() < time_end) {
898     sys_lock_mutex(gCUDAMutex);
899     static int lockuphack = 0;
900     if (gCUDA.state == cuda_idle) {
901     if (!gCUDA.left /*&& !(gCUDA.rIFR & SR_INT)*/) {
902     lockuphack = 0;
903     bool k = doProcessCudaEvent(ev);
904     sys_unlock_mutex(gCUDAMutex);
905     // IO_CUDA_WARN("Tried to process event: %d.\n", k);
906     return k;
907     } else {
908     IO_CUDA_TRACE2("left: %d\n", gCUDA.left);
909     if (lockuphack++ == 20) {
910     /* gCUDA.left = 0;
911     gCUDA.rA = TREQ;
912     gCUDA.rACR = 0;
913     lockuphack = 0;
914     IO_CUDA_WARN("lock-up parachute\n");*/
915     }
916     }
917     } else {
918     IO_CUDA_TRACE2("cuda not idle (%d)!\n", gCUDA.state);
919     }
920     sys_unlock_mutex(gCUDAMutex);
921     sys_lock_semaphore(gCUDA.idle_sem);
922     sys_wait_semaphore_bounded(gCUDA.idle_sem, 10);
923     sys_unlock_semaphore(gCUDA.idle_sem);
924     }
925     IO_CUDA_WARN("Event processing timed out. Event dropped.\n");
926     return false;
927     }
928    
929     static void *cudaEventLoop(void *arg)
930     {
931     if (sys_create_semaphore(&gCUDAEventSem)) {
932     IO_CUDA_ERR("Can't create semaphore\n");
933     }
934     gKeyboard->attachEventHandler(cudaEventHandler);
935     gMouse->attachEventHandler(cudaEventHandler);
936     sys_lock_semaphore(gCUDAEventSem);
937     while (1) {
938     // IO_CUDA_WARN("waiting on semaphore\n");
939     sys_wait_semaphore(gCUDAEventSem);
940     // IO_CUDA_WARN("semaphore signalled\n");
941     SystemEventObject *seo;
942     while ((seo = (SystemEventObject*)gCUDAEvents.deQueue())) {
943     tryProcessCudaEvent(seo->mEv);
944     delete seo;
945     }
946     }
947     }
948    
949     bool cuda_prom_get_key(uint32 &key)
950     {
951     if (gCUDA.left == 5 && gCUDA.data[2] == 0x2c) {
952     key = gCUDA.data[3];
953     gCUDA.left = 0;
954     return true;
955     } else {
956     gCUDA.left = 0;
957     return false;
958     }
959     }
960    
961     void cuda_init()
962     {
963     memset(&gCUDA, 0, sizeof gCUDA);
964     gCUDA.state = cuda_idle;
965     gCUDA.keybaddr = ADB_KEYBOARD;
966     gCUDA.keybhandler = 1;
967     gCUDA.mouseaddr = ADB_MOUSE;
968     gCUDA.mousehandler = 2;
969     gCUDA.T1_end = 0;
970     gCUDA.rT1LL = 0xff;
971     gCUDA.rT1LH = 0xff;
972    
973     if (sys_create_mutex(&gCUDAMutex)) {
974     IO_CUDA_ERR("Can't create mutex\n");
975     }
976    
977     if (sys_create_semaphore(&gCUDA.idle_sem)) {
978     IO_CUDA_ERR("Can't create semaphore\n");
979     }
980    
981     sys_thread cudaEventLoopThread;
982     sys_create_thread(&cudaEventLoopThread, 0, cudaEventLoop, NULL);
983     }
984    
985     void cuda_done()
986     {
987     sys_destroy_mutex(gCUDAMutex);
988     sys_destroy_semaphore(gCUDA.idle_sem);
989     }
990    
991     void cuda_init_config()
992     {
993     }

  ViewVC Help
Powered by ViewVC 1.1.26