3 * 8259 programmable interrupt controller library.
4 * (C) 2009-2012 Jonathan Campbell.
5 * Hackipedia DOS library.
7 * This code is licensed under the LGPL.
8 * <insert LGPL legal text here>
10 * Compiles for intended target environments:
11 * - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box]
13 * In PC hardware the 8259 is responsible for taking IRQ signals off the ISA bus, prioritizing
14 * them, and interrupting the CPU to service the interrupts. The chip includes logic to keep
15 * track of what interrupts are pending, active, not yet acknowledged by the CPU, etc. so that
16 * the x86 CPU can properly handle them.
18 * In mid 1990s hardware the PIC was retained and often connected through a PCI core chipset
19 * that routed both ISA and PCI interrupts into it. Some chipsets have additional registers
20 * that allow "routing control", to determine whether a particular IRQ is to be associated
21 * with a PCI device or the ISA bus.
23 * Starting in late 1990s hardware, the APIC (Advanced Programmable Interrupt Controller)
24 * appeared on motherboards and was either put alongside with, or replaced, the traditional
25 * PIC. But the traditional I/O ports are emulated just the same to ensure compatibility with
26 * older software. Even today (in 2012) DOS programs can still communicate with I/O ports
27 * 20-21h and A0-A1h to manage interrupts, at least until an APIC aware OS or program takes
31 /* NTS: As of 2011/02/27 the 8254 routines no longer do cli/sti for us, we are expected
32 * to do them ourself. This is for performance reasons as well as for sanity reasons
33 * should we ever need to use the subroutines from within an interrupt handler */
36 #include <conio.h> /* this is where Open Watcom hides the outp() etc. functions */
42 #include "src/lib/doslib/8259.h"
44 unsigned char p8259_slave_present = 0;
45 signed char p8259_probed = 0;
47 void p8259_ICW(unsigned char a,unsigned char b,unsigned char c,unsigned char d) {
48 outp(p8259_irq_to_base_port(c,0),a | 0x10); /* D4 == 1 */
49 outp(p8259_irq_to_base_port(c,1),b);
50 outp(p8259_irq_to_base_port(c,1),c);
51 if (a & 1) outp(p8259_irq_to_base_port(c,1),d);
54 /* NTS: bit 7 is set if there was an interrupt */
55 /* WARNING: This code crashes DOSBox 0.74 with "PIC poll not handled" error message */
56 unsigned char p8259_poll(unsigned char c) {
57 /* issue poll command to read and ack an interrupt */
58 p8259_OCW3(c,0x0C); /* OCW3 = POLL=1 SMM=0 RR=0 */
59 return inp(p8259_irq_to_base_port(c,0));
63 unsigned char om,cm,c2;
67 return (int)p8259_probed;
69 /* don't let the BIOS fiddle with the mask during
70 the test. Fixes: Pentium machine where 1 out of
71 100 times programs fail with "cannot init PIC" */
72 flags = get_cpu_flags(); _cli();
73 om = p8259_read_mask(0);
74 p8259_write_mask(0,0xFF);
75 cm = p8259_read_mask(0);
76 p8259_write_mask(0,0x00);
77 c2 = p8259_read_mask(0);
78 p8259_write_mask(0,om);
81 if (cm != 0xFF || c2 != 0x00)
82 return (p8259_probed=0);
84 /* is a slave present too? */
85 flags = get_cpu_flags(); _cli();
86 om = p8259_read_mask(8);
87 p8259_write_mask(8,0xFF);
88 cm = p8259_read_mask(8);
89 p8259_write_mask(8,0x00);
90 c2 = p8259_read_mask(8);
91 p8259_write_mask(8,om);
94 if (cm == 0xFF && c2 == 0x00)
95 p8259_slave_present = 1;
97 return (p8259_probed=1);