Revision b6981cb5 hw/pci.c
b/hw/pci.c | ||
---|---|---|
518 | 518 |
dev->wmask[PCI_CACHE_LINE_SIZE] = 0xff; |
519 | 519 |
dev->wmask[PCI_INTERRUPT_LINE] = 0xff; |
520 | 520 |
pci_set_word(dev->wmask + PCI_COMMAND, |
521 |
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); |
|
521 |
PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | |
|
522 |
PCI_COMMAND_INTX_DISABLE); |
|
522 | 523 |
|
523 | 524 |
memset(dev->wmask + PCI_CONFIG_HEADER_SIZE, 0xff, |
524 | 525 |
config_size - PCI_CONFIG_HEADER_SIZE); |
... | ... | |
938 | 939 |
} |
939 | 940 |
} |
940 | 941 |
|
942 |
static inline int pci_irq_disabled(PCIDevice *d) |
|
943 |
{ |
|
944 |
return pci_get_word(d->config + PCI_COMMAND) & PCI_COMMAND_INTX_DISABLE; |
|
945 |
} |
|
946 |
|
|
947 |
/* Called after interrupt disabled field update in config space, |
|
948 |
* assert/deassert interrupts if necessary. |
|
949 |
* Gets original interrupt disable bit value (before update). */ |
|
950 |
static void pci_update_irq_disabled(PCIDevice *d, int was_irq_disabled) |
|
951 |
{ |
|
952 |
int i, disabled = pci_irq_disabled(d); |
|
953 |
if (disabled == was_irq_disabled) |
|
954 |
return; |
|
955 |
for (i = 0; i < PCI_NUM_PINS; ++i) { |
|
956 |
int state = pci_irq_state(d, i); |
|
957 |
pci_change_irq_level(d, i, disabled ? -state : state); |
|
958 |
} |
|
959 |
} |
|
960 |
|
|
941 | 961 |
uint32_t pci_default_read_config(PCIDevice *d, |
942 | 962 |
uint32_t address, int len) |
943 | 963 |
{ |
... | ... | |
950 | 970 |
|
951 | 971 |
void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l) |
952 | 972 |
{ |
953 |
int i; |
|
973 |
int i, was_irq_disabled = pci_irq_disabled(d);
|
|
954 | 974 |
uint32_t config_size = pci_config_size(d); |
955 | 975 |
|
956 | 976 |
for (i = 0; i < l && addr + i < config_size; val >>= 8, ++i) { |
... | ... | |
962 | 982 |
ranges_overlap(addr, l, PCI_ROM_ADDRESS1, 4) || |
963 | 983 |
range_covers_byte(addr, l, PCI_COMMAND)) |
964 | 984 |
pci_update_mappings(d); |
985 |
|
|
986 |
if (range_covers_byte(addr, l, PCI_COMMAND)) |
|
987 |
pci_update_irq_disabled(d, was_irq_disabled); |
|
965 | 988 |
} |
966 | 989 |
|
967 | 990 |
/***********************************************************/ |
... | ... | |
979 | 1002 |
|
980 | 1003 |
pci_set_irq_state(pci_dev, irq_num, level); |
981 | 1004 |
pci_update_irq_status(pci_dev); |
1005 |
if (pci_irq_disabled(pci_dev)) |
|
1006 |
return; |
|
982 | 1007 |
pci_change_irq_level(pci_dev, irq_num, change); |
983 | 1008 |
} |
984 | 1009 |
|
Also available in: Unified diff