home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 7
/
FreshFishVol7.bin
/
new
/
disk
/
cdrom
/
amicdfs
/
src
/
device.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-03
|
42KB
|
1,717 lines
/* device.c:
*
* Handler for ISO-9660 (+ Rock Ridge) + HFS CDROM filing system.
* Originally based on DOSDEV V1.10 (2 Nov 87) by Matthew Dillon.
* Major changes made by Nicola Salmoria.
*
* ----------------------------------------------------------------------
* This code is (C) Copyright 1993,1994 by Frank Munkert.
* All rights reserved.
* This software may be freely distributed and redistributed for
* non-commercial purposes, provided this notice is included.
* ----------------------------------------------------------------------
* [History removed]
*/
#include <stdlib.h>
#include <string.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <exec/resident.h>
#include <dos/dosextens.h>
#include <dos/dostags.h>
#include <dos/filehandler.h>
#include <devices/timer.h>
#include <devices/input.h>
#include <devices/inputevent.h>
#include <devices/trackdisk.h>
#include <utility/date.h>
#include <intuition/intuitionbase.h>
#include <workbench/workbench.h>
#include <resources/filesysres.h>
#include <clib/alib_protos.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/intuition.h>
#include <proto/icon.h>
#include <proto/wb.h>
#include "cdrom.h"
#include "generic.h"
#include "rock.h"
#define VERSION 37
#define REVISION 5
static const UBYTE versionstring20[] = "\0$VER: amicdfilesystem 37.5 (2.10.94)";
/*
* The only purpose of this Resident structure is to make
* Version CD0:
* return the version number of the filesystem.
*/
static const struct Resident versiontag =
{
RTC_MATCHWORD,
&versiontag,
&versiontag + 1,
0,
VERSION,
0,
-81,
NULL,
&versionstring20[7],
NULL
};
/* the only global data used is library bases, therefore this code is */
/* reentrant, and could be run several times. If we added the filesystem */
/* to the filesystem resource, one instance would be used for multiple */
/* devices. */
struct ExecBase *SysBase;
struct DosLibrary *DOSBase;
struct Library *UtilityBase;
struct IntuitionBase *IntuitionBase;
struct Library *InputBase;
struct Library *IconBase;
struct Library *WorkbenchBase;
/* global data is kept in the HData structure, instead, which is located */
/* on the stack. */
struct HConfig
{
BOOL UseTrackdisk; /* Use trackdisk calls instead of SCSI-direct */
BOOL Lowercase; /* Map ISO names to lower case */
ULONG ScanInterval; /* Time between successive diskchange checks */
};
struct HData
{
struct MsgPort *MyPort; /* our handler port */
struct DosList *MyDevNode; /* our device node */
struct FileSysStartupMsg *fssm;
struct DosEnvec *envec;
struct DosList *CurrentVolume; /* current volume, or NULL */
BPTR LockList; /* list of open locks */
LONG DiskInserted; /* see #defines below */
LONG Inhibited; /* !0 if the volume is inhibited (nesting count) */
CDROM *CD;
VOLUME *CDVolume;
CDROM_OBJ *TopLevelObj;
UBYTE VolumeName[40]; /* When a dos disk is inserted, contains the */
/* volume name in BCPL form. */
/* When an audio disk is inserted, contains */
/* tha name which will be used for the AppIcon, */
/* for example CD0:CDDA */
struct AppIcon *AppIcon; /* CDDA AppIcon */
struct MsgPort *AppPort; /* MsgPort used by the AppIcon */
struct MsgPort *TimerPort; /* timer.device I/O port */
struct timerequest *TimerIO; /* timer.device I/O request */
struct IOStdReq *InputIO; /* input.device I/O request */
UBYTE PlayCDDA[128]; /* Command invoked if appicon is activated */
/* (initialized by Show_CDDA_Icon()) */
BOOL Playing; /* TRUE if a CDDA disk is playing */
BOOL pad;
struct HConfig HConfig; /* configuration */
};
/* allowed values for the DiskInserted field */
#define DI_NO_DISK 0 /* no disk in the drive */
#define DI_DISK_OK 1 /* disk in drive */
#define DI_UNREADABLE_DISK 2 /* disk in drive, but couldn't be read for some reason */
#define DI_CDDA_DISK 3 /* CDDA disk in drive */
ULONG Centrypoint(VOID);
VOID ReturnPacket(struct DosPacket *packet,struct MsgPort *port,LONG res1,LONG res2);
VOID AddToFSResource(ULONG dostype,BPTR seglist);
void btos(LONG, char *);
CDROM_OBJ *OpenObject(BPTR parentlock,BSTR name,struct HData *HData);
BPTR cdlock(CDROM_OBJ *, int,struct HData *HData);
void cdunlock(BPTR lock,struct HData *HData);
LONG CheckLock(BPTR lock,struct HData *HData);
CDROM_OBJ *getlockfile(BPTR lock,struct HData *HData);
int Check_For_Volume_Name_Prefix (char *);
VOID Fill_InfoData(struct InfoData *id,struct HData *HData);
void Fill_FileInfoBlock (struct FileInfoBlock *, CDROM_INFO *, VOLUME *,struct HData *HData);
void Mount(struct HData *HData);
struct DosList *CreateVolumeNode(struct HData *HData);
void RemoveVolumeNode (struct HData *HData);
VOID RemoveDosList(struct DosList *vol);
void Check_Disk (struct HData *HData);
void Send_Timer_Request(struct HData *HData);
int Open_Timer_Device(struct HData *HData);
int Open_Input_Device(struct HData *HData);
VOID CreateInputEvent(BOOL inserted,struct HData *HData);
int Get_Startup (struct HData *HData);
VOID Display_Error(UBYTE *text,APTR par1, ...);
VOID Show_CDDA_Icon(struct HData *HData);
VOID Hide_CDDA_Icon (struct HData *HData);
ULONG _stackswap(ULONG function(),...);
ULONG entrypoint(VOID)
{
/* we must always swap the stack because when mounted from RDB we will get */
/* only 600 bytes of stack. */
return(_stackswap(Centrypoint));
}
ULONG __saveds Centrypoint(VOID)
{
struct DosPacket *packet;
struct Process *process;
struct HData HData;
LONG timercount = 0;
SysBase = *((struct ExecBase **)4);
process = (struct Process *)FindTask(NULL);
/* if we were run from a shell, fail */
if (process->pr_CLI) return(RETURN_FAIL);
WaitPort(&process->pr_MsgPort); /* get startup packet */
packet = (struct DosPacket *)GetMsg(&process->pr_MsgPort)->mn_Node.ln_Name;
memset(&HData,0,sizeof(struct HData));
if (!(HData.fssm = BADDR(packet->dp_Arg2)) ||
!(HData.envec = BADDR(HData.fssm->fssm_Environ)) ||
/* make sure that the mountlist has enough fields */
HData.envec->de_TableSize < DE_DOSTYPE)
{
Forbid();
ReturnPacket(packet,&process->pr_MsgPort,DOSFALSE,0);
return(0); /* exit */
}
HData.MyDevNode = BADDR(packet->dp_Arg3);
/* add the seglist to the filesystem.resource so it will be reused by other */
/* devices with the same DosType */
AddToFSResource(HData.envec->de_DosType,HData.MyDevNode->dol_misc.dol_handler.dol_SegList);
if (SysBase->LibNode.lib_Version < 37 ||
!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37)) ||
!(UtilityBase = OpenLibrary("utility.library",37)) ||
!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)) ||
!(HData.MyPort = CreateMsgPort()) ||
!Open_Timer_Device(&HData) ||
!Open_Input_Device(&HData) ||
!Get_Startup(&HData))
{
if (DOSBase)
{
DeleteMsgPort(HData.MyPort);
CloseLibrary(IntuitionBase);
CloseLibrary(UtilityBase);
CloseLibrary(DOSBase);
}
Forbid();
ReturnPacket(packet,&process->pr_MsgPort,DOSFALSE,0);
return(0); /* exit */
}
/* initialize dn_Task so that DOS won't start a new process for every access */
HData.MyDevNode->dol_Task = HData.MyPort;
ReturnPacket(packet,HData.MyPort,DOSTRUE,0);
Send_Timer_Request(&HData);
Check_Disk(&HData);
for (;;)
{
ULONG dossignal,appsignal,timersignal,sigrec;
dossignal = 1L << HData.MyPort->mp_SigBit;
appsignal = HData.AppPort ? 1L << HData.AppPort->mp_SigBit : 0;
timersignal = 1L << HData.TimerPort->mp_SigBit;
sigrec = Wait(dossignal | timersignal | appsignal | SIGBREAKF_CTRL_F);
if (sigrec & SIGBREAKF_CTRL_F)
{
D(kprintf("diskchange interrupt!\n"));
Check_Disk(&HData);
}
if (sigrec & timersignal)
{
if (HData.HConfig.ScanInterval)
{
if (++timercount == HData.HConfig.ScanInterval)
{
Check_Disk(&HData);
timercount = 0;
}
}
/* turn off the motor if it is on (Motor_Off() knows whether it's on) */
Motor_Off(HData.CD);
/* retry to display the AppIcon, in case something went wrong before */
if (HData.DiskInserted == DI_CDDA_DISK) Show_CDDA_Icon(&HData);
GetMsg(HData.TimerPort);
Send_Timer_Request(&HData);
}
if (sigrec & appsignal)
{
struct Message *msg;
while (msg = GetMsg(HData.AppPort))