home *** CD-ROM | disk | FTP | other *** search
- /* comm -- communications port i/o */
- /* copyright 1987 Michael M Rubenstein */
-
- #pragma inline
- #include <stdio.h>
- #include <dos.h>
- #include "atfinish.h"
- #include "comm.h"
-
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
-
- #define NUMUNIT 2 /* number of comm units */
-
- #define COMM_BUFSIZE 256 /* must be power of 2 <= 2^7 */
-
- #define DATA0 0x3f8 /* COM1 port address */
- #define DATA1 0x2f8 /* COM2 port address */
- #define INTMASK0 0xef /* mask for COM1 interrupt */
- #define INTMASK1 0xf7 /* mask for COM2 interrupt */
- #define INTERRUPT_VEC0 0x0c /* interrupt vector for COM1 */
- #define INTERRUPT_VEC1 0x0b /* interrupt vector for COM2 */
-
- #define DATA comm_base[unit]
- #define ENABLE_INT (comm_base[unit] + 1)
- #define DIVISOR0 (comm_base[unit] + 0)
- #define DIVISOR1 (comm_base[unit] + 1)
- #define INTERRUPT_ID (comm_base[unit] + 2)
- #define LINE_CTL (comm_base[unit] + 3)
- #define MODEM_CTL (comm_base[unit] + 4)
- #define LINE_STATUS (comm_base[unit] + 5)
- #define MODEM_STATUS (comm_base[unit] + 6)
-
- #define INTERRUPT_CTL 0x20
- #define INTERRUPT_MASK 0x21
-
- static unsigned comm_base[NUMUNIT] = { DATA0, DATA1 };
- static unsigned char interrupt_mask[NUMUNIT] = { INTMASK0, INTMASK1 };
- static unsigned interrupt_vector[NUMUNIT] = { INTERRUPT_VEC0,
- INTERRUPT_VEC1
- };
-
- static void interrupt (*holdvec[NUMUNIT])();
- static unsigned char hold_interrupt_enable[NUMUNIT];
- static unsigned char hold_interrupt_mask[NUMUNIT];
-
- static unsigned char buffer0[COMM_BUFSIZE];
- static unsigned char buffer1[COMM_BUFSIZE];
- static unsigned char *buffer[NUMUNIT] = { buffer0, buffer1 };
-
- static int first[NUMUNIT] = { 0, 0 },
- next[NUMUNIT] = { 0, 0 };
-
- static int any_opened = FALSE;
- static int opened[NUMUNIT] = { FALSE, FALSE };
-
- void comm_int0(void);
- void comm_int1(void);
-
- /* open comm port. */
- int comm_open(unsigned unit, unsigned baud, int parity, int stop,
- int wordsize)
- {
- unsigned divisor;
- struct { char p_char;
- unsigned int p_bits;
- } parity_bits[] = { { 'n', 0x00 },
- { 'o', 0x04 },
- { 'e', 0x0c },
- { 0, 0 }
- },
- *pb;
- unsigned lctl;
-
-
- if (unit >= NUMUNIT)
- return FALSE;
-
- lctl = 0;
- for (pb = parity_bits; pb->p_char != 0; ++ pb)
- if (pb->p_char == parity)
- {
- lctl = pb->p_bits;
- break;
- }
- lctl |= (wordsize - 5);
- lctl |= (stop - 1) << 2;
-
-
- holdvec[unit] = getvect(interrupt_vector[unit]);
- setvect(interrupt_vector[unit],
- (unit == 0) ? (void interrupt (*)()) comm_int0
- : (void interrupt (*)()) comm_int1);
-
- hold_interrupt_enable[unit] = inportb(ENABLE_INT);
-
- outportb(ENABLE_INT, 0x01); /* set data ready int */
- hold_interrupt_mask[unit] = inportb(INTERRUPT_MASK);
- outportb(INTERRUPT_MASK, hold_interrupt_mask[unit] & interrupt_mask[unit]);
-
- outportb(LINE_CTL, 0x80); /* access divisor latch */
-
- divisor = (int) (0x1c200l / (long) baud);
- outportb(DIVISOR0, divisor); /* set baud divisor */
- outportb(DIVISOR1, divisor >> 8);
- outportb(LINE_CTL, lctl); /* 81n */
- outportb(MODEM_CTL, 0x0b); /* DTR, RTS, interrupts */
- outportb(INTERRUPT_CTL, 0x20); /* EOI to 8259 */
-
- if (!any_opened)
- atfinish(comm_close_all);
-
- any_opened = opened[unit] = TRUE;
-
- comm_clr(unit);
- return TRUE;
- }
-
- /* close all comm ports */
- void comm_close_all(void)
- {
- int i;
-
- for (i = 0; i < NUMUNIT; ++i)
- comm_close(i);
- }
-
- /* close a comm port -- drop modem control signals and stop interrupts */
- void comm_close(unsigned unit)
- {
- if (unit < NUMUNIT && opened[unit])
- {
- outportb(MODEM_CTL, 0x00); /* no DTR, RTS, interrupts */
- outportb(ENABLE_INT, hold_interrupt_enable[unit]);
- outportb(INTERRUPT_MASK, hold_interrupt_mask[unit]);
- setvect(interrupt_vector[unit], holdvec[unit]);
- opened[unit] = FALSE;
- }
- }
-
- /* interrupt handler for COM1 */
- static void comm_int0(void)
- {
- asm push ds
- asm push dx
- asm push bx
- asm push ax
-
- asm mov dx,dgroup
- asm mov ds,dx
- asm mov dx,3f8h
- asm in al,dx /* get character */
- asm sub bx,bx
- asm mov bx,next+0*2
- asm mov byte ptr buffer0[bx],al /* mov char. into buffer */
- asm inc bx /* advance buffer pointer */
- asm and bx,COMM_BUFSIZE-1
- asm cmp bx,first+0*2
- asm je finish /* don't update ptr if no room */
- asm mov next+0*2,bx
-
- finish:
- asm mov al,20h /* send EOI to 8259 */
- asm out 20h,al
-
- asm pop ax
- asm pop bx
- asm pop dx
- asm pop ds
- asm iret
- }
-
- /* interrupt handler for COM2 */
- static void comm_int1(void)
- {
- asm push ds
- asm push dx
- asm push bx
- asm push ax
-
- asm mov dx,dgroup
- asm mov ds,dx
- asm mov dx,2f8h
- asm in al,dx /* get character */
- asm sub bx,bx
- asm mov bx,next+1*2
- asm mov byte ptr buffer1[bx],al /* mov char. into buffer */
- asm inc bx /* advance buffer pointer */
- asm and bx,COMM_BUFSIZE-1
- asm cmp bx,first+1*2
- asm je finish /* don't update ptr if no room */
- asm mov next+1*2,bx
- finish:
- asm mov al,20h /* send EOI to 8259 */
- asm out 20h,al
-
- asm pop ax
- asm pop bx
- asm pop dx
- asm pop ds
- asm iret
- }
-
- /* get character from comm */
- int comm_getc(unsigned unit)
- {
- int c;
-
- if (unit >= NUMUNIT)
- return -1;
-
- if (first[unit] == next[unit])
- return -1;
-
- c = buffer[unit][first[unit]];
- first[unit] = (first[unit] == COMM_BUFSIZE - 1) ? 0 : first[unit] + 1;
- return c;
- }
-
- /* clear input buffer */
- void comm_clr(unsigned unit)
- {
- if (unit < NUMUNIT)
- {
- disable();
- first[unit] = next[unit];
- inportb(DATA); /* also clear anything in the chip */
- inportb(DATA);
- enable();
- }
- }
-
- /* put character to comm */
- int comm_putc(unsigned unit, int c)
- {
- if (unit > NUMUNIT)
- return FALSE;
-
- if (inportb(LINE_STATUS) & 0x20)
- {
- outportb(DATA, c);
- return TRUE;
- }
- return FALSE;
- }
-