fix(vkernel/ide): PIO 命令块寄存器连写补 io_wait + 读完核 ERR - 修读盘读错扇区(根目录扇区读回 ELF 头致 app spawn 失败)
This commit is contained in:
1 parent
2eea065a67
commit
0ee5ec5dcc
1 file changed
+22
@@ -70,17 +70,30 @@ def readSector(lba: uint32, buffer: rawptr) -> int:
|
||||
if err != IDError.IDE_ERR_NONE:
|
||||
return err
|
||||
asm.outb(0x3F6, 0x00)
|
||||
asm.io_wait()
|
||||
# 命令块寄存器**连写之间必须插 I/O 延时**:QEMU 的 IDE 是逐条采样寄存器的,缺延时
|
||||
# 会出现"只写入部分寄存器"⇒ LBA 保留上一次的值 ⇒ 读到**另一个扇区**的数据(现场:
|
||||
# 读根目录扇区 LBA 8192 却读回 ELF 文件头,导致目录项全是垃圾 → spawn 失败)。
|
||||
asm.outb(0x1F2, 1)
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F3, uint8(lba & 0xFF))
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F4, uint8((lba >> 8) & 0xFF))
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F5, uint8((lba >> 16) & 0xFF))
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F6, uint8(0xE0 | ((lba >> 24) & 0x0F)))
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F7, 0x20)
|
||||
asm.io_wait()
|
||||
err = waitDataReady(IDE_baseport_PRIMARY)
|
||||
if err != IDError.IDE_ERR_NONE:
|
||||
st: uint8 = asm.inb(0x1F7)
|
||||
return err
|
||||
st2: uint8 = asm.inb(0x1F7)
|
||||
# 读完再核一次 ERR:置位说明这次数据无效,不能当成功返回(否则上层会拿到错内容)
|
||||
if st2 & IDE_STATUS_ERR:
|
||||
return IDError.IDE_ERR_DEVICE_ERROR
|
||||
buf: uint16* = uint16*(buffer)
|
||||
for j in range(256):
|
||||
*buf = asm.inw(0x1F0)
|
||||
@@ -96,12 +109,21 @@ def writeSector(lba: uint32, buffer: const rawptr) -> int:
|
||||
err: IDError = waitReady(IDE_baseport_PRIMARY)
|
||||
if err != IDError.IDE_ERR_NONE: return err
|
||||
asm.outb(0x3F6, 0x00)
|
||||
asm.io_wait()
|
||||
# 与 readSector 同理:命令块寄存器连写之间必须插 I/O 延时,否则 QEMU 只采样到部分寄存器
|
||||
# ⇒ LBA 残留旧值 ⇒ 把数据写到**错误的扇区**(写盘路径同样致命)。
|
||||
asm.outb(0x1F2, 1)
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F3, uint8(lba & 0xFF))
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F4, uint8((lba >> 8) & 0xFF))
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F5, uint8((lba >> 16) & 0xFF))
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F6, uint8(0xE0 | ((lba >> 24) & 0x0F)))
|
||||
asm.io_wait()
|
||||
asm.outb(0x1F7, 0x30)
|
||||
asm.io_wait()
|
||||
err = waitDataReady(IDE_baseport_PRIMARY)
|
||||
if err != IDError.IDE_ERR_NONE: return err
|
||||
buf: uint16* = uint16*(buffer)
|
||||
|
||||
Reference in new issue
Block a user