/* functions for the 8259 pic. test */ #include #include "mult.h" /* external variables */ int int0(),int1(),int2(),int3(),int4(),int5(),int6(),int7(); char inted = 0; /* 1 if int occured */ char intnum = 0; /* interrupt number left here after int occurs */ char level = 'y'; /* level or edge triggered */ char addint = 's'; /* address interval */ char single = 'y'; /* single or multiple */ char icw4 = 'y'; /* icw4 needed */ char fulnst = 'n'; /* fully nested mode */ char buffed = 'y'; /* buffered or sp/en mode */ char ms = 'm'; /* master/slave */ char aeoi = 'n'; /* automatic end of interrupt */ unsigned char jtable[128] = 0; /* jump table */ unsigned char *addr = 0; /* 32 byte boundry address */ inttest() { error = inttest; /* setup error for loop */ disab(); /* disable interrupts */ jumploc(); /* setup the jump table */ icw4 = 'y'; /* to send icw4 */ buffed = 'y'; /* to enable buffered mode */ intint(); /* initialize interrupt chip */ intset(); /* setup all interrupts to occur */ intwait(); /* wait for all interrupts and check isr */ } eoi() /* end of int */ { out(TBASE+4,0x20); } intint() /* initialize interrupter */ { int icw1,icw2,ocw1; out(TBASE+7,0x08); /* select group and allow int to occur */ icw1 = (unsigned)(addr) & 0xe0; /* mask off 5 lsbs */ if(icw4 == 'y') /* is icw4 needed */ icw1 |= 1; /* set bit 0 high */ if(single == 'y') /* is this the only pic */ icw1 |= 2; /* set bit 1 high */ if(addint == 's') /* short or long interval */ icw1 |= 4; /* set bit 2 high */ if(level == 'y') /* level triggered */ icw1 |= 8; /* set bit 3 high */ icw1 |= 0x10; /* set bit 4 high for icw1 */ icw2 = (unsigned)(addr) >> 8; /* set up icw2 */ out(TBASE+4,icw1); /* issue first icw */ out(TBASE+5,icw2); /* issue second icw */ if(icw4 == 'y') /* send icw4 if needed */ nicw4(); ocw1 = 0xff; /* mask off all interrupts */ out(TBASE+5,ocw1); /* issue first ocw */ } nicw4() /* output icw4 to pic. */ { int ic4; ic4 = 0; /* clear icw4 */ if(aeoi == 'y') /* if automatic end of int then */ ic4 |= 2; /* set bit 1 high */ if(buffed == 'y') /* if in buffered mode */ { ic4 |= 8; /* set bit 3 high if so (mult/io won't work */ /* if it isn't buffered) */ if(ms == 'm') /* if master set bit 2 high */ ic4 |= 4; } if(fulnst == 'y') /* is it fully nested mode */ ic4 |= 0x10; /* set bit 4 high */ out(TBASE+5,ic4); /* output icw4 to pic */ } jumploc() /* locate the 32 byte boundry in the array jtable */ { int i; int routine[8]; unsigned char *rout; routine[0] = int0; /* load int0 addr in routine[0] */ routine[1] = int1; /* load int1 addr in routine[1] */ routine[2] = int2; /* load int2 addr in routine[2] */ routine[3] = int3; /* load int3 addr in routine[3] */ routine[4] = int4; /* load int4 addr in routine[4] */ routine[5] = int5; /* load int5 addr in routine[5] */ routine[6] = int6; /* load int6 addr in routine[6] */ routine[7] = int7; /* load int7 addr in routine[7] */ addr = (unsigned)(jtable) & 0x3f; /* check for 32 byte bound */ if(addr == 0x20) addr = jtable; else addr = ((unsigned)(jtable) & ~0x1f) + 0x20; /* force it */ for( i = 0 ; i < 8 ; ++i) { rout = addr +(i * 4); *rout = 0xc3; /* jump machine code */ *(rout+1) = routine[i] & 0xff; /* low addr of jump */ *(rout+2) = routine[i] >> 8; /* high addr of jump */ } } intwait() /* loops in wait for int 10000 times */ { int a,i,j; out(TBASE+5,0); /* allow all interrupts to occur */ eoi(); /* send an end of interrupt to clear the pic */ putcnw('\n'); /* for spacing on the first int */ for( j = 0 ; j < 8 ; ++j) { inted = 0; /* reset interrupted flag */ enab(); /* enable interrupts */ for( i=0; i < 10000; ++i) { if(inted == 1) break; } disab(); /* disable interrupts */ if(inted == 0) { puts("test was not interrupted during int #"); putdec(j); putc('\n'); terflg(); } else if((a = girs()) == 0xff) /* get the in service reg */ { puts("their was no int in service during int #"); putdec(j); putc('\n'); terflg(); } else if(a != intnum) { puts("failed the interrupt test the in "); puts("service register had "); putdec(a); puts("\nwhen the int level was "); putdec(intnum); putc('\n'); terflg(); } else { puts("interrupt level #"); putdec(j); puts(" occured\n"); } setmask(); /* calculate the new mask */ eoi(); /* send end of int */ } if(erflg == 0 && verflg == 0) puts("passes interrupt test!\n"); } setmask() /* setup int mask for next lower priority */ { int a; a = in(TBASE+5); /* input int mask */ a = a * 2 + 1; /* multiply by two and add 1 */ out(TBASE+5,a); /* output new mask */ } girs() /* get the isr data */ { int a,b,c,i; out(TBASE+4,0x0b); /* send out ocw3 */ a = in(TBASE+4); /* input isr */ c = 0xff; /* will still be this if no isr */ for(i=0; i<8 ; ++i) { b = (a >> i) & 1; /* b equals one bit in a */ if(b == 1) { c = i; /* c equals the bit # */ break; } } return(c); /* return the int # */ } intset() /* setup all interrupts to occur */ { int i; threint = 'y'; /* set interrupts on thre all groups */ base = TBASE; /* set base to test board */ for(i=1; i<4; ++i) { group = i; /* set group to i */ groupsel(); /* select the group */ setint(); /* set up ace to interrupt on thre */ } out(TBASE+7,08); /* allow interrupts to occur */ out(SBASE+7,0x20); /* select group 0 with printer ports enabled */ out(SBASE+1,0xbf); /* set bit 5 of port 1 low */ out(SBASE,0x1f); /* set the 3 msb of port 0 low */ /* the clock should always be interrupting */ }