📄 floppy.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 + -