/* * Used to be * Copyright 1994, Eric A. Edwards * After substantial changes * Copyright 2003, Leonid A. Broukhis */ /* * service.c - Event handler system and interrupt service. */ #include "defines.h" #include "intl.h" #include "ops.h" /* Allows up to 32 different HW interrupts, * there can be no more than 1 pending interrupt of each kind. */ unsigned long pending_interrupts = 0; double earliest = 0.0; event events[NUM_PRI]; /* * ev_init() - Initialize the event system. */ void ev_init() { pending_interrupts = 0; } /* * ev_register() - Register an event. */ void ev_register(unsigned priority, int (*handler)(d_word), unsigned long delay, /* in clock ticks */ d_word info) { if (pending_interrupts & (1 << priority)) { /* There is one pending already */ return; } /* * Fill in the info. */ events[priority].handler = handler; events[priority].info = info; events[priority].when = ticks + delay; if (!pending_interrupts || ticks + delay < earliest) { earliest = ticks + delay; } pending_interrupts |= 1 << priority; /* fprintf(stderr, "Registering pri %d @ %g\n", priority, earliest); */ } /* * ev_fire() - Fire off any pending event by the mask * priority list. */ void ev_fire( int priority ) { int x; unsigned long mask = 0; switch (priority) { case 0: mask = ~0; break; case 1: mask = ~0; break; case 2: mask = ~0; break; case 3: mask = ~0; break; /* BK-0010 uses MTPS #200 to block keyboard interrupts */ case 4: mask = 1; break; case 5: mask = 0; break; case 6: mask = 0; break; case 7: mask = 0; break; } if (!(mask & pending_interrupts) || ticks < earliest) { return; } earliest = 10.0e38; for( x = 0; x < NUM_PRI && (1<= events[x].when) { events[x].handler(events[x].info); /* fprintf(stderr, "Firing pri %d\n", x); */ pending_interrupts &= ~(1 << x); mask = 0; } else if (pending_interrupts & (1<regs[PC]; oldpsw = p->psw; oldpc = p->regs[PC]; /* If we're servicing an interrupt while a WAIT instruction * was executing, we need to return after the WAIT. */ if (in_wait_instr) { oldpc += 2; in_wait_instr = 0; } if (( result = lc_word( vector, &newpc)) != OK) return result; if (( result = lc_word( vector + 2, &newpsw)) != OK) return result; // fprintf(stderr, "Int %o to %06o\n", vector, p->regs[PC]); addtocybuf(-vector); if (( result = push( p, oldpsw )) != OK ) return result; if (( result = push( p, oldpc )) != OK ) return result; p->psw = newpsw; p->regs[PC] = newpc; return OK; } /* * rti() - Return from Interrupt Instruction. */ int rti( p ) register pdp_regs *p; { d_word newpsw; d_word newpc; int result; last_branch = p->regs[PC]; if (( result = pop( p, &newpc )) != OK ) return result; if (( result = pop( p, &newpsw )) != OK ) return result; p->psw = newpsw; p->regs[PC] = newpc; return OK; } /* * rtt() - Return from Interrupt Instruction. */ int rtt( p ) register pdp_regs *p; { d_word newpsw; d_word newpc; int result; last_branch = p->regs[PC]; if (( result = pop( p, &newpc )) != OK ) return result; if (( result = pop( p, &newpsw )) != OK ) return result; p->psw = newpsw; p->regs[PC] = newpc; return CPU_RTT; }