⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 async.asm

📁 这是经典的卫星编程应用程序
💻 ASM
📖 第 1 页 / 共 2 页
字号:
;  Async Module.
%	MODEL	MEMMOD
	IDEAL
	P8086

EOIX		equ	020h		; 8259 end-of-interupt
EOIX2		equ	0a0h		; 8259 #2 end-of-interrupt
Ctrl8259_0	equ	020h		; 8259 port
Ctrl8259_1	equ	021h		; 8259 port (Masks)
Ctrl8259_2	equ	0a0h		; 8259 port #2
Ctrl8259_3	equ	0a1h		; 8259 port (Masks) #2
BufSize		equ	512		; Buffer Size
IIRx		equ	002h		; Interrupt Ident Reg
IIR_FIFO_ENABLED equ	0c0h		; FIFO enabled (FCR0,1=1)-16550A only
FCR     	equ	002h            ; FIFO control register (16550A only)
FIFO_ENABLE     equ	001h            ; enable TX & RX fifo 
BufBytes	equ	4		; FIFO Trigger point

;	DATASEG
	FARDATA
	ends
;
;  I can't take the time to figure out how to handle all the addressing for the data in the 
;   far segments in the tchuge model so I'll just put all of the data in the code seg
;   and make ds=cs.  crh Sept 25, 1998
;
	CODESEG
    assume  cs:ASYNC_TEXT,ds:ASYNC_TEXT

; 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
IRQgen		dw	0		; 0 until tx int received
_TXints		dd	0		; Transmitter interrupts
_RXints		dd	0		; Receiver interrupts
_TXhw		dw	0		; Transmitter software hi water
_RXhw		dw	0		; Receiver software hi water
_TXoverrun	dw	0		; Transmitter software overrun
_RXoverrun	dw	0		; Receiver software overrun
_Is_16550a	dw	0		; 1 if UART is 16550a with FIFO

; 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

Isat		dw	0		; 1 if irq > 7

; Register Offsets for the UART
RegOffsets	dw	0, 0, 0, 1, 1, 2, 3, 4, 5, 6


	PUBLIC	_AsyncInit,	_AsyncClear, 	_AsyncStop
	PUBLIC	_AsyncIn,	_AsyncOut, 	_AsyncSet, _TXoverrun
	PUBLIC	_AsyncHand,	_AsyncStat,	_AsyncInStat, _RXoverrun
	PUBLIC	_AsyncOutStat,	_kbraw, _TXints, _RXints, _RXhw, _TXhw
	PUBLIC  _Is_16550a

PROC	_kbraw
	mov     ah,06h  ; Direct Console I/O
	mov     dl,0ffh ; Read keyboard
	int     21h     ; DOS
	jz      @@1     ; zero flag set implies no character ready
	mov     ah,0    ; 
	ret
@@1:    mov     ax,-1   ; no char, return -1
	ret
endp	_kbraw

;-----------------------------------------------------------------------------
; Re-arm 8259 interrupt controller(s)
; Should be called just after taking an interrupt, instead of just
; before returning. This is because the 8259 inputs are edge triggered, and
; new interrupts arriving during an interrupt service routine might be missed.

PROC    eoi
	push ds
	push cs
	pop ds
	cmp     [Isat],1
	jnz     @@1             ; Only one 8259?
	mov     al,0bh          ; read in-service register from
	out     Ctrl8259_2,al   ;   secondary 8259
	nop                     ; settling delay
	nop
	nop
	in      al,Ctrl8259_2   ; get it
	or      al,al           ; Any bits set?
	jz      @@1             ; nope, not a secondary interrupt
	mov     al,EOIX         ; Get EOI instruction
	out     Ctrl8259_2,al   ; Secondary 8259 (PC/AT only)
@@1:    mov     al,EOIX         ; 8259 end-of-interrupt command
	out     Ctrl8259_0,al   ; Primary 8259
	pop ds
	ret
endp    eoi

;-----------------------------------------------------------------------------
; AsyncClear				Empty the receive buffer
;-----------------------------------------------------------------------------
; void	AsyncClear( void);
;
;
;-----------------------------------------------------------------------------
PROC	_AsyncClear
	cli
	push ds
	push cs
	pop ds
	push	ax
	mov	ax, offset RecBuffer
	mov	[RecHead], ax
	mov	[RecTail], ax
	mov	ax, offset TransBuffer
	mov	[TransHead], ax
	mov	[TransTail], ax
	pop	ax
	pop ds
	sti
	ret
