mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3241 lines
84 KiB
3241 lines
84 KiB
#include "insignia.h"
|
|
#include "host_def.h"
|
|
/*
|
|
* SoftPC Version 2.0
|
|
*
|
|
* Title: keyba.c
|
|
*
|
|
* Description: AT keyboard Adaptor I/O functions.
|
|
*
|
|
* kbd_inb(port,val)
|
|
* int port;
|
|
* half_word *val;
|
|
* provides the next scan code from the
|
|
* keyboard controller (8042), or the
|
|
* status byte of the controller, depending
|
|
* on the port accessed.
|
|
* kbd_outb(port,val)
|
|
* int port;
|
|
* half_word val;
|
|
* Sends a byte to the controller or the
|
|
* keyboard processor (6805), depending on
|
|
* the port accessed.
|
|
* AT_kbd_init()
|
|
* Performs any initialisation of the
|
|
* keyboard code necessary.
|
|
*
|
|
* The system presents an interface to the host environment
|
|
* which is provided with the calls:
|
|
*
|
|
* host_key_down(key)
|
|
* int key;
|
|
* host_key_up(key)
|
|
* int key;
|
|
*
|
|
* These routines provide the keyboard code with information
|
|
* on the events which occur on the host keyboard. The key codes
|
|
* are the key numbers as given in the XT286 Technical Manual.
|
|
*
|
|
* Author: William Charnell
|
|
*
|
|
* Notes:
|
|
*
|
|
*/
|
|
|
|
|
|
#ifdef SCCSID
|
|
static char SccsID[]="@(#)keyba.c 1.57 06/22/95 Copyright Insignia Solutions Ltd.";
|
|
#endif
|
|
|
|
#ifdef SEGMENTATION
|
|
/*
|
|
* The following #include specifies the code segment into which this
|
|
* module will by placed by the MPW C compiler on the Mac II running
|
|
* MultiFinder.
|
|
*/
|
|
#include "SOFTPC_PPI.seg"
|
|
#endif
|
|
|
|
|
|
/*
|
|
* O/S include files.
|
|
*/
|
|
#include <stdio.h>
|
|
#include TypesH
|
|
#include TimeH
|
|
|
|
/*
|
|
* SoftPC include files
|
|
*/
|
|
#include "xt.h"
|
|
#include CpuH
|
|
#include "sas.h"
|
|
#include "ios.h"
|
|
#include "ppi.h"
|
|
#include "timeval.h"
|
|
#include "timer.h"
|
|
#include "keyboard.h"
|
|
#include "error.h"
|
|
#include "config.h"
|
|
#include "ica.h"
|
|
#include "keyba.h"
|
|
#include "quick_ev.h"
|
|
#ifdef macintosh
|
|
#include "ckmalloc.h"
|
|
#endif /* macintosh */
|
|
|
|
#include "debug.h"
|
|
|
|
|
|
/* <tur 12-Jul-93> BCN 2040
|
|
** KBD_CONT_DELAY is the delay time for continuing keyboard interrupts
|
|
** when a "sloppy" read of port 0x60 occurs while the keyboard interface
|
|
** is enabled. It's the "delay" parameter to add_q_event_t(), and is
|
|
** measured in microseconds.
|
|
** Perhaps this should be settable in the host; I've allowed for that here
|
|
** by defining the delay to be 7 milliseconds unless it's already defined.
|
|
** See comments in kbd_inb() below for more details.
|
|
*/
|
|
|
|
#ifndef KBD_CONT_DELAY
|
|
#define KBD_CONT_DELAY 7000 /* microseconds */
|
|
#endif /* KBD_CONT_DELAY */
|
|
|
|
|
|
#ifdef NTVDM
|
|
#include "idetect.h"
|
|
#include "nt_eoi.h"
|
|
|
|
/* exported for NT host event code */
|
|
GLOBAL VOID KbdResume(VOID);
|
|
GLOBAL BOOL bPifFastPaste=TRUE;
|
|
|
|
|
|
/* imported from NT host code */
|
|
IMPORT ULONG WaitKbdHdw(ULONG dwTimeOut);
|
|
IMPORT ULONG KbdHdwFull;
|
|
|
|
IMPORT VOID HostReleaseKbd(VOID);
|
|
|
|
/* imported from keybd_io.c */
|
|
IMPORT int bios_buffer_size(void);
|
|
|
|
IMPORT BOOL bBiosOwnsKbdHdw; // our kbd bios code owns the Keyboard Mutex
|
|
word KbdInt09Seg;
|
|
word KbdInt09Off;
|
|
|
|
#undef LOCAL
|
|
#define LOCAL
|
|
|
|
// local state variables for kbd interrupt regulation
|
|
VOID KbdIntDelay(VOID);
|
|
BOOL bBiosBufferSpace = TRUE;
|
|
BOOL bKbdIntHooked = FALSE;
|
|
char KbdData = -1;
|
|
BOOL bKbdEoiPending = TRUE; // Kbd interrupts blocked until KbdResume invoked
|
|
BOOL bDelayIntPending = FALSE;
|
|
BOOL bForceDelayInts = FALSE;
|
|
ULONG LastKbdInt=0;
|
|
|
|
// The Brazilian ABNT keyboard has 104 keys, 2 more than 'usual'
|
|
//
|
|
// Key Number Set 1 Set 2 Set 3 Character
|
|
// ---------- ------ ------- ------- ---------------
|
|
// 56 0x73 0x51 0x51 NumPad .
|
|
// 107 0x7E 0x6D 0x7B / ? Degree Sign
|
|
//
|
|
// See also ..\..\host\src\nt_keycd.c and
|
|
// ..\..\..\dos\v86\cmd\keyb\keybi9c.asm
|
|
//
|
|
#define BRAZILIAN_ABNT_KBD
|
|
|
|
#endif /* NTVDM */
|
|
|
|
|
|
|
|
#define NUM_LOCK_ADD_ARRAY 127
|
|
#define L_SHIFT_ADD_ARRAY 128
|
|
#define R_SHIFT_ADD_ARRAY 129
|
|
#define CASE_4_SHIFTED_ARRAY 130
|
|
#define ALT_CASE_4_ARRAY 131
|
|
#define CASE_5_CTRLED_ARRAY 132
|
|
|
|
#define NUM_LOCK_ADD 7
|
|
#define L_SHIFT_ADD 8
|
|
#define R_SHIFT_ADD 9
|
|
#define CASE_4_SHIFTED 10
|
|
#define ALT_CASE_4 11
|
|
#define CASE_5_CTRLED 12
|
|
|
|
#define KEYBOARD_INT_ADAPTER 0
|
|
#define KEYBOARD_INT_LINE 1
|
|
#define BASE_DELAY_UNIT 5
|
|
#define DEFAULT_REPEAT_TARGET 1
|
|
|
|
#define SET_3_KEY_TYPE_SET_SEQUENCE 1
|
|
#define SET_STATUS_INDICATORS_SEQUENCE 2
|
|
#define SET_RATE_DELAY_SEQUENCE 3
|
|
#define SCAN_CODE_CHANGE_SEQUENCE 4
|
|
|
|
#define WRITE_8042_CMD_BYTE_SEQUENCE 1
|
|
#define WRITE_8042_OUTPUT_PORT_SEQUENCE 2
|
|
|
|
#define KEY_DOWN_EVENT 1
|
|
#define KEY_UP_EVENT 2
|
|
|
|
#define DEFAULT_SCAN_CODE_SET 2
|
|
|
|
#ifdef REAL_KBD
|
|
extern void send_to_real_kbd();
|
|
extern void wait_for_ack_from_kb();
|
|
#endif
|
|
|
|
/*
|
|
* Globally available function pointers
|
|
*/
|
|
GLOBAL VOID ( *host_key_down_fn_ptr )();
|
|
GLOBAL VOID ( *host_key_up_fn_ptr )();
|
|
|
|
#ifndef NTVDM
|
|
GLOBAL VOID ( *do_key_repeats_fn_ptr )();
|
|
#endif /* NTVDM */
|
|
|
|
/*
|
|
* 6805 code buffer:
|
|
*
|
|
* This is a cyclic buffer storing key events that have been accepted from
|
|
* the host operating system, but not yet requested by the keyboard BIOS.
|
|
*
|
|
* It is equivalent to a 16 byte buffer present in the real keyboard hardware
|
|
* on the PC-AT.
|
|
*
|
|
* We make the physical size of the buffer BUFF_6805_PMAX a power of 2
|
|
* so that a mask BUFF_6805_PMASK can be used to wrap array indices quickly.
|
|
*
|
|
* Each character entered at the keyboard results in at least 3 bytes of
|
|
* event data in the keyboard buffer. Thus the PC-AT's 16 byte buffer allows
|
|
* at most 5 characters to be typed ahead. In practice this is never used
|
|
* as the CPU is always active, allowing character data to be moved almost
|
|
* immediately to the BIOS type ahead buffer.
|
|
*
|
|
* On SoftPC, however, the CPU can become inactive for significant periods;
|
|
* at the same time, the keyboard hardware emulation may be forced to
|
|
* process a large number of keyboard events from the host operating system.
|
|
*
|
|
* In order to give a constant amount of type ahead, regardless of where the
|
|
* type ahead information is stored in SoftPC, we make the virtual size
|
|
* of the hardware buffer BUFF_6805_VMAX 48 bytes long (16 characters X
|
|
* 3 bytes of event data per character).
|
|
*/
|
|
|
|
/*
|
|
18.5.92 MG !!! TEMPORARY HACK !!! To fix windows bugs in Notepad and Word,
|
|
set the buffer to 2k. Windows crashes when the keyboard buffer overflows,
|
|
so we delay this for as long as sensible. It will still crash if you type
|
|
too fast for too long.
|
|
|
|
It works OK on a real PC, so the real reason it fails on SoftPC needs to
|
|
be determined one day.
|
|
|
|
20.5.92 MG - took out the hack - see below.
|
|
*/
|
|
|
|
#ifdef NTVDM /* JonLe NT Mod */
|
|
#define BUFF_6805_VMAX 496
|
|
#define BUFF_6805_PMAX 512
|
|
#define BUFF_6805_PMASK (BUFF_6805_PMAX - 1)
|
|
#else
|
|
#define BUFF_6805_VMAX 48
|
|
#define BUFF_6805_PMAX 64
|
|
#define BUFF_6805_PMASK (BUFF_6805_PMAX - 1)
|
|
#endif /* NTVDM */
|
|
|
|
#ifndef macintosh
|
|
static half_word buff_6805[BUFF_6805_PMAX];
|
|
#else
|
|
static half_word *buff_6805=NULL;
|
|
#endif /* macintosh */
|
|
static int buff_6805_in_ptr,buff_6805_out_ptr;
|
|
|
|
#ifdef NTVDM
|
|
static unsigned char key_marker_value = 0;
|
|
static unsigned char key_marker_buffer[BUFF_6805_PMAX];
|
|
int LastKeyDown= -1;
|
|
void Reset6805and8042(void);
|
|
#endif
|
|
|
|
#if defined(IRET_HOOKS) && defined(GISP_CPU)
|
|
extern IBOOL HostDelayKbdInt IPT1(char, scancode);
|
|
extern IBOOL HostPendingKbdInt IPT1(char *,scancode);
|
|
extern void HostResetKdbInts IPT0();
|
|
|
|
#endif /* IRET_HOOKS && GISP_CPU */
|
|
|
|
/*
|
|
20.5.92 MG
|
|
|
|
Real fix for my temporary hack in the last edition of this file.
|
|
|
|
The problem with windows seems to be due to receipt of a huge
|
|
number of overrun characters in a row, so now when we send an overrun
|
|
character we set an 'overrun enable' flag, which is cleared when
|
|
three bytes have been read from the buffer.
|
|
|
|
The effect of this is to spread out the overruns, which seems to stop
|
|
the illegal instructions occuring.
|
|
|
|
Obviously this may have bad effects on real-mode DOS applications !!!
|
|
*/
|
|
|
|
LOCAL BOOL sent_overrun=FALSE;
|
|
|
|
#ifndef macintosh
|
|
|
|
#ifndef REAL_KBD
|
|
/* make arrays */
|
|
static int *make_sizes;
|
|
static half_word *make_arrays [134];
|
|
|
|
/* break arrays */
|
|
static int *break_sizes;
|
|
static half_word *break_arrays [134];
|
|
|
|
/* set 3 key states (eg. typematic, make/break, make only, typematic make/break) */
|
|
|
|
static half_word set_3_key_state [127];
|
|
#endif /* REAL_KBD */
|
|
|
|
static int key_down_count [127];
|
|
|
|
#else /* macintosh */
|
|
/* make arrays */
|
|
static int *make_sizes;
|
|
static half_word **make_arrays;
|
|
|
|
/* break arrays */
|
|
static int *break_sizes;
|
|
static half_word **break_arrays;
|
|
|
|
/* set 3 key states (eg. typematic, make/break, make only, typematic make/break) */
|
|
|
|
static half_word *set_3_key_state;
|
|
static int *key_down_count;
|
|
|
|
#endif /* macintosh */
|
|
|
|
/* anomalous state handling variables */
|
|
half_word *anomalous_array;
|
|
int anomalous_size, anom_key;
|
|
int in_anomalous_state;
|
|
|
|
/* held events (while doing multiple code 6805 commands) */
|
|
#define HELD_EVENT_MAX 16
|
|
int held_event_count;
|
|
int held_event_key[HELD_EVENT_MAX];
|
|
int held_event_type[HELD_EVENT_MAX];
|
|
|
|
#ifdef NTVDM /* JonLe NTVDM Mod:remove repeat related vars */
|
|
int scan_code_6805_size,key_set;
|
|
int input_port_val;
|
|
int waiting_for_next_code, waiting_for_next_8042_code, num_lock_on;
|
|
#else
|
|
int scan_code_6805_size,key_set,repeat_delay_target,repeat_target,repeat_delay_count,repeat_count;
|
|
int typematic_key, input_port_val;
|
|
int typematic_key_valid,waiting_for_next_code, waiting_for_next_8042_code, num_lock_on;
|
|
#endif /* NTVDM */
|
|
int shift_on, l_shift_on, r_shift_on;
|
|
int ctrl_on, l_ctrl_on, r_ctrl_on;
|
|
int alt_on, l_alt_on, r_alt_on;
|
|
int waiting_for_upcode;
|
|
int next_code_sequence_number, next_8042_code_sequence_number, set_3_key_type_change_dest;
|
|
GLOBAL int free_6805_buff_size; /* Must be global for NT VDM */
|
|
int translating, keyboard_disabled, int_enabled, output_full;
|
|
int pending_8042, keyboard_interface_disabled, scanning_discontinued;
|
|
half_word output_contents, pending_8042_value, kbd_status, op_port_remembered_bits, cmd_byte_8042;
|
|
half_word *scan_code_6805_array;
|
|
|
|
#ifdef PM
|
|
int gate_a20_status;
|
|
#ifndef NTVDM
|
|
long reset_was_by_kbd = FALSE;
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef NTVDM
|
|
LOCAL q_ev_handle refillDelayedHandle = 0;
|
|
#endif
|
|
|
|
half_word current_light_pattern;
|
|
|
|
#ifdef macintosh
|
|
/*
|
|
** The Mac cannot cope with loads of global data. So declare these
|
|
** as pointers and load the tables up from a Mac resource.
|
|
*/
|
|
half_word *scan_codes_temp_area;
|
|
half_word *keytypes;
|
|
int *set_1_make_sizes, *set_2_make_sizes, *set_3_make_sizes;
|
|
int *set_1_break_sizes, *set_2_break_sizes, *set_3_break_sizes;
|
|
half_word *trans_8042, *set_3_reverse_lookup, *set_3_default_key_state, *most_set_2_make_codes;
|
|
half_word *most_set_3_make_codes, *set_1_extra_codes, *set_2_extra_codes, *set_3_extra_codes;
|
|
half_word *set_1_extra_bk_codes, *set_2_extra_bk_codes, *set_3_extra_bk_codes, *buff_overrun_6805;
|
|
half_word *most_set_1_make_codes;
|
|
|
|
#else
|
|
|
|
half_word scan_codes_temp_area[300];
|
|
|
|
#ifndef REAL_KBD
|
|
/* Data Tables */
|
|
|
|
/*
|
|
* The meaning of the keytype values as far as I can tell (IanJa) :
|
|
*
|
|
* 1 = extended key (rh Alt, rh Ctrl, Numpad Enter)
|
|
* 2 = grey cursor movement keys (Insert, Home, Delete, up arrow etc.
|
|
* 3 = NumPad /
|
|
* 4 = Print Screen/SysRq
|
|
* 5 = pause/Break
|
|
* 6 = not a key
|
|
*/
|
|
static half_word keytypes[127] =
|
|
{ 0,0,0,0,0,0,0,0,0,0, /* 0-9 */
|
|
0,0,0,0,6,0,0,0,0,0, /* 10-19 */
|
|
0,0,0,0,0,0,0,0,0,0, /* 20-29 */
|
|
0,0,0,0,0,0,0,0,0,0, /* 30-39 */
|
|
0,0,0,0,0,0,0,0,0,0, /* 40-49 */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0,0,0,0,0,0,0,0,0,6, /* 50-59 */
|
|
#else
|
|
0,0,0,0,0,0,6,0,0,6, /* 50-59 */
|
|
#endif
|
|
0,0,1,6,1,6,6,6,6,6, /* 60-69 */
|
|
6,6,6,6,6,2,2,6,6,2, /* 70-79 */
|
|
2,2,6,2,2,2,2,6,6,2, /* 80-89 */
|
|
0,0,0,0,6,3,0,0,0,0, /* 90-99 */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0,0,0,0,0,0,0,0,1,6, /* 100-109 */
|
|
#else
|
|
0,0,0,0,0,0,0,6,1,6, /* 100-109 */
|
|
#endif
|
|
0,6,0,0,0,0,0,0,0,0, /* 110-119 */
|
|
0,0,0,0,4,0,5 /* 120-126 */
|
|
};
|
|
|
|
static int set_1_make_sizes [13]=
|
|
{ 1,2,2,2,4,6, /* categories 1 to 6 inclusive */
|
|
0, /* size for error case - non existant key */
|
|
2, /* Num lock add size */
|
|
2, /* Left shift add size */
|
|
2, /* Right shift add size */
|
|
2, /* Case 4 shifted size */
|
|
1, /* Alt Case 4 size */
|
|
4 /* Case 5 ctrled size */
|
|
};
|
|
|
|
static int set_2_make_sizes [13]=
|
|
{ 1,2,2,2,4,8, /* categories 1 to 6 inclusive */
|
|
0, /* size for error case - non existant key */
|
|
2, /* Num lock add size */
|
|
3, /* Left shift add size */
|
|
3, /* Right shift add size */
|
|
2, /* Case 4 shifted size */
|
|
1, /* Alt Case 4 size */
|
|
5 /* Case 5 ctrled size */
|
|
};
|
|
|
|
static int set_3_make_sizes [13]=
|
|
{ 1,1,1,1,1,1, /* categories 1 to 6 inclusive */
|
|
0, /* size for error case - non existant key */
|
|
0, /* Num lock add size */
|
|
0, /* Left shift add size */
|
|
0, /* Right shift add size */
|
|
1, /* Case 4 shifted size */
|
|
1, /* Alt Case 4 size */
|
|
1 /* Case 5 ctrled size */
|
|
};
|
|
|
|
static int set_1_break_sizes [13]=
|
|
{ 1,2,2,2,4,0, /* categories 1 to 6 inclusive */
|
|
0, /* size for error case - non existant key */
|
|
2, /* Num lock add size */
|
|
2, /* Left shift add size */
|
|
2, /* Right shift add size */
|
|
2, /* Case 4 shifted size */
|
|
1, /* Alt Case 4 size */
|
|
0 /* Case 5 ctrled size */
|
|
};
|
|
|
|
static int set_2_break_sizes [13]=
|
|
{ 2,3,3,3,6,0, /* categories 1 to 6 inclusive */
|
|
0, /* size for error case - non existant key */
|
|
3, /* Num lock add size */
|
|
2, /* Left shift add size */
|
|
2, /* Right shift add size */
|
|
3, /* Case 4 shifted size */
|
|
2, /* Alt Case 4 size */
|
|
0 /* Case 5 ctrled size */
|
|
};
|
|
|
|
static int set_3_break_sizes [13]=
|
|
{ 2,2,2,2,2,0, /* categories 1 to 6 inclusive */
|
|
0, /* size for error case - non existant key */
|
|
0, /* Num lock add size */
|
|
0, /* Left shift add size */
|
|
0, /* Right shift add size */
|
|
2, /* Case 4 shifted size */
|
|
2, /* Alt Case 4 size */
|
|
2 /* Case 5 ctrled size */
|
|
};
|
|
|
|
#endif
|
|
|
|
static half_word trans_8042 [256] =
|
|
{ 0xff,0x43,0x02,0x3f,0x3d,0x3b,0x3c,0x58,0x08,0x44,0x42,0x40,0x3e,0x0f,0x29,0x0f, /* 00-0f */
|
|
0x10,0x38,0x2a,0x13,0x1d,0x10,0x02,0x17,0x18,0x19,0x2c,0x1f,0x1e,0x11,0x03,0x1f, /* 10-1f */
|
|
0x20,0x2e,0x2d,0x20,0x12,0x05,0x04,0x27,0x28,0x39,0x2f,0x21,0x14,0x13,0x06,0x2f, /* 20-2f */
|
|
0x30,0x31,0x30,0x23,0x22,0x15,0x07,0x37,0x38,0x39,0x32,0x24,0x16,0x08,0x09,0x3f, /* 30-3f */
|
|
0x40,0x33,0x25,0x17,0x18,0x0b,0x0a,0x47,0x48,0x34,0x35,0x26,0x27,0x19,0x0c,0x4f, /* 40-4f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x50,0x73,0x28,0x53,0x1a,0x0d,0x56,0x57,0x3a,0x36,0x1c,0x1b,0x5c,0x2b,0x5e,0x5f, /* 50-5f */
|
|
0x60,0x56,0x62,0x63,0x64,0x65,0x0e,0x67,0x68,0x4f,0x6a,0x4b,0x47,0x7e,0x6e,0x6f, /* 60-6f */
|
|
#else
|
|
0x50,0x51,0x28,0x53,0x1a,0x0d,0x56,0x57,0x3a,0x36,0x1c,0x1b,0x5c,0x2b,0x5e,0x5f, /* 50-5f */
|
|
0x60,0x56,0x62,0x63,0x64,0x65,0x0e,0x67,0x68,0x4f,0x6a,0x4b,0x47,0x6d,0x6e,0x6f, /* 60-6f */
|
|
#endif
|
|
0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x54, /* 70-7f */
|
|
0x80,0x81,0x82,0x41,0x54,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, /* 80-8f */
|
|
0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, /* 90-9f */
|
|
0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, /* a0-af */
|
|
0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, /* b0-bf */
|
|
0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, /* c0-cf */
|
|
0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, /* d0-df */
|
|
0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, /* e0-ef */
|
|
0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff /* f0-ff */
|
|
};
|
|
|
|
#ifndef REAL_KBD
|
|
static half_word set_3_reverse_lookup [256]=
|
|
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x6e,0x00,0x00,0x00,0x00,0x10,0x01,0x71, /* 00-0f */
|
|
0x00,0x3a,0x2c,0x2d,0x1e,0x11,0x02,0x72,0x00,0x3c,0x2e,0x20,0x1f,0x12,0x03,0x73, /* 10-1f */
|
|
0x00,0x30,0x2f,0x21,0x13,0x05,0x04,0x74,0x00,0x3d,0x31,0x22,0x15,0x14,0x06,0x75, /* 20-2f */
|
|
0x00,0x33,0x32,0x24,0x23,0x16,0x07,0x76,0x00,0x3e,0x34,0x25,0x17,0x08,0x09,0x77, /* 30-3f */
|
|
0x00,0x35,0x26,0x18,0x19,0x0b,0x0a,0x78,0x00,0x36,0x37,0x27,0x28,0x1a,0x0c,0x79, /* 40-4f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x00,0x38,0x29,0x2a,0x1b,0x0d,0x7a,0x7c,0x40,0x39,0x2b,0x1c,0x1d,0x00,0x7b,0x7d, /* 50-5f */
|
|
#else
|
|
0x00,0x00,0x29,0x2a,0x1b,0x0d,0x7a,0x7c,0x40,0x39,0x2b,0x1c,0x1d,0x00,0x7b,0x7d, /* 50-5f */
|
|
#endif
|
|
0x54,0x4f,0x7e,0x53,0x4c,0x51,0x0f,0x4b,0x00,0x5d,0x59,0x5c,0x5b,0x56,0x50,0x55, /* 60-6f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x63,0x68,0x62,0x61,0x66,0x60,0x5a,0x5f,0x00,0x6c,0x67,0x6b,0x6a,0x65,0x64,0x00, /* 70-7f */
|
|
#else
|
|
0x63,0x68,0x62,0x61,0x66,0x60,0x5a,0x5f,0x00,0x6c,0x67,0x00,0x6a,0x65,0x64,0x00, /* 70-7f */
|
|
#endif
|
|
0x00,0x00,0x00,0x00,0x69,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 80-8f */
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 90-9f */
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* a0-af */
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* b0-bf */
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* c0-cf */
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* d0-df */
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* e0-ef */
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 /* f0-ff */
|
|
};
|
|
|
|
static half_word set_3_default_key_state [127]=
|
|
{ 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x01, /* 00-0f */
|
|
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01, /* 10-1f */
|
|
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x01,0x01,0x01, /* 20-2f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x00,0x02,0x01,0x03,0x00, /* 30-3f */
|
|
#else
|
|
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x02,0x02,0x00,0x02,0x01,0x03,0x00, /* 30-3f */
|
|
#endif
|
|
0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x00,0x00,0x01, /* 40-4f */
|
|
0x03,0x03,0x00,0x01,0x01,0x03,0x03,0x00,0x00,0x01,0x03,0x03,0x03,0x03,0x00,0x03, /* 50-5f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x03,0x03,0x00,0x03,0x00, /* 60-6f */
|
|
#else
|
|
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x01,0x00,0x03,0x00,0x03,0x00, /* 60-6f */
|
|
#endif
|
|
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03 /* 70-7d */
|
|
};
|
|
|
|
static half_word most_set_1_make_codes [127]=
|
|
{ 0x00,0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x00,0x0e, /* 00-0f */
|
|
0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x2b,0x3a,0x1e, /* 10-1f */
|
|
0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2b,0x1c,0x2a,0x56,0x2c,0x2d, /* 20-2f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x73,0x36,0x1d,0x00,0x38,0x39,0x38,0x00, /* 30-3f */
|
|
#else
|
|
0x2e,0x2f,0x30,0x31,0x32,0x33,0x34,0x35,0x00,0x36,0x1d,0x00,0x38,0x39,0x38,0x00, /* 30-3f */
|
|
#endif
|
|
0x1d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x53,0x00,0x00,0x4b, /* 40-4f */
|
|
0x47,0x4f,0x00,0x48,0x50,0x49,0x51,0x00,0x00,0x4d,0x45,0x47,0x4b,0x4f,0x00,0x35, /* 50-5f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x48,0x4c,0x50,0x52,0x37,0x49,0x4d,0x51,0x53,0x4a,0x4e,0x7e,0x1c,0x00,0x01,0x00, /* 60-6f */
|
|
#else
|
|
0x48,0x4c,0x50,0x52,0x37,0x49,0x4d,0x51,0x53,0x4a,0x4e,0x00,0x1c,0x00,0x01,0x00, /* 60-6f */
|
|
#endif
|
|
0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x57,0x58,0x00,0x46,0x00 /* 70-7e */
|
|
};
|
|
|
|
static half_word most_set_2_make_codes [127]=
|
|
{ 0x00,0x0e,0x16,0x1e,0x26,0x25,0x2e,0x36,0x3d,0x3e,0x46,0x45,0x4e,0x55,0x00,0x66, /* 00-0f */
|
|
0x0d,0x15,0x1d,0x24,0x2d,0x2c,0x35,0x3c,0x43,0x44,0x4d,0x54,0x5b,0x5d,0x58,0x1c, /* 10-1f */
|
|
0x1b,0x23,0x2b,0x34,0x33,0x3b,0x42,0x4b,0x4c,0x52,0x5d,0x5a,0x12,0x61,0x1a,0x22, /* 20-2f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x21,0x2a,0x32,0x31,0x3a,0x41,0x49,0x4a,0x51,0x59,0x14,0x00,0x11,0x29,0x11,0x00, /* 30-3f */
|
|
#else
|
|
0x21,0x2a,0x32,0x31,0x3a,0x41,0x49,0x4a,0x00,0x59,0x14,0x00,0x11,0x29,0x11,0x00, /* 30-3f */
|
|
#endif
|
|
0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x71,0x00,0x00,0x6b, /* 40-4f */
|
|
0x6c,0x69,0x00,0x75,0x72,0x7d,0x7a,0x00,0x00,0x74,0x77,0x6c,0x6b,0x69,0x00,0x4a, /* 50-5f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x75,0x73,0x72,0x70,0x7c,0x7d,0x74,0x7a,0x71,0x7b,0x79,0x6d,0x5a,0x00,0x76,0x00, /* 60-6f */
|
|
#else
|
|
0x75,0x73,0x72,0x70,0x7c,0x7d,0x74,0x7a,0x71,0x7b,0x79,0x00,0x5a,0x00,0x76,0x00, /* 60-6f */
|
|
#endif
|
|
0x05,0x06,0x04,0x0c,0x03,0x0b,0x83,0x0a,0x01,0x09,0x78,0x07,0x00,0x7e,0x00 /* 70-7e */
|
|
};
|
|
|
|
static half_word most_set_3_make_codes [127]=
|
|
{ 0x00,0x0e,0x16,0x1e,0x26,0x25,0x2e,0x36,0x3d,0x3e,0x46,0x45,0x4e,0x55,0x00,0x66, /* 00-0f */
|
|
0x0d,0x15,0x1d,0x24,0x2d,0x2c,0x35,0x3c,0x43,0x44,0x4d,0x54,0x5b,0x5c,0x14,0x1c, /* 10-1f */
|
|
0x1b,0x23,0x2b,0x34,0x33,0x3b,0x42,0x4b,0x4c,0x52,0x53,0x5a,0x12,0x13,0x1a,0x22, /* 20-2f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x21,0x2a,0x32,0x31,0x3a,0x41,0x49,0x4a,0x51,0x59,0x11,0x00,0x19,0x29,0x39,0x00, /* 30-3f */
|
|
#else
|
|
0x21,0x2a,0x32,0x31,0x3a,0x41,0x49,0x4a,0x00,0x59,0x11,0x00,0x19,0x29,0x39,0x00, /* 30-3f */
|
|
#endif
|
|
0x58,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0x64,0x00,0x00,0x61, /* 40-4f */
|
|
0x6e,0x65,0x00,0x63,0x60,0x6f,0x6d,0x00,0x00,0x6a,0x76,0x6c,0x6b,0x69,0x00,0x77, /* 50-5f */
|
|
#ifdef BRAZILIAN_ABNT_KBD
|
|
0x75,0x73,0x72,0x70,0x7e,0x7d,0x74,0x7a,0x71,0x84,0x7c,0x7b,0x79,0x00,0x08,0x00, /* 60-6f */
|
|
#else
|
|
0x75,0x73,0x72,0x70,0x7e,0x7d,0x74,0x7a,0x71,0x84,0x7c,0x00,0x79,0x00,0x08,0x00, /* 60-6f */
|
|
#endif
|
|
0x07,0x0f,0x17,0x1f,0x27,0x2f,0x37,0x3f,0x47,0x4f,0x56,0x5e,0x57,0x5f,0x62 /* 70-7e */
|
|
};
|
|
|
|
static half_word set_1_extra_codes []=
|
|
{ 0xe0,0x2a,0xe0,0x37, /* Case 4 norm */
|
|
0xe1,0x1d,0x45,0xe1,0x9d,0xc5, /* Case 5 norm */
|
|
/* Error case -non existant (empty) */
|
|
0xe0,0x2a, /* Num lock add sequence */
|
|
0xe0,0xaa, /* Left shift add sequence */
|
|
0xe0,0xb6, /* Right shift add sequence */
|
|
0xe0,0x37, /* case 4 shifted */
|
|
0x54, /* Alt case 4 */
|
|
0xe0,0x46,0xe0,0xc6 /* Case 5 ctrled */
|
|
};
|
|
|
|
static half_word set_2_extra_codes []=
|
|
{ 0xe0,0x12,0xe0,0x7c, /* Case 4 norm */
|
|
0xe1,0x14,0x77,0xe1,0xf0,0x14,0xf0,0x77, /* Case 5 norm */
|
|
/* Error case -non existant (empty) */
|
|
0xe0,0x12, /* Num lock add sequence */
|
|
0xe0,0xf0,0x12, /* Left shift add sequence */
|
|
0xe0,0xf0,0x59, /* Right shift add sequence */
|
|
0xe0,0x7c, /* case 4 shifted */
|
|
0x84, /* Alt case 4 */
|
|
0xe0,0x7e,0xe0,0xf0,0x7e /* Case 5 ctrled */
|
|
};
|
|
|
|
|
|
static half_word set_3_extra_codes []=
|
|
{ 0x57, /* Case 4 norm */
|
|
0x62, /* Case 5 norm */
|
|
/* Error case -non existant (empty) */
|
|
/* Num lock add sequence (empty) */
|
|
/* Left shift add sequence (empty) */
|
|
/* Right shift add sequence (empty) */
|
|
0x57, /* case 4 shifted */
|
|
0x57, /* Alt case 4 */
|
|
0x62 /* Case 5 ctrled */
|
|
};
|
|
|
|
|
|
static half_word set_1_extra_bk_codes []=
|
|
{ 0xe0,0xb7,0xe0,0xaa, /* Case 4 norm */
|
|
/* Case 5 norm (empty) */
|
|
/* Error case -non existant (empty) */
|
|
0xe0,0xaa, /* Num lock add sequence */
|
|
0xe0,0x2a, /* Left shift add sequence */
|
|
0xe0,0x36, /* Right shift add sequence */
|
|
0xe0,0xb7, /* case 4 shifted */
|
|
0xd4, /* Alt case 4 */
|
|
/* Case 5 ctrled (empty) */
|
|
};
|
|
|
|
static half_word set_2_extra_bk_codes []=
|
|
{ 0xe0,0xf0,0x7c,0xe0,0xf0,0x12, /* Case 4 norm */
|
|
/* Case 5 norm (empty) */
|
|
/* Error case -non existant (empty) */
|
|
0xe0,0xf0,0x12, /* Num lock add sequence */
|
|
0xe0,0x12, /* Left shift add sequence */
|
|
0xe0,0x59, /* Right shift add sequence */
|
|
0xe0,0xf0,0x7c, /* case 4 shifted */
|
|
0xf0,0x84 /* Alt case 4 */
|
|
/* Case 5 ctrled (empty) */
|
|
};
|
|
|
|
|
|
static half_word set_3_extra_bk_codes []=
|
|
{ 0xf0,0x57, /* Case 4 norm */
|
|
/* Case 5 norm (empty) */
|
|
/* Error case -non existant (empty) */
|
|
/* Num lock add sequence (empty) */
|
|
/* Left shift add sequence (empty) */
|
|
/* Right shift add sequence (empty) */
|
|
0xf0,0x57, /* case 4 shifted */
|
|
0xf0,0x57, /* Alt case 4 */
|
|
0xf0,0x62 /* Case 5 ctrled */
|
|
};
|
|
#endif
|
|
|
|
static half_word buff_overrun_6805 [4]=
|
|
{
|
|
0,0xff,0,0
|
|
};
|
|
|
|
#endif /* macintosh */
|
|
|
|
#ifdef SECURE /* { */
|
|
/*
|
|
* This table 'secure_keytab' identifies certain characters which
|
|
* need special treatment by Secure SoftWindows. The table is
|
|
* indexed by keycodes, as used by the ROM routine for the U.S. English
|
|
* keyboard. These codes are defined in IBM Personal Computer AT
|
|
* Hardware Technical Reference, Section 5 System BIOS Keyboard
|
|
* Encoding and Usage.
|
|
*
|
|
* Characters requiring special treatment include Ctrl-Alt-DEL,
|
|
* Ctrl-C and the others, including keys which modify the Boot.
|
|
* Such keys require different treatment, but can be grouped into
|
|
* about 4 different ActionClasses.
|
|
* Any key which would generate an undesirable code has the action
|
|
* bit set, along with the ActionClass number. Additionally the
|
|
* modifier keys are also tracked with this table.
|
|
*/
|
|
|
|
#define SEC_ACTCLASS 0x07
|
|
/* Action Classes have to be sequential from 0,
|
|
* as they are used as an index into function
|
|
* tables 'down_class' and 'up_class'
|
|
*/
|
|
#define SEC_CLASS_0 0x00
|
|
#define SEC_CLASS_1 0x01
|
|
#define SEC_CLASS_2 0x02
|
|
#define SEC_CLASS_3 0x03
|
|
#define SEC_CLASS_4 0x04
|
|
#define SEC_CLASS_5 0x05
|
|
#define SEC_CLASS_6 0x06
|
|
#define SEC_CLASS_7 0x07
|
|
#define SEC_ACTION 0x08
|
|
#define SEC_CTRL_L 0x10
|
|
#define SEC_CTRL_R 0x20
|
|
#define SEC_ALT_L 0x40
|
|
#define SEC_ALT_R 0x80
|
|
#define SEC_MOD_MASK (SEC_CTRL_L|SEC_CTRL_R|SEC_ALT_L|SEC_ALT_R)
|
|
|
|
LOCAL IU8 secure_keytab [] = {
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0-15 */
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16-31 */
|
|
0,0,0,0,0,0,0,0,0,0,0,0, /* 32-43 */
|
|
SEC_ACTION|SEC_CLASS_3, /* 44(LShft) Boot Modifier. */
|
|
0,0,0, /* 45-47 */
|
|
SEC_ACTION|SEC_CLASS_2, /* 48("C") Used with Cntrl. */
|
|
0,0,0,0,0,0,0,0, /* 49-56 */
|
|
SEC_ACTION|SEC_CLASS_3, /* 57(RShft) Boot Modifier. */
|
|
SEC_CTRL_L,0,SEC_ALT_L,0, /* 58-61 */
|
|
SEC_ALT_R,0,SEC_CTRL_R, /* 62-64 */
|
|
0,0,0,0,0,0,0,0,0,0,0, /* 65-75 */
|
|
SEC_ACTION|SEC_CLASS_0, /* 76(Delete) */
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 77-90 */
|
|
SEC_ACTION|SEC_CLASS_1, /* 91(KeyPad 7) */
|
|
SEC_ACTION|SEC_CLASS_1, /* 92(KeyPad 4) */
|
|
SEC_ACTION|SEC_CLASS_1, /* 93(KeyPad 1) */
|
|
0,0, /* 94-95 */
|
|
SEC_ACTION|SEC_CLASS_1, /* 96(KeyPad 8) */
|
|
SEC_ACTION|SEC_CLASS_1, /* 97(KeyPad 5) */
|
|
SEC_ACTION|SEC_CLASS_1, /* 98(KeyPad 2) */
|
|
SEC_ACTION|SEC_CLASS_1, /* 99(KeyPad 0) */
|
|
0, /* 100 */
|
|
SEC_ACTION|SEC_CLASS_1, /* 101(KeyPad 9) */
|
|
SEC_ACTION|SEC_CLASS_1, /* 102(KeyPad 6) */
|
|
SEC_ACTION|SEC_CLASS_1, /* 103(KeyPad 3) */
|
|
SEC_ACTION|SEC_CLASS_0, /* 104(KeyPad . DEL) */
|
|
0,0,0,0,0,0,0, /* 105-111 */
|
|
SEC_ACTION|SEC_CLASS_3, /* 112(F1) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 113(F2) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 114(F3) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 115(F4) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 116(F5) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 117(F6) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 118(F7) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 119(F8) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 120(F9) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 121(F10) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 122(F11) */
|
|
SEC_ACTION|SEC_CLASS_3, /* 123(F12) */
|
|
0,0, /* 124-125 */
|
|
SEC_ACTION|SEC_CLASS_2, /* 126(Break) */
|
|
0 /* 127 */
|
|
};
|
|
#endif /* SECURE } */
|
|
|
|
LOCAL VOID calc_buff_6805_left IPT0();
|
|
LOCAL VOID do_host_key_down IPT1( int,key );
|
|
LOCAL VOID do_host_key_up IPT1( int,key );
|
|
LOCAL VOID codes_to_translate IPT0();
|
|
GLOBAL VOID continue_output IPT0();
|
|
LOCAL VOID cmd_to_8042 IPT1( half_word,cmd_code );
|
|
LOCAL VOID cmd_to_6805 IPT1( half_word,cmd_code );
|
|
#ifndef HUNTER
|
|
LOCAL INT buffer_status_8042 IPT0();
|
|
#endif
|
|
|
|
#ifdef SECURE /* { */
|
|
/* Track the Modifier keys. */
|
|
LOCAL IU8 keys_down = 0;
|
|
|
|
/* Track which key downs have been supressed. */
|
|
LOCAL IU8 keys_suppressed [0x80] = {0};
|
|
|
|
/* Forward declarations keep compiler happy. */
|
|
LOCAL VOID filtered_host_key_down IPT1(int,key);
|
|
LOCAL VOID filtered_host_key_up IPT1(int,key);
|
|
|
|
/* Here are the functions for handling special keys. */
|
|
LOCAL VOID filt_dwn_reboot IFN1(int, key)
|
|
{
|
|
/* The key is only nasty if Cntrl and Alt are down. */
|
|
if ((keys_down & (SEC_CTRL_L | SEC_CTRL_R)) != 0 &&
|
|
(keys_down & (SEC_ALT_L | SEC_ALT_R )) != 0 )
|
|
{
|
|
keys_suppressed[key] = 1;
|
|
}
|
|
else
|
|
{
|
|
filtered_host_key_down(key);
|
|
}
|
|
}
|
|
LOCAL VOID filt_dwn_kpad_numerics IFN1(int, key)
|
|
{
|
|
/* The keys are only nasty if Alt is down. */
|
|
if ((keys_down & (SEC_CTRL_L | SEC_CTRL_R)) == 0 &&
|
|
(keys_down & (SEC_ALT_L | SEC_ALT_R )) != 0 )
|
|
{
|
|
keys_suppressed[key] = 1;
|
|
}
|
|
else
|
|
{
|
|
filtered_host_key_down(key);
|
|
}
|
|
}
|
|
LOCAL VOID filt_dwn_breaks IFN1(int, key)
|
|
{
|
|
/*
|
|
* The keys are only nasty if Control is down.
|
|
* The upness of the Alt key is not checked as the
|
|
* typematic feature would allow ALT-CTRL-C to be held
|
|
* down, then ALT could be released to deliver a stream
|
|
* of CTRL-C.
|
|
*/
|
|
if ((keys_down & (SEC_CTRL_L | SEC_CTRL_R)) != 0)
|
|
{
|
|
keys_suppressed[key] = 1;
|
|
}
|
|
else
|
|
{
|
|
filtered_host_key_down(key);
|
|
}
|
|
}
|
|
LOCAL VOID filt_dwn_boot_mods IFN1(int, key)
|
|
{
|
|
/* The keys are only nasty if in Boot mode. */
|
|
if (!has_boot_finished())
|
|
{
|
|
keys_suppressed[key] = 1;
|
|
}
|
|
else
|
|
{
|
|
filtered_host_key_down(key);
|
|
}
|
|
}
|
|
LOCAL VOID filt_dwn_supress_up IFN1(int, key)
|
|
{
|
|
if (keys_suppressed[key])
|
|
{
|
|
/* Key down was suppressed, do not forward key-up. */
|
|
keys_suppressed[key] = 0;
|
|
}
|
|
else
|
|
{
|
|
filtered_host_key_up(key);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The following function table is indexed by the Action Class,
|
|
* as defined in secure_keytab[].
|
|
*/
|
|
LOCAL VOID (*down_class[]) IPT1(int, key) = {
|
|
filt_dwn_reboot,
|
|
filt_dwn_kpad_numerics,
|
|
filt_dwn_breaks,
|
|
filt_dwn_boot_mods,
|
|
filtered_host_key_down,
|
|
filtered_host_key_down,
|
|
filtered_host_key_down,
|
|
filtered_host_key_down
|
|
};
|
|
LOCAL VOID (*up_class[]) IPT1(int, key) = {
|
|
filt_dwn_supress_up,
|
|
filt_dwn_supress_up,
|
|
filt_dwn_supress_up,
|
|
filt_dwn_supress_up,
|
|
filtered_host_key_up,
|
|
filtered_host_key_up,
|
|
filtered_host_key_up,
|
|
filtered_host_key_up
|
|
};
|
|
#endif /* SECURE } */
|
|
|
|
/*
|
|
* 6805 code buffer access procedures
|
|
*/
|
|
|
|
/*(
|
|
=============================== keyba_running ==================================
|
|
PURPOSE:
|
|
This access function is used to by other modules to check whether
|
|
keyba.c is currently passing on keyboard events, or whether it is buffering
|
|
them. This allows calling functions to avoid filling up keyba's buffers.
|
|
|
|
INPUT:
|
|
None.
|
|
|
|
OUTPUT:
|
|
The return value is true if keystrokes are being passed on.
|
|
|
|
ALGORITHM:
|
|
If the scanning_discontinued flag is set, or if the 6905 buffer is not
|
|
empty, FALSE is returned.
|
|
================================================================================
|
|
)*/
|
|
GLOBAL BOOL
|
|
keyba_running IFN0()
|
|
{
|
|
if (scanning_discontinued || (buff_6805_in_ptr != buff_6805_out_ptr))
|
|
return(FALSE);
|
|
else
|
|
return(TRUE);
|
|
}
|
|
|
|
#define QUEUED_OUTPUT 0
|
|
#define IMMEDIATE_OUTPUT 1
|
|
|
|
LOCAL VOID add_to_6805_buff IFN2(half_word,code,int, immediate)
|
|
/* immediate ---> = 0 queue on buffer end,
|
|
= 1 queue on buffer start */
|
|
{
|
|
/* iff room in buffer */
|
|
if (((buff_6805_out_ptr -1)& BUFF_6805_PMASK) != buff_6805_in_ptr)
|
|
{
|
|
if ( immediate )
|
|
{
|
|
/* queue at start */
|
|
buff_6805_out_ptr = (buff_6805_out_ptr - 1) & BUFF_6805_PMASK;
|
|
buff_6805[buff_6805_out_ptr]=code;
|
|
}
|
|
else
|
|
{
|
|
/* queue at end */
|
|
buff_6805[buff_6805_in_ptr]=code;
|
|
buff_6805_in_ptr = (buff_6805_in_ptr + 1) & BUFF_6805_PMASK;
|
|
}
|
|
}
|
|
calc_buff_6805_left();
|
|
|
|
#ifdef NTVDM /* JonLe NTVDM Mod */
|
|
KbdHdwFull = BUFF_6805_VMAX - free_6805_buff_size;
|
|
#endif /* NTVDM */
|
|
|
|
} /* end of add_to_6805_buff */
|
|
|
|
static half_word remove_from_6805_buff IFN0()
|
|
{
|
|
half_word ch;
|
|
|
|
ch=buff_6805[buff_6805_out_ptr];
|
|
|
|
#ifdef NTVDM
|
|
key_marker_buffer[buff_6805_out_ptr]=0;
|
|
#endif
|
|
|
|
if (buff_6805_out_ptr != buff_6805_in_ptr)
|
|
{
|
|
buff_6805_out_ptr = (buff_6805_out_ptr +1) & BUFF_6805_PMASK;
|
|
}
|
|
calc_buff_6805_left();
|
|
|
|
#ifdef NTVDM
|
|
KbdHdwFull = BUFF_6805_VMAX - free_6805_buff_size;
|
|
#endif /* NTVDM */
|
|
|
|
return (ch);
|
|
} /* end of remove_from_6805_buff */
|
|
|
|
|
|
LOCAL VOID clear_buff_6805 IFN0()
|
|
{
|
|
/* 18/5/92 MG On a macintosh, allocate buffer space so that we're
|
|
not grabbing it from the global allocation. */
|
|
|
|
#ifdef macintosh
|
|
if (buff_6805==NULL) {
|
|
check_malloc(buff_6805,BUFF_6805_PMAX,half_word);
|
|
}
|
|
#endif /* macintosh */
|
|
|
|
buff_6805_in_ptr=buff_6805_out_ptr;
|
|
free_6805_buff_size=BUFF_6805_VMAX;
|
|
|
|
#ifdef NTVDM
|
|
KbdHdwFull = BUFF_6805_VMAX - free_6805_buff_size;
|
|
|
|
/* Clear key marker buffer */
|
|
{
|
|
register int loop = sizeof(key_marker_buffer) / sizeof(unsigned char);
|
|
while(--loop >= 0) key_marker_buffer[loop] = 0;
|
|
}
|
|
#endif /* NTVDM */
|
|
}
|
|
|
|
#ifdef NTVDM
|
|
|
|
#define ONECHARCODEMASK (0x80)
|
|
|
|
LOCAL VOID mark_key_codes_6805_buff IFN1(int, start)
|
|
{
|
|
static int start_offset;
|
|
|
|
/* Room in buffer */
|
|
if(((buff_6805_out_ptr -1)& BUFF_6805_PMASK) != buff_6805_in_ptr)
|
|
{
|
|
|
|
/* Bump key start/end marker is start of seq */
|
|
if(start)
|
|
{
|
|
start_offset = buff_6805_in_ptr;
|
|
if(++key_marker_value > 127) key_marker_value = 1;
|
|
}
|
|
else
|
|
{
|
|
/* End of seq, mark first & last byte */
|
|
|
|
if(start_offset != buff_6805_in_ptr)
|
|
{
|
|
|
|
key_marker_buffer[start_offset] = key_marker_value;
|
|
|
|
if(((buff_6805_in_ptr -1)& BUFF_6805_PMASK) == start_offset)
|
|
{
|
|
key_marker_buffer[(buff_6805_in_ptr -1)& BUFF_6805_PMASK] =
|
|
key_marker_value | ONECHARCODEMASK;
|
|
}
|
|
else
|
|
{
|
|
/* mult byte seq */
|
|
|
|
key_marker_buffer[(buff_6805_in_ptr -1)& BUFF_6805_PMASK] =
|
|
key_marker_value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* This function returns the number of keys in the 6805 buffers
|
|
* and also clears down these buffers
|
|
*/
|
|
|
|
GLOBAL int keys_in_6805_buff(int *part_key_transferred)
|
|
{
|
|
int keys_in_buffer = held_event_count; /* key to yet processed by adapter */
|
|
int tmp_6805_out_ptr;
|
|
char last_marker = 0;
|
|
|
|
*part_key_transferred = FALSE;
|
|
|
|
for(tmp_6805_out_ptr = buff_6805_out_ptr;
|
|
tmp_6805_out_ptr != buff_6805_in_ptr;
|
|
tmp_6805_out_ptr = (tmp_6805_out_ptr +1) & BUFF_6805_PMASK)
|
|
{
|
|
if(key_marker_buffer[tmp_6805_out_ptr] != 0)
|
|
{
|
|
if(last_marker == 0)
|
|
{
|
|
/* start of key seq found */
|
|
if(key_marker_buffer[tmp_6805_out_ptr] & ONECHARCODEMASK)
|
|
keys_in_buffer++; /* one byte seq else */
|
|
last_marker = key_marker_buffer[tmp_6805_out_ptr];
|
|
}
|
|
else
|
|
{
|
|
if(key_marker_buffer[tmp_6805_out_ptr] == last_marker)
|
|
{
|
|
keys_in_buffer++;/* End of key seq found, bump key count */
|
|
last_marker = 0; /* no longer in middle of key seq */
|
|
}
|
|
else
|
|
{
|
|
/* Scan terminate early, part key seq found */
|
|
*part_key_transferred = TRUE;
|
|
last_marker = key_marker_buffer[tmp_6805_out_ptr];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Terminated scan in middle of key seq ??? */
|
|
if(last_marker) *part_key_transferred = TRUE;
|
|
|
|
|
|
/* Is there currently a key in the one char 8042 buffer */
|
|
if(output_full)
|
|
{
|
|
keys_in_buffer++;
|
|
}
|
|
|
|
Reset6805and8042();
|
|
|
|
return(keys_in_buffer);
|
|
}
|
|
|
|
void Reset6805and8042(void)
|
|
{
|
|
int key;
|
|
|
|
/* Reset 6805 */
|
|
|
|
buff_6805_out_ptr=0;
|
|
clear_buff_6805();
|
|
current_light_pattern=0;
|
|
|
|
//Removed, function call attempts to push characters back into
|
|
//the keyboard adapter, just as we are trying to reset it.
|
|
//This problem could be fixed by clearing the keyboard interrupt
|
|
//line after the following function call (DAB)
|
|
//host_kb_light_on(7);
|
|
|
|
for(key = 0; key < 127; key++)
|
|
{
|
|
set_3_key_state [key] = set_3_default_key_state[key];
|
|
key_down_count[key]=0;
|
|
}
|
|
|
|
waiting_for_next_code=waiting_for_next_8042_code=FALSE;
|
|
|
|
shift_on = l_shift_on = r_shift_on = FALSE;
|
|
ctrl_on = l_ctrl_on = r_ctrl_on = FALSE;
|
|
alt_on = l_alt_on = r_alt_on = FALSE;
|
|
waiting_for_upcode = FALSE;
|
|
|
|
/* Reset 8042 */
|
|
|
|
kbd_status = 0x14;
|
|
cmd_byte_8042 = 0x45;
|
|
keyboard_disabled = keyboard_interface_disabled = FALSE;
|
|
op_port_remembered_bits = 0xc;
|
|
|
|
pending_8042 = output_full = in_anomalous_state = FALSE;
|
|
int_enabled = translating = TRUE;
|
|
scanning_discontinued = FALSE;
|
|
held_event_count = 0;
|
|
|
|
//Removed by (DAB)
|
|
//host_kb_light_off (5);
|
|
num_lock_on = TRUE;
|
|
}
|
|
|
|
#endif /* NTVDM */
|
|
|
|
LOCAL VOID calc_buff_6805_left IFN0()
|
|
{
|
|
free_6805_buff_size = BUFF_6805_VMAX-((buff_6805_in_ptr - buff_6805_out_ptr) & BUFF_6805_PMASK);
|
|
if (free_6805_buff_size<0)
|
|
{
|
|
free_6805_buff_size=0;
|
|
sure_note_trace0(AT_KBD_VERBOSE,"Keyboard buffer full");
|
|
}
|
|
} /* end of calc_buff_6805_left */
|
|
|
|
LOCAL VOID add_codes_to_6805_buff IFN2(int,codes_size,half_word *,codes_buff)
|
|
{
|
|
int code_index;
|
|
|
|
if (free_6805_buff_size < codes_size)
|
|
{
|
|
|
|
/* 20.5.92 MG Don't send the overrun if we only just sent one */
|
|
|
|
if (!sent_overrun)
|
|
add_to_6805_buff(buff_overrun_6805[key_set], QUEUED_OUTPUT);
|
|
sent_overrun=TRUE;
|
|
sure_note_trace0(AT_KBD_VERBOSE,"Keyboard buffer overrun");
|
|
}
|
|
else
|
|
{
|
|
|
|
/* If some characters have been read out, clear the sent_overrun flag */
|
|
|
|
if (free_6805_buff_size>(codes_size+3))
|
|
sent_overrun=FALSE;
|
|
for (code_index=0;code_index<codes_size;code_index++) {
|
|
add_to_6805_buff(codes_buff[code_index], QUEUED_OUTPUT);
|
|
}
|
|
}
|
|
} /* end of add_codes_to_6805_buff */
|
|
|
|
|
|
#ifndef REAL_KBD
|
|
/* initialisation code */
|
|
|
|
LOCAL VOID init_key_arrays IFN0()
|
|
{
|
|
int key;
|
|
half_word *next_free, *extra_ptr, *extra_bk_ptr;
|
|
|
|
sure_note_trace1(AT_KBD_VERBOSE,"Keyboard key set initialisation: key set %d",key_set);
|
|
next_free = scan_codes_temp_area;
|
|
switch (key_set)
|
|
{
|
|
case 1:
|
|
make_sizes=set_1_make_sizes;
|
|
break_sizes=set_1_break_sizes;
|
|
for (key=0;key<127;key++)
|
|
{
|
|
switch (keytypes[key])
|
|
{
|
|
case 0:
|
|
make_arrays[key]= &(most_set_1_make_codes[key]);
|
|
break_arrays[key]=next_free;
|
|
*next_free++=(most_set_1_make_codes[key])^0x80;
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
make_arrays[key]=next_free;
|
|
*next_free++ = 0xe0;
|
|
*next_free++ = most_set_1_make_codes[key];
|
|
break_arrays[key]=next_free;
|
|
*next_free++ = 0xe0;
|
|
*next_free++ = (most_set_1_make_codes[key]) ^ 0x80;
|
|
break;
|
|
}
|
|
}
|
|
extra_ptr=set_1_extra_codes;
|
|
extra_bk_ptr=set_1_extra_bk_codes;
|
|
break;
|
|
case 2:
|
|
make_sizes=set_2_make_sizes;
|
|
break_sizes=set_2_break_sizes;
|
|
for (key=0;key<127;key++)
|
|
{
|
|
switch (keytypes[key])
|
|
{
|
|
case 0:
|
|
make_arrays[key]= &(most_set_2_make_codes[key]);
|
|
break_arrays[key]=next_free;
|
|
*next_free++ = 0xf0;
|
|
*next_free++ = most_set_2_make_codes[key];
|
|
break;
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
make_arrays[key]=next_free;
|
|
*next_free++ = 0xe0;
|
|
*next_free++ = most_set_2_make_codes[key];
|
|
break_arrays[key]=next_free;
|
|
*next_free++ = 0xe0;
|
|
*next_free++ = 0xf0;
|
|
*next_free++ = most_set_2_make_codes[key];
|
|
break;
|
|
}
|
|
}
|
|
extra_ptr=set_2_extra_codes;
|
|
extra_bk_ptr=set_2_extra_bk_codes;
|
|
break;
|
|
case 3:
|
|
make_sizes=set_3_make_sizes;
|
|
break_sizes=set_3_break_sizes;
|
|
for (key=0;key<127;key++)
|
|
{
|
|
if (keytypes[key] != 6)
|
|
{
|
|
make_arrays[key]= &(most_set_3_make_codes[key]);
|
|
break_arrays[key]=next_free;
|
|
*next_free++ = 0xf0;
|
|
*next_free++ = most_set_3_make_codes[key];
|
|
}
|
|
}
|
|
extra_ptr=set_3_extra_codes;
|
|
extra_bk_ptr=set_3_extra_bk_codes;
|
|
break;
|
|
} /* end of switch */
|
|
|
|
make_arrays[124]=extra_ptr;
|
|
extra_ptr+=make_sizes[4];
|
|
make_arrays[126]=extra_ptr;
|
|
extra_ptr+=make_sizes[5];
|
|
extra_ptr+=make_sizes[6];
|
|
make_arrays[NUM_LOCK_ADD_ARRAY]=extra_ptr;
|
|
extra_ptr+=make_sizes[7];
|
|
make_arrays[L_SHIFT_ADD_ARRAY]=extra_ptr;
|
|
extra_ptr+=make_sizes[8];
|
|
make_arrays[R_SHIFT_ADD_ARRAY]=extra_ptr;
|
|
extra_ptr+=make_sizes[9];
|
|
make_arrays[CASE_4_SHIFTED_ARRAY]=extra_ptr;
|
|
extra_ptr+=make_sizes[10];
|
|
make_arrays[ALT_CASE_4_ARRAY]=extra_ptr;
|
|
extra_ptr+=make_sizes[11];
|
|
make_arrays[CASE_5_CTRLED_ARRAY]=extra_ptr;
|
|
extra_ptr+=make_sizes[12];
|
|
|
|
break_arrays[124]=extra_bk_ptr;
|
|
extra_bk_ptr+=break_sizes[4];
|
|
break_arrays[126]=extra_bk_ptr;
|
|
extra_bk_ptr+=break_sizes[5];
|
|
extra_bk_ptr+=break_sizes[6];
|
|
break_arrays[NUM_LOCK_ADD_ARRAY]=extra_bk_ptr;
|
|
extra_bk_ptr+=break_sizes[7];
|
|
break_arrays[L_SHIFT_ADD_ARRAY]=extra_bk_ptr;
|
|
extra_bk_ptr+=break_sizes[8];
|
|
break_arrays[R_SHIFT_ADD_ARRAY]=extra_bk_ptr;
|
|
extra_bk_ptr+=break_sizes[9];
|
|
break_arrays[CASE_4_SHIFTED_ARRAY]=extra_bk_ptr;
|
|
extra_bk_ptr+=break_sizes[10];
|
|
break_arrays[ALT_CASE_4_ARRAY]=extra_bk_ptr;
|
|
extra_bk_ptr+=break_sizes[11];
|
|
break_arrays[CASE_5_CTRLED_ARRAY]=extra_bk_ptr;
|
|
extra_bk_ptr+=break_sizes[12];
|
|
} /* end of init_key_arrays () */
|
|
|
|
|
|
/* Key pressed on host keyboard */
|
|
|
|
GLOBAL VOID host_key_down IFN1(int,key)
|
|
#ifdef SECURE /* { */
|
|
{
|
|
IU8 keytab_entry;
|
|
/* Make a note of any modifier bits. */
|
|
keytab_entry = secure_keytab[key];
|
|
keys_down |= keytab_entry;
|
|
/* If any filtering action is required, go do it. */
|
|
if (config_inquire(C_SECURE, NULL) && (keytab_entry & SEC_ACTION) != 0)
|
|
{
|
|
/* The key may need filtering. */
|
|
(*down_class[keytab_entry & SEC_ACTCLASS])(key);
|
|
}
|
|
else
|
|
{
|
|
filtered_host_key_down(key);
|
|
}
|
|
}
|
|
|
|
LOCAL VOID filtered_host_key_down IFN1(int,key)
|
|
#endif /* SECURE } */
|
|
{
|
|
if (scanning_discontinued)
|
|
{
|
|
held_event_type[held_event_count]=KEY_DOWN_EVENT;
|
|
held_event_key[held_event_count++]=key;
|
|
|
|
/* check for held event buffer overflow (SHOULD never happen) */
|
|
if (held_event_count >= HELD_EVENT_MAX)
|
|
{
|
|
held_event_count = HELD_EVENT_MAX-1;
|
|
always_trace0("host_key_down held event buffer overflow");
|
|
}
|
|
}
|
|
#ifdef NTVDM
|
|
else if (!keyboard_disabled) {
|
|
//
|
|
// Ignore contiguous repeat keys if keys are still in the 6805
|
|
// this keeps the apps responsive to the corresponding up key
|
|
// when it comes.
|
|
//
|
|
if (LastKeyDown != key || (KbdHdwFull < 8)) {
|
|
LastKeyDown = key;
|
|
key_down_count[key]++;
|
|
do_host_key_down(key);
|
|
}
|
|
}
|
|
#else
|
|
else
|
|
{
|
|
do_host_key_down(key);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
GLOBAL VOID host_key_up IFN1(int,key)
|
|
#ifdef SECURE /* { */
|
|
{
|
|
IU8 keytab_entry;
|
|
/* Make a note of any modifier bits. */
|
|
keytab_entry = secure_keytab[key];
|
|
keys_down &= SEC_MOD_MASK ^ keytab_entry;
|
|
/* If any filtering action is required, go do it. */
|
|
if (config_inquire(C_SECURE, NULL) && (keytab_entry & SEC_ACTION) != 0)
|
|
{
|
|
/* The key may need filtering. */
|
|
(*up_class[keytab_entry & SEC_ACTCLASS])(key);
|
|
}
|
|
else
|
|
{
|
|
filtered_host_key_up(key);
|
|
}
|
|
}
|
|
|
|
LOCAL VOID filtered_host_key_up IFN1(int,key)
|
|
#endif /* SECURE } */
|
|
{
|
|
if (scanning_discontinued)
|
|
{
|
|
held_event_type[held_event_count]=KEY_UP_EVENT;
|
|
held_event_key[held_event_count++]=key;
|
|
|
|
/* check for held event buffer overflow (SHOULD never happen) */
|
|
if (held_event_count >= HELD_EVENT_MAX)
|
|
{
|
|
held_event_count = HELD_EVENT_MAX-1;
|
|
always_trace0("host_key_up held event buffer overflow");
|
|
}
|
|
}
|
|
#ifdef NTVDM
|
|
else if (!keyboard_disabled && key_down_count[key]) {
|
|
#else
|
|
else
|
|
{
|
|
#endif
|
|
#ifdef NTVDM
|
|
LastKeyDown = -1;
|
|
#endif
|
|
do_host_key_up(key);
|
|
}
|
|
}
|
|
|
|
#ifdef NTVDM
|
|
GLOBAL VOID RaiseAllDownKeys(VOID)
|
|
{
|
|
int i;
|
|
|
|
i = sizeof(key_down_count)/sizeof(int);
|
|
while (i--) {
|
|
if (key_down_count[i]) {
|
|
host_key_up(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
GLOBAL int IsKeyDown(int Key)
|
|
{
|
|
return key_down_count[Key];
|
|
}
|
|
|
|
|
|
#endif /* NTVDM */
|
|
|
|
LOCAL VOID do_host_key_down IFN1(int,key)
|
|
{
|
|
int overrun,keytype;
|
|
|
|
sure_note_trace1(AT_KBD_VERBOSE,"key down:%d",key);
|
|
|
|
if (!keyboard_disabled)
|
|
{
|
|
|
|
#ifdef NTVDM
|
|
mark_key_codes_6805_buff(TRUE);
|
|
#else
|
|
key_down_count[key]++;
|
|
if (key_down_count[key]==1)
|
|
{ /* first press */
|
|
repeat_delay_count=0;
|
|
repeat_count=0;
|
|
typematic_key_valid=FALSE;
|
|
|
|
#endif /* NTVDM */
|
|
keytype=keytypes[key];
|
|
overrun=FALSE;
|
|
if (in_anomalous_state)
|
|
{
|
|
if (anomalous_size > free_6805_buff_size)
|
|
{ overrun=TRUE; }
|
|
else
|
|
{
|
|
scan_code_6805_size = anomalous_size;
|
|
scan_code_6805_array = anomalous_array;
|
|
add_codes_to_6805_buff(anomalous_size,anomalous_array);
|
|
in_anomalous_state=FALSE;
|
|
}
|
|
}
|
|
|
|
switch (keytype)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 6:
|
|
scan_code_6805_size=make_sizes[keytype];
|
|
scan_code_6805_array=make_arrays[key];
|
|
break;
|
|
case 2:
|
|
if (num_lock_on && !shift_on)
|
|
{
|
|
scan_code_6805_size=make_sizes[NUM_LOCK_ADD];
|
|
scan_code_6805_array=make_arrays[NUM_LOCK_ADD_ARRAY];
|
|
if (scan_code_6805_size+make_sizes[keytype] >free_6805_buff_size)
|
|
{ overrun=TRUE; }
|
|
else
|
|
{
|
|
in_anomalous_state=TRUE;
|
|
anom_key=key;
|
|
anomalous_array=break_arrays[NUM_LOCK_ADD_ARRAY];
|
|
anomalous_size=break_sizes[NUM_LOCK_ADD];
|
|
add_codes_to_6805_buff(scan_code_6805_size,scan_code_6805_array);
|
|
}
|
|
}
|
|
if (!num_lock_on && shift_on)
|
|
{
|
|
if (l_shift_on)
|
|
{
|
|
scan_code_6805_size=make_sizes[L_SHIFT_ADD];
|
|
scan_code_6805_array=make_arrays[L_SHIFT_ADD_ARRAY];
|
|
in_anomalous_state=TRUE;
|
|
anom_key=key;
|
|
anomalous_array=break_arrays[L_SHIFT_ADD_ARRAY];
|
|
anomalous_size=break_sizes[L_SHIFT_ADD];
|
|
}
|
|
else
|
|
{
|
|
scan_code_6805_size=make_sizes[R_SHIFT_ADD];
|
|
scan_code_6805_array=make_arrays[R_SHIFT_ADD_ARRAY];
|
|
in_anomalous_state=TRUE;
|
|
anom_key=key;
|
|
anomalous_array=break_arrays[R_SHIFT_ADD_ARRAY];
|
|
anomalous_size=break_sizes[R_SHIFT_ADD];
|
|
}
|
|
if (scan_code_6805_size+make_sizes[keytype] >free_6805_buff_size)
|
|
{
|
|
overrun=TRUE;
|
|
in_anomalous_state=FALSE;
|
|
}
|
|
else
|
|
{
|
|
add_codes_to_6805_buff(scan_code_6805_size,scan_code_6805_array);
|
|
}
|
|
}
|
|
scan_code_6805_size=make_sizes[keytype];
|
|
scan_code_6805_array=make_arrays[key];
|
|
break;
|
|
case 3:
|
|
if (shift_on)
|
|
{
|
|
if (l_shift_on)
|
|
{
|
|
scan_code_6805_size=make_sizes[L_SHIFT_ADD];
|
|
scan_code_6805_array=make_arrays[L_SHIFT_ADD_ARRAY];
|
|
in_anomalous_state=TRUE;
|
|
anom_key=key;
|
|
anomalous_array=break_arrays[L_SHIFT_ADD_ARRAY];
|
|
anomalous_size=break_sizes[L_SHIFT_ADD];
|
|
}
|
|
else
|
|
{
|
|
scan_code_6805_size=make_sizes[R_SHIFT_ADD];
|
|
scan_code_6805_array=make_arrays[R_SHIFT_ADD_ARRAY];
|
|
in_anomalous_state=TRUE;
|
|
anom_key=key;
|
|
anomalous_array=break_arrays[R_SHIFT_ADD_ARRAY];
|
|
anomalous_size=break_sizes[R_SHIFT_ADD];
|
|
}
|
|
if (scan_code_6805_size+make_sizes[keytype] >free_6805_buff_size)
|
|
{
|
|
overrun=TRUE;
|
|
in_anomalous_state=FALSE;
|
|
}
|
|
else
|
|
{
|
|
add_codes_to_6805_buff(scan_code_6805_size,scan_code_6805_array);
|
|
}
|
|
}
|
|
scan_code_6805_size=make_sizes[keytype];
|
|
scan_code_6805_array=make_arrays[key];
|
|
break;
|
|
case 4:
|
|
if (shift_on || ctrl_on || alt_on)
|
|
{
|
|
if (shift_on || ctrl_on)
|
|
{
|
|
scan_code_6805_size=make_sizes[CASE_4_SHIFTED];
|
|
scan_code_6805_array=make_arrays[CASE_4_SHIFTED_ARRAY];
|
|
}
|
|
else
|
|
{
|
|
scan_code_6805_size=make_sizes[ALT_CASE_4];
|
|
scan_code_6805_array=make_arrays[ALT_CASE_4_ARRAY];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
in_anomalous_state=TRUE;
|
|
anomalous_array=break_arrays[L_SHIFT_ADD_ARRAY];
|
|
anomalous_size=break_sizes[L_SHIFT_ADD];
|
|
anom_key=key;
|
|
scan_code_6805_size=make_sizes[keytype];
|
|
scan_code_6805_array=make_arrays[key];
|
|
}
|
|
break;
|
|
case 5:
|
|
if (ctrl_on)
|
|
{
|
|
scan_code_6805_size=make_sizes[CASE_5_CTRLED];
|
|
scan_code_6805_array=make_arrays[CASE_5_CTRLED_ARRAY];
|
|
}
|
|
else
|
|
{
|
|
scan_code_6805_size=make_sizes[keytype];
|
|
scan_code_6805_array=make_arrays[key];
|
|
}
|
|
break;
|
|
} /* end of switch */
|
|
if (overrun)
|
|
{
|
|
if (!sent_overrun)
|
|
add_to_6805_buff(buff_overrun_6805[key_set],
|
|
QUEUED_OUTPUT);
|
|
sent_overrun=TRUE;
|
|
|
|
sure_note_trace0(AT_KBD_VERBOSE,"Keyboard buffer overrun");
|
|
}
|
|
else
|
|
{
|
|
add_codes_to_6805_buff(scan_code_6805_size,scan_code_6805_array);
|
|
}
|
|
switch (key)
|
|
{
|
|
case 44:
|
|
l_shift_on =TRUE;
|
|
shift_on = TRUE;
|
|
break;
|
|
case 57:
|
|
r_shift_on = TRUE;
|
|
shift_on = TRUE;
|
|
break;
|
|
case 58:
|
|
l_ctrl_on =TRUE;
|
|
ctrl_on = TRUE;
|
|
break;
|
|
case 64:
|
|
r_ctrl_on = TRUE;
|
|
ctrl_on = TRUE;
|
|
break;
|
|
case 60:
|
|
l_alt_on =TRUE;
|
|
alt_on = TRUE;
|
|
break;
|
|
case 62:
|
|
r_alt_on =TRUE;
|
|
alt_on = TRUE;
|
|
break;
|
|
case 90:
|
|
num_lock_on = !num_lock_on;
|
|
break;
|
|
}
|
|
|
|
#ifndef NTVDM /* JonLe NTVDM Mod */
|
|
|
|
if (key!=126)
|
|
{
|
|
if ((key_set != 3) || (set_3_key_state[key] == 1) || (set_3_key_state[key] == 4))
|
|
{
|
|
typematic_key = key;
|
|
typematic_key_valid = TRUE;
|
|
}
|
|
}
|
|
#else
|
|
mark_key_codes_6805_buff(FALSE);
|
|
#endif /* NTVDM */
|
|
|
|
if (free_6805_buff_size < BUFF_6805_VMAX)
|
|
{
|
|
codes_to_translate();
|
|
}
|
|
|
|
#ifndef NTVDM
|
|
} /* end of if first press */
|
|
#endif /* NTVDM */
|
|
|
|
} /* end of if not disabled */
|
|
} /* end of do_host_key_down */
|
|
|
|
|
|
/* Key released on host keyboard */
|
|
LOCAL VOID do_host_key_up IFN1(int,key)
|
|
{
|
|
half_word *temp_arr_array;
|
|
int temp_arr_size,keytype,overrun;
|
|
|
|
sure_note_trace1(AT_KBD_VERBOSE,"key up:%d",key);
|
|
|
|
if (!keyboard_disabled)
|
|
{
|
|
#ifdef DEMO_COPY
|
|
host_check_demo_expire ();
|
|
#endif
|
|
if( key_down_count[key] == 0){
|
|
/*
|
|
** This will ignore extra key ups.
|
|
*/
|
|
#ifndef PROD
|
|
sure_note_trace1( AT_KBD_VERBOSE, "Ignored extra key up:%d", key );
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
key_down_count[key] = 0;
|
|
|
|
#ifndef NTVDM /* JonLe NTVDM Mod */
|
|
if ((key==typematic_key) && typematic_key_valid)
|
|
{
|
|
typematic_key_valid=FALSE;
|
|
}
|
|
#endif /* NTVDM */
|
|
|
|
keytype=keytypes[key];
|
|
overrun=FALSE;
|
|
if (!(key_set ==3) || (set_3_key_state[key]==2) || (set_3_key_state[key]==4))
|
|
{
|
|
#ifdef NTVDM
|
|
mark_key_codes_6805_buff(TRUE);
|
|
#endif
|
|
switch (keytype)
|
|
{
|
|
case 0:
|
|
case 1:
|
|
case 6:
|
|
scan_code_6805_size=break_sizes[keytype];
|
|
scan_code_6805_array=break_arrays[key];
|
|
break;
|
|
case 2:
|
|
temp_arr_size=0;
|
|
if (in_anomalous_state && (anom_key == key))
|
|
{
|
|
in_anomalous_state=FALSE;
|
|
if (num_lock_on && !shift_on)
|
|
{
|
|
temp_arr_size=break_sizes[NUM_LOCK_ADD];
|
|
temp_arr_array=break_arrays[NUM_LOCK_ADD_ARRAY];
|
|
}
|
|
if (!num_lock_on && shift_on)
|
|
{
|
|
if (l_shift_on)
|
|
{
|
|
temp_arr_size=break_sizes[L_SHIFT_ADD];
|
|
temp_arr_array=break_arrays[L_SHIFT_ADD_ARRAY];
|
|
}
|
|
else
|
|
{
|
|
temp_arr_size=break_sizes[R_SHIFT_ADD];
|
|
temp_arr_array=break_arrays[R_SHIFT_ADD_ARRAY];
|
|
}
|
|
}
|
|
}
|
|
scan_code_6805_size=break_sizes[keytype];
|
|
scan_code_6805_array=break_arrays[key];
|
|
if (scan_code_6805_size+temp_arr_size > free_6805_buff_size)
|
|
{ overrun=TRUE; }
|
|
else
|
|
{
|
|
add_codes_to_6805_buff(scan_code_6805_size,scan_code_6805_array);
|
|
}
|
|
scan_code_6805_size=temp_arr_size;
|
|
scan_code_6805_array=temp_arr_array;
|
|
break;
|
|
case 3:
|
|
temp_arr_size=0;
|
|
if (in_anomalous_state && (anom_key == key))
|
|
{
|
|
in_anomalous_state = FALSE;
|
|
if (shift_on)
|
|
{
|
|
if (l_shift_on)
|
|
{
|
|
temp_arr_size=break_sizes[L_SHIFT_ADD];
|
|
temp_arr_array=break_arrays[L_SHIFT_ADD_ARRAY];
|
|
}
|
|
else
|
|
{
|
|
temp_arr_size=break_sizes[R_SHIFT_ADD];
|
|
temp_arr_array=break_arrays[R_SHIFT_ADD_ARRAY];
|
|
}
|
|
}
|
|
}
|
|
scan_code_6805_size=break_sizes[keytype];
|
|
scan_code_6805_array=break_arrays[key];
|
|
if (scan_code_6805_size+temp_arr_size > free_6805_buff_size)
|
|
{ overrun=TRUE; }
|
|
else
|
|
{
|
|
add_codes_to_6805_buff(scan_code_6805_size,scan_code_6805_array);
|
|
}
|
|
scan_code_6805_size=temp_arr_size;
|
|
scan_code_6805_array=temp_arr_array;
|
|
break;
|
|
case 4:
|
|
if (shift_on || ctrl_on || alt_on)
|
|
{
|
|
if (shift_on || ctrl_on)
|
|
{
|
|
scan_code_6805_size=break_sizes[CASE_4_SHIFTED];
|
|
scan_code_6805_array=break_arrays[CASE_4_SHIFTED_ARRAY];
|
|
}
|
|
else
|
|
{
|
|
scan_code_6805_size=break_sizes[ALT_CASE_4];
|
|
scan_code_6805_array=break_arrays[ALT_CASE_4_ARRAY];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (in_anomalous_state && (anom_key==key))
|
|
{
|
|
in_anomalous_state=FALSE;
|
|
scan_code_6805_size=break_sizes[keytype];
|
|
scan_code_6805_array=break_arrays[key];
|
|
}
|
|
else
|
|
{
|
|
scan_code_6805_size=break_sizes[CASE_4_SHIFTED];
|
|
scan_code_6805_array=break_arrays[CASE_4_SHIFTED_ARRAY];
|
|
}
|
|
}
|
|
break;
|
|
case 5:
|
|
scan_code_6805_size=0;
|
|
break;
|
|
} /* end of switch */
|
|
if (overrun)
|
|
{
|
|
if (!sent_overrun)
|
|
add_to_6805_buff(buff_overrun_6805[key_set], QUEUED_OUTPUT);
|
|
sent_overrun=TRUE;
|
|
|
|
sure_note_trace0(AT_KBD_VERBOSE,"Keyboard buffer overrun");
|
|
}
|
|
else
|
|
{
|
|
add_codes_to_6805_buff(scan_code_6805_size,scan_code_6805_array);
|
|
}
|
|
#ifdef NTVDM
|
|
mark_key_codes_6805_buff(FALSE);
|
|
#endif
|
|
} /* end of if not set 3 etc. */
|
|
switch (key)
|
|
{
|
|
case 44:
|
|
l_shift_on =FALSE;
|
|
if (!r_shift_on) { shift_on = FALSE; }
|
|
break;
|
|
case 57:
|
|
r_shift_on = FALSE;
|
|
if (!l_shift_on) { shift_on = FALSE; }
|
|
break;
|
|
case 58:
|
|
l_ctrl_on =FALSE;
|
|
if (!r_ctrl_on) { ctrl_on = FALSE; }
|
|
break;
|
|
case 64:
|
|
r_ctrl_on = FALSE;
|
|
if (!l_ctrl_on) { ctrl_on = FALSE; }
|
|
break;
|
|
case 60:
|
|
l_alt_on =FALSE;
|
|
if (!r_alt_on) { alt_on = FALSE; }
|
|
break;
|
|
case 62:
|
|
r_alt_on =FALSE;
|
|
if (!l_alt_on) { alt_on = FALSE; }
|
|
break;
|
|
} /* end of switch */
|
|
|
|
if (free_6805_buff_size < BUFF_6805_VMAX)
|
|
{
|
|
codes_to_translate();
|
|
}
|
|
} /* end of if last release */
|
|
} /* end of if not disabled */
|
|
} /* end of do_host_key_up */
|
|
#endif /* REAL_KBD */
|
|
|
|
#ifdef NTVDM
|
|
/*
|
|
* force filling of Kbd data port just like the real kbd
|
|
* since we no longer clear output_full in the Kbd_inb routine
|
|
*/
|
|
LOCAL VOID AddTo6805BuffImm IFN1(half_word,code)
|
|
{
|
|
add_to_6805_buff(code,IMMEDIATE_OUTPUT);
|
|
output_full = FALSE;
|
|
KbdData = -1;
|
|
}
|
|
#else
|
|
#define AddTo6805BuffImm(code) add_to_6805_buff(code, IMMEDIATE_OUTPUT);
|
|
#endif
|
|
|
|
LOCAL VOID cmd_to_6805 IFN1(half_word,cmd_code)
|
|
{
|
|
int i,key_to_change;
|
|
half_word change_to;
|
|
unsigned int cmd_code_temp; /* Mac MPW3 compiler prefers unsigned ints in switches */
|
|
|
|
sure_note_trace1(AT_KBD_VERBOSE,"6805 received cmd:0x%x",cmd_code);
|
|
|
|
#ifndef REAL_KBD
|
|
|
|
if (waiting_for_next_code)
|
|
{
|
|
switch (next_code_sequence_number)
|
|
{
|
|
case SCAN_CODE_CHANGE_SEQUENCE:
|
|
if (cmd_code>3 || cmd_code <0)
|
|
{ AddTo6805BuffImm(RESEND_CODE); }
|
|
else
|
|
{
|
|
if (cmd_code == 0)
|
|
{
|
|
/* order of reception of scan codes is reverse their order of insertion
|
|
* if 'IMMEDIATE_OUTPUT' method of insertion is used
|
|
*/
|
|
AddTo6805BuffImm(key_set);
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
}
|
|
else
|
|
{
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
key_set=cmd_code;
|
|
init_key_arrays();
|
|
}
|
|
}
|
|
break;
|
|
case SET_3_KEY_TYPE_SET_SEQUENCE:
|
|
sure_note_trace2(AT_KBD_VERBOSE,"Keyboard key type change: key 0x%x, new type %d",cmd_code,set_3_key_type_change_dest);
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
key_to_change=set_3_reverse_lookup[cmd_code];
|
|
set_3_key_state[key_to_change]=set_3_key_type_change_dest;
|
|
break;
|
|
case SET_STATUS_INDICATORS_SEQUENCE:
|
|
if ((cmd_code & 0xf8) == 0)
|
|
{
|
|
sure_note_trace1(AT_KBD_VERBOSE,"Changing kbd lights to :%x",cmd_code);
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
#ifdef NTVDM
|
|
host_kb_light_on ((cmd_code & 0x07) | 0xf0);
|
|
#else
|
|
cmd_code &= 0x7;
|
|
host_kb_light_on (cmd_code);
|
|
host_kb_light_off ((~cmd_code)&0x7);
|
|
#endif
|
|
}
|
|
break;
|
|
case SET_RATE_DELAY_SEQUENCE:
|
|
#ifndef NTVDM /* JonLe Mod */
|
|
if ((cmd_code & 0x80)==0)
|
|
{
|
|
repeat_delay_target = (1+((cmd_code>>5)&3))*BASE_DELAY_UNIT;
|
|
cmd_code &= 0x1f;
|
|
if (cmd_code<0xb) { repeat_target =0; }
|
|
else { if (cmd_code<0x11) { repeat_target =1; }
|
|
else { if (cmd_code<0x19) { repeat_target=(cmd_code-0x12)/3 +3;}
|
|
else { if (cmd_code<0x1e) { repeat_target=(cmd_code-0x1a)/2+6;}
|
|
else { repeat_target=(cmd_code-0x1e)+8;}}}}
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
}
|
|
sure_note_trace2(AT_KBD_VERBOSE,"Changing kbd rate/delay: rate = %d, dealy=%d ",repeat_target,repeat_delay_target);
|
|
|
|
#else /* NTVDM */
|
|
|
|
if ((cmd_code & 0x80)==0)
|
|
{
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
}
|
|
|
|
#endif /* NTVDM */
|
|
break;
|
|
}
|
|
waiting_for_next_code = FALSE;
|
|
}
|
|
else
|
|
{
|
|
|
|
#endif /* not REAL_KBD */
|
|
|
|
/*
|
|
** Mac MPW3 compiler does not like bytes sized switch
|
|
** variables if a case matches on 0xff. It seems to
|
|
** generate dodgy code. Different type seems OK.
|
|
*/
|
|
cmd_code_temp = (unsigned int)cmd_code;
|
|
switch ( cmd_code_temp )
|
|
{
|
|
#ifndef REAL_KBD
|
|
case 0xf5:
|
|
/* Default Disable */
|
|
clear_buff_6805 ();
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
for (key_to_change=1;key_to_change<127;key_to_change++)
|
|
{
|
|
set_3_key_state[key_to_change]=set_3_default_key_state[key_to_change];
|
|
}
|
|
|
|
#ifndef NTVDM /* JonLe NTVDM Mod */
|
|
repeat_delay_target=2*BASE_DELAY_UNIT;
|
|
repeat_target=DEFAULT_REPEAT_TARGET;
|
|
typematic_key_valid=FALSE;
|
|
#endif /* NTVDM */
|
|
|
|
keyboard_disabled=TRUE;
|
|
sure_note_trace0(AT_KBD_VERBOSE,"Keyboard disabled");
|
|
break;
|
|
case 0xee:
|
|
/* echo */
|
|
AddTo6805BuffImm(0xee);
|
|
break;
|
|
case 0xf4:
|
|
/* enable */
|
|
clear_buff_6805 ();
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
|
|
#ifndef NTVDM /* JonLe NTVDM Mod */
|
|
typematic_key_valid=FALSE;
|
|
#endif /* NTVDM */
|
|
|
|
keyboard_disabled=FALSE;
|
|
sure_note_trace0(AT_KBD_VERBOSE,"Keyboard enabled");
|
|
break;
|
|
#endif
|
|
case 0xf2:
|
|
/* Read ID */
|
|
/* order of reception of scan codes is reverse their order of insertion
|
|
* if 'IMMEDIATE_OUTPUT' method of insertion is used
|
|
*/
|
|
AddTo6805BuffImm(0x83);
|
|
AddTo6805BuffImm(0xab);
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
break;
|
|
case 0xfe:
|
|
/* resend */
|
|
buff_6805_out_ptr=(buff_6805_out_ptr-1) & BUFF_6805_PMASK;
|
|
calc_buff_6805_left();
|
|
break;
|
|
#ifndef REAL_KBD
|
|
case 0xff:
|
|
/* reset */
|
|
/* order of reception of scan codes is reverse their order of insertion
|
|
* if 'IMMEDIATE_OUTPUT' method of insertion is used
|
|
*/
|
|
AddTo6805BuffImm(BAT_COMPLETION_CODE);
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
keyboard_disabled=FALSE;
|
|
sure_note_trace0(AT_KBD_VERBOSE,"Keyboard reset");
|
|
break;
|
|
case 0xf0:
|
|
/* Select Alternate Scan Codes */
|
|
clear_buff_6805 ();
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
|
|
#ifndef NTVDM /* JonLe NTVDM Mod */
|
|
typematic_key_valid=FALSE;
|
|
#endif /* NTVDM */
|
|
|
|
next_code_sequence_number=SCAN_CODE_CHANGE_SEQUENCE;
|
|
held_event_count=0;
|
|
scanning_discontinued = waiting_for_next_code=TRUE;
|
|
break;
|
|
case 0xf7:
|
|
case 0xf8:
|
|
case 0xf9:
|
|
case 0xfa:
|
|
/* Set all keys */
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
change_to=cmd_code - 0xf6;
|
|
for (key_to_change=1;key_to_change<127;key_to_change++)
|
|
{
|
|
set_3_key_state[key_to_change]=change_to;
|
|
}
|
|
sure_note_trace1(AT_KBD_VERBOSE,"All keys set to type :0x%x",change_to);
|
|
break;
|
|
case 0xf6:
|
|
/* Set Default */
|
|
clear_buff_6805 ();
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
for (key_to_change=1;key_to_change<127;key_to_change++)
|
|
{
|
|
set_3_key_state[key_to_change]=set_3_default_key_state[key_to_change];
|
|
}
|
|
|
|
#ifndef NTVDM /* JonLe NTVDM Mod */
|
|
repeat_delay_target=2*BASE_DELAY_UNIT;
|
|
repeat_target=DEFAULT_REPEAT_TARGET;
|
|
typematic_key_valid=FALSE;
|
|
#endif /* NTVDM */
|
|
keyboard_disabled=FALSE;
|
|
sure_note_trace0(AT_KBD_VERBOSE,"Keyboard set to default (and enabled)");
|
|
break;
|
|
case 0xfb:
|
|
case 0xfc:
|
|
case 0xfd:
|
|
/* Set key type */
|
|
clear_buff_6805 ();
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
|
|
#ifndef NTVDM /* JonLe NTVDM Mod */
|
|
typematic_key_valid=FALSE;
|
|
#endif /* NTVDM */
|
|
|
|
next_code_sequence_number=SET_3_KEY_TYPE_SET_SEQUENCE;
|
|
held_event_count=0;
|
|
scanning_discontinued = waiting_for_next_code=TRUE;
|
|
set_3_key_type_change_dest=cmd_code - 0xfa;
|
|
break;
|
|
case 0xed:
|
|
/* Set/Reset Status Indicators */
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
next_code_sequence_number=SET_STATUS_INDICATORS_SEQUENCE;
|
|
held_event_count=0;
|
|
scanning_discontinued = waiting_for_next_code=TRUE;
|
|
break;
|
|
case 0xf3:
|
|
/* Set typematic Rate/Delay */
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
next_code_sequence_number=SET_RATE_DELAY_SEQUENCE;
|
|
held_event_count=0;
|
|
scanning_discontinued = waiting_for_next_code=TRUE;
|
|
break;
|
|
default :
|
|
/* unrecognised code */
|
|
#ifdef JOKER
|
|
AddTo6805BuffImm(ACK_CODE);
|
|
#else /* JOKER */
|
|
AddTo6805BuffImm(RESEND_CODE);
|
|
#endif /* JOKER */
|
|
break;
|
|
|
|
#else
|
|
default :
|
|
/* cmd to be sent on to real kbd */
|
|
send_to_real_kbd(cmd_code);
|
|
#endif
|
|
} /* end of switch */
|
|
#ifndef REAL_KBD
|
|
}
|
|
#else
|
|
waiting_for_next_code=FALSE;
|
|
#endif
|
|
|
|
#ifndef REAL_KBD
|
|
if (scanning_discontinued && !waiting_for_next_code)
|
|
{
|
|
if (held_event_count != 0)
|
|
{
|
|
for (i=0;i<held_event_count;i++)
|
|
{
|
|
switch (held_event_type[i])
|
|
{
|
|
case KEY_DOWN_EVENT:
|
|
do_host_key_down(held_event_key[i]);
|
|
break;
|
|
case KEY_UP_EVENT:
|
|
do_host_key_up(held_event_key[i]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
scanning_discontinued=FALSE;
|
|
}
|
|
#endif
|
|
|
|
#ifndef NTVDM
|
|
if (free_6805_buff_size < BUFF_6805_VMAX)
|
|
{
|
|
codes_to_translate();
|
|
}
|
|
#endif
|
|
|
|
} /* end of cmd_to_6805 */
|
|
|
|
/* interface to interrupts */
|
|
|
|
#ifdef NTVDM /* JonLe NTVDM Mod */
|
|
|
|
|
|
|
|
/* KbdIntDelay
|
|
*
|
|
* UNDER ALL CONDITIONS we must provide a SAFE key rate that 16 bit apps
|
|
* can handle. This must be done without looking at the bios buffer,
|
|
* since not all apps use the bios int 9 handler.
|
|
*
|
|
*/
|
|
|
|
LOCAL VOID KbdIntDelay(VOID)
|
|
{
|
|
|
|
|
|
//
|
|
// Wait until the kbd scancode has been read,
|
|
// before invoking the next interrupt.
|
|
//
|
|
if (bKbdEoiPending)
|
|
return;
|
|
|
|
|
|
if (int_enabled) {
|
|
bKbdEoiPending = TRUE;
|
|
|
|
if (!bForceDelayInts) {
|
|
kbd_status |= 1;
|
|
ica_hw_interrupt(KEYBOARD_INT_ADAPTER, KEYBOARD_INT_LINE, 1);
|
|
}
|
|
else {
|
|
ULONG ulDelay = 2000;
|
|
|
|
if (bKbdIntHooked) {
|
|
ulDelay += 2000;
|
|
}
|
|
|
|
if (KbdHdwFull > 8) {
|
|
ulDelay += 4000;
|
|
}
|
|
|
|
if (!bBiosBufferSpace) {
|
|
ulDelay += 4000;
|
|
}
|
|
|
|
if (!bPifFastPaste) {
|
|
ulDelay <<= 1;
|
|
}
|
|
|
|
bDelayIntPending = TRUE;
|
|
host_DelayHwInterrupt(KEYBOARD_INT_LINE,
|
|
1,
|
|
ulDelay
|
|
);
|
|
}
|
|
|
|
HostIdleNoActivity();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//This function is called by the ICA with the ica lock
|
|
void KbdEOIHook(int IrqLine, int CallCount)
|
|
{
|
|
|
|
if (!bKbdEoiPending) // sanity
|
|
return;
|
|
|
|
if (!bBiosOwnsKbdHdw && WaitKbdHdw(0xffffffff)) {
|
|
bKbdEoiPending = FALSE;
|
|
return;
|
|
}
|
|
|
|
bKbdIntHooked = KbdInt09Off != *(word *)(Start_of_M_area+0x09*4) ||
|
|
KbdInt09Seg != *(word *)(Start_of_M_area+0x09*4+2);
|
|
|
|
bBiosBufferSpace = bBiosOwnsKbdHdw &&
|
|
(bios_buffer_size() < (bPifFastPaste ? 8 : 2));
|
|
|
|
output_full = FALSE;
|
|
bKbdEoiPending = FALSE;
|
|
|
|
bForceDelayInts = TRUE;
|
|
continue_output();
|
|
bForceDelayInts = FALSE;
|
|
|
|
if (!bBiosOwnsKbdHdw)
|
|
HostReleaseKbd();
|
|
}
|
|
|
|
|
|
|
|
|
|
LOCAL VOID do_q_int(char scancode)
|
|
{
|
|
output_full = TRUE;
|
|
output_contents = scancode;
|
|
|
|
KbdIntDelay();
|
|
}
|
|
|
|
#else /* NTVDM */
|
|
|
|
LOCAL VOID do_int IFN1(long,scancode)
|
|
{
|
|
output_contents = (char)scancode;
|
|
kbd_status |= 1; /* Character now available! */
|
|
if (int_enabled)
|
|
{
|
|
sure_note_trace0(AT_KBD_VERBOSE,"keyboard interrupting");
|
|
ica_hw_interrupt(KEYBOARD_INT_ADAPTER, KEYBOARD_INT_LINE, 1);
|
|
}
|
|
}
|
|
|
|
LOCAL VOID do_q_int IFN1(char,scancode)
|
|
{
|
|
output_full = TRUE;
|
|
|
|
#if defined(IRET_HOOKS) && defined(GISP_CPU)
|
|
if (!HostDelayKbdInt(scancode))
|
|
{ /* no host need to delay this kbd int, so generate one now. */
|
|
do_int ((long) scancode);
|
|
}
|
|
|
|
#else /* !IRET_HOOKS || !GISP_CPU */
|
|
|
|
#ifdef DELAYED_INTS
|
|
do_int ((long) scancode);
|
|
#else
|
|
add_q_event_i( do_int, HOST_KEYBA_INST_DELAY, (long)scancode);
|
|
#endif /* DELAYED_INTS */
|
|
|
|
#endif /* IRET_HOOKS && GISP_CPU */
|
|
}
|
|
|
|
|
|
/* typematic keyboard repeats */
|
|
|
|
GLOBAL VOID do_key_repeats IFN0()
|
|
{
|
|
#ifndef REAL_KBD
|
|
|
|
#ifdef JOKER
|
|
/* If there are characters available, tell Joker... */
|
|
if (kbd_status & 1)
|
|
do_int((long)output_contents);
|
|
#endif
|
|
|
|
if (typematic_key_valid)
|
|
{
|
|
if (repeat_count==repeat_target && repeat_delay_count==repeat_delay_target)
|
|
{
|
|
scan_code_6805_size=make_sizes[keytypes[typematic_key]];
|
|
scan_code_6805_array=make_arrays[typematic_key];
|
|
add_codes_to_6805_buff(scan_code_6805_size,scan_code_6805_array);
|
|
codes_to_translate ();
|
|
repeat_count=0;
|
|
}
|
|
else
|
|
{
|
|
if (repeat_delay_count==repeat_delay_target)
|
|
{
|
|
repeat_count++;
|
|
}
|
|
else
|
|
{
|
|
repeat_delay_count++;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
} /* end of do_key_repeats */
|
|
|
|
#endif /* NTVDM */
|
|
|
|
|
|
LOCAL VOID cmd_to_8042 IFN1(half_word,cmd_code)
|
|
{
|
|
int code_to_send,code_to_send_valid;
|
|
|
|
sure_note_trace1(AT_KBD_VERBOSE,"8042 received cmd:0x%x",cmd_code);
|
|
|
|
code_to_send_valid = FALSE;
|
|
if (waiting_for_next_8042_code)
|
|
{
|
|
switch (next_8042_code_sequence_number)
|
|
{
|
|
case WRITE_8042_CMD_BYTE_SEQUENCE:
|
|
if ( (kbd_status & 0x8) == 0)
|
|
{
|
|
cmd_byte_8042=cmd_code;
|
|
if ( (cmd_byte_8042 & 0x40) == 0)
|
|
{
|
|
translating=FALSE;
|
|
}
|
|
else
|
|
{
|
|
translating=TRUE;
|
|
}
|
|
if ( (cmd_byte_8042 & 0x20) != 0 || (cmd_byte_8042 & 0x10) != 0)
|
|
{
|
|
keyboard_interface_disabled=TRUE;
|
|
}
|
|
else
|
|
{
|
|
keyboard_interface_disabled=FALSE;
|
|
}
|
|
kbd_status &= 0xfb;
|
|
kbd_status |= cmd_byte_8042 & 0x4;
|
|
if ((cmd_byte_8042 & 1) == 0)
|
|
{
|
|
int_enabled=FALSE;
|
|
}
|
|
else
|
|
{
|
|
int_enabled=TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
waiting_for_next_8042_code=FALSE;
|
|
}
|
|
break;
|
|
case WRITE_8042_OUTPUT_PORT_SEQUENCE:
|
|
if ( (kbd_status & 0x8) == 0)
|
|
{
|
|
#ifndef JOKER /* Reset and GateA20 done in hardware for JOKER */
|
|
if ( (cmd_code & 1) == 0)
|
|
{
|
|
host_error(EG_CONT_RESET,ERR_QUIT | ERR_RESET,NULL);
|
|
}
|
|
if ( (cmd_code & 2) == 2)
|
|
{
|
|
#ifdef PM
|
|
if ( !gate_a20_status )
|
|
{
|
|
#ifdef NTVDM
|
|
/* call xms function to deal with A20 */
|
|
xmsDisableA20Wrapping();
|
|
#else
|
|
sas_disable_20_bit_wrapping();
|
|
#endif /* NTVDM */
|
|
gate_a20_status = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( gate_a20_status )
|
|
{
|
|
#ifdef NTVDM
|
|
xmsEnableA20Wrapping();
|
|
#else
|
|
sas_enable_20_bit_wrapping();
|
|
#endif /* NTVDM */
|
|
gate_a20_status = 0;
|
|
}
|
|
#else
|
|
host_error(EG_GATE_A20,ERR_QUIT | ERR_RESET | ERR_CONT,NULL);
|
|
#endif /* PM */
|
|
}
|
|
#endif /* JOKER */
|
|
|
|
if ( (cmd_code & 0x10) == 0)
|
|
{
|
|
int_enabled=FALSE;
|
|
}
|
|
else
|
|
{
|
|
int_enabled=TRUE;
|
|
}
|
|
#ifdef PM
|
|
op_port_remembered_bits=cmd_code & 0x2e;
|
|
#else
|
|
op_port_remembered_bits=cmd_code & 0x2c;
|
|
#endif /* PM */
|
|
}
|
|
else
|
|
{
|
|
waiting_for_next_8042_code=FALSE;
|
|
}
|
|
break;
|
|
} /* end of switch */
|
|
}
|
|
|
|
if (!waiting_for_next_8042_code)
|
|
{
|
|
switch (cmd_code)
|
|
{
|
|
case 0x20:
|
|
/* Read cmd byte */
|
|
code_to_send=cmd_byte_8042;
|
|
code_to_send_valid=TRUE;
|
|
break;
|
|
case 0x60:
|
|
/* Write cmd byte */
|
|
waiting_for_next_8042_code=TRUE;
|
|
next_8042_code_sequence_number=WRITE_8042_CMD_BYTE_SEQUENCE;
|
|
break;
|
|
case 0xaa:
|
|
/* Self Test (always returns 'pass') */
|
|
code_to_send=0x55;
|
|
code_to_send_valid=TRUE;
|
|
break;
|
|
case 0xab:
|
|
/* Interface Test (always returns 'pass') */
|
|
code_to_send=0x00;
|
|
code_to_send_valid=TRUE;
|
|
break;
|
|
case 0xad:
|
|
/* Disable keyboard interface */
|
|
cmd_byte_8042 |= 0x10;
|
|
keyboard_interface_disabled=TRUE;
|
|
break;
|
|
case 0xae:
|
|
/* Enable keyboard interface */
|
|
cmd_byte_8042 &= 0xef;
|
|
if ((cmd_byte_8042 & 0x20) == 0)
|
|
{
|
|
keyboard_interface_disabled=FALSE;
|
|
}
|
|
break;
|
|
case 0xc0:
|
|
/* Read Input Port */
|
|
/* But don't cause an interrupt */
|
|
code_to_send_valid=TRUE;
|
|
break;
|
|
case 0xd0:
|
|
/* Read Output Port */
|
|
code_to_send=0xc1 + op_port_remembered_bits;
|
|
code_to_send_valid=TRUE;
|
|
break;
|
|
case 0xd1:
|
|
/* Write to Output Port */
|
|
waiting_for_next_8042_code=TRUE;
|
|
next_8042_code_sequence_number=WRITE_8042_OUTPUT_PORT_SEQUENCE;
|
|
break;
|
|
case 0xe0:
|
|
/* Read Test Input */
|
|
code_to_send=0x02;
|
|
code_to_send_valid=TRUE;
|
|
break;
|
|
|
|
#ifndef JOKER /* Reset and GateA20 done in hardware for JOKER */
|
|
case 0xf0:
|
|
case 0xf1:
|
|
case 0xf2:
|
|
case 0xf3:
|
|
case 0xf4:
|
|
case 0xf5:
|
|
case 0xf6:
|
|
case 0xf7:
|
|
case 0xf8:
|
|
case 0xf9:
|
|
case 0xfa:
|
|
case 0xfb:
|
|
case 0xfc:
|
|
case 0xfd:
|
|
case 0xfe:
|
|
case 0xff:
|
|
|
|
#ifndef MONITOR
|
|
/*
|
|
* For reasons which I don't understand the monitor never
|
|
* did emulate the cpu_interrupt - HW_RESET in pr 1.0.
|
|
* and still doesn't in 1.0a. although maybe it should
|
|
* do something. Note this is required for 286 style pm.
|
|
* 06-Dec-1993 Jonle
|
|
*
|
|
*/
|
|
|
|
/* Pulse Output Port bits */
|
|
|
|
if ((cmd_code & 1) == 0)
|
|
{
|
|
/* pulse the reset line */
|
|
#ifdef PM
|
|
#ifndef NTVDM
|
|
reset_was_by_kbd = TRUE;
|
|
#endif
|
|
#ifdef CPU_30_STYLE
|
|
cpu_interrupt(CPU_HW_RESET, 0);
|
|
#else /* CPU_30_STYLE */
|
|
cpu_interrupt_map |= CPU_RESET_EXCEPTION_MASK;
|
|
host_cpu_interrupt();
|
|
#endif /* CPU_30_STYLE */
|
|
#endif
|
|
sure_note_trace0(AT_KBD_VERBOSE,"CPU RESET via keyboard");
|
|
}
|
|
#endif /* ! MONITOR */
|
|
break;
|
|
#endif /* JOKER */
|
|
|
|
} /* end of switch */
|
|
}
|
|
else
|
|
{
|
|
waiting_for_next_8042_code=FALSE;
|
|
}
|
|
|
|
|
|
/*Is there a valid code to put in the 8042 output buffer? Values written
|
|
to the 8042 output buffer as a conseqence of a 8042 command do not
|
|
generate an interrupt. Output generated by 8042 commands must be presented to
|
|
the application at the next INB, failure to do so it likely to result in the
|
|
8042 being placed in an unusable state. */
|
|
|
|
if (code_to_send_valid)
|
|
{
|
|
#ifdef NTVDM
|
|
/*
|
|
* force filling of Kbd data port just like the real kbd
|
|
* since we no longer clear output_full in the Kbd_inb routine
|
|
*/
|
|
output_full = FALSE;
|
|
KbdData = -1;
|
|
#else /* NTVDM else */
|
|
|
|
/* Transfer 8042 command output to output buffer, overwriting value
|
|
already in the buffer. */
|
|
|
|
output_contents = (char)code_to_send;
|
|
kbd_status |= 1; /* Character now available! */
|
|
|
|
#endif /* end of NTVDM else */
|
|
}
|
|
|
|
} /* end of cmd_to_8042 */
|
|
|
|
|
|
|
|
|
|
LOCAL half_word translate_6805_8042 IFN0()
|
|
{
|
|
|
|
half_word first_code,code;
|
|
|
|
/* performs the translation on scan codes which is done by the
|
|
8042 keyboard controller in a real XT286 */
|
|
|
|
first_code=remove_from_6805_buff();
|
|
|
|
if (translating)
|
|
{
|
|
sure_note_trace1(AT_KBD_VERBOSE,"translating code %#x",first_code);
|
|
if (first_code==0xf0)
|
|
{
|
|
if (free_6805_buff_size<BUFF_6805_VMAX) {
|
|
code=remove_from_6805_buff();
|
|
sure_note_trace1(AT_KBD_VERBOSE,"translating code %#x",code);
|
|
if ((code != 0xfa) && (code != 0xfe)) {
|
|
code=trans_8042[code]+0x80;
|
|
}
|
|
else {
|
|
waiting_for_upcode=TRUE;
|
|
}
|
|
sure_note_trace1(AT_KBD_VERBOSE,"translated to %#x",code);
|
|
waiting_for_upcode=FALSE;
|
|
}
|
|
else {
|
|
waiting_for_upcode=TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
code=trans_8042[first_code];
|
|
if (waiting_for_upcode) {
|
|
if ((code !=0xfa) &&(code != 0xfe)){
|
|
code+=0x80;
|
|
waiting_for_upcode=FALSE;
|
|
}
|
|
}
|
|
sure_note_trace1(AT_KBD_VERBOSE,"translated to %#x",code);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
code=first_code;
|
|
}
|
|
return (code);
|
|
} /* end of translate_6805_8042 */
|
|
|
|
#ifdef HUNTER
|
|
/*
|
|
** Put a scan code into the 8042 single char buffer.
|
|
** Called from do_hunter() in hunter.c
|
|
*/
|
|
|
|
#define HUNTER_REJECTED_CODES_LIMIT 100
|
|
|
|
int hunter_codes_to_translate IFN1( half_word, scan_code )
|
|
{
|
|
LOCAL ULONG rejected_scan_codes = 0;
|
|
|
|
sure_note_trace1(HUNTER_VERBOSE,"Requesting scan=%d",scan_code);
|
|
|
|
if (!pending_8042 && !keyboard_interface_disabled && !output_full)
|
|
{
|
|
do_q_int(scan_code);
|
|
sure_note_trace1( HUNTER_VERBOSE, "Accepted scan=%d", scan_code );
|
|
|
|
rejected_scan_codes = 0;
|
|
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
sure_note_trace0( HUNTER_VERBOSE, "Rejected scan" );
|
|
|
|
if( rejected_scan_codes++ > HUNTER_REJECTED_CODES_LIMIT )
|
|
{
|
|
printf( "Application hung up - not reading scan codes\n" );
|
|
printf( "Trapper terminating\n" );
|
|
|
|
terminate();
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
} /* end of hunter_codes_to_translate() */
|
|
|
|
#endif /* HUNTER */
|
|
|
|
/*
|
|
** Returns number of chars in buffer.
|
|
** As buffer is quite small there can either be 1 char or none in it.
|
|
* This needs to be global for HUNTER, but only needs be local otherwise.
|
|
*/
|
|
#ifdef HUNTER
|
|
GLOBAL INT
|
|
#else
|
|
LOCAL INT
|
|
#endif
|
|
buffer_status_8042 IFN0()
|
|
{
|
|
if (!pending_8042 && !keyboard_interface_disabled && !output_full)
|
|
return( 0 );
|
|
else
|
|
return( 1 );
|
|
} /* END 8042_buffer_status() */
|
|
|
|
LOCAL VOID codes_to_translate IFN0()
|
|
{
|
|
char tempscan;
|
|
|
|
while (!pending_8042 && (free_6805_buff_size < BUFF_6805_VMAX) && !keyboard_interface_disabled && !output_full)
|
|
{
|
|
tempscan= translate_6805_8042();
|
|
if (!waiting_for_upcode) {
|
|
do_q_int(tempscan);
|
|
}
|
|
}
|
|
} /* end of codes_to_translate */
|
|
|
|
/* Thanks to Jonathan Lew of MS for code tidyup in this fn */
|
|
GLOBAL VOID continue_output IFN0()
|
|
{
|
|
char tempscan;
|
|
|
|
#ifdef NTVDM
|
|
if (bKbdEoiPending || keyboard_interface_disabled) {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if(!output_full)
|
|
{
|
|
if (pending_8042)
|
|
{
|
|
pending_8042=FALSE;
|
|
do_q_int(pending_8042_value);
|
|
}
|
|
else
|
|
{
|
|
if ((free_6805_buff_size < BUFF_6805_VMAX) && (!keyboard_interface_disabled))
|
|
{
|
|
tempscan=translate_6805_8042();
|
|
if (!waiting_for_upcode) {
|
|
do_q_int(tempscan);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#ifdef NTVDM
|
|
else
|
|
KbdIntDelay();
|
|
#endif
|
|
|
|
} /* end of continuous_output */
|
|
|
|
|
|
#ifdef NTVDM
|
|
|
|
/* NT port:
|
|
* the host (nt_event.c) calls this to notify that
|
|
* it is resuming after blocking, to do any reinitialization
|
|
* necessary
|
|
*
|
|
* - resets kbd flow regulators
|
|
*/
|
|
GLOBAL VOID KbdResume(VOID)
|
|
{
|
|
WaitKbdHdw(0xffffffff);
|
|
bKbdEoiPending = FALSE;
|
|
bKbdIntHooked = FALSE;
|
|
bBiosBufferSpace = TRUE;
|
|
if (!keyboard_interface_disabled && output_full)
|
|
KbdIntDelay();
|
|
HostReleaseKbd();
|
|
}
|
|
#endif /* NTVDM */
|
|
|
|
|
|
#ifndef NTVDM
|
|
/* allowRefill -- used in conjunction with the Delayed Quick Event
|
|
** below (kbd_inb from port 0x60 while the keyboard interface is
|
|
** enabled.) This is called 10ms after a dubious read from port 0x60
|
|
** and allows the port to be overwritten with the next scancode.
|
|
*/
|
|
|
|
LOCAL VOID allowRefill IFN1(long, unusedParam)
|
|
{
|
|
UNUSED(unusedParam);
|
|
|
|
/* Clear "refillDelayedHandle" so we know we're all clear... */
|
|
|
|
refillDelayedHandle = 0;
|
|
|
|
/* continue with filling the buffer... */
|
|
continue_output();
|
|
}
|
|
#endif
|
|
|
|
GLOBAL VOID kbd_inb IFN2(io_addr,port,half_word *,val)
|
|
{
|
|
sure_note_trace1(AT_KBD_VERBOSE,"kbd_inb(%#x)...", port);
|
|
|
|
#ifdef NTVDM /* JonLe NTVDM Mod */
|
|
|
|
if (!bBiosOwnsKbdHdw && WaitKbdHdw(0xffffffff)) {
|
|
return;
|
|
}
|
|
|
|
|
|
if (!(DelayIrqLine & 0x2) || KbdData == -1) {
|
|
if (bDelayIntPending) {
|
|
bDelayIntPending = FALSE;
|
|
kbd_status |= 1;
|
|
}
|
|
KbdData = output_contents;
|
|
|
|
}
|
|
#endif
|
|
|
|
port &= 0x64;
|
|
|
|
if (port==0x64)
|
|
{
|
|
*val = kbd_status;
|
|
}
|
|
else /* port == 0x60 */
|
|
|
|
#ifdef NTVDM /* JonLe NTVDM Mod */
|
|
|
|
{
|
|
|
|
*val=KbdData;
|
|
kbd_status &= 0xfe;
|
|
sure_note_trace1(AT_KBD_VERBOSE,"scan code read:0x%x",*val);
|
|
|
|
|
|
// Sloppy keyboard fix is not needed for the NT port. An EOI
|
|
// hook is used to control priming of the adapter.
|
|
|
|
}
|
|
|
|
if (!bBiosOwnsKbdHdw)
|
|
HostReleaseKbd();
|
|
|
|
#else /* not NTVDM */
|
|
|
|
{
|
|
*val=output_contents;
|
|
|
|
output_full = FALSE;
|
|
|
|
kbd_status &= 0xfe; /* Mask out "char avail" bit */
|
|
|
|
/* Other ports should really clear this IRQ as well, but... */
|
|
|
|
#ifdef JOKER
|
|
ica_clear_int(KEYBOARD_INT_ADAPTER, KEYBOARD_INT_LINE);
|
|
#endif /* JOKER */
|
|
|
|
/* <tur 06-Jul-93> BCN 2040 Replace previous horrible hack with a better one!
|
|
**
|
|
** The following is to cope with programs that read this port more than once
|
|
** expecting the same value each time, while the keyboard interface is ENABLED.
|
|
** On a real PC, this port is filled via a serial connection, and so there's at
|
|
** least a few milliseconds before a new char arrives and the port is overwritten.
|
|
** SoftPC, however, doesn't have this delay; ideally, we'd like to
|
|
** refill the buffer immediately. However, if the keyboard interface is
|
|
** enabled, we should delay refilling the buffer for a few ms.
|
|
*/
|
|
|
|
if (keyboard_interface_disabled) { /* We're in business */
|
|
|
|
/* NB: We have always assumed that anyone reading this port with the
|
|
** Keyboard interface disabled will ONLY READ IT ONCE (like the BIOS.)
|
|
**
|
|
** Since this seems to work, let's just go ahead and refill the buffer.
|
|
** (If any problems show up, we'll just have to do a quick event as in
|
|
** the keyboard interface enabled case below.)
|
|
*/
|
|
|
|
/* If there is an outstanding sloppy read quick event delete it */
|
|
if (refillDelayedHandle) {
|
|
delete_q_event(refillDelayedHandle);
|
|
refillDelayedHandle = 0;
|
|
}
|
|
|
|
continue_output();
|
|
|
|
}
|
|
else { /* keyboard interface is enabled */
|
|
|
|
/* Do not allow port 0x60 to be overwritten for a few milliseconds.
|
|
** Even 10 ms isn't as bad as the two whole timer ticks (100ms) which
|
|
** is what it was doing previously.
|
|
** Keyboard response for some games, including Windows, should now
|
|
** be a good bit better.
|
|
** The original code continued output after the second read of the port
|
|
** with the interface enabled, which seems to imply that no PC apps have
|
|
** been found which read the port more than twice while expecing the same
|
|
** value. However, we now allow for multipe reads of the port, while enabled.
|
|
** Under this circumstance the port will only be re-primed after the quick event
|
|
** from the first sloppy read has been processed.
|
|
*/
|
|
|
|
if (!refillDelayedHandle) /* if we're not already delaying, delay! */
|
|
refillDelayedHandle = add_q_event_t(allowRefill, KBD_CONT_DELAY, 0);
|
|
|
|
}
|
|
|
|
}
|
|
#endif /* NTVDM */
|
|
|
|
sure_note_trace2(AT_KBD_VERBOSE,"...kbd_inb(%#x) returns %#x", port, *val);
|
|
|
|
} /* end of kbd_inb */
|
|
|
|
|
|
|
|
GLOBAL VOID kbd_outb IFN2(io_addr,port,half_word,val)
|
|
{
|
|
sure_note_trace2(AT_KBD_VERBOSE,"kbd_outb(%#x, %#x)", port, val);
|
|
|
|
#ifdef NTVDM
|
|
if (!bBiosOwnsKbdHdw && WaitKbdHdw(0xffffffff))
|
|
{
|
|
return;
|
|
}
|
|
#endif /* NTVDM */
|
|
|
|
port &= 0x64;
|
|
if (port == 0x64)
|
|
{
|
|
kbd_status |= 0x08;
|
|
cmd_to_8042(val);
|
|
}
|
|
else
|
|
{
|
|
cmd_byte_8042 &= 0xef;
|
|
if ( !(cmd_byte_8042 & 0x20) )
|
|
keyboard_interface_disabled=FALSE;
|
|
|
|
kbd_status &= 0xf7;
|
|
if (waiting_for_next_8042_code)
|
|
cmd_to_8042(val);
|
|
else
|
|
cmd_to_6805(val);
|
|
}
|
|
|
|
#ifndef NTVDM /* JonLe NTVDM Mod */
|
|
|
|
if (free_6805_buff_size < BUFF_6805_VMAX)
|
|
codes_to_translate();
|
|
|
|
#else /* NTVDM */
|
|
|
|
bForceDelayInts = TRUE;
|
|
continue_output();
|
|
bForceDelayInts = FALSE;
|
|
|
|
if (!bBiosOwnsKbdHdw)
|
|
HostReleaseKbd();
|
|
|
|
#endif /* NTVDM */
|
|
|
|
} /*end of kbd_outb */
|
|
|
|
#ifndef NTVDM
|
|
/* Nothing seems to call this. I've no idea why it's here ... Simion */
|
|
/* I have been assured that these functions are used by sun - gvdl */
|
|
|
|
GLOBAL int status_6805_buffer IFN0()
|
|
{
|
|
int free_space;
|
|
|
|
free_space = BUFF_6805_VMAX-
|
|
((buff_6805_in_ptr - buff_6805_out_ptr) & BUFF_6805_PMASK);
|
|
if (free_space<0)
|
|
{
|
|
free_space=0;
|
|
sure_note_trace0(AT_KBD_VERBOSE,"Keyboard buffer full");
|
|
}
|
|
return(free_space);
|
|
}
|
|
|
|
/*
|
|
* Name: read_6805_buffer_variables
|
|
*
|
|
* Purpose: To allow the host to access the state of the 6805 buffer
|
|
* This means eg. on Sun that cut/paste can be optimised.
|
|
*
|
|
* Output: *in_ptr - value of the 6805 start pointer.
|
|
* Output: *out_ptr - value of the 6805 end pointer.
|
|
* Output: *buf_size - value of the 6805 buffer size.
|
|
*/
|
|
GLOBAL void read_6805_buffer_variables IFN3(
|
|
int *, in_ptr,
|
|
int *, out_ptr,
|
|
int *, buf_size)
|
|
{
|
|
*in_ptr = buff_6805_in_ptr;
|
|
*out_ptr = buff_6805_out_ptr;
|
|
*buf_size = BUFF_6805_PMASK;
|
|
}
|
|
|
|
GLOBAL VOID insert_code_into_6805_buf IFN1(half_word,code)
|
|
{
|
|
sure_note_trace1(AT_KBD_VERBOSE,"got real keyboard scan code : %#x",code);
|
|
add_codes_to_6805_buff(1,&code);
|
|
sure_note_trace1(AT_KBD_VERBOSE,"new free buf size = %#x",free_6805_buff_size);
|
|
if (code != 0xf0) {
|
|
codes_to_translate();
|
|
}
|
|
}
|
|
#endif /* ! NTVDM */
|
|
|
|
#ifdef SEGMENTATION
|
|
/*
|
|
* The following #include specifies the code segment into which this
|
|
* module will by placed by the MPW C compiler on the Mac II running
|
|
* MultiFinder.
|
|
*/
|
|
#include "SOFTPC_INIT.seg"
|
|
#endif
|
|
|
|
GLOBAL VOID AT_kbd_post IFN0()
|
|
{
|
|
kbd_status = 0x14;
|
|
|
|
#ifndef NTVDM
|
|
/* Clear out any pending keyboard buffer (port 0x60) refill delays */
|
|
refillDelayedHandle = 0;
|
|
#endif
|
|
}
|
|
|
|
#if defined(IRET_HOOKS) && defined(GISP_CPU)
|
|
/*(
|
|
*======================= KbdHookAgain() ============================
|
|
* KbdHookAgain
|
|
*
|
|
* Purpose
|
|
* This is the function that we tell the ica to call when a keybd
|
|
* interrupt service routine IRETs.
|
|
*
|
|
* Input
|
|
* adapter_id The adapter id for the line. (Note the caller doesn't
|
|
* know what this is, he's just returning something
|
|
* we gave him earlier).
|
|
*
|
|
* Outputs
|
|
* return TRUE if there are more interrupts to service, FALSE otherwise.
|
|
*
|
|
* Description
|
|
* Check if we have a delayed scancode, if so then generate the kbd int
|
|
* and return TRUE, else return FALSE
|
|
)*/
|
|
|
|
GLOBAL IBOOL
|
|
KbdHookAgain IFN1(IUM32, adapter)
|
|
{ char scancode;
|
|
|
|
if (HostPendingKbdInt(&scancode))
|
|
{ /* We have a host delayed scancode, so generate a kdb int. */
|
|
sure_note_trace0(AT_KBD_VERBOSE,"callback with saved code");
|
|
output_full = TRUE;
|
|
do_int ((long) scancode);
|
|
return(TRUE); /* more to do */
|
|
}
|
|
else
|
|
{
|
|
sure_note_trace0(AT_KBD_VERBOSE,"no saved data after IRET");
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
#endif /* IRET_HOOKS && GISP_CPU */
|
|
|
|
#ifndef NTVDM
|
|
|
|
GLOBAL VOID AT_kbd_init IFN0()
|
|
{
|
|
int key,i;
|
|
SHORT videoAdapt;
|
|
|
|
sure_note_trace0(AT_KBD_VERBOSE,"AT Keyboard initialisation");
|
|
|
|
#if defined(IRET_HOOKS) && defined(GISP_CPU)
|
|
/*
|
|
* Remove any existing hook call-back, and re-instate it afresh.
|
|
* KbdHookAgain is what gets called on a keyboard int iret.
|
|
*/
|
|
|
|
Ica_enable_hooking(KEYBOARD_INT_LINE, NULL, KEYBOARD_INT_ADAPTER);
|
|
Ica_enable_hooking(KEYBOARD_INT_LINE, KbdHookAgain, KEYBOARD_INT_ADAPTER);
|
|
|
|
/* Host routine to reset any internal data for IRET_HOOK delayed ints. */
|
|
HostResetKdbInts();
|
|
|
|
#endif /* IRET_HOOKS && GISP_CPU */
|
|
|
|
#ifdef macintosh
|
|
if (!make_arrays)
|
|
{
|
|
/* Allocate the world and its mother. Why does something as "simple"
|
|
** as the keyboard require more global data than the video emulation?
|
|
** Just wondering.
|
|
*/
|
|
make_arrays = (half_word **)host_malloc(134*sizeof(half_word *));
|
|
break_arrays = (half_word **)host_malloc(134*sizeof(half_word *));
|
|
set_3_key_state = (half_word *)host_malloc(127*sizeof(half_word));
|
|
key_down_count = (int *)host_malloc(127*sizeof(int));
|
|
scan_codes_temp_area = (half_word *)host_malloc(300*sizeof(half_word));
|
|
}
|
|
#endif /* macintosh */
|
|
|
|
videoAdapt = (ULONG) config_inquire(C_GFX_ADAPTER, NULL);
|
|
|
|
buff_6805_out_ptr=0;
|
|
clear_buff_6805 ();
|
|
key_set=DEFAULT_SCAN_CODE_SET;
|
|
current_light_pattern=0;
|
|
#ifdef REAL_KBD
|
|
send_to_real_kbd(0xf6); /* set default */
|
|
wait_for_ack_from_kb();
|
|
#endif
|
|
host_kb_light_on (7);
|
|
|
|
#ifndef REAL_KBD
|
|
for (key=0;key<127;key++)
|
|
{
|
|
set_3_key_state [key] = set_3_default_key_state [key];
|
|
key_down_count[key]=0;
|
|
}
|
|
repeat_delay_target=2*BASE_DELAY_UNIT;
|
|
repeat_target=DEFAULT_REPEAT_TARGET;
|
|
#endif
|
|
typematic_key_valid = waiting_for_next_code =
|
|
waiting_for_next_8042_code=FALSE;
|
|
shift_on = l_shift_on = r_shift_on=FALSE;
|
|
ctrl_on = l_ctrl_on = r_ctrl_on=FALSE;
|
|
alt_on = l_alt_on = r_alt_on=FALSE;
|
|
waiting_for_upcode=FALSE;
|
|
input_port_val=0xbf;
|
|
if (videoAdapt == MDA || videoAdapt == HERCULES)
|
|
input_port_val |= 0x40;
|
|
kbd_status = 0x10;
|
|
cmd_byte_8042=0x45;
|
|
keyboard_disabled = keyboard_interface_disabled=FALSE;
|
|
op_port_remembered_bits=0xc;
|
|
|
|
#ifdef PM
|
|
if ( gate_a20_status )
|
|
{
|
|
sas_enable_20_bit_wrapping();
|
|
gate_a20_status = 0;
|
|
}
|
|
#endif
|
|
|
|
pending_8042 = output_full = in_anomalous_state=FALSE;
|
|
int_enabled = translating=TRUE;
|
|
scanning_discontinued=FALSE;
|
|
held_event_count=0;
|
|
|
|
io_define_inb(AT_KEYB_ADAPTOR, kbd_inb);
|
|
io_define_outb(AT_KEYB_ADAPTOR, kbd_outb);
|
|
|
|
for (i=KEYBA_PORT_START;i<=KEYBA_PORT_END;i+=2)
|
|
io_connect_port(i, AT_KEYB_ADAPTOR, IO_READ_WRITE);
|
|
|
|
#ifndef REAL_KBD
|
|
init_key_arrays();
|
|
#endif
|
|
|
|
host_kb_light_off (5);
|
|
num_lock_on = TRUE;
|
|
|
|
host_key_down_fn_ptr = host_key_down;
|
|
host_key_up_fn_ptr = host_key_up;
|
|
do_key_repeats_fn_ptr = do_key_repeats;
|
|
|
|
} /* end of AT_kbd_init */
|
|
|
|
#else /* NTVDM */
|
|
|
|
GLOBAL VOID AT_kbd_init()
|
|
{
|
|
int i;
|
|
|
|
sure_note_trace0(AT_KBD_VERBOSE,"AT Keyboard initialisation");
|
|
|
|
clear_buff_6805 ();
|
|
key_set=2;
|
|
|
|
i = 127;
|
|
while (i--)
|
|
set_3_key_state [i] = set_3_default_key_state [i];
|
|
|
|
input_port_val=0xbf;
|
|
kbd_status = 0x10;
|
|
cmd_byte_8042=0x45;
|
|
op_port_remembered_bits=0xc;
|
|
|
|
int_enabled = translating = TRUE;
|
|
|
|
io_define_inb(AT_KEYB_ADAPTOR, kbd_inb);
|
|
io_define_outb(AT_KEYB_ADAPTOR, kbd_outb);
|
|
|
|
for (i=KEYBA_PORT_START;i<=KEYBA_PORT_END;i+=2)
|
|
io_connect_port(i, AT_KEYB_ADAPTOR, IO_READ_WRITE);
|
|
|
|
init_key_arrays();
|
|
|
|
num_lock_on = TRUE;
|
|
host_key_down_fn_ptr = host_key_down;
|
|
host_key_up_fn_ptr = host_key_up;
|
|
|
|
/* Register an EOI hook for the keyboard */
|
|
RegisterEOIHook(KEYBOARD_INT_LINE,KbdEOIHook);
|
|
|
|
|
|
} /* end of AT_kbd_init */
|
|
#endif /* NTVDM */
|