mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-22 16:04:18 +00:00
349 lines
10 KiB
Plaintext
349 lines
10 KiB
Plaintext
;*****************************************************
|
||
;* *
|
||
;* 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 CP/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 ;write to allocated
|
||
wrdir equ 1 ;write to directory
|
||
wrual equ 2 ;write to unallocated
|
||
;
|
||
;*****************************************************
|
||
;* *
|
||
;* 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
|
||
cmp cl,wrual ;write unallocated?
|
||
jnz 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
|
||
cmp wrtype,wrdir ;write type to directory?
|
||
mov al,erflag ;in case of errors
|
||
jnz 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
|
||
|