home *** CD-ROM | disk | FTP | other *** search
- ; Async Module.
-
- IDEAL
- MODEL compact
-
- EOI equ 020h ; 8259 end-of-interupt
- Ctrl8259_0 equ 020h ; 8259 port
- Ctrl8259_1 equ 021h ; 8259 port (Masks)
- BufSize equ 8196 ; Buffer Size
-
-
-
-
- DATASEG
-
- ; Various things to be set upon AsyncInit()
- VectorNum db ? ; Vector Number
- EnableIRQ db ? ; Mask to enable 8259 IRQ
- DisableIRQ db ? ; Mask to disable 8259 IRQ
- VectorSeg dw ? ; Old Vector Segment
- VectorOfs dw ? ; Old Vector Offset
-
- ; Register Addresses for the 8250 UART
- Port dw ? ; Port Base Address
- LABEL RegStart word
- THR dw ? ; Transmitter Holding Register
- RDR dw ? ; Reciever Data Register
- BRDL dw ? ; Baud Rate Divisor, Low byte
- BRDH dw ? ; Baud Rate Divisor, High Byte
- IER dw ? ; Interupt Enable Register
- IIR dw ? ; Interupt Identification Register
- LCR dw ? ; Line Control Register
- MCR dw ? ; Modem Control Register
- LSR dw ? ; Line Status Register
- MSR dw ? ; Modem Status Register
-
- ; Buffer Data
- RecBuffer db BufSize DUP (?) ; Recieve Buffer
- RecHead dw ? ; Buffer Head Pointer
- RecTail dw ? ; Buffer Tail Pointer
- TransBuffer db BufSize DUP (?) ; Transmit Buffer
- TransHead dw ? ; Buffer Head Pointer
- TransTail dw ? ; Buffer Tail Pointer
-
- ; Register Offsets for the UART
- RegOffsets dw 0, 0, 0, 1, 1, 2, 3, 4, 5, 6
-
-
- CODESEG
-
- PUBLIC _AsyncInit, _AsyncClear, _AsyncStop
- PUBLIC _AsyncIn, _AsyncOut, _AsyncSet
- PUBLIC _AsyncHand, _AsyncStat, _AsyncInStat
- PUBLIC _AsyncOutStat
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncClear Empty the recieve buffer
- ;-----------------------------------------------------------------------------
- ; void AsyncClear( void);
- ;
- ;
- ;-----------------------------------------------------------------------------
- PROC _AsyncClear
- cli
- push ax
- mov ax, offset RecBuffer
- mov [RecHead], ax
- mov [RecTail], ax
- mov ax, offset TransBuffer
- mov [TransHead], ax
- mov [TransTail], ax
- pop ax
- sti
- ret
- ENDP _AsyncClear
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncInit Initalize Serial Port and install ISR
- ;-----------------------------------------------------------------------------
- ; void AsyncInit( int port)
- ;
- ; Where Port is
- ; 0 = COM1
- ; 1 = COM2
- ; 2 = COM3
- ; 3 = COM4
- ;
- ;-----------------------------------------------------------------------------
- PROC _AsyncInit
- ARG CommPort:word
-
- push bp
- mov bp, sp
-
- ;---- Set various things according to com port number
- mov ax, [CommPort]
-
- ;----- COM1
- cmp ax, 0
- jne @@1
- mov [Port], 03F8h
- mov [VectorNum], 0Ch
- mov [EnableIRQ], 0EFh
- mov [DisableIRQ], 10h
- jmp @@Done
- @@1:
- ;----- COM2
- cmp ax, 1
- jne @@2
- mov [Port], 02F8h
- mov [VectorNum], 0Bh
- mov [EnableIRQ], 0F7h
- mov [DisableIRQ], 08h
- jmp @@Done
- @@2:
- ;----- COM3
- cmp ax, 2 ; 2
- jne @@3
- mov [Port], 03E8h ; 03E8
- mov [VectorNum], 0Ch ; 0C
- mov [EnableIRQ], 0EFh ; EF
- mov [DisableIRQ], 10h ; 10
- jmp @@Done
- @@3:
- ;----- COM4
- mov [Port], 02E8h ; 02E8
- mov [VectorNum], 0Bh ; 0B
- mov [EnableIRQ], 0F7h ; F7
- mov [DisableIRQ], 08h ; 08
- @@Done:
-
- ;---- Compute Register locations
- mov cx, 10
- mov bx, offset RegOffsets
- push di
- mov di, offset RegStart
- @@4:
- mov ax, [bx]
- add ax, [Port]
- mov [di], ax
- add bx, 2
- add di, 2
- loop @@4
-
- pop di
-
-
- ;----- Initalize Buffer
- call _AsyncClear
-
- ;--- Save and reassign interrupt vector
- push ds ; Save Old Vector
- mov al,[VectorNum]
- mov ah,35h
- int 21h
- mov [VectorSeg], es
- mov [VectorOfs], bx
-
- mov al, [VectorNum]
- push cs ; Set New Vector
- pop ds
- mov dx, offset AsyncISR
- mov ah, 25h
- int 21h
- pop ds
-
- ;----- Enable 8259 interrupt (IRQ) line for this async adapter
- in al, Ctrl8259_1
- and al, [EnableIRQ]
- out Ctrl8259_1, al
-
- ;----- Enable 8250 Interrupt-on-data-ready
- mov dx, [LCR] ; Read Line control register and clear
- in al, dx ; bit 7, the Divisor Latch Address
- and al, 07Fh
- out dx, al
- mov dx, [IER]
-
- mov al, 0 ;we're gonna test the UART first
- out dx, al
- in al, dx ;if this isn't 0, there's no UART
- cmp al, 0
- jnz @@222
-
- mov al, 3
- out dx, al
-
- ;----- Clear 8250 Status and data registers
- @@10:
- mov dx, [RDR] ; Clear RDR by reading port
- in al, dx
- mov dx, [LSR] ; Clear LSR
- in al, dx
- mov dx, [MSR] ; Clear MSR
- in al, dx
- mov dx, [IIR] ; Clear IIR
- in al, dx
- test al, 1
- jz @@10
-
- ;----- Set Bit 3 of MCR -- Enable interupts
- mov dx, [MCR]
- in al, dx
- or al, 08h
- out dx, al
-
- ;----- Clear Buffer Just in case
- call _AsyncClear
-
- ;----- Return
- xor ax, ax
- @@222:
- pop bp
- ret
- ENDP _AsyncInit
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncStop Uninstall ISR
- ;-----------------------------------------------------------------------------
- ; void AsyncStop( void)
- ;-----------------------------------------------------------------------------
- PROC _AsyncStop
- push bp
- mov bp, sp
-
- ;----- Mask (disable) 8259 IRQ Interrupt
- in al, Ctrl8259_1
- or al, [DisableIRQ]
- out Ctrl8259_1, al
-
- ;----- Disable 8250 interrupt
- mov dx, [LCR]
- in al, dx
- and al, 07Fh
- out dx, al
- mov dx, [IER]
- xor al, al
- out dx, al
-
- ;----- Set bit 3 in MCR to 0
- mov dx, [MCR]
- in al, dx
- and al, 0F7h
- out dx, al
-
- ;----- Interrupts are disables. Restore saved interrupt vector.
- push ds
- mov al, [VectorNum]
- mov ah, 25h
- mov dx, [VectorOfs]
- mov ds, [VectorSeg]
- int 21h
- pop ds
-
- ;----- Return
- pop bp
- ret
- ENDP _AsyncStop
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncISR Async Interrupt Service Routine
- ;-----------------------------------------------------------------------------
- ; To be called only as an interrupt.
- ;-----------------------------------------------------------------------------
- PROC AsyncISR
- push ax ; Save Registers
- push bx
- push ds
- push dx
-
- mov ax, @data ; Address local data with ds
- mov ds, ax
-
- mov dx, [IIR] ; Check if data actually recieved
- in al, dx
- and al, 06h
- cmp al, 04h
- je @@recieve
- cmp al, 02h
- jne @@end
-
- ;----- Transmit A byte
- @@transmit:
- mov bx, [TransTail]
- cmp bx, [TransHead]
- jne @@1
-
- mov dx, [IER] ; Buffer empty
- mov al, 1
- out dx, al ; Disable THR empty interrupt
- jmp @@end
-
- @@1:
- mov al, [byte ptr bx] ; Get Byte
- inc [TransTail] ; Update buffer pointer
- cmp [word ptr TransTail], offset TransBuffer + BufSize
- jb @@2
- mov [TransTail], offset TransBuffer
- @@2:
- mov dx, [THR]
- out dx, al
- jmp @@end
-
- ;----- Recieve a byte
- @@recieve:
- mov dx, [RDR] ; Get Byte
- in al, dx
- mov bx, [RecHead] ; Store Byte in buffer
- mov [byte ptr bx], al
- inc bx ; Update RecHead
- cmp bx, offset RecBuffer + BufSize
- jb @@10
- mov bx, offset RecBuffer
- @@10:
- cmp bx, [RecTail]
- jne @@20
- mov bx, [RecHead] ; Cancel Pointer advance on overflow
- @@20:
- mov [RecHead], bx ; Store new pointer
-
- @@end:
- mov al, EOI ; Signal end ot interrupt
- out Ctrl8259_0, al
-
- ; Disable and re-enable interrupts so that there
- ; is an interrupt edge.
-
- mov dx,[IER] ; Point to Interrupt Enable Register.
- in al,dx ; Read the current value.
- push ax ; Save it.
- mov al,0 ; Disable the interrupts.
- out dx,al
- pop ax ; Restore original mask.
- out dx,al ; Re-enable interrupts.
-
- pop dx ; Restore saved registers.
- pop ds
- pop bx
- pop ax
-
- iret
-
- ENDP AsyncISR
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncIn Gets a byte from the input buffer
- ;-----------------------------------------------------------------------------
- ; int AsyncIn( void)
- ;-----------------------------------------------------------------------------
- PROC _AsyncIn
- push bp
- mov bp, sp
-
- xor ax, ax ; Pre-Set result to 0
- mov bx, [RecTail]
- cmp bx, [RecHead]
- je @@return
- mov al, [byte ptr bx]
- inc [RecTail]
- cmp [word ptr RecTail], offset RecBuffer + BufSize
- jb @@return
- mov [RecTail], offset RecBuffer
-
- @@return:
- pop bp
- ret
- ENDP _AsyncIn
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncOut Output a byte
- ;-----------------------------------------------------------------------------
- ; void AsyncOut( int c)
- ;-----------------------------------------------------------------------------
- PROC _AsyncOut
- ARG CharOut:word
-
- push bp
- mov bp, sp
-
- mov ax, [CharOut]
-
- mov bx, [TransHead]
- mov cx, bx
- inc cx ; Compute NEW buffer position
- cmp cx, offset TransBuffer + BufSize
- jb @@1
- mov cx, offset TransBuffer
- @@1:
- cmp cx, [TransTail] ; Wait for space in buffer
- je @@1
-
- mov [byte ptr bx], al ; Add byte to buffer
- mov [TransHead], cx ; Update pointer
-
- mov dx, [IER] ; Enable THR empty interrupt
- mov al, 3
- out dx, al
-
- pop bp
- ret
- ENDP _AsyncOut
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncSet Set communication paramaters
- ;-----------------------------------------------------------------------------
- ; void AsyncSet( int Baud, int Control)
- ;
- ; Baud = 150, 300, 600, 1200, 2400, 4800, 9600, 19200, 28800, 38400, 57600
- ; Control = The valure to place in the LCR
- ;-----------------------------------------------------------------------------
- PROC _AsyncSet
- ARG Baud:word, Control:word
-
- push bp
- mov bp, sp
-
- mov bx, [Baud]
- cmp bx, 0
- je @@abort
-
- mov ax, 0C200h ; Baud rate divisor = 115200 / Baud
- mov dx, 0001h ; 115200 = 0001C200h
- div bx
- mov cx, ax
-
- cli
- mov dx, [LCR] ; Set Port Toggle to BRDL/BRDH registers
- mov al, 0ffh
- out dx, al
-
- mov dx, [BRDL] ; Set Baud Rate
- mov al, cl
- out dx, al
- mov dx, [BRDH]
- mov al, ch
- out dx, al
-
- mov dx, [LCR] ; Set LCR and Port Toggle
- mov ax, [Control]
- and al, 07Fh
- out dx, al
-
- sti
- @@abort:
- pop bp
- ret
- ENDP _AsyncSet
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncInStat Returns the # of characters in buffer
- ;-----------------------------------------------------------------------------
- ; int AsyncInStat( void)
- ;-----------------------------------------------------------------------------
- PROC _AsyncInStat
- push bp
- mov bp, sp
-
- mov ax,[RecHead]
- sub ax, [RecTail]
- jge @@10
- add ax, BufSize
- @@10:
-
- pop bp
- ret
- ENDP _AsyncInStat
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncOutStat Returns the # of characters in buffer
- ;-----------------------------------------------------------------------------
- ; int AsyncOutStat( void)
- ;-----------------------------------------------------------------------------
- PROC _AsyncOutStat
- push bp
- mov bp, sp
-
- mov ax,[TransHead]
- sub ax, [TransTail]
- jge @@10
- add ax, BufSize
- @@10:
-
- pop bp
- ret
- ENDP _AsyncOutStat
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncHand Sets various handshaking lines
- ;-----------------------------------------------------------------------------
- ; void AsyncHand( int Hand)
- ;-----------------------------------------------------------------------------
- PROC _AsyncHand
- ARG Hand:word
- push bp
- mov bp, sp
-
- mov dx, [MCR]
- mov ax, [Hand]
- or al, 08h ; Keep interrupt enable ON
- out dx, al
-
- pop bp
- ret
- ENDP _AsyncHand
-
-
-
- ;-----------------------------------------------------------------------------
- ; AsyncStat Returns Async/Modem status
- ;-----------------------------------------------------------------------------
- ; unsigned AsyncStat( void)
- ;
- ; MSR is returned in the high byte, LSR in the low byte
- ;-----------------------------------------------------------------------------
- PROC _AsyncStat
- push bp
- mov bp, sp
-
- mov dx, [MSR]
- in al, dx
- mov cl, al
- mov dx, [LSR]
- in al, dx ; LSR in low byte
- mov ah, cl ; MSR in high byte
-
- pop bp
- ret
- ENDP _AsyncStat
-
-
- END