2 * HP-PARISC Astro/Pluto/Ike/REO system bus adapter (SBA)
3 * with Elroy PCI bus (LBA) adapter emulation
4 * Found in C3000 and similar machines
6 * (C) 2023 by Helge Deller <deller@gmx.de>
8 * This work is licensed under the GNU GPL license version 2 or later.
10 * Chip documentation is available at:
11 * https://parisc.wiki.kernel.org/index.php/Technical_Documentation
14 * - All user-added devices are currently attached to the first
15 * Elroy (PCI bus) only for now. To fix this additional work in
16 * SeaBIOS and this driver is needed. See "user_creatable" flag below.
17 * - GMMIO (Greater than 4 GB MMIO) register
20 #define TYPE_ASTRO_IOMMU_MEMORY_REGION "astro-iommu-memory-region"
22 #define F_EXTEND(addr) ((addr) | MAKE_64BIT_MASK(32, 32))
24 #include "qemu/osdep.h"
25 #include "qemu/module.h"
26 #include "qemu/units.h"
27 #include "qapi/error.h"
29 #include "hw/pci/pci_device.h"
30 #include "hw/pci/pci_bus.h"
31 #include "hw/qdev-properties.h"
32 #include "hw/pci-host/astro.h"
33 #include "hw/hppa/hppa_hardware.h"
34 #include "migration/vmstate.h"
35 #include "target/hppa/cpu.h"
37 #include "qom/object.h"
43 static uint64_t mask_32bit_val(hwaddr addr
, unsigned size
, uint64_t val
)
56 static void put_val_in_int64(uint64_t *p
, hwaddr addr
, unsigned size
,
61 } else if (size
== 4) {
63 *p
= ((*p
<< 32) >> 32) | (val
<< 32);
65 *p
= ((*p
>> 32) << 32) | (uint32_t) val
;
70 static void put_val_in_arrary(uint64_t *array
, hwaddr start_addr
,
71 hwaddr addr
, unsigned size
, uint64_t val
)
75 index
= (addr
- start_addr
) / 8;
76 put_val_in_int64(&array
[index
], addr
, size
, val
);
81 * The Elroy PCI host bridge. We have at least 4 of those under Astro.
84 static MemTxResult
elroy_chip_read_with_attrs(void *opaque
, hwaddr addr
,
85 uint64_t *data
, unsigned size
,
88 MemTxResult ret
= MEMTX_OK
;
89 ElroyState
*s
= opaque
;
93 switch ((addr
>> 3) << 3) {
95 val
= 0x6000005; /* func_class */
99 * Scratch register, but firmware initializes it with the
100 * PCI BUS number and Linux/HP-UX uses it then.
102 val
= s
->pci_bus_num
;
103 /* Upper byte holds the end of this bus number */
104 val
|= s
->pci_bus_num
<< 8;
107 val
= s
->arb_mask
; /* set ARB mask */
110 val
= s
->status_control
;
112 case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */
113 index
= (addr
- 0x200) / 8;
114 val
= s
->mmio_base
[index
];
117 val
= s
->error_config
;
120 val
= 0; /* ERROR_STATUS */
122 case 0x0800: /* IOSAPIC_REG_SELECT */
123 val
= s
->iosapic_reg_select
;
125 case 0x0810: /* IOSAPIC_REG_WINDOW */
126 switch (s
->iosapic_reg_select
) {
127 case 0x01: /* IOSAPIC_REG_VERSION */
128 val
= (32 << 16) | 1; /* upper 16bit holds max entries */
131 if (s
->iosapic_reg_select
< ARRAY_SIZE(s
->iosapic_reg
)) {
132 val
= s
->iosapic_reg
[s
->iosapic_reg_select
];
137 trace_iosapic_reg_read(s
->iosapic_reg_select
, size
, val
);
141 if (s
->status_control
& HF_ENABLE
) {
143 ret
= MEMTX_DECODE_ERROR
;
145 /* return -1ULL if HardFail is disabled */
150 trace_elroy_read(addr
, size
, val
);
152 /* for 32-bit accesses mask return value */
153 val
= mask_32bit_val(addr
, size
, val
);
155 trace_astro_chip_read(addr
, size
, val
);
161 static MemTxResult
elroy_chip_write_with_attrs(void *opaque
, hwaddr addr
,
162 uint64_t val
, unsigned size
,
165 ElroyState
*s
= opaque
;
168 trace_elroy_write(addr
, size
, val
);
170 switch ((addr
>> 3) << 3) {
171 case 0x000: /* PCI_ID & PCI_COMMAND_STATUS_REG */
174 put_val_in_int64(&s
->arb_mask
, addr
, size
, val
);
177 put_val_in_int64(&s
->status_control
, addr
, size
, val
);
179 case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */
180 put_val_in_arrary(s
->mmio_base
, 0x200, addr
, size
, val
);
182 case 0x300: /* ibase */
183 case 0x308: /* imask */
186 put_val_in_int64(&s
->error_config
, addr
, size
, val
);
188 case 0x0800: /* IOSAPIC_REG_SELECT */
189 s
->iosapic_reg_select
= val
;
191 case 0x0810: /* IOSAPIC_REG_WINDOW */
192 trace_iosapic_reg_write(s
->iosapic_reg_select
, size
, val
);
193 if (s
->iosapic_reg_select
< ARRAY_SIZE(s
->iosapic_reg
)) {
194 s
->iosapic_reg
[s
->iosapic_reg_select
] = val
;
199 case 0x0840: /* IOSAPIC_REG_EOI */
200 val
= le64_to_cpu(val
);
202 for (i
= 0; i
< ELROY_IRQS
; i
++) {
203 if ((s
->iosapic_reg
[0x10 + 2 * i
] & 63) == val
) {
204 s
->ilr
&= ~(1ull << i
);
210 if (s
->status_control
& HF_ENABLE
) {
211 return MEMTX_DECODE_ERROR
;
217 static const MemoryRegionOps elroy_chip_ops
= {
218 .read_with_attrs
= elroy_chip_read_with_attrs
,
219 .write_with_attrs
= elroy_chip_write_with_attrs
,
220 .endianness
= DEVICE_LITTLE_ENDIAN
,
222 .min_access_size
= 4,
223 .max_access_size
= 8,
226 .min_access_size
= 4,
227 .max_access_size
= 8,
232 /* Unlike pci_config_data_le_ops, no check of high bit set in config_reg. */
234 static uint64_t elroy_config_data_read(void *opaque
, hwaddr addr
, unsigned len
)
238 PCIHostState
*s
= opaque
;
239 val
= pci_data_read(s
->bus
, s
->config_reg
| (addr
& 3), len
);
240 trace_elroy_pci_config_data_read(s
->config_reg
| (addr
& 3), len
, val
);
244 static void elroy_config_data_write(void *opaque
, hwaddr addr
,
245 uint64_t val
, unsigned len
)
247 PCIHostState
*s
= opaque
;
248 pci_data_write(s
->bus
, s
->config_reg
| (addr
& 3), val
, len
);
249 trace_elroy_pci_config_data_write(s
->config_reg
| (addr
& 3), len
, val
);
252 static const MemoryRegionOps elroy_config_data_ops
= {
253 .read
= elroy_config_data_read
,
254 .write
= elroy_config_data_write
,
255 .endianness
= DEVICE_LITTLE_ENDIAN
,
258 static uint64_t elroy_config_addr_read(void *opaque
, hwaddr addr
, unsigned len
)
260 ElroyState
*s
= opaque
;
261 return s
->config_reg_elroy
;
264 static void elroy_config_addr_write(void *opaque
, hwaddr addr
,
265 uint64_t val
, unsigned len
)
267 PCIHostState
*s
= opaque
;
268 ElroyState
*es
= opaque
;
269 es
->config_reg_elroy
= val
; /* keep a copy of original value */
273 static const MemoryRegionOps elroy_config_addr_ops
= {
274 .read
= elroy_config_addr_read
,
275 .write
= elroy_config_addr_write
,
276 .valid
.min_access_size
= 4,
277 .valid
.max_access_size
= 8,
278 .endianness
= DEVICE_LITTLE_ENDIAN
,
282 /* Handle PCI-to-system address translation. */
283 static IOMMUTLBEntry
astro_translate_iommu(IOMMUMemoryRegion
*iommu
,
285 IOMMUAccessFlags flag
,
288 AstroState
*s
= container_of(iommu
, AstroState
, iommu
);
289 hwaddr pdir_ptr
, index
, ibase
;
290 hwaddr addr_mask
= 0xfff; /* 4k translation */
293 #define IOVP_SHIFT 12 /* equals PAGE_SHIFT */
294 #define PDIR_INDEX(iovp) ((iovp) >> IOVP_SHIFT)
295 #define SBA_PDIR_VALID_BIT 0x8000000000000000ULL
300 * Default translation: "32-bit PCI Addressing on 40-bit Runway".
301 * For addresses in the 32-bit memory address range ... and then
302 * language which not-coincidentally matches the PSW.W=0 mapping.
304 if (addr
<= UINT32_MAX
) {
305 entry
= hppa_abs_to_phys_pa2_w0(addr
);
310 /* "range enable" flag cleared? */
311 if ((s
->tlb_ibase
& 1) == 0) {
315 ibase
= s
->tlb_ibase
& ~1ULL;
316 if ((addr
& s
->tlb_imask
) != ibase
) {
317 /* do not translate this one! */
321 index
= PDIR_INDEX(addr
);
322 pdir_ptr
= s
->tlb_pdir_base
+ index
* sizeof(entry
);
323 entry
= ldq_le_phys(&address_space_memory
, pdir_ptr
);
325 if (!(entry
& SBA_PDIR_VALID_BIT
)) { /* I/O PDIR entry valid ? */
327 return (IOMMUTLBEntry
) { .perm
= IOMMU_NONE
};
330 entry
&= ~SBA_PDIR_VALID_BIT
;
331 entry
>>= IOVP_SHIFT
;
335 return (IOMMUTLBEntry
) {
336 .target_as
= &address_space_memory
,
338 .translated_addr
= entry
,
339 .addr_mask
= addr_mask
,
344 static AddressSpace
*elroy_pcihost_set_iommu(PCIBus
*bus
, void *opaque
,
347 ElroyState
*s
= opaque
;
348 return &s
->astro
->iommu_as
;
351 static const PCIIOMMUOps elroy_pcihost_iommu_ops
= {
352 .get_address_space
= elroy_pcihost_set_iommu
,
356 * Encoding in IOSAPIC:
357 * base_addr == 0xfffa0000, we want to get 0xa0ff0000.
358 * eid 0x0ff00000 -> 0x00ff0000
359 * id 0x000ff000 -> 0xff000000
361 #define SWIZZLE_HPA(a) \
362 ((((a) & 0x0ff00000) >> 4) | (((a) & 0x000ff000) << 12))
363 #define UNSWIZZLE_HPA(a) \
364 (((((a) << 4) & 0x0ff00000) | (((a) >> 12) & 0x000ff000) | 0xf0000000))
366 /* bits in the "low" I/O Sapic IRdT entry */
367 #define IOSAPIC_IRDT_DISABLE 0x10000 /* if bit is set, mask this irq */
368 #define IOSAPIC_IRDT_PO_LOW 0x02000
369 #define IOSAPIC_IRDT_LEVEL_TRIG 0x08000
370 #define IOSAPIC_IRDT_MODE_LPRI 0x00100
372 #define CPU_IRQ_OFFSET 2
374 static void elroy_set_irq(void *opaque
, int irq
, int level
)
376 ElroyState
*s
= opaque
;
378 uint32_t old_ilr
= s
->ilr
;
382 val
= s
->iosapic_reg
[0x10 + 2 * irq
];
383 cpu_hpa
= s
->iosapic_reg
[0x11 + 2 * irq
];
384 /* low nibble of val has value to write into CPU irq reg */
385 bit
= 1u << (val
& (ELROY_IRQS
- 1));
386 cpu_hpa
= UNSWIZZLE_HPA(cpu_hpa
);
388 if (level
&& (!(val
& IOSAPIC_IRDT_DISABLE
)) && cpu_hpa
) {
389 uint32_t ena
= bit
& ~old_ilr
;
390 s
->ilr
= old_ilr
| bit
;
392 stl_be_phys(&address_space_memory
, F_EXTEND(cpu_hpa
), val
& 63);
395 s
->ilr
= old_ilr
& ~bit
;
399 static int elroy_pci_map_irq(PCIDevice
*d
, int irq_num
)
401 int slot
= PCI_SLOT(d
->devfn
);
403 assert(irq_num
>= 0 && irq_num
< ELROY_IRQS
);
404 return slot
& (ELROY_IRQS
- 1);
407 static void elroy_reset(DeviceState
*dev
)
409 ElroyState
*s
= ELROY_PCI_HOST_BRIDGE(dev
);
413 * Make sure to disable interrupts at reboot, otherwise the Linux kernel
414 * serial8250_config_port() in drivers/tty/serial/8250/8250_port.c
415 * will hang during autoconfig().
418 for (irq
= 0; irq
< ELROY_IRQS
; irq
++) {
419 s
->iosapic_reg
[0x10 + 2 * irq
] = IOSAPIC_IRDT_PO_LOW
|
420 IOSAPIC_IRDT_LEVEL_TRIG
| (irq
+ CPU_IRQ_OFFSET
) |
421 IOSAPIC_IRDT_DISABLE
;
422 s
->iosapic_reg
[0x11 + 2 * irq
] = SWIZZLE_HPA(CPU_HPA
);
426 static void elroy_pcihost_init(Object
*obj
)
428 ElroyState
*s
= ELROY_PCI_HOST_BRIDGE(obj
);
429 PCIHostState
*phb
= PCI_HOST_BRIDGE(obj
);
430 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
432 /* Elroy config access from CPU. */
433 memory_region_init_io(&s
->this_mem
, OBJECT(s
), &elroy_chip_ops
,
436 /* Elroy PCI config. */
437 memory_region_init_io(&phb
->conf_mem
, OBJECT(phb
),
438 &elroy_config_addr_ops
, DEVICE(s
),
440 memory_region_init_io(&phb
->data_mem
, OBJECT(phb
),
441 &elroy_config_data_ops
, DEVICE(s
),
443 memory_region_add_subregion(&s
->this_mem
, 0x40,
445 memory_region_add_subregion(&s
->this_mem
, 0x48,
448 /* Elroy PCI bus memory. */
449 memory_region_init(&s
->pci_mmio
, OBJECT(s
), "pci-mmio", UINT64_MAX
);
450 memory_region_init_io(&s
->pci_io
, OBJECT(s
), &unassigned_io_ops
, obj
,
452 ((uint32_t) IOS_DIST_BASE_SIZE
) / ROPES_PER_IOC
);
454 phb
->bus
= pci_register_root_bus(DEVICE(s
), "pci",
455 elroy_set_irq
, elroy_pci_map_irq
, s
,
456 &s
->pci_mmio
, &s
->pci_io
,
457 PCI_DEVFN(0, 0), ELROY_IRQS
, TYPE_PCI_BUS
);
459 sysbus_init_mmio(sbd
, &s
->this_mem
);
461 qdev_init_gpio_in(DEVICE(obj
), elroy_set_irq
, ELROY_IRQS
);
464 static Property elroy_pcihost_properties
[] = {
465 DEFINE_PROP_END_OF_LIST(),
468 static const VMStateDescription vmstate_elroy
= {
471 .minimum_version_id
= 1,
472 .fields
= (const VMStateField
[]) {
473 VMSTATE_UINT64(hpa
, ElroyState
),
474 VMSTATE_UINT32(pci_bus_num
, ElroyState
),
475 VMSTATE_UINT64(config_address
, ElroyState
),
476 VMSTATE_UINT64(config_reg_elroy
, ElroyState
),
477 VMSTATE_UINT64(status_control
, ElroyState
),
478 VMSTATE_UINT64(arb_mask
, ElroyState
),
479 VMSTATE_UINT64_ARRAY(mmio_base
, ElroyState
, (0x0250 - 0x200) / 8),
480 VMSTATE_UINT64(error_config
, ElroyState
),
481 VMSTATE_UINT32(iosapic_reg_select
, ElroyState
),
482 VMSTATE_UINT64_ARRAY(iosapic_reg
, ElroyState
, 0x20),
483 VMSTATE_UINT32(ilr
, ElroyState
),
484 VMSTATE_END_OF_LIST()
488 static void elroy_pcihost_class_init(ObjectClass
*klass
, void *data
)
490 DeviceClass
*dc
= DEVICE_CLASS(klass
);
492 dc
->reset
= elroy_reset
;
493 device_class_set_props(dc
, elroy_pcihost_properties
);
494 dc
->vmsd
= &vmstate_elroy
;
495 dc
->user_creatable
= false;
498 static const TypeInfo elroy_pcihost_info
= {
499 .name
= TYPE_ELROY_PCI_HOST_BRIDGE
,
500 .parent
= TYPE_PCI_HOST_BRIDGE
,
501 .instance_init
= elroy_pcihost_init
,
502 .instance_size
= sizeof(ElroyState
),
503 .class_init
= elroy_pcihost_class_init
,
506 static void elroy_register_types(void)
508 type_register_static(&elroy_pcihost_info
);
511 type_init(elroy_register_types
)
514 static ElroyState
*elroy_init(int num
)
518 dev
= qdev_new(TYPE_ELROY_PCI_HOST_BRIDGE
);
519 dev
->id
= g_strdup_printf("elroy%d", num
);
520 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev
), &error_fatal
);
522 return ELROY_PCI_HOST_BRIDGE(dev
);
529 static MemTxResult
astro_chip_read_with_attrs(void *opaque
, hwaddr addr
,
530 uint64_t *data
, unsigned size
,
533 AstroState
*s
= opaque
;
534 MemTxResult ret
= MEMTX_OK
;
538 switch ((addr
>> 3) << 3) {
540 case 0x0000: /* ID */
541 val
= (0x01 << 3) | 0x01ULL
;
543 case 0x0008: /* IOC_CTRL */
546 case 0x0010: /* TOC_CLIENT_ID */
548 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */
551 case 0x0078: /* NetBSD reads 0x78 ? */
554 case 0x0300 ... 0x03d8: /* LMMIO_DIRECT0_BASE... */
555 index
= (addr
- 0x300) / 8;
556 val
= s
->ioc_ranges
[index
];
562 case 0x10230: /* HP-UX 11.11 reads it. No idea. */
565 case 0x22108: /* IOC STATUS_CONTROL */
566 val
= s
->ioc_status_ctrl
;
568 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
569 index
= (addr
- 0x20200) / 8;
570 val
= s
->ioc_rope_control
[index
];
572 case 0x20040: /* IOC Rope config */
573 val
= s
->ioc_rope_config
;
575 case 0x20050: /* IOC Rope debug */
578 case 0x20108: /* IOC STATUS_CONTROL */
579 val
= s
->ioc_status_control
;
581 case 0x20310: /* IOC_PCOM */
583 /* TODO: flush iommu */
586 val
= s
->ioc_flush_control
;
588 /* empty placeholders for non-existent elroys */
589 #define EMPTY_PORT(x) case x: case x+8: val = 0; break; \
590 case x+40: case x+48: val = UINT64_MAX; break;
603 ret
= MEMTX_DECODE_ERROR
;
606 /* for 32-bit accesses mask return value */
607 val
= mask_32bit_val(addr
, size
, val
);
609 trace_astro_chip_read(addr
, size
, val
);
614 static MemTxResult
astro_chip_write_with_attrs(void *opaque
, hwaddr addr
,
615 uint64_t val
, unsigned size
,
618 MemTxResult ret
= MEMTX_OK
;
619 AstroState
*s
= opaque
;
621 trace_astro_chip_write(addr
, size
, val
);
623 switch ((addr
>> 3) << 3) {
624 case 0x0000: /* ID */
626 case 0x0008: /* IOC_CTRL */
628 put_val_in_int64(&s
->ioc_ctrl
, addr
, size
, val
);
630 case 0x0010: /* TOC_CLIENT_ID */
632 case 0x0030: /* HP-UX 10.20 and 11.11 reads it. No idea. */
634 case 0x0300 ... 0x03d8 - 1: /* LMMIO_DIRECT0_BASE... */
635 put_val_in_arrary(s
->ioc_ranges
, 0x300, addr
, size
, val
);
639 case 0x10230: /* HP-UX 11.11 reads it. No idea. */
641 case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
642 put_val_in_arrary(s
->ioc_rope_control
, 0x20200, addr
, size
, val
);
644 case 0x20040: /* IOC Rope config */
646 put_val_in_int64(&s
->ioc_rope_config
, addr
, size
, val
);
650 put_val_in_int64(&s
->tlb_ibase
, addr
, size
, val
);
654 put_val_in_int64(&s
->tlb_imask
, addr
, size
, val
);
658 put_val_in_int64(&s
->tlb_pcom
, addr
, size
, val
);
659 /* TODO: flush iommu */
663 put_val_in_int64(&s
->tlb_tcnfg
, addr
, size
, val
);
667 put_val_in_int64(&s
->tlb_pdir_base
, addr
, size
, val
);
669 case 0x22000: /* func_id */
671 case 0x22008: /* func_class */
673 case 0x22050: /* rope_debug */
675 case 0x22108: /* IOC STATUS_CONTROL */
676 put_val_in_int64(&s
->ioc_status_ctrl
, addr
, size
, val
);
679 * empty placeholders for non-existent elroys, e.g.
680 * func_class, pci config & data
682 #define EMPTY_PORT(x) case x: case x+8: case x+0x40: case x+0x48:
695 ret
= MEMTX_DECODE_ERROR
;
700 static const MemoryRegionOps astro_chip_ops
= {
701 .read_with_attrs
= astro_chip_read_with_attrs
,
702 .write_with_attrs
= astro_chip_write_with_attrs
,
703 .endianness
= DEVICE_LITTLE_ENDIAN
,
705 .min_access_size
= 4,
706 .max_access_size
= 8,
709 .min_access_size
= 4,
710 .max_access_size
= 8,
714 static const VMStateDescription vmstate_astro
= {
717 .minimum_version_id
= 1,
718 .fields
= (const VMStateField
[]) {
719 VMSTATE_UINT64(ioc_ctrl
, AstroState
),
720 VMSTATE_UINT64(ioc_status_ctrl
, AstroState
),
721 VMSTATE_UINT64_ARRAY(ioc_ranges
, AstroState
, (0x03d8 - 0x300) / 8),
722 VMSTATE_UINT64(ioc_rope_config
, AstroState
),
723 VMSTATE_UINT64(ioc_status_control
, AstroState
),
724 VMSTATE_UINT64(ioc_flush_control
, AstroState
),
725 VMSTATE_UINT64_ARRAY(ioc_rope_control
, AstroState
, 8),
726 VMSTATE_UINT64(tlb_ibase
, AstroState
),
727 VMSTATE_UINT64(tlb_imask
, AstroState
),
728 VMSTATE_UINT64(tlb_pcom
, AstroState
),
729 VMSTATE_UINT64(tlb_tcnfg
, AstroState
),
730 VMSTATE_UINT64(tlb_pdir_base
, AstroState
),
731 VMSTATE_END_OF_LIST()
735 static void astro_reset(DeviceState
*dev
)
737 AstroState
*s
= ASTRO_CHIP(dev
);
740 s
->ioc_ctrl
= 0x29cf;
741 s
->ioc_rope_config
= 0xc5f;
742 s
->ioc_flush_control
= 0xb03;
743 s
->ioc_status_control
= 0;
744 memset(&s
->ioc_rope_control
, 0, sizeof(s
->ioc_rope_control
));
747 * The SBA BASE/MASK registers control CPU -> IO routing.
748 * The LBA BASE/MASK registers control IO -> System routing (in Elroy)
750 memset(&s
->ioc_ranges
, 0, sizeof(s
->ioc_ranges
));
751 s
->ioc_ranges
[(0x360 - 0x300) / 8] = LMMIO_DIST_BASE_ADDR
| 0x01; /* LMMIO_DIST_BASE (SBA) */
752 s
->ioc_ranges
[(0x368 - 0x300) / 8] = 0xfc000000; /* LMMIO_DIST_MASK */
753 s
->ioc_ranges
[(0x370 - 0x300) / 8] = 0; /* LMMIO_DIST_ROUTE */
754 s
->ioc_ranges
[(0x390 - 0x300) / 8] = IOS_DIST_BASE_ADDR
| 0x01; /* IOS_DIST_BASE */
755 s
->ioc_ranges
[(0x398 - 0x300) / 8] = 0xffffff0000; /* IOS_DIST_MASK */
756 s
->ioc_ranges
[(0x3a0 - 0x300) / 8] = 0x3400000000000000ULL
; /* IOS_DIST_ROUTE */
757 s
->ioc_ranges
[(0x3c0 - 0x300) / 8] = 0xfffee00000; /* IOS_DIRECT_BASE */
758 s
->ioc_ranges
[(0x3c8 - 0x300) / 8] = 0xffffff0000; /* IOS_DIRECT_MASK */
759 s
->ioc_ranges
[(0x3d0 - 0x300) / 8] = 0x0; /* IOS_DIRECT_ROUTE */
765 s
->tlb_pdir_base
= 0;
767 for (i
= 0; i
< ELROY_NUM
; i
++) {
768 elroy_reset(DEVICE(s
->elroy
[i
]));
772 static void astro_init(Object
*obj
)
776 static void astro_realize(DeviceState
*obj
, Error
**errp
)
778 AstroState
*s
= ASTRO_CHIP(obj
);
779 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
782 memory_region_init_io(&s
->this_mem
, OBJECT(s
), &astro_chip_ops
,
783 s
, "astro", 0x40000);
784 sysbus_init_mmio(sbd
, &s
->this_mem
);
786 /* Host memory as seen from Elroys PCI side, via the IOMMU. */
787 memory_region_init_iommu(&s
->iommu
, sizeof(s
->iommu
),
788 TYPE_ASTRO_IOMMU_MEMORY_REGION
, OBJECT(s
),
789 "iommu-astro", UINT64_MAX
);
790 address_space_init(&s
->iommu_as
, MEMORY_REGION(&s
->iommu
),
793 /* Create Elroys (PCI host bus chips). */
794 for (i
= 0; i
< ELROY_NUM
; i
++) {
795 static const int elroy_hpa_offsets
[ELROY_NUM
] = {
796 0x30000, 0x32000, 0x38000, 0x3c000 };
797 static const char elroy_rope_nr
[ELROY_NUM
] = {
798 0, 1, 4, 6 }; /* busnum path, e.g. [10:6] */
805 addr_offset
= elroy_hpa_offsets
[i
];
806 rope
= elroy_rope_nr
[i
];
808 elroy
= elroy_init(i
);
810 elroy
->hpa
= ASTRO_HPA
+ addr_offset
;
811 elroy
->pci_bus_num
= i
;
815 * NOTE: we only allow PCI devices on first Elroy for now.
816 * SeaBIOS will not find devices on the other busses.
819 qbus_mark_full(&PCI_HOST_BRIDGE(elroy
)->bus
->qbus
);
822 /* map elroy config addresses into Astro space */
823 memory_region_add_subregion(&s
->this_mem
, addr_offset
,
827 elroy
->mmio_base
[(0x0200 - 0x200) / 8] = 0xf0000001;
828 elroy
->mmio_base
[(0x0208 - 0x200) / 8] = 0xf8000000;
830 elroy
->mmio_base
[(0x0210 - 0x200) / 8] = 0x000000f800000001;
831 elroy
->mmio_base
[(0x0218 - 0x200) / 8] = 0x000000ff80000000;
833 elroy
->mmio_base
[(0x0220 - 0x200) / 8] = 0xf0000001;
834 elroy
->mmio_base
[(0x0228 - 0x200) / 8] = 0xf0000000;
836 elroy
->mmio_base
[(0x0230 - 0x200) / 8] = 0x000000f800000001;
837 elroy
->mmio_base
[(0x0238 - 0x200) / 8] = 0x000000fc00000000;
839 map_size
= IOS_DIST_BASE_SIZE
/ ROPES_PER_IOC
;
840 elroy
->mmio_base
[(0x0240 - 0x200) / 8] = rope
* map_size
| 0x01;
841 elroy
->mmio_base
[(0x0248 - 0x200) / 8] = 0x0000e000;
843 /* map elroys mmio */
844 map_size
= LMMIO_DIST_BASE_SIZE
/ ROPES_PER_IOC
;
845 map_addr
= F_EXTEND(LMMIO_DIST_BASE_ADDR
+ rope
* map_size
);
846 memory_region_init_alias(&elroy
->pci_mmio_alias
, OBJECT(elroy
),
848 &elroy
->pci_mmio
, (uint32_t) map_addr
, map_size
);
849 memory_region_add_subregion(get_system_memory(), map_addr
,
850 &elroy
->pci_mmio_alias
);
853 map_size
= IOS_DIST_BASE_SIZE
/ ROPES_PER_IOC
;
854 map_addr
= F_EXTEND(IOS_DIST_BASE_ADDR
+ rope
* map_size
);
855 memory_region_add_subregion(get_system_memory(), map_addr
,
858 /* Host memory as seen from the PCI side, via the IOMMU. */
859 pci_setup_iommu(PCI_HOST_BRIDGE(elroy
)->bus
, &elroy_pcihost_iommu_ops
,
864 static void astro_class_init(ObjectClass
*klass
, void *data
)
866 DeviceClass
*dc
= DEVICE_CLASS(klass
);
868 dc
->reset
= astro_reset
;
869 dc
->vmsd
= &vmstate_astro
;
870 dc
->realize
= astro_realize
;
872 * astro with elroys are hard part of the newer PA2.0 machines and can not
873 * be created without that hardware
875 dc
->user_creatable
= false;
878 static const TypeInfo astro_chip_info
= {
879 .name
= TYPE_ASTRO_CHIP
,
880 .parent
= TYPE_SYS_BUS_DEVICE
,
881 .instance_init
= astro_init
,
882 .instance_size
= sizeof(AstroState
),
883 .class_init
= astro_class_init
,
886 static void astro_iommu_memory_region_class_init(ObjectClass
*klass
,
889 IOMMUMemoryRegionClass
*imrc
= IOMMU_MEMORY_REGION_CLASS(klass
);
891 imrc
->translate
= astro_translate_iommu
;
894 static const TypeInfo astro_iommu_memory_region_info
= {
895 .parent
= TYPE_IOMMU_MEMORY_REGION
,
896 .name
= TYPE_ASTRO_IOMMU_MEMORY_REGION
,
897 .class_init
= astro_iommu_memory_region_class_init
,
901 static void astro_register_types(void)
903 type_register_static(&astro_chip_info
);
904 type_register_static(&astro_iommu_memory_region_info
);
907 type_init(astro_register_types
)