home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / c / croutes.zip / CASYNC.ASM < prev    next >
Assembly Source File  |  1984-07-29  |  11KB  |  425 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_comm ;initialize the comm port,
  10. public uninit_comm ;remove initialization,
  11. public set_xoff  ;enable/disable XON/XOFF,
  12. public get_xoff  ;read XON/XOFF state,
  13. public rcvd_xoff ;returns true if XOFF rcvd,
  14. public sent_xoff ;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_flush ;flush input buffer,
  18. public outp_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_xoff() 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_xoff(); Returns true if an XOFF
  124. ;   character was sent, indicating
  125. ;the receive buffer is 3/4 full.
  126. ;
  127. sent_xoff 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_xoff endp
  138. ;
  139. ;rcvd_xoff()  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_xoff 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_xoff 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_flush() Flush the input buffer.
  173. ;
  174. inp_flush 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_flush 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_comm 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. ;  ---  Enbl 8250 data ready interrupt
  221.  
  222.  mov dx,LCR  ; DX ==> LCR
  223.  in al,dx  ; Reset DLAB for IER access
  224.  and al,7FH
  225.  out dx,al
  226.  mov dx,IER  ; Interrupt Enbl Register
  227.  mov al,EnblDRdy ; Enable 'data-ready' interrupt
  228.  out dx,al
  229.  
  230. ;  ---  Enbl OUT2 on 8250
  231.  
  232.  mov dx,MCR  ; modem control register
  233.  mov al,08H  ; Enable OUT2
  234.  out dx,al
  235.  
  236.  sti
  237.  
  238.  pop bp
  239.  ret
  240. init_comm endp
  241. ;
  242. ;uninit_comm()  Removes the interrupt structure
  243. ;   installed by init_comm(). Must be
  244. ;done before passing control to the DOS, else chars received
  245. ;will be stored into the next program loaded!
  246. ;
  247. uninit_comm proc near
  248.  push bp
  249. ; --- Disable IRQ4 on 8259
  250.  
  251.  cli
  252.  in al,IntCtlr ;GET OCW1 FROM 8259
  253.  or al,MaskIRQ4 ;DISABLE COMMUNICATIONS INTERRUPT
  254.  out IntCtlr,al
  255.  
  256. ; --- Disable 8250 data ready interrupt
  257.  
  258.  mov dx,LCR  ; DX ==> LCR
  259.  in al,dx  ; Reset DLAB for IER access
  260.  and al,7FH
  261.  out dx,al
  262.  mov dx,IER  ; Interrupt Enbl Register
  263.  mov al,0  ; Disable all 8250 interrupts
  264.  out dx,al
  265.  
  266. ;  ---  Disable OUT2 on 8250
  267.  
  268.  mov dx,MCR  ; modem control register
  269.  mov al,0  ; Disable OUT2
  270.  out dx,al
  271.  
  272.  sti
  273.   pop bp
  274.  ret
  275. uninit_comm endp
  276. ;
  277. ;char inp_char() Return a character from the input
  278. ;   buffer. Assumes you have called
  279. ;inp_cnt() to see if theres any characters to get.
  280. ;
  281. inp_char proc near
  282.  push bp
  283.  push ds  ; save data reg
  284.  push cs
  285.  pop ds  ; move code seg addr to data seg reg.
  286.  mov bx,circ_cur
  287.  xor ax,ax
  288.  mov al,[bx]  ;get next char from circ_buf
  289.  DEC circ_ct  ;decrement circ_buf COUNT
  290.  CMP bx,circ_top ;ARE WE AT THE TOP OF THE circ_buf?
  291.  JZ reset_cur ;JUMP IF SO
  292.  INC bx  ;ELSE, BUMP PTR
  293.  JMP SHORT upd_cur
  294. reset_cur:
  295.  mov bx,OFFSET circ_buf ;RESET circ_in TO BOTTOM OF BUF.
  296. upd_cur:
  297.  mov circ_cur,bx  ;SAVE NEW PTR
  298.  xor cx,cx
  299.  mov cl,see_xoff ;check if interested in xon/xoff
  300.  cmp cl,TRUE
  301.  jnz clnup2  ;not interested, so goto return
  302.  cmp snt_xoff,TRUE ;have we sent an xoff?
  303.  jnz clnup2  ;no, so return
  304.  cmp circ_ct,80h ;yes, so see in buf is now emptying
  305.  jg clnup2  ;not empty enuf to send xon, jump to ret
  306.  mov snt_xoff,FALSE
  307.  mov cl,XON
  308.  push ax  ; save char
  309.  call comout
  310.  pop ax
  311. clnup2: pop DS  ;GET BACK ENTERING DS
  312.  pop bp
  313.  ret
  314. inp_char endp
  315. ;
  316. ;outp_char(c)  Output the character to the
  317. ;char c;  serial port. This is not buffered
  318. ;   or interrupt driven.
  319. ;
  320. outp_char proc near
  321.  push bp
  322.  mov bp,sp
  323.  mov cl,[bp+4]
  324.  sti
  325.  call comout
  326.  pop bp
  327.  ret
  328. outp_char endp
  329. ;
  330. ;Local subroutine: output CL to the port.
  331. ;
  332. comout: mov dx,MDMSTA
  333.  in al,dx  ; get 8250 status
  334.  and al,MDMTBE ; check for transmitter ready
  335.  jz comout  ; jump if not to wait
  336.  mov al,cl  ; get char to al
  337.  mov dx,DATAPORT
  338.  out dx,al  ; output char to 8251
  339.  ret
  340. ;
  341. ; RECEIVE INTERRUPT HANDLER (CHANGED TO PLACE CHARACTERS IN A
  342. ;  CIRCULAR circ_buf AND TO SEND AN XOFF IF THE circ_buf IS MORE THAN
  343. ;  3/4 FULL - S.G.)
  344. ;
  345. IntHdlr:
  346.  CLI
  347.  push cx
  348.  push dx
  349.  push bx
  350.  push ax
  351.  push ds
  352.  mov ax,cs  ;get cur code segment
  353.  mov ds,ax  ; and set it as data segment
  354.  mov bx,circ_in ;GET circ_buf IN PTR
  355.  mov DX,DATAPORT ;GET DATA PORT NUMBER
  356.  IN AL,DX  ;GET RECEIVED CHARACTER
  357. ; push ax
  358. ; push dx
  359. ; xor ax,ax
  360. ; xor dx,dx
  361. ; mov dl,al
  362. ; mov ah,2
  363. ; int DosCall
  364. ; pop dx
  365. ; pop ax
  366.  xor cx,cx
  367.  mov cl,see_xoff ;check if interested in xon/xoff
  368.  cmp cl,TRUE
  369.  jnz ck_full  ;not interested goto ck if buf full
  370.  mov cl,al  ;put char in cl for testing
  371.  and cl,7fh  ;turn off any parity bits
  372.  cmp cl,XOFF  ;see if we got an xoff
  373.  jnz ck_xon
  374.  mov got_Xoff,TRUE ; code for handling xon/xoff from remote
  375.  jmp clnup
  376. ck_xon: cmp cl,XON
  377.  jnz reg_ch
  378.  mov got_Xoff,FALSE
  379.  jmp clnup
  380. ;
  381. ;Normal character; not XON/XOFF, or XON/XOFF disabled.
  382. ;
  383. reg_ch: test snt_Xoff,TRUE ;SEE IF sentXoff IS SET
  384.  jnz ck_full  ;IF SO, DON'T SEND ANOTHER XOFF
  385.  CMP circ_ct,(BUFSIZ * 3)/4 ;ALLOW BUF TO BECOME 3/4 FULL BEFORE
  386.      ; SENDING XOFF
  387.  jb savch  ;IF IT'S OK, CONTINUE
  388.  push ax  ;SAVE CHARACTER
  389.  mov CL,XOFF  ;GET XOFF CHARACTER
  390.  mov snt_Xoff,TRUE  ;RESET sentXoff
  391.  call comout  ; AND SEND IT
  392.  pop ax  ;RETRIEVE CHARACTER
  393.  JMP SHORT savch  ;IF WE'RE HERE, THE circ_buf HAS BUFSIZ-80H
  394.     ;  CHARACTERS
  395. ck_full:
  396.  CMP circ_ct,BUFSIZ ;SEE IF circ_buf ALREADY FULL
  397.  JZ clnup  ; JUMP IF SO, DO NOT PLACE CHARACTER IN BFR
  398. savch:
  399.  mov [bx],AL  ;SAVE NEW CHARACTER IN circ_buf
  400.  inc circ_ct  ;BUMP circ_buf COUNT
  401.  CMP bx,circ_top ;ARE WE AT THE TOP OF THE circ_buf?
  402.  JZ reset_in ;JUMP IF SO
  403.  inc bx  ;ELSE, BUMP PTR
  404.  JMP SHORT into_buf
  405. reset_in:
  406.  mov bx,OFFSET circ_buf ;RESET circ_in TO BOTTOM OF BUF.
  407. into_buf:
  408.  mov circ_in,bx  ;SAVE NEW PTR
  409. clnup:
  410.  mov AL,RSTINT
  411.  OUT RS8259,AL ;ISSUE SPECIFIC EOI FOR 8259
  412.  pop ds  ;GET BACK ENTERING DS
  413.  pop ax
  414.  pop bx
  415.  pop dx
  416.  pop cx
  417.  sti
  418.  iret
  419. ;
  420. prog ends
  421.  
  422. end
  423.  
  424. *** COPIED 01/25/84 04:31:17 BY KSC ***
  425.