Exemple #1
0
void run_irqs(void)
/* find the highest priority unmasked requested irq and run it */
{
       int local_pic_ilevel, ret;

       /* don't allow HW interrupts in force trace mode */
       pic_activate();
       if (!isset_IF()) {
		if (pic_pending())
			set_VIP();
		return;                      /* exit if ints are disabled */
       }
       clear_VIP();

       /* 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.
        * This is needed, because irq 8-15 must do 2 outb20s, which, if the dos
        * irq code actually runs, will reset the bits.  We also reset them here,
        * since dos code won't necessarily run.
        */
       while((local_pic_ilevel = pic_get_ilevel()) != -1) { /* while something to do*/
               pic_print(1, "Running irq lvl ", local_pic_ilevel, "");
               clear_bit(local_pic_ilevel, &pic_irr);
	       /* pic_isr bit is set in do_irq() */
               ret = (pic_iinfo[local_pic_ilevel].func ?
	    	      pic_iinfo[local_pic_ilevel].func(local_pic_ilevel) : 1);      /* run the function */
	       if (ret) {
		       do_irq(local_pic_ilevel);
	       }
       }
}
Exemple #2
0
void coopth_sleep(void)
{
    assert(_coopth_is_in_thread());
    if (!is_detached() && !isset_IF())
	dosemu_error("sleep with interrupts disabled\n");
    switch_state(COOPTH_SLEEP);
    check_cancel();
}
Exemple #3
0
void coopth_wait(void)
{
    assert(_coopth_is_in_thread());
    ensure_attached();
    if (!isset_IF())
	dosemu_error("sleep with interrupts disabled\n");
    switch_state(COOPTH_WAIT);
    check_cancel();
}
Exemple #4
0
/* DANG_BEGIN_FUNCTION write_pic0,write_pic1
 *
 * write_pic_0() and write_pic1() implement dos writes to the pic ports.
 * They are called by the code that emulates inb and outb instructions.
 * Each function implements both ports for the pic:  pic0 is on ports
 * 0x20 and 0x21; pic1 is on ports 0xa0 and 0xa1.  These functions take
 * two arguments: a port number (0 or 1) and a value to be written.
 *
 * DANG_END_FUNCTION
 */
void write_pic0(ioport_t port, Bit8u value)
{

/* if port == 0 this must be either an ICW1, OCW2, or OCW3
 * if port == 1 this must be either ICW2, ICW3, ICW4, or load IMR
 */

#if 0
static char  icw_state,              /* !=0 => port 1 does icw 2,3,(4) */
#endif
static char                icw_max_state;          /* number of icws expected        */
int ilevel;			  /* level to reset on outb 0x20  */

port -= 0x20;
ilevel = 32;
if (pic_isr)
  ilevel=find_bit(pic_isr);
if (ilevel != 32 && !test_bit(ilevel, &pic_irqall)) {
  /* this is a fake IRQ, don't allow to reset its ISR bit */
  pic_print(1, "Protecting ISR bit for lvl ", ilevel, " from spurious EOI");
  ilevel = 32;
}

if (in_dpmi_pm())
  dpmi_return_request();	/* we have to leave the signal context */

if(!port){                          /* icw1, ocw2, ocw3 */
  if(value&0x10){                   /* icw1 */
    icw_max_state = (value & 1) + 1;
    if(value&2) ++icw_max_state;
    pic0_icw_state = 1;
    pic0_cmd=1;
    }

  else if (value&0x08){              /* ocw3 */
    if(value&2) pic0_isr_requested = value&1;
    if(value&64)pic_smm = value&32; /* must be either 0 or 32, conveniently */
    pic0_cmd=3;
    }
  else if((value&0xb8) == 0x20) {    /* ocw2 */
    /* 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_print(1,"EOI resetting bit ",ilevel, " on pic0");
#if 1
	/* XXX hack: to avoid timer interrupt re-entrancy,
	 * we try to disable interrupts in a hope IRET will re-enable
	 * them. This fixes Tetris Classic problem:
	 * https://github.com/stsp/dosemu2/issues/99
	 * Need to check also IMR because DPMI uses another hack
	 * that masks the IRQs. */
       if (ilevel == PIC_IRQ0 && isset_IF() && !(pic_imr & (1 << ilevel))) {
         r_printf("PIC: disabling interrupts to avoid reentrancy\n");
         clear_IF_timed();
       }
#endif
       }
     else
       pic_print(1,"EOI resetting bit ",ilevel, " on pic1");
     pic0_cmd=2;
      }
   }
else                              /* icw2, icw3, icw4, or mask register */
    switch(pic0_icw_state){
     case 0:                        /* mask register */
       set_pic0_imr(value);
       pic_print(1, "Set mask to ", value, " on pic0");
       break;
     case 1:                        /* icw2          */
       set_pic0_base(value);
     default:                       /* icw2, 3, and 4*/
       if(pic0_icw_state++ >= icw_max_state) pic0_icw_state=0;
  }
}