OSDN Git Service

wwww
[proj16/16.git] / src / lib / doslib / 8259.h
1 /* 8259.h
2  *
3  * 8259 programmable interrupt controller library.
4  * (C) 2009-2012 Jonathan Campbell.
5  * Hackipedia DOS library.
6  *
7  * This code is licensed under the LGPL.
8  * <insert LGPL legal text here>
9  *
10  * Compiles for intended target environments:
11  *   - MS-DOS [pure DOS mode, or Windows or OS/2 DOS Box] */
12
13 #ifndef __HW_8259_8259_H
14 #define __HW_8259_8259_H
15
16 #include "src/lib/doslib/cpu.h"
17 #include <stdint.h>
18
19 /* PIC hardware register description
20  *
21  *    ICW1        I/O port base + 0  (NTS: bit D4 == 1 when writing this)
22  *    ICW2        I/O port base + 1
23  *    ICW3        I/O port base + 1
24  *    ICW4        I/O port base + 1
25  *
26  *    OCW1        R/W interrupt mask register. setting the bit masks the interrupt. Use I/O port base + 0
27  *    OCW2        R/? EOI and rotate command opcodes (NTS: bit D3-4 == 0). I/O port base + 1
28  *    OCW3        R/? poll/read/etc command opcodes (NTS: bit D3-4 == 1) I/O port base + 1
29  *
30  */
31 /* PIC library warning:
32  *
33  * For performance and sanity reasons this code does NOT mask interrupts during the function. You are
34  * expected to wrap your calls with cli/sti functions. Though it is unlikely, leaving interrupts enabled
35  * while doing this can cause problems in case the BIOS fiddles with the PIC during an IRQ */
36
37 #define P8259_MASTER_DATA               0x20
38 #define P8259_MASTER_MASK               0x21
39
40 #define P8259_SLAVE_DATA                0xA0
41 #define P8259_SLAVE_MASK                0xA1
42
43 /* OCW2 command bits. For most commands you are expected to OR the low 3 bits with the IRQ for the command to take effect on */
44 #define P8259_OCW2_ROTATE_AUTO_EOI_CLEAR        (0U << 5U)
45 #define P8259_OCW2_NON_SPECIFIC_EOI             (1U << 5U)
46 #define P8259_OCW2_NO_OP                        (2U << 5U)
47 #define P8259_OCW2_SPECIFIC_EOI                 (3U << 5U)
48 #define P8259_OCW2_ROTATE_AUTO_EOI_SET          (4U << 5U)
49 #define P8259_OCW2_ROTATE_NON_SPECIFIC_EOI      (5U << 5U)
50 #define P8259_OCW2_SET_PRIORITY                 (6U << 5U)
51 #define P8259_OCW2_ROTATE_SPECIFIC_EOI          (7U << 5U)
52
53 #define P8259_MASK_BIT(x)               (1U << ((x)&7U))
54
55 extern unsigned char p8259_slave_present;
56
57 /* c = IRQ  which = I/O port */
58 static inline unsigned char p8259_irq_to_base_port(unsigned char c,unsigned char which) {
59         return ((c & 8) ? P8259_SLAVE_DATA : P8259_MASTER_DATA) + which;
60 }
61
62 /* c = IRQ. */
63 static inline unsigned char p8259_read_mask(unsigned char c) { /* mask register AKA OCW1 */
64         outp(p8259_irq_to_base_port(c,0),P8259_OCW2_NO_OP); /* issue NO-OP to make sure the PIC is ready to accept OCW1 */
65         return inp(p8259_irq_to_base_port(c,1)); /* mask register */
66 }
67
68 static inline void p8259_write_mask(unsigned char c,unsigned char m) { /* mask register AKA OCW1 */
69         outp(p8259_irq_to_base_port(c,0),P8259_OCW2_NO_OP); /* issue NO-OP to make sure the PIC is ready to accept OCW1 */
70         outp(p8259_irq_to_base_port(c,1),m); /* write mask register */
71 }
72
73 static inline void p8259_OCW2(unsigned char c,unsigned char w) {
74         outp(p8259_irq_to_base_port(c,0),w & 0xE7);     /* D3-4 == 0 */
75 }
76
77 static inline void p8259_OCW3(unsigned char c,unsigned char w) {
78         outp(p8259_irq_to_base_port(c,0),(w & 0xE7) | 0x08);    /* D3-4 == 1 */
79 }
80
81 static inline unsigned char p8259_read_IRR(unsigned char c) {
82         p8259_OCW3(c,0x02);     /* OCW3 = read register command RR=1 RIS=0 */
83         return inp(p8259_irq_to_base_port(c,0)); /* mask register */
84 }
85
86 static inline unsigned char p8259_read_ISR(unsigned char c) {
87         p8259_OCW3(c,0x03);     /* OCW3 = read register command RR=1 RIS=1 */
88         return inp(p8259_irq_to_base_port(c,0)); /* mask register */
89 }
90
91 static inline unsigned char irq2int(unsigned char c) {
92         c &= 0xF;
93         if (c & 8) return c-8+0x70;
94         return c+0x08;
95 }
96
97 static inline void p8259_unmask(unsigned char c) {
98         unsigned char m = p8259_read_mask(c);
99         p8259_write_mask(c,m & ~(1 << (c&7)));
100 }
101
102 static inline void p8259_mask(unsigned char c) {
103         unsigned char m = p8259_read_mask(c);
104         p8259_write_mask(c,m | (1 << (c&7)));
105 }
106
107 static inline unsigned char p8259_is_masked(unsigned char c) {
108         return (p8259_read_mask(c) & (1 << (c&7)));
109 }
110
111 void p8259_ICW(unsigned char a,unsigned char b,unsigned char c,unsigned char d);
112 unsigned char p8259_poll(unsigned char c);
113 int probe_8259();
114
115 #endif /* __HW_8259_8259_H */
116