home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cdisk.zip / SERIAL / SERIAL.C < prev    next >
C/C++ Source or Header  |  1992-12-23  |  20KB  |  716 lines

  1. /* file sample.c
  2.    sample OS/2 serial device driver
  3. */
  4.  
  5. #include "drvlib.h"
  6. #include "uart.h"
  7. #include "serial.h"
  8.  
  9. extern void near STRAT(); /* name of strat rout.*/
  10. extern void near TIM_HNDLR(); /* timer handler  */
  11. extern int  near INT_HNDLR(); /* interrupt hand */
  12.  
  13. DEVICEHDR devhdr = {
  14.  (void far *) 0xFFFFFFFF,  /* link              */
  15.  (DAW_CHR | DAW_OPN | DAW_LEVEL1),/* attribute  */
  16.  (OFF) STRAT,              /* &strategy         */
  17.  (OFF) 0,                  /* &IDCroutine       */
  18.  "DEVICE1 "
  19.   };
  20.  
  21. CHARQUEUE   rx_queue;      /* receiver queue    */
  22. CHARQUEUE   tx_queue;      /* transmitter queue */
  23. FPFUNCTION  DevHlp=0;      /* for DevHlp calls  */
  24. LHANDLE     lock_seg_han;  /* handle for locking*/
  25. PHYSADDR    appl_buffer=0; /* address of caller */
  26. PREQPACKET  p=0L;          /* Request Packet ptr*/
  27. ERRCODE     err=0;         /* error return      */
  28. void        far *ptr;      /* temp far pointer  */
  29. DEVICEHDR   *hptr;         /* pointer to Device */
  30. USHORT      i;             /* general counter   */
  31. UARTREGS    uart_regs;     /* uart registers    */
  32. ULONG       WriteID=0L;    /* ID for write Block*/
  33. ULONG       ReadID=0L;     /* ID for read Block */
  34. PREQPACKET  ThisReadRP=0L; /* for read Request  */
  35. PREQPACKET  ThisWriteRP=0L;/* for write Request */
  36. char        inchar,outchar;/* temp chars        */
  37. USHORT      baud_rate;     /* current baud rate */
  38. unsigned    int savepid;   /* PID of driver own */
  39. UCHAR       opencount;     /* number of times   */
  40. ULONG       tickcount;     /* for timeouts      */
  41. unsigned    int com_error_word; /* UART status  */
  42. USHORT      port;          /* port variable     */
  43. USHORT      temp_bank;     /* holds UART bank   */
  44. QUEUE       rqueue;        /* receive queue info*/
  45.  
  46. void near init();
  47. void near enable_write();
  48. void near disable_write();
  49. void near set_dlab();
  50. void near reset_dlab();
  51. void near config_82050();
  52.  
  53. char   IntFailMsg[] = " interrupt handler failed to install.\r\n";
  54. char   MainMsg[] = " OS/2 Serial Device Driver V1.0 installed.\r\n";
  55.  
  56. /* common entry point to strat routines */
  57.  
  58. int main(PREQPACKET rp, int dev )
  59. {
  60.    void far *ptr;
  61.    int far *pptr;
  62.    PLINFOSEG liptr;    /* pointer to local info */
  63.    int i;
  64.    ULONG addr;
  65.  
  66.    switch(rp->RPcommand)
  67.     {
  68.     case RPINIT:       /* 0x00                  */
  69.  
  70.         /* init called by kernel in prot mode */
  71.  
  72.         return Init(rp,dev);
  73.  
  74.     case RPOPEN:       /* 0x0d                  */
  75.  
  76.         /* get current processes id */
  77.  
  78.         if (GetDOSVar(2,&ptr))
  79.             return (RPDONE|RPERR|ERROR_BAD_COMMAND);
  80.  
  81.         /* get process info */
  82.  
  83.         liptr = *((PLINFOSEG far *) ptr);
  84.  
  85.         /* if this device never opened */
  86.  
  87.         if (opencount == 0) /* 1st time dev op'd*/
  88.         {
  89.             ThisReadRP=0L;
  90.             ThisWriteRP=0L;
  91.             opencount=1;  /* set open counter   */
  92.             savepid = liptr->pidCurrent; /* PID */
  93.             QueueInit(&rx_queue);/* init driver */
  94.             QueueInit(&tx_queue);
  95.         }
  96.         else
  97.             {
  98.             if (savepid != liptr->pidCurrent)
  99.                 return (RPDONE | RPERR | RPBUSY );
  100.             ++opencount;       /* bump counter  */
  101.         }
  102.         return (RPDONE);
  103.  
  104.     case RPCLOSE:        /* 0x0e                */
  105.  
  106.         /* get process info of caller */
  107.  
  108.         if (GetDOSVar(2,&ptr))
  109.             return (RPDONE|RPERR|ERROR_BAD_COMMAND); /* no info  */
  110.  
  111.         /* get process info from os/2 */
  112.  
  113.         liptr= *((PLINFOSEG far *) ptr); /* PID */
  114.         if (savepid != liptr->pidCurrent ||
  115.            opencount == 0)
  116.         return (RPDONE|RPERR|ERROR_BAD_COMMAND);
  117.         --opencount;   /* close counts down open*/
  118.  
  119.         if (ThisReadRP !=0 && opencount == 0) {
  120.             Run((ULONG) ThisReadRP); /* dangling*/
  121.             ThisReadRP=0L;
  122.         }
  123.         return (RPDONE);     /* return 'done'   */
  124.  
  125.     case RPREAD:             /* 0x04            */
  126.  
  127.         /*  Try to read a character */
  128.  
  129.         ThisReadRP = rp;
  130.         if (opencount == 0)/* drvr was closed   */
  131.         {
  132.             rp->s.ReadWrite.count = 0;  /* EOF  */
  133.             return(RPDONE);
  134.         }
  135.         com_error_word=0;/* start off no errors */
  136.         ReadID = (ULONG) rp;
  137.         if (Block(ReadID, -1L, 0, &err))
  138.             if (err == 2)       /* interrupted  */
  139.                return(RPDONE|RPERR|ERROR_CHAR_CALL_INTERRUPTED);
  140.  
  141.         if (rx_queue.qcount == 0) {
  142.            rp->s.ReadWrite.count=0;
  143.            return (RPDONE|RPERR|ERROR_NOT_READY);
  144.            }
  145.  
  146.         i=0;
  147.         do {
  148.           if (MoveData((FARPOINTER)&inchar,
  149.           (FARPOINTER) (rp->s.ReadWrite.buffer+i),
  150.           1,
  151.              MOVE_VIRTTOPHYS))
  152.             return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  153.             }
  154.         while (++i < rp->s.ReadWrite.count
  155.             && !QueueRead(&rx_queue,&inchar));
  156.         rp->s.ReadWrite.count = i;
  157.         QueueInit(&rx_queue);
  158.         return(rp->RPstatus);
  159.  
  160.     case RPWRITE:        /* 0x08                */
  161.  
  162.         ThisWriteRP = rp;
  163.  
  164.         /* transfer characters from user buffer */
  165.  
  166.         addr=rp->s.ReadWrite.buffer;/* get addr */
  167.         for (i = rp->s.ReadWrite.count; i; --i,++addr)
  168.         {
  169.           if (MoveData((FARPOINTER)addr,
  170.              (FARPOINTER)&outchar,
  171.                  1,
  172.                  MOVE_PHYSTOVIRT))
  173.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  174.  
  175.           if (QueueWrite(&tx_queue,outchar))
  176.               return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  177.           }
  178.         WriteID = (ULONG) rp;
  179.         enable_write();
  180.  
  181.         if (Block(WriteID, -1L, 0, &err))
  182.             if (err == 2)   /* interrupted      */
  183.                 return(RPDONE|RPERR|ERROR_CHAR_CALL_INTERRUPTED);
  184.  
  185.         tickcount=MIN_TIMEOUT; /* reset timeout */
  186.         QueueInit(&tx_queue);
  187.         return (rp->RPstatus);
  188.  
  189.     case RPINPUT_FLUSH:      /* 0x07            */
  190.  
  191.         QueueFlush(&rx_queue);
  192.         return (RPDONE);
  193.  
  194.     case RPOUTPUT_FLUSH:     /* 0x0b            */
  195.  
  196.         QueueFlush(&tx_queue);
  197.         return (RPDONE);
  198.  
  199.     case RPIOCTL:            /* 0x10            */
  200.  
  201.         if (!((rp->s.IOCtl.category == SAMPLE_CAT)
  202.            || (rp->s.IOCtl.category == 0x01)))
  203.               return (RPDONE);
  204.  
  205.         switch (rp->s.IOCtl.function)
  206.         {
  207.         case 0x41:    /* set baud rate          */
  208.         /* set baud rate to 1.2, 2.4, 9.6, 19.2 */
  209.         /* verify caller owns the buffer area   */
  210.  
  211.         if(VerifyAccess(
  212.          SELECTOROF(rp->s.IOCtl.parameters),
  213.          OFFSETOF(rp->s.IOCtl.parameters),
  214.          2,             /* two bytes            */
  215.          1) )           /* read/write           */
  216.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  217.  
  218.          /* lock the segment down temp */
  219.  
  220.          if(LockSeg(
  221.          SELECTOROF(rp->s.IOCtl.parameters),
  222.          0,          /* lock for < 2 sec      */
  223.          0,          /* wait for seg lock     */
  224.          (PLHANDLE) &lock_seg_han)) /* handle */
  225.              return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  226.  
  227.          /* get physical address of buffer */
  228.          if (VirtToPhys(
  229.          (FARPOINTER) rp->s.IOCtl.parameters,
  230.          (FARPOINTER) &appl_buffer))
  231.              return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  232.  
  233.          /* move data to local driver buffer */
  234.  
  235.          if(MoveData(
  236.          (FARPOINTER) appl_buffer,  /* source             */
  237.          (FARPOINTER)&baud_rate,    /* destination        */
  238.          2,                         /* 2 bytes            */
  239.             MOVE_PHYSTOVIRT))
  240.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  241.  
  242.          if (UnPhysToVirt()) /* release selector*/
  243.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  244.  
  245.          /* unlock segment */
  246.  
  247.          if(UnLockSeg(lock_seg_han))
  248.               return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  249.  
  250.          switch (baud_rate)
  251.             {
  252.             case 1200:
  253.  
  254.                 uart_regs.Bal=0xe0;
  255.                 uart_regs.Bah=0x01;
  256.                 break;
  257.  
  258.             case 2400:
  259.  
  260.                 uart_regs.Bal=0xf0;
  261.                 uart_regs.Bah=0x00;
  262.                 break;
  263.  
  264.             case 9600:
  265.  
  266.                 uart_regs.Bal=0x3c;
  267.                 uart_regs.Bah=0x00;
  268.                 break;
  269.  
  270.             case 19200:
  271.  
  272.                 uart_regs.Bal=0x1e;
  273.                 uart_regs.Bah=0x00;
  274.                 break;
  275.  
  276.             case 38400:
  277.  
  278.                 uart_regs.Bal=0x0f;
  279.                 uart_regs.Bah=0x00;
  280.                 break;
  281.  
  282. error:
  283.             return (RPDONE|RPERR|ERROR_BAD_COMMAND);
  284.  
  285.             }
  286.             init();      /* reconfigure uart    */
  287.             return (RPDONE);
  288.  
  289.         case 0x68:       /* get number of chars */
  290.  
  291.             /* verify caller owns the buffer    */
  292.  
  293.             if(VerifyAccess(
  294.             SELECTOROF(rp->s.IOCtl.buffer),
  295.             OFFSETOF(rp->s.IOCtl.buffer),
  296.             4,            /* 4 bytes            */
  297.             1) )          /* read/write         */
  298.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  299.  
  300.             /* lock the segment down temp */
  301.  
  302.             if(LockSeg(
  303.             SELECTOROF(rp->s.IOCtl.buffer),
  304.             0,           /* lock for < 2 sec    */
  305.             0,           /* wait for seg lock   */
  306.             (PLHANDLE) &lock_seg_han)) /* handle*/
  307.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  308.  
  309.             /* get physical address of buffer */
  310.  
  311.             if (VirtToPhys(
  312.             (FARPOINTER) rp->s.IOCtl.buffer,
  313.             (FARPOINTER) &appl_buffer))
  314.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  315.  
  316.             rqueue.cch=rx_queue.qcount;
  317.             rqueue.cb=rx_queue.qsize;
  318.  
  319.             /* move data to local driver buffer */
  320.  
  321.             if(MoveData(
  322.             (FARPOINTER)&rx_queue,  /* source   */
  323.             (FARPOINTER) appl_buffer, /* dest   */
  324.             4,           /* 4 bytes             */         
  325.                 MOVE_PHYSTOVIRT))
  326.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  327.  
  328.             if (UnPhysToVirt())
  329.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  330.  
  331.             /* unlock segment */
  332.  
  333.             if(UnLockSeg(lock_seg_han))
  334.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  335.  
  336.             return (RPDONE);
  337.  
  338.         case 0x6d:    /* get COM error info     */
  339.  
  340.             /* verify caller owns the buffer    */
  341.  
  342.             if(VerifyAccess(
  343.             SELECTOROF(rp->s.IOCtl.buffer),
  344.             OFFSETOF(rp->s.IOCtl.buffer),
  345.             2,        /* two bytes              */
  346.             1) )      /* read/write             */
  347.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  348.  
  349.             /* lock the segment down temp */
  350.  
  351.             if(LockSeg(
  352.             SELECTOROF(rp->s.IOCtl.buffer),
  353.             0,        /* lock for < 2 sec       */
  354.             0,        /* wait for seg lock      */
  355.             (PLHANDLE) &lock_seg_han)) /* handle*/
  356.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  357.  
  358.             /* get physical address of buffer */
  359.  
  360.             if (VirtToPhys(
  361.             (FARPOINTER) rp->s.IOCtl.buffer,
  362.             (FARPOINTER) &appl_buffer))
  363.                return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  364.  
  365.             /* move data to application buffer */
  366.  
  367.             if(MoveData(
  368.             (FARPOINTER)&com_error_word, /* source */
  369.             (FARPOINTER) appl_buffer,    /* dest   */
  370.             2,            /* 2 bytes               */
  371.                 MOVE_VIRTTOPHYS))
  372.                 return (RPDONE|RPERR|ERROR_GEN_FAILURE);
  373.  
  374.             if (UnPhysToVirt())
  375.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  376.  
  377.             /* unlock segment */
  378.  
  379.             if(UnLockSeg(lock_seg_han))
  380.                 return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  381.  
  382.             return (RPDONE);
  383.  
  384.         default:
  385.             return(RPDONE|RPERR|ERROR_GEN_FAILURE);
  386.         }
  387.  
  388.         /* don't allow deinstall */
  389.  
  390.     case RPDEINSTALL:  /* 0x14                  */
  391.         return(RPDONE|RPERR|ERROR_BAD_COMMAND);
  392.  
  393.     /* all other commands are ignored */
  394.  
  395.     default:
  396.         return(RPDONE);
  397.  
  398.     }
  399. }
  400.  
  401. void enable_write()
  402.  
  403. /* enable write interrupts on uart */
  404.  
  405. {
  406.     int  port;
  407.     int  reg_val;
  408.  
  409.     port=UART_PORT_ADDRESS;
  410.     reg_val=inp(port+2) & 0x60;
  411.     set_bank(00);
  412.     outp((port+1),inp(port+1) | 0x12);
  413.     outp((port+2),reg_val);
  414.  
  415. }
  416. void disable_write()
  417.  
  418. /* turn off write interrupts on uart */
  419.  
  420. {
  421.     int  port;
  422.     int  reg_val;
  423.  
  424.     port=UART_PORT_ADDRESS;
  425.     reg_val=inp(port+2) & 0x60;
  426.     set_bank(00);
  427.     outp((port+1),inp(port+1) & 0xed);
  428.     outp((port+2),reg_val);
  429.  
  430. }
  431.  
  432. void init ()
  433.  
  434. /* intializes software and configures 82050 */
  435.  
  436. {
  437.     config_82050 ();    /* Configure 82050      */
  438.     set_bank(01);
  439. }
  440.  
  441. void config_82050()
  442.  
  443. /*  Configure the 82050      */
  444.  
  445. {
  446.     int  port;
  447.     int inval;
  448.  
  449.     Disable();                          /* disable interrupts    */
  450.     port=UART_PORT_ADDRESS;
  451.  
  452.     /* set stick bit */
  453.  
  454.     set_bank(01);                       /* stick bit            */
  455.     outp((port+7),0x10);                /* reset port           */
  456.     outp ((port+1), uart_regs.Txf);     /* stick bit            */
  457.  
  458.     set_bank (02);                      /* general config       */
  459.     outp ((port + 4), uart_regs.Imd);   /*auto rupt             */
  460.     outp ((port + 7), uart_regs.Rmd);
  461.     outp ((port + 5), uart_regs.Acr1);  /* cntl-z               */
  462.     outp ((port + 3), uart_regs.Tmd);   /* no 9 bit             */
  463.     outp ((port + 1), uart_regs.Fmd);   /* rx fifo              */
  464.     outp ((port + 6), uart_regs.Rie);   /* enable               */
  465.  
  466.     set_bank (03);                      /* modemconfiguration   */
  467.  
  468.     outp ((port + 0), uart_regs.Clcf);  /* clock                */
  469.     set_dlab (03);                      /*                      */
  470.     outp ((port + 0), uart_regs.Bbl);   /* BRGB lsb             */
  471.     outp ((port + 1), uart_regs.Bbh);   /* BRGB msb             */
  472.     reset_dlab (03);                    /*                      */
  473.     outp ((port + 3), uart_regs.Bbcf);  /* BRGB                 */
  474.     outp ((port + 6), uart_regs.Tmie);  /* timer b              */
  475.  
  476.     set_bank (00);                      /* general cfg          */
  477.     outp ((port + 1), uart_regs.Ger);   /* enable               */
  478.     outp ((port + 3), uart_regs.Lcr);   /* 8 bit                */
  479.     outp ((port + 7), uart_regs.Acr0);  /* CR                   */
  480.     outp ((port + 4), uart_regs.Mcr_0); /* no DTR               */
  481.     set_dlab (00);                      /*                      */
  482.     outp ((port + 0), uart_regs.Bal);   /* BRGA lsb             */
  483.     outp ((port + 1), uart_regs.Bah);   /* BRGA msb             */
  484.     reset_dlab (00);
  485.     set_bank(01);
  486.  
  487.     Enable();                           /* turn on              */
  488. }
  489.  
  490. void set_dlab (bank)
  491.  
  492. /*  Set DLAB bit to allow access to divisior registers  */
  493.  
  494. int bank;
  495. {
  496.     int  inval;
  497.     int  port;
  498.  
  499.     port=UART_PORT_ADDRESS;
  500.     set_bank (00);
  501.     inval=inp(port +3);
  502.     inval =inval | 0x80;                 /* set dlab in LCR     */
  503.     outp ((port+3),inval);
  504.     set_bank (bank);
  505. }
  506.  
  507. getsrc()
  508.  
  509. {
  510.     int   v,src;
  511.     int   port;
  512.  
  513.     port=UART_PORT_ADDRESS;             /* get base address     */
  514.     v=inp(port+2);                      /* get data             */
  515.     src=v & 0x0e;                       /* mask bits            */
  516.     src=src/2;                          /* divide by 2          */
  517.     return(src);                        /* and pass it back     */
  518. }
  519.  
  520. set_bank(bank_num)
  521.  
  522. /* set bank of 82050 uart */
  523.  
  524. int  bank_num;
  525.  
  526. {
  527.     int reg_val;
  528.     int   port;
  529.  
  530.     reg_val=bank_num*0x20;              /* select bank numb */
  531.     port=UART_PORT_ADDRESS;             /* get real port    */
  532.     outp(port+gir_addr,reg_val);        /* output      */
  533. }
  534.  
  535. void reset_dlab (bank)
  536.  
  537. /*  Reset DLAB bit of LCR   */
  538.  
  539. int bank;
  540.  
  541. {
  542.     int  inval;
  543.     int  port;
  544.  
  545.     port=UART_PORT_ADDRESS;
  546.     set_bank (00);
  547.     inval=inp (port +3);
  548.     inval = (inval & 0x7f);             /* dlab = 0 in LCR      */
  549.     outp ((port+3),inval);
  550.     set_bank (bank);
  551. }
  552.  
  553. /* 82050 interrupt handler */
  554.  
  555. void interrupt_handler ()
  556. {
  557.     int  rupt_dev;
  558.     int  source;
  559.     int  cmd_b;
  560.     int  st_b;
  561.     int  port;
  562.     int  temp;
  563.     int  rxlevel;
  564.  
  565.  
  566.     port=UART_PORT_ADDRESS;
  567.     outp((port+2),0x20);                /* switch to bank 1     */
  568.     source = getsrc ();                 /* get vector           */
  569.     switch (source)
  570.     {
  571.  
  572.     /* optional timer service routine */
  573.  
  574.     case timer :
  575.  
  576.         st_b=inp (port+3);              /* dec transmit count   */
  577.         if ( ThisReadRP == 0)           /* nobody waiting       */
  578.             break;
  579.         ThisReadRP->RPstatus=(RPDONE|RPERR|ERROR_NOT_READY);
  580.         Run ((ULONG)  ThisWriteRP);     /* run thread           */
  581.         ThisWriteRP=0;
  582.         break;
  583.  
  584.     case txm   :
  585.     case txf   :
  586.  
  587.         /* spurious write interrupt */
  588.  
  589.         if ( ThisWriteRP == 0) {
  590.             temp=inp(port+2);
  591.             break;
  592.         }
  593.  
  594.         /* keep transmitting until no data left */
  595.  
  596.         if  (!(QueueRead(&tx_queue,&outchar)))
  597.         {
  598.              outp((port), outchar);
  599.              tickcount=MIN_TIMEOUT;
  600.              break;
  601.         }
  602.  
  603.         /* done writing, run blocked thread     */
  604.  
  605.         tickcount=MIN_TIMEOUT;
  606.         disable_write();
  607.         ThisWriteRP->RPstatus = (RPDONE);
  608.         Run ((ULONG)  ThisWriteRP);
  609.         ThisWriteRP=0;
  610.         break;
  611.  
  612.     case ccr   :
  613.  
  614.         /* control character, treat as normal   */
  615.  
  616.         inchar=inp(port+5);
  617.  
  618.     case rxf   :
  619.  
  620.         /* rx fifo service routine */
  621.  
  622.         if ( ThisReadRP == 0)
  623.             inchar=inp (port); /* get character */
  624.         else
  625.         {
  626.         temp=inp(port+4);
  627.         rxlevel=(temp & 0x70) / 0x10;
  628.  
  629.          /* empty out chip FIFO */
  630.  
  631.          while (rxlevel !=0) {
  632.  
  633.            inchar=inp (port); /* get character */
  634.            rxlevel--;
  635.            tickcount=MIN_TIMEOUT;
  636.  
  637.            /* write input data to queue */
  638.  
  639.            if(QueueWrite(&rx_queue,inchar))
  640.  
  641.              /* error, queue must be full */
  642.  
  643.              {
  644.              ThisReadRP->RPstatus=(RPDONE|RPERR|ERROR_GEN_FAILURE);
  645.              Run ((ULONG) ThisReadRP);
  646.              ThisReadRP=0;
  647.              break;
  648.              }
  649.            com_error_word |= inp(port+5);
  650.  
  651.         } /* while rxlevel */
  652.      } /* else */
  653.   } /* switch (source) */
  654.   EOI(5);
  655. }
  656. void timer_handler()
  657. {
  658.   if (ThisReadRP == 0)
  659.         return;
  660.  
  661.   tickcount--;
  662.   if(tickcount == 0)  {
  663.     ThisReadRP->RPstatus=(RPDONE);
  664.     Run ((ULONG) ThisReadRP);
  665.     ThisReadRP=0L;
  666.     tickcount=MIN_TIMEOUT;
  667.     }
  668. }
  669.  
  670. /* Device Initialization Routine */
  671.  
  672. int Init(PREQPACKET rp, int dev)
  673. {
  674.     register char far *p;
  675.  
  676.     /* store DevHlp entry point */
  677.  
  678.     DevHlp = rp->s.Init.DevHlp;
  679.  
  680.     /* install interrupt hook in vector */
  681.  
  682.     if (SetTimer((PFUNCTION)TIM_HNDLR))
  683.                 goto fail;
  684.  
  685.     rx_queue.qsize=QUEUE_SIZE;
  686.     tx_queue.qsize=QUEUE_SIZE; /* init queue    */
  687.     init();                    /* init the port */
  688.     tickcount=MIN_TIMEOUT;     /* set timeout   */
  689.  
  690.     if(SetIRQ(5,(PFUNCTION)INT_HNDLR,0)) {
  691.  
  692.      /* if we failed, deinstall driver cs+ds=0 */
  693. fail:
  694.      DosPutMessage(1, 8, devhdr.DHname);
  695.      DosPutMessage (1,strlen(IntFailMsg),IntFailMsg);
  696.      rp->s.InitExit.finalCS = (OFF) 0;
  697.      rp->s.InitExit.finalDS = (OFF) 0;
  698.      return (RPDONE | RPERR | ERROR_BAD_COMMAND);
  699.      }
  700.  
  701. /* output initialization message */
  702.  
  703. DosPutMessage(1, 8, devhdr.DHname);
  704. DosPutMessage(1, strlen(MainMsg), MainMsg);
  705.  
  706. /* send back our cs and ds values to os/2 */
  707.  
  708. if (SegLimit(HIUSHORT((void far *) Init),&rp->s.InitExit.finalCS)
  709.     || SegLimit(HIUSHORT((void far *) MainMsg),
  710.     &rp->s.InitExit.finalDS))
  711.      Abort();
  712.    return(RPDONE);
  713. }
  714.  
  715.  
  716.