#include #include #include //In C++, ISRs take (...) arguments #ifdef __cplusplus #define __CPPARGS ... #else #define __CPPARGS #endif //Kills the current interrupt, no matter where it is void sendEOI(void); void interrupt far (*oldisr[16])(__CPPARGS); //global to store old handler pointer void sendEOI(void) { outportb(0xA0, 0x20); outportb(0x20, 0x20); } unsigned char initirq(char IRQnumber,void interrupt (*ISR)(__CPPARGS)) { unsigned char intmask, oldmask; if (IRQnumber <=7) { oldmask = inportb(0x21); oldisr[IRQnumber] = getvect(IRQnumber + 8); setvect(IRQnumber + 8,ISR); intmask = oldmask & (~(1 << IRQnumber)); outportb(0x21,intmask); } else { oldmask = inportb(0xA1); oldisr[IRQnumber] = getvect(IRQnumber + 0x70 - 8); setvect(IRQnumber - 8 + 0x70, ISR); intmask = oldmask & (~(1 << (IRQnumber - 8))); outportb(0xA1, intmask); } return(oldmask); } void restoreirq(char IRQnumber) { unsigned char intmask; if (IRQnumber <=7 ){ intmask = inportb(0x21); intmask |= (1 << IRQnumber); setvect(IRQnumber + 8,oldisr[IRQnumber]); outportb(0x21, intmask); } else { intmask = inportb(0xA1); intmask |= (1 << (IRQnumber - 8)); setvect(IRQnumber - 8 + 0x70, oldisr[IRQnumber]); outportb(0xA1, intmask); } } // sets ISR to IRQnumber service routine // returns the old PIC mask unsigned char initirq(char IRQnumber,void interrupt (*ISR)(__CPPARGS)); // restores IRQnumber service routine void restoreirq(char IRQnumber); int IRQoccurred; unsigned int BASE; int IRQ; void interrupt far newisr(__CPPARGS) { IRQoccurred++; outportb(BASE + 0xF, 0); sendEOI(); } unsigned AskForBaseAddress(unsigned int OldOne) { char msg[7]; int NewOne = 0, Success = 0, Dummy; int AddrInputPosX, AddrInputPosY; puts("\nPlease enter the Base Address for your card (in hex)"); printf("or press ENTER for %X.\n>", OldOne); AddrInputPosX = wherex(); AddrInputPosY = wherey(); do { gotoxy(AddrInputPosX, AddrInputPosY); clreol(); msg[0] = 5; msg[1] = 0; cgets(msg); sscanf(msg + 2, "%x", &NewOne); Success = 1; Dummy = NewOne; if (msg[1] == 0) { gotoxy(AddrInputPosX, AddrInputPosY); printf("%X", OldOne); Success = 1; Dummy = OldOne; } } while(!Success); return (Dummy); } /* end of AskForBaseAddress */ int getIRQnum(int defIRQ) { char line[8]; int IRQ; clrscr(); printf("Please enter the IRQ number or press for %d\n=>", defIRQ); gets(line); if (sscanf(line, "%d", &IRQ) == 0) IRQ = defIRQ; return IRQ; } void doIO () { int done = 0; char stroke; unsigned int portA; //set up Ports A and B for input //set up Port C for output so we can generate interrupts with it. outportb(BASE + 0x3, 0x92); outportb(BASE + 0xE, 0); //enable the card to generate interrupts while (!done) { printf("Press 'q' to quit. Any other key to generate an interrupt\n"); printf("and read the digital bits on Port A\n"); while(!kbhit()); stroke = getch(); if (stroke == 'q' || stroke == 'Q') return; outportb(BASE + 0x2, 0); delay(0); outportb(BASE + 0x2, 0x8); delay(1); //1 millisecond should be more than enough time for the card to //create an interrupt; if (IRQoccurred) { portA = inportb(BASE); printf("Reading from PortA is: %02x Hex\n", portA); IRQoccurred = 0; } else { printf("No interrupt occurred\n"); } } } void main (void) { //init global variables BASE = 0xE000; IRQ = 11; //get the cards base address and current IRQ clrscr(); BASE = AskForBaseAddress(BASE); IRQ = getIRQnum(IRQ); //set up our new IRQ handler, but don't enable the card to //generate them just yet initirq(IRQ, newisr); //do the interrupts doIO(); //disable interrupts on the card outportb(BASE + 0xD, 0); //restore the old IRQ and allow the program to exit restoreirq(IRQ); }