Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,350 @@
;*****************************************************
;* *
;* Sector Blocking / Deblocking *
;* *
;* This algorithm is a direct translation of the *
;* CP/M-80 Version, and is included here for refer- *
;* ence purposes only. The file DEBLOCK.LIB is in- *
;* cluded on your MP/M-86 disk, and should be used *
;* for actual applications. You may wish to contact *
;* Digital Research for notices of updates. *
;* *
;*****************************************************
;
;*****************************************************
;* *
;* CP/M to host disk constants *
;* *
;* (This example is setup for CP/M block size of 16K *
;* with a host sector size of 512 bytes, and 12 sec- *
;* tors per track. Blksiz, hstsiz, hstspt, hstblk *
;* and secshf may change for different hardware.) *
;*****************************************************
una equ byte ptr [BX] ;name for byte at BX
;
blksiz equ 16384 ;CP/M allocation size
hstsiz equ 512 ;host disk sector size
hstspt equ 12 ;host disk sectors/trk
hstblk equ hstsiz/128 ;CP/M sects/host buff
;
;*****************************************************
;* *
;* secshf is log2(hstblk), and is listed below for *
;* values of hstsiz up to 2048. *
;* *
;* hstsiz hstblk secshf *
;* 256 2 1 *
;* 512 4 2 *
;* 1024 8 3 *
;* 2048 16 4 *
;* *
;*****************************************************
secshf equ 2 ;log2(hstblk)
cpmspt equ hstblk * hstspt ;CP/M sectors/track
secmsk equ hstblk-1 ;sector mask
;
;*****************************************************
;* *
;* BDOS constants on entry to write *
;* *
;*****************************************************
wrall equ 0 ; deferred write
wrdir equ 1 ; non-deferred write
wrual equ 2 ; def wrt 1st sect unalloc blk
wrdal equ 3 ; non-def 1st sect unalloc blk
;
;*****************************************************
;* *
;* The BIOS entry points given below show the *
;* code which is relevant to deblocking only. *
;* *
;*****************************************************
seldsk:
;select disk
;is this the first activation of the drive?
test DL,1 ;lsb = 0?
jnz selset
;this is the first activation, clear host buff
mov hstact,0
mov unacnt,0
selset:
mov al,cl ! cbw ;put in AX
mov sekdsk,al ;seek disk number
mov cl,4 ! shl al,cl ;times 16
add ax,offset dpbase
mov bx,ax
ret
;
home:
;home the selected disk
mov al,hstwrt ;check for pending write
test al,al
jnz homed
mov hstact,0 ;clear host active flag
homed:
mov cx,0 ;now, set track zero
; (continue HOME routine)
ret
;
settrk:
;set track given by registers CX
mov sektrk,CX ;track to seek
ret
;
setsec:
;set sector given by register cl
mov seksec,cl ;sector to seek
ret
;
setdma:
;set dma address given by CX
mov dma_off,CX
ret
;
setdmab:
;set segment address given by CX
mov dma_seg,CX
ret
;
sectran:
;translate sector number CX with table at [DX]
test DX,DX ;test for hard skewed
jz notran ;(blocked must be hard skewed)
mov BX,CX
add BX,DX
mov BL,[BX]
ret
no_tran:
;hard skewed disk, physical = logical sector
mov BX,CX
ret
;
read:
;read the selected CP/M sector
mov unacnt,0 ;clear unallocated counter
mov readop,1 ;read operation
mov rsflag,1 ;must read data
mov wrtype,wrual ;treat as unalloc
jmp rwoper ;to perform the read
;
write:
;write the selected CP/M sector
mov readop,0 ;write operation
mov wrtype,cl
and cl,wrual ;write unallocated?
jz chkuna ;check for unalloc
;
; write to unallocated, set parameters
;
mov unacnt,(blksiz/128) ;next unalloc recs
mov al,sekdsk ;disk to seek
mov unadsk,al ;unadsk = sekdsk
mov ax,sektrk
mov unatrk,ax ;unatrk = sektrk
mov al,seksec
mov unasec,al ;unasec = seksec
;
chkuna:
;check for write to unallocated sector
;
mov bx,offset unacnt ;point "UNA" at UNACNT
mov al,una ! test al,al ;any unalloc remain?
jz alloc ;skip if not
;
; more unallocated records remain
dec al ;unacnt = unacnt-1
mov una,al
mov al,sekdsk ;same disk?
mov BX,offset unadsk
cmp al,una ;sekdsk = unadsk?
jnz alloc ;skip if not
;
; disks are the same
mov AX, unatrk
cmp AX, sektrk
jnz alloc ;skip if not
;
; tracks are the same
mov al,seksec ;same sector?
;
mov BX,offset unasec ;point una at unasec
;
cmp al,una ;seksec = unasec?
jnz alloc ;skip if not
;
; match, move to next sector for future ref
inc una ;unasec = unasec+1
mov al,una ;end of track?
cmp al,cpmspt ;count CP/M sectors
jb noovf ;skip if below
;
; overflow to next track
mov una,0 ;unasec = 0
inc unatrk ;unatrk=unatrk+1
;
noovf:
;match found, mark as unnecessary read
mov rsflag,0 ;rsflag = 0
jmps rwoper ;to perform the write
;
alloc:
;not an unallocated record, requires pre-read
mov unacnt,0 ;unacnt = 0
mov rsflag,1 ;rsflag = 1
;drop through to rwoper
;
;*****************************************************
;* *
;* Common code for READ and WRITE follows *
;* *
;*****************************************************
rwoper:
;enter here to perform the read/write
mov erflag,0 ;no errors (yet)
mov al, seksec ;compute host sector
mov cl, secshf
shr al,cl
mov sekhst,al ;host sector to seek
;
; active host sector?
mov al,1
xchg al,hstact ;always becomes 1
test al,al ;was it already?
jz filhst ;fill host if not
;
; host buffer active, same as seek buffer?
mov al,sekdsk
cmp al,hstdsk ;sekdsk = hstdsk?
jnz nomatch
;
; same disk, same track?
mov ax,hsttrk
cmp ax,sektrk ;host track same as seek track
jnz nomatch
;
; same disk, same track, same buffer?
mov al,sekhst
cmp al,hstsec ;sekhst = hstsec?
jz match ;skip if match
nomatch:
;proper disk, but not correct sector
mov al, hstwrt
test al,al ;"dirty" buffer ?
jz filhst ;no, don't need to write
call writehst ;yes, clear host buff
; (check errors here)
;
filhst:
;may have to fill the host buffer
mov al,sekdsk ! mov hstdsk,al
mov ax,sektrk ! mov hsttrk,ax
mov al,sekhst ! mov hstsec,al
mov al,rsflag
test al,al ;need to read?
jz filhst1
;
call readhst ;yes, if 1
; (check errors here)
;
filhst1:
mov hstwrt,0 ;no pending write
;
match:
;copy data to or from buffer depending on "readop"
mov al,seksec ;mask buffer number
and ax,secmsk ;least signif bits are masked
mov cl, 7 ! shl ax,cl ;shift left 7 (* 128 = 2**7)
;
; ax has relative host buffer offset
;
add ax,offset hstbuf ;ax has buffer address
mov si,ax ;put in source index register
mov di,dma_off ;user buffer is dest if readop
;
push DS ! push ES ;save segment registers
;
mov ES,dma_seg ;set destseg to the users seg
;SI/DI and DS/ES is swapped
;if write op
mov cx,128/2 ;length of move in words
mov al,readop
test al,al ;which way?
jnz rwmove ;skip if read
;
; write operation, mark and switch direction
mov hstwrt,1 ;hstwrt = 1 (dirty buffer now)
xchg si,di ;source/dest index swap
mov ax,DS
mov ES,ax
mov DS,dma_seg ;setup DS,ES for write
;
rwmove:
cld ! rep movs AX,AX ;move as 16 bit words
pop ES ! pop DS ;restore segment registers
;
; data has been moved to/from host buffer
and wrtype,wrdir ;write type to directory?
mov al,erflag ;in case of errors
jz return_rw ;no further processing
;
; clear host buffer for directory write
test al,al ;errors?
jnz return_rw ;skip if so
mov hstwrt,0 ;buffer written
call writehst
mov al,erflag
return_rw:
ret
;
;*****************************************************
;* *
;* WRITEHST performs the physical write to the host *
;* disk, while READHST reads the physical disk. *
;* *
;*****************************************************
writehst:
ret
;
readhst:
ret
;
;*****************************************************
;* *
;* Use the GENDEF utility to create disk def tables *
;* *
;*****************************************************
dpbase equ offset $
; disk parameter tables go here
;
;*****************************************************
;* *
;* Uninitialized RAM areas follow, including the *
;* areas created by the GENDEF utility listed above. *
;* *
;*****************************************************
sek_dsk rb 1 ;seek disk number
sek_trk rw 1 ;seek track number
sek_sec rb 1 ;seek sector number
;
hst_dsk rb 1 ;host disk number
hst_trk rw 1 ;host track number
hst_sec rb 1 ;host sector number
;
sek_hst rb 1 ;seek shr secshf
hst_act rb 1 ;host active flag
hst_wrt rb 1 ;host written flag
;
una_cnt rb 1 ;unalloc rec cnt
una_dsk rb 1 ;last unalloc disk
una_trk rw 1 ;last unalloc track
una_sec rb 1 ;last unalloc sector
;
erflag rb 1 ;error reporting
rsflag rb 1 ;read sector flag
readop rb 1 ;1 if read operation
wrtype rb 1 ;write operation type
dma_seg rw 1 ;last dma segment
dma_off rw 1 ;last dma offset
hstbuf rb hstsiz ;host buffer
end


View File

@@ -0,0 +1,132 @@
;******************* BDOS data area ********************
;
;
; 8086 variables that must recide in code segment
;
cseg $
;
axsave dw 0 ; register saves
SS_save dw 0
SP_save dw 0
;
; Variables in data segment:
;
dseg cpmsegment
org bdosoffset+bdoscodesize
;
; byte I/O variables:
;
compcol db 0 ;true if computing column position
strtcol db 0 ;starting column position after read
column db 0 ;column position
listcp db 0 ;listing toggle
kbchar db 0 ;initial key char = 00
;
; common values shared between bdosi and bdos
;
usrcode db 0 ;current user number
curdsk db 0 ;current disk number
info dw 0 ;information address
aret dw 0 ;address value to return
lret EQU byte ptr aret ;low(aret)
;
; data areas for file system:
;
; initialized data
;
efcb db empty ;0e5=available dir entry
rodsk dw 0 ;read only disk vector
dlog dw 0 ;logged-in disks
dmaad dw 0 ;dma address
;
; curtrka - alloca are set upon disk select
; (data must be adjacent, do not insert variables)
; (address of translate vector, not used)
;
cdrmaxa dw 0 ;pointer to cur dir max value
curtrka dw 0 ;current track address
curreca dw 0 ;current record address
buffa dw 0 ;pointer to directory dma address
dpbaddr dw 0 ;current disk parameter block address
checka dw 0 ;current checksum vector address
alloca dw 0 ;current allocation vector address
addlist EQU 8 ;"$-buffa" = address list size
;
; sectpt - offset obtained from disk parm block at dpbaddr
; (data must be adjacent, do not insert variables)
sectpt dw 0 ;sectors per track
blkshf db 0 ;block shift factor
blkmsk db 0 ;block mask
extmsk db 0 ;extent mask
maxall dw 0 ;maximum allocation number
dirmax dw 0 ;largest directory number
dirblk dw 0 ;reserved allocation bits for direct.
chksiz dw 0 ;size of checksum vector
offsetv dw 0 ;offset tracks at beginning
endlist rs 0 ;end of list
dpblist equ (offset endlist)-(offset sectpt) ;size
;
; local variables
tranv dw 0 ;address of translate vector
fcbcopied db 0 ;set true if copy$fcb called
rmf db 0 ;read mode flag for open$reel
dirloc db 0 ;directory flag in rename, etc.
seqio db 0 ;1 if sequential i/o
linfo db 0 ;low(info)
dminx db 0 ;local for diskwrite
srchl db 0 ;search length
srcha dw 0 ;search address
tinfo dw 0 ;temp for info in "make"
single db 0 ;set true if single byte
;allocation map
resel db 0 ;reselection flag
olddsk db 0 ;disk on entry to bdos
fcbdsk db 0 ;disk named in fcb
rcount db 0 ;record count in current fcb
extval db 0 ;extent number and extmsk
vrecord dw 0 ;current virtual record
lvrecord equ byte ptr vrecord ;low (vrecord)
arecord dw 0 ;current actual record
ablock dw 0 ;current actual block# * blkmsk
;
; local variables for directory access
dptr db 0 ;directory pointer 0,1,2,3
dcnt dw 0 ;directory counter 0,1,...,dirmax
ldcnt equ byte ptr dcnt ;low(dcnt)
drec dw 0 ;directory record 0,1,...,dirmax/4
;
; Special 8086 variables:
;
ioloc db 0 ;iobyte
dmabase dw 0 ;segment base for disk I/O
infosave dw 0 ;save for FCB address
parametersegment dw 0 ;user parameter segment
parcopfl db 0 ;true if parameter block copied
parlg db 0 ;length of parameter block
nallocmem db 0 ;no. of allocated memory segments
ncrmem db 0 ;no. of available memory segments
crmem dw 0,0 ;memory table (16 elements)
dw 0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
dw 0,0,0,0,0,0,0,0
;
;
; error messages
;
dskmsg db 'Bdos Err On '
dskerr db ' : $' ;filled in by errflg
permsg db 'Bad Sector$'
selmsg db 'Select$'
rofmsg db 'File '
rodmsg db 'R/O$'
;
; Local buffer area:
;
loc_par_area rb 258 ;local user parameter (FCB,...)
stackarea rw ssize ;stack size
endstack rb 0 ;top of stack
;
;******************** end BDOS data area *******************
end


View File

@@ -0,0 +1,212 @@
;******************** BDOS entry module ********************
;
; Perform branching, error handling and special
; 8086 stuff.
;
;
cseg cpmsegment
org bdosoffset
;
db 0,0,0,0,0,0
;
; enter here from the user's program with function number in cl,
; and information address in dx
;
JMP bdose ;past parameter block
;
; ************************************************
; *** relative locations 0009 - 000e ***
; ************************************************
pererr dw persub ;permanent error subroutine
seler dw selsub ;select error subroutine
roderr dw rodsub ;ro disk error subroutine
rofer dw rofsub ;ro file error subroutine
;
;
bdose: ;arrive here from user progs
mov axsave,ax ;switch stack segment
mov SS_save,ss
mov SP_save,sp
mov ax,cs
; add ax,(bdosoffset+bdoscodesize)/16
mov ss,ax
lea sp,endstack
;
;pick up parameter segment
mov ax,ds
;
push ds ;save registers
push es
push bp
push di
push si
;
push ss ;switch to local segment registers
push ss
pop es
pop ds
;
mov parametersegment,ax
mov ax,axsave
;
call oldbdos ;call 8080 BDOS
;
pop si ;unsave 8086 registers
pop di
pop bp
pop es
pop ds
;
;switch back to entry stack
mov sp,SP_save
mov ss,SS_save
iret ; return from interrupt
;
;
oldbdos: ;8080 bdos entry point
MOV info,dx ;info=dx
MOV linfo,dl ;linfo = low(info) - don't equ
MOV aret,0 ;return value defaults to 0000
mov parcopfl,false ;set true if parameter
;block copied from user
; MOV entsp,sp ;entsp = stackptr
; LEA sp,lstack ;local stack setup
XOR AL,AL
MOV fcbdsk,AL
MOV resel,AL ;fcbdsk,resel=false
MOV BX,offset goback ;common return point
PUSH BX ;jmp goback equivalent to ret
CMP cl,nfuncs80
jb branch
sub cl,sfunc86-nfuncs80
cmp cl,nfuncs
jb branch
RET
; ;skip if invalid #
branch: MOV bl,cl
mov bh,0
MOV CL,DL ;possible output char. to CL
add bx,bx ;branch
jmp cs:functab[bx]
;
; dispatch table for functions
;
functab dw wbootf,func1,func2,func3
dw punchf,listf,func6,func7
dw func8,func9,func10,func11
diskf equ 12 ;beginning of disk functions
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
dw func50,func51,func52,func53 ;8086 functions
dw func54,func55,func56,func57
nfuncs80 equ 41 ;number of 8080 functions
sfunc86 equ 50 ;start number for 8086 functions
nfuncs equ 49 ;total number of BDOS functions
;
;
; error subroutines
persub: ;report permanent error
LEA BX,permsg
CALL errflg ;to report the error
CMP AL,ctlc
jnz parret ;rnz
JMP wbootf
;reboot if response is ctlc
;and ignore the error
;
selsub: ;report select error
LEA BX,selmsg
JMPS waiterr ;wait console before boot
;
rodsub: ;report write to R/O disk
LEA BX,rodmsg
JMPS waiterr
;
rofsub: ;report read/only file
LEA BX,rofmsg ;wait for console
;
waiterr:
;wait for response before boot
CALL errflg
JMP wbootf
;
errflg:
;report error to console,
;message address in BX
PUSH BX
CALL crlf ;stack mssg address, new line
MOV AL,curdsk
ADD AL,'A'
MOV dskerr,AL ;current disk name
LEA CX,dskmsg
CALL print ;the error message
POP CX
CALL print ;error mssage tail
jmp coninf ;jump to input character
;note: conin is now coninf for cpm loader, goes to bios
;
parsave:
;copy parameterblock from user segment to BDOS segment
;CL-reg = lenght of parameter block
;
push ds
push ax
push cx
mov parcopfl,true
mov parlg,cl
xor ch,ch
mov si,info
mov infosave,si
lea di,loc_par_area
mov info,di
mov ds,parametersegment
rep movs al,al
pop cx
pop ax
pop ds
parret: ret
;
parsave33:
;copy 33 byte length parameterblock
push cx
mov cl,33
jmps pscommon
;
parsave36:
;copy 36 byte length parameterblock
push cx
mov cl,36
pscommon:
call parsave
pop cx
ret
;
parunsave:
;copy local parameter block to user segment
;
push es
push ax
push cx
mov cl,parlg
xor ch,ch
mov es,parametersegment
lea si,loc_par_area
mov di,infosave
mov info,di
rep movs al,al
pop cx
pop ax
pop es
ret
;
;
;***************** end BDOS entry module ****************
end


View File

