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

📄 n8250.inc

📁 VRTX 商用嵌入式实时操作系统
💻 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 + -