mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
simple test program for assign IRQs
This commit is contained in:
parent
aa3f0a8485
commit
7f4c4ca875
2 changed files with 207 additions and 2 deletions
|
@ -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
|
||||
|
|
202
util/getpir/assignirq.c
Normal file
202
util/getpir/assignirq.c
Normal file
|
@ -0,0 +1,202 @@
|
|||
/* checkpir.c : This software is released under GPL
|
||||
For Linuxbios use only
|
||||
Aug 26 2001 , Nikolai Vladychevski, <niko@isl.net.mx>
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <pci/pci.h>
|
||||
#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;i<rt->size;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;i<ts;i++) {
|
||||
rcount=fread(&rt.slots[i],1,16,fmem);
|
||||
count=count+rcount;
|
||||
}
|
||||
print=1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
count=count+rcount;
|
||||
}
|
||||
}
|
||||
} while (rcount>0);
|
||||
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);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue