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