qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: Isaku Yamahata <yamahata@valinux.co.jp>
Cc: mtosatti@redhat.com, qemu-devel@nongnu.org, armbru@redhat.com
Subject: [Qemu-devel] Re: pci_default_config_write() clean up.
Date: Thu, 7 May 2009 12:29:08 +0300	[thread overview]
Message-ID: <20090507092908.GC32039@redhat.com> (raw)
In-Reply-To: <20090507084019.GA25512%yamahata@valinux.co.jp>

In my opinion, the approach of a mask-filling function is cleaner,
maintaining the tables manually at you do will be more fragile.  For
example:

On Thu, May 07, 2009 at 05:40:19PM +0900, Isaku Yamahata wrote:
> +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,
> +    },

This looks wrong: I think the status register is read-only or
clear on write.

> +    [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,

You really should have PCI_MEMORY_RANGE_MASK >> 8 here, right?

> +        .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,
> +    },

Same here .... etc ...

> +    [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,
> +    },

AFAIK the "..." construct is a GNU extension. Would be better to stick with C99?

> +    [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);


This does not pass the info on the write performed.
In turn this means that this callback can't be used to properly emulate
clear on write registers in status.



> +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;

-- 
MST

  parent reply	other threads:[~2009-05-07  9:30 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-07  8:40 [Qemu-devel] pci_default_config_write() clean up Isaku Yamahata
2009-05-07  8:50 ` [Qemu-devel] " Michael S. Tsirkin
2009-05-07  9:06   ` Isaku Yamahata
2009-05-07  9:34     ` Michael S. Tsirkin
2009-05-07  9:29 ` Michael S. Tsirkin [this message]
2009-05-07  9:55   ` Isaku Yamahata
2009-05-07 10:25     ` Michael S. Tsirkin
2009-05-07 11:13       ` Isaku Yamahata
2009-05-07 11:46         ` Michael S. Tsirkin
2009-05-07 11:57           ` Paul Brook
  -- strict thread matches above, loose matches on Subject: below --
2009-05-08  3:43 [Qemu-devel] " Isaku Yamahata
2009-05-08 14:21 ` [Qemu-devel] " Michael S. Tsirkin
2009-05-10  8:38 ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090507092908.GC32039@redhat.com \
    --to=mst@redhat.com \
    --cc=armbru@redhat.com \
    --cc=mtosatti@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=yamahata@valinux.co.jp \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).