Files
Digital-Research-Source-Code/CPM OPERATING SYSTEMS/CPM 8000 (CPM8K)/CPM 8K 1.1/disk4/biostrap.8kn
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1 line
7.4 KiB
Plaintext

;********** biostrap.8kn cpm.sys + cpmldr.sys ******
;* Copyright 1984, Digital Research Inc.
;*
;* Trap handlers for CP/M-8000(tm) BIOS
;*
;* 821013 S. Savitzky (Zilog) -- created
;* 821123 D. Dunlop (Zilog) -- added Olivetti M20-
;* specific code to invalidate track buffer
;* contents when disk drive motor stops
;* (fixes directory-overwrite on disk change)
;* 830305 D. Sallume (Zilog) -- added FPE trap
;* code.
;* 840815 R. WEISER (DRI) -- conditional assembly
;*
__text: .sect
;****************************************************
;*
;* NOTE
;* Trap and interrupt handlers are started up
;* in segmented mode.
;*
;****************************************************
;****************************************************
;*
;* Externals
;*
;****************************************************
.if LOADER
.global _bios ; C portion of Loader Bios
.else
.global __bios ;C portion of Normal Bios
.endif
.global memsc ;memory-management SC
.global _tbvalid ;disk track buff valid
.global _tbdirty ;disk track buff is dirty
.global _tbdsk ;current drive code
.global _sysseg, _usrseg, _sysstk, _psap,
.if LOADER
.else ; only the normal Bios
.global fp_epu
.endif
;****************************************************
;*
;* M-20 ROM scratchpad RAM addresses
;*
;****************************************************
rtc_ext: .equ 82000022h ;Place to put address
; of list of functions
; for each clock tick
motor_on: .equ 82000020h ;Disk motor timeout
;****************************************************
;*
;* Global declarations
;*
;****************************************************
.global _trapinit
.global _trapvec
.global _trap
.global xfersc
;****************************************************
;*
;* System Call and General Trap Handler And Dispatch
;*
;* It is assumed that the system runs
;* non-segmented on a segmented CPU.
;*
;* _trap is jumped to segmented, with the
;* following information on the stack:
;*
;* trap type: WORD
;* reason: WORD
;* fcw: WORD
;* pc: LONG
;*
;* The trap handler is called as a subroutine,
;* with all registers saved on the stack,
;* IN SEGMENTED MODE. This allows the trap
;* handler to be in another segment (with some
;* care). This is useful mainly to the debugger.
;*
;* All registers except rr0 are also passed
;* intact to the handler.
;*
;****************************************************
__text: .sect
sc_trap: ;system call trap server
push @r14,@r14
_trap:
sub r15,#30 ; push caller state
ldm @r14,r0,#14
NONSEG ; go nonsegmented
ldctl r1,NSP
ld nr14(r15),r14
ex r1,nr15(r15)
; trap# now in r1
cpb rh1,#7Fh ; system call?
jr ne trap_disp ; no
; yes: map it
clrb rh1
add r1,#SC0TRAP
;=== need range check ===
trap_disp: ; dispatch
sll r1,#2
ldl rr0,_trapvec(r1)
testl rr0
jr z _trap_ret ; zero -- no action
; else call seg @rr0
pushl @r15,rr0 ; (done via kludge)
SEG
popl rr0,@r14
calr trap_1
jr _trap_ret
trap_1: ; jp @rr0
pushl @r14,rr0
ret
_trap_ret: ;return from trap or interrupt
NONSEG
ld r1,nr15(r15) ; pop state
ld r14,nr14(r15)
ldctl NSP,r1
SEG ; go segmented for the iret.
ldm r0,@r14,#14
add r15,#32
iret ; return from interrupt
;****************************************************
;*
;* Assorted Trap Handlers
;*
;****************************************************
epu_trap:
push @r14,#EPUTRAP
jr _trap
pi_trap:
push @r14,#PITRAP
jr _trap
seg_trap:
push @r14,#SEGTRAP
jr _trap
nmi_trap:
push @r14,#NMITRAP
jr _trap
.if LOADER
.else ; not used in Loader Bios
;****************************************************
;*
;* Bios system call handler
;*
;****************************************************
biossc: ;call bios
NONSEG
; r3 = operation code
; rr4= P1
; rr6= P2
ld r0,scfcw+4(r15) ; if caller nonseg, normal
and r0,#0C000h
jr nz seg_ok
ld r4,scseg+4(r15) ; then add seg to P1, P2
ld r6,r4
seg_ok:
; set up C stack frame
;===
pushl @r15,rr6
pushl @r15,rr4
push @r15,r3
; call C program
call __bios
; clean stack & return
add r15,#10
ldl cr6+4(r15),rr6 ; with long in rr6
SEG
ret
.endif
;****************************************************
;*
;* Context Switch System Call
;*
;* xfer(context)
;* long context;
;*
;* context is the physical (long) address of:
;* r0
;* ...
;* r13
;* r14 (normal r14)
;* r15 (normal r15)
;* ignored word
;* FCW (had better specify normal mode)
;* PC segment
;* PC offset
;*
;* The system stack pointer is not affected.
;*
;* Control never returns to the caller.
;*
;****************************************************
xfersc: ;enter here from system call
SEG
; build frame on system stack
; when called from system call, the frame replaces
; the caller's context, which will never be resumed.
inc r15,#4 ;discard return addr
ldl rr4,rr14 ;move context
ld r2,#FRAMESZ/2
ldir @r4,@r6,r2
jr _trap_ret ;restore context
;****************************************************
;*
;* _motor_c -- check if disk motor still running.
;* Entered each clock tick. Invalidates
;* track buffer when motor stops
;* (Note: runs segmented)
;*
;****************************************************
_motor_c:
ld r5,#_tbdsk ;Which disk is it?
cp r5,#2 ; is it the hard disk
ret z
ldl rr4,#motor_on ;Motor running?
test @r4
ret nz ;Yes: do nothing
ldar r4,$
ld r5,#_tbdirty ; Is track buff dirty?
test @r4 ; Yes...
ret nz ; ...return without invalidating
ld r5,#_tbvalid
clr @r4 ;No: mark track buffer
ret ; invalid
; Table of functions run each real time clock tick
_ticktab:
.long -1 ;Will contain _motor_c
.word 0ffffh ;Terminator
;****************************************************
;*
;* _trapinit -- initialize trap system
;*
;****************************************************
;*
;* PSA (Program Status Area) structure
;*
ps .equ 8 ; size of a program status entry
; --- segmented ---
psa_epu .equ 1*ps ; EPU trap offset
psa_prv .equ 2*ps ; priviledged instruction trap
psa_sc .equ 3*ps ; system call trap
psa_seg .equ 4*ps ; segmentation trap
psa_nmi .equ 5*ps ; non-maskable interrupt
psa_nvi .equ 6*ps ; non-vectored interrupt
psa_vi .equ 7*ps ; vectored interrupt
psa_vec .equ psa_vi+(ps/2) ; vectors
_trapinit:
; initialize trap table
lda r2,_trapvec
ld r0,#NTRAPS
subl rr4,rr4
clrtraps:
ldl @r2,rr4
inc r2,#4
djnz r0,clrtraps
ld r2,_sysseg
.if LOADER
.else ;not used by Loader Bios
lda r3,biossc
ldl _trapvec+(BIOS_SC+SC0TRAP)*4,rr2
.endif
lda r3,memsc
ldl _trapvec+(MEM_SC+SC0TRAP)*4,rr2
.if LOADER
.else ; not used by Loader Bios
lda r3,fp_epu
ldl _trapvec+EPUTRAP*4,rr2
.endif
; initialize some PSA entries.
; rr0 PSA entry: FCW (ints ENABLED)
; rr2 PSA entry: PC
; rr4 -> PSA slot
ldl rr4,_psap
SEG
ldl rr0,#0000D800h ; traps here
add r5,#ps ; EPU trap
ldar r2,epu_trap
ldm @r4,r0,#4
add r5,#ps ; Priviledged Inst
ldar r2,pi_trap
ldm @r4,r0,#4
add r5,#ps ; System Call
ldar r2,sc_trap
ldm @r4,r0,#4
add r5,#ps ; segmentation
ldar r2,seg_trap
ldm @r4,r0,#4
add r5,#ps ; Non-Maskable Int.
ldar r2,nmi_trap
ldm @r4,r0,#4
; Set up Real-Time Clock external call loc
ldar r2,_motor_c
ldar r4,_ticktab
ldl @r4,rr2
ldl rr2,#rtc_ext
ldl @r2,rr4
NONSEG
ret
;****************************************************
;****************************************************
NONSEG
ret
;****************************************************
;****************************************************