From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1M1zKG-0002Bv-34 for qemu-devel@nongnu.org; Thu, 07 May 2009 04:51:32 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1M1zKB-00028M-Ne for qemu-devel@nongnu.org; Thu, 07 May 2009 04:51:31 -0400 Received: from [199.232.76.173] (port=38949 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1M1zKA-00027X-4c for qemu-devel@nongnu.org; Thu, 07 May 2009 04:51:26 -0400 Received: from mx2.redhat.com ([66.187.237.31]:57036) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1M1zK9-0008Iv-7h for qemu-devel@nongnu.org; Thu, 07 May 2009 04:51:25 -0400 Date: Thu, 7 May 2009 11:50:10 +0300 From: "Michael S. Tsirkin" Message-ID: <20090507085010.GA32039@redhat.com> References: <20090507084019.GA25512%yamahata@valinux.co.jp> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20090507084019.GA25512%yamahata@valinux.co.jp> Subject: [Qemu-devel] Re: pci_default_config_write() clean up. List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Isaku Yamahata Cc: mtosatti@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com Hmm, this adds more code that it removes. Did you take a look at my attempt at the rewrite of the same function? This had this diffstat: hw/pci.c | 146 ++++++++++++++------------------------------------------------ hw/pci.h | 16 +++++++ 2 files changed, 49 insertions(+), 113 deletions(-) Better, no? On Thu, May 07, 2009 at 05:40:19PM +0900, Isaku Yamahata wrote: > > >From 9b87d45e497785cb615eef8a96debea805276392 Mon Sep 17 00:00:00 2001 > From: Isaku Yamahata > 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 > Signed-off-by: Isaku Yamahata > --- > 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 > + > #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 -- MST