|
Listing 12:
/* [excerpted from i386.c] */
...
init386() {
...
outb(0xf1,0); /* clear coprocessor to cover all bases */
/* initialize 8259 ICU's in preperation for device interrupts */
outb(ICU1,0x11); /* reset the unit */
outb(ICU1+1,32); /* start with idt 32 */
outb(ICU1+1,4); /* master please */
outb(ICU1+1,1);
outb(ICU1+1,0xff); /* all disabled */
outb(ICU2,0x11);
outb(ICU2+1,40); /* start with idt 40 */
outb(ICU2+1,2); /* just a slave */
outb(ICU2+1,1);
outb(ICU2+1,0xff); /* all disabled */
/* initialize 8253 timer on interrupt #0 */
outb (0x43, 0x36);
outb (0x40, 193182/60);
outb (0x40, (193182/60)/256);
}
test386(){
...
/* test interrupts for a while */
printf("inton"); getchar();
outb(ICU1+1,0); /* unmask all interrupts */
outb(ICU2+1,0);
inton();
timeout = 0x8000000;
do nothing(); while (timeout-- );
intoff();
...
# excerpted from srt.s
...
#define INTR(a) \
pushal ; \
push %ds ; \
push %es ; \
movw $0x10, %ax ; \
movw %ax, %ds ; \
movw %ax,%es ; \
pushl $##a ; \
call _intr ; \
pop %eax ; \
pop %es ; \
pop %ds ; \
popal ; \
iret
/* hardware 32 - 47 */
IDTVEC(intr0)
INTR(0)
IDTVEC(intr1)
INTR(1)
IDTVEC(intr2)
INTR(2)
IDTVEC(intr3)
INTR(3)
IDTVEC(intr4)
INTR(4)
IDTVEC(intr5)
INTR(5)
IDTVEC(intr6)
INTR(6)
IDTVEC(intr7)
INTR(7)
IDTVEC(intr8)
INTR(8)
IDTVEC(intr9)
INTR(9)
IDTVEC(intr10)
INTR(10)
IDTVEC(intr11)
INTR(11)
IDTVEC(intr12)
INTR(12)
IDTVEC(intr13)
INTR(13)
IDTVEC(intr14)
INTR(14)
IDTVEC(intr15)
INTR(15)
.globl _inton
_inton:
sti
ret
.globl _intoff
_intoff:
cli
ret
...
/* back to i386.c */
...
/* Interrupt vector processing code */
intr(ivec) {
static clk;
int omsk1, omsk2;
/* mask off interrupt being serviced, save old mask */
if (ivec > 7) {
omsk2 = inb(ICU2+1);
outb(ICU2+1, 1<<(ivec-8));
} else {
omsk1 = inb(ICU1+1);
outb(ICU1+1, 1<<ivec);
}
/* re-enable processor's interrupts, allowing others in */
inton();
/* if we are the clock, count clock tick */
if (ivec == 0) clk++;
/* if we are the keyboard, show data incoming */
else if (ivec == 1) printf("kbd data %x, clk %d\n", inb(0x60), clk);
/* otherwise print message stating source and time */
else {
printf("intr %d, clk %d \n", ivec, clk);
getchar();
}
/* turn off interrupts, re-enable old mask, do interrupt acknowledge */
intoff();
if (ivec > 7) {
outb(ICU2+1,omsk2);
outb(ICU2,0x20);
} else
outb(ICU1+1,omsk1);
outb(ICU1,0x20);
/* return to interrupt stub */
}
...
Listing 12:
/* [excerpted from i386.c] */
...
init386() {
...
outb(0xf1,0); /* clear coprocessor to cover all bases */
/* initialize 8259 ICU's in preperation for device interrupts */
outb(ICU1,0x11); /* reset the unit */
outb(ICU1+1,32); /* start with idt 32 */
outb(ICU1+1,4); /* master please */
outb(ICU1+1,1);
outb(ICU1+1,0xff); /* all disabled */
outb(ICU2,0x11);
outb(ICU2+1,40); /* start with idt 40 */
outb(ICU2+1,2); /* just a slave */
outb(ICU2+1,1);
outb(ICU2+1,0xff); /* all disabled */
/* initialize 8253 timer on interrupt #0 */
outb (0x43, 0x36);
outb (0x40, 193182/60);
outb (0x40, (193182/60)/256);
}
test386(){
...
/* test interrupts for a while */
printf("inton"); getchar();
outb(ICU1+1,0); /* unmask all interrupts */
outb(ICU2+1,0);
inton();
timeout = 0x8000000;
do nothing(); while (timeout-- );
intoff();
...
# excerpted from srt.s
...
#define INTR(a) \
pushal ; \
push %ds ; \
push %es ; \
movw $0x10, %ax ; \
movw %ax, %ds ; \
movw %ax,%es ; \
pushl $##a ; \
call _intr ; \
pop %eax ; \
pop %es ; \
pop %ds ; \
popal ; \
iret
/* hardware 32 - 47 */
IDTVEC(intr0)
INTR(0)
IDTVEC(intr1)
INTR(1)
IDTVEC(intr2)
INTR(2)
IDTVEC(intr3)
INTR(3)
IDTVEC(intr4)
INTR(4)
IDTVEC(intr5)
INTR(5)
IDTVEC(intr6)
INTR(6)
IDTVEC(intr7)
INTR(7)
IDTVEC(intr8)
INTR(8)
IDTVEC(intr9)
INTR(9)
IDTVEC(intr10)
INTR(10)
IDTVEC(intr11)
INTR(11)
IDTVEC(intr12)
INTR(12)
IDTVEC(intr13)
INTR(13)
IDTVEC(intr14)
INTR(14)
IDTVEC(intr15)
INTR(15)
.globl _inton
_inton:
sti
ret
.globl _intoff
_intoff:
cli
ret
...
/* back to i386.c */
...
/* Interrupt vector processing code */
intr(ivec) {
static clk;
int omsk1, omsk2;
/* mask off interrupt being serviced, save old mask */
if (ivec > 7) {
omsk2 = inb(ICU2+1);
outb(ICU2+1, 1<<(ivec-8));
} else {
omsk1 = inb(ICU1+1);
outb(ICU1+1, 1<<ivec);
}
/* re-enable processor's interrupts, allowing others in */
inton();
/* if we are the clock, count clock tick */
if (ivec == 0) clk++;
/* if we are the keyboard, show data incoming */
else if (ivec == 1) printf("kbd data %x, clk %d\n", inb(0x60), clk);
/* otherwise print message stating source and time */
else {
printf("intr %d, clk %d \n", ivec, clk);
getchar();
}
/* turn off interrupts, re-enable old mask, do interrupt acknowledge */
intoff();
if (ivec > 7) {
outb(ICU2+1,omsk2);
outb(ICU2,0x20);
} else
outb(ICU1+1,omsk1);
outb(ICU1,0x20);
/* return to interrupt stub */
}
...
After saving the processor state, all trap stubs call common code, which calls the C language trap handler; they also have code following, which restores the state and returns to whatever code was running when the trap occurred. The C language handler merely notifies us of the processor state and exception type and then returns. Since our test function will test different traps in a sequence, we prefer to bypass faults that don't move the program counter. We do this by manually incrementing the program counter, knowing that all faults we intend to encounter happen to be 1 byte in size. Obviously, this convenience doesn't hold for the BSD kernel, but it is satisfactory for the moment.
|
|