cuda.c (d9c92ae335d99dd32c52fc7b075ef4820b4c6571) | cuda.c (2e3e5c7e92452900e2bb5143c5fb6d47c0897a34) |
---|---|
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 --- 51 unchanged lines hidden (view full) --- 60 * the timebase frequency and cuda_get_counter_value() with 61 * cuda_get_load_time() to steer MacOS to calculate calibrate its timers 62 * correctly for both TCG and KVM (see commit b981289c49 "PPC: Cuda: Use cuda 63 * timer to expose tbfreq to guest" for more information) */ 64 65static uint64_t cuda_get_counter_value(MOS6522State *s, MOS6522Timer *ti) 66{ 67 MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj); | 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 --- 51 unchanged lines hidden (view full) --- 60 * the timebase frequency and cuda_get_counter_value() with 61 * cuda_get_load_time() to steer MacOS to calculate calibrate its timers 62 * correctly for both TCG and KVM (see commit b981289c49 "PPC: Cuda: Use cuda 63 * timer to expose tbfreq to guest" for more information) */ 64 65static uint64_t cuda_get_counter_value(MOS6522State *s, MOS6522Timer *ti) 66{ 67 MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj); |
68 CUDAState *cs = mcs->cuda; | 68 CUDAState *cs = container_of(mcs, CUDAState, mos6522_cuda); |
69 70 /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup */ 71 uint64_t tb_diff = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 72 cs->tb_frequency, NANOSECONDS_PER_SECOND) - 73 ti->load_time; 74 75 return (tb_diff * 0xBF401675E5DULL) / (cs->tb_frequency << 24); 76} 77 78static uint64_t cuda_get_load_time(MOS6522State *s, MOS6522Timer *ti) 79{ 80 MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj); | 69 70 /* Reverse of the tb calculation algorithm that Mac OS X uses on bootup */ 71 uint64_t tb_diff = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 72 cs->tb_frequency, NANOSECONDS_PER_SECOND) - 73 ti->load_time; 74 75 return (tb_diff * 0xBF401675E5DULL) / (cs->tb_frequency << 24); 76} 77 78static uint64_t cuda_get_load_time(MOS6522State *s, MOS6522Timer *ti) 79{ 80 MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj); |
81 CUDAState *cs = mcs->cuda; | 81 CUDAState *cs = container_of(mcs, CUDAState, mos6522_cuda); |
82 83 uint64_t load_time = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 84 cs->tb_frequency, NANOSECONDS_PER_SECOND); 85 return load_time; 86} 87 88static void cuda_set_sr_int(void *opaque) 89{ 90 CUDAState *s = opaque; | 82 83 uint64_t load_time = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), 84 cs->tb_frequency, NANOSECONDS_PER_SECOND); 85 return load_time; 86} 87 88static void cuda_set_sr_int(void *opaque) 89{ 90 CUDAState *s = opaque; |
91 MOS6522CUDAState *mcs = s->mos6522_cuda; | 91 MOS6522CUDAState *mcs = &s->mos6522_cuda; |
92 MOS6522State *ms = MOS6522(mcs); 93 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); 94 95 mdc->set_sr_int(ms); 96} 97 98static void cuda_delay_set_sr_int(CUDAState *s) 99{ | 92 MOS6522State *ms = MOS6522(mcs); 93 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); 94 95 mdc->set_sr_int(ms); 96} 97 98static void cuda_delay_set_sr_int(CUDAState *s) 99{ |
100 MOS6522CUDAState *mcs = s->mos6522_cuda; | 100 MOS6522CUDAState *mcs = &s->mos6522_cuda; |
101 MOS6522State *ms = MOS6522(mcs); 102 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); 103 int64_t expire; 104 105 if (ms->dirb == 0xff || s->sr_delay_ns == 0) { 106 /* Disabled or not in Mac OS, fire the IRQ directly */ 107 mdc->set_sr_int(ms); 108 return; 109 } 110 111 trace_cuda_delay_set_sr_int(); 112 113 expire = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->sr_delay_ns; 114 timer_mod(s->sr_delay_timer, expire); 115} 116 117/* NOTE: TIP and TREQ are negated */ 118static void cuda_update(CUDAState *s) 119{ | 101 MOS6522State *ms = MOS6522(mcs); 102 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); 103 int64_t expire; 104 105 if (ms->dirb == 0xff || s->sr_delay_ns == 0) { 106 /* Disabled or not in Mac OS, fire the IRQ directly */ 107 mdc->set_sr_int(ms); 108 return; 109 } 110 111 trace_cuda_delay_set_sr_int(); 112 113 expire = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->sr_delay_ns; 114 timer_mod(s->sr_delay_timer, expire); 115} 116 117/* NOTE: TIP and TREQ are negated */ 118static void cuda_update(CUDAState *s) 119{ |
120 MOS6522CUDAState *mcs = s->mos6522_cuda; | 120 MOS6522CUDAState *mcs = &s->mos6522_cuda; |
121 MOS6522State *ms = MOS6522(mcs); 122 int packet_received, len; 123 124 packet_received = 0; 125 if (!(ms->b & TIP)) { 126 /* transfer requested from host */ 127 128 if (ms->acr & SR_OUT) { --- 328 unchanged lines hidden (view full) --- 457 cuda_receive_packet(s, data + 1, len - 1); 458 break; 459 } 460} 461 462static uint64_t mos6522_cuda_read(void *opaque, hwaddr addr, unsigned size) 463{ 464 CUDAState *s = opaque; | 121 MOS6522State *ms = MOS6522(mcs); 122 int packet_received, len; 123 124 packet_received = 0; 125 if (!(ms->b & TIP)) { 126 /* transfer requested from host */ 127 128 if (ms->acr & SR_OUT) { --- 328 unchanged lines hidden (view full) --- 457 cuda_receive_packet(s, data + 1, len - 1); 458 break; 459 } 460} 461 462static uint64_t mos6522_cuda_read(void *opaque, hwaddr addr, unsigned size) 463{ 464 CUDAState *s = opaque; |
465 MOS6522CUDAState *mcs = s->mos6522_cuda; | 465 MOS6522CUDAState *mcs = &s->mos6522_cuda; |
466 MOS6522State *ms = MOS6522(mcs); 467 468 addr = (addr >> 9) & 0xf; 469 return mos6522_read(ms, addr, size); 470} 471 472static void mos6522_cuda_write(void *opaque, hwaddr addr, uint64_t val, 473 unsigned size) 474{ 475 CUDAState *s = opaque; | 466 MOS6522State *ms = MOS6522(mcs); 467 468 addr = (addr >> 9) & 0xf; 469 return mos6522_read(ms, addr, size); 470} 471 472static void mos6522_cuda_write(void *opaque, hwaddr addr, uint64_t val, 473 unsigned size) 474{ 475 CUDAState *s = opaque; |
476 MOS6522CUDAState *mcs = s->mos6522_cuda; | 476 MOS6522CUDAState *mcs = &s->mos6522_cuda; |
477 MOS6522State *ms = MOS6522(mcs); 478 479 addr = (addr >> 9) & 0xf; 480 mos6522_write(ms, addr, val, size); 481} 482 483static const MemoryRegionOps mos6522_cuda_ops = { 484 .read = mos6522_cuda_read, 485 .write = mos6522_cuda_write, 486 .endianness = DEVICE_BIG_ENDIAN, 487 .valid = { 488 .min_access_size = 1, 489 .max_access_size = 1, 490 }, 491}; 492 493static const VMStateDescription vmstate_cuda = { 494 .name = "cuda", | 477 MOS6522State *ms = MOS6522(mcs); 478 479 addr = (addr >> 9) & 0xf; 480 mos6522_write(ms, addr, val, size); 481} 482 483static const MemoryRegionOps mos6522_cuda_ops = { 484 .read = mos6522_cuda_read, 485 .write = mos6522_cuda_write, 486 .endianness = DEVICE_BIG_ENDIAN, 487 .valid = { 488 .min_access_size = 1, 489 .max_access_size = 1, 490 }, 491}; 492 493static const VMStateDescription vmstate_cuda = { 494 .name = "cuda", |
495 .version_id = 4, 496 .minimum_version_id = 4, | 495 .version_id = 5, 496 .minimum_version_id = 5, |
497 .fields = (VMStateField[]) { | 497 .fields = (VMStateField[]) { |
498 VMSTATE_STRUCT(mos6522_cuda.parent_obj, CUDAState, 0, vmstate_mos6522, 499 MOS6522State), |
|
498 VMSTATE_UINT8(last_b, CUDAState), 499 VMSTATE_UINT8(last_acr, CUDAState), 500 VMSTATE_INT32(data_in_size, CUDAState), 501 VMSTATE_INT32(data_in_index, CUDAState), 502 VMSTATE_INT32(data_out_index, CUDAState), 503 VMSTATE_UINT8(autopoll, CUDAState), 504 VMSTATE_UINT8(autopoll_rate_ms, CUDAState), 505 VMSTATE_UINT16(adb_poll_mask, CUDAState), --- 19 unchanged lines hidden (view full) --- 525static void cuda_realize(DeviceState *dev, Error **errp) 526{ 527 CUDAState *s = CUDA(dev); 528 SysBusDevice *sbd; 529 MOS6522State *ms; 530 DeviceState *d; 531 struct tm tm; 532 | 500 VMSTATE_UINT8(last_b, CUDAState), 501 VMSTATE_UINT8(last_acr, CUDAState), 502 VMSTATE_INT32(data_in_size, CUDAState), 503 VMSTATE_INT32(data_in_index, CUDAState), 504 VMSTATE_INT32(data_out_index, CUDAState), 505 VMSTATE_UINT8(autopoll, CUDAState), 506 VMSTATE_UINT8(autopoll_rate_ms, CUDAState), 507 VMSTATE_UINT16(adb_poll_mask, CUDAState), --- 19 unchanged lines hidden (view full) --- 527static void cuda_realize(DeviceState *dev, Error **errp) 528{ 529 CUDAState *s = CUDA(dev); 530 SysBusDevice *sbd; 531 MOS6522State *ms; 532 DeviceState *d; 533 struct tm tm; 534 |
533 d = qdev_create(NULL, TYPE_MOS6522_CUDA); 534 object_property_set_link(OBJECT(d), OBJECT(s), "cuda", errp); 535 qdev_init_nofail(d); 536 s->mos6522_cuda = MOS6522_CUDA(d); 537 | |
538 /* Pass IRQ from 6522 */ | 535 /* Pass IRQ from 6522 */ |
536 d = DEVICE(&s->mos6522_cuda); |
|
539 ms = MOS6522(d); 540 sbd = SYS_BUS_DEVICE(s); 541 sysbus_pass_irq(sbd, SYS_BUS_DEVICE(ms)); 542 543 qemu_get_timedate(&tm, 0); 544 s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET; 545 546 s->sr_delay_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_set_sr_int, s); --- 4 unchanged lines hidden (view full) --- 551 s->autopoll_rate_ms = 20; 552} 553 554static void cuda_init(Object *obj) 555{ 556 CUDAState *s = CUDA(obj); 557 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 558 | 537 ms = MOS6522(d); 538 sbd = SYS_BUS_DEVICE(s); 539 sysbus_pass_irq(sbd, SYS_BUS_DEVICE(ms)); 540 541 qemu_get_timedate(&tm, 0); 542 s->tick_offset = (uint32_t)mktimegm(&tm) + RTC_OFFSET; 543 544 s->sr_delay_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cuda_set_sr_int, s); --- 4 unchanged lines hidden (view full) --- 549 s->autopoll_rate_ms = 20; 550} 551 552static void cuda_init(Object *obj) 553{ 554 CUDAState *s = CUDA(obj); 555 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 556 |
557 object_initialize(&s->mos6522_cuda, sizeof(s->mos6522_cuda), 558 TYPE_MOS6522_CUDA); 559 qdev_set_parent_bus(DEVICE(&s->mos6522_cuda), sysbus_get_default()); 560 |
|
559 memory_region_init_io(&s->mem, obj, &mos6522_cuda_ops, s, "cuda", 0x2000); 560 sysbus_init_mmio(sbd, &s->mem); 561 562 qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS, 563 DEVICE(obj), "adb.0"); 564} 565 566static Property cuda_properties[] = { --- 18 unchanged lines hidden (view full) --- 585 .instance_size = sizeof(CUDAState), 586 .instance_init = cuda_init, 587 .class_init = cuda_class_init, 588}; 589 590static void mos6522_cuda_portB_write(MOS6522State *s) 591{ 592 MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj); | 561 memory_region_init_io(&s->mem, obj, &mos6522_cuda_ops, s, "cuda", 0x2000); 562 sysbus_init_mmio(sbd, &s->mem); 563 564 qbus_create_inplace(&s->adb_bus, sizeof(s->adb_bus), TYPE_ADB_BUS, 565 DEVICE(obj), "adb.0"); 566} 567 568static Property cuda_properties[] = { --- 18 unchanged lines hidden (view full) --- 587 .instance_size = sizeof(CUDAState), 588 .instance_init = cuda_init, 589 .class_init = cuda_class_init, 590}; 591 592static void mos6522_cuda_portB_write(MOS6522State *s) 593{ 594 MOS6522CUDAState *mcs = container_of(s, MOS6522CUDAState, parent_obj); |
595 CUDAState *cs = container_of(mcs, CUDAState, mos6522_cuda); |
|
593 | 596 |
594 cuda_update(mcs->cuda); | 597 cuda_update(cs); |
595} 596 597static void mos6522_cuda_realize(DeviceState *dev, Error **errp) 598{ 599 MOS6522State *ms = MOS6522(dev); 600 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); 601 602 mdc->parent_realize(dev, errp); 603 604 ms->timers[0].frequency = CUDA_TIMER_FREQ; 605 ms->timers[1].frequency = (SCALE_US * 6000) / 4700; 606} 607 | 598} 599 600static void mos6522_cuda_realize(DeviceState *dev, Error **errp) 601{ 602 MOS6522State *ms = MOS6522(dev); 603 MOS6522DeviceClass *mdc = MOS6522_DEVICE_GET_CLASS(ms); 604 605 mdc->parent_realize(dev, errp); 606 607 ms->timers[0].frequency = CUDA_TIMER_FREQ; 608 ms->timers[1].frequency = (SCALE_US * 6000) / 4700; 609} 610 |
608static void mos6522_cuda_init(Object *obj) 609{ 610 MOS6522CUDAState *s = MOS6522_CUDA(obj); 611 612 object_property_add_link(obj, "cuda", TYPE_CUDA, 613 (Object **) &s->cuda, 614 qdev_prop_allow_set_link_before_realize, 615 0, NULL); 616} 617 | |
618static void mos6522_cuda_class_init(ObjectClass *oc, void *data) 619{ 620 DeviceClass *dc = DEVICE_CLASS(oc); 621 MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc); 622 623 dc->realize = mos6522_cuda_realize; 624 mdc->portB_write = mos6522_cuda_portB_write; 625 mdc->get_timer1_counter_value = cuda_get_counter_value; 626 mdc->get_timer2_counter_value = cuda_get_counter_value; 627 mdc->get_timer1_load_time = cuda_get_load_time; 628 mdc->get_timer2_load_time = cuda_get_load_time; 629} 630 631static const TypeInfo mos6522_cuda_type_info = { 632 .name = TYPE_MOS6522_CUDA, 633 .parent = TYPE_MOS6522, 634 .instance_size = sizeof(MOS6522CUDAState), | 611static void mos6522_cuda_class_init(ObjectClass *oc, void *data) 612{ 613 DeviceClass *dc = DEVICE_CLASS(oc); 614 MOS6522DeviceClass *mdc = MOS6522_DEVICE_CLASS(oc); 615 616 dc->realize = mos6522_cuda_realize; 617 mdc->portB_write = mos6522_cuda_portB_write; 618 mdc->get_timer1_counter_value = cuda_get_counter_value; 619 mdc->get_timer2_counter_value = cuda_get_counter_value; 620 mdc->get_timer1_load_time = cuda_get_load_time; 621 mdc->get_timer2_load_time = cuda_get_load_time; 622} 623 624static const TypeInfo mos6522_cuda_type_info = { 625 .name = TYPE_MOS6522_CUDA, 626 .parent = TYPE_MOS6522, 627 .instance_size = sizeof(MOS6522CUDAState), |
635 .instance_init = mos6522_cuda_init, | |
636 .class_init = mos6522_cuda_class_init, 637}; 638 639static void cuda_register_types(void) 640{ 641 type_register_static(&mos6522_cuda_type_info); 642 type_register_static(&cuda_type_info); 643} 644 645type_init(cuda_register_types) | 628 .class_init = mos6522_cuda_class_init, 629}; 630 631static void cuda_register_types(void) 632{ 633 type_register_static(&mos6522_cuda_type_info); 634 type_register_static(&cuda_type_info); 635} 636 637type_init(cuda_register_types) |