home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 458.lha / fmsdisk_v3.0 / fms.c < prev    next >
C/C++ Source or Header  |  1990-12-12  |  10KB  |  463 lines

  1. /*
  2.  *  FMS.C
  3.  *
  4.  *  File Disk Device (fmsdisk.device)
  5.  *
  6.  *  Simulates a trackdisk by using a large file to hold the 'blocks'.
  7.  */
  8.  
  9. #include <exec/types.h>
  10. #include <exec/nodes.h>
  11. #include <exec/errors.h>
  12. #include <exec/memory.h>
  13. #include <exec/libraries.h>
  14. #include <devices/trackdisk.h>
  15. #include <libraries/dos.h>
  16. #include <libraries/dosextens.h>
  17. #ifdef LATTICE
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <proto/dos.h>
  21. #include <proto/exec.h>
  22. #endif
  23.  
  24. #define CMD_OPENUNIT    (0x7FF0 & ~TDF_EXTCOM)
  25. #define CMD_CLOSEUNIT    (0x7FF1 & ~TDF_EXTCOM)
  26. #define CMD_KILLPROC    (0x7FF2 & ~TDF_EXTCOM)
  27.  
  28. #define EXT_CHUNK   4096
  29.  
  30. void SynchroMsg();
  31. void ExtendSize();
  32.  
  33. extern int TagDevOpen();
  34. extern int TagDevClose();
  35. extern int TagDevExpunge();
  36. extern int TagDevBeginIO();
  37. extern int TagDevAbortIO();
  38.  
  39. typedef struct Library    LIB;
  40. typedef struct Device    DEV;
  41. typedef struct Process    PROC;
  42. typedef struct MsgPort    PORT;
  43. typedef struct Message    MSG;
  44. typedef struct List    LIST;
  45. typedef struct Node    NODE;
  46. typedef long (*func_ptr)();
  47.  
  48. typedef struct {
  49.     struct  Unit U;
  50.     UWORD   OpenCnt;
  51.     long    Fh;     /*  file handle         */
  52.     long    Size;    /*  current size        */
  53.     long    Pos;    /*  current position        */
  54.     char    Extended;    /*  file has been extended  */
  55.     char    Reserved;
  56. } NDUnit;
  57.  
  58. typedef struct {
  59.     LIB     Lib;
  60.     NDUnit  Unit[32];
  61. } NDev;
  62.  
  63. typedef struct {
  64.     struct  Message io_Message;
  65.     struct  Device  *io_Device;     /* device node pointer  */
  66.     struct  Unit    *io_Unit;        /* unit (driver private)*/
  67.     UWORD   io_Command;         /* device command */
  68.     UBYTE   io_Flags;
  69.     BYTE    io_Error;            /* error or warning num */
  70.     ULONG   io_Actual;            /* actual number of bytes transferred */
  71.     ULONG   io_Length;            /* requested number bytes transferred*/
  72.     APTR    io_Data;            /* points to data area */
  73.     ULONG   io_Offset;            /* offset for block structured devices */
  74.  
  75.     long    iotd_Count;         /*    (extension)     */
  76.     long    iotd_SecLabel;        /*    (extension)     */
  77. } IOB;
  78.  
  79. extern char DeviceName[];
  80. extern char IdString[];
  81. extern void DUMmySeg();
  82.  
  83. long SysBase           = NULL;
  84. struct DosLibrary *DOSBase = NULL;
  85. NDev *DevBase           = NULL;
  86. APTR DevSegment        = NULL;
  87. PORT *FProc           = NULL;
  88. PORT FPort;
  89.  
  90. NDev *
  91. Init(seg)
  92. APTR seg;
  93. {
  94.     static func_ptr DevVectors[] = {
  95.     (func_ptr)TagDevOpen,
  96.     (func_ptr)TagDevClose,
  97.     (func_ptr)TagDevExpunge,
  98.     NULL,
  99.     (func_ptr)TagDevBeginIO,
  100.     (func_ptr)TagDevAbortIO,
  101.     (func_ptr)-1
  102.     };
  103.     NDev *db;
  104.  
  105.  
  106.     SysBase = *(long *)4;
  107.     DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0);
  108.  
  109.     DevBase = db = (NDev *)MakeLibrary((long **)DevVectors,NULL,NULL,sizeof(NDev),NULL);
  110.     db->Lib.lib_Node.ln_Type = NT_DEVICE;
  111.     db->Lib.lib_Node.ln_Name = DeviceName;
  112.     db->Lib.lib_Flags = LIBF_CHANGED|LIBF_SUMUSED;
  113.     db->Lib.lib_Version = 1;
  114.     db->Lib.lib_IdString= (APTR)IdString;
  115.  
  116.     DevSegment = seg;
  117.     AddDevice((DEV *)db);
  118.     return(db);
  119. }
  120.  
  121. NDev *
  122. DevOpen(unitnum, iob, flags)
  123. long unitnum;
  124. IOB  *iob;
  125. long flags;
  126. {
  127.     NDev *nd = DevBase;
  128.     NDUnit *unit = &nd->Unit[unitnum];
  129.  
  130.     if (++nd->Lib.lib_OpenCnt == 1) {
  131.     FProc = CreateProc("FMS-Dummy", 0, (long)DUMmySeg >> 2, 4096);
  132.     FPort.mp_SigBit = SIGBREAKB_CTRL_D;    /*  port init */
  133.     FPort.mp_SigTask= FProc->mp_SigTask;
  134.     FPort.mp_Flags = PA_SIGNAL;
  135.     NewList(&FPort.mp_MsgList);
  136.     }
  137.  
  138.     if (++unit->OpenCnt == 1)
  139.     SynchroMsg(CMD_OPENUNIT, unit);
  140.  
  141.     nd->Lib.lib_Flags &= ~LIBF_DELEXP;
  142.     iob->io_Unit = (struct Unit *)unit;
  143.     iob->io_Error = 0;
  144.     return(nd);
  145. }
  146.  
  147.  
  148. APTR
  149. DevExpunge()
  150. {
  151.     NDev *nd = DevBase;
  152.  
  153.     if (DevSegment == NULL)
  154.     Alert(24, (char *)24);
  155.     if (nd->Lib.lib_OpenCnt) {
  156.     nd->Lib.lib_Flags |= LIBF_DELEXP;
  157.     return(NULL);
  158.     }
  159.     Remove((NODE *)nd);
  160.     FreeMem((char *)nd - nd->Lib.lib_NegSize, nd->Lib.lib_NegSize + nd->Lib.lib_PosSize);
  161.     DevSegment = NULL;
  162.     return(DevSegment);
  163. }
  164.  
  165. APTR
  166. DevClose(iob)
  167. IOB *iob;
  168. {
  169.     NDev *nd = DevBase;
  170.  
  171.     {
  172.     NDUnit *unit = (NDUnit *)iob->io_Unit;
  173.     if (unit->OpenCnt && --unit->OpenCnt == 0)
  174.         SynchroMsg(CMD_CLOSEUNIT, unit);
  175.     }
  176.  
  177.     if (nd->Lib.lib_OpenCnt && --nd->Lib.lib_OpenCnt)
  178.     return(NULL);
  179.     if (FProc) {
  180.     SynchroMsg(CMD_KILLPROC, NULL);
  181.     FProc = NULL;
  182.     }
  183.     if (nd->Lib.lib_Flags & LIBF_DELEXP)
  184.     return(DevExpunge());
  185.     /*
  186.      *    close down resources
  187.      */
  188.     return(NULL);
  189. }
  190.  
  191. void
  192. DevBeginIO(iob)
  193. IOB *iob;
  194. {
  195.     /*NDev *nd = DevBase;*/
  196.  
  197.     iob->io_Error = 0;
  198.     iob->io_Actual = 0;
  199.  
  200.     switch(iob->io_Command & ~TDF_EXTCOM) {
  201.     case CMD_INVALID:
  202.     iob->io_Error = IOERR_NOCMD;
  203.     break;
  204.     case CMD_RESET:
  205.     break;
  206.     case CMD_READ:
  207.     PutMsg(&FPort, &iob->io_Message);
  208.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  209.     iob = NULL;
  210.     break;
  211.     case CMD_WRITE:
  212.     PutMsg(&FPort, &iob->io_Message);
  213.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  214.     iob = NULL;
  215.     break;
  216.     case CMD_UPDATE:
  217.     break;
  218.     case CMD_CLEAR:
  219.     break;
  220.     case CMD_STOP:
  221.     break;
  222.     case CMD_START:
  223.     break;
  224.     case CMD_FLUSH:
  225.     break;
  226.     case TD_MOTOR:        /*    motor,    no action   */
  227.     case TD_SEEK:        /*    seek,    no action   */
  228.     break;
  229.     case TD_FORMAT:        /*    format            */
  230.     PutMsg(&FPort, &iob->io_Message);
  231.     iob->io_Flags &= ~IOF_QUICK;    /*  not quick */
  232.     iob = NULL;
  233.     break;
  234.     case TD_REMOVE:        /*    not supported        */
  235.     iob->io_Error = IOERR_NOCMD;
  236.     break;
  237.     case TD_CHANGENUM:        /*    change count never changes  */
  238.     iob->io_Actual = 1;
  239.     break;
  240.     case TD_CHANGESTATE:    /*    0=disk in drive     */
  241.     iob->io_Actual = 0;
  242.     break;
  243.     case TD_PROTSTATUS:     /*    io_Actual -> 0 (rw) */
  244.     iob->io_Actual = 0;
  245.     break;
  246.     case TD_RAWREAD:        /*    not supported        */
  247.     case TD_RAWWRITE:
  248.     iob->io_Error = IOERR_NOCMD;
  249.     break;
  250.     case TD_GETDRIVETYPE:   /*    drive type?        */
  251.     iob->io_Actual = 0;
  252.     break;
  253.     case TD_GETNUMTRACKS:
  254.     iob->io_Actual = 0; /*    # of tracks?        */
  255.     break;
  256.     case TD_ADDCHANGEINT:   /*    action never taken  */
  257.     case TD_REMCHANGEINT:
  258.     break;
  259.     default:
  260.     iob->io_Error = IOERR_NOCMD;
  261.     break;
  262.     }
  263.     if (iob) {
  264.     if ((iob->io_Flags & IOF_QUICK) == 0)
  265.         ReplyMsg((MSG *)iob);
  266.     }
  267. }
  268.  
  269. void
  270. DevAbortIO(iob)
  271. IOB *iob;
  272. {
  273.  
  274. }
  275.  
  276.  
  277. /*
  278.  *  Server communications
  279.  */
  280.  
  281. void
  282. SynchroMsg(cmd, unit)
  283. UWORD cmd;
  284. struct Unit *unit;
  285. {
  286.     IOB Iob;
  287.  
  288.     Iob.io_Message.mn_ReplyPort = CreatePort(NULL, 0);
  289.     Iob.io_Command = cmd;
  290.     Iob.io_Unit = unit;
  291.  
  292.     PutMsg(&FPort, &Iob.io_Message);
  293.     WaitPort(Iob.io_Message.mn_ReplyPort);
  294.     DeletePort(Iob.io_Message.mn_ReplyPort);
  295. }
  296.  
  297. /*
  298.  *    SERVER SIDE (IS A PROCESS)
  299.  *
  300.  *    File name is:
  301.  */
  302.  
  303. void
  304. CoProc()
  305. {
  306.     IOB *iob;
  307.     NDUnit *unit;
  308.     char buf[128];
  309.     char notdone = 1;
  310. #ifdef DEBUG
  311.     long fh = Open("con:0/0/640/102/Debug", 1006);
  312. #endif
  313.  
  314.     Wait(SIGBREAKF_CTRL_D);     /*  wait for port init  */
  315.  
  316.     while (notdone) {
  317.     WaitPort(&FPort);
  318.     while (iob = (IOB *)GetMsg(&FPort)) {
  319.         unit = (NDUnit *)iob->io_Unit;
  320.  
  321. #ifdef DEBUG
  322.         sprintf(buf, "Cmd %08lx/%04x @ %08lx Buf %08lx %04x\n", unit,
  323.         iob->io_Command, iob->io_Offset, iob->io_Data, iob->io_Length
  324.         );
  325.         Write(fh, buf, strlen(buf));
  326. #endif
  327.         switch(iob->io_Command & ~TDF_EXTCOM) {
  328.         case CMD_OPENUNIT:
  329. #ifdef LATTICE
  330.         strcpy(buf, "FMS:Unit");
  331.         stci_d(&buf[strlen(buf)], unit - &DevBase->Unit[0]);
  332. #else
  333.         sprintf(buf, "FMS:Unit%d", unit - &DevBase->Unit[0]);
  334. #endif
  335.         unit->Fh = Open(buf, 1005);
  336.         if (unit->Fh == NULL) {
  337.             unit->Fh = Open(buf, 1006);
  338.             unit->Extended = 1;
  339.         }
  340. #ifdef DEBUG
  341.         Write(fh, "OPEN ", 5);
  342.         Write(fh, buf, strlen(buf));
  343.         Write(fh, "\n", 1);
  344. #endif
  345.         if (unit->Fh) {
  346.             Seek(unit->Fh, 0L, OFFSET_END);
  347.             unit->Size = Seek(unit->Fh, 0L, OFFSET_BEGINNING);
  348.         }
  349.         unit->Pos = -1;
  350.         break;
  351.         case CMD_CLOSEUNIT:
  352.         if (unit->Fh) {
  353.             Close(unit->Fh);
  354.             unit->Fh = NULL;
  355.         }
  356.         break;
  357.         case CMD_KILLPROC:
  358.         notdone = 0;
  359.         break;
  360.         case CMD_READ:
  361.         if (unit->Fh == NULL)
  362.             break;
  363.         if (iob->io_Offset + iob->io_Length > unit->Size)
  364.             ExtendSize(unit, iob->io_Offset + iob->io_Length);
  365.         if (unit->Pos != iob->io_Offset) {
  366. #ifdef DEBUG
  367.             sprintf(buf, "READ: Seeking %ld bytes from current.\n",
  368.                 ((long)iob->io_Offset - (long)unit->Pos));
  369.             Write(fh, buf, strlen(buf));
  370. #endif
  371.             if (unit->Pos >= 0) {
  372.               Seek(unit->Fh, ((long)iob->io_Offset - (long)unit->Pos),
  373.                OFFSET_CURRENT);
  374.             } else {
  375.               Seek(unit->Fh, iob->io_Offset, OFFSET_BEGINNING);
  376.             }
  377.         }
  378.         iob->io_Actual = Read(unit->Fh, (char *)iob->io_Data, iob->io_Length);
  379.         if (iob->io_Actual == iob->io_Length)
  380.             unit->Pos = iob->io_Offset + iob->io_Actual;
  381.         else
  382.             unit->Pos = -1;
  383.         break;
  384.         case CMD_WRITE:
  385.         /*
  386.          *  This causes file to be closed/reopened after
  387.          *  formatting.
  388.          */
  389.         if (unit->Extended && unit->Fh) {
  390.             Close(unit->Fh);
  391. #ifdef LATTICE
  392.             strcpy(buf, "FMS:Unit");
  393.             stci_d(&buf[strlen(buf)], unit - &DevBase->Unit[0]);
  394. #else
  395.             sprintf(buf, "FMS:Unit%d", unit - &DevBase->Unit[0]);
  396. #endif
  397.             unit->Fh = Open(buf, 1005);
  398.             unit->Extended = 0;
  399.             unit->Pos = 0;
  400.         }
  401.         /* fall through */
  402.         case TD_FORMAT:
  403.         if (unit->Fh == NULL)
  404.             break;
  405.  
  406.         if (iob->io_Offset > unit->Size)
  407.             ExtendSize(unit, iob->io_Offset);
  408.         if (unit->Pos != iob->io_Offset) {
  409. #ifdef DEBUG
  410.             sprintf(buf, "WRITE: Seeking %ld bytes from current.\n",
  411.                 ((long)iob->io_Offset - (long)unit->Pos));
  412.             Write(fh, buf, strlen(buf));
  413. #endif
  414.             if (unit->Pos >= 0) {
  415.               Seek(unit->Fh, ((long)iob->io_Offset - (long)unit->Pos),
  416.                OFFSET_CURRENT);
  417.             } else {
  418.               Seek(unit->Fh, iob->io_Offset, OFFSET_BEGINNING);
  419.             }
  420.         }
  421.         iob->io_Actual = Write(unit->Fh, (char *)iob->io_Data, iob->io_Length);
  422.         if (iob->io_Actual == iob->io_Length)
  423.             unit->Pos = iob->io_Offset + iob->io_Actual;
  424.         else
  425.             unit->Pos = -1;
  426.         break;
  427.         }
  428.  
  429.         if (notdone == 0)       /*  forbid before falling through */
  430.         Forbid();           /*  and esp before replying       */
  431.         ReplyMsg(&iob->io_Message);
  432.     }
  433.     }
  434.     /* fall through to exit */
  435. }
  436.  
  437. /*
  438.  *  Extend the file size in 4K chunks
  439.  */
  440.  
  441. void
  442. ExtendSize(unit, offset)
  443. NDUnit *unit;
  444. long offset;
  445. {
  446.     long pos;
  447.     char *buf = AllocMem(EXT_CHUNK, MEMF_CLEAR|MEMF_PUBLIC);
  448.  
  449.     if (buf) {
  450.     if (unit->Extended == 0)
  451.         unit->Extended = 1;
  452.     Seek(unit->Fh, 0L, OFFSET_END);
  453.     pos = Seek(unit->Fh, 0L, OFFSET_CURRENT);
  454.     unit->Pos = pos;
  455.     while (pos < offset) {
  456.         if (Write(unit->Fh, buf, EXT_CHUNK) != EXT_CHUNK)
  457.         break;
  458.         pos += EXT_CHUNK;
  459.     }
  460.     FreeMem(buf, EXT_CHUNK);
  461.     }
  462. }
  463.