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