orange's学习--第九章:a硬盘驱动open

驱动程序的作用在于隐藏硬件细节,向上层进程提供统一的接口。由于我们的进程通过收发消息来相互通信,那么驱动程序的接口自然也是消息了。所以只要我们定义了驱动程序可以接收什么消息,也就定义了驱动程序的接口。

我们先只定义一种消息:DEV_OPEN。我们过会儿通过FS任务向硬盘驱动程序发送一个DEV_OPEN消息。可是硬盘驱动程序收到这个消息之后干点什么呢?我们还是先干点简单工作:向硬盘驱动器发送一个IDENTIFY命令,这个命令可用来获取硬盘数。 

task_hd( )是硬盘驱动的主循环,它跟我们之前的任务没什么两样。开头调用init_hd()做一些初始化工作,然后开始不停地处理消息。我们目前只接收DEV_OPEN消息,收到它之后将会调用hd_identify()来获取并打印部分硬盘参数。

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

hd_identify(int drive)便是获取硬盘参数的函数了。用了一个函数hd_cmd_out()来进行实际的向硬盘驱动器发送命令的工作,因为今后我们还会用到它。当发送命令之后,我们用interrupt_wait()这一函数来等待中断的发生,而等待的方法是调用了一个接收消息的函数。向硬盘发送命令以后,硬盘不是实时返回数据的,硬盘执行完命令以后,会产生中断,所以驱动程序需要等待中断程序通知驱动程序继续执行。

                      发送接收消息                       执行out命令后主动阻塞
task_fs进程<-------------------->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_identify(0);
            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.
 *****************************************************************************/
PRIVATE void init_hd()
{
    /* 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);
}

/*****************************************************************************
 *                                hd_identify
 *****************************************************************************/
/**
 * <Ring 1> Get the disk information.
 * 
 * @param drive  Drive Nr.
 *****************************************************************************/
PRIVATE void hd_identify(int drive)
{
    struct hd_cmd cmd;
    cmd.device  = MAKE_DEVICE_REG(0, drive, 0);
    cmd.command = ATA_IDENTIFY;
    hd_cmd_out(&cmd);
    interrupt_wait();

    port_read(REG_DATA, hdbuf, SECTOR_SIZE);

    print_identify_info((u16*)hdbuf);
}

/*****************************************************************************
 *                                interrupt_wait
 *****************************************************************************/
/**
 * <Ring 1> Wait until a disk interrupt occurs.
 * 
 *****************************************************************************/
PRIVATE void interrupt_wait()
{
    MESSAGE msg;
    send_recv(RECEIVE, INTERRUPT, &msg);
}

/*****************************************************************************
 *                                hd_handler
 *****************************************************************************/
/**
 * <Ring 0> Interrupt handler.
 * 
 * @param irq  IRQ nr of the disk interrupt.
 *****************************************************************************/
PUBLIC void hd_handler(int irq)
{
    /*
     * Interrupts are cleared when the host
     *   - reads the Status Register,
     *   - issues a reset, or
     *   - writes to the Command Register.
     */
    hd_status = in_byte(REG_STATUS);

    inform_int(TASK_HD);
}

我们新建立的文件系统进程其实就是个空壳,它什么都不做,只是向硬盘驱动程序发送一个DEV_OPEN消息。跟之前的所有进程一样,FS进程会在系统启动时开始运行,所以我们在启动操作系统之后很快硬盘驱动就会接收到DEV_OPEN消息,并且获取硬盘参数并进行一些打印工作。

/*****************************************************************************
 *                                task_fs
 *****************************************************************************/
/**
 * <Ring 1> The main loop of TASK FS.
 * 
 *****************************************************************************/

PUBLIC void task_fs()
{
    printl("Task FS begins.\n");

    /* open the device: hard disk */
    MESSAGE driver_msg;
    driver_msg.type = DEV_OPEN;
    send_recv(BOTH, TASK_HD, &driver_msg);

    spin("FS");
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值