📄 n8250.inc
字号:
; ====================================================================
; @(#)n8250.inc 5.1 5/7/91
;
; N8250.INC - I/O driver for National 8250 UART
; NS16C450 and INS8250A
;
; Module Name: n8250.inc
; Module Desc: include file (as hwequ.inc) for board.src
; Created: Nov. 1990
;
; Rev 1.2 J. Fuchigami, MRI, March 22, 1991
; Removed leading underscore from MO_START
; Changed call MOHALT to jmp
;
; New rev #1.1 J. Fuchigami, MRI, March 21, 1991
; Put under SCCS
;
; Revision: 1.0
; --------------------------------------------------------------------
; General Information:
;
; ====================================================================
;=====================================================================
; PORT INITIALIZATION ROUTINE.
;=====================================================================
; INCLUDE(n8250.ieq) ;8250 definitions
public IO_INIT
; ;INITIALIZE UART
%IF ((%CONIO AND %INITIO) ne 0) THEN (
IO_INIT proc near
cmp ax,0
jnz INIT_RESET ;not first init
; initialize the uart
mov dx,LCR_REG ;from line configuration reg
mov al,LCR_DLAB ; select baud rate registers
out dx,al ;set baud rate low and high regs
mov dx,BAL_REG ;low baud rate reg
mov al,BAUD_COUNT and 0ffh
out dx,al
mov dx,BAH_REG ;high baud rate reg
mov al,BAUD_COUNT/100h
out dx,al
mov dx,LCR_REG ;LINE CNTRL for data frame
mov al,LCR_PARITY+LCR_LENGTH
out dx,al ;set parity and bit length
; if interrupt driven, set them up
%IF ((%CONIO AND %INTRPT) ne 0) THEN (
mov al,08h ;modem control register (MCR) need to set
mov dx, LCR_REG+1 ; address of MCR
out dx,al ;called for by the WAITE group book
;ENABLE interrupts in UART
mov dx,IER_REG ;general interrupt enable register
mov al,IER_REC_INT ; enable only recv. buf full interrupt
out dx,al ;
;THIS SETUP FOR COM PORT 1 only
;************************************************************************
; :SETUP 8259 CONTROLLER
; These defined in n8250.ieq
;SET (NUM_8259, 2) ;set the number of 8259's 1 or 2
;MASTER_8259 EQU 020H
;SLAVE_8259 EQU 0A0H
;MASTER_8259_BASE EQU 038H ;base for interrupts from the 1st 8259
;SLAVE_8259_BASE EQU 040H ;base of interrupts for the 2nd 8259 lwr 3 bits
;must be 0
%IF (%NUM_8259 EQ 2) THEN (
mov al, 11h ;ICW 1, bit 0 = for ICW4 used, bit 4 = ICW1
) ELSE (
mov al, 13h ;ICW 1, no slaves, bit 1= 1 for no slaves
) FI
out MASTER_8259,al
mov al, MASTER_8259_BASE ;ICW 2 set the base of vectors from this 8259
out MASTER_8259+1,al
mov al, 04H ;ICW 3 the other 8259 is cascaded to this unit
out MASTER_8259+1,al
mov al, 01h ;ICW 4 NO EOI, NO SPECIAL NESTED MODE
out MASTER_8259+1,al
;OCW 1 ENABLE interrupts in controller
%IF (%PC_PORT EQ 1) THEN (
mov al, 0EFh ;enable IRQ4 in OCW1 wrd/set all bits but D4
) ELSE (
%IF (%PC_PORT EQ 2) THEN (
mov al, 0F7h ;enable IRQ3 in OCW1 wrd /set all bits but D3
) ELSE (
ERROR - PC PORT not set interrupts can not be enabled
) FI
) FI
out MASTER_8259+1,al ; OCW1
mov al, 20h ;OCW2 NON SPECIFIC EOI
out MASTER_8259,al;
mov al, 08H ;OCW2 Operation command word no action
out MASTER_8259,al;
%IF (%NUM_8259 EQ 2) THEN (
;initialize the second 8259
mov al, 11h ;ICW 1, this is the slave unit
out SLAVE_8259,al
mov al, SLAVE_8259_BASE ;ICW 2 set the base of vectors from this 8259
out SLAVE_8259+1,al
mov al, 04H ;ICW 3 the other 8259 is cascaded to this unit
out SLAVE_8259+1,al
mov al, 01h ;ICW 4 NO EOI, NO SPECIAL NESTED MODE
out SLAVE_8259+1,al
;OCW 1 ENABLE interrupts in controller
mov al, 0FFh ; disable all interrupt in lines
out SLAVE_8259+1,al ; OCW1
mov al, 20h ;OCW2 NON SPECIFIC EOI
out SLAVE_8259,al;
mov al, 08H ;OCW2 Operation command word no action
out SLAVE_8259,al;
) FI
; setup the interrupt vector in IVT to point at the desired entry
; point in xmentry to handle a serial port interrupt
push MORXINT ;offset into the xmentry table
%IF (%PC_PORT EQ 1) THEN (
push COM1_INTERRUPT ;this is the interrupt taken by IRQ3
) ELSE ( ; MASTER_8259_BASE + 4 (SIOINT0)
%IF (%PC_PORT EQ 2) THEN (
push COM2_INTERRUPT ;this is the interrupt taken by IRQ4
) ELSE ( ; MASTER_8259_BASE + 3 (SIOINT1)
REPORT ERROR: Cannot initialize interrupt vector unless PC_PORT defined 1 or 2
) FI
) FI
call set_ivt_offs ;and set the interrupt in the IVT table
add esp,8 ;pop the two long words off the esp
ret
) FI
INIT_RESET: ;reset port from aux-mon (interrupt, etc)
ret
IO_TERM: ;reset port to aux-mon (disable int, etc)
ret
IO_INIT endp
) FI ; INITIO
;-============================================================
;
; Polled output
;
; -> DL = character to transmit
; <- AX = RET_OK (transmitted ok)
; ER_TBF (transmit buffer full)
;
;-============================================================
CON_OUT proc near
mov ah,dl
mov dx,STATUS_REG
in al,dx ;read status register
test al,TBEMPTY ;check for transmit buffer empty
jz con_out40 ;its busy
mov dx,DATA_REG ;address of transmit buffer
mov al,ah
out dx,al ;send it
mov ax,RET_OK
ret ;return to caller
con_out40:
mov ax,ER_TBF
ret
CON_OUT endp
;-============================================================
;
; Polled input
;
; <- DL = received character
; -> AX = RET_OK (received ok)
; ER_NCA (no character available)
; ER_REC (receive error)
;
;-============================================================
%IF ((%CONIO AND %POLLED) ne 0) THEN (
CON_IN proc near
mov dx,STATUS_REG ;address of status register
in al,dx ;get status byte
test al,RBFULL
jz con_in50 ;nothing here
; check for errors
test al,FRAME_ERR+OVERRUN_ERR+PARITY_ERR
jnz con_in70 ;have an error
; get the character
mov dx,DATA_REG ;input buffer address
in al,dx ;get character available
mov dl,al
mov ax,RET_OK
ret ;return to caller
; no character available
con_in50:
mov ax,ER_NCA
ret
; have an error
con_in70:
mov dx,DATA_REG ;input buffer address
in al,dx ;get any character
mov dl,al
mov ax,ER_REC
ret ;return to caller
CON_IN endp
) FI
;-============================================================
;
; Interrupt input
;
;
%IF ((%CONIO AND %INTRPT) ne 0) THEN (
public RX_INT
RX_INT proc near ;input from recieve interrupt
push eax ;save registers
push edx
; mov eax, 0110cH ;jjj debug
; inc DWORD PTR [eax]
; get the character
mov dx,DATA_REG ;input buffer address
in al,dx
mov ah,al
mov dx,STATUS_REG ;address of status register
in al,dx ;get status byte
mov dl,ah ;put char in correct register
; check for errors
test al,FRAME_ERR+OVERRUN_ERR+PARITY_ERR
jnz rx_int_err ;have an error
; tell the monitor we have character
mov ax,RET_OK
jmp short rx_int_report
; have some kind of error
rx_int_err:
mov ax,ER_REC
rx_int_report:
call mo_start+MORXCHR
cmp ax,ER_HLT ;should we stop
jnz rx_int_done ;no
; monitor tells us to stop
; if have interrupt controller would do an EOI here
;EOI
mov al,20h ;OCW2 output an non specific EOI
out MASTER_8259,al
pop edx
pop eax
jmp mo_start+MOHALT
rx_int_done:
; if have interrupt controller would do an EOI here
mov al,20h ;OCW2 output an non specific EOI
out MASTER_8259,al
pop edx
pop eax ;restore registers
iretd
RX_INT endp
) ELSE (
; 04-29-97 KL: need to define this dummy for polled only case, since
; xdm core always refer to RX_INT. CAR 51649
public RX_INT
RX_INT proc near ;input from recieve interrupt
iretd
RX_INT endp
) FI
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -