babyos2(8)——读IDE硬盘
来源:互联网 发布:淘宝网天猫童鞋 编辑:程序博客网 时间:2024/05/17 04:23
/* * guzhoudiaoke@126.com * 2017-10-29 */#ifndef _HARDDISK_H_#define _HARDDISK_H_#include "types.h"#include "spinlock.h"#include "kernel.h"#define HD_STATE_READY 0x40#define HD_STATE_BUSY 0x80#define IO_CMD_READ 0x20#define IO_CMD_WRITE 0x30#define IO_STATE_DONE 0x01/* io control block */typedef struct io_clb_s { uint32 flags; uint32 read; uint32 dev; uint32 lba; struct io_clb_s* next; uint8 buffer[SECT_SIZE];} io_clb_t;class ide_t {public: ide_t(); ~ide_t(); void init(); void do_irq(); void wait(); void request(io_clb_t *clb); void start(io_clb_t *clb);private: io_clb_t* m_head; spinlock_t m_lock;};#endif
void ide_t::init(){ os()->get_arch()->get_8259a()->enable_irq(IRQ_HARDDISK); wait(); outb(0x1f6, 0xe0 | (0 << 4));}
初始化只需要开启中断,并选择dev号。
void ide_t::request(io_clb_t *clb){ m_lock.lock(); clb->next = NULL; if (m_head == NULL) { m_head = clb; } else { io_clb_t *p = m_head; while (p->next != NULL) { p = p->next; } p->next = clb; } m_lock.unlock(); if (m_head == clb) { start(clb); } while ((clb->flags & IO_STATE_DONE) != IO_STATE_DONE) { os()->get_arch()->get_cpu()->sleep(); }}
当需要读取硬盘时,调用request,参数时一个io_clb_t,表示一个IO控制块。首先会把这个clb添加到链表尾部去排队处理。同时,若当前仅有这一个IO需要处理,则调用start开始处理这个IO。之后一直等待处理完成,因为读盘属于慢操作,所以调用sleep,让当前进程睡眠等待。目前sleep尚未实现,也一直还处于内核态,所以这个sleep目前啥也没做,只是个空函数。
void ide_t::start(io_clb_t *clb){ int lba = clb->lba; wait(); outb(0x3f6, 0); // generate interrupt outb(0x1f2, 1); // sector num outb(0x1f3, lba & 0xff); outb(0x1f4, (lba >> 8) & 0xff); outb(0x1f5, (lba >> 16) & 0xff); outb(0x1f6, 0xe0 | ((clb->dev & 0x1) << 4) | ((lba >> 24) & 0xff)); if (clb->read) { outb(0x1f7, IO_CMD_READ); } else { outb(0x1f7, IO_CMD_WRITE); outsl(0x1f0, clb->buffer, SECT_SIZE/4); }}
start 则会根据clb中的信息,将要读取的lba通过写端口告知IDE硬盘控制器,进行读操作。此时正常情况下系统应该调度到其他进程。当读硬盘完成后,会收到中断。
void ide_t::do_irq(){ console()->kprintf(WHITE, "ide_t::do_irq()\n"); m_lock.lock(); if (m_head == NULL) { m_lock.unlock(); return; } io_clb_t *clb = m_head; m_head = clb->next; m_lock.unlock(); insl(0x1f0, clb->buffer, SECT_SIZE/4); clb->flags |= IO_STATE_DONE; // wakeup() if (m_head != NULL) { start(m_head); }}
中断服务程序如上所示,会将数据读到clb指定的buffer,并将flag标记设为DONE,然后唤醒等待的进程。
io_clb_t clb;void test_ide(){ return; // only test clb.flags = 0; clb.read = 1; clb.dev = 0; clb.lba = 244; memset(clb.buffer, 0, 512); os()->get_ide()->request(&clb); for (int i = 0; i < SECT_SIZE/4; i++) { if (i % 8 == 0) { console()->kprintf(PINK, "\n"); } console()->kprintf(PINK, "%x ", ((uint32 *)clb.buffer)[i]); } console()->kprintf(PINK, "\n");}
上面是一段测试代码,及结果。
阅读全文
0 0
- babyos2(8)——读IDE硬盘
- babyos2(0)——从零开始
- babyos2(1)——boot
- babyos2(3)—— console, kprintf
- babyos2(4)——memory ranges
- babyos2(5)——分页
- babyos2(9)——系统调用
- babyos2(16)—— sleep, wakeup
- babyos2(2)—— load elf format kernel
- babyos2(6)——IDT,中断,异常
- babyos2(11)——物理内存管理,伙伴系统
- babyos2(12)——pagefault, vm_area, mmap
- babyos2(15)—— bug fix 1
- babyos2(7)——键盘中断、时钟中断、实时钟
- babyos2(10)——进程,调度,fork,exec,用户空间
- babyos2(13)——进程页表,fork, COW(copy on write)
- babyos2(14)—— 用户态栈的扩展,加载elf
- 认识IDE硬盘(上)(转)
- UVA 11440 Help Tomisu
- 杭电ACM OJ 1011 Starship Troopers 树的动态规划(树的dp)经典树形背包 java写的 包看懂 递归流程完全解析
- Coursea吴恩达《结构化机器学习》课程笔记(2)机器学习策略下
- java注解的详解-适合java初学者
- 面向对象程序设计的特征
- babyos2(8)——读IDE硬盘
- java的函数重载
- FZU
- 求二叉树的高度
- 我的学习记录32
- LeetCode解题-#7-Reverse Integer
- Homestead中安装yarn教程
- JSP语言做简易留言板
- C# 扩展方法 白话总结