home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / new / disk / cdrom / amicdfs / src / device.c < prev    next >
C/C++ Source or Header  |  1994-10-03  |  42KB  |  1,717 lines

  1. /* device.c:
  2.  *
  3.  * Handler for ISO-9660 (+ Rock Ridge) + HFS CDROM filing system.
  4.  * Originally based on DOSDEV V1.10 (2 Nov 87) by Matthew Dillon.
  5.  * Major changes made by Nicola Salmoria.
  6.  *
  7.  * ----------------------------------------------------------------------
  8.  * This code is (C) Copyright 1993,1994 by Frank Munkert.
  9.  * All rights reserved.
  10.  * This software may be freely distributed and redistributed for
  11.  * non-commercial purposes, provided this notice is included.
  12.  * ----------------------------------------------------------------------
  13.  * [History removed]
  14.  */
  15.  
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <exec/memory.h>
  19. #include <exec/execbase.h>
  20. #include <exec/resident.h>
  21. #include <dos/dosextens.h>
  22. #include <dos/dostags.h>
  23. #include <dos/filehandler.h>
  24. #include <devices/timer.h>
  25. #include <devices/input.h>
  26. #include <devices/inputevent.h>
  27. #include <devices/trackdisk.h>
  28. #include <utility/date.h>
  29. #include <intuition/intuitionbase.h>
  30. #include <workbench/workbench.h>
  31. #include <resources/filesysres.h>
  32. #include <clib/alib_protos.h>
  33. #include <proto/dos.h>
  34. #include <proto/exec.h>
  35. #include <proto/utility.h>
  36. #include <proto/intuition.h>
  37. #include <proto/icon.h>
  38. #include <proto/wb.h>
  39.  
  40. #include "cdrom.h"
  41. #include "generic.h"
  42. #include "rock.h"
  43.  
  44. #define VERSION 37
  45. #define REVISION 5
  46. static const UBYTE versionstring20[] = "\0$VER: amicdfilesystem 37.5 (2.10.94)";
  47.  
  48.  
  49. /*
  50.  * The only purpose of this Resident structure is to make
  51.  * Version CD0:
  52.  * return the version number of the filesystem.
  53.  */
  54. static const struct Resident versiontag =
  55. {
  56.     RTC_MATCHWORD,
  57.     &versiontag,
  58.     &versiontag + 1,
  59.     0,
  60.     VERSION,
  61.     0,
  62.     -81,
  63.     NULL,
  64.     &versionstring20[7],
  65.     NULL
  66. };
  67.  
  68.  
  69. /* the only global data used is library bases, therefore this code is */
  70. /* reentrant, and could be run several times. If we added the filesystem */
  71. /* to the filesystem resource, one instance would be used for multiple */
  72. /* devices. */
  73.  
  74. struct ExecBase *SysBase;
  75. struct DosLibrary *DOSBase;
  76. struct Library *UtilityBase;
  77. struct IntuitionBase *IntuitionBase;
  78. struct Library *InputBase;
  79. struct Library *IconBase;
  80. struct Library *WorkbenchBase;
  81.  
  82.  
  83.  
  84. /* global data is kept in the HData structure, instead, which is located */
  85. /* on the stack. */
  86.  
  87. struct HConfig
  88. {
  89.     BOOL UseTrackdisk;            /* Use trackdisk calls instead of SCSI-direct */
  90.  
  91.     BOOL Lowercase;                /* Map ISO names to lower case */
  92.  
  93.     ULONG ScanInterval;            /* Time between successive diskchange checks */
  94. };
  95.  
  96. struct HData
  97. {
  98.     struct MsgPort *MyPort;        /* our handler port */
  99.     struct DosList *MyDevNode;        /* our device node */
  100.     struct FileSysStartupMsg *fssm;
  101.     struct DosEnvec *envec;
  102.     struct DosList *CurrentVolume;     /* current volume, or NULL */
  103.     BPTR LockList;            /* list of open locks */
  104.     LONG DiskInserted;        /* see #defines below */
  105.     LONG Inhibited;            /* !0 if the volume is inhibited (nesting count) */
  106.  
  107.     CDROM *CD;
  108.     VOLUME *CDVolume;
  109.     CDROM_OBJ *TopLevelObj;
  110.  
  111.     UBYTE VolumeName[40];        /* When a dos disk is inserted, contains the */
  112.                                 /* volume name in BCPL form. */
  113.                                 /* When an audio disk is inserted, contains */
  114.                                 /* tha name which will be used for the AppIcon, */
  115.                                 /* for example CD0:CDDA */
  116.  
  117.     struct AppIcon *AppIcon;    /* CDDA AppIcon */
  118.     struct MsgPort *AppPort;    /* MsgPort used by the AppIcon */
  119.  
  120.     struct MsgPort *TimerPort;        /* timer.device I/O port */
  121.     struct timerequest *TimerIO;    /* timer.device I/O request */
  122.     struct IOStdReq *InputIO;        /* input.device I/O request */
  123.  
  124.     UBYTE PlayCDDA[128];            /* Command invoked if appicon is activated */
  125.                                     /* (initialized by Show_CDDA_Icon()) */
  126.     BOOL Playing;                /* TRUE if a CDDA disk is playing */
  127.     BOOL pad;
  128.  
  129.     struct HConfig HConfig;        /* configuration */
  130. };
  131.  
  132.  
  133. /* allowed values for the DiskInserted field */
  134.  
  135. #define DI_NO_DISK 0        /* no disk in the drive */
  136. #define DI_DISK_OK 1        /* disk in drive */
  137. #define DI_UNREADABLE_DISK 2    /* disk in drive, but couldn't be read for some reason */
  138. #define DI_CDDA_DISK 3        /* CDDA disk in drive */
  139.  
  140.  
  141.  
  142.  
  143. ULONG Centrypoint(VOID);
  144.  
  145. VOID ReturnPacket(struct DosPacket *packet,struct MsgPort *port,LONG res1,LONG res2);
  146. VOID AddToFSResource(ULONG dostype,BPTR seglist);
  147. void btos(LONG, char *);
  148. CDROM_OBJ *OpenObject(BPTR parentlock,BSTR name,struct HData *HData);
  149. BPTR cdlock(CDROM_OBJ *, int,struct HData *HData);
  150. void cdunlock(BPTR lock,struct HData *HData);
  151. LONG CheckLock(BPTR lock,struct HData *HData);
  152. CDROM_OBJ *getlockfile(BPTR lock,struct HData *HData);
  153. int Check_For_Volume_Name_Prefix (char *);
  154. VOID Fill_InfoData(struct InfoData *id,struct HData *HData);
  155. void Fill_FileInfoBlock (struct FileInfoBlock *, CDROM_INFO *, VOLUME *,struct HData *HData);
  156. void Mount(struct HData *HData);
  157. struct DosList *CreateVolumeNode(struct HData *HData);
  158. void RemoveVolumeNode (struct HData *HData);
  159. VOID RemoveDosList(struct DosList *vol);
  160. void Check_Disk (struct HData *HData);
  161. void Send_Timer_Request(struct HData *HData);
  162. int Open_Timer_Device(struct HData *HData);
  163. int Open_Input_Device(struct HData *HData);
  164. VOID CreateInputEvent(BOOL inserted,struct HData *HData);
  165. int Get_Startup (struct HData *HData);
  166.  
  167. VOID Display_Error(UBYTE *text,APTR par1, ...);
  168. VOID Show_CDDA_Icon(struct HData *HData);
  169. VOID Hide_CDDA_Icon (struct HData *HData);
  170.  
  171. ULONG _stackswap(ULONG function(),...);
  172.  
  173.  
  174.  
  175.  
  176. ULONG entrypoint(VOID)
  177. {
  178. /* we must always swap the stack because when mounted from RDB we will get */
  179. /* only 600 bytes of stack. */
  180. return(_stackswap(Centrypoint));
  181. }
  182.  
  183.  
  184.  
  185. ULONG __saveds Centrypoint(VOID)
  186. {
  187. struct DosPacket *packet;
  188. struct Process *process;
  189. struct HData HData;
  190. LONG timercount = 0;
  191.  
  192.  
  193. SysBase = *((struct ExecBase **)4);
  194.  
  195. process = (struct Process *)FindTask(NULL);
  196. /* if we were run from a shell, fail */
  197. if (process->pr_CLI) return(RETURN_FAIL);
  198.  
  199. WaitPort(&process->pr_MsgPort);        /* get startup packet */
  200. packet = (struct DosPacket *)GetMsg(&process->pr_MsgPort)->mn_Node.ln_Name;
  201.  
  202. memset(&HData,0,sizeof(struct HData));
  203.  
  204. if (!(HData.fssm = BADDR(packet->dp_Arg2)) ||
  205.         !(HData.envec = BADDR(HData.fssm->fssm_Environ)) ||
  206.     /* make sure that the mountlist has enough fields */
  207.         HData.envec->de_TableSize < DE_DOSTYPE)
  208. {
  209.     Forbid();
  210.     ReturnPacket(packet,&process->pr_MsgPort,DOSFALSE,0);
  211.     return(0);        /* exit */
  212. }
  213.  
  214. HData.MyDevNode = BADDR(packet->dp_Arg3);
  215.  
  216. /* add the seglist to the filesystem.resource so it will be reused by other */
  217. /* devices with the same DosType */
  218. AddToFSResource(HData.envec->de_DosType,HData.MyDevNode->dol_misc.dol_handler.dol_SegList);
  219.  
  220. if (SysBase->LibNode.lib_Version < 37 ||
  221.         !(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",37)) ||
  222.         !(UtilityBase = OpenLibrary("utility.library",37)) ||
  223.         !(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)) ||
  224.         !(HData.MyPort = CreateMsgPort()) ||
  225.         !Open_Timer_Device(&HData) ||
  226.         !Open_Input_Device(&HData) ||
  227.         !Get_Startup(&HData))
  228. {
  229.     if (DOSBase)
  230.     {
  231.         DeleteMsgPort(HData.MyPort);
  232.         CloseLibrary(IntuitionBase);
  233.         CloseLibrary(UtilityBase);
  234.         CloseLibrary(DOSBase);
  235.     }
  236.     Forbid();
  237.     ReturnPacket(packet,&process->pr_MsgPort,DOSFALSE,0);
  238.     return(0);        /* exit */
  239. }
  240.  
  241. /* initialize dn_Task so that DOS won't start a new process for every access */
  242. HData.MyDevNode->dol_Task = HData.MyPort;
  243.  
  244. ReturnPacket(packet,HData.MyPort,DOSTRUE,0);
  245.  
  246. Send_Timer_Request(&HData);
  247.  
  248. Check_Disk(&HData);
  249.  
  250.  
  251. for (;;)
  252. {
  253.     ULONG dossignal,appsignal,timersignal,sigrec;
  254.  
  255.  
  256.     dossignal = 1L << HData.MyPort->mp_SigBit;
  257.     appsignal = HData.AppPort ? 1L << HData.AppPort->mp_SigBit : 0;
  258.     timersignal = 1L << HData.TimerPort->mp_SigBit;
  259.  
  260.     sigrec = Wait(dossignal | timersignal | appsignal | SIGBREAKF_CTRL_F);
  261.  
  262.     if (sigrec & SIGBREAKF_CTRL_F)
  263.     {
  264. D(kprintf("diskchange interrupt!\n"));
  265.         Check_Disk(&HData);
  266.     }
  267.  
  268.     if (sigrec & timersignal)
  269.     {
  270.         if (HData.HConfig.ScanInterval)
  271.         {
  272.             if (++timercount == HData.HConfig.ScanInterval)
  273.             {
  274.                 Check_Disk(&HData);
  275.  
  276.                 timercount = 0;
  277.             }
  278.         }
  279.  
  280. /* turn off the motor if it is on (Motor_Off() knows whether it's on) */
  281.         Motor_Off(HData.CD);
  282.  
  283. /* retry to display the AppIcon, in case something went wrong before */
  284.         if (HData.DiskInserted == DI_CDDA_DISK) Show_CDDA_Icon(&HData);
  285.  
  286.         GetMsg(HData.TimerPort);
  287.         Send_Timer_Request(&HData);
  288.     }
  289.  
  290.     if (sigrec & appsignal)
  291.     {
  292.         struct Message *msg;
  293.  
  294.  
  295.         while (msg = GetMsg(HData.AppPort))