home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cdisk.zip / PARALLEL / DIGIO.C next >
C/C++ Source or Header  |  1992-07-29  |  12KB  |  349 lines

  1. /*
  2.    This driver supports DosOpen, DosClose, DosRead, DosWrite
  3.    and IOCtl 0x91 codes 1, 2 and 3. All other driver calls and
  4.    IOCtls are ignored (returns ERROR_BAD_COMMAND).
  5.  
  6.    The driver also uses these #defs
  7.  
  8.    #define  DIGIO_CAT    0x91         driver category       
  9.    #define  DIGIO_BASE   0x2c0        base port address
  10.    #define  DIGIO_OUTPUT DIGIO_BASE   output port
  11.    #define  DIGIO_INPUT  DIGIO_BASE+1 input port
  12.    #define  DIGIO_CONFIG DIGIO_BASE+3 initialization port
  13.  
  14.    1. Open the driver with:
  15.  
  16.       if ((RetCode=DosOpen("DIGIO$",
  17.          &digio_handle,
  18.          &ActionTaken,
  19.          FileSize,
  20.          FileAttribute,
  21.          FILE_OPEN,
  22.          OPEN_SHARE_DENYNONE | OPEN_FLAGS_FAIL_ON_ERROR
  23.          | OPEN_ACCESS_READWRITE,Reserved)) !=0) 
  24.             printf("\nopen error = %d",RetCode);
  25.  
  26.    2. Output byte to the output port (base +0) with this IOCtl:
  27.          
  28.       DosDevIOCtl(NULL,&char,1,0x91,digio_handle);
  29.  
  30.       or with this standard request:
  31.  
  32.       DosWrite(digio_handle,&char,1,&bytes_written;
  33.  
  34.    3. Read data from the input port (base + 1) with this IOCtl.
  35.       The driver will block until the bit in specified in the
  36.       mask is set:
  37.  
  38.       DosDevIOCtl(&char,NULL,2,0x91,digio_handle);
  39.  
  40.    4. Read data from the input port (base + 1) with this IOCtl.
  41.       This IOCtl returns immediately with the status:
  42.  
  43.       DosDevIOCtl(&char,NULL,3,0x91,digio_handle);
  44.  
  45.       or with this standard driver request:
  46.  
  47.       DosRead(digio_handle,&char,1,&bytes_read;
  48. */
  49.  
  50. #include "drvlib.h"
  51. #include "digio.h"
  52.  
  53. extern void STRATEGY();       /* name of strat rout. in drvstart*/
  54. extern void TIMER_HANDLER();  /* timer handler in drvstart      */
  55.  
  56. DEVICEHDR devhdr = {
  57.     (void far *) 0xFFFFFFFF,  /* link                           */
  58.     (DAW_CHR | DAW_OPN | DAW_LEVEL1),/* attribute word          */
  59.     (OFF) STRATEGY,           /* &strategy                      */
  60.     (OFF) 0,                  /* &IDC routine                   */
  61.     "DIGIO$  "                /* name/#units                    */
  62. };
  63.  
  64. FPFUNCTION  DevHlp=0;         /* pointer to DevHlp entry point  */
  65. UCHAR       opencount = 0;    /* keeps track of open's          */
  66. USHORT      savepid=0;        /* save thread pid                */
  67. LHANDLE     lock_seg_han;     /* handle for locking appl. seg   */
  68. PHYSADDR    appl_buffer=0;    /* address of caller's buffer     */
  69. ERRCODE     err=0;            /* error return                   */
  70. ULONG       ReadID=0L;        /* current read pointer           */
  71. USHORT      num_rupts=0;      /* count of interrupts            */
  72. USHORT      temp_char;        /* temp character for in-out      */
  73. void        far *ptr;         /* temp far pointer               */
  74. FARPOINTER  appl_ptr=0;       /* pointer to application buffer  */
  75. char        input_char,output_char; /* temp character storage   */
  76. char        input_mask;       /* mask for input byte            */
  77.  
  78. /* messages */
  79.  
  80. char     CrLf[]= "\r\n"; 
  81. char     InitMessage1[] = " 8 bit Digital I/O ";
  82. char     InitMessage2[] = " driver installed\r\n";
  83. char     FailMessage[]  = " driver failed to install.\r\n";
  84.  
  85. /* common entry point for calls to Strategy routines */
  86.  
  87. int main(PREQPACKET rp)
  88. {
  89.     void far *ptr;     
  90.     PLINFOSEG liptr;             /* pointer to global info seg  */
  91.     int i;
  92.     
  93.     switch(rp->RPcommand)
  94.     {
  95.     case RPINIT:                 /* 0x00                        */
  96.  
  97.         /* init called by kernel in protected mode */
  98.  
  99.         return Init(rp);
  100.  
  101.     case RPREAD:                 /* 0x04                        */
  102.  
  103.         rp->s.ReadWrite.count = 0; /* in case we fail           */
  104.         
  105.         input_char = inp(DIGIO_INPUT);/* get data               */
  106.  
  107.         if (PhysToVirt( (ULONG) rp->s.ReadWrite.buffer,
  108.            1,0,&appl_ptr))
  109.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  110.  
  111.         if (MoveBytes((FARPOINTER)&input_char,appl_ptr,1)) /* move one byte */
  112.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  113.  
  114.         rp->s.ReadWrite.count = 1;  /* one byte read           */
  115.         return (RPDONE);
  116.  
  117.     case RPWRITE:                /* 0x08                       */
  118.  
  119.         rp->s.ReadWrite.count = 0;
  120.  
  121.         if (PhysToVirt( (ULONG) rp->s.ReadWrite.buffer,
  122.            1,0,&appl_ptr))
  123.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  124.  
  125.         if (MoveBytes(appl_ptr,(FARPOINTER)&output_char,1)) /* move 1 byte */
  126.              return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  127.  
  128.         outp (DIGIO_OUTPUT,output_char); /* send byte          */
  129.  
  130.         rp->s.ReadWrite.count = 1; /* one byte written         */
  131.         return (RPDONE);
  132.  
  133.     case RPOPEN:                 /* 0x0d open driver           */
  134.  
  135.         /* get current process id */
  136.  
  137.         if (GetDOSVar(2,&ptr))
  138.             return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  139.  
  140.         /* get process info */
  141.  
  142.         liptr = *((PLINFOSEG far *) ptr);
  143.  
  144.         /* if this device never opened, can be opened by anyone*/
  145.  
  146.         if (opencount == 0)      /* first time this dev opened */
  147.         {
  148.             opencount=1;         /* bump open counter          */
  149.             savepid = liptr->pidCurrent; /* save current PID   */
  150.         }
  151.         else
  152.             {
  153.             if (savepid != liptr->pidCurrent) /* another proc  */
  154.                 return (RPDONE | RPERR | ERROR_NOT_READY);/*err*/
  155.             ++opencount;         /* bump counter, same pid     */
  156.         }
  157.         return (RPDONE);
  158.  
  159.     case RPCLOSE:                /* 0x0e DosClose,ctl-C, kill  */
  160.  
  161.         /* get process info of caller */
  162.  
  163.         if (GetDOSVar(2,&ptr))
  164.             return (RPDONE | RPERR | ERROR_BAD_COMMAND); 
  165.  
  166.         /* get process info from os/2 */
  167.  
  168.         liptr= *((PLINFOSEG far *) ptr); /* ptr to linfoseg    */
  169.  
  170.         /* 
  171.         make sure that process attempting to close this device
  172.         is the one that originally opened it and the device was
  173.         open in the first place.
  174.         */
  175.  
  176.         if (savepid != liptr->pidCurrent || opencount == 0)  
  177.             return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  178.  
  179.         --opencount;             /* close counts down open cntr*/
  180.          return (RPDONE);        /* return 'done' status       */
  181.  
  182.     case RPIOCTL:                /* 0x10                       */
  183.  
  184.         /*
  185.         The function code in an IOCtl packet has the high bit set
  186.         for the DIGIO$ board. We return all others with the done
  187.         bit set so we don't have to handle things like the 5-48
  188.         code page IOCtl
  189.         */
  190.  
  191.         if (rp->s.IOCtl.category != DIGIO_CAT)/* other IOCtls  */
  192.             return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  193.  
  194.         switch (rp->s.IOCtl.function)
  195.         {
  196.  
  197.         case 0x01:               /* write byte to digio port   */
  198.  
  199.             /* verify caller owns this buffer area */
  200.  
  201.             if(VerifyAccess(
  202.             SELECTOROF(rp->s.IOCtl.parameters), /* selector    */
  203.             OFFSETOF(rp->s.IOCtl.parameters),   /* offset      */
  204.             1,                                  /* 1 byte      */
  205.             0) )                                /* read only   */
  206.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  207.  
  208.             if(MoveBytes(rp->s.IOCtl.parameters,(FARPOINTER)&output_char,1))
  209.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  210.  
  211.             outp(DIGIO_OUTPUT,output_char);     /*send to digio*/
  212.             return (RPDONE);
  213.  
  214.         case 0x02:               /* read byte w/wait from port */
  215.  
  216.             /* verify caller owns this buffer area */
  217.  
  218.             if(VerifyAccess(
  219.             SELECTOROF(rp->s.IOCtl.buffer), /* selector        */
  220.             OFFSETOF(rp->s.IOCtl.buffer),   /* offset          */
  221.             1,                              /* 1 bytes)        */
  222.             0))                             /* read only       */
  223.                return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  224.  
  225.             /* lock the segment down temp */
  226.  
  227.             if(LockSeg(
  228.             SELECTOROF(rp->s.IOCtl.buffer), /* selector        */
  229.             1,                              /* lock forever    */
  230.             0,                              /* wait for seg loc*/
  231.             (PLHANDLE) &lock_seg_han))      /* handle returned */
  232.                return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  233.  
  234.             if(MoveBytes(rp->s.IOCtl.parameters,(FARPOINTER)&input_mask,1))
  235.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  236.  
  237.             /* wait for switch to be pressed */
  238.  
  239.             ReadID = (ULONG)rp;             /* block ID        */
  240.             if (Block(ReadID,-1L,0,&err))
  241.               if (err == 2)
  242.                 return(RPDONE | RPERR
  243.                        | ERROR_CHAR_CALL_INTERRUPTED);
  244.             
  245.             /* move data to users buffer */
  246.  
  247.             if(MoveBytes((FARPOINTER)&input_char,rp->s.IOCtl.buffer,1))
  248.                 return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  249.  
  250.             /* unlock segment */
  251.  
  252.             if(UnLockSeg(lock_seg_han))
  253.                 return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  254.  
  255.             return (RPDONE);
  256.  
  257.         case 0x03:               /* read byte immed digio port */
  258.  
  259.             /* verify caller owns this buffer area */
  260.  
  261.             if(VerifyAccess(
  262.             SELECTOROF(rp->s.IOCtl.buffer), /* selector        */
  263.             OFFSETOF(rp->s.IOCtl.buffer),   /* offset          */
  264.             4,                              /* 4 bytes         */
  265.             0))                             /* read only       */
  266.                 return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  267.  
  268.             input_char = inp(DIGIO_INPUT);  /* get data        */
  269.  
  270.             if(MoveBytes((FARPOINTER)&input_char,rp->s.IOCtl.buffer,1))
  271.                 return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  272.  
  273.             return (RPDONE);
  274.  
  275.         default:
  276.             return(RPDONE | RPERR | ERROR_GEN_FAILURE);
  277.         }
  278.  
  279.         /* don't allow deinstall */
  280.  
  281.     case RPDEINSTALL:            /* 0x14                       */
  282.         return(RPDONE | RPERR | ERROR_BAD_COMMAND);
  283.  
  284.         /* all other commands are flagged as bad */
  285.  
  286.     default:
  287.         return(RPDONE | RPERR | ERROR_BAD_COMMAND);
  288.  
  289.     }
  290. }
  291.  
  292. timr_handler()
  293. {
  294.  
  295.    if (ReadID != 0) {
  296.       
  297.       /* read data from port */
  298.       
  299.       input_char = inp(DIGIO_INPUT );/* get data               */
  300.  
  301.       if ((input_char && input_mask) !=0) {
  302.          Run (ReadID);
  303.          ReadID=0L;
  304.          }
  305.     }
  306. }
  307.  
  308. /* Device Initialization Routine */
  309.  
  310. int Init(PREQPACKET rp)
  311. {
  312.     /* store DevHlp entry point */
  313.  
  314.     DevHlp = rp->s.Init.DevHlp;
  315.  
  316.     /* install timer handler */
  317.  
  318.     if(SetTimer((PFUNCTION)TIMER_HANDLER)) {
  319.  
  320.       /* if we failed, effectively deinstall driver with cs+ds=0 */
  321.  
  322.       DosPutMessage(1, 8, devhdr.DHname);
  323.       DosPutMessage(1,strlen(FailMessage),FailMessage);
  324.       rp->s.InitExit.finalCS = (OFF) 0;
  325.       rp->s.InitExit.finalDS = (OFF) 0;
  326.       return (RPDONE | RPERR | ERROR_GEN_FAILURE);
  327.       }
  328.  
  329.     /* configure 8255 parallel chip */
  330.  
  331.     outp (DIGIO_CONFIG,0x91);
  332.  
  333.     /* output initialization message */
  334.  
  335.     DosPutMessage(1, 2, CrLf);
  336.     DosPutMessage(1, 8, devhdr.DHname);
  337.     DosPutMessage(1, strlen(InitMessage1), InitMessage1);
  338.     DosPutMessage(1, strlen(InitMessage2), InitMessage2);
  339.  
  340.     /* send back our code and data end values to os/2 */
  341.  
  342.     if (SegLimit(HIUSHORT((void far *) Init),
  343.       &rp->s.InitExit.finalCS) || SegLimit(HIUSHORT((void far *)
  344.       InitMessage2), &rp->s.InitExit.finalDS))
  345.         Abort();
  346.     return(RPDONE);
  347. }
  348.  
  349.