As it was mentioned earlier, there are two main problems when we are trying to handle PCI interruption.
First, all PCI interruptions are shared. It means that we must provide information for driver to determine if it is our interruption or not.
Second, it's very important for level sensitive interrupts to inactivate bus interrupt level just after it's activation (clear interruption or acknowledge interruption, in other words).
Let's assume that we have to write 0x0F0F to some register for interrupt acknowledge. Register is a word displacement 0x320 in the memory area with the physical address 0x3C000:
| IRQ_CLEAR_REC ClearRec; // Clear control structure
|
| IRQ_SHARE_REC ShareRec; // sharing control structure
|
| memset(&ClearRec,0,sizeof(ClearRec)); // clean structures
|
| memset(&ShareRec,0,sizeof(ShareRec));
|
| ClearRec.ClearIrq = 1; // Interrupt acknowledge needed
|
| ClearRec.TypeOfRegister = 1; // Register type - memory-mapped
|
| ClearRec.WideOfRegister = 2; // Register size - 2 bytes (a word)
|
| ClearRec.ReadOrWrite = 1; // acknowledge means write to a register
|
| ClearRec.RegBaseAddress = 0x3C000; // base physical memory address
|
| ClearRec.RegOffset = 0x320; // register first byte displacement in memory
|
| ClearRec.ValueToWrite = 0x0F0F; // A value to write to a register for interrupt acknowledge
|
Also assume we should see 1 in bit 5 of memory mapped register if it is our interruption and the driver must handle it.
| ShareRec.ShareIrq = 1; // Irq can be shared
|
| ShareRec.TypeOfRegister = 0; // memory-mapped register
|
| ShareRec.WideOfRegister = 1; // 1 - Byte
|
| SharRec.RegBaseAddress = PhysAddr; // Memory register base address
|
| ShareRec.RegOffset = 0x40; // Register offset
|
| ShareRec.MaskValue = 0x20; // Bitmap mask to make AND operation
|
| ShareRec.ResultMask = 0x20; // What should be in result if it is our interrupt
|
| // Set an interrupt handler and unmask Irq
|
|