mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 16:34:07 +00:00
1571 lines
35 KiB
NASM
1571 lines
35 KiB
NASM
title 'CP/M V3.0 Loader'
|
|
|
|
|
|
; Copyright (C) 1982
|
|
; Digital Research
|
|
; Box 579, Pacific Grove
|
|
; California, 93950
|
|
|
|
; Revised:
|
|
; 01 Nov 82 by Bruce Skidmore
|
|
|
|
base equ $
|
|
abase equ base-0100h
|
|
|
|
cr equ 0dh
|
|
lf equ 0ah
|
|
|
|
fcb equ abase+005ch ;default FCB address
|
|
buff equ abase+0080h ;default buffer address
|
|
|
|
;
|
|
; System Equates
|
|
;
|
|
resetsys equ 13 ;reset disk system
|
|
printbuf equ 09 ;print string
|
|
open$func equ 15 ;open function
|
|
read$func equ 20 ;read sequential
|
|
setdma$func equ 26 ;set dma address
|
|
;
|
|
; Loader Equates
|
|
;
|
|
comtop equ abase+80h
|
|
comlen equ abase+81h
|
|
bnktop equ abase+82h
|
|
bnklen equ abase+83h
|
|
osentry equ abase+84h
|
|
|
|
cseg
|
|
|
|
lxi sp,stackbot
|
|
|
|
call bootf ;first call is to Cold Boot
|
|
|
|
mvi c,resetsys ;Initialize the System
|
|
call bdos
|
|
|
|
mvi c,printbuf ;print the sign on message
|
|
lxi d,signon
|
|
call bdos
|
|
|
|
mvi c,open$func ;open the CPM3.SYS file
|
|
lxi d,cpmfcb
|
|
call bdos
|
|
cpi 0ffh
|
|
lxi d,openerr
|
|
jz error
|
|
|
|
lxi d,buff
|
|
call setdma$proc
|
|
|
|
call read$proc ;read the load record
|
|
|
|
lxi h,buff
|
|
lxi d,mem$top
|
|
mvi c,6
|
|
cloop:
|
|
mov a,m
|
|
stax d
|
|
inx d
|
|
inx h
|
|
dcr c
|
|
jnz cloop
|
|
|
|
call read$proc ;read display info
|
|
|
|
mvi c,printbuf ;print the info
|
|
lxi d,buff
|
|
call bdos
|
|
|
|
;
|
|
; Main System Load
|
|
;
|
|
|
|
;
|
|
; Load Common Portion of System
|
|
;
|
|
lda res$len
|
|
mov h,a
|
|
lda mem$top
|
|
call load
|
|
;
|
|
; Load Banked Portion of System
|
|
;
|
|
lda bank$len
|
|
ora a
|
|
jz execute
|
|
mov h,a
|
|
lda bank$top
|
|
call load
|
|
;
|
|
; Execute System
|
|
;
|
|
execute:
|
|
lxi h,fcb+1
|
|
mov a,m
|
|
cpi '$'
|
|
jnz execute$sys
|
|
inx h
|
|
mov a,m
|
|
cpi 'B'
|
|
cz break
|
|
execute$sys:
|
|
lxi sp,osentry$adr
|
|
ret
|
|
|
|
;
|
|
; Load Routine
|
|
;
|
|
; Input: A = Page Address of load top
|
|
; H = Length in pages of module to read
|
|
;
|
|
load:
|
|
ora a ;clear carry
|
|
mov d,a
|
|
mvi e,0
|
|
mov a,h
|
|
ral
|
|
mov h,a ;h = length in records of module
|
|
loop:
|
|
xchg
|
|
lxi b,-128
|
|
dad b ;decrement dma address by 128
|
|
xchg
|
|
push d
|
|
push h
|
|
call setdma$proc
|
|
call read$proc
|
|
pop h
|
|
pop d
|
|
dcr h
|
|
jnz loop
|
|
ret
|
|
|
|
;
|
|
; Set DMA Routine
|
|
;
|
|
setdma$proc:
|
|
mvi c,setdma$func
|
|
call bdos
|
|
ret
|
|
|
|
;
|
|
; Read Routine
|
|
;
|
|
read$proc:
|
|
mvi c,read$func ;Read the load record
|
|
lxi d,cpmfcb ;into address 80h
|
|
call bdos
|
|
ora a
|
|
lxi d,readerr
|
|
rz
|
|
;
|
|
; Error Routine
|
|
;
|
|
error:
|
|
mvi c,printbuf ;print error message
|
|
call bdos
|
|
di
|
|
hlt
|
|
|
|
break:
|
|
db 0ffh
|
|
ret
|
|
|
|
cpmfcb:
|
|
db 0,'CPM3 SYS',0,0,0,0,0,0
|
|
dw 0,0,0,0,0,0,0,0,0
|
|
|
|
openerr:
|
|
db cr,lf
|
|
db 'CPMLDR error: failed to open CPM3.SYS'
|
|
db cr,lf,'$'
|
|
|
|
readerr:
|
|
db cr,lf
|
|
db 'CPMLDR error: failed to read CPM3.SYS'
|
|
db cr,lf,'$'
|
|
|
|
signon:
|
|
db cr
|
|
db lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
|
|
db lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf,lf
|
|
db 'CP/M V3.0 Loader',cr,lf
|
|
db 'Copyright (C) 1982, Digital Research'
|
|
db cr,lf,'$'
|
|
|
|
db '021182',0,0,0,0
|
|
stackbot:
|
|
|
|
mem$top:
|
|
ds 1
|
|
res$len:
|
|
ds 1
|
|
bank$top:
|
|
ds 1
|
|
bank$len:
|
|
ds 1
|
|
osentry$adr:
|
|
ds 2
|
|
|
|
; title 'CP/M 3.0 LDRBDOS Interface, Version 3.1 Nov, 1982'
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
;** **
|
|
;** B a s i c D i s k O p e r a t i n g S y s t e m **
|
|
;** **
|
|
;** I n t e r f a c e M o d u l e **
|
|
;** **
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
;
|
|
; Copyright (c) 1978, 1979, 1980, 1981, 1982
|
|
; Digital Research
|
|
; Box 579, Pacific Grove
|
|
; California
|
|
;
|
|
; Nov 1982
|
|
;
|
|
;
|
|
; equates for non graphic characters
|
|
;
|
|
|
|
rubout equ 7fh ; char delete
|
|
tab equ 09h ; tab char
|
|
cr equ 0dh ; carriage return
|
|
lf equ 0ah ; line feed
|
|
ctlh equ 08h ; backspace
|
|
|
|
|
|
;
|
|
serial: db 0,0,0,0,0,0
|
|
;
|
|
; Enter here from the user's program with function number in c,
|
|
; and information address in d,e
|
|
;
|
|
|
|
bdos:
|
|
bdose: ; Arrive here from user programs
|
|
xchg! shld info! xchg ; info=de, de=info
|
|
|
|
mov a,c! cpi 14! jc bdose2
|
|
sta fx ; Save disk function #
|
|
xra a! sta dircnt
|
|
lda seldsk! sta olddsk ; Save seldsk
|
|
|
|
bdose2:
|
|
mov a,e! sta linfo ; linfo = low(info) - don't equ
|
|
lxi h,0! shld aret ; Return value defaults to 0000
|
|
shld resel ; resel = 0
|
|
; Save user's stack pointer, set to local stack
|
|
dad sp! shld entsp ; entsp = stackptr
|
|
|
|
lxi sp,lstack ; local stack setup
|
|
|
|
lxi h,goback ; Return here after all functions
|
|
push h ; jmp goback equivalent to ret
|
|
mov a,c! cpi nfuncs! jnc high$fxs ; Skip if invalid #
|
|
mov c,e ; possible output character to c
|
|
lxi h,functab! jmp bdos$jmp
|
|
|
|
; look for functions 100 ->
|
|
high$fxs:
|
|
sbi 100! jc lret$eq$ff ; Skip if function < 100
|
|
|
|
bdos$jmp:
|
|
|
|
mov e,a! mvi d,0 ; de=func, hl=.ciotab
|
|
dad d! dad d! mov e,m! inx h! mov d,m ; de=functab(func)
|
|
lhld info ; info in de for later xchg
|
|
xchg! pchl ; dispatched
|
|
|
|
|
|
; dispatch table for functions
|
|
|
|
functab:
|
|
dw func$ret, func1, func2, func3
|
|
dw func$ret, func$ret, func6, func$ret
|
|
dw func$ret, func9, func10, func11
|
|
diskf equ ($-functab)/2 ; disk funcs
|
|
dw func12,func13,func14,func15
|
|
dw func16,func17,func18,func19
|
|
dw func20,func21,func22,func23
|
|
dw func24,func25,func26,func27
|
|
dw func28,func29,func30,func31
|
|
dw func32,func33,func34,func35
|
|
dw func36,func37,func38,func39
|
|
dw func40,func42,func43
|
|
dw func44,func45,func46,func47
|
|
dw func48,func49,func50
|
|
nfuncs equ ($-functab)/2
|
|
|
|
|
|
entsp: ds 2 ; entry stack pointer
|
|
|
|
; 40 level stack
|
|
|
|
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
|
|
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
|
|
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
|
|
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
|
|
dw 0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h,0c7c7h
|
|
lstack:
|
|
|
|
|
|
page
|
|
title 'CP/M 3.0 LDRBDOS Interface, Version 3.1 July, 1982'
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
;** **
|
|
;** B a s i c D i s k O p e r a t i n g S y s t e m **
|
|
;** **
|
|
;** C o n s o l e P o r t i o n **
|
|
;** **
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
;
|
|
; July, 1982
|
|
;
|
|
;
|
|
; console handlers
|
|
|
|
conout:
|
|
;compute character position/write console char from C
|
|
;compcol = true if computing column position
|
|
lda compcol! ora a! jnz compout
|
|
;write the character, then compute the column
|
|
;write console character from C
|
|
push b ;recall/save character
|
|
call conoutf ;externally, to console
|
|
pop b ;recall the character
|
|
compout:
|
|
mov a,c ;recall the character
|
|
;and compute column position
|
|
lxi h,column ;A = char, HL = .column
|
|
cpi rubout! rz ;no column change if nulls
|
|
inr m ;column = column + 1
|
|
cpi ' '! rnc ;return if graphic
|
|
;not graphic, reset column position
|
|
dcr m ;column = column - 1
|
|
mov a,m! ora a! rz ;return if at zero
|
|
;not at zero, may be backspace or eol
|
|
mov a,c ;character back to A
|
|
cpi ctlh! jnz notbacksp
|
|
;backspace character
|
|
dcr m ;column = column - 1
|
|
ret
|
|
|
|
notbacksp:
|
|
;not a backspace character, eol?
|
|
cpi lf! rnz ;return if not
|
|
;end of line, column = 0
|
|
mvi m,0 ;column = 0
|
|
ret
|
|
;
|
|
;
|
|
tabout:
|
|
;expand tabs to console
|
|
mov a,c! cpi tab! jnz conout ;direct to conout if not
|
|
;tab encountered, move to next tab pos
|
|
tab0:
|
|
mvi c,' '! call conout ;another blank
|
|
lda column! ani 111b ;column mod 8 = 0 ?
|
|
jnz tab0 ;back for another if not
|
|
ret
|
|
;
|
|
print:
|
|
;print message until M(BC) = '$'
|
|
LXI H,OUTDELIM
|
|
ldax b! CMP M! rz ;stop on $
|
|
;more to print
|
|
inx b! push b! mov c,a ;char to C
|
|
call tabout ;another character printed
|
|
pop b! jmp print
|
|
;
|
|
;
|
|
func2: equ tabout
|
|
;write console character with tab expansion
|
|
;
|
|
func9:
|
|
;write line until $ encountered
|
|
xchg ;was lhld info
|
|
mov c,l! mov b,h ;BC=string address
|
|
jmp print ;out to console
|
|
;
|
|
sta$ret:
|
|
;store the A register to aret
|
|
sta aret
|
|
func$ret:
|
|
ret ;jmp goback (pop stack for non cp/m functions)
|
|
;
|
|
setlret1:
|
|
;set lret = 1
|
|
mvi a,1! jmp sta$ret
|
|
;
|
|
func1: equ func$ret
|
|
;
|
|
func3: equ func$ret
|
|
;
|
|
func6: equ func$ret
|
|
;
|
|
func10: equ func$ret
|
|
func11: equ func$ret
|
|
;
|
|
; data areas
|
|
;
|
|
|
|
|
|
compcol:db 0 ;true if computing column position
|
|
; end of BDOS Console module
|
|
|
|
;**********************************************************************
|
|
;*****************************************************************
|
|
;
|
|
; Error Messages
|
|
|
|
md equ 24h
|
|
|
|
err$msg: db cr,lf,'BDOS ERR: ',md
|
|
err$select: db 'Select',md
|
|
err$phys: db 'Perm.',md
|
|
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
;
|
|
; common values shared between bdosi and bdos
|
|
|
|
|
|
aret: ds 2 ; address value to return
|
|
lret equ aret ; low(aret)
|
|
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
;** **
|
|
;** b a s i c d i s k o p e r a t i n g s y s t e m **
|
|
;** **
|
|
;*****************************************************************
|
|
;*****************************************************************
|
|
|
|
; literal constants
|
|
|
|
true equ 0ffh ; constant true
|
|
false equ 000h ; constant false
|
|
enddir equ 0ffffh ; end of directory
|
|
byte equ 1 ; number of bytes for "byte" type
|
|
word equ 2 ; number of bytes for "word" type
|
|
|
|
; fixed addresses in low memory
|
|
|
|
tbuff equ 0080h ; default buffer location
|
|
|
|
; error message handlers
|
|
|
|
sel$error:
|
|
; report select error
|
|
lxi b,err$msg
|
|
call print
|
|
lxi b,err$select
|
|
jmp goerr1
|
|
|
|
goerr:
|
|
lxi b,err$msg
|
|
call print
|
|
lxi b,err$phys
|
|
goerr1:
|
|
call print
|
|
di ! hlt
|
|
|
|
bde$e$bde$m$hl:
|
|
mov a,e! sub l! mov e,a
|
|
mov a,d! sbb h! mov d,a
|
|
rnc! dcr b! ret
|
|
|
|
bde$e$bde$p$hl:
|
|
mov a,e! add l! mov e,a
|
|
mov a,d! adc h! mov d,a
|
|
rnc! inr b! ret
|
|
|
|
shl3bv:
|
|
inr c
|
|
shl3bv1:
|
|
dcr c! rz
|
|
dad h! adc a! jmp shl3bv1
|
|
|
|
compare:
|
|
ldax d! cmp m! rnz
|
|
inx h! inx d! dcr c! rz
|
|
jmp compare
|
|
|
|
;
|
|
; local subroutines for bios interface
|
|
;
|
|
|
|
move:
|
|
; Move data length of length c from source de to
|
|
; destination given by hl
|
|
inr c ; in case it is zero
|
|
move0:
|
|
dcr c! rz ; more to move
|
|
ldax d! mov m,a ; one byte moved
|
|
inx d! inx h ; to next byte
|
|
jmp move0
|
|
|
|
selectdisk:
|
|
; Select the disk drive given by register D, and fill
|
|
; the base addresses curtrka - alloca, then fill
|
|
; the values of the disk parameter block
|
|
mov c,d ; current disk# to c
|
|
; lsb of e = 0 if not yet logged - in
|
|
call seldskf ; hl filled by call
|
|
; hl = 0000 if error, otherwise disk headers
|
|
mov a,h! ora l! rz ; Return with C flag reset if select error
|
|
; Disk header block address in hl
|
|
mov e,m! inx h! mov d,m! inx h ; de=.tran
|
|
inx h ! inx h
|
|
shld curtrka! inx h! inx h ; hl=.currec
|
|
shld curreca! inx h! inx h ; hl=.buffa
|
|
inx h! inx h
|
|
inx h! inx h
|
|
; de still contains .tran
|
|
xchg! shld tranv ; .tran vector
|
|
lxi h,dpbaddr ; de= source for move, hl=dest
|
|
mvi c,addlist! call move ; addlist filled
|
|
; Now fill the disk parameter block
|
|
lhld dpbaddr! xchg ; de is source
|
|
lxi h,sectpt ; hl is destination
|
|
mvi c,dpblist! call move ; data filled
|
|
; Now set single/double map mode
|
|
lhld maxall ; largest allocation number
|
|
mov a,h ; 00 indicates < 255
|
|
lxi h,single! mvi m,true ; Assume a=00
|
|
ora a! jz retselect
|
|
; high order of maxall not zero, use double dm
|
|
mvi m,false
|
|
retselect:
|
|
; C flag set indicates successful select
|
|
stc
|
|
ret
|
|
|
|
home:
|
|
; Move to home position, then offset to start of dir
|
|
call homef
|
|
xra a ; constant zero to accumulator
|
|
lhld curtrka! mov m,a! inx h! mov m,a ; curtrk=0000
|
|
lhld curreca! mov m,a! inx h! mov m,a ; currec=0000
|
|
inx h! mov m,a ; currec high byte=00
|
|
|
|
ret
|
|
|
|
pass$arecord:
|
|
lxi h,arecord
|
|
mov e,m! inx h! mov d,m! inx h! mov b,m
|
|
ret
|
|
|
|
rdbuff:
|
|
; Read buffer and check condition
|
|
call pass$arecord
|
|
call readf ; current drive, track, sector, dma
|
|
|
|
|
|
diocomp: ; Check for disk errors
|
|
ora a! rz
|
|
mov c,a
|
|
cpi 3! jc goerr
|
|
mvi c,1! jmp goerr
|
|
|
|
seekdir:
|
|
; Seek the record containing the current dir entry
|
|
|
|
lhld dcnt ; directory counter to hl
|
|
mvi c,dskshf! call hlrotr ; value to hl
|
|
|
|
mvi b,0! xchg
|
|
|
|
lxi h,arecord
|
|
mov m,e! inx h! mov m,d! inx h! mov m,b
|
|
ret
|
|
|
|
seek:
|
|
; Seek the track given by arecord (actual record)
|
|
|
|
lhld curtrka! mov c,m! inx h! mov b,m ; bc = curtrk
|
|
push b ; s0 = curtrk
|
|
lhld curreca! mov e,m! inx h! mov d,m
|
|
inx h! mov b,m ; bde = currec
|
|
lhld arecord! lda arecord+2! mov c,a ; chl = arecord
|
|
seek0:
|
|
mov a,l! sub e! mov a,h! sbb d! mov a,c! sbb b
|
|
push h ; Save low(arecord)
|
|
jnc seek1 ; if arecord >= currec then go to seek1
|
|
lhld sectpt! call bde$e$bde$m$hl ; currec = currec - sectpt
|
|
pop h! xthl! dcx h! xthl ; curtrk = curtrk - 1
|
|
jmp seek0
|
|
seek1:
|
|
lhld sectpt! call bde$e$bde$p$hl ; currec = currec + sectpt
|
|
pop h ; Restore low(arecord)
|
|
mov a,l! sub e! mov a,h! sbb d! mov a,c! sbb b
|
|
jc seek2 ; if arecord < currec then go to seek2
|
|
xthl! inx h! xthl ; curtrk = curtrk + 1
|
|
push h ; save low (arecord)
|
|
jmp seek1
|
|
seek2:
|
|
xthl! push h ; hl,s0 = curtrk, s1 = low(arecord)
|
|
lhld sectpt! call bde$e$bde$m$hl ; currec = currec - sectpt
|
|
pop h! push d! push b! push h ; hl,s0 = curtrk,
|
|
; s1 = high(arecord,currec), s2 = low(currec),
|
|
; s3 = low(arecord)
|
|
xchg! lhld offset! dad d
|
|
mov b,h! mov c,l! shld track
|
|
call settrkf ; call bios settrk routine
|
|
; Store curtrk
|
|
pop d! lhld curtrka! mov m,e! inx h! mov m,d
|
|
; Store currec
|
|
pop b! pop d!
|
|
lhld curreca! mov m,e! inx h! mov m,d
|
|
inx h! mov m,b ; currec = bde
|
|
pop b ; bc = low(arecord), de = low(currec)
|
|
mov a,c! sub e! mov l,a ; hl = bc - de
|
|
mov a,b! sbb d! mov h,a
|
|
call shr$physhf
|
|
mov b,h! mov c,l
|
|
|
|
lhld tranv! xchg ; bc=sector#, de=.tran
|
|
call sectran ; hl = tran(sector)
|
|
mov c,l! mov b,h ; bc = tran(sector)
|
|
shld sector
|
|
call setsecf ; sector selected
|
|
lhld curdma! mov c,l! mov b,h! jmp setdmaf
|
|
|
|
shr$physhf:
|
|
lda physhf! mov c,a! jmp hlrotr
|
|
|
|
|
|
; file control block (fcb) constants
|
|
|
|
empty equ 0e5h ; empty directory entry
|
|
recsiz equ 128 ; record size
|
|
fcblen equ 32 ; file control block size
|
|
dirrec equ recsiz/fcblen ; directory fcbs / record
|
|
dskshf equ 2 ; log2(dirrec)
|
|
dskmsk equ dirrec-1
|
|
fcbshf equ 5 ; log2(fcblen)
|
|
|
|
extnum equ 12 ; extent number field
|
|
maxext equ 31 ; largest extent number
|
|
ubytes equ 13 ; unfilled bytes field
|
|
|
|
namlen equ 15 ; name length
|
|
reccnt equ 15 ; record count field
|
|
dskmap equ 16 ; disk map field
|
|
nxtrec equ fcblen
|
|
|
|
; utility functions for file access
|
|
|
|
dm$position:
|
|
; Compute disk map position for vrecord to hl
|
|
lxi h,blkshf! mov c,m ; shift count to c
|
|
lda vrecord ; current virtual record to a
|
|
dmpos0:
|
|
ora a! rar! dcr c! jnz dmpos0
|
|
; a = shr(vrecord,blkshf) = vrecord/2**(sect/block)
|
|
mov b,a ; Save it for later addition
|
|
mvi a,8! sub m ; 8-blkshf to accumulator
|
|
mov c,a ; extent shift count in register c
|
|
lda extval ; extent value ani extmsk
|
|
dmpos1:
|
|
; blkshf = 3,4,5,6,7, c=5,4,3,2,1
|
|
; shift is 4,3,2,1,0
|
|
dcr c! jz dmpos2
|
|
ora a! ral! jmp dmpos1
|
|
dmpos2:
|
|
; Arrive here with a = shl(ext and extmsk,7-blkshf)
|
|
add b ; Add the previous shr(vrecord,blkshf) value
|
|
; a is one of the following values, depending upon alloc
|
|
; bks blkshf
|
|
; 1k 3 v/8 + extval * 16
|
|
; 2k 4 v/16+ extval * 8
|
|
; 4k 5 v/32+ extval * 4
|
|
; 8k 6 v/64+ extval * 2
|
|
; 16k 7 v/128+extval * 1
|
|
ret ; with dm$position in a
|
|
|
|
getdma:
|
|
lhld info! lxi d,dskmap! dad d! ret
|
|
|
|
getdm:
|
|
; Return disk map value from position given by bc
|
|
call getdma
|
|
dad b ; Index by a single byte value
|
|
lda single ; single byte/map entry?
|
|
ora a! jz getdmd ; Get disk map single byte
|
|
mov l,m! mov h,b! ret ; with hl=00bb
|
|
getdmd:
|
|
dad b ; hl=.fcb(dm+i*2)
|
|
; double precision value returned
|
|
mov a,m! inx h! mov h,m! mov l,a! ret
|
|
|
|
index:
|
|
; Compute disk block number from current fcb
|
|
call dm$position ; 0...15 in register a
|
|
sta dminx
|
|
mov c,a! mvi b,0! call getdm ; value to hl
|
|
shld arecord! mov a,l! ora h! ret
|
|
|
|
atran:
|
|
; Compute actual record address, assuming index called
|
|
|
|
; arecord = shl(arecord,blkshf)
|
|
|
|
lda blkshf! mov c,a
|
|
lhld arecord! xra a! call shl3bv
|
|
shld arecord! sta arecord+2
|
|
|
|
shld arecord1 ; Save low(arecord)
|
|
|
|
; arecord = arecord or (vrecord and blkmsk)
|
|
|
|
lda blkmsk! mov c,a! lda vrecord! ana c
|
|
mov b,a ; Save vrecord & blkmsk in reg b & blk$off
|
|
sta blk$off
|
|
lxi h,arecord! ora m! mov m,a! ret
|
|
|
|
|
|
getexta:
|
|
; Get current extent field address to hl
|
|
lhld info! lxi d,extnum! dad d ; hl=.fcb(extnum)
|
|
ret
|
|
|
|
getrcnta:
|
|
; Get reccnt address to hl
|
|
lhld info! lxi d,reccnt! dad d! ret
|
|
|
|
getfcba:
|
|
; Compute reccnt and nxtrec addresses for get/setfcb
|
|
call getrcnta! xchg ; de=.fcb(reccnt)
|
|
lxi h,(nxtrec-reccnt)! dad d ; hl=.fcb(nxtrec)
|
|
ret
|
|
|
|
getfcb:
|
|
; Set variables from currently addressed fcb
|
|
call getfcba ; addresses in de, hl
|
|
mov a,m! sta vrecord ; vrecord=fcb(nxtrec)
|
|
xchg! mov a,m! sta rcount ; rcount=fcb(reccnt)
|
|
call getexta ; hl=.fcb(extnum)
|
|
lda extmsk ; extent mask to a
|
|
ana m ; fcb(extnum) and extmsk
|
|
sta extval
|
|
ret
|
|
|
|
setfcb:
|
|
; Place values back into current fcb
|
|
call getfcba ; addresses to de, hl
|
|
mvi c,1
|
|
|
|
lda vrecord! add c! mov m,a ; fcb(nxtrec)=vrecord+seqio
|
|
xchg! lda rcount! mov m,a ; fcb(reccnt)=rcount
|
|
ret
|
|
|
|
hlrotr:
|
|
; hl rotate right by amount c
|
|
inr c ; in case zero
|
|
hlrotr0: dcr c! rz ; return when zero
|
|
|
|
mov a,h! ora a! rar! mov h,a ; high byte
|
|
mov a,l! rar! mov l,a ; low byte
|
|
jmp hlrotr0
|
|
|
|
hlrotl:
|
|
; Rotate the mask in hl by amount in c
|
|
inr c ; may be zero
|
|
hlrotl0: dcr c! rz ; return if zero
|
|
|
|
dad h! jmp hlrotl0
|
|
|
|
set$cdisk:
|
|
; Set a "1" value in curdsk position of bc
|
|
lda seldsk
|
|
push b ; Save input parameter
|
|
mov c,a ; Ready parameter for shift
|
|
lxi h,1 ; number to shift
|
|
call hlrotl ; hl = mask to integrate
|
|
pop b ; original mask
|
|
mov a,c! ora l! mov l,a
|
|
mov a,b! ora h! mov h,a ; hl = mask or rol(1,curdsk)
|
|
ret
|
|
|
|
test$vector:
|
|
lda seldsk
|
|
mov c,a! call hlrotr
|
|
mov a,l! ani 1b! ret ; non zero if curdsk bit on
|
|
|
|
getdptra:
|
|
; Compute the address of a directory element at
|
|
; positon dptr in the buffer
|
|
|
|
lhld buffa! lda dptr
|
|
; hl = hl + a
|
|
add l! mov l,a! rnc
|
|
; overflow to h
|
|
inr h! ret
|
|
|
|
clr$ext:
|
|
; fcb ext = fcb ext & 1fh
|
|
|
|
call getexta! mov a,m! ani 0001$1111b! mov m,a!
|
|
ret
|
|
|
|
|
|
subdh:
|
|
; Compute hl = de - hl
|
|
mov a,e! sub l! mov l,a! mov a,d! sbb h! mov h,a
|
|
ret
|
|
|
|
get$buffa:
|
|
push d! lxi d,10! dad d
|
|
mov e,m! inx h! mov d,m
|
|
xchg! pop d! ret
|
|
|
|
|
|
rddir:
|
|
; Read a directory entry into the directory buffer
|
|
call seek$dir
|
|
lda phymsk! ora a! jz rddir1
|
|
mvi a,3
|
|
call deblock$dir! jmp setdata
|
|
|
|
rddir1:
|
|
call setdir ; directory dma
|
|
shld buffa! call seek
|
|
call rdbuff ; directory record loaded
|
|
|
|
setdata:
|
|
; Set data dma address
|
|
lhld dmaad! jmp setdma ; to complete the call
|
|
|
|
setdir:
|
|
; Set directory dma address
|
|
|
|
lhld dirbcba
|
|
call get$buffa
|
|
|
|
setdma:
|
|
; hl=.dma address to set (i.e., buffa or dmaad)
|
|
shld curdma! ret
|
|
|
|
end$of$dir:
|
|
; Return zero flag if at end of directory, non zero
|
|
; if not at end (end of dir if dcnt = 0ffffh)
|
|
lxi h,dcnt
|
|
mov a,m ; may be 0ffh
|
|
inx h! cmp m ; low(dcnt) = high(dcnt)?
|
|
rnz ; non zero returned if different
|
|
; high and low the same, = 0ffh?
|
|
inr a ; 0ffh becomes 00 if so
|
|
ret
|
|
|
|
set$end$dir:
|
|
; Set dcnt to the end of the directory
|
|
lxi h,enddir! shld dcnt! ret
|
|
|
|
|
|
read$dir:
|
|
; Read next directory entry, with c=true if initializing
|
|
|
|
lhld dirmax! xchg ; in preparation for subtract
|
|
lhld dcnt! inx h! shld dcnt ; dcnt=dcnt+1
|
|
|
|
; while(dirmax >= dcnt)
|
|
call subdh ; de-hl
|
|
jc set$end$dir
|
|
; not at end of directory, seek next element
|
|
; initialization flag is in c
|
|
|
|
lda dcnt! ani dskmsk ; low(dcnt) and dskmsk
|
|
mvi b,fcbshf ; to multiply by fcb size
|
|
|
|
read$dir1:
|
|
add a! dcr b! jnz read$dir1
|
|
; a = (low(dcnt) and dskmsk) shl fcbshf
|
|
sta dptr ; ready for next dir operation
|
|
ora a! rnz ; Return if not a new record
|
|
|
|
push b ; Save initialization flag c
|
|
call rd$dir ; Read the directory record
|
|
pop b ; Recall initialization flag
|
|
ret
|
|
compext:
|
|
; Compare extent# in a with that in c, return nonzero
|
|
; if they do not match
|
|
push b ; Save c's original value
|
|
push psw! lda extmsk! cma! mov b,a
|
|
; b has negated form of extent mask
|
|
mov a,c! ana b! mov c,a ; low bits removed from c
|
|
pop psw! ana b ; low bits removed from a
|
|
sub c! ani maxext ; Set flags
|
|
pop b ; Restore original values
|
|
ret
|
|
|
|
get$dir$ext:
|
|
; Compute directory extent from fcb
|
|
; Scan fcb disk map backwards
|
|
call getfcba ; hl = .fcb(vrecord)
|
|
mvi c,16! mov b,c! inr c! push b
|
|
; b=dskmap pos (rel to 0)
|
|
get$de0:
|
|
pop b
|
|
dcr c
|
|
xra a ; Compare to zero
|
|
get$de1:
|
|
dcx h! dcr b ; Decr dskmap position
|
|
cmp m! jnz get$de2 ; fcb(dskmap(b)) ~= 0
|
|
dcr c! jnz get$de1
|
|
; c = 0 -> all blocks = 0 in fcb disk map
|
|
get$de2:
|
|
mov a,c! sta dminx
|
|
lda single! ora a! mov a,b
|
|
jnz get$de3
|
|
rar ; not single, divide blk idx by 2
|
|
get$de3:
|
|
push b! push h ; Save dskmap position & count
|
|
mov l,a! mvi h,0 ; hl = non-zero blk idx
|
|
; Compute ext offset from last non-zero
|
|
; block index by shifting blk idx right
|
|
; 7 - blkshf
|
|
lda blkshf! mov d,a! mvi a,7! sub d
|
|
mov c,a! call hlrotr! mov b,l
|
|
; b = ext offset
|
|
lda extmsk! cmp b! pop h! jc get$de0
|
|
; Verify computed extent offset <= extmsk
|
|
call getexta! mov c,m
|
|
cma! ani maxext! ana c! ora b
|
|
; dir ext = (fcb ext & (~ extmsk) & maxext) | ext offset
|
|
pop b ; Restore stack
|
|
ret ; a = directory extent
|
|
|
|
|
|
search:
|
|
; Search for directory element of length c at info
|
|
lhld info! shld searcha ; searcha = info
|
|
mov a,c! sta searchl ; searchl = c
|
|
|
|
call set$end$dir ; dcnt = enddir
|
|
call home ; to start at the beginning
|
|
|
|
searchn:
|
|
; Search for the next directory element, assuming
|
|
; a previous call on search which sets searcha and
|
|
; searchl
|
|
|
|
mvi c,false! call read$dir ; Read next dir element
|
|
call end$of$dir! jz lret$eq$ff
|
|
; not end of directory, scan for match
|
|
lhld searcha! xchg ; de=beginning of user fcb
|
|
|
|
call getdptra ; hl = buffa+dptr
|
|
lda searchl! mov c,a ; length of search to c
|
|
mvi b,0 ; b counts up, c counts down
|
|
|
|
mov a,m! cpi empty! jz searchn
|
|
|
|
searchloop:
|
|
mov a,c! ora a! jz endsearch
|
|
; Scan next character if not ubytes
|
|
mov a,b! cpi ubytes! jz searchok
|
|
; not the ubytes field, extent field?
|
|
cpi extnum ; may be extent field
|
|
jz searchext ; Skip to search extent
|
|
ldax d
|
|
sub m! ani 7fh ; Mask-out flags/extent modulus
|
|
jnz searchn ; Skip if not matched
|
|
jmp searchok ; matched character
|
|
searchext:
|
|
ldax d
|
|
; Attempt an extent # match
|
|
push b ; Save counters
|
|
mov c,m ; directory character to c
|
|
call compext ; Compare user/dir char
|
|
pop b ; Recall counters
|
|
ora a ; Set flag
|
|
jnz searchn ; Skip if no match
|
|
searchok:
|
|
; current character matches
|
|
inx d! inx h! inr b! dcr c
|
|
jmp searchloop
|
|
endsearch:
|
|
; entire name matches, return dir position
|
|
xra a
|
|
sta lret ; lret = 0
|
|
; successful search -
|
|
; return with zero flag reset
|
|
mov b,a! inr b
|
|
ret
|
|
lret$eq$ff:
|
|
; unsuccessful search -
|
|
; return with zero flag set
|
|
; lret,low(aret) = 0ffh
|
|
mvi a,255 ! mov b,a ! inr b ! jmp sta$ret
|
|
|
|
open:
|
|
; Search for the directory entry, copy to fcb
|
|
mvi c,namlen! call search
|
|
rz ; Return with lret=255 if end
|
|
|
|
; not end of directory, copy fcb information
|
|
open$copy:
|
|
call getexta ! mov a,m ! push a ; save extent to check for extent
|
|
; folding - move moves entire dir FCB
|
|
call getdptra! xchg ; hl = .buff(dptr)
|
|
lhld info ; hl=.fcb(0)
|
|
mvi c,nxtrec ; length of move operation
|
|
call move ; from .buff(dptr) to .fcb(0)
|
|
|
|
; Note that entire fcb is copied, including indicators
|
|
|
|
call get$dir$ext! mov c,a
|
|
pop a ! mov m,a ; restore extent
|
|
|
|
; hl = .user extent#, c = dir extent#
|
|
; above move set fcb(reccnt) to dir(reccnt)
|
|
; if fcb ext < dir ext then fcb(reccnt) = fcb(reccnt) | 128
|
|
; if fcb ext = dir ext then fcb(reccnt) = fcb(reccnt)
|
|
; if fcb ext > dir ext then fcb(reccnt) = 0
|
|
|
|
set$rc: ; hl=.fcb(ext), c=dirext
|
|
mvi b,0
|
|
xchg! lxi h,(reccnt-extnum)! dad d
|
|
ldax d! sub c! jz set$rc2
|
|
mov a,b! jnc set$rc1
|
|
mvi a,128! mov b,m
|
|
|
|
set$rc1:
|
|
mov m,a! mov a,b! sta actual$rc! ret
|
|
set$rc2:
|
|
sta actual$rc
|
|
mov a,m! ora a! rnz ; ret if rc ~= 0
|
|
lda dminx! ora a! rz ; ret if no blks in fcb
|
|
lda fx! cpi 15! rz ; ret if fx = 15
|
|
mvi m,128 ; rc = 128
|
|
ret
|
|
|
|
restore$rc:
|
|
; hl = .fcb(extnum)
|
|
; if actual$rc ~= 0 then rcount = actual$rc
|
|
push h
|
|
lda actual$rc! ora a! jz restore$rc1
|
|
lxi d,(reccnt-extnum)! dad d
|
|
mov m,a! xra a! sta actual$rc
|
|
|
|
restore$rc1:
|
|
pop h! ret
|
|
|
|
open$reel:
|
|
; Close the current extent, and open the next one
|
|
; if possible.
|
|
|
|
call getexta
|
|
mov a,m! mov c,a
|
|
inr c! call compext
|
|
jz open$reel3
|
|
|
|
mvi a,maxext! ana c! mov m,a ; Incr extent field
|
|
mvi c,namlen! call search ; Next extent found?
|
|
; not end of file, open
|
|
call open$copy
|
|
|
|
open$reel2:
|
|
call getfcb ; Set parameters
|
|
xra a! sta vrecord! jmp sta$ret ; lret = 0
|
|
open$reel3:
|
|
inr m ; fcb(ex) = fcb(ex) + 1
|
|
call get$dir$ext! mov c,a
|
|
; Is new extent beyond dir$ext?
|
|
cmp m! jnc open$reel4 ; no
|
|
dcr m ; fcb(ex) = fcb(ex) - 1
|
|
jmp set$lret1
|
|
open$reel4:
|
|
call restore$rc
|
|
call set$rc! jmp open$reel2
|
|
|
|
seqdiskread:
|
|
; Sequential disk read operation
|
|
; Read the next record from the current fcb
|
|
|
|
call getfcb ; sets parameters for the read
|
|
|
|
lda vrecord! lxi h,rcount! cmp m ; vrecord-rcount
|
|
; Skip if rcount > vrecord
|
|
jc recordok
|
|
|
|
; not enough records in the extent
|
|
; record count must be 128 to continue
|
|
cpi 128 ; vrecord = 128?
|
|
jnz setlret1 ; Skip if vrecord<>128
|
|
call open$reel ; Go to next extent if so
|
|
; Check for open ok
|
|
lda lret! ora a! jnz setlret1 ; Stop at eof
|
|
|
|
recordok:
|
|
; Arrive with fcb addressing a record to read
|
|
|
|
call index ; Z flag set if arecord = 0
|
|
|
|
jz setlret1 ; Reading unwritten data
|
|
|
|
; Record has been allocated
|
|
call atran ; arecord now a disk address
|
|
|
|
lda phymsk! ora a ; if not 128 byte sectors
|
|
jnz read$deblock ; go to deblock
|
|
|
|
call setdata ; Set curdma = dmaad
|
|
call seek ; Set up for read
|
|
call rdbuff ; Read into (curdma)
|
|
jmp setfcb ; Update FCB
|
|
|
|
curselect:
|
|
lda seldsk! inr a! jz sel$error
|
|
dcr a! lxi h,curdsk! cmp m! rz
|
|
|
|
; Skip if seldsk = curdsk, fall into select
|
|
select:
|
|
; Select disk info for subsequent input or output ops
|
|
mov m,a ; curdsk = seldsk
|
|
|
|
mov d,a ; Save seldsk in register D for selectdisk call
|
|
lhld dlog! call test$vector ; test$vector does not modify DE
|
|
mov e,a! push d ; Send to seldsk, save for test below
|
|
call selectdisk! pop h ; Recall dlog vector
|
|
jnc sel$error ; returns with C flag set if select ok
|
|
; Is the disk logged in?
|
|
dcr l ; reg l = 1 if so
|
|
rz ; yes - drive previously logged in
|
|
|
|
lhld dlog! mov c,l! mov b,h ; call ready
|
|
call set$cdisk! shld dlog ; dlog=set$cdisk(dlog)
|
|
ret
|
|
|
|
set$seldsk:
|
|
lda linfo! sta seldsk! ret
|
|
|
|
reselectx:
|
|
xra a! sta high$ext! jmp reselect1
|
|
reselect:
|
|
; Check current fcb to see if reselection necessary
|
|
mvi a,80h! mov b,a! dcr a! mov c,a ; b = 80h, c = 7fh
|
|
lhld info! lxi d,7! xchg! dad d
|
|
mov a,m! ana b
|
|
; fcb(7) = fcb(7) & 7fh
|
|
mov a,m! ana c! mov m,a
|
|
; high$ext = 80h & fcb(8)
|
|
inx h! mov a,m! ana b! sta high$ext
|
|
; fcb(8) = fcb(8) & 7fh
|
|
mov a,m! ana c! mov m,a
|
|
; fcb(ext) = fcb(ext) & 1fh
|
|
call clr$ext
|
|
|
|
; if fcb(rc) & 80h
|
|
; then fcb(rc) = 80h, actual$rc = fcb(rc) & 7fh
|
|
; else actual$rc = 0
|
|
|
|
call getrcnta! mov a,m! ana b! jz reselect1
|
|
mov a,m! ana c! mov m,b
|
|
|
|
reselect1:
|
|
sta actual$rc
|
|
|
|
lxi h,0
|
|
shld fcbdsk ; fcbdsk = 0
|
|
mvi a,true! sta resel ; Mark possible reselect
|
|
lhld info! mov a,m ; drive select code
|
|
ani 1$1111b ; non zero is auto drive select
|
|
dcr a ; Drive code normalized to 0..30, or 255
|
|
sta linfo ; Save drive code
|
|
cpi 0ffh! jz noselect
|
|
; auto select function, seldsk saved above
|
|
mov a,m! sta fcbdsk ; Save drive code
|
|
call set$seldsk
|
|
|
|
noselect:
|
|
call curselect
|
|
mvi a,0 ! lhld info ! mov m,a
|
|
ret
|
|
|
|
;
|
|
; individual function handlers
|
|
;
|
|
|
|
func12 equ func$ret
|
|
|
|
func13:
|
|
|
|
; Reset disk system - initialize to disk 0
|
|
lxi h,0! shld dlog
|
|
|
|
xra a! sta seldsk
|
|
dcr a! sta curdsk
|
|
|
|
lxi h,tbuff! shld dmaad ; dmaad = tbuff
|
|
jmp setdata ; to data dma address
|
|
|
|
func14:
|
|
; Select disk info
|
|
call set$seldsk ; seldsk = linfo
|
|
jmp curselect
|
|
|
|
func15:
|
|
; Open file
|
|
call reselectx
|
|
call open! call openx ; returns if unsuccessful, a = 0
|
|
ret
|
|
|
|
openx:
|
|
call end$of$dir! rz
|
|
call getfcba! mov a,m! inr a! jnz openxa
|
|
dcx d! dcx d! ldax d! mov m,a
|
|
openxa:
|
|
; open successful
|
|
pop h ; Discard return address
|
|
mvi c,0100$0000b
|
|
ret
|
|
|
|
func16 equ func$ret
|
|
|
|
func17 equ func$ret
|
|
|
|
func18 equ func$ret
|
|
|
|
func19 equ func$ret
|
|
|
|
func20:
|
|
; Read a file
|
|
call reselect
|
|
jmp seqdiskread
|
|
|
|
func21 equ func$ret
|
|
|
|
func22 equ func$ret
|
|
|
|
func23 equ func$ret
|
|
|
|
func24 equ func$ret
|
|
|
|
func25: lda seldsk ! jmp sta$ret
|
|
|
|
func26: xchg ! shld dmaad
|
|
jmp setdata
|
|
|
|
func27 equ func$ret
|
|
|
|
func28: equ func$ret
|
|
|
|
func29 equ func$ret
|
|
|
|
func30 equ func$ret
|
|
|
|
func31 equ func$ret
|
|
|
|
func32 equ func$ret
|
|
|
|
func33 equ func$ret
|
|
|
|
func34 equ func$ret
|
|
|
|
func35 equ func$ret
|
|
|
|
func36 equ func$ret
|
|
|
|
func37 equ func$ret
|
|
|
|
func38 equ func$ret
|
|
|
|
func39 equ func$ret
|
|
|
|
func40 equ func$ret
|
|
|
|
func42 equ func$ret
|
|
|
|
func43 equ func$ret
|
|
|
|
func44 equ func$ret
|
|
|
|
func45 equ func$ret
|
|
|
|
func46 equ func$ret
|
|
|
|
func47 equ func$ret
|
|
|
|
func48 equ func$ret
|
|
|
|
func49 equ func$ret
|
|
|
|
func50 equ func$ret
|
|
|
|
func100 equ func$ret
|
|
|
|
func101 equ func$ret
|
|
|
|
func102 equ func$ret
|
|
|
|
func103 equ func$ret
|
|
|
|
func104 equ func$ret
|
|
|
|
func105 equ func$ret
|
|
|
|
func106 equ func$ret
|
|
|
|
func107 equ func$ret
|
|
|
|
func108 equ func$ret
|
|
|
|
func109 equ func$ret
|
|
|
|
|
|
goback:
|
|
; Arrive here at end of processing to return to user
|
|
lda fx! cpi 15! jc retmon
|
|
lda olddsk! sta seldsk ; Restore seldsk
|
|
lda resel! ora a! jz retmon
|
|
|
|
lhld info! mvi m,0 ; fcb(0)=0
|
|
lda fcbdsk! ora a! jz goback1
|
|
; Restore fcb(0)
|
|
mov m,a ; fcb(0)=fcbdsk
|
|
goback1:
|
|
; fcb(8) = fcb(8) | high$ext
|
|
inx h! lda high$ext! ora m! mov m,a
|
|
; fcb(rc) = fcb(rc) | actual$rc
|
|
call getrcnta! lda actual$rc! ora m! mov m,a
|
|
; return from the disk monitor
|
|
retmon:
|
|
lhld entsp! sphl
|
|
lhld aret! mov a,l! mov b,h
|
|
ret
|
|
;
|
|
; data areas
|
|
;
|
|
dlog: dw 0 ; logged-in disks
|
|
curdma ds word ; current dma address
|
|
buffa: ds word ; pointer to directory dma address
|
|
|
|
;
|
|
; curtrka - alloca are set upon disk select
|
|
; (data must be adjacent, do not insert variables)
|
|
; (address of translate vector, not used)
|
|
cdrmaxa:ds word ; pointer to cur dir max value (2 bytes)
|
|
curtrka:ds word ; current track address (2)
|
|
curreca:ds word ; current record address (3)
|
|
drvlbla:ds word ; current drive label byte address (1)
|
|
lsn$add:ds word ; login sequence # address (1)
|
|
; +1 -> bios media change flag (1)
|
|
dpbaddr:ds word ; current disk parameter block address
|
|
checka: ds word ; current checksum vector address
|
|
alloca: ds word ; current allocation vector address
|
|
dirbcba:ds word ; dir bcb list head
|
|
dtabcba:ds word ; data bcb list head
|
|
hash$tbla:
|
|
ds word
|
|
ds byte
|
|
|
|
addlist equ $-dpbaddr ; address list size
|
|
|
|
;
|
|
; buffer control block format
|
|
;
|
|
; bcb format : drv(1) || rec(3) || pend(1) || sequence(1) ||
|
|
; 0 1 4 5
|
|
;
|
|
; track(2) || sector(2) || buffer$add(2) ||
|
|
; 6 8 10
|
|
;
|
|
; link(2)
|
|
; 12
|
|
;
|
|
|
|
; sectpt - offset obtained from disk parm block at dpbaddr
|
|
; (data must be adjacent, do not insert variables)
|
|
sectpt: ds word ; sectors per track
|
|
blkshf: ds byte ; block shift factor
|
|
blkmsk: ds byte ; block mask
|
|
extmsk: ds byte ; extent mask
|
|
maxall: ds word ; maximum allocation number
|
|
dirmax: ds word ; largest directory number
|
|
dirblk: ds word ; reserved allocation bits for directory
|
|
chksiz: ds word ; size of checksum vector
|
|
offset: ds word ; offset tracks at beginning
|
|
physhf: ds byte ; physical record shift
|
|
phymsk: ds byte ; physical record mask
|
|
dpblist equ $-sectpt ; size of area
|
|
;
|
|
; local variables
|
|
;
|
|
blk$off: ds byte ; record offset within block
|
|
dir$cnt: ds byte ; direct i/o count
|
|
|
|
tranv: ds word ; address of translate vector
|
|
linfo: ds byte ; low(info)
|
|
dminx: ds byte ; local for diskwrite
|
|
|
|
actual$rc:
|
|
ds byte ; directory ext record count
|
|
|
|
single: ds byte ; set true if single byte allocation map
|
|
|
|
|
|
olddsk: ds byte ; disk on entry to bdos
|
|
rcount: ds byte ; record count in current fcb
|
|
extval: ds byte ; extent number and extmsk
|
|
|
|
vrecord:ds byte ; current virtual record
|
|
|
|
curdsk:
|
|
|
|
adrive: db 0ffh ; current disk
|
|
arecord:ds word ; current actual record
|
|
ds byte
|
|
|
|
arecord1: ds word ; current actual block# * blkmsk
|
|
|
|
;******** following variable order critical *****************
|
|
|
|
high$ext: ds byte ; fcb high ext bits
|
|
;xfcb$read$only: ds byte
|
|
|
|
; local variables for directory access
|
|
dptr: ds byte ; directory pointer 0,1,2,3
|
|
|
|
;
|
|
; local variables initialized by bdos at entry
|
|
;
|
|
fcbdsk: ds byte ; disk named in fcb
|
|
|
|
phy$off: ds byte
|
|
curbcba: ds word
|
|
|
|
track: ds word
|
|
sector: ds word
|
|
|
|
read$deblock:
|
|
mvi a,1! call deblock$dta
|
|
jmp setfcb
|
|
|
|
column db 0
|
|
outdelim: db '$'
|
|
|
|
dmaad: dw 0080h
|
|
seldsk: db 0
|
|
info: dw 0
|
|
resel: db 0
|
|
fx: db 0
|
|
dcnt: dw 0
|
|
searcha: dw 0
|
|
searchl: db 0
|
|
|
|
|
|
; **************************
|
|
; Blocking/Deblocking Module
|
|
; **************************
|
|
|
|
deblock$dir:
|
|
|
|
lhld dirbcba
|
|
|
|
jmp deblock
|
|
|
|
deblock$dta:
|
|
lhld dtabcba
|
|
|
|
deblock:
|
|
|
|
; BDOS Blocking/Deblocking routine
|
|
; a = 1 -> read command
|
|
; a = 2 -> write command
|
|
; a = 3 -> locate command
|
|
; a = 4 -> flush command
|
|
; a = 5 -> directory update
|
|
|
|
push a ; Save z flag and deblock fx
|
|
|
|
; phy$off = low(arecord) & phymsk
|
|
; low(arecord) = low(arecord) & ~phymsk
|
|
call deblock8
|
|
lda arecord! mov e,a! ana b! sta phy$off
|
|
mov a,e! ana c! sta arecord
|
|
|
|
shld curbcba! call getbuffa! shld curdma
|
|
|
|
call deblock9
|
|
; Is command flush?
|
|
pop a! push a! cpi 4
|
|
jnc deblock1 ; yes
|
|
; Is referenced physical record
|
|
;already in buffer?
|
|
call compare! jz deblock45 ; yes
|
|
xra a
|
|
deblock1:
|
|
call deblock10
|
|
; Read physical record buffer
|
|
mvi a,2! call deblock$io
|
|
|
|
call deblock9 ; phypfx = adrive || arecord
|
|
call move! mvi m,0 ; zero pending flag
|
|
|
|
deblock45:
|
|
; recadd = phybuffa + phy$off*80h
|
|
lda phy$off! inr a! lxi d,80h! lxi h,0ff80h
|
|
deblock5:
|
|
dad d! dcr a! jnz deblock5
|
|
xchg! lhld curdma! dad d
|
|
; If deblock command = locate
|
|
; then buffa = recadd; return
|
|
pop a! cpi 3! jnz deblock6
|
|
shld buffa! ret
|
|
deblock6:
|
|
xchg! lhld dmaad! lxi b,80h
|
|
; If deblock command = read
|
|
jmp move$tpa ; then move to dma
|
|
|
|
deblock8:
|
|
lda phymsk! mov b,a! cma! mov c,a! ret
|
|
|
|
deblock9:
|
|
lhld curbcba! lxi d,adrive! mvi c,4! ret
|
|
|
|
deblock10:
|
|
lxi d,4
|
|
deblock11:
|
|
lhld curbcba! dad d! ret
|
|
|
|
deblock$io:
|
|
; a = 0 -> seek only
|
|
; a = 1 -> write
|
|
; a = 2 -> read
|
|
push a! call seek
|
|
pop a! dcr a
|
|
cp rdbuff
|
|
; Move track & sector to bcb
|
|
call deblock10! inx h! inx h
|
|
lxi d,track! mvi c,4! jmp move
|
|
|
|
org base+((($-base)+255) and 0ff00h)-1
|
|
db 0
|
|
|
|
; Bios equates
|
|
|
|
bios$pg equ $
|
|
|
|
bootf equ bios$pg+00 ; 00. cold boot
|
|
conoutf equ bios$pg+12 ; 04. console output function
|
|
homef equ bios$pg+24 ; 08. disk home function
|
|
seldskf equ bios$pg+27 ; 09. select disk function
|
|
settrkf equ bios$pg+30 ; 10. set track function
|
|
setsecf equ bios$pg+33 ; 11. set sector function
|
|
setdmaf equ bios$pg+36 ; 12. set dma function
|
|
sectran equ bios$pg+48 ; 16. sector translate
|
|
movef equ bios$pg+75 ; 25. memory move function
|
|
readf equ bios$pg+39 ; 13. read disk function
|
|
move$out equ movef
|
|
move$tpa equ movef
|
|
|
|
end
|