aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2012-03-30 14:44:03 -0700
committerH. Peter Anvin <hpa@zytor.com>2012-03-30 14:51:01 -0700
commitef1e15adc91cd0d26fe70df00ec7d94b1417fa87 (patch)
tree387825b52f601b616fa275f5ded13ceadeaef97f
parent6b6d07cc4afdb8f1bf56f44f3fee6f02a590bb84 (diff)
downloadsyslinux-ef1e15adc91cd0d26fe70df00ec7d94b1417fa87.tar.gz
syslinux-ef1e15adc91cd0d26fe70df00ec7d94b1417fa87.tar.xz
syslinux-ef1e15adc91cd0d26fe70df00ec7d94b1417fa87.zip
pxe: Unmask the cascade if applicable, handle bad IRQ numbers
IRQ 2 is really IRQ 9; if IRQ > 15 then it is meaningless. Also, since we enable the IRQ at the PIC "just in case", we might also have to enable the cascade for IRQ 8-15. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--core/fs/pxe/isr.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/core/fs/pxe/isr.c b/core/fs/pxe/isr.c
index 15287247..0c0b8991 100644
--- a/core/fs/pxe/isr.c
+++ b/core/fs/pxe/isr.c
@@ -21,7 +21,6 @@ static bool install_irq_vector(uint8_t irq, void (*isr)(void), far_ptr_t *old)
far_ptr_t *entry;
unsigned int vec;
uint8_t mask;
- uint16_t maskreg;
irq_state_t irqstate;
if (irq < 8)
@@ -38,10 +37,18 @@ static bool install_irq_vector(uint8_t irq, void (*isr)(void), far_ptr_t *old)
entry->ptr = (uint32_t)isr;
/* Enable this interrupt at the PIC level, just in case... */
- maskreg = 0x21 + ((irq & 8) << (7-3));
- mask = inb(maskreg);
- mask &= ~(1 << (irq & 3));
- outb(mask, maskreg);
+ if (irq >= 8) {
+ mask = inb(0x21);
+ mask &= ~(1 << 2); /* Enable cascade */
+ outb(mask, 0x21);
+ mask = inb(0xa1);
+ mask &= ~(1 << (irq & 3));
+ outb(0xa1, mask);
+ } else {
+ mask = inb(0x21);
+ mask &= ~(1 << (irq & 3));
+ outb(0x21, mask);
+ }
irq_restore(irqstate);
@@ -185,13 +192,19 @@ void pxe_init_isr(void)
*/
void pxe_start_isr(void)
{
- pxe_irq_vector = pxe_undi_info.IntNumber; /* Used in 16-bit code */
+ int irq = pxe_undi_info.IntNumber;
+
+ if (irq == 2)
+ irq = 9; /* IRQ 2 is really IRQ 9 */
+ else if (irq > 15)
+ irq = 0; /* Invalid IRQ */
+
+ pxe_irq_vector = irq;
- if (pxe_undi_info.IntNumber)
- install_irq_vector(pxe_undi_info.IntNumber, pxe_isr, &pxe_irq_chain);
+ if (irq)
+ install_irq_vector(irq, pxe_isr, &pxe_irq_chain);
- if (!pxe_undi_info.IntNumber ||
- !(pxe_undi_iface.ServiceFlags & PXE_UNDI_IFACE_FLAG_IRQ))
+ if (!irq || !(pxe_undi_iface.ServiceFlags & PXE_UNDI_IFACE_FLAG_IRQ))
poll_thread = start_thread("pxe poll", 4096, POLL_THREAD_PRIORITY,
pxe_poll_thread, NULL);
}
@@ -210,8 +223,8 @@ int reset_pxe(void)
if (undi_close.Status)
printf("PXENV_UNDI_CLOSE failed: 0x%x\n", undi_close.Status);
- if (pxe_undi_info.IntNumber)
- uninstall_irq_vector(pxe_undi_info.IntNumber, pxe_isr, &pxe_irq_chain);
+ if (pxe_irq_vector)
+ uninstall_irq_vector(pxe_irq_vector, pxe_isr, &pxe_irq_chain);
if (poll_thread)
kill_thread(poll_thread);