4 * Copyright 2014 IBM Corp.
5 * Author(s): Frank Blaschka <frank.blaschka@de.ibm.com>
6 * Hong Bo Li <lihbbj@cn.ibm.com>
7 * Yi Min Zhao <zyimin@cn.ibm.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or (at
10 * your option) any later version. See the COPYING file in the top-level
14 #include "qemu/osdep.h"
15 #include "qapi/error.h"
16 #include "qapi/visitor.h"
17 #include "qemu-common.h"
19 #include "s390-pci-bus.h"
20 #include "s390-pci-inst.h"
21 #include "hw/pci/pci_bus.h"
22 #include "hw/pci/msi.h"
23 #include "qemu/error-report.h"
25 /* #define DEBUG_S390PCI_BUS */
26 #ifdef DEBUG_S390PCI_BUS
27 #define DPRINTF(fmt, ...) \
28 do { fprintf(stderr, "S390pci-bus: " fmt, ## __VA_ARGS__); } while (0)
30 #define DPRINTF(fmt, ...) \
34 static S390pciState
*s390_get_phb(void)
36 static S390pciState
*phb
;
39 phb
= S390_PCI_HOST_BRIDGE(
40 object_resolve_path(TYPE_S390_PCI_HOST_BRIDGE
, NULL
));
47 int chsc_sei_nt2_get_event(void *res
)
49 ChscSeiNt2Res
*nt2_res
= (ChscSeiNt2Res
*)res
;
53 SeiContainer
*sei_cont
;
54 S390pciState
*s
= s390_get_phb();
56 sei_cont
= QTAILQ_FIRST(&s
->pending_sei
);
58 QTAILQ_REMOVE(&s
->pending_sei
, sei_cont
, link
);
60 nt2_res
->cc
= sei_cont
->cc
;
61 nt2_res
->length
= cpu_to_be16(sizeof(ChscSeiNt2Res
));
62 switch (sei_cont
->cc
) {
63 case 1: /* error event */
64 eccdf
= (PciCcdfErr
*)nt2_res
->ccdf
;
65 eccdf
->fid
= cpu_to_be32(sei_cont
->fid
);
66 eccdf
->fh
= cpu_to_be32(sei_cont
->fh
);
67 eccdf
->e
= cpu_to_be32(sei_cont
->e
);
68 eccdf
->faddr
= cpu_to_be64(sei_cont
->faddr
);
69 eccdf
->pec
= cpu_to_be16(sei_cont
->pec
);
71 case 2: /* availability event */
72 accdf
= (PciCcdfAvail
*)nt2_res
->ccdf
;
73 accdf
->fid
= cpu_to_be32(sei_cont
->fid
);
74 accdf
->fh
= cpu_to_be32(sei_cont
->fh
);
75 accdf
->pec
= cpu_to_be16(sei_cont
->pec
);
87 int chsc_sei_nt2_have_event(void)
89 S390pciState
*s
= s390_get_phb();
91 return !QTAILQ_EMPTY(&s
->pending_sei
);
94 S390PCIBusDevice
*s390_pci_find_next_avail_dev(S390PCIBusDevice
*pbdev
)
97 S390PCIBusDevice
*dev
= NULL
;
98 S390pciState
*s
= s390_get_phb();
101 idx
= (pbdev
->fh
& FH_MASK_INDEX
) + 1;
104 for (; idx
< PCI_SLOT_MAX
; idx
++) {
106 if (dev
&& dev
->state
!= ZPCI_FS_RESERVED
) {
114 S390PCIBusDevice
*s390_pci_find_dev_by_fid(uint32_t fid
)
116 S390PCIBusDevice
*pbdev
;
118 S390pciState
*s
= s390_get_phb();
120 for (i
= 0; i
< PCI_SLOT_MAX
; i
++) {
122 if (pbdev
&& pbdev
->fid
== fid
) {
130 void s390_pci_sclp_configure(SCCB
*sccb
)
132 PciCfgSccb
*psccb
= (PciCfgSccb
*)sccb
;
133 S390PCIBusDevice
*pbdev
= s390_pci_find_dev_by_fid(be32_to_cpu(psccb
->aid
));
136 if (be16_to_cpu(sccb
->h
.length
) < 16) {
137 rc
= SCLP_RC_INSUFFICIENT_SCCB_LENGTH
;
142 DPRINTF("sclp config no dev found\n");
143 rc
= SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED
;
147 switch (pbdev
->state
) {
148 case ZPCI_FS_RESERVED
:
149 rc
= SCLP_RC_ADAPTER_IN_RESERVED_STATE
;
151 case ZPCI_FS_STANDBY
:
152 pbdev
->state
= ZPCI_FS_DISABLED
;
153 rc
= SCLP_RC_NORMAL_COMPLETION
;
156 rc
= SCLP_RC_NO_ACTION_REQUIRED
;
159 psccb
->header
.response_code
= cpu_to_be16(rc
);
162 void s390_pci_sclp_deconfigure(SCCB
*sccb
)
164 PciCfgSccb
*psccb
= (PciCfgSccb
*)sccb
;
165 S390PCIBusDevice
*pbdev
= s390_pci_find_dev_by_fid(be32_to_cpu(psccb
->aid
));
168 if (be16_to_cpu(sccb
->h
.length
) < 16) {
169 rc
= SCLP_RC_INSUFFICIENT_SCCB_LENGTH
;
174 DPRINTF("sclp deconfig no dev found\n");
175 rc
= SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED
;
179 switch (pbdev
->state
) {
180 case ZPCI_FS_RESERVED
:
181 rc
= SCLP_RC_ADAPTER_IN_RESERVED_STATE
;
183 case ZPCI_FS_STANDBY
:
184 rc
= SCLP_RC_NO_ACTION_REQUIRED
;
187 if (pbdev
->summary_ind
) {
188 pci_dereg_irqs(pbdev
);
190 if (pbdev
->iommu_enabled
) {
191 pci_dereg_ioat(pbdev
);
193 pbdev
->state
= ZPCI_FS_STANDBY
;
194 rc
= SCLP_RC_NORMAL_COMPLETION
;
196 if (pbdev
->release_timer
) {
197 qdev_unplug(DEVICE(pbdev
->pdev
), NULL
);
201 psccb
->header
.response_code
= cpu_to_be16(rc
);
204 static S390PCIBusDevice
*s390_pci_find_dev_by_uid(uint16_t uid
)
207 S390PCIBusDevice
*pbdev
;
208 S390pciState
*s
= s390_get_phb();
210 for (i
= 0; i
< PCI_SLOT_MAX
; i
++) {
216 if (pbdev
->uid
== uid
) {
224 static S390PCIBusDevice
*s390_pci_find_dev_by_target(const char *target
)
227 S390PCIBusDevice
*pbdev
;
228 S390pciState
*s
= s390_get_phb();
234 for (i
= 0; i
< PCI_SLOT_MAX
; i
++) {
240 if (!strcmp(pbdev
->target
, target
)) {
248 S390PCIBusDevice
*s390_pci_find_dev_by_idx(uint32_t idx
)
250 S390pciState
*s
= s390_get_phb();
252 return s
->pbdev
[idx
& FH_MASK_INDEX
];
255 S390PCIBusDevice
*s390_pci_find_dev_by_fh(uint32_t fh
)
257 S390pciState
*s
= s390_get_phb();
258 S390PCIBusDevice
*pbdev
;
260 pbdev
= s
->pbdev
[fh
& FH_MASK_INDEX
];
261 if (pbdev
&& pbdev
->fh
== fh
) {
268 static void s390_pci_generate_event(uint8_t cc
, uint16_t pec
, uint32_t fh
,
269 uint32_t fid
, uint64_t faddr
, uint32_t e
)
271 SeiContainer
*sei_cont
;
272 S390pciState
*s
= s390_get_phb();
274 sei_cont
= g_malloc0(sizeof(SeiContainer
));
279 sei_cont
->faddr
= faddr
;
282 QTAILQ_INSERT_TAIL(&s
->pending_sei
, sei_cont
, link
);
283 css_generate_css_crws(0);
286 static void s390_pci_generate_plug_event(uint16_t pec
, uint32_t fh
,
289 s390_pci_generate_event(2, pec
, fh
, fid
, 0, 0);
292 void s390_pci_generate_error_event(uint16_t pec
, uint32_t fh
, uint32_t fid
,
293 uint64_t faddr
, uint32_t e
)
295 s390_pci_generate_event(1, pec
, fh
, fid
, faddr
, e
);
298 static void s390_pci_set_irq(void *opaque
, int irq
, int level
)
303 static int s390_pci_map_irq(PCIDevice
*pci_dev
, int irq_num
)
309 static uint64_t s390_pci_get_table_origin(uint64_t iota
)
311 return iota
& ~ZPCI_IOTA_RTTO_FLAG
;
314 static unsigned int calc_rtx(dma_addr_t ptr
)
316 return ((unsigned long) ptr
>> ZPCI_RT_SHIFT
) & ZPCI_INDEX_MASK
;
319 static unsigned int calc_sx(dma_addr_t ptr
)
321 return ((unsigned long) ptr
>> ZPCI_ST_SHIFT
) & ZPCI_INDEX_MASK
;
324 static unsigned int calc_px(dma_addr_t ptr
)
326 return ((unsigned long) ptr
>> PAGE_SHIFT
) & ZPCI_PT_MASK
;
329 static uint64_t get_rt_sto(uint64_t entry
)
331 return ((entry
& ZPCI_TABLE_TYPE_MASK
) == ZPCI_TABLE_TYPE_RTX
)
332 ? (entry
& ZPCI_RTE_ADDR_MASK
)
336 static uint64_t get_st_pto(uint64_t entry
)
338 return ((entry
& ZPCI_TABLE_TYPE_MASK
) == ZPCI_TABLE_TYPE_SX
)
339 ? (entry
& ZPCI_STE_ADDR_MASK
)
343 static uint64_t s390_guest_io_table_walk(uint64_t guest_iota
,
344 uint64_t guest_dma_address
)
346 uint64_t sto_a
, pto_a
, px_a
;
347 uint64_t sto
, pto
, pte
;
348 uint32_t rtx
, sx
, px
;
350 rtx
= calc_rtx(guest_dma_address
);
351 sx
= calc_sx(guest_dma_address
);
352 px
= calc_px(guest_dma_address
);
354 sto_a
= guest_iota
+ rtx
* sizeof(uint64_t);
355 sto
= address_space_ldq(&address_space_memory
, sto_a
,
356 MEMTXATTRS_UNSPECIFIED
, NULL
);
357 sto
= get_rt_sto(sto
);
363 pto_a
= sto
+ sx
* sizeof(uint64_t);
364 pto
= address_space_ldq(&address_space_memory
, pto_a
,
365 MEMTXATTRS_UNSPECIFIED
, NULL
);
366 pto
= get_st_pto(pto
);
372 px_a
= pto
+ px
* sizeof(uint64_t);
373 pte
= address_space_ldq(&address_space_memory
, px_a
,
374 MEMTXATTRS_UNSPECIFIED
, NULL
);
380 static IOMMUTLBEntry
s390_translate_iommu(MemoryRegion
*iommu
, hwaddr addr
,
385 S390PCIBusDevice
*pbdev
= container_of(iommu
, S390PCIBusDevice
, iommu_mr
);
387 IOMMUTLBEntry ret
= {
388 .target_as
= &address_space_memory
,
390 .translated_addr
= 0,
391 .addr_mask
= ~(hwaddr
)0,
395 switch (pbdev
->state
) {
396 case ZPCI_FS_ENABLED
:
397 case ZPCI_FS_BLOCKED
:
398 if (!pbdev
->iommu_enabled
) {
406 DPRINTF("iommu trans addr 0x%" PRIx64
"\n", addr
);
408 s
= S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev
->pdev
)->qbus
.parent
);
409 /* s390 does not have an APIC mapped to main storage so we use
410 * a separate AddressSpace only for msix notifications
412 if (addr
== ZPCI_MSI_ADDR
) {
413 ret
.target_as
= &s
->msix_notify_as
;
415 ret
.translated_addr
= addr
;
416 ret
.addr_mask
= 0xfff;
421 if (addr
< pbdev
->pba
|| addr
> pbdev
->pal
) {
425 pte
= s390_guest_io_table_walk(s390_pci_get_table_origin(pbdev
->g_iota
),
431 flags
= pte
& ZPCI_PTE_FLAG_MASK
;
433 ret
.translated_addr
= pte
& ZPCI_PTE_ADDR_MASK
;
434 ret
.addr_mask
= 0xfff;
436 if (flags
& ZPCI_PTE_INVALID
) {
437 ret
.perm
= IOMMU_NONE
;
445 static const MemoryRegionIOMMUOps s390_iommu_ops
= {
446 .translate
= s390_translate_iommu
,
449 static AddressSpace
*s390_pci_dma_iommu(PCIBus
*bus
, void *opaque
, int devfn
)
451 S390pciState
*s
= opaque
;
453 return &s
->iommu
[PCI_SLOT(devfn
)]->as
;
456 static uint8_t set_ind_atomic(uint64_t ind_loc
, uint8_t to_be_set
)
458 uint8_t ind_old
, ind_new
;
462 ind_addr
= cpu_physical_memory_map(ind_loc
, &len
, 1);
464 s390_pci_generate_error_event(ERR_EVENT_AIRERR
, 0, 0, 0, 0);
469 ind_new
= ind_old
| to_be_set
;
470 } while (atomic_cmpxchg(ind_addr
, ind_old
, ind_new
) != ind_old
);
471 cpu_physical_memory_unmap(ind_addr
, len
, 1, len
);
476 static void s390_msi_ctrl_write(void *opaque
, hwaddr addr
, uint64_t data
,
479 S390PCIBusDevice
*pbdev
;
480 uint32_t io_int_word
;
481 uint32_t idx
= data
>> ZPCI_MSI_VEC_BITS
;
482 uint32_t vec
= data
& ZPCI_MSI_VEC_MASK
;
487 DPRINTF("write_msix data 0x%" PRIx64
" idx %d vec 0x%x\n", data
, idx
, vec
);
489 pbdev
= s390_pci_find_dev_by_idx(idx
);
491 e
|= (vec
<< ERR_EVENT_MVN_OFFSET
);
492 s390_pci_generate_error_event(ERR_EVENT_NOMSI
, idx
, 0, addr
, e
);
496 if (pbdev
->state
!= ZPCI_FS_ENABLED
) {
500 ind_bit
= pbdev
->routes
.adapter
.ind_offset
;
501 sum_bit
= pbdev
->routes
.adapter
.summary_offset
;
503 set_ind_atomic(pbdev
->routes
.adapter
.ind_addr
+ (ind_bit
+ vec
) / 8,
504 0x80 >> ((ind_bit
+ vec
) % 8));
505 if (!set_ind_atomic(pbdev
->routes
.adapter
.summary_addr
+ sum_bit
/ 8,
506 0x80 >> (sum_bit
% 8))) {
507 io_int_word
= (pbdev
->isc
<< 27) | IO_INT_WORD_AI
;
508 s390_io_interrupt(0, 0, 0, io_int_word
);
512 static uint64_t s390_msi_ctrl_read(void *opaque
, hwaddr addr
, unsigned size
)
517 static const MemoryRegionOps s390_msi_ctrl_ops
= {
518 .write
= s390_msi_ctrl_write
,
519 .read
= s390_msi_ctrl_read
,
520 .endianness
= DEVICE_LITTLE_ENDIAN
,
523 void s390_pci_iommu_enable(S390PCIBusDevice
*pbdev
)
525 memory_region_init_iommu(&pbdev
->iommu_mr
, OBJECT(&pbdev
->iommu
->mr
),
526 &s390_iommu_ops
, "iommu-s390", pbdev
->pal
+ 1);
527 memory_region_add_subregion(&pbdev
->iommu
->mr
, 0, &pbdev
->iommu_mr
);
528 pbdev
->iommu_enabled
= true;
531 void s390_pci_iommu_disable(S390PCIBusDevice
*pbdev
)
533 memory_region_del_subregion(&pbdev
->iommu
->mr
, &pbdev
->iommu_mr
);
534 object_unparent(OBJECT(&pbdev
->iommu_mr
));
535 pbdev
->iommu_enabled
= false;
538 static void s390_pcihost_init_as(S390pciState
*s
)
543 for (i
= 0; i
< PCI_SLOT_MAX
; i
++) {
544 iommu
= g_malloc0(sizeof(S390PCIIOMMU
));
545 memory_region_init(&iommu
->mr
, OBJECT(s
),
546 "iommu-root-s390", UINT64_MAX
);
547 address_space_init(&iommu
->as
, &iommu
->mr
, "iommu-pci");
552 memory_region_init_io(&s
->msix_notify_mr
, OBJECT(s
),
553 &s390_msi_ctrl_ops
, s
, "msix-s390", UINT64_MAX
);
554 address_space_init(&s
->msix_notify_as
, &s
->msix_notify_mr
, "msix-pci");
557 static int s390_pcihost_init(SysBusDevice
*dev
)
561 PCIHostState
*phb
= PCI_HOST_BRIDGE(dev
);
562 S390pciState
*s
= S390_PCI_HOST_BRIDGE(dev
);
564 DPRINTF("host_init\n");
566 b
= pci_register_bus(DEVICE(dev
), NULL
,
567 s390_pci_set_irq
, s390_pci_map_irq
, NULL
,
568 get_system_memory(), get_system_io(), 0, 64,
570 s390_pcihost_init_as(s
);
571 pci_setup_iommu(b
, s390_pci_dma_iommu
, s
);
574 qbus_set_hotplug_handler(bus
, DEVICE(dev
), NULL
);
577 s
->bus
= S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS
, DEVICE(s
), NULL
));
578 qbus_set_hotplug_handler(BUS(s
->bus
), DEVICE(s
), NULL
);
580 QTAILQ_INIT(&s
->pending_sei
);
584 static int s390_pcihost_setup_msix(S390PCIBusDevice
*pbdev
)
590 pos
= pci_find_capability(pbdev
->pdev
, PCI_CAP_ID_MSIX
);
592 pbdev
->msix
.available
= false;
596 ctrl
= pci_host_config_read_common(pbdev
->pdev
, pos
+ PCI_MSIX_FLAGS
,
597 pci_config_size(pbdev
->pdev
), sizeof(ctrl
));
598 table
= pci_host_config_read_common(pbdev
->pdev
, pos
+ PCI_MSIX_TABLE
,
599 pci_config_size(pbdev
->pdev
), sizeof(table
));
600 pba
= pci_host_config_read_common(pbdev
->pdev
, pos
+ PCI_MSIX_PBA
,
601 pci_config_size(pbdev
->pdev
), sizeof(pba
));
603 pbdev
->msix
.table_bar
= table
& PCI_MSIX_FLAGS_BIRMASK
;
604 pbdev
->msix
.table_offset
= table
& ~PCI_MSIX_FLAGS_BIRMASK
;
605 pbdev
->msix
.pba_bar
= pba
& PCI_MSIX_FLAGS_BIRMASK
;
606 pbdev
->msix
.pba_offset
= pba
& ~PCI_MSIX_FLAGS_BIRMASK
;
607 pbdev
->msix
.entries
= (ctrl
& PCI_MSIX_FLAGS_QSIZE
) + 1;
608 pbdev
->msix
.available
= true;
612 static S390PCIBusDevice
*s390_pci_device_new(const char *target
)
614 DeviceState
*dev
= NULL
;
615 S390pciState
*s
= s390_get_phb();
617 dev
= qdev_try_create(BUS(s
->bus
), TYPE_S390_PCI_DEVICE
);
622 qdev_prop_set_string(dev
, "target", target
);
623 qdev_init_nofail(dev
);
625 return S390_PCI_DEVICE(dev
);
628 static void s390_pcihost_hot_plug(HotplugHandler
*hotplug_dev
,
629 DeviceState
*dev
, Error
**errp
)
631 PCIDevice
*pdev
= NULL
;
632 S390PCIBusDevice
*pbdev
= NULL
;
633 S390pciState
*s
= s390_get_phb();
635 if (object_dynamic_cast(OBJECT(dev
), TYPE_PCI_DEVICE
)) {
636 pdev
= PCI_DEVICE(dev
);
639 /* In the case the PCI device does not define an id */
640 /* we generate one based on the PCI address */
641 dev
->id
= g_strdup_printf("auto_%02x:%02x.%01x",
642 pci_bus_num(pdev
->bus
),
643 PCI_SLOT(pdev
->devfn
),
644 PCI_FUNC(pdev
->devfn
));
647 pbdev
= s390_pci_find_dev_by_target(dev
->id
);
649 pbdev
= s390_pci_device_new(dev
->id
);
651 error_setg(errp
, "create zpci device failed");
655 if (object_dynamic_cast(OBJECT(dev
), "vfio-pci")) {
656 pbdev
->fh
|= FH_SHM_VFIO
;
658 pbdev
->fh
|= FH_SHM_EMUL
;
662 pbdev
->iommu
= s
->iommu
[PCI_SLOT(pdev
->devfn
)];
663 pbdev
->state
= ZPCI_FS_STANDBY
;
664 s390_pcihost_setup_msix(pbdev
);
666 if (dev
->hotplugged
) {
667 s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY
,
668 pbdev
->fh
, pbdev
->fid
);
670 } else if (object_dynamic_cast(OBJECT(dev
), TYPE_S390_PCI_DEVICE
)) {
673 pbdev
= S390_PCI_DEVICE(dev
);
674 for (idx
= 0; idx
< PCI_SLOT_MAX
; idx
++) {
675 if (!s
->pbdev
[idx
]) {
676 s
->pbdev
[idx
] = pbdev
;
682 error_setg(errp
, "no slot for plugging zpci device");
686 static void s390_pcihost_timer_cb(void *opaque
)
688 S390PCIBusDevice
*pbdev
= opaque
;
690 if (pbdev
->summary_ind
) {
691 pci_dereg_irqs(pbdev
);
693 if (pbdev
->iommu_enabled
) {
694 pci_dereg_ioat(pbdev
);
697 pbdev
->state
= ZPCI_FS_STANDBY
;
698 s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES
,
699 pbdev
->fh
, pbdev
->fid
);
700 qdev_unplug(DEVICE(pbdev
), NULL
);
703 static void s390_pcihost_hot_unplug(HotplugHandler
*hotplug_dev
,
704 DeviceState
*dev
, Error
**errp
)
707 PCIDevice
*pci_dev
= NULL
;
708 S390PCIBusDevice
*pbdev
= NULL
;
709 S390pciState
*s
= s390_get_phb();
711 if (object_dynamic_cast(OBJECT(dev
), TYPE_PCI_DEVICE
)) {
712 pci_dev
= PCI_DEVICE(dev
);
714 for (i
= 0 ; i
< PCI_SLOT_MAX
; i
++) {
715 if (s
->pbdev
[i
] && s
->pbdev
[i
]->pdev
== pci_dev
) {
722 object_unparent(OBJECT(pci_dev
));
725 } else if (object_dynamic_cast(OBJECT(dev
), TYPE_S390_PCI_DEVICE
)) {
726 pbdev
= S390_PCI_DEVICE(dev
);
727 pci_dev
= pbdev
->pdev
;
730 switch (pbdev
->state
) {
731 case ZPCI_FS_RESERVED
:
733 case ZPCI_FS_STANDBY
:
736 s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST
,
737 pbdev
->fh
, pbdev
->fid
);
738 pbdev
->release_timer
= timer_new_ns(QEMU_CLOCK_VIRTUAL
,
739 s390_pcihost_timer_cb
,
741 timer_mod(pbdev
->release_timer
,
742 qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL
) + HOT_UNPLUG_TIMEOUT
);
746 if (pbdev
->release_timer
&& timer_pending(pbdev
->release_timer
)) {
747 timer_del(pbdev
->release_timer
);
748 timer_free(pbdev
->release_timer
);
749 pbdev
->release_timer
= NULL
;
752 s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED
,
753 pbdev
->fh
, pbdev
->fid
);
754 object_unparent(OBJECT(pci_dev
));
756 pbdev
->state
= ZPCI_FS_RESERVED
;
759 s
->pbdev
[pbdev
->fh
& FH_MASK_INDEX
] = NULL
;
760 object_unparent(OBJECT(pbdev
));
763 static void s390_pcihost_class_init(ObjectClass
*klass
, void *data
)
765 SysBusDeviceClass
*k
= SYS_BUS_DEVICE_CLASS(klass
);
766 DeviceClass
*dc
= DEVICE_CLASS(klass
);
767 HotplugHandlerClass
*hc
= HOTPLUG_HANDLER_CLASS(klass
);
769 dc
->cannot_instantiate_with_device_add_yet
= true;
770 k
->init
= s390_pcihost_init
;
771 hc
->plug
= s390_pcihost_hot_plug
;
772 hc
->unplug
= s390_pcihost_hot_unplug
;
773 msi_nonbroken
= true;
776 static const TypeInfo s390_pcihost_info
= {
777 .name
= TYPE_S390_PCI_HOST_BRIDGE
,
778 .parent
= TYPE_PCI_HOST_BRIDGE
,
779 .instance_size
= sizeof(S390pciState
),
780 .class_init
= s390_pcihost_class_init
,
781 .interfaces
= (InterfaceInfo
[]) {
782 { TYPE_HOTPLUG_HANDLER
},
787 static const TypeInfo s390_pcibus_info
= {
788 .name
= TYPE_S390_PCI_BUS
,
790 .instance_size
= sizeof(S390PCIBus
),
793 static uint16_t s390_pci_generate_uid(void)
799 if (!s390_pci_find_dev_by_uid(uid
)) {
802 } while (uid
< ZPCI_MAX_UID
);
804 return UID_UNDEFINED
;
807 static uint32_t s390_pci_generate_fid(Error
**errp
)
811 while (fid
<= ZPCI_MAX_FID
) {
812 if (!s390_pci_find_dev_by_fid(fid
)) {
816 if (fid
== ZPCI_MAX_FID
) {
823 error_setg(errp
, "no free fid could be found");
827 static void s390_pci_device_realize(DeviceState
*dev
, Error
**errp
)
829 S390PCIBusDevice
*zpci
= S390_PCI_DEVICE(dev
);
832 error_setg(errp
, "target must be defined");
836 if (s390_pci_find_dev_by_target(zpci
->target
)) {
837 error_setg(errp
, "target %s already has an associated zpci device",
842 if (zpci
->uid
== UID_UNDEFINED
) {
843 zpci
->uid
= s390_pci_generate_uid();
845 error_setg(errp
, "no free uid could be found");
848 } else if (s390_pci_find_dev_by_uid(zpci
->uid
)) {
849 error_setg(errp
, "uid %u already in use", zpci
->uid
);
853 if (!zpci
->fid_defined
) {
854 Error
*local_error
= NULL
;
856 zpci
->fid
= s390_pci_generate_fid(&local_error
);
858 error_propagate(errp
, local_error
);
861 } else if (s390_pci_find_dev_by_fid(zpci
->fid
)) {
862 error_setg(errp
, "fid %u already in use", zpci
->fid
);
866 zpci
->state
= ZPCI_FS_RESERVED
;
869 static void s390_pci_device_reset(DeviceState
*dev
)
871 S390PCIBusDevice
*pbdev
= S390_PCI_DEVICE(dev
);
873 switch (pbdev
->state
) {
874 case ZPCI_FS_RESERVED
:
876 case ZPCI_FS_STANDBY
:
879 pbdev
->fh
&= ~FH_MASK_ENABLE
;
880 pbdev
->state
= ZPCI_FS_DISABLED
;
884 if (pbdev
->summary_ind
) {
885 pci_dereg_irqs(pbdev
);
887 if (pbdev
->iommu_enabled
) {
888 pci_dereg_ioat(pbdev
);
894 static void s390_pci_get_fid(Object
*obj
, Visitor
*v
, const char *name
,
895 void *opaque
, Error
**errp
)
897 Property
*prop
= opaque
;
898 uint32_t *ptr
= qdev_get_prop_ptr(DEVICE(obj
), prop
);
900 visit_type_uint32(v
, name
, ptr
, errp
);
903 static void s390_pci_set_fid(Object
*obj
, Visitor
*v
, const char *name
,
904 void *opaque
, Error
**errp
)
906 DeviceState
*dev
= DEVICE(obj
);
907 S390PCIBusDevice
*zpci
= S390_PCI_DEVICE(obj
);
908 Property
*prop
= opaque
;
909 uint32_t *ptr
= qdev_get_prop_ptr(dev
, prop
);
912 qdev_prop_set_after_realize(dev
, name
, errp
);
916 visit_type_uint32(v
, name
, ptr
, errp
);
917 zpci
->fid_defined
= true;
920 static PropertyInfo s390_pci_fid_propinfo
= {
922 .get
= s390_pci_get_fid
,
923 .set
= s390_pci_set_fid
,
926 #define DEFINE_PROP_S390_PCI_FID(_n, _s, _f) \
927 DEFINE_PROP(_n, _s, _f, s390_pci_fid_propinfo, uint32_t)
929 static Property s390_pci_device_properties
[] = {
930 DEFINE_PROP_UINT16("uid", S390PCIBusDevice
, uid
, UID_UNDEFINED
),
931 DEFINE_PROP_S390_PCI_FID("fid", S390PCIBusDevice
, fid
),
932 DEFINE_PROP_STRING("target", S390PCIBusDevice
, target
),
933 DEFINE_PROP_END_OF_LIST(),
936 static void s390_pci_device_class_init(ObjectClass
*klass
, void *data
)
938 DeviceClass
*dc
= DEVICE_CLASS(klass
);
940 dc
->desc
= "zpci device";
941 dc
->reset
= s390_pci_device_reset
;
942 dc
->bus_type
= TYPE_S390_PCI_BUS
;
943 dc
->realize
= s390_pci_device_realize
;
944 dc
->props
= s390_pci_device_properties
;
947 static const TypeInfo s390_pci_device_info
= {
948 .name
= TYPE_S390_PCI_DEVICE
,
949 .parent
= TYPE_DEVICE
,
950 .instance_size
= sizeof(S390PCIBusDevice
),
951 .class_init
= s390_pci_device_class_init
,
954 static void s390_pci_register_types(void)
956 type_register_static(&s390_pcihost_info
);
957 type_register_static(&s390_pcibus_info
);
958 type_register_static(&s390_pci_device_info
);
961 type_init(s390_pci_register_types
)