@@ -0,0 +1,114 @@
;**************************************************************
; *
; BDOS symbols: *
; *
;**************************************************************
;
;
dvers EQU 22h ;version 2.2
;
on EQU 0ffffh
off EQU 00000h
testf EQU off
;
; Special 8086 symbols:
;
b equ byte ptr 0
w equ word ptr 0
;
; bios value defined at end of module
;
ssize EQU 96 ;96 level stack
;
;
cseg cpmsegment
;
; BIOS routines
;
org biosoffset
bios:
bootf EQU BIOS+3*0 ;cold boot function
wbootf EQU BIOS+3*1 ;warm boot function
constf EQU BIOS+3*2 ;console status function
coninf EQU BIOS+3*3 ;console input function
conouf EQU BIOS+3*4 ;console output function
listf EQU BIOS+3*5 ;list output function
punchf EQU BIOS+3*6 ;punch output function
readerf EQU BIOS+3*7 ;reader input function
homef EQU BIOS+3*8 ;disk home function
seldskf EQU BIOS+3*9 ;select disk function
settrkf EQU BIOS+3*10 ;set track function
setsecf EQU BIOS+3*11 ;set sector function
setdmf EQU BIOS+3*12 ;set dma function
readf EQU BIOS+3*13 ;read disk function
writef EQU BIOS+3*14 ;write disk function
liststf EQU BIOS+3*15 ;list status function
sectran EQU BIOS+3*16 ;sector translate
setdmbf EQU BIOS+3*17 ;set base for disk I/O
getsegtabf EQU BIOS+3*18 ;get segment table address
nbiosfuncs equ 19 ;number of BIOS functions
;
; equates for non graphic characters
ctlc EQU 03h ;control c
ctle EQU 05h ;physical eol
ctlh EQU 08h ;backspace
ctlp EQU 10h ;prnt toggle
ctlr EQU 12h ;repeat line
ctls EQU 13h ;stop/start screen
ctlu EQU 15h ;line delete
ctlx EQU 18h ;=ctl-u
ctlz EQU 1ah ;end of file
rubout EQU 7fh ;char delete
tab EQU 09h ;tab char
cr EQU 0dh ;carriage return
lf EQU 0ah ;line feed
ctl EQU 5eh ;up arrow
;
;
; module addresses
;
; literal constants
true EQU 0ffh ;constant true
false EQU 000h ;constant false
enddir EQU 0ffffh ;end of directory
;
;
; file control block (fcb) constants
empty EQU 0e5h ;empty directory entry
lstrec EQU 127 ;last record# in extent
recsiz EQU 128 ;record size
fcblen EQU 32 ;file control block size
dirrec EQU recsiz/fcblen ;directory elts / 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
modnum EQU 14 ;data module number
maxmod EQU 15 ;largest module number
fwfmsk EQU 80h ;file write flag is high
;order modnum
namlen EQU 15 ;name length
reccnt EQU 15 ;record count field
dskmap EQU 16 ;disk map field
lstfcb EQU fcblen-1
nxtrec EQU fcblen
ranrec EQU nxtrec+1 ;random record field (2 bytes)
;
; reserved file indicators
rofile EQU 9 ;high order of first type char
invis EQU 10 ;invisible file in dir command
; equ 11 ;reserved
;
; Memory management symbols:
;
membase equ word ptr 0
memlg equ word ptr 2
memdescrlg equ 4
;
;
;********************* end of BDOS symbols ***********************
end


View File

