uhci.control_transfer:除错误位外再比对 DATA TD 的 Actual Length(bit10:0)。短读时错误位可能全 0(QEMU/硬件不把短包当错误),只查错误位会漏 —— 现场是 USB 鼠标的 25 字节配置描述符只落下前 9 字节 ⇒ 接口解析为 0 ⇒ [usb_mse] no USB mouse found。 usb._parse_config 改为返回实际走完的偏移,enumerate_port 要求恰好走完 total_len,否则重读、仍不完整即报错返回(fail-fast,不带着半截描述符继续);同时删除两条探针。 keyboard.init/mouse.init 读-改-写 CCB 全程 pic.setMask(1):读 CCB 的 0x20 会把 CCB 值放进 0x60 输出缓冲并拉高 IRQ1,IRQ1 handler 会把它当扫描码抢走(现场 sc=0x47),使回读拿到残留值。改为只在校验失败时打印错误,去掉全部 [kbd] 探针。 清理已验证调试输出:idt 的 IRQ1 handler 探针及其计数器、desktop 的 [dbg] back_fb/row_buf/bg_row_buf、main 的 [DBG] LAPIC/idt32/swint/pic_isr 与 [DB] BootInfo 转储、timer 的 [PIT] 与自旋打印及随之无用的 import。
109 lines
3.5 KiB
Plaintext
109 lines
3.5 KiB
Plaintext
import platform.pch.pic as pic
|
||
import platform.pch.pit as pit
|
||
import sched.sched as sched
|
||
import drivers.core.cpu.apic as apic
|
||
import asm
|
||
|
||
|
||
define TIMER_FREQUENCY = 1000
|
||
define TICKS_PER_SECOND = TIMER_FREQUENCY
|
||
define MILLISECONDS_PER_TICK = (1000 / TIMER_FREQUENCY)
|
||
|
||
static ticks: volatile uint64 = 0
|
||
static seconds: volatile uint32 = 0
|
||
static milliseconds: volatile uint32 = 0
|
||
static timer_running: volatile bool = False
|
||
|
||
def timer_init():
|
||
global ticks, seconds, milliseconds, timer_running
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
ticks = 0
|
||
seconds = 0
|
||
milliseconds = 0
|
||
timer_running = True
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
pit.pit_init(TIMER_FREQUENCY)
|
||
|
||
def timer_handler():
|
||
global ticks, seconds, milliseconds, timer_running
|
||
if not timer_running:
|
||
pic.eoi(0)
|
||
apic.eoi()
|
||
return
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
ticks = ticks + 1
|
||
milliseconds = milliseconds + MILLISECONDS_PER_TICK
|
||
if milliseconds >= 1000:
|
||
seconds = seconds + 1
|
||
milliseconds = milliseconds - 1000
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
sched.Scheduler.sched_tick()
|
||
pic.eoi(0)
|
||
# LAPIC EOI:APIC 启用后中断经 LINT0(EXTINT) 送达会置 LAPIC ISR,
|
||
# 只发 PIC EOI 不清 LAPIC ISR → 首个定时中断后后续中断被屏蔽 →
|
||
# ticks 不推进 → msleep 永久挂起(QEMU/OVMF 下 APIC 必启用)。
|
||
apic.eoi()
|
||
|
||
def timer_start():
|
||
global timer_running
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
timer_running = True
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def timer_stop():
|
||
global timer_running
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
timer_running = False
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def timer_reset():
|
||
global ticks, seconds, milliseconds
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
ticks = 0
|
||
seconds = 0
|
||
milliseconds = 0
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def timer_get_ticks() -> uint64:
|
||
current_ticks: uint64
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
current_ticks = ticks
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
return current_ticks
|
||
|
||
def timer_get_seconds() -> uint32:
|
||
current_seconds: uint32
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
current_seconds = seconds
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
return current_seconds
|
||
|
||
def timer_get_milliseconds() -> uint32:
|
||
current_milliseconds: uint32
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
current_milliseconds = milliseconds
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
return current_milliseconds
|
||
|
||
def timer_get_time(out_seconds: uint32*, out_milliseconds: uint32*):
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
if out_seconds:
|
||
*out_seconds = seconds
|
||
if out_milliseconds:
|
||
*out_milliseconds = milliseconds
|
||
__asm__("mfence", op=[ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def timer_msleep(ms: uint32):
|
||
target: uint64 = ticks + (ms + MILLISECONDS_PER_TICK - 1) / MILLISECONDS_PER_TICK
|
||
while ticks < target:
|
||
asm.sti()
|
||
asm.hlt()
|
||
sched.Scheduler._yield()
|
||
|
||
def timer_sleep(sec: uint32):
|
||
target: uint64 = ticks + sec * TICKS_PER_SECOND
|
||
while ticks < target:
|
||
asm.sti()
|
||
asm.hlt()
|
||
sched.Scheduler._yield()
|