From patchwork Wed Sep 30 10:18:20 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Isaku Yamahata X-Patchwork-Id: 34569 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id AEB46B7BCA for ; Wed, 30 Sep 2009 22:23:34 +1000 (EST) Received: from localhost ([127.0.0.1]:39704 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MsyDT-0006TD-EY for incoming@patchwork.ozlabs.org; Wed, 30 Sep 2009 08:23:31 -0400 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MswIr-0004tP-2i for qemu-devel@nongnu.org; Wed, 30 Sep 2009 06:20:57 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MswIU-0004cQ-D3 for qemu-devel@nongnu.org; Wed, 30 Sep 2009 06:20:51 -0400 Received: from [199.232.76.173] (port=43917 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MswIQ-0004cL-Q3 for qemu-devel@nongnu.org; Wed, 30 Sep 2009 06:20:30 -0400 Received: from mail.valinux.co.jp ([210.128.90.3]:55874) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MswIP-0005q7-Kx for qemu-devel@nongnu.org; Wed, 30 Sep 2009 06:20:30 -0400 Received: from nm.local.valinux.co.jp (vagw.valinux.co.jp [210.128.90.14]) by mail.valinux.co.jp (Postfix) with ESMTP id D089049C33; Wed, 30 Sep 2009 19:20:17 +0900 (JST) Received: from yamahata by nm.local.valinux.co.jp with local (Exim 4.69) (envelope-from ) id 1MswGd-0003su-8X; Wed, 30 Sep 2009 19:18:39 +0900 From: Isaku Yamahata To: qemu-devel@nongnu.org, anthony@codemonkey.ws Date: Wed, 30 Sep 2009 19:18:20 +0900 Message-Id: <1254305917-14784-45-git-send-email-yamahata@valinux.co.jp> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <1254305917-14784-1-git-send-email-yamahata@valinux.co.jp> References: <1254305917-14784-1-git-send-email-yamahata@valinux.co.jp> X-Virus-Scanned: clamav-milter 0.95.2 at va-mail.local.valinux.co.jp X-Virus-Status: Clean X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 3) Cc: yamahata@valinux.co.jp Subject: [Qemu-devel] [PATCH 44/61] pci: initialize wmask according to pci header type. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org - initialize wmask according to pci header type. So far, header of type 01 was not correctly initialized. - only sets default subsystem id for header type 00. header type 01 doesn't have subsystem id, and uses the register for other purpose. So setting default subsystem id doesn't make sense. Signed-off-by: Isaku Yamahata --- hw/cirrus_vga.c | 2 +- hw/pci.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- hw/pci.h | 64 +++++++++++++++++++- 3 files changed, 241 insertions(+), 7 deletions(-) diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c index 5103763..f4a16d4 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 335ab5f..94fe87f 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -426,11 +426,86 @@ void pci_conf_initl(PCIDevice *d, uint32_t addr, uint32_t wmask) pci_conf_init(d, addr, wmask, 4); } +static void pci_conf_init_type_00_default(PCIDevice *d) +{ + uint32_t addr; + + pci_set_default_subsystem_id(d); + + /* Vendor ID, Device ID: read only */ + pci_conf_initw(d, PCI_VENDOR_ID, 0); + pci_conf_initw(d, PCI_DEVICE_ID, 0); + + pci_conf_initw(d, PCI_COMMAND, + 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 | + PCI_COMMAND_SERR | + PCI_COMMAND_FAST_BACK | + PCI_COMMAND_INTX_DISABLE); + + /* nothing is emulated at this moment */ + pci_conf_initw(d, PCI_STATUS, 0); + + /* revision id, class code: read only */ + pci_conf_initb(d, PCI_REVISION_ID, 0); + pci_conf_initb(d, PCI_CLASS_PROG, 0); + pci_conf_initw(d, PCI_CLASS_DEVICE, 0); + + pci_conf_initb(d, PCI_CACHE_LINE_SIZE, ~0); + pci_conf_initb(d, PCI_LATENCY_TIMER, ~0); + + /* header type: read only */ + pci_conf_initb(d, PCI_HEADER_TYPE, 0); + + /* BIST emulation isn't implemented */ + pci_conf_initb(d, PCI_BIST, 0); + + /* bar:wmask will be updated by pci_register_bar() */ + pci_conf_initl(d, PCI_BASE_ADDRESS_0, 0); + pci_conf_initl(d, PCI_BASE_ADDRESS_1, 0); + pci_conf_initl(d, PCI_BASE_ADDRESS_2, 0); + pci_conf_initl(d, PCI_BASE_ADDRESS_3, 0); + pci_conf_initl(d, PCI_BASE_ADDRESS_4, 0); + pci_conf_initl(d, PCI_BASE_ADDRESS_5, 0); + + /* not card bus*/ + pci_conf_initl(d, PCI_CARDBUS_CIS, 0); + + /* Subsystem ID, Subsystem Vendor ID: read only*/ + pci_conf_initw(d, PCI_SUBSYSTEM_VENDOR_ID, 0); + pci_conf_initw(d, PCI_SUBSYSTEM_ID, 0); + + + /* mask will be updated by pci_register_bar() */ + pci_conf_initl(d, PCI_ROM_ADDRESS, 0); + + pci_conf_initb(d, PCI_CAPABILITY_LIST, 0); + + /* offset 0x35 ... 0x3d are reserved so is read only */ + + pci_conf_initb(d, PCI_INTERRUPT_LINE, ~0); + pci_conf_initb(d, PCI_INTERRUPT_PIN, 0); + pci_conf_initb(d, PCI_MIN_GNT, 0); + pci_conf_initb(d, PCI_MAX_LAT, 0); + + /* device dependent part */ + for (addr = PCI_CONFIG_HEADER_SIZE; addr < PCI_CONFIG_SPACE_SIZE; addr++) + pci_conf_initb(d, addr, ~0); +} + /* -1 for devfn means auto assign */ +typedef void (*pci_conf_init_t)(PCIDevice *d); static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, const char *name, int devfn, PCIConfigReadFunc *config_read, - PCIConfigWriteFunc *config_write) + PCIConfigWriteFunc *config_write, + pci_conf_init_t conf_init) { if (devfn < 0) { for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { @@ -446,9 +521,9 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); memset(pci_dev->irq_state, 0, sizeof(pci_dev->irq_state)); pci_config_init(pci_dev); - pci_set_default_subsystem_id(pci_dev); pci_init_cmask(pci_dev); pci_init_wmask(pci_dev); + conf_init(pci_dev); if (!config_read) config_read = pci_default_read_config; @@ -471,11 +546,15 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name, pci_dev = qemu_mallocz(instance_size); pci_dev = do_pci_register_device(pci_dev, bus, name, devfn, - config_read, config_write); - /* XXX for non-qdevfied device */ + config_read, config_write, + pci_conf_init_type_00_default); + + /* XXX for non-qdevfied device + Once all pci device is qdevfied this function will disapear */ pci_dev->bus = bus; return pci_dev; } + static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr) { return addr + pci_mem_base; @@ -1252,6 +1331,83 @@ PCIDevice *pci_find_device(int bus_num, int slot, int function) return bus->devices[PCI_DEVFN(slot, function)]; } +static void pci_conf_init_type_01_default(PCIDevice *d) +{ + uint32_t addr; + + /* Vendor ID, Device ID: read only */ + pci_conf_initw(d, PCI_VENDOR_ID, 0); + pci_conf_initw(d, PCI_DEVICE_ID, 0); + + pci_conf_initw(d, PCI_COMMAND, + 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 | + PCI_COMMAND_SERR | + PCI_COMMAND_FAST_BACK | + PCI_COMMAND_INTX_DISABLE); + + /* nothing is emulated at this moment */ + pci_conf_initw(d, PCI_STATUS, 0); + + /* revision id, class code: read only */ + pci_conf_initb(d, PCI_REVISION_ID, 0); + pci_conf_initb(d, PCI_CLASS_PROG, 0); + pci_conf_initw(d, PCI_CLASS_DEVICE, 0); + + pci_conf_initb(d, PCI_CACHE_LINE_SIZE, ~0); + pci_conf_initb(d, PCI_LATENCY_TIMER, ~0); + + /* header type: read only */ + pci_conf_initb(d, PCI_HEADER_TYPE, 0); + + /* BIST emulation isn't implemented */ + pci_conf_initb(d, PCI_BIST, 0); + + /* bar:wmask will be updated by pci_register_bar() */ + pci_conf_initl(d, PCI_BASE_ADDRESS_0, 0); + pci_conf_initl(d, PCI_BASE_ADDRESS_1, 0); + + pci_conf_initb(d, PCI_PRIMARY_BUS, ~0); + pci_conf_initb(d, PCI_SECONDARY_BUS, ~0); + pci_conf_initb(d, PCI_SUBORDINATE_BUS, ~0); + pci_conf_initb(d, PCI_SEC_LATENCY_TIMER, ~0); + pci_conf_initb(d, PCI_IO_BASE, PCI_IO_RANGE_MASK & 0xff); + pci_conf_initb(d, PCI_IO_LIMIT, PCI_IO_RANGE_MASK & 0xff); + + /* sec status isn't emulated (yet) */ + pci_conf_initw(d, PCI_SEC_STATUS, 0); + + pci_conf_initw(d, PCI_MEMORY_BASE, PCI_MEMORY_RANGE_MASK & 0xffff); + pci_conf_initw(d, PCI_MEMORY_LIMIT, PCI_MEMORY_RANGE_MASK & 0xffff); + pci_conf_initw(d, PCI_PREF_MEMORY_BASE, PCI_PREF_RANGE_MASK & 0xffff); + pci_conf_initw(d, PCI_PREF_MEMORY_LIMIT, PCI_PREF_RANGE_MASK & 0xffff); + pci_conf_initl(d, PCI_PREF_BASE_UPPER32, ~0); + pci_conf_initl(d, PCI_PREF_LIMIT_UPPER32, ~0); + + /* only support 64K io port */ + pci_conf_initw(d, PCI_IO_BASE_UPPER16, 0); + pci_conf_initw(d, PCI_IO_LIMIT_UPPER16, 0); + + pci_conf_initb(d, PCI_CAPABILITY_LIST, 0); + + /* wmask will be updated by pci_register_bar() */ + pci_conf_initl(d, PCI_ROM_ADDRESS1, 0); + + pci_conf_initb(d, PCI_INTERRUPT_LINE, ~0); + pci_conf_initb(d, PCI_INTERRUPT_PIN, 0); + pci_conf_initw(d, PCI_BRIDGE_CONTROL, ~0); + + /* device dependent part */ + for (addr = PCI_CONFIG_HEADER_SIZE; addr < PCI_CONFIG_SPACE_SIZE; addr++) + pci_conf_initb(d, addr, ~0); +} + int pci_bridge_initfn(PCIDevice *pci_dev) { uint8_t *pci_conf; @@ -1326,6 +1482,21 @@ PCIBus *pci_bridge_init(PCIBus *bus, int devfn, uint16_t vid, map_irq, name, PCI_BRIDGE_DEFAULT); } +static pci_conf_init_t pci_get_config_initfn(uint8_t header_type) +{ + switch (header_type & ~PCI_HEADER_TYPE_MULTI_FUNCTION) { + case PCI_HEADER_TYPE_NORMAL: + return pci_conf_init_type_00_default; + case PCI_HEADER_TYPE_BRIDGE: + return pci_conf_init_type_01_default; + case PCI_HEADER_TYPE_CARDBUS: + default: + abort(); + break; + } + /* NOTREACHED */ +} + static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base) { PCIDevice *pci_dev = (PCIDevice *)qdev; @@ -1336,7 +1507,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base) bus = FROM_QBUS(PCIBus, qdev_get_parent_bus(qdev)); devfn = pci_dev->devfn; pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn, - info->config_read, info->config_write); + info->config_read, info->config_write, + pci_get_config_initfn(info->header_type)); assert(pci_dev); return info->init(pci_dev); } diff --git a/hw/pci.h b/hw/pci.h index e1d8564..15deb03 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -110,6 +110,14 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r) #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_PROG 0x09 /* Reg. Level Programming Interface */ @@ -121,15 +129,30 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r) #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 */ @@ -171,9 +194,45 @@ static inline int pci_bar_is_64bit(const PCIIORegion *r) #define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8) /* Header type 1 (PCI-to-PCI bridges) */ -#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */ #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_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 @@ -460,6 +519,9 @@ typedef struct { PCIConfigReadFunc *config_read; PCIConfigWriteFunc *config_write; + /* pci config header type */ + uint8_t header_type; + /* pcie stuff */ int pcie; } PCIDeviceInfo;