#include #include int COMPort = 0; unsigned long IRQCount[16]; void HandleInterrupt(int IRQNumber) { unsigned char Status = inportb(COMPort + 2) & 0x0F; switch(Status) { case 1: // This happens after we've changed the OUT2 line state break; case 0: // Clear the interrupt state by reading the Modem Status Register inportb(COMPort + 6); break; case 2: // Clear the interrupt state by reading the Interrupt Identification Register // or by writing into the Transmit Holding Register inportb(COMPort + 2); break; case 4: // Clear the interrupt state by reading the received data printf("%c", inportb(COMPort + 0)); break; case 6: // Clear the interrupt state by reading the Line Status Register if(inportb(COMPort + 5) & 0x01) inportb(COMPort + 0); // a byte was available (read it now) break; case 12: // Clear the interrupt state by reading the Receiver Buffer Register inportb(COMPort + 0); break; default: // hmmm, should not have happened (but it did!) ; } // Increase the counter and send an EOI IRQCount[IRQNumber] ++; if(IRQNumber >= 8) outportb(0xA0, 0x20); outportb(0x20, 0x20); } void interrupt Interrupt03(...) { HandleInterrupt(3); } void interrupt Interrupt04(...) { HandleInterrupt(4); } void interrupt Interrupt05(...) { HandleInterrupt(5); } void interrupt Interrupt06(...) { HandleInterrupt(6); } void interrupt Interrupt07(...) { HandleInterrupt(7); } void interrupt Interrupt08(...) { HandleInterrupt(8); } void interrupt Interrupt09(...) { HandleInterrupt(9); } void interrupt Interrupt10(...) { HandleInterrupt(10); } void interrupt Interrupt11(...) { HandleInterrupt(11); } void interrupt Interrupt12(...) { HandleInterrupt(12); } void interrupt Interrupt13(...) { HandleInterrupt(13); } void interrupt Interrupt14(...) { HandleInterrupt(14); } void interrupt Interrupt15(...) { HandleInterrupt(15); } void Init(int far *COMPorts) { for(int COMPortNumber = 0; COMPortNumber < 4; COMPortNumber ++) { // Stop if the last UART has been initialised COMPort = COMPorts[COMPortNumber]; if(!COMPort) continue; outportb(COMPort + 3, inportb(COMPort + 3) & 0x7F); inportb(COMPort + 2); while(inportb(COMPort + 5) & 1) inportb(COMPort); inportb(COMPort + 6); outportb(COMPort + 1, 0x0F - 2); // we don't care about TR being empty outportb(COMPort + 2, 0x01); inportb(COMPort + 2); // Handle some waiting IRQ's char OldMask1 = inportb(0x21); char OldMask2 = inportb(0xA1); outportb(0x21, 0); outportb(0xA1, 0); outportb(COMPort + 4, 0x00); outportb(0x21, OldMask1); outportb(0xA1, OldMask2); } } void main(void) { int i, COMPort; int far *COMPorts = (int far *) MK_FP(0x0000, 0x0400); // Print some info printf("UART IRQ Detector 1.0 (made by Peter Lemmens)\n\n"); // Save the interrupt vectors void interrupt (*OudeInterrupt03)(...) = getvect(0x0B); void interrupt (*OudeInterrupt04)(...) = getvect(0x0C); void interrupt (*OudeInterrupt05)(...) = getvect(0x0D); void interrupt (*OudeInterrupt06)(...) = getvect(0x0E); void interrupt (*OudeInterrupt07)(...) = getvect(0x0F); void interrupt (*OudeInterrupt08)(...) = getvect(0x70); void interrupt (*OudeInterrupt09)(...) = getvect(0x71); void interrupt (*OudeInterrupt10)(...) = getvect(0x72); void interrupt (*OudeInterrupt11)(...) = getvect(0x73); void interrupt (*OudeInterrupt12)(...) = getvect(0x74); void interrupt (*OudeInterrupt13)(...) = getvect(0x75); void interrupt (*OudeInterrupt14)(...) = getvect(0x76); void interrupt (*OudeInterrupt15)(...) = getvect(0x77); // Get control over the interrupt vectors setvect(0x0B, Interrupt03); setvect(0x0C, Interrupt04); setvect(0x0D, Interrupt05); setvect(0x0E, Interrupt08); setvect(0x0F, Interrupt07); setvect(0x70, Interrupt08); setvect(0x71, Interrupt09); setvect(0x72, Interrupt10); setvect(0x73, Interrupt11); setvect(0x74, Interrupt12); setvect(0x75, Interrupt13); setvect(0x76, Interrupt14); setvect(0x77, Interrupt15); // Initialise and check the IRQ's Init(COMPorts); for(int COMPortNumber = 0; COMPortNumber < 4; COMPortNumber ++) { // Stop if the last UART has been checked COMPort = COMPorts[COMPortNumber]; if(!COMPort) continue; // Save the IRQ mask unsigned char OldMask1 = inportb(0x21); unsigned char OldMask2 = inportb(0xA1); // Reset the IRQ counters for(i = 0; i < 16; i ++) IRQCount[i] = 0; // Set the correct IRQ mask (all IRQ's may occur) outportb(0x21, 0x00); outportb(0xA1, 0x00); // Trigger the IRQ outportb(COMPort + 4, inportb(COMPort + 4) ^ 8); outportb(COMPort + 4, inportb(COMPort + 4) ^ 8); // Print the IRQ numbers that occured int IRQValidated = 0; printf(" COM%d (0x%03X): ", COMPortNumber + 1, COMPort); for(i = 0; i < 16; i ++) if(IRQCount[i]) { // This happens if another device has triggered an IRQ if(IRQValidated) printf(" or "); IRQValidated ++; // Print it printf("IRQ %d", i); } if(!IRQValidated) printf("Unknown IRQ"); printf("\n"); // Restore the IRQ mask outportb(0x21, OldMask1); outportb(0xA1, OldMask2); } printf("\n"); // Restore the interrupt vectors setvect(0x77, OudeInterrupt15); setvect(0x76, OudeInterrupt14); setvect(0x75, OudeInterrupt13); setvect(0x74, OudeInterrupt12); setvect(0x73, OudeInterrupt11); setvect(0x72, OudeInterrupt10); setvect(0x71, OudeInterrupt09); setvect(0x70, OudeInterrupt08); setvect(0x0F, OudeInterrupt07); setvect(0x0E, OudeInterrupt06); setvect(0x0D, OudeInterrupt05); setvect(0x0C, OudeInterrupt04); setvect(0x0B, OudeInterrupt03); }