Category : HD Utilities
Archive   : ERRMON.ZIP
Filename : ERRMON.ASM

 
Output of file : ERRMON.ASM contained in archive : ERRMON.ZIP
name ERRMON ;version 1.1

page 60,132

comment *
monitors INT 13 disk i/o and reports any errors encountered;
version 1.1 also reports the offending command
and the drive, cylinder, head, sector and number of sectors requested

AT disk change error is ignored
*

.radix 16

attribute equ 0f ;video attribute for error message
line equ 24d ;line for error message, 0-24

cr equ 0dh
lf equ 0a

com_org equ 100 ;ORG for com files

; error codes from IBM bios listings
sense_fail equ 0ff ;not implemented on AT
no_error equ 0e0 ;not implemented on PC, XT
write_fault equ 0cc ;not implemented on PC, XT
undef_err equ 0bbh
not_rdy equ 0aa ;not implemented on PC, XT
time_out equ 80
bad_seek equ 40
bad_cntlr equ 20
data_corrected equ 11
bad_eec equ 10
bad_track equ 0bh ;not implemented on AT
bad_sector equ 0a ;not implemented on PC, XT
dma_boundry equ 9
bad_dma equ 8
init_fail equ 7
media_change equ 6 ;ignore this AT error
bad_reset equ 5
record_not_fnd equ 4
write_protect equ 3
bad_addr_mark equ 2
bad_cmd equ 1

popff macro ;simulate POPF to avoid any '286 problems
jmp short $+3 ;jump around IRET
iret ;pops IP, CS, FLAGS
push cs ;CS to stack
call cs:$-2 ;IP to stack (cs: avoids masm error)
endm

entry struc ;map each entry in the error table
err_nmbr db ? ;error code number for this entry
msg_offset dw ? ;offset to message text for this error
msg_len db ? ;length of the message text
entry ends

stack struc ;stack structure
cur_loc dw ? ;save cursor location
reg_bp dw ?
reg_di dw ?
reg_si dw ?
reg_dx dw ? ;cx and dx hold the
reg_cx dw ? ; drive, cylinder, head, sector info
reg_bx dw ?
reg_ax dw ?
reg_f dw ? ;cy if error, code in ah
stack ends

errmon segment para public 'CODE'
assume cs:errmon
org com_org

start: jmp init ;go install

err_tbl db sense_fail
dw msg_ff
db len_ff
db no_error
dw msg_e0
db len_e0
db write_fault
dw msg_cc
db len_cc
ude db undef_err
dw msg_bb
db len_bb
db not_rdy
dw msg_aa
db len_aa
db time_out
dw msg_80
db len_80
db bad_seek
dw msg_40
db len_40
db bad_cntlr
dw msg_20
db len_20
db data_corrected
dw msg_11
db len_11
db bad_eec
dw msg_10
db len_10
db bad_track
dw msg_0b
db len_0b
db bad_sector
dw msg_0a
db len_0a
db dma_boundry
dw msg_09
db len_09
db bad_dma
dw msg_08
db len_08
db init_fail
dw msg_07
db len_07
; db media_change ;ignore this AT error
; dw msg_06
; db len_06
db bad_reset
dw msg_05
db len_05
db record_not_fnd
dw msg_04
db len_04
db write_protect
dw msg_03
db len_03
db bad_addr_mark
dw msg_02
db len_02
db bad_cmd
dw msg_01
db len_01
nmbr_errs equ ($-err_tbl)/size entry

msg_ff db 'Sense failure'
len_ff equ $-msg_ff
msg_e0 db 'Status error'
len_e0 equ $-msg_e0
msg_cc db 'Write fault'
len_cc equ $-msg_cc
msg_bb db 'Undefined error'
len_bb equ $-msg_bb
msg_aa db 'Drive not ready'
len_aa equ $-msg_aa
msg_80 db 'No response'
len_80 equ $-msg_80
msg_40 db 'Seek failure'
len_40 equ $-msg_40
msg_20 db 'Controller failure'
len_20 equ $-msg_20
msg_11 db 'EEC error corrected'
len_11 equ $-msg_11
msg_10 db 'Bad CRC/EEC on read'
len_10 equ $-msg_10
msg_0b db 'Bad track'
len_0b equ $-msg_0b
msg_0a db 'Bad sector'
len_0a equ $-msg_0a
msg_09 db 'DMA boundry crossed'
len_09 equ $-msg_09
msg_08 db 'DMA overrun'
len_08 equ $-msg_08
msg_07 db 'Drive init failure'
len_07 equ $-msg_07
;msg_06 db 'Disk changed' ;ignore this AT error
;len_06 equ $-msg_06
msg_05 db 'Drive reset failure'
len_05 equ $-msg_05
msg_04 db 'Sector not found'
len_04 equ $-msg_04
msg_03 db 'Disk write protected'
len_03 equ $-msg_03
msg_02 db 'DAM not found'
len_02 equ $-msg_02
msg_01 db 'Bad drive or command'
len_01 equ $-msg_01

msg_0 db ' ' ;display location of error sector
cmd db 2 dup (0)
db 'D'
drive db 2 dup (0)
db 'C'
cyl db 4 dup (0)
db 'H'
head db 2 dup (0)
db 'S'
sector db 2 dup (0)
db 'N'
number db 2 dup (0)
len_0 equ $-msg_0

