home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / program / c / bts314b4 / com_st.c < prev    next >
C/C++ Source or Header  |  1994-01-08  |  11KB  |  536 lines

  1. /*
  2.  * com_st.c
  3.  *
  4.  * Atari ST specific Comms stuff
  5.  *
  6.  * see also com.h and com_st.h
  7.  *
  8.  */
  9.  
  10. #include <stdio.h>
  11. #ifdef __TOS__
  12. #pragma warn -sus
  13. #include <stddef.h>
  14. #else
  15. #include <osbind.h>
  16. #endif
  17. #include <portab.h>
  18. #include <time.h>
  19. #include <stdlib.h>
  20.  
  21. #include "bink.h"
  22. #include "com.h"
  23.  
  24. #ifndef min
  25. #define min(a,b)     ((a)<=(b)?(a):(b))
  26. #endif
  27.  
  28. #ifdef TXINT
  29. extern long set_txint(void);
  30. extern long reset_txint(void);
  31. #endif
  32.  
  33.  
  34. #if !defined(LATTICE) || (__REVISION__ < 50)
  35. /*
  36.  * Bios I/O Record
  37.  */
  38.  
  39. struct iorec {
  40.     char *ibuf;
  41.     short ibufsiz;
  42.     volatile short ibufhd;    /* New characters written here */
  43.     volatile short ibuftl;    /* Read characters from here */
  44.     short ibuflow;
  45.     short ibufhi;
  46. };
  47. #endif
  48.  
  49. /*
  50.  * Variables used by BUFFER_BYTES
  51.  */
  52.  
  53. #define TSIZE 8192                    /* Default buffer sizes */
  54. #define RSIZE 8192
  55.  
  56. static unsigned char zTxBuf[TSIZE];
  57. static size_t zpos = 0;
  58.  
  59. #if 0
  60. static unsigned char rbuf[RSIZE];
  61. static unsigned char tbuf[TSIZE];
  62. #else
  63. static unsigned char *rbuf = NULL;    /* New RS232 buffers */
  64. static unsigned char *tbuf = NULL;
  65.  
  66. size_t tBufSize = 8192;            /* New size of buffers */
  67. size_t rBufSize = 8192;
  68.  
  69. #endif
  70.  
  71. static short old_obufsize = 0;        /* Old output buffer */
  72. static char *old_obuf = NULL;
  73. static short old_obuflow;
  74. static short old_obufhi;
  75. static short old_ibufsize = 0;        /* Old input buffer */
  76. static char *old_ibuf = NULL;
  77. static short old_ibuflow;
  78. static short old_ibufhi;
  79.  
  80. BOOLEAN ikbdclock = FALSE;            /* IKBD clock update Disabled by default */
  81. int ctsflow = USE_CTS;                /* RTS/CTS is enabled */
  82. BOOLEAN hard_38400 = FALSE;            /* set if using hardware 38400 locking */
  83. BOOLEAN rsve_board = FALSE;            /* RSVE board installed    */
  84.  
  85. /* int xonflow = USE_XON; */        /* Xon/Xoff is enabled during Zmodem */
  86. static unsigned int last_baud = 0;    /* Current setting */
  87.  
  88. static BOOLEAN is_installed = FALSE;
  89.  
  90. BOOLEAN HardCTS = FALSE;                /* Use Hardware CTS checking! */
  91.  
  92. /*
  93.  * Initialise comms port
  94.  *
  95.  * Currently the port is ignored, but it may be possible later to provide
  96.  * support to any device that lets you have several ports
  97.  *
  98.  * It may also be neccessary to fiddle with the iobuffers to make their
  99.  * sizes configurable.
  100.  *
  101.  */
  102.  
  103. int Cominit(int port)
  104. {
  105.     struct iorec *io = Iorec(0);        /* Input buffer */
  106.  
  107.     if ( port )
  108.     {
  109.     }
  110.     
  111.     if(!is_installed)
  112.     {
  113.  
  114. #ifdef TXINT
  115.         Supexec(set_txint);                    /* Change the interrupt vector */
  116. #endif
  117.  
  118.         if(rBufSize)
  119.         {
  120.             if(rbuf == NULL)
  121.             {
  122.                 rbuf = malloc(rBufSize);
  123.                 if(rbuf == NULL)
  124.                 {
  125.                     status_line("!Could not allocate memory for RS232 buffers");
  126.                     return -1;
  127.                 }
  128. #ifdef DEBUG
  129.                 status_line(">Allocated %d bytes for RBUF", (int)rBufSize);
  130. #endif
  131.             }
  132.             old_ibuf = io->ibuf;
  133.             old_ibufsize = io->ibufsiz;
  134.             old_ibuflow = io->ibuflow;
  135.             old_ibufhi = io->ibufhi;
  136.  
  137.             Jdisint(12);                /* Disable receive buffer full interrupt */
  138.             io->ibufhd = 0;                /* the order of these 2 is important */
  139.             io->ibuftl = 0;
  140.             io->ibuf = rbuf;
  141.             io->ibufsiz = (int) rBufSize;
  142.             io->ibuflow = (short) (rBufSize >> 2);        /* 1/4 buffer size */
  143.             io->ibufhi = (short) (rBufSize - (rBufSize >> 2));    /* 3/4 buffer size */
  144.             Jenabint(12);
  145.         }
  146.         else
  147.         {
  148.             rBufSize = io->ibufsiz;
  149.             rbuf = io->ibuf;
  150. #ifdef DEBUG
  151.             status_line(">Using default RBUF of %d bytes", (int)rBufSize);
  152. #endif            
  153.         }
  154.         
  155.         /* Fiddle transmit buffer */    
  156.  
  157.         io++;                        /* Advance to output buffer */
  158.  
  159.         if(tBufSize)
  160.         {
  161.             if(tbuf == NULL)
  162.             {
  163.                 tbuf = malloc(tBufSize);
  164.                 if(tbuf == NULL)
  165.                 {
  166.                     status_line("!Could not allocate memory for RS232 buffers");
  167.                     return -1;
  168.                 }
  169. #ifdef DEBUG
  170.                 status_line(">Allocated %d bytes for TBUF", (int)tBufSize);
  171. #endif
  172.             }
  173.             
  174.             old_obuf = io->ibuf;
  175.             old_obufsize = io->ibufsiz;
  176.             old_obuflow = io->ibuflow;
  177.             old_obufhi = io->ibufhi;
  178.     
  179.             Jdisint(10);                /* Disable transmit buffer empty interrupt */
  180.             io->ibuftl = 0;                /* the order of these 2 is important */
  181.             io->ibufhd = 0;
  182.             io->ibuf = tbuf;
  183.             io->ibufsiz = (int) tBufSize;
  184.             io->ibuflow = (short)(tBufSize/4);        /* 1/4 buffer size */
  185.             io->ibufhi = (short)((tBufSize*3)/4);    /* 3/4 buffer size */
  186.             Jenabint(10);
  187.         }
  188.         else
  189.         {
  190.             tBufSize = io->ibufsiz;
  191.             tbuf = io->ibuf;
  192. #ifdef DEBUG
  193.             status_line(">Using default RBUF of %d bytes", (int)tBufSize);
  194. #endif            
  195.         }
  196.  
  197.         is_installed = TRUE;
  198.  
  199.     }
  200.         
  201. #ifndef OLDCTS
  202.     Rsconf(-1, ctsflow,-1,-1,-1,-1);    /* Enable RTS/CTS */
  203. #endif
  204.  
  205.  
  206.     last_baud = 0;
  207.     zpos = 0;
  208.  
  209.     return 0x1954;                /* Return magic number */
  210. }
  211.  
  212. /*
  213.  * Close up the comms port and restore everything to normal
  214.  */
  215.  
  216. void MDM_DISABLE(void)
  217. {
  218.     struct iorec *io = Iorec(0);        /* Input buffer */
  219.  
  220.     if(is_installed)
  221.     {
  222.  
  223.         /* Restore receive buffer */
  224.  
  225.         if(old_ibuf != NULL)
  226.         {
  227.             Jdisint(12);                /* Disable receive buffer full interrupt */
  228.             io->ibufhd = 0;                /* the order of these 2 is important */
  229.             io->ibuftl = 0;
  230.             io->ibuf = old_ibuf;
  231.             io->ibufsiz = old_ibufsize;
  232.             io->ibuflow = old_ibuflow;
  233.             io->ibufhi = old_ibufhi;
  234.  
  235.             Jenabint(12);
  236.             
  237.             old_ibuf = NULL;
  238.         }
  239.  
  240.         /* Restore transmit buffer */    
  241.  
  242.         io++;                        /* Advance to output buffer */
  243.  
  244.         if(old_obuf != NULL)
  245.         {
  246.             Jdisint(10);                /* Disable transmit buffer empty interrupt */
  247.             io->ibuftl = 0;                /* the order of these 2 is important */
  248.             io->ibufhd = 0;
  249.             io->ibuf = old_obuf;
  250.             io->ibufsiz = old_obufsize;
  251.             io->ibuflow = old_obuflow;
  252.             io->ibufhi = old_obufhi;
  253.             Jenabint(10);
  254.             old_obuf = NULL;
  255.         }
  256.         
  257. #ifdef TXINT
  258.         Supexec(reset_txint);        /* Restore the interrupt vector */
  259. #endif
  260.  
  261.         is_installed = FALSE;
  262.  
  263.     }
  264. }
  265.  
  266.  
  267. /*
  268.  * Initialise modem to give baud rate
  269.  *
  270.  * The baud will be the bits defined as BAUD_??? in com_st.h
  271.  *
  272.  * Note that baud is now the actual baud rate rather than a mask
  273.  */
  274.  
  275.  
  276. static struct {
  277.     unsigned short rate;
  278.     short mask;
  279. } rates[] = {
  280.     { 50L,15 },
  281.     { 75L,14 },
  282.     { 110L,13 },
  283.     { 134L,12 },
  284.     { 150L,11 },
  285.     { 200L,10 },
  286.     { 300L,9 },
  287.     { 600L,10 },
  288.     { 1200L,7 },
  289.     { 1800L,6 },
  290.     { 2000L,5 },
  291.     { 2400L,4 },
  292.     { 3600L,3 },
  293.     { 4800L,2 },
  294.     { 9600L,1 },
  295.     { 19200L,0 },
  296.     { 38400L,4 },    /* Same as 2400 baud, but without /16 */
  297.     { 57600L,12 },    /* with rsve */
  298.     { 115200L,11 },
  299.     { 0L,-1 }            /* End of list.. unchanged rate */
  300. };
  301.  
  302. unsigned int st_lock_baud = 0;    /* Baud rate above which to force baud rate */
  303.  
  304.  
  305. void MDM_ENABLE(unsigned baud)
  306. {
  307.     int i;
  308.     
  309.    if(st_lock_baud && (baud >= st_lock_baud))
  310.            baud = max_baud.rate_mask;
  311.  
  312.     if(hard_38400)            /* Adjust for hardware /2 counter */
  313.         baud >>= 1;
  314.  
  315.  
  316.     if(baud != last_baud)
  317.     {
  318.         UBYTE ucr = stop_bits|parity|comm_bits;
  319.  
  320.         if(baud != 38400L || (baud == 38400L && rsve_board))
  321.             ucr |= 0x80;
  322. #if 0
  323.         else
  324.             ucr |= 0x18;        /* Use 2 stop bits */
  325. #endif
  326.  
  327.         last_baud = baud;
  328.  
  329.         if(rsve_board) rates[16].mask = 13;
  330.         i = 0;
  331.         while( rates[i].rate && (rates[i].rate != baud) )
  332.             i++;
  333.  
  334.         if(rates[i].rate)
  335.             Rsconf(rates[i].mask, -1, ucr, -1, -1, -1);
  336.     }
  337. }
  338.  
  339.  
  340. /*
  341.  * Find out if RS232 buffer is empty
  342.  */
  343.  
  344. /* BOOLEAN OUT_EMPTY(void)
  345. {    struct iorec *buf = Iorec(0);
  346.     buf++;
  347.     return (buf->ibufhd == buf->ibuftl);
  348. } */
  349.  
  350.  
  351. /*
  352.  * Clear the output buffer
  353.  */
  354.  
  355. void CLEAR_OUTBOUND(void)
  356. {
  357.     struct iorec *buf = Iorec(0);    /* Rs232 output buffer */
  358.     buf++;
  359.  
  360.     buf->ibufhd = buf->ibuftl;        /* head = tail (interrupt changes hd) */
  361.  
  362.     zpos = 0;                        /* Clear the buffer BUFFER */
  363. }
  364.  
  365. /*
  366.  * Clear the input buffer
  367.  */
  368.  
  369. void CLEAR_INBOUND(void)
  370. {
  371.     struct iorec *buf = Iorec(0);
  372.     buf->ibuftl = buf->ibufhd;        /* Set tail to head (int changes tl) */
  373. }
  374.  
  375.  
  376. /*
  377.  * Output a character, but dont wait for buffer space
  378.  *
  379.  * Returns TRUE if character was output
  380.  *          FALSE if buffer was full
  381.  */
  382.  
  383. BOOLEAN Com_Tx_NW(char c)
  384. {
  385.     if(Bcostat(1))
  386.     {
  387. #ifdef __TOS__
  388.         Bconout(1, c);
  389.         return TRUE;
  390. #else
  391.         return (BOOLEAN)Bconout(1, c);
  392. #endif
  393.  
  394.     }
  395.     else
  396.         return FALSE;
  397.  
  398. }
  399.  
  400.  
  401. /*
  402.  * Send character, but buffer it up
  403.  * and force a send with UNBUFFER_BYTES
  404.  * used by zsend and janus
  405.  */
  406.  
  407.  
  408. void UNBUFFER_BYTES(void)
  409. {
  410.    if (zpos && CARRIER)
  411.       if(zpos == 1)
  412.         SENDBYTE(zTxBuf[0]);
  413.       else
  414.         SENDCHARS(zTxBuf,zpos,1 );
  415.  
  416.    zpos = 0;
  417. }
  418.  
  419. void BUFFER_BYTE(unsigned char ch)
  420. {
  421.       if (zpos == tBufSize)            /* If buffer full, then empty it */
  422.          UNBUFFER_BYTES();
  423.       zTxBuf[zpos++]  = ch;            /* Add character to buffer */
  424. }
  425.  
  426.  
  427. /*
  428.  * ST specific Timer functions
  429.  */
  430.  
  431. /* Return the ST's 200Hz clock counter (MUST be called in Superviser mode */
  432.  
  433. #define _HZ_200 (*((long *)0x4ba))
  434.  
  435. static long get_200hz(void)
  436. {
  437.     return _HZ_200;
  438. }
  439.  
  440. /* Indicate timer is to time out in t/100 second */
  441.  
  442. long timerset(unsigned long t)
  443. {
  444.     return (long) (Supexec((long(*)(void))get_200hz) + t*2);
  445. }
  446.  
  447. /*
  448.  * Return TRUE if timer as timed out
  449.  */
  450.  
  451. int timeup(long t)
  452. {
  453.     long newtime = Supexec((long(*)(void))get_200hz);
  454.  
  455.     /*
  456.      * It is possible that it wrapped around, but that only happens
  457.      * every 248 days.    Is it really worth it?
  458.      * OK... I never took into account signed numbers, but its still
  459.      * 4 months!!!!
  460.      */
  461.  
  462.     return (newtime >= t);
  463. }
  464.  
  465. void dostime( int *hour, int *min, int *sec, int *hdths )
  466. {
  467.     time_t t;
  468.     struct tm *dt;
  469.  
  470.     if(ikbdclock)
  471.         update_time();
  472.     
  473.     time(&t);
  474.     dt = localtime(&t);
  475.  
  476.     *hour       = dt->tm_hour;                         /* current hour */
  477.     *min       = dt->tm_min;                      /* current minute */
  478.     *sec       = dt->tm_sec;                    /* current second */
  479.     *hdths       = 0;                                /* hundredths of seconds */
  480. }
  481.  
  482. void dosdate( int *month, int *mday, int *year, int *weekday )
  483. {
  484.     time_t t;
  485.     struct tm *dt;
  486.  
  487.     if(ikbdclock)
  488.         update_time();
  489.     
  490.     time(&t);
  491.     dt = localtime(&t);
  492.  
  493.     *mday       = dt->tm_mday;                           /* current day */
  494.     *month       = dt->tm_mon;                        /* current month */
  495.     *year       = dt->tm_year;                          /* current year */
  496.     *weekday   = dt->tm_wday;                       /* current day of week */
  497. }
  498.  
  499. void do_break(int onoff)
  500. {
  501.     Rsconf(-1,-1,-1,-1, onoff ? 9 : 1,-1);
  502. }
  503.  
  504. /*
  505.  * Update the GEMDOS clock from the IKBD one
  506.  *
  507.  * Its possible that odd things can happen if interrupts occur between
  508.  * setting the date and time.  Lets hope it doesn't happen.
  509.  */
  510.  
  511. void update_time(void)
  512. {
  513.     union {
  514.         long ikbd;
  515.         struct {
  516.             short tosdate;
  517.             short tostime;
  518.         } tos;
  519.     } thetime;
  520.     short gemtime;
  521.  
  522.     if(ikbdclock)
  523.     {
  524.         thetime.ikbd = Gettime();
  525.         gemtime = Tgettime() - thetime.tos.tostime;
  526.  
  527.         /* If 2 times differ by more than 2 seconds then update the TOS time */
  528.     
  529.         if((gemtime > 2) || (gemtime < -2))
  530.         {
  531.             Tsettime(thetime.tos.tostime);
  532.             Tsetdate(thetime.tos.tosdate);
  533.         }
  534.     }
  535. }
  536.