📄 ide.cpp
字号:
/*
* Copyright (C) 2004, Thejesh AP. All rights reserved.
*/
#include <sys\types.h>
#include <null.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <mm\new.h>
#include <mm\heap.h>
#include <jazmyn\desc.h>
#include <mm\memory.h>
#include <fs\file_sys.h>
#include <jazmyn\process.h>
#include <queue.h>
#include <jazmyn\handlers.h>
#include <fs\devmgr.h>
#include <drivers\console.h>
#include <drivers\keyboard.h>
#include <drivers\timer.h>
#include <drivers\ide.h>
extern device_manager _dev_mgr;
extern process *curr_proc;
extern timer _timer_obj;
extern "C" void sys_delay(uint millisecs);
int ide::serviced = 0;
__queue<hdreq> ide::hdr_queue;
ide::ide(char *name,int type):disk_driver(name,type)
{
num_drives = get_num_drives();
no_media = -1;
for(int i=0;i<num_drives;i++)
{
if(get_drive_param(i,d_id[i]) < 0) no_media = i;
}
int err;
if((err = _dev_mgr.register_driver(num_drives,this->name,this->disk_type,ide_main))<0)
{
cout<<"register_driver ERROR : "<<this->name<<" "<<err<<endl;
return;
}
if((err = set_handler(IRQ14,ide_handler))<0)
{
cout<<"set_handler ERROR : "<<this->name<<" "<<err<<endl;
return;
}
enable_irq(IRQ14);
cout<<"ide driver succesfully registered [name] = "<<this->name<<endl;
}
ide::~ide()
{
int err;
if((err = _dev_mgr.deregister_driver(this->name))<0)
{
cout<<"deregister driver ERROR : "<<this->name<<" "<<err<<endl;
return;
}
}
inline int ide::get_num_drives()
{
outportb(0x70,0x12);
byte val = inportb(0x71);
int cnt = 0;
if(val & 0xF) cnt++;
if((val >> 4) & 0xF) cnt++;
return cnt;
}
int ide::get_drive_param(byte drive,drive_id &id)
{
byte val = 0xA0 | (drive << 4);
outportb(IDE_DRHD,val);
unsigned tmp = 10;
outportb(IDE_CR,0xEC);
if(waitdata() < 0) return -1;
WORD *buf = (WORD*)&id;
for(int i=0;i<256;i++)
buf[i] = inport(IDE_DR);
inportb(IDE_SR);
return 0;
}
void ide::service(int opcode,uint start,uint num,void *buf,int dev,int *fin)
{
*fin = 0;
if (dev > num_drives-1)
{
cout<<"dev num err\n";
*fin = -1;
return;
}
hdreq r;
r.opcode = opcode;
r.proc = curr_proc;
r.start = start;
r.num = num;
r.buf = buf;
r.finished = fin;
r.dev = dev;
r.n_start = start;
r.n_num = (num > MAX_LOG_SEC) ? MAX_LOG_SEC : num;
cli();
hdr_queue.insert(r);
if(curr_proc)
curr_proc->block();
if(hdr_queue.size() == 1)
{
service_req();
}
sti();
}
int ide::waitdata()
{
byte val;
int error=100000;
while(1)
{
val = inportb(IDE_ASR);
if((val & DATA)!=DATA && (val & BUSY)==BUSY)
{
error --;
if(error == 0) return -1;
}
else return 0;
}
}
int ide::issue_rw_req(hdreq &r)
{
hdreq t = r;
if(r.num == 0) return 1;
r.num = r.num - r.n_num;
r.buf = (void*)((uint)r.buf + r.n_num * 512);
r.n_start = r.n_start + r.n_num;
r.n_num = (r.num > MAX_LOG_SEC) ? MAX_LOG_SEC : r.num;
long2byte lb = {t.n_start};
while(inportb(IDE_ASR) & BUSY);
outportb(IDE_SECCNT,t.n_num);
outportb(IDE_SECNUM,lb.b.ll);
outportb(IDE_CYLLSB,lb.b.lh);
outportb(IDE_CYLMSB,lb.b.hl);
byte val = 0xE0 | (t.dev << 4) | (lb.b.hh & 0x0F);
outportb(IDE_DRHD,val);
byte cmd = (t.opcode == DISK_READ) ? IDE_READ : IDE_WRITE;
outportb(IDE_CR,cmd);
if(waitdata() < 0) return -1;
for(int i=0;i<t.n_num;i++)
{
rw_data(t.buf,128,t.dev,t.opcode);
inportb(IDE_SR);
if(waitdata() < 0) return -1;
t.buf = (void*)((uint)t.buf + 512);
}
if(inportb(IDE_ASR) & ERR) return -1;
return 0;
}
inline void ide::rw_data(void *buf,unsigned int lcount,int dev,int opcode)
{
serviced = 0;
(opcode == DISK_READ) ? insw(IDE_DR,buf,lcount*2) : outsw(IDE_DR,buf,lcount*2);
// while(!ide::serviced);
}
ide _ide_obj("ide",HARD_DISK);
void service_req()
{
if(ide::hdr_queue.size() == 0) return;
int ret;
loc: hdreq &r = ide::hdr_queue.get_front();
if((ret = _ide_obj.issue_rw_req(r)) == 0)
goto loc;
cli();
if(r.proc)
r.proc->unblock();
*r.finished = ret;
ide::hdr_queue.remove();
sti();
if(ide::hdr_queue.size())
service_req();
}
void ide_handler()
{
// cout<<"ide handler\n";
ide::serviced = 1;
}
int ide_main(void *req)
{
disk_req *d_req = (disk_req*)req;
if(d_req->opcode == DISK_WRITE)
{
cout<<"Sorry write cant be supported\n";
while(1);
}
if(d_req->num == 0) return -1;
int *fin = new int;
_ide_obj.service(d_req->opcode,d_req->start,d_req->num,d_req->buf,d_req->dev_num,fin);
while(!*fin);
int ret = *fin;
delete fin;
return ret;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -