/*
 * kbdio.S86  -  keyboard I/O routines for netboot boot images
 *
 * Copyright (C) 2003-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  This program 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 of the License, or
 *  any later version.
 *
 *  This program 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 this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: kbdio.S86,v 1.5 2007/01/06 18:30:51 gkminix Exp $
 *
 *====================================================================
 */


#include <common.i86>
#include <system/bios.i86>

.file __FILE__
.line __LINE__



/*
 *====================================================================
 *
 * Some definitions which are local to this module
 */


/*
 * Flags to define the keyboard functionality
 */

#define KBD_INIT	0b00000001	/* set if functionality determined */
#define KBD_ENHANCED	0b00010000	/* set if enhanced keyboard */
#define KBD_EXTENDED	0b00100000	/* set if extended keyboard */
#define KBD_FLAGMASK	0b00110000	/* flag mask */




.line __LINE__
/*
 *====================================================================
 *
 * Start the text segment and define all public entry points
 */

	.text

	.extern	set_timeout		# define external symbols
	.extern	chk_timeout

	.global	keyget			# define global symbols
	.global	keycheck
	.global	keywait



/*
 *====================================================================
 *
 * Wait for the user to press a key
 * Input:  none
 * Output: AL    -  ASCII character of pressed key
 *         AH    -  Scan code of pressed key
 * Changed registers: AX
 */
keyget:	xor	ah,ah
	call	chkfunc			# check keyboard functionality
	int	INT_KBD			# use the BIOS to wait for the key
	ret



/*
 *====================================================================
 *
 * Check if the user pressed a key. This routine will then destroy the
 * key code from the input buffer.
 * Input:  none
 * Output: AL    -  ASCII character of pressed key
 *         AH    -  Scan code of pressed key
 *         Carry flag set if no key pressed
 * Changed registers: AX
 */
keycheck:

	mov	ah,0x01
	call	chkfunc			# check keyboard functionality
	int	INT_KBD			# use BIOS to check for key press
	mov	ax,-1
	stc
	jz	9f			# set carry flag correctly
	call	keyget			# get keystroke from input buffer
	clc
9:	ret



/*
 *====================================================================
 *
 * Wait for a certain time for a key press
 * Input:  AX    -  Number of seconds to wait
 * Output: AL    -  ASCII character of pressed key
 *         AH    -  Scan code of pressed key
 *         Carry flag set if no key pressed
 * Changed registers: AX
 */
keywait:

	or	ax,ax			# check if to wait forever
	jz	keyget
	call	set_timeout		# set timeout value
1:	call	keycheck		# check if we got a key
	jnc	9f
	call	chk_timeout		# check if we timed out
	jnc	1b
	mov	ax,-1			# return timeout reached
9:	ret



/*
 *====================================================================
 *
 * Determine keyboard functionality
 * Input:  AH    -  Keyboard function code
 * Output: AL    -  Keyboard functionality flags
 *         AH    -  Keyboard function code according to functionality
 * Changed registers: AX
 */
chkfunc:

	mov	al,[kbdfunc]
	test	al,KBD_INIT		# check if already initialized
	jnz	9f

	push	es
	push	bx
	push	dx
	push	ax
	xor	dl,dl
	mov	ah,0xC0			# ask BIOS if the functionality
	int	INT_MISC		# check if supported at all
	jc	8f
	or	ah,ah
	jnz	8f
	test	byte ptr es:[bx + 6],0x40
	jz	8f			# check if Int 0x16, Func 09 supported

	mov	ah,0x09
	int	INT_KBD			# ask BIOS about functionality
	test	al,0x20
	jz	1f
	or	dl,KBD_ENHANCED		# check for enhanced keyboard
1:	test	al,0x40
	jz	8f
	or	dl,KBD_EXTENDED		# check for extended keyboard

8:	pop	ax
	or	dl,KBD_INIT		# set initialized flag
	mov	[kbdfunc],dl
	mov	al,dl			# return flags in AL
	pop	dx
	pop	bx
	pop	es
9:	and	ax,0x0F00 + KBD_FLAGMASK
	or	ah,al
	ret




/*
 *====================================================================
 *
 * Variable definitions
 */
	.bss

	.lcomm	kbdfunc,1		# keyboard functionality




/*
 *====================================================================
 */
	.end

