You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ATA驱动卡在DRQ等待循环,Grub引导自制OS故障排查

ATA驱动在Grub引导下卡在等待DRQ的问题

我编写了一个超简易操作系统,改用Grub引导后,ATA驱动无法正常工作,卡在等待DRQ的环节。该驱动在旧Bootloader下可正常工作,因此问题大概率和Grub引导有关。目前IDT沿用旧Bootloader的,GDT采用某视频中的配置,中断功能正常(除零异常、键盘输入均无问题),仅ATA驱动出现故障。

相关代码

错误的DRQ等待函数

void ATA_wait_DRQ() // Wait fot drq to be 1
{
    while (!(insb(0x1F7) & STATUS_RDY))
        ;
}

扇区读取函数

int disk_read_sector(int lba, void *buf)
{
    ATA_wait_BSY();
    print("f1");
    ATA_wait_DRQ(); // estes dois nao estavam aqui antes pus so pq no write tive de por
    print("f2");

    lba = lba + OS_SECTORS + HEADER_SECTORS;
    outb(0x1F6, (lba >> 24) | 0xE0);
    outb(0x1F2, 1);
    outb(0x1F3, (unsigned char)(lba & 0xff));
    outb(0x1F4, (unsigned char)(lba >> 8));
    outb(0x1F5, (unsigned char)(lba >> 16));
    outb(0x1F7, 0x20);

    unsigned short *ptr = (unsigned short *)buf;

    ATA_wait_BSY();
    ATA_wait_DRQ();

    for (int i = 0; i < 256; i++)
    {
        *ptr = insw(0x1F0);
        ptr++;
    }

    return 0;
}

状态检查函数及现象

void checkPort()
{
    char a = insb(0x1F7);
    a = a + 48;
    write_char_pos(5, 5, a, 0x00ff00);
    if (a == '0')
    {
        char b = insb(0x1F1);
        b = b + 48;
        write_char_pos(6, 6, a, 0x00ff00);
    }
}

执行该函数后,(5,5)和(6,6)位置均输出'0',判断磁盘控制器出现错误。

问题分析与修复方案

  1. DRQ等待函数逻辑错误
    函数注释是等待DRQ置位,但实际判断的是STATUS_RDY(就绪位,第6位0x40),而DRQ对应的是状态寄存器的第3位(0x08)。修正后的函数:

    #define STATUS_DRQ 0x08
    void ATA_wait_DRQ() // 等待DRQ置位
    {
        while (!(insb(0x1F7) & STATUS_DRQ))
            ;
    }
    
  2. 错误的等待时机
    发送读取命令前调用ATA_wait_DRQ完全不合理——DRQ位只有磁盘准备好传输数据时才会置位,应该在发送读取命令后再等待DRQ。去掉发送命令前的ATA_wait_DRQ调用即可。

  3. LBA地址验证
    检查OS_SECTORS和HEADER_SECTORS的偏移值在Grub引导环境下是否依然正确,错误的LBA地址会导致磁盘控制器无法定位扇区,进而触发错误状态。

  4. 控制器状态确认
    Grub可能已初始化过ATA控制器,导致其状态与旧Bootloader环境不同。可以在驱动初始化时重新重置控制器,确保进入正确的PIO工作模式。

内容的提问来源于stack exchange,提问作者Rabyt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 05:53:11