Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 86/CONCURRENT/CCPM-86 3.1 SOURCE/D4/XBEGIN.LIB
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1501 lines
37 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

eject ; Dec 13, 1983
; SYSTEM INFO
; -----------
;************************************************
;* *
;* CCP/M-86 SYSTEM DATA AREA FORMAT *
;* *
;************************************************
dseg
org 0
supmod rw 2
org 038h
dispatcher rw 2
org 040h
mpmseg rw 1
org 044h
endseg rw 1
org 04ah
n_flags rb 1 ;total number of system flags
sys_disk rb 1 ;system disk number patched at init
org 050h
temp_disk rb 1 ;temporary disk number patched at init
org 058h
mdul rw 1 ;root of unused memory descriptors
mfl rw 1 ;root of memory free list
org 068h
rlr rw 1
org 072h
thrdrt rw 1
qlr rw 1
org 078h
version rw 1
vernum rw 1
mpmvernum rw 1
tod_day rw 1 ;binary days since january 1 1978
tod_hour rb 1 ;bcd
tod_min rb 1 ;bcd
tod_sec rb 1 ;bcd
org 088h
open_vec rw 1 ;16 bit vector of drives with open
;files - used by status line routine
rw 1 ;reserved
owner_8087 dw 0FFFFh ;process descriptor of 8087 owner
org 0A0h
ndp_int_off rw 1 ;offset of 8087 interrupt vector
ndp_int_seg rw 1 ;segment of same
ndp_vec_off rw 1 ;offset of 8087 interrupt entry
ndp_vec_seg rw 1 ;segment of same
;********************************************************
;* *
;* CCP/M-86 SYSTEM EQUATES *
;* *
;********************************************************
true equ 0ffffh
false equ 0
; CCP/M-86 system calls used by the XIOS
;process control functions:
p_delay equ 141 ;delay specified number of ticks
p_dispatch equ 142 ;let other another process run
p_pdadr equ 156 ;dbl word ptr of process descriptor
p_term equ 143 ;terminate process
;device control functions:
dev_poll equ 131 ;poll device
dev_flagwait equ 132 ;flag wait
dev_flagset equ 133 ;flag set
;Time function:
t_seconds equ 155 ;get date,hours,minutes,seconds
; Definition of flag table used by by CCP/M and this XIOS
;0 - is reserved
tick_flag equ 1 ;tick flag number
sec_flag equ 2 ;seconds flag number
min_flag equ 3 ;minutes flag number
;XIOS flags:
fdc_flag equ 4 ;disk operation flag
ci_flag equ 5 ;console in flag
ww_flag equ 6 ;window manager flag
er_flag equ 7 ;get errror response
s_in0_flag equ 8 ;serial input port 0
s_out0_flag equ 9 ;serial output port 0
s_in1_flag equ 10 ;serial input port 1
s_out1_flag equ 11 ;serial output port 0
screen_flag equ 12 ;graphics mode switch
last_flag equ 12
;********************************************************
;* *
;* PROCESS DESCRIPTOR *
;* *
;********************************************************
; The Process Descriptor (PD) along with the
; associated User Data Area (UDA), describe
; the current state of a Process under CCP/M-86.
; The process descriptor is always within the System
; Data Segment.
; Process Descriptor:
; +-----+-----+-----+-----+-----+-----+-----+-----+
; 00| link | thread |stat |prior| flag |
; +-----+-----+-----+-----+-----+-----+-----+-----+
; 08| name |
; +-----+-----+-----+-----+-----+-----+-----+-----+
; 10| uda |disk | user| reserved |
; +-----+-----+-----+-----+-----+-----+-----+-----+
; 18| resereved | parent |
; +-----+-----+-----+-----+-----+-----+-----+-----+
; 20|cons | reserved |list | reserved |
; +-----+-----+-----+-----+-----+-----+-----+-----+
; 28| reserved |
; +-----+-----+-----+-----+-----+-----+-----+-----+
; link - used for placement into System Lists
; thread - link field for Thread List
; stat - current process activity
; prior - priority
; flag - process state flags
; name - name of process
; uda - segment address of user data area
; disk - current default disk
; user - current default user number
; mem - pointer to MD list of memory owned
; by this process
; parent - process that created this process
; cons - default console device (doesn't imply ownership)
; list - default list device (doesn't imply ownership)
p_link equ word ptr 0
p_thread equ word ptr p_link + word
p_stat equ byte ptr p_thread + word
p_prior equ byte ptr p_stat + byte
p_flag equ word ptr p_prior + byte
p_name equ byte ptr p_flag + word
p_uda equ word ptr p_name + 8
p_disk equ byte ptr p_uda + word
p_user equ byte ptr p_disk + byte
p_mem equ word ptr p_user + 3
p_parent equ word ptr p_mem + 8
p_cons equ byte ptr p_parent + word
p_list equ byte ptr p_cons + 4
pd_len equ 30H
; Values of Process descriptor p_status field:
ps_run equ 0 ;in ready list root
ps_poll equ 1 ;in poll list
ps_delay equ 2 ;in delay list
ps_swap equ 3 ;in swap list
ps_term equ 4 ;terminating
ps_sleep equ 5 ;sleep processing
ps_dq equ 6 ;in dq list
ps_nq equ 7 ;in nq list
ps_flagwait equ 8 ;in flag table
ps_ciowait equ 9 ;waiting for character
; Bit flags in Process descriptor p_flag field:
pf_sys equ 00001h ;system process
pf_keep equ 00002h ;do not terminate
pf_kernal equ 00004h ;resident in kernal
pf_pure equ 00008h ;pure memory descibed
pf_table equ 00010h ;from pd table
pf_resource equ 00020h ;waiting for resource
pf_raw equ 00040h ;raw console i/o
pf_ctlc equ 00080h ;abort pending
pf_active equ 00100h ;active tty
pf_tempkeep equ 00200h ;don't terminate yet...
pf_ctld equ 00400h ;explicit detach occured
pf_childabort equ 00800h ;child terminated abnormally
pf_noctls equ 01000h ;control S not allowed
pf_dskld equ 02000h ;process was loaded from disk
;************************************************
;*
;* Virtual Console Control Block Definition
;*
;* +---------+---------+---------+---------+
;* 00 | owner | reserved |
;* +---------+---------+---------+---------+
;* 04 | reserved |
;* +---------+---------+---------+---------+
;* 08 | mimic | reserved |
;* +---------+---------+---------+---------+
;* 0C | reserved | state |
;* +---------+---------+---------+---------+
;* 10 | maxbufsiz | reserved |
;* +---------+---------+---------+---------+
;* 14 | reserved |
;* +---------+---------+---------+---------+
;* 18 | reserved |
;* +---------+---------+---------+---------+
;* 1C | reserved |
;* +---------+---------+---------+---------+
;* 20 | reserved |
;* +---------+---------+---------+---------+
;* 24 | reserved |
;* +---------+---------+---------+---------+
;* 28 | reserved |
;* +---------+---------+---------+---------+
;*
;*
;*
;* owner - current owner of device
;* if 0, no owner
;* mimic - list dev that mimics us.
;* 0ffh means no mimic device
;* state - current state of virtual console
;* maxbufsiz - maximum file size for buffered mode
c_owner equ word ptr 00h
c_mimic equ byte ptr 08h
c_state equ word ptr 0Eh
c_maxbufsiz equ word ptr 10h
ccblen equ 2ch
;CCB state flags
csm_buffered equ 00001h
csm_background equ 00002h
csm_purging equ 00004h
csm_noswitch equ 00008h
csm_suspend equ 00010h
csm_abort equ 00020h
csm_filefull equ 00040h
csm_ctrlS equ 00080h
csm_ctrlO equ 00100h
csm_ctrlP equ 00200h
; Memory Descriptor Format for Init memory trimming
md_link equ word ptr 0
md_start equ word ptr md_link + word
md_length equ word ptr md_start + word
;*******************************************************
;* *
;* 8087 NUMERIC DATA PROCESSOR CODEMACROS *
;* *
;********************************************************
codemacro FNINIT
dw 0e3dbh
endm
codemacro FNDISI
dw 0e1dbh
endm
codemacro FNSTCW dst:Mw
segfix dst
db 0d9h
modrm 7,dst
endm
codemacro FNCLEX
dw 0e2dbh
endm
codemacro FNSTENV dst:M
segfix dst
db 0d9h
modrm 6,dst
endm
codemacro FLDENV src:M
db 9bh
segfix src
db 0d9h
modrm 4,src
endm
FWAIT equ WAIT
;****************************************************************
;* *
;* 8259 PROGRAMMABLE INTERRUPT CONTROLLER COMMANDS *
;* AND PORTS *
;* *
;****************************************************************
ticks_per_second equ 60
pic_ocw_port equ 020h ;port 0
pic_ocw_nseoi equ 020h ;non specific end of interupt
pic_ocw_seoi equ 060h ;specific end of interupt channel 0
disk_channel equ 06h
keyboard_channel equ 01h
timer_channel equ 00h
;************************************************
;* *
;* ASCII CODES *
;* *
;************************************************
nul equ 00h
soh equ 01h
stx equ 02h
etx equ 03h
eot equ 04h
enq equ 05h
ack equ 06h
bel equ 07h
bs equ 08h
ht equ 09h
lf equ 0ah
vt equ 0bh
ff equ 0ch
cr equ 0dh
so equ 0eh
shi equ 0fh
dle equ 10h
dc1 equ 11h
dc2 equ 12h
dc3 equ 13h
dc4 equ 14h
nak equ 15h
syn equ 16h
etb equ 17h
can equ 18h
em equ 19h
subb equ 1ah
esc equ 1bh
fs equ 1ch
gs equ 1dh
rds equ 1eh
us equ 1fh
del equ 7fh
xon equ dc1
xoff equ dc3
eject
; XIOS HEADER AND INTERFACE
; -------------------------
;************************************************
;* *
;* XIOS HEADER *
;* *
;************************************************
cseg
org 0C00h ;8080 model XIOS base
;CCP/M-86 entry points to XIOS:
jmp init ;called once at system boot
jmp entry ;subsequent calls go through here
reorg1 equ offset $
dseg
org reorg1
num_vir_cons equ 4 ;number of virtual consoles
sysdat dw 0
supervisor_o rw 1
supervisor_s rw 1
supervisor equ dword ptr supervisor_o
tick db false
ticks_sec db 60
door db false
db 0 ;reserved
npcns db 1 ;1 physical console
nvcns db num_vir_cons ;4 virtual consoles
nccb db 4 ;total number of ccbs
nlcb db 5 ;5 list devices
ccb dw offset ccb_tab ;pointer to the first ccb
lcb dw offset lcb_tab ;pointer to the first lcb
; This table of disk parameter header offsets is used by
; genccpm for internal allocations. It gets modified by
; the INIT routine to match the actual physical drives.
dph_tbl dw dph0,dph1 ; A: B: floppies
dw dph2,dph3 ; C: D: floppies
dw hd_dph0,hd_dph1 ; E: F: hard disks
dw 0,0,0,0,0,0 ; G: - L:
md_dph dw dph_md ; M: memory disk
dw 0,0,0 ; N: - P:
genccpm_buf dw buffer_size/16
debug db false ;save debugger interrupts
;********************************************************
;* *
;* INTERFACE TO CCP/M O.S. *
;* *
;********************************************************
reorg2 equ offset $
cseg
org reorg2
;=====
;=====
entry: ;arrive here from JMP at
;===== ;03H in XIOS code segment
;=====
; Note: no alteration of stack is allowed during entry except
; for the return address caused by the "call function_table[bx]"
; instruction.
cld ;set the direction flag
cbw ;ah = 0
shl al,1 ;multiply by 2
xchg bx,ax ;save bx in ax
call function_table[bx] ;no range checking needed
mov bx,ax ;only called by O.S.
retf ;return to O.S. kernel
function_table:
dw io_const ; 0 console status
dw io_conin ; 1 console input
dw io_conout ; 2 console output
dw io_listst ; 3 list status
dw io_list ; 4 list output
dw io_auxin ; 5 auxillary input
dw io_auxout ; 6 auxillary out
dw io_switch ; 7 switch screen
dw io_statline ; 8 update or print new status
dw io_seldsk ; 9 select disk
dw io_read ;10 read logical sector
dw io_write ;11 write logical sector
dw io_flushbuf ;12 flush buffers
dw io_poll ;13 poll device
dw io_pointer ;14 general pointer return
dw io_format ;15 format floppy track
; back door window control entry points
dw ww_pointer ;16 return data pointers
dw ww_key ;17 wait for a key
dw ww_statline ;18 char/attib status line
dw ww_im_here ;19 window process state
dw ww_new_window ;20 redefine a window
dw ww_cursor_view ;21 track mode, viewpoint
dw ww_wrap_column ;22 set wrap around column
dw ww_full_window ;23 same as full key
dw ww_switch_display ;24 mono/color monitors
dw io_ret ;25 dummy
dw io_ret ;26 dummy
dw io_ret ;27 dummy
dw io_ret ;28 dummy
dw io_ret ;29 dummy
dw get_set_screen ;30 alpha/graphics screens
io_ret:
ret ; for null function calls
flagset:
mov cl,dev_flagset
jmps supif
flagwait:
mov cl,dev_flagwait
; jmps supif ;fall through
supif:
mov ch,0
callf supervisor
ret
; Here is a little bit of room for assorted corrections
patch_space rb 100h ; hope that will do
eject
; INTERRUPT HANDLERS
; ------------------
;********************************************************
;* *
;* XIOS BACK DOOR ENTRY *
;* *
;********************************************************
; This is included primarily for version 1.0 compatiblity
; It is entered with an INT 0E6h, and returns pointers to
; screen base addresses and PFK tables, or information to
; be used by HDMAINT.
; entry: al = 18 ; resume normal status line
; or
; entry: al = 21 ; display status line
; cx:si -> new status information
; or
; entry: al = 29 ; hd_maint info return
; exit: al = true if there are any open files
; dx:cx -> hd_rom_entry
; or
; entry: al = 31 ; version 1.0 pfk_control
; cx = vc num
; exit: ax,bx -> pfk offset
; si -> vc segment
; or
; entry: al = 32 ; return max disk
; exit: al = max floppy disk number
xios_v1_entry:
cbw
cmp al,32 ; if al > 32
ja xios_v1_exit ; then forget it
sub al,18 ; shift the offset
jb xios_v1_exit ; and ignore < 18
push ds ! push cs ! pop ds ; local data segment
shl ax,1
xchg ax,bx ; bx = table index
call xios_v1_table[bx] ; branch to routine
push ds ! pop es ! pop ds ; es = sysdat, ds restored
xios_v1_exit:
iret
xios_v1_table dw xios_v1_status_on ; 18
dw v1_null,v1_null ; 19, 20
dw xios_v1_display_stat ; 21
dw v1_null,v1_null,v1_null ; 22,23,24
dw v1_null,v1_null,v1_null ; 25,26,27
dw v1_null ; 28
dw xios_v1_hd ; 29
dw v1_null ; 30
dw xios_v1_pfk_vc ; 31
dw xios_v1_max_disk ; 32
; restore normal status line operation
xios_v1_status_on:
mov cx,0FFFFh ; that's the code
jmps xios_v1_statline ; shared entry
; display cx:si on the status line
xios_v1_display_stat:
mov dx,cx ; segment to dx
mov cx,si ; offset to cx
xios_v1_statline:
call io_statline ; try to display
test al,al ; check success
jnz xios_v1_statline ; retry if failure
ret
; return hdmaint information
xios_v1_hd:
mov ax,open_vec ; one bit per drive
test ax,ax ; if no files open
jz xios_v1_hd1 ; then leave al=00
mov al,true ; else al=0FFh
xios_v1_hd1:
mov cx,hd_rom_ofs ; get rom offset
mov dx,hd_rom_seg ; and segment
ret
; return pfk and vc buffer pointers
xios_v1_pfk_vc:
push dx
mov dx,cx ; copy vc number
call point_vs ; bx -> vs_
mov si,vs_vc_seg ; si -> virtual console seg
mov ax,vs_pfk_tbl ; ax -> pfk table
mov bx,ax ; copy return to bx
pop dx
ret
; return maximum floppy disk number
xios_v1_max_disk:
mov al,byte ptr num_flop ; max number is one less
dec al ; then the number of flops
ret
; for ignored entry codes
v1_null:
ret ; just return
;********************************************************
;* *
;* KEYBOARD INPUT EQUATES *
;* *
;********************************************************
; IBM PC keyboard ports
kbd_data equ 060h ;input port for the key board data
kbd_control equ 061h ;control port for the key board
; Some of the IBM PC key codes returned from keyboard.
; Other key codes are used as indices into the
; translation tables key_table, shift_table and control_table
; below.
ctrl equ 29
shft_left equ 42
shft_right equ 54
alt equ 56
numlock equ 69
capslock equ 58
; Keyboard interrupt handler bit masks for special function keys
ctrl_bit equ 001h
shft_left_bit equ 002h
shft_right_bit equ 004h
alt_bit equ 008h
numlock_bit equ 010h
capslock_bit equ 020h
setflag_bit equ 040h ;0 = no set flag call, 1 = set flag
data_bit equ 080h ;0 = no data available, 1 = data
;********************************************************
;* *
;* KEYBOARD INTERRUPT HANDLER *
;* *
;********************************************************
; The following routine gets control after a keyboard interrupt.
; Interrupts are generated on the IBM PC when a key is depressed
; or released.
;----------
i_keyboard:
;----------
mov cs:keyboard_ax,ax ;save AX,SS,SP
mov cs:keyboard_ss,ss
mov cs:keyboard_sp,sp
mov ax,cs ;set up local stack
mov ss,ax ;and save all registers
mov sp,offset keyboard_i_stack ;keyboard interrupt stack
push bx ! push cx ! push dx ! push bp
push si ! push di ! push ds ! push es
mov ds,ax ;set up the data segment
mov es,ax ;and extra segment
in al,kbd_data ;get the scan code
mov scan_code,al ;save the scan code
in al,kbd_control ;get the current control port
mov ah,al ;save the current state
or al,080h ;reset the key board
out kbd_control,al ;send to control port
mov al,ah
out kbd_control,al ;set keyboard back to normal state
mov al,scan_code ;restore the scan code
; Test for CTRL, ALT already being down and DEL being current
; scan code. If yes, call the ROM reset routine.
cmp al,83 ! jnz mask_release ;is scan code the DEL key ?
test down_bits,ctrl_bit ;yes $ is control down ?
jz mask_release
test down_bits,alt_bit ;yes $ is alt down ?
jz mask_release
jmp reset ;we're gone baby
mask_release: ;parity is on when key is released
and al,07fh ;mask off the release bit
cmp al,83 ! jle valid_key ;test for non$existent key
jmp key_scan_done
; Test for CTRL, SHIFT_RIGHT, SHIFT_LEFT, ALT, NUMBLOCK, CAPSLOCK
; keys. The scan codes for these keys are in action_key_table.
; and are refered to as action keys in the comments below.
; The bit position in AH corresponds with what kind of key is
; found, see the section KEYBOARD PORT AND KEY EQUATES, above.
; The DOWN_BITS byte has bits on for action keys that are currently
; being held down by the operator. The TOGGLE_BITS byte is similar
; but for keys that have toggle action, NUM LOCK, SCROLL LOCK,
; SHIFT
valid_key:
mov cx,6 ;loop count for number of action keys
mov ah,ctrl_bit ;first bit mask
mov bx,offset action_key_table ;point at table of action keys
action_loop:
cmp al,[bx] ;is it this key
jnz action_loop_next ;no then try the next
jmp action_key
action_loop_next:
shl ah,1 ;adjust bit mask
inc bx ;and point at next element
loop action_loop
mov al,scan_code ;restore scan code
or al,al ! jns key_make ;sign is on if key just released
jmp key_scan_done ;ignore release condition on
;non$action type key
key_make:
mov bx,offset key_table ;translation table for single keys
test down_bits,ctrl_bit ;was control key already down ?
jz test_for_keypad ;no $ try numlock
mov bx,offset control_table ;yes $ point to control key table
jmps translate
test_for_keypad:
cmp al,71 ! jb test_for_shift ;test for keypad
test toggle_bits,numlock_bit ;from keypad, numlock on ?
jz test_for_shift
test down_bits,shft_left_bit or shft_right_bit
jnz translate ;use key_table if numlock,shifted
mov bx,offset shift_table
jmps translate ;use shift table if numlock
test_for_shift:
test down_bits,shft_left_bit or shft_right_bit
jz translate ;no $ return key from key_table
mov bx,offset shift_table ;yes $ get key from shift_table
translate:
xlat bx ;look up the key
cmp al,0ffh ;is it undefined
jz key_scan_done ;yes $ done
cbw ;extend sign into AH
mov key_type,ah ;save the key type, 0 or 0FFH
test toggle_bits,capslock_bit ;test for caps lock
jz test_for_alt
cmp al,'z' ;yes
ja test_for_alt ;not alphabetic
cmp al,'a' ;is it lower case ?
jae do_case_change ;yes $ switch case
cmp al,'Z'
ja test_for_alt ;not alphabetic
cmp al,'A' ;test for upper case
jb test_for_alt ;not alphabetic
do_case_change:
xor al,020h ;switch the case
test_for_alt:
test down_bits,alt_bit ;is alt key currently down ?
jz save_key_code ;no
cmp al,80h ;check for function key
jb turn_on_msb ;skip if below F1
cmp al,89h
ja key_scan_done ;ignore if above F10
add al,20 ;fudge the alt-pfk code
jmps save_key_code
turn_on_msb:
or al,080h ;yes $ turn on msb for alt key
jmps save_with_msb
save_key_code:
and al,07fh ;mask off sign bit from table
save_with_msb:
mov key_value,al ;save the character
mov dx,key_flag ;get the flag number
cmp dx,ww_flag ;if keys to window manager
jnz set_key_flag ; then inform status flag
mov ww_stat_flag,true
set_key_flag:
call flagset
key_scan_done:
mov al,pic_ocw_nseoi
out pic_ocw_port,al ;ack the interrupt
pop es ! pop ds ! pop di ! pop si
pop bp ! pop dx ! pop cx ! pop bx
mov ax,cs:keyboard_ax ;restore the stack
mov ss,cs:keyboard_ss
mov sp,cs:keyboard_sp
jmpf cs: dword ptr dispatcher ;let dispatcher do iret
action_key:
;----------
; Scan code in AL indicates an action key. AH has a bit on
; in the position corresponding to the action key type.
; Live action keys are those that must remain pressed down
; to have an effect, i.e., CTRL, SHIFT, ALT.
; Toggle action keys are those that switch back and forth in
; function each time they are depressed, i.e., NUMLOCK, CAPSLOCK.
; entry: AL = scan code, one of CTLR, SHIFT_LEFT, SHIFT_RIGHT,
; ALT, NUMLOCK, CAPSLOCK
; AH = bit set in position corresponding to value in AL
; exit: None
cmp al,alt ;if live action: ALT,SHIFT,CTRL
ja toggle_action ;no $ its a toggle type key
test scan_code,80H ;pressed or released ?
jz action_make ;no high bit $ turn it on
not ah ;high bit on $ turn it off
and down_bits,ah ;clear the bit for this key
jmps action_key_done
action_make:
or down_bits,ah ;set bit for this key
jmps action_key_done
toggle_action:
test scan_code,80H ;pressed or released ?
jnz action_key_done ;ignore release of toggle
xor toggle_bits,ah ;it is toggle: reverse state
;jmps action_key_done
action_key_done:
jmps key_scan_done ;acknowledge interrupt but
;do not set the keyboard input
;flag
;********************************************************
;* *
;* KEYBOARD INTERRUPT DATA AREA *
;* *
;********************************************************
reorg3 equ (offset $ + 1) and -2
dseg
org reorg3
; Keyboard interrupt routine stack
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
dw 0CCCCH,0CCCCH,0CCCCH,0CCCCH
keyboard_i_stack rs 0
keyboard_ax dw 0 ;register save are for
keyboard_ss dw 0 ;keyboard interrupt
keyboard_sp dw 0 ;handler
key rw 0 ;label for word load
key_value db 0 ;from one of 3 tables below
key_type db 0 ;if 0 then value is ASCII data
;if 0FFH then value is switch
;screen value or function key
key_flag dw ci_flag ;console in or window manager
ww_stat_flag db 0 ;to help with window status
scan_code db 0 ;value returned from keyboard
down_bits db 0 ;bit vector of
;action keys currently pressed
toggle_bits db 0 ;bit vector of toggle action
;keys
action_key_table: ;search table for action keys
db ctrl ;scan codes
db shft_right
db shft_left
db alt
db numlock
db capslock
pfk_id_table db ';<=>?@abcdghikmopqrs'
;********************************************************
;* *
;* KEYBOARD TRANSLATION TABLES *
;* *
;********************************************************
; Three keyboard translation tables follow. The IBM PC returns
; a "scan code" from the keyboard which is used as an index into
; the following tables.
; KEY_TABLE contains ASCII for keys that have no other keys held
; down simultaneously. The SHIFT_TABLE is for keys depressed
; when the shift, capslocks, or numslock keys are also down
; The CTRL_TABLE is for keys depressed when the CTRL is down.
; 0FFH in the translation table designates an illegal key code.
; The most significant bit is set for keys that are programmable
; or are fixed function keys, and also for the switch screen keys.
key_table:
; translation keyboard scan code
; ----------- ------------------
db 0ffH ;0 - doesn't exist
db esc ;1
db '1234567890-=' ;2-13 (1st row)
db bs,ht ;14-15 (backspace, horizontal tab)
db 'qwertyuiop[]' ;16-27 (2nd row)
db cr, 0ffh ;28-29 (carriage return)
db 'asdfghjkl;''`' ;30-41 (3rd row)
db 0ffh ;42 (left shift)
db '\zxcvbnm,./' ;43-53 (4th row)
db 0ffh ;54 (right shift)
db '*' ;55
db 0ffh ;56 (alt)
db ' ' ;57 (space bar)
db 0ffh ;58 (caps lock)
;-function keys-
;-programmable-
db 80h,81h,82h,83h ;59-62 (fucntion keys f1,f2,f3,f4)
db 84h,85h,86h,87h ;63-66 (function keys f5,f6,f7,f8)
db 88h,89h ;67-68 (function keys f9,f10)
db 0ffh ;69 (num lock)
db dc3 ;70 (scroll lock)
;- key pad -
;-programmable-
db 8ah ;71 (home)
db 8bh ;72 (up arrow)
db 8ch ;73 (Pg Up)
db '-' ;74
db 8dh ;75 (left arrow)
db 0ffh ;76
db 8eh ;77 (right arror)
db '+' ;78
db 8fh ;79 (end)
db 90h ;80 (down arrow)
db 91h ;81 (Pg Dn)
db 92h ;82 (Ins)
db 93h ;83 (Del)
shift_table:
; translation keyboard scan code
; ----------- ------------------
db 0ffH ;0 - doesn't exist
db esc ;1
db '!@#$%^&*()_+' ;2-13 (1st row)
db bs,ff ;14-15 (backspace, form feed)
db 'QWERTYUIOP{}' ;16-27 (2nd row)
db cr ;28 (carriage return)
db 0ffh ;29 (ctrl)
db 'ASDFGHJKL:"~' ;30-41 (3rd row)
db 0ffh ;42 (left shift)
db '|ZXCVBNM<>?' ;43-53 (4th row)
db 0ffh ;54 (right shift)
db dle ;55 (Prt Sc - ^P)
db 0ffh ;56 (Alt)
db ' ' ;57 (space bar)
db 0ffh ;58 (Caps Lock)
;-function keys-
;-return fixed strings-
db 9Eh,9Fh,0A0h,0A1h ;F1 - F4
db 0A2h,0A3h,0A4h,0A5h ;F5 - F8
db 0A6h,0A7h ;F9 - F10
db 0ffh ;69 (Num Lock)
db dc1 ;70 (Scroll Lock - ^Q)
;-key pad-
db '789-456+1230.' ;71-83 (ascii values on keys)
control_table:
; translation keyboard scan code
; ----------- ------------------
db 0ffh ;0 (no such key code)
db ESC ;1
db 0ffh ;2
db NUL ;3 (ctrl @)
db 0ffh,0ffh,0ffh ;4-6
db RDS ;7 (ctrl ^)
db 0ffh,0ffh,0ffh,0ffh ;8-11
db US ;12 (ctrl _)
db 0ffh ;13
db DEL ;14 (left arrow)
db 0ffh ;15
db DC1,ETB,ENQ,DC2 ;16-19 (ctrl q,w,e,r)
db DC4,EM,NAK,HT ;20-23 (ctrl t,y,u,i)
db SHI,DLE,ESC,GS ;24-27 (ctrl o,p,[,])
db cr ;28 (ctrl carriage return)
db 0ffh ;29
db SOH,DC3,EOT,ACK ;30-33 (ctrl a,s,d,f)
db BEL,BS,LF,VT ;34-37 (ctrl g,h,j,k)
db FF ;38 (ctrl l)
db 0ffh,0ffh,0ffh,0ffh ;39-42
db FS,SUBB,CAN,ETX ;43-47 (ctrl \,z,x,c)
db SYN,STX,SO,CR ;47-50 (ctrl v,b,n,m)
db 0ffh,0ffh,0ffh,0ffh ;51-54
db DLE ;55 (^PrtSc = ^P)
db 0ffh,' ',0ffh ;56-58
;-function keys
db 0A8H,0A9H,0AAH,0ABH ;F1 - F4
db 0ACH,0ADH,0AEH,0AFH ;F5 - F8
db 0B0H,0B1H ;F9 - F10
db 0ffh ;69
db ETX ;70 break (^scroll lock = ctrl c)
;-key pad-
;-reserved for switch screens-
db 247,248,249,0FCH ;7,8,9,-
db 244,245,246,0FDH ;4,5,6,+
db 241,242,243 ;1,2,3
db 240,0FEH ;0,.
;********************************************************
;* *
;* DISK INTERRUPT HANDLER *
;* *
;*******************************************************
reorg4 equ offset $
cseg
org reorg4
; The following routine gets control from an interrupt from the
; FDC. The current state is saved and dev_flagset is called.
;------
i_disk:
;------
mov cs:user_ax,ax ;save ax
mov cs:user_ss,ss ;save the stack segment
mov cs:user_sp,sp ;and stack segment
mov ax,cs ;get code segment
mov ss,ax ;into stack segment
mov sp,offset user_save_area ;point at the save area
push bx! push cx
push dx! push bp
push si! push di
push ds! push es
mov al,pic_ocw_seoi + disk_channel
out pic_ocw_port,al
mov ds,cs:sysdat
mov dx,fdc_flag
call flagset
pop es! pop ds
pop di! pop si
pop bp! pop dx
pop cx! pop bx
mov ss,cs:user_ss
mov sp,cs:user_sp
mov ax,cs:user_ax
jmpf cs:dword ptr dispatcher
;********************************************************
;* *
;* 8253-5 COUNTER TIMER PORT AND DATA EQUATES *
;* *
;********************************************************
timer_0_reg equ 040h ;first counter timer port
timer_1_reg equ 041h
timer_2_reg equ 042h
timer_cmnd_reg equ 043h ;command port
timer_60_hz equ 19886 ;constant for 60.001 hz tick
timer_1000_hz equ 533h ;constant for 1000 hz tone
beep_cmnd equ 10110110b ;timer 2 lsb,msb binary
beep_on equ 03h
beep_off equ 0fch
port_a equ 060h
port_b equ 061h
port_c equ 062h
;********************************************************
;* *
;* CLOCK INTERRUPT HANDLER *
;* *
;********************************************************
; The following routine gets control on a timer interrupt,
; from the 8253-5 (?).
;-------
i_clock:
;------- ;interrupts are off
push ds ;use one level of user stack
mov ds,cs:sysdat
mov tickint_ss,ss ;save the registers
mov tickint_sp,sp
mov ss,sysdat
mov sp,offset tickint_save_area
push ax ! push bx ! push cx ! push dx
push bp ! push di ! push si ! push es
cmp beep_counter,00 ;test for beeping now
jz check_motor_off ;no then leap to the next test
cmp beep_ticks,00 ;is this the first time through
jnz check_beep_tick ;no the leap around set up
set_beep_tick:
mov beep_ticks,0ch ;set up for a beep
check_beep_tick:
dec beep_ticks ;are we all done with this beep
jz check_more_beeps ;yes then leap
cmp beep_ticks,2 ;where are we in the beep cycle
jb turn_beep_off ;low enough to turn off
in al,port_b ;else turn on the beeper
or al,beep_on
out port_b,al
jmps check_motor_off
check_more_beeps:
dec beep_counter ;count down the beep
jnz set_beep_tick ;not the last set a new one
turn_beep_off:
in al,port_b ;else get the bits
and al,beep_off
out port_b,al ;silence the beeper
check_motor_off:
cmp disk_on_going,00h ;test for disk operation under way
jnz check_disk_time ;yes, don't touch motor off counter
dec motor_off_counter
jnz check_disk_time ;not timed out yet leap
mov dx,fdc_port
mov al,fdc_on ;keep the fdc not reset
mov motor_flags,al ;deselect the motors
out dx,al
check_disk_time:
cmp disk_time_out,0 ;if zero, then it's not being used
jz update_tick ; so, go about your business
dec disk_time_out ;if it hasn't timed out
jnz update_tick ; then there's no need to worry
mov disk_error,80h ;if it has timed out
mov dx,fdc_flag ; then tell the error routine why
call flagset ; and do a flag set to unstick us
update_tick:
cmp tick_counter,ticks_per_second ;test for new second
jnz update_tick_dec
update_tick_dec:
dec tick_counter
jnz do_tick_flag ;not a second then leap
mov tick_counter,ticks_per_second
mov dx,sec_flag
call flagset
do_tick_flag:
cmp tick,0
je timer_interrupt_exit
mov dx,tick_flag
call flagset
timer_interrupt_exit:
mov al,pic_ocw_seoi + timer_channel ;pick up end of interrupt word
out pic_ocw_port,al ;signal EOI
pop es ! pop si ! pop di ! pop bp
pop dx ! pop cx ! pop bx ! pop ax
mov ss,tickint_ss
mov sp,tickint_sp
pop ds ;get DS from interrupted
;process's stack
jmpf cs:dword ptr dispatcher ;go run the next ready process
;------
i_tick: ;don't do anything
;------
iret
;********************************************************
;* *
;* CLOCK INTERRUPT DATA AREA *
;* *
;********************************************************
reorg5 equ (offset $ + 1) and -2
dseg
org reorg5
beep_counter db 0 ;how many control g's
beep_ticks db 0 ;elapsed ticks this beep
tick_counter db ticks_per_second ;counter for tick interupts
rs 30h
tickint_save_area rs 2
tickint_ax rw 1 ;storage for interrupted task
tickint_ss rw 1
tickint_sp rw 1
;************************************************
;* *
;* 8087 NDP INTERRUPT HANDLER *
;* *
;************************************************
reorg_nmi equ offset $
cseg
org reorg_nmi
i_nmi:
push ax ; first check parity error
in al,port_c
test al,0C0h ; if not a parity error
pop ax ; then it really is
jz i_ndp ; from the 8087
; memory parity error interrupt
i_parity:
push cs ! pop ds ; there's no coming back
push cs ! pop es ; so forget the registers
mov di,offset parity_p_msg
call fatal_proc ; store the process name
mov di,offset parity_a_msg
call fatal_addr ; store the return address
add beep_counter,3 ; beep the thrice
mov sl_exit_value,true ; take over the status line
mov dx,cs
mov cx,offset parity_msg
call io_statline ; print the error message
sti
mov bx,4 ; about 1 second
i_parity_pause:
loop i_parity_pause ; wait for beeps to end
dec bx
jnz i_parity_pause
i_parity_freeze:
cli
hlt ; wait here foever
jmps i_parity_freeze ; and a day
; numeric data processor interrupt
i_ndp:
push ds ; on user's stack
mov ds,cs:sysdat
mov ndp_ss_save,ss ; save user's stack
mov ndp_sp_save,sp
mov ss,sysdat ; get our own stack
mov sp,ndp_stack_top
push ax ! push bx ! push cx ! push dx
push si ! push di ! push bp ! push es
mov es,sysdat
FNSTENV env_8087 ; store 8087 environment
FWAIT ; await completion
FNCLEX ; clear int request bit
xor ax,ax
FNDISI ; disable its int's
mov si,offset env_8087
mov bx,owner_8087 ; get current owner
test bx,bx ; if owner has already
jz i_ndp_continue ; terminated, skip
mov ax,ndp_status[si] ; if not severe error, continue
test ax,003Ah ; 3A = under/overflow, precision
jnz i_ndp_continue ; or denormalized operand
or p_flag[bx],80h ; terminate interrupting process
i_ndp_continue:
mov byte ptr 2[si],0 ; clear stat word for env restore
pop es ! pop bp ! pop di ! pop si
pop dx ! pop cx ! pop bx ! pop ax
mov ss,ndp_ss_save ; restore user's stack
mov sp,ndp_sp_save
FLDENV env_8087 ; restore 8087 environment
FWAIT ; await completion
pop ds
iret
; NUMERIC DATA PROCESSOR INTERRUPT HANDLER DATA
reorg_nmi_dat equ offset $
dseg
org reorg_nmi_dat
ndp_ss_save rw 1 ; save area for user's stack
ndp_sp_save rw 1
env_8087 rw 7 ; save area for 8087's stack
ndp_status equ word ptr 2 ; status word in env_8087
ndp_control rw 1 ; for 8087 init routine
rb 32 ; i_ndp stack area
ndp_stack_top equ offset $
; parity error messages
parity_msg db 'Parity error from '
parity_p_msg db 'PROCNAME at '
parity_a_msg db '0000:0000 '
db ' **** MACHINE IS HALTED! ****'
db ' '
;************************************************
;* *
;* FATAL INTERRUPT HANDLER *
;* *
;************************************************
fatal_reorg equ offset $
cseg
org fatal_reorg
; Division by zero or any division overflow
i_divide:
mov si,offset fatal_div ; divide by zero
jmps fatal_int
; Arithmetic overflow when followed by an Int on ovf
i_overflow:
mov si,offset fatal_ovf ; divide by zero
jmps fatal_int
; Any undefined interrupt vectors here
i_unexpected:
mov si,offset fatal_unx ; divide by zero
; jmps fatal_int ; fall through
fatal_int:
sti ; allow further ints
push cs ! pop ds ; local data segment
push cs ! pop es ; and extra too
mov di,offset fatal_t_msg ; error type destination
call fatal_type ; save sub message
mov di,offset fatal_p_msg ; proc name destination
call fatal_proc ; save process name
mov di,offset fatal_a_msg ; address destination
call fatal_addr ; save come-from addr
mov bx,rlr ; get process descriptor
mov es,p_uda[bx] ; set up user data area
inc beep_counter ; and extra beep here
mov si,offset fatal_msg
mov di,offset fatal_resp ; allow any key
call sl_error_out ; display message
mov bx,rlr ;terminate the running process
and p_flag[bx],not (pf_keep + pf_tempkeep)
mov cx,p_term
mov dx,0FFFFh
jmp supif ;process is terminated
; store the "type" of fatal interrupt
fatal_type:
mov cx,length fatal_t_msg ; sub message length
cld
rep movsb ; store the type of int
ret
; store the process name which caused this mess
fatal_proc:
mov bx,rlr ; get process descriptor
lea si,p_name[bx] ; point to proc name
mov cx,8 ; max process name
cld
rep movsb ; store the process name
ret
; store the address whence this interrupt came
fatal_addr:
mov bp,sp
add bp,5 ; look up the stack
mov bx,offset hex_digits ; for translation
call fatal_word ; print segment
inc di ; skip the :
; jmp fatal_word ; and offset
fatal_word:
call fatal_byte ; print ms byte
; jmp fatal_byte ; and ls byte
fatal_byte:
mov al,[bp] ; return byte from stack
dec bp ; next byte down
call fatal_nibble ; print ms nibble
; jmp fatal_nibble ; and ls nibble
fatal_nibble:
mov cl,4
rol al,cl ; ms nibble first
push ax ; save for ls nibble
and al,0Fh ; 4 bits only
xlat bx
stosb ; store hex code
pop ax
ret
; Fatal error messages are all in the code seg
fatal_msg rb 0
fatal_t_msg db 'Unexpected'
db ' Interrupt from '
fatal_p_msg db 'PROCNAME at '
fatal_a_msg db '0000:0000 '
db ' Type any key to stop process. '
fatal_div db ' Division'
fatal_ovf db ' Overflow'
fatal_unx db 'Unexpected'
fatal_type_len equ offset $ - offset fatal_unx
fatal_resp db 0 ; allow any key
hex_digits db '0123456789ABCDEF'
;************************************************
;* *
;* RESET FUNCTION - CTRL/ALT/DEL REBOOT *
;* *
;************************************************
reset_flag equ word ptr .72h
reset:
mov ax,40H
mov ds,ax ;ROM data segment
mov reset_flag,1234H
jmpf cs:dword ptr rom_reset
; Reset routine data
reset_key rb 1
rom_reset dw 0000h,0FFFFh