#include #include #include #include #include struct PIR_header { int8_t ph_signature[4]; u_int16_t ph_version; u_int16_t ph_length; u_int8_t ph_router_bus; u_int8_t ph_router_dev_fn; u_int16_t ph_pci_irqs; u_int16_t ph_router_vendor; u_int16_t ph_router_device; u_int32_t ph_miniport; u_int8_t ph_res[11]; u_int8_t ph_checksum; } __attribute__ ((packed)); struct PIR_intpin { u_int8_t link; u_int16_t irqs; } __attribute__ ((packed)); struct PIR_entry { u_int8_t pe_bus; u_int8_t pe_res1:3; u_int8_t pe_device:5; struct PIR_intpin pe_intpin[4]; u_int8_t pe_slot; u_int8_t pe_res3; } __attribute__ ((packed)); struct PIR_table { struct PIR_header pt_header; struct PIR_entry pt_entry[0]; } __attribute__ ((packed)); #define SEARCHSIZE 0x20000 static char *format_ints(u_int16_t mask); int main(int argc, char *argv[]) { int fd; char *biosbase, *cp; int offset, i; struct PIR_table *pt; struct PIR_header *ph; struct PIR_entry *pe; int nentry; int ck; if ((fd = open("/dev/mem", O_RDONLY)) < 0) err(1, "can't open /dev/mem"); if ((biosbase = mmap(NULL, SEARCHSIZE, PROT_READ, 0, fd, 0xe0000)) == MAP_FAILED) err(1, "can't mmap /dev/mem"); pt = NULL; for (offset = 0; offset < SEARCHSIZE; offset += 16) { if (!strncmp(biosbase + offset, "$PIR", 4)) { pt = (struct PIR_table *)(biosbase + offset); break; } } if (pt == NULL) errx(1, "can't find $PIR in BIOS segment"); ph = &pt->pt_header; ck = 0; for (offset = 0, cp = (char *)pt; offset < ph->ph_length; offset++, cp++) ck += *cp; ck %= 256; if (ck != 0) warnx("WARNING: $PIR table checksum mismatch (%d != 0)", ck); printf("$PIR table at %p version %x.%x\n", pt, ph->ph_version >> 8, ph->ph_version & 0xff); printf("PCI interrupt router at %d:%d.%d vendor 0x%x device 0x%x\n", ph->ph_router_bus, ph->ph_router_dev_fn >> 4, ph->ph_router_dev_fn & 0xf, ph->ph_router_vendor, ph->ph_router_device); printf("PCI-only interrupts %s\n", format_ints(ph->ph_pci_irqs)); nentry = (ph->ph_length - sizeof(struct PIR_header)) / sizeof(struct PIR_entry); printf("entry bus slot device\n"); for (offset = 0, pe = &pt->pt_entry[0]; offset < nentry; offset++, pe++) { for (i = 0; i < 4; i++) { if (i == 0) { printf(" %02d: %02d %02d %02d INTA", offset, pe->pe_bus, pe->pe_slot, pe->pe_device); } else { printf(" INT%c", 'A' + i); } printf(" %02x %s\n", pe->pe_intpin[i].link, format_ints(pe->pe_intpin[i].irqs)); } } } static char * format_ints(u_int16_t mask) { static char buf[40]; sprintf(buf, "[%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s]", mask & (1 << 0) ? "0" : " ", mask & (1 << 1) ? "1" : " ", mask & (1 << 2) ? "2" : " ", mask & (1 << 3) ? "3" : " ", mask & (1 << 4) ? "4" : " ", mask & (1 << 5) ? "5" : " ", mask & (1 << 6) ? "6" : " ", mask & (1 << 7) ? "7" : " ", mask & (1 << 8) ? "8" : " ", mask & (1 << 9) ? "9" : " ", mask & (1 << 10) ? "10" : " ", mask & (1 << 11) ? "11" : " ", mask & (1 << 12) ? "12" : " ", mask & (1 << 13) ? "13" : " ", mask & (1 << 14) ? "14" : " ", mask & (1 << 15) ? "15" : " "); return(buf); }