forked from SanseroGames/LetsGo-OS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpic.go
117 lines (98 loc) · 2.35 KB
/
pic.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main
const (
PIC_PRINT_DEBUG = ENABLE_DEBUG
PIC1Port uint16 = 0x20
PIC1Data uint16 = PIC1Port + 1
PIC2Port uint16 = 0xA0
PIC2Data uint16 = PIC2Port + 1
PIC1Offset byte = 0x20
PIC2Offset byte = 0x28
PIC_ICW1_ICW4 byte = 0x01 // ICW4 will be sent
PIC_ICW1_Init byte = 0x10
PIC_ICW4_8086 byte = 0x01 // Set 8086/88 mode. unset MCS-80/85 mode
PIC_EOI byte = 0x20 // End of interrupt
PIC_ReadIRR byte = 0xa
PIC_ReadISR byte = 0xb
)
var picHandlers [16]func()
func PICInterruptHandler() {
info := ¤tThread.info
if currentThread.isKernelInterrupt {
info = ¤tThread.kernelInfo
}
irq := info.InterruptNumber - uint32(PIC1Offset)
if irq == 7 {
Outb(PIC1Port, PIC_ReadISR)
res := Inb(PIC1Port)
if res&(1<<7) == 0 {
// Spurious IRQ
return
}
}
if irq == 15 {
Outb(PIC1Port, PIC_ReadISR)
res := Inb(PIC1Port)
if res&(1<<7) == 0 {
// Spurious IRQ
// PIC1 does not know it is spurious
Outb(PIC1Port, PIC_EOI)
return
}
}
if PIC_PRINT_DEBUG && irq != 0 {
kdebugln("[PIC] Handler nr ", irq)
}
picHandlers[irq]()
if irq >= 8 {
Outb(PIC2Port, PIC_EOI)
}
Outb(PIC1Port, PIC_EOI)
}
func defaultPicHandler() {
kerrorln("Unhandled IRQ")
}
func InitPIC() {
Outb(PIC1Port, PIC_ICW1_Init|PIC_ICW1_ICW4)
Outb(PIC2Port, PIC_ICW1_Init|PIC_ICW1_ICW4)
Outb(PIC1Data, PIC1Offset)
Outb(PIC2Data, PIC2Offset)
Outb(PIC1Data, 0b0100) // Tells PIC1 that there is slave PIC at IRQ2
Outb(PIC2Data, 2) // Tells slave PIC what IRQ it is on master PIC (binary form)
Outb(PIC1Data, PIC_ICW4_8086)
Outb(PIC2Data, PIC_ICW4_8086)
Outb(PIC1Data, 0xff)
Outb(PIC2Data, 0xff)
for i := 0; i < 8; i++ {
SetInterruptHandler(PIC1Offset+byte(i), PICInterruptHandler, KCS_SELECTOR, PRIV_USER)
}
for i := 0; i < 8; i++ {
SetInterruptHandler(PIC2Offset+byte(i), PICInterruptHandler, KCS_SELECTOR, PRIV_USER)
}
for i := range picHandlers {
RegisterPICHandler(uint8(i), defaultPicHandler)
}
}
func DisableIRQ(irq uint8) {
port := PIC1Data
if irq > 7 {
port = PIC2Data
irq -= 8
}
value := Inb(port) | (1 << irq)
Outb(port, value)
}
func EnableIRQ(irq uint8) {
port := PIC1Data
if irq > 7 {
port = PIC2Data
irq -= 8
}
value := Inb(port) &^ (1 << irq)
Outb(port, value)
}
func RegisterPICHandler(irq uint8, f func()) {
if irq > 15 {
kernelPanic("[PIC] The requested irq does not exist")
}
picHandlers[irq] = f
}