Rewrite interrupt handling in coreboot to be more comprehensible and

more flexible. Also some minore device allocator cleanups that sneaked 
in.

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Peter Stuge <peter@stuge.se>



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4452 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Stefan Reinauer
2009-07-21 21:36:41 +00:00
committed by Stefan Reinauer
parent c366cd0650
commit 4d933dd2d6
5 changed files with 192 additions and 109 deletions

View File

@@ -50,6 +50,10 @@
#if CONFIG_CARDBUS_PLUGIN_SUPPORT == 1
#include <device/cardbus.h>
#endif
#define CONFIG_PC80_SYSTEM 1
#if CONFIG_PC80_SYSTEM == 1
#include <pc80/i8259.h>
#endif
u8 pci_moving_config8(struct device *dev, unsigned int reg)
{
@@ -110,10 +114,10 @@ u32 pci_moving_config32(struct device * dev, unsigned int reg)
unsigned pci_find_next_capability(struct device *dev, unsigned cap,
unsigned last)
{
unsigned pos;
unsigned pos = 0;
unsigned status;
unsigned reps = 48;
pos = 0;
status = pci_read_config16(dev, PCI_STATUS);
if (!(status & PCI_STATUS_CAP_LIST)) {
return 0;
@@ -1193,86 +1197,62 @@ unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
return max;
}
#if CONFIG_PC80_SYSTEM == 1
/**
* Tell the EISA int controller this int must be level triggered.
*
* @brief Assign IRQ numbers
*
* THIS IS A KLUDGE -- sorry, this needs to get cleaned up.
*/
void pci_level_irq(unsigned char intNum)
{
unsigned short intBits = inb(0x4d0) | (((unsigned)inb(0x4d1)) << 8);
printk_spew("%s: current ints are 0x%x\n", __func__, intBits);
intBits |= (1 << intNum);
printk_spew("%s: try to set ints 0x%x\n", __func__, intBits);
/* Write new values. */
outb((unsigned char)intBits, 0x4d0);
outb((unsigned char)(intBits >> 8), 0x4d1);
/* This seems like an error but is not. */
if (inb(0x4d0) != (intBits & 0xff)) {
printk_err(
"%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
__func__, intBits & 0xff, inb(0x4d0));
}
if (inb(0x4d1) != ((intBits >> 8) & 0xff)) {
printk_err(
"%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
__func__, (intBits >> 8) & 0xff, inb(0x4d1));
}
}
/**
* This function assigns IRQs for all functions contained within the
* indicated device address. If the device does not exist or does not
* require interrupts then this function has no effect.
* This function assigns IRQs for all functions contained within the indicated
* device address. If the device does not exist or does not require interrupts
* then this function has no effect.
*
* This function should be called for each PCI slot in your system.
*
* pIntAtoD is an array of IRQ #s that are assigned to PINTA through PINTD of
* this slot.
*
* The particular irq #s that are passed in depend on the routing inside
* your southbridge and on your motherboard.
*
* -kevinh@ispiri.com
*
*/
* @param bus
* @param slot
* @param pIntAtoD is an array of IRQ #s that are assigned to PINTA through
* PINTD of this slot. The particular irq #s that are passed in
* depend on the routing inside your southbridge and on your
* motherboard.
*/
void pci_assign_irqs(unsigned bus, unsigned slot,
const unsigned char pIntAtoD[4])
const unsigned char pIntAtoD[4])
{
unsigned functNum;
struct device *pdev;
unsigned char line;
unsigned char irq;
unsigned char readback;
unsigned int funct;
device_t pdev;
u8 line;
u8 irq;
u8 readback;
/* Each slot may contain up to eight functions. */
for (functNum = 0; functNum < 8; functNum++) {
pdev = dev_find_slot(bus, (slot << 3) + functNum);
/* Each slot may contain up to eight functions */
for (funct = 0; funct < 8; funct++) {
pdev = dev_find_slot(bus, (slot << 3) + funct);
if (pdev) {
line = pci_read_config8(pdev, PCI_INTERRUPT_PIN);
if (!pdev)
continue;
/* PCI spec says all other values are reserved. */
if ((line >= 1) && (line <= 4)) {
irq = pIntAtoD[line - 1];
line = pci_read_config8(pdev, PCI_INTERRUPT_PIN);
printk_debug("Assigning IRQ %d to %d:%x.%d\n",
irq, bus, slot, functNum);
// PCI spec says all values except 1..4 are reserved.
if ((line < 1) || (line > 4))
continue;
pci_write_config8(pdev, PCI_INTERRUPT_LINE,
pIntAtoD[line - 1]);
irq = pIntAtoD[line - 1];
readback =
pci_read_config8(pdev, PCI_INTERRUPT_LINE);
printk_debug(" Readback = %d\n", readback);
printk_debug("Assigning IRQ %d to %d:%x.%d\n",
irq, bus, slot, funct);
// Change to level triggered.
pci_level_irq(pIntAtoD[line - 1]);
}
}
pci_write_config8(pdev, PCI_INTERRUPT_LINE,
pIntAtoD[line - 1]);
#ifdef PARANOID_IRQ_ASSIGNMENTS
readback = pci_read_config8(pdev, PCI_INTERRUPT_LINE);
printk_debug(" Readback = %d\n", readback);
#endif
// Change to level triggered
i8259_configure_irq_trigger(pIntAtoD[line - 1], IRQ_LEVEL_TRIGGERED);
}
}
#endif