home *** CD-ROM | disk | FTP | other *** search
/ Aminet 18 / aminetcdnumber181997.iso / Aminet / misc / emu / AROSdev.lha / AROS / workbench / devs / fdsk_device.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-27  |  11.3 KB  |  479 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: fdsk_device.c,v 1.4 1997/01/27 00:22:40 ldp Exp $
  4.     $Log: fdsk_device.c,v $
  5.     Revision 1.4  1997/01/27 00:22:40  ldp
  6.     Include proto instead of clib
  7.  
  8.     Revision 1.3  1996/12/10 13:59:49  aros
  9.     Moved #include into first column to allow makedepend to see it.
  10.  
  11.     Revision 1.2  1996/11/16 01:18:18  aros
  12.     Fixed register usage (register used twice)
  13.  
  14.     Revision 1.1  1996/11/14 08:53:29  aros
  15.     First attempt for a real fastfilesystem
  16.     (only directoryscans for now)
  17.  
  18.     Desc:
  19.     Lang:
  20. */
  21. #include <devices/trackdisk.h>
  22. #include <exec/resident.h>
  23. #include <exec/errors.h>
  24. #include <exec/memory.h>
  25. #include <proto/exec.h>
  26. #include <dos/dosextens.h>
  27. #include <dos/dostags.h>
  28. #include <proto/dos.h>
  29. #include <aros/asmcall.h>
  30. #include <aros/machine.h>
  31. #ifdef __GNUC__
  32. #include "fdsk_device_gcc.h"
  33. #endif
  34.  
  35. #define NEWLIST(l)                          \
  36. ((l)->lh_Head=(struct Node *)&(l)->lh_Tail, \
  37.  (l)->lh_Tail=NULL,                         \
  38.  (l)->lh_TailPred=(struct Node *)(l))
  39.  
  40. extern const char name[];
  41. extern const char version[];
  42. extern const APTR inittabl[4];
  43. extern void *const functable[];
  44. extern const UBYTE datatable;
  45. extern struct fdskbase *AROS_SLIB_ENTRY(init,fdsk)();
  46. extern void AROS_SLIB_ENTRY(open,fdsk)();
  47. extern BPTR AROS_SLIB_ENTRY(close,fdsk)();
  48. extern BPTR AROS_SLIB_ENTRY(expunge,fdsk)();
  49. extern int AROS_SLIB_ENTRY(null,fdsk)();
  50. extern void AROS_SLIB_ENTRY(beginio,fdsk)();
  51. extern LONG AROS_SLIB_ENTRY(abortio,fdsk)();
  52. extern const char end;
  53.  
  54. int deventry(void)
  55. {
  56.     /* If the device was executed by accident return error code. */
  57.     return -1;
  58. }
  59.  
  60. const struct Resident resident=
  61. {
  62.     RTC_MATCHWORD,
  63.     (struct Resident *)&resident,
  64.     (APTR)&end,
  65.     RTF_AUTOINIT,
  66.     1,
  67.     NT_DEVICE,
  68.     0,
  69.     (char *)name,
  70.     (char *)&version[6],
  71.     (ULONG *)inittabl
  72. };
  73.  
  74. const char name[]="fdsk.device";
  75.  
  76. const char version[]="$VER: file-disk device 1.0 (10.9.96)\n\015";
  77.  
  78. const APTR inittabl[4]=
  79. {
  80.     (APTR)sizeof(struct fdskbase),
  81.     (APTR)functable,
  82.     (APTR)&datatable,
  83.     &AROS_SLIB_ENTRY(init,fdsk)
  84. };
  85.  
  86. void *const functable[]=
  87. {
  88.     &AROS_SLIB_ENTRY(open,fdsk),
  89.     &AROS_SLIB_ENTRY(close,fdsk),
  90.     &AROS_SLIB_ENTRY(expunge,fdsk),
  91.     &AROS_SLIB_ENTRY(null,fdsk),
  92.     &AROS_SLIB_ENTRY(beginio,fdsk),
  93.     &AROS_SLIB_ENTRY(abortio,fdsk),
  94.     (void *)-1
  95. };
  96.  
  97. const UBYTE datatable=0;
  98.  
  99. AROS_LH2(struct fdskbase *, init,
  100.  AROS_LHA(struct fdskbase *, fdskbase, D0),
  101.  AROS_LHA(BPTR,             segList,   A0),
  102.        struct ExecBase *, sysbase, 0, fdsk)
  103. {
  104.     AROS_LIBFUNC_INIT
  105.  
  106.     /* Store arguments */
  107.     SysBase=sysbase;
  108.     fdskbase->seglist=segList;
  109.     InitSemaphore(&fdskbase->sigsem);
  110.     NEWLIST((struct List *)&fdskbase->units);
  111.     fdskbase->port.mp_Node.ln_Type=NT_MSGPORT;
  112.     fdskbase->port.mp_Flags=PA_SIGNAL;
  113.     fdskbase->port.mp_SigBit=SIGB_SINGLE;
  114.     NEWLIST((struct List *)&fdskbase->port.mp_MsgList);
  115.     DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",37);
  116.     if(DOSBase!=NULL)
  117.     return fdskbase;
  118.  
  119.     return NULL;
  120.     AROS_LIBFUNC_EXIT
  121. }
  122.  
  123. LONG AROS_SLIB_ENTRY(entry,)();
  124.  
  125. AROS_LH3(void, open,
  126.  AROS_LHA(struct IOExtTD *, iotd, A1),
  127.  AROS_LHA(ULONG,              unitnum, D0),
  128.  AROS_LHA(ULONG,              flags, D1),
  129.        struct fdskbase *, fdskbase, 1, fdsk)
  130. {
  131.     AROS_LIBFUNC_INIT
  132.     
  133.     static const struct TagItem tags[]=
  134.     {
  135.         { NP_Name, (LONG)"file disk unit process" },
  136.         { NP_Input, 0 },
  137.         { NP_Output, 0 },
  138.         { NP_Error, 0 },
  139.         { NP_CurrentDir, 0 },
  140.         { NP_Priority, 0 },
  141.         { NP_HomeDir, 0 },
  142.         { NP_CopyVars, 0 },
  143.         { NP_Entry, (LONG)AROS_SLIB_ENTRY(entry,) },
  144.         { TAG_END, 0 }
  145.     };
  146.     struct unit *unit;
  147.  
  148.     /* Keep compiler happy */
  149.     flags=0;
  150.  
  151.     /* I have one more opener. */
  152.     fdskbase->device.dd_Library.lib_OpenCnt++;
  153.     fdskbase->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  154.  
  155.     ObtainSemaphore(&fdskbase->sigsem);
  156.  
  157.     for(unit=(struct unit *)fdskbase->units.mlh_Head;
  158.     unit->msg.mn_Node.ln_Succ!=NULL;
  159.     unit=(struct unit *)unit->msg.mn_Node.ln_Succ)
  160.     if(unit->unitnum==unitnum)
  161.     {
  162.         unit->usecount++;
  163.         ReleaseSemaphore(&fdskbase->sigsem);
  164.         iotd->iotd_Req.io_Unit=(struct Unit *)unit;
  165.         iotd->iotd_Req.io_Error=0;
  166.         iotd->iotd_Req.io_Message.mn_Node.ln_Type=NT_REPLYMSG;
  167.         return;
  168.     }
  169.  
  170.     unit=(struct unit *)AllocMem(sizeof(struct unit),MEMF_PUBLIC);
  171.     if(unit!=NULL)
  172.     {
  173.     unit->usecount=1;
  174.     unit->fdskbase=fdskbase;
  175.     unit->unitnum=unitnum;
  176.     unit->msg.mn_ReplyPort=&fdskbase->port;
  177.     unit->msg.mn_Length=sizeof(struct unit);
  178.     fdskbase->port.mp_SigTask=FindTask(NULL);
  179.     unit->port.mp_Node.ln_Type=NT_MSGPORT;
  180.     unit->port.mp_Flags=PA_IGNORE;
  181.     NEWLIST((struct List *)&unit->port.mp_MsgList);
  182.     unit->port.mp_SigTask=CreateNewProc((struct TagItem *)tags);
  183.     if(unit->port.mp_SigTask!=NULL)
  184.     {
  185.         PutMsg(&((struct Process *)unit->port.mp_SigTask)->pr_MsgPort,&unit->msg);
  186.         WaitPort(&fdskbase->port);
  187.         (void)GetMsg(&fdskbase->port);
  188.         if(unit->file)
  189.         {
  190.         AddTail((struct List *)&fdskbase->units,&unit->msg.mn_Node);
  191.         iotd->iotd_Req.io_Unit=(struct Unit *)unit;
  192.         /* Set returncode */
  193.         iotd->iotd_Req.io_Error=0;
  194.         ReleaseSemaphore(&fdskbase->sigsem);
  195.         fdskbase->device.dd_Library.lib_Flags&=~LIBF_DELEXP;
  196.         return;
  197.         }else
  198.         iotd->iotd_Req.io_Error=TDERR_NotSpecified;
  199.     }else
  200.         iotd->iotd_Req.io_Error=TDERR_NoMem;
  201.     FreeMem(unit,sizeof(struct unit));
  202.     }else
  203.     iotd->iotd_Req.io_Error=TDERR_NoMem;
  204.  
  205.     ReleaseSemaphore(&fdskbase->sigsem);
  206.  
  207.     fdskbase->device.dd_Library.lib_OpenCnt--;
  208.     AROS_LIBFUNC_EXIT
  209. }
  210.  
  211. AROS_LH1(BPTR, close,
  212.  AROS_LHA(struct IOExtTD *, iotd, A1),
  213.        struct fdskbase *, fdskbase, 2, fdsk)
  214. {
  215.     AROS_LIBFUNC_INIT
  216.     struct unit *unit;
  217.  
  218.     /* Let any following attemps to use the device crash hard. */
  219.     iotd->iotd_Req.io_Device=(struct Device *)-1;
  220.  
  221.     ObtainSemaphore(&fdskbase->sigsem);
  222.     unit=(struct unit *)iotd->iotd_Req.io_Unit;
  223.     if(!--unit->usecount)
  224.     {
  225.     Remove(&unit->msg.mn_Node);
  226.     fdskbase->port.mp_SigTask=FindTask(NULL);
  227.     PutMsg(&unit->port,&unit->msg);
  228.     WaitPort(&fdskbase->port);
  229.     (void)GetMsg(&fdskbase->port);
  230.     FreeMem(unit,sizeof(struct unit));
  231.     }
  232.     ReleaseSemaphore(&fdskbase->sigsem);
  233.  
  234.     /* I have one fewer opener. */
  235.     if(!--fdskbase->device.dd_Library.lib_OpenCnt)
  236.     {
  237.     /* Delayed expunge pending? */
  238.     if(fdskbase->device.dd_Library.lib_Flags&LIBF_DELEXP)
  239.         /* Then expunge the device */
  240.         return expunge();
  241.     }
  242.     return 0;
  243.     AROS_LIBFUNC_EXIT
  244. }
  245.  
  246. AROS_LH0(BPTR, expunge, struct fdskbase *, fdskbase, 3, fdsk)
  247. {
  248.     AROS_LIBFUNC_INIT
  249.  
  250.     BPTR ret;
  251.     /*
  252.     This function is single-threaded by exec by calling Forbid.
  253.     Never break the Forbid() or strange things might happen.
  254.     */
  255.  
  256.     /* Test for openers. */
  257.     if(fdskbase->device.dd_Library.lib_OpenCnt)
  258.     {
  259.     /* Set the delayed expunge flag and return. */
  260.     fdskbase->device.dd_Library.lib_Flags|=LIBF_DELEXP;
  261.     return 0;
  262.     }
  263.  
  264.     /* Free resources */
  265.     CloseLibrary((struct Library *)DOSBase);
  266.  
  267.     /* Get rid of the device. Remove it from the list. */
  268.     Remove(&fdskbase->device.dd_Library.lib_Node);
  269.  
  270.     /* Get returncode here - FreeMem() will destroy the field. */
  271.     ret=fdskbase->seglist;
  272.  
  273.     /* Free the memory. */
  274.     FreeMem((char *)fdskbase-fdskbase->device.dd_Library.lib_NegSize,
  275.         fdskbase->device.dd_Library.lib_NegSize+fdskbase->device.dd_Library.lib_PosSize);
  276.  
  277.     return ret;
  278.     AROS_LIBFUNC_EXIT
  279. }
  280.  
  281. AROS_LH0I(int, null, struct fdskbase *, fdskbase, 4, fdsk)
  282. {
  283.     AROS_LIBFUNC_INIT
  284.     return 0;
  285.     AROS_LIBFUNC_EXIT
  286. }
  287.  
  288. AROS_LH1(void, beginio,
  289.  AROS_LHA(struct IOExtTD *, iotd, A1),
  290.        struct fdskbase *, fdskbase, 5, fdsk)
  291. {
  292.     AROS_LIBFUNC_INIT
  293.  
  294.     switch(iotd->iotd_Req.io_Command)
  295.     {
  296.     case CMD_UPDATE:
  297.     case CMD_CLEAR:
  298.     case TD_MOTOR:
  299.         /* Ignore but don't fail */
  300.         iotd->iotd_Req.io_Error=0;
  301.         break;
  302.     case CMD_READ:
  303.     case CMD_WRITE:
  304.     case TD_FORMAT:
  305.         /* Forward to unit thread */
  306.         PutMsg(&((struct unit *)iotd->iotd_Req.io_Unit)->port,
  307.            &iotd->iotd_Req.io_Message);
  308.         /* Not done quick */
  309.         iotd->iotd_Req.io_Flags&=~IOF_QUICK;
  310.         return;
  311.     default:
  312.         /* Not supported */
  313.         iotd->iotd_Req.io_Error=IOERR_NOCMD;
  314.         break;
  315.     }
  316.  
  317.     /* WaitIO will look into this */
  318.     iotd->iotd_Req.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  319.  
  320.     /* Finish message */
  321.     if(!(iotd->iotd_Req.io_Flags&IOF_QUICK))
  322.     ReplyMsg(&iotd->iotd_Req.io_Message);
  323.     
  324.     AROS_LIBFUNC_EXIT
  325. }
  326.  
  327. AROS_LH1(LONG, abortio,
  328.  AROS_LHA(struct IOExtTD *, iotd, A1),
  329.        struct fdskbase *, fdskbase, 6, fdsk)
  330. {
  331.     AROS_LIBFUNC_INIT
  332.     return IOERR_NOCMD;
  333.     AROS_LIBFUNC_EXIT
  334. }
  335.  
  336. #define fdskbase unit->fdskbase
  337.  
  338. static LONG error(LONG error)
  339. {
  340.     switch(error)
  341.     {
  342.     case ERROR_SEEK_ERROR:
  343.         return TDERR_SeekError;
  344.     case ERROR_DISK_WRITE_PROTECTED:
  345.     case ERROR_WRITE_PROTECTED:
  346.         return TDERR_WriteProt;
  347.     case ERROR_NO_DISK:
  348.         return TDERR_DiskChanged;
  349.     default:
  350.         return TDERR_NotSpecified;
  351.     }
  352. }
  353.  
  354. static LONG read(struct unit *unit, struct IOExtTD *iotd)
  355. {
  356.     STRPTR buf;
  357.     LONG size, subsize;
  358.     if(iotd->iotd_SecLabel)
  359.     return IOERR_NOCMD;
  360.     if(Seek(unit->file,iotd->iotd_Req.io_Offset,OFFSET_BEGINNING)==-1)
  361.     return TDERR_SeekError;
  362.     buf =iotd->iotd_Req.io_Data;
  363.     size=iotd->iotd_Req.io_Length;
  364.     iotd->iotd_Req.io_Actual=size;
  365.     while(size)
  366.     {
  367.     subsize=Read(unit->file,buf,size);
  368.     if(!subsize)
  369.     {
  370.          iotd->iotd_Req.io_Actual-=size;
  371.          return IOERR_BADLENGTH;
  372.     }
  373.     if(subsize==-1)
  374.     {
  375.         iotd->iotd_Req.io_Actual-=size;
  376.         return error(IoErr());
  377.     }
  378.     buf +=subsize;
  379.     size-=subsize;
  380.     }
  381.     return 0;
  382. }
  383.  
  384. static LONG write(struct unit *unit, struct IOExtTD *iotd)
  385. {
  386.     STRPTR buf;
  387.     LONG size, subsize;
  388.     if(iotd->iotd_SecLabel)
  389.     return IOERR_NOCMD;
  390.     if(Seek(unit->file,iotd->iotd_Req.io_Offset,OFFSET_BEGINNING)==-1)
  391.     return TDERR_SeekError;
  392.     buf =iotd->iotd_Req.io_Data;
  393.     size=iotd->iotd_Req.io_Length;
  394.     iotd->iotd_Req.io_Actual=size;
  395.     while(size)
  396.     {
  397.     subsize=Write(unit->file,buf,size);
  398.     if(subsize==-1)
  399.     {
  400.         iotd->iotd_Req.io_Actual-=size;
  401.         return error(IoErr());
  402.     }
  403.     buf +=subsize;
  404.     size-=subsize;
  405.     }
  406.     return 0;
  407. }
  408.  
  409. AROS_UFH2(void,putchr,
  410.     AROS_UFHA(UBYTE,chr,D0),
  411.     AROS_UFHA(STRPTR *,p,A3)
  412. )
  413. {
  414.     AROS_LIBFUNC_INIT
  415.     *(*p)++=chr;
  416.     AROS_LIBFUNC_EXIT
  417. }
  418.  
  419. #ifdef SysBase
  420. #undef SysBase
  421. #endif
  422.  
  423. /* TODO: This won't work for normal AmigaOS since you can't expect SysBase in A6 */
  424. AROS_LH0(LONG,entry,struct ExecBase *,SysBase,,)
  425. {
  426.     UBYTE buf[10+sizeof(LONG)*8*301/1000+1];
  427.     STRPTR ptr=buf;
  428.     struct Process *me=(struct Process *)FindTask(NULL);
  429.     LONG err;
  430.     struct IOExtTD *iotd;
  431.     struct unit *unit;
  432.  
  433.     WaitPort(&me->pr_MsgPort);
  434.     unit=(struct unit *)GetMsg(&me->pr_MsgPort);
  435.     unit->port.mp_SigBit=AllocSignal(-1);
  436.     unit->port.mp_Flags=PA_SIGNAL;
  437.  
  438.     (void)RawDoFmt("FDSK:Unit%ld",&unit->unitnum,(VOID_FUNC)putchr,&ptr);
  439.     
  440.     unit->file=Open(buf,MODE_READWRITE);
  441.     if(!unit->file)
  442.     {
  443.     iotd->iotd_Req.io_Error=error(IoErr());
  444.     Forbid();
  445.     ReplyMsg(&unit->msg);
  446.     return 0;
  447.     }
  448.     ReplyMsg(&unit->msg);
  449.  
  450.     for(;;)
  451.     {
  452.     while((iotd=(struct IOExtTD *)GetMsg(&unit->port))!=NULL)
  453.     {
  454.         if(&iotd->iotd_Req.io_Message==&unit->msg)
  455.         {
  456.         Close(unit->file);
  457.         Forbid();
  458.         ReplyMsg(&unit->msg);
  459.         return 0;
  460.         }
  461.          switch(iotd->iotd_Req.io_Command)
  462.          {
  463.          case CMD_READ:
  464.              err=read(unit,iotd);
  465.              break;
  466.          case CMD_WRITE:
  467.          case TD_FORMAT:
  468.              err=write(unit,iotd);
  469.              break;
  470.          }
  471.          iotd->iotd_Req.io_Error=err;
  472.          ReplyMsg(&iotd->iotd_Req.io_Message);
  473.     }
  474.     WaitPort(&unit->port);
  475.     }
  476. }
  477.  
  478. const char end=0;
  479.