diff --git a/util/getpir/Makefile b/util/getpir/Makefile index 63be3c9386..823fa1f7db 100644 --- a/util/getpir/Makefile +++ b/util/getpir/Makefile @@ -1,5 +1,5 @@ # change to the path of your linuxbios tree -LINUXBIOSROOT=/home/rminnich/src/freebios/ +LINUXBIOSROOT=/home/rminnich/src/bios/freebios/ INCLUDEPATH=$(LINUXBIOSROOT)/src/arch/i386/include/arch INCLUDE2=$(LINUXBIOSROOT)/src/include @@ -12,11 +12,14 @@ getpir: getpir.c checkpir: checkpir.c irq_tables.o gcc -o checkpir -I$(INCLUDEPATH) -I$(INCLUDE2) irq_tables.o checkpir.c +assignirq: assignirq.c irq_tables.o + gcc -g -o assignirq -I$(INCLUDEPATH) -I$(INCLUDE2) assignirq.c -lpci + irq_tables.o: irq_tables.c gcc -c -I$(INCLUDEPATH) -I$(INCLUDE2) -I$(INCLUDE3) irq_tables.c clean: - rm -f irq_table.o getpir checkpir + rm -f irq_table.o getpir checkpir assignirq cleantable: rm -f irq_table.o diff --git a/util/getpir/assignirq.c b/util/getpir/assignirq.c new file mode 100644 index 0000000000..c130fab9af --- /dev/null +++ b/util/getpir/assignirq.c @@ -0,0 +1,202 @@ +/* checkpir.c : This software is released under GPL + For Linuxbios use only + Aug 26 2001 , Nikolai Vladychevski, +*/ + +#include +#include +#include + +#include +#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24)) +#define PIRQ_VERSION 0x0100 +#define IRQ_SLOT_COUNT 128 + +struct irq_info { + u8 bus, devfn; /* Bus, device and function */ + struct { + u8 link; /* IRQ line ID, chipset dependent, 0=not routed */ + u16 bitmap; /* Available IRQs */ + } __attribute__((packed)) irq[4]; + u8 slot; /* Slot number, 0=onboard */ + u8 rfu; +} __attribute__((packed)); + +struct irq_routing_table { + u32 signature; /* PIRQ_SIGNATURE should be here */ + u16 version; /* PIRQ_VERSION */ + u16 size; /* Table size in bytes */ + u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */ + u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */ + u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */ + u32 miniport_data; /* Crap */ + u8 rfu[11]; + u8 checksum; /* Modulo 256 checksum must give zero */ +#ifndef IRQ_SLOT_COUNT +#if (__GNUC__ < 3) + struct irq_info slots[1]; +#else + struct irq_info slots[]; +#endif // __GNUC__ < 3 +#else + struct irq_info slots[IRQ_SLOT_COUNT]; +#endif // ! IRQ_SLOT_COUNT +} __attribute__((packed)); + + + +#define PIRQ_SIGNATURE (('$' << 0) + ('P' << 8) + ('I' << 16) + ('R' << 24)) +#define PIRQ_VERS 0x0100 + + +struct irq_routing_table rt; + +struct pci_access *pacc; +struct pci_dev *dev; + +// work to minimize: irqused and num* used + +unsigned int irqused[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +int numa = 0, numb = 0, numbc = 0, numd = 0; + +int +getint(u16 m){ + int mask = m, i; + unsigned int min = (unsigned int) -1; + unsigned int minindex; + /* find the least-used interrupt compatible with mask */ + printf("getint mask 0x%x\n", mask); + for(minindex = 0, i = 0; i < 16; i++, mask>>=1) { + printf("Check %d\n", i); + if (! (mask & 1)) + continue; + printf("Irqused[%d] is %d\n", i, irqused[i]); + if (irqused[i] < min) { + minindex = i; + min = irqused[i]; + irqused[i]++; + } + printf("end of loop minindex is %d\n", minindex); + } + return minindex; +} +int calc_checksum(struct irq_routing_table *rt) { + long sum=0,i; + u8 *addr,sum2=0; + + addr= (u8 *) rt; + for (i=0;isize;i++) sum2 += addr[i]; + return(sum2); +} + +int +findpir() { + FILE *fmem, *fpir; + size_t rcount=0; + unsigned long b,p,pir=PIRQ_SIGNATURE; + unsigned long count; + int i,valid=1,print=0; + char cksum=0; + unsigned char *ptr; + unsigned short ts; + + printf("Opening memory...\n"); + fmem=fopen("/dev/mem","r"); + do { + rcount=fread(&b,1,4,fmem); + if (rcount>0) { + if (b==pir) { + valid=1; + printf("Found PCI IRQ Routing table signature at %x bytes from top of the memory\nValidating../\n",count); + rt.signature=PIRQ_SIGNATURE; + ptr=(char*) &rt; + ptr=ptr+4; // signature was read, advance 4 bytes + rcount=fread(ptr,1,sizeof(struct irq_routing_table)-4,fmem); + count=count+rcount; + printf("Version is:%d Table size:%d\n",rt.version,rt.size); + if (rt.version!=PIRQ_VERS) {printf("Invalid version\n");valid=0;} + if (rt.size<32) {printf(" Invalid table size\n"); valid=0;} + if (rt.size%16) {printf (" Invalid table size (not a multiple of 16)\n"); valid=0;} + if (valid) + break; +#if 0 + if (valid) { + // read slot entries + ts=(rt.size-32)/16; + printf("Reading %d slot entries...\n",ts); + for (i=0;i0); + if (!calc_checksum(&rt)) printf("Checksum is ok!\n"); + printf("Closing memory\n"); + fclose(fmem); + return valid; +} +main () { + u8 sum,newsum, pin, interrupt, line; + u16 mask; + int numdevices, i; + struct irq_info *slot; + + if (getuid()) { perror("Run me as root, I need access to /dev/mem"); exit(1);} + + if (iopl(3) != 0) { + perror("Can not set io priviliage"); + exit(1); + } + + if (! findpir()) { + printf("can't find the pir\n"); + exit(1); + } + pacc = pci_alloc(); + + pci_init(pacc); + pci_scan_bus(pacc); + + printf("Validating checksum, file: irq_tables.c that was in ./ at compile time...\n"); + printf("(no other tests are done)\n"); + if (!sum) { printf("Checksum for IRQ Routing table is ok. You can use it in LinuxBios now\n"); } + else { + newsum=rt.checksum-sum; + printf("BAD CHECKSUM for IRQ Routing table !!!!\n"); + printf("If you want to make it valid, change the checksum to: %#x\n",newsum); + } + /* now try assigning interrupts */ + numdevices = (rt.size-32)/16; + printf("There are %d devices\n", numdevices); + for(slot = rt.slots, i = 0; i < numdevices; i++, slot++) { + printf("bus 0x%x devfn 0x%x\n", slot->bus, slot->devfn); + dev = pci_get_dev(pacc, slot->bus, slot->devfn>>3, 0); + if (! dev) { + printf("no dev at this place\n"); + } + /* get the interrupt pin */ + pin = pci_read_byte(dev, PCI_INTERRUPT_PIN); + printf("pin is %d\n", pin); + if ((pin < 1) || (pin > 4)) { + printf("invalid pin\n"); + continue; + } + + mask = slot->irq[pin-1].bitmap; + printf("irq mask for this pin is 0x%x\n", mask); + + interrupt = getint(mask); + printf("interrupt is 0x%x\n", interrupt); + line = pci_read_byte(dev, PCI_INTERRUPT_LINE); + printf("would set reg 0x%x to 0x%x, currently is 0x%x\n", + PCI_INTERRUPT_LINE, interrupt, line); + pci_free_dev(dev); + } +}