📄 ser1.asm
字号:
in al, dx
pop dx
ret
sl_GetMSRCom1 endp
;
;
; sl_SetMCRCom1-Writes the data in AL to the modem control register.
; sl_GetMCRCom1-Reads the data from the modem control register into AL.
;
; AL:
; bit 0- Data terminal ready (DTR)
; bit 1- Request to send (RTS)
; bit 2- Out 1
; bit 3- Out 2
; bit 4- Loop
; bits 5-7 (must be zero)
;
public sl_SetMCRCom1
sl_SetMCRCom1 proc far
push dx
mov dx, com1MCR
out dx, al
pop dx
ret
sl_SetMCRCom1 endp
;
public sl_GetMCRCom1
sl_GetMCRCom1 proc far
push dx
mov dx, com1MCR
in al, dx
pop dx
ret
sl_GetMCRCom1 endp
;
;
;
; sl_GetLCRCom1- Reads the value from the line control register into AL.
; sl_SetLCRCom1- Writes the value in AL to the line control register.
;
; AL:
; bits 0,1- Word length selection
; bit 2- Number of stop bits
; bit 3- Parity Enable
; bit 4- Even parity select
; bit 5- Stuck parity
; bit 6- Set Break
; bit 7- Divisor latch access bit
;
public sl_GetLCRCom1
sl_GetLCRCom1 proc far
push dx
mov dx, com1LCR
in al, dx
pop dx
ret
sl_GetLCRCom1 endp
;
public sl_SetLCRCom1
sl_SetLCRCom1 proc far
push dx
mov dx, com1LCR
out dx, al
pop dx
ret
sl_SetLCRCom1 endp
;
;
; sl_GetIIRCom1-Reads the interrupt indentification register and returns its
; value in AL.
;
; AL:
; bit 0- 0 if interrupt pending, 1 if no interrupt.
; bits 1,2- Interrupt ID (highest priority).
; bits 3-7- Always zero.
;
; Interrupt ID
; bit 2 1 Source Reset by
; ---- ----------------------------- ------------------------------
; 0 0 CTS, DSR, RI Reading the MSR
; 0 1 Xmtr holding register empty Reading IIR or writing to xmtr
; 1 0 Receiver data available Reading rcvr buffer
; 1 1 Overrun, parity, framing, or Reading the LSR.
; break
;
;
public sl_GetIIRCom1
sl_GetIIRCom1 proc far
push dx
mov dx, com1IIR
in al, dx
pop dx
ret
sl_GetIIRCom1 endp
;
;
; sl_GetIERCom1-Reads the IER and returns it in AL.
; sl_SetIERCom1-Stores the value in AL into the IER.
;
; AL:
; bit 0- Enable data available interrupt.
; bit 1- Enable xmtr holding register empty interrupt.
; bit 2- Enable receive line status interrupt.
; bit 3- Enable modem status interrupt
; bits 4-7 Always zero.
;
public sl_GetIERCom1
sl_GetIERCom1 proc far
push dx
call sl_GetLCRCom1
push ax ;Save divisor access bit.
and al, 7fh ;Address the IER.
call sl_SetLCRCom1
mov dx, com1IER
in al, dx
mov dl, al ;Save for now
pop ax
call sl_SetLCRCom1 ;Restore divisor latch
mov al, dl ;Restore IER value
pop dx
ret
sl_GetIERCom1 endp
;
;
public sl_SetIERCom1
sl_SetIERCom1 proc far
push dx
push ax
mov ah, al ;Save value to output
call sl_GetLCRCom1 ;Get and save divsor access
push ax ;bit.
and al, 7fh ;Address the IER.
call sl_SetLCRCom1
mov al, ah
mov dx, com1IER
out dx, al
pop ax ;Restore divisor latch bit.
call sl_SetLCRCom1
pop ax
pop dx
ret
sl_SetIERCom1 endp
;
;
;****************************************************************************
;
; Interrupt-driven Serial I/O
;
;
; sl_InitCom1Int- Initializes the hardware to use interrupt-driven I/O
; for COM1:
;
public sl_InitCom1Int
sl_InitCom1Int proc far
pushf ;Save interrupt disable flag.
push es
push ax
push dx
;
; Turn off the interrupts while we're screwing around here.
;
cli
;
; Save old interrupt vector.
;
xor ax, ax ;Point at interrupt vectors
mov es, ax
mov ax, Int0Cofs ;Get ofs int 0ch vector.
mov word ptr StdGrp:int0cVec, ax
mov ax, Int0Cseg ;Get seg int 0ch vector.
mov word ptr StdGrp:int0cVec+2, ax
;
; Point int 0ch vector at our interrupt service routine:
;
mov ax, cs
mov Int0Cseg, ax
mov ax, offset stdgrp:Com1IntISR
mov Int0Cofs, ax
;
; Clear any pending interrupts:
;
call far ptr sl_GetLSRCom1 ;Clear Receiver line status
call far ptr sl_GetMSRCom1 ;Clear CTS/DSR/RI Interrupts
call far ptr sl_GetIIRCom1 ;Clear xmtr empty interrupt
mov dx, Com1Port
in al, dx ;Clear data available intr.
;
; Clear divisor latch access bit. WHILE OPERATING IN INTERRUPT MODE, THE
; DIVISOR ACCESS LATCH BIT MUST ALWAYS BE ZERO. If for some horrible reason
; you need to change the baud rate in the middle of a transmission (or while
; the interrupts are enabled) clear the interrupt flag, do your dirty work,
; clear the divisor latch bit, and finally restore interrupts.
;
call far ptr sl_getLCRCom1
and al, 7fh
call far ptr sl_SetLCRCom1
;
;
; Enable the receiver and transmitter interrupts
;
mov al, 3 ;Enable rcv/xmit interrupts
call far ptr sl_SetIERCom1
;
; Must set the OUT2 line for interrupts to work.
; Also sets DTR and RTS active.
;
mov al, 00001011b
call far ptr sl_SetMCRCom1
;
; Activate the COM1 (int 0ch) bit in the 8259A interrupt controller chip.
;
in al, 21h
mov StdGrp:i8259a, al ;Save interrupt enable bit.
and al, 0efh ;Bit 4=IRQ 4 = INT 0Ch
out 21h, al
;
pop dx
pop ax
pop es
popf ;Restore interrupt disable flag.
ret
sl_InitCom1Int endp
;
;
; sl_IntsOffCom1- Disconnects the interrupt system and shuts off interrupt
; activity at the COM1: port.
;
; Warning! This routine assumes that interrupts are currently active
; due to a call to sl_InitCom1Int. If you call this guy
; w/o first calling sl_InitCom1Int you will probably crash
; the system. Furthermore, this routine makes the (rather
; presumptuous) assumption that no one else has patched into
; the INT 0Ch vector since SL_InitCom1Int was called.
;
public sl_IntsOffCom1
sl_IntsOffCom1 proc far
pushf
push es
push dx
push ax
;
cli ;Don't allow interrupts while messing
xor ax, ax ; with the interrupt vectors.
mov es, ax ;Point at interrupt vectors.
;
; First, turn off the interrupt source:
;
call far ptr sl_GetMCRCom1
and al, 3 ;Mask out OUT 2 bit (masks ints)
call far ptr sl_SetMCRCom1
;
in al, 21h ;Get 8259a ier
and al, 0efh ;Clear IRQ 4 bit.
mov ah, StdGrp:i8259a ;Get our saved value
and ah, 1000b ;Mask out com1: bit (IRQ 4).
or al, ah ;Put bit back in.
out 21h, al
;
; Restore the interrupt vector:
;
mov ax, word ptr StdGrp:Int0cVec
mov Int0Cofs, ax
mov ax, word ptr StdGrp:Int0cVec+2
mov Int0Cseg, ax
;
pop ax
pop dx
pop es
popf
ret
sl_IntsOffCom1 endp
;
;----------------------------------------------------------------------------
;
; Com1IntISR- Interrupt service routine for COM1:
;
Com1IntISR proc far
push ax
push bx
push dx
TryAnother: mov dx, Com1IIR
in al, dx ;Get id
test al, 1 ;Any interrupts left?
jnz IntRtn
test al, 100b
jnz ReadCom1
test al, 10b
jnz WriteCom1
;
; Bogus interrupt?
;
call sl_GetLSRCom1 ;Clear receiver line status
call sl_GetMSRCom1 ;Clear modem status.
jmp TryAnother
;
IntRtn: mov al, 20h ;Acknowledge interrupt to the
out 20h, al ; 8259A interrupt controller.
pop dx
pop bx
pop ax
iret
;
; Handle incoming data here:
; (Warning: This is a critical region. Interrupts MUST BE OFF while executing
; this code. By default, interrupts are off in an ISR. DO NOT TURN THEM ON
; if you modify this code).
;
ReadCom1: mov dx, Com1Port
in al, dx ;Get the input char
mov bx, StdGrp:InHead
mov StdGrp:[bx], al
inc bx
cmp bx, offset stdgrp:InpBufEnd
jb NoInpWrap
mov bx, offset stdgrp:InpBuf
NoInpWrap: cmp bx, StdGrp:InTail
je TryAnother
mov StdGrp:InHead, bx
jmp TryAnother
;
;
; Handle outgoing data here (This is also a critical region):
;
WriteCom1: mov bx, StdGrp:OutTail
cmp bx, StdGrp:OutHead
jne OutputChar
;
; If head and tail are equal, simply set the TestBuffer variable to zero
; and quit. If they are not equal, then there is data in the buffer and
; we should output the next character.
;
mov StdGrp:TestBuffer, 0
jmp TryAnother
;
; The buffer pointers are not equal, output the next character down here.
;
OutputChar: mov al, StdGrp:[bx]
mov dx, Com1Port
out dx, al
inc bx
cmp bx, offset stdgrp:OutBufEnd
jb NoOutWrap
mov bx, offset stdgrp:OutBuf
NoOutWrap: mov StdGrp:OutTail, bx
jmp TryAnother
Com1IntISR endp
;
;
;----------------------------------------------------------------------------
;
; Routines to read/write characters in serial buffers.
;
public sl_InCom1
sl_InCom1 proc far
pushf ;Save interrupt flag
push bx
sti ;Make sure interrupts are on.
TstInLoop: mov bx, StdGrp:InTail
cmp bx, StdGrp:InHead
je TstInLoop
mov al, StdGrp:[bx] ;Get next char.
cli ;Turn off ints while adjusting
inc bx ; buffer pointers.
cmp bx, offset stdgrp:InpBufEnd
jne NoWrap2
mov bx, offset stdgrp:InpBuf
NoWrap2: mov StdGrp:InTail, bx
pop bx
popf ;Restore interrupt flag.
ret
sl_InCom1 endp
;
;
public sl_OutCom1
sl_OutCom1 proc far
pushf
cli ;No interrupts now!
cmp StdGrp:TestBuffer, 0 ;Write directly to serial chip?
jnz BufferItUp
call far ptr sl_WriteCom1 ;Output to port
mov StdGrp:TestBuffer, 1 ;Must buffer up next char.
popf
ret
;
BufferItUp: push bx
mov bx, StdGrp:OutHead
mov StdGrp:[bx], al
inc bx
cmp bx, offset stdgrp:OutBufEnd
jne NoWrap3
mov bx, offset stdgrp:OutBuf
NoWrap3: cmp bx, StdGrp:OutTail
je NoSetTail
mov StdGrp:OutHead, bx
NoSetTail: pop bx
popf
ret
sl_OutCom1 endp
;
stdlib ends
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -