On Wed, Sep 15, 2010 at 02:38:16PM +0900, Isaku Yamahata wrote: > introduce helper function pci_shift_{word, long}() which returns > returns shifted word/long of given position and range. > They will be used later. > > Signed-off-by: Isaku Yamahata <yamah...@valinux.co.jp>
So I think the reason you *think* you need these is because you set the wmask wrong: you make all capability readonly and then write a ton of custom code to tweak it. Instead, Make writeable registers writeable, even if read always returns 0. Then in your handler do if (dev->config[offset] & mask) { handle bit write dev->config[offset] &= ~mask; } no range checks necessary. If you need to do something on register change, just keep the old state in your structure, then dev->exp.a != dev->config[offset] tells you there was a change. BTW if you need to do this to words or longs, not just bytes, maybe pci_set_word/pci_clear_word would be helpful? > --- > hw/pci.h | 19 +++++++++++++++++++ > 1 files changed, 19 insertions(+), 0 deletions(-) > > diff --git a/hw/pci.h b/hw/pci.h > index f4ea97a..630631b 100644 > --- a/hw/pci.h > +++ b/hw/pci.h > @@ -327,6 +327,25 @@ pci_config_set_interrupt_pin(uint8_t *pci_config, > uint8_t val) > pci_set_byte(&pci_config[PCI_INTERRUPT_PIN], val); > } > > +static inline uint32_t > +pci_shift_long(uint32_t addr, uint32_t val, uint32_t pos) > +{ > + if (addr >= pos) { > + assert(addr - pos <= 32 / 8); > + val <<= (addr - pos) * 8; > + } else { > + assert(pos - addr <= 32 / 8); > + val >>= (pos - addr) * 8; > + } > + return val; > +} > + > +static inline uint16_t > +pci_shift_word(uint32_t addr, uint32_t val, uint32_t pos) > +{ > + return pci_shift_long(addr, val, pos); > +} > + > typedef int (*pci_qdev_initfn)(PCIDevice *dev); > typedef struct { > DeviceInfo qdev; > -- > 1.7.1.1