[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] pci_default_config_write() clean up.
From: |
Isaku Yamahata |
Subject: |
[Qemu-devel] pci_default_config_write() clean up. |
Date: |
Thu, 7 May 2009 17:40:19 +0900 |
User-agent: |
Mutt/1.5.6i |
>From 9b87d45e497785cb615eef8a96debea805276392 Mon Sep 17 00:00:00 2001
From: Isaku Yamahata <address@hidden>
Date: Thu, 7 May 2009 16:14:04 +0900
Subject: [PATCH] pci: pci_default_config_write() clean up.
clean up of pci_default_config_write() by table driven code.
Cc: Michael S. Tsirkin <address@hidden>
Signed-off-by: Isaku Yamahata <address@hidden>
---
hw/cirrus_vga.c | 2 +-
hw/pci.c | 403 ++++++++++++++++++++++++++++++++++++++-----------------
hw/pci.h | 98 +++++++++++++-
3 files changed, 377 insertions(+), 126 deletions(-)
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index e4728a4..3c68884 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -180,7 +180,7 @@
#define PCI_COMMAND_PALETTESNOOPING 0x0020
#define PCI_COMMAND_PARITYDETECTION 0x0040
#define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080
-#define PCI_COMMAND_SERR 0x0100
+//#define PCI_COMMAND_SERR 0x0100 /* duplicated */
#define PCI_COMMAND_BACKTOBACKTRANS 0x0200
// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
#define PCI_CLASS_BASE_DISPLAY 0x03
diff --git a/hw/pci.c b/hw/pci.c
index ee7d403..3406e46 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -21,6 +21,9 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
+#include <assert.h>
+
#include "hw.h"
#include "pci.h"
#include "monitor.h"
@@ -236,6 +239,89 @@ int pci_assign_devaddr(const char *addr, int *domp, int
*busp, unsigned *slotp)
return pci_parse_devaddr(devaddr, domp, busp, slotp);
}
+static const struct PCIConfigReg
+pci_default_config_regs_type_00[PCI_CONFIG_SPACE_SIZE] =
+{
+ /* Vendor ID, Device ID: read only */
+ [PCI_COMMAND] = {
+ .wmask =
+ (PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER |
+ PCI_COMMAND_SPECIAL |
+ PCI_COMMAND_INVALIDATE |
+ PCI_COMMAND_VGA_PALETTE |
+ PCI_COMMAND_PARITY |
+ PCI_COMMAND_WAIT),
+ .changed = pci_update_mappings,
+ },
+ [PCI_COMMAND + 1] = {
+ .wmask =
+ (PCI_COMMAND_SERR |
+ PCI_COMMAND_FAST_BACK |
+ PCI_COMMAND_INTX_DISABLE) >> 8,
+ .changed = NULL,
+ },
+ [PCI_STATUS ... (PCI_STATUS + 1)] = {
+ /* nothing is emulated at this moment */
+ .wmask = 0,
+ .changed = NULL,
+ },
+ /* revision id, class code: read only */
+ [PCI_CACHE_LINE_SIZE] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_LATENCY_TIMER] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ /* header type: read only */
+ [PCI_BIST] = {
+ .wmask = 0, /* BIST emulation isn't implemented */
+ .changed = NULL,
+ },
+ [PCI_BASE_ADDRESS_0 ... (PCI_BASE_ADDRESS_5 + 3)] = {
+ .wmask = 0, /* this will be updated by pci_register_io_region() */
+ .changed = pci_update_mappings,
+ },
+ [PCI_CARDBUS_CIS ... (PCI_CARDBUS_CIS + 3)] = {
+ .wmask = 0, /* not card bus */
+ .changed = NULL,
+ },
+ [PCI_ROM_ADDRESS ... (PCI_ROM_ADDRESS + 3)] = {
+ .wmask = 0, /* this will be updated by pci_register_io_region() */
+ .changed = pci_update_mappings,
+ },
+ [PCI_CAPABILITY_LIST] = {
+ .wmask = 0,
+ .changed = NULL,
+ },
+ /* offset 0x35 ... 0x3d are reserved so is read only */
+ [PCI_INTERRUPT_LINE] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_INTERRUPT_PIN] = {
+ .wmask = 0,
+ .changed = NULL,
+ },
+ [PCI_MIN_GNT] = {
+ .wmask = 0,
+ .changed = NULL,
+ },
+ [PCI_MAX_LAT] = {
+ .wmask = 0,
+ .changed = NULL,
+ },
+
+ /* device dependent part */
+ [PCI_CONFIG_HEADER_SIZE ... (PCI_CONFIG_SPACE_SIZE - 1)] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+};
+
/* -1 for devfn means auto assign */
PCIDevice *pci_register_device(PCIBus *bus, const char *name,
int instance_size, int devfn,
@@ -261,6 +347,8 @@ PCIDevice *pci_register_device(PCIBus *bus, const char
*name,
pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state));
pci_set_default_subsystem_id(pci_dev);
+ memcpy(pci_dev->config_regs, pci_default_config_regs_type_00,
+ sizeof(pci_dev->config_regs));
if (!config_read)
config_read = pci_default_read_config;
@@ -322,6 +410,7 @@ void pci_register_io_region(PCIDevice *pci_dev, int
region_num,
{
PCIIORegion *r;
uint32_t addr;
+ uint32_t mask;
if ((unsigned int)region_num >= PCI_NUM_REGIONS)
return;
@@ -337,12 +426,20 @@ void pci_register_io_region(PCIDevice *pci_dev, int
region_num,
r->size = size;
r->type = type;
r->map_func = map_func;
+ mask = ~(size - 1);
if (region_num == PCI_ROM_SLOT) {
addr = 0x30;
+ /* ROM enable bit is writeable */
+ mask |= PCI_ROM_ADDRESS_ENABLE;
} else {
addr = 0x10 + region_num * 4;
}
*(uint32_t *)(pci_dev->config + addr) = cpu_to_le32(type);
+
+ pci_dev->config_regs[addr ].wmask = mask && 0xff;
+ pci_dev->config_regs[addr + 1].wmask = (mask >> 8) && 0xff;
+ pci_dev->config_regs[addr + 2].wmask = (mask >> 16) && 0xff;
+ pci_dev->config_regs[addr + 3].wmask = (mask >> 24) && 0xff;
}
static void pci_update_mappings(PCIDevice *d)
@@ -452,117 +549,33 @@ uint32_t pci_default_read_config(PCIDevice *d,
}
void pci_default_write_config(PCIDevice *d,
- uint32_t address, uint32_t val, int len)
+ uint32_t addr, uint32_t val, int len)
{
- int can_write, i;
- uint32_t end, addr;
-
- if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) ||
- (address >= 0x30 && address < 0x34))) {
- PCIIORegion *r;
- int reg;
-
- if ( address >= 0x30 ) {
- reg = PCI_ROM_SLOT;
- }else{
- reg = (address - 0x10) >> 2;
- }
- r = &d->io_regions[reg];
- if (r->size == 0)
- goto default_config;
- /* compute the stored value */
- if (reg == PCI_ROM_SLOT) {
- /* keep ROM enable bit */
- val &= (~(r->size - 1)) | 1;
- } else {
- val &= ~(r->size - 1);
- val |= r->type;
- }
- *(uint32_t *)(d->config + address) = cpu_to_le32(val);
- pci_update_mappings(d);
- return;
- }
- default_config:
- /* not efficient, but simple */
- addr = address;
- for(i = 0; i < len; i++) {
- /* default read/write accesses */
- switch(d->config[0x0e]) {
- case 0x00:
- case 0x80:
- switch(addr) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x06:
- case 0x07:
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0e:
- case 0x10 ... 0x27: /* base */
- case 0x2c ... 0x2f: /* read-only subsystem ID & vendor ID */
- case 0x30 ... 0x33: /* rom */
- case 0x3d:
- can_write = 0;
- break;
- default:
- can_write = 1;
- break;
- }
- break;
- default:
- case 0x01:
- switch(addr) {
- case 0x00:
- case 0x01:
- case 0x02:
- case 0x03:
- case 0x06:
- case 0x07:
- case 0x08:
- case 0x09:
- case 0x0a:
- case 0x0b:
- case 0x0e:
- case 0x2c ... 0x2f: /* read-only subsystem ID & vendor ID */
- case 0x38 ... 0x3b: /* rom */
- case 0x3d:
- can_write = 0;
- break;
- default:
- can_write = 1;
- break;
- }
- break;
- }
- if (can_write) {
- /* Mask out writes to reserved bits in registers */
- switch (addr) {
- case 0x05:
- val &= ~PCI_COMMAND_RESERVED_MASK_HI;
- break;
- case 0x06:
- val &= ~PCI_STATUS_RESERVED_MASK_LO;
- break;
- case 0x07:
- val &= ~PCI_STATUS_RESERVED_MASK_HI;
- break;
+ int i;
+ pci_config_changed_t callback[4] = {NULL, NULL, NULL, NULL};
+ int changed = 0;
+
+ assert(len == 1 || len == 2 || len == 4);
+ for (i = 0; i < len; val >>= 8, ++i) {
+ uint8_t mask = d->config_regs[addr].wmask;
+ uint8_t old_val = d->config[addr];
+ uint8_t new_val = (old_val & ~mask) | (val & mask);
+
+ d->config[addr] = new_val;
+ if (old_val != new_val && d->config_regs[addr].changed != NULL) {
+ if (changed == 0 ||
+ callback[changed] != d->config_regs[addr].changed) {
+ callback[changed] = d->config_regs[addr].changed;
+ changed++;
}
- d->config[addr] = val;
}
- if (++addr > 0xff)
- break;
- val >>= 8;
- }
- end = address + len;
- if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) {
- /* if the command register is modified, we must modify the mappings */
- pci_update_mappings(d);
+ if (++addr >= PCI_CONFIG_SPACE_SIZE)
+ break;
}
+
+ for (i = 0; i < changed; i++)
+ (callback[i])(d);
}
void pci_data_write(void *opaque, uint32_t addr, uint32_t val, int len)
@@ -829,23 +842,6 @@ typedef struct {
PCIBus *bus;
} PCIBridge;
-static void pci_bridge_write_config(PCIDevice *d,
- uint32_t address, uint32_t val, int len)
-{
- PCIBridge *s = (PCIBridge *)d;
-
- if (address == 0x19 || (address == 0x18 && len > 1)) {
- if (address == 0x19)
- s->bus->bus_num = val & 0xff;
- else
- s->bus->bus_num = (val >> 8) & 0xff;
-#if defined(DEBUG_PCI)
- printf ("pci-bridge: %s: Assigned bus %d\n", d->name, s->bus->bus_num);
-#endif
- }
- pci_default_write_config(d, address, val, len);
-}
-
PCIBus *pci_find_bus(int bus_num)
{
PCIBus *bus = first_bus;
@@ -866,15 +862,174 @@ PCIDevice *pci_find_device(int bus_num, int slot, int
function)
return bus->devices[PCI_DEVFN(slot, function)];
}
+static void pci_conf_secondary_bus_changed(PCIDevice *d)
+{
+ PCIBridge *s = (PCIBridge*) d;
+ s->bus->bus_num = s->dev.config[PCI_SECONDARY_BUS];
+}
+
+static const struct PCIConfigReg
+pci_default_config_regs_type_01[PCI_CONFIG_SPACE_SIZE] =
+{
+ /* Vendor ID, Device ID: read only */
+ [PCI_COMMAND] = {
+ .wmask =
+ (PCI_COMMAND_IO |
+ PCI_COMMAND_MEMORY |
+ PCI_COMMAND_MASTER |
+ PCI_COMMAND_SPECIAL |
+ PCI_COMMAND_INVALIDATE |
+ PCI_COMMAND_VGA_PALETTE |
+ PCI_COMMAND_PARITY |
+ PCI_COMMAND_WAIT),
+ .changed = pci_update_mappings,
+ },
+ [PCI_COMMAND + 1] = {
+ .wmask =
+ (PCI_COMMAND_SERR |
+ PCI_COMMAND_FAST_BACK |
+ PCI_COMMAND_INTX_DISABLE) >> 8,
+ .changed = NULL,
+ },
+ [PCI_STATUS ... (PCI_STATUS + 1)] = {
+ /* nothing is emulated at this moment */
+ .wmask = 0,
+ .changed = NULL,
+ },
+ /* revision id, class code: read only */
+ [PCI_CACHE_LINE_SIZE] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_LATENCY_TIMER] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ /* header type: read only */
+ [PCI_BIST] = {
+ .wmask = 0, /* BIST emulation isn't implemented */
+ .changed = NULL,
+ },
+ [PCI_BASE_ADDRESS_0 ... (PCI_BASE_ADDRESS_1 + 3)] = {
+ .wmask = 0, /* this will be updated by pci_register_io_region() */
+ .changed = pci_update_mappings,
+ },
+ [PCI_PRIMARY_BUS] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_SECONDARY_BUS] = {
+ .wmask = 0xff,
+ .changed = pci_conf_secondary_bus_changed,
+ },
+ [PCI_SUBORDINATE_BUS] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_SEC_LATENCY_TIMER] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_IO_BASE] = {
+ .wmask = PCI_IO_RANGE_MASK & 0xff,
+ .changed = NULL,
+ },
+ [PCI_IO_LIMIT] = {
+ .wmask = PCI_IO_RANGE_MASK & 0xff,
+ .changed = NULL,
+ },
+ [PCI_SEC_STATUS ... (PCI_SEC_STATUS + 1)] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_MEMORY_BASE] = {
+ .wmask = PCI_MEMORY_RANGE_MASK & 0xff,
+ .changed = NULL,
+ },
+ [PCI_MEMORY_BASE + 1] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_MEMORY_LIMIT] = {
+ .wmask = PCI_MEMORY_RANGE_MASK & 0xff,
+ .changed = NULL,
+ },
+ [PCI_MEMORY_LIMIT + 1] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_PREF_MEMORY_BASE] = {
+ .wmask = PCI_PREF_RANGE_MASK & 0xff,
+ .changed = NULL,
+ },
+ [PCI_PREF_MEMORY_BASE + 1] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_PREF_MEMORY_LIMIT] = {
+ .wmask = PCI_PREF_RANGE_MASK & 0xff,
+ .changed = NULL,
+ },
+ [PCI_PREF_MEMORY_LIMIT + 1] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_PREF_BASE_UPPER32 ... (PCI_PREF_BASE_UPPER32 + 3)] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_PREF_LIMIT_UPPER32 ... (PCI_PREF_LIMIT_UPPER32 + 3)] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_IO_BASE_UPPER16] = {
+ .wmask = 0, /* only support 64K io port */
+ .changed = NULL,
+ },
+ [PCI_IO_LIMIT_UPPER16] = {
+ .wmask = 0, /* only support 64K io port */
+ .changed = NULL,
+ },
+ [PCI_CAPABILITY_LIST] = {
+ .wmask = 0,
+ .changed = NULL,
+ },
+ [PCI_ROM_ADDRESS1 ... (PCI_ROM_ADDRESS1 + 3)] = {
+ .wmask = 0, /* this will be updated by pci_register_io_region() */
+ .changed = pci_update_mappings,
+ },
+ /* 0x35 - 0x37 reserved */
+ [PCI_INTERRUPT_LINE] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+ [PCI_INTERRUPT_PIN] = {
+ .wmask = 0,
+ .changed = NULL,
+ },
+ [PCI_BRIDGE_CONTROL] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+
+ /* device dependent part */
+ [PCI_CONFIG_HEADER_SIZE ... (PCI_CONFIG_SPACE_SIZE - 1)] = {
+ .wmask = 0xff,
+ .changed = NULL,
+ },
+};
+
PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, uint16_t did,
pci_map_irq_fn map_irq, const char *name)
{
PCIBridge *s;
s = (PCIBridge *)pci_register_device(bus, name, sizeof(PCIBridge),
- devfn, NULL, pci_bridge_write_config);
+ devfn, NULL, NULL);
pci_config_set_vendor_id(s->dev.config, vid);
pci_config_set_device_id(s->dev.config, did);
+ memcpy(s->dev.config_regs, pci_default_config_regs_type_01,
+ sizeof(s->dev.config_regs));
s->dev.config[0x04] = 0x06; // command = bus master, pci mem
s->dev.config[0x05] = 0x00;
diff --git a/hw/pci.h b/hw/pci.h
index ff858a1..c220a19 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -98,16 +98,52 @@ typedef struct PCIIORegion {
#define PCI_COMMAND 0x04 /* 16 bits */
#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space
*/
#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
+#define PCI_COMMAND_MASTER 0x4 /* Enable bus master */
+#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
+#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
+#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
+#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
+#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
+#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
+#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
+#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
#define PCI_STATUS 0x06 /* 16 bits */
#define PCI_REVISION_ID 0x08 /* 8 bits */
#define PCI_CLASS_DEVICE 0x0a /* Device class */
+#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
+#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
#define PCI_HEADER_TYPE 0x0e /* 8 bits */
#define PCI_HEADER_TYPE_NORMAL 0
#define PCI_HEADER_TYPE_BRIDGE 1
#define PCI_HEADER_TYPE_CARDBUS 2
#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
+#define PCI_BIST 0x0f /* 8 bits */
+#define PCI_BIST_CODE_MASK 0x0f /* Return result */
+#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or
less */
+#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
+#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
+#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
+#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
+#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O
*/
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
+#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
+#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
+#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit
14 used */
+#define PCI_CARDBUS_CIS 0x28
#define PCI_SUBSYSTEM_VENDOR_ID 0x2c /* 16 bits */
#define PCI_SUBSYSTEM_ID 0x2e /* 16 bits */
+#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list
entry */
#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
#define PCI_MIN_GNT 0x3e /* 8 bits */
@@ -117,6 +153,10 @@ typedef struct PCIIORegion {
#define PCI_SUBVENDOR_ID 0x2c /* obsolete, use
PCI_SUBSYSTEM_VENDOR_ID */
#define PCI_SUBDEVICE_ID 0x2e /* obsolete, use PCI_SUBSYSTEM_ID */
+#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1
reserved */
+#define PCI_ROM_ADDRESS_ENABLE 0x01
+#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
+
/* Bits in the PCI Status Register (PCI 2.3 spec) */
#define PCI_STATUS_RESERVED1 0x007
#define PCI_STATUS_INT_STATUS 0x008
@@ -137,9 +177,65 @@ typedef struct PCIIORegion {
#define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
+#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge
*/
+#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary
interface */
+#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
+#define PCI_IO_LIMIT 0x1d
+#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */
+#define PCI_IO_RANGE_TYPE_16 0x00
+#define PCI_IO_RANGE_TYPE_32 0x01
+#define PCI_IO_RANGE_MASK (~0x0fUL)
+#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit
14 used */
+#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
+#define PCI_MEMORY_LIMIT 0x22
+#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
+#define PCI_MEMORY_RANGE_MASK (~0x0fUL)
+#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT 0x26
+#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL
+#define PCI_PREF_RANGE_TYPE_32 0x00
+#define PCI_PREF_RANGE_TYPE_64 0x01
+#define PCI_PREF_RANGE_MASK (~0x0fUL)
+#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory
range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16 0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for
htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL 0x3e
+#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary
interface */
+#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
+#define PCI_BRIDGE_CTL_ISA 0x04 /* Enable ISA mode */
+#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
+#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
+#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on
secondary interface */
+
+/* Bits in the PCI Command Register (PCI 2.3 spec) */
+#define PCI_COMMAND_RESERVED_BRIDGE 0xf880
+
+#define PCI_COMMAND_RESERVED_MASK_HI_BRIDGE (PCI_COMMAND_RESERVED >> 8)
+
+/* Size of the standard PCI config header */
+#define PCI_CONFIG_HEADER_SIZE 0x40
+/* Size of the standard PCI config space */
+#define PCI_CONFIG_SPACE_SIZE 0x100
+
+typedef void (*pci_config_changed_t)(struct PCIDevice *d);
+struct PCIConfigReg {
+ uint8_t wmask;
+ pci_config_changed_t changed;
+};
+
struct PCIDevice {
/* PCI config space */
- uint8_t config[256];
+ uint8_t config[PCI_CONFIG_SPACE_SIZE];
+ struct PCIConfigReg config_regs[PCI_CONFIG_SPACE_SIZE];
/* the following fields are read only */
PCIBus *bus;
--
1.6.0.2
--
yamahata
- [Qemu-devel] pci_default_config_write() clean up.,
Isaku Yamahata <=