int13 label dword
sav_int13 dw 2 dup(0) ;previous INT 13 vector
sav_ax dw 0 ;save command, number sectors requested
sav_col db 0 ;save number of screen columns

; INT 13 enters here
error proc far
pushf ;real INT 13 expects flags on stack
mov cs:[sav_ax],ax ;save command, number of sectors
call cs:[int13] ;do the real INT 13
jc chk_6 ;go if we have an error condition
ret 2 ;else discard caller's flags and return
chk_6: pushf ;save the flags from INT 13 for caller
cmp ah,media_change ;disk change error?
jne valid_err ;no
jmp exit ;yes, ignore it

; have a valid error, first save registers to be used
valid_err:
push ax ;ah = error code
push bx
push cx ;cl = sector and high bits of cylinder, ch = cylinder
push dx ;dl = drive, dh = head
push si
push di
push bp

; find the error in the table
mov di,offset err_tbl ;=> table
mov cx,nmbr_errs ;load number of errors in table
search: cmp ah,cs:[di].err_nmbr ;no SCAS, can't override ES register!

je found ;got a match
add di,size entry ;bump to next table entry
loop search
mov di,offset ude ;make it an undefined error

; find out where to print the report
found: mov ah,15d
int 10 ;get current mode, columns, page
mov cs:[sav_col],ah ;save for end of line check
sub ah,cs:[di].msg_len ;columns less msg_x
sub ah,len_0 ;less msg_0
jns len_ok ;if column >= 0
xor ah,ah ;else set column to 0
len_ok: mov al,ah ;starting column to al
mov ah,line ;row to ah
push ax ;save row, column to write to
mov bp,sp ;=> stack

; calculate the offending sector location
mov si,offset drive
mov ax,[bp].reg_dx
call cvt1 ;process drive number
mov si,offset head
mov al,ah
call cvt1 ;process head number
mov si,offset cyl
mov ax,[bp].reg_cx
mov bl,al ;save for later
and al,11000000b ;mask for high cyl bits
rol al,1
rol al,1 ;move to low nibble
call cvt1 ;process 1st part of cyl number
mov al,ah
call cvt1 ;process 2nd part of cyl number
mov si,offset sector
mov al,bl ;restore
and al,00111111b ;mask for sector number bits
call cvt1 ;process sector number
mov si,offset number
mov ax,cs:[sav_ax]
call cvt1 ;process number of sectors
mov si,offset cmd
mov al,ah
call cvt1 ;process command number

; write the report to the screen
mov ah,3
int 10 ;get current cursor position
xchg dx,[bp].cur_loc ;swap cursor positions
mov bl,attribute ;video attribute
mov cx,1 ;number characters to write
mov si,cs:[di].msg_offset ;=> msg_x
mov di,cs:[di].word ptr msg_len ;get len msg_x
and di,0000000011111111b ;need to clear high bits
call write ;write it
mov si,offset msg_0 ;=> msg_0
mov di,len_0 ;get len msg_0
call write ;write it
pop dx ;old cursor position
mov ah,2
int 10 ;restore cursor position

; now let caller do its thing with the error
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
exit: popff
ret 2 ;done, discard flags from caller
error endp

; convert hex byte in al to two ascii digits, store in si, si+1
cvt1 proc near
mov ch,al ;will need again
mov cl,4
shr al,cl ;high nibble to low
call cvt2 ;make it ascii and store
mov al,ch ;recover byte
and al,00001111b ;mask for low nibble
cvt2: add al,'0' ;make an ascii digit
cmp al,'9' ;need adjustment?
jbe no_adj ;nope
add al,7 ;adjust to A-F
no_adj: mov cs:[si],al ;stuff in msg_0
inc si ;bump pointer
ret
cvt1 endp

; write a defined length string to the screen
write proc near
cmp cs:[sav_col],dl ;end of line?
jbe no_wrt ;yes
mov ah,2
int 10 ;reset cursor position
inc dl ;bump column
mov al,cs:[si] ;get char to write
inc si ;bump pointer
mov ah,9
int 10 ;put it on screen
dec di ;decrement counter
jnz write ;if more to write
no_wrt: ret
write endp

pgm_len equ $-start+com_org ;rinky dink to get an absolute constant
remain equ pgm_len mod 10 gt 0 ;any remainder?
prot equ (pgm_len/10)-remain ;convert bytes to paragraphs, round

assume cs:errmon, ds:errmon, es:errmon, ss:errmon

id db 'ERRMON Version 1.1 - Copyright (C) 1985 by Robert J. Newton',cr,lf,'$'
dos_msg db 'ERRMON requires DOS 2.0 or greater',cr,lf,'$'

init proc near
mov ah,30
int 21
cmp al,2
jb bad_dos ;dos 2.x+ required
mov cx,es
mov ax,3513
int 21 ;fetch INT 13 vector
mov [sav_int13],bx
mov [sav_int13+2],es ;save in error proc
mov es,cx
mov dx,offset error ;=> new INT 13 routine
mov ax,2513
int 21 ;set INT 13 to error
mov dx,offset id ;=> msg
mov ah,9
int 21 ;show id
mov dx,prot ;paragraphs to protect
mov ax,3100
int 21 ;TSR, no error

bad_dos:
mov dx,offset dos_msg
mov ah,9
int 21 ;show bad news
mov ax,4cff
int 21 ;flag error at exit
init endp

errmon ends

end start


  3 Responses to “Category : HD Utilities
Archive   : ERRMON.ZIP
Filename : ERRMON.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/