; ; 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