1 /*
2  * Basic support for controlling the 8259 Programmable Interrupt Controllers.
3  *
4  * Initially written by Michael Brown (mcb30).
5  */
6 
7 #ifndef PIC8259_H
8 #define PIC8259_H
9 
10 /* For segoff_t */
11 #include <segoff.h>
12 
13 #define IRQ_PIC_CUTOFF (8)
14 
15 /* 8259 register locations */
16 #define PIC1_ICW1 (0x20)
17 #define PIC1_OCW2 (0x20)
18 #define PIC1_OCW3 (0x20)
19 #define PIC1_ICR (0x20)
20 #define PIC1_IRR (0x20)
21 #define PIC1_ISR (0x20)
22 #define PIC1_ICW2 (0x21)
23 #define PIC1_ICW3 (0x21)
24 #define PIC1_ICW4 (0x21)
25 #define PIC1_IMR (0x21)
26 #define PIC2_ICW1 (0xa0)
27 #define PIC2_OCW2 (0xa0)
28 #define PIC2_OCW3 (0xa0)
29 #define PIC2_ICR (0xa0)
30 #define PIC2_IRR (0xa0)
31 #define PIC2_ISR (0xa0)
32 #define PIC2_ICW2 (0xa1)
33 #define PIC2_ICW3 (0xa1)
34 #define PIC2_ICW4 (0xa1)
35 #define PIC2_IMR (0xa1)
36 
37 /* Register command values */
38 #define OCW3_ID (0x08)
39 #define OCW3_READ_IRR (0x03)
40 #define OCW3_READ_ISR (0x02)
41 #define ICR_EOI_NON_SPECIFIC (0x20)
42 #define ICR_EOI_NOP (0x40)
43 #define ICR_EOI_SPECIFIC (0x60)
44 #define ICR_EOI_SET_PRIORITY (0xc0)
45 
46 /* Macros to enable/disable IRQs */
47 #define IMR_REG(x) ( (x) < IRQ_PIC_CUTOFF ? PIC1_IMR : PIC2_IMR )
48 #define IMR_BIT(x) ( 1 << ( (x) % IRQ_PIC_CUTOFF ) )
49 #define irq_enabled(x) ( ( inb ( IMR_REG(x) ) & IMR_BIT(x) ) == 0 )
50 #define enable_irq(x) outb ( inb( IMR_REG(x) ) & ~IMR_BIT(x), IMR_REG(x) )
51 #define disable_irq(x) outb ( inb( IMR_REG(x) ) | IMR_BIT(x), IMR_REG(x) )
52 
53 /* Macros for acknowledging IRQs */
54 #define ICR_REG(x) ( (x) < IRQ_PIC_CUTOFF ? PIC1_ICR : PIC2_ICR )
55 #define ICR_VALUE(x) ( (x) % IRQ_PIC_CUTOFF )
56 #define CHAINED_IRQ 2
57 
58 /* Utility macros to convert IRQ numbers to INT numbers and INT vectors  */
59 #define IRQ_INT(x) ( (x)<IRQ_PIC_CUTOFF ? (x)+0x08 : (x)-IRQ_PIC_CUTOFF+0x70 )
60 #define INT_VECTOR(x) ( (segoff_t*) phys_to_virt( 4 * (x) ) )
61 #define IRQ_VECTOR(x) ( INT_VECTOR ( IRQ_INT(x) ) )
62 
63 /* Other constants */
64 typedef uint8_t irq_t;
65 #define IRQ_MAX (15)
66 #define IRQ_NONE (0xff)
67 
68 /* Labels in assembly code (asm.S)
69  */
70 extern void _undi_irq_handler_start;
71 extern void _undi_irq_handler ( void );
72 extern volatile uint16_t _undi_irq_trigger_count;
73 extern volatile uint16_t _undi_irq_fail_count;
74 extern volatile uint16_t _undi_irq_not_ours_count;
75 extern segoff_t _undi_irq_chain_to;
76 extern uint8_t _undi_irq_chain;
77 extern uint8_t _pxenv_undi_irq;
78 extern segoff_t _pxenv_undi_entrypointsp;
79 
80 /* Function prototypes
81  */
82 int install_irq_handler ( irq_t irq, segoff_t *handler,
83 			  uint8_t *previously_enabled,
84 			  segoff_t *previous_handler );
85 int remove_irq_handler ( irq_t irq, segoff_t *handler,
86 			 uint8_t *previously_enabled,
87 			 segoff_t *previous_handler );
88 int install_undi_irq_handler ( irq_t irq, segoff_t );
89 int remove_undi_irq_handler ( irq_t irq );
90 int undi_irq_triggered ( irq_t irq );
91 void send_specific_eoi ( irq_t irq );
92 #ifdef DEBUG_IRQ
93 void dump_irq_status ( void );
94 #else
95 #define dump_irq_status()
96 #endif
97 
98 #endif /* PIC8259_H */
99