@ -23,6 +23,9 @@
# define TYPE_PXB_BUS "pxb-bus"
# define PXB_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_BUS)
# define TYPE_PXB_PCIE_BUS "pxb-pcie-bus"
# define PXB_PCIE_BUS(obj) OBJECT_CHECK(PXBBus, (obj), TYPE_PXB_PCIE_BUS)
typedef struct PXBBus {
/*< private >*/
PCIBus parent_obj ;
@ -34,6 +37,9 @@ typedef struct PXBBus {
# define TYPE_PXB_DEVICE "pxb"
# define PXB_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_DEVICE)
# define TYPE_PXB_PCIE_DEVICE "pxb-pcie"
# define PXB_PCIE_DEV(obj) OBJECT_CHECK(PXBDev, (obj), TYPE_PXB_PCIE_DEVICE)
typedef struct PXBDev {
/*< private >*/
PCIDevice parent_obj ;
@ -43,13 +49,18 @@ typedef struct PXBDev {
uint16_t numa_node ;
} PXBDev ;
static PXBDev * convert_to_pxb ( PCIDevice * dev )
{
return pci_bus_is_express ( dev - > bus ) ? PXB_PCIE_DEV ( dev ) : PXB_DEV ( dev ) ;
}
static GList * pxb_dev_list ;
# define TYPE_PXB_HOST "pxb-host"
static int pxb_bus_num ( PCIBus * bus )
{
PXBDev * pxb = PXB_DEV ( bus - > parent_dev ) ;
PXBDev * pxb = convert_to_pxb ( bus - > parent_dev ) ;
return pxb - > bus_nr ;
}
@ -61,7 +72,7 @@ static bool pxb_is_root(PCIBus *bus)
static uint16_t pxb_bus_numa_node ( PCIBus * bus )
{
PXBDev * pxb = PXB_DEV ( bus - > parent_dev ) ;
PXBDev * pxb = convert_to_pxb ( bus - > parent_dev ) ;
return pxb - > numa_node ;
}
@ -82,10 +93,18 @@ static const TypeInfo pxb_bus_info = {
. class_init = pxb_bus_class_init ,
} ;
static const TypeInfo pxb_pcie_bus_info = {
. name = TYPE_PXB_PCIE_BUS ,
. parent = TYPE_PCIE_BUS ,
. instance_size = sizeof ( PXBBus ) ,
. class_init = pxb_bus_class_init ,
} ;
static const char * pxb_host_root_bus_path ( PCIHostState * host_bridge ,
PCIBus * rootbus )
{
PXBBus * bus = PXB_BUS ( rootbus ) ;
PXBBus * bus = pci_bus_is_express ( rootbus ) ?
PXB_PCIE_BUS ( rootbus ) : PXB_BUS ( rootbus ) ;
snprintf ( bus - > bus_path , 8 , " 0000:%02x " , pxb_bus_num ( rootbus ) ) ;
return bus - > bus_path ;
@ -103,7 +122,7 @@ static char *pxb_host_ofw_unit_address(const SysBusDevice *dev)
pxb_host = PCI_HOST_BRIDGE ( dev ) ;
pxb_bus = pxb_host - > bus ;
pxb_dev = PXB_DEV ( pxb_bus - > parent_dev ) ;
pxb_dev = convert_to_pxb ( pxb_bus - > parent_dev ) ;
position = g_list_index ( pxb_dev_list , pxb_dev ) ;
assert ( position > = 0 ) ;
@ -193,10 +212,10 @@ static gint pxb_compare(gconstpointer a, gconstpointer b)
0 ;
}
static int pxb_dev_initf n ( PCIDevice * dev )
static int pxb_dev_init_commo n ( PCIDevice * dev , bool pcie )
{
PXBDev * pxb = PXB_DEV ( dev ) ;
DeviceState * ds , * bds ;
PXBDev * pxb = convert_to_pxb ( dev ) ;
DeviceState * ds , * bds = NULL ;
PCIBus * bus ;
const char * dev_name = NULL ;
@ -211,18 +230,21 @@ static int pxb_dev_initfn(PCIDevice *dev)
}
ds = qdev_create ( NULL , TYPE_PXB_HOST ) ;
bus = pci_bus_new ( ds , " pxb-internal " , NULL , NULL , 0 , TYPE_PXB_BUS ) ;
if ( pcie ) {
bus = pci_bus_new ( ds , dev_name , NULL , NULL , 0 , TYPE_PXB_PCIE_BUS ) ;
} else {
bus = pci_bus_new ( ds , " pxb-internal " , NULL , NULL , 0 , TYPE_PXB_BUS ) ;
bds = qdev_create ( BUS ( bus ) , " pci-bridge " ) ;
bds - > id = dev_name ;
qdev_prop_set_uint8 ( bds , PCI_BRIDGE_DEV_PROP_CHASSIS_NR , pxb - > bus_nr ) ;
qdev_prop_set_bit ( bds , PCI_BRIDGE_DEV_PROP_SHPC , false ) ;
}
bus - > parent_dev = dev ;
bus - > address_space_mem = dev - > bus - > address_space_mem ;
bus - > address_space_io = dev - > bus - > address_space_io ;
bus - > map_irq = pxb_map_irq_fn ;
bds = qdev_create ( BUS ( bus ) , " pci-bridge " ) ;
bds - > id = dev_name ;
qdev_prop_set_uint8 ( bds , PCI_BRIDGE_DEV_PROP_CHASSIS_NR , pxb - > bus_nr ) ;
qdev_prop_set_bit ( bds , PCI_BRIDGE_DEV_PROP_SHPC , false ) ;
PCI_HOST_BRIDGE ( ds ) - > bus = bus ;
if ( pxb_register_bus ( dev , bus ) ) {
@ -230,7 +252,9 @@ static int pxb_dev_initfn(PCIDevice *dev)
}
qdev_init_nofail ( ds ) ;
qdev_init_nofail ( bds ) ;
if ( bds ) {
qdev_init_nofail ( bds ) ;
}
pci_word_test_and_set_mask ( dev - > config + PCI_STATUS ,
PCI_STATUS_66MHZ | PCI_STATUS_FAST_BACK ) ;
@ -240,9 +264,19 @@ static int pxb_dev_initfn(PCIDevice *dev)
return 0 ;
}
static int pxb_dev_initfn ( PCIDevice * dev )
{
if ( pci_bus_is_express ( dev - > bus ) ) {
error_report ( " pxb devices cannot reside on a PCIe bus! " ) ;
return - EINVAL ;
}
return pxb_dev_init_common ( dev , false ) ;
}
static void pxb_dev_exitfn ( PCIDevice * pci_dev )
{
PXBDev * pxb = PXB_DEV ( pci_dev ) ;
PXBDev * pxb = convert_to_pxb ( pci_dev ) ;
pxb_dev_list = g_list_remove ( pxb_dev_list , pxb ) ;
}
@ -276,11 +310,45 @@ static const TypeInfo pxb_dev_info = {
. class_init = pxb_dev_class_init ,
} ;
static int pxb_pcie_dev_initfn ( PCIDevice * dev )
{
if ( ! pci_bus_is_express ( dev - > bus ) ) {
error_report ( " pxb-pcie devices cannot reside on a PCI bus! " ) ;
return - EINVAL ;
}
return pxb_dev_init_common ( dev , true ) ;
}
static void pxb_pcie_dev_class_init ( ObjectClass * klass , void * data )
{
DeviceClass * dc = DEVICE_CLASS ( klass ) ;
PCIDeviceClass * k = PCI_DEVICE_CLASS ( klass ) ;
k - > init = pxb_pcie_dev_initfn ;
k - > exit = pxb_dev_exitfn ;
k - > vendor_id = PCI_VENDOR_ID_REDHAT ;
k - > device_id = PCI_DEVICE_ID_REDHAT_PXB_PCIE ;
k - > class_id = PCI_CLASS_BRIDGE_HOST ;
dc - > desc = " PCI Express Expander Bridge " ;
dc - > props = pxb_dev_properties ;
}
static const TypeInfo pxb_pcie_dev_info = {
. name = TYPE_PXB_PCIE_DEVICE ,
. parent = TYPE_PCI_DEVICE ,
. instance_size = sizeof ( PXBDev ) ,
. class_init = pxb_pcie_dev_class_init ,
} ;
static void pxb_register_types ( void )
{
type_register_static ( & pxb_bus_info ) ;
type_register_static ( & pxb_pcie_bus_info ) ;
type_register_static ( & pxb_host_info ) ;
type_register_static ( & pxb_dev_info ) ;
type_register_static ( & pxb_pcie_dev_info ) ;
}
type_init ( pxb_register_types )