--- src/base/async/int.c Sun Dec 1 21:33:25 2002 +++ src/base/async/int.c Mon Dec 2 11:35:10 2002 @@ -1248,7 +1248,6 @@ case 0x4C: /* program exit */ if(pic_icount) { pic_resched(); - pic_icount=0; } return 0; --- src/base/dev/pic/pic.c Mon Sep 16 18:55:56 2002 +++ src/base/dev/pic/pic.c Mon Sep 16 20:03:37 2002 @@ -179,17 +179,8 @@ static unsigned long pic_wirr; /* watchdog timer for pic_pirr */ static unsigned long pic_wcount = 0; /* watchdog for pic_icount */ unsigned long pic_icount_od = 1; /* overdrive for pic_icount_od */ -#if 0 -unsigned long pic0_imr = 0xf800; /* IRQs 3-7 on pic0 start out disabled */ -unsigned long pic1_imr = 0x07f8; /* IRQs 8-15 on pic1 start out disabled */ -unsigned long pic_imr = 0xfff8; /* interrupt mask register, enable irqs 0,1 */ -unsigned long pice_imr = -1; /* interrupt mask register, dos emulator */ -unsigned long pic_stack[32]; /* stack of interrupt levels */ -unsigned long pic_sp = 0; /* pointer to stack */ -unsigned long pic_vm86_count=0; /* counter for trips around vm86 loop */ -unsigned long pic_dpmi_count=0; /* counter for trips around dpmi loop */ - hitimer_t pic_sys_time=NEVER; /* system time for scheduling interrupts */ -#endif +unsigned long pic_irqs_active = 0; + static hitimer_t pic_ltime[33] = /* timeof last pic request honored */ {NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, NEVER, @@ -408,13 +399,12 @@ int ilevel; /* level to reset on outb 0x20 */ port -= 0x20; -ilevel=pic_ilevel; -if(pic_sp) { - if(ilevel!=pic_stack[pic_sp-1]) { - pic_print(2,"ilevel=",ilevel," differed from pic_stack"); - } - ilevel=pic_stack[pic_sp-1]; -} +ilevel = 32; +if (pic_isr) + ilevel=find_bit(pic_isr); +if(ilevel != pic_ilevel) + error("PIC0: ilevel=%x != pic_ilevel=%x, pic_isr=%lx\n", + ilevel, pic_ilevel, pic_isr); if(!port){ /* icw1, ocw2, ocw3 */ if(value&0x10){ /* icw1 */ @@ -430,15 +420,9 @@ pic0_cmd=3; } else if((value&0xb8) == 0x20) { /* ocw2 */ - if(!pic_sp) { - pic_print(2,"EOI with nothing on pic_stack! ilevel=",ilevel,""); - } else if(pic_stack[pic_sp-1]!=ilevel) { - pic_print(2,"Stack value differed from ilevel! stack=",pic_stack[pic_sp-1],""); - } /* irqs on pic1 require an outb20 to each pic. we settle for any 2 */ if(!clear_bit(ilevel,&pic1_isr)) { clear_bit(ilevel,&pic_isr); /* the famous outb20 */ - pic_ilevel=pic_pop(); /* only pop stack when pic_isr gets cleared */ pic_print(1,"EOI resetting bit ",ilevel, " on pic0"); } else @@ -468,13 +452,12 @@ int ilevel; /* level to reset on outb 0x20 */ port -= 0xa0; -ilevel=pic_ilevel; -if(pic_sp) { - if(ilevel!=pic_stack[pic_sp-1]) { - pic_print(2,"ilevel=",ilevel," differed from pic_stack"); - } - ilevel=pic_stack[pic_sp-1]; -} +ilevel = 32; +if (pic_isr) + ilevel=find_bit(pic_isr); +if(ilevel != pic_ilevel) + error("PIC1: ilevel=%x != pic_ilevel=%x, pic_isr=%lx\n", + ilevel, pic_ilevel, pic_isr); if(!port){ /* icw1, ocw2, ocw3 */ if(value&0x10){ /* icw1 */ @@ -489,15 +472,9 @@ pic1_cmd=3; } else if((value&0xb8) == 0x20) { /* ocw2 */ - if(!pic_sp) { - pic_print(2,"EOI with nothing on pic_stack! ilevel=",ilevel,""); - } else if(pic_stack[pic_sp-1]!=ilevel) { - pic_print(2,"Stack value differed from ilevel! stack=",pic_stack[pic_sp-1],""); - } /* irqs on pic1 require an outb20 to each pic. we settle for any 2 */ if(!clear_bit(ilevel,&pic1_isr)) { clear_bit(ilevel,&pic_isr); /* the famous outb20 */ - pic_ilevel=pic_pop(); /* only pop stack when pic_isr gets cleared */ pic_print(1,"EOI resetting bit ",ilevel, " on pic0"); } else @@ -650,14 +627,10 @@ { int old_ilevel; int int_request; - int priority; /* don't allow HW interrupts in force trace mode */ if (vm86s.vm86plus.vm86dbg_TFpendig) return; - /* Old hack, to be removed */ - if (in_dpmi && in_dpmi_timer_int) return; - /* check for and find any requested irqs. Having found one, we atomic-ly * clear it and verify it was there when we cleared it. If it wasn't, we * look for the next request. There are two in_service bits for pic1 irqs. @@ -667,7 +640,6 @@ */ old_ilevel=pic_ilevel; /* save old pic_ilevl */ - priority = pic_smm + old_ilevel; /* check spec. mask mode */ while((int_request = pic_irr & ~(pic_isr | pic_imr)) != 0) { /* while something to do*/ int local_pic_ilevel; @@ -675,22 +647,25 @@ if (!isset_IF() && !in_dpmi) goto exit; /* exit if ints are disabled */ - do { - local_pic_ilevel = find_bit(int_request); /* find out what it is */ - /* In case int_request has no bits set */ - if (local_pic_ilevel == -1) - goto exit; - if (local_pic_ilevel > priority) /* priority check */ - goto exit; - } while (clear_bit(local_pic_ilevel, &pic_irr) == 0); /* dbl check & clear req */ + local_pic_ilevel = find_bit(int_request); /* find out what it is */ + /* In case int_request has no bits set */ + if (local_pic_ilevel == -1) + goto exit; + if (local_pic_ilevel >= old_ilevel + pic_smm) /* priority check */ + goto exit; + + if (pic_irqs_active && local_pic_ilevel >= find_bit(pic_irqs_active)) + goto exit; + + clear_bit(local_pic_ilevel, &pic_irr); pic_ilevel = local_pic_ilevel; set_bit(local_pic_ilevel, &pic_isr); /* set in-service bit */ set_bit(local_pic_ilevel, &pic1_isr); /* pic1 too */ pic1_isr &= pic_isr & pic1_mask; /* isolate pic1 irqs */ pic_iinfo[local_pic_ilevel].func(); /* run the function */ - local_pic_ilevel = pic_ilevel; clear_bit(local_pic_ilevel, &pic_isr); /* clear in_service bit */ clear_bit(local_pic_ilevel, &pic1_isr); /* pic1 too */ + pic_ilevel=old_ilevel; } exit: /* whether we did or didn't :-( get one, we must still reset pic_ilevel */ @@ -743,7 +718,10 @@ if(ilevel==PIC_IRQ9) /* unvectored irq9 just calls int 0x0a.. */ if(!IS_REDIRECTED(intr)) {intr=0x0a;pic1_isr&= 0xffef;} /* & one EOI */ { - if (test_bit(ilevel, &pic_irqall)) pic_push(ilevel); + if (test_bit(ilevel, &pic_irqall)) { + pic_push(ilevel); + set_bit(ilevel, &pic_irqs_active); + } if (!in_dpmi || in_dpmi_dos_int) { ssp = (unsigned char *)(LWORD(ss)<<4); @@ -824,9 +802,23 @@ void pic_resched() { -unsigned long pic_newirr; - if(pic_icount) +unsigned long pic_newirr, pic_last_ilevel; + if(pic_icount) { pic_icount--; + pic_last_ilevel = pic_pop(); + if (pic_icount != pic_sp) + error("pic_icount=%i != pic_sp=%i\n", pic_icount, pic_sp); + if (!test_bit(pic_last_ilevel, &pic_irqs_active)) { + error("PIC: bit %li is not set, irqs_active=%lx\n", + pic_last_ilevel, pic_irqs_active); + pic_irqs_active = 0; + } + clear_bit(pic_last_ilevel, &pic_irqs_active); + } else if (pic_irqs_active) { + error("pic_icount=%i and pic_irqs_active=%lx are out of sync!\n", + pic_icount, pic_irqs_active); + pic_irqs_active = 0; + } if(pic_icount<=pic_icount_od) { pic_newirr=pic_pirr&~pic_irr&~pic_isr; pic_irr|=pic_newirr; --- src/dosext/dpmi/dpmi.c Mon Sep 16 16:58:36 2002 +++ src/dosext/dpmi/dpmi.c Mon Sep 16 20:06:10 2002 @@ -1936,6 +1936,7 @@ } cli_blacklisted = 0; in_dpmi_dos_int = 1; + in_dpmi_pm_stack = 0; in_dpmi--; in_win31 = 0; if(pic_icount) { @@ -2104,7 +2105,6 @@ dpmi_stack_frame[current_client].ss = CLIENT_PMSTACK_SEL; dpmi_stack_frame[current_client].esp = PMSTACK_ESP; in_dpmi_pm_stack++; - if (i == 0x08 || in_dpmi_timer_int) in_dpmi_timer_int++; in_dpmi_dos_int = 0; dpmi_cli(); } @@ -3080,7 +3080,6 @@ "interrupt at %p\n", lina); } pic_iret(); - if (in_dpmi_timer_int) in_dpmi_timer_int--; } else if (_eip==DPMI_OFF+1+HLT_OFF(DPMI_return_from_exception)) { D_printf("DPMI: Return from client exception handler\n"); --- src/dosext/dpmi/dpmi.h Mon Sep 16 04:16:41 2002 +++ src/dosext/dpmi/dpmi.h Mon Sep 16 20:05:02 2002 @@ -41,7 +41,6 @@ EXTERN int in_win31 INIT(0); /* Set to 1 when running Windows 3.1 */ EXTERN int dpmi_eflags INIT(0); /* used for virtual interruptflag and pending interrupts */ EXTERN int in_dpmi_dos_int INIT(0); -EXTERN int in_dpmi_timer_int INIT(0); EXTERN int dpmi_mhp_TF INIT(0); EXTERN unsigned char dpmi_mhp_intxxtab[256] INIT({0}); EXTERN int is_cli INIT(0);