注册 登录
编程论坛 操作系统内核开发

求助,关于AT兼容硬盘的写操作。

malpower 发布于 2010-07-10 00:49, 3510 次点击
小弟目前正在为内核编写驱动,在对AT硬盘进行写操作时出现了一些问题。
在我发出0x30命令后,一直不会出现中断。
不知是什么问题。
代码如下:

KRNL_HD_WriteSector:
    cli
    push ebp
    mov ebp,esp
    push eax
    push edx
    push ds
    mov ax,24
    mov ds,ax
    mov eax,dword[ebp+20]                        ;;要写入的数据的线性地址
    mov dword[dRwAddress],eax                        ;;将地址存入变量
    mov al,1
    mov byte[dRwSwitch],al                        ;;我的方向变量1表示写操作
    mov ax,0x1F2
    mov dx,ax
    mov al,1
    out dx,al
    inc dx
    mov al,byte[ebp+8]                           ;;扇区号参数
    out dx,al
    inc dx
    mov al,byte[ebp+12]                            ;;磁道号参数低8位
    out dx,al
    inc dx
    mov al,byte[ebp+13]                                ;;磁道号参数高8位
    out dx,al
    mov al,0xA0
    add al,byte[ebp+16]                                ;;磁头号参数
    inc dx
    out dx,al
    mov dx,0x1F7
    mov al,0x30
    out dx,al                                        ;;发出命令0x30(读带重试)
    pop ds
    pop edx
    pop eax
    pop ebp
    sti
    ret        
9 回复
#2
malpower2010-07-10 00:50
忘了说明:使用NASM编译器。
#3
chengstone2010-07-10 08:52
  if(blk_dev[HARD].current_request->cmd==WRITE)
  {
    hd_out(sub_dev,nsects,sect,head,cyl,WIN_WRITE,&write_hd);
          /*硬盘号 扇区数 起始扇区 磁头号 柱面号 0x30 硬盘中断将调用的函数指针(就是连续写)*/

    for(i=0;i<10000&&!(r=inb_p(HD_STATUS)&DRQ_STAT);i++);
    /*循环读取状态寄存器信息并判断请求服务标志DRQ_STAT (0x08)是否置位.DRQ_STAT是硬盘状态寄存器的请求服务位,表示驱动器已经准备好在主机和数据端口之间传输一个字或一个字节的数据.HD_STATUS=0x1f7*/
    if(!r) /*写盘命令失败*/
    {
      bad_intr();
      goto repeat;
    }                                             

    port_write(HD_DATA,blk_dev[HARD].current_request->buffer,256);  /*开始向硬盘写一扇区数据 硬盘中断开始*/
  }

这段代码是我使用的硬盘写操作
粗略看了一下KRNL_HD_WriteSector函数,感觉很像是上面的hd_out函数
光是这样是无法开始写的,必须要查询硬盘控制器的状态,然后将数据发送到硬盘数据端口才会产生中断

这部分建议你查看一下赵炯关于linux0.12内核的块设备部分的HD.C代码注释
#4
chengstone2010-07-10 09:09
另外 我很不看好NASM编译器哦
有一次我用NASM编译LOADER部分,刚跳转到保护模式下有一句代码NASM就翻译错了
;mov word [gs:ebx],ax   变成了mov dword ptr gs:[bp+di],eax
;mov word [gs:edi],ax   变成了mov dword ptr gs:[ebx],eax
;linux下变成了mov dword ptr gs:[bx],eax
;mov word [ds:edi],ax    这样就变成了mov dword ptr ds:[bx],eax
当时用BOCHS跟踪调试了半天才发现这句二进制与我的汇编指令不一致
于是为了要mov dword ptr ds:[bx],eax这句话的效果,只好把汇编指令改成了mov word [ds:edi],ax

本人才疏学浅,一致不明白为什么会出现这种情况 呵呵
所以现在很少用NASM了
#5
malpower2010-07-10 11:12
呵呵,我一直使用的 nasm啦,感觉还好。
大哥的意思是,除了发出命令以外还需要将一个数据写到0x1F0以后才会发生中断吗?
#6
chengstone2010-07-10 11:36
当然要向数据口写数据了 好像是以扇区为单位的 当写入一扇区数据后 硬盘控制器就启动中断了
我现在有点记不清了
#7
malpower2010-07-10 12:05
主要是我在做读扇区操作时,是发出了0x20命令后,硬盘完成寻道就发生中断,在中断处理程序里读取扇区的数据。
不知写操作是否类似。
#8
chengstone2010-07-10 12:13
应该是正相反 硬盘控制器将读到的一扇区数据放在数据口上 每读完一个扇区当然要产生中断通知CPU一个扇区读完了
写的时候 将一扇区数据发送到数据端口 当硬盘控制器写入一扇区数据后产生中断通知CPU写完了 如果还有数据的话重复操作将新的数据以扇区为单位发送到数据口 循环如此直到数据写完
#9
malpower2010-07-10 12:16
恍然大悟~~~~~~~~~~~
谢谢大哥指点~~~~~~
#10
woami662010-07-10 15:32
先寫數據後中斷,第一個扇區要先把數據寫上!
1