/* Handhaben des sio-Interrupts */ /* Datei: sioint4.c */ #include #include #include #include #define COMUSED 1 struct SIO { int base; char intno; char intmask; }; typedef struct SIO sio; enum sioregs{DATA, IER, IIR, LCR, MCR, LSR, MSR, SRC}; enum picregs{IMR=0x21,OCW1=0x21,OCW2=0x20,OCW3=0x20}; typedef void interrupt (*isra)(void); void interrupt shandler(); sio s8250[4] = { { 0x3f8, 4, 0x10 }, { 0x2f8, 3, 0x08 }, { 0x3e8, 4, 0x10 }, { 0x2e8, 3, 0x08 } }; isra oldint; volatile int got_int = 0; volatile int test[4] = { 0,0,0,0 }; int comindex; volatile unsigned int count = 0; void interrupt shandler (void) { register int x; count++; got_int = 1; do { x = inportb (s8250[comindex].base + IIR); if (x & 1) break; switch (x >> 1) { case 0: /* Modem Status */ test[0]++; x=inportb(s8250[comindex].base+MSR); break; case 1: /* Sendeinterrupt */ test[1]++; break; case 2: /* Empfangsdaten */ test[2]++; /* data received */ x=inportb(s8250[comindex].base+DATA); break; case 3: /* Empfangsstatus */ test[3]++; x=inportb(s8250[comindex].base+LSR); if (x & 1) x=inportb(s8250[comindex].base+DATA); break; } } while (1); outportb (OCW2,0x20); /* non specific EOI */ } int sioSetParam(sio *sp,int bd,int bit,int pr,int st) { union { unsigned short int i16; unsigned char b[2]; } takt; unsigned char x; if (bd < 300 || bd > 19200) return -2; if (bit < 5 || bit > 8) return -3; if (st < 1 || st > 2) return -4; if (strchr ("nNmMEeOoSs",pr) == NULL) return -5; x = bit -5; /* bit 0 /bit 1*/ if (st == 2) x = x | 0x4; /* bit 2 */ if (strchr("nN",pr) == NULL) { x = x | 0x08; /* bit 3 */ if (strchr ("eEsS",pr) != NULL) x = x | 0x10; if (strchr ("mMsS",pr) != NULL) x = x | 0x20; } takt.i16 = 115200L / bd; outportb(sp->base +LCR,inportb(sp->base + LCR) |0x80); outportb(sp->base,takt.b[0]); /* LSB */ outportb(sp->base +1,takt.b[1]);/* MSB */ outportb(sp->base +LCR ,x); return takt.i16; } void installint (sio * sp) { /* Interrupt am 8259a abschalten */ char y; y = inportb (IMR); y = y | sp->intmask; outportb (IMR,y); y = 99; outportb (OCW2, 0x0b); y = inportb (OCW2); if (y & sp->intmask) { /* R³cksetzen Interrupt */ outportb (OCW2,0x60 | sp->intno); } oldint = getvect(sp->intno +8); setvect(sp->intno +8, shandler); sioSetParam (sp, 1200, 7,'n',1); outportb(sp->base +MCR,0x0b); /* set dtr, rts out2 */ y= y*5; outportb (sp->base + IER, 5); y = inportb (IMR); y = y &~sp->intmask; outportb (IMR,y); } void restoreint(sio * sp) { /* Interrupt am 8259a abschalten */ char y; y = inportb (IMR); y = y | sp->intmask; outportb (IMR,y); outportb (sp->base +IIR,0); setvect (sp->intno +8, oldint); } int main () { int i; comindex = COMUSED -1; clrscr(); printf ("\nTest der SIO Interrupts \n\n"); installint (& s8250[comindex]); while (!kbhit()) {if (got_int) { got_int = 0; printf ("\r%06d",count); } } printf ("\n\nZõhler ist %d\n",count); restoreint(&s8250[comindex]); for (i = 0; i < 4; i++) printf ("\nTEST: = %d-Werte %d",i,test[i]); printf ("\n\nProgrammende.\n"); return 0; }