home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / disk / Devs+Handler / Device-Handler / Source / Dev.c next >
Encoding:
C/C++ Source or Header  |  1994-07-05  |  7.8 KB  |  340 lines

  1.  
  2. #include <exec/memory.h>
  3. #include <exec/execbase.h>
  4. #include <devices/trackdisk.h>
  5. #include <dos/dosextens.h>
  6. #include <dos/filehandler.h>
  7.  
  8. #define __USE_SYSBASE 42
  9.  
  10. #include <proto/exec.h>
  11.  
  12. #include <string.h>
  13.  
  14. struct DosPacket *WaitDosPacket(void);
  15. void __regargs ReplyDosPacket(struct DosPacket *,LONG,LONG);
  16.  
  17. void __regargs OpenDH(struct DosPacket *,ULONG *);
  18. void __regargs CloseDH(struct DHHandle *,ULONG *);
  19.  
  20. LONG __regargs RawRead(struct DHHandle *,UBYTE *,LONG);
  21. LONG __regargs RawWrite(struct DHHandle *,UBYTE *,LONG);
  22.  
  23. struct ExecBase *SysBase;
  24.  
  25. struct DHHandle
  26.  {
  27.   struct IOStdReq *rh_IO;
  28.   struct DriveGeometry rh_DG;
  29.   ULONG rh_Len,rh_Pos,rh_Left;
  30.   UBYTE *rh_Buffer,*rh_Ptr;
  31.   BOOL rh_Write;
  32.  };
  33.  
  34. #define BCPL_MAX_LEN 256
  35. #define MIN __builtin_min
  36.  
  37. char *Version = "$VER: Device-Handler 1.0 "__AMIGADATE__;
  38.  
  39. LONG __saveds DeviceHandler(void)
  40.  
  41. {
  42.  struct Process *MyProc;
  43.  struct DosPacket *Pkt;
  44.  struct DeviceNode *DeviceNode;
  45.  BOOL Done;
  46.  ULONG OpenCnt;
  47.  
  48.  SysBase=*(struct ExecBase **)4L;
  49.  if ((MyProc=(struct Process *)SysBase->ThisTask)->pr_CLI) return 20L;
  50.  
  51.  Pkt=WaitDosPacket();
  52.  DeviceNode=(struct DeviceNode *)BADDR(Pkt->dp_Arg3);
  53.  if (SysBase->LibNode.lib_Version<37)
  54.   {
  55.    ReplyDosPacket (Pkt,DOSFALSE,0L);
  56.    return 0L;
  57.   }
  58.  
  59.  DeviceNode->dn_Task=&MyProc->pr_MsgPort;
  60.  ReplyDosPacket (Pkt,DOSTRUE,Pkt->dp_Res2);
  61.  
  62.  Done=FALSE;
  63.  OpenCnt=0L;
  64.  
  65.  while (!Done)
  66.   {
  67.    Pkt=WaitDosPacket();
  68.  
  69.    switch (Pkt->dp_Type)
  70.     {
  71.      case ACTION_FINDINPUT:
  72.       OpenDH (Pkt,&OpenCnt);
  73.       ReplyDosPacket (Pkt,Pkt->dp_Res1,Pkt->dp_Res2);
  74.       break;
  75.      case ACTION_FINDOUTPUT:
  76.       OpenDH (Pkt,&OpenCnt);
  77.       ReplyDosPacket (Pkt,Pkt->dp_Res1,Pkt->dp_Res2);
  78.       break;
  79.      case ACTION_END:
  80.       CloseDH ((struct DHHandle *)Pkt->dp_Arg1,&OpenCnt);
  81.       ReplyDosPacket (Pkt,DOSTRUE,0L);
  82.       break;
  83.      case ACTION_READ:
  84.       if (!((struct DHHandle *)Pkt->dp_Arg1)->rh_Write)
  85.        {
  86.         LONG Bytes;
  87.  
  88.         Bytes=RawRead((struct DHHandle *)Pkt->dp_Arg1,(UBYTE *)Pkt->dp_Arg2,Pkt->dp_Arg3);
  89.         if (Bytes<0L) ReplyDosPacket (Pkt,-1L,ERROR_SEEK_ERROR);
  90.         else ReplyDosPacket (Pkt,Bytes,0L);
  91.        }
  92.       else ReplyDosPacket (Pkt,-1L,ERROR_OBJECT_WRONG_TYPE);
  93.       break;
  94.      case ACTION_WRITE:
  95.       if (((struct DHHandle *)Pkt->dp_Arg1)->rh_Write)
  96.        {
  97.         LONG Bytes;
  98.  
  99.         Bytes=RawWrite((struct DHHandle *)Pkt->dp_Arg1,(UBYTE *)Pkt->dp_Arg2,Pkt->dp_Arg3);
  100.         if (Bytes<0L) ReplyDosPacket (Pkt,-1L,ERROR_SEEK_ERROR);
  101.         else ReplyDosPacket (Pkt,Bytes,0L);
  102.        }
  103.       else ReplyDosPacket (Pkt,-1L,ERROR_OBJECT_WRONG_TYPE);
  104.       break;
  105.      case ACTION_IS_FILESYSTEM:
  106.       ReplyDosPacket (Pkt,DOSFALSE,0L);
  107.       break;
  108.      default:
  109.       ReplyDosPacket (Pkt,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
  110.     }
  111.  
  112.    if (OpenCnt==0L)
  113.     {
  114.      Disable();
  115.      if (MyProc->pr_MsgPort.mp_MsgList.lh_Head->ln_Succ==NULL)
  116.       {
  117.        DeviceNode->dn_Task=NULL;
  118.        Done=TRUE;
  119.       }
  120.      Enable();
  121.     }
  122.   }
  123.  
  124.  return 0L;
  125. }
  126.  
  127. struct DosPacket *WaitDosPacket(void)
  128.  
  129. {
  130.  struct Process *MyProc;
  131.  
  132.  MyProc=(struct Process *)SysBase->ThisTask;
  133.  (void)WaitPort(&MyProc->pr_MsgPort);
  134.  return (struct DosPacket *)GetMsg(&MyProc->pr_MsgPort)->mn_Node.ln_Name;
  135. }
  136.  
  137. void __regargs ReplyDosPacket(struct DosPacket *Packet,LONG Res1,LONG Res2)
  138.  
  139. {
  140.  struct MsgPort *ReplyPort;
  141.  
  142.  ReplyPort=Packet->dp_Port;
  143.  Packet->dp_Port=&((struct Process *)SysBase->ThisTask)->pr_MsgPort;
  144.  Packet->dp_Link->mn_Node.ln_Name=(char *)Packet;
  145.  Packet->dp_Res1=Res1;
  146.  Packet->dp_Res2=Res2;
  147.  
  148.  PutMsg (ReplyPort,Packet->dp_Link);
  149. }
  150.  
  151. void __regargs OpenDH(struct DosPacket *Pkt,ULONG *OpenCnt)
  152.  
  153. {
  154.  struct FileHandle *FH;
  155.  UBYTE *BStr,Name[BCPL_MAX_LEN],*Ptr;
  156.  ULONG Unit;
  157.  struct DHHandle *RH;
  158.  struct MsgPort *IOPort;
  159.  
  160.  Pkt->dp_Res1=DOSFALSE;
  161.  FH=(struct FileHandle *)BADDR(Pkt->dp_Arg1);
  162.  FH->fh_Port=(struct MsgPort *)FALSE;
  163.  FH->fh_Arg1=0L;
  164.  
  165.  BStr=(UBYTE *)BADDR(Pkt->dp_Arg3);
  166.  (void)memcpy(Name,&BStr[1],BStr[0]);
  167.  Name[BStr[0]]='\0';
  168.  
  169.  if (Ptr=strchr(Name,':')) (void)strcpy(Name,Ptr+1L);
  170.  if ((Ptr=strchr(Name,'/'))==NULL)
  171.   {
  172.    Pkt->dp_Res2=ERROR_BAD_STREAM_NAME;
  173.    return;
  174.   }
  175.  *Ptr++='\0';
  176.  
  177.  if ((Name[0]=='\0')||(*Ptr=='\0'))
  178.   {
  179.    Pkt->dp_Res2=ERROR_BAD_STREAM_NAME;
  180.    return;
  181.   }
  182.  
  183.  Unit=0L;
  184.  while (*Ptr)
  185.   if ((*Ptr<'0')||(*Ptr>'9'))
  186.    {
  187.     Pkt->dp_Res2=ERROR_BAD_NUMBER;
  188.     return;
  189.    }
  190.   else Unit=10L*Unit+(*Ptr++-'0');
  191.  
  192.  Pkt->dp_Res2=ERROR_NO_FREE_STORE;
  193.  if (RH=AllocVec(sizeof(struct DHHandle),MEMF_PUBLIC|MEMF_CLEAR))
  194.   {
  195.    if (IOPort=CreateMsgPort())
  196.     {
  197.      if (RH->rh_IO=CreateStdIO(IOPort))
  198.       {
  199.        if (OpenDevice(Name,Unit,(struct IORequest *)RH->rh_IO,0L)==0L)
  200.         {
  201.          RH->rh_IO->io_Command=TD_GETGEOMETRY;
  202.          RH->rh_IO->io_Length=sizeof(struct DriveGeometry);
  203.          RH->rh_IO->io_Data=&RH->rh_DG;
  204.          if (DoIO((struct IORequest *)RH->rh_IO)==0L)
  205.           if (RH->rh_Buffer=AllocMem(RH->rh_DG.dg_SectorSize,RH->rh_DG.dg_BufMemType))
  206.            {
  207.             RH->rh_Len=RH->rh_DG.dg_SectorSize*RH->rh_DG.dg_TotalSectors;
  208.             if (Pkt->dp_Type==ACTION_FINDOUTPUT)
  209.              {
  210.               RH->rh_Write=TRUE;
  211.               RH->rh_Left=RH->rh_DG.dg_SectorSize;
  212.               RH->rh_Ptr=RH->rh_Buffer;
  213.              }
  214.             else RH->rh_Write=FALSE;
  215.             FH->fh_Arg1=(LONG)RH;
  216.             Pkt->dp_Res1=DOSTRUE;
  217.             Pkt->dp_Res2=0L;
  218.  
  219.             (*OpenCnt)++;
  220.             return;
  221.            }
  222.          CloseDevice ((struct IORequest *)RH->rh_IO);
  223.         }
  224.        else Pkt->dp_Res2=ERROR_OBJECT_NOT_FOUND;
  225.  
  226.        DeleteStdIO (RH->rh_IO);
  227.       }
  228.      DeleteMsgPort (IOPort);
  229.     }
  230.    FreeVec (RH);
  231.   }
  232. }
  233.  
  234. void __regargs CloseDH(struct DHHandle *RH,ULONG *OpenCnt)
  235.  
  236. {
  237.  if (RH->rh_Write)
  238.   {
  239.    if (RH->rh_Left<RH->rh_DG.dg_SectorSize)
  240.     {
  241.      (void)memset(RH->rh_Ptr,'\0',RH->rh_Left);
  242.      RH->rh_IO->io_Command=CMD_WRITE;
  243.      RH->rh_IO->io_Length=RH->rh_DG.dg_SectorSize;
  244.      RH->rh_IO->io_Data=RH->rh_Buffer;
  245.      RH->rh_IO->io_Offset=RH->rh_Pos+RH->rh_Left-RH->rh_DG.dg_SectorSize;
  246.      (void)DoIO((struct IORequest *)RH->rh_IO);
  247.     }
  248.    RH->rh_IO->io_Command=CMD_UPDATE;
  249.    (void)DoIO((struct IORequest *)RH->rh_IO);
  250.   }
  251.  
  252.  FreeMem (RH->rh_Buffer,RH->rh_DG.dg_SectorSize);
  253.  
  254.  RH->rh_IO->io_Command=TD_MOTOR;
  255.  RH->rh_IO->io_Length=0L;
  256.  (void)DoIO((struct IORequest *)RH->rh_IO);
  257.  CloseDevice ((struct IORequest *)RH->rh_IO);
  258.  
  259.  DeleteMsgPort (RH->rh_IO->io_Message.mn_ReplyPort);
  260.  DeleteStdIO (RH->rh_IO);
  261.  
  262.  FreeVec (RH);
  263.  
  264.  (*OpenCnt)--;
  265. }
  266.  
  267. LONG __regargs RawRead(struct DHHandle *RH,UBYTE *Buffer,LONG Bytes)
  268.  
  269. {
  270.  LONG Total,RDBytes;
  271.  
  272.  if ((RH->rh_Pos+Bytes)>RH->rh_Len) Bytes=RH->rh_Len-RH->rh_Pos;
  273.  
  274.  Total=0L;
  275.  while (Bytes)
  276.   {
  277.    if (RH->rh_Left)
  278.     {
  279.      RDBytes=MIN(RH->rh_Left,Bytes);
  280.      (void)memcpy(Buffer,RH->rh_Ptr,RDBytes);
  281.  
  282.      Buffer+=RDBytes;
  283.      Bytes-=RDBytes;
  284.      Total+=RDBytes;
  285.  
  286.      RH->rh_Pos+=RDBytes;
  287.      RH->rh_Ptr+=RDBytes;
  288.      RH->rh_Left-=RDBytes;
  289.  
  290.      if (Bytes==0L) return Total;
  291.     }
  292.  
  293.    RH->rh_IO->io_Command=CMD_READ;
  294.    RH->rh_IO->io_Length=RH->rh_DG.dg_SectorSize;
  295.    RH->rh_IO->io_Data=RH->rh_Buffer;
  296.    RH->rh_IO->io_Offset=RH->rh_Pos;
  297.    if (DoIO((struct IORequest *)RH->rh_IO)) return -1L;
  298.  
  299.    RH->rh_Ptr=RH->rh_Buffer;
  300.    RH->rh_Left=RH->rh_IO->io_Actual;
  301.   }
  302.  return Total;
  303. }
  304.  
  305. LONG __regargs RawWrite(struct DHHandle *RH,UBYTE *Buffer,LONG Bytes)
  306.  
  307. {
  308.  LONG Total,WRBytes;
  309.  
  310.  if ((RH->rh_Pos+Bytes)>RH->rh_Len) Bytes=RH->rh_Len-RH->rh_Pos;
  311.  
  312.  Total=0L;
  313.  while (Bytes)
  314.   {
  315.    WRBytes=MIN(RH->rh_Left,Bytes);
  316.    (void)memcpy(RH->rh_Ptr,Buffer,WRBytes);
  317.  
  318.    Buffer+=WRBytes;
  319.    Bytes-=WRBytes;
  320.    Total+=WRBytes;
  321.  
  322.    RH->rh_Pos+=WRBytes;
  323.    RH->rh_Ptr+=WRBytes;
  324.    RH->rh_Left-=WRBytes;
  325.  
  326.    if (RH->rh_Left==0L)
  327.     {
  328.      RH->rh_IO->io_Command=CMD_WRITE;
  329.      RH->rh_IO->io_Length=RH->rh_DG.dg_SectorSize;
  330.      RH->rh_IO->io_Data=RH->rh_Buffer;
  331.      RH->rh_IO->io_Offset=RH->rh_Pos-RH->rh_DG.dg_SectorSize;
  332.      if (DoIO((struct IORequest *)RH->rh_IO)) return -1L;
  333.  
  334.      RH->rh_Ptr=RH->rh_Buffer;
  335.      RH->rh_Left=RH->rh_DG.dg_SectorSize;
  336.     }
  337.   }
  338.  return Total;
  339. }
  340.