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); } } }
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(); }
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(); }
/* 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; } }