⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide.cpp

📁 Jazmyn is a 32-bit, protected mode, multitasking OS which runs on i386 & above CPU`s. Its complete
💻 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 + -