root / hw / cuda.c @ 267002cd
History | View | Annotate | Download (13.3 kB)
1 | 267002cd | bellard | /*
|
---|---|---|---|
2 | 267002cd | bellard | * QEMU CUDA support
|
3 | 267002cd | bellard | *
|
4 | 267002cd | bellard | * Copyright (c) 2004 Fabrice Bellard
|
5 | 267002cd | bellard | *
|
6 | 267002cd | bellard | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 | 267002cd | bellard | * of this software and associated documentation files (the "Software"), to deal
|
8 | 267002cd | bellard | * in the Software without restriction, including without limitation the rights
|
9 | 267002cd | bellard | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10 | 267002cd | bellard | * copies of the Software, and to permit persons to whom the Software is
|
11 | 267002cd | bellard | * furnished to do so, subject to the following conditions:
|
12 | 267002cd | bellard | *
|
13 | 267002cd | bellard | * The above copyright notice and this permission notice shall be included in
|
14 | 267002cd | bellard | * all copies or substantial portions of the Software.
|
15 | 267002cd | bellard | *
|
16 | 267002cd | bellard | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17 | 267002cd | bellard | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18 | 267002cd | bellard | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
19 | 267002cd | bellard | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20 | 267002cd | bellard | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21 | 267002cd | bellard | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22 | 267002cd | bellard | * THE SOFTWARE.
|
23 | 267002cd | bellard | */
|
24 | 267002cd | bellard | #include "vl.h" |
25 | 267002cd | bellard | |
26 | 267002cd | bellard | /* Bits in B data register: all active low */
|
27 | 267002cd | bellard | #define TREQ 0x08 /* Transfer request (input) */ |
28 | 267002cd | bellard | #define TACK 0x10 /* Transfer acknowledge (output) */ |
29 | 267002cd | bellard | #define TIP 0x20 /* Transfer in progress (output) */ |
30 | 267002cd | bellard | |
31 | 267002cd | bellard | /* Bits in ACR */
|
32 | 267002cd | bellard | #define SR_CTRL 0x1c /* Shift register control bits */ |
33 | 267002cd | bellard | #define SR_EXT 0x0c /* Shift on external clock */ |
34 | 267002cd | bellard | #define SR_OUT 0x10 /* Shift out if 1 */ |
35 | 267002cd | bellard | |
36 | 267002cd | bellard | /* Bits in IFR and IER */
|
37 | 267002cd | bellard | #define IER_SET 0x80 /* set bits in IER */ |
38 | 267002cd | bellard | #define IER_CLR 0 /* clear bits in IER */ |
39 | 267002cd | bellard | #define SR_INT 0x04 /* Shift register full/empty */ |
40 | 267002cd | bellard | #define T1_INT 0x40 /* Timer 1 interrupt */ |
41 | 267002cd | bellard | |
42 | 267002cd | bellard | /* Bits in ACR */
|
43 | 267002cd | bellard | #define T1MODE 0xc0 /* Timer 1 mode */ |
44 | 267002cd | bellard | #define T1MODE_CONT 0x40 /* continuous interrupts */ |
45 | 267002cd | bellard | |
46 | 267002cd | bellard | /* commands (1st byte) */
|
47 | 267002cd | bellard | #define ADB_PACKET 0 |
48 | 267002cd | bellard | #define CUDA_PACKET 1 |
49 | 267002cd | bellard | #define ERROR_PACKET 2 |
50 | 267002cd | bellard | #define TIMER_PACKET 3 |
51 | 267002cd | bellard | #define POWER_PACKET 4 |
52 | 267002cd | bellard | #define MACIIC_PACKET 5 |
53 | 267002cd | bellard | #define PMU_PACKET 6 |
54 | 267002cd | bellard | |
55 | 267002cd | bellard | |
56 | 267002cd | bellard | /* CUDA commands (2nd byte) */
|
57 | 267002cd | bellard | #define CUDA_WARM_START 0x0 |
58 | 267002cd | bellard | #define CUDA_AUTOPOLL 0x1 |
59 | 267002cd | bellard | #define CUDA_GET_6805_ADDR 0x2 |
60 | 267002cd | bellard | #define CUDA_GET_TIME 0x3 |
61 | 267002cd | bellard | #define CUDA_GET_PRAM 0x7 |
62 | 267002cd | bellard | #define CUDA_SET_6805_ADDR 0x8 |
63 | 267002cd | bellard | #define CUDA_SET_TIME 0x9 |
64 | 267002cd | bellard | #define CUDA_POWERDOWN 0xa |
65 | 267002cd | bellard | #define CUDA_POWERUP_TIME 0xb |
66 | 267002cd | bellard | #define CUDA_SET_PRAM 0xc |
67 | 267002cd | bellard | #define CUDA_MS_RESET 0xd |
68 | 267002cd | bellard | #define CUDA_SEND_DFAC 0xe |
69 | 267002cd | bellard | #define CUDA_BATTERY_SWAP_SENSE 0x10 |
70 | 267002cd | bellard | #define CUDA_RESET_SYSTEM 0x11 |
71 | 267002cd | bellard | #define CUDA_SET_IPL 0x12 |
72 | 267002cd | bellard | #define CUDA_FILE_SERVER_FLAG 0x13 |
73 | 267002cd | bellard | #define CUDA_SET_AUTO_RATE 0x14 |
74 | 267002cd | bellard | #define CUDA_GET_AUTO_RATE 0x16 |
75 | 267002cd | bellard | #define CUDA_SET_DEVICE_LIST 0x19 |
76 | 267002cd | bellard | #define CUDA_GET_DEVICE_LIST 0x1a |
77 | 267002cd | bellard | #define CUDA_SET_ONE_SECOND_MODE 0x1b |
78 | 267002cd | bellard | #define CUDA_SET_POWER_MESSAGES 0x21 |
79 | 267002cd | bellard | #define CUDA_GET_SET_IIC 0x22 |
80 | 267002cd | bellard | #define CUDA_WAKEUP 0x23 |
81 | 267002cd | bellard | #define CUDA_TIMER_TICKLE 0x24 |
82 | 267002cd | bellard | #define CUDA_COMBINED_FORMAT_IIC 0x25 |
83 | 267002cd | bellard | |
84 | 267002cd | bellard | #define CUDA_TIMER_FREQ (4700000 / 6) |
85 | 267002cd | bellard | |
86 | 267002cd | bellard | typedef struct CUDATimer { |
87 | 267002cd | bellard | unsigned int latch; |
88 | 267002cd | bellard | uint16_t counter_value; /* counter value at load time */
|
89 | 267002cd | bellard | int64_t load_time; |
90 | 267002cd | bellard | int64_t next_irq_time; |
91 | 267002cd | bellard | QEMUTimer *timer; |
92 | 267002cd | bellard | } CUDATimer; |
93 | 267002cd | bellard | |
94 | 267002cd | bellard | typedef struct CUDAState { |
95 | 267002cd | bellard | /* cuda registers */
|
96 | 267002cd | bellard | uint8_t b; /* B-side data */
|
97 | 267002cd | bellard | uint8_t a; /* A-side data */
|
98 | 267002cd | bellard | uint8_t dirb; /* B-side direction (1=output) */
|
99 | 267002cd | bellard | uint8_t dira; /* A-side direction (1=output) */
|
100 | 267002cd | bellard | uint8_t sr; /* Shift register */
|
101 | 267002cd | bellard | uint8_t acr; /* Auxiliary control register */
|
102 | 267002cd | bellard | uint8_t pcr; /* Peripheral control register */
|
103 | 267002cd | bellard | uint8_t ifr; /* Interrupt flag register */
|
104 | 267002cd | bellard | uint8_t ier; /* Interrupt enable register */
|
105 | 267002cd | bellard | uint8_t anh; /* A-side data, no handshake */
|
106 | 267002cd | bellard | |
107 | 267002cd | bellard | CUDATimer timers[2];
|
108 | 267002cd | bellard | |
109 | 267002cd | bellard | uint8_t last_b; /* last value of B register */
|
110 | 267002cd | bellard | uint8_t last_acr; /* last value of B register */
|
111 | 267002cd | bellard | |
112 | 267002cd | bellard | int data_in_size;
|
113 | 267002cd | bellard | int data_in_index;
|
114 | 267002cd | bellard | int data_out_index;
|
115 | 267002cd | bellard | |
116 | 267002cd | bellard | int irq;
|
117 | 267002cd | bellard | uint8_t autopoll; |
118 | 267002cd | bellard | uint8_t data_in[128];
|
119 | 267002cd | bellard | uint8_t data_out[16];
|
120 | 267002cd | bellard | } CUDAState; |
121 | 267002cd | bellard | |
122 | 267002cd | bellard | static CUDAState cuda_state;
|
123 | 267002cd | bellard | ADBBusState adb_bus; |
124 | 267002cd | bellard | |
125 | 267002cd | bellard | static void cuda_update(CUDAState *s); |
126 | 267002cd | bellard | static void cuda_receive_packet_from_host(CUDAState *s, |
127 | 267002cd | bellard | const uint8_t *data, int len); |
128 | 267002cd | bellard | |
129 | 267002cd | bellard | static void cuda_update_irq(CUDAState *s) |
130 | 267002cd | bellard | { |
131 | 267002cd | bellard | if (s->ifr & s->ier & SR_INT) {
|
132 | 267002cd | bellard | pic_set_irq(s->irq, 1);
|
133 | 267002cd | bellard | } else {
|
134 | 267002cd | bellard | pic_set_irq(s->irq, 0);
|
135 | 267002cd | bellard | } |
136 | 267002cd | bellard | } |
137 | 267002cd | bellard | |
138 | 267002cd | bellard | static unsigned int get_counter(CUDATimer *s) |
139 | 267002cd | bellard | { |
140 | 267002cd | bellard | int64_t d; |
141 | 267002cd | bellard | unsigned int counter; |
142 | 267002cd | bellard | |
143 | 267002cd | bellard | d = muldiv64(qemu_get_clock(vm_clock) - s->load_time, |
144 | 267002cd | bellard | CUDA_TIMER_FREQ, ticks_per_sec); |
145 | 267002cd | bellard | if (d <= s->counter_value) {
|
146 | 267002cd | bellard | counter = d; |
147 | 267002cd | bellard | } else {
|
148 | 267002cd | bellard | counter = s->latch - 1 - ((d - s->counter_value) % s->latch);
|
149 | 267002cd | bellard | } |
150 | 267002cd | bellard | return counter;
|
151 | 267002cd | bellard | } |
152 | 267002cd | bellard | |
153 | 267002cd | bellard | static void set_counter(CUDATimer *s, unsigned int val) |
154 | 267002cd | bellard | { |
155 | 267002cd | bellard | s->load_time = qemu_get_clock(vm_clock); |
156 | 267002cd | bellard | s->counter_value = val; |
157 | 267002cd | bellard | } |
158 | 267002cd | bellard | |
159 | 267002cd | bellard | static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
|
160 | 267002cd | bellard | { |
161 | 267002cd | bellard | int64_t d, next_time, base; |
162 | 267002cd | bellard | /* current counter value */
|
163 | 267002cd | bellard | d = muldiv64(current_time - s->load_time, |
164 | 267002cd | bellard | CUDA_TIMER_FREQ, ticks_per_sec); |
165 | 267002cd | bellard | if (d <= s->counter_value) {
|
166 | 267002cd | bellard | next_time = s->counter_value + 1;
|
167 | 267002cd | bellard | } else {
|
168 | 267002cd | bellard | base = ((d - s->counter_value) % s->latch); |
169 | 267002cd | bellard | base = (base * s->latch) + s->counter_value; |
170 | 267002cd | bellard | next_time = base + s->latch; |
171 | 267002cd | bellard | } |
172 | 267002cd | bellard | next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) + |
173 | 267002cd | bellard | s->load_time; |
174 | 267002cd | bellard | if (next_time <= current_time)
|
175 | 267002cd | bellard | next_time = current_time + 1;
|
176 | 267002cd | bellard | return next_time;
|
177 | 267002cd | bellard | } |
178 | 267002cd | bellard | |
179 | 267002cd | bellard | static void cuda_timer1(void *opaque) |
180 | 267002cd | bellard | { |
181 | 267002cd | bellard | CUDAState *s = opaque; |
182 | 267002cd | bellard | CUDATimer *ti = &s->timers[0];
|
183 | 267002cd | bellard | |
184 | 267002cd | bellard | ti->next_irq_time = get_next_irq_time(ti, ti->next_irq_time); |
185 | 267002cd | bellard | qemu_mod_timer(ti->timer, ti->next_irq_time); |
186 | 267002cd | bellard | s->ifr |= T1_INT; |
187 | 267002cd | bellard | cuda_update_irq(s); |
188 | 267002cd | bellard | } |
189 | 267002cd | bellard | |
190 | 267002cd | bellard | static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr) |
191 | 267002cd | bellard | { |
192 | 267002cd | bellard | CUDAState *s = opaque; |
193 | 267002cd | bellard | uint32_t val; |
194 | 267002cd | bellard | |
195 | 267002cd | bellard | addr = (addr >> 9) & 0xf; |
196 | 267002cd | bellard | switch(addr) {
|
197 | 267002cd | bellard | case 0: |
198 | 267002cd | bellard | val = s->b; |
199 | 267002cd | bellard | break;
|
200 | 267002cd | bellard | case 1: |
201 | 267002cd | bellard | val = s->a; |
202 | 267002cd | bellard | break;
|
203 | 267002cd | bellard | case 2: |
204 | 267002cd | bellard | val = s->dirb; |
205 | 267002cd | bellard | break;
|
206 | 267002cd | bellard | case 3: |
207 | 267002cd | bellard | val = s->dira; |
208 | 267002cd | bellard | break;
|
209 | 267002cd | bellard | case 4: |
210 | 267002cd | bellard | val = get_counter(&s->timers[0]) & 0xff; |
211 | 267002cd | bellard | s->ifr &= ~T1_INT; |
212 | 267002cd | bellard | cuda_update_irq(s); |
213 | 267002cd | bellard | break;
|
214 | 267002cd | bellard | case 5: |
215 | 267002cd | bellard | val = get_counter(&s->timers[0]) >> 8; |
216 | 267002cd | bellard | s->ifr &= ~T1_INT; |
217 | 267002cd | bellard | cuda_update_irq(s); |
218 | 267002cd | bellard | break;
|
219 | 267002cd | bellard | case 6: |
220 | 267002cd | bellard | val = s->timers[0].latch & 0xff; |
221 | 267002cd | bellard | break;
|
222 | 267002cd | bellard | case 7: |
223 | 267002cd | bellard | val = (s->timers[0].latch >> 8) & 0xff; |
224 | 267002cd | bellard | break;
|
225 | 267002cd | bellard | case 8: |
226 | 267002cd | bellard | val = get_counter(&s->timers[1]) & 0xff; |
227 | 267002cd | bellard | break;
|
228 | 267002cd | bellard | case 9: |
229 | 267002cd | bellard | val = get_counter(&s->timers[1]) >> 8; |
230 | 267002cd | bellard | break;
|
231 | 267002cd | bellard | case 10: |
232 | 267002cd | bellard | if (s->data_in_index < s->data_in_size) {
|
233 | 267002cd | bellard | val = s->data_in[s->data_in_index]; |
234 | 267002cd | bellard | } else {
|
235 | 267002cd | bellard | val = 0;
|
236 | 267002cd | bellard | } |
237 | 267002cd | bellard | break;
|
238 | 267002cd | bellard | case 11: |
239 | 267002cd | bellard | val = s->acr; |
240 | 267002cd | bellard | break;
|
241 | 267002cd | bellard | case 12: |
242 | 267002cd | bellard | val = s->pcr; |
243 | 267002cd | bellard | break;
|
244 | 267002cd | bellard | case 13: |
245 | 267002cd | bellard | val = s->ifr; |
246 | 267002cd | bellard | break;
|
247 | 267002cd | bellard | case 14: |
248 | 267002cd | bellard | val = s->ier; |
249 | 267002cd | bellard | break;
|
250 | 267002cd | bellard | default:
|
251 | 267002cd | bellard | case 15: |
252 | 267002cd | bellard | val = s->anh; |
253 | 267002cd | bellard | break;
|
254 | 267002cd | bellard | } |
255 | 267002cd | bellard | #ifdef DEBUG_CUDA
|
256 | 267002cd | bellard | printf("cuda: read: reg=0x%x val=%02x\n", addr, val);
|
257 | 267002cd | bellard | #endif
|
258 | 267002cd | bellard | return val;
|
259 | 267002cd | bellard | } |
260 | 267002cd | bellard | |
261 | 267002cd | bellard | static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
262 | 267002cd | bellard | { |
263 | 267002cd | bellard | CUDAState *s = opaque; |
264 | 267002cd | bellard | |
265 | 267002cd | bellard | addr = (addr >> 9) & 0xf; |
266 | 267002cd | bellard | #ifdef DEBUG_CUDA
|
267 | 267002cd | bellard | printf("cuda: write: reg=0x%x val=%02x\n", addr, val);
|
268 | 267002cd | bellard | #endif
|
269 | 267002cd | bellard | |
270 | 267002cd | bellard | switch(addr) {
|
271 | 267002cd | bellard | case 0: |
272 | 267002cd | bellard | s->b = val; |
273 | 267002cd | bellard | cuda_update(s); |
274 | 267002cd | bellard | break;
|
275 | 267002cd | bellard | case 1: |
276 | 267002cd | bellard | s->a = val; |
277 | 267002cd | bellard | break;
|
278 | 267002cd | bellard | case 2: |
279 | 267002cd | bellard | s->dirb = val; |
280 | 267002cd | bellard | break;
|
281 | 267002cd | bellard | case 3: |
282 | 267002cd | bellard | s->dira = val; |
283 | 267002cd | bellard | break;
|
284 | 267002cd | bellard | case 4: |
285 | 267002cd | bellard | val = val | (get_counter(&s->timers[0]) & 0xff00); |
286 | 267002cd | bellard | set_counter(&s->timers[0], val);
|
287 | 267002cd | bellard | break;
|
288 | 267002cd | bellard | case 5: |
289 | 267002cd | bellard | val = (val << 8) | (get_counter(&s->timers[0]) & 0xff); |
290 | 267002cd | bellard | set_counter(&s->timers[0], val);
|
291 | 267002cd | bellard | break;
|
292 | 267002cd | bellard | case 6: |
293 | 267002cd | bellard | s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; |
294 | 267002cd | bellard | break;
|
295 | 267002cd | bellard | case 7: |
296 | 267002cd | bellard | s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); |
297 | 267002cd | bellard | break;
|
298 | 267002cd | bellard | case 8: |
299 | 267002cd | bellard | val = val | (get_counter(&s->timers[1]) & 0xff00); |
300 | 267002cd | bellard | set_counter(&s->timers[1], val);
|
301 | 267002cd | bellard | break;
|
302 | 267002cd | bellard | case 9: |
303 | 267002cd | bellard | val = (val << 8) | (get_counter(&s->timers[1]) & 0xff); |
304 | 267002cd | bellard | set_counter(&s->timers[1], val);
|
305 | 267002cd | bellard | break;
|
306 | 267002cd | bellard | case 10: |
307 | 267002cd | bellard | s->sr = val; |
308 | 267002cd | bellard | break;
|
309 | 267002cd | bellard | case 11: |
310 | 267002cd | bellard | s->acr = val; |
311 | 267002cd | bellard | if ((s->acr & T1MODE) == T1MODE_CONT) {
|
312 | 267002cd | bellard | if ((s->last_acr & T1MODE) != T1MODE_CONT) {
|
313 | 267002cd | bellard | CUDATimer *ti = &s->timers[0];
|
314 | 267002cd | bellard | /* activate timer interrupt */
|
315 | 267002cd | bellard | ti->next_irq_time = get_next_irq_time(ti, qemu_get_clock(vm_clock)); |
316 | 267002cd | bellard | qemu_mod_timer(ti->timer, ti->next_irq_time); |
317 | 267002cd | bellard | } |
318 | 267002cd | bellard | } else {
|
319 | 267002cd | bellard | if ((s->last_acr & T1MODE) == T1MODE_CONT) {
|
320 | 267002cd | bellard | CUDATimer *ti = &s->timers[0];
|
321 | 267002cd | bellard | qemu_del_timer(ti->timer); |
322 | 267002cd | bellard | } |
323 | 267002cd | bellard | } |
324 | 267002cd | bellard | cuda_update(s); |
325 | 267002cd | bellard | break;
|
326 | 267002cd | bellard | case 12: |
327 | 267002cd | bellard | s->pcr = val; |
328 | 267002cd | bellard | break;
|
329 | 267002cd | bellard | case 13: |
330 | 267002cd | bellard | /* reset bits */
|
331 | 267002cd | bellard | s->ifr &= ~val; |
332 | 267002cd | bellard | cuda_update_irq(s); |
333 | 267002cd | bellard | break;
|
334 | 267002cd | bellard | case 14: |
335 | 267002cd | bellard | if (val & IER_SET) {
|
336 | 267002cd | bellard | /* set bits */
|
337 | 267002cd | bellard | s->ier |= val & 0x7f;
|
338 | 267002cd | bellard | } else {
|
339 | 267002cd | bellard | /* reset bits */
|
340 | 267002cd | bellard | s->ier &= ~val; |
341 | 267002cd | bellard | } |
342 | 267002cd | bellard | cuda_update_irq(s); |
343 | 267002cd | bellard | break;
|
344 | 267002cd | bellard | default:
|
345 | 267002cd | bellard | case 15: |
346 | 267002cd | bellard | s->anh = val; |
347 | 267002cd | bellard | break;
|
348 | 267002cd | bellard | } |
349 | 267002cd | bellard | } |
350 | 267002cd | bellard | |
351 | 267002cd | bellard | /* NOTE: TIP and TREQ are negated */
|
352 | 267002cd | bellard | static void cuda_update(CUDAState *s) |
353 | 267002cd | bellard | { |
354 | 267002cd | bellard | if (s->data_in_index < s->data_in_size) {
|
355 | 267002cd | bellard | /* data input */
|
356 | 267002cd | bellard | if (!(s->b & TIP) &&
|
357 | 267002cd | bellard | (s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { |
358 | 267002cd | bellard | s->sr = s->data_in[s->data_in_index++]; |
359 | 267002cd | bellard | s->ifr |= SR_INT; |
360 | 267002cd | bellard | cuda_update_irq(s); |
361 | 267002cd | bellard | } |
362 | 267002cd | bellard | } |
363 | 267002cd | bellard | if (s->data_in_index < s->data_in_size) {
|
364 | 267002cd | bellard | /* there is some data to read */
|
365 | 267002cd | bellard | s->b = (s->b & ~TREQ); |
366 | 267002cd | bellard | } else {
|
367 | 267002cd | bellard | s->b = (s->b | TREQ); |
368 | 267002cd | bellard | } |
369 | 267002cd | bellard | |
370 | 267002cd | bellard | if (s->acr & SR_OUT) {
|
371 | 267002cd | bellard | /* data output */
|
372 | 267002cd | bellard | if (!(s->b & TIP) &&
|
373 | 267002cd | bellard | (s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { |
374 | 267002cd | bellard | if (s->data_out_index < sizeof(s->data_out)) { |
375 | 267002cd | bellard | s->data_out[s->data_out_index++] = s->sr; |
376 | 267002cd | bellard | } |
377 | 267002cd | bellard | s->ifr |= SR_INT; |
378 | 267002cd | bellard | cuda_update_irq(s); |
379 | 267002cd | bellard | } |
380 | 267002cd | bellard | } |
381 | 267002cd | bellard | |
382 | 267002cd | bellard | /* check end of data output */
|
383 | 267002cd | bellard | if (!(s->acr & SR_OUT) && (s->last_acr & SR_OUT)) {
|
384 | 267002cd | bellard | if (s->data_out_index > 0) |
385 | 267002cd | bellard | cuda_receive_packet_from_host(s, s->data_out, s->data_out_index); |
386 | 267002cd | bellard | s->data_out_index = 0;
|
387 | 267002cd | bellard | } |
388 | 267002cd | bellard | s->last_acr = s->acr; |
389 | 267002cd | bellard | s->last_b = s->b; |
390 | 267002cd | bellard | } |
391 | 267002cd | bellard | |
392 | 267002cd | bellard | static void cuda_send_packet_to_host(CUDAState *s, |
393 | 267002cd | bellard | const uint8_t *data, int len) |
394 | 267002cd | bellard | { |
395 | 267002cd | bellard | memcpy(s->data_in, data, len); |
396 | 267002cd | bellard | s->data_in_size = len; |
397 | 267002cd | bellard | s->data_in_index = 0;
|
398 | 267002cd | bellard | cuda_update(s); |
399 | 267002cd | bellard | s->ifr |= SR_INT; |
400 | 267002cd | bellard | cuda_update_irq(s); |
401 | 267002cd | bellard | } |
402 | 267002cd | bellard | |
403 | 267002cd | bellard | void adb_send_packet(ADBBusState *bus, const uint8_t *buf, int len) |
404 | 267002cd | bellard | { |
405 | 267002cd | bellard | CUDAState *s = &cuda_state; |
406 | 267002cd | bellard | uint8_t data[16];
|
407 | 267002cd | bellard | |
408 | 267002cd | bellard | memcpy(data + 1, buf, len);
|
409 | 267002cd | bellard | data[0] = ADB_PACKET;
|
410 | 267002cd | bellard | cuda_send_packet_to_host(s, data, len + 1);
|
411 | 267002cd | bellard | } |
412 | 267002cd | bellard | |
413 | 267002cd | bellard | static void cuda_receive_packet(CUDAState *s, |
414 | 267002cd | bellard | const uint8_t *data, int len) |
415 | 267002cd | bellard | { |
416 | 267002cd | bellard | uint8_t obuf[16];
|
417 | 267002cd | bellard | int ti;
|
418 | 267002cd | bellard | |
419 | 267002cd | bellard | switch(data[0]) { |
420 | 267002cd | bellard | case CUDA_AUTOPOLL:
|
421 | 267002cd | bellard | s->autopoll = data[1];
|
422 | 267002cd | bellard | obuf[0] = CUDA_PACKET;
|
423 | 267002cd | bellard | obuf[1] = data[1]; |
424 | 267002cd | bellard | cuda_send_packet_to_host(s, obuf, 2);
|
425 | 267002cd | bellard | break;
|
426 | 267002cd | bellard | case CUDA_GET_TIME:
|
427 | 267002cd | bellard | /* XXX: add time support ? */
|
428 | 267002cd | bellard | ti = 0;
|
429 | 267002cd | bellard | obuf[0] = CUDA_PACKET;
|
430 | 267002cd | bellard | obuf[1] = 0; |
431 | 267002cd | bellard | obuf[2] = 0; |
432 | 267002cd | bellard | obuf[3] = ti >> 24; |
433 | 267002cd | bellard | obuf[4] = ti >> 16; |
434 | 267002cd | bellard | obuf[5] = ti >> 8; |
435 | 267002cd | bellard | obuf[6] = ti;
|
436 | 267002cd | bellard | cuda_send_packet_to_host(s, obuf, 7);
|
437 | 267002cd | bellard | break;
|
438 | 267002cd | bellard | case CUDA_SET_TIME:
|
439 | 267002cd | bellard | case CUDA_FILE_SERVER_FLAG:
|
440 | 267002cd | bellard | case CUDA_SET_DEVICE_LIST:
|
441 | 267002cd | bellard | case CUDA_SET_AUTO_RATE:
|
442 | 267002cd | bellard | case CUDA_SET_POWER_MESSAGES:
|
443 | 267002cd | bellard | obuf[0] = CUDA_PACKET;
|
444 | 267002cd | bellard | obuf[1] = 0; |
445 | 267002cd | bellard | cuda_send_packet_to_host(s, obuf, 2);
|
446 | 267002cd | bellard | break;
|
447 | 267002cd | bellard | default:
|
448 | 267002cd | bellard | break;
|
449 | 267002cd | bellard | } |
450 | 267002cd | bellard | } |
451 | 267002cd | bellard | |
452 | 267002cd | bellard | static void cuda_receive_packet_from_host(CUDAState *s, |
453 | 267002cd | bellard | const uint8_t *data, int len) |
454 | 267002cd | bellard | { |
455 | 267002cd | bellard | switch(data[0]) { |
456 | 267002cd | bellard | case ADB_PACKET:
|
457 | 267002cd | bellard | adb_receive_packet(&adb_bus, data + 1, len - 1); |
458 | 267002cd | bellard | break;
|
459 | 267002cd | bellard | case CUDA_PACKET:
|
460 | 267002cd | bellard | cuda_receive_packet(s, data + 1, len - 1); |
461 | 267002cd | bellard | break;
|
462 | 267002cd | bellard | } |
463 | 267002cd | bellard | } |
464 | 267002cd | bellard | |
465 | 267002cd | bellard | static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value) |
466 | 267002cd | bellard | { |
467 | 267002cd | bellard | } |
468 | 267002cd | bellard | |
469 | 267002cd | bellard | static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value) |
470 | 267002cd | bellard | { |
471 | 267002cd | bellard | } |
472 | 267002cd | bellard | |
473 | 267002cd | bellard | static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr) |
474 | 267002cd | bellard | { |
475 | 267002cd | bellard | return 0; |
476 | 267002cd | bellard | } |
477 | 267002cd | bellard | |
478 | 267002cd | bellard | static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr) |
479 | 267002cd | bellard | { |
480 | 267002cd | bellard | return 0; |
481 | 267002cd | bellard | } |
482 | 267002cd | bellard | |
483 | 267002cd | bellard | static CPUWriteMemoryFunc *cuda_write[] = {
|
484 | 267002cd | bellard | &cuda_writeb, |
485 | 267002cd | bellard | &cuda_writew, |
486 | 267002cd | bellard | &cuda_writel, |
487 | 267002cd | bellard | }; |
488 | 267002cd | bellard | |
489 | 267002cd | bellard | static CPUReadMemoryFunc *cuda_read[] = {
|
490 | 267002cd | bellard | &cuda_readb, |
491 | 267002cd | bellard | &cuda_readw, |
492 | 267002cd | bellard | &cuda_readl, |
493 | 267002cd | bellard | }; |
494 | 267002cd | bellard | |
495 | 267002cd | bellard | int cuda_init(void) |
496 | 267002cd | bellard | { |
497 | 267002cd | bellard | CUDAState *s = &cuda_state; |
498 | 267002cd | bellard | int cuda_mem_index;
|
499 | 267002cd | bellard | |
500 | 267002cd | bellard | s->timers[0].latch = 0x10000; |
501 | 267002cd | bellard | set_counter(&s->timers[0], 0xffff); |
502 | 267002cd | bellard | s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
|
503 | 267002cd | bellard | s->timers[1].latch = 0x10000; |
504 | 267002cd | bellard | set_counter(&s->timers[1], 0xffff); |
505 | 267002cd | bellard | cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
|
506 | 267002cd | bellard | return cuda_mem_index;
|
507 | 267002cd | bellard | } |