1
2
3
4
5
6
7
8
9#include "qemu/osdep.h"
10#include "qapi/error.h"
11#include "cpu.h"
12#include "hw/hw.h"
13#include "hw/devices.h"
14#include "sysemu/sysemu.h"
15#include "alpha_sys.h"
16#include "exec/address-spaces.h"
17
18
19#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
20#define TYPE_TYPHOON_IOMMU_MEMORY_REGION "typhoon-iommu-memory-region"
21
22typedef struct TyphoonCchip {
23 MemoryRegion region;
24 uint64_t misc;
25 uint64_t drir;
26 uint64_t dim[4];
27 uint32_t iic[4];
28 AlphaCPU *cpu[4];
29} TyphoonCchip;
30
31typedef struct TyphoonWindow {
32 uint64_t wba;
33 uint64_t wsm;
34 uint64_t tba;
35} TyphoonWindow;
36
37typedef struct TyphoonPchip {
38 MemoryRegion region;
39 MemoryRegion reg_iack;
40 MemoryRegion reg_mem;
41 MemoryRegion reg_io;
42 MemoryRegion reg_conf;
43
44 AddressSpace iommu_as;
45 IOMMUMemoryRegion iommu;
46
47 uint64_t ctl;
48 TyphoonWindow win[4];
49} TyphoonPchip;
50
51#define TYPHOON_PCI_HOST_BRIDGE(obj) \
52 OBJECT_CHECK(TyphoonState, (obj), TYPE_TYPHOON_PCI_HOST_BRIDGE)
53
54typedef struct TyphoonState {
55 PCIHostState parent_obj;
56
57 TyphoonCchip cchip;
58 TyphoonPchip pchip;
59 MemoryRegion dchip_region;
60 MemoryRegion ram_region;
61} TyphoonState;
62
63
64static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
65{
66
67 if (cpu != NULL) {
68 CPUState *cs = CPU(cpu);
69 if (req) {
70 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
71 } else {
72 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
73 }
74 }
75}
76
77static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size)
78{
79 CPUState *cpu = current_cpu;
80 TyphoonState *s = opaque;
81 uint64_t ret = 0;
82
83 switch (addr) {
84 case 0x0000:
85
86
87
88 break;
89
90 case 0x0040:
91
92
93 break;
94
95 case 0x0080:
96
97 ret = s->cchip.misc | (cpu->cpu_index & 3);
98 break;
99
100 case 0x00c0:
101
102 break;
103
104 case 0x0100:
105 case 0x0140:
106 case 0x0180:
107 case 0x01c0:
108
109
110 break;
111
112 case 0x0200:
113
114 ret = s->cchip.dim[0];
115 break;
116 case 0x0240:
117
118 ret = s->cchip.dim[1];
119 break;
120 case 0x0280:
121
122 ret = s->cchip.dim[0] & s->cchip.drir;
123 break;
124 case 0x02c0:
125
126 ret = s->cchip.dim[1] & s->cchip.drir;
127 break;
128 case 0x0300:
129
130 ret = s->cchip.drir;
131 break;
132
133 case 0x0340:
134
135 break;
136
137 case 0x0380:
138
139 ret = s->cchip.iic[0];
140 break;
141 case 0x03c0:
142
143 ret = s->cchip.iic[1];
144 break;
145
146 case 0x0400:
147 case 0x0440:
148 case 0x0480:
149 case 0x04c0:
150
151 break;
152
153 case 0x0580:
154
155
156 break;
157 case 0x05c0:
158
159 break;
160
161 case 0x0600:
162
163 ret = s->cchip.dim[2];
164 break;
165 case 0x0640:
166
167 ret = s->cchip.dim[3];
168 break;
169 case 0x0680:
170
171 ret = s->cchip.dim[2] & s->cchip.drir;
172 break;
173 case 0x06c0:
174
175 ret = s->cchip.dim[3] & s->cchip.drir;
176 break;
177
178 case 0x0700:
179
180 ret = s->cchip.iic[2];
181 break;
182 case 0x0740:
183
184 ret = s->cchip.iic[3];
185 break;
186
187 case 0x0780:
188
189 break;
190
191 case 0x0c00:
192 case 0x0c40:
193 case 0x0c80:
194 case 0x0cc0:
195 break;
196
197 default:
198 cpu_unassigned_access(cpu, addr, false, false, 0, size);
199 return -1;
200 }
201
202 return ret;
203}
204
205static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size)
206{
207
208 return 0;
209}
210
211static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size)
212{
213 TyphoonState *s = opaque;
214 uint64_t ret = 0;
215
216 switch (addr) {
217 case 0x0000:
218
219 ret = s->pchip.win[0].wba;
220 break;
221 case 0x0040:
222
223 ret = s->pchip.win[1].wba;
224 break;
225 case 0x0080:
226
227 ret = s->pchip.win[2].wba;
228 break;
229 case 0x00c0:
230
231 ret = s->pchip.win[3].wba;
232 break;
233
234 case 0x0100:
235
236 ret = s->pchip.win[0].wsm;
237 break;
238 case 0x0140:
239
240 ret = s->pchip.win[1].wsm;
241 break;
242 case 0x0180:
243
244 ret = s->pchip.win[2].wsm;
245 break;
246 case 0x01c0:
247
248 ret = s->pchip.win[3].wsm;
249 break;
250
251 case 0x0200:
252
253 ret = s->pchip.win[0].tba;
254 break;
255 case 0x0240:
256
257 ret = s->pchip.win[1].tba;
258 break;
259 case 0x0280:
260
261 ret = s->pchip.win[2].tba;
262 break;
263 case 0x02c0:
264
265 ret = s->pchip.win[3].tba;
266 break;
267
268 case 0x0300:
269
270 ret = s->pchip.ctl;
271 break;
272 case 0x0340:
273
274 break;
275 case 0x03c0:
276
277 break;
278 case 0x0400:
279
280 break;
281 case 0x0440:
282
283 break;
284 case 0x0480:
285
286 break;
287 case 0x04c0:
288
289 break;
290 case 0x0500:
291 case 0x0540:
292 case 0x0800:
293 break;
294
295 default:
296 cpu_unassigned_access(current_cpu, addr, false, false, 0, size);
297 return -1;
298 }
299
300 return ret;
301}
302
303static void cchip_write(void *opaque, hwaddr addr,
304 uint64_t val, unsigned size)
305{
306 TyphoonState *s = opaque;
307 uint64_t oldval, newval;
308
309 switch (addr) {
310 case 0x0000:
311
312
313 break;
314
315 case 0x0040:
316
317
318 break;
319
320 case 0x0080:
321
322 newval = oldval = s->cchip.misc;
323 newval &= ~(val & 0x10000ff0);
324 if (val & 0x100000) {
325 newval &= ~0xff0000ull;
326 } else {
327 newval |= val & 0x00f00000;
328 if ((newval & 0xf0000) == 0) {
329 newval |= val & 0xf0000;
330 }
331 }
332 newval |= (val & 0xf000) >> 4;
333
334 newval &= ~0xf0000000000ull;
335 newval |= val & 0xf0000000000ull;
336 s->cchip.misc = newval;
337
338
339 if ((newval ^ oldval) & 0xff0) {
340 int i;
341 for (i = 0; i < 4; ++i) {
342 AlphaCPU *cpu = s->cchip.cpu[i];
343 if (cpu != NULL) {
344 CPUState *cs = CPU(cpu);
345
346 if (newval & (1 << (i + 8))) {
347 cpu_interrupt(cs, CPU_INTERRUPT_SMP);
348 } else {
349 cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
350 }
351
352
353 if ((newval & (1 << (i + 4))) == 0) {
354 cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
355 }
356 }
357 }
358 }
359 break;
360
361 case 0x00c0:
362
363 break;
364
365 case 0x0100:
366 case 0x0140:
367 case 0x0180:
368 case 0x01c0:
369
370
371 break;
372
373 case 0x0200:
374
375 s->cchip.dim[0] = val;
376 cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
377 break;
378 case 0x0240:
379
380 s->cchip.dim[1] = val;
381 cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
382 break;
383
384 case 0x0280:
385 case 0x02c0:
386 case 0x0300:
387 break;
388
389 case 0x0340:
390
391 break;
392
393 case 0x0380:
394 s->cchip.iic[0] = val & 0xffffff;
395 break;
396 case 0x03c0:
397 s->cchip.iic[1] = val & 0xffffff;
398 break;
399
400 case 0x0400:
401 case 0x0440:
402 case 0x0480:
403 case 0x04c0:
404
405 break;
406
407 case 0x0580:
408
409
410 break;
411 case 0x05c0:
412
413 break;
414
415 case 0x0600:
416
417 s->cchip.dim[2] = val;
418 cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
419 break;
420 case 0x0640:
421
422 s->cchip.dim[3] = val;
423 cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
424 break;
425
426 case 0x0680:
427 case 0x06c0:
428 break;
429
430 case 0x0700:
431 s->cchip.iic[2] = val & 0xffffff;
432 break;
433 case 0x0740:
434 s->cchip.iic[3] = val & 0xffffff;
435 break;
436
437 case 0x0780:
438
439 break;
440
441 case 0x0c00:
442 case 0x0c40:
443 case 0x0c80:
444 case 0x0cc0:
445 break;
446
447 default:
448 cpu_unassigned_access(current_cpu, addr, true, false, 0, size);
449 return;
450 }
451}
452
453static void dchip_write(void *opaque, hwaddr addr,
454 uint64_t val, unsigned size)
455{
456
457}
458
459static void pchip_write(void *opaque, hwaddr addr,
460 uint64_t val, unsigned size)
461{
462 TyphoonState *s = opaque;
463 uint64_t oldval;
464
465 switch (addr) {
466 case 0x0000:
467
468 s->pchip.win[0].wba = val & 0xfff00003u;
469 break;
470 case 0x0040:
471
472 s->pchip.win[1].wba = val & 0xfff00003u;
473 break;
474 case 0x0080:
475
476 s->pchip.win[2].wba = val & 0xfff00003u;
477 break;
478 case 0x00c0:
479
480 s->pchip.win[3].wba = (val & 0x80fff00001ull) | 2;
481 break;
482
483 case 0x0100:
484
485 s->pchip.win[0].wsm = val & 0xfff00000u;
486 break;
487 case 0x0140:
488
489 s->pchip.win[1].wsm = val & 0xfff00000u;
490 break;
491 case 0x0180:
492
493 s->pchip.win[2].wsm = val & 0xfff00000u;
494 break;
495 case 0x01c0:
496
497 s->pchip.win[3].wsm = val & 0xfff00000u;
498 break;
499
500 case 0x0200:
501
502 s->pchip.win[0].tba = val & 0x7fffffc00ull;
503 break;
504 case 0x0240:
505
506 s->pchip.win[1].tba = val & 0x7fffffc00ull;
507 break;
508 case 0x0280:
509
510 s->pchip.win[2].tba = val & 0x7fffffc00ull;
511 break;
512 case 0x02c0:
513
514 s->pchip.win[3].tba = val & 0x7fffffc00ull;
515 break;
516
517 case 0x0300:
518
519 oldval = s->pchip.ctl;
520 oldval &= ~0x00001cff0fc7ffull;
521 oldval |= val & 0x00001cff0fc7ffull;
522 s->pchip.ctl = oldval;
523 break;
524
525 case 0x0340:
526
527 break;
528 case 0x03c0:
529
530 break;
531 case 0x0400:
532
533 break;
534 case 0x0440:
535
536 break;
537
538 case 0x0480:
539
540 break;
541
542 case 0x04c0:
543
544 break;
545
546 case 0x0500:
547
548 case 0x0540:
549
550 case 0x0800:
551
552 break;
553
554 default:
555 cpu_unassigned_access(current_cpu, addr, true, false, 0, size);
556 return;
557 }
558}
559
560static const MemoryRegionOps cchip_ops = {
561 .read = cchip_read,
562 .write = cchip_write,
563 .endianness = DEVICE_LITTLE_ENDIAN,
564 .valid = {
565 .min_access_size = 8,
566 .max_access_size = 8,
567 },
568 .impl = {
569 .min_access_size = 8,
570 .max_access_size = 8,
571 },
572};
573
574static const MemoryRegionOps dchip_ops = {
575 .read = dchip_read,
576 .write = dchip_write,
577 .endianness = DEVICE_LITTLE_ENDIAN,
578 .valid = {
579 .min_access_size = 8,
580 .max_access_size = 8,
581 },
582 .impl = {
583 .min_access_size = 8,
584 .max_access_size = 8,
585 },
586};
587
588static const MemoryRegionOps pchip_ops = {
589 .read = pchip_read,
590 .write = pchip_write,
591 .endianness = DEVICE_LITTLE_ENDIAN,
592 .valid = {
593 .min_access_size = 8,
594 .max_access_size = 8,
595 },
596 .impl = {
597 .min_access_size = 8,
598 .max_access_size = 8,
599 },
600};
601
602
603
604static bool make_iommu_tlbe(hwaddr taddr, hwaddr mask, IOMMUTLBEntry *ret)
605{
606 *ret = (IOMMUTLBEntry) {
607 .target_as = &address_space_memory,
608 .translated_addr = taddr,
609 .addr_mask = mask,
610 .perm = IOMMU_RW,
611 };
612 return true;
613}
614
615
616
617static bool pte_translate(hwaddr pte_addr, IOMMUTLBEntry *ret)
618{
619 uint64_t pte = address_space_ldq(&address_space_memory, pte_addr,
620 MEMTXATTRS_UNSPECIFIED, NULL);
621
622
623 if ((pte & 1) == 0) {
624 return false;
625 }
626
627 return make_iommu_tlbe((pte & 0x3ffffe) << 12, 0x1fff, ret);
628}
629
630
631
632static bool window_translate(TyphoonWindow *win, hwaddr addr,
633 IOMMUTLBEntry *ret)
634{
635 uint32_t wba = win->wba;
636 uint64_t wsm = win->wsm;
637 uint64_t tba = win->tba;
638 uint64_t wsm_ext = wsm | 0xfffff;
639
640
641 if ((wba & 1) == 0) {
642 return false;
643 }
644
645
646 if ((addr & ~wsm_ext) != (wba & 0xfff00000u)) {
647 return false;
648 }
649
650 if (wba & 2) {
651
652 hwaddr pte_addr;
653
654
655 pte_addr = tba & ~(wsm >> 10);
656 pte_addr |= (addr & (wsm | 0xfe000)) >> 10;
657 return pte_translate(pte_addr, ret);
658 } else {
659
660 return make_iommu_tlbe(tba & ~wsm_ext, wsm_ext, ret);
661 }
662}
663
664
665
666
667static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
668 hwaddr addr,
669 IOMMUAccessFlags flag)
670{
671 TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
672 IOMMUTLBEntry ret;
673 int i;
674
675 if (addr <= 0xffffffffu) {
676
677
678
679 if ((pchip->ctl & 0x20)
680 && addr >= 0x80000
681 && addr <= 0xfffff) {
682 goto failure;
683 }
684
685
686 for (i = 0; i < 3; ++i) {
687 if (window_translate(&pchip->win[i], addr, &ret)) {
688 goto success;
689 }
690 }
691
692
693 if ((pchip->win[3].wba & 0x80000000000ull) == 0
694 && window_translate(&pchip->win[3], addr, &ret)) {
695 goto success;
696 }
697 } else {
698
699
700 if (addr >= 0x10000000000ull && addr < 0x20000000000ull) {
701
702 if (pchip->ctl & 0x40) {
703
704 make_iommu_tlbe(0, 0x007ffffffffull, &ret);
705 goto success;
706 }
707 }
708
709 if (addr >= 0x80000000000ull && addr <= 0xfffffffffffull) {
710
711 if ((pchip->win[3].wba & 0x80000000001ull) == 0x80000000001ull) {
712 uint64_t pte_addr;
713
714 pte_addr = pchip->win[3].tba & 0x7ffc00000ull;
715 pte_addr |= (addr & 0xffffe000u) >> 10;
716 if (pte_translate(pte_addr, &ret)) {
717 goto success;
718 }
719 }
720 }
721 }
722
723 failure:
724 ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE };
725 success:
726 return ret;
727}
728
729static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
730{
731 TyphoonState *s = opaque;
732 return &s->pchip.iommu_as;
733}
734
735static void typhoon_set_irq(void *opaque, int irq, int level)
736{
737 TyphoonState *s = opaque;
738 uint64_t drir;
739 int i;
740
741
742 drir = s->cchip.drir;
743 if (level) {
744 drir |= 1ull << irq;
745 } else {
746 drir &= ~(1ull << irq);
747 }
748 s->cchip.drir = drir;
749
750 for (i = 0; i < 4; ++i) {
751 cpu_irq_change(s->cchip.cpu[i], s->cchip.dim[i] & drir);
752 }
753}
754
755static void typhoon_set_isa_irq(void *opaque, int irq, int level)
756{
757 typhoon_set_irq(opaque, 55, level);
758}
759
760static void typhoon_set_timer_irq(void *opaque, int irq, int level)
761{
762 TyphoonState *s = opaque;
763 int i;
764
765
766
767
768
769 if (level == 0) {
770 return;
771 }
772
773
774 for (i = 0; i < 4; ++i) {
775 AlphaCPU *cpu = s->cchip.cpu[i];
776 if (cpu != NULL) {
777 uint32_t iic = s->cchip.iic[i];
778
779
780
781
782
783
784
785
786
787
788 iic = ((iic - 1) & 0x1ffffff) | (iic & 0x1000000);
789 s->cchip.iic[i] = iic;
790
791 if (iic & 0x1000000) {
792
793 s->cchip.misc |= 1 << (i + 4);
794
795 cpu_interrupt(CPU(cpu), CPU_INTERRUPT_TIMER);
796 }
797 }
798 }
799}
800
801static void typhoon_alarm_timer(void *opaque)
802{
803 TyphoonState *s = (TyphoonState *)((uintptr_t)opaque & ~3);
804 int cpu = (uintptr_t)opaque & 3;
805
806
807 s->cchip.misc |= 1 << (cpu + 4);
808 cpu_interrupt(CPU(s->cchip.cpu[cpu]), CPU_INTERRUPT_TIMER);
809}
810
811PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
812 qemu_irq *p_rtc_irq,
813 AlphaCPU *cpus[4], pci_map_irq_fn sys_map_irq)
814{
815 const uint64_t MB = 1024 * 1024;
816 const uint64_t GB = 1024 * MB;
817 MemoryRegion *addr_space = get_system_memory();
818 DeviceState *dev;
819 TyphoonState *s;
820 PCIHostState *phb;
821 PCIBus *b;
822 int i;
823
824 dev = qdev_create(NULL, TYPE_TYPHOON_PCI_HOST_BRIDGE);
825
826 s = TYPHOON_PCI_HOST_BRIDGE(dev);
827 phb = PCI_HOST_BRIDGE(dev);
828
829 s->cchip.misc = 0x800000000ull;
830 s->pchip.win[3].wba = 2;
831
832
833 for (i = 0; i < 4; i++) {
834 AlphaCPU *cpu = cpus[i];
835 s->cchip.cpu[i] = cpu;
836 if (cpu != NULL) {
837 cpu->alarm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
838 typhoon_alarm_timer,
839 (void *)((uintptr_t)s + i));
840 }
841 }
842
843 *p_rtc_irq = qemu_allocate_irq(typhoon_set_timer_irq, s, 0);
844
845
846
847 memory_region_allocate_system_memory(&s->ram_region, OBJECT(s), "ram",
848 ram_size);
849 memory_region_add_subregion(addr_space, 0, &s->ram_region);
850
851
852
853
854
855
856 memory_region_init_io(&s->pchip.region, OBJECT(s), &pchip_ops, s, "pchip0",
857 256*MB);
858 memory_region_add_subregion(addr_space, 0x80180000000ULL,
859 &s->pchip.region);
860
861
862 memory_region_init_io(&s->cchip.region, OBJECT(s), &cchip_ops, s, "cchip0",
863 256*MB);
864 memory_region_add_subregion(addr_space, 0x801a0000000ULL,
865 &s->cchip.region);
866
867
868 memory_region_init_io(&s->dchip_region, OBJECT(s), &dchip_ops, s, "dchip0",
869 256*MB);
870 memory_region_add_subregion(addr_space, 0x801b0000000ULL,
871 &s->dchip_region);
872
873
874 memory_region_init(&s->pchip.reg_mem, OBJECT(s), "pci0-mem", 4*GB);
875 memory_region_add_subregion(addr_space, 0x80000000000ULL,
876 &s->pchip.reg_mem);
877
878
879 memory_region_init_io(&s->pchip.reg_io, OBJECT(s), &alpha_pci_ignore_ops,
880 NULL, "pci0-io", 32*MB);
881 memory_region_add_subregion(addr_space, 0x801fc000000ULL,
882 &s->pchip.reg_io);
883
884 b = pci_register_root_bus(dev, "pci",
885 typhoon_set_irq, sys_map_irq, s,
886 &s->pchip.reg_mem, &s->pchip.reg_io,
887 0, 64, TYPE_PCI_BUS);
888 phb->bus = b;
889 qdev_init_nofail(dev);
890
891
892 memory_region_init_iommu(&s->pchip.iommu, sizeof(s->pchip.iommu),
893 TYPE_TYPHOON_IOMMU_MEMORY_REGION, OBJECT(s),
894 "iommu-typhoon", UINT64_MAX);
895 address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
896 "pchip0-pci");
897 pci_setup_iommu(b, typhoon_pci_dma_iommu, s);
898
899
900 memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops,
901 b, "pci0-iack", 64*MB);
902 memory_region_add_subregion(addr_space, 0x801f8000000ULL,
903 &s->pchip.reg_iack);
904
905
906 memory_region_init_io(&s->pchip.reg_conf, OBJECT(s), &alpha_pci_conf1_ops,
907 b, "pci0-conf", 16*MB);
908 memory_region_add_subregion(addr_space, 0x801fe000000ULL,
909 &s->pchip.reg_conf);
910
911
912
913
914
915
916
917
918
919
920
921
922 {
923 qemu_irq *isa_irqs;
924
925 *isa_bus = isa_bus_new(NULL, get_system_memory(), &s->pchip.reg_io,
926 &error_abort);
927 isa_irqs = i8259_init(*isa_bus,
928 qemu_allocate_irq(typhoon_set_isa_irq, s, 0));
929 isa_bus_irqs(*isa_bus, isa_irqs);
930 }
931
932 return b;
933}
934
935static int typhoon_pcihost_init(SysBusDevice *dev)
936{
937 return 0;
938}
939
940static void typhoon_pcihost_class_init(ObjectClass *klass, void *data)
941{
942 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
943
944 k->init = typhoon_pcihost_init;
945}
946
947static const TypeInfo typhoon_pcihost_info = {
948 .name = TYPE_TYPHOON_PCI_HOST_BRIDGE,
949 .parent = TYPE_PCI_HOST_BRIDGE,
950 .instance_size = sizeof(TyphoonState),
951 .class_init = typhoon_pcihost_class_init,
952};
953
954static void typhoon_iommu_memory_region_class_init(ObjectClass *klass,
955 void *data)
956{
957 IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
958
959 imrc->translate = typhoon_translate_iommu;
960}
961
962static const TypeInfo typhoon_iommu_memory_region_info = {
963 .parent = TYPE_IOMMU_MEMORY_REGION,
964 .name = TYPE_TYPHOON_IOMMU_MEMORY_REGION,
965 .class_init = typhoon_iommu_memory_region_class_init,
966};
967
968static void typhoon_register_types(void)
969{
970 type_register_static(&typhoon_pcihost_info);
971 type_register_static(&typhoon_iommu_memory_region_info);
972}
973
974type_init(typhoon_register_types)
975