home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS 1999 January / Simtel-MSDOS-Jan1999-CD2.iso / io_utils / comm.c < prev    next >
C/C++ Source or Header  |  1998-12-10  |  5KB  |  306 lines

  1.  
  2.  
  3. /* NOTE: this code is indented using tabs set every 4 columns, not 8. */
  4.  
  5. /*
  6.  * Rudimentary communication program; written in C with I/O
  7.  * routines in assembler, using "#asm" construct in DeSmet C.
  8.  */
  9.  
  10. #define TRUE 1
  11. #define FALSE 0
  12. #define NULL 0
  13.  
  14. #define comm_stat head!=tail
  15.  
  16. int head=0,
  17.     tail=0;
  18.  
  19. char comm_buffer[8192];
  20.  
  21. main()
  22. {
  23.     char commget();
  24.  
  25.     int c,
  26.         echo=FALSE,
  27.         verbose=FALSE;
  28.  
  29.     initcomm();
  30.  
  31.     goto inside;
  32.     while((c=my_ci())<256) /* alt's and function keys are >=256 */
  33.     {
  34.         commput(c);
  35.         if(echo)
  36.             my_co(c);
  37. inside:    while(my_stat()==0)
  38.             if(comm_stat)
  39.                 if(is_nice(c=commget()))
  40.                     my_co(c);
  41.                 else
  42.                     if(verbose)
  43.                     {
  44.                         my_co('^');
  45.                         my_co(127&(c+'@'));
  46.                     }
  47.     }
  48.     switch(c>>8) /* process function key */
  49.     {
  50.         case '\060': /* b    send break    */
  51.             make_break();
  52.             my_puts("** break **\n");
  53.             break;
  54.         case '\022': /* e    echo toggle    */
  55.             echo = !echo;
  56.             if(echo)
  57.                 my_puts("** echo on **\n");
  58.             else
  59.                 my_puts("** echo off **\n");
  60.             break;
  61.         case '\020': /* q    quit        */
  62.             my_puts("** returning to DOS **\n");
  63.             goto byebye;
  64.         case '\057': /* v    verbose        */
  65.             verbose = !verbose;
  66.             if(verbose)
  67.                 my_puts("** verbose on **\n");
  68.             else
  69.                 my_puts("** verbose off **\n");
  70.             break;
  71.     }
  72.     goto inside;
  73.  
  74. byebye:
  75.     killcomm();
  76. }
  77.  
  78. initcomm()
  79. {
  80. #asm
  81.  
  82. ; initialize communication port,
  83. ; and install interrupt handler
  84.  
  85. ; save dseg for interrupt handler
  86.     mov        ax,ds
  87.     mov        cs:dssave,ax
  88.  
  89. ; set int vector to my handler
  90.     push    ds
  91.     xor        ax,ax
  92.     mov        ds,ax
  93.     mov        [30h],offset handler
  94.     mov        ax,cs
  95.     mov        [32h],ax
  96.     pop        ds
  97.  
  98. ; assert DTR, RTS, and OUT2
  99.     mov        dx,3fch
  100.     mov        al,11
  101.     out        dx,al
  102.  
  103. ; enable interrupts for data ready
  104.     mov        dx,3f9h
  105.     mov        al,1
  106.     out        dx,al
  107.  
  108. ; clear any outstanding int
  109.     mov        dx,3f8h
  110.     in        al,dx
  111.  
  112. ; enable interrupts
  113.     sti
  114.  
  115. ; enable IRQ4 on 8259A
  116.     in        al,21h
  117.     and        al,0efh
  118.     out        21h,al
  119.  
  120. ; and return
  121.     jmp        init_finis
  122.  
  123. dssave:    dw 0
  124.  
  125. handler:
  126.     push    ds
  127.     push    ax
  128.     push    dx
  129.     push    bx
  130.  
  131. ; restore appropriate dseg
  132.     mov        ax,cs:dssave
  133.     mov        ds,ax
  134.  
  135. ; grab the byte from comm port
  136.     mov        dx,3f8h
  137.     in        al,dx
  138.  
  139. ; put it in the buffer
  140.     mov        bx,tail_
  141.     mov        comm_buffer_[bx],al
  142.  
  143. ; tail=tail+1 (mod 8192)
  144.     inc        bx
  145.     cmp        bx,8192
  146.     jl        handler_around
  147.     xor        bx,bx
  148.  
  149. handler_around:
  150.     mov        tail_,bx
  151.  
  152. ; tell the 8259A EOI
  153.     mov        dx,20h
  154.     mov        al,32
  155.     out        dx,al
  156.  
  157.     pop        bx
  158.     pop        dx
  159.     pop        ax
  160.     pop        ds
  161.  
  162. ; reenable interrupts
  163.     sti
  164.  
  165.     iret
  166.  
  167. init_finis:
  168. #
  169. }
  170.  
  171. commput(c)
  172. int c;
  173. {
  174. #asm
  175. ; put the character out the port
  176.     mov        dx,3f8h
  177.     mov        ax,[bp+4]
  178.     out        dx,al
  179. #
  180. }
  181.  
  182. char commget()
  183. {
  184.     char temp;
  185.  
  186.         temp=comm_buffer[head++];
  187.         head%=8192;
  188.         return(temp);
  189. }
  190.  
  191. killcomm()
  192. {
  193. #asm
  194. ; disconnect the interrupt handler
  195.     in        al,21h
  196.     or        al,10h
  197.     out        21h,al
  198. #
  199. }
  200.  
  201. make_break()
  202. {
  203. #asm
  204. ; set bit on LCR
  205.     mov        dx,3fbh
  206.     in        al,dx
  207.     push    ax
  208.     or        al,40h
  209.     out        dx,al
  210.  
  211. ; wait a wee bit (~200 ms)
  212.     mov        bx,8
  213. outer:
  214.     mov        cx,7000
  215. tight:
  216.     loop    tight
  217.     dec        bx
  218.     jnz        outer
  219.  
  220. ; and turn break back off
  221.     pop        ax
  222.     out        dx,al
  223. #
  224. }
  225.  
  226. is_nice(c) /* true for those characters that "should" be received */
  227. char c;
  228. {
  229.     c&=127;
  230.     if(c>=' ' && c<='~')    /* printable */
  231.         return(TRUE);
  232.     if(c>6 && c<11)            /* BEL, BS, HT, LF */
  233.         return(TRUE);
  234.     if(c==13 || c==27)        /* CR, ESC */
  235.         return(TRUE);
  236.     return(FALSE);
  237. }
  238.  
  239. my_puts(s) /* puts, using my_co() */
  240. char *s;
  241. {
  242.     while(*s)
  243.     {
  244.         if(*s=='\n')
  245.             my_co('\r');
  246.         my_co(*(s++));
  247.     }
  248. }
  249.  
  250. my_co(c) /* character output, smaller and faster than DeSmet's,
  251.             using DOS function call 2.00 */
  252. char c;
  253. {
  254. #asm
  255.     mov        ah,2
  256.     mov        dx,[bp+4]
  257.     int        21h
  258. #
  259. }
  260.  
  261. my_stat() /* true if character is ready from keyboard */
  262. {
  263. #asm
  264.     mov        ah,1
  265.     int        16h
  266.     jz        stat_no_char
  267.     mov        ax,1
  268.     jmp        stat_finis
  269.  
  270. stat_no_char:
  271.     xor        ax,ax
  272.  
  273. stat_finis:
  274. #
  275. }
  276.  
  277. my_ci() /* get character from keyboard, using BIOS function call */
  278. {
  279. #asm
  280.     xor        ah,ah
  281.     int        16h
  282.     or        al,al
  283.     jz        my_ci_finis
  284.     xor        ah,ah
  285.  
  286. my_ci_finis:
  287. #
  288. }
  289. ------------------------------------------------------------------------------
  290. The termcap for DOS 2.00 with ansi device driver follows:
  291. ------------------------------------------------------------------------------
  292. pm|pcmon|IBM-PC using DOS 2.00 ansi device driver (monochrome)|\
  293.     :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
  294.     :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
  295.     :pt:se=\E[0m:so=\E[1m:ta=^I:up=\E[A:xt:
  296. pc|pccol|IBM-PC using DOS 2.00 ansi device driver (color)|\
  297.     :am:bc=^H:bw:ce=\E[K:cl=\E[2J:cm=\E[%i%d;%dH:co#80:cr=^M:\
  298.     :do=^J:ho=\E[H:kb=^H:li#25:ll=\E[25H:nd=\E[C:\
  299.     :pt:se=\E[0;32m:so=\E[1m:ta=^I:up=\E[A:xt:
  300. ------------------------------------------------------------------------------
  301. and that's it! Enjoy. I place this in the public domain, and would appreciate
  302. feedback. Improvements and bug reports especially desired. If the code is too
  303. cryptic or uncommented, feel free to send questions to:
  304.                     Bennett Todd
  305.                     ...{decvax,ihnp4,akgua}!mcnc!ecsvax!bet
  306.