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