FreeDOS/kernel/console.asm

313 lines
10 KiB
NASM

;
; File:
; console.asm
; Description:
; Console device driver
;
; Copyright (c) 1998
; Pasquale J. Villani
; All Rights Reserved
;
; This file is part of DOS-C.
;
; DOS-C is free software; you can redistribute it and/or
; modify it under the terms of the GNU General Public License
; as published by the Free Software Foundation; either version
; 2, or (at your option) any later version.
;
; DOS-C is distributed in the hope that it will be useful, but
; WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
; the GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public
; License along with DOS-C; see the file COPYING. If not,
; write to the Free Software Foundation, 675 Mass Ave,
; Cambridge, MA 02139, USA.
;
; $Header$
;
%include "io.inc"
segment _IO_FIXED_DATA
global ConTable
ConTable db 0Ah
dw ConInit
dw _IOExit
dw _IOExit
dw _IOCommandError
dw ConRead
dw CommonNdRdExit
dw CommonNdRdExit
dw ConInpFlush
dw ConWrite
dw ConWrite
dw _IOExit
CTL_PRT_SCREEN equ 7200h
CTL_P equ 10h
segment _LOWTEXT
uScanCode db 0 ; Scan code for con: device
global _kbdType
_kbdType db 0 ; 00 for 84key, 10h for 102key
%IFDEF DEBUG_PRINT_COMPORT
ASYNC_NEED_INIT db 1
%ENDIF
global ConInit
ConInit:
xor ax,ax
mov ds,ax
mov al,[496h]
and al,10h
mov byte[cs:_kbdType],al ; enhanced keyboard if bit 4 set
jmp _IOExit
;
; Name:
; ConRead
;
; Function:
; Read to address in es:di characters from the keyboard. Cx contains
; a count of how many characters are to be transferred.
;
; Description:
; Calls KbdRdChar to read the characters. Destroys ax.
;
global ConRead
ConRead:
jcxz ConRead2 ; Exit if read of zero
ConRead1:
call KbdRdChar ; Get a char from kbd in al
stosb ; Store al to es:[di]
loop ConRead1 ; Loop until all are read
ConRead2:
jmp _IOExit
readkey:
mov ah,[cs:_kbdType]
int 16h
checke0: cmp al,0xe0 ; must check for 0xe0 scan code
jne .ret
or ah,ah ; check for Greek alpha
jz .ret
mov al,0 ; otherwise destroy the 0xe0
.ret: retn
;
; Name:
; KbdRdChar
;
; Function:
; Read a character from the keyboard.
;
; Description:
; This subroutine reads a character from the keyboard. It also handles
; a couple of special functions.
; It converts ctrl-printscreen to a control-P.
; It also accounts for extended scan codes by saving off
; the high byte of the return and returning it if it was non-zero on
; the previous read.
;
global KbdRdChar
KbdRdChar:
xor ax,ax ; Zero the scratch register
xchg [cs:uScanCode],al ; and swap with scan code
; now AL is set if previous key was extended,
; and previous is erased in any case
or al,al ; Test to see if it was set
jnz KbdRdRtn ; Exit if it was, returning it
call readkey ; get keybd char in al, ah=scan
or ax,ax ; Zero ?
jz KbdRdChar ; Loop if it is
cmp ax,CTL_PRT_SCREEN ; Ctrl-Print screen?
jne KbdRd1 ; Nope, keep going
mov al,CTL_P ; Yep, make it ^P
KbdRd1:
or al,al ; Extended key?
jnz KbdRdRtn ; Nope, just exit
mov [cs:uScanCode],ah ; Yep, save the scan code
KbdRdRtn:
retn
;
; Name:
; CommonNdRdExit
;
; Function:
; Checks the keyboard input buffer.
;
; Description:
; Calls int 16 (get status). Sets Busy-Flag in status field. Destroys ax.
;
global CommonNdRdExit
CommonNdRdExit: ; *** tell if key waiting and return its ASCII if yes
mov al,[cs:uScanCode] ; Test for last scan code
; now AL is set if previous key was extended,
or al,al ; Was it zero ?
jnz ConNdRd2 ; Jump if there's a char waiting
mov ah,1
add ah,[cs:_kbdType]
int 16h ; Get status, if zf=0 al=char
jz ConNdRd4 ; Jump if no char available
or ax,ax ; Also check for ax=0 as apparently some
jz ConNdRd4 ; int16h handlers set ax=0 to indicate unsupported function
call checke0 ; check for e0 scancode
or ax,ax ; Zero ?
jnz ConNdRd1 ; Jump if not zero
call readkey
jmp short CommonNdRdExit
; if char was there but 0, fetch and retry...
; (why do we check uScanCode here?)
ConNdRd1:
cmp ax,CTL_PRT_SCREEN ; Was ctl+prntscrn key pressed?
jne ConNdRd2 ; Jump if not
mov al,CTL_P
ConNdRd2:
lds bx,[cs:_ReqPktPtr] ; Set the status
cmp byte[bx+2],6 ; input status call?
je ConNdRd3
mov [bx+0Dh],al ; return the ASCII of that key
ConNdRd3:
jmp _IOExit
ConNdRd4:
jmp _IODone
global ConInpFlush
ConInpFlush: ; *** flush that keyboard queue
call KbdInpChar ; get all available keys
jmp _IOExit ; do not even remember the last one
KbdInpChar: ; *** get ??00 or the last waiting key after flushing the queue
xor ax,ax
mov byte [cs:uScanCode],al
KbdInpCh1:
mov ah,1
add ah,[cs:_kbdType]
int 16h ; get status, if zf=0 al=char
jz KbdInpRtnZero ; Jump if zero
; returns 0 or the last key that was waiting in AL
call readkey
jmp short KbdInpCh1
; just read any key that is waiting, then check if
; more keys are waiting. if not, return AL of this
; key (which is its ASCII). AH (scan) discarded!
KbdInpRtnZero: mov ah,1 ; if anybody wants "1 if no key was waiting"!
KbdInpRtn:
retn
global ConWrite
ConWrite:
jcxz ConNdRd3 ; Exit if nothing to write
ConWr1:
mov al,[es:di]
inc di
int 29h ; Do fast output call
loop ConWr1 ; Loop if more to output
jmp _IOExit
CBreak:
mov byte [cs:uScanCode],3 ; Put a ^C into the buffer
IntRetn:
iret
; global _cso
;_cso
; push bp
; mov bp,sp
; push ax
; mov ax,[bp+4]
; int 29h
; pop ax
; pop bp
; retn
global _int29_handler
_int29_handler:
push ax
push si
push di
push bp
push bx
%IFDEF DEBUG_PRINT_COMPORT
cmp bx, 0xFD05 ; magic value for COM print routine
je .comprint
%ENDIF
mov ah,0Eh
mov bx,7
int 10h ; write char al, teletype mode
.int29hndlr_ret:
pop bx
pop bp
pop di
pop si
pop ax
iret
%IFDEF DEBUG_PRINT_COMPORT
%ifnum DEBUG_PRINT_COMPORT
%define DEBUG_USE_COMPORT DEBUG_PRINT_COMPORT
%else
%define DEBUG_USE_COMPORT 1 ; default to COM2 if not specified
%endif
.comprint:
push dx
mov dx, DEBUG_USE_COMPORT ; 0=COM1,1=COM2,2=COM3,3=COM4
mov ah, [cs:ASYNC_NEED_INIT]
or ah,ah
jz .skip_init
push ax ; preserve char (AL) to print
; initialize serial port using BIOS to DOS default
; of 2400 bps, 8 data bits, 1 stop bit, and no parity
mov ax, 0x00A3
int 14h ; BIOS initialize serial port
mov ax, 0x011B ; clear the remote screen (ESC[2J)
int 14h ; BIOS write character to serial port
mov ax, 0x015B ; '['
int 14h ; BIOS write character to serial port
mov ax, 0x0132 ; '2'
int 14h ; BIOS write character to serial port
mov ax, 0x014A ; 'J'
int 14h ; BIOS write character to serial port
; mark initialization complete
mov byte [cs:ASYNC_NEED_INIT], 0
pop ax ; restore char to print
.skip_init:
cmp al, 0x0A ; do we need to add a carriage return?
jne .print_it
mov ax, 0x010D ; print as \r\n
int 14h
mov al, 0x0A
.print_it:
mov ah, 0x01
int 14h ; BIOS write character to serial port
pop dx
jmp .int29hndlr_ret
%ENDIF ; DEBUG_PRINT_COMPORT