mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
Create PCI properties "interrupts", "interrupt-map" and "interrupt-map-mask" (Laurent Vivier)
git-svn-id: svn://coreboot.org/openbios/openbios-devel@363 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
@@ -68,14 +68,17 @@ static const pci_arch_t known_arch[] = {
|
|||||||
[ARCH_PREP] = { "PREP", 0x1057, 0x4801, 0x80800000, 0x800c0000,
|
[ARCH_PREP] = { "PREP", 0x1057, 0x4801, 0x80800000, 0x800c0000,
|
||||||
0x80000000, 0x00100000, 0xf0000000, 0x10000000,
|
0x80000000, 0x00100000, 0xf0000000, 0x10000000,
|
||||||
0x80000000, 0x00010000, 0x00000000, 0x00400000,
|
0x80000000, 0x00010000, 0x00000000, 0x00400000,
|
||||||
|
{ 9, 11, 9, 11 }
|
||||||
},
|
},
|
||||||
[ARCH_MAC99] = { "MAC99", 0x106b, 0x001F, 0xf2800000, 0xf2c00000,
|
[ARCH_MAC99] = { "MAC99", 0x106b, 0x001F, 0xf2800000, 0xf2c00000,
|
||||||
0xf2000000, 0x02000000, 0x80000000, 0x10000000,
|
0xf2000000, 0x02000000, 0x80000000, 0x10000000,
|
||||||
0xf2000000, 0x00800000, 0x00000000, 0x01000000,
|
0xf2000000, 0x00800000, 0x00000000, 0x01000000,
|
||||||
|
{ 8, 9, 10, 11 }
|
||||||
},
|
},
|
||||||
[ARCH_HEATHROW] = { "HEATHROW", 0x1057, 0x0002, 0xfec00000, 0xfee00000,
|
[ARCH_HEATHROW] = { "HEATHROW", 0x1057, 0x0002, 0xfec00000, 0xfee00000,
|
||||||
0x80000000, 0x7f000000, 0x80000000, 0x01000000,
|
0x80000000, 0x7f000000, 0x80000000, 0x01000000,
|
||||||
0xfe000000, 0x00800000, 0xfd000000, 0x01000000,
|
0xfe000000, 0x00800000, 0xfd000000, 0x01000000,
|
||||||
|
{ 21, 22, 23, 24 }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
uint32_t isa_io_base;
|
uint32_t isa_io_base;
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ static const struct hwdef hwdefs[] = {
|
|||||||
.cfg_data = 0,
|
.cfg_data = 0,
|
||||||
.cfg_base = 0x80000000ULL,
|
.cfg_base = 0x80000000ULL,
|
||||||
.cfg_len = 0,
|
.cfg_len = 0,
|
||||||
|
.irqs = { 1, 2, 3, 4 },
|
||||||
},
|
},
|
||||||
.machine_id_low = 0,
|
.machine_id_low = 0,
|
||||||
.machine_id_high = 255,
|
.machine_id_high = 255,
|
||||||
|
|||||||
@@ -195,6 +195,52 @@ int eth_config_cb (const pci_config_t *config)
|
|||||||
return 0;
|
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)
|
int macio_config_cb (const pci_config_t *config)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_DRIVER_MACIO
|
#ifdef CONFIG_DRIVER_MACIO
|
||||||
@@ -232,8 +278,8 @@ static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev,
|
|||||||
set_int_property(dev, "revision-id", rev);
|
set_int_property(dev, "revision-id", rev);
|
||||||
set_int_property(dev, "class-code", class_code << 8);
|
set_int_property(dev, "class-code", class_code << 8);
|
||||||
|
|
||||||
set_int_property(dev, "interrupts",
|
if (config->irq_pin)
|
||||||
pci_config_read8(addr, PCI_INTERRUPT_LINE));
|
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, "min-grant", pci_config_read8(addr, PCI_MIN_GNT));
|
||||||
set_int_property(dev, "max-latency", pci_config_read8(addr, PCI_MAX_LAT));
|
set_int_property(dev, "max-latency", pci_config_read8(addr, PCI_MAX_LAT));
|
||||||
@@ -275,11 +321,24 @@ static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev,
|
|||||||
if (pci_dev->compat)
|
if (pci_dev->compat)
|
||||||
set_property(dev, "compatible",
|
set_property(dev, "compatible",
|
||||||
pci_dev->compat, pci_compat_len(pci_dev));
|
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)
|
if (pci_dev->config_cb)
|
||||||
pci_dev->config_cb(config);
|
pci_dev->config_cb(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ob_pci_add_reg(pci_addr addr)
|
static void ob_pci_add_reg(pci_addr addr)
|
||||||
{
|
{
|
||||||
PUSH(0);
|
PUSH(0);
|
||||||
@@ -342,6 +401,17 @@ ob_pci_configure(pci_addr addr, pci_config_t *config, unsigned long *mem_base,
|
|||||||
unsigned long base;
|
unsigned long base;
|
||||||
pci_addr config_addr;
|
pci_addr config_addr;
|
||||||
int reg;
|
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;
|
omask = 0x00000000;
|
||||||
for (reg = 0; reg < 7; reg++) {
|
for (reg = 0; reg < 7; reg++) {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ struct pci_config_t {
|
|||||||
uint32_t dev; /* bus, dev, fn */
|
uint32_t dev; /* bus, dev, fn */
|
||||||
uint32_t regions[7];
|
uint32_t regions[7];
|
||||||
uint32_t sizes[7];
|
uint32_t sizes[7];
|
||||||
|
int irq_pin;
|
||||||
|
int irq_line;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct pci_dev_t pci_dev_t;
|
typedef struct pci_dev_t pci_dev_t;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ struct pci_arch_t {
|
|||||||
unsigned long io_len;
|
unsigned long io_len;
|
||||||
unsigned long rbase;
|
unsigned long rbase;
|
||||||
unsigned long rlen;
|
unsigned long rlen;
|
||||||
|
uint8_t irqs[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const pci_arch_t *arch;
|
extern const pci_arch_t *arch;
|
||||||
|
|||||||
Reference in New Issue
Block a user