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