; INTINIT.ASM
;
; Copyright (c) 1986 Peter W. Gofton
; Interrupt handler for IBM PC Serial i/o
; Designed to interface with Microsoft 'C'
; Compile as: MASM INTHAND;
;


PORT_AD    equ 03F8H            ; 02F8H for COM2
RX         equ 03F8H
TX         equ 03F8H
INT_EN     equ 03F9H
INT_ID     equ 03FAH
LCONT      equ 03FBH
MCONT      equ 03FCH
LSTAT      equ 03FDH
MSTAT      equ 03FEH

COM_INT    equ 0CH              ; 0BH for COM2     

_TEXT	SEGMENT  BYTE PUBLIC 'CODE'
_TEXT	ENDS
CONST	SEGMENT  WORD PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT  WORD PUBLIC 'BSS'
_BSS	ENDS
_DATA	SEGMENT  WORD PUBLIC 'DATA'
_DATA	ENDS
DGROUP	GROUP	CONST,	_BSS,	_DATA
	ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP, ES: DGROUP

_TEXT SEGMENT

EXTRN _inthand: NEAR

PUBLIC _myds
_myds DW "DS"

;--------------------------------------------------------------------------
PUBLIC _intinit

_intinit    PROC NEAR

; This function is called from 'C' as intinit().
; It sets up the interrupt handler below to be called automatically when
; an i/o interrupt occurs.
;
; First we want to save our DS in an area in CS so we can find it later

    MOV    SI, OFFSET _myds
    MOV    CS:[SI], DS


; Now we use the DOS Set Interrupt Vector call to point INT 0C to
; our interrupt handler.

    PUSH   DS           ; Save DS

    PUSH   CS           ; To load into CS
    POP    DS           ; Load CS into DS

    LEA    DX, _inthand ; Address of the interrupt handler
    MOV    AH, 025H     ; Function call to set vector
    MOV    AL, COM_INT  ; Vector to set.
    INT    21H          ; DOS interrupt

    POP    DS           ; Restore DS

; Now we enable the interrupts on the Programmable Interrupt Controller

    CLI

    MOV    DX, PORT_AD
    ADD    DX, 4        ; Modem Control Register
    MOV    AL, 3        ; DTR, RTS
    OUT    DX, AL       ; Enable handshaking
    
    MOV    DX, 21H      ; Address of the PIC
    IN     AL, DX       ; Get contents
    AND    AL, NOT 10H  ; Set off the bit for IRQ4. NOT 8 for IRQ3
    OUT    DX, AL       ; Sent it out to the controller

    STI

; Reset the serial interface by reading all the registers

    MOV    DX, INT_EN
    MOV    AL, 0
    OUT    DX, AL

    MOV    DX, LSTAT
    IN     AL, DX

    MOV    DX, MSTAT
    IN     AL, DX

    MOV    DX, RX
    IN     AL, DX

    MOV    DX, INT_ID
    IN     AL, DX
        
; Now we enable the interrupts on the serial interface

    MOV    DX, INT_EN
    MOV    AL, 0FH     ; Enable all four interrupts
    OUT    DX, AL

    MOV    DX, PORT_AD
    IN     AL, DX       

    ADD    DX, 5        ; Line status
    IN     AL, DX
    IN     AL, DX

    INC    DX           ; Modem status
    IN     AL, DX
    IN     AL, DX
         

    MOV    DX, 20H    
    MOV    AL, 20H
    OUT    DX, AL       ; Reset the PIC            

    RET

_intinit endp

_TEXT ends

END


; Figure 17.1: Interrupt Handler Initialization 


