brucee@runx.ips.oz (Bruce Evans) (11/26/88)
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 3 (of 7)."
# Contents: kernel/db/int88.s kernel/db/keyboard.c kernel/db/sym.c
# Wrapped by sys@besplex on Sat Nov 26 06:00:18 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'kernel/db/int88.s' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kernel/db/int88.s'\"
else
echo shar: Extracting \"'kernel/db/int88.s'\" \(6686 characters\)
sed "s/^X//" >'kernel/db/int88.s' <<'END_OF_FILE'
X| int88.s
X
X| exported routines
X
X .define _db
X .define _dbinit
X| .define _exit | DOS only
X| .define .fat | DOS only & Minix cc only
X| .define _main | DOS only
X
X| imported routines
X
X .extern _db_main
X
X| exported variables
X
X| .define begdata | DOS only & Minix cc only
X| .define begbss | DOS only & Minix cc only
X .define _db_stacktop | temp exported for 386 protected mode init
X
X| imported variables
X
X .data
X .extern _db_processor | processor type 86, 186, 286, 386
X .extern _edata
X .extern _end
X .extern _protected
X
XBIOS_DATA_SEG = 0x40
X KB_FLAG = 0x17 | byte
X ALT_SHIFT = 8 | state bits
X CTL_SHIFT = 4
X LEFT_SHIFT = 2
XBREAK_VECTOR = 4*3 | offset for breakpoint interrupt vector
XCLICK_SHIFT = 4 | log2 CLICK_SIZE
XCLICK_SIZE = 16 | allocation unit for TSR's
XCOM_OFFSET = 0x100 | offset of program in an MS DOS .COM file
XDB_DS = 4 | db data seg held here in kernel code seg
XFARI1_CALL = 0xFF | as386 doesn't have far indirect calls yet
XFARI2_CALL = 0x1E
XKEYBOARD_VECTOR = 4*9 | PC BIOS hardware keyboard interrupt number
XMS_DOS = 0x21 | MS DOS main software interrupt number
X TSR = 0x31
XOS = 0x66 | operand size override for 386
XPE = 0x00000001 | protected mode cr0 flag bit for 386
XSSTEP_VECTOR = 4*1 | offset for single step interrupt vector
XSTACK_SIZE = 256
XTF = 0x0100 | trap bit in flags
XVECTOR_SEG = 0 | segment for interrupt vectors
X
X .text
X
X| .space COM_OFFSET | DOS only (COM program)
X
X| enter here for startup code (DOS only)
X
X| _main: | DOS only
X jmp dos_init
X
X| call this to enter db
X| initialisation is done automatically
X
X_db:
X call _dbinit
X int BREAK_VECTOR/4
X ret
X
X_dbinit:
X pushf
X push ax
X call _get_processor
X cmp ax,#386
X jne db_setvect | only support protected mode for 386
X| push eax
X .byte OS
X push ax
X| mov eax,cr0
X .byte 0x0F,0x20,0xC0
X andb al,#PE
X| pop eax
X .byte OS
X pop ax
X jne over_db_setvect | protected init is too hard here, assume it
Xdb_setvect:
X push ds
X call setvect
X pop ds
Xover_db_setvect:
X pop ax
X popf
X ret
X
Xsetvect:
X mov ax,#VECTOR_SEG
X mov ds,ax
X mov ax,#sstep_int
X cli
X mov SSTEP_VECTOR,ax
X mov SSTEP_VECTOR+2,cs
X mov ax,#break_int
X mov BREAK_VECTOR,ax
X mov BREAK_VECTOR+2,cs
X ret | leave ds = VECTOR_SEG and cli
X
X| enter here for hardware keyboard int (DOS only)
X| do a breakpoint if CTRL - ALT - LEFT_SHIFT
X
Xkb_int:
X pushf
X seg cs
X| call far old_kb_vector
X .byte FARI1_CALL
X .byte FARI2_CALL
X .word old_kb_vector
X push ax
X push ds
X mov ax,*BIOS_DATA_SEG
X mov ds,ax
X movb al,KB_FLAG
X andb al,*CTL_SHIFT+ALT_SHIFT+LEFT_SHIFT
X cmpb al,*CTL_SHIFT+ALT_SHIFT+LEFT_SHIFT
X pop ds
X pop ax
X jnz db_iret
X
X| enter here from software breakpoint int
X
Xbreak_int:
X seg cs
X sarb db_enable,*1 | test and set to 0xFF
X jc db_iret | it was and remains set at 0xFF
X seg cs
X movb is_sstep,*0
X j db_int
X
Xdb_iret:
X iret
X
X| enter here from hardware single step int
X
Xsstep_int:
X seg cs
X sarb db_enable,*1
X jc db_iret
X seg cs
X movb is_sstep,*1
X
X| common entry point
X| this code writes to the code segment, so only works in real mode (286/386)
X| it also assumes operand size == 16, again limiting it to real mode
X| but it decides if the processor is a 386 and records 32 bit registers if so
X
X| go through lots of contortions to avoid using current stack
X| an earlier version of db attempted to be reentrant by switching the
X| stack, but that is not feasible because there are too many global
X| variables (like 8K of screen buffers!) which would have to be switched too
X
Xdb_int:
X seg cs
X mov old_ds,ds
X seg cs
X mov ds,DB_DS
X pop old_ip | set up sp:ss:ip:cs:f at top of local stack
X pop old_cs
X pop old_f
X mov old_sp,sp
X mov old_ss,ss
X seg cs
X mov ss,DB_DS
X mov sp,#stacktop
X
X push es | continue setting up local stack
X seg cs
X push old_ds
X push zero | place holder (prepare for not 80386)
X push bp
X pushf | test trace flag
X pop bp | it should be clear (was cleared by int)
X and bp,*TF | but if int is traced it will be set
X jnz to_db_exit | resist attempt to trace self or breakpoint
X
X push ax
X call _get_processor
X mov _db_processor,ax
X cmp ax,#386
X pop ax
X jne save16
X
X| 386, fix up saved flags, ip, sp and bp to 32 bits
X| then save rest of (full 32 bit) regs
X
X .byte OS | operand size override to 32 bits
X pushf | top 16 bits of old flags are current
X add sp,*2 | discard non-current low 16 bits
X pop old_f+2
X mov old_ip+2,*0 | it's too hard to get at ip, assume top is 0
X .byte OS
X push sp
X add sp,*2
X pop old_sp+2 | this should be 0 too
X pop bp
X add sp,*2
X .byte OS
X push bp
X
X .byte OS
X push di
X .byte OS
X push si
X .byte OS
X push dx
X .byte OS
X push cx
X .byte OS
X push bx
X .byte OS
X push ax
X j call_C
X
Xto_db_exit:
X j db_exit
X
Xsave16:
X sub bp,bp
X push bp
X push di
X push bp
X push si
X push bp
X push dx
X push bp
X push cx
X push bp
X push bx
X push bp
X push ax
X
Xcall_C:
X cld | direction UP for C
X mov ax,ds
X mov es,ax | es == ds for C
X seg cs
X push is_sstep
X call _db_main
X add sp,*2
X
X cmp _db_processor,#386
X jnz restore16
X .byte OS
X pop ax
X .byte OS
X pop bx
X .byte OS
X pop cx
X .byte OS
X pop dx
X .byte OS
X pop si
X .byte OS
X pop di
X .byte OS
X pop bp
X seg cs
X pop old_ds
X pop es
X mov ss,old_ss
X .byte OS | fatal if no longer 16 bits?
X mov sp,old_sp
X j db_1exit
X
Xrestore16:
X pop ax
X add sp,*2
X pop bx
X add sp,*2
X pop cx
X add sp,*2
X pop dx
X add sp,*2
X pop si
X add sp,*2
X pop di
X add sp,*2
Xdb_exit:
X pop bp
X add sp,*2
X seg cs
X pop old_ds
X pop es
X mov ss,old_ss
X mov sp,old_sp
X
Xdb_1exit:
X push old_f
X push old_cs
X push old_ip
X seg cs
X mov ds,old_ds
X seg cs
X shlb db_enable,*1 | unset to 0xFE
X jmp db_iret
X
X| some variables are in code seg for more convenient (probably faster) access
X
Xdb_enable:
X .byte 0xFE | special value for test-and-set flag
X .even
X| DB_DS: | DOS only
X .zerow 1
Xis_sstep:
X .word 0 | top half is constant 0
Xold_ds:
X .zerow 1
Xold_kb_vector:
X .zerow 2
X
X| dos_init is only used for DOS initialisation
X| it becomes a safe overflow error for the stack
X
Xdos_init:
X mov DB_DS,ds
X mov di,#_edata
X mov cx,#_end
X sub cx,di
X subb al,al
X cld
X rep
X stob
X call setvect | returns ds = VECTOR_SEG and cli
X les ax,KEYBOARD_VECTOR
X seg cs
X mov old_kb_vector,ax
X seg cs
X mov old_kb_vector+2,es
X mov ax,#kb_int
X mov KEYBOARD_VECTOR,ax
X mov KEYBOARD_VECTOR+2,cs
X sti
X mov dx,#_end+CLICK_SIZE-1
X movb cl,*CLICK_SHIFT
X shr dx,cl
X movb ah,*TSR
X int MS_DOS
X ret
X
X| _exit: | DOS only - should never be called
X| .fat: | DOS only - should never be called
X| j _exit | DOS only
X
X .data
X .even
X| begdata: | DOS only & Minix cc only
Xzero:
X .word 0
Xstack:
X .space STACK_SIZE
Xstacktop:
Xold_sp: | following "old" variables are really on stack
X .zerow 1 | and order is important
X .word 0
Xold_ss:
X .zerow 1
Xold_ip:
X .zerow 1
X .word 0
Xold_cs:
X .zerow 1
Xold_f:
X .zerow 1
X .word 0
X_db_stacktop:
X
X .bss
X| begbss: | DOS only & Minix cc only
END_OF_FILE
if test 6686 -ne `wc -c <'kernel/db/int88.s'`; then
echo shar: \"'kernel/db/int88.s'\" unpacked with wrong size!
fi
# end of 'kernel/db/int88.s'
fi
if test -f 'kernel/db/keyboard.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kernel/db/keyboard.c'\"
else
echo shar: Extracting \"'kernel/db/keyboard.c'\" \(10418 characters\)
sed "s/^X//" >'kernel/db/keyboard.c' <<'END_OF_FILE'
X/* keyboard.c */
X
X#include "const.h"
X#include "keyboard.h"
X
X#define KEYBD 0x60
X#define KBIT 0x80
X#define PORTB 0x61
X
X#define FIRST_RELEASE_CODE 0x80 /* codes below this are keypresses */
X /* from here to 0xff are releases */
X#define PREFIX0 0xe0 /* prefix for single scan code */
X#define PREFIX1 0xe1 /* prefix for double scan code */
X#define N_SCAN_CODES 0x80
X#define RELEASE_CODE_BIT 0x80
X
X/* states, 0 is normal */
X
X#define S_PRE0 1 /* just seen PREFIX0 */
X#define S_PRE1 2 /* just seen PREFIX1 */
X#define S_PRE1A 3 /* just seen PREFIX1-LEFT_CTRL */
X#define S_PRE1B 4 /* just seen PREFIX1-LEFT_SHIFT */
X
X/*
X Ordinary scan codes candidates for re-mapping only.
X The other scan codes are declared in a more localized way in our tables.
X*/
X
X#define SC_DEL 0x53
X#define SC_DN 0x50
X#define SC_END 0x4f
X#define SC_ENTER 0x1c
X#define SC_HOME 0x47
X#define SC_INS 0x52
X#define SC_LEFT 0x4b
X#define SC_LEFT_ALT 0x38
X#define SC_LEFT_CTRL 0x1d
X#define SC_LEFT_SHIFT 0x2a
X#define SC_NUM_SHIFT 0x45
X#define SC_PGDN 0x51
X#define SC_PGUP 0x49
X#define SC_PRTSC 0x37
X#define SC_RIGHT 0x4d
X#define SC_SLASH 0x35
X#define SC_UP 0x48
X
X/*
X Re-mapped scan codes from enhanced keyboard.
X The new codes can be any unique codes < 0x80.
X Our area map, shift map and key maps depend on the choices made.
X*/
X
X#define SC_CPAD_DEL 0x79
X#define SC_CPAD_DN 0x76
X#define SC_CPAD_END 0x75
X#define SC_CPAD_HOME 0x70
X#define SC_CPAD_LEFT 0x73
X#define SC_CPAD_INS 0x78
X#define SC_CPAD_PGDN 0x77
X#define SC_CPAD_PGUP 0x72
X#define SC_CPAD_RIGHT 0x74
X#define SC_CPAD_UP 0x71
X#define SC_NPAD_ENTER 0x7f
X#define SC_NPAD_SLASH 0x7e
X#define SC_PAUSE 0x7d /* 0xe1-LeftCtrl-NumLock-0xe1-<release codes> */
X#define SC_PRINTSCREEN 0x7c /* 0xe1-LeftShift-0x37-0xe0-<release codes> */
X#define SC_RIGHT_ALT 0x7a
X#define SC_RIGHT_CTRL 0x7b
X
X/*
X Map of keyboard areas.
X Cursor Pad 0x70 to 0x79, 0x7e to 0x7f (our re-mapping).
X F1-F10 0x3b to 0x64
X F11-F12 0x57 to 0x58
X Numeric 0x47 to 0x53
X Other 0x54 to 0x7f not C/F/N or Right Alt/Ctrl or (prefix & 0x7f)
X*/
XPRIVATE area_t area_map[N_SCAN_CODES] =
X{
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, FKEY, FKEY, FKEY, FKEY, FKEY,
X FKEY, FKEY, FKEY, FKEY, FKEY, 0, 0, NKEY,
X NKEY, NKEY, NKEY, NKEY, NKEY, NKEY, NKEY, NKEY,
X NKEY, NKEY, NKEY, NKEY, OKEY, OKEY, OKEY, FKEY,
X FKEY, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY,
X 0, 0, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY,
X OKEY, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY, OKEY,
X CKEY, CKEY, CKEY, CKEY, CKEY, CKEY, CKEY, CKEY,
X CKEY, CKEY, 0, 0, OKEY, OKEY, NKEY, NKEY,
X};
X
X/*
X Map of shift scan codes.
X Caps Lock 0x3a
X Ins 0x52
X Ins 0x52 preceded by 0xe0 (state kept is inadequate)
X Left Alt 0x38
X Left Ctrl 0x1d
X Left Shift 0x2a
X Num Lock 0x45
X Right Alt 0x38 preceded by 0xe0
X Right Ctrl 0x1d preceded by 0xe0
X Right Shift 0x36
X Scroll Lock 0x46
X*/
XPRIVATE shift_t shift_map[N_SCAN_CODES] =
X{
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, LEFT_CTRL, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, LEFT_SHIFT, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, RIGHT_SHIFT, 0,
X LEFT_ALT, 0, CAPS_SHIFT, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, NUM_SHIFT, SCROLL_SHIFT, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, INS_SHIFT, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X 0, 0, 0, 0, 0, 0, 0, 0,
X INS_SHIFT, 0, RIGHT_ALT, RIGHT_CTRL, 0, 0, 0, 0,
X};
X
X/*
X Scan codes to ASCII.
X \000 means a special key which is handled by another table.
X The numeric keypad '.' or DEL key is always mapped to DEL.
X The other keypad keys are always mapped to numbers.
X A higher level routine can remap the keypad as it likes using the
X shift state.
X*/
X
X/* Scan codes to ASCII for unshifted keys for PC through enhanced AT */
XPRIVATE unsigned char unshifted[N_SCAN_CODES] =
X{
X 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=','\b',
X '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']','\r',
X 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';','\'', '`',
X 0,'\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*',
X 0, ' ', 0,
X 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
X 0, 0,
X '7', '8', '9', '-',
X '4', '5', '6', '+',
X '1', '2', '3',
X '0', 127,
X 212, 213, 214,
X 'K', 'L',
X 217, 218, 219, 220, 221, 222, 223,
X 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,237,238,239,
X '7', '8', '9',
X '4', '6',
X '1', '2', '3',
X '0', 127,
X 0, 0, '*', 253, '/', '\r',
X};
X/*
X The first 5 rows correspond to rows on the keyboard.
X Function keys return 1234567890 plus their shift flags.
X The numeric keypad returns 789-456+1230..
X Our mapping of enhanced AT codes in disorganized order is at the end.
X*/
X
X/* Scan codes to ASCII for shifted keys for PC through enhanced AT */
XPRIVATE char shifted[N_SCAN_CODES + 1] =
X{
X 0, 27, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+','\b',
X '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}','\r',
X 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':','\"', '~',
X 0, '|', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, '*',
X 0, ' ', 0,
X 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
X 0, 0,
X '7', '8', '9', '-',
X '4', '5', '6', '+',
X '1', '2', '3',
X '0', 127,
X 212, 213, 214,
X 'K', 'L',
X 217, 218, 219, 220, 221, 222, 223,
X 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,237,238,239,
X '7', '8', '9',
X '4', '6',
X '1', '2', '3',
X '0', 127,
X 0, 0, '*', 253, '/', '\r',
X};
X
X/*
X Translate a scan code from a PC-style keyboard for a given shift state.
X All "normal" keys return an ASCII code packed with the shift state.
X*/
X
XPUBLIC void parsecode();
X
X#ifdef DEBUG_KEYBOARD
X
Xmain()
X{
X static struct echar_s ech;
X scancode_pt code;
X scancode_pt oldcode;
X
X oldcode = inportb( KEYBD );
X while ( 1 )
X if ( (code = inportb( KEYBD )) != oldcode )
X {
X parsecode( code, &ech );
X if ( ech.area != RKEY )
X {
X if ( ech.ch == 3 )
X exit( 0 );
X printf( "%c %2d %04x %02x\n",
X ech.ch >= 32 ? ech.ch : 'x', ech.area, ech.shift, ech.ch );
X }
X oldcode = code;
X }
X}
X
X#endif /* DEBUG_KEYBOARD */
X
XPUBLIC void parsecode( code, eptr )
Xscancode_pt code;
Xregister struct echar_s *eptr;
X{
X scancode_pt newcode;
X shift_pt newshift;
X
X eptr->area = RKEY; /* prepare to return early */
X if ( eptr->state != 0 )
X {
X /*
X Re-map known special keys so rest of routine can be table-driven.
X Hardware does it the *wrong* way for backward compatibility.
X */
X newcode = code & ~RELEASE_CODE_BIT;
X switch( eptr->state )
X {
X case S_PRE0:
X switch( newcode )
X {
X case SC_DEL: newcode = SC_CPAD_DEL; break;
X case SC_DN: newcode = SC_CPAD_DN; break;
X case SC_END: newcode = SC_CPAD_END; break;
X case SC_ENTER: newcode = SC_NPAD_ENTER; break;
X case SC_HOME: newcode = SC_CPAD_HOME; break;
X case SC_INS: newcode = SC_CPAD_INS; break;
X case SC_LEFT: newcode = SC_CPAD_LEFT; break;
X case SC_LEFT_ALT: newcode = SC_RIGHT_ALT; break;
X case SC_LEFT_CTRL: newcode = SC_RIGHT_CTRL; break;
X case SC_PGDN: newcode = SC_CPAD_PGDN; break;
X case SC_PGUP: newcode = SC_CPAD_PGUP; break;
X case SC_RIGHT: newcode = SC_CPAD_RIGHT; break;
X case SC_SLASH: newcode = SC_NPAD_SLASH; break;
X case SC_UP: newcode = SC_CPAD_UP; break;
X }
X break;
X case S_PRE1:
X switch( newcode )
X {
X case SC_LEFT_CTRL: eptr->state = S_PRE1A; return;
X case SC_LEFT_SHIFT: eptr->state = S_PRE1B; return;
X }
X break;
X case S_PRE1A:
X if ( newcode == SC_NUM_SHIFT )
X newcode = SC_PAUSE;
X break;
X case S_PRE1B:
X if ( newcode == SC_PRTSC )
X newcode = SC_PRINTSCREEN;
X break;
X }
X if ( code >= FIRST_RELEASE_CODE )
X newcode |= RELEASE_CODE_BIT;
X code = newcode;
X eptr->state = 0;
X }
X
X if ( code == PREFIX0 )
X {
X eptr->state = S_PRE0;
X return;
X }
X if ( code == PREFIX1 )
X {
X eptr->state = S_PRE1;
X return;
X }
X
X if ( code >= FIRST_RELEASE_CODE )
X {
X /* key release, drop shift state if this is a shift key */
X if ( (newshift = (shift_map - FIRST_RELEASE_CODE)[code]) != 0 )
X eptr->shift &= ~newshift;
X return;
X }
X
X /* key press */
X if ( (newshift = shift_map[code]) != 0 &&
X (code != SC_INS || !(eptr->shift & NUM_LOCK)) )
X {
X /* toggle if lock and keypress is new, record shift */
X if ( newshift & (CAPS_SHIFT | INS_SHIFT | NUM_SHIFT | SCROLL_SHIFT) &&
X !(newshift & eptr->shift) )
X /* same ratio for all */
X eptr->shift ^= newshift / (CAPS_SHIFT / CAPS_LOCK);
X eptr->shift |= newshift;
X if ( newshift != INS_SHIFT )
X {
X eptr->area = RKEY;
X return;
X }
X }
X if ( (eptr->area = area_map[code]) != 0 )
X {
X /*
X Non-ASCII key.
X Return it as unique ASCII with nonzero area code.
X Caller can decode it further if required.
X Function keys are converted to letters.
X Numeric keypad keys are converted to numbers and punctuation.
X */
X eptr->ch = unshifted[code];
X return;
X }
X if ( eptr->shift & (LEFT_CTRL | RIGHT_CTRL) &&
X (eptr->ch = shifted[code] - '@') < 0x20 )
X return;
X if ( eptr->shift & (LEFT_SHIFT | RIGHT_SHIFT) )
X eptr->ch = shifted[code];
X else
X eptr->ch = unshifted[code];
X if ( eptr->shift & CAPS_LOCK &&
X (eptr->ch & ~('a' - 'A')) - 'A' <= 'Z' -'A' )
X eptr->ch ^= 'a' - 'A';
X}
X
XPUBLIC scancode_pt scan_keyboard()
X{
X /* fetch character from keyboard hardware and acknowledge it */
X
X scancode_pt code;
X unsigned status;
X
X code = inportb( KEYBD ); /* scan code */
X status = inportb( PORTB ); /* strobe keyboard to acknowledge */
X oportb( PORTB, status | KBIT ); /* strobe high */
X oportb( PORTB, status ); /* strobe low */
X return code;
X}
END_OF_FILE
if test 10418 -ne `wc -c <'kernel/db/keyboard.c'`; then
echo shar: \"'kernel/db/keyboard.c'\" unpacked with wrong size!
fi
# end of 'kernel/db/keyboard.c'
fi
if test -f 'kernel/db/sym.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kernel/db/sym.c'\"
else
echo shar: Extracting \"'kernel/db/sym.c'\" \(7256 characters\)
sed "s/^X//" >'kernel/db/sym.c' <<'END_OF_FILE'
X/* sym.c */
X
X#include "const.h"
X#include "type.h"
X#include "var.h"
X#include "/usr/include/a.out.h" /* full pathname to get right one! */
X
X#define SYMSIZE_MAGIC ((peekoff_t) 2)
X
X#define anticlick( off ) ((off) * CLICK_SIZE)/* good only for unsigned off's */
X#define click( off ) ((off) / CLICK_SIZE)
X#define clickrest( off ) ((unsigned) (off) % CLICK_SIZE)
X#define NSYMPROC 4 /* kernel, mm, fs, init */
X
Xextern unsigned sizes[2 * NSYMPROC];
X
Xstruct symtab_s
X{
X char *stname;
X segment_t stseg;
X struct nlist *start;
X struct nlist *end;
X segment_t text;
X segment_t data;
X unsigned nsym;
X};
X
XPRIVATE struct symtab_s proc_sym[NSYMPROC] =
X{
X { "kernel" }, { "mm" }, { "fs" }, { "init" },
X};
X
XPUBLIC void syminit()
X{
X static bool_t already = FALSE;
X segment_t base;
X int p;
X u16_t symoff;
X register struct symtab_s *tp;
X
X if ( !already )
X {
X already = TRUE;
X info();
X for ( base = codeseg(), tp = &proc_sym[0], p = 0; tp < &proc_sym[NSYMPROC];
X base += sizes[p] + sizes[p + 1], ++tp, p += 2 )
X {
X if ( (symoff = peekw( base, SYMSIZE_MAGIC )) == 0 )
X /* symbols not loaded - p should be 0 so all tables remain null */
X break;
X tp->text = base;
X tp->stseg = (tp->data = base + sizes[p]) + click( symoff );
X tp->start = (struct nlist *) clickrest( symoff );
X tp->nsym = (anticlick( sizes[p + 1] ) - symoff) / sizeof (struct nlist);
X tp->end = tp->start + tp->nsym;
X /* sort on value only, name search not used much and storage a problem */
X outstr( "Sorting " );
X outh16( tp->nsym );
X outspace();
X outstr( tp->stname );
X outstr( " symbols ... " );
X sortsyms( tp->start, tp->end, tp->stseg );
X outnl();
X }
X }
X}
X
XPRIVATE struct nlist *buildsym( sp, tableseg )
Xstruct nlist *sp;
Xsegment_t tableseg;
X{
X static struct nlist sym;
X register char *s;
X register char *t;
X char *tend;
X
X for ( s = sp->n_name, t = sym.n_name, tend = t + sizeof sym;
X t < tend; ++s, ++t )
X *t = peekb( tableseg, (peekboff_t) s );
X return &sym;
X}
X
XPUBLIC struct nlist *findsname( name, where, allflag )
Xchar *name;
Xint where;
Xbool_pt allflag;
X{
X struct nlist *matchsp;
X char *s;
X unsigned char sclass;
X int schar;
X char *send;
X register struct nlist *sp;
X segment_t tableseg;
X register struct symtab_s *tp;
X
X for ( tp = &proc_sym[0]; tp < &proc_sym[NSYMPROC]; ++tp )
X /* find process to use */
X if ( tp->text == uptr.seg )
X {
X if ( allflag )
X {
X /* find and print all matching symbols */
X for ( sp = tp->start, tableseg = tp->stseg; sp < tp->end; ++sp )
X {
X if ( symprefix( name, sp, tableseg ) )
X {
X matchsp = buildsym( sp, tableseg );
X for ( s = matchsp->n_name, send = s + sizeof matchsp->n_name;
X *s != 0 && s < send; ++s )
X outbyte( *s );
X for ( ; s <= send; ++s )
X outspace();
X switch( matchsp->n_sclass & N_SECT )
X {
X case N_ABS: schar = 'a'; break;
X case N_TEXT: schar = 't'; break;
X case N_DATA: schar = 'd'; break;
X case N_BSS: schar = 'b'; break;
X default: schar = '?'; break;
X }
X if ( (matchsp->n_sclass & N_CLASS) == C_EXT && schar != '?' )
X schar += 'A' - 'a';
X outbyte( schar );
X outspace();
X outh16( (u16_t) matchsp->n_value );
X if ( !outnl() )
X break;
X }
X }
X return NULL;
X }
X else
X {
X /* find symbol by dumb linear search */
X for ( sp = tp->start, tableseg = tp->stseg; sp < tp->end; ++sp )
X {
X sclass = peekw( tableseg, (peekoff_t) &sp->n_sclass ) & N_SECT;
X if ( (where == CSEG && sclass == N_TEXT ||
X where != CSEG && (sclass == N_DATA || sclass == N_BSS)) &&
X symeq( name, sp, tableseg ) )
X return buildsym( sp, tableseg );
X }
X return NULL;
X }
X }
X return NULL;
X}
X
XPUBLIC struct nlist *findsval( value, where )
Xoffset_t value;
Xint where;
X{
X int left;
X int middle;
X int right;
X unsigned char sclass;
X register struct nlist *sp;
X segment_t tableseg;
X register struct symtab_s *tp;
X
X for ( tp = &proc_sym[0]; tp < &proc_sym[NSYMPROC]; ++tp )
X /* find process to use */
X if ( tp->text == uptr.seg )
X {
X prompt = *tp->stname;
X /* find last symbol with value <= desired one by binary search */
X for ( left = 0, right = tp->nsym - 1, tableseg = tp->stseg;
X left <= right; )
X {
X middle = (left + right) / 2;
X sp = tp->start + middle;
X if ( value < peekw( tableseg, (peekoff_t) &sp->n_value ) )
X right = middle - 1;
X else
X left = middle + 1;
X }
X if ( right >= 0 )
X /* otherwise tp->start + right may wrap around to > tp->start !! */
X for ( sp = tp->start + right; sp >= tp->start; --sp )
X {
X sclass = peekw( tableseg, (peekoff_t) &sp->n_sclass ) & N_SECT;
X if ( (where == CSEG && sclass == N_TEXT ||
X where != CSEG && (sclass == N_DATA || sclass == N_BSS)) )
X return buildsym( sp, tableseg );
X }
X return NULL;
X }
X if ( where == CSEG )
X prompt = '?';
X return NULL;
X}
X
XPUBLIC void outsym( sp, off )
Xstruct nlist *sp;
Xoffset_t off;
X{
X register char *s;
X char *send;
X
X for ( s = sp->n_name, send = s + sizeof sp->n_name; *s != 0 && s < send; ++s )
X outbyte( *s );
X if ( (off -= sp->n_value) != 0 )
X {
X outbyte( '+' );
X if ( off >= 65536L )
X outh32( off );
X else if ( off >= 256 )
X outh16( (u16_t) off );
X else
X outh8( (u8_pt) off );
X }
X}
X
XPUBLIC void setproc( c, pdptr, pmptr )
Xchar_pt c;
Xstruct adr *pdptr;
Xstruct adr *pmptr;
X{
X register struct symtab_s *tp;
X
X for ( tp = &proc_sym[0]; tp < &proc_sym[NSYMPROC]; ++tp )
X if ( tp->stname[0] == c )
X {
X uptr.seg = tp->text;
X pmptr->seg = pdptr->seg = tp->data;
X prompt = c;
X return;
X }
X}
X
X/* shell sort symbols on value */
X
XPRIVATE void sortsyms( array, top, tableseg )
Xstruct nlist *array;
Xstruct nlist *top;
Xsegment_t tableseg;
X{
X int gap;
X int i;
X int j;
X register struct nlist *left;
X register struct nlist *right;
X int size;
X
X size = top - array;
X /* choose gaps according to Knuth V3 p95 */
X for ( gap = 1, i = 4; (j = 3 * i + 1) < size; gap = i, i = j )
X ;
X do
X {
X for ( j = gap; j < size; ++j )
X for ( i = j - gap; i >= 0; i -= gap )
X {
X left = array + i;
X right = array + (i + gap);
X if ( (unsigned) peekw( tableseg, (peekoff_t) &left->n_value )
X <= peekw( tableseg, (peekoff_t) &right->n_value ) )
X break;
X symswap( left, right, tableseg, sizeof *left );
X }
X }
X while ( (gap /= 3) != 0 );
X}
X
XPRIVATE bool_pt symeq( t, sp, tableseg )
Xregister char *t;
Xstruct nlist *sp;
Xsegment_t tableseg;
X{
X register char *s;
X char *send;
X
X for ( s = sp->n_name, send = s + sizeof sp->n_name; s < send; ++s, ++t )
X if ( *t != peekb( tableseg, (peekboff_t) s ) )
X return FALSE;
X return TRUE;
X}
X
XPRIVATE bool_pt symprefix( t, sp, tableseg )
Xregister char *t;
Xstruct nlist *sp;
Xsegment_t tableseg;
X{
X register char *s;
X char *send;
X
X for ( ; *t == '_'; ++t )
X ;
X for ( s = sp->n_name, send = s + sizeof sp->n_name;
X s < send && peekb( tableseg, (peekboff_t) s ) == '_'; ++s )
X ;
X for ( ; *t != 0 && s < send; ++s, ++t )
X if ( *t != peekb( tableseg, (peekboff_t) s ) )
X return FALSE;
X return TRUE;
X}
X
X#ifdef LINT
X
X/* prototypes for assembler functions */
X
X/* ARGSUSED */
XPRIVATE void symswap( left, right, tableseg, length )
Xstruct nlist *left;
Xstruct nlist *right;
Xsegment_t tableseg;
Xunsigned length; /* must be even */
X{
X}
X
X#endif
END_OF_FILE
if test 7256 -ne `wc -c <'kernel/db/sym.c'`; then
echo shar: \"'kernel/db/sym.c'\" unpacked with wrong size!
fi
# end of 'kernel/db/sym.c'
fi
echo shar: End of archive 3 \(of 7\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 7 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
Bruce Evans
Internet: brucee@runx.ips.oz.au UUCP: uunet!runx.ips.oz.au!brucee