SERIAL.C 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  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. #pragma off (unreferenced)
  53. static char rcsid[] = "$Id: serial.c 2.1 1995/03/30 16:36:21 mike Exp $";
  54. #pragma on (unreferenced)
  55. #include <stdio.h>
  56. #include <stdlib.h>
  57. #include <dos.h>
  58. #include <conio.h>
  59. #include "serial.h"
  60. #include "dpmi.h"
  61. typedef struct {
  62. char buffer[256];
  63. unsigned char write_index;
  64. unsigned char read_index;
  65. } BUFFER;
  66. typedef struct {
  67. void (interrupt far * old_vector)();
  68. int uart_base;
  69. int irq_mask;
  70. int interrupt_number;
  71. BUFFER in;
  72. BUFFER out;
  73. } PORT;
  74. #define RBR 0 /* Receive buffer register */
  75. #define THR 0 /* Trasmit holding register */
  76. #define IER 1 /* Interrupt Enable reg. */
  77. #define IER_RX_DATA 1 /* Enable RX interrupt bit */
  78. #define IER_THRE 2 /* Enable TX interrupt bit */
  79. #define IIR 2 /* interrupt ID register */
  80. #define IIR_MODEM_STATUS 0 /* Modem stat. interrupt ID */
  81. #define IIR_TRANSMIT 2 /* Transmit interrupt ID */
  82. #define IIR_RECEIVE 4 /* Receive interrupt ID */
  83. #define IIR_LINE_STATUS 6 /* Line stat. interrupt ID */
  84. #define LCR 3 /* Line control register */
  85. #define LCR_DLAB 0x80 /* Divisor access bit */
  86. #define LCR_EVEN_PARITY 0x18 /* Set parity 'E' bits */
  87. #define LCR_ODD_PARITY 0x8 /* Set parity 'O' bits */
  88. #define LCR_NO_PARITY 0 /* Set parity 'N' bits */
  89. #define LCR_1_STOP_BIT 0 /* Bits to set 1 stop bit */
  90. #define LCR_2_STOP_BITS 4 /* Bits to set 2 stop bits */
  91. #define LCR_5_DATA_BITS 0 /* Bits to set 5 data bits */
  92. #define LCR_6_DATA_BITS 1 /* Bits to set 6 data bits */
  93. #define LCR_7_DATA_BITS 2 /* Bits to set 7 data bits */
  94. #define LCR_8_DATA_BITS 3 /* Bits to set 8 data bits */
  95. #define MCR 4 /* Modem Control Register */
  96. #define MCR_DTR 1 /* Bit to turn on DTR */
  97. #define MCR_RTS 2 /* Bit to turn on RTS */
  98. #define MCR_OUT1 4 /* Bit to turn on OUT1 */
  99. #define MCR_OUT2 8 /* Bit to turn on OUT2 */
  100. #define LSR 5 /* Line status register */
  101. #define LSR_TEMT 32 /* transmitter holding status empty */
  102. #define MSR 6 /* Modem status register */
  103. #define DLL 0 /* Divisor latch LSB */
  104. #define DLM 1 /* Divisor latch MSB */
  105. #define INT_CONTROLLER 0x20 /* Address of 8259 */
  106. #define EOI 0x20 /* the end of int command */
  107. #define BREAK_VECTOR 0x23 /* the CTRL-BREAK vector */
  108. #define COM1_UART 0x3f8
  109. #define COM1_INTERRUPT 12
  110. #define COM2_UART 0x2f8
  111. #define COM2_INTERRUPT 11
  112. #define COM3_UART 0x2e8
  113. #define COM3_INTERRUPT 11
  114. #define COM4_UART 0x2d8
  115. #define COM4_INTERRUPT 12
  116. static PORT port;
  117. #pragma off (check_stack)
  118. void __interrupt __far serial_isr()
  119. {
  120. unsigned char c;
  121. _enable();
  122. while(1) {
  123. switch( inp( port.uart_base + IIR ) ) {
  124. case IIR_MODEM_STATUS :
  125. inp( port.uart_base + MSR );
  126. break;
  127. case IIR_TRANSMIT :
  128. if ( port.out.read_index == port.out.write_index )
  129. outp( port.uart_base + IER, IER_RX_DATA );
  130. else {
  131. c = port.out.buffer[ port.out.read_index++ ];
  132. outp( port.uart_base + THR, c );
  133. }
  134. break;
  135. case IIR_RECEIVE :
  136. c = (unsigned char) inp( port.uart_base+RBR );
  137. if ((port.in.write_index+1 ) != port.in.read_index)
  138. port.in.buffer[ port.in.write_index++ ] = c;
  139. break;
  140. case IIR_LINE_STATUS :
  141. inp( port.uart_base + LSR );
  142. break;
  143. default:
  144. outp( INT_CONTROLLER, EOI );
  145. return;
  146. }
  147. }
  148. }
  149. void serial_isr_end() // Used to mark the end of interrupt
  150. {
  151. }
  152. #pragma on (check_stack)
  153. void serial_open(int port_number, long speed, char parity, int data, int stopbits )
  154. {
  155. int address, int_number;
  156. unsigned char temp;
  157. unsigned char lcr_out;
  158. unsigned char mcr_out;
  159. unsigned char low_divisor;
  160. unsigned char high_divisor;
  161. if (!dpmi_lock_region ((void near *)serial_isr, (char *)serial_isr_end - (char near *)serial_isr)) {
  162. printf( "%s\n", TXT_ERROR_SERIAL_LOCK );
  163. exit(1);
  164. }
  165. if (!dpmi_lock_region (&port, sizeof(PORT) ) ) {
  166. printf( "%s\n", TXT_ERROR_SERIAL_LOCK_2 );
  167. exit(1);
  168. }
  169. switch( port_number ) {
  170. case 1:
  171. address = COM1_UART;
  172. int_number = COM1_INTERRUPT;
  173. break;
  174. case 2:
  175. address = COM2_UART;
  176. int_number = COM2_INTERRUPT;
  177. break;
  178. case 3:
  179. address = COM3_UART;
  180. int_number = COM3_INTERRUPT;
  181. break;
  182. case 4:
  183. address = COM4_UART;
  184. int_number = COM4_INTERRUPT;
  185. break;
  186. default:
  187. address = COM1_UART;
  188. int_number = COM1_INTERRUPT;
  189. }
  190. port.in.write_index = port.in.read_index = 0;
  191. port.out.write_index = port.out.read_index = 0;
  192. port.uart_base = address;
  193. port.irq_mask = (char) 1 << (int_number % 8 );
  194. port.interrupt_number = int_number;
  195. port.old_vector = _dos_getvect( int_number );
  196. _dos_setvect( int_number, serial_isr );
  197. temp = (char) inp( INT_CONTROLLER + 1 );
  198. outp( INT_CONTROLLER + 1, ~port.irq_mask & temp );
  199. /* Disable all interrupts from the port */
  200. outp( port.uart_base + IER, 0 );
  201. /* read RBR just in case there is a char sitting there */
  202. inp( port.uart_base );
  203. /* write the baud rate */
  204. low_divisor = (char)(115200L / speed ) & 0xff;
  205. high_divisor = (char)((115200L / speed ) >> 8 );
  206. outp( port.uart_base + LCR, LCR_DLAB );
  207. outp( port.uart_base + DLL, low_divisor );
  208. outp( port.uart_base + DLM, high_divisor );
  209. outp( port.uart_base + LCR, 0 );
  210. /* set up parity, stop bits, word length */
  211. if ( parity == 'E' )
  212. lcr_out = LCR_EVEN_PARITY;
  213. else if ( parity == 'O' )
  214. lcr_out = LCR_ODD_PARITY;
  215. else
  216. lcr_out = LCR_NO_PARITY;
  217. if ( stopbits == 2 )
  218. lcr_out |= LCR_2_STOP_BITS;
  219. if ( data == 6 )
  220. lcr_out |= LCR_6_DATA_BITS;
  221. else if ( data == 7 )
  222. lcr_out |= LCR_7_DATA_BITS;
  223. else if ( data == 8 )
  224. lcr_out |= LCR_8_DATA_BITS;
  225. outp( port.uart_base + LCR, lcr_out );
  226. /* Turn on RTS, DTR, OUT2 */
  227. mcr_out = MCR_RTS | MCR_DTR | MCR_OUT2;
  228. outp( port.uart_base + MCR, mcr_out );
  229. /* restart reciever interrupts and exit */
  230. outp( port.uart_base + IER, IER_RX_DATA );
  231. }
  232. void serial_close( )
  233. {
  234. unsigned char temp;
  235. outp( port.uart_base + IER, 0 );
  236. temp = (unsigned char) inp( INT_CONTROLLER + 1 );
  237. outp( INT_CONTROLLER + 1, port.irq_mask | temp );
  238. _dos_setvect( port.interrupt_number, port.old_vector );
  239. outp( port.uart_base + MCR, 0 );
  240. }
  241. //--unused-- int serial_putc( unsigned char c ) {
  242. //--unused-- if ((port.out.write_index+1 ) == port.out.read_index )
  243. //--unused-- return(-1);
  244. //--unused-- port.out.buffer[ port.out.write_index ] = c;
  245. //--unused-- port.out.write_index += 1;
  246. //--unused-- if ((inp( port.uart_base + IER ) & IER_THRE) == 0 )
  247. //--unused-- outp( port.uart_base + IER, IER_THRE | IER_RX_DATA );
  248. //--unused-- return( c );
  249. //--unused-- }
  250. //--unused--
  251. int serial_getc() {
  252. if (port.in.write_index == port.in.read_index )
  253. return(-1);
  254. else
  255. return( port.in.buffer[ port.in.read_index++ ] );
  256. }
  257. void serial_test()
  258. {
  259. }