1 /* 2 * QEMU PowerMac CUDA device support 3 * 4 * Copyright (c) 2004-2007 Fabrice Bellard 5 * Copyright (c) 2007 Jocelyn Mayer 6 * 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 */ 25 #include "hw/hw.h" 26 #include "hw/ppc/mac.h" 27 #include "hw/input/adb.h" 28 #include "qemu/timer.h" 29 #include "sysemu/sysemu.h" 30 31 /* XXX: implement all timer modes */ 32 33 /* debug CUDA */ 34 //#define DEBUG_CUDA 35 36 /* debug CUDA packets */ 37 //#define DEBUG_CUDA_PACKET 38 39 #ifdef DEBUG_CUDA 40 #define CUDA_DPRINTF(fmt, ...) \ 41 do { printf("CUDA: " fmt , ## __VA_ARGS__); } while (0) 42 #else 43 #define CUDA_DPRINTF(fmt, ...) 44 #endif 45 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 SR_DATA_INT 0x08 61 #define SR_CLOCK_INT 0x10 62 #define T1_INT 0x40 /* Timer 1 interrupt */ 63 #define T2_INT 0x20 /* Timer 2 interrupt */ 64 65 /* Bits in ACR */ 66 #define T1MODE 0xc0 /* Timer 1 mode */ 67 #define T1MODE_CONT 0x40 /* continuous interrupts */ 68 69 /* commands (1st byte) */ 70 #define ADB_PACKET 0 71 #define CUDA_PACKET 1 72 #define ERROR_PACKET 2 73 #define TIMER_PACKET 3 74 #define POWER_PACKET 4 75 #define MACIIC_PACKET 5 76 #define PMU_PACKET 6 77 78 79 /* CUDA commands (2nd byte) */ 80 #define CUDA_WARM_START 0x0 81 #define CUDA_AUTOPOLL 0x1 82 #define CUDA_GET_6805_ADDR 0x2 83 #define CUDA_GET_TIME 0x3 84 #define CUDA_GET_PRAM 0x7 85 #define CUDA_SET_6805_ADDR 0x8 86 #define CUDA_SET_TIME 0x9 87 #define CUDA_POWERDOWN 0xa 88 #define CUDA_POWERUP_TIME 0xb 89 #define CUDA_SET_PRAM 0xc 90 #define CUDA_MS_RESET 0xd 91 #define CUDA_SEND_DFAC 0xe 92 #define CUDA_BATTERY_SWAP_SENSE 0x10 93 #define CUDA_RESET_SYSTEM 0x11 94 #define CUDA_SET_IPL 0x12 95 #define CUDA_FILE_SERVER_FLAG 0x13 96 #define CUDA_SET_AUTO_RATE 0x14 97 #define CUDA_GET_AUTO_RATE 0x16 98 #define CUDA_SET_DEVICE_LIST 0x19 99 #define CUDA_GET_DEVICE_LIST 0x1a 100 #define CUDA_SET_ONE_SECOND_MODE 0x1b 101 #define CUDA_SET_POWER_MESSAGES 0x21 102 #define CUDA_GET_SET_IIC 0x22 103 #define CUDA_WAKEUP 0x23 104 #define CUDA_TIMER_TICKLE 0x24 105 #define CUDA_COMBINED_FORMAT_IIC 0x25 106 107 #define CUDA_TIMER_FREQ (4700000 / 6) 108 #define CUDA_ADB_POLL_FREQ 50 109 110 /* CUDA returns time_t's offset from Jan 1, 1904, not 1970 */ 111 #define RTC_OFFSET 2082844800 112 113 static void cuda_update(CUDAState *s); 114 static void cuda_receive_packet_from_host(CUDAState *s, 115 const uint8_t *data, int len); 116 static void cuda_timer_update(CUDAState *s, CUDATimer *ti, 117 int64_t current_time); 118 119 static void cuda_update_irq(CUDAState *s) 120 { 121 if (s->ifr & s->ier & (SR_INT | T1_INT)) { 122 qemu_irq_raise(s->irq); 123 } else { 124 qemu_irq_lower(s->irq); 125 } 126 } 127 128 static uint64_t get_tb(uint64_t freq) 129 { 130 return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 131 freq, get_ticks_per_sec()); 132 } 133 134 static unsigned int get_counter(CUDATimer *s) 135 { 136 int64_t d; 137 unsigned int counter; 138 uint64_t tb_diff; 139 140 /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup. */ 141 tb_diff = get_tb(s->frequency) - s->load_time; 142 d = (tb_diff * 0xBF401675E5DULL) / (s->frequency << 24); 143 144 if (s->index == 0) { 145 /* the timer goes down from latch to -1 (period of latch + 2) */ 146 if (d <= (s->counter_value + 1)) { 147 counter = (s->counter_value - d) & 0xffff; 148 } else { 149 counter = (d - (s->counter_value + 1)) % (s->latch + 2); 150 counter = (s->latch - counter) & 0xffff; 151 } 152 } else { 153 counter = (s->counter_value - d) & 0xffff; 154 } 155 return counter; 156 } 157 158 static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val) 159 { 160 CUDA_DPRINTF("T%d.counter=%d\n", 1 + (ti->timer == NULL), val); 161 ti->load_time = get_tb(s->frequency); 162 ti->counter_value = val; 163 cuda_timer_update(s, ti, ti->load_time); 164 } 165 166 static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) 167 { 168 int64_t d, next_time; 169 unsigned int counter; 170 171 /* current counter value */ 172 d = muldiv64(current_time - s->load_time, 173 CUDA_TIMER_FREQ, get_ticks_per_sec()); 174 /* the timer goes down from latch to -1 (period of latch + 2) */ 175 if (d <= (s->counter_value + 1)) { 176 counter = (s->counter_value - d) & 0xffff; 177 } else { 178 counter = (d - (s->counter_value + 1)) % (s->latch + 2); 179 counter = (s->latch - counter) & 0xffff; 180 } 181 182 /* Note: we consider the irq is raised on 0 */ 183 if (counter == 0xffff) { 184 next_time = d + s->latch + 1; 185 } else if (counter == 0) { 186 next_time = d + s->latch + 2; 187 } else { 188 next_time = d + counter; 189 } 190 CUDA_DPRINTF("latch=%d counter=%" PRId64 " delta_next=%" PRId64 "\n", 191 s->latch, d, next_time - d); 192 next_time = muldiv64(next_time, get_ticks_per_sec(), CUDA_TIMER_FREQ) + 193 s->load_time; 194 if (next_time <= current_time) 195 next_time = current_time + 1; 196 return next_time; 197 } 198 199 static void cuda_timer_update(CUDAState *s, CUDATimer *ti, 200 int64_t current_time) 201 { 202 if (!ti->timer) 203 return; 204 if ((s->acr & T1MODE) != T1MODE_CONT) { 205 timer_del(ti->timer); 206 } else { 207 ti->next_irq_time = get_next_irq_time(ti, current_time); 208 timer_mod(ti->timer, ti->next_irq_time); 209 } 210 } 211 212 static void cuda_timer1(void *opaque) 213 { 214 CUDAState *s = opaque; 215 CUDATimer *ti = &s->timers[0]; 216 217 cuda_timer_update(s, ti, ti->next_irq_time); 218 s->ifr |= T1_INT; 219 cuda_update_irq(s); 220 } 221 222 static uint32_t cuda_readb(void *opaque, hwaddr addr) 223 { 224 CUDAState *s = opaque; 225 uint32_t val; 226 227 addr = (addr >> 9) & 0xf; 228 switch(addr) { 229 case 0: 230 val = s->b; 231 break; 232 case 1: 233 val = s->a; 234 break; 235 case 2: 236 val = s->dirb; 237 break; 238 case 3: 239 val = s->dira; 240 break; 241 case 4: 242 val = get_counter(&s->timers[0]) & 0xff; 243 s->ifr &= ~T1_INT; 244 cuda_update_irq(s); 245 break; 246 case 5: 247 val = get_counter(&s->timers[0]) >> 8; 248 cuda_update_irq(s); 249 break; 250 case 6: 251 val = s->timers[0].latch & 0xff; 252 break; 253 case 7: 254 /* XXX: check this */ 255 val = (s->timers[0].latch >> 8) & 0xff; 256 break; 257 case 8: 258 val = get_counter(&s->timers[1]) & 0xff; 259 s->ifr &= ~T2_INT; 260 break; 261 case 9: 262 val = get_counter(&s->timers[1]) >> 8; 263 break; 264 case 10: 265 val = s->sr; 266 s->ifr &= ~(SR_INT | SR_CLOCK_INT | SR_DATA_INT); 267 cuda_update_irq(s); 268 break; 269 case 11: 270 val = s->acr; 271 break; 272 case 12: 273 val = s->pcr; 274 break; 275 case 13: 276 val = s->ifr; 277 if (s->ifr & s->ier) 278 val |= 0x80; 279 break; 280 case 14: 281 val = s->ier | 0x80; 282 break; 283 default: 284 case 15: 285 val = s->anh; 286 break; 287 } 288 if (addr != 13 || val != 0) { 289 CUDA_DPRINTF("read: reg=0x%x val=%02x\n", (int)addr, val); 290 } 291 292 return val; 293 } 294 295 static void cuda_writeb(void *opaque, hwaddr addr, uint32_t val) 296 { 297 CUDAState *s = opaque; 298 299 addr = (addr >> 9) & 0xf; 300 CUDA_DPRINTF("write: reg=0x%x val=%02x\n", (int)addr, val); 301 302 switch(addr) { 303 case 0: 304 s->b = val; 305 cuda_update(s); 306 break; 307 case 1: 308 s->a = val; 309 break; 310 case 2: 311 s->dirb = val; 312 break; 313 case 3: 314 s->dira = val; 315 break; 316 case 4: 317 s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; 318 cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); 319 break; 320 case 5: 321 s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); 322 s->ifr &= ~T1_INT; 323 set_counter(s, &s->timers[0], s->timers[0].latch); 324 break; 325 case 6: 326 s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; 327 cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); 328 break; 329 case 7: 330 s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); 331 s->ifr &= ~T1_INT; 332 cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); 333 break; 334 case 8: 335 s->timers[1].latch = val; 336 set_counter(s, &s->timers[1], val); 337 break; 338 case 9: 339 set_counter(s, &s->timers[1], (val << 8) | s->timers[1].latch); 340 break; 341 case 10: 342 s->sr = val; 343 break; 344 case 11: 345 s->acr = val; 346 cuda_timer_update(s, &s->timers[0], qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); 347 cuda_update(s); 348 break; 349 case 12: 350 s->pcr = val; 351 break; 352 case 13: 353 /* reset bits */ 354 s->ifr &= ~val; 355 cuda_update_irq(s); 356 break; 357 case 14: 358 if (val & IER_SET) { 359 /* set bits */ 360 s->ier |= val & 0x7f; 361 } else { 362 /* reset bits */ 363 s->ier &= ~val; 364 } 365 cuda_update_irq(s); 366 break; 367 default: 368 case 15: 369 s->anh = val; 370 break; 371 } 372 } 373 374 /* NOTE: TIP and TREQ are negated */ 375 static void cuda_update(CUDAState *s) 376 { 377 int packet_received, len; 378 379 packet_received = 0; 380 if (!(s->b & TIP)) { 381 /* transfer requested from host */ 382 383 if (s->acr & SR_OUT) { 384 /* data output */ 385 if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { 386 if (s->data_out_index < sizeof(s->data_out)) { 387 CUDA_DPRINTF("send: %02x\n", s->sr); 388 s->data_out[s->data_out_index++] = s->sr; 389 s->ifr |= SR_INT; 390 cuda_update_irq(s); 391 } 392 } 393 } else { 394 if (s->data_in_index < s->data_in_size) { 395 /* data input */ 396 if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { 397 s->sr = s->data_in[s->data_in_index++]; 398 CUDA_DPRINTF("recv: %02x\n", s->sr); 399 /* indicate end of transfer */ 400 if (s->data_in_index >= s->data_in_size) { 401 s->b = (s->b | TREQ); 402 } 403 s->ifr |= SR_INT; 404 cuda_update_irq(s); 405 } 406 } 407 } 408 } else { 409 /* no transfer requested: handle sync case */ 410 if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) { 411 /* update TREQ state each time TACK change state */ 412 if (s->b & TACK) 413 s->b = (s->b | TREQ); 414 else 415 s->b = (s->b & ~TREQ); 416 s->ifr |= SR_INT; 417 cuda_update_irq(s); 418 } else { 419 if (!(s->last_b & TIP)) { 420 /* handle end of host to cuda transfer */ 421 packet_received = (s->data_out_index > 0); 422 /* always an IRQ at the end of transfer */ 423 s->ifr |= SR_INT; 424 cuda_update_irq(s); 425 } 426 /* signal if there is data to read */ 427 if (s->data_in_index < s->data_in_size) { 428 s->b = (s->b & ~TREQ); 429 } 430 } 431 } 432 433 s->last_acr = s->acr; 434 s->last_b = s->b; 435 436 /* NOTE: cuda_receive_packet_from_host() can call cuda_update() 437 recursively */ 438 if (packet_received) { 439 len = s->data_out_index; 440 s->data_out_index = 0; 441 cuda_receive_packet_from_host(s, s->data_out, len); 442 } 443 } 444 445 static void cuda_send_packet_to_host(CUDAState *s, 446 const uint8_t *data, int len) 447 { 448 #ifdef DEBUG_CUDA_PACKET 449 { 450 int i; 451 printf("cuda_send_packet_to_host:\n"); 452 for(i = 0; i < len; i++) 453 printf(" %02x", data[i]); 454 printf("\n"); 455 } 456 #endif 457 memcpy(s->data_in, data, len); 458 s->data_in_size = len; 459 s->data_in_index = 0; 460 cuda_update(s); 461 s->ifr |= SR_INT; 462 cuda_update_irq(s); 463 } 464 465 static void cuda_adb_poll(void *opaque) 466 { 467 CUDAState *s = opaque; 468 uint8_t obuf[ADB_MAX_OUT_LEN + 2]; 469 int olen; 470 471 olen = adb_poll(&s->adb_bus, obuf + 2); 472 if (olen > 0) { 473 obuf[0] = ADB_PACKET; 474 obuf[1] = 0x40; /* polled data */ 475 cuda_send_packet_to_host(s, obuf, olen + 2); 476 } 477 timer_mod(s->adb_poll_timer, 478 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 479 (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ)); 480 } 481 482 static void cuda_receive_packet(CUDAState *s, 483 const uint8_t *data, int len) 484 { 485 uint8_t obuf[16] = { CUDA_PACKET, 0, data[0] }; 486 int autopoll; 487 uint32_t ti; 488 489 switch(data[0]) { 490 case CUDA_AUTOPOLL: 491 autopoll = (data[1] != 0); 492 if (autopoll != s->autopoll) { 493 s->autopoll = autopoll; 494 if (autopoll) { 495 timer_mod(s->adb_poll_timer, 496 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 497 (get_ticks_per_sec() / CUDA_ADB_POLL_FREQ)); 498 } else { 499 timer_del(s->adb_poll_timer); 500 } 501 } 502 cuda_send_packet_to_host(s, obuf, 3); 503 break; 504 case CUDA_GET_6805_ADDR: 505 cuda_send_packet_to_host(s, obuf, 3); 506 break; 507 case CUDA_SET_TIME: 508 ti = (((uint32_t)data[1]) << 24) + (((uint32_t)data[2]) << 16) + (((uint32_t)data[3]) << 8) + data[4]; 509 s->tick_offset = ti - (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / get_ticks_per_sec()); 510 cuda_send_packet_to_host(s, obuf, 3); 511 break; 512 case CUDA_GET_TIME: 513 ti = s->tick_offset + (qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / get_ticks_per_sec()); 514 obuf[3] = ti >> 24; 515 obuf[4] = ti >> 16; 516 obuf[5] = ti >> 8; 517 obuf[6] = ti; 518 cuda_send_packet_to_host(s, obuf, 7); 519 break; 520 case CUDA_FILE_SERVER_FLAG: 521 case CUDA_SET_DEVICE_LIST: 522 case CUDA_SET_AUTO_RATE: 523 case CUDA_SET_POWER_MESSAGES: 524 cuda_send_packet_to_host(s, obuf, 3); 525 break; 526 case CUDA_POWERDOWN: 527 cuda_send_packet_to_host(s, obuf, 3); 528 qemu_system_shutdown_request(); 529 break; 530 case CUDA_RESET_SYSTEM: 531 cuda_send_packet_to_host(s, obuf, 3); 532 qemu_system_reset_request(); 533 break; 534 case CUDA_COMBINED_FORMAT_IIC: 535 obuf[0] = ERROR_PACKET; 536 obuf[1] = 0x5; 537 obuf[2] = CUDA_PACKET; 538 obuf[3] = data[0]; 539 cuda_send_packet_to_host(s, obuf, 4); 540 break; 541 case CUDA_GET_SET_IIC: 542 if (len == 4) { 543 cuda_send_packet_to_host(s, obuf, 3); 544 } else { 545 obuf[0] = ERROR_PACKET; 546 obuf[1] = 0x2; 547 obuf[2] = CUDA_PACKET; 548 obuf[3] = data[0]; 549 cuda_send_packet_to_host(s, obuf, 4); 550 } 551 break; 552 default: 553 break; 554 } 555 } 556 557 static void cuda_receive_packet_from_host(CUDAState *s, 558 const uint8_t *data, int len) 559 { 560 #ifdef DEBUG_CUDA_PACKET 561 { 562 int i; 563 printf("cuda_receive_packet_from_host:\n"); 564 for(i = 0; i < len; i++) 565 printf(" %02x", data[i]); 566 printf("\n"); 567 } 568 #endif 569 switch(data[0]) { 570 case ADB_PACKET: 571 { 572 uint8_t obuf[ADB_MAX_OUT_LEN + 3]; 573 int olen; 574 olen = adb_request(&s->adb_bus, obuf + 2, data + 1, len - 1); 575 if (olen > 0) { 576 obuf[0] = ADB_PACKET; 577 obuf[1] = 0x00; 578 cuda_send_packet_to_host(s, obuf, olen + 2); 579 } else { 580 /* error */ 581 obuf[0] = ADB_PACKET; 582 obuf[1] = -olen; 583 obuf[2] = data[1]; 584 olen = 0; 585 cuda_send_packet_to_host(s, obuf, olen + 3); 586 } 587 } 588 break; 589 case CUDA_PACKET: 590 cuda_receive_packet(s, data + 1, len - 1); 591 break; 592 } 593 } 594 595 static void cuda_writew (void *opaque, hwaddr addr, uint32_t value) 596 { 597 } 598 599 static void cuda_writel (void *opaque, hwaddr addr, uint32_t value) 600 { 601 } 602 603 static uint32_t cuda_readw (void *opaque, hwaddr addr) 604 { 605 return 0; 606 } 607 608 static uint32_t cuda_readl (void *opaque, hwaddr addr) 609 { 610 return 0; 611 } 612 613 static const MemoryRegionOps cuda_ops = { 614 .old_mmio = { 615 .write = { 616 cuda_writeb, 617 cuda_writew, 618 cuda_writel, 619 }, 620 .read = { 621 cuda_readb, 622 cuda_readw, 623 cuda_readl, 624 }, 625 }, 626 .endianness = DEVICE_NATIVE_ENDIAN, 627 }; 628 629 static bool cuda_timer_exist(void *opaque, int version_id) 630 { 631 CUDATimer *s = opaque; 632 633 return s->timer != NULL; 634 } 635 636 static const VMStateDescription vmstate_cuda_timer = { 637 .name = "cuda_timer", 638 .version_id = 0, 639 .minimum_version_id = 0, 640 .fields = (VMStateField[]) { 641 VMSTATE_UINT16(latch, CUDATimer), 642 VMSTATE_UINT16(counter_value, CUDATimer), 643 VMSTATE_INT64(load_time, CUDATimer), 644 VMSTATE_INT64(next_irq_time, CUDATimer), 645 VMSTATE_TIMER_PTR_TEST(timer, CUDATimer, cuda_timer_exist), 646 VMSTATE_END_OF_LIST() 647 } 648 }; 649 650 static const VMStateDescription vmstate_cuda = { 651 .name = "cuda", 652 .version_id = 2, 653 .minimum_version_id = 2, 654 .fields = (VMStateField[]) { 655 VMSTATE_UINT8(a, CUDAState), 656 VMSTATE_UINT8(b, CUDAState), 657 VMSTATE_UINT8(dira, CUDAState), 658 VMSTATE_UINT8(dirb, CUDAState), 659 VMSTATE_UINT8(sr, CUDAState), 660 VMSTATE_UINT8(acr, CUDAState), 661 VMSTATE_UINT8(pcr, CUDAState), 662 VMSTATE_UINT8(ifr, CUDAState), 663 VMSTATE_UINT8(ier, CUDAState), 664 VMSTATE_UINT8(anh, CUDAState), 665 VMSTATE_INT32(data_in_size, CUDAState), 666 VMSTATE_INT32(data_in_index, CUDAState), 667 VMSTATE_INT32(data_out_index, CUDAState), 668 VMSTATE_UINT8(autopoll, CUDAState), 669 VMSTATE_BUFFER(data_in, CUDAState), 670 VMSTATE_BUFFER(data_out, CUDAState), 671 VMSTATE_UINT32(tick_offset, CUDAState), 672 VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1, 673 vmstate_cuda_timer, CUDATimer), 674 VMSTATE_TIMER_PTR(adb_poll_timer, CUDAState), 675 VMSTATE_END_OF_LIST() 676 } 677 }; 678 679 static void cuda_reset(DeviceState *dev) 680 { 681 CUDAState *s = CUDA(dev); 682 683 s->b = 0; 684 s->a = 0; 685 s->dirb = 0; 686 s->dira = 0; 687 s->sr = 0; 688 s->acr = 0; 689 s->pcr = 0; 690 s->ifr = 0; 691 s->ier = 0; 692 // s->ier = T1_INT | SR_INT; 693 s->anh = 0; 694 s->data_in_size = 0; 695 s->data_in_index = 0; 696 s->data_out_index = 0; 697 s->autopoll = 0; 698 699 s->timers[0].latch = 0xffff; 700 set_counter(s, &s->timers[0], 0xffff); 701 702 s->timers[1].latch = 0; 703 set_counter(s, &s->timers[1], 0xffff); 704 } 705 706 static void cuda_realizefn(DeviceState *dev, Error **errp) 707 { 708 CUDAState *s = CUDA(dev); 709 struct tm tm; 710 711 s->timers[0].timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_timer1, s); 712 s->timers[0].frequency = s->frequency; 713 s->timers[1].frequency = s->frequency; 714 715 qemu_get_timedate(&tm, 0); 716 s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET; 717 718 s->adb_poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_adb_poll, s); 719 } 720 721 static void cuda_initfn(Object *obj) 722 { 723 SysBusDevice *d = SYS_BUS_DEVICE(obj); 724 CUDAState *s = CUDA(obj); 725 int i; 726 727 memory_region_init_io(&s->mem, obj, &cuda_ops, s, "cuda", 0x2000); 728 sysbus_init_mmio(d, &s->mem); 729 sysbus_init_irq(d, &s->irq); 730 731 for (i = 0; i < ARRAY_SIZE(s->timers); i++) { 732 s->timers[i].index = i; 733 } 734 735 qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS, 736 DEVICE(obj), "adb.0"); 737 } 738 739 static Property cuda_properties[] = { 740 DEFINE_PROP_UINT64("frequency", CUDAState, frequency, 0), 741 DEFINE_PROP_END_OF_LIST() 742 }; 743 744 static void cuda_class_init(ObjectClass *oc, void *data) 745 { 746 DeviceClass *dc = DEVICE_CLASS(oc); 747 748 dc->realize = cuda_realizefn; 749 dc->reset = cuda_reset; 750 dc->vmsd = &vmstate_cuda; 751 dc->props = cuda_properties; 752 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 753 } 754 755 static const TypeInfo cuda_type_info = { 756 .name = TYPE_CUDA, 757 .parent = TYPE_SYS_BUS_DEVICE, 758 .instance_size = sizeof(CUDAState), 759 .instance_init = cuda_initfn, 760 .class_init = cuda_class_init, 761 }; 762 763 static void cuda_register_types(void) 764 { 765 type_register_static(&cuda_type_info); 766 } 767 768 type_init(cuda_register_types) 769