@@ -0,0 +1,602 @@
;
;*****************************************************************
;*****************************************************************
;** **
;** B a s i c D i s k O p e r a t i n g S y s t e m **
;** **
;*****************************************************************
;*****************************************************************
;
selerror:
;report select error
LEA BX,seler ;
;
;
goerr:
;BX = .errorhandler,call subr.
JMP w[bx] ;to subroutine
;
;
;
; local subroutines for bios interface
;
move:
;move data length of length CL from source DX to
;destination given by BX
push cx
mov ch,0
mov si,dx
mov di,bx
rep movs al,al
pop cx
ret
;
;
selectdisk:
;select the disk drive given by curdsk, and fill
;the base addresses curtrka - alloca, then fill
;the values of the disk parameter block
;
MOV cl,curdsk ;current disk# to CL
;lsb of DL = 0 if not yet
;logged in
CALL seldskf ;BX filled by call
;BX = 0000 if error,
;otherwise disk headers
cmp bx,0
jz ret4 ;rz
MOV DX,[bx]
add bx,2
MOV cdrmaxa,BX
add bx,2
MOV curtrka,BX
add bx,2
MOV curreca,BX
add bx,2
;DX still contains .tran
xchg bx,dx
MOV tranv,bx ;.tran vector
LEA BX,buffa ;DX= source for move, BX=dest
MOV CL,addlist
CALL move ;addlist filled
;now fill the disk
;parameter block
MOV dx,dpbaddr
LEA BX,sectpt ;BX is destination
MOV CL,dpblist
CALL move ;data filled
;set single/double map mode
MOV al,byte ptr maxall+1 ;largest allocation number
LEA BX,single
MOV b[bx],true ;assume a=00
OR AL,AL
JZ retselect
;high order of maxall not
;zero, use double dm
MOV b[bx],false
retselect:
MOV AL,true
OR AL,AL
ret4: RET ;select disk function ok
;
home:
;move to home position, then offset to start of dir
CALL homef
;first directory pos. selected
XOR AX,AX ;constant zero to accumulator
MOV BX,curtrka
MOV [bx],ax ;curtrk=0000
;curtrk, currec both set to 0
RET
;
rdbuff:
;read buffer and check if ok
CALL readf ;current drive, track,....
jmps diocomp ;check for i/o errors
;
wrbuff:
;write buffer and check condition
;write type (wrtype) is in register CL
;wrtype = 0 => normal write operation
;wrtype = 1 => directory write operation
;wrtype = 2 => start of new block
CALL writef ;current drive, track, ...
diocomp: ;check for disk errors
OR AL,AL
jz ret4 ;rz
LEA BX,pererr
JMP goerr
;
seekdir:
;seek the record containing the current dir entry
MOV BX,dcnt ;directory counter to BX
MOV CL,dskshf
shr bx,cl ;value to BX
MOV arecord,BX
MOV drec,BX ;ready for seek
; jmp seek
;ret
;
seek:
;seek the track given by arecord (actual record)
;
;
mov ax,arecord ;compute track/sector
mov dx,0
div sectpt ;dx=sector, ax=track
push dx
mov cx,ax ;update curtrk
mov si,curtrka
mov [si],cx
add cx,offsetv ;set BIOS track
call settrkf
pop cx ;set BIOS sector
mov dx,tranv
call sectran
mov cx,bx
jmp setsecf
;ret
;
;
; utility functions for file access
;
dmposition:
;compute disk map position for vrecord to BX
lea bx,blkshf
MOV CL,[bx] ;shift count to CL
MOV AL,lvrecord ;current virtual record to A
shr al,cl
;A = shr(vrecord,blkshf) = vrecord/2**(sect/block)
MOV CH,AL ;save it for later addition
MOV cl,7
SUB cl,[bx]
MOV AL,extval ;extent value ani extmsk
;
;blkshf = 3,4,5,6,7
;CL=4,3,2,1,0
;shift is 4,3,2,1,0
shl al,cl
;arrive here with A = shl(ext and extmsk,7-blkshf)
ADD AL,CH ;add the previous
;shr(vrecord,blkshf) value
;AL 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
;
getdm:
;return disk map value from position given by CX
MOV BX,info ;base address of file
;file control block
ADD BX,dskmap ;bx=.diskmap
ADD BX,CX ;index by asingle byte value
cmp single,0 ;single byte/map entry?
JZ getdmd ;get disk map single byte
MOV BL,[bx]
MOV BH,0
RET ;with BX=00bb
getdmd:
ADD BX,CX ;bx=.fcb(dm+1*2)
;return double precision value
MOV bx,[bx]
RET
;
index:
;compute disk block number from current FCB
CALL dmposition ;0...15 in register AL
MOV CL,AL
MOV CH,0
CALL getdm ;value to BX
MOV arecord,BX
RET
;
alloct:
;called following index to see if block allocated
MOV BX,arecord
or bx,bx
RET
;
atran:
;compute actual record address, assuming index called
MOV cl,blkshf ;shift count to reg AL
MOV BX,arecord
shl bx,cl
MOV ablock,BX ;save shifted block #
MOV AL,lvrecord
AND AL,blkmsk ;masked value in AL
OR bl,al
MOV arecord,BX ;arecord=BX or
;(vrecord and blkmsk)
RET
;
getexta:
;get current extent field address to AL
MOV BX,info
add bx,extnum ;bx=.fcb(extnum)
mov al,[bx]
RET
;
gtfcba:
;compute reccnt and nxtrec addresses for get/setfcb
MOV DX,reccnt
add dx,info ;DX=.fcb(reccnt)
MOV BX,(nxtrec-reccnt)
ADD BX,DX ;bx=.fcb(nxtrec)
RET
;
getfcb:
;set variables from currently addressed FCB
CALL gtfcba ;addresses in DX, BX
MOV AL,[bx]
MOV lvrecord,al ;vrecord=fcb(nxtrec)
XCHG BX,DX
MOV AL,[bx]
MOV rcount,AL ;rcount=fcb(reccnt)
CALL getexta ;BX=.fcb(extnum)
MOV AL,extmsk ;extent mask to a
AND AL,[bx] ;fcb(extnum) and extmsk
MOV extval,AL
RET
;
setfcb:
;place values back into current fcb
CALL gtfcba ;addresses to DX, BX
MOV AL,seqio
CMP AL,02
JNZ setfc1
XOR AL,AL ;check ranfill
setfc1:
;=1 if sequential i/o
add AL,lvrecord
MOV [bx],al ;fcb(nxtrec)=vrecord+seqio
XCHG BX,DX
MOV AL,rcount
MOV [bx],al ;fcb(reccnt)=rcount
RET
;
;
cmpecs:
;compute checksum for current directory buffer
MOV cx,recsiz ;size of directory buffer
MOV BX,buffa ;current directory buffer
XOR AL,AL ;clear checksum value
cmpec0:
ADD AL,[bx]
INC BX
loop cmpec0
RET ;with checksum in A
;
setcdisk:
;set a "1" value in curdsk position of CX
PUSH CX ;save input parameter
MOV cl,curdsk
MOV BX,1 ;number to shift
shl bx,cl ;BX = mask to integrate
POP CX ;original mask
or bx,cx ;BX = mask or rol(1,curdsk)
RET
;
nowrite:
;return true if dir checksum difference occurred
MOV ax,rodsk
MOV cl,curdsk
shr ax,cl
AND AL,1
RET ;non zero if nowrite
;
setro:
;set current disk to read only
mov cx,rodsk
CALL setcdisk ;sets bit to 1
MOV rodsk,BX
;high water mark in directory
;goes to max
MOV dx,dirmax
INC dx
MOV BX,cdrmaxa ;BX = .cdrmax
MOV [bx],dx ;cdrmax = dirmax
RET
;
ckrodir:
;check current directory element for read/only status
CALL getdptra ;address of element
;
ckrofile:
;check current buff(dptr) or fcb(0) for r/o status
MOV DX,rofile
ADD BX,DX ;offset to r/o bit
MOV AL,[bx]
RCL AL,1
jae ret5 ;rnc
LEA BX,rofer
JMP goerr ;
; jmp roferror ;exit to read only disk message
;
;
checkwrite:
;check for write protected disk
CALL nowrite
jz ret5 ;rz
LEA BX,roderr
JMP goerr
; jmp roderror ;read only disk error
;
getdptra:
;compute the address of a directory element at
;positon dptr in the buffer
MOV BX,buffa
MOV AL,dptr
addh:
;BX = BX + AL
mov ah,0
add bx,ax
ret5: ret
;
;
getmodnum:
;compute the address of the module number
;bring module number to accumulator
;(high order bit is fwf (file write flag)
MOV BX,info
add bx,modnum
MOV AL,[bx]
RET ;AL=fcb(modnum)
;
clrmodnum:
;clear the module number field for user open/make
CALL getmodnum
MOV b[bx],0 ;fcb(modnum)=0
RET
;
setfwf:
CALL getmodnum ;BX=.fcb(modnum),
;AL=fcb(modnum)
;set fwf(file write flag) to 1
OR AL,fwfmsk
MOV [bx],al ;fcb(modnum)=fcb(modnum) + 80h
;also returns non zero
;in accumulator
RET
;
;
compcdr:
;return cy if cdrmax > dcnt
MOV dx,dcnt ;DX = directory counter
MOV BX,cdrmaxa ;BX=.cdrmax
cmp dx,[bx]
;condition dcnt - cdrmax
;produces cy if cdrmax>dcnt
ret6: RET
;
setcdr:
;if not (cdrmax > dcnt) then cdrmax = dcnt+1
CALL compcdr
jb ret6 ;return if cdrmax > dcnt
;otherwise, BX = .cdrmax+1,
;DX = dcnt
INC DX
MOV [bx],dx
RET
;
subdh:
;compute BX = DX - BX
push dx
sub dx,bx
mov bx,dx
pop dx
RET
;
newchecksum:
;drop through to compute new checksum
MOV CL,true
checksum:
;compute current checksum record and update the
;directory element if CL=true, or check for = if not
;drec < chksiz?
MOV DX,drec
MOV BX,chksiz
CALL subdh ;DX-BX
jae ret6 ;skip checksum if past
;checksum vector size
;drec < chksiz, so continue
PUSH CX ;save init flag
CALL cmpecs ;check sum value to AL
MOV BX,drec ;value of drec
ADD BX,checka ;bx=.check(drec)
POP CX ;recall true or false to CL
INC CL ;true produces zero flag
JZ initcs
;not initializing, compare
CMP AL,[bx] ;compute$cs=check(drec)?
jz ret7 ;no message if ok
;checksum error, are we beyond
;the end of the disk?
CALL compcdr
jae ret7 ;no message if so
CALL setro ;read/only disk set
RET
initcs:
;initializing the checksum
MOV [bx],al
ret7: RET
;
;
wrdir:
;write the current directory entry, set checksum
CALL newchecksum ;initialize entry
CALL setdir ;directory dma
MOV CL,1 ;indicates a write directory
CALL wrbuff ;write the buffer
JMP setdata ;to data dma address
;ret
;
rddirbuf:
;read a directory entry into the directory buffer
CALL setdir ;directory dma
CALL rdbuff ;directory record loaded
; jmp setdata
; ret
;
setdata:
;set data dma address
mov cx,dmabase
call setdmbf ;set BIOS disk I/O base
LEA BX,dmaad
jmps setdma ;to complete the call
;
setdir:
;set directory dma address
mov cx,ds
call setdmbf ;set BIOS disk I/O base
LEA BX,buffa ;jmp setdma to complete call
;
setdma:
;BX=.dma address to set (i.e., buffa or dmaad)
MOV CX,[bx] ;parameter ready
JMP setdmf
;
;
dirtouser:
;copy the directory entry to the user buffer
;after call to search or searchn by user code
MOV DX,buffa ;source is directory buffer
MOV BX,dmaad ;destination is user dma addr.
MOV CL,recsiz ;copy entire record
push es ;move to user segment
mov es,parametersegment
call move
pop es
ret
;ret
;
endofdir:
;return zero flag if at end of director, non zero
;if not at end (end of dir if dcnt = 0ffffh)
LEA BX,dcnt
MOV AL,[bx] ;may be 0ffh
INC BX
CMP AL,[bx] ;low(dcnt) = high(dcnt)?
jnz ret8 ;return non zero if different
;high and low the same,= 0ffh?
INC AL ;0ffh becomes 00 if so
ret8: RET
;
setenddir:
;set dcnt to the end of the directory
MOV BX,enddir
MOV dcnt,bx
RET
;
rddir:
;read next directory entry, with CL=true if initializing
MOV DX,dirmax ;in preparation for subtract
MOV BX,dcnt
INC BX
MOV dcnt,bx ;dcnt=dcnt+1
;continue while dirmax >= dcnt
;(dirmax-dcnt no cy)
CALL subdh ;DX-BX
JAE rddir0
;yes, set dcnt to end
;of directory
jmps setenddir
; ret
rddir0:
;not at end of directory, seek next element
;CL=initialization flag
MOV AL,ldcnt
AND AL,dskmsk ;low(dcnt) and dskmsk
push cx
MOV cl,fcbshf ;to multiply by fcb size
shl al,cl
pop cx
;A = (low(dcnt) and dskmsk)
;shl fcbshf
MOV dptr,AL ;ready for next dir operation
OR AL,AL
jnz ret71 ;return if not a new record
PUSH CX ;save initialization flag CL
CALL seekdir ;seek proper record
CALL rddirbuf ;read the directory record
POP CX ;recall initialization flag
JMP checksum ;checksum the directory elt
;ret
;
;
getallocbit:
;given allocation vector
;position on CX, return byte
;containing CX shifted so that the least significant
;bit is in the low order accumulator position. BX is
;the address of the byte for
;possible replacement in
;memory upon return, and DH contains the number of shifts
;required to place the returned value back into position
;
MOV dl,CL
AND dl,111b
INC dl
MOV DH,dl
;dh and dl both contain the
;number of bit positions to
;shift
MOV AL,CL
mov cl,3
ror al,cl
AND AL,11111b
MOV CL,AL ;CL shr 3 to CL
push cx
mov cl,5
shl al,cl
pop cx
or CL,AL ;bbbccccc to CL
MOV AL,CH
ROR AL,1
ROR AL,1
ROR AL,1
AND AL,11111b
MOV CH,AL ;CX shr 3 to CX
MOV BX,alloca ;base addr. of alloc. vector
ADD BX,CX
;byte to A, hl =
MOV AL,[bx] ;.alloc(CX shr 3)
;now move the bit to the
;low order position of AL
push cx
mov cl,dl
rol al,cl
pop cx
ret71: RET
;
;
setallocbit:
;CX is the bit position of ALLOC to set or reset. The
;value of the bit is in register DL.
PUSH DX
CALL getallocbit ;shifted val AL,count in DL
AND AL,11111110b ;mask low bit to zero
;(may be set)
POP CX
OR AL,CL ;low bit of CL masked into AL
; jmp rotr
; ret
rotr:
;byte value from ALLOC is in register AL, with shift count
;in register CH (to place bit back into position), and
;target ALLOC position in registers BX, rotate and replace
;
push cx
mov cl,ch
ror al,cl
mov [bx],al
pop cx
ret
;
;************* end BDOS filesystem part 1 **************
end


View File

@@ -0,0 +1,666 @@
;***************** BDOS file system part 2 *****************
;
scndm:
;scan the disk map addressed by dptr for non-zero
;entries, the allocation vector entry corresponding
;to a non-zero entry is set to the value of CL (0,1)
;BX addresses the beginning of the directory entry
;
CALL getdptra ;BX = buffa + dptr
ADD BX,dskmap ;BX = diskmap address
PUSH CX ;save the 0/1 bit to set
MOV CL,fcblen-dskmap+1 ;size of single byte diskmap+1
scndm0:
;loop for each diskmap entry
POP DX ;recall bit parity
DEC CL
JNZ L_41
RET
L_41: ;all done scanning?
;no, get next entry for scan
PUSH DX ;replace bit parity
cmp single,0
JZ scndm1
;single byte scan operation
PUSH CX ;save counter
PUSH BX ;save map address
MOV CL,[bx]
MOV CH,0 ;CX=block#
jmps scndm2
scndm1:
;double byte scan operation
DEC CL ;count for double byte
PUSH CX ;save counter
MOV cx,[bx] ;CX=block
INC BX
PUSH BX ;save map address
scndm2:
;arrive here with CX=block#,
;DL= 0/1
OR cx,cx ;skip if = 0000
JZ scan3
MOV BX,maxall ;check invalid index
cmp bx,cx
JNAE L_42
CALL setallocbit
L_42: ;
;bit set to 0/1
scan3: ;
POP BX
INC BX ;to next bit position
POP CX ;recall counter
jmps scndm0 ;for another item
;
initialize:
;initialize the current disk
;lret = false ;set to true if $ file exists
;compute the length of the allocation vector - 2
MOV BX,maxall
MOV CL,3 ;perform maxall/8
shr bx,cl
INC BX
mov cx,bx
MOV BX,alloca ;base of allocation vector
;fill the allocation vector
;with zeros
init0:
MOV b[bx],0
INC BX ;alloc(i)=0
loop init0
;set the reserved space for
;the directory
MOV DX,dirblk
MOV BX,alloca ;BX=.alloc()
MOV [bx],dx ;sets reserved directory blks
;allocation vector initialized
CALL home ;home disk
;cdrmax = 3 (scans at least
;one directory record)
MOV BX,cdrmaxa
mov w[bx],3
;cdrmax = 0000
CALL setenddir ;dcnt = enddir
;read directory entries and
;check for allocated storage
init2:
MOV CL,true
CALL rddir
CALL endofdir
jz ret8b ;rz
;not end of directory,
;valid entry ?
CALL getdptra ;BX = buffa + dptr
cmp b[bx],empty
JZ init2 ;go get another item
;not empty,user code the same?
MOV AL,usrcode
CMP AL,[bx]
JNZ pdollar
;same user code,
;check for '$' submit
INC BX
MOV AL,[bx] ;first character
SUB AL,'$' ;dollar file?
JNZ pdollar
;$ file found, mark in lret
DEC AL
MOV lret,al ;lret = 255
pdollar:
;now scan the disk map for
;allocated blocks
MOV CL,1 ;set to allocated
CALL scndm
CALL setcdr ;set cdrmax to dcnt
jmps init2 ;for another entry
;
cpydirloc:
;copy directory location to lret following
;delete, rename, ... ops
MOV AL,dirloc
JMP staret
; ret
;
compext:
;compare extent# in AL with that in CL, return nonzero
;if they do not match
PUSH CX ;save CL's original value
MOV ch,extmsk
NOT ch
;CH has negated form of
;extent mask
and cl,ch ;low bits removed from CL
AND AL,CH ;low bits removed from AL
SUB AL,CL
AND AL,maxext ;set flags
POP CX ;restore original values
ret8b: RET
;
srch:
;search for directory element
;of lenght
MOV dirloc,0ffh ;changed if actually found
MOV srchl,cl ;searchl = CL
MOV BX,info
MOV srcha,BX ;searcha = info
CALL setenddir ;dcnt = enddir
CALL home ;to start at the beginning
;(drop through to searchn) ;
;
srchn:
;search for the next directory element, assuming
;a previous call on search which sets searcha and searchhl
MOV CL,false
CALL rddir ;read next dir element
CALL endofdir
jz srchfin
;skip to end if so
;not end of directory,
;scan for match
MOV dx,srcha ;DX=beginning of user fcb
MOV SI,DX
LODS al ;first character
CMP AL,empty ;keep scanning if empty
JZ srchnext
;not empty, may be end of
;logical directory
PUSH DX ;save search address
CALL compcdr ;past logical end?
POP DX ;recall address
jnb srchfin
;artificial stop
srchnext:
CALL getdptra ;BX = buffa+dptr
MOV AL,srchl
MOV CL,AL ;length of search to CL
MOV CH,0 ;CH counts up, CL counts down
srchloop:
or cl,cl
JZ endsearch
MOV SI,DX
LODS al
CMP AL,'?'
JZ srchok ;? matches all
;scan next character if not
;ubytes
CMP ch,ubytes
JZ srchok
;not the ubytes field,
;extent field
CMP ch,extnum ;may be extent field
MOV SI,DX
LODS al ;fcb character
JZ srchext ;skip to search extent
SUB AL,[bx]
AND AL,7fh ;mask-out flags/extent modulus
jnz srchn
jmps srchok ;matched character
srchext:
;A has fcb character
;attempt an extent # match
PUSH CX ;save counters
MOV CL,[bx] ;directory character to c
CALL compext ;compare user/dir char
POP CX ;recall counters
jnz srchn ;skip if no match
srchok:
;current character matches
INC DX
INC BX
INC CH
DEC CL
jmps srchloop
endsearch:
;entire name matches, return dir position
MOV AL,ldcnt
AND AL,dskmsk
MOV lret,al
;lret = low(dcnt) and 11b
LEA BX,dirloc
MOV AL,[bx]
RCL AL,1
jae ret9 ;rnc
;yes, change it to 0 to
;mark as found
XOR AL,AL
MOV [bx],al ;dirloc=0
ret9: RET
srchfin:
;end of directory, or empty name
CALL setenddir ;may be artifical end
MOV AL,255
JMP staret
;
;
delet:
;delete the currently addressed file
CALL checkwrite ;write protected?
MOV CL,extnum
CALL srch ;search through file type
delet0:
;loop while directory matches
CALL endofdir
jz ret9
;set each non zero disk map
;entry to 0
;in the allocation vector
;may be r/o file
CALL ckrodir ;ro disk error if found
CALL getdptra ;BX=.buff(dptr)
MOV b[bx],empty
MOV CL,0
CALL scndm ;alloc elts set to 0
CALL wrdir ;write the directory
CALL srchn ;to next element
jmps delet0 ;for another record
;
getblock:
;given allocation vector position CX, find the zero bit
;closest to this position by searching left and right.
;if found, set the bit to 1 and return the bit position
;in BX. if not found (i.e., we pass 0 on the left, or
;maxall on the right), return 0000 in BX
;
MOV dx,cx ;copy start pos. to DX
lefttst:
or cx,cx
JZ righttst ;skip if left=0000
;left not at position zero,
;bit zero ?
DEC CX
PUSH DX
PUSH CX ;left,right pushed
CALL getallocbit
RCR AL,1
JAE rblok ;return block number if zero
;bit is one, so try the right
POP CX
POP DX ;left, right restored
righttst:
cmp dx,maxall ;value of maximum allocation#
JAE rblok0 ;return block 0000 if so
INC DX
PUSH CX
PUSH DX ;left, right pushed
MOV cx,dx ;ready right for call
CALL getallocbit
RCR AL,1
JAE rblok ;return block number if zero
POP DX
POP CX ;restore left and right ptr
jmps lefttst ;for another attempt
rblok:
RCL AL,1
INC AL ;bit back into position
;and set to 1
;DL contains the number of
;shifts required to reposition
CALL rotr ;move bit back to position
;and store
POP BX
POP DX ;BX returned value,
;DX discarded
RET
rblok0:
;cannot find an available
;bit, return 0000
or cx,cx
jnz lefttst
MOV BX,0000h
RET
;
copyfcb:
;copy the entire FCB
MOV CL,0
MOV DL,fcblen ;start at 0, to fcblen-1
; jmp copydir ;
;
copydir:
;copy fcb information starting
;into the currently addressed directory entry
PUSH DX ;save length for later
MOV CH,0 ;double index to CX
MOV dx,info ;BX = source for data
ADD dx,CX ;DX=.fcb(CL), source for copy
CALL getdptra ;BX=.buff(dptr), destination
POP CX ;DX=source, BX=dest, C=length
CALL move ;data moved
seekcopy:
;enter from close to seek and copy current element
CALL seekdir ;to the directory element
JMP wrdir ;write the directory element
;ret
;
;
rename:
;rename the file described by the first half of
;the currently addressed file control block. the
;new name is contained in the last half of the
;currently addressed file conrol block. the file
;name and type are changed, but the reel number
;is ignored. the user number is identical.
;
CALL checkwrite ;may be write protected
;search up to the extent field
MOV CL,extnum
CALL srch
;copy position 0
MOV BX,info
MOV AL,[bx] ;BX=.fcb(0), A=fcb(0)
ADD BX,dskmap ;bx=.fcb(diskmap)
MOV [bx],al ;fcb(dskmap)=fcb(0)
;assume the same disk
;for new named file
renam0:
CALL endofdir
JNZ L_51
ret10: RET
L_51: ;stop at end of dir
;not end of directory,
;rename next element
CALL ckrodir ;may be read-only file
MOV CL,dskmap
MOV DL,extnum
CALL copydir
;element renamed, move to next
CALL srchn
jmps renam0
;
indicators:
;set file indicators for current fcb
MOV CL,extnum
CALL srch ;through file type
indic0:
CALL endofdir
jz ret10 ;stop at end of dir
;not end of directory,
;continue to change
MOV CL,0
MOV DL,extnum ;copy name
CALL copydir
CALL srchn
jmps indic0
;
open:
;search for the directory entry, copy to FCB
MOV CL,namlen
CALL srch
CALL endofdir
jz ret10 ;return with lret=255 if end
;not end of directory,copy fcb
opencopy:
;(referenced below to copy fcb
CALL getexta
PUSH AX
PUSH BX ;save extent#
CALL getdptra
XCHG BX,DX ;DX = .buff(dptr)
MOV BX,info ;BX=.fcb(0)
MOV CL,nxtrec ;length of move operation
PUSH DX ;save .buff(dptr)
CALL move ;from .buff(dptr) to .fcb(0)
;note that entire fcb is
;copied, including indicators
CALL setfwf ;sets file write flag
POP DX
MOV BX,extnum
ADD BX,DX ;bx=.buff(dptr+extnum)
mov cl,[bx]
MOV BX,reccnt
ADD BX,DX
mov ch,[bx]
POP BX
POP AX
MOV [bx],al ;restore extent number
;
;BX = .user extent#, CH = dir rec cnt, CL = dir extent#
;if user ext < dir ext then user := 128 records
;if user ext = dir ext then user := dir records
;if user ext > dir ext then user := 0 records
;
CMP cl,[bx]
MOV AL,CH ;ready dir reccnt
JZ openrcnt ;if same, user gets dir reccnt
MOV AL,0
JB openrcnt ;user is larger
MOV AL,128 ;directory is larger
openrcnt: ;A has record count to fill
MOV BX,info
MOV DX,reccnt
ADD BX,DX
MOV [bx],al
ret11: RET
;
mergezero:
;BX = .fcb1(i), DX = .fcb2(i),
;if fcb1(i) = 0
;then fcb1(i) := fcb2(i)
cmp w[bx],0
jnz ret11 ;rnz
MOV SI,DX
LODS ax
mov [bx],ax
ret12: RET
;
close:
;locate the directory element and re-write it
XOR AX,AX
MOV lret,al
MOV dcnt,ax
CALL nowrite
jnz ret12 ;skip close if r/o disk
;check file write flag -
;0 indicates written
CALL getmodnum ;fcb(modnum) in A
AND AL,fwfmsk
jnz ret12 ;return if bit remains set
MOV CL,namlen
CALL srch ;locate file
CALL endofdir
jz ret12 ;return if not found
;merge the disk map at info
MOV CX,dskmap
CALL getdptra
ADD BX,CX
XCHG BX,DX ;DX is .buff(dptr+16)
MOV BX,info
ADD BX,CX ;dx=.buff(dptr+16),
;bx=.fcb(16)
MOV CL,(fcblen-dskmap) ;length of single byte dm
merge0:
cmp single,0
JZ merged ;skip to double
;
;this is a single byte map
;if fcb(i) = 0 then fcb(i) = buff(i)
;if buff(i) = 0 then buff(i) = fcb(i)
;if fcb(i) <> buff(i) then error
;
MOV AL,[bx]
OR AL,AL
MOV SI,DX
LODS al
JNZ fcbnzero
;fcb(i) = 0
MOV [bx],al ;fcb(i) = buff(i)
fcbnzero:
OR AL,AL
JNZ buffnzero
;buff(i) = 0
MOV AL,[bx]
MOV DI,DX
stos al ;buff(i)=fcb(i)
buffnzero:
CMP AL,[bx]
jnz mergerr ;fcb(i) = buff(i)?
jmps dmset ;if merge ok
merged:
;this is a double byte merge
CALL mergezero ;buff = fcb if buff 0000
XCHG BX,DX
CALL mergezero
XCHG BX,DX ;fcb = buff if fcb 0000
;they should be identical
;at this point
MOV SI,DX
mov ax,[si]
cmp ax,[bx]
jnz mergerr
inc dx
inc bx
;merge ok for this pair
DEC CL ;extra count for double byte
dmset:
INC DX
INC BX
DEC CL
JNZ merge0 ;for more
;end of disk map merge,
;check record count
;DX = .buff(dptr)+32,
;BX = .fcb(32)
MOV CX,-(fcblen-extnum)
ADD BX,CX
XCHG BX,DX
ADD BX,CX
;DX = .fcb(extnum),
;BX = .buff(dptr+extnum)
MOV SI,DX
LODS al ;current user extent number
;if fcb(ext) >= buff(fcb) then
;buff(ext) := fcb(ext),
;buff(rec) := fcb(rec)
CMP AL,[bx]
JB endmerge
;fcb extent number >=
;dir extent number
MOV [bx],al ;buff(ext) = fcb(ext)
;update dir. rec count field
MOV CX,(reccnt-extnum)
ADD BX,CX
XCHG BX,DX
ADD BX,CX
;DX=.buff(reccnt),
;BX=.fcb(reccnt)
MOV AL,[bx]
MOV DI,DX
stos al ;buff(reccnt)=fcb(reccnt)
endmerge:
MOV fcbcopied,true ;mark as copied
JMP seekcopy ;ok to "wrdir" here -
;1.4 compatible
; ret
mergerr:
;elements did not merge ok
dec lret ;=255 non zero flag set
ret13: RET
;
make:
;create a new file by creating a directory entry
;then opening the file
CALL checkwrite ;may be write protected
push info
MOV info,offset efcb ;info = .empty
MOV CL,1
CALL srch ;length 1 match on empty entry
CALL endofdir ;zero flag set if no space
pop info ;recall word ptr info address
jz ret13 ;return with error condition
;255 if not found
XCHG BX,DX ;DX = word ptr info address
;clear the remainder of fcb
MOV BX,namlen
ADD BX,DX ;bx=.fcb(namlen)
MOV CL,fcblen-namlen ;number of bytes to fill
XOR AL,AL ;clear AL for fill
make0:
MOV [bx],al
INC BX
DEC CL
JNZ make0
MOV BX,ubytes
ADD BX,DX ;bx=.fcb(ubytes)
MOV [bx],al ;fcb(ubytes) = 0
CALL setcdr ;may have extended dir
;now copy entry to dir
CALL copyfcb
;set file write flag to "1"
JMP setfwf
;ret
;
openreel:
;close the current extent, and open the next one
;if possible. RMF is true if in read mode.
XOR AL,AL
MOV fcbcopied,AL ;set true if actually copied
CALL close ;close current extent
;lret remains at enddir
;if we cannot open next ext
CALL endofdir
jz ret13 ;return if end
;increment extent number
MOV BX,info
ADD BX,extnum ;BX=.fcb(extnum)
MOV AL,[bx]
INC AL
AND AL,maxext
MOV [bx],al ;fcb(extnum)=++1
JZ openmod ;move to next module if 0
;may be in same extent group
MOV CH,AL
MOV AL,extmsk
AND AL,CH
;if 0, then not in same group
and al,fcbcopied ;true if fcb was copied to dir
;puts 0 in AL if not written
JZ openr0 ;go to next physical extent
;result is non zero,
;so we must be in same extent
jmps openr1 ;to copy fcb info
openmod:
;extent number overflow, go to next module
ADD BX,(modnum-extnum) ;bx=.fcb(modnum)
INC b[bx] ;fcb(modnum)=++1
;module number incremented,
;check for overflow
MOV AL,[bx]
AND AL,maxmod ;mask high order bits
JZ openerr ;cannot overflow to 0
;otherwise, ok to continue
;with new module
openr0:
MOV CL,namlen
CALL srch ;next extent found?
CALL endofdir
JNZ openr1
;end of file encountered
MOV AL,rmf
INC AL ;0ffh becomes 00 if read
JZ openerr ;sets lret = 1
;try to extend current file
CALL make
;cannot be end of directory
CALL endofdir
JZ openerr ;with lret = 1
jmps openr2
openr1:
;not end of file, open
CALL opencopy
openr2:
CALL getfcb ;set parameters
XOR AL,AL
JMP staret ;lret = 0
; ret
openerr:
;cannot move to next extent
;of this file
CALL setlret1 ;lret = 1
JMP setfwf ;ensure that it will not
;be closed
;ret
;
;*************** end BDOS file system part 2 ***************
end


View File

@@ -0,0 +1,477 @@
;******************** BDOS filesystem part 3 ****************
;
;
sqread:
;sequential disk read operation
MOV seqio,1
;drop through to diskread
;
diskread: ;(may enter from seqdiskread)
MOV rmf,true ;read mode flag =
;true (open$reel)
;read the next record from
;the current FCB
CALL getfcb ;sets parameters for the read
MOV AL,lvrecord
CMP AL,rcount ;vrecord-rcount
;skip if rcount > vrecord
JB recordok
;not enough records in extent
;record count must be 128
;to continue
CMP AL,128 ;vrecord = 128?
JNZ diskeof ;skip if vrecord<>128
CALL openreel ;go to next extent if so
MOV vrecord,0 ;vrecord=00
;now check for open ok
cmp lret,0 ;stop at eof
JNZ diskeof
recordok:
;arrive with fcb addressing a record to read
CALL index
;error 2 if reading
;unwritten data
;(returns 1 to be compatible
;with 1.4)
CALL alloct ;arecord=0000?
JZ diskeof
;record has been allocated,
;read it
CALL atran ;arecord now a disk address
CALL seek ;to proper track,sector
CALL rdbuff ;to dma address
JMP setfcb ;replace parameter
; ret
diskeof:
JMP setlret1 ;lret = 1
;ret
;
slect:
;select disk word ptr info for subsequent input or output ops
MOV BX,dlog
MOV cl,curdsk
ror bx,cl
PUSH BX
XCHG BX,DX ;save it for test below,
;send to seldsk
CALL selectdisk
POP BX ;recall dlog vector
JNZ L_67
CALL selerror
L_67: ;returns true if select ok
;is the disk logged in?
RCR bl,1
jb ret20 ;rc
;return if bit is set
;disk not logged in,
;set bit and initialize
mov cx,dlog
CALL setcdisk
MOV dlog,BX ;dlog=set$cdisk(dlog)
JMP initialize
;ret
;
curselect:
MOV AL,linfo
mov curdsk,al ;curdsk=info
jmps slect
;ret
;
reselect:
;check current fcb to see if reselection necessary
MOV resel,true ;mark possible reselect
MOV BX,info
MOV AL,[bx] ;drive select code
AND AL,00011111b ;non zero is auto drive select
dec AL ;drive code normalized to
;0...30, or 255
MOV linfo,AL ;save drive code
CMP AL,30
JAE noselect
;auto select function,
;save curdsk
MOV AL,curdsk
MOV olddsk,AL ;olddsk=curdsk
MOV AL,[bx]
MOV fcbdsk,AL ;save drive code
AND AL,11100000b
MOV [bx],al ;preserve hi bits
CALL curselect
noselect:
;set user code
MOV AL,usrcode ;0...31
MOV BX,info
OR AL,[bx]
MOV [bx],al
ret20: RET
;
; individual function handlers
func12 equ return
func13:
;
;reset disk system - initialize to disk 0
;
xor bx,bx
MOV rodsk,BX
MOV dlog,BX
MOV curdsk,bl ;note that usrcode remains
;unchanged
JMP slect
;ret ;jmp goback
;
func14 EQU curselect ;
;
;select disk info
;
;
func15:
;
;open file
;
CALL parsave33 ;copy FCB from user seg.
CALL clrmodnum ;clear the module number
CALL reselect
jmp open
;ret ;jmp goback
;
func16 equ return
func17 equ return
func18 equ return
func19 equ return
;
func20:
;
;read a file
;
CALL parsave33
CALL reselect
jmp sqread
;jmp goback
;
func21 equ return
func22 equ return
func23 equ return
func24 equ return
func25 equ return
;
func26:
;
;set the subsequent dma address to info
;
;was MOV BX,INFO
MOV dmaad,dx ;dmaad = info
JMP setdata ;to data dma address
;ret ;jmp goback
;
func27 equ return
func28 equ return
func29 equ return
func30 equ return
func31 equ return
func32 equ return
func33 equ return
func34 equ return
func35 equ return
func36 equ return
func37 equ return
;
goback:
;arrive here at end of processing to return to user
cmp resel,0
JZ retmon
;reselection may have
;taken place
MOV BX,info
MOV b[bx],0 ;fcb(0)=0
MOV AL,fcbdsk
OR AL,AL
JZ retmon
;restore disk number
MOV [bx],al ;fcb(0)=fcbdsk
MOV AL,olddsk
MOV linfo,AL
CALL curselect
;
; return from the disk monitor
retmon:
cmp parcopfl,true ;test if parameter block
jnz retm1 ;to be copied back to user
call parunsave
retm1: MOV BX,aret
MOV AL,BL
MOV CH,BH ;BA = BX = aret
RET
func38 EQU funcret
func39 EQU funcret
func40 equ return
;
;******************* end BDOS filesystem part 3 ***************
end
 BX
; MOV arecord,BX
; CALL setdata
;dskw11:
; CALL seek ;to proper file position
; POP CX
; PUSH CX ;restore/save write flag
; ;(CL=2 if new block,0 if not)
; CALL wrbuff ;written to disk
; POP CX
;increment record count
;if rcount <= vrecord
; MOV AL,lvrecord
; LEA BX,rcount
; CMP AL,[bx] ;vrecord-rcount
; JB dskwr2
;rcount <= vrecord
; MOV [bx],al
; INC b[bx] ;rcount = vrecord+1
; MOV CL,2 ;mark as record count
;incremented
;dskwr2:
;AL has vrecord,
;CL=2 if new block or record#
; dec CL
; dec CL
; JNZ noupdate
; PUSH AX ;save vrecord value
; CALL getmodnum ;BX=.fcb(modnum),
;AL=fcb(modnum)
;reset the file write flag to
;mark as written FCB
; AND AL,not fwfmsk ;bit reset
; MOV [bx],al ;fcb(modnum) = fcb(modnum)
;and 7fh
; POP AX ;restore vrecord
;noupdate:
;check for end of extent, if found attempt to open
;next extent in preparation for next write
; CMP AL,lstrec ;vrecord=lstrec?
; JNZ dskwr3 ;skip if not
;may be random access write,
;if so we are done
;change next
; cmp seqio,1
; JNZ dskwr3 ;skip next extent open op
;update current fcb before
;going to next extent
; CALL setfcb
; CALL openreel ;rmf=false
;vrecord remains at lstrec
;causing eof if no more dir
;space is available
; LEA BX,lret
; MOV AL,[bx]
; OR AL,AL
; JNZ nospace
;space available,
;set vrecord = 255
; dec AL
; MOV lvrecord,al ;goes to 00 next time
;nospace:
; MOV b[bx],0 ;lret = 00 for returned value
;dskwr3:
; JMP setfcb ;replace parameters
;ret
;
;rseek:
;random access seek operation, C=0ffh if read mode
;fcb is assumed to address an active FCB
;(modnum has been set to 1100$0000b if previous bad seek)
;
; MOV seqio,0 ;marked as random access op.
;rseek1:
; PUSH CX ;save r/w flag
; MOV DX,info
;dx will hold base of fcb
; MOV BX,ranrec
; ADD BX,DX ;bx=.fcb(ranrec)
; MOV AL,[bx]
; AND AL,7fh
; PUSH AX ;record number
; MOV AL,[bx]
; RCL AL,1 ;cy=lsb of extent#
; INC BX
; MOV AL,[bx]
; RCL AL,1
; AND AL,11111b ;AL=ext#
; MOV CL,AL ;CL holds extent number,
;record stacked
; MOV AL,[bx]
; RCR AL,1
; RCR AL,1
; RCR AL,1
; RCR AL,1
; AND AL,1111b ;mod#
; MOV CH,AL ;CH = module#,CL = ext#
; POP AX ;recall sought record #
;check to insure high byte
; INC BX
; MOV BL,[bx] ;l=high byte (must be 00)
; or bl,bl
; MOV BL,6 ;zero flag, l=6
;produce error 6,
;seek past physical eod
; jnz seekerr
;otherwise, high byte = 0
; MOV BX,nxtrec
; ADD BX,DX ;bx=.fcb(nxtrec)
; MOV [bx],al ;sought rec# stored away
;
;arrive here with CH=mod#, CL=ext#, DX=.fcb, rec stored
;the r/w flag is still stacked. compare fcb values
;
; MOV BX,extnum
; ADD BX,DX
; MOV AL,CL ;A=seek ext#
; SUB AL,[bx]
; JNZ ranclose ;tests for = extents
;extents match, check mod#
; MOV BX,modnum
; ADD BX,DX
; MOV AL,CH ;B=seek mod#
;could be overflow at eof,
;producing module# of 90h
;or 10h, so compare all
;but fwf
; SUB AL,[bx]
; AND AL,7fh
; JZ seekok ;same?
;ranclose:
; PUSH CX
; PUSH DX ;save seek mod#,ext#, .fcb
; CALL close ;current extent closed
; POP DX
; POP CX ;recall parameters and fill
; MOV BL,3 ;cannot close error #3
; MOV AL,lret
; INC AL
; JZ badseek
; MOV BX,extnum
; ADD BX,DX
; MOV [bx],cl ;fcb(extnum)=ext#
; MOV BX,modnum
; ADD BX,DX
; MOV [bx],ch ;fcb(modnum)=mod#
; CALL open ;is the file present?
; MOV AL,lret
; INC AL
; JNZ seekok ;open successful?
;cannot open file, read mode?
; POP CX ;r/w flag to c (=0ffh if read)
; PUSH CX ;everyone expects this
;item stacked
; MOV BL,4 ;seek to unwritten extent #4
; INC CL ;becomes 00 if read operation
; JZ badseek ;error if read operation
;write, make new extent
; CALL make
; MOV BL,5 ;cannot create new extent #5
; MOV AL,lret
; INC AL
; JZ badseek ;no dir space
;file make successful
;seekok:
; POP CX ;discard r/w flag
; XOR AL,AL
; JMP staret ;with zero set
;badseek:
;
;fcb no longer contains a valid fcb, mark
;with 1100$000b in modnum field so that it
;appears as overflow with file write flag set
;
; PUSH BX ;save error flag
; CALL getmodnum ;BX = .modnum
; MOV b[bx],11000000b
; POP BX ;and drop through
;seekerr:
; POP CX ;discard r/w flag
; MOV AL,BL
; MOV lret,al ;lret=#, nonzero
;setfwf returns <> 0 if error
; JMP setfwf ;flag set, so subsequent
;close ok
;ret
;
;rdread:
;
;random disk read operation
;
; MOV CL,true ;marked as read operation
; CALL rseek
; JNZ L_65
; CALL diskread
;L_65: ;if seek successful
; RET
;
;rdwrite:
;random disk write operation
; MOV CL,false ;marked as write operation
; CALL rseek
; JNZ L_66
; CALL diskwite
;L_66: ;if seek successful
; RET
;
;cmperr:
;compute random record position for getfilesize/setrandom
; XCHG BX,DX
; ADD BX,DX
;DX=.buf(dptr) or .fcb(0),
;BX=.f(nxtrec/reccnt)
; MOV CL,[bx] ;pick up record no.
; MOV CH,0 ;CX = 0000 0000 ?rrr rrrr
; MOV BX,extnum
; ADD BX,DX
; MOV ah,[bx]
; mov al,0
; shr ax,1
; and ah,0fh
; add cx,ax
;CX = 000? eeee errrr rrrr
; MOV BX,modnum
; ADD BX,DX
; MOV AL,[bx] ;A=XXX? mmmm
; mov ah,16
; mul ah
; PUSH AX
; ADD ch,al
;cy=?,CX = mmmm eeee errr rrrr
; pushf ;possible second carry
; POP BX ;cy = lsb of L
; MOV AL,BL ;cy = lsb of A
; POP BX ;cy = lsb of L
; OR AL,BL ;cy/cy = lsb of A
; AND AL,1 ;Al=0? possible carry-out
; RET
;
;getfilesize:
;compute logical file size for current fcb
; MOV CL,extnum
; CALL srch
;zero receiving ranrec field
; MOV BX,info
; MOV DX,ranrec
; ADD BX,DX
; PUSH BX ;save position
; MOV [bx],dh
; INC BX
; MOV [bx],dh
; INC BX
; MOV [bx],dh ;=00 00 00
;getsize:
; CALL endofdir
; JZ setsize
;current fcb addressed by dptr
; CALL getdptra
; MOV DX,reccnt ;ready for compute size
; CALL cmperr
;AL=0000 000?,
;CX = mmmm eeee errr rrrr
;compare with memory, larger?
; POP BX
; PUSH BX

View File

@@ -0,0 +1,169 @@
;***************** BDOS byte I/O module ****************
;
; console handlers
ret0: RET ;carry set if not graphic
;
conbrk: ;check for character ready
MOV AL,kbchar
OR AL,AL
JNZ conb1 ;skip if active kbchar
;no active kbchar,
;check external break
CALL constf
AND AL,1
jz ret0 ;rz
;character ready, read it
CALL coninf ;to A
CMP AL,ctls
JNZ conb0 ;check stop screen function
;found ctls, read next char
CALL coninf ;to A
CMP AL,ctlc
JNZ L_10
JMP wbootf
L_10: ;ctlc implies re-boot
;not a reboot,
;act as if nothing happened
XOR AL,AL
RET ;with zero in accumulator
conb0:
;character in accum, save it
MOV kbchar,AL
conb1:
;return with true set
MOV AL,1
RET
;
conout:
;compute character position/write conso
;compcol = true if computing
;column position
MOV AL,compcol
OR AL,AL
JNZ compout
;write the character,
;then compute column
;write console char from CL
PUSH CX
CALL conbrk ;check for screen stop func.
POP CX
PUSH CX ;recall/save character
CALL conouf ;externally, to console
POP CX
PUSH CX ;recall/save character
;may be copying to list dev.
cmp listcp,0
JZ L_11
CALL listf
L_11: ;to printer, if so
POP CX ;recall the character
compout:
MOV AL,CL ;recall the character
;and compute column position
LEA BX,column ;A = char, BX = .column
CMP AL,rubout
jz ret1 ;no column change if nulls
INC b[bx] ;column = column + 1
CMP AL,' '
jae ret1 ;rnc
;not graphic, reset column
DEC b[bx] ;column = column - 1
MOV AL,[bx]
OR AL,AL
jz ret1 ;return if at zero
;not at zero, may be
;bacspace or end of line
MOV AL,CL ;character back to A
CMP al,ctlh
JNZ notbacksp
;backspace character
DEC b[bx] ;column = column - 1
ret1: RET
notbacksp:
;not backspace, eol ?
CMP AL,lf
jnz ret1 ;return if not
;end of line, column = 0
MOV b[bx],0 ;column = 0
RET
;
tabout:
;expand tabs to console
CMP cl,tab
jnz conout ;direct to conout if not
;tab encountered, move to
;next tab position
tab0:
MOV CL,' '
CALL conout ;another blank
MOV AL,column
AND AL,111b ;column mod 8 = 0 ?
JNZ tab0 ;back for another if not
ret2: RET
;
crlf:
;carriage return line feed sequence
MOV CL,cr
CALL conout
MOV CL,lf
JMP conout
;ret
;
print:
;print message until M(BC) = '$'
MOV SI,CX
LODS al
CMP AL,'$'
jz ret2 ; rz
;more to print
INC CX
PUSH CX
MOV CL,AL ;char to C
push ds ;restore data segment
push ss
pop ds
CALL tabout ;another character printed
pop ds
POP CX
jmps print
return: ret
func1 equ return
func2 EQU tabout
func3 equ return
func6 equ return
func7 equ return
func8 equ return
;
func9:
;write line until $ encountered
;
MOV CX,DX ;CX=string address
push ds ;read from user segment
mov ds,parametersegment
call print ;out to console
pop ds
ret
;
func10 equ return
func11 equ return
;check console status
;(drop through to sta$ret)
staret:
;store the A register to aret
MOV lret,al
funcret: ;
RET ;jmp goback
;(pop stack for non CP/M func)
;
setlret1:
;set lret = 1
MOV AL,1
jmps staret
;
; end of Basic I/O System
;
;*****************************************************************
end


View File

@@ -0,0 +1,15 @@
;******************* New BDOS functions for 8086 ****************
func51: ;set segment base for disk I/O
mov dmabase,dx
func50:
func52:
func53:
func54:
func55:
func56:
func57:ret
end


View File

@@ -0,0 +1,40 @@
; title 'Bdos Interface, Bdos, Version 2.2 Feb, 1980'
;*****************************************************************
;*****************************************************************
;** **
;** L o a d e r **
;** 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
; Digital Research
; Box 579, Pacific Grove
; California
;
;
; 5 september, 1980
; smaller version of BDOS for CP/M-86 Loader
;
;**********************************************
;
cpmsegment equ 0 ; base of CP/M-86
ldroffset equ 0 ; offset of CPMLDR
bdosoffset equ 400H ; offset of LBDOS-86
biosoffset equ 1200H ; offset of LBIOS-86
bdoscodesize equ 0B00H ; size of BDOS code
;
eject ! include lbdosequ.a86 ; symbol definition
eject ! include lbdosent.a86 ; entry module
eject ! include lbdosnew.a86 ; new 8086 BDOS functions
eject ! include lbdosio.a86 ; byte I/O module
eject ! include lbdosf1.a86 ; file system part 1
eject ! include lbdosf2.a86 ; file system part 2
eject ! include lbdosf3.a86 ; file system part 3
eject ! include lbdosdat.a86 ; data area
eject
;********************** end of BDOS ********************
end


View File

@@ -0,0 +1,110 @@
:02000085000079
:02000085000079
:0400000300000400F5
:1B040081000000000000E90800E804F604FC0402052EA3CD0D2E8C16CF0D2EFD
:1B041B818926D10D8CC88ED08D2685118CD81E065557561616071FA3520F2EAF
:1B043681A1CD0DE810005E5F5D071F2E8B26D10D2E8E16CF0DCF8916070F8800
:1B04518116350FC706090F0000C606540F0032C0A23F0FA23D0FBB9A0D53809C
:1B046C81F929720980E90980F9317201C38AD9B7008ACA03DB2EFFA786040358
:1B048781121F06EE051F0612120F121F061F061F0620061F061F061F066D0DC7
:1B04A281310D7E0D1F061F061F061F068A0D1F061F061F061F061F06930D1F52
:1B04BD81061F061F061F061F061F061F061F061F061F061F062F062F061F069C
:1B04D8817E057A057E057E057E057E057E057E058D1EA80FE81D003C03755AFF
:1B04F381E90D0D8D1EB30FEB0A8D1EBF0FEB048D1EBA0FE80300E9F70C53E81A
:1B050E81F000A0060F0441A2A40F8D0E980FE8EB0059E8E700E9E30C1E50513E
:1B052981C606540FFF880E550F32ED8B36070F8936500F8D3EC30F893E070F80
:1B0544818E1E520FF3A459581FC351B121EB0351B124E8CDFF59C30650518AAC
:1B055F810E550F32ED8E06520F8D36C30F8B3E500F893E070FF3A4595807C3CE
:1B057A8189164E0FC3C3A0040F0AC0751EE87C0C240174F1E8780C3C13750D1C
:1B059581E8710C3C037503E9640C32C0C3A2040FB001C3A0000F0AC075165122
:1B05B081E8CDFF5951E8540C5951803E030F007403E84B0C598AC18D1E020F79
:1B05CB813C7F7416FE073C207310FE0F8A070AC074088AC13C087503FE0FC3B0
:1B05E6813C0A75FBC60700C380F90975B5B120E8B0FFA0020F240775F4C3B166
:1B0601810DE8A3FFB10AE99EFF8BF1AC3C2474EE41518AC81E161FE8D3FF1F8B
:1B061C8159EBEBC38BCA1E8E1E520FE8E0FF1FC3A2090FC3B001EBF88D1E0B60
:1B06378104FF2751B5008BF28BFBF3A459C38A0E060FE8CF0B83FB00744B8B0A
:1B0652811783C302891E120F83C302891E140F83C302891E160F83C30287DA16
:1B066D81891E2F0F8D1E180FB108E8C0FF8B161A0F8D1E200FB10FE8B3FFA03C
:1B068881260F8D1E3C0FC607FF0AC07403C60700B0FF0AC0C3E8780B33C08BAC
:1B06A3811E140F8907C3E87B0BEB03E8790B0AC074E78D1E0904E97CFF8B1E75
:1B06BE81490FB102D3EB891E440F891E4B0FA1440FBA0000F736200F528BC82D
:1B06D9818B36140F890C030E2D0FE8380B598B162F0FE8420B8BCBE92E0B8D22
:1B06F4811E220F8A0FA0420FD2E88AE8B1072A0FA0410FD2E002C5C38B1E0798
:1B070F810F83C31003D9803E3C0F0074058A1FB700C303D98B1FC3E8CAFF8AE4
:1B072A81C8B500E8DCFF891E440FC38B1E440F0BDBC38A0E220F8B1E440FD3F9
:1B074581E3891E460FA0420F2206230F0AD8891E440FC38B1E070F83C30C8AB4
:1B07608107C3BA0F000316070FBB110003DAC3E8F0FF8A07A2420F87DA8A0782
:1B077B81A2400FE8D7FFA0240F2207A2410FC3E8D5FFA0340F3C02750232C03C
:1B0796810206420F880787DAA0400F8807C3B980008B1E180F32C0020743E214
:1B07B181FBC3518A0E060FBB0100D3E3590BD9C3A10C0F8A0E060FD3E8240135
:1B07CC81C38B0E0C0FE8DFFF891E0C0F8B16270F428B1E120F8917C3E81E0046
:1B07E781BA090003DA8A07D0D0731E8D1E0F04E93FFEE8C5FF74128D1E0D0442
:1B080281E933FE8B1E180FA0480FB40003D8C38B1E070F83C30E8A07C3E8F3E5
:1B081D81FFC60700C3E8ECFF0C808807C38B16490F8B1E120F3B17C3E8F2FF4E
:1B08388172FA428917C3522BD38BDA5AC3B1FF8B164B0F8B1E2B0FE8ECFF736D
:1B085381E051E84CFF8B1E4B0F031E1C0F59FEC1740D3A07740BE8BEFF7306DF
:1B086E81E85CFFC38807C3E8CDFFE81B00B101E82EFEE90600E81000E820FE2C
:1B0889818B0E4E0FE8A3098D1E100FEB098CD9E898098D1E180F8B0FE98009BF
:1B08A4818B16180F8B1E100FB180068E06520FE884FD07C38D1E490F8A0743F2
:1B08BF813A077502FEC0C3BBFFFF891E490FC38B16270F8B1E490F43891E49DE
:1B08DA810FE860FF7302EBE4A0490F240351B105D2E059A2480F0AC0754051EE
:1B08F581E8C4FDE888FF59E948FF8AD180E207FEC28AF28AC1B103D2C8241FEA
:1B0910818AC851B105D2E0590AC88AC5D0C8D0C8D0C8241F8AE88B1E1E0F0370
:1B092B81D98A07518ACAD2C059C352E8C6FF24FE590AC1518ACDD2C888075904
:1B094681C3E8BBFE83C31051B1115AFEC97501C352803E3C0F00740851538AE9
:1B0961810FB500EB07FEC9518B0F43530BC9740B8B1E250F3BD97203E8B9FFA3
:1B097C815B4359EBCF8B1E250FB103D3EB438BCB8B1E1E0FC6070043E2FA8BF9
:1B09978116290F8B1E1E0F8917E8FAFC8B1E120FC7070300E818FFB1FFE81BD5
:1B09B281FFE802FF743BE84AFE803FE574EEA0050F3A07750C438A072C2475CD
:1B09CD8105FEC8A2090FB101E86FFFE85AFEEBD1A0330FE949FC518A2E240FB9
:1B09E881F6D522CD22C52AC1241F59C3C606330FFF880E370F8B1E070F891E39
:1B0A0381380FE8BEFEE892FCB100E8BEFEE8A5FE74648B16380F8BF2AC3CE50C
:1B0A1E81740752E806FE5A7352E8DBFDA0370F8AC8B5000AC9742D8BF2AC3CDE
:1B0A39813F741E80FD0D741980FD0C8BF2AC74082A07247F75BCEB09518A0F28
:1B0A5481E88CFF5975B14243FEC5FEC9EBCFA0490F2403A2090F8D1E330F8AFB
:1B0A6F8107D0D0730432C08807C3E84AFEB0FFE9ABFBE875FDB10CE86BFFE8CA
:1B0A8A812CFE74EAE853FDE871FDC607E5B100E8ABFEE8D6FDE869FFEBE58B60
:1B0AA581D10BC9740C495251E84FFED0D87318595A3B16250F731A4251528B07
:1B0AC081CAE83BFED0D873045A59EBDAD0D0FEC0E86BFE5B5AC30BC975CCBB21
:1B0ADB810000C3B100B22052B5008B16070F03D1E817FD59E848FBE8C7FBE994
:1B0AF6817DFDE8FEFCB10CE8F4FE8B1E070F8A0783C3108807E8AAFD7501C374
:1B0B1181E8D0FCB110B20CE8C7FFE8EDFEEBEBB10CE8CFFEE890FD74E6B100CC
:1B0B2C81B20CE8B1FFE8D7FEEBEFB10FE8B9FEE87AFD74D0E815FC5053E8BDFD
:1B0B4781FC87DA8B1E070FB12052E8E6FAE8CBFC5ABB0C0003DA8A0FBB0F00FB
:1B0B628103DA8A2F5B5888073A0F8AC57406B0007202B0808B1E070FBA0F0031
:1B0B7D8103DA8807C3833F0075FA8BF2AD8907C333C0A2090FA3490FE829FC4A
:1B0B988175F2E874FC248075EBB10FE84EFEE80FFD74E1B91000E854FC03D9E4
:1B0BB38187DA8B1E070F03D9B110803E3C0F00741A8A070AC08BF2AC750288CF
:1B0BCE81070AC075058A078BFAAA3A077546EB16E8A1FF87DAE89CFF87DA8B2B
:1B0BE981F28B043B0775324243FEC94243FEC975C3B9ECFF03D987DA03D98BEE
:1B0C0481F2AC3A0772108807B9030003D987DA03D98A078BFAAAC606310FFFC4
:1B0C1F81E9D0FEFE0E090FC3E8CFFBFF36070FC706070F0B0FB101E8BBFDE867
:1B0C3A817CFC8F06070F74E487DABB0F0003DAB11132C0880743FEC975F9BB25
:1B0C55810D0003DA8807E8D7FBE87DFEE9BEFB32C0A2310FE821FFE849FC744E
:1B0C7081B58B1E070F83C30C8A07FEC0241F8807740F8AE8A0240F22C522062A
:1B0C8B81310F740DEB2683C302FE078A07240F7426B10FE853FDE814FC7511DA
:1B0CA681A0320FFEC07415E877FFE805FC740DEB03E886FEE8B2FA32C0E96A8F
:1B0CC181F9E86BF9E95AFBC606340F01C606320FFFE89AFAA0420F3A06400FFC
:1B0CDC8172143C807524E87FFFC706420F0000803E090F007514E831FAE83D86
:1B0CF781FA740CE83FFAE8CCF9E8A6F9E984FAE927F98B1E0E0F8A0E060FD3DC
:1B0D1281CB5387DAE82CF95B7503E815F9D0DB72498B0E0E0FE889FA891E0EB4
:1B0D2D810FE950FCA0350FA2060FEBD0C6063D0FFF8B1E070F8A07241FFEC820
:1B0D4881A2350F3C1E7312A0060FA23E0F8A07A23F0F24E08807E8D0FFA00536
:1B0D63810F8B1E070F0A078807C333DB891E0C0F891E0E0F881E060FE98BFF01
:1B0D7E81E8CDF7E897FAE8B2FFE9ACFDE8C1F7E8A9FFE935FF8916100FE9EFA6
:1B0D9981FA803E3D0F0074198B1E070FC60700A03F0F0AC0740B8807A03E0FEE
:190DB481A2350FE877FF803E540FFF7503E897F78B1E090F8AC38AEFC309
:02000085000079
:060DCD810000000000009F
:02000086000078
:1B0F00820000000000000000000000E50000000000000000000000000000006F
:1B0F1B8200000000000000000000000000000000000000000000000000000039
:1B0F36820000000000000000000000000000000000000000000000000000001E
:1B0F518200000000000000000000000000000000000000000000000000000003
:1B0F6C82000000000000000000000000000000000000000000000000000000E8
:1B0F8782000000000000000000000000000000000042646F7320457272204F8D
:1B0FA2826E20203A202442616420536563746F722453656C6563742446696C2C
:060FBD826520522F4F2433
:00000001FF
78
:1B0F00820000000000000000000000E500000000000000000000000000

View File

@@ -0,0 +1,618 @@
title '8086 Disk I/O Drivers'
;*********************************************
;* *
;* Loader Basic Input/Output System (LDBIOS) *
;* for LDMPM Configured for iSBC 86/12 with *
;* the iSBC 204 Floppy Disk Controller *
;* *
;* The only modifications of the CP/M-86 *
;* LDBIOS for this MP/M-86 LDBIOS are the *
;* CCP offset and the contents of the signon *
;* message, which is printed by LDMPM.A86 *
;* in place of the INIT routine. *
;* *
;* (Note: this file contains both embedded *
;* tabs and blanks to minimize the list file *
;* width for printing purposes. You may wish*
;* to expand the blanks before performing *
;* major editing.) *
;*********************************************
; Copyright (C) 1980,1981
; Digital Research, Inc.
; Box 579, Pacific Grove
; California, 93950
;
; (Permission is hereby granted to use
; or abstract the following program in
; the implementation of CP/M, MP/M or
; CP/NET for the 8086 or 8088 Micro-
; processor)
true equ -1
false equ not true
;*********************************************
;* *
;* Bdos_int is interrupt used for earlier *
;* versions. *
;* *
;*********************************************
bdos_int equ 224 ;reserved BDOS Interrupt
bios_code equ 1200h ;start of LDBIOS
ccp_offset equ 0103h ;base of MPMLOADER
bdos_ofst equ 0406h ;stripped BDOS entry
csts equ 0DAh ;i8251 status port
cdata equ 0D8h ; " data port
;*********************************************
;* *
;* Intel iSBC 204 Disk Controller Ports *
;* *
;*********************************************
base204 equ 0a0h ;SBC204 assigned address
fdc_com equ base204+0 ;8271 FDC out command
fdc_stat equ base204+0 ;8271 in status
fdc_parm equ base204+1 ;8271 out parameter
fdc_rslt equ base204+1 ;8271 in result
fdc_rst equ base204+2 ;8271 out reset
dmac_adr equ base204+4 ;8257 DMA base address out
dmac_cont equ base204+5 ;8257 out control
dmac_scan equ base204+6 ;8257 out scan control
dmac_sadr equ base204+7 ;8257 out scan address
dmac_mode equ base204+8 ;8257 out mode
dmac_stat equ base204+8 ;8257 in status
fdc_sel equ base204+9 ;FDC select port (not used)
fdc_segment equ base204+10 ;segment address register
reset_204 equ base204+15 ;reset entire interface
max_retries equ 10 ;max retries on disk i/o
;before perm error
cr equ 0dh ;carriage return
lf equ 0ah ;line feed
cseg
org ccpoffset
ccp:
org bios_code
;*********************************************
;* *
;* BIOS Jump Vector for Individual Routines *
;* *
;*********************************************
jmp INIT ;Enter from BOOT ROM or LOADER
jmp WBOOT ;Arrive here from BDOS call 0
jmp CONST ;return console keyboard status
jmp CONIN ;return console keyboard char
jmp CONOUT ;write char to console device
jmp LISTOUT ;write character to list device
jmp PUNCH ;write character to punch device
jmp READER ;return char from reader device
jmp HOME ;move to trk 00 on cur sel drive
jmp SELDSK ;select disk for next rd/write
jmp SETTRK ;set track for next rd/write
jmp SETSEC ;set sector for next rd/write
jmp SETDMA ;set offset for user buff (DMA)
jmp READ ;read a 128 byte sector
jmp WRITE ;write a 128 byte sector
jmp LISTST ;return list status
jmp SECTRAN ;xlate logical->physical sector
jmp SETDMAB ;set seg base for buff (DMA)
jmp GETSEGT ;return offset of Mem Desc Table
jmp GETIOBF ;return I/O map byte (IOBYTE)
jmp SETIOBF ;set I/O map byte (IOBYTE)
;*********************************************
;* *
;* INIT Entry Point, Differs for LDBIOS and *
;* BIOS, according to "Loader_Bios" value *
;* *
;*********************************************
INIT: ;initialize hardware
mov ax,cs ;we entered with a JMPF so use
mov ss,ax ; CS: as the initial value of SS:,
mov ds,ax ; DS:,
mov es,ax ; and ES:
;use local stack during initialization
mov sp,offset stkbase
cld ;set forward direction
push ds ;save data segment
mov ax,0
mov ds,ax ;point to segment zero
;BDOS interrupt offset
mov bdos_offset,bdos_ofst
mov bdos_segment,CS ;bdos interrupt segment
pop ds ;restore data segment
mov cl,0 ;default to dr A: on coldstart
jmp ccp ;jump to cold start entry of CCP
WBOOT: jmp ccp+6 ;direct entry to CCP at command level
;*********************************************
;* *
;* CP/M Character I/O Interface Routines *
;* Console is Usart (i8251a) on iSBC 86/12 *
;* at ports D8/DA *
;* *
;*********************************************
CONST: ;console status
in al,csts
and al,2
jz const_ret
or al,255 ;return non-zero if RDA
const_ret:
ret ;Receiver Data Available
CONIN: ;console input
call const
jz CONIN ;wait for RDA
in al,cdata
and al,7fh ;read data and remove parity bit
ret
CONOUT: ;console output
in al,csts
and al,1 ;get console status
jz CONOUT ;wait for TBE
mov al,cl
out cdata,al ;Transmitter Buffer Empty
ret ;then return data
LISTOUT: ;list device output
LISTST: ;poll list status
ret
PUNCH: ;not implemented in this configuration
READER:
mov al,1ah
ret ;return EOF for now
GETIOBF:
mov al,0 ;TTY: for consistency
ret ;IOBYTE not implemented
SETIOBF:
ret ;iobyte not implemented
zero_ret:
and al,0
ret ;return zero in AL and flags
; Routine to get and echo a console character
; and shift it to upper case
uconecho:
call CONIN ;get a console character
push ax
mov cl,al ;save and
call CONOUT
pop ax ;echo to console
cmp al,'a'
jb uret ;less than 'a' is ok
cmp al,'z'
ja uret ;greater than 'z' is ok
sub al,'a'-'A' ;else shift to caps
uret:
ret
; utility subroutine to print messages
pmsg:
mov al,[BX] ;get next char from message
test al,al
jz return ;if zero return
mov CL,AL
call CONOUT ;print it
inc BX
jmps pmsg ;next character and loop
;*********************************************
;* *
;* Disk Input/Output Routines *
;* *
;*********************************************
SELDSK: ;select disk given by register CL
mov bx,0000h
cmp cl,2 ;this BIOS only supports 2 disks
jnb return ;return w/ 0000 in BX if bad drive
mov al, 80h
cmp cl,0
jne sel1 ;drive 1 if not zero
mov al, 40h ;else drive is 0
sel1: mov sel_mask,al ;save drive select mask
;now, we need disk parameter address
mov ch,0
mov bx,cx ;BX = word(CL)
mov cl,4
shl bx,cl ;multiply drive code * 16
;create offset from Disk Parameter Base
add bx,offset dp_base
return:
ret
HOME: ;move selected disk to home position (Track 0)
mov trk,0 ;set disk i/o to track zero
mov bx,offset hom_com
call execute
jz return ;home drive and return if OK
mov bx,offset bad_hom ;else print
call pmsg ;"Home Error"
jmps home ;and retry
SETTRK: ;set track address given by CX
mov trk,cl ;we only use 8 bits of track address
ret
SETSEC: ;set sector number given by cx
mov sect,cl ;we only use 8 bits of sector address
ret
SECTRAN: ;translate sector CX using table at [DX]
mov bx,cx
add bx,dx ;add sector to tran table address
mov bl,[bx] ;get logical sector
ret
SETDMA: ;set DMA offset given by CX
mov dma_adr,CX
ret
SETDMAB: ;set DMA segment given by CX
mov dma_seg,CX
ret
;
GETSEGT: ;return address of physical memory table
mov bx,offset seg_table
ret
;*********************************************
;* *
;* All disk I/O parameters are setup: the *
;* Read and Write entry points transfer one *
;* sector of 128 bytes to/from the current *
;* DMA address using the current disk drive *
;* *
;*********************************************
READ:
mov al,12h ;basic read sector command
jmps r_w_common
WRITE:
mov al,0ah ;basic write sector command
r_w_common:
mov bx,offset io_com ;point to command string
mov byte ptr 1[BX],al ;put command into string
; fall into execute and return
execute: ;execute command string.
;[BX] points to length,
; followed by Command byte,
; followed by length-1 parameter bytes
mov last_com,BX ;save command address for retries
outer_retry:
;allow some retrying
mov rtry_cnt,max_retries
retry:
mov BX,last_com
call send_com ;transmit command to i8271
; check status poll
mov BX,last_com
mov al,1[bx] ;get command op code
mov cx,0800h ;mask if it will be "int req"
cmp al,2ch
jb exec_poll ;ok if it is an interrupt type
mov cx,8080h ;else we use "not command busy"
and al,0fh
cmp al,0ch ;unless there isn't
mov al,0
ja exec_exit ; any result
;poll for bits in CH,
exec_poll: ; toggled with bits in CL
in al,fdc_stat ;read status
and al,ch
xor al,cl ; isolate what we want to poll
jz exec_poll ;and loop until it is done
;Operation complete,
in al,fdc_rslt ; see if result code indicates error
and al,1eh
jz exec_exit ;no error, then exit
;some type of error occurred . . .
cmp al,10h
je dr_nrdy ;was it a not ready drive ?
;no,
dr_rdy: ; then we just retry read or write
dec rtry_cnt
jnz retry ; up to 10 times
; retries do not recover from the
; hard error
mov ah,0
mov bx,ax ;make error code 16 bits
mov bx,errtbl[BX]
call pmsg ;print appropriate message
in al,cdata ;flush usart receiver buffer
call uconecho ;read upper case console character
cmp al,'C'
je wboot_l ;cancel
cmp al,'R'
je outer_retry ;retry 10 more times
cmp al,'I'
je z_ret ;ignore error
or al,255 ;set code for permanent error
exec_exit:
ret
dr_nrdy: ;here to wait for drive ready
call test_ready
jnz retry ;if it's ready now we are done
call test_ready
jnz retry ;if not ready twice in row,
mov bx,offset nrdymsg
call pmsg ;"Drive Not Ready"
nrdy01:
call test_ready
jz nrdy01 ;now loop until drive ready
jmps retry ;then go retry without decrement
zret:
and al,0
ret ;return with no error code
wboot_l: ;can't make it w/ a short leap
jmp WBOOT
;*********************************************
;* *
;* The i8271 requires a read status command *
;* to reset a drive-not-ready after the *
;* drive becomes ready *
;* *
;*********************************************
test_ready:
mov dh, 40h ;proper mask if dr 1
test sel_mask,80h
jnz nrdy2
mov dh, 04h ;mask for dr 0 status bit
nrdy2:
mov bx,offset rds_com
call send_com
dr_poll:
in al,fdc_stat ;get status word
test al,80h
jnz dr_poll ;wait for not command busy
in al,fdc_rslt ;get "special result"
test al,dh ;look at bit for this drive
ret ;return status of ready
;*********************************************
;* *
;* Send_com sends a command and parameters *
;* to the i8271: BX addresses parameters. *
;* The DMA controller is also initialized *
;* if this is a read or write *
;* *
;*********************************************
send_com:
in al,fdc_stat
test al,80h ;insure command not busy
jnz send_com ;loop until ready
;see if we have to initialize for a DMA operation
mov al,1[bx] ;get command byte
cmp al,12h
jne write_maybe ;if not a read it could be write
mov cl,40h
jmps init_dma ;is a read command, go set DMA
write_maybe:
cmp al,0ah
jne dma_exit ;leave DMA alone if not read or write
mov cl,80h ;we have write, not read
init_dma:
;we have a read or write operation, setup DMA controller
; (CL contains proper direction bit)
mov al,04h
out dmac_mode,al ;enable dmac
mov al,00
out dmac_cont,al ;send first byte to control port
mov al,cl
out dmac_cont,al ;load direction register
mov ax,dma_adr
out dmac_adr,al ;send low byte of DMA
mov al,ah
out dmac_adr,al ;send high byte
mov ax,dma_seg
out fdc_segment,al ;send low byte of segment address
mov al,ah
out fdc_segment,al ;then high segment address
dma_exit:
mov cl,[BX] ;get count
inc BX
mov al,[BX] ;get command
or al,sel_mask ;merge command and drive code
out fdc_com,al ;send command byte
parm_loop:
dec cl
jz exec_exit ;no (more) parameters, return
inc BX ;point to (next) parameter
parm_poll:
in al,fdc_stat
test al,20h ;test "parameter register full" bit
jnz parm_poll ;idle until parm reg not full
mov al,[BX]
out fdc_parm,al ;send next parameter
jmps parm_loop ;go see if there are more parameters
;*********************************************
;* *
;* Data Areas *
;* *
;*********************************************
data_offset equ offset $
dseg
org data_offset ;contiguous with code segment
signon db cr,lf,cr,lf
db 'MP/M-86 Loader 2.0',cr,lf,0
bad_hom db cr,lf,'Home Error',cr,lf,0
int_trp db cr,lf,'Interrupt Trap Halt',cr,lf,0
errtbl dw er0,er1,er2,er3
dw er4,er5,er6,er7
dw er8,er9,erA,erB
dw erC,erD,erE,erF
er0 db cr,lf,'Null Error ??',0
er1 equ er0
er2 equ er0
er3 equ er0
er4 db cr,lf,'Clock Error :',0
er5 db cr,lf,'Late DMA :',0
er6 db cr,lf,'ID CRC Error :',0
er7 db cr,lf,'Data CRC Error :',0
er8 db cr,lf,'Drive Not Ready :',0
er9 db cr,lf,'Write Protect :',0
erA db cr,lf,'Trk 00 Not Found :',0
erB db cr,lf,'Write Fault :',0
erC db cr,lf,'Sector Not Found :',0
erD equ er0
erE equ er0
erF equ er0
nrdymsg equ er8
rtry_cnt db 0 ;disk error retry counter
last_com dw 0 ;address of last command string
dma_adr dw 0 ;dma offset stored here
dma_seg dw 0 ;dma segment stored here
sel_mask db 40h ;select mask, 40h or 80h
; Various command strings for i8271
io_com db 3 ;length
rd_wr db 0 ;read/write function code
trk db 0 ;track #
sect db 0 ;sector #
hom_com db 2,29h,0 ;home drive command
rds_com db 1,2ch ;read status command
; System Memory Segment Table
segtable db 1 ;1 segment
dw tpa_seg ;seg starts after BIOS
dw tpa_len ;and extends to 20000
; DISKS 2
dpbase equ $ ;Base of Disk Parameter Blocks
dpe0 dw xlt0,0000h ;Translate Table
dw 0000h,0000h ;Scratch Area
dw dirbuf,dpb0 ;Dir Buff, Parm Block
dw csv0,alv0 ;Check, Alloc Vectors
dpe1 dw xlt1,0000h ;Translate Table
dw 0000h,0000h ;Scratch Area
dw dirbuf,dpb1 ;Dir Buff, Parm Block
dw csv1,alv1 ;Check, Alloc Vectors
; DISKDEF 0,1,26,6,1024,243,64,64,2
;
; 1944: 128 Byte Record Capacity
; 243: Kilobyte Drive Capacity
; 64: 32 Byte Directory Entries
; 64: Checked Directory Entries
; 128: Records / Extent
; 8: Records / Block
; 26: Sectors / Track
; 2: Reserved Tracks
; 6: Sector Skew Factor
;
dpb0 equ offset $ ;Disk Parameter Block
dw 26 ;Sectors Per Track
db 3 ;Block Shift
db 7 ;Block Mask
db 0 ;Extnt Mask
dw 242 ;Disk Size - 1
dw 63 ;Directory Max
db 192 ;Alloc0
db 0 ;Alloc1
dw 16 ;Check Size
dw 2 ;Offset
xlt0 equ offset $ ;Translate Table
db 1,7,13,19
db 25,5,11,17
db 23,3,9,15
db 21,2,8,14
db 20,26,6,12
db 18,24,4,10
db 16,22
als0 equ 31 ;Allocation Vector Size
css0 equ 16 ;Check Vector Size
; DISKDEF 1,0
;
; Disk 1 is the same as Disk 0
;
dpb1 equ dpb0 ;Equivalent Parameters
als1 equ als0 ;Same Allocation Vector Size
css1 equ css0 ;Same Checksum Vector Size
xlt1 equ xlt0 ;Same Translate Table
; ENDEF
;
; Uninitialized Scratch Memory Follows:
;
begdat equ offset $ ;Start of Scratch Area
dirbuf rs 128 ;Directory Buffer
alv0 rs als0 ;Alloc Vector
csv0 rs css0 ;Check Vector
alv1 rs als1 ;Alloc Vector
csv1 rs css1 ;Check Vector
enddat equ offset $ ;End of Scratch Area
datsiz equ offset $-begdat ;Size of Scratch Area
db 0 ;Marks End of Module
loc_stk rw 32 ;local stack for initialization
stkbase equ offset $
lastoff equ offset $
tpa_seg equ (lastoff+0400h+15) / 16
tpa_len equ 2000h - tpa_seg
db 0 ;fill last address for GENCMD
;*********************************************
;* *
;* Dummy Data Section *
;* *
;*********************************************
dseg 0 ;absolute low memory
org 0 ;(interrupt vectors)
int0_offset rw 1
int0_segment rw 1
; pad to system call vector
rw 2*(bdos_int-1)
bdos_offset rw 1
bdos_segment rw 1
END


View File

@@ -0,0 +1,40 @@
:0400000300001200E7
:1B120081E93C00E95B00E95B00E96100E96800E97000E96E00E96B00E9B60067
:1B121B81E99200E9C500E9C700E9D000E9DB00E9DC00E95200E9BD00E9C6008C
:1B123681E9C800E94A00E94A008CC88ED08ED88EC0BC8A16FC1EB800008ED80B
:1B125181C706800306048C0E82031FB100E9A2EEE9A5EEE4DA240274020CFF5E
:1B126C81C3E8F4FF74FBE4D8247FC3E4DA240174FA8AC1E6D8C3C3B01AC3B09A
:1B12878100C3C32400C3E8DDFF508AC8E8E1FF583C6172063C7A77022C20C385
:1B12A2818A0784C074288AC8E8CAFF43EBF2BB000080F9027318B08080F900B2
:1B12BD817502B040A21315B5008BD9B104D3E381C32215C3C606161500BB18D8
:1B12D88115E8350074F2BB1414E8BEFFEBEB880E1615C3880E1715C38BD90314
:1B12F381DA8A1FC3890E0F15C3890E1115C3BB1D15C3B012EB02B00ABB14151E
:1B130E81884701891E0D15C6060C150A8B1E0D15E889008B1E0D158A4701B921
:1B13298100083C2C720BB98080240F3C0CB0007736E4A022C532C174F8E4A15B
:1B134481241E74283C107425FE0E0C1575C8B4008BD88B9F3B14E845FFE4D868
:1B135F81E82BFF3C4374253C5274AB3C49741A0CFFC3E81A0075A4E8150075AD
:1B137A819FBBAC14E821FFE80A0074FBEB922400C3E9D3FEB640F6061315809C
:1B1395817502B604BB1B15E80B00E4A0A88075FAE4A184C6C3E4A0A88075FAE5
:1B13B0818A47013C127504B140EB063C0A7520B180B004E6A8B000E6A58AC152
:1B13CB81E6A5A10F15E6A48AC4E6A4A11115E6AA8AC4E6AA8A0F438A070A0622
:1513E6811315E6A0FEC9748243E4A0A82075FA8A07E6A1EBEF16
:1B13FB820D0A0D0A4D502F4D2D3836204C6F6164657220322E300D0A000D0A1E
:1B141682486F6D65204572726F720D0A000D0A496E74657272757074205472A5
:1B14318261702048616C740D0A005B145B145B145B146B147B1488149914ACCE
:1B144C8214C014D214E714F7145B145B145B140D0A4E756C6C204572726F7206
:1B146782203F3F000D0A436C6F636B204572726F72203A000D0A4C6174652006
:1B148282444D41203A000D0A494420435243204572726F72203A000D0A4461C5
:1B149D82746120435243204572726F72203A000D0A4472697665204E6F7420DF
:1B14B8825265616479203A000D0A57726974652050726F74656374203A000DBE
:1B14D3820A54726B203030204E6F7420466F756E64203A000D0A5772697465D8
:1B14EE82204661756C74203A000D0A536563746F72204E6F7420466F756E64F7
:1B150982203A00000000000000004003000000022900012C01A901571E5115CA
:1B1524820000000000006B1542150A16EB1551150000000000006B15421539BD
:1B153F82161A161A00030700F2003F00C0001000020001070D1319050B111729
:11155A8203090F1502080E141A060C1218040A101618
:01164982001E
:01168A8200DD
:02000086000078
:00000001FF

:1B14B8825265616479203A000D0A577269746520

View File

@@ -0,0 +1,321 @@
title 'MP /M-86 Loader'
; The MPMLDR consists of this module along with the
; LDBDOS and LDBIOS. The LDBDOS is the same as for
; for CP/M-86, and the LDBIOS has only the login message
; changed.
; MPMLDR resides on the first two tracks of a
; MP/M-86 system diskette and is brought into memory
; by the ROM bootstrap loader to load initiate MP/M-86
; It opens the file 'MPM.SYS' using the LDBDOS and LDBIOS
; and then reads it into memory. The DS register is set
; to the start of the MPM DATA area, and a JMPF to the
; first byte of the MPM code is executed.
; The first 128 byte record of the MPM.SYS file is a header
; with the following format:
; ty rb 1 ;seg type
; len rw 1 ;length
; abs dw 1 ;absolute segment address for LOADER
; min rw 1 ;minimum mem
; max rw 1 ;max mem needed
; The code is expected first and then the data within MPM.SYS
; This header record is constructed automatically by the
; GENSYS-86 utility. See the variables declared at 'SEC1:'
; where the first sector of MPM.SYS will be read
; MPMLDR may be read into any segment that does not
; overlap the desired system load segment as it makes
; all memory references using copies of the CS: register
; it is entered with.
;
; For debugging under CP/M and DDT a 'IB' can be used to force a
; break to DDT just before 'Far Jumping' to MPM.
;
false equ 0
true equ not false
cr equ 0dh
lf equ 0ah
ldbdos_offset equ 406H ;offset of LDBDOS
mldbios_offset equ 1200h ;offset of LDBIOS
bdos_int equ 224 ;lbdos interrupt number
bootdrv equ 0 ; boot drive always zero
codetype equ 1 ; code type CMD header
datatype equ 2 ; data type CMD header
; dummy section for interrupt vectors
dseg 0
org 0
abs_zero rw 2*bdosint
bdos_offset rw 1
bdos_segment rw 1
fcb1 equ 5dh ; look here for 'B' to break
ddt_int equ 3 ; DDT interrupt
; bdos function numbers
coutf equ 2
pstrf equ 9
seldsk equ 14
openf equ 15
readsf equ 20
dmaf equ 26
dmabf equ 51
;*******************************
;*
;* MPMLDR starts here
;*
;*******************************
cseg ; JMPF to here from boot ROM
org 0
jmp start ; if loaded under DDT this
; gets overlayed and IP = 100H
; want 100h byte header for
; 'IB' option
db 'COPYRIGHT (C) 1981,' ; found by serial program
db ' DIGITAL RESEARCH '
db '654321'
db ' MP/M-86 Loader V2.0 (9/21/81)'
org 80H ; read first sector of MPM.SYS
sec1 rb 128 ; here
org offset sec1 ;CMD header fields
ctype rb 1 ;type
clen rw 1 ;length
cldseg rw 1 ;abs
cmin rw 1 ;minimum
cmax rw 1 ;maximum
dtype rb 1
dlen rw 1
dldseg rw 1
dmin rw 1
dmax rw 1
org 100H
start: ; execution begins here if DDT
jmp mldbios ; initialize mldbios
; mldbios returns here: 103H
xor ax,ax ! mov ds,ax ; temp DS at absolute zero
mov bdos_offset,offset ldbdos_offset ; to patch in interrupt table
mov bdos_segment,cs ; offset and segment
mov ax,cs ! mov ss,ax ; make ss, ds, es = cs
mov ds,ax ! mov es,ax
mov sp,offset(stack) ; set up local stack
mov dx,offset signon
call msg
call initlbdos ; warm up lbdos and lbios
call openfnc ; open MPM.SYS
cmp al,255 ! jne perr ; insure good file
mov dx,offset nofile ! call msg ; no MPM.SYS file
jmp stop ; then halt the machine
perr:
mov dx,cs ! call setdmab
mov dx,offset sec1 ! call setdma ; read first sector of MPM.SYS
call read
cmp ctype,codetype ; code should be first
jnz badhdr
cmp dtype,datatype ; then data
jnz badhdr
mov ax,cldseg ; code abs + code length
add ax,clen ; should be = to data abs
cmp ax,dldseg ! jnz badhdr
add ax,dlen ! cmp ax,cldseg ; check for wrap around
ja hdrok
badhdr:
mov dx,offset hdrerr ! call msg
jmp stop
hdrok:
mov dx,offset csegment ! call msg ; put memory map on console
mov ax,cldseg ! call phex ; print base code segment
mov dx,offset dsegment ! call msg ; print base data segment
mov ax,dldseg ! call phex
;
mov dx,cldseg
mov dmab,dx ; initial DMA segment
readit1:
call setdmab ; set DMA segment for disk IO
mov dx,0 ; offset of MPM in segment
readit2:
call setdma ; set DMA offset for
push dx ! call read ; next sector read
cmp al,01H ! je done ; check for EOF
cmp al,0 ! je prerr ; check for good write
mov dx,offset rerr ! call msg ; print READ ERROR message
jmp stop ; hard stop on any error
prerr: pop dx ! add dx,80H
cmp dx,0 ; more than 64K ?
jnz readit2
add dmab,1000h ; add 64K to base
mov dx,dmab
jmp readit1
done:
pop ax ; number of bytes read
mov cl,4
shr ax,cl ; number of paragraphs read
add ax,dmab ; number of 64K segments read
sub ax,cldseg ; (dmab - cldseg)
mov cx,clen
add cx,dlen
cmp ax,cx
jae lenok ; MPM.SYS at least as long
mov dx,offset shortmsg ; as header claims ?
call msg ! jmp stop
lenok:
push cx ; clen + dlen in cx
mov dx,offset lenmsg ! call msg ; print length message
pop ax
add ax,cldseg
dec ax ; last paragraph
call phex
call pcrlf ; and a crlf
mov ax,cldseg
mov mpmcseg,ax
mov ds,dldseg ; MP/M data segment
mov al, cs:.fcb1 ; must use CS over-ride
cmp al,'B'
jnz gompm
int ddt_int ; break to mpm
gompm:
jmpf mpm ; leap to MPM initialization
;*****************************
;*
;* subroutines
;*
;*****************************
;******
phex: ;print 4 hex characters from ax
mov cx,0404h ; 4 in both CH and CL
lhex:
rol ax,cl ; rotate left 4
push cx ! push ax ; save crucial registers
call pnib ; print hex nibble
pop ax ! pop cx ; restore registers
dec ch ! jnz lhex ; and loop four times
ret
pnib: ;print low nibble in AL as hex char
and al,0fh ! cmp al,9
ja p10 ;above 9 ?
add al,'0' ;digit
jmp prn
p10: add al,'A'-10 ;char a-e
prn: mov dl,al
;******
putchar:
mov cl,coutf
jmp sys_vec
;******
initlbdos:
mov cl,seldsk ! mov dx,bootdrv ; select boot disk
jmp sys_vec
;******
openfnc:
mov cl,openf ! mov dx,offset fcb ; fcb already initialized
mov cl,openf
jmp sys_vec
;********
;
setdma: ;set new dma addr in dx
mov cl,dmaf
jmp sys_vec
;********
;
setdmab: ; set new dma segment base from DX
mov cl,dmabf
jmp sys_vec
;******
;
pcrlf: mov dx,offset crlf ;print carriage return, line feed
;******
;
msg: ;print msg starting at dx until $
mov cl,pstrf ;print string function
jmp sys_vec
;*****
;
read:
mov dx,offset fcb ! mov cl,readsf
; jmp sys_vec
;******
;
sys_vec:
int bdos_int
ret
;******
;
stop: mov ax,0 ; hard stop 8086 for error
mov ds,ax
mov word ptr .8h,ax
mov word ptr .0ah,cs
stop2:
jmp stop2
;********************************
;*
;* DATA AREA
;*
;********************************
signon db cr,lf,lf,'MP/M-86 V2.0 Loader',cr,lf,'$'
nofile db cr,lf,'The File MPM.SYS Not Found On This Disk$'
rerr db cr,lf,'Error In Reading MPM.SYS$'
hdrerr db cr,lf,'Bad Header Record in MPM.SYS$'
shortmsg db cr,lf,'MPM.SYS Too Short $'
csegment db cr,lf,'Code Paragraph Address = $'
dsegment db cr,lf,'Data Paragraph Address = $'
lenmsg db cr,lf,'Last Paragragh = $'
crlf db cr,lf,'$'
; vector for jmpf indirect to start MP/M
mpm dd abs_zero ; (dummy value)
org offset mpm ; overlay preceding with DW's
mpmstart dw 0 ; first word of MPM code
mpmcseg rw 1 ; second is segmet of MPM code
dmab rw 1 ; current DMA segment
fcb db 0,'MPM ','SYS',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
; look on m disk first
org (offset $+1) and 0FFFEh ; even address for stack
rw 32
stack equ offset $
db 0
; dummy section for BIOS init label
org mldbios_offset
mldbios:
end


View File

@@ -0,0 +1,37 @@
:02000086000078
:0400000300000000F9
:1B000081E9FD00434F505952494748542028432920313938312C2044494749B5
:1B001B8154414C20524553454152434820363534333231204D502F4D2D3836D2
:16003681204C6F616465722056322E302028392F32312F383129E2
:1B010081E9FD1033C08ED8C706800306048C0E82038CC88ED08ED88EC0BCD8A1
:1B011B8103BA8802E84A01E82801E82D013CFF7509BAA102E83A01E944018CB4
:1B013681CAE82A01BA8000E81F01E82E012E803E80000175242E803E8900027A
:1B015181751C2EA183002E030681002E3B068C00750C2E03068A002E3B068348
:1B016C81007709BAE602E8F700E90101BA1A03E8EE002EA18300E8A300BA3691
:1B01878103E8E1002EA18C00E896002E8B1683002E89167503E8C500BA000039
:1B01A281E8BA0052E8C8003C0174263C007409BACB02E8B500E9BF005A81C224
:1B01BD81800083FA0075DE2E8106750300102E8B167503E9C9FF58B104D3E859
:1B01D8812E030675032E2B0683002E8B0E81002E030E8A003BC17309BA0503AF
:1B01F381E87600E9800051BA5203E86C00582E0306830048E81E00E85C002E23
:1B020E81A183002EA373032E8E1E8C002EA05D003C427501CC2EFF2E7103B910
:1B0229810404D3C05150E807005859FECD75F3C3240F3C0977050430E9020054
:1B02448104378AD0B102E92900B10EBA0000E92100B10FBA7703B10FE917008D
:1B025F81B11AE91200B133E90D00BA6E03B109E90500BA7703B114CDE0C3B86F
:1B027A8100008ED8A308008C0E0A00E9FDFF0D0A0A4D502F4D2D3836205632D1
:1B0295812E30204C6F616465720D0A240D0A5468652046696C65204D504D2EAD
:1B02B081535953204E6F7420466F756E64204F6E2054686973204469736B24E2
:1B02CB810D0A4572726F7220496E2052656164696E67204D504D2E535953246A
:1B02E6810D0A42616420486561646572205265636F726420696E204D504D2E47
:1B030181535953240D0A4D504D2E53595320546F6F2053686F727420240D0A32
:1B031C81436F6465205061726167726170682041646472657373203D20240D80
:1B0337810A44617461205061726167726170682041646472657373203D202469
:1B0352810D0A4C617374205061726167726167682020202020202020203D203A
:08036D81240D0A2400000000A8
:02037181000009
:1B037781004D504D202020202053595300000000000000000000000000000061
:06039281000000000000E4
:0103D88100A3
:00000001FF
5953246A
:1B02E6810D0A42616420486561646572205265636F726420696E204D504D2E47
:1B030181535953240D0A4D504D2E53595

View File

@@ -0,0 +1,36 @@
;
; GENERATE XIOS.MPM
;
a86 xios
gencmd xios 8080
era xios.mpm
ren xios.mpm=xios.cmd
vax xios.lst $$atn
xref86 xios
vax xios.xrf $$atn
;
; GENERATE LDMPM.H86
a86 ldmpm
xref86 ldmpm
vax ldmpm.lst $$atn
vax ldmpm.xrf $$atn
;
; GENERATE LDBDOS.H86
a86 ldbdos
xref86 ldbdos
vax ldbdos.lst $$atn
vax ldbdos.xrf $$atn
;
; GENERATE LDBIOS.H86
;
a86 ldbios
xref86 ldbios
vax ldbios.lst $$atn
vax ldbios.xrf $$atn
;
; GENERATE MPMLDR.CMD
;
pip mpmldr.h86=ldmpm.h86,ldbdos.h86,ldbios.h86
gencmd mpmldr 8080 code[a0400]
;


View File

@@ -0,0 +1,181 @@
:02000086000078
:0400000300000000F9
:1B000081E9FD00434F505952494748542028432920313938312C2044494749B5
:1B001B8154414C20524553454152434820363534333231204D502F4D2D3836D2
:16003681204C6F616465722056322E302028392F32312F383129E2
:1B010081E9FD1033C08ED8C706800306048C0E82038CC88ED08ED88EC0BCD8A1
:1B011B8103BA8802E84A01E82801E82D013CFF7509BAA102E83A01E944018CB4
:1B013681CAE82A01BA8000E81F01E82E012E803E80000175242E803E8900027A
:1B015181751C2EA183002E030681002E3B068C00750C2E03068A002E3B068348
:1B016C81007709BAE602E8F700E90101BA1A03E8EE002EA18300E8A300BA3691
:1B01878103E8E1002EA18C00E896002E8B1683002E89167503E8C500BA000039
:1B01A281E8BA0052E8C8003C0174263C007409BACB02E8B500E9BF005A81C224
:1B01BD81800083FA0075DE2E8106750300102E8B167503E9C9FF58B104D3E859
:1B01D8812E030675032E2B0683002E8B0E81002E030E8A003BC17309BA0503AF
:1B01F381E87600E9800051BA5203E86C00582E0306830048E81E00E85C002E23
:1B020E81A183002EA373032E8E1E8C002EA05D003C427501CC2EFF2E7103B910
:1B0229810404D3C05150E807005859FECD75F3C3240F3C0977050430E9020054
:1B02448104378AD0B102E92900B10EBA0000E92100B10FBA7703B10FE917008D
:1B025F81B11AE91200B133E90D00BA6E03B109E90500BA7703B114CDE0C3B86F
:1B027A8100008ED8A308008C0E0A00E9FDFF0D0A0A4D502F4D2D3836205632D1
:1B0295812E30204C6F616465720D0A240D0A5468652046696C65204D504D2EAD
:1B02B081535953204E6F7420466F756E64204F6E2054686973204469736B24E2
:1B02CB810D0A4572726F7220496E2052656164696E67204D504D2E535953246A
:1B02E6810D0A42616420486561646572205265636F726420696E204D504D2E47
:1B030181535953240D0A4D504D2E53595320546F6F2053686F727420240D0A32
:1B031C81436F6465205061726167726170682041646472657373203D20240D80
:1B0337810A44617461205061726167726170682041646472657373203D202469
:1B0352810D0A4C617374205061726167726167682020202020202020203D203A
:08036D81240D0A2400000000A8
:02037181000009
:1B037781004D504D202020202053595300000000000000000000000000000061
:06039281000000000000E4
:0103D88100A3
:00000001FF
:02000085000079
:02000085000079
:0400000300000400F5
:1B040081000000000000E90800E804F604FC0402052EA3CD0D2E8C16CF0D2EFD
:1B041B818926D10D8CC88ED08D2685118CD81E065557561616071FA3520F2EAF
:1B043681A1CD0DE810005E5F5D071F2E8B26D10D2E8E16CF0DCF8916070F8800
:1B04518116350FC706090F0000C606540F0032C0A23F0FA23D0FBB9A0D53809C
:1B046C81F929720980E90980F9317201C38AD9B7008ACA03DB2EFFA786040358
:1B048781121F06EE051F0612120F121F061F061F0620061F061F061F066D0DC7
:1B04A281310D7E0D1F061F061F061F068A0D1F061F061F061F061F06930D1F52
:1B04BD81061F061F061F061F061F061F061F061F061F061F062F062F061F069C
:1B04D8817E057A057E057E057E057E057E057E058D1EA80FE81D003C03755AFF
:1B04F381E90D0D8D1EB30FEB0A8D1EBF0FEB048D1EBA0FE80300E9F70C53E81A
:1B050E81F000A0060F0441A2A40F8D0E980FE8EB0059E8E700E9E30C1E50513E
:1B052981C606540FFF880E550F32ED8B36070F8936500F8D3EC30F893E070F80
:1B0544818E1E520FF3A459581FC351B121EB0351B124E8CDFF59C30650518AAC
:1B055F810E550F32ED8E06520F8D36C30F8B3E500F893E070FF3A4595807C3CE
:1B057A8189164E0FC3C3A0040F0AC0751EE87C0C240174F1E8780C3C13750D1C
:1B059581E8710C3C037503E9640C32C0C3A2040FB001C3A0000F0AC075165122
:1B05B081E8CDFF5951E8540C5951803E030F007403E84B0C598AC18D1E020F79
:1B05CB813C7F7416FE073C207310FE0F8A070AC074088AC13C087503FE0FC3B0
:1B05E6813C0A75FBC60700C380F90975B5B120E8B0FFA0020F240775F4C3B166
:1B0601810DE8A3FFB10AE99EFF8BF1AC3C2474EE41518AC81E161FE8D3FF1F8B
:1B061C8159EBEBC38BCA1E8E1E520FE8E0FF1FC3A2090FC3B001EBF88D1E0B60
:1B06378104FF2751B5008BF28BFBF3A459C38A0E060FE8CF0B83FB00744B8B0A
:1B0652811783C302891E120F83C302891E140F83C302891E160F83C30287DA16
:1B066D81891E2F0F8D1E180FB108E8C0FF8B161A0F8D1E200FB10FE8B3FFA03C
:1B068881260F8D1E3C0FC607FF0AC07403C60700B0FF0AC0C3E8780B33C08BAC
:1B06A3811E140F8907C3E87B0BEB03E8790B0AC074E78D1E0904E97CFF8B1E75
:1B06BE81490FB102D3EB891E440F891E4B0FA1440FBA0000F736200F528BC82D
:1B06D9818B36140F890C030E2D0FE8380B598B162F0FE8420B8BCBE92E0B8D22
:1B06F4811E220F8A0FA0420FD2E88AE8B1072A0FA0410FD2E002C5C38B1E0798
:1B070F810F83C31003D9803E3C0F0074058A1FB700C303D98B1FC3E8CAFF8AE4
:1B072A81C8B500E8DCFF891E440FC38B1E440F0BDBC38A0E220F8B1E440FD3F9
:1B074581E3891E460FA0420F2206230F0AD8891E440FC38B1E070F83C30C8AB4
:1B07608107C3BA0F000316070FBB110003DAC3E8F0FF8A07A2420F87DA8A0782
:1B077B81A2400FE8D7FFA0240F2207A2410FC3E8D5FFA0340F3C02750232C03C
:1B0796810206420F880787DAA0400F8807C3B980008B1E180F32C0020743E214
:1B07B181FBC3518A0E060FBB0100D3E3590BD9C3A10C0F8A0E060FD3E8240135
:1B07CC81C38B0E0C0FE8DFFF891E0C0F8B16270F428B1E120F8917C3E81E0046
:1B07E781BA090003DA8A07D0D0731E8D1E0F04E93FFEE8C5FF74128D1E0D0442
:1B080281E933FE8B1E180FA0480FB40003D8C38B1E070F83C30E8A07C3E8F3E5
:1B081D81FFC60700C3E8ECFF0C808807C38B16490F8B1E120F3B17C3E8F2FF4E
:1B08388172FA428917C3522BD38BDA5AC3B1FF8B164B0F8B1E2B0FE8ECFF736D
:1B085381E051E84CFF8B1E4B0F031E1C0F59FEC1740D3A07740BE8BEFF7306DF
:1B086E81E85CFFC38807C3E8CDFFE81B00B101E82EFEE90600E81000E820FE2C
:1B0889818B0E4E0FE8A3098D1E100FEB098CD9E898098D1E180F8B0FE98009BF
:1B08A4818B16180F8B1E100FB180068E06520FE884FD07C38D1E490F8A0743F2
:1B08BF813A077502FEC0C3BBFFFF891E490FC38B16270F8B1E490F43891E49DE
:1B08DA810FE860FF7302EBE4A0490F240351B105D2E059A2480F0AC0754051EE
:1B08F581E8C4FDE888FF59E948FF8AD180E207FEC28AF28AC1B103D2C8241FEA
:1B0910818AC851B105D2E0590AC88AC5D0C8D0C8D0C8241F8AE88B1E1E0F0370
:1B092B81D98A07518ACAD2C059C352E8C6FF24FE590AC1518ACDD2C888075904
:1B094681C3E8BBFE83C31051B1115AFEC97501C352803E3C0F00740851538AE9
:1B0961810FB500EB07FEC9518B0F43530BC9740B8B1E250F3BD97203E8B9FFA3
:1B097C815B4359EBCF8B1E250FB103D3EB438BCB8B1E1E0FC6070043E2FA8BF9
:1B09978116290F8B1E1E0F8917E8FAFC8B1E120FC7070300E818FFB1FFE81BD5
:1B09B281FFE802FF743BE84AFE803FE574EEA0050F3A07750C438A072C2475CD
:1B09CD8105FEC8A2090FB101E86FFFE85AFEEBD1A0330FE949FC518A2E240FB9
:1B09E881F6D522CD22C52AC1241F59C3C606330FFF880E370F8B1E070F891E39
:1B0A0381380FE8BEFEE892FCB100E8BEFEE8A5FE74648B16380F8BF2AC3CE50C
:1B0A1E81740752E806FE5A7352E8DBFDA0370F8AC8B5000AC9742D8BF2AC3CDE
:1B0A39813F741E80FD0D741980FD0C8BF2AC74082A07247F75BCEB09518A0F28
:1B0A5481E88CFF5975B14243FEC5FEC9EBCFA0490F2403A2090F8D1E330F8AFB
:1B0A6F8107D0D0730432C08807C3E84AFEB0FFE9ABFBE875FDB10CE86BFFE8CA
:1B0A8A812CFE74EAE853FDE871FDC607E5B100E8ABFEE8D6FDE869FFEBE58B60
:1B0AA581D10BC9740C495251E84FFED0D87318595A3B16250F731A4251528B07
:1B0AC081CAE83BFED0D873045A59EBDAD0D0FEC0E86BFE5B5AC30BC975CCBB21
:1B0ADB810000C3B100B22052B5008B16070F03D1E817FD59E848FBE8C7FBE994
:1B0AF6817DFDE8FEFCB10CE8F4FE8B1E070F8A0783C3108807E8AAFD7501C374
:1B0B1181E8D0FCB110B20CE8C7FFE8EDFEEBEBB10CE8CFFEE890FD74E6B100CC
:1B0B2C81B20CE8B1FFE8D7FEEBEFB10FE8B9FEE87AFD74D0E815FC5053E8BDFD
:1B0B4781FC87DA8B1E070FB12052E8E6FAE8CBFC5ABB0C0003DA8A0FBB0F00FB
:1B0B628103DA8A2F5B5888073A0F8AC57406B0007202B0808B1E070FBA0F0031
:1B0B7D8103DA8807C3833F0075FA8BF2AD8907C333C0A2090FA3490FE829FC4A
:1B0B988175F2E874FC248075EBB10FE84EFEE80FFD74E1B91000E854FC03D9E4
:1B0BB38187DA8B1E070F03D9B110803E3C0F00741A8A070AC08BF2AC750288CF
:1B0BCE81070AC075058A078BFAAA3A077546EB16E8A1FF87DAE89CFF87DA8B2B
:1B0BE981F28B043B0775324243FEC94243FEC975C3B9ECFF03D987DA03D98BEE
:1B0C0481F2AC3A0772108807B9030003D987DA03D98A078BFAAAC606310FFFC4
:1B0C1F81E9D0FEFE0E090FC3E8CFFBFF36070FC706070F0B0FB101E8BBFDE867
:1B0C3A817CFC8F06070F74E487DABB0F0003DAB11132C0880743FEC975F9BB25
:1B0C55810D0003DA8807E8D7FBE87DFEE9BEFB32C0A2310FE821FFE849FC744E
:1B0C7081B58B1E070F83C30C8A07FEC0241F8807740F8AE8A0240F22C522062A
:1B0C8B81310F740DEB2683C302FE078A07240F7426B10FE853FDE814FC7511DA
:1B0CA681A0320FFEC07415E877FFE805FC740DEB03E886FEE8B2FA32C0E96A8F
:1B0CC181F9E86BF9E95AFBC606340F01C606320FFFE89AFAA0420F3A06400FFC
:1B0CDC8172143C807524E87FFFC706420F0000803E090F007514E831FAE83D86
:1B0CF781FA740CE83FFAE8CCF9E8A6F9E984FAE927F98B1E0E0F8A0E060FD3DC
:1B0D1281CB5387DAE82CF95B7503E815F9D0DB72498B0E0E0FE889FA891E0EB4
:1B0D2D810FE950FCA0350FA2060FEBD0C6063D0FFF8B1E070F8A07241FFEC820
:1B0D4881A2350F3C1E7312A0060FA23E0F8A07A23F0F24E08807E8D0FFA00536
:1B0D63810F8B1E070F0A078807C333DB891E0C0F891E0E0F881E060FE98BFF01
:1B0D7E81E8CDF7E897FAE8B2FFE9ACFDE8C1F7E8A9FFE935FF8916100FE9EFA6
:1B0D9981FA803E3D0F0074198B1E070FC60700A03F0F0AC0740B8807A03E0FEE
:190DB481A2350FE877FF803E540FFF7503E897F78B1E090F8AC38AEFC309
:02000085000079
:060DCD810000000000009F
:02000086000078
:1B0F00820000000000000000000000E50000000000000000000000000000006F
:1B0F1B8200000000000000000000000000000000000000000000000000000039
:1B0F36820000000000000000000000000000000000000000000000000000001E
:1B0F518200000000000000000000000000000000000000000000000000000003
:1B0F6C82000000000000000000000000000000000000000000000000000000E8
:1B0F8782000000000000000000000000000000000042646F7320457272204F8D
:1B0FA2826E20203A202442616420536563746F722453656C6563742446696C2C
:060FBD826520522F4F2433
:00000001FF
:0400000300001200E7
:1B120081E93C00E95B00E95B00E96100E96800E97000E96E00E96B00E9B60067
:1B121B81E99200E9C500E9C700E9D000E9DB00E9DC00E95200E9BD00E9C6008C
:1B123681E9C800E94A00E94A008CC88ED08ED88EC0BC8A16FC1EB800008ED80B
:1B125181C706800306048C0E82031FB100E9A2EEE9A5EEE4DA240274020CFF5E
:1B126C81C3E8F4FF74FBE4D8247FC3E4DA240174FA8AC1E6D8C3C3B01AC3B09A
:1B12878100C3C32400C3E8DDFF508AC8E8E1FF583C6172063C7A77022C20C385
:1B12A2818A0784C074288AC8E8CAFF43EBF2BB000080F9027318B08080F900B2
:1B12BD817502B040A21315B5008BD9B104D3E381C32215C3C606161500BB18D8
:1B12D88115E8350074F2BB1414E8BEFFEBEB880E1615C3880E1715C38BD90314
:1B12F381DA8A1FC3890E0F15C3890E1115C3BB1D15C3B012EB02B00ABB14151E
:1B130E81884701891E0D15C6060C150A8B1E0D15E889008B1E0D158A4701B921
:1B13298100083C2C720BB98080240F3C0CB0007736E4A022C532C174F8E4A15B
:1B134481241E74283C107425FE0E0C1575C8B4008BD88B9F3B14E845FFE4D868
:1B135F81E82BFF3C4374253C5274AB3C49741A0CFFC3E81A0075A4E8150075AD
:1B137A819FBBAC14E821FFE80A0074FBEB922400C3E9D3FEB640F6061315809C
:1B1395817502B604BB1B15E80B00E4A0A88075FAE4A184C6C3E4A0A88075FAE5
:1B13B0818A47013C127504B140EB063C0A7520B180B004E6A8B000E6A58AC152
:1B13CB81E6A5A10F15E6A48AC4E6A4A11115E6AA8AC4E6AA8A0F438A070A0622
:1513E6811315E6A0FEC9748243E4A0A82075FA8A07E6A1EBEF16
:1B13FB820D0A0D0A4D502F4D2D3836204C6F6164657220322E300D0A000D0A1E
:1B141682486F6D65204572726F720D0A000D0A496E74657272757074205472A5
:1B14318261702048616C740D0A005B145B145B145B146B147B1488149914ACCE
:1B144C8214C014D214E714F7145B145B145B140D0A4E756C6C204572726F7206
:1B146782203F3F000D0A436C6F636B204572726F72203A000D0A4C6174652006
:1B148282444D41203A000D0A494420435243204572726F72203A000D0A4461C5
:1B149D82746120435243204572726F72203A000D0A4472697665204E6F7420DF
:1B14B8825265616479203A000D0A57726974652050726F74656374203A000DBE
:1B14D3820A54726B203030204E6F7420466F756E64203A000D0A5772697465D8
:1B14EE82204661756C74203A000D0A536563746F72204E6F7420466F756E64F7
:1B150982203A00000000000000004003000000022900012C01A901571E5115CA
:1B1524820000000000006B1542150A16EB1551150000000000006B15421539BD
:1B153F82161A161A00030700F2003F00C0001000020001070D1319050B111729
:11155A8203090F1502080E141A060C1218040A101618
:01164982001E
:01168A8200DD
:02000086000078
:00000001FF


View File

@@ -0,0 +1,443 @@
title 'SBC86/12 w/ SBC204 Bootstrap EPROM'
;
; ROM bootstrap for CP/M-86 on an iSBC86/12
; with the
; Intel SBC 204 Floppy Disk Controller
;
; Copyright (C) 1980,1981
; Digital Research, Inc.
; Box 579, Pacific Grove
; California, 93950
;
;********************************************
;* This is the BOOT ROM which is initiated *
;* by a system reset. First, the ROM moves *
;* a copy of its data area to RAM at loca- *
;* tion 00000H, then initializes the segment*
;* registers and the stack pointer. The *
;* various peripheral interface chips on the*
;* SBC 86/12 are initialized. The 8251 *
;* serial interface is configured for a 9600*
;* baud asynchronous terminal, and the in- *
;* terrupt controller is setup for inter- *
;* rupts 10H-17H (vectors at 00040H-0005FH) *
;* and edge-triggered auto-EOI (end of in- *
;* terrupt) mode with all interrupt levels *
;* masked-off. Next, the SBC 204 Diskette *
;* controller is initialized, and track 1 *
;* sector 1 is read to determine the target *
;* paragraph address for LOADER. Finally, *
;* the LOADER on track 0 sectors 2-26 and *
;* track 1 sectors 1-26 is read into the *
;* target address. Control then transfers *
;* to LOADER. This program resides in two *
;* 2716 EPROM's (2K each) at location *
;* 0FF000H on the SBC 86/12 CPU board. ROM *
;* 0 contains the even memory locations, and*
;* ROM 1 contains the odd addresses. BOOT *
;* ROM uses RAM between 00000H and 000FFH *
;* (absolute) for a scratch area, along with*
;* the sector 1 buffer. *
;********************************************
true equ 0ffh
false equ not true
;
debug equ true
;debug = true indicates bootstrap is in same roms
;with SBC 957 "Execution Vehicle" monitor
;at FE00:0 instead of FF00:0
;
cr equ 13
lf equ 10
;
; disk ports and commands
;
base204 equ 0a0h
fdccom equ base204+0
fdcstat equ base204+0
fdcparm equ base204+1
fdcrslt equ base204+1
fdcrst equ base204+2
dmacadr equ base204+4
dmaccont equ base204+5
dmacscan equ base204+6
dmacsadr equ base204+7
dmacmode equ base204+8
dmacstat equ base204+8
fdcsel equ base204+9
fdcsegment equ base204+10
reset204 equ base204+15
;
;actual console baud rate
baud_rate equ 9600
;value for 8253 baud counter
baud equ 768/(baud_rate/100)
;
csts equ 0DAh ;i8251 status port
cdata equ 0D8h ; " data port
;
tch0 equ 0D0h ;8253 PIC channel 0 port
tch1 equ tch0+2 ;ch 1 port
tch2 equ tch0+4 ;ch 2 port
tcmd equ tch0+6 ;8253 command port
;
icp1 equ 0C0h ;8259a port 0
icp2 equ 0C2h ;8259a port 1
;
;
IF NOT DEBUG
ROMSEG EQU 0FF00H ;normal
ENDIF
;
IF DEBUG ;share prom with SBC 957
ROMSEG EQU 0FE00H
ENDIF
;
;
; This long jump prom'd in by hand
; cseg 0ffffh ;reset goes to here (ffff0h)
; JMPF BOTTOM ;boot is at bottom of PROM
; EA 00 00 00 FF ;cs = bottom of prom (ff000h)
; ip = 0
; EVEN PROM ODD PROM
; 7F8 - EA 7F8 - 00
; 7F9 - 00 7F9 - 00
; 7FA - FF ;this is not done if special = true
;
cseg romseg
;
;First, move our data area into RAM at 0000:0200
;
mov ax,cs
mov ds,ax ;point DS to CS for source
mov SI,drombegin ;start of data
mov DI,offset ram_start ;offset of destination
mov ax,0
mov es,ax ;destination segment is 0000
mov CX,data_length ;how much to move in bytes
rep movs al,al ;move out of eprom a byte at a time
;
mov ax,0
mov ds,ax ;data segment now in RAM
mov ss,ax
mov sp,stack_offset ;Initialize stack segment/pointer
cld ;clear the direction flag
;
IF NOT DEBUG
;
;Now, initialize the console USART and baud rate
;
mov al,0Eh
out csts,al ;give 8251 dummy mode
mov al,40h
out csts,al ;reset 8251 to accept mode
mov al,4Eh
out csts,al ;normal 8 bit asynch mode, * 16
mov al,37h
out csts,al ;enable Tx & Rx
mov al,0B6h
out tcmd,al ;8253 ch.2 square wave mode
mov ax,baud
out tch2,al ;low of the baud rate
mov al,ah
out tch2,al ;high of the baud rate
;
ENDIF
;
;Setup the 8259 Programmable Interrupt Controller
;
mov al,13h
out icp1,al ;8259a ICW 1 8086 mode
mov al,10h
out icp2,al ;8259a ICW 2 vector @ 40-5F
mov al,1Fh
out icp2,al ;8259a ICW 4 auto EOI master
mov al,0FFh
out icp2,al ;8259a OCW 1 mask all levels off
;
;Reset and initialize the iSBC 204 Diskette Interface
;
restart: ;also come back here on fatal errors
out reset204,AL ;reset iSBC 204 logic and
mov AL,1
out fdcrst,AL ;give 8271 FDC
mov al,0
out fdcrst,AL ; a reset command
mov BX,offset specs1
CALL sendcom ;program
mov BX,offset specs2
CALL sendcom ; Shugart SA-800 drive
mov BX,offset specs3
call sendcom ; characteristics
homer: mov BX,offset home
CALL execute ;home drive 0
;
mov bx,sector1 ;offset for first sector DMA
mov ax,0
mov es,ax ;segment " " " "
call setup_dma
;
mov bx,offset read0
call execute ;get T0 S1
;
mov es,ABS
mov bx,0 ;get loader load address
call setup_dma ;setup DMA to read loader
;
mov bx,offset read1
call execute ;read track 0
mov bx,offset read2
call execute ;read track 1
;
mov leap_segment,ES
; setup far jump vector
mov leap_offset,0
;
; enter LOADER
jmpf dword ptr leap_offset
;
pmsg:
mov cl,[BX]
test cl,cl
jz return
call conout
inc BX
jmp pmsg
;
conout:
in al,csts
test al,1
jz conout
mov al,cl
out cdata,al
ret
;
conin:
in al,csts
test al,2
jz conin
in al,cdata
and al,7Fh
ret
;
;
;
execute: ;execute command string @ [BX]
;<BX> points to length,
;followed by Command byte
;followed by length-1 parameter bytes
;
mov lastcom,BX ;remember what it was
retry: ;retry if not ready drive
call sendcom ;execute the command
;now, let's see what type
;of status poll was necessary
;for that command type . . .
mov BX,lastcom ;point to command string
mov AL,1[BX] ;get command op code
and AL,3fh ;drop drive code bits
mov CX,0800h ;mask if it will be "int req"
cmp AL,2ch ;see if interrupt type
jb execpoll
mov CX,8080h ;else we use "not command busy"
and AL,0fh ;unless . . .
cmp AL,0ch ;there isn't
mov AL,0
ja return ;any result at all
;
execpoll: ;poll for bit in b, toggled with c
in AL,FDCSTAT
and AL,CH
xor AL,CL ! JZ execpoll
;
in AL,fdcrslt ;get result register
and AL,1eh ;look only at result type & code
jz return ;zero means it was a good operation
;
cmp al,10h
jne fatal ;if other than "Not Ready", stop
;
mov bx,offset rdstat
call sendcom ;perform read status command
rd_poll:
in al,fdc_stat
test al,80h ;wait for command not busy
jnz rd_poll
mov bx,last_com ;recover last attempted command
jmp retry ;and try it over again
;
fatal: ; fatal error
mov ah,0
mov bx,ax ;make 16 bits
mov bx,errtbl[BX]
; print appropriate error message
call pmsg
call conin ;wait for key strike
pop ax ;discard unused item
jmp restart ;then start all over
;
return:
RET ;return from EXECUTE
;
setupdma:
mov AL,04h
out dmacmode,AL ;enable dmac
mov al,0
out dmaccont,AL ;set first (dummy) byte to
mov AL,40h
out dmaccont,AL ;force read data mode
mov AX,ES
out fdcsegment,AL
mov AL,AH
out fdcsegment,AL
mov AX,BX
out dmacadr,AL
mov AL,AH
out dmacadr,AL
RET
;
;
;
sendcom: ;routine to send a command string to SBC204
in AL,fdcstat
and AL,80h
jnz sendcom ;insure command not busy
mov CL,[BX] ;get count
inc BX
mov al,[BX] ;point to and fetch command byte
out fdccom,AL ;send command
parmloop:
dec CL
jz return ;see if any (more) parameters
inc BX ;point to next parameter
parmpoll:
in AL,fdcstat
and AL,20h
jnz parmpoll ;loop until parm not full
mov AL,[BX]
out fdcparm,AL ;output next parameter
jmp parmloop ;go see about another
;
;
; Image of data to be moved to RAM
;
drombegin equ offset $
;
clastcom dw 0000h ;last command
;
creadstring db 3 ;length
db 52h ;read function code for drive 0
db 0 ;track #
db 1 ;sector #
;
creadtrk0 db 4
db 53h ;read multiple
db 0 ;track 0
db 2 ;sectors 2
db 25 ;through 26
;
creadtrk1 db 4
db 53h
db 1 ;track 1
db 1 ;sectors 1
db 26 ;through 26
;
chome0 db 2,69h,0
crdstat0 db 1,6ch
cspecs1 db 5,35h,0dh
db 08h,08h,0e9h
cspecs2 db 5,35h,10h
db 255,255,255
cspecs3 db 5,35h,18h
db 255,255,255
;
cerrtbl dw offset er0
dw offset er1
dw offset er2
dw offset er3
dw offset er4
dw offset er5
dw offset er6
dw offset er7
dw offset er8
dw offset er9
dw offset erA
dw offset erB
dw offset erC
dw offset erD
dw offset erE
dw offset erF
;
Cer0 db cr,lf,'Null Error ??',0
Cer1 equ cer0
Cer2 equ cer0
Cer3 equ cer0
Cer4 db cr,lf,'Clock Error',0
Cer5 db cr,lf,'Late DMA',0
Cer6 db cr,lf,'ID CRC Error',0
Cer7 db cr,lf,'Data CRC Error',0
Cer8 db cr,lf,'Drive Not Ready',0
Cer9 db cr,lf,'Write Protect',0
CerA db cr,lf,'Trk 00 Not Found',0
CerB db cr,lf,'Write Fault',0
CerC db cr,lf,'Sector Not Found',0
CerD equ cer0
CerE equ cer0
CerF equ cer0
;
dromend equ offset $
;
data_length equ dromend-drombegin
;
; reserve space in RAM for data area
; (no hex records generated here)
;
dseg 0
org 0200h
;
ram_start equ $
lastcom rw 1 ;last command
read0 rb 4 ;read track 0 sector 1
read1 rb 5 ;read T0 S2-26
read2 rb 5 ;read T1 S1-26
home rb 3 ;home drive 0
rdstat rb 2 ;read status
specs1 rb 6
specs2 rb 6
specs3 rb 6
errtbl rw 16
er0 rb length cer0 ;16
er1 equ er0
er2 equ er0
er3 equ er0
er4 rb length cer4 ;14
er5 rb length cer5 ;11
er6 rb length cer6 ;15
er7 rb length cer7 ;17
er8 rb length cer8 ;18
er9 rb length cer9 ;16
erA rb length cerA ;19
erB rb length cerB ;14
erC rb length cerC ;19
erD equ er0
erE equ er0
erF equ er0
;
leap_offset rw 1
leap_segment rw 1
;
;
rw 32 ;local stack
stack_offset equ offset $;stack from here down
;
; T0 S1 read in here
sector1 equ offset $
;
Ty rb 1
Len rw 1
Abs rw 1 ;ABS is all we care about
Min rw 1
Max rw 1
end


View File

@@ -0,0 +1,6 @@
disks 3
diskdef 0,1,26,6,1024,243,64,64,2
diskdef 1,0
diskdef 2,1,26,,1024,127,64,0,0
endef


View File

@@ -0,0 +1,96 @@
; DISKS 3
dpbase equ $ ;Base of Disk Parameter Blocks
dpe0 dw xlt0,0000h ;Translate Table
dw 0000h,0000h ;Scratch Area
dw dirbuf,dpb0 ;Dir Buff, Parm Block
dw csv0,alv0 ;Check, Alloc Vectors
dpe1 dw xlt1,0000h ;Translate Table
dw 0000h,0000h ;Scratch Area
dw dirbuf,dpb1 ;Dir Buff, Parm Block
dw csv1,alv1 ;Check, Alloc Vectors
dpe2 dw xlt2,0000h ;Translate Table
dw 0000h,0000h ;Scratch Area
dw dirbuf,dpb2 ;Dir Buff, Parm Block
dw csv2,alv2 ;Check, Alloc Vectors
; DISKDEF 0,1,26,6,1024,243,64,64,2
;
; 1944: 128 Byte Record Capacity
; 243: Kilobyte Drive Capacity
; 64: 32 Byte Directory Entries
; 64: Checked Directory Entries
; 128: Records / Extent
; 8: Records / Block
; 26: Sectors / Track
; 2: Reserved Tracks
; 6: Sector Skew Factor
;
dpb0 equ offset $ ;Disk Parameter Block
dw 26 ;Sectors Per Track
db 3 ;Block Shift
db 7 ;Block Mask
db 0 ;Extnt Mask
dw 242 ;Disk Size - 1
dw 63 ;Directory Max
db 192 ;Alloc0
db 0 ;Alloc1
dw 16 ;Check Size
dw 2 ;Offset
xlt0 equ offset $ ;Translate Table
db 1,7,13,19
db 25,5,11,17
db 23,3,9,15
db 21,2,8,14
db 20,26,6,12
db 18,24,4,10
db 16,22
als0 equ 31 ;Allocation Vector Size
css0 equ 16 ;Check Vector Size
; DISKDEF 1,0
;
; Disk 1 is the same as Disk 0
;
dpb1 equ dpb0 ;Equivalent Parameters
als1 equ als0 ;Same Allocation Vector Size
css1 equ css0 ;Same Checksum Vector Size
xlt1 equ xlt0 ;Same Translate Table
; DISKDEF 2,1,26,,1024,127,64,0,0
;
; 1016: 128 Byte Record Capacity
; 127: Kilobyte Drive Capacity
; 64: 32 Byte Directory Entries
; 0: Checked Directory Entries
; 128: Records / Extent
; 8: Records / Block
; 26: Sectors / Track
; 0: Reserved Tracks
;
dpb2 equ offset $ ;Disk Parameter Block
dw 26 ;Sectors Per Track
db 3 ;Block Shift
db 7 ;Block Mask
db 0 ;Extnt Mask
dw 126 ;Disk Size - 1
dw 63 ;Directory Max
db 192 ;Alloc0
db 0 ;Alloc1
dw 0 ;Check Size
dw 0 ;Offset
xlt2 equ 0 ;No Translate Table
als2 equ 16 ;Allocation Vector Size
css2 equ 0 ;Check Vector Size
; ENDEF
;
; Uninitialized Scratch Memory Follows:
;
begdat equ offset $ ;Start of Scratch Area
dirbuf rs 128 ;Directory Buffer
alv0 rs als0 ;Alloc Vector
csv0 rs css0 ;Check Vector
alv1 rs als1 ;Alloc Vector
csv1 rs css1 ;Check Vector
alv2 rs als2 ;Alloc Vector
csv2 rs css2 ;Check Vector
enddat equ offset $ ;End of Scratch Area
datsiz equ offset $-begdat ;Size of Scratch Area
db 0 ;Marks End of Module


View File

@@ -0,0 +1,34 @@
;*****************************************************
;*
;* System Data Area
;*
;*****************************************************
org 00h
supmod rw 2
org 038h
dispatcher equ (offset $)
org 040h
mpmseg rw 1
org 044h
endseg rw 1
org 068h
rlr rw 1 ;Ready List Root
org 072h
thrdrt rw 1 ;Process Thread Root
qlr rw 1 ;Queue List Root
org 078h
version rw 1 ;addr. version in SUP
vernum rw 1 ;MPM-86 w/BDOS v3.0
mpmvernum rw 1 ;MPM-86 Version 2.0
tod rb 5 ;Time of Day Structure
org 01000h


View File

@@ -0,0 +1,26 @@
;*****************************************************
;*
;* SYSTEM DEFINITIONS
;*
;*****************************************************
true equ 0ffffh ; value of TRUE
false equ 0 ; value of FALSE
unknown equ 0 ; value to be filled in
dskrecl equ 128 ; log. disk record len
fcblen equ 32 ; size of file control block
pnamsiz equ 8 ; size of process name
qnamsiz equ pnamsiz ; size of queue name
fnamsiz equ pnamsiz ; size of file name
ftypsiz equ 3 ; size of file type
mpmint equ 224 ; int vec for mpm ent.
debugint equ mpmint+1 ; int vec for debuggers
ulen equ 0100h ; size of uda
pdlen equ 030h ; size of Process Descriptor
todlen equ 5 ; size of Time of Day struct
flag_tick equ 1 ; flag 0 = tick flag
flag_sec equ 2 ; flag 1 = second flag
flag_min equ 3 ; flag 2 = minute flag
ldtabsiz equ 0aah ; ldtablen=11, 10 entries


File diff suppressed because it is too large Load Diff