读/写硬盘数据的过程

读数据

1.系统调用hd_out函数向硬盘控制器发送写命令
向硬盘控制器发送命令块。
// 调用参数:drive - 硬盘号(0-1); nsect - 读写扇区数;
// sect - 起始扇区; head - 磁头号;
// cyl - 柱面号; cmd - 命令码(读/写);
// *intr_addr() - 硬盘中断处理程序中将调用的C 处理函数。
static void hd_out (unsigned int drive, unsigned int nsect, unsigned int sect,
                  unsigned int head, unsigned int cyl, unsigned int cmd,
                  void (*intr_addr) (void))
{
  register int port asm ("dx");       // port 变量对应寄存器dx。

  if (drive > 1 || head > 15)   // 如果驱动器号(0,1)>1 或磁头号>15,则程序不支持。
    panic ("Trying to write bad sector");
  if (!controller_ready ())     // 如果等待一段时间后仍未就绪则出错,死机。
    panic ("HD controller not ready");
  do_hd = intr_addr;            // do_hd 函数指针将在硬盘中断程序中被调用。
  outb_p (hd_info[drive].ctl, HD_CMD);    // 向控制寄存器(0x3f6)输出控制字节。
  port = HD_DATA;             // 置dx 为数据寄存器端口(0x1f0)。
  outb_p (hd_info[drive].wpcom >> 2, ++port); // 参数:写预补偿柱面号(需除4)。
  outb_p (nsect, ++port);     // 参数:读/写扇区总数。
  outb_p (sect, ++port);       // 参数:起始扇区。
  outb_p (cyl, ++port);        // 参数:柱面号低8 位。
  outb_p (cyl >> 8, ++port); // 参数:柱面号高8 位。
  outb_p (0xA0 | (drive     // 参数:驱动器号+磁头号。
  outb (cmd, ++port);          // 命令:硬盘控制命令。
}

这个函数的作用就是把要读取的drive - 硬盘号(0-1)、 nsect - 读写扇区数、sect - 起始扇区、 head - 磁头号、cyl - 柱面号、cmd - 命令码(读/写)都通过端口发送到硬盘控制器去。就是相当于系统向硬盘发出了读取数据的通知。当这个函数运行结束后就返回了,接下下的读数据的工作交给硬盘控制器。如果读取数据成功,那么数据会被放到硬盘控制器的一个缓冲区中。当然由于一些原因,硬盘控制器和硬盘也有可能读取数据失败。无论是以失败还是成功结束读取操作,硬盘控制器都会通知操作系统。通知操作系统的方式是通过中断(这个中断是外部中断由硬盘控制器触发中断控制器8259产生的)。中断的处理函数就是intr_addr参数 这是一个函数指针,如果中读操作intr_addr参数就会被值为read_intr()如果是写操作intr_addr参数就会被值为write_intr()。硬盘中断处理程序中将调用的C 处理函数。这里说的是读,那么intr_addr参数就被值为read_intr()。
下面就简单的来说一下static void 
read_intr
(void)在这个函数中必须判断读硬盘操作是成功了,失败了。static void 
read_intr
(void)会去调用
static int 
win_result
(void)函数的检测读操作是否成功。这里也插入讲一下static int 
win_result
(void)函数是如何来检测的。
static int 
win_result
(void)
{
         int i=
inb_p
(
HD_STATUS
);
         if ((i & (
BUSY_STAT

READY_STAT

WRERR_STAT

SEEK_STAT

ERR_STAT
))
                == (
READY_STAT

SEEK_STAT
))
                 return(0); /* ok */
         if (i&1) i=
inb
(
HD_ERROR
);
         return (1);
}
从代码来看,这个函数就是读硬盘控制和CPU引脚相连接的端口
HD_STATUS
。硬盘控制器在读写结束后就会设置这个读写状态端口的值。这个端口的值描述了读写操作是以成功还是失败结束的。当然通过判断这个端口的值就可以知道读写操作是成功了还是失败了。从static int 
win_result
(void)返回0是成功的,1是失败的。

static void 
read_intr
(void)调用static int 
win_result
(void)函数调用这个函数检测到读硬盘失败后会尝试几次再读硬盘,几次都失败后才“判刑”是失败。如果检测到读操作成功,说明硬盘控制器已经把数据从硬盘里读出来了,并且数据已放到了硬盘控制器的缓冲区中去,这时static void 
read_intr
(void)调用就会调用这个宏
port_read
(port,
buf
,nr),把数据从硬盘控制器的缓冲区中读到系统的缓冲区中去。
#define 
port_read
(port,
buf
,nr) \
__asm__("cld;rep;insw"::"d" (port),"D" (
buf
),"c" (nr):"cx","di")
这个宏就很简单了,就是把port端口的nr个字(2 bytes)读到buf缓冲区中。这个port就是硬盘控制器的缓冲区,而buf则是系统的缓冲区。最后读硬盘操作结束后
static void 
read_intr
(void)调用static void 
end_request
(int uptodate)函数的做一些后期处理的工作。static void 
end_request
(int uptodate)函数的作用是检测uptodate参数,uptodate = 1说明读写硬盘的操作成功 = 0为读写失败。如果读写失败了就会打印出错的信息。然后把当前的硬盘读写请求项指向下一下请求项。如果读写成功就不打印任何信息,直接把当前的硬盘读写请求项指向下一下请求项。
最后static void 
read_intr
(void)调用static void 
do_hd_request
(void)接着处理下一个硬盘读写的请求项。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值