home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / disk / amicdrom-1.11.lha / AmiCDROM-1.11 / devsupp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-19  |  14.2 KB  |  522 lines

  1. /* devsupp.c:
  2.  *
  3.  * Support routines for the device handler.
  4.  * - debugging
  5.  * - Mountlist "Startup" field parsing
  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:
  14.  * 
  15.  * 17-May-94   fmu   New option MAYBELOWERCASE (=ML).
  16.  * 09-Apr-94   fmu   Larger buffer for startup strings.
  17.  * 02-Jan-94   fmu   New options XPOS and YPOS.
  18.  * 11-Dec-93   fmu   Memory type can now be chosen by the user:
  19.  *                   new options CHIP, DMA and ANY.
  20.  * 11-Dec-93   fmu   The assembly code stubs for the debugging process
  21.  *                   are no longer necessary; the debugger code is now
  22.  *                   called with CreateNewProcTags().
  23.  * 21-Nov-93   fmu   New option SCANINTERVAL.
  24.  * 14-Nov-93   fmu   Added Handle_Control_Packet for 'cdcontrol' program.
  25.  * 10-Nov-93   fmu   New options SHOWVERSION and HFSFIRST.
  26.  * 23-Oct-93   fmu   MacHFS options added.
  27.  * 15-Oct-93   fmu   Adapted to new VOLUME structure.
  28.  */
  29.  
  30. /*
  31.  * Extract information from Mountlist "Startup" field.
  32.  */
  33.  
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <stdarg.h>
  37. #include <stdio.h>
  38.  
  39. #ifdef _DCC
  40. #define abs
  41. #endif
  42.  
  43. #include <exec/types.h>
  44. #include <dos/dostags.h>
  45. #include <clib/dos_protos.h>
  46. #include "device.h"
  47. #include "devsupp.h"
  48. #include "intui.h"
  49. #include "params.h"
  50. #include "cdcontrol.h"
  51.  
  52. static char *TheVersion = "$VER: " VERSION;
  53.  
  54. unsigned long g_memory_type;
  55.  
  56. int
  57. Get_Startup (LONG p_startup)
  58. {
  59.   enum {
  60.     ARG_DEVICE,
  61.     ARG_UNIT,
  62.     ARG_CHIP,
  63.     ARG_FAST,
  64.     ARG_DMA,
  65.     ARG_ANY,
  66.     ARG_LOWERCASE,
  67.     ARG_MAYBELOWERCASE,
  68.     ARG_ROCKRIDGE,
  69.     ARG_TRACKDISK,
  70.     ARG_MACTOISO,
  71.     ARG_CONVERTSPACES,
  72.     ARG_SHOWVERSION,
  73.     ARG_HFSFIRST,
  74.     ARG_STDBUFFERS,
  75.     ARG_FILEBUFFERS,
  76.     ARG_DATAEXT,
  77.     ARG_RESOURCEEXT,
  78.     ARG_SCANINTERVAL,
  79.     ARG_PLAYCDDA,
  80.     ARG_XPOS,
  81.     ARG_YPOS,
  82.     ARGCOUNT
  83.   };
  84.  
  85.   STRPTR Args[ARGCOUNT],Index;
  86.   UBYTE LocalBuffer[250];
  87.   struct RDArgs *ArgsPtr;
  88.   int result = FALSE,len,i;
  89.   int cnt;
  90.  
  91.   /* Clear the argument vector. */
  92.   memset (Args, 0, sizeof(Args));
  93.  
  94.   /* valid startup entry? */
  95.   if (!p_startup) {
  96.     Display_Error ("Filesystem startup entry invalid");
  97.     return FALSE;
  98.   }
  99.  
  100.   /* Get the contents of the startup field. */
  101.   len = ((STRPTR)(BADDR(p_startup)))[0];
  102.   if (len > sizeof (LocalBuffer) - 1)
  103.     len = sizeof (LocalBuffer) - 1;
  104.   memcpy (LocalBuffer, ((STRPTR)(BADDR(p_startup))) + 1, len);
  105.  
  106.   /* Provide null-termination. */
  107.   LocalBuffer[len] = 0;
  108.  
  109.   /* Remove leading quotes. */
  110.   for (i = 0 ; i < len ; i++) {
  111.     if (LocalBuffer[i] != ' ') {
  112.       if (LocalBuffer[i] == '\"')
  113.     LocalBuffer[i] = ' ';
  114.       break;
  115.     }
  116.   }
  117.  
  118.   /* Remove trailing quotes. */
  119.   for (i = len - 1 ; i >= 0 ; i--) {
  120.     if (LocalBuffer[i] != ' '){
  121.       if (LocalBuffer[i] == '\"')
  122.     LocalBuffer[i] = ' ';
  123.       break;
  124.     }
  125.   }
  126.  
  127.   /* Replace "-" by spaces, except "--" which is replaced by "-". */
  128.   Index = LocalBuffer;
  129.   for (i = 0 ; i < len ; i++) {
  130.     if (LocalBuffer[i] == '-') {
  131.       if (i+1 < len && LocalBuffer[i+1] == '-') {
  132.         *Index++ = '-';
  133.     i++;
  134.       } else
  135.         *Index++ = ' ';
  136.     } else
  137.       *Index++ = LocalBuffer[i];
  138.   }
  139.  
  140.   /* Provide null-termination. */
  141.   *Index = 0;
  142.  
  143.   /* Don't forget the newline, or ReadArgs won't work. */
  144.   strcat ((char *) LocalBuffer, "\n");
  145.  
  146.   if (ArgsPtr = (struct RDArgs *) AllocDosObjectTags (DOS_RDARGS,TAG_DONE)) {
  147.  
  148.     /* Don't prompt for input! */
  149.     ArgsPtr -> RDA_Flags |= RDAF_NOPROMPT;
  150.  
  151.     /* Set up for local parsing. */
  152.     ArgsPtr->RDA_Source.CS_Buffer = LocalBuffer;
  153.     ArgsPtr->RDA_Source.CS_Length = strlen ((char *) LocalBuffer);
  154.     ArgsPtr->RDA_Source.CS_CurChr = 0;
  155.  
  156.     /* Read the arguments. */
  157.     if (ReadArgs ((UBYTE *)
  158.                 "D=DEVICE,U=UNIT/N,C=CHIP/S,F=FAST/S,DMA/S,ANY/S,"
  159.           "L=LOWERCASE/S,ML=MAYBELOWERCASE/S,"
  160.              "R=ROCKRIDGE/S,T=TRACKDISK/S,"
  161.           "MI=MACTOISO/S,CS=CONVERTSPACES/S,"
  162.           "SV=SHOWVERSION/S,HF=HFSFIRST/S,"
  163.           "SB=STDBUFFERS/K/N,FB=FILEBUFFERS/K/N,"
  164.           "DE=DATAEXT/K,RE=RESOURCEEXT/K,"
  165.           "SI=SCANINTERVAL/K/N,PC=PLAYCDDA/K,"
  166.           "X=XPOS/K/N,Y=YPOS/K/N",
  167.           (LONG *) Args, ArgsPtr)) {
  168.       result = TRUE;
  169.  
  170.       if (Args[ARG_DEVICE]) {
  171.         len = strlen((char *) (Args[ARG_DEVICE]));
  172.  
  173.         if (len >= sizeof (g_device)) {
  174.        Display_Error ("Device name entry too long");
  175.        result = FALSE;
  176.         } else
  177.       strcpy (g_device, (char *) (Args[ARG_DEVICE]));
  178.       } else
  179.         Display_Error("Device name entry missing");
  180.  
  181.       g_unit = *(long *) (Args[ARG_UNIT]);
  182.  
  183.       g_memory_type = MEMF_CHIP;
  184.       cnt = 0;
  185.       if (Args[ARG_FAST] != NULL) {
  186.         g_memory_type = MEMF_FAST;
  187.     cnt++;
  188.       }
  189.       if (Args[ARG_CHIP] != NULL) {
  190.         g_memory_type = MEMF_CHIP;
  191.     cnt++;
  192.       }
  193.       if (Args[ARG_DMA] != NULL) {
  194.         g_memory_type = MEMF_24BITDMA;
  195.     cnt++;
  196.       }
  197.       if (Args[ARG_ANY] != NULL) {
  198.         g_memory_type = MEMF_ANY;
  199.     cnt++;
  200.       }
  201.       if (cnt > 1) {
  202.         Display_Error ("Only ONE memory option may be used!");
  203.     result = FALSE;
  204.       }
  205.  
  206.       g_map_to_lowercase = (Args[ARG_LOWERCASE] != NULL);
  207.       g_maybe_map_to_lowercase = (Args[ARG_MAYBELOWERCASE] != NULL);
  208.  
  209.       if (g_map_to_lowercase && g_maybe_map_to_lowercase) {
  210.         Display_Error ("Options L and ML are mutually exclusive!");
  211.     result = FALSE;
  212.       }
  213.  
  214.       g_use_rock_ridge = (Args[ARG_ROCKRIDGE] != NULL);
  215.       g_trackdisk = (Args[ARG_TRACKDISK] != NULL);
  216.       g_show_version_numbers = (Args[ARG_SHOWVERSION] != NULL);
  217.       g_hfs_first = (Args[ARG_HFSFIRST] != NULL);
  218.  
  219.       if (Args[ARG_STDBUFFERS]) {      
  220.         g_std_buffers = *(long *) (Args[ARG_STDBUFFERS]);
  221.         if (g_std_buffers <= 0) {
  222.           Display_Error ("Illegal number of standard buffers: %ld", g_std_buffers);
  223.       result = FALSE;
  224.         }
  225.       } else
  226.         g_std_buffers = 5;
  227.       
  228.       if (Args[ARG_FILEBUFFERS]) {
  229.         g_file_buffers = *(long *) (Args[ARG_FILEBUFFERS]);
  230.         if (g_file_buffers <= 0) {
  231.           Display_Error ("Illegal number of file buffers: %ld", g_std_buffers);
  232.       result = FALSE;
  233.         }
  234.       } else
  235.         g_file_buffers = 5;
  236.  
  237.       if (Args[ARG_DATAEXT])
  238.         strcpy (g_data_fork_extension, (char *) Args[ARG_DATAEXT]);
  239.  
  240.       if (Args[ARG_RESOURCEEXT])
  241.         strcpy (g_resource_fork_extension, (char *) Args[ARG_RESOURCEEXT]);
  242.  
  243.       g_convert_hfs_filenames = (Args[ARG_MACTOISO] != NULL);
  244.       g_convert_hfs_spaces = (Args[ARG_CONVERTSPACES] != NULL);
  245.  
  246.       if (Args[ARG_SCANINTERVAL]) {
  247.         g_scan_interval = *(long *) (Args[ARG_SCANINTERVAL]);
  248.         if (g_scan_interval < 0)
  249.           g_scan_interval = 0;
  250.       } else
  251.         g_scan_interval = 3;
  252.  
  253.       if (Args[ARG_PLAYCDDA]) {
  254.         len = strlen((char *) (Args[ARG_PLAYCDDA]));
  255.  
  256.         if (len >= sizeof (g_play_cdda_command)) {
  257.        Display_Error ("PLAYCDDA command name too long");
  258.        result = FALSE;
  259.         } else
  260.       strcpy (g_play_cdda_command, (char *) (Args[ARG_PLAYCDDA]));
  261.       } else
  262.         g_play_cdda_command[0] = 0;
  263.  
  264.       if (Args[ARG_XPOS])
  265.         g_xpos = *(long *) (Args[ARG_XPOS]);
  266.       if (Args[ARG_YPOS])
  267.         g_ypos = *(long *) (Args[ARG_YPOS]);
  268.  
  269.       FreeArgs(ArgsPtr);
  270.     } else {
  271.       Fault(IoErr (), (UBYTE *) "", LocalBuffer, sizeof (LocalBuffer));
  272.       Display_Error ("Error while parsing \"Startup\" field in Mountlist:\n%s",
  273.                    LocalBuffer + 2);
  274.     }
  275.  
  276.     FreeDosObject (DOS_RDARGS, ArgsPtr);
  277.   } else
  278.     Display_Error ("Out of memory");
  279.  
  280.   if (result) {
  281.     if (!(g_cd = Open_CDROM (g_device, g_unit, g_trackdisk, g_memory_type,
  282.                    g_std_buffers, g_file_buffers))) {
  283.       switch (g_cdrom_errno) {
  284.       case CDROMERR_NO_MEMORY:
  285.         Display_Error ("Out of memory: cannot allocate buffers\n"
  286.                "(Try CHIP, FAST, DMA or ANY option.)");
  287.         break;
  288.       case CDROMERR_MSGPORT:
  289.         Display_Error ("Cannot open the message port.");
  290.         break;
  291.       case CDROMERR_IOREQ:
  292.         Display_Error ("Cannot open the I/O request structure.");
  293.         break;
  294.       case CDROMERR_DEVICE:
  295.         Display_Error ("Cannot open \"%s\" unit %ld", g_device, (int) g_unit);
  296.         break;
  297.       case CDROMERR_BLOCKSIZE:
  298.         Display_Error ("Cannot access CDROM drive: illegal blocksize.");
  299.     break;
  300.       default:
  301.         break;
  302.       }
  303.       result = FALSE;
  304.     }
  305.   }
  306.  
  307.   return result;
  308. }
  309.  
  310. int Handle_Control_Packet (ULONG p_type, ULONG p_par1, ULONG p_par2)
  311. {
  312.   switch (p_type) {
  313.   case CDCMD_LOWERCASE:
  314.     g_map_to_lowercase = p_par1;
  315.     break;
  316.   case CDCMD_MACTOISO:
  317.     g_convert_hfs_filenames = p_par1;
  318.     break;
  319.   case CDCMD_CONVERTSPACES:
  320.     g_convert_hfs_spaces = p_par1;
  321.     break;
  322.   case CDCMD_SHOWVERSION:
  323.     g_show_version_numbers = p_par1;
  324.     break;
  325.   case CDCMD_HFSFIRST:
  326.     g_hfs_first = p_par1;
  327.     break;
  328.   case CDCMD_DATAEXT:
  329.     strcpy (g_data_fork_extension, (char *) p_par1);
  330.     break;
  331.   case CDCMD_RESOURCEEXT:
  332.     strcpy (g_resource_fork_extension, (char *) p_par1);
  333.     break;
  334.   default:
  335.     return 999;
  336.   }
  337.   return 0;
  338. }
  339.  
  340. #ifdef _DCC
  341. extern void debugproc (void);
  342. #if defined(NDEBUG) && !defined(DEBUG_SECTORS)
  343. void debugmain (void) {;}
  344. #endif
  345. #endif
  346.  
  347. #if !defined(NDEBUG) || defined(DEBUG_SECTORS)
  348.  
  349. char *typetostr (int ty)
  350. {
  351.     switch(ty) {
  352.     case ACTION_DIE:        return("DIE");
  353.     case ACTION_FINDUPDATE:     return("OPEN-RW");
  354.     case ACTION_FINDINPUT:    return("OPEN-OLD");
  355.     case ACTION_FINDOUTPUT:    return("OPEN-NEW");
  356.     case ACTION_READ:        return("READ");
  357.     case ACTION_WRITE:        return("WRITE");
  358.     case ACTION_END:        return("CLOSE");
  359.     case ACTION_SEEK:        return("SEEK");
  360.     case ACTION_EXAMINE_NEXT:    return("EXAMINE NEXT");
  361.     case ACTION_EXAMINE_OBJECT: return("EXAMINE OBJ");
  362.     case ACTION_INFO:        return("INFO");
  363.     case ACTION_DISK_INFO:    return("DISK INFO");
  364.     case ACTION_PARENT:     return("PARENTDIR");
  365.     case ACTION_DELETE_OBJECT:    return("DELETE");
  366.     case ACTION_CREATE_DIR:    return("CREATEDIR");
  367.     case ACTION_LOCATE_OBJECT:    return("LOCK");
  368.     case ACTION_COPY_DIR:    return("DUPLOCK");
  369.     case ACTION_FREE_LOCK:    return("FREELOCK");
  370.     case ACTION_SET_PROTECT:    return("SETPROTECT");
  371.     case ACTION_SET_COMMENT:    return("SETCOMMENT");
  372.     case ACTION_RENAME_OBJECT:    return("RENAME");
  373.     case ACTION_INHIBIT:    return("INHIBIT");
  374.     case ACTION_RENAME_DISK:    return("RENAME DISK");
  375.     case ACTION_MORE_CACHE:    return("MORE CACHE");
  376.     case ACTION_WAIT_CHAR:    return("WAIT FOR CHAR");
  377.     case ACTION_FLUSH:        return("FLUSH");
  378.     case ACTION_SCREEN_MODE:    return("SCREENMODE");
  379.     case ACTION_IS_FILESYSTEM:    return("IS_FILESYSTEM");
  380.     case ACTION_SAME_LOCK:      return("SAME_LOCK");
  381.     case ACTION_COPY_DIR_FH:    return("COPY_DIR_FH");
  382.     case ACTION_PARENT_FH:      return("PARENT_FH");
  383.     case ACTION_EXAMINE_FH:     return("EXAMINE_FH");
  384.     case ACTION_FH_FROM_LOCK:   return("FH_FROM_LOCK");
  385.     case ACTION_CURRENT_VOLUME: return("CURRENT_VOLUME");
  386.     case ACTION_READ_LINK:    return("READ LINK");
  387.     case ACTION_USER:        return("USER");
  388.     default:            return("---------UNKNOWN-------");
  389.     }
  390. }
  391.  
  392. /*
  393.  *  DEBUGGING CODE.    You cannot make DOS library calls that access other
  394.  *  devices from within a DOS device driver because they use the same
  395.  *  message port as the driver.  If you need to make such calls you must
  396.  *  create a port and construct the DOS messages yourself.  I do not
  397.  *  do this.  To get debugging info out another PROCESS is created to which
  398.  *  debugging messages can be sent.
  399.  *
  400.  *  You want the priority of the debug process to be larger than the
  401.  *  priority of your DOS handler.  This is so if your DOS handler crashes
  402.  *  you have a better idea of where it died from the debugging messages
  403.  *  (remember that the two processes are asyncronous from each other).
  404.  */
  405.  
  406. /*
  407.  *  BTW, the DOS library used by debugmain() was actually opened by
  408.  *  the device driver.    Note: DummyMsg cannot be on debugmain()'s stack
  409.  *  since debugmain() goes away on the final handshake.
  410.  */
  411.  
  412. #ifdef LATTICE
  413. void __saveds debugmain (void)
  414. #else
  415. void debugmain (void)
  416. #endif    /* LATTICE */
  417. {
  418.     MSG *msg;
  419.     short len;
  420.     void *fh;
  421. #ifdef LOG_MESSAGES
  422.     void *out;
  423. #endif
  424.  
  425. #ifdef AZTEC_C
  426.     extern void geta4 (void);
  427.  
  428.     geta4();
  429. #endif
  430.  
  431.     Dbport = CreateMsgPort ();
  432.     fh = (void *) Open ((UBYTE *) "con:0/0/640/100/debugwindow", 1006);
  433.     PutMsg(Dback, &DummyMsg);
  434. #ifdef LOG_MESSAGES
  435. #ifdef LOG_TO_PAR
  436.     out = (void *) Open ((UBYTE *) "PAR:", 1006);
  437. #else
  438.     out = (void *) Open ((UBYTE *) "ram:cd.log", 1006);
  439. #endif
  440. #endif
  441.     for (;;) {
  442.     WaitPort(Dbport);
  443.     msg = GetMsg(Dbport);
  444.     len = msg->mn_Length;
  445.     if (len == 0)
  446.         break;
  447.     --len;                  /*  Fix length up   */
  448.     Write((BPTR) fh, msg+1, len);
  449. #ifdef LOG_MESSAGES
  450.     Write((BPTR) out, msg+1, len);
  451. #endif
  452.     FreeMem(msg,sizeof(MSG)+len+1);
  453.     }
  454.     Close ((BPTR) fh);
  455. #ifdef LOG_MESSAGES
  456.     Close ((BPTR) out);
  457. #endif
  458.     DeleteMsgPort(Dbport);
  459.     PutMsg(Dback,&DummyMsg);          /*  Kill handshake  */
  460. }
  461.  
  462. void dbinit (void)
  463. {
  464.     TASK *task = FindTask(NULL);
  465.  
  466.     Dback = CreateMsgPort();
  467.     if (CreateNewProcTags (
  468. #ifdef _DCC
  469.                NP_Seglist, (BPTR) (CTOB(debugproc)),
  470. #else
  471.                NP_Entry, debugmain,
  472. #endif
  473.                    NP_Name, "DEV_DB",
  474.                       NP_Priority, task->tc_Node.ln_Pri+1,
  475.                       NP_StackSize, 4096,
  476.                       TAG_DONE)) {
  477.       WaitPort(Dback);                    /* handshake startup    */
  478.       GetMsg(Dback);                    /* remove dummy msg     */
  479.       dbprintf("Debugger running: %s, %s\n", TheVersion+6, __TIME__);
  480.     };
  481. }
  482.  
  483. void dbuninit (void)
  484. {
  485.     MSG killmsg;
  486.  
  487.     if (Dbport) {
  488.     killmsg.mn_Length = 0;        /*    0 means die        */
  489.     PutMsg(Dbport,&killmsg);
  490.     WaitPort(Dback);        /*    He's dead jim!      */
  491.     GetMsg(Dback);
  492.     DeleteMsgPort(Dback);
  493.  
  494.     /*
  495.      *  Since the debug process is running at a greater priority, I
  496.      *  am pretty sure that it is guarenteed to be completely removed
  497.      *  before this task gets control again.  Still, it doesn't hurt...
  498.      */
  499.  
  500.     Delay(100);            /*    ensure he's dead    */
  501.     }
  502. }
  503.  
  504. void dbprintf (char *format, ...)
  505. {
  506.     va_list arg;
  507.     char buf[256];
  508.     MSG *msg;
  509.  
  510.     va_start (arg, format);
  511.     if (Dbport && !DBDisable) {
  512.     vsprintf (buf, format, arg);
  513.     msg = AllocMem(sizeof(MSG)+strlen(buf)+1, MEMF_PUBLIC|MEMF_CLEAR);
  514.     msg->mn_Length = strlen(buf)+1;     /*    Length NEVER 0    */
  515.     strcpy((char *) (msg+1), buf);
  516.     PutMsg(Dbport,msg);
  517.     }
  518.     va_end (arg);
  519. }
  520.  
  521. #endif /* !NDEBUG || DEBUG_SECTORS */
  522.