一个操作系统的实现第九章笔记

来源:互联网 发布:深入浅出mysql豆瓣 编辑:程序博客网 时间:2024/06/06 08:50

9.2

硬盘控制器操作通过I/O端口进行,端口分为两组: 1.命令块寄存器Command Block Registers 2 控制块寄存器 Control Block Register

硬盘操作:先写入命令块寄存器,通过控制块寄存器发送命令即可。


获取硬盘的参数:

向硬盘发送IDENTIFY命令,通过Device寄存器第四位指定驱动器 (0:master 1:slave),然后向控制寄存器写入十六进制的ECh。硬盘准备好参数以后,会产生一个中断,这时通过Data寄存器读取数据。参数总共有256字(WORD),

/*****************************************************************************
 *                                task_hd
 *****************************************************************************/
/**
 * Main loop of HD driver.
 * task_hd  作为一个守护进程,初始化硬盘,然后一直运行,等待接收来自其他进程的消息 ,硬盘驱动的主循环
 *****************************************************************************/
PUBLIC void task_hd()
{
MESSAGE msg;
init_hd();                 //初始化工作,
while (1) { //开始不停地处理消息
send_recv(RECEIVE, ANY, &msg);
int src = msg.source;
switch (msg.type) {
case DEV_OPEN:
hd_open(msg.DEVICE);//读取硬盘的状态 调用hd_identify()来获取并打印部分硬盘参数
break;
case DEV_CLOSE:
hd_close(msg.DEVICE);
break;
case DEV_READ:
case DEV_WRITE:
hd_rdwt(&msg);
break;
case DEV_IOCTL:
hd_ioctl(&msg);
break;
default:
dump_msg("HD driver::unknown msg", &msg);
spin("FS::main_loop (invalid msg.type)");
break;
}


send_recv(SEND, src, &msg);//;通知驱动程序文件系统向驱动程序发送“打开设备”的命令
}
}


/*****************************************************************************
 *                                init_hd
 *****************************************************************************/
/**
 * <Ring 1> Check hard drive, set IRQ handler, enable IRQ and initialize data
 *          structures.

所做工作分两部分,先是从物理地址0x475处获取系统内硬盘数量,这个地址是由BIOS指定的,然后它指定hd_handler()为硬盘中断处理程序,并且打开硬盘中断。

这里不仅仅需要打开硬盘对应的中断信号线,还要打开主8259A用于级联从片的信号线

Device Register 
 *****************************************************************************/
PRIVATE void init_hd()
{
int i;
/* Get the number of drives from the BIOS data area */
u8 * pNrDrives = (u8*)(0x475);
printl("NrDrives:%d.\n", *pNrDrives);
assert(*pNrDrives);


put_irq_handler(AT_WINI_IRQ, hd_handler);
enable_irq(CASCADE_IRQ);
enable_irq(AT_WINI_IRQ);


for (i = 0; i < (sizeof(hd_info) / sizeof(hd_info[0])); i++)
memset(&hd_info[i], 0, sizeof(hd_info[0]));
hd_info[0].open_cnt = 0;
}

0 0
原创粉丝点击