ENDP	_AsyncClear

;-----------------------------------------------------------------------------
; AsyncInit			Initalize Serial Port and install ISR
;-----------------------------------------------------------------------------
;	void	AsyncInit( int IOAddress, IRQnum)
;
;	Where IOAddress is normally
;
;		COM1 = 03f8
;		COM2 = 02f8
;		COM3 = 03e8
;		COM2 = 02e8
;
;-----------------------------------------------------------------------------
PROC	_AsyncInit
	ARG	IOAddress:word,IRQnum:word

	push	bp
	mov	bp, sp
	push ds
	push cs
	pop ds

;----- COM Setup
	mov	ax,[IOAddress]
	mov	[Port], ax
	mov	ax,[IRQnum]
	cmp	al,8
	jge	@@1			; must be an AT

	add	al,8
	mov	[VectorNum],al
	mov	[Isat],0
	jmp	@@3
;
; IRQ >7 indicates an AT
;
@@1:	
	mov	[Isat],1
	sub	al,8
	add	al,070h

@@3:
	mov	cx,[IRQnum]
	mov	ax,1
	sal	ax,cl
	mov	[DisableIRQ],al
	not	ax
	mov	[EnableIRQ], al

;---- Check for 16550a with FIFO
;
;  set enable bit and check reg.  If bits 6&7 (0xC0) are not set then
;   the UART is not a 16550a or is defective.  This routine always
;   returns 'not an 16550a' under WinNT.
;
	mov	ax,[IOAddress]
	add	ax,FCR
	mov	dx,ax
	push	dx			; save address for later use
	mov	ax,[IOAddress]		; setup base address
	add	ax,IIRx			;  add FIFO control reg offset
	mov	dx,ax
	mov	al,FIFO_ENABLE		; setup enable check
	out	dx,al
	in	al,dx
	and	al,IIR_FIFO_ENABLED
	cmp	al,IIR_FIFO_ENABLED	; do we have a valid FIFO?
	jne	@@x			; No, jump

	mov	[_Is_16550a],1		; Yes, we do
	pop	dx			; restore FIFO cntl reg address
	mov	al,BufBytes
	jmp	@@y
@@x:
	mov	[_Is_16550a],0		; No FIFO or a defective FIFO
	pop	dx			; restore FIFO cntl reg address
	mov	al,0
@@y:
	out	dx,al

;---- 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
	cmp	[Isat],1
	je	@@33
	in	al, Ctrl8259_1
	and	al, [EnableIRQ]
	out	Ctrl8259_1, al
	jmp	@@34
@@33:
	in	al, Ctrl8259_3
	and	al, [EnableIRQ]
	out	Ctrl8259_3, al
@@34:

;----- 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 ds
	pop	bp
	ret
ENDP	_AsyncInit

;-----------------------------------------------------------------------------
;  AsyncStop				Uninstall ISR
;-----------------------------------------------------------------------------
;	void  AsyncStop( void)
;-----------------------------------------------------------------------------
PROC	_AsyncStop
	push	bp
	mov	bp, sp
	push ds
	push cs
	pop ds

;----- Mask (disable) 8259 IRQ Interrupt
	cmp	[Isat],1
	je	@@1
	in	al, Ctrl8259_1
	or	al, [DisableIRQ]
	out	Ctrl8259_1, al
	jmp	@@2
@@1:
	in	al, Ctrl8259_3
	or	al, [DisableIRQ]
	out	Ctrl8259_3, al
@@2:

;----- 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 disabled.  Restore saved interrupt vector.
	push	ds
	mov	al, [VectorNum]
	mov	ah, 25h
	mov	dx, [VectorOfs]
	mov	ds, [VectorSeg]
	int	21h
	pop	ds

;----- Clear UART buffer
	mov	ax,[_Is_16550a]
	cmp	ax,1
	jne	@@z
	mov	ax,[IOAddress]
	add	ax,FCR
	mov	dx,ax
	mov	al,BufBytes
	jmp	@@x
@@z:
	mov	al,0
@@x:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -