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

📄 floppy.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 <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 <fs\devmgr.h>
#include <jazmyn\handlers.h>
#include <drivers\dma.h>
#include <drivers\console.h>
#include <drivers\timer.h>
#include <drivers\floppy.h>

extern device_manager   _dev_mgr;
extern DMA              _DMA_obj;
extern timer            _timer_obj;
extern  process         *curr_proc;
extern "C" void sys_delay(uint millisecs);

int floppy::motor = OFF;
__queue<fdreq> floppy::fdr_queue;

floppy::floppy(char *name,int type):disk_driver(name,type)
{
	int err;
	if((err = _dev_mgr.register_driver(1,this->name,this->disk_type,floppy_main))<0)
	{
		cout<<"register_driver ERROR : "<<this->name<<" "<<err<<endl;
		return;
	}
	if((err = set_handler(IRQ6,floppy_handler))<0)
	{
		cout<<"set_handler ERROR : "<<this->name<<" "<<err<<endl;
		return;
	}
	enable_irq(IRQ6);
        cout<<"floppy driver succesfully registered            [name] = "<<this->name<<endl;
	last_operation = NONE;
	motor = OFF;
}

floppy::~floppy()
{
	int err;
	if((err = _dev_mgr.deregister_driver(this->name))<0)
	{
		cout<<"deregister driver ERROR : "<<this->name<<" "<<err<<endl;
		return;
	}
}

/* sendbyte() routine from intel manual */
void floppy::sendbyte(byte val)
{
	volatile int msr;
	int tmo;
	for (tmo = 0;tmo < 128;tmo++)
	{
		msr = inportb(FDC_MSR);
		/* The following condition checks MRQ & data i/o bits*/
		if ((msr & 0xc0) == 0x80)
		{
			outportb(FDC_DATA,val);
			return;
		}
		inportb(0x80);   /* delay */
	}
}

/* getbyte() routine from intel manual */
byte floppy::getbyte()
{
	volatile int msr;
	int tmo;
	for (tmo = 0;tmo < 128;tmo++)
	{
		msr = inportb(FDC_MSR);
		/* The following condition checks MRQ,data i/o & BUSY bits*/
		if ((msr & 0xd0) == 0xd0)
		{
			return inportb(FDC_DATA);
		}
		inportb(0x80);   /* delay */
	}
	return -1;   /* read timeout */
}

void floppy::set_drive_param()
{
        sendbyte(0x03);
        sendbyte(0xDF);
        sendbyte(0x02);
}

void floppy::get_phys_sec(uint LBA,chs &_chs)
{
        _chs.sec = (LBA % DG144_SPT) + 1;
        _chs.cyl = (LBA / DG144_SPT) / DG144_HEADS;
	_chs.head = (LBA / DG144_SPT) % DG144_HEADS;
}

void floppy::service(int opcode,uint start,uint num,void *buf,int *fin)
{
	chs _chs;
	get_phys_sec(start,_chs);

        fdreq r;  
        r.opcode = opcode,
        r.proc = curr_proc,
        r.start = start,
        r.num = num,
        r.buf = buf,
        r.finished = new int,
        r.n_cyl = _chs.cyl,
        r.n_head = _chs.head,
        r.s_sec = _chs.sec,
	r.num_sec = (_chs.sec + num - 1 > DG144_SPT) ? (DG144_SPT - _chs.sec + 1) : num;

	cli();
	fdr_queue.insert(r);
	fdr_queue.get_rear().proc->block();	
	if(fdr_queue.size() == 1)
		_timer_obj.call_after(200,send_fst_req);
        fin = fdr_queue.get_rear().finished; 
	sti();
	
}

void floppy::wait(int condition,int sensei)
{
	while(last_operation != condition);
	if(sensei)
	{
		sendbyte(CMD_SENSEI);
		st0 = getbyte();
		cyl = getbyte();
	}
}
	
int floppy::issue_rw_req()
{
        fdreq &r = floppy::fdr_queue.get_front();

        if(r.num == 0) return 1;

	motoron();
	set_drive_param();
	seek(r.n_cyl,r.n_head);
        wait(SEEK_SERVICED,TRUE);
        if((st0 & 0xC0) || cyl != r.n_cyl)
        {
                motoroff();
                return -1;
        }

        fdreq t = r;            //copy old fdreq to temp
  	
        r.num = r.num - r.num_sec;
        r.buf = (void*)((uint)r.buf + r.num_sec*512);
        if(r.n_head == 0) r.n_head = 1;
        else { r.n_head = 0;r.n_cyl++; }
	r.s_sec = 1;
	r.num_sec = (r.s_sec + r.num - 1 > DG144_SPT) ? (DG144_SPT - r.s_sec + 1) : r.num;

	DMA_req dmareq = {	
				DMA_SINGLE,
                                (t.opcode == DISK_READ) ? DMA_WRITE : DMA_READ,
                                2,
				t.buf,
                                t.num_sec * 512
			 };
	_DMA_obj.set_DMA(&dmareq);

	byte cmd = (r.opcode == DISK_READ) ? CMD_READ : CMD_WRITE;
	sendbyte(cmd);
	sendbyte((t.n_head<<2)|0);
	sendbyte(t.n_cyl);
	sendbyte(t.n_head);
	sendbyte(t.s_sec);
	sendbyte(0x02);
	sendbyte(18);
	sendbyte(DG144_GAP3RW);
	sendbyte(0xFF);
	return 0;
}	

void floppy::seek(byte cyl,byte head)
{
	last_operation = SEEK;
	sendbyte(CMD_SEEK);
	sendbyte((head<<2)|0);
	sendbyte(cyl);
} 

floppy _floppy_obj("floppy",FLOPPY_DISK);

void send_fst_req()
{
	fdreq &r = floppy::fdr_queue.get_front();	
        if(_floppy_obj.issue_rw_req() < 0)
	{
		cli();
		r.proc->unblock();
                *r.finished = -1;
                floppy::fdr_queue.remove();
		sti();
		if(!floppy::fdr_queue.is_empty())
			send_fst_req();
	}
} 

void floppy_handler()
{
        if(_floppy_obj.last_operation == SEEK) _floppy_obj.last_operation = SEEK_SERVICED;return;
        if(_floppy_obj.last_operation == RECALIBRATE) _floppy_obj.last_operation = RECALIBRATE_SERVICED;return;

        _timer_obj.call_after(2000,motoroff); 
        if(floppy::fdr_queue.is_empty()) return;


        _floppy_obj.st0 = _floppy_obj.getbyte();
        _floppy_obj.st1 = _floppy_obj.getbyte();
        _floppy_obj.st2 = _floppy_obj.getbyte();
        _floppy_obj.cyl = _floppy_obj.getbyte();
        _floppy_obj.head = _floppy_obj. getbyte();
        _floppy_obj.sec = _floppy_obj.getbyte();
        _floppy_obj.secsz = _floppy_obj.getbyte();

        int ret;
        if(_floppy_obj.st0 & 0xC0) 
	{
		ret = -1;
	}

cont:	fdreq &r = floppy::fdr_queue.get_front();
        if(ret == -1) goto loc;
        ret = _floppy_obj.issue_rw_req();

loc:	if(ret)
	{
		cli();
		r.proc->unblock();
                *r.finished = ret;
                floppy::fdr_queue.remove();
		sti();
                if(!floppy::fdr_queue.is_empty())
			goto cont;
        }
}

void motoron()
{
        if(floppy::motor == ON) return;
	outportb(FDC_DOR,0x1C);
        floppy::motor = ON;
        sys_delay(500);
}

void motoroff()
{
        if(floppy::motor == OFF) return;
	outportb(FDC_DOR,0x0C);
        floppy::motor = OFF;
}

int floppy_main(void *req)
{
        disk_req *d_req = (disk_req*)req;
	if(d_req->num == 0) return -1;
        int *fin;
        _floppy_obj.service(d_req->opcode,d_req->start,d_req->num,d_req->buf,fin);
        while(!*fin);
	int ret = *fin;
	delete fin;
        return ret;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -