Author: blueswirl Date: 2009-01-07 16:45:26 +0100 (Wed, 07 Jan 2009) New Revision: 363
Modified: openbios-devel/arch/ppc/qemu/init.c openbios-devel/arch/sparc64/openbios.c openbios-devel/drivers/pci.c openbios-devel/drivers/pci_database.h openbios-devel/include/openbios/pci.h Log: Create PCI properties "interrupts", "interrupt-map" and "interrupt-map-mask" (Laurent Vivier)
Modified: openbios-devel/arch/ppc/qemu/init.c =================================================================== --- openbios-devel/arch/ppc/qemu/init.c 2009-01-07 15:43:10 UTC (rev 362) +++ openbios-devel/arch/ppc/qemu/init.c 2009-01-07 15:45:26 UTC (rev 363) @@ -68,14 +68,17 @@ [ARCH_PREP] = { "PREP", 0x1057, 0x4801, 0x80800000, 0x800c0000, 0x80000000, 0x00100000, 0xf0000000, 0x10000000, 0x80000000, 0x00010000, 0x00000000, 0x00400000, + { 9, 11, 9, 11 } }, [ARCH_MAC99] = { "MAC99", 0x106b, 0x001F, 0xf2800000, 0xf2c00000, 0xf2000000, 0x02000000, 0x80000000, 0x10000000, 0xf2000000, 0x00800000, 0x00000000, 0x01000000, + { 8, 9, 10, 11 } }, [ARCH_HEATHROW] = { "HEATHROW", 0x1057, 0x0002, 0xfec00000, 0xfee00000, 0x80000000, 0x7f000000, 0x80000000, 0x01000000, 0xfe000000, 0x00800000, 0xfd000000, 0x01000000, + { 21, 22, 23, 24 } }, }; uint32_t isa_io_base;
Modified: openbios-devel/arch/sparc64/openbios.c =================================================================== --- openbios-devel/arch/sparc64/openbios.c 2009-01-07 15:43:10 UTC (rev 362) +++ openbios-devel/arch/sparc64/openbios.c 2009-01-07 15:45:26 UTC (rev 363) @@ -68,6 +68,7 @@ .cfg_data = 0, .cfg_base = 0x80000000ULL, .cfg_len = 0, + .irqs = { 1, 2, 3, 4 }, }, .machine_id_low = 0, .machine_id_high = 255,
Modified: openbios-devel/drivers/pci.c =================================================================== --- openbios-devel/drivers/pci.c 2009-01-07 15:43:10 UTC (rev 362) +++ openbios-devel/drivers/pci.c 2009-01-07 15:45:26 UTC (rev 363) @@ -195,6 +195,52 @@ return 0; }
+static void pci_set_interrupt_map(const pci_config_t *config) +{ + phandle_t parent, dev; + cell props[4]; + cell *old_props, *new_props; + int ncells; + int retlen; + + if (config->irq_line != -1) { + dev = get_cur_dev(); + activate_device(config->path); + activate_device(".."); + parent = get_cur_dev(); + + ncells = 0; + if (get_property(parent, "interrupt-map-mask", NULL) == 0) { + props[ncells++] = 0xF800; + props[ncells++] = 0; + props[ncells++] = 0; + props[ncells++] = 0; + set_property(parent, "interrupt-map-mask", + (char*)props, ncells * sizeof(cell)); + } + + old_props = (cell*)get_property(parent, "interrupt-map", &retlen); + if (old_props) { + new_props = malloc(retlen + 6 * 4); + memcpy(new_props, old_props, retlen); + } else { + retlen = 0; + new_props = malloc(6 * 4); + } + ncells = retlen / 4; + new_props[ncells++] = config->dev & 0xf800; /* devfn */ + new_props[ncells++] = 0; + new_props[ncells++] = 0; + new_props[ncells++] = 0; + new_props[ncells++] = 0; + new_props[ncells++] = config->irq_line; + set_property(parent, "interrupt-map", + (char*)new_props, ncells * sizeof(cell)); + free(new_props); + activate_dev(dev); + } +} + int macio_config_cb (const pci_config_t *config) { #ifdef CONFIG_DRIVER_MACIO @@ -232,8 +278,8 @@ set_int_property(dev, "revision-id", rev); set_int_property(dev, "class-code", class_code << 8);
- set_int_property(dev, "interrupts", - pci_config_read8(addr, PCI_INTERRUPT_LINE)); + if (config->irq_pin) + set_int_property(dev, "interrupts", config->irq_pin);
set_int_property(dev, "min-grant", pci_config_read8(addr, PCI_MIN_GNT)); set_int_property(dev, "max-latency", pci_config_read8(addr, PCI_MAX_LAT)); @@ -275,11 +321,24 @@ if (pci_dev->compat) set_property(dev, "compatible", pci_dev->compat, pci_compat_len(pci_dev)); + + pci_set_interrupt_map(config); + + if (pci_dev->acells) + set_int_property(dev, "#address-cells", pci_dev->acells); + if (pci_dev->scells) + set_int_property(dev, "#size-cells", pci_dev->scells); + if (pci_dev->icells) + set_int_property(dev, "#interrupt-cells", pci_dev->icells); + +#ifdef CONFIG_DEBUG_PCI + printk("\n"); +#endif + if (pci_dev->config_cb) pci_dev->config_cb(config); }
- static void ob_pci_add_reg(pci_addr addr) { PUSH(0); @@ -342,7 +401,18 @@ unsigned long base; pci_addr config_addr; int reg; + uint8_t irq_pin, irq_line;
+ irq_pin = pci_config_read8(addr, PCI_INTERRUPT_PIN); + if (irq_pin) { + config->irq_pin = irq_pin; + irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3; + irq_line = arch->irqs[irq_pin]; + pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line); + config->irq_line = irq_line; + } else + config->irq_line = -1; + omask = 0x00000000; for (reg = 0; reg < 7; reg++) {
Modified: openbios-devel/drivers/pci_database.h =================================================================== --- openbios-devel/drivers/pci_database.h 2009-01-07 15:43:10 UTC (rev 362) +++ openbios-devel/drivers/pci_database.h 2009-01-07 15:45:26 UTC (rev 363) @@ -5,6 +5,8 @@ uint32_t dev; /* bus, dev, fn */ uint32_t regions[7]; uint32_t sizes[7]; + int irq_pin; + int irq_line; };
typedef struct pci_dev_t pci_dev_t;
Modified: openbios-devel/include/openbios/pci.h =================================================================== --- openbios-devel/include/openbios/pci.h 2009-01-07 15:43:10 UTC (rev 362) +++ openbios-devel/include/openbios/pci.h 2009-01-07 15:45:26 UTC (rev 363) @@ -6,19 +6,20 @@ typedef struct pci_arch_t pci_arch_t;
struct pci_arch_t { - const char * name; - uint16_t vendor_id; - uint16_t device_id; - unsigned long cfg_addr; - unsigned long cfg_data; - unsigned long cfg_base; - unsigned long cfg_len; - unsigned long mem_base; - unsigned long mem_len; - unsigned long io_base; - unsigned long io_len; - unsigned long rbase; - unsigned long rlen; + const char * name; + uint16_t vendor_id; + uint16_t device_id; + unsigned long cfg_addr; + unsigned long cfg_data; + unsigned long cfg_base; + unsigned long cfg_len; + unsigned long mem_base; + unsigned long mem_len; + unsigned long io_base; + unsigned long io_len; + unsigned long rbase; + unsigned long rlen; + uint8_t irqs[4]; };
extern const pci_arch_t *arch;