home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 3
/
Meeting_Pearls_III.iso
/
Pearls
/
disk
/
Devs+Handler
/
RawDiskHandler
/
RawDisk.c
< prev
Wrap
C/C++ Source or Header
|
1994-02-12
|
16KB
|
305 lines
/* RawDisk-Handler V1.1
© 1993 Christian Stieber
stieber@informatik.tu-muenchen.de
freely distributable */
#ifndef EXEC_ALERTS_H
#include <exec/alerts.h>
#endif
#ifndef DOS_FILEHANDLER_H
#include <dos/filehandler.h>
#endif
#ifndef DEVICES_TRACKDISK_H
#include <devices/trackdisk.h>
#endif
#include <string.h>
#include <proto/exec.h>
#include <proto/dos.h>
/***********************************************/
struct MyFileHandle
{
long FilePos;
};
static char Version[]="$VER: RawDisk-Handler 1.1 (13.01.94) © Christian Stieber (stieber@informatik.tu-muenchen.de); freely distributable";
/***********************************************/
long MyDoIO(struct IOExtTD *IORequest)
{
long Error;
Error=DoIO(IORequest);
switch(Error)
{
case TDERR_WriteProt: return ERROR_DISK_WRITE_PROTECTED;
case TDERR_DiskChanged: return ERROR_NO_DISK;
case TDERR_NoMem: return ERROR_NO_FREE_STORE;
case 0: return 0;
default: return ABORT_DISK_ERROR;
}
}
/***********************************************/
void __saveds RawDisk(void)
{
struct DosLibrary *DOSBase;
struct DosPacket *Packet;
struct DeviceNode *DeviceNode;
ULONG OpenCnt;
int Quit;
struct IOExtTD IORequest;
struct DriveGeometry DriveGeometry;
UBYTE *Buffer;
if (!(DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37L)))
{
Alert(AT_DeadEnd | AG_OpenLib | AO_DOSLib);
}
IORequest.iotd_Req.io_Message.mn_ReplyPort=&((struct Process *)FindTask(NULL))->pr_MsgPort;
Packet=WaitPkt();
DeviceNode=BADDR(Packet->dp_Arg3);
DeviceNode->dn_Task=IORequest.iotd_Req.io_Message.mn_ReplyPort;
{
struct FileSysStartupMsg *FileSysStartupMsg;
struct DosEnvec *DosEnvec;
FileSysStartupMsg=BADDR(DeviceNode->dn_Startup);
DosEnvec=BADDR(FileSysStartupMsg->fssm_Environ);
DriveGeometry.dg_TotalSectors=DosEnvec->de_BlocksPerTrack*DosEnvec->de_Surfaces*(DosEnvec->de_HighCyl-DosEnvec->de_LowCyl+1);
DriveGeometry.dg_SectorSize=DosEnvec->de_SizeBlock*4;
if (OpenDevice(((char *)BADDR(FileSysStartupMsg->fssm_Device))+1,FileSysStartupMsg->fssm_Unit,&IORequest,FileSysStartupMsg->fssm_Flags))
{
ReplyPkt(Packet,DOSFALSE,ERROR_OBJECT_NOT_FOUND);
Quit=TRUE;
}
else
{
ReplyPkt(Packet,DOSTRUE,0);
Quit=FALSE;
}
}
OpenCnt=0;
while (!Quit)
{
Packet=WaitPkt();
switch(Packet->dp_Type)
{
case ACTION_FINDUPDATE:
case ACTION_FINDINPUT:
case ACTION_FINDOUTPUT: {
struct FileHandle *FileHandle;
struct MyFileHandle *MyFileHandle;
if (!OpenCnt)
{
long Error;
IORequest.iotd_Req.io_Command=TD_GETGEOMETRY;
IORequest.iotd_Req.io_Data=&DriveGeometry;
IORequest.iotd_Req.io_Length=sizeof(struct DriveGeometry);
if (Error=MyDoIO(&IORequest))
{
ReplyPkt(Packet,DOSFALSE,Error);
}
if (!(Buffer=AllocMem(DriveGeometry.dg_SectorSize,0))) goto OutOfMem;
}
if (MyFileHandle=AllocMem(sizeof(struct MyFileHandle),0))
{
FileHandle=BADDR(Packet->dp_Arg1);
MyFileHandle->FilePos=0;
FileHandle->fh_Arg1=(long)MyFileHandle;
OpenCnt++;
ReplyPkt(Packet,DOSTRUE,0);
}
else
{
OutOfMem: ReplyPkt(Packet,DOSFALSE,ERROR_NO_FREE_STORE);
}
}
break;
case ACTION_READ: {
struct MyFileHandle *MyFileHandle;
long Length;
UBYTE *Destination;
long Error;
MyFileHandle=(struct MyFileHandle *)Packet->dp_Arg1;
Destination=(UBYTE *)Packet->dp_Arg2;
Length=Packet->dp_Arg3;
Error=0;
while (!Error && Length && (MyFileHandle->FilePos!=DriveGeometry.dg_TotalSectors*DriveGeometry.dg_SectorSize))
{
int Size;
int BufferPos;
BufferPos=MyFileHandle->FilePos % DriveGeometry.dg_SectorSize;
IORequest.iotd_Req.io_Command=CMD_READ;
IORequest.iotd_Req.io_Data=Buffer;
IORequest.iotd_Req.io_Length=DriveGeometry.dg_SectorSize;
IORequest.iotd_Req.io_Offset=MyFileHandle->FilePos-BufferPos;
if (!(Error=MyDoIO(&IORequest)))
{
Size=DriveGeometry.dg_SectorSize-BufferPos;
if (Length<Size) Size=Length;
memcpy(Destination,Buffer+BufferPos,Size);
Length-=Size;
Destination+=Size;
MyFileHandle->FilePos+=Size;
}
}
ReplyPkt(Packet,Error ? -1 : Packet->dp_Arg3-Length,Error);
}
break;
case ACTION_WRITE: {
struct MyFileHandle *MyFileHandle;
long Length;
UBYTE *Source;
long Error;
MyFileHandle=(struct MyFileHandle *)Packet->dp_Arg1;
Source=(UBYTE *)Packet->dp_Arg2;
Length=Packet->dp_Arg3;
Error=0;
while (Length)
{
if (MyFileHandle->FilePos!=DriveGeometry.dg_TotalSectors*DriveGeometry.dg_SectorSize)
{
int Size;
int BufferPos;
BufferPos=MyFileHandle->FilePos % DriveGeometry.dg_SectorSize;
if (BufferPos || Length<DriveGeometry.dg_SectorSize)
{
IORequest.iotd_Req.io_Command=CMD_READ;
IORequest.iotd_Req.io_Data=Buffer;
IORequest.iotd_Req.io_Length=DriveGeometry.dg_SectorSize;
IORequest.iotd_Req.io_Offset=MyFileHandle->FilePos-BufferPos;
if (Error=MyDoIO(&IORequest))
{
break;
}
}
Size=DriveGeometry.dg_SectorSize-BufferPos;
if (Length<Size) Size=Length;
memcpy(Buffer+BufferPos,Source,Size);
IORequest.iotd_Req.io_Command=CMD_WRITE;
IORequest.iotd_Req.io_Data=Buffer;
IORequest.iotd_Req.io_Length=DriveGeometry.dg_SectorSize;
IORequest.iotd_Req.io_Offset=MyFileHandle->FilePos-BufferPos;
if (Error=MyDoIO(&IORequest))
{
break;
}
Length-=Size;
Source+=Size;
MyFileHandle->FilePos+=Size;
}
else
{
if (!(Packet->dp_Arg3-Length))
{
Error=ERROR_DISK_FULL;
}
break;
}
}
ReplyPkt(Packet,Error ? -1 : Packet->dp_Arg3-Length,Error);
}
break;
case ACTION_SEEK: {
struct MyFileHandle *MyFileHandle;
long NewFilePos;
NewFilePos=-1;
MyFileHandle=(struct MyFileHandle *)Packet->dp_Arg1;
switch(Packet->dp_Arg3)
{
case OFFSET_BEGINNING: NewFilePos=Packet->dp_Arg2;
break;
case OFFSET_CURRENT: NewFilePos=MyFileHandle->FilePos+Packet->dp_Arg2;
break;
case OFFSET_END: NewFilePos=DriveGeometry.dg_TotalSectors*DriveGeometry.dg_SectorSize-Packet->dp_Arg2;
break;
}
if (NewFilePos<0 || NewFilePos>DriveGeometry.dg_TotalSectors*DriveGeometry.dg_SectorSize)
{
ReplyPkt(Packet,-1,ERROR_SEEK_ERROR);
}
else
{
long OldPos=MyFileHandle->FilePos;
MyFileHandle->FilePos=NewFilePos;
ReplyPkt(Packet,OldPos,0);
}
}
break;
case ACTION_END: {
long Error;
Error=0;
FreeMem((struct MyFileHandle *)Packet->dp_Arg1,sizeof(struct MyFileHandle));
if (!--OpenCnt)
{
IORequest.iotd_Req.io_Command=CMD_UPDATE;
Error=MyDoIO(&IORequest);
IORequest.iotd_Req.io_Command=TD_MOTOR;
IORequest.iotd_Req.io_Length=0;
DoIO(&IORequest);
FreeMem(Buffer,DriveGeometry.dg_SectorSize);
}
ReplyPkt(Packet,Error ? DOSTRUE : DOSFALSE,Error);
}
break;
case ACTION_DIE: if (!OpenCnt)
{
Forbid();
ReplyPkt(Packet,DOSTRUE,0);
while (!IsMsgPortEmpty(IORequest.iotd_Req.io_Message.mn_ReplyPort))
{
ReplyPkt(WaitPkt(),DOSFALSE,ERROR_OBJECT_NOT_FOUND);
}
Quit=TRUE;
}
else
{
ReplyPkt(Packet,DOSFALSE,ERROR_OBJECT_IN_USE);
}
break;
default: {
ReplyPkt(Packet,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
}
break;
}
}
{
BPTR SegList;
SegList=DeviceNode->dn_SegList;
DeviceNode->dn_Task=NULL;
DeviceNode->dn_SegList=NULL;
CloseDevice(&IORequest);
UnLoadSeg(DeviceNode->dn_SegList);
CloseLibrary((struct Library *)DOSBase);
}
}