home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / serial.c < prev    next >
C/C++ Source or Header  |  1998-06-08  |  9KB  |  295 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/main/rcs/serial.c $
  15.  * $Revision: 2.1 $
  16.  * $Author: mike $
  17.  * $Date: 1995/03/30 16:36:21 $
  18.  * 
  19.  * .
  20.  * 
  21.  * $Log: serial.c $
  22.  * Revision 2.1  1995/03/30  16:36:21  mike
  23.  * text localization.
  24.  * 
  25.  * Revision 2.0  1995/02/27  11:27:38  john
  26.  * New version 2.0, which has no anonymous unions, builds with
  27.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  28.  * 
  29.  * Revision 1.7  1994/11/19  15:15:11  mike
  30.  * remove unused code and data
  31.  * 
  32.  * Revision 1.6  1994/11/12  19:58:17  john
  33.  * Turned off stack checking around interrupt.
  34.  * 
  35.  * Revision 1.5  1994/11/12  19:47:20  matt
  36.  * Added paren
  37.  * 
  38.  * Revision 1.4  1994/11/12  19:46:16  john
  39.  * Fixed buug that didn't lock down isr data.
  40.  * 
  41.  * Revision 1.3  1994/11/12  17:59:54  john
  42.  * Added code to lock down interrupt code and data for serial isr.
  43.  * 
  44.  * Revision 1.2  1994/07/21  21:31:32  john
  45.  * First cheapo version of VictorMaxx tracking.
  46.  * 
  47.  * Revision 1.1  1994/07/21  18:40:38  john
  48.  * Initial revision
  49.  * 
  50.  * 
  51.  */
  52.  
  53.  
  54. #pragma off (unreferenced)
  55. static char rcsid[] = "$Id: serial.c 2.1 1995/03/30 16:36:21 mike Exp $";
  56. #pragma on (unreferenced)
  57.  
  58. #include <stdio.h>
  59. #include <stdlib.h>
  60. #include <dos.h>
  61. #include <conio.h>
  62. #include "serial.h"
  63. #include "dpmi.h"
  64.  
  65. typedef struct  {
  66.     char buffer[256];
  67.     unsigned char write_index;
  68.     unsigned char read_index;
  69. } BUFFER;
  70.  
  71. typedef struct  {
  72.     void (interrupt far * old_vector)();
  73.     int uart_base;
  74.     int irq_mask;
  75.     int interrupt_number;
  76.     BUFFER in;
  77.     BUFFER out;
  78. } PORT;
  79.  
  80.  
  81. #define RBR                 0   /* Receive buffer register */
  82. #define THR                 0   /* Trasmit holding register */
  83. #define IER                 1   /* Interrupt Enable reg. */
  84. #define IER_RX_DATA         1   /* Enable RX interrupt bit */
  85. #define IER_THRE            2   /* Enable TX interrupt bit */
  86. #define IIR                 2   /* interrupt ID register */
  87. #define IIR_MODEM_STATUS    0   /* Modem stat. interrupt ID */
  88. #define IIR_TRANSMIT        2   /* Transmit interrupt ID */
  89. #define IIR_RECEIVE         4   /* Receive interrupt ID */
  90. #define IIR_LINE_STATUS     6   /* Line stat. interrupt ID */
  91. #define LCR                 3   /* Line control register */
  92. #define LCR_DLAB            0x80 /* Divisor access bit */
  93. #define LCR_EVEN_PARITY     0x18 /* Set parity 'E' bits */
  94. #define LCR_ODD_PARITY      0x8 /* Set parity 'O' bits */
  95. #define LCR_NO_PARITY       0    /* Set parity 'N' bits */
  96. #define LCR_1_STOP_BIT      0   /* Bits to set 1 stop bit */
  97. #define LCR_2_STOP_BITS     4   /* Bits to set 2 stop bits */
  98. #define LCR_5_DATA_BITS     0   /* Bits to set 5 data bits */
  99. #define LCR_6_DATA_BITS     1   /* Bits to set 6 data bits */
  100. #define LCR_7_DATA_BITS     2   /* Bits to set 7 data bits */
  101. #define LCR_8_DATA_BITS     3   /* Bits to set 8 data bits */
  102. #define MCR                 4   /* Modem Control Register */
  103. #define MCR_DTR             1   /* Bit to turn on DTR */
  104. #define MCR_RTS             2   /* Bit to turn on RTS */
  105. #define MCR_OUT1            4   /* Bit to turn on OUT1 */
  106. #define MCR_OUT2            8   /* Bit to turn on OUT2 */
  107. #define LSR                 5   /* Line status register */
  108. #define LSR_TEMT            32  /* transmitter holding status empty */
  109. #define MSR                 6   /* Modem status register */
  110. #define DLL                 0   /* Divisor latch LSB */
  111. #define DLM                 1   /* Divisor latch MSB */
  112.  
  113. #define INT_CONTROLLER      0x20    /* Address of 8259 */
  114. #define EOI                 0x20    /* the end of int command */
  115. #define BREAK_VECTOR        0x23    /* the CTRL-BREAK vector */
  116.  
  117. #define COM1_UART       0x3f8
  118. #define COM1_INTERRUPT  12
  119. #define COM2_UART       0x2f8
  120. #define COM2_INTERRUPT  11
  121. #define COM3_UART       0x2e8
  122. #define COM3_INTERRUPT  11
  123. #define COM4_UART       0x2d8
  124. #define COM4_INTERRUPT  12
  125.  
  126. static PORT port;
  127.  
  128. #pragma off (check_stack)
  129. void __interrupt __far serial_isr()   
  130. {
  131.     unsigned char c;
  132.  
  133.     _enable();
  134.     while(1)    {
  135.         switch( inp( port.uart_base + IIR ) )   {
  136.         case IIR_MODEM_STATUS :
  137.             inp( port.uart_base + MSR );
  138.             break;
  139.         case IIR_TRANSMIT :
  140.             if ( port.out.read_index == port.out.write_index )
  141.                 outp( port.uart_base + IER, IER_RX_DATA );
  142.             else    {
  143.                 c = port.out.buffer[ port.out.read_index++ ];
  144.                 outp( port.uart_base + THR, c );
  145.             }
  146.             break;
  147.         case IIR_RECEIVE :
  148.             c = (unsigned char) inp( port.uart_base+RBR );
  149.             if ((port.in.write_index+1 ) != port.in.read_index)
  150.                 port.in.buffer[ port.in.write_index++ ] = c;
  151.             break;
  152.         case IIR_LINE_STATUS :
  153.             inp( port.uart_base + LSR );
  154.             break;
  155.         default:
  156.             outp( INT_CONTROLLER, EOI );
  157.             return;
  158.         }
  159.     }
  160. }
  161.  
  162. void serial_isr_end()        // Used to mark the end of interrupt
  163. {
  164. }
  165. #pragma on (check_stack)
  166.  
  167.  
  168. void serial_open(int port_number, long speed, char parity, int data, int stopbits )
  169. {
  170.     int address, int_number;
  171.     unsigned char temp;
  172.     unsigned char lcr_out;
  173.     unsigned char mcr_out;
  174.     unsigned char low_divisor;
  175.     unsigned char high_divisor;
  176.  
  177.     if (!dpmi_lock_region ((void near *)serial_isr, (char *)serial_isr_end - (char near *)serial_isr))    {
  178.         printf( "%s\n", TXT_ERROR_SERIAL_LOCK );
  179.         exit(1);
  180.     }
  181.  
  182.     if (!dpmi_lock_region (&port, sizeof(PORT) ) )    {
  183.         printf( "%s\n", TXT_ERROR_SERIAL_LOCK_2 );
  184.         exit(1);
  185.     }
  186.     
  187.     switch( port_number )   {
  188.     case 1:
  189.         address = COM1_UART;
  190.         int_number = COM1_INTERRUPT;
  191.         break;
  192.     case 2:
  193.         address = COM2_UART;
  194.         int_number = COM2_INTERRUPT;
  195.         break;
  196.     case 3:
  197.         address = COM3_UART;
  198.         int_number = COM3_INTERRUPT;
  199.         break;
  200.     case 4:
  201.         address = COM4_UART;
  202.         int_number = COM4_INTERRUPT;
  203.         break;
  204.     default:
  205.         address = COM1_UART;
  206.         int_number = COM1_INTERRUPT;
  207.     }
  208.  
  209.     port.in.write_index = port.in.read_index = 0;
  210.     port.out.write_index = port.out.read_index = 0;
  211.     port.uart_base = address;
  212.     port.irq_mask = (char) 1 << (int_number % 8 );
  213.     port.interrupt_number = int_number;
  214.     port.old_vector = _dos_getvect( int_number );
  215.     _dos_setvect( int_number, serial_isr );
  216.     temp = (char) inp( INT_CONTROLLER + 1 );
  217.     outp( INT_CONTROLLER + 1, ~port.irq_mask & temp );
  218.  
  219.     /* Disable all interrupts from the port */
  220.     outp( port.uart_base + IER, 0 );
  221.  
  222.     /* read RBR just in case there is a char sitting there */
  223.     inp( port.uart_base );
  224.  
  225.     /* write the baud rate */
  226.     low_divisor = (char)(115200L / speed ) & 0xff;
  227.     high_divisor = (char)((115200L / speed ) >> 8 );
  228.     outp( port.uart_base + LCR, LCR_DLAB );
  229.     outp( port.uart_base + DLL, low_divisor );
  230.     outp( port.uart_base + DLM, high_divisor );
  231.     outp( port.uart_base + LCR, 0 );
  232.  
  233.     /* set up parity, stop bits, word length */
  234.     if ( parity == 'E' )
  235.         lcr_out = LCR_EVEN_PARITY;
  236.     else if ( parity == 'O' )
  237.         lcr_out = LCR_ODD_PARITY;
  238.     else
  239.         lcr_out = LCR_NO_PARITY;
  240.  
  241.     if ( stopbits == 2 )
  242.         lcr_out |= LCR_2_STOP_BITS;
  243.  
  244.     if ( data == 6 )
  245.         lcr_out |= LCR_6_DATA_BITS;
  246.     else if ( data == 7 )
  247.         lcr_out |= LCR_7_DATA_BITS;
  248.     else if ( data == 8 )
  249.         lcr_out |= LCR_8_DATA_BITS;
  250.  
  251.     outp( port.uart_base + LCR, lcr_out );
  252.  
  253.     /* Turn on RTS, DTR, OUT2 */
  254.     mcr_out = MCR_RTS | MCR_DTR | MCR_OUT2;
  255.     outp( port.uart_base + MCR, mcr_out );
  256.  
  257.     /* restart reciever interrupts and exit */
  258.     outp( port.uart_base + IER, IER_RX_DATA );
  259. }
  260.  
  261. void serial_close( )
  262. {
  263.     unsigned char temp;
  264.  
  265.     outp( port.uart_base + IER, 0 );
  266.     temp = (unsigned char) inp( INT_CONTROLLER + 1 );
  267.     outp( INT_CONTROLLER + 1, port.irq_mask | temp );
  268.     _dos_setvect( port.interrupt_number, port.old_vector );
  269.     outp( port.uart_base + MCR, 0 );
  270. }
  271.  
  272. //--unused-- int serial_putc( unsigned char c )    {
  273. //--unused--     if ((port.out.write_index+1 ) == port.out.read_index )
  274. //--unused--         return(-1);
  275. //--unused--     port.out.buffer[ port.out.write_index ] = c;
  276. //--unused--     port.out.write_index += 1;
  277. //--unused--     if ((inp( port.uart_base + IER ) & IER_THRE) == 0 )
  278. //--unused--         outp( port.uart_base + IER, IER_THRE | IER_RX_DATA );
  279. //--unused--     return( c );
  280. //--unused-- }
  281. //--unused-- 
  282.  
  283. int serial_getc()  {
  284.     if (port.in.write_index == port.in.read_index )
  285.         return(-1);
  286.     else
  287.         return( port.in.buffer[ port.in.read_index++ ] );
  288. }
  289.  
  290. void serial_test()
  291. {
  292.  
  293. }
  294.  
  295.