
/*
 * mask of available IRQs for the PCI bus
 * Here you can see how to select specific IRQ channels
 * for IRQ_BITMAP_LINK[0..3]
 *
 * 0x???? = 1100 1110 1011 1000
 *                            ^_ IRQ0 (used by timer)
 *                           ^__ IRQ1 (used by keyboard)
 *                         ^____ IRQ3 (used by legacy UART0)
 *                       ^______ IRQ4 (used by legacy UART0)
 *                      ^_______ IRQ5
 *                    ^_________ IRQ7 (used by legacy LPT)
 *                 ^____________ IRQ9
 *                ^_____________ IRQ10
 *               ^______________ IRQ11
 *             ^________________ IRQ12 (used by PS/2 mouse)
 *             ^________________ IRQ13 (used by copro)
 *           ^__________________ IRQ14
 *          ^___________________ IRQ15
 */

/*
 * Define one interrupt channel per INT?# line
 * Do NOT share them for the test!.
 */
#define IRQ_BITMAP_LINK0 0x0800		/* chipset's INTA# input should be routed to IRQ11 */
#define IRQ_BITMAP_LINK1 0x0000		/* chipset's INTB# input should be routed to nothing (disabled) */
#define IRQ_BITMAP_LINK2 0x8000		/* chipset's INTC# input should be routed to IRQ15 */
#define IRQ_BITMAP_LINK3 0x0000		/* chipset's INTD# input should be routed to nothing (disabled) */

/*
 * define here the mask what interrupts are
 * exclusive to the PCI bus. I'm not sure
 * if this value will be used.
 */
#define EXCLUSIVE_PCI_IRQS 0x8800

/*
 * define here the device count on your
 * PCI bus
 */
#define SLOT_DEVICE_COUNT 2

/*
 * This is from the Linux kernel. But modified to be
 * able to define the slots
 */
struct my_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 */
	struct irq_info slots[SLOT_DEVICE_COUNT];
} __attribute__((packed));

/*
 * Here starts the faked table
 */
static const struct my_irq_routing_table intel_irq_routing_table = {
	.signature = PIRQ_SIGNATURE,
	.version = PIRQ_VERSION,
	.size = 32+16*SLOT_DEVICE_COUNT,
	.rtr_bus = 0x00,		/* Where the interrupt router lies (bus) */
	.rtr_devfn = (0x12<<3)|0x0,	/* Where the interrupt router lies (dev) */
	.exclusive_irqs = EXCLUSIVE_PCI_IRQS,
	.rtr_vendor = 0x1078,		/* TODO add your IRQ router device Vendor ID here */
	.rtr_device = 0x0100,		/* TODO add your IRQ router Device ID here */
	.miniport_data = 0,		/* Crap (miniport) */
	.checksum = 0x00,		/* keep it at 0, to calculate the right one */
/*
 * One definition for a slot or device
 */
	.slots = {
		[0] = {
			.slot = 0x0,	/* should be 0 when it is no real slot. My device is soldered */
			.bus = 0x00,
			.devfn = (0x13<<3)|0x0,	/* 0x13 is my USB OHCI */
			.irq = {
				[0] = {	/* <-- 0 means this is INTA# output from the device or slot */
					.link = 0x01,			/* 0x01 means its connected to INTA# input at chipset */
					.bitmap = IRQ_BITMAP_LINK0
				},
				[1] = {	/* <-- 1 means this is INTB# output from the device or slot */
					.link = 0x02,			/* 0x02 means its connected to INTB# input at chipset */
					.bitmap = IRQ_BITMAP_LINK1
				},
				[2] = {	/* <-- 2 means this is INTC# output from the device or slot */
					.link = 0x03,			/* 0x03 means its connected to INTC# input at chipset */
					.bitmap = IRQ_BITMAP_LINK2
				},
				[3] = {	/* <-- 3 means this is INTD# output from the device or slot */
					.link = 0x04,			/* 0x04 means its connected to INTD# input at chipset */
					.bitmap = IRQ_BITMAP_LINK3
				}
			}
		},
/*
 * Next definition for a slot or device
 */
		[1] = {
			.slot = 0x0,	/* means also "on board" */
			.bus = 0x00,
			.devfn = (0x0f<<3)|0x0,	/* 0x0f is my Realtek Network device */
			.irq = {
				[0] = {	/* <-- 0 means this is INTA# output from the device or slot */
					.link = 0x03,			/* 0x03 means its connected to INTC# input at chipset */
					.bitmap = IRQ_BITMAP_LINK2
				},
				[1] = {	/* <-- 1 means this is INTB# output from the device or slot */
					.link = 0x04,			/* 0x04 means its connected to INTD# input at chipset */
					.bitmap = IRQ_BITMAP_LINK3
				},
				[2] = {	/* <-- 2 means this is INTC# output from the device or slot */
					.link = 0x01,			/* 0x01 means its connected to INTA# input at chipset */
					.bitmap = IRQ_BITMAP_LINK0
				},
				[3] = {	/* <-- 3 means this is INTD# output from the device or slot */
					.link = 0x02,			/* 0x02 means its connected to INTB# input at chipset */
					.bitmap = IRQ_BITMAP_LINK1
				}
			}
		}
	}
/* TODO: Add more entries if your SLOT_DEVICE_COUNT > 2 */
};


/* the following functions replacing the original functions in irq.c */

/*
 *  Check passed address for the PCI IRQ Routing Table signature
 *  and perform checksum verification.
 */

static inline struct irq_routing_table * pirq_check_routing_table(u8 *addr)
{
	struct irq_routing_table *rt;
	int i;
	u8 sum;

	rt = (struct irq_routing_table *) addr;
	if (rt->signature != PIRQ_SIGNATURE ||
	    rt->version != PIRQ_VERSION ||
	    rt->size % 16 ||
	    rt->size < sizeof(struct irq_routing_table))
		return NULL;
	sum = 0;
	for (i=0; i < rt->size; i++)
		sum += addr[i];
	if (!sum) {
		DBG(KERN_DEBUG "PCI: Interrupt Routing Table found at 0x%p\n", rt);
		return rt;
	}
	printk(KERN_WARNING"PCI: PIRQ checksum should be 0x%02x!\n",0x100-sum);	/* this will output the right checksum */
	return NULL;
}

/*
 * give our faked local routing table
 */
static struct irq_routing_table * __init pirq_find_routing_table(void)
{
	printk(KERN_WARNING "PCI: PIRQ table is a fake only!\n");
	pirq_check_routing_table((u8*)&intel_irq_routing_table);
	return (struct irq_routing_table*)&intel_irq_routing_table;
}

