#include #include /* p.g.a. printf */ #include /* p.g.a. open() */ #include /* p.g.a. open() */ #include /* p.g.a. streng opp. */ #define UTPORT_ADR 0x0f1c /* Port adresser: lamper */ #define INT_NUM 15 /* Avbrudds-vektor nr. */ #define HEAP_LENGDE 0x0400 /* Resident progr. HEAP */ #undef inportb() /* Bruk funksjoner */ #undef outportb() static unsigned tsr_psp; /* Lager for PSP-adresse */ static unsigned tsr_ss,tsr_sp; /* Egen SS- og SP-reg */ static unsigned avbrutt_ss,avbrutt_sp; /* Lager: progr. SS og SP */ static char iret = (char)0xcf; /* Dummy IRET. */ static char krav_om_irq7; /* Krav om IRQ kommet ? */ static char betjener_irq7; /* Blir IRQ betjent ? */ static char kaller_irq; /* Kalles betjeningsrutinen*/ static char far *dos_i_bruk; /* Peker til DOS-flagg */ static char disk_i_bruk; /* BIOS disk flagg */ static char far *avbrutt_dta; /* Lager for forgr. DTA */ static char far *tsr_dta; /* Lager for TSR's DTA */ static unsigned avbrutt_psp; /* Lager for forgr. PSP */ static unsigned lflag; static int int28_kall,int8_kall; /* Variable som brukes i TSR */ static char buf[128] = "Test-tekst for TSR\n"; /* Test tekst i TSR */ static int tsri; static long tsrj; FILE *pfile; /* Lager for gamle avbrudds-vektorer */ static void interrupt (*gammelint28)(void); static void interrupt (*gammelint13)(void); static void interrupt (*gammelint8)(void); static void interrupt (*gammelint24)(void); static void interrupt (*gammelint1b)(void); static void interrupt (*gammelint23)(void); /* Funksjonsprototyper */ /*********************************************************************** * * * servirq7() betjeningsrutine for avbrudd via IRQ7 * * nyint28() avskjærer int 28. DOS venter. * * nyint13() avskjærer int 13. BIOS disk akt. * * nyint8() avskjærer int 8. Klokke avbrudd. * * nyint24() avskjærer int 24. Fatal feil i DOS. * * til_tsr_miljoe() fra forgrunns- til bakgrunns-program * * fra_tsr_miljoe() fra bakrunns- til forgrunns-program * * setsignatur() setter signatur/fjerner resident prog. * * * ***********************************************************************/ void interrupt servirq7(void); void interrupt nyint28(void); void interrupt nyint13(unsigned bp, unsigned di, unsigned si, unsigned ds, unsigned es, unsigned dx, unsigned cx, unsigned bx, unsigned ax, unsigned ip, unsigned cs, unsigned flags); void interrupt nyint24(unsigned bp, unsigned di, unsigned si, unsigned ds, unsigned es, unsigned dx, unsigned cx, unsigned bx, unsigned ax, unsigned ip, unsigned cs, unsigned flags); void interrupt nyint8(void); int near sett_signatur(int signatur); void near til_tsr_miljoe(void); void near fra_tsr_miljoe(void); main() { int i,j; unsigned lengde; /* Program-lengden */ char far *mcbadr; /* Peker på MCB */ int resident; /* Resident flagg */ unsigned long gammel_irq; /* Opprinnelig IRQ-vektor */ outportb(0x20,0x67); /* Selektiv EOI til IRQ7 */ tsr_psp = (unsigned)getpsp(); /* Hent PSP-adressen */ resident = sett_signatur(INT_NUM); /* Sett/fjern signatur */ if(resident) { printf("Programmet var allerede resident. Er fjernet.\n"); printf("Ved ny installering: Kjør programmet igjen\n"); } else { /* mcbadr skal peke på MCB, som ligger 16 byte foran PSP */ mcbadr = ((char far *)((long int)(tsr_psp-1) << 16)); printf("TSR-PSP-adr= 0x%x MCB-adr= 0x%Fp\n",tsr_psp,mcbadr); tsr_ss = _SS; /* Sett TSR stakk-adr. */ tsr_sp = _SP; tsr_dta= getdta(); /* Hent TSR's DTA */ _AH = 0x34; /* Hent adresse til */ geninterrupt(0x21); /* dos_i_bruk flagg */ dos_i_bruk = MK_FP(_ES,_BX); disable(); /* Slå avbrudd av */ j = inportb(0x21); /* Muliggjør avbrudd på IRQ 7 */ outportb(0x21,(j & 0x7f)); /* Hent inn gamle avbrudsvektorer */ gammel_irq = (unsigned long)getvect(INT_NUM); gammelint28 = getvect(0x28); gammelint13 = getvect(0x13); gammelint8 = getvect(0x8); /* Ta vare på de gamle avbrudsvektorene */ setvect(0x78,(void interrupt(*)())gammel_irq); /* Eks. på kasting */ setvect(0x79,gammelint28); setvect(0x7a,gammelint13); setvect(0x7b,gammelint8); /* Sett inn nye avbrudsvektorer */ setvect(INT_NUM,servirq7); setvect(0x28,nyint28); setvect(0x13,nyint13); setvect(0x8,nyint8); enable(); /* Slå på avbrudd */ /* Programmets lengde i MCB offset 3 */ lengde = *(unsigned int far *)(mcbadr+3); lengde = lengde + HEAP_LENGDE; /* Legg til en HEAP */ printf("Lengden i antall paragrafer%u \n",lengde); /* Skriv ut MCB, 16 byte av PSP */ printf("MCB-blokken: \n"); for(j=0; j<=15; j++) printf("%02x ",*(mcbadr+j)); printf("\n\n"); printf("16 byter av PSP-blokken: \n"); for(j=16; j<=31; j++) printf("%02x ",*(mcbadr+j)); printf("\n"); keep(0,lengde); /* Installer som resident */ } } /********************************************************************** Navn:int sett_signatur(int signatur); 8 <= signatur <= 15 En ledig avbrudds-vektor fra 0x60 til 0x67 skal inneholde signaturen som vektorens offset- og programmets PSP som vektorens segmentadresse. Returnerer: 0 dersom ok. 1 dersom signaturen allerede var installert - ved retur er den fjernet. 2 dersom det ikke er plass. Dersom signaturen allerede finnes vil den bli fjernet d.v.s. satt til 0:0, den tilhørende avbrudds-vektoren erstattes med den opprinnelige og det tilhørende lagerområdet frigis. Funksjonen returnerer da 1. **********************************************************************/ int near sett_signatur(int signatur) { int i; int fjernet,signatur_vektor; void interrupt (*gvektor)(); unsigned far *enviradr; fjernet = 0; /* Ikke fjernet som start */ signatur_vektor = 0; for(i=0x60; i<=0x67; i++) /* Søk etter signaturen */ { gvektor = getvect(i); if(gvektor == 0) signatur_vektor = i; /* <>0 indikerer plass */ if(FP_OFF(getvect(i)) == signatur) { /* Signaturen funnet */ _ES = FP_SEG(getvect(i)); /* Frigi program-lagret */ _AH = 0x49; geninterrupt(0x21); /* Adressen til environment-blokken finnes i PSP:002c */ enviradr= (unsigned far *)((long)(FP_SEG(getvect(i)))<<16) + 0x16; _ES = *enviradr; /* Frigi environment blokken */ _AH = 0x49; geninterrupt(0x21); gvektor = NULL; /* Erstatt signaturen med 0:0 */ setvect(i,gvektor); /* Opprinnelig avdrudds-vektorer tilbake på plass. Finnes fra nr. 0x78 */ gvektor = getvect(0x78); setvect(INT_NUM,gvektor); gvektor = getvect(0x79); setvect(0x28,gvektor); gvektor = getvect(0x7a); setvect(0x13,gvektor); gvektor = getvect(0x7b); setvect(0x08,gvektor); fjernet = 1; break; } } i--; if((signatur_vektor>0) && (fjernet==0)) { /* Sett inn ny signatur på siste ledige plass */ gvektor = (void interrupt (*)())MK_FP(tsr_psp,signatur); setvect(i,gvektor); } if((signatur_vektor==0) && (fjernet==0)) fjernet=2; /* Marker ikke plass */ return(fjernet); } /* Betjeningsrutine for IRQ 7 */ void interrupt servirq7() { disable(); if(betjener_irq7) { outportb(0x20,0x20); /* Send EOI til 8259A */ return; } /* Fortsetter dersom ok for DOS eller kalt fra int(0x28) eller int(0x8) */ if( ((!(*dos_i_bruk)) && (!disk_i_bruk)) || kaller_irq) { betjener_irq7 = 1; krav_om_irq7 = 0; avbrutt_ss =_SS; /* Bevar SS og SP */ avbrutt_sp =_SP; _SS = tsr_ss; /* Over til egen stakk */ _SP = tsr_sp; /* Skriv til H-lamper: bit 8=int8_kall, bit 7 = int28_kall bit 3 = kaller_irq, bit 2 = disk_i_bruk, bit 0 = *(dos_i_bruk) */ lflag = 128*int8_kall + 64*int28_kall + 8*kaller_irq + 4*disk_i_bruk + (*dos_i_bruk); outportb(UTPORT_ADR+1,lflag); kaller_irq = 0; /* Slå av Kall-flagg */ til_tsr_miljoe(); /* Over til TRS DTA/PSP */ gammelint1b = getvect(0x1b); /* Fjerner ctrl C */ setvect(0x1b,(void interrupt(*)())&iret); /* Erstatt med IRET */ gammelint23 = getvect(0x23); /* Fjerner ctrl BREAK */ setvect(0x23,(void interrupt(*)())&iret); /* Erstatt med IRET */ gammelint24 = getvect(0x24); setvect(0x24,nyint24); /* Ny kritisk feil rut.*/ enable(); /* Slå på avbrudd */ /**************Selve betjeningsrutinen starter her*********************** Betjeningsrutinen. Teller binært til 10 på lampene og skriver en test-tekst til fil. */ for (tsri=1; tsri<= 10; tsri++) { outportb(UTPORT_ADR,tsri); for(tsrj=1; tsrj<= 800000l; tsrj++); /* Venteløkke */ } pfile = fopen("c:testfil.txt","a+"); fputs(buf,pfile); fclose(pfile); /*************** betjeningsrutinen er ferdig ****************************/ setvect(0x24,gammelint24); /* Tilbake med de gamle */ setvect(0x23,gammelint23); /* avbrudds-vektorene */ setvect(0x1b,gammelint1b); disable(); fra_tsr_miljoe(); /* Tilbake til forgr.prog */ outportb(0x20,0x20); /* Send EOI til 8259A */ _SS=avbrutt_ss; /* Tilbake til prog. stakk */ _SP=avbrutt_sp; } else /* DOS i bruk, vi må vente med betjeningen */ { krav_om_irq7 = 1; /* Sett opp IRQ flagg: int(0x28) */ /* eller int(0x8) overtar */ utportb(0x20,0x20); /* Send EOI til 8259 */ } betjener_irq7 = 0; } /* DOS tomgangsrutine. Kalles 18.2 ganger pr. sek. når DOS venter på kommando */ void interrupt nyint28() { (*gammelint28)(); /* Utfør gammel int(0x28) */ if((!disk_i_bruk) && krav_om_irq7 && (!betjener_irq7)) { disable(); int28_kall = 1; /* Sett int28-flagg */ kaller_irq = 1; /* Viser at servirq kalles */ krav_om_irq7 = 0; /* Slå av betj. krav */ servirq7(); /* Kall betjeningsrutinen */ int28_kall = 0; } } /* ROM-BIOS disk rutine. */ void interrupt nyint13(unsigned bp, unsigned di, unsigned si, unsigned ds, unsigned es, unsigned dx, unsigned cx, unsigned bx, unsigned ax, unsigned ip, unsigned cs, unsigned flags) { disk_i_bruk = 1; /* Sett opp BIOS disk flagg */ (*gammelint13)(); /* Utfør gammel int(0x13) */ ax = _AX; /* All info må returneres */ dx = _DX; cx = _CX; flags = _FLAGS; disk_i_bruk = 0; /* Ta ned flagget */ } /* Klokke-avbrudd. Kalles 18.2 ganger pr. sek. */ void interrupt nyint8() { (*gammelint8)(); if((!(*dos_i_bruk)) && (!disk_i_bruk) && krav_om_irq7 && (!betjener_irq7)) { int8_kall = 1; /* Sett int8-flagg */ kaller_irq = 1; /* Viser at servirq kalles */ krav_om_irq7 = 0; /* Slå av betj. krav */ servirq7(); /* Kall betjeningsrutinen */ int8_kall = 0; } } /* Fatal feil rutine. Kalles f.eks. ved åpen dør på drive. */ void interrupt nyint24(unsigned bp, unsigned di, unsigned si, unsigned ds, unsigned es, unsigned dx, unsigned cx, unsigned bx, unsigned ax, unsigned ip, unsigned cs, unsigned flags) { ax= 0; } /* Skifter over til TSR-miljø d.v.s. til TSR-DTA og TSR-PSP Tar vare på forgrunnsprogrammets DTA og PSP */ void near til_tsr_miljoe() { avbrutt_dta = getdta(); /* Ta vare på gammel DTA */ setdta(tsr_dta); /* Gi DOS info om TSR-DTA */ avbrutt_psp = getpsp(); /* Ta vare på gammel PSP */ _BX = tsr_psp; /* Gi DOS info om TSR-PSP */ _AH = 0x50; geninterrupt(0x21); } /* Skifter over til forgrunnsprogrammets DTA og PSP */ void near fra_tsr_miljoe() { setdta(avbrutt_dta); /* Tilbake til gammel DTA */ _BX = avbrutt_psp; /* Sett inn gammel PSP */ _AH = 0x50; geninterrupt(0x21); }