home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / library / asm_kit / ibm_comm.asm < prev    next >
Assembly Source File  |  1985-06-21  |  15KB  |  438 lines

  1. title IBM PC Communications I/O Routines -- Curt Klinsing
  2. pgroup  group   prog
  3. prog segment byte public 'prog'
  4. ;
  5. ;A set  of Lattice C callable functions to support
  6. ;interrupt driven character I/O on the  IBM PC. Input
  7. ;is buffered, output is polled.
  8. ;
  9. public  init_com        ;initialize the comm port,
  10. public  unin_com        ;remove initialization,
  11. public  set_xoff                ;enable/disable XON/XOFF,
  12. public  get_xoff                ;read XON/XOFF state,
  13. public  rcvd_xof        ;returns true if XOFF rcvd,
  14. public  sent_xof        ;true if XOFF sent,
  15. public  inp_cnt         ;returns count of rcv chars,
  16. public  inp_char                ;get one char from buffer,
  17. public  inp_flsh        ;flush input buffer,
  18. public  out_char        ;output a character,
  19. ;
  20. ;A better description can be found in the comment
  21. ;block  in each function.
  22. ;
  23.         assume  cs:pgroup
  24.  
  25. ;
  26. FALSE   EQU     0
  27. TRUE    EQU     NOT FALSE
  28. ;
  29. BASE    EQU     03F8H   ;BASE FOR SERIAL BOARD
  30. ;
  31. LCR     equ     BASE+3  ; Line control register
  32. IER     equ     BASE+1  ; Interrup Enable Register
  33. MCR     EQU     BASE+4  ;modem control register
  34. EnblDRdy equ    01H     ; enable 'data-ready' interrupt bit
  35. IntCtlr  EQU    21H     ;OCW 1 FOR 8259 CONTROLLER
  36. EnblIRQ4 EQU    0EFH    ;Enable COMMUNICATIONS (IRQ4)
  37. DATAPORT EQU    BASE    ;transmit/receive data port
  38. MaskIRQ4 EQU    10H     ;BIT TO DISABLE COMM INTERRUPT (IRQ4)
  39.  
  40. MDMSTA  EQU     BASE+5  ;line status register
  41. MDMMSR  EQU     BASE+6  ;modem status register
  42. MDMBAD  EQU     BASE    ;lsb baud resgister
  43. MDMBD1  EQU     BASE+1  ;msb baud rate register
  44. MDMCD   EQU     80H     ;mask for carrier dectect
  45. SETBAU  EQU     80H     ;code for Divisor Latch Access Bit
  46. MDMTBE  EQU     20H     ;8250 tbe flag
  47. MDMBRK  EQU     40H     ;command code for 8250 break
  48. LINMOD  EQU     03H     ;line mode=8 bit, no parity
  49. MDMMOD  EQU     0BH     ;modem mode = DTR and RTS HIGH
  50. STOP2   EQU     04H     ;BIT FOR TWO STOP BITS IF BAUD<300
  51. RS8259  EQU     20H     ;OCW 3 FOR 8259
  52. RSTINT  EQU     64H     ;SPECIFIC EOI FOR COMM INTERRUPT
  53. XOFF    EQU     13H     ;XOFF character
  54. XON     EQU     11H     ;XON character
  55. ;
  56. ;       MISCELLANEOUS EQUATES
  57. ;
  58. CR      EQU     13
  59. LF      EQU     10
  60. DosCall EQU     33      ;INTERRUPT NUMBER FOR DOS CALL
  61. CNSTAT  EQU     11      ;FUNCTION NUMBER FOR CONSOLE STATUS
  62. CNIN    EQU     1       ;FUNCTION NUMBER FOR CONSOLE INPUT
  63. BUFSIZ  EQU     512     ;Max NUMBER OF CHARS
  64. SetIntVect  EQU 25H     ;SET INTERRUPT VECTOR FUNCTION NUMBER
  65.  
  66. ;
  67. ;       DUMP BUFFER, COUNT AND POINTER.
  68. ;
  69. CIRC_BUF DB     BUFSIZ DUP(?)   ;ALLOW 512 MaxIMUM BUFFERED CHARACTERS
  70. BUF_TOP EQU     $ - 1           ;KEEP TRACK OF THE TOP OF THE BUFFER
  71. CIRC_TOP DW     BUF_TOP         ;
  72. ;
  73. CIRC_IN DW      OFFSET CIRC_BUF ;POINTER TO LAST CHAR. PLACED IN BUFFER
  74. CIRC_CUR DW     OFFSET CIRC_BUF ;POINTER TO NEXT CHAR. TO BE RETRIEVED FROM
  75.                                 ; BUFFER
  76. CIRC_CT DW      0               ;COUNT OF CHARACTERS USED IN BUFFER
  77. SNT_XOFF DB     FALSE           ;FLAG TO CHECK IF AN XOFF HAS BEEN SEND
  78. GOT_XOFF  DB    FALSE           ;FLAG TO CHECK IF AN XOFF HAS BEEN RECEIVED
  79. SEE_XOFF  DB    FALSE           ;FLAT TO SEE IF WE ARE INTERESTED IN XON/XOFF
  80. ;
  81. ;
  82. ;
  83. ;set_xoff(flag)         Enable (flag != 0) or disable
  84. ;int flag;              (flag == 0) XON/ XOFF protocol
  85. ;                       for the character input stream.
  86. ;If enabled, an XOFF will be sent when  the buffer
  87. ;reaches 3/4 full. NOTE: an XON will not be sent auto-
  88. ;matically. Your program must do it when it sees
  89. ;the rcvd_xof() flag,  and ready for more chars.
  90. ;
  91. set_xoff proc near
  92.         push    bp
  93.         PUSH    DS              ;SAVE DATA SEGMENT
  94.         mov     bx,[bp+6]
  95.         push    cs
  96.         pop     ds              ; move code seg addr to data seg reg.
  97.         cmp     bx,0
  98.         jnz     to_on
  99.         mov     see_xoff,FALSE
  100.         jmp     done1
  101. to_on:  mov     see_xoff,TRUE
  102. done1:  pop     ds
  103.         pop     bp
  104.         ret
  105. set_xoff endp
  106. ;
  107. ;flag=  get_xoff()      Returns the current setting
  108. ;                       of the XON/ XOFF flag set
  109. ;by set_xoff(), above.
  110. ;
  111. get_xoff proc near
  112.         push    bp
  113.         push    ds              ; save data reg
  114.         push    cs
  115.         pop     ds              ; move code seg addr to data seg reg.
  116.         xor     ax,ax
  117.         mov     al,see_xoff
  118.         pop     ds
  119.         pop     bp
  120.         ret
  121. get_xoff endp
  122. ;
  123. ;flag=  sent_xof();    Returns true if an XOFF
  124. ;                       character was sent, indicating
  125. ;the receive buffer is  3/4 full.
  126. ;
  127. sent_xof proc  near
  128.         push    bp
  129.         push    ds              ; save data reg
  130.         push    cs
  131.         pop     ds              ; move code seg addr to data seg reg.
  132.         xor     ax,ax
  133.         mov     al,snt_xoff
  134.         pop     ds
  135.         pop     bp
  136.         ret
  137. sent_xof endp
  138. ;
  139. ;rcvd_xof()            Returns true if an XOFF was
  140. ;                       received; will return false as
  141. ;soon as an XON is received. Does not effect data output,
  142. ;only indicates the above. (Obviously useless for binary
  143. ;data.)
  144. ;
  145. rcvd_xof proc  near
  146.         push    bp
  147.         push    ds              ; save data reg
  148.         push    cs
  149.         pop     ds              ; move code seg addr to data seg reg.
  150.         xor     ax,ax
  151.         mov     al,got_xoff
  152.         pop     ds              ; restore data reg
  153.         pop     bp
  154.         ret
  155. rcvd_xof endp
  156. ;
  157. ;count= inp_cnt()       Returns the number of characters
  158. ;                       available in the input buffer.
  159. ;
  160.  
  161. inp_cnt proc near
  162.         push    bp
  163.         push    ds              ; save data segment
  164.         push    cs
  165.         pop     ds              ; move code seg addr to data seg reg
  166.         mov     ax,circ_ct
  167.         pop     ds
  168.         pop     bp
  169.         ret
  170. inp_cnt endp
  171. ;
  172. ;inp_flsh()    Flush the input buffer.
  173. ;
  174. inp_flsh proc  near
  175.         push    bp
  176.         push    ds              ; save data reg
  177.         push    cs
  178.         pop     ds              ; move code seg addr to data seg reg.
  179.         mov     bx,offset circ_buf
  180.         mov     circ_in,bx
  181.         mov     circ_cur,bx
  182.         xor     ax,ax
  183.         mov     circ_ct,ax
  184.         pop     ds
  185.         pop     bp
  186.         ret
  187. inp_flsh endp
  188.  
  189. ; --------- Init -----------------------------------
  190. ; Program initialization:
  191. ;   --  Set up vector for RS232 interrupt (0CH)
  192. ;   --  Enbl IRQ4
  193. ;   --  Enbl RS232 interrupt on data ready
  194. ;
  195. ; ---------------------------------------------------
  196.  
  197. init_com proc  near
  198.         push    bp
  199.         cli
  200.  
  201. ;  ---- Set up  INT x'0C' for IRQ4
  202.  
  203.         push    ds
  204.         push    cs
  205.         pop     ds              ;cs to ds
  206.         mov     dx,offset IntHdlr ;relative adddres of interrupt handler
  207.         mov     al,0cH          ;interrupt number for comm.
  208.         mov     ah,SetIntVect   ;function number for setting int vector
  209.         int     DosCall         ;set interrupt in 8086 table
  210.         pop     ds              ;restore DS
  211.  
  212. ;  ---- Enbl IRQ4 on 8259 interrupt controller
  213.  
  214.         cli
  215.  
  216.         in      al,IntCtlr      ; get current masks
  217.         and     al,EnblIRQ4     ; Reset IRQ4 mask
  218.         out     IntCtlr,al      ; And restore to IMR
  219.  
  220. ;  ---   Set 8250 baud rate, parity, and number bits
  221.  
  222.         mov     dx,LCR          ; DX ==> LCR
  223.         mov     al,83H          ; word length = 8
  224.                                 ; stop bits = 1
  225.                                 ; no parity
  226.                                 ; DLAB enabled
  227.         out     dx,al
  228.         mov     dx,MDMBAD       ; DLL - Division Latch Register
  229.         mov     al,60H          ; divisor for 1200 baud
  230.         out     dx,al           ; least signficant bit
  231.         mov     dx,MDMBD1       ; DLL
  232.         xor     al,al           ; set to zero
  233.         out     dx,al           ; most signficant bit
  234.  
  235. ;  ---   Enbl 8250 data ready interrupt
  236.  
  237.         mov     dx,LCR          ; DX ==> LCR
  238.         in      al,dx           ; Reset DLAB for IER access
  239.         and     al,7FH
  240.         out     dx,al
  241.         mov     dx,IER          ; Interrupt Enbl Register
  242.         mov     al,EnblDRdy     ; Enable 'data-ready' interrupt
  243.         out     dx,al
  244.  
  245. ;  ---   Enbl OUT2 on 8250
  246.  
  247.         mov     dx,MCR          ; modem control register
  248.         mov     al,09H          ; Enable OUT2 - CHANGED FROM 08H
  249.         out     dx,al
  250.  
  251.         sti
  252.  
  253.         pop     bp
  254.         ret
  255. init_com endp
  256. ;
  257. ;unin_com()          Removes the interrupt structure
  258. ;                       installed by init_com(). Must be
  259. ;done before passing control to the DOS, else chars received
  260. ;will be stored into the next program loaded!
  261. ;
  262. unin_com proc near
  263.         push    bp
  264. ; ---   Disable IRQ4 on 8259
  265.  
  266.         cli
  267.         in      al,IntCtlr      ;GET OCW1 FROM 8259
  268.         or      al,MaskIRQ4     ;DISABLE COMMUNICATIONS INTERRUPT
  269.         out     IntCtlr,al
  270.  
  271. ; ---   Disable 8250 data ready interrupt
  272.  
  273.         mov     dx,LCR          ; DX ==> LCR
  274.         in      al,dx           ; Reset DLAB for IER access
  275.         and     al,7FH
  276.         out     dx,al
  277.         mov     dx,IER          ; Interrupt Enbl Register
  278.         mov     al,0            ; Disable all 8250 interrupts
  279.         out     dx,al
  280.  
  281. ;  ---   Disable OUT2 on 8250
  282.  
  283.         mov     dx,MCR          ; modem control register
  284.         mov     al,0            ; Disable OUT2
  285.         out     dx,al
  286.  
  287.         sti
  288.                 pop     bp
  289.         ret
  290. unin_com endp
  291. ;
  292. ;char inp_char()        Return a character from the input
  293. ;                       buffer. Assumes you have called
  294. ;inp_cnt() to see if theres any characters to get.
  295. ;
  296. inp_char proc near
  297.         push    bp
  298.         push    ds              ; save data reg
  299.         push    cs
  300.         pop     ds              ; move code seg addr to data seg reg.
  301.         mov     bx,circ_cur
  302.         xor     ax,ax
  303.         mov     al,[bx]         ;get next char from circ_buf
  304.         DEC     circ_ct         ;decrement circ_buf COUNT
  305.         CMP     bx,circ_top     ;ARE WE AT THE TOP OF THE circ_buf?
  306.         JZ      reset_cur       ;JUMP IF SO
  307.         INC     bx              ;ELSE, BUMP PTR
  308.         JMP SHORT upd_cur
  309. reset_cur:
  310.         mov     bx,OFFSET circ_buf      ;RESET circ_in TO BOTTOM OF BUF.
  311. upd_cur:
  312.         mov     circ_cur,bx             ;SAVE NEW PTR
  313.         xor     cx,cx
  314.         mov     cl,see_xoff     ;check if interested in xon/xoff
  315.         cmp     cl,TRUE
  316.         jnz     clnup2          ;not interested, so goto return
  317.         cmp     snt_xoff,TRUE   ;have we sent an xoff?
  318.         jnz     clnup2          ;no, so return
  319.         cmp     circ_ct,80h     ;yes, so see in buf is now emptying
  320.         jg      clnup2          ;not empty enuf to send xon, jump to ret
  321.         mov     snt_xoff,FALSE
  322.         mov     cl,XON
  323.         push    ax              ; save char
  324.         call    comout
  325.         pop     ax
  326. clnup2: pop     DS              ;GET BACK ENTERING DS
  327.         pop     bp
  328.         ret
  329. inp_char endp
  330. ;
  331. ;out_char(c)           Output the character to the
  332. ;char c;                serial port. This is not buffered
  333. ;                       or interrupt driven.
  334. ;
  335. out_char proc  near
  336.         push    bp
  337.         mov     bp,sp
  338.         mov     cl,[bp+4]
  339.         sti
  340.         call    comout
  341.         pop     bp
  342.         ret
  343. out_char endp
  344. ;
  345. ;Local  subroutine: output CL to the port.
  346. ;
  347. comout: mov     dx,MDMSTA
  348.         in      al,dx           ; get 8250 status
  349.         and     al,MDMTBE       ; check for transmitter ready
  350.         jz      comout          ; jump if not to wait
  351.         mov     al,cl           ; get char to al
  352.         mov     dx,DATAPORT
  353.         out     dx,al           ; output char to 8251
  354.         ret
  355. ;
  356. ;       RECEIVE INTERRUPT HANDLER (CHANGED TO PLACE CHARACTERS IN A
  357. ;        CIRCULAR circ_buf AND TO SEND AN XOFF IF THE circ_buf IS MORE THAN
  358. ;        3/4 FULL - S.G.)
  359. ;
  360. IntHdlr:
  361.         CLI
  362.         push    cx
  363.         push    dx
  364.         push    bx
  365.         push    ax
  366.         push    ds
  367.         mov     ax,cs           ;get cur code segment
  368.         mov     ds,ax           ; and set it as data segment
  369.         mov     bx,circ_in      ;GET circ_buf IN PTR
  370.         mov     DX,DATAPORT     ;GET DATA PORT NUMBER
  371.         IN      AL,DX           ;GET RECEIVED CHARACTER
  372. ;       push    ax
  373. ;       push    dx
  374. ;       xor     ax,ax
  375. ;       xor     dx,dx
  376. ;       mov     dl,al
  377. ;       mov     ah,2
  378. ;       int     DosCall
  379. ;       pop     dx
  380. ;       pop     ax
  381.         xor     cx,cx
  382.         mov     cl,see_xoff     ;check if interested in xon/xoff
  383.         cmp     cl,TRUE
  384.         jnz     ck_full         ;not interested goto ck if buf full
  385.         mov     cl,al           ;put char in cl for testing
  386.         and     cl,7fh          ;turn off any parity bits
  387.         cmp     cl,XOFF         ;see if we got an xoff
  388.         jnz     ck_xon
  389.         mov     got_Xoff,TRUE   ; code for handling xon/xoff from remote
  390.         jmp     clnup
  391. ck_xon: cmp     cl,XON
  392.         jnz     reg_ch
  393.         mov     got_Xoff,FALSE
  394.         jmp     clnup
  395. ;
  396. ;Normal character; not  XON/XOFF, or XON/XOFF disabled.
  397. ;
  398. reg_ch: test    snt_Xoff,TRUE   ;SEE IF sentXoff IS SET
  399.         jnz     ck_full         ;IF SO, DON'T SEND ANOTHER XOFF
  400.         CMP     circ_ct,(BUFSIZ * 3)/4  ;ALLOW BUF TO BECOME 3/4 FULL BEFORE
  401.                                         ; SENDING XOFF
  402.         jb      savch           ;IF IT'S OK, CONTINUE
  403.         push    ax              ;SAVE CHARACTER
  404.         mov     CL,XOFF         ;GET XOFF CHARACTER
  405.         mov     snt_Xoff,TRUE  ;RESET sentXoff
  406.         call    comout          ; AND SEND IT
  407.         pop     ax              ;RETRIEVE CHARACTER
  408.         JMP SHORT savch         ;IF WE'RE HERE, THE circ_buf HAS BUFSIZ-80H
  409.                                 ;  CHARACTERS
  410. ck_full:
  411.         CMP     circ_ct,BUFSIZ  ;SEE IF circ_buf ALREADY FULL
  412.         JZ      clnup           ; JUMP IF SO, DO NOT PLACE CHARACTER IN BFR
  413. savch:
  414.         mov     [bx],AL         ;SAVE NEW CHARACTER IN circ_buf
  415.         inc     circ_ct         ;BUMP circ_buf COUNT
  416.         CMP     bx,circ_top     ;ARE WE AT THE TOP OF THE circ_buf?
  417.         JZ      reset_in        ;JUMP IF SO
  418.         inc     bx              ;ELSE, BUMP PTR
  419.         JMP SHORT into_buf
  420. reset_in:
  421.         mov     bx,OFFSET circ_buf      ;RESET circ_in TO BOTTOM OF BUF.
  422. into_buf:
  423.         mov     circ_in,bx              ;SAVE NEW PTR
  424. clnup:
  425.         mov     AL,RSTINT
  426.         OUT     RS8259,AL       ;ISSUE SPECIFIC EOI FOR 8259
  427.         pop     ds              ;GET BACK ENTERING DS
  428.         pop     ax
  429.         pop     bx
  430.         pop     dx
  431.         pop     cx
  432.         sti
  433.         iret
  434. ;
  435. prog    ends
  436.  
  437. end
  438.