| plan 9 kernel history: overview | file list | diff list |
1998/1022/pc/i8259.c (diff list | history)
| 1997/0327/sys/src/9/pc/i8259.c:91,100 – 1997/0521/sys/src/9/pc/i8259.c:91,98 (short | long) | ||
|
format edit
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | elcr = (inb(Elcr2)<<8)|elcr1; } outb(Elcr1, elcr1); | |
| 1997/0521 | // if(elcr) // print("ELCR: %4.4uX\n", elcr); | |
| 1997/0327 | } int | |
| 1997/0521/sys/src/9/pc/i8259.c:121,128 – 1998/0320/sys/src/9/pc/i8259.c:121,130 (short | long) | ||
|
add print for out-of-range vectors
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | int i8259enable(int v, int, Irqctl* irqctl) { | |
| 1998/0320 | if(v < VectorPIC || v > MaxVectorPIC){ print("i8259enable: vector %d out of range\n", v); return -1; } | |
| 1997/0327 | v -= VectorPIC; /* | |
| 1998/0320/sys/src/9/pc/i8259.c:27,46 – 1998/0910/sys/src/9/pc/i8259.c:27,47 (short | long) | ||
|
XXX bug fix?: add i8259lock. Change Vector* to Irq*.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | static int int0mask; /* interrupts enabled for first 8259 */ static int int1mask; /* interrupts enabled for second 8259 */ | |
| 1998/0910 | static int elcr; /* mask of level-triggered interrupts */ static Lock i8259lock; | |
| 1997/0327 |
| |
| 1998/0910 | ilock(&i8259lock); | |
| 1997/0327 | int0mask = 0xFF; int1mask = 0xFF; /* * Set up the first 8259 interrupt processor. | |
| 1998/0910 | * Make 8259 interrupts start at CPU vector VectorPIC. | |
| 1997/0327 | * Set the 8259 as master with edge triggered * input with fully nested interrupts. */ | |
| 1998/0320/sys/src/9/pc/i8259.c:91,149 – 1998/0910/sys/src/9/pc/i8259.c:92,158 | ||
| 1997/0327 | elcr = (inb(Elcr2)<<8)|elcr1; } outb(Elcr1, elcr1); | |
| 1998/0910 | iunlock(&i8259lock); | |
| 1997/0521 | // if(elcr) // print("ELCR: %4.4uX\n", elcr); | |
| 1997/0327 | } int | |
| 1998/0910 | i8259isr(int vno) | |
| 1997/0327 | { int isr; | |
| 1998/0910 | if(vno < VectorPIC || vno > VectorPIC+MaxIrqPIC) return 0; | |
| 1997/0327 | /* * tell the 8259 that we're done with the * highest level interrupt (interrupts are still * off at this point) */ | |
| 1998/0910 | ilock(&i8259lock); isr = inb(Int0ctl); outb(Int0ctl, EOI); if(vno >= VectorPIC+8){ isr |= inb(Int1ctl)<<8; outb(Int1ctl, EOI); | |
| 1997/0327 | } | |
| 1998/0910 | iunlock(&i8259lock); | |
| 1997/0327 |
| |
| 1998/0910 | return isr & (1<<(vno-VectorPIC)); | |
| 1997/0327 | } int | |
| 1998/0910 | i8259enable(Vctl* v) | |
| 1997/0327 | { | |
| 1998/0320 |
| |
| 1997/0327 |
| |
| 1998/0910 | int irq; | |
| 1997/0327 | /* | |
| 1998/0910 | * Given an IRQ, enable the corresponding interrupt in the i8259 * and return the vector to be used. The i8259 is set to use a fixed * range of vectors starting at VectorPIC. | |
| 1997/0327 | */ | |
| 1998/0910 | 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<<irq); | |
| 1997/0327 | outb(Int0aux, int0mask); } else{ | |
| 1998/0910 | int1mask &= ~(1<<(irq-8)); | |
| 1997/0327 | outb(Int1aux, int1mask); } | |
| 1998/0910 | if(elcr & (1<<irq)) v->eoi = i8259isr; | |
| 1997/0327 | else | |
| 1998/0910 | v->isr = i8259isr; iunlock(&i8259lock); | |
| 1997/0327 |
| |
| 1998/0910 | return VectorPIC+irq; | |
| 1997/0327 | } | |
| 1998/0910/sys/src/9/pc/i8259.c:27,39 – 1998/1022/sys/src/9/pc/i8259.c:27,39 (short | long) | ||
|
hw BUG fix? better test for edge/level register. publish elcr
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | static int int0mask; /* interrupts enabled for first 8259 */ static int int1mask; /* interrupts enabled for second 8259 */ | |
| 1998/0910 |
| |
| 1998/1022 | int elcr; /* mask of level-triggered interrupts */ | |
| 1998/0910 | static Lock i8259lock; | |
| 1997/0327 | void i8259init(void) { | |
| 1998/1022 | int x; | |
| 1997/0327 | ||
| 1998/0910 | ilock(&i8259lock); | |
| 1997/0327 | int0mask = 0xFF; | |
| 1998/0910/sys/src/9/pc/i8259.c:83,100 – 1998/1022/sys/src/9/pc/i8259.c:83,104 | ||
| 1997/0327 | /* * Check for Edge/Level register. * This check may not work for all chipsets. | |
| 1998/1022 | * 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. | |
| 1997/0327 | */ | |
| 1998/1022 | 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); } | |
| 1997/0327 | } | |
| 1998/0910 | iunlock(&i8259lock); | |
| 1997/0521 |
| |
| 1997/0327 | } int | |
| 1998/1022/sys/src/9/pc/i8259.c:62,67 – 1998/1114/sys/src/9/pc/i8259.c:62,68 (short | long) | ||
|
set int1mask (BUG fix?)
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | 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 */ | |
| 1998/1114 | outb(Int1aux, int1mask); | |
| 1997/0327 | /* * pass #2 8259 interrupts to #1 | |
| 1998/1114/sys/src/9/pc/i8259.c:25,34 – 1999/0301/sys/src/9/pc/i8259.c:25,33 (short | long) | ||
|
replace int0mask, int1mask with i8259mask. replace elcr with i8259elcr. check for shared non-level-triggered interrupts.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | Elcr2= 0x4D1, }; | |
| 1998/1022 |
| |
| 1998/0910 | static Lock i8259lock; | |
| 1999/0301 | static int i8259mask = 0xFFFF; /* disabled interrupts */ int i8259elcr; /* mask of level-triggered interrupts */ | |
| 1997/0327 | void i8259init(void) | |
| 1998/1114/sys/src/9/pc/i8259.c:36,43 – 1999/0301/sys/src/9/pc/i8259.c:35,40 | ||
| 1998/1022 | int x; | |
| 1997/0327 | ||
| 1998/0910 | ilock(&i8259lock); | |
| 1997/0327 |
| |
| 1998/1114/sys/src/9/pc/i8259.c:62,74 – 1999/0301/sys/src/9/pc/i8259.c:59,71 | ||
| 1997/0327 | 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 */ | |
| 1998/1114 |
| |
| 1999/0301 | outb(Int1aux, (i8259mask>>8) & 0xFF); | |
| 1997/0327 | /* * pass #2 8259 interrupts to #1 */ | |
| 1999/0301 | i8259mask &= ~0x04; outb(Int0aux, i8259mask & 0xFF); | |
| 1997/0327 | /* * Set Ocw3 to return the ISR when ctl read. | |
| 1998/1114/sys/src/9/pc/i8259.c:94,102 – 1999/0301/sys/src/9/pc/i8259.c:91,99 | ||
| 1998/1022 | if(inb(Elcr1) == 0){ outb(Elcr1, 0x20); if(inb(Elcr1) == 0x20) | |
| 1999/0301 | i8259elcr = x; | |
| 1998/1022 | outb(Elcr1, x & 0xFF); | |
| 1999/0301 | //print("ELCR: %4.4uX\n", i8259elcr); | |
| 1998/1022 | } | |
| 1997/0327 | } | |
| 1998/0910 | iunlock(&i8259lock); | |
| 1998/1114/sys/src/9/pc/i8259.c:105,114 – 1999/0301/sys/src/9/pc/i8259.c:102,112 | ||
| 1997/0327 | int | |
| 1998/0910 | i8259isr(int vno) | |
| 1997/0327 | { | |
| 1999/0301 | int irq, isr; | |
| 1997/0327 | ||
| 1998/0910 | if(vno < VectorPIC || vno > VectorPIC+MaxIrqPIC) return 0; | |
| 1999/0301 | irq = vno-VectorPIC; | |
| 1998/0910 | ||
| 1997/0327 | /* * tell the 8259 that we're done with the | |
| 1998/1114/sys/src/9/pc/i8259.c:118,136 – 1999/0301/sys/src/9/pc/i8259.c:116,134 | ||
| 1998/0910 | ilock(&i8259lock); isr = inb(Int0ctl); outb(Int0ctl, EOI); | |
| 1999/0301 | if(irq >= 8){ | |
| 1998/0910 | isr |= inb(Int1ctl)<<8; outb(Int1ctl, EOI); | |
| 1997/0327 | } | |
| 1998/0910 | iunlock(&i8259lock); | |
| 1997/0327 | ||
| 1998/0910 |
| |
| 1999/0301 | return isr & (1<<irq); | |
| 1997/0327 | } int | |
| 1998/0910 | i8259enable(Vctl* v) | |
| 1997/0327 | { | |
| 1998/0910 |
| |
| 1999/0301 | int irq, irqbit; | |
| 1997/0327 | /* | |
| 1998/0910 | * Given an IRQ, enable the corresponding interrupt in the i8259 | |
| 1998/1114/sys/src/9/pc/i8259.c:142,159 – 1999/0301/sys/src/9/pc/i8259.c:140,160 | ||
| 1998/0910 | print("i8259enable: irq %d out of range\n", irq); return -1; } | |
| 1999/0301 | irqbit = 1<<irq; | |
| 1998/0910 | ilock(&i8259lock); | |
| 1997/0327 |
| |
| 1999/0301 | if(!(i8259mask & irqbit) && !(i8259elcr & irqbit)){ print("i8259enable: irq %d shared but not level\n", irq); iunlock(&i8259lock); return -1; | |
| 1997/0327 | } | |
| 1998/0910 |
| |
| 1997/0327 |
| |
| 1999/0301 | i8259mask &= ~irqbit; if(irq < 8) outb(Int0aux, i8259mask & 0xFF); else outb(Int1aux, (i8259mask>>8) & 0xFF); | |
| 1997/0327 | ||
| 1998/0910 |
| |
| 1999/0301 | if(i8259elcr & irqbit) | |
| 1998/0910 | v->eoi = i8259isr; | |
| 1997/0327 | else | |
| 1998/0910 | v->isr = i8259isr; | |
| 1999/0301/sys/src/9/pc/i8259.c:34,39 – 1999/0714/sys/src/9/pc/i8259.c:34,41 (short | long) | ||
|
Use ioalloc.
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | { | |
| 1998/1022 | int x; | |
| 1997/0327 | ||
| 1999/0714 | ioalloc(Int0ctl, 2, 0, "i8259.0"); ioalloc(Int1ctl, 2, 0, "i8259.1"); | |
| 1998/0910 | ilock(&i8259lock); | |
| 1997/0327 | /* | |
| 1999/0714/sys/src/9/pc/i8259.c:164,166 – 2001/0222/sys/src/9/pc/i8259.c:164,176 (short | long) | ||
|
add i8259dump
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | ||
| 1998/0910 | return VectorPIC+irq; | |
| 1997/0327 | } | |
| 2001/0222 | void i8259dump(void) { uchar aux0, aux1; aux0 = inb(Int0aux); aux1 = inb(Int1aux); print("i8269: %ux %2.2ux %2.2ux\n", i8259mask, aux0, aux1); } | |
| 2001/0222/sys/src/9/pc/i8259.c:164,176 – 2001/0428/sys/src/9/pc/i8259.c:164,166 (short | long) | ||
|
remove i8259dump
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | ||
| 1998/0910 | return VectorPIC+irq; | |
| 1997/0327 | } | |
| 2001/0222 |
| |
| 2001/0428/sys/src/9/pc/i8259.c:95,101 – 2001/0527/sys/src/9/pc/i8259.c:95,101 (short | long) | ||
|
enable ELCR print
rsc Fri Mar 4 12:44:25 2005 | ||
| 1998/1022 | if(inb(Elcr1) == 0x20) | |
| 1999/0301 | i8259elcr = x; | |
| 1998/1022 | outb(Elcr1, x & 0xFF); | |
| 1999/0301 |
| |
| 2001/0527 | print("ELCR: %4.4uX\n", i8259elcr); | |
| 1998/1022 | } | |
| 1997/0327 | } | |
| 1998/0910 | iunlock(&i8259lock); | |
| 2001/0527/sys/src/9/pc/i8259.c:164,166 – 2001/0905/sys/src/9/pc/i8259.c:164,199 (short | long) | ||
|
add i8259disable, i8259vecno (new arch code? XXX)
rsc Fri Mar 4 12:44:25 2005 | ||
| 1997/0327 | ||
| 1998/0910 | return VectorPIC+irq; | |
| 1997/0327 | } | |
| 2001/0905 | 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<<irq; ilock(&i8259lock); if(!(i8259mask & irqbit)){ i8259mask |= irqbit; if(irq < 8) outb(Int0aux, i8259mask & 0xFF); else outb(Int1aux, (i8259mask>>8) & 0xFF); } iunlock(&i8259lock); return 0; } | |