All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.