X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Farch%2Fi386%2Fboot%2Fpirq_routing.c;h=bb8a7b605ad1f49d908eaf2c14bbf0d8d827c938;hb=198cb96387c457affa01696405ffaa4531e8e361;hp=6c7f640ca33edbf30de2753b0ebf4a3e049df8c7;hpb=abf9fea4a0c975f56190d061efef9ddeb6b84f81;p=coreboot.git diff --git a/src/arch/i386/boot/pirq_routing.c b/src/arch/i386/boot/pirq_routing.c index 6c7f640ca..bb8a7b605 100644 --- a/src/arch/i386/boot/pirq_routing.c +++ b/src/arch/i386/boot/pirq_routing.c @@ -1,52 +1,43 @@ #include #include #include +#include -#if DEBUG==1 -void check_pirq_routing_table(void) +#if CONFIG_DEBUG_PIRQ +static void check_pirq_routing_table(struct irq_routing_table *rt) { - const uint8_t *addr; - const struct irq_routing_table *rt; + uint8_t *addr = (uint8_t *)rt; + uint8_t sum=0; int i; - uint8_t sum; - printk_info("Checking IRQ routing tables...\n"); + printk(BIOS_INFO, "Checking Interrupt Routing Table consistency...\n"); -#if defined(IRQ_SLOT_COUNT) - if (sizeof(intel_irq_routing_table) != intel_irq_routing_table.size) { - printk_warning("Inconsistent IRQ routing table size (0x%x/0x%x)\n", - sizeof(intel_irq_routing_table), - intel_irq_routing_table.size - ); - intel_irq_routing_table.size=sizeof(intel_irq_routing_table); + if (sizeof(struct irq_routing_table) != rt->size) { + printk(BIOS_WARNING, "Inconsistent Interrupt Routing Table size (0x%x/0x%x).\n", + (unsigned int) sizeof(struct irq_routing_table), + rt->size + ); + rt->size=sizeof(struct irq_routing_table); } -#endif - - rt = &intel_irq_routing_table; - addr = (uint8_t *)rt; - sum = 0; for (i = 0; i < rt->size; i++) sum += addr[i]; - printk_debug("%s:%6d:%s() - irq_routing_table located at: 0x%p\n", - __FILE__, __LINE__, __FUNCTION__, addr); + printk(BIOS_DEBUG, "%s(): Interrupt Routing Table located at %p.\n", + __func__, addr); + - sum = rt->checksum - sum; if (sum != rt->checksum) { - printk_warning("%s:%6d:%s() - " - "checksum is: 0x%02x but should be: 0x%02x\n", - __FILE__, __LINE__, __FUNCTION__, rt->checksum, sum); + printk(BIOS_WARNING, "Interrupt Routing Table checksum is: 0x%02x but should be: 0x%02x.\n", + rt->checksum, sum); rt->checksum = sum; } if (rt->signature != PIRQ_SIGNATURE || rt->version != PIRQ_VERSION || - rt->size % 16 || rt->size < sizeof(struct irq_routing_table)) { - printk_warning("%s:%6d:%s() - " - "Interrupt Routing Table not valid\n", - __FILE__, __LINE__, __FUNCTION__); + rt->size % 16 ) { + printk(BIOS_WARNING, "Interrupt Routing Table not valid.\n"); return; } @@ -54,34 +45,38 @@ void check_pirq_routing_table(void) for (i=0; isize; i++) sum += addr[i]; + /* We're manually fixing the checksum above. This warning can probably + * never happen because if the target location is read-only this + * function would have bailed out earlier. + */ if (sum) { - printk_warning("%s:%6d:%s() - " - "checksum error in irq routing table\n", - __FILE__, __LINE__, __FUNCTION__); + printk(BIOS_WARNING, "Checksum error in Interrupt Routing Table " + "could not be fixed.\n"); } - printk_info("done.\n"); + printk(BIOS_INFO, "done.\n"); } -int verify_copy_pirq_routing_table(unsigned long addr) +static int verify_copy_pirq_routing_table(unsigned long addr) { int i; uint8_t *rt_orig, *rt_curr; rt_curr = (uint8_t*)addr; rt_orig = (uint8_t*)&intel_irq_routing_table; - printk_info("Verifing copy of IRQ routing tables at 0x%x...", addr); + printk(BIOS_INFO, "Verifying copy of Interrupt Routing Table at 0x%08lx... ", addr); for (i = 0; i < intel_irq_routing_table.size; i++) { if (*(rt_curr + i) != *(rt_orig + i)) { - printk_info("failed\n"); + printk(BIOS_INFO, "failed\n"); return -1; } } - printk_info("done\n"); + printk(BIOS_INFO, "done\n"); + + check_pirq_routing_table((struct irq_routing_table *)addr); + return 0; } -#else -#define verify_copy_pirq_routing_table(addr) #endif unsigned long copy_pirq_routing_table(unsigned long addr) @@ -91,9 +86,84 @@ unsigned long copy_pirq_routing_table(unsigned long addr) addr &= ~15; /* This table must be betweeen 0xf0000 & 0x100000 */ - printk_info("Copying IRQ routing tables to 0x%x...", addr); + printk(BIOS_INFO, "Copying Interrupt Routing Table to 0x%08lx... ", addr); memcpy((void *)addr, &intel_irq_routing_table, intel_irq_routing_table.size); - printk_info("done.\n"); + printk(BIOS_INFO, "done.\n"); +#if CONFIG_DEBUG_PIRQ verify_copy_pirq_routing_table(addr); +#endif + pirq_routing_irqs(addr); return addr + intel_irq_routing_table.size; } + +#if CONFIG_PIRQ_ROUTE +void pirq_routing_irqs(unsigned long addr) +{ + int i, j, k, num_entries; + unsigned char irq_slot[4]; + unsigned char pirq[4] = {0, 0, 0, 0}; + struct irq_routing_table *pirq_tbl; + + pirq_tbl = (struct irq_routing_table *)(addr); + num_entries = (pirq_tbl->size - 32) / 16; + + /* Set PCI IRQs. */ + for (i = 0; i < num_entries; i++) { + + printk(BIOS_DEBUG, "PIRQ Entry %d Dev/Fn: %X Slot: %d\n", i, + pirq_tbl->slots[i].devfn >> 3, pirq_tbl->slots[i].slot); + + for (j = 0; j < 4; j++) { + + int link = pirq_tbl->slots[i].irq[j].link; + int bitmap = pirq_tbl->slots[i].irq[j].bitmap; + int irq = 0; + + printk(BIOS_DEBUG, "INT: %c link: %x bitmap: %x ", + 'A' + j, link, bitmap); + + if (!bitmap|| !link || link > 4) { + + printk(BIOS_DEBUG, "not routed\n"); + irq_slot[j] = irq; + continue; + } + + /* yet not routed */ + if (!pirq[link - 1]) { + + for (k = 2; k <= 15; k++) { + + if (!((bitmap >> k) & 1)) + continue; + + irq = k; + + /* yet not routed */ + if (pirq[0] != irq && pirq[1] != irq && pirq[2] != irq && pirq[3] != irq) + break; + } + + if (irq) + pirq[link - 1] = irq; + } + else + irq = pirq[link - 1]; + + printk(BIOS_DEBUG, "IRQ: %d\n", irq); + irq_slot[j] = irq; + } + + /* Bus, device, slots IRQs for {A,B,C,D}. */ + pci_assign_irqs(pirq_tbl->slots[i].bus, + pirq_tbl->slots[i].devfn >> 3, irq_slot); + } + + printk(BIOS_DEBUG, "PIRQ1: %d\n", pirq[0]); + printk(BIOS_DEBUG, "PIRQ2: %d\n", pirq[1]); + printk(BIOS_DEBUG, "PIRQ3: %d\n", pirq[2]); + printk(BIOS_DEBUG, "PIRQ4: %d\n", pirq[3]); + + pirq_assign_irqs(pirq); +} +#endif