home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 58 / af058sub.adf / fmsdisk2.lha / src / fms.c < prev    next >
C/C++ Source or Header  |  1990-04-17  |  9KB  |  432 lines

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