home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff294.lzh / DNet / amiga / doshand / uuser.c < prev    next >
C/C++ Source or Header  |  1989-12-11  |  13KB  |  533 lines

  1.  
  2. /*
  3.  *  UUSER.C UUSER:devicename/unitnumber/options
  4.  *        UUSER:serial.device/0/R1000
  5.  *
  6.  *  options:
  7.  *    Rn    Set read timeout when no data available to n millisecs
  8.  *    C0    Ignore carrier detect
  9.  *
  10.  *  features:
  11.  *    1K asynchronous write capability (write 0 bytes to sync up)
  12.  *    programmable read-timeout (Getty starts procs up w/ 1sec to)
  13.  *
  14.  *    combined together, you can easily implement 100% efficient
  15.  *    protocols even with that 1 second read timeout!
  16.  */
  17.  
  18. #include <exec/types.h>
  19. #include <exec/memory.h>
  20. #include <devices/serial.h>
  21. #include <devices/timer.h>
  22. #include <libraries/dos.h>
  23. #include <libraries/dosextens.h>
  24. #include <libraries/filehandler.h>
  25. #include <hardware/cia.h>
  26. #include <proto/all.h>
  27.  
  28. #define WRITEBUFSIZE    1024
  29. #define MPC (MEMF_PUBLIC|MEMF_CLEAR)        /* options to AllocMem()    */
  30.  
  31. #define BTOC(x, type)   ((type *)((long)x << 2))
  32. #define CTOB(x)         ((BPTR)((long)x >> 2))
  33.  
  34. #define DOS_FALSE    0
  35. #define DOS_TRUE     -1
  36.  
  37. typedef struct IOExtSer     IOS;
  38. typedef struct timerequest  IOT;
  39. typedef struct IORequest    IOR;
  40. typedef struct timeval        TimeVal;
  41.  
  42. typedef struct FileLock     LOCK;
  43. typedef struct DosPacket    Packet;
  44. typedef struct Process        PROC;
  45. typedef struct DeviceNode   DEVNODE;
  46. typedef struct FileHandle   FH;
  47. typedef struct Message        MSG;
  48. typedef struct Node        NODE;
  49. typedef struct List        LIST;
  50. typedef struct MsgPort        PORT;
  51.  
  52. typedef struct SHandle {
  53.     NODE    Node;
  54.     IOT     Iot;        /* wait-for-char and read req    */
  55.     IOS     Ios;
  56.     IOS     Iosr;        /* 1005             */
  57.     IOS     Iosw;        /* 1005,1006            */
  58.     char    IotIP;
  59.     char    IosrIP;
  60.     char    IoswIP;
  61.     char    RxIn[1];        /* one char buffer        */
  62.     char    *TxOut;        /* asynch write buffer        */
  63.     Packet  *RPacket;        /* current pending read packet    */
  64.     Packet  *WPacket;        /* current pending write packet */
  65.     short   Flags;
  66.     LIST    RxWait;        /* requests waiting for data    */
  67.     LIST    TxWait;        /* requests waiting to write    */
  68.     LIST    CxWait;        /* wait for char        */
  69.     TimeVal ReadTo;
  70. } SHandle;
  71.  
  72. #define HF_IGNORECD    0x01
  73. #define HF_CDLOST    0x02
  74. #define HF_RTO        0x04
  75. #define HF_DONTLOCK    0x08    /* if G option for from-getty    */
  76.  
  77. extern Packet *taskwait();   /* wait for a message           */
  78.  
  79. long SysBase;            /* required to make Exec calls    */
  80. char ScrBuf[256];        /* Scratch buffer        */
  81. PORT *IoSink;
  82. LIST HanList;
  83. LIST NodList;
  84. IOT  Iot;            /* Iot master, also used for CD */
  85. char IotIP;
  86.  
  87. void    AttemptRead();
  88. void    AttemptWrite();
  89. void    AbortPackets();
  90. void    StartTimer();
  91.  
  92. __saveds void
  93. _dummy()
  94. {
  95.     PROC    *myproc;
  96.     DEVNODE    *mynode;
  97.     UBYTE    notdone;
  98.     long    mask;
  99.  
  100.     SysBase = *(long *)4;
  101.     IoSink = CreatePort(NULL, 0);
  102.     NewList(&HanList);
  103.     NewList(&NodList);
  104.  
  105.     Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
  106.     OpenDevice("timer.device", UNIT_VBLANK, &Iot, 0);
  107.     Iot.tr_node.io_Command = TR_ADDREQUEST;
  108.     Iot.tr_time.tv_secs = 4;
  109.     Iot.tr_time.tv_micro= 0;
  110.     SendIO(&Iot);
  111.     IotIP = 1;
  112.  
  113.     myproc  = (PROC *)FindTask(0L);
  114.  
  115.     /*
  116.      * INITIAL STARTUP MESSAGE
  117.      */
  118.  
  119.     {
  120.     Packet *mypkt;
  121.  
  122.     mypkt    = taskwait(myproc);
  123.     mynode    = BTOC(mypkt->dp_Arg3, DEVNODE);
  124.     mynode->dn_Task = &myproc->pr_MsgPort;
  125.     returnpkt(mypkt, myproc, DOS_TRUE, 0);
  126.     }
  127.  
  128. loop:
  129.     notdone = 1;
  130.     mask = (1 << IoSink->mp_SigBit) | (1 << myproc->pr_MsgPort.mp_SigBit);
  131.     while (notdone) {
  132.     Packet *mypkt;         /* dos packet received      */
  133.     IOR *ior;
  134.     SHandle *handle;
  135.     long type;            /* type of packet        */
  136.  
  137.     ior = (IOR *)GetMsg(IoSink);
  138.     mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
  139.     if (mypkt)
  140.         mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
  141.     while (mypkt == NULL && ior == NULL) {
  142.         Wait(mask);
  143.         ior = (IOR *)GetMsg(IoSink);
  144.         mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
  145.         if (mypkt)
  146.         mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
  147.     }
  148.  
  149.     /*
  150.      *  Make sure there is at least one free node in node list
  151.      */
  152.  
  153.     if (NodList.lh_Head == (NODE *)&NodList.lh_Tail) {
  154.         NODE *pknode = AllocMem(sizeof(NODE), MPC);
  155.         AddTail(&NodList, pknode);
  156.     }
  157.  
  158.     /*
  159.      *  Returned IO request, sift through lists to find it.
  160.      */
  161.  
  162.     if (ior) {
  163.         if (ior == &Iot) {      /*  Check for carrier lost */
  164.         for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
  165.             if (!(handle->Flags & HF_IGNORECD) && !(handle->Flags & HF_CDLOST)) {
  166.             handle->Ios.IOSer.io_Command = SDCMD_QUERY;
  167.             DoIO(&handle->Ios);
  168.             if (handle->Ios.io_Status & CIAF_COMCD) {
  169.                 handle->Flags |= HF_CDLOST;
  170.                 AbortPackets(handle, myproc);
  171.             }
  172.             }
  173.         }
  174.         if (HanList.lh_Head == (NODE *)&HanList.lh_Tail) {
  175.             IotIP = 0;
  176.         } else {
  177.             Iot.tr_time.tv_secs = 4;
  178.             Iot.tr_time.tv_micro= 0;
  179.             SendIO(&Iot);
  180.             IotIP = 1;
  181.         }
  182.         } else
  183.         for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
  184.         if (ior == (IOR *)&handle->Iosr) {
  185.             returnpkt(handle->RPacket, myproc, handle->Iosr.IOSer.io_Actual, 0);
  186.             handle->IosrIP = 0;
  187.             handle->RPacket = NULL;
  188.  
  189.             if (handle->IotIP) {
  190.             AbortIO(&handle->Iot);
  191.             WaitIO(&handle->Iot);
  192.             handle->IotIP = 0;
  193.             }
  194.             AttemptRead(handle, myproc);
  195.         }
  196.         if (ior == (IOR *)&handle->Iosw) {
  197.             handle->IoswIP = 0;
  198.             if (handle->WPacket) {
  199.             handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
  200.             handle->Iosw.IOSer.io_Length= handle->WPacket->dp_Arg3 - handle->WPacket->dp_Res1;
  201.             SendIO(&handle->Iosw);
  202.             handle->IoswIP = 1;
  203.             handle->WPacket->dp_Res1 = handle->WPacket->dp_Arg3;
  204.             returnpktplain(handle->WPacket, myproc);
  205.             handle->WPacket = NULL;
  206.             } else {
  207.             AttemptWrite(handle, myproc);
  208.             }
  209.         }
  210.         if (ior == (IOR *)&handle->Iot) {
  211.             handle->IotIP = 0;
  212.             if ((handle->Flags & HF_RTO) && handle->IosrIP) {
  213.             AbortIO(&handle->Iosr);
  214.             }
  215.         }
  216.         }
  217.     }
  218.  
  219.     if (mypkt) {
  220.         mypkt->dp_Res1 = DOS_TRUE;    /* default return value     */
  221.         mypkt->dp_Res2 = 0;     /* default no error        */
  222.         type = mypkt->dp_Type;    /* packet type            */
  223.  
  224.         /*
  225.          *    Extract pipe pointer (only applies to read/write)
  226.          */
  227.  
  228.         handle = (SHandle *)mypkt->dp_Arg1;     /*  READ/WRITE only */
  229.  
  230.         switch(type) {
  231.         case ACTION_FINDINPUT:
  232.         case ACTION_FINDOUTPUT:
  233.         case ACTION_FINDUPDATE:
  234.         if (IotIP == 0)
  235.             StartTimer(4);
  236.         {
  237.             FH     *fh = BTOC(mypkt->dp_Arg1, FH);
  238.             char *path = BTOC(mypkt->dp_Arg3, char);
  239.             char *unit;
  240.             long n;
  241.  
  242.             movmem(path + 1, ScrBuf, *path);
  243.             ScrBuf[*path] = 0;
  244.             path = ScrBuf;
  245.  
  246.             handle = AllocMem(sizeof(SHandle), MPC);
  247.  
  248.             if (strcmp(ScrBuf, "*") == 0)
  249.             strcpy(ScrBuf, "serial.device/0");
  250.             for (unit = path; *unit && *unit != '/'; ++unit) {
  251.             if (*unit == ':')
  252.                 path = unit + 1;
  253.             }
  254.             if (*unit == '/') {
  255.             char *opts;
  256.  
  257.             *unit = 0;
  258.             ++unit;
  259.             for (opts = unit; *opts && *opts != '/'; ++opts);
  260.             while (*opts) {
  261.                 n = atoi(opts + 1);
  262.                 switch(*opts) {
  263.                 case '/':
  264.                 break;
  265.                 case 'R':
  266.                 handle->ReadTo.tv_secs = n / 1000;
  267.                 handle->ReadTo.tv_micro= (n % 1000) * 1000;
  268.                 handle->Flags |= HF_RTO;
  269.                 break;
  270.                 case 'C':
  271.                 handle->Flags |= HF_IGNORECD;
  272.                 break;
  273.                 case 'G':
  274.                 if (n)
  275.                     handle->Flags |= HF_DONTLOCK;
  276.                 break;
  277.                 }
  278.                 ++opts;
  279.             }
  280.             }
  281.  
  282.             /* proc = (PROC *)mypkt->dp_Port->mp_SigTask; */
  283.  
  284.             /*
  285.              * Open the device
  286.              */
  287.  
  288.             handle->Ios.IOSer.io_Message.mn_ReplyPort = IoSink;
  289.             handle->Ios.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
  290.             if (OpenDevice(path, atoi(unit), &handle->Ios, 0)) {
  291.             FreeMem(handle, sizeof(SHandle));
  292.             mypkt->dp_Res1 = DOS_FALSE;
  293.             mypkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
  294.             returnpktplain(mypkt, myproc);
  295.             break;
  296.             }
  297.             fh->fh_Arg1 = (long)handle;
  298.             fh->fh_Port = (struct MsgPort *)DOS_TRUE;
  299.  
  300.             handle->Iosr = handle->Ios;
  301.             handle->Iosw = handle->Ios;
  302.             handle->Iosr.IOSer.io_Command = CMD_READ;
  303.             handle->Iosw.IOSer.io_Command = CMD_WRITE;
  304.             handle->Iot = Iot;
  305.             NewList(&handle->RxWait);
  306.             NewList(&handle->TxWait);
  307.             NewList(&handle->CxWait);
  308.             AddTail(&HanList, handle);
  309.             returnpktplain(mypkt, myproc);
  310.         }
  311.         break;
  312.         case ACTION_END:
  313.         Remove(handle);
  314.         if (handle->IosrIP) {
  315.             AbortIO(&handle->Iosr);
  316.             WaitIO(&handle->Iosr);
  317.         }
  318.         if (handle->IoswIP) {
  319.             WaitIO(&handle->Iosw);
  320.         }
  321.         if (handle->IotIP) {
  322.             AbortIO(&handle->Iot);
  323.             WaitIO(&handle->Iot);
  324.         }
  325.         AbortPackets(handle, myproc);
  326.         CloseDevice(&handle->Ios);
  327.         returnpktplain(mypkt, myproc);
  328.         if (handle->TxOut)
  329.             FreeMem(handle->TxOut, WRITEBUFSIZE);
  330.         FreeMem(handle, sizeof(SHandle));
  331.         break;
  332.         case ACTION_READ:
  333.         {
  334.             NODE *pknode = RemHead(&NodList);
  335.             mypkt->dp_Res1 = 0;
  336.             pknode->ln_Name = (char *)mypkt;
  337.             AddTail(&handle->RxWait, pknode);
  338.             AttemptRead(handle, myproc);
  339.         }
  340.         break;
  341.         case ACTION_WRITE:
  342.         {
  343.             NODE *pknode = RemHead(&NodList);
  344.             mypkt->dp_Res1 = 0;
  345.             pknode->ln_Name = (char *)mypkt;
  346.             AddTail(&handle->TxWait, pknode);
  347.             AttemptWrite(handle, myproc);
  348.         }
  349.         break;
  350.         case ACTION_WAIT_CHAR:
  351.         default:
  352.         returnpkt(mypkt, myproc, DOS_FALSE, ERROR_ACTION_NOT_KNOWN);
  353.         break;
  354.         }
  355.     }
  356.     }
  357.  
  358.     /*
  359.      *    Can only exit if no messages pending.  There might be a window
  360.      *    here, but there is nothing that can be done about it.
  361.      */
  362.  
  363.     Forbid();
  364.     if (taskpktrdy(myproc)) {
  365.     Permit();
  366.     goto loop;
  367.     }
  368.     mynode->dn_Task = FALSE;
  369.     Permit();
  370.  
  371.     if (IotIP) {
  372.     AbortIO(&Iot);
  373.     WaitIO(&Iot);
  374.     }
  375.     CloseDevice(&Iot);
  376.  
  377.     /* we are a process "so we fall off the end of the world" */
  378.     /* MUST fall through */
  379. }
  380.  
  381. void
  382. AttemptRead(handle, myproc)
  383. SHandle *handle;
  384. PROC *myproc;
  385. {
  386.     Packet *mypkt;
  387.     NODE *pknode;
  388.  
  389.     if (handle->Flags & HF_CDLOST) {
  390.     AbortPackets(handle, myproc);
  391.     return;
  392.     }
  393. loop:
  394.     if (handle->IosrIP == 0 && (pknode = RemHead(&handle->RxWait))) {
  395.     long n;
  396.  
  397.     AddTail(&NodList, pknode);
  398.  
  399.     mypkt = (Packet *)pknode->ln_Name;
  400.  
  401.     /*
  402.      *  special case.  If you read 0 bytes, 0 is returned if data
  403.      *  is pending, else -1, and NO timeout occurs.
  404.      */
  405.  
  406.     handle->Ios.IOSer.io_Command = SDCMD_QUERY;
  407.     DoIO(&handle->Ios);
  408.  
  409.     if (mypkt->dp_Arg3 == 0) {
  410.         if (handle->Ios.IOSer.io_Actual > 0)
  411.         returnpkt(mypkt, myproc, 0, 0);     /* 0=data rdy */
  412.         else
  413.         returnpkt(mypkt, myproc, -1, 0);    /* -1=data not rdy */
  414.         goto loop;
  415.     }
  416.  
  417.     if ((n = handle->Ios.IOSer.io_Actual) > 0) {
  418.         if (n > mypkt->dp_Arg3)
  419.         n = mypkt->dp_Arg3;
  420.         handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
  421.         handle->Iosr.IOSer.io_Length = n;
  422.         DoIO(&handle->Iosr);
  423.         mypkt->dp_Res1 = handle->Iosr.IOSer.io_Actual;
  424.         returnpktplain(mypkt, myproc);
  425.         goto loop;
  426.     }
  427.     handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
  428.     handle->Iosr.IOSer.io_Length = 1;
  429.     SendIO(&handle->Iosr);
  430.     handle->IosrIP = 1;
  431.     handle->RPacket = mypkt;
  432.  
  433.     if (handle->Flags & HF_RTO) {
  434.         if (handle->IotIP) {
  435.         AbortIO(&handle->Iot);
  436.         WaitIO(&handle->Iot);
  437.         }
  438.         handle->Iot.tr_time = handle->ReadTo;
  439.         SendIO(&handle->Iot);
  440.         handle->IotIP = 1;
  441.     }
  442.     }
  443. }
  444.  
  445. void
  446. AttemptWrite(handle, myproc)
  447. SHandle *handle;
  448. PROC *myproc;
  449. {
  450.     Packet *mypkt;
  451.     NODE *pknode;
  452.  
  453.     if (handle->Flags & HF_CDLOST) {
  454.     AbortPackets(handle, myproc);
  455.     return;
  456.     }
  457.     if (handle->IoswIP == 0 && (pknode = RemHead(&handle->TxWait))) {
  458.     AddTail(&NodList, pknode);
  459.  
  460.     mypkt = (Packet *)pknode->ln_Name;
  461.  
  462.     if (handle->TxOut == NULL)
  463.         handle->TxOut = AllocMem(WRITEBUFSIZE, MPC);
  464.  
  465.     if (mypkt->dp_Arg3 <= WRITEBUFSIZE) {   /* fully asynch */
  466.         movmem((char *)mypkt->dp_Arg2, handle->TxOut, mypkt->dp_Arg3);
  467.         handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
  468.         handle->Iosw.IOSer.io_Length = mypkt->dp_Arg3;
  469.         SendIO(&handle->Iosw);
  470.         mypkt->dp_Res1 = mypkt->dp_Arg3;
  471.         returnpktplain(mypkt, myproc);
  472.         handle->WPacket = NULL;
  473.     } else {                /*  semi-asynch */
  474.         long n = mypkt->dp_Arg3 - WRITEBUFSIZE;
  475.         handle->Iosw.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
  476.         handle->Iosw.IOSer.io_Length = n;
  477.         SendIO(&handle->Iosw);
  478.         movmem((char *)mypkt->dp_Arg2 + n, handle->TxOut, WRITEBUFSIZE);
  479.         mypkt->dp_Res1 += n;
  480.         handle->WPacket = mypkt;
  481.     }
  482.     handle->IoswIP = 1;
  483.     }
  484. }
  485.  
  486. void
  487. AbortPackets(handle, myproc)
  488. SHandle *handle;
  489. {
  490.     NODE *pknode;
  491.     Packet *mypkt;
  492.  
  493.     if (handle->RPacket)
  494.     returnpktplain(handle->RPacket, myproc);
  495.     if (handle->WPacket)
  496.     returnpktplain(handle->RPacket, myproc);
  497.  
  498.     handle->RPacket = NULL;
  499.     handle->WPacket = NULL;
  500.  
  501.     while (pknode = RemHead(&handle->RxWait)) {
  502.     mypkt = (Packet *)pknode->ln_Name;
  503.     if (mypkt->dp_Arg3 == 0)
  504.         mypkt->dp_Res1 = 0;     /* for poll, return data rdy */
  505.     else
  506.         mypkt->dp_Res1 = -1;
  507.     returnpktplain(mypkt, myproc);
  508.     AddTail(&NodList, pknode);
  509.     }
  510.  
  511.     while (pknode = RemHead(&handle->TxWait)) {
  512.     mypkt = (Packet *)pknode->ln_Name;
  513.     mypkt->dp_Res1 = -1;
  514.     returnpktplain(mypkt, myproc);
  515.     AddTail(&NodList, pknode);
  516.     }
  517. }
  518.  
  519. void
  520. StartTimer(secs)
  521. {
  522.     if (IotIP) {
  523.     AbortIO(&Iot);
  524.     WaitIO(&Iot);
  525.     }
  526.     Iot.tr_time.tv_secs = secs;
  527.     Iot.tr_time.tv_micro= 0;
  528.     SendIO(&Iot);
  529.     IotIP = 1;
  530. }
  531.  
  532.  
  533.