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;
}