/* * QEMU PCI bus manager * * Copyright (c) 2004 Fabrice Bellard * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include "vl.h" //#define DEBUG_PCI #define PCI_VENDOR_ID 0x00 /* 16 bits */ #define PCI_DEVICE_ID 0x02 /* 16 bits */ #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_CLASS_DEVICE 0x0a /* Device class */ #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ #define PCI_MIN_GNT 0x3e /* 8 bits */ #define PCI_MAX_LAT 0x3f /* 8 bits */ /* just used for simpler irq handling. */ #define PCI_DEVICES_MAX 64 #define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32) struct PCIBus { int bus_num; int devfn_min; void (*set_irq)(PCIDevice *pci_dev, int irq_num, int level); uint32_t config_reg; /* XXX: suppress */ openpic_t *openpic; /* XXX: suppress */ PCIDevice *devices[256]; }; target_phys_addr_t pci_mem_base; static int pci_irq_index; static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS]; static PCIBus *first_bus; extern FILE *logfile; static PCIBus *pci_register_bus(void) { PCIBus *bus; bus = qemu_mallocz(sizeof(PCIBus)); first_bus = bus; return bus; } void generic_pci_save(QEMUFile* f, void *opaque) { PCIDevice* s=(PCIDevice*)opaque; qemu_put_buffer(f, s->config, 256); } int generic_pci_load(QEMUFile* f, void *opaque, int version_id) { PCIDevice* s=(PCIDevice*)opaque; if (version_id != 1) return -EINVAL; qemu_get_buffer(f, s->config, 256); return 0; } /* -1 for devfn means auto assign */ PCIDevice *pci_register_device(PCIBus *bus, const char *name, int instance_size, int devfn, PCIConfigReadFunc *config_read, PCIConfigWriteFunc *config_write) { PCIDevice *pci_dev; if (pci_irq_index >= PCI_DEVICES_MAX) return NULL; if (devfn < 0) { for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { if (!bus->devices[devfn]) goto found; } return NULL; found: ; } pci_dev = qemu_mallocz(instance_size); if (!pci_dev) return NULL; pci_dev->bus = bus; pci_dev->devfn = devfn; pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); if (!config_read) config_read = pci_default_read_config; if (!config_write) conf