[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [qemu-xen-unstable] passthrough: multi-function PCI in ACPI
commit a41a773ac5a8aed20222593711509d43bafaf275 Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Date: Thu Jun 25 18:32:29 2009 +0100 passthrough: multi-function PCI in ACPI This changes the interface beween qemu-xen and the ACPI portion of hvmlader. As such it breaks compatibility with older hvmloaders and a companion patch to hvmloader is needed. There is a subsequent "noise" companion to this change which changes slot to devfn as appropriate. Cc: Dexuan Cui <dexuan.cui@xxxxxxxxx> Cc: Masaki Kanno <kanno.masaki@xxxxxxxxxxxxxx> Signed-off-by: Simon Horman <horms@xxxxxxxxxxxx> [6/8; cross-compatibility issues with xen-unstable.hg] --- hw/piix4acpi.c | 112 +++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 82 insertions(+), 30 deletions(-) diff --git a/hw/piix4acpi.c b/hw/piix4acpi.c index 49c5204..48aebf0 100644 --- a/hw/piix4acpi.c +++ b/hw/piix4acpi.c @@ -56,8 +56,9 @@ /* The bit in GPE0_STS/EN to notify the pci hotplug event */ #define ACPI_PHP_GPE_BIT 3 -typedef struct AcpiDeviceState AcpiDeviceState; -AcpiDeviceState *acpi_device_table; +#define NR_PHP_SLOT_REG (NR_PCI_DEVFN/2) +#define DEVFN_TO_PHP_SLOT_REG(devfn) (devfn >> 1) +#define PHP_SLOT_REG_TO_DEVFN(reg, hilo) ((reg << 1) | hilo) typedef struct PCIAcpiState { PCIDevice dev; @@ -77,17 +78,46 @@ typedef struct GPEState { static GPEState gpe_state; typedef struct PHPSlots { - uint8_t status[NR_PCI_DEV]; /* Apaptor stats */ - uint8_t plug_evt; /* PHP_EVT_ADD or PHP_EVT_REMOVE - * PSTA in ASL */ - uint8_t plug_slot; /* Slot number - * PSTB in ASL */ + uint8_t status[NR_PHP_SLOT_REG]; /* Apaptor n stats | Adaptor n+1 status */ + uint8_t plug_evt; /* PHP_EVT_ADD or PHP_EVT_REMOVE + * PSTA in ASL */ + uint8_t plug_slot; /* Slot number + * PSTB in ASL */ } PHPSlots; static PHPSlots php_slots; int s3_shutdown_flag; static qemu_irq sci_irq; +static void php_reg_set(PHPSlots *hotplug_slots, int devfn, uint8_t val) +{ + uint8_t *reg = &(hotplug_slots->status[DEVFN_TO_PHP_SLOT_REG(devfn)]); + + /* Value may only use a nibble */ + val &= 0xf; + + if (devfn & 0x1) + *reg = (*reg & 0x0f) | (val << 4); + else + *reg = (*reg & 0xf0) | val; +} + + +static uint8_t php_reg_get(PHPSlots *hotplug_slots, int devfn) +{ + uint8_t reg = hotplug_slots->status[DEVFN_TO_PHP_SLOT_REG(devfn)]; + uint8_t val; + + if (devfn & 0x1) + val = (reg & 0xf0) >> 4; + else + val = reg & 0x0f; + + return val; +} + +typedef struct AcpiDeviceState AcpiDeviceState; +AcpiDeviceState *acpi_device_table; static void piix4acpi_save(QEMUFile *f, void *opaque) { PCIAcpiState *s = opaque; @@ -225,8 +255,8 @@ static void acpi_dbg_writel(void *opaque, uint32_t addr, uint32_t val) * ACPI_PHP_IO_ADDR + : * 0 - the hotplug event * 1 - the slot that has a hotplug event - * 2 - 1st php slot ctr/sts reg - * 3 - 2nd php slot ctr/sts reg + * 2 - 1st php slot ctr/sts reg|2nd php slot ctr/sts reg + * 3 - 3rd php slot ctr/sts reg|4th php slot ctr/sts reg * ... */ static uint32_t acpi_php_readb(void *opaque, uint32_t addr) @@ -248,7 +278,7 @@ static uint32_t acpi_php_readb(void *opaque, uint32_t addr) val = hotplug_slots->status[num]; } - fprintf(logfile, "ACPI PCI hotplug: read addr=0x%x, val=0x%x.\n", + fprintf(logfile, "ACPI PCI hotplug: read addr=0x%x, val=0x%02x.\n", addr, val); return val; @@ -257,9 +287,9 @@ static uint32_t acpi_php_readb(void *opaque, uint32_t addr) static void acpi_php_writeb(void *opaque, uint32_t addr, uint32_t val) { PHPSlots *hotplug_slots = opaque; - int slot; + int devfn, num, func, i; - fprintf(logfile, "ACPI PCI hotplug: write addr=0x%x, val=0x%x.\n", + fprintf(logfile, "ACPI PCI hotplug: write addr=0x%x, val=0x%02x.\n", addr, val); switch (addr) @@ -268,17 +298,39 @@ static void acpi_php_writeb(void *opaque, uint32_t addr, uint32_t val) case ACPI_PHP_IO_ADDR + 1: break; default: - slot = addr - ACPI_PHP_IO_ADDR - 2; - if ( val == 0x1 ) { /* Eject command */ - /* make _STA of the slot 0 */ - hotplug_slots->status[slot] = 0; + num = addr - ACPI_PHP_IO_ADDR - 2; + if ( val == 0x01 || val == 0x10 ) { /* Eject command */ + if ( val == 0x01 ) + devfn = PHP_SLOT_REG_TO_DEVFN(num, 0); + else + devfn = PHP_SLOT_REG_TO_DEVFN(num, 1); + + fprintf(logfile, "ACPI PCI hotplug: write devfn=0x%02x.\n", + devfn); + + if (hotplug_slots->plug_evt != PHP_EVT_REMOVE || + hotplug_slots->plug_slot != devfn ) + { + fprintf(logfile, "ACPI PCI hotplug: not expecting " + "devfn 0x%02x to be removed. Expected event 0x%x " + "for devfn 0x%02x\n", devfn, + hotplug_slots->plug_evt, hotplug_slots->plug_slot); + return; + } /* clear the hotplug event */ hotplug_slots->plug_evt = 0; - hotplug_slots->plug_slot = 0; - /* power off the slot */ - power_off_php_devfn(PCI_DEVFN(slot, 0)); + for ( func = NR_PCI_FUNC - 1; func >= 0; func-- ) + { + i = PCI_DEVFN(PCI_SLOT(devfn), func); + + /* make _STA of the slot 0 */ + php_reg_set(hotplug_slots, i, 0); + + /* power off the slot */ + power_off_php_devfn(i); + } /* signal the CP ACPI hot remove done. */ xenstore_record_dm_state("pci-removed"); @@ -290,7 +342,7 @@ static void pcislots_save(QEMUFile* f, void* opaque) { PHPSlots *hotplug_slots = opaque; int i; - for ( i = 0; i < NR_PCI_DEV; i++ ) { + for ( i = 0; i < NR_PHP_SLOT_REG; i++ ) { qemu_put_8s( f, &hotplug_slots->status[i]); } qemu_put_8s(f, &hotplug_slots->plug_evt); @@ -303,7 +355,7 @@ static int pcislots_load(QEMUFile* f, void* opaque, int version_id) int i; if (version_id != 1) return -EINVAL; - for ( i = 0; i < NR_PCI_DEV; i++ ) { + for ( i = 0; i < NR_PHP_SLOT_REG; i++ ) { qemu_get_8s( f, &hotplug_slots->status[i]); } qemu_get_8s(f, &hotplug_slots->plug_evt); @@ -317,15 +369,15 @@ static void php_slots_init(void) memset(&php_slots, 0, sizeof(PHPSlots)); /* update the pci slot status */ - for ( i = 0; i < NR_PCI_DEV; i++ ) { + for ( i = 0; i < NR_PCI_DEVFN; i++ ) { if ( test_pci_devfn(i) ) - php_slots.status[i] = 0xf; + php_reg_set(&php_slots, i, 0xf); } /* ACPI PCI hotplug controller */ - register_ioport_read(ACPI_PHP_IO_ADDR, NR_PCI_DEV + 2, 1, + register_ioport_read(ACPI_PHP_IO_ADDR, NR_PHP_SLOT_REG + 2, 1, acpi_php_readb, &php_slots); - register_ioport_write(ACPI_PHP_IO_ADDR, NR_PCI_DEV + 2, 1, + register_ioport_write(ACPI_PHP_IO_ADDR, NR_PHP_SLOT_REG + 2, 1, acpi_php_writeb, &php_slots); register_savevm("pcislots", 0, 1, pcislots_save, pcislots_load, &php_slots); @@ -489,7 +541,7 @@ void acpi_php_del(int devfn) /* update the php controller status */ php_slots.plug_evt = PHP_EVT_REMOVE; - php_slots.plug_slot = slot; + php_slots.plug_slot = devfn; /* generate a SCI interrupt */ acpi_sci_intr(s); @@ -530,12 +582,12 @@ void acpi_php_add(int devfn) { /* update the php controller status */ php_slots.plug_evt = PHP_EVT_ADD; - php_slots.plug_slot = slot; - - /* update the slot status as present */ - php_slots.status[slot] = 0xf; + php_slots.plug_slot = devfn; } + /* update the slot status as present */ + php_reg_set(&php_slots, devfn, 0xf); + /* power on the function */ power_on_php_devfn(devfn); -- generated by git-patchbot for /home/xen/git/qemu-xen-unstable.git _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |