コード例 #1
0
ファイル: pic.c プロジェクト: andrewbird/dosemu2
void write_pic1(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 */
static char /* icw_state, */     /* !=0 => port 1 does icw 2,3,(4) */
               icw_max_state;    /* number of icws expected        */
int ilevel;			  /* level to reset on outb 0x20  */

port -= 0xa0;
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;
    pic1_icw_state = 1;
    pic1_cmd=1;
    }
  else if (value&0x08) {                /* ocw3 */
    if(value&2) pic1_isr_requested = value&1;
    if(value&64)pic_smm = value&32; /* must be either 0 or 32, conveniently */
    pic1_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");
       }
     else
       pic_print(1,"EOI resetting bit ",ilevel, " on pic1");
     pic0_cmd=2;
     }
  }
else                         /* icw2, icw3, icw4, or mask register */
  switch(pic1_icw_state){
     case 0:                    /* mask register */
       set_pic1_imr(value);
       pic_print(1, "Set mask to ", value, " on pic1");
       break;
     case 1:                    /* icw 2         */
       set_pic1_base(value);
     default:                   /* icw 2,3 and 4 */
       if(pic1_icw_state++ >= icw_max_state) pic1_icw_state=0;
  }
}
コード例 #2
0
ファイル: pic.c プロジェクト: andrewbird/dosemu2
void pic_sched(int ilevel, int interval)
{
  char mesg[35];

 /* default for interval is 65536 (=54.9ms)
  * There's a problem with too small time intervals - an interrupt can
  * be continuously scheduled, without letting any time to process other
  * code.
  *
  * BIG WARNING - in non-periodic timer modes pit[0].cntr goes to -1
  *	at the end of the interval - was this the reason for the following
  *	[1u-15sec] range check?
  */
  if(interval > 0 && interval < 0x3fffffff) {
     if(pic_ltime[ilevel]==NEVER) {
	pic_itime[ilevel] = pic_itime[32] + interval;
     } else {
	pic_itime[ilevel] = pic_itime[ilevel] + interval;
     }
  }
  if (debug_level('r') > 2) {
    /* avoid going through sprintf for non-debugging */
    sprintf(mesg,", delay= %d.",interval);
    pic_print(2,"Scheduling lvl= ",ilevel,mesg);
    pic_print2(2,"pic_itime set to ",pic_itime[ilevel],"");
  }
}
コード例 #3
0
ファイル: pic.c プロジェクト: andrewbird/dosemu2
/* DANG_BEGIN_FUNCTION pic_activate
 *
 * pic_activate requests any interrupts whose scheduled time has arrived.
 * anything after pic_dos_time and before pic_sys_time is activated.
 * pic_dos_time is advanced to the earliest time scheduled.
 * DANG_END_FUNCTION
 */
static void pic_activate(void)
{
  hitimer_t earliest;
  int timer, count;
  unsigned pic_newirr = pic_pirr & ~(pic_irr | pic_isr);
  pic_irr |= pic_newirr;
  pic_pirr &= ~pic_newirr;

/*if(pic_irr&~pic_imr) return;*/
   earliest = pic_sys_time;
   count = 0;
   for (timer=0; timer<32; ++timer) {
      if ((pic_itime[timer] != NEVER) && (pic_itime[timer] < pic_sys_time)) {
         if (pic_itime[timer] != pic_ltime[timer]) {
               if ((earliest == NEVER) || (pic_itime[timer] < earliest))
                    earliest = pic_itime[timer];
               pic_request(timer);
               ++count;
         }
      }
   }
   if(count) pic_print(2,"Activated ",count, " interrupts.");
   pic_print2(2,"Activate ++ dos time to ",earliest, " ");
   pic_print2(2,"pic_sys_time is ",pic_sys_time," ");
   /*if(!pic_icount)*/ pic_dos_time = pic_itime[32] = earliest;
}
コード例 #4
0
ファイル: pic.c プロジェクト: andrewbird/dosemu2
void pic_untrigger(int inum)
{
    if (!((pic_irr | pic_pirr) & (1<<inum)))
      return;
    /* Note: untriggering works similar in both edge and level modes.
     * In fact, these modes are very similar in that IRR bits mirror
     * the IRQ lines as-is. The only difference is that in edge mode
     * the IRR bit is reset by INTA and remains at 0 until the first
     * low->high transition is detected. After which, it again mirrors
     * the IRQ pin directly. In level mode it always mirrors the input.
     * This means that with "level-delivering" devices there is no
     * difference AT ALL with what triggering mode is used. Their
     * inactive state is low, so on the first transition to high, IRR
     * bit starts following the input in any trigger mode. The difference
     * is there only with the "edge-delivering" devices: their inactive
     * state is high and the IRQ delivery start from the short pulse to
     * low and back. Before that starting pulse, IRR bit remains low even
     * though the IRQ line is high. There are probably not much of the
     * "edge-delivering" devices though: PIT in mode 2 is the only
     * one known to me.
     * In short: we should allow untriggering the interrupt regardless
     * of the trigger mode.
     *
     * Note: spurious IRQ should be generated in any trigger mode if
     * all IRQ lines went low before INTA. This is because even in edge
     * mode the IRR bit gets cleared when IRQ line goes down, so at
     * INTA time there will be nothing to read from IRR.
     */
    pic_pirr &= ~(1<<inum);
    pic_irr &= ~(1<<inum);
    pic_print(2,"Requested irq lvl ", inum, " untriggered");
}
コード例 #5
0
ファイル: pic.c プロジェクト: andrewbird/dosemu2
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);
	       }
       }
}
コード例 #6
0
int main(void)
{
	pic_insert("1.jpg");
	pic_insert("2.jpg");
	pic_insert("3.jpg");
	pic_insert("4.jpg");
	
	pic_print();
	pic_destroy();
	
	return 0;
}
コード例 #7
0
ファイル: pic.c プロジェクト: andrewbird/dosemu2
/* DANG_BEGIN_FUNCTION pic_request
 *
 * pic_request triggers an interrupt.  There is presently no way to
 * "un-trigger" an interrupt.  The interrupt will be initiated the
 * next time pic_run is called, unless masked or superceded by a
 * higher priority interrupt.  pic_request takes one argument, an
 * interrupt level, which specifies the interrupt to be triggered.
 * If that interrupt is already active, the request will be queued
 * until all active interrupts have been completed.  The queue is
 * only one request deep for each interrupt, so it is the responsibility
 * of the interrupt code to retrigger itself if more interrupts are
 * needed.
 *
 * DANG_END_FUNCTION
 */
int pic_request(int inum)
{
static char buf[81];
  int ret=PIC_REQ_NOP;

  if ((pic_irr|pic_isr)&(1<<inum))
    {
    if (pic_pirr&(1<<inum)){
     ret=PIC_REQ_LOST;
     pic_print(2,"Requested irq lvl ",    inum, " lost     ");
      }
    else {
     ret=PIC_REQ_PEND;
     pic_print(2,"Requested irq lvl ",    inum, " pending  ");
      }
    pic_pirr|=(1<<inum);
    if(pic_itime[inum] == pic_ltime[inum]) {
       pic_print(2,"pic_itime and pic_ltime for timer ",inum," matched!");
       pic_itime[inum] = pic_itime[32];
    }
    pic_ltime[inum] = pic_itime[inum];
  }
  else {
    pic_print(2,"Requested irq lvl ",    inum, " successfully");
    pic_irr|=(1<<inum);
    if(pic_itime[inum] == pic_ltime[inum]) pic_itime[inum] = pic_itime[32];
    pic_ltime[inum] = pic_itime[inum];
    ret=PIC_REQ_OK;
  }
  if (debug_level('r') >2) {
    /* avoid going through sprintf for non-debugging */
    sprintf(buf,", k%d",(int)pic_dpmi_count);
    pic_print(2,"Zeroing vm86, DPMI from ",pic_vm86_count,buf);
  }
  pic_vm86_count=pic_dpmi_count=0;
  return ret;
}
コード例 #8
0
ファイル: pic.c プロジェクト: andrewbird/dosemu2
/* 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;
  }
}