Files
ViperOS/VKernel/Kernel/platform/pch/pic.vp
T
TermiNexus dcb7c5c2c0 chore(ViperOS): 落库内核侧进行中的改动(26 文件,+1573/-1805)
内容由用户产出,本次仅代为提交、未做任何语义修改;含 static 修饰符前置迁移等(新增 static 前缀 16 行)。提交消息为中性描述——如需更精确的说明请 amend。
2026-09-28 15:24:52 +08:00

120 lines
3.6 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import asm
# PIC端口定义
define PIC1_COMMAND = 0x20
define PIC1_DATA = 0x21
define PIC2_COMMAND = 0xA0
define PIC2_DATA = 0xA1
# ICW1 - 初始化命令字1
define ICW1_ICW4 = 0x01 # 需要ICW4
define ICW1_SINGLE = 0x02 # 单级模式
define ICW1_INTERVAL4 = 0x04 # 间隔4字节
define ICW1_LEVEL = 0x08 # 电平触发模式
define ICW1_INIT = 0x10 # 初始化
# ICW4 - 初始化命令字4
define ICW4_8086 = 0x01 # 8086/88模式
define ICW4_AUTO = 0x02 # 自动EOI
define ICW4_BUF_SLAVE = 0x08 # 缓冲模式(从片)
define ICW4_BUF_MASTER = 0x0C # 缓冲模式(主片)
define ICW4_SFNM = 0x10 # 特殊全嵌套模式
# OCW2 - 操作命令字2
define OCW2_EOI = 0x20 # 结束中断
# OCW3 - 操作命令字3
define OCW3_READ_ISR = 0x0B # 读取中断服务寄存器(ISR)
# 初始化PIC
def init():
# 发送ICW1:开始初始化,需要ICW4
asm.outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4)
asm.io_wait()
asm.outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4)
asm.io_wait()
# 发送ICW2:中断向量偏移
asm.outb(PIC1_DATA, 0x20) # IRQ0-7映射到0x20-0x27
asm.io_wait()
asm.outb(PIC2_DATA, 0x28) # IRQ8-15映射到0x28-0x2F
asm.io_wait()
# 发送ICW3:级联信息
asm.outb(PIC1_DATA, 0x04) # 主PIC的IRQ2连接从PIC
asm.io_wait()
asm.outb(PIC2_DATA, 0x02) # 从PIC连接到主PIC的IRQ2
asm.io_wait()
# 发送ICW4:8086模式
asm.outb(PIC1_DATA, ICW4_8086)
asm.io_wait()
asm.outb(PIC2_DATA, ICW4_8086)
asm.io_wait()
# 设置初始屏蔽字:只启用IRQ0(定时器)、IRQ1(键盘)、IRQ2(级联)
# 主PIC: 屏蔽所有除了IRQ0, IRQ1, IRQ2 (0xF8 = 11111000)
# 从PIC: 屏蔽所有 (0xFF = 11111111),鼠标中断由驱动程序自己启用
asm.outb(PIC1_DATA, 0xF8) # 启用IRQ0, IRQ1, IRQ2
asm.io_wait()
asm.outb(PIC2_DATA, 0xFF) # 屏蔽所有从PIC中断
asm.io_wait()
# 发送EOI信号
def eoi(irq: uint8):
if irq >= 8: asm.outb(PIC2_COMMAND, OCW2_EOI)
asm.outb(PIC1_COMMAND, OCW2_EOI)
# 检查是否是虚假中断(spurious interrupt)
# 返回 1 表示是虚假中断,0 表示是真实中断
def isSpurious(irq: int) -> int:
# 边界检查
if irq < 0 or irq > 15: return 0
isr: uint8
if irq < 8:
# 发送OCW3,读取ISR(Interrupt Service Register)
asm.outb(PIC1_COMMAND, OCW3_READ_ISR)
asm.io_wait()
isr = asm.inb(PIC1_COMMAND)
# 如果ISR中对应位为0,说明是虚假中断
return not (isr & (1 << irq))
else:
# 发送OCW3,读取从PIC的ISR
asm.outb(PIC2_COMMAND, OCW3_READ_ISR)
asm.io_wait()
isr = asm.inb(PIC2_COMMAND)
# 如果ISR中对应位为0,说明是虚假中断
return not (isr & (1 << (irq - 8)))
# 设置IRQ屏蔽
def setMask(irq: uint8):
# 边界检查
if irq > 15: return
port: uint16
value: uint8
if irq < 8:
port = PIC1_DATA
else:
port = PIC2_DATA
irq -= 8
value = asm.inb(port) | (1 << irq)
asm.outb(port, value)
asm.io_wait() # 确保命令生效
# 清除IRQ屏蔽
def clearMask(irq: uint8):
# 边界检查
if irq > 15: return
port: uint16
value: uint8
if irq < 8:
port = PIC1_DATA
else:
port = PIC2_DATA
irq -= 8
value = asm.inb(port) & ~(1 << irq)
asm.outb(port, value)
asm.io_wait() # 确保命令生效