## diffname pc/i8259.c 1997/0327 ## diff -e /dev/null /n/emeliedump/1997/0327/sys/src/brazil/pc/i8259.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" /* * 8259 interrupt controllers */ enum { Int0ctl= 0x20, /* control port (ICW1, OCW2, OCW3) */ Int0aux= 0x21, /* everything else (ICW2, ICW3, ICW4, OCW1) */ Int1ctl= 0xA0, /* control port */ Int1aux= 0xA1, /* everything else (ICW2, ICW3, ICW4, OCW1) */ Icw1= 0x10, /* select bit in ctl register */ Ocw2= 0x00, Ocw3= 0x08, EOI= 0x20, /* non-specific end of interrupt */ Elcr1= 0x4D0, /* Edge/Level Triggered Register */ Elcr2= 0x4D1, }; static int int0mask; /* interrupts enabled for first 8259 */ static int int1mask; /* interrupts enabled for second 8259 */ int elcr; /* mask of level-triggered interrupts */ void i8259init(void) { int elcr1; int0mask = 0xFF; int1mask = 0xFF; /* * Set up the first 8259 interrupt processor. * Make 8259 interrupts start at CPU vector Int0vec. * Set the 8259 as master with edge triggered * input with fully nested interrupts. */ outb(Int0ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered, ICW4 will be sent */ outb(Int0aux, VectorPIC); /* ICW2 - interrupt vector offset */ outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */ outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */ /* * Set up the second 8259 interrupt processor. * Make 8259 interrupts start at CPU vector VectorPIC+8. * Set the 8259 as slave with edge triggered * input with fully nested interrupts. */ outb(Int1ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered, ICW4 will be sent */ outb(Int1aux, VectorPIC+8); /* ICW2 - interrupt vector offset */ outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */ outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */ /* * pass #2 8259 interrupts to #1 */ int0mask &= ~0x04; outb(Int0aux, int0mask); /* * Set Ocw3 to return the ISR when ctl read. * After initialisation status read is set to IRR. * Read IRR first to possibly deassert an outstanding * interrupt. */ inb(Int0ctl); outb(Int0ctl, Ocw3|0x03); inb(Int1ctl); outb(Int1ctl, Ocw3|0x03); /* * Check for Edge/Level register. * This check may not work for all chipsets. */ elcr1 = inb(Elcr1); outb(Elcr1, 0); if(inb(Elcr1) == 0){ outb(Elcr1, 0x20); if(inb(Elcr1) == 0x20) elcr = (inb(Elcr2)<<8)|elcr1; } outb(Elcr1, elcr1); /* if(elcr) print("ELCR: %4.4uX\n", elcr); */ } int i8259isr(int v) { int isr; /* * tell the 8259 that we're done with the * highest level interrupt (interrupts are still * off at this point) */ isr = 0; if(v >= VectorPIC && v <= MaxVectorPIC){ isr = inb(Int0ctl); outb(Int0ctl, EOI); if(v >= VectorPIC+8){ isr |= inb(Int1ctl)<<8; outb(Int1ctl, EOI); } } return isr & (1<<(v-VectorPIC)); } int i8259enable(int v, int, Irqctl* irqctl) { if(v < VectorPIC || v > MaxVectorPIC) return 0; v -= VectorPIC; /* * enable corresponding interrupt in 8259 */ if(v < 8){ int0mask &= ~(1<eoi = i8259isr; else irqctl->isr = i8259isr; irqctl->isintr = 1; return v; } . ## diffname pc/i8259.c 1997/0521 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/i8259.c /n/emeliedump/1997/0521/sys/src/brazil/pc/i8259.c 94,97c // if(elcr) // print("ELCR: %4.4uX\n", elcr); . ## diffname pc/i8259.c 1998/0320 ## diff -e /n/emeliedump/1997/0521/sys/src/brazil/pc/i8259.c /n/emeliedump/1998/0320/sys/src/brazil/pc/i8259.c 124,125c if(v < VectorPIC || v > MaxVectorPIC){ print("i8259enable: vector %d out of range\n", v); return -1; } . ## diffname pc/i8259.c 1998/0910 ## diff -e /n/emeliedump/1998/0320/sys/src/brazil/pc/i8259.c /n/emeliedump/1998/0910/sys/src/brazil/pc/i8259.c 148c return VectorPIC+irq; . 145,146c v->isr = i8259isr; iunlock(&i8259lock); . 142,143c if(elcr & (1<eoi = i8259isr; . 138c int1mask &= ~(1<<(irq-8)); . 133,134c irq = v->irq; if(irq < 0 || irq > MaxIrqPIC){ print("i8259enable: irq %d out of range\n", irq); return -1; } ilock(&i8259lock); if(irq < 8){ int0mask &= ~(1<= VectorPIC+8){ isr |= inb(Int1ctl)<<8; outb(Int1ctl, EOI); . 102a if(vno < VectorPIC || vno > VectorPIC+MaxIrqPIC) return 0; . 99c i8259isr(int vno) . 93a iunlock(&i8259lock); . 43c * Make 8259 interrupts start at CPU vector VectorPIC. . 37a ilock(&i8259lock); . 31,32d 29a static int elcr; /* mask of level-triggered interrupts */ static Lock i8259lock; . ## diffname pc/i8259.c 1998/1022 ## diff -e /n/emeliedump/1998/0910/sys/src/brazil/pc/i8259.c /n/emeliedump/1998/1022/sys/src/brazil/pc/i8259.c 96,97d 94d 87,92c x = (inb(Elcr2)<<8)|inb(Elcr1); if(!(x & 0x2107)){ outb(Elcr1, 0); if(inb(Elcr1) == 0){ outb(Elcr1, 0x20); if(inb(Elcr1) == 0x20) elcr = x; outb(Elcr1, x & 0xFF); //print("ELCR: %4.4uX\n", elcr); } . 85a * First try a non-intrusive test - the bits for * IRQs 13, 8, 2, 1 and 0 must be edge (0). If * that's OK try a R/W test. . 36c int x; . 30c int elcr; /* mask of level-triggered interrupts */ . ## diffname pc/i8259.c 1998/1114 ## diff -e /n/emeliedump/1998/1022/sys/src/brazil/pc/i8259.c /n/emeliedump/1998/1114/sys/src/brazil/pc/i8259.c 64a outb(Int1aux, int1mask); . ## diffname pc/i8259.c 1999/0301 ## diff -e /n/emeliedump/1998/1114/sys/src/brazil/pc/i8259.c /n/emeliedump/1999/0301/sys/src/brazil/pc/i8259.c 156c if(i8259elcr & irqbit) . 151,154c i8259mask &= ~irqbit; if(irq < 8) outb(Int0aux, i8259mask & 0xFF); else outb(Int1aux, (i8259mask>>8) & 0xFF); . 147,149c if(!(i8259mask & irqbit) && !(i8259elcr & irqbit)){ print("i8259enable: irq %d shared but not level\n", irq); iunlock(&i8259lock); return -1; . 144a irqbit = 1<= 8){ . 111a irq = vno-VectorPIC; . 108c int irq, isr; . 99c //print("ELCR: %4.4uX\n", i8259elcr); . 97c i8259elcr = x; . 70,71c i8259mask &= ~0x04; outb(Int0aux, i8259mask & 0xFF); . 65c outb(Int1aux, (i8259mask>>8) & 0xFF); . 39,40d 31a static int i8259mask = 0xFFFF; /* disabled interrupts */ int i8259elcr; /* mask of level-triggered interrupts */ . 28,30d ## diffname pc/i8259.c 1999/0714 ## diff -e /n/emeliedump/1999/0301/sys/src/brazil/pc/i8259.c /n/emeliedump/1999/0714/sys/src/brazil/pc/i8259.c 36a ioalloc(Int0ctl, 2, 0, "i8259.0"); ioalloc(Int1ctl, 2, 0, "i8259.1"); . ## diffname pc/i8259.c 2001/0222 ## diff -e /n/emeliedump/1999/0714/sys/src/brazil/pc/i8259.c /n/emeliedump/2001/0222/sys/src/9/pc/i8259.c 166a void i8259dump(void) { uchar aux0, aux1; aux0 = inb(Int0aux); aux1 = inb(Int1aux); print("i8269: %ux %2.2ux %2.2ux\n", i8259mask, aux0, aux1); } . ## diffname pc/i8259.c 2001/0428 ## diff -e /n/emeliedump/2001/0222/sys/src/9/pc/i8259.c /n/emeliedump/2001/0428/sys/src/9/pc/i8259.c 167,176d ## diffname pc/i8259.c 2001/0527 ## diff -e /n/emeliedump/2001/0428/sys/src/9/pc/i8259.c /n/emeliedump/2001/0527/sys/src/9/pc/i8259.c 98c print("ELCR: %4.4uX\n", i8259elcr); . ## diffname pc/i8259.c 2001/0905 ## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/i8259.c /n/emeliedump/2001/0905/sys/src/9/pc/i8259.c 166a int i8259vecno(int irq) { return VectorPIC+irq; } int i8259disable(int irq) { int irqbit; /* * Given an IRQ, disable the corresponding interrupt * in the 8259. */ if(irq < 0 || irq > MaxIrqPIC){ print("i8259disable: irq %d out of range\n", irq); return -1; } irqbit = 1<>8) & 0xFF); } iunlock(&i8259lock); return 0; } .