mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-02 23:33:54 -06:00
pci: initialize pci config headers depending it pci header type.
- Only sets default subsystem id for header type 00.(normal header type) because header type 01 doesn't have subsystem id, and uses the register for other purpose. So setting default subsystem id doesn't make sense. - initialize wmask more for header type 01.(bridge header type) Without those wmasks, linux was confused not boot, and lspci was confused not to print out expected IO/memory range. Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
edb000350d
commit
fb23162885
3 changed files with 67 additions and 5 deletions
42
hw/pci.c
42
hw/pci.c
|
@ -445,6 +445,30 @@ static void pci_init_wmask(PCIDevice *dev)
|
|||
dev->wmask[i] = 0xff;
|
||||
}
|
||||
|
||||
static void pci_init_wmask_bridge(PCIDevice *d)
|
||||
{
|
||||
/* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and
|
||||
PCI_SEC_LETENCY_TIMER */
|
||||
memset(d->wmask + PCI_PRIMARY_BUS, 0xff, 4);
|
||||
|
||||
/* base and limit */
|
||||
d->wmask[PCI_IO_BASE] = PCI_IO_RANGE_MASK & 0xff;
|
||||
d->wmask[PCI_IO_LIMIT] = PCI_IO_RANGE_MASK & 0xff;
|
||||
pci_set_word(d->wmask + PCI_MEMORY_BASE,
|
||||
PCI_MEMORY_RANGE_MASK & 0xffff);
|
||||
pci_set_word(d->wmask + PCI_MEMORY_LIMIT,
|
||||
PCI_MEMORY_RANGE_MASK & 0xffff);
|
||||
pci_set_word(d->wmask + PCI_PREF_MEMORY_BASE,
|
||||
PCI_PREF_RANGE_MASK & 0xffff);
|
||||
pci_set_word(d->wmask + PCI_PREF_MEMORY_LIMIT,
|
||||
PCI_PREF_RANGE_MASK & 0xffff);
|
||||
|
||||
/* PCI_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */
|
||||
memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8);
|
||||
|
||||
pci_set_word(d->wmask + PCI_BRIDGE_CONTROL, 0xffff);
|
||||
}
|
||||
|
||||
static void pci_config_alloc(PCIDevice *pci_dev)
|
||||
{
|
||||
int config_size = pci_config_size(pci_dev);
|
||||
|
@ -467,7 +491,8 @@ static void pci_config_free(PCIDevice *pci_dev)
|
|||
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,
|
||||
uint8_t header_type)
|
||||
{
|
||||
if (devfn < 0) {
|
||||
for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
|
||||
|
@ -484,9 +509,16 @@ 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_alloc(pci_dev);
|
||||
pci_set_default_subsystem_id(pci_dev);
|
||||
|
||||
header_type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
|
||||
if (header_type == PCI_HEADER_TYPE_NORMAL) {
|
||||
pci_set_default_subsystem_id(pci_dev);
|
||||
}
|
||||
pci_init_cmask(pci_dev);
|
||||
pci_init_wmask(pci_dev);
|
||||
if (header_type == PCI_HEADER_TYPE_BRIDGE) {
|
||||
pci_init_wmask_bridge(pci_dev);
|
||||
}
|
||||
|
||||
if (!config_read)
|
||||
config_read = pci_default_read_config;
|
||||
|
@ -509,7 +541,8 @@ 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);
|
||||
config_read, config_write,
|
||||
PCI_HEADER_TYPE_NORMAL);
|
||||
return pci_dev;
|
||||
}
|
||||
static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
|
||||
|
@ -1059,7 +1092,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,
|
||||
info->header_type);
|
||||
assert(pci_dev);
|
||||
rc = info->init(pci_dev);
|
||||
if (rc != 0)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue