home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 341b.lha / uucp1_v1.03d / src / uuser / uuser.c < prev    next >
C/C++ Source or Header  |  1990-01-28  |  13KB  |  535 lines

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