home *** CD-ROM | disk | FTP | other *** search
- ;----------------------------------------------------------------------------
- ; INT4.ASM August 23,1987
- ;
- ; Data input/output via RS-232C (COM 1)
- ; * initialization
- ; * ISR
- ;----------------------------------------------------------------------------
- int4_TEXT SEGMENT byte public 'CODE'
- int4_TEXT ENDS
- _DATA SEGMENT byte public 'DATA'
- _DATA ENDS
- _BSS SEGMENT byte public 'BSS'
- _BSS ENDS
- ;
- DGROUP GROUP _DATA,_BSS
-
- ASSUME cs:int4_TEXT, ds:DGROUP, es:DGROUP
- ;
- ;----------------------------------------------------------------------------
- ;
- _DATA SEGMENT byte public 'DATA'
- old_int4_CS dw 0 ;old interrupt 4 CS
- old_int4_IP dw 0 ;old interrupt 4 IP
- _DATA ENDS
- ;
- ;----------------------------------------------------------------------------
- ; PROGRAM EXTERNALS
- ;
- extrn _com1_input_queue:byte
- extrn _com1_in_queue_ptr:word
-
- extrn _com1_rs232_error:word
- extrn _com1_port_status:word
- extrn _com1_interrupt_status:word
-
- extrn _com1_out_queue_ptr:word
- extrn _com1_out_queue_out:word
- extrn _com1_output_queue:byte
- ;
- ;----------------------------------------------------------------------------
- ; PROGRAM EQUATES
- ;
- BASE_ADR EQU 03F8h ;COM 1 port base address
- BUFSIZ EQU 2048 ;size of data queues
- ;
- ; Don't enable the xmit interrupt unless there is something to xmit
- ;
- ; 1 ='s enable interrupt
- ; 0 ='s disable interrupt
- ;
- ; Bits 7 to 4 ------ unused
- ; 3 ------ change in modem status register
- ; 2 ------ data reception error
- ; 1 ------ transmit register empty
- ; 0 ------ data received
- ;
- INT_CODE EQU 1101B ;receive, error and modem change
- ;interrupts are enabled here
-
- RTS_ON EQU 0bh ;interrupts on, RTS on, DTR on
- RTS_OFF EQU 09h ;interrupts on, RTS off, DTR on
- ;
- ;----------------------------------------------------------------------------
- ; Initialize the 8250 UART depending on parameter given as argument
- ; and enable communication interrupts via INT 4 (primary com. port)
- ;
- ; BIT 7 6 5 4 3 2 1 0
- ; { baud rate } { parity } { stop bits } { word length }
- ; 110 = 0 0 0 NONE = 0 0 1 = 0 7 bits = 1 0
- ; 150 = 0 0 1 or 1 0 2 = 1 8 bits = 1 1
- ; 300 = 0 1 0 ODD = 0 1
- ; 600 = 0 1 1 EVEN = 1 1
- ; 1200 = 1 0 0
- ; 2400 = 1 0 1
- ; 4800 = 1 1 0
- ; 9600 = 1 1 1
- ;
- ;----------------------------------------------------------------------------
- ;
- int4_TEXT SEGMENT byte public 'CODE'
- ;
- PUBLIC _com1_set_interrupt
- _com1_set_interrupt PROC FAR
- push bp ;save the registers used
- mov bp,sp ;make a copy for variable access
-
- push ax ;save all registers used
- push bx
- push dx
- push ds
- push es
-
- mov ah,35h ;get vector function
- mov al,0ch ;want INT 4 CS and IP vector
- int 21h ;execute DOS function call
- mov old_int4_CS,es ;ES contains the CS for INT 4
- mov old_int4_IP,bx ;BX contains the IP for INT 4
-
- mov dx,offset INT4 ;point DS:DX to COM routine
- mov ax,seg INT4 ;segment
- mov ds,ax ;point DS
- mov al,0ch ;INT 4 vector
- mov ah,25h ;function to change vector
- int 21h ;execute DOS function call
-
- mov ax,[bp+6] ;grab baud rate and parms
- mov dx,0 ;0 = COM 1 1 = COM 2
- int 14h ;initialize RS232 port to given parameters
- ;(warning: COM interrupts are left disabled)
-
- mov dx,BASE_ADR+4 ;modem control register (3fc)
- mov al,RTS_ON ;INT's on(bit3), RTS on(bit1), DTR on(bit0)
- out dx,al
-
- mov dx,BASE_ADR+1 ;interrupt enable register (3f9)
- mov al,INT_CODE ;which interrupts to enable
- out dx,al ;enable interrupts on 8250
-
- mov dx,BASE_ADR ;point at recieve buffer register(3f8)
- in al,dx ;read any trash in buffer
-
- mov dx,BASE_ADR+5 ;line status register(3fd)
- in al,dx ;read any trash in status register
-
- mov dx,BASE_ADR+6 ;modem status register (3fe)
- in al,dx ;read any trash in status register
-
- in al,21h ;find out which interrupts are currently on
- and al,0efh ;enable bit 4 (INT 4 ='s PRIMARY COM. PORT)
- out 21h,al ;rewrite new interrupt flags
-
- pop es ;restore registers used
- pop ds
- pop dx
- pop bx
- pop ax
- pop bp
- ret
- _com1_set_interrupt ENDP
- ;
- ;----------------------------------------------------------------------------
- ;
- ; This routine restores the interrupt vector which was modified by the
- ; _set_interrupt routine so don't call this routine without 1st
- ; calling the other routine.
- ;
- PUBLIC _com1_restore_interrupt
- _com1_restore_interrupt PROC FAR
- push ax ;save all registers used
- push dx
- push ds
-
- mov dx,old_int4_IP ;point DS:DX to COM routine
- mov ax,old_int4_CS ;segment
- mov ds,ax ;point DS
- mov al,0ch ;INT 4 vector
- mov ah,25h ;function to change vector
- int 21h ;execute DOS function call
-
- in al,21h ;read current interrupt status
- or al,10h ;disable bit 4 (INT 4)
- out 21h,al ;rewrite new interrupt status
-
- pop ds ;restore all registers used
- pop dx
- pop ax
- ret
- _com1_restore_interrupt ENDP
- ;
- ;----------------------------------------------------------------------------
- ; This is the interrupt routine that is executed with every
- ; INT 4.
- ;
- ; Options currenty implemented are:
- ; 1. receive interrupt
- ; 2. data reception error interrupt
- ; 3. transmit holding register empty interrupt
- ; 4. change in modem status register
- ;
- ; Receive interrupt places characters in _input_queue at _in_queue_ptr
- ; bytes into the queue.
- ;
- ; Data reception error places the error int _rs232_error.
- ;
- ; Transmit interrupt xmits characters in _output_queue at _out_queue_ptr
- ; bytes into the queue.
- ;
- ; Modem status register change stores its status in port_status
- ;
- ;----------------------------------------------------------------------------
- ;
- public INT4
-
- INT4 PROC FAR
- push ds ;always save anything you use in an INT routine
- push di
- push dx
- push cx
- push ax
-
- mov ax, SEG _DATA ;make sure your pointing to the correct
- mov ds,ax ; segment otherwise it's lockup city.
- ;----------------------------------------------------------------------------
- pending_interrupt:
- mov dx,BASE_ADR+2 ;interrupt ident. register (3fa)
- in al,dx ;read whose requesting service
-
- mov ah,00h ;zero high byte
- mov _com1_interrupt_status,ax;store status
-
- cmp al,00h ;modem interrupt?
- je status_int ;YES! jump
-
- cmp al,02h ;is it a transmit buf empty interrupt?
- je transmit_int ;YES! jump
-
- cmp al,04h ;is it a recieve interrupt?
- je receive_int ;YES! jump
-
- cmp al,06h ;is it reception error interrupt?
- je reception_error ;YES! jump
-
- jmp leave_interrupt ;no more left.... so leave
- ;
- ;----------------------------------------------------------------------------
- ; Modem status register change
- ;
- status_int:
- mov dx,BASE_ADR+6 ;modem status register (3fe)
- in al,dx
-
- mov ah,00h ;zero high byte
- mov _com1_port_status,ax ;store status
- jmp leave_interrupt ;go see if any interrupts pending
- ;
- ;----------------------------------------------------------------------------
- ; Receive buffer routine
- ;
- receive_int:
- mov dx,BASE_ADR ;COM 1 recieve buffer (3f8)
- in al,dx ;read the character in
-
- mov dl,al ;save character in another register for now
-
- mov di,[_com1_in_queue_ptr] ;grab input pointer
-
- mov _com1_input_queue[di],dl;and place the char in the queue
-
- cmp di,BUFSIZ ;check for queue wrap
- jge reset_queue ;reset if past end or equal
-
- inc word ptr [_com1_in_queue_ptr] ;bump input pointer
- jmp leave_interrupt
- reset_queue:
- mov word ptr [_com1_in_queue_ptr],0 ;reset pointer to beginning
- ;----------------------------------------------------------------------------
- leave_interrupt:
- mov dx,BASE_ADR+2 ;interrupt ident. register (3fa)
- in al,dx ;read whose request service
-
- and al,01h ;is there a pending interrupt?
- jz pending_interrupt ;YES! jump
- ack_interrupt:
- mov al,20h ;EOI code
- out 20h,al ;acknowledge END OF INTERRUPT
-
- pop ax ;put em back so the machine doesn't
- pop cx ; DIE!
- pop dx
- pop di
- pop ds
- iret ;interrupt return
- ;
- ;----------------------------------------------------------------------------
- ; Reception error routine
- ;
- reception_error:
- mov dx,BASE_ADR+5 ;line status register (3fd)
- in al,dx ; read which error occured
-
- mov ah,00h ;zero high byte
- mov _com1_rs232_error,ax ;save error flags for someone else
-
- jmp leave_interrupt ;go look for pending interrupts
- ;
- ;----------------------------------------------------------------------------
- ; Transmit buffer empty routine
- ;
- transmit_int:
-
- mov ax,[_com1_out_queue_ptr];grab input pointer
- mov di,[_com1_out_queue_out];grab output pointer
-
- cmp ax,di ;are the pointers equal?
- jz disable_xmit_int ;YES! then disable interrupts
-
- mov dx,BASE_ADR+6 ;point at modem status reg. (3fe)
- mov cx,200 ;give it 200 trys for CTS signal
-
- wait_for_CTS:
- in al,dx ;read port status
- and al,10h ;test CTS line
- loopnz wait_for_CTS ;
-
-
- mov al,_com1_output_queue[di];grab next char to output
- mov dx,BASE_ADR ;output buffer port (3f8)
- out dx,al ;send character out
-
- cmp di,BUFSIZ ;check for queue wrap
- jge out_queue_reset ;reset if past end or equal
-
- inc word ptr [_com1_out_queue_out] ;bump output pointer
- jmp leave_interrupt ;and check for pending interrupts
- out_queue_reset:
- mov word ptr [_com1_out_queue_out],0 ;reset pointer to beginning
- jmp leave_interrupt ;and check for pending interrupts
-
- disable_xmit_int:
- mov dx,BASE_ADR+1 ;interrupt enable register (3f9)
- in al,dx ;read current interrupt status
- and al,11111101B ;turn off xmit interrupts (fdh)
- out dx,al ;disable xmit interrupts on 8250
- jmp leave_interrupt ; and check for pending interrupts
-
- INT4 ENDP
- ;----------------------------------------------------------------------------
- int4_TEXT ENDS
- END
-