|
|
1.1 root 1: /*
1.1.1.3 root 2: * QEMU PowerMac CUDA device support
3: *
4: * Copyright (c) 2004-2007 Fabrice Bellard
5: * Copyright (c) 2007 Jocelyn Mayer
6: *
1.1 root 7: * Permission is hereby granted, free of charge, to any person obtaining a copy
8: * of this software and associated documentation files (the "Software"), to deal
9: * in the Software without restriction, including without limitation the rights
10: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11: * copies of the Software, and to permit persons to whom the Software is
12: * furnished to do so, subject to the following conditions:
13: *
14: * The above copyright notice and this permission notice shall be included in
15: * all copies or substantial portions of the Software.
16: *
17: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23: * THE SOFTWARE.
24: */
1.1.1.3 root 25: #include "hw.h"
26: #include "ppc_mac.h"
1.1.1.10! root 27: #include "adb.h"
1.1.1.3 root 28: #include "qemu-timer.h"
29: #include "sysemu.h"
1.1 root 30:
31: /* XXX: implement all timer modes */
32:
1.1.1.4 root 33: /* debug CUDA */
1.1 root 34: //#define DEBUG_CUDA
1.1.1.4 root 35:
36: /* debug CUDA packets */
1.1 root 37: //#define DEBUG_CUDA_PACKET
38:
1.1.1.4 root 39: #ifdef DEBUG_CUDA
1.1.1.5 root 40: #define CUDA_DPRINTF(fmt, ...) \
41: do { printf("CUDA: " fmt , ## __VA_ARGS__); } while (0)
1.1.1.4 root 42: #else
1.1.1.5 root 43: #define CUDA_DPRINTF(fmt, ...)
1.1.1.4 root 44: #endif
45:
1.1 root 46: /* Bits in B data register: all active low */
47: #define TREQ 0x08 /* Transfer request (input) */
48: #define TACK 0x10 /* Transfer acknowledge (output) */
49: #define TIP 0x20 /* Transfer in progress (output) */
50:
51: /* Bits in ACR */
52: #define SR_CTRL 0x1c /* Shift register control bits */
53: #define SR_EXT 0x0c /* Shift on external clock */
54: #define SR_OUT 0x10 /* Shift out if 1 */
55:
56: /* Bits in IFR and IER */
57: #define IER_SET 0x80 /* set bits in IER */
58: #define IER_CLR 0 /* clear bits in IER */
59: #define SR_INT 0x04 /* Shift register full/empty */
60: #define T1_INT 0x40 /* Timer 1 interrupt */
61: #define T2_INT 0x20 /* Timer 2 interrupt */
62:
63: /* Bits in ACR */
64: #define T1MODE 0xc0 /* Timer 1 mode */
65: #define T1MODE_CONT 0x40 /* continuous interrupts */
66:
67: /* commands (1st byte) */
68: #define ADB_PACKET 0
69: #define CUDA_PACKET 1
70: #define ERROR_PACKET 2
71: #define TIMER_PACKET 3
72: #define POWER_PACKET 4
73: #define MACIIC_PACKET 5
74: #define PMU_PACKET 6
75:
76:
77: /* CUDA commands (2nd byte) */
78: #define CUDA_WARM_START 0x0
79: #define CUDA_AUTOPOLL 0x1
80: #define CUDA_GET_6805_ADDR 0x2
81: #define CUDA_GET_TIME 0x3
82: #define CUDA_GET_PRAM 0x7
83: #define CUDA_SET_6805_ADDR 0x8
84: #define CUDA_SET_TIME 0x9
85: #define CUDA_POWERDOWN 0xa
86: #define CUDA_POWERUP_TIME 0xb
87: #define CUDA_SET_PRAM 0xc
88: #define CUDA_MS_RESET 0xd
89: #define CUDA_SEND_DFAC 0xe
90: #define CUDA_BATTERY_SWAP_SENSE 0x10
91: #define CUDA_RESET_SYSTEM 0x11
92: #define CUDA_SET_IPL 0x12
93: #define CUDA_FILE_SERVER_FLAG 0x13
94: #define CUDA_SET_AUTO_RATE 0x14
95: #define CUDA_GET_AUTO_RATE 0x16
96: #define CUDA_SET_DEVICE_LIST 0x19
97: #define CUDA_GET_DEVICE_LIST 0x1a
98: #define CUDA_SET_ONE_SECOND_MODE 0x1b
99: #define CUDA_SET_POWER_MESSAGES 0x21
100: #define CUDA_GET_SET_IIC 0x22
101: #define CUDA_WAKEUP 0x23
102: #define CUDA_TIMER_TICKLE 0x24
103: #define CUDA_COMBINED_FORMAT_IIC 0x25
104:
105: #define CUDA_TIMER_FREQ (4700000 / 6)
106: #define CUDA_ADB_POLL_FREQ 50
107:
108: /* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */
109: #define RTC_OFFSET 2082844800
110:
111: typedef struct CUDATimer {
1.1.1.3 root 112: int index;
1.1 root 113: uint16_t latch;
114: uint16_t counter_value; /* counter value at load time */
115: int64_t load_time;
116: int64_t next_irq_time;
117: QEMUTimer *timer;
118: } CUDATimer;
119:
120: typedef struct CUDAState {
1.1.1.10! root 121: MemoryRegion mem;
1.1 root 122: /* cuda registers */
123: uint8_t b; /* B-side data */
124: uint8_t a; /* A-side data */
125: uint8_t dirb; /* B-side direction (1=output) */
126: uint8_t dira; /* A-side direction (1=output) */
127: uint8_t sr; /* Shift register */
128: uint8_t acr; /* Auxiliary control register */
129: uint8_t pcr; /* Peripheral control register */
130: uint8_t ifr; /* Interrupt flag register */
131: uint8_t ier; /* Interrupt enable register */
132: uint8_t anh; /* A-side data, no handshake */
133:
134: CUDATimer timers[2];
1.1.1.3 root 135:
1.1.1.4 root 136: uint32_t tick_offset;
137:
1.1 root 138: uint8_t last_b; /* last value of B register */
139: uint8_t last_acr; /* last value of B register */
1.1.1.3 root 140:
1.1 root 141: int data_in_size;
142: int data_in_index;
143: int data_out_index;
144:
1.1.1.3 root 145: qemu_irq irq;
1.1 root 146: uint8_t autopoll;
147: uint8_t data_in[128];
148: uint8_t data_out[16];
149: QEMUTimer *adb_poll_timer;
150: } CUDAState;
151:
152: static CUDAState cuda_state;
153: ADBBusState adb_bus;
154:
155: static void cuda_update(CUDAState *s);
1.1.1.3 root 156: static void cuda_receive_packet_from_host(CUDAState *s,
1.1 root 157: const uint8_t *data, int len);
1.1.1.3 root 158: static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
1.1 root 159: int64_t current_time);
160:
161: static void cuda_update_irq(CUDAState *s)
162: {
163: if (s->ifr & s->ier & (SR_INT | T1_INT)) {
1.1.1.3 root 164: qemu_irq_raise(s->irq);
1.1 root 165: } else {
1.1.1.3 root 166: qemu_irq_lower(s->irq);
1.1 root 167: }
168: }
169:
170: static unsigned int get_counter(CUDATimer *s)
171: {
172: int64_t d;
173: unsigned int counter;
174:
1.1.1.9 root 175: d = muldiv64(qemu_get_clock_ns(vm_clock) - s->load_time,
1.1.1.6 root 176: CUDA_TIMER_FREQ, get_ticks_per_sec());
1.1 root 177: if (s->index == 0) {
178: /* the timer goes down from latch to -1 (period of latch + 2) */
179: if (d <= (s->counter_value + 1)) {
180: counter = (s->counter_value - d) & 0xffff;
181: } else {
182: counter = (d - (s->counter_value + 1)) % (s->latch + 2);
1.1.1.3 root 183: counter = (s->latch - counter) & 0xffff;
1.1 root 184: }
185: } else {
186: counter = (s->counter_value - d) & 0xffff;
187: }
188: return counter;
189: }
190:
191: static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
192: {
1.1.1.4 root 193: CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val);
1.1.1.9 root 194: ti->load_time = qemu_get_clock_ns(vm_clock);
1.1 root 195: ti->counter_value = val;
196: cuda_timer_update(s, ti, ti->load_time);
197: }
198:
199: static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
200: {
201: int64_t d, next_time;
202: unsigned int counter;
203:
204: /* current counter value */
1.1.1.3 root 205: d = muldiv64(current_time - s->load_time,
1.1.1.6 root 206: CUDA_TIMER_FREQ, get_ticks_per_sec());
1.1 root 207: /* the timer goes down from latch to -1 (period of latch + 2) */
208: if (d <= (s->counter_value + 1)) {
209: counter = (s->counter_value - d) & 0xffff;
210: } else {
211: counter = (d - (s->counter_value + 1)) % (s->latch + 2);
1.1.1.3 root 212: counter = (s->latch - counter) & 0xffff;
1.1 root 213: }
1.1.1.3 root 214:
1.1 root 215: /* Note: we consider the irq is raised on 0 */
216: if (counter == 0xffff) {
217: next_time = d + s->latch + 1;
218: } else if (counter == 0) {
219: next_time = d + s->latch + 2;
220: } else {
221: next_time = d + counter;
222: }
1.1.1.4 root 223: CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n",
224: s->latch, d, next_time - d);
1.1.1.6 root 225: next_time = muldiv64(next_time, get_ticks_per_sec(), CUDA_TIMER_FREQ) +
1.1 root 226: s->load_time;
227: if (next_time <= current_time)
228: next_time = current_time + 1;
229: return next_time;
230: }
231:
1.1.1.3 root 232: static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
1.1 root 233: int64_t current_time)
234: {
235: if (!ti->timer)
236: return;
237: if ((s->acr & T1MODE) != T1MODE_CONT) {
238: qemu_del_timer(ti->timer);
239: } else {
240: ti->next_irq_time = get_next_irq_time(ti, current_time);
241: qemu_mod_timer(ti->timer, ti->next_irq_time);
242: }
243: }
244:
245: static void cuda_timer1(void *opaque)
246: {
247: CUDAState *s = opaque;
248: CUDATimer *ti = &s->timers[0];
249:
250: cuda_timer_update(s, ti, ti->next_irq_time);
251: s->ifr |= T1_INT;
252: cuda_update_irq(s);
253: }
254:
255: static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
256: {
257: CUDAState *s = opaque;
258: uint32_t val;
259:
260: addr = (addr >> 9) & 0xf;
261: switch(addr) {
262: case 0:
263: val = s->b;
264: break;
265: case 1:
266: val = s->a;
267: break;
268: case 2:
269: val = s->dirb;
270: break;
271: case 3:
272: val = s->dira;
273: break;
274: case 4:
275: val = get_counter(&s->timers[0]) & 0xff;
276: s->ifr &= ~T1_INT;
277: cuda_update_irq(s);
278: break;
279: case 5:
280: val = get_counter(&s->timers[0]) >> 8;
281: cuda_update_irq(s);
282: break;
283: case 6:
284: val = s->timers[0].latch & 0xff;
285: break;
286: case 7:
287: /* XXX: check this */
288: val = (s->timers[0].latch >> 8) & 0xff;
289: break;
290: case 8:
291: val = get_counter(&s->timers[1]) & 0xff;
292: s->ifr &= ~T2_INT;
293: break;
294: case 9:
295: val = get_counter(&s->timers[1]) >> 8;
296: break;
297: case 10:
298: val = s->sr;
299: s->ifr &= ~SR_INT;
300: cuda_update_irq(s);
301: break;
302: case 11:
303: val = s->acr;
304: break;
305: case 12:
306: val = s->pcr;
307: break;
308: case 13:
309: val = s->ifr;
1.1.1.3 root 310: if (s->ifr & s->ier)
1.1 root 311: val |= 0x80;
312: break;
313: case 14:
314: val = s->ier | 0x80;
315: break;
316: default:
317: case 15:
318: val = s->anh;
319: break;
320: }
1.1.1.7 root 321: if (addr != 13 || val != 0) {
1.1.1.4 root 322: CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val);
1.1.1.7 root 323: }
324:
1.1 root 325: return val;
326: }
327:
328: static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
329: {
330: CUDAState *s = opaque;
1.1.1.3 root 331:
1.1 root 332: addr = (addr >> 9) & 0xf;
1.1.1.4 root 333: CUDA_DPRINTF("write: reg=0x%x val=%02x\n", (int)addr, val);
1.1 root 334:
335: switch(addr) {
336: case 0:
337: s->b = val;
338: cuda_update(s);
339: break;
340: case 1:
341: s->a = val;
342: break;
343: case 2:
344: s->dirb = val;
345: break;
346: case 3:
347: s->dira = val;
348: break;
349: case 4:
350: s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
1.1.1.9 root 351: cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
1.1 root 352: break;
353: case 5:
354: s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
355: s->ifr &= ~T1_INT;
356: set_counter(s, &s->timers[0], s->timers[0].latch);
357: break;
358: case 6:
359: s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
1.1.1.9 root 360: cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
1.1 root 361: break;
362: case 7:
363: s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
364: s->ifr &= ~T1_INT;
1.1.1.9 root 365: cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
1.1 root 366: break;
367: case 8:
368: s->timers[1].latch = val;
369: set_counter(s, &s->timers[1], val);
370: break;
371: case 9:
372: set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch);
373: break;
374: case 10:
375: s->sr = val;
376: break;
377: case 11:
378: s->acr = val;
1.1.1.9 root 379: cuda_timer_update(s, &s->timers[0], qemu_get_clock_ns(vm_clock));
1.1 root 380: cuda_update(s);
381: break;
382: case 12:
383: s->pcr = val;
384: break;
385: case 13:
386: /* reset bits */
387: s->ifr &= ~val;
388: cuda_update_irq(s);
389: break;
390: case 14:
391: if (val & IER_SET) {
392: /* set bits */
393: s->ier |= val & 0x7f;
394: } else {
395: /* reset bits */
396: s->ier &= ~val;
397: }
398: cuda_update_irq(s);
399: break;
400: default:
401: case 15:
402: s->anh = val;
403: break;
404: }
405: }
406:
407: /* NOTE: TIP and TREQ are negated */
408: static void cuda_update(CUDAState *s)
409: {
410: int packet_received, len;
411:
412: packet_received = 0;
413: if (!(s->b & TIP)) {
414: /* transfer requested from host */
415:
416: if (s->acr & SR_OUT) {
417: /* data output */
418: if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
419: if (s->data_out_index < sizeof(s->data_out)) {
1.1.1.4 root 420: CUDA_DPRINTF("send: %02x\n", s->sr);
1.1 root 421: s->data_out[s->data_out_index++] = s->sr;
422: s->ifr |= SR_INT;
423: cuda_update_irq(s);
424: }
425: }
426: } else {
427: if (s->data_in_index < s->data_in_size) {
428: /* data input */
429: if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
430: s->sr = s->data_in[s->data_in_index++];
1.1.1.4 root 431: CUDA_DPRINTF("recv: %02x\n", s->sr);
1.1 root 432: /* indicate end of transfer */
433: if (s->data_in_index >= s->data_in_size) {
434: s->b = (s->b | TREQ);
435: }
436: s->ifr |= SR_INT;
437: cuda_update_irq(s);
438: }
439: }
440: }
441: } else {
442: /* no transfer requested: handle sync case */
443: if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) {
444: /* update TREQ state each time TACK change state */
445: if (s->b & TACK)
446: s->b = (s->b | TREQ);
447: else
448: s->b = (s->b & ~TREQ);
449: s->ifr |= SR_INT;
450: cuda_update_irq(s);
451: } else {
452: if (!(s->last_b & TIP)) {
1.1.1.3 root 453: /* handle end of host to cuda transfer */
1.1 root 454: packet_received = (s->data_out_index > 0);
1.1.1.3 root 455: /* always an IRQ at the end of transfer */
1.1 root 456: s->ifr |= SR_INT;
457: cuda_update_irq(s);
458: }
459: /* signal if there is data to read */
460: if (s->data_in_index < s->data_in_size) {
461: s->b = (s->b & ~TREQ);
462: }
463: }
464: }
465:
466: s->last_acr = s->acr;
467: s->last_b = s->b;
468:
469: /* NOTE: cuda_receive_packet_from_host() can call cuda_update()
470: recursively */
471: if (packet_received) {
472: len = s->data_out_index;
473: s->data_out_index = 0;
474: cuda_receive_packet_from_host(s, s->data_out, len);
475: }
476: }
477:
1.1.1.3 root 478: static void cuda_send_packet_to_host(CUDAState *s,
1.1 root 479: const uint8_t *data, int len)
480: {
481: #ifdef DEBUG_CUDA_PACKET
482: {
483: int i;
484: printf("cuda_send_packet_to_host:\n");
485: for(i = 0; i < len; i++)
486: printf(" %02x", data[i]);
487: printf("\n");
488: }
489: #endif
490: memcpy(s->data_in, data, len);
491: s->data_in_size = len;
492: s->data_in_index = 0;
493: cuda_update(s);
494: s->ifr |= SR_INT;
495: cuda_update_irq(s);
496: }
497:
498: static void cuda_adb_poll(void *opaque)
499: {
500: CUDAState *s = opaque;
501: uint8_t obuf[ADB_MAX_OUT_LEN + 2];
502: int olen;
503:
504: olen = adb_poll(&adb_bus, obuf + 2);
505: if (olen > 0) {
506: obuf[0] = ADB_PACKET;
507: obuf[1] = 0x40; /* polled data */
508: cuda_send_packet_to_host(s, obuf, olen + 2);
509: }
1.1.1.3 root 510: qemu_mod_timer(s->adb_poll_timer,
1.1.1.9 root 511: qemu_get_clock_ns(vm_clock) +
1.1.1.6 root 512: (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
1.1 root 513: }
514:
1.1.1.3 root 515: static void cuda_receive_packet(CUDAState *s,
1.1 root 516: const uint8_t *data, int len)
517: {
518: uint8_t obuf[16];
1.1.1.4 root 519: int autopoll;
520: uint32_t ti;
1.1 root 521:
522: switch(data[0]) {
523: case CUDA_AUTOPOLL:
524: autopoll = (data[1] != 0);
525: if (autopoll != s->autopoll) {
526: s->autopoll = autopoll;
527: if (autopoll) {
1.1.1.3 root 528: qemu_mod_timer(s->adb_poll_timer,
1.1.1.9 root 529: qemu_get_clock_ns(vm_clock) +
1.1.1.6 root 530: (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ));
1.1 root 531: } else {
532: qemu_del_timer(s->adb_poll_timer);
533: }
534: }
535: obuf[0] = CUDA_PACKET;
536: obuf[1] = data[1];
537: cuda_send_packet_to_host(s, obuf, 2);
538: break;
539: case CUDA_SET_TIME:
1.1.1.4 root 540: ti = (((uint32_t)data[1]) << 24) + (((uint32_t)data[2]) << 16) + (((uint32_t)data[3]) << 8) + data[4];
1.1.1.9 root 541: s->tick_offset = ti - (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
1.1.1.4 root 542: obuf[0] = CUDA_PACKET;
543: obuf[1] = 0;
544: obuf[2] = 0;
545: cuda_send_packet_to_host(s, obuf, 3);
546: break;
547: case CUDA_GET_TIME:
1.1.1.9 root 548: ti = s->tick_offset + (qemu_get_clock_ns(vm_clock) / get_ticks_per_sec());
1.1 root 549: obuf[0] = CUDA_PACKET;
550: obuf[1] = 0;
551: obuf[2] = 0;
552: obuf[3] = ti >> 24;
553: obuf[4] = ti >> 16;
554: obuf[5] = ti >> 8;
555: obuf[6] = ti;
556: cuda_send_packet_to_host(s, obuf, 7);
557: break;
558: case CUDA_FILE_SERVER_FLAG:
559: case CUDA_SET_DEVICE_LIST:
560: case CUDA_SET_AUTO_RATE:
561: case CUDA_SET_POWER_MESSAGES:
562: obuf[0] = CUDA_PACKET;
563: obuf[1] = 0;
564: cuda_send_packet_to_host(s, obuf, 2);
565: break;
566: case CUDA_POWERDOWN:
567: obuf[0] = CUDA_PACKET;
568: obuf[1] = 0;
569: cuda_send_packet_to_host(s, obuf, 2);
1.1.1.4 root 570: qemu_system_shutdown_request();
571: break;
1.1.1.3 root 572: case CUDA_RESET_SYSTEM:
573: obuf[0] = CUDA_PACKET;
574: obuf[1] = 0;
575: cuda_send_packet_to_host(s, obuf, 2);
576: qemu_system_reset_request();
577: break;
1.1 root 578: default:
579: break;
580: }
581: }
582:
1.1.1.3 root 583: static void cuda_receive_packet_from_host(CUDAState *s,
1.1 root 584: const uint8_t *data, int len)
585: {
586: #ifdef DEBUG_CUDA_PACKET
587: {
588: int i;
589: printf("cuda_receive_packet_from_host:\n");
590: for(i = 0; i < len; i++)
591: printf(" %02x", data[i]);
592: printf("\n");
593: }
594: #endif
595: switch(data[0]) {
596: case ADB_PACKET:
597: {
598: uint8_t obuf[ADB_MAX_OUT_LEN + 2];
599: int olen;
600: olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1);
601: if (olen > 0) {
602: obuf[0] = ADB_PACKET;
603: obuf[1] = 0x00;
604: } else {
605: /* error */
606: obuf[0] = ADB_PACKET;
607: obuf[1] = -olen;
608: olen = 0;
609: }
610: cuda_send_packet_to_host(s, obuf, olen + 2);
611: }
612: break;
613: case CUDA_PACKET:
614: cuda_receive_packet(s, data + 1, len - 1);
615: break;
616: }
617: }
618:
619: static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
620: {
621: }
622:
623: static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
624: {
625: }
626:
627: static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)
628: {
629: return 0;
630: }
631:
632: static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
633: {
634: return 0;
635: }
636:
1.1.1.10! root 637: static MemoryRegionOps cuda_ops = {
! 638: .old_mmio = {
! 639: .write = {
! 640: cuda_writeb,
! 641: cuda_writew,
! 642: cuda_writel,
! 643: },
! 644: .read = {
! 645: cuda_readb,
! 646: cuda_readw,
! 647: cuda_readl,
! 648: },
! 649: },
! 650: .endianness = DEVICE_NATIVE_ENDIAN,
1.1 root 651: };
652:
1.1.1.9 root 653: static bool cuda_timer_exist(void *opaque, int version_id)
1.1.1.4 root 654: {
1.1.1.9 root 655: CUDATimer *s = opaque;
1.1.1.4 root 656:
1.1.1.9 root 657: return s->timer != NULL;
1.1.1.4 root 658: }
659:
1.1.1.9 root 660: static const VMStateDescription vmstate_cuda_timer = {
661: .name = "cuda_timer",
662: .version_id = 0,
663: .minimum_version_id = 0,
664: .minimum_version_id_old = 0,
665: .fields = (VMStateField[]) {
666: VMSTATE_UINT16(latch, CUDATimer),
667: VMSTATE_UINT16(counter_value, CUDATimer),
668: VMSTATE_INT64(load_time, CUDATimer),
669: VMSTATE_INT64(next_irq_time, CUDATimer),
670: VMSTATE_TIMER_TEST(timer, CUDATimer, cuda_timer_exist),
671: VMSTATE_END_OF_LIST()
672: }
673: };
674:
675: static const VMStateDescription vmstate_cuda = {
676: .name = "cuda",
677: .version_id = 1,
678: .minimum_version_id = 1,
679: .minimum_version_id_old = 1,
680: .fields = (VMStateField[]) {
681: VMSTATE_UINT8(a, CUDAState),
682: VMSTATE_UINT8(b, CUDAState),
683: VMSTATE_UINT8(dira, CUDAState),
684: VMSTATE_UINT8(dirb, CUDAState),
685: VMSTATE_UINT8(sr, CUDAState),
686: VMSTATE_UINT8(acr, CUDAState),
687: VMSTATE_UINT8(pcr, CUDAState),
688: VMSTATE_UINT8(ifr, CUDAState),
689: VMSTATE_UINT8(ier, CUDAState),
690: VMSTATE_UINT8(anh, CUDAState),
691: VMSTATE_INT32(data_in_size, CUDAState),
692: VMSTATE_INT32(data_in_index, CUDAState),
693: VMSTATE_INT32(data_out_index, CUDAState),
694: VMSTATE_UINT8(autopoll, CUDAState),
695: VMSTATE_BUFFER(data_in, CUDAState),
696: VMSTATE_BUFFER(data_out, CUDAState),
697: VMSTATE_UINT32(tick_offset, CUDAState),
698: VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1,
699: vmstate_cuda_timer, CUDATimer),
700: VMSTATE_END_OF_LIST()
701: }
702: };
703:
1.1.1.4 root 704: static void cuda_reset(void *opaque)
705: {
706: CUDAState *s = opaque;
707:
708: s->b = 0;
709: s->a = 0;
710: s->dirb = 0;
711: s->dira = 0;
712: s->sr = 0;
713: s->acr = 0;
714: s->pcr = 0;
715: s->ifr = 0;
716: s->ier = 0;
717: // s->ier = T1_INT | SR_INT;
718: s->anh = 0;
719: s->data_in_size = 0;
720: s->data_in_index = 0;
721: s->data_out_index = 0;
722: s->autopoll = 0;
723:
724: s->timers[0].latch = 0xffff;
725: set_counter(s, &s->timers[0], 0xffff);
726:
727: s->timers[1].latch = 0;
728: set_counter(s, &s->timers[1], 0xffff);
729: }
730:
1.1.1.10! root 731: void cuda_init (MemoryRegion **cuda_mem, qemu_irq irq)
1.1 root 732: {
1.1.1.4 root 733: struct tm tm;
1.1 root 734: CUDAState *s = &cuda_state;
735:
736: s->irq = irq;
737:
738: s->timers[0].index = 0;
1.1.1.9 root 739: s->timers[0].timer = qemu_new_timer_ns(vm_clock, cuda_timer1, s);
1.1 root 740:
741: s->timers[1].index = 1;
1.1.1.4 root 742:
743: qemu_get_timedate(&tm, 0);
744: s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET;
1.1 root 745:
1.1.1.9 root 746: s->adb_poll_timer = qemu_new_timer_ns(vm_clock, cuda_adb_poll, s);
1.1.1.10! root 747: memory_region_init_io(&s->mem, &cuda_ops, s, "cuda", 0x2000);
! 748:
! 749: *cuda_mem = &s->mem;
1.1.1.9 root 750: vmstate_register(NULL, -1, &vmstate_cuda, s);
1.1.1.4 root 751: qemu_register_reset(cuda_reset, s);
1.1 root 752: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.