xref: /minix/minix/kernel/arch/i386/i8259.c (revision 83133719)
1 /* This file contains routines for initializing the 8259 interrupt controller:
2  *	put_irq_handler: register an interrupt handler
3  *	rm_irq_handler: deregister an interrupt handler
4  *	intr_handle:	handle a hardware interrupt
5  *	intr_init:	initialize the interrupt controller(s)
6  */
7 
8 #include "kernel/kernel.h"
9 #include "arch_proto.h"
10 #include "hw_intr.h"
11 #include <minix/portio.h>
12 #include <machine/cpu.h>
13 
14 #define ICW1_AT         0x11	/* edge triggered, cascade, need ICW4 */
15 #define ICW1_PC         0x13	/* edge triggered, no cascade, need ICW4 */
16 #define ICW1_PS         0x19	/* level triggered, cascade, need ICW4 */
17 #define ICW4_AT_SLAVE   0x01	/* not SFNM, not buffered, normal EOI, 8086 */
18 #define ICW4_AT_MASTER  0x05	/* not SFNM, not buffered, normal EOI, 8086 */
19 #define ICW4_PC_SLAVE   0x09	/* not SFNM, buffered, normal EOI, 8086 */
20 #define ICW4_PC_MASTER  0x0D	/* not SFNM, buffered, normal EOI, 8086 */
21 #define ICW4_AT_AEOI_SLAVE   0x03 /* not SFNM, not buffered, auto EOI, 8086 */
22 #define ICW4_AT_AEOI_MASTER  0x07 /* not SFNM, not buffered, auto EOI, 8086 */
23 #define ICW4_PC_AEOI_SLAVE   0x0B /* not SFNM, buffered, auto EOI, 8086 */
24 #define ICW4_PC_AEOI_MASTER  0x0F /* not SFNM, buffered, auto EOI, 8086 */
25 
26 /*===========================================================================*
27  *				intr_init				     *
28  *===========================================================================*/
29 int intr_init(const int auto_eoi)
30 {
31 /* Initialize the 8259s, finishing with all interrupts disabled.  */
32       outb( INT_CTL, ICW1_AT);
33       outb( INT_CTLMASK, IRQ0_VECTOR);
34 					/* ICW2 for master */
35       outb( INT_CTLMASK, (1 << CASCADE_IRQ));
36 					/* ICW3 tells slaves */
37       if (auto_eoi)
38           outb( INT_CTLMASK, ICW4_AT_AEOI_MASTER);
39       else
40           outb( INT_CTLMASK, ICW4_AT_MASTER);
41       outb( INT_CTLMASK, ~(1 << CASCADE_IRQ)); /* IRQ 0-7 mask */
42       outb( INT2_CTL, ICW1_AT);
43       outb( INT2_CTLMASK, IRQ8_VECTOR);
44 						/* ICW2 for slave */
45       outb( INT2_CTLMASK, CASCADE_IRQ);	/* ICW3 is slave nr */
46       if (auto_eoi)
47          outb( INT2_CTLMASK, ICW4_AT_AEOI_SLAVE);
48       else
49          outb( INT2_CTLMASK, ICW4_AT_SLAVE);
50       outb( INT2_CTLMASK, ~0);		/* IRQ 8-15 mask */
51 
52   return OK;
53 }
54 
55 void irq_8259_unmask(const int irq)
56 {
57 	const unsigned ctl_mask = irq < 8 ? INT_CTLMASK : INT2_CTLMASK;
58 	outb(ctl_mask, inb(ctl_mask) & ~(1 << (irq & 0x7)));
59 }
60 
61 void irq_8259_mask(const int irq)
62 {
63 	const unsigned ctl_mask = irq < 8 ? INT_CTLMASK : INT2_CTLMASK;
64 	outb(ctl_mask, inb(ctl_mask) | (1 << (irq & 0x7)));
65 }
66 
67 /* Disable 8259 - write 0xFF in OCW1 master and slave. */
68 void i8259_disable(void)
69 {
70 	outb(INT2_CTLMASK, 0xFF);
71 	outb(INT_CTLMASK, 0xFF);
72 	inb(INT_CTLMASK);
73 }
74 
75 void irq_8259_eoi(int irq)
76 {
77 	if (irq < 8)
78 		eoi_8259_master();
79 	else
80 		eoi_8259_slave();
81 }
82