home *** CD-ROM | disk | FTP | other *** search
-
-
- /* NOTE: this code is indented using tabs set every 4 columns, not 8. */
-
- /*
- * Rudimentary communication program; written in C with I/O
- * routines in assembler, using "#asm" construct in DeSmet C.
- */
-
- #define TRUE 1
- #define FALSE 0
- #define NULL 0
-
- #define comm_stat head!=tail
-
- int head=0,
- tail=0;
-
- char comm_buffer[8192];
-
- main()
- {
- char commget();
-
- int c,
- echo=FALSE,
- verbose=FALSE;
-
- initcomm();
-
- goto inside;
- while((c=my_ci())<256) /* alt's and function keys are >=256 */
- {
- commput(c);
- if(echo)
- my_co(c);
- inside: while(my_stat()==0)
- if(comm_stat)
- if(is_nice(c=commget()))
- my_co(c);
- else
- if(verbose)
- {
- my_co('^');
- my_co(127&(c+'@'));
- }
- }
- switch(c>>8) /* process function key */
- {
- case '\060': /* b send break */
- make_break();
- my_puts("** break **\n");
- break;
- case '\022': /* e echo toggle */
- echo = !echo;
- if(echo)
- my_puts("** echo on **\n");
- else
- my_puts("** echo off **\n");
- break;
- case '\020': /* q quit */
- my_puts("** returning to DOS **\n");
- goto byebye;
- case '\057': /* v verbose */
- verbose = !verbose;
- if(verbose)
- my_puts("** verbose on **\n");
- else
- my_puts("** verbose off **\n");
- break;
- }
- goto inside;
-
- byebye:
- killcomm();
- }
-
- initcomm()
- {
- #asm
-
- ; initialize communication port,
- ; and install interrupt handler
-
- ; save dseg for interrupt handler
- mov ax,ds
- mov cs:dssave,ax
-
- ; set int vector to my handler
- push ds
- xor ax,ax
- mov ds,ax
- mov [30h],offset handler
- mov ax,cs
- mov [32h],ax
- pop ds
-
- ; assert DTR, RTS, and OUT2
- mov dx,3fch
- mov al,11
- out dx,al
-
- ; enable interrupts for data ready
- mov dx,3f9h
- mov al,1
- out dx,al
-
- ; clear any outstanding int
- mov dx,3f8h
- in al,dx
-
- ; enable interrupts
- sti
-
- ; enable IRQ4 on 8259A
- in al,21h
- and al,0efh
- out 21h,al
-
- ; and return
- jmp init_finis
-
- dssave: dw 0
-
- handler:
- push ds
- push ax
- push dx
- push bx
-
- ; restore appropriate dseg
- mov ax,cs:dssave
- mov ds,ax
-
- ; grab the byte from comm port
- mov dx,3f8h
- in al,dx
-
- ; put it in the buffer
- mov bx,tail_
- mov comm_buffer_[bx],al
-
- ; tail=tail+1 (mod 8192)
- inc bx
- cmp bx,8192
- jl handler_around
- xor bx,bx
-
- handler_around:
- mov tail_,bx
-
- ; tell the 8259A EOI
- mov dx,20h
- mov al,32
- out dx,al
-
- pop bx
- pop dx
- pop ax
- pop ds
-
- ; reenable interrupts
- sti
-
- iret
-
- init_finis:
- #
- }
-
- commput(c)
- int c;
- {
- #asm
- ; put the character out the port
- mov dx,3f8h
- mov ax,[bp+4]
- out dx,al
- #
- }
-
- char commget()
- {
- char temp;
-
- temp=comm_buffer[head++];
- head%=8192;
- return(temp);
- }
-
- killcomm()
- {
- #asm
- ; disconnect the interrupt handler
- in al,21h
- or al,10h
- out 21h,al
- #
- }
-
- make_break()
- {
- #asm
- ; set bit on LCR
- mov dx,3fbh
- in al,dx
- push ax
- or al,40h
- out dx,al
-
- ; wait a wee bit (~200 ms)
- mov bx,8
- outer:
- mov cx,7000
- tight:
- loop tight
- dec bx
- jnz outer
-
- ; and turn break back off
- pop ax
- out dx,al
- #
- }
-
- is_nice(c) /* true for those characters that "should" be received */
- char c;
- {
- c&=127;
- if(c>=' ' && c<='~') /* printable */
- return(TRUE);
- if(c>6 && c<11) /* BEL, BS, HT, LF */
- return(TRUE);
- if(c==13 || c==27) /* CR, ESC */
- return(TRUE);
- return(FALSE);
- }
-
- my_puts(s) /* puts, using my_co() */
- char *s;
- {
- while(*s)
- {
- if(*s=='\n')
- my_co('\r');
- my_co(*(s++));
- }
- }
-
- my_co(c) /* character output, smaller and faster than DeSmet's,
- using DOS function call 2.00 */
- char c;
- {
- #asm
- mov ah,2
- mov dx,[bp+4]
- int 21h
- #
- }
-
- my_stat() /* true if character is ready from keyboard */
- {
- #asm
- mov ah,1
- int 16h
- jz stat_no_char
- mov ax,1
- jmp stat_finis
-
- stat_no_char:
- xor ax,ax
-
- stat_finis:
- #
- }
-
- my_ci() /* get character from keyboard, using BIOS function call */
- {
- #asm
- xor ah,ah
- int 16h
- or al,al
- jz my_ci_finis
- xor ah,ah
-
- my_ci_finis:
- #
- }
- ------------------------------------------------------------------------------
- The termcap for DOS 2.00 with ansi device driver follows:
- ------------------------------------------------------------------------------
- pm|pcmon|IBM-PC using DOS 2.00 ansi device driver (monochrome)|\
- :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
- :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
- :pt:se=\E[0m:so=\E[1m:ta=^I:up=\E[A:xt:
- pc|pccol|IBM-PC using DOS 2.00 ansi device driver (color)|\
- :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
- :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
- :pt:se=\E[0;32m:so=\E[1m:ta=^I:up=\E[A:xt:
- ------------------------------------------------------------------------------
- and that's it! Enjoy. I place this in the public domain, and would appreciate
- feedback. Improvements and bug reports especially desired. If the code is too
- cryptic or uncommented, feel free to send questions to:
- Bennett Todd
- ...{decvax,ihnp4,akgua}!mcnc!ecsvax!bet
-