📄 lpt_pkg.asm
字号:
ADD DX,DATREG ;;; DX equals port to send data to.
MOV AL,ES:[BX+DI] ;;; Get data from buffer.
OUT DX,AL ;;; Put data in output register.
ADD DX,(CMDREG-DATREG) ;;; Point to command register.
MOV AL,(IRQE+SELECT+INIT+STROBE) ;;; Prepare to strobe data.
OUT DX,AL ;;; Set strobe high.
MOV AL,(IRQE+SELECT+INIT) ;;;
OUT DX,AL ;;; Set strobe low.
INC BX ;;; Increment START_TDATA.
CMP BX,[SI].TBUF_SIZE ;;; See if gone past end.
JB NTADJ ;;; If not then skip.
XOR BX,BX ;;; Reset to beginning.
NTADJ: MOV [SI].START_TDATA,BX ;;; Save START_TDATA.
DEC [SI].SIZE_TDATA ;;; One less character in x-mit buffer.
JMP REPOLL ;;; Check again is ready for next char.
INT_END:
POP DX ;;; Restore previous context.
POP CX ;;;
POP BX ;;;
POP AX ;;;
POP DI ;;;
POP SI ;;;
POP BP ;;;
POP ES ;;;
POP DS ;;;
IRET ;;; Return from interrupt.
INT_HNDLR ENDP
.SBHED <LPT_INI -- Initialize Communication Port>
; void
; lpt_ini(unit, tbuf, tbuflen, pinit)
; /* Initializes port and interrupt vector. */
; int unit; /* 1 ==> LPT1:, 2 ==> LPT2:. */
; char *tbuf; /* Transmit buffer address. */
; int tbuflen; /* Transmit buffer length. */
; bool pinit; /* TRUE ==> force printer initialization. */
; Initialize the Intel 8250 and set up interrupt vector to int_hndlr.
IF LDATA
BENTRY LPT_INI <UNIT,TBOFF,TBSEG,TBLEN,PINIT>
ELSE
BENTRY LPT_INI <UNIT,TBOFF,TBLEN,PINIT>
ENDIF
MOV AX,DS ; Copy our data segment number.
IFE LDATA
MOV ES,AX ; Save for buffer addresses.
ENDIF
MOV CS:DATASEG,AX ; Store segment # in code space (gulp!).
MOV SI,OFFSET LPT1_CTRL ; Setup pointer to control structure.
; Pickup printer port from BIOS:
PUSH DS ; Save current data segment.
XOR AX,AX ; Zero AX.
MOV DS,AX ; Switch to segment zero.
MOV AX,WORD PTR DS:PRINTER_BASE ; Get the printer port.
POP DS ; Restore our data segment.
MOV [SI].LPTX_BASE,AX ; Save printer base address.
IF LDATA
MOV AX,TBSEG ; Get the transmit buffer segment number.
ELSE
MOV AX,ES ; Default transmit buffer segment number.
ENDIF
MOV [SI].TBUF_SEG,AX ; Save it.
MOV AX,TBOFF ; Copy the transmit buffer offset.
MOV [SI].TBUF_OFF,AX ;
MOV AX,TBLEN ; Copy the transmit buffer length.
MOV [SI].TBUF_SIZE,AX ;
XOR AX,AX ; Clear the accumulator.
MOV [SI].START_TDATA,AX ; Reset start of transmitted data.
MOV [SI].END_TDATA,AX ; Reset end of transmitted data.
MOV [SI].SIZE_TDATA,AX ; Reset number of transmitted chars.
CMP WORD PTR PINIT,0 ; Do we want a printer init?
JE NOINIT ; (nope)
MOV DX,[SI].LPTX_BASE ; Get printer base address.
ADD DX,CMDREG ; Point to command register.
MOV AL,(SELECT)
OUT DX,AL ; Start initialization.
MOV AX,1000 ; Prepare to burn some time.
INILOP: DEC AX
JNZ INILOP
MOV AL,(SELECT+INIT)
OUT DX,AL ; Stop initialization.
NOINIT:
; Setup the LPT interrupt vector:
MOV AX,(LPT_INT+INT_OFF) ; Get the LPT: interrupt number.
MOV BX,OFFSET INT_HNDLR ; Start of the interrupt routine.
BCALL INT_SETU <AX BX CS> ; Call int_setup(vec, newip, newcs).
CLI ; ******* Disable Interrupts *******
;;; Enable interrupts on 8259:
IN AL,IMR ;;; Get current enable bits on 8259.
MOV CL,LPT_INT ;;; Get interrupt number.
MOV BL,1 ;;; Convert to
SHL BL,CL ;;; bit position.
NOT BL ;;; Clear current
AND AL,BL ;;; interrupt bit.
OUT IMR,AL ;;; Set enable on 8259.
STI ;;; ******* Enable Interrupts *******
;;; (Next instruction still disabled)
BEND LPT_INI
.SBHED <LPT_TRM -- Turn Off Interrupts and Shutdown>
; void
; lpt_trm(unit) /* Turns off interrupts from the LPT: port. */
; int unit; /* 1 ==> LPT1:, 2 ==> LPT2:. */
BENTRY LPT_TRM <UNIT>
MOV SI,OFFSET LPT1_CTRL ; Setup pointer to control structure.
MOV DX,[SI].LPTX_BASE
ADD DX,CMDREG ; Turn off line printer interface.
MOV AL,(SELECT+INIT)
OUT DX,AL
IN AL,IMR ; Turn off 8259 interrupt controller.
MOV CL,LPT_INT ; Get interrupt number.
MOV BL,1 ; Convert to
SHL BL,CL ; bit position.
OR AL,BL ; Disable this interrupt.
OUT IMR,AL
; Restore the LPT interrupt vector:
MOV AX,(LPT_INT+INT_OFF) ; Get the LPT: interrupt number.
BCALL INT_REST <AX> ; Call int_restore(vec).
BEND LPT_TRM
.SBHED <LPT_OCNT -- Returns Number of Free Bytes>
; int /* Number of free bytes in output buffer. */
; lpt_ocnt(unit) /* Returns number of free bytes in output buffer. */
; int unit; /* 1 ==> LPT1:, 2 ==> LPT2:. */
BENTRY LPT_OCNT <UNIT>
MOV SI,OFFSET LPT1_CTRL ; Setup pointer to control structure.
MOV AX,[SI].TBUF_SIZE ; Get the size of the x-mit buffer.
SUB AX,[SI].SIZE_TDATA ; Subtract the number of bytes used.
BEND LPT_OCNT
.SBHED <LPT_PUTC -- Queue a Character for Output>
; bool /* Returns FALSE if no more room. */
; lpt_putc(unit, ch) /* Writes a character to the output buffer. */
; int unit; /* 1 ==> LPT1:, 2 ==> LPT2:. */
; char ch; /* The character to write. */
BENTRY LPT_PUTC <UNIT,OCHAR>
MOV SI,OFFSET LPT1_CTRL ; Setup pointer to control structure.
MOV AX,[SI].TBUF_SIZE ; Get the size of the x-mit buffer.
SUB AX,[SI].SIZE_TDATA ; Subtract the number of bytes used.
JE L24 ; No more free space.
MOV ES,[SI].TBUF_SEG ; Get transmit buffer segment number.
MOV DI,[SI].TBUF_OFF ; Get transmit buffer offset.
MOV BX,[SI].END_TDATA ; BX points to free space.
MOV AL,OCHAR ; Move data from stack to x-mit buffer.
MOV ES:[BX+DI],AL
INC BX ; Increment END_TDATA to point to free space.
CMP BX,[SI].TBUF_SIZE ; See if past end.
JB L20 ; If not then skip.
XOR BX,BX ; Adjust to beginning.
L20: MOV [SI].END_TDATA,BX ; Save new END_TDATA.
INC [SI].SIZE_TDATA ; One more character in x-mit buffer.
MOV DX,[SI].LPTX_BASE ; Prepare to manipulate printer interrupts.
ADD DX,CMDREG ; Point to printer command register.
IN AL,DX ; Read command register.
TEST AL,IRQE ; Are printer interrupts enabled?
JNZ L22 ; Yes, so output is active.
MOV AL,(IRQE+SELECT+INIT) ; No, so enable printer interrupts.
OUT DX,AL ;
INT (LPT_INT+INT_OFF) ; Request an interrupt to start output.
L22:
MOV AX,TRUE ; Indicate all's OK.
JMP SHORT L26 ; Go join common return code.
L24: MOV AX,FALSE ; No more space in buffer.
L26: BEND LPT_PUTC
.SBHED <LPT_STAT -- Return Line Printer Hardware Status>
; int /* Returns printer status bits. */
; lpt_stat(unit) /* Reads printer hardware status. */
; int unit; /* 1 ==> LPT1:, 2 ==> LPT2:. */
BENTRY LPT_STAT <UNIT>
MOV SI,OFFSET LPT1_CTRL ; Setup pointer to control structure.
MOV DX,[SI].LPTX_BASE ; Get LPT: base register.
ADD DX,STATREG ; Point to status bits.
IN AL,DX ; Read the status bits.
XOR AH,AH ; Clear high bits.
; Return result in AX.
BEND LPT_STAT
ENDPS
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -