home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
dskutl
/
scav31.arc
/
SCAV31.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-10-06
|
13KB
|
541 lines
title scavenge Copyright (c) T. Jennings 1983
;
;****************************************
;* *
;* SCAVENGE *
;* *
;* Mark bad blocks on MSDOS *
;* as allocated in the FAT. *
;* *
;* T. Jennings 5 June 82 *
;* created 15 Sept. 82 *
;* Modified 14 December 1984 *
;* by David Gwillim *
;* *
;* *
;****************************************
;
;See SCAV31.DOC for details on functioning, updates, etc. v3.01
;
;Reads all sectors in logical MSDOS blocks
;and marks the file allocation tables such
;that the blocks are permanently allocated
;where CHKDSK will not deallocate them.
;
;
;This version works on any 2.xx MSDOS or
;PCDOS, on any media type, fixed or removable.
;One (major) limitation: it will not map out
;blocks that are already allocated to a file;
;it will say "block used", but won't tell you
;which file it is in.
;
;If SCAVENGE finds any bad blocks, it will ask
;you whether or not you want the disk updated.
;You can safely run it just to see if the disk
;is OK.
;
;Enter 'Q' at any time to abort the run. v3.01
;MASM, LINK, then EXE2BIN this to make a COM
;file. It will not run as an EXE file. NOTE:
;LINK will give you a 'Warning: no STACK
;segment' error: ignore it.
;
;v3.01
; - Slight tweaking, reformatting.
; - v3.00 forced DS, SS to CS; unnecessary.
; - v3.00 had its own stack; unnecessary.
; - Removed some system functions, placing them inline.
; - Separated extensive documentation into separate file,
; SCAVENGE.DOC.
; - No functional changes.
; David Kirschbaum
; Toad Hall
; kirsch@braggvax.ARPA
CR equ 0dh
LF equ 0ah
PutStr macro ; v3.01
mov ah,9
int 21h
endm
;Beep procedure count values
;---------------------------
;To generate a given freqency note out of the speaker with the Beep procedure
;on the PC using Channel 2 of the 8253 timer, the channel 2 count register
;must be loaded with a value such that the 8253 input clock frequency
;(1.19318 MHz) divided by the count figure equals the audio frequency.
F176HZ equ 6779 ; 176 Hz count value
F352HZ equ 3390 ; 352 Hz count value
F704HZ equ 1695 ; 704 Hz count value
F1408HZ equ 847 ; 1408 Hz count value
page
Cseg segment para public 'code'
assume CS:Cseg, DS:Cseg, ES:Cseg, SS:Cseg
;
;MSDOS PSP stuff.
;
org 5ch
tfcb label byte
org 80h
tbuff label byte
org 100h
Scavenge proc near
jmp Start
;
;Disk parameters:
;
blkcnt dw 0 ;blocks this disk
blksize dw 0 ;sectors per block
secsize dw 0 ;phys. sector size
badcnt dw 0 ;# bad blocks found
newbad dw 0 ;new bad ones
block dw 0 ;current block
sector dw 0 ;sector to read
disk db 0 ;selected disk
curdsk db 0 ;current disk.
fatsec dw 0 ;1st FAT sector,
fatcnt dw 0 ;FAT sec count.
; dw 128 dup 0
;stack dw 0 ;what else
; db 16 dup('STACK ')
;stack equ $
Scavenge endp
page
;
;Say who we are, describe the disk we are
;about to fix, ask to continue or abort.
;
Start proc near
; cli ;Disable interrupts while we move stack
; mov sp,offset stack
; sti ;Re-enable interrupts
mov dx,offset signon
PutStr
mov bx,F176HZ ;Alert user audibly
call Beep
mov bx,F704HZ
call Beep
mov bx,F352HZ
call Beep
mov bx,F1408HZ
call Beep
mov ax,0C08H ;flush, char in with no echo v3.01
int 21h
or al,20h ;Make character lower case
cmp al,'q' ;Quit?
jne St0
mov dx,offset abort
jmp short Msg_Exit ;display, terminate v3.01
St0: call SetUp ;get disk stuff
jnc St1 ;went ok
Msg_Exit: ; v3.01
PutStr
int 20h ;error, terminate.
St1: call ListStat ;describe dsk
;
;Find all the bad blocks, if any, display them,
;ask if we should update the FAT. If so, write
;it out.
;
mov dx,offset crlf ;new line
PutStr
call FindBad ;map bad,
call ListBad ;list them,
cmp newbad,0 ;if new bad
je St2 ;blocks...
mov dx,offset updstr ;ask if we
PutStr ;should update
mov ax,0C08H ;flush, char in with no echo v3.01
int 21h
and al,5fh ;uppercase
mov dx,offset noupdte ;assume no update v3.01
cmp al,'Y'
jne St1B ;nope, no update
mov al,disk ;write out the
mov dx,fatsec ;FAT,
mov cx,fatcnt
mov bx,offset fatbuf
int 26h
pop ax ;pop flags after Int 26H
mov dx,offset update ;fall thru to v3.01
St1B: PutStr ;display msg v3.01
St2:
mov dl,curdsk ;reselect the original disk v3.01
mov ah,0eh ; v3.01
int 21h ; v3.01
int 20h ;terminate
signon db CR,LF,9,'*********************************************'
db CR,LF,9,'* DOS 2.xx Bad Sector Mapper - Version 3.01 *'
db CR,LF,9,'* Updated by David Gwillim 18 December 1984 *'
db CR,LF,9,'* Again by Toad Hall, 6 Oct 88 *'
db CR,LF,9,'* Original program by T. Jennings 5 June 83 *'
db CR,LF,9,'*********************************************'
db CR,LF,LF
db 'Type Q to abort at any time, any other key to continue ...'
db CR,LF,'$'
updstr db CR,LF,LF,'Want the disk updated? [y,n] $'
noupdte db CR,LF,LF,'FAT not updated',CR,LF,'$'
update db CR,LF,LF,'FAT updated'
crlf db CR,LF,'$' ;share this v3.01
Start endp
page
;
;Get the data on the specified disk. Return
;carry if no drive specified. Returns ES:DI
;pointing to the FAT for the selected drive.
;
SetUp proc near
mov ah,0dh ;reset disk system v3.01
int 21h
mov ah,19h ;get current disk v3.01
int 21h
mov curdsk,al ;save it,
mov al,tfcb ;make sure a
cmp al,0 ;new one spec'd
stc ;quit if none,
mov dx,offset strstr ;'Must specify disk drive' msg
jz gd1 ;exit
dec al ;make 0-N,
mov disk,al
mov dl,al ;select disk, v3.01
mov ah,0eh
int 21h
mov di,DS ;save our DS a sec v3.01
mov ah,1bh
int 21h
mov DS,di ;restore DS v3.01
mov blkcnt,dx ;save # blocks,
mov secsize,cx ;sector size,
xor ah,ah ;clear msb v3.01
mov blksize,ax ;secs/block.
mov di,DS ;save DS a sec v3.01
mov dl,disk ;now get the
inc dl ;drive 1=A, b=2
mov ah,32h ;FAT,
int 21h ;get the DPB,
mov cx,[bx+15] ;CX= sec count,
xor ch,ch ;clear msb v3.01
mov dx,[bx+6] ;DX= 1st sec,
mov DS,di ;restore DS v3.01
mov fatcnt,cx ;save both,
mov fatsec,dx
mov al,disk ;AL= drive #,
mov bx,offset fatbuf ;DS:BX= buffer
int 25h ;read the FAT,
pop ax ;pop flags after Int 25H
mov dx,offset bscstr ;return with msg
gd1: ret
strstr db CR,LF,'Must specify a disk drive.$'
bscstr db CR,LF,'Bad FAT sector: disk not useable.$'
SetUp endp
page
;
;Read the entire disk looking for bad blocks.
;When one is found, go mark it as an allocated
;bad block.
;
FindBad proc near
xor ax,ax ;get a handy 0 v3.01
mov block,ax ;1st block,
mov badcnt,ax ;none yet,
BlockLup:
call KbdChk ;QUIT char input from the keyboard?
jnc FB1A ;nope
mov dx,offset abort ;'Aborting program'
PutStr
ret
FB1A: mov dx,offset blkstr ;type 'block '
PutStr
mov bx,block ;block number,
call OutDec
call ReadBlk ;read a block,
jnc Fb3 ;if bad,
inc badcnt ;count it,
mov dx,offset badstr
PutStr ;type 'bad'
call MapOut ;mark bad,
mov dx,offset cntstr ;'Already used'
jc Fb2 ;error if can't
add newbad,cx ;count it,
mov dx,offset alrstr ;'Already marked'
jcxz Fb2 ;error if already marked
mov dx,offset mrkstr ;'mapped out'
mov bx,F704HZ ;Warn user audibly
call Beep
mov bx,F176HZ
call Beep
Fb2: PutStr
mov bx,F1408HZ ;Warn user audibly
call Beep
mov bx,F176HZ
call Beep
Fb3: inc block ;next block,
dec blkcnt ;another...
jnz BlockLup ;keep looking.
ret
blkstr db CR,'Block $'
badstr db ' bad,$'
alrstr db ' already marked.',CR,LF,'$'
mrkstr db ' mapped out.',LF,'$'
cntstr db " already used! I don't know which file.",LF,'$'
abort db ' ... Aborting program',CR,LF,LF,'$'
FindBad endp
page
;
;Mark the current block as bad in the FAT.
;Multiply the block number by 1.5 to find the
;block number, (actually *3, /2) and if not
;used, mark it bad. If used, report which file
;it's in. If it's already mapped as bad,
;return CX=0, else return CX=1.
;
MapOut proc near
mov bx,block ;block,
shl bx,1 ;first times 2,
add bx,block ;then add one to make times 3,
shr bx,1 ;now divide by 2,
mov ax,word ptr fatbuf[bx] ;get word,
;
;If carry is set, we want the high 12 bits in
;the word in AX, else the low 12 bits. Set CH
;as the shift count, DX as the mask.
;
mov ch,0 ;assume low,
mov dx,0fffh
jnc Mo1
mov ch,4 ;else high 12,
mov dl,0F0H ; v3.01
Mo1: and ax,dx ;mask it,
mov cl,ch
shr ax,cl ;shift it,
;
;AX is the block number; if it's anything
;but 000 or ff7, return with carry set,
;indicating that it's already used.
;
cmp ax,0ff7h ;if ff7,
je Mo2 ;already marked
or ax,ax ;if allocated v3.01
je Mo3
stc ;error!
Mo2: mov cx,0 ;none mapped,
ret
;
;Bad unused block. Mark as bad in the FAT.
;
Mo3: mov ax,0ff7h ;marker,
mov cl,ch
shl ax,cl ;shift it,
or word ptr fatbuf[bx],ax ;mark it.
mov cx,1 ;1 mapped,
ret
MapOut endp
page
;
;Read one block, return carry set if read
;error. Leave the useless data in the buffer
;following the end of this program.
;
ReadBlk proc near
mov ax,block ;find start
mov cx,blksize ;sector,
mul cx ;CX= count,
mov dx,ax ;DX= sector,
mov al,disk
mov bx,offset blkbuf ;our buffer,
int 25h ;read sectors,
pop dx ;pop flags after Int 25H
ret
ReadBlk endp
page
;
;List the general info on the disk, like
;number of blocks, block size, FAT size & location, etc.
;
ListStat proc near
mov al,disk ;disk nr v3.01
add al,'A' ;asciify v3.01
mov st2str,al ;stuff in string v3.01
mov dx,offset st1str ;'Disk %: Total of ' v3.01
PutStr ;display str v3.01
mov bx,blkcnt
call OutDec1 ;we know >9 v3.01
mov dx,offset st3str ;'Data blocks'
PutStr
mov ax,512
mul blksize
mov bx,ax
call OutDec1 ;we know >9 v3.01
mov dx,offset st4str ;' bytes each'
PutStr
mov bx,fatcnt
call OutDec ;probably <10 v3.01
mov dx,offset st5str ;' FAT sectors, first ...'
PutStr
mov bx,fatsec
call OutDec ;display first FAT sector
mov dx,offset crlf ;CR,LF v3.01
PutStr
ret
;Disk A: Total of 12345 data blocks 1024 bytes each.
st1str db CR,LF,'Disk ' ; v3.01
st2str db '%: Total of $' ; v3.01
st3str db ' data blocks $'
st4str db ' bytes each.',CR,LF,'$'
st5str db ' FAT sectors, first FAT sector is logical sector $'
ListStat endp
;
;List out the bad things about this disk.
;
ListBad proc near
mov dx,offset bd1str ;'Total of '
PutStr
mov bx,badcnt
call OutDec
mov dx,offset bd2str ;' bad blocks' v3.01
PutStr
mov dx,offset crlf ;assume no bad blocks v3.01
cmp badcnt,0 ;no bad blocks yet? v3.01
jz NoBad ;nope, display no more v3.01
mov dx,offset bd3str ;', found ' v3.01
PutStr ; v3.01
mov bx,newbad
call OutDec
mov dx,offset bd4str ;' more this pass.'
NoBad: PutStr ; v3.01
ret
;Total of 12345 bad blocks, found 12234 more this pass.
bd1str db CR,'Total of $' ;note no linefeed.
bd2str db ' bad blocks$'
bd3str db ', found $'
bd4str db ' more this pass.',CR,LF,'$'
ListBad endp
page
;
;Type BX in decimal, suppressing leading zeros.
;
OutDec proc near
cmp bx,9 ;single digit? v3.01
ja OutDec1 ;nope v3.01
mov dl,bl ;get single digit v3.01
add dl,'0' ;asciify v3.01
mov ah,2 ;display char
int 21h ; v3.01
ret ; v3.01
OutDec1:
xor cl,cl ;0 suppress flag v3.01
mov dx,10000
call RsDiv
mov dx,1000
call RsDiv
mov dx,100
call RsDiv
mov dx,10
call RsDiv
mov ch,bl
jmp short Odf
RsDiv: mov ch,-1 ;iteration -1,
Rs1: inc ch ;count,
sub bx,dx ;subtract,
jnc Rs1 ;til underflow,
add bx,dx ;adjust back,
or ch,ch ;if non-zero v3.01
jne Odf ;type it,
test cl,1 ;don't type 0's
jz OdX ;if leading v3.01
Odf: push dx
mov dl,ch
add dl,'0' ;ASCII,
mov ah,2 ;display char
int 21h
pop dx
mov cl,1 ;no suppress,
OdX: ret ; v3.01
OutDec endp
;
KbdChk proc near
mov ah,0Bh ;Check keyboard for character waiting
int 21h
or al,al ;anything there? v3.01
jz Chk1 ;nope v3.01
mov ah,8 ;Character waiting - see what it is
int 21h
or al,20h ;Make it lower case
cmp al,'q' ;Time to QUIT?
je Chk2 ;Yes
Chk1: clc ;No - Make sure carry flag is cleared
ret
Chk2: stc ;Yep - set carry flag
ret
KbdChk endp
;
; BEEP - entry conditions BX register contains count figure for frequency
; to be generated.
;
Beep proc near
mov al,0b6h ; Channel 2, LSB then MSB, Square Wave, Binary
out 43h,al ; Program 8253 command register
mov ax,bx ; Get the frequency to be generated
out 42h,al ; Load Channel 2 count register LSB
mov al,ah
out 42h,al ; Load Channel 2 count register MSB
in al,61h ; Read settings from 8255 PPI I/O Port "PB"
mov ah,al ; Save original settings in AH
or al,3 ; Enable Timer Channel 2 & Speaker data
out 61h,al ; program the 8255 with new setting-speaker on
sub cx,cx ; Sneaky way to put 0FFFFH into CX when
wait2: loop wait2 ; LOOP is first executed
mov al,ah ; Get original 8255 Port "PB" settings
out 61h,al ; Reset port to original values-speaker off
ret
Beep endp
blkbuf equ $ ;cluster buffer
fatbuf equ $+16384 ;FAT buffer.
Cseg ENDS
END Scavenge