home *** CD-ROM | disk | FTP | other *** search
/ The Devil's Doorknob BBS Capture (1996-2003) / devilsdoorknobbbscapture1996-2003.iso / Dloads / PROGRAMM / SERIAL.ZIP / SERIAL.C < prev    next >
C/C++ Source or Header  |  1992-01-29  |  10KB  |  424 lines

  1. /**********************************************************************
  2. * serial.c - Low-Level Serial Communications Routines                 *
  3. *            Copyright (c) 1992 By Mark D. Goodwin                    *
  4. **********************************************************************/
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <dos.h>
  8. #include <conio.h>
  9. #ifdef __TURBOC__
  10. #include <alloc.h>
  11. #else
  12. #include <malloc.h>
  13. #endif
  14. #include <time.h>
  15. #include "serial.h"
  16.  
  17. #ifndef __TURBOC__
  18. #define enable _enable
  19. #define inportb inp
  20. #define outportb outp
  21. #define getvect _dos_getvect
  22. #define disable _disable
  23. #define setvect _dos_setvect
  24. #define farmalloc _fmalloc
  25. #endif
  26.  
  27. /* UART register constants */
  28. #define TX 0                            /* transmit register */
  29. #define RX 0                            /* receive register */
  30. #define DLL 0                            /* divisor latch low */
  31. #define IER 1                            /* interrupt enable register */
  32. #define DLH 1                            /* divisor latch high */
  33. #define IIR 2                            /* interrupt id register */
  34. #define LCR 3                            /* line control register */
  35. #define MCR 4                            /* modem control register */
  36. #define LSR 5                            /* line status register */
  37. #define MSR 6                            /* modem status register */
  38.  
  39. /* interrupt enable register constants */
  40. #define RX_INT 1                        /* received data bit mask */
  41.  
  42. /* interrupt id register constants */
  43. #define INT_MASK 7                        /* interrupt mask */
  44. #define RX_ID 4                            /* received data interrupt */
  45.  
  46. /* line control register constants */
  47. #define DLAB 0x80                        /* DLAB bit mask */
  48.  
  49. /* modem control register constants */
  50. #define DTR 1                            /* Date Terminal Ready bit mask */
  51. #define RTS 2                            /* Request To Send bit mask */
  52. #define MC_INT 8                        /* GPO2 bit mask */
  53.  
  54. /* line status register constants */
  55. #define RX_RDY 0x01
  56. #define TX_RDY 0x20
  57.  
  58. /* modem status register constants */
  59. #define CTS 0x10
  60. #define DSR 0x20
  61. #define DCD 0x80
  62.  
  63. /* 8259 PIC constants */
  64. #define IMR 0x21                        /* interrupt mask register */
  65. #define ICR 0x20                        /* interrupt control register */
  66.  
  67. /* interrupt mask register constants */
  68. #define IRQ3 0xf7                        /* IRQ 3 interrupt mask */
  69. #define IRQ4 0xef                        /* IRQ 4 interrupt mask */
  70.  
  71. /* interrupt control register constants */
  72. #define EOI 0x20                        /* end of interrupt mask */
  73.  
  74. /* XON/XOFF flow control constants */
  75. #define XON 0x11
  76. #define XOFF 0x13
  77.  
  78. int port_open = FALSE, irq;
  79. #ifdef __TURBOC__
  80. void interrupt (*oldvect)();
  81. #else
  82. void (_interrupt _far *oldvect)();
  83. #endif
  84.  
  85. /* Check for a Port's Existence */
  86. int port_exist(int port)
  87. {
  88.     return mpeek(0, 0x400 + (port - 1) * 2);
  89. }
  90.  
  91. /* Open a Serial Port */
  92. void open_port(int port, int inlen)
  93. {
  94.     long i;
  95.  
  96.     /* make sure a port isn't already open */
  97.     if (port_open) {
  98.         printf("Unable to open port: A port is already open!\n");
  99.         exit(1);
  100.     }
  101.  
  102.     /* make sure the port if valid */
  103.     if (port < 1 || port > 4 || !port_exist(port)) {
  104.         printf("Unable to open port: Invalid port number!\n");
  105.         exit(1);
  106.     }
  107.  
  108.     /* allocate the space for the buffers */
  109.     ilen = inlen;
  110.     if ((inbuff = farmalloc(ilen)) == NULL) {
  111.         printf("Unable to open port: Not enough memory for the buffer!\n");
  112.         exit(1);
  113.     }
  114.  
  115.     /* calculate the flow control limits */
  116.     foff = (int)((long)ilen * 90L / 100L);
  117.     fon = (int)((long)ilen * 80L / 100L);
  118.     rx_flow = FALSE;
  119.  
  120.     /* set the base address and IRQ*/
  121.     switch (port) {
  122.         case 1:
  123.             base = 0x3f8;
  124.             irq = 0x0c;
  125.             break;
  126.         case 2:
  127.             base = 0x2f8;
  128.             irq = 0x0b;
  129.             break;
  130.         case 3:
  131.             base = 0x3e8;
  132.             irq = 0x0c;
  133.             break;
  134.         case 4:
  135.             base = 0x2e8;
  136.             irq = 0x0b;
  137.             break;
  138.     }
  139.  
  140.     /* set up the interrupt handler */
  141.     disable();                                 /* disable the interupts */
  142.     oldvect = getvect(irq);                    /* save the current vector */
  143.     setvect(irq, handler);                    /* set the new vector */
  144.     sibuff = eibuff = 0;                    /* set the buffer pointers */
  145.     outportb(base + MCR,
  146.         inportb(base + MCR) | MC_INT | DTR | RTS); /* assert GPO2, RTS, and DTR */
  147.     outportb(base + IER, RX_INT);            /* set received data interrupt */
  148.     outportb(IMR,
  149.         inportb(IMR) & (irq == 0x0b ? IRQ3 : IRQ4)); /* set the interrupt */
  150.     enable();                                /* enable the interrupts */
  151.     fifo(14);                                /* set FIFO buffer for 14 bytes */
  152.     set_tx_rts(FALSE);                        /* turn off RTS/CTS flow control */
  153.     set_tx_dtr(FALSE);                        /* turn off DTR/DSR flow control */
  154.     set_tx_xon(FALSE);                        /* turn off XON/XOFF flow control */
  155.     set_rx_rts(FALSE);                        /* turn off RTS/CTS flow control */
  156.     set_rx_dtr(FALSE);                        /* turn off DTR/DSR flow control */
  157.     set_rx_xon(FALSE);                        /* turn off XON/XOFF flow control */
  158.     port_open = TRUE;                        /* flag port is open */
  159. }
  160.  
  161. /* close serial port routine */
  162. void close_port(void)
  163. {
  164.     /* check to see if a port is open */
  165.     if (!port_open)
  166.         return;
  167.  
  168.     port_open = FALSE;                        /* flag port not opened */
  169.  
  170.     disable();                                /* disable the interrupts */
  171.     outportb(IMR,
  172.         inportb(IMR) | (irq == 0x0b ? ~IRQ3 : ~IRQ4)); /* clear the interrupt */
  173.     outportb(base + IER, 0);                /* clear recceived data int */
  174.     outportb(base + MCR,
  175.         inportb(base + MCR) & ~MC_INT);        /* unassert GPO2 */
  176.     setvect(irq, oldvect);                    /* reset the old int vector */
  177.     enable();                                /* enable the interrupts */
  178.     outportb(base + MCR,
  179.         inportb(base + MCR) & ~RTS);        /* unassert RTS */
  180. }
  181.  
  182. /* purge input buffer */
  183. void purge_in(void)
  184. {
  185.     disable();                                 /* disable the interrupts */
  186.     sibuff = eibuff = 0;                    /* set the buffer pointers */
  187.     enable();                                /* enable the interrupts */
  188. }
  189.  
  190. /* set the baud rate */
  191. void set_baud(long baud)
  192. {
  193.     int c, n;
  194.  
  195.     /* check for 0 baud */
  196.     if (baud == 0L)
  197.         return;
  198.     n = (int)(115200L / baud);                /* figure the divisor */
  199.     disable();                                /* disable the interrupts */
  200.     c = inportb(base + LCR);                /* get line control reg */
  201.     outportb(base + LCR, (c | DLAB));        /* set divisor latch bit */
  202.     outportb(base + DLL, n & 0x00ff);        /* set LSB of divisor latch */
  203.     outportb(base + DLH, (n >> 8) & 0x00ff); /* set MSB of divisor latch */
  204.     outportb(base + LCR, c);                /* restore line control reg */
  205.     enable();                                /* enable the interrupts */
  206. }
  207.  
  208. /* get the baud rate */
  209. long get_baud(void)
  210. {
  211.     int c, n;
  212.  
  213.     disable();                                /* disable the interrupts */
  214.     c = inportb(base + LCR);                /* get line control reg */
  215.     outportb(base + LCR, (c | DLAB));        /* set divisor latch bit */
  216.     n = inportb(base + DLH) << 8;            /* get MSB of divisor latch */
  217.     n |= inportb(base + DLL);                /* get LSB of divisor latch */
  218.     outportb(base + LCR, c);                /* restore the line control reg */
  219.     enable();                                /* enable the interrupts */
  220.     return 115200L / (long)n;                /* return the baud rate */
  221. }
  222.  
  223. /* get number of data bits */
  224. int get_bits(void)
  225. {
  226.     return (inportb(base + LCR) & 3) + 5;        /* return number of data bits */
  227. }
  228.  
  229. /* get parity */
  230. int get_parity(void)
  231. {
  232.     switch ((inportb(base + LCR) >> 3) & 7) {
  233.         case 0:
  234.             return NO_PARITY;
  235.         case 1:
  236.             return ODD_PARITY;
  237.         case 3:
  238.             return EVEN_PARITY;
  239.     }
  240.     return -1;
  241. }
  242.  
  243. /* get number of stop bits */
  244. int get_stopbits(void)
  245. {
  246.     if (inportb(base + LCR) & 4)
  247.         return 2;
  248.     return 1;
  249. }
  250.  
  251. void set_data_format(int bits, int parity, int stopbit)
  252. {
  253.     int n;
  254.  
  255.     /* check parity value */
  256.     if (parity < NO_PARITY || parity > ODD_PARITY)
  257.         return;
  258.  
  259.     /* check number of bits */
  260.     if (bits < 5 || bits > 8)
  261.         return;
  262.  
  263.     /* check number of stop bits */
  264.     if (stopbit < 1 || stopbit > 2)
  265.         return;
  266.  
  267.     n = bits - 5;                            /* figure the bits value */
  268.     n |= ((stopbit == 1) ? 0 : 4);            /* figure the stop bit value */
  269.  
  270.     /* figure the parity value */
  271.     switch (parity) {
  272.         case NO_PARITY:
  273.             break;
  274.         case ODD_PARITY:
  275.             n |= 0x08;
  276.             break;
  277.         case EVEN_PARITY:
  278.             n |= 0x18;
  279.             break;
  280.     }
  281.  
  282.     disable();                                /* disable the interrupts */
  283.     outportb(base + LCR, n);                /* set the port */
  284.     enable();                                /* enable the interrupts */
  285. }
  286.  
  287. void set_port(long baud, int bits, int parity, int stopbit)
  288. {
  289.     /* check for open port */
  290.     if (!port_open)
  291.         return;
  292.  
  293.     set_baud(baud);                            /* set the baud rate */
  294.     set_data_format(bits, parity, stopbit); /* set the data format */
  295. }
  296.  
  297. /* check for byte in input buffer */
  298. int in_ready(void)
  299. {
  300.     return !(sibuff == eibuff);
  301. }
  302.  
  303. /* check for carrier routine */
  304. int carrier(void)
  305. {
  306.     return inportb(base + MSR) & DCD ? TRUE : FALSE;
  307. }
  308.  
  309. /* set DTR routine */
  310. void set_dtr(int n)
  311. {
  312.     if (n)
  313.         outportb(base + MCR, inportb(base + MCR) | DTR); /* assert DTR */
  314.     else
  315.         outportb(base + MCR, inportb(base + MCR) & ~DTR); /* unassert RTS */
  316. }
  317.  
  318. /* 16550 FIFO routine */
  319. void fifo(int n)
  320. {
  321.     int i;
  322.  
  323.     switch (n) {
  324.         case 1:
  325.             i = 1;                            /* 1 byte FIFO buffer */
  326.             break;
  327.         case 4:
  328.             i = 0x41;                        /* 4 byte FIFO buffer */
  329.             break;
  330.         case 8:
  331.             i = 0x81;                        /* 8 byte FIFO buffer */
  332.             break;
  333.         case 14:
  334.             i = 0xc1;                        /* 14 byte FIFO buffer */
  335.             break;
  336.         default:
  337.             i = 0;                            /* turn FIFO off for all others */
  338.     }
  339.     outportb(base + IIR, i);                /* set the FIFO buffer */
  340. }
  341.  
  342. #ifndef __TURBOC__
  343. void delay(clock_t n)
  344. {
  345.     clock_t i;
  346.  
  347.     i = n + clock();
  348.     while (i > clock()) ;
  349. }
  350. #endif
  351.  
  352. /* set transmit RTS/CTS flag */
  353. void set_tx_rts(int n)
  354. {
  355.     tx_rts = n;
  356. }
  357.  
  358. /* set transmit DTR/DSR flag */
  359. void set_tx_dtr(int n)
  360. {
  361.     tx_dtr = n;
  362. }
  363.  
  364. /* set transmit XON/XOFF flag */
  365. void set_tx_xon(int n)
  366. {
  367.     tx_xon = n;
  368.     tx_xonoff = FALSE;
  369. }
  370.  
  371. /* set receive RTS/CTS flag */
  372. void set_rx_rts(int n)
  373. {
  374.     rx_rts = n;
  375. }
  376.  
  377. /* set receive DTR/DSR flag */
  378. void set_rx_dtr(int n)
  379. {
  380.     rx_dtr = n;
  381. }
  382.  
  383. /* set receive XON/XOFF flag */
  384. void set_rx_xon(int n)
  385. {
  386.     rx_xon = n;
  387. }
  388.  
  389. /* get transmit RTS flag */
  390. int get_tx_rts(void)
  391. {
  392.     return tx_rts;
  393. }
  394.  
  395. /* get transmit DTR/DSR flag */
  396. int get_tx_dtr(void)
  397. {
  398.     return tx_dtr;
  399. }
  400.  
  401. /* get transmit XON/XOFF flag */
  402. int get_tx_xon(void)
  403. {
  404.     return tx_xon;
  405. }
  406.  
  407. /* get receive RTS/CTS flag */
  408. int get_rx_rts(void)
  409. {
  410.     return rx_rts;
  411. }
  412.  
  413. /* get receive DTR/DSR flag */
  414. int get_rx_dtr(void)
  415. {
  416.     return rx_dtr;
  417. }
  418.  
  419. /* get receive XON/XOFF flag */
  420. int get_rx_xon(void)
  421. {
  422.     return rx_xon;
  423. }
  424.