9d39a80e |
1 | #include "common.h" |
2 | |
3 | void spin(int loops); |
71b41fdd |
4 | u16 read_frt(void); |
9d39a80e |
5 | |
30a57837 |
6 | // vram map: |
7 | // 00-0f: master irq counters (16bit) |
8 | // 10-1f: slave ... |
9 | |
6474d733 |
10 | // comm area map: |
11 | // 00-01: cmd |
30a57837 |
12 | // 02: error counter |
13 | // 03: handler input: no 32x irqsrc clear flag for both (if val == 0x5a) |
6474d733 |
14 | // 04-07: arg0/response |
15 | // 08-0b: arg1 |
16 | // 0c: last_irq_vec_master |
17 | // 0d: last_irq_vec_slave |
18 | // 0e: exception_index_master |
19 | // 0f: exception_index_slave |
06d7984c |
20 | static void do_cmd(u16 cmd, u16 r[6], u32 is_slave) |
21 | { |
22 | u32 *rl = (u32 *)r; |
30a57837 |
23 | u8 *r8 = (u8 *)r; |
06d7984c |
24 | u32 a, d; |
25 | u16 v; |
26 | |
27 | switch (cmd) |
28 | { |
29 | case CMD_ECHO: |
30 | v = read16(&r[4/2]) ^ (is_slave << 15); |
31 | write16(&r[6/2], v); |
32 | break; |
33 | case CMD_READ_FRT: |
34 | v = read_frt(); |
35 | write16(&r[4/2], v); |
36 | break; |
37 | case CMD_READ8: |
38 | a = read32(&rl[4/4]); |
39 | d = read8(a); |
40 | write32(&rl[4/4], d); |
41 | break; |
42 | case CMD_READ16: |
43 | a = read32(&rl[4/4]); |
44 | d = read16(a); |
45 | write32(&rl[4/4], d); |
46 | break; |
47 | case CMD_READ32: |
48 | a = read32(&rl[4/4]); |
49 | d = read32(a); |
50 | write32(&rl[4/4], d); |
51 | break; |
52 | case CMD_WRITE8: |
53 | a = read32(&rl[4/4]); |
54 | d = read32(&rl[8/4]); |
55 | write8(a, d); |
56 | break; |
57 | case CMD_WRITE16: |
58 | a = read32(&rl[4/4]); |
59 | d = read32(&rl[8/4]); |
60 | write16(a, d); |
61 | break; |
62 | case CMD_WRITE32: |
63 | a = read32(&rl[4/4]); |
64 | d = read32(&rl[8/4]); |
65 | write32(a, d); |
66 | break; |
5073ab5a |
67 | case CMD_GETGBR: |
ec8170d9 |
68 | asm volatile("stc gbr, %0" : "=r"(d)); |
5073ab5a |
69 | write32(&rl[4/4], d); |
70 | break; |
71 | case CMD_GETVBR: |
ec8170d9 |
72 | asm volatile("stc vbr, %0" : "=r"(d)); |
5073ab5a |
73 | write32(&rl[4/4], d); |
74 | break; |
ec8170d9 |
75 | case CMD_GETSR: |
76 | asm volatile("stc sr, %0" : "=r"(d)); |
77 | write32(&rl[4/4], d); |
78 | break; |
79 | case CMD_SETSR: |
80 | d = read32(&rl[4/4]); |
81 | asm volatile("ldc %0, sr" :: "r"(d)); |
82 | break; |
06d7984c |
83 | default: |
30a57837 |
84 | r8[2]++; // error |
06d7984c |
85 | mem_barrier(); |
86 | break; |
87 | } |
88 | } |
89 | |
9d39a80e |
90 | void main_c(u32 is_slave) |
91 | { |
06d7984c |
92 | u16 *r = (u16 *)0x20004000; |
9d39a80e |
93 | |
94 | for (;;) |
95 | { |
71b41fdd |
96 | u16 cmd, cmdr; |
9d39a80e |
97 | |
98 | mem_barrier(); |
99 | cmd = read16(&r[0x20/2]); |
71b41fdd |
100 | mem_barrier(); |
101 | cmdr = read16(&r[0x20/2]); |
06d7984c |
102 | if (cmd == 0 |
103 | || cmd != cmdr // documented as "normal" case |
104 | || ((cmd & 0x8000) ^ (is_slave << 15)) |
105 | || cmd == 0x4d5f) { // 'M_' from BIOS |
9d39a80e |
106 | spin(64); |
107 | continue; |
108 | } |
109 | cmd &= 0x7fff; |
06d7984c |
110 | do_cmd(cmd, &r[0x20/2], is_slave); |
9d39a80e |
111 | write16(&r[0x20/2], 0); |
112 | } |
113 | } |
114 | |
115 | // vim:ts=4:sw=4:expandtab |