/[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

Contents of /src/io/cuda/cuda.cc

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1 - (show annotations)
Wed Sep 5 17:11:21 2007 UTC (16 years, 6 months ago) by dpavlin
File size: 26006 byte(s)
import upstream CVS
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