home *** CD-ROM | disk | FTP | other *** search
- Comment "
-
- Resident program to report intermittant disk I/O errors, before DOS
- reports them after trying 5 times. Error handling remains with DOS.
-
- Errors reported:
- No Response No response from disk
- Failed Seek Could not locate data
- NEC Error Controller error
- Bad CRC Seen Circular Redundancy Check error
- DMA overrun CPU too busy to allow data on bus (unusual)
- Impos Sector NEC tried to read non existent sector
- No Addr Mark No address mark on disk
- W Protected Write protected disk
- Err Unknown Severe problem; NEC does not know what happened
-
- Note: some copy protected disks will show disk errors, which are part of
- the scheme.
-
- Author Steve Holzner, as published in PC Magazine Vol. 4 No. 12, p. 263.
-
- To produce a .com file
- [m]asm dskwatch
- link dskwatch (Ignore missing stack segment warning.)
- exe2bin dskwatch.exe dskwatch.com
-
- Program may be invoked in autoexec.bat for a permanent watchdog. Once
- started, can only be removed by re-booting.
- "
-
- INTERRUPTS SEGMENT AT 0H ;This is where the disk interrupt
- ORG 13H*4 ;holds the address of its service routine
- DISK_INT LABEL DWORD
- INTERRUPTS ENDS
-
- SCREEN SEGMENT AT 0B000H ;A dummy segment to use as the Extra Segment
- SCREEN ENDS ; so we can write to the screen
-
- CODE_SEG SEGMENT
- ASSUME CS:CODE_SEG
- ORG 100H ;ORG = 100H to make this into a .COM file
- FIRST: JMP LOAD_WATCH ;First time through jump to initialize routine
-
- MSG_PART_1 DB 'Disk Error: ' ;Here are the error messages
- MSG_PART_2 DB 'No response Failed Seek NEC Error '
- DB 'Bad CRC SeenDMA Overrun Impos Sector'
- DB 'No Addr MarkW. ProtectedErr Unknown '
- FIRST_POSITION DW ? ;Position of 1st char on screen
- FLAGS DW ?
- SCREEN_SEG_OFFSET DW 0 ;0 for mono, 8000H for graphics
- OLD_DISK_INT DD ? ;Location of old disk interrupt
- RET_ADDR LABEL DWORD ;Used in fooling around with
- RET_ADDR_WORD DW 2 DUP(?) ; stack.
-
- DISK_WATCH PROC FAR ;The Disk interrupt will now come here
- ASSUME CS:CODE_SEG
- PUSHF ;First, call old disk interrupt
- CALL OLD_DISK_INT
- PUSHF ;Save the flags in memory location "FLAGS"
- POP FLAGS ; (cunning name)
- JC ERROR ;If there was an error, carry flag will have
- JMP FIN ; been set by Disk interrupt
- ERROR: PUSH AX ;AH has the status of the error
- PUSH CX ;Push all used registers for politeness
- PUSH DX
- PUSH DI
- PUSH SI
- PUSH ES
- LEA SI,MSG_PART_1 ;Always print "Disk Error: " part.
- ASSUME ES:SCREEN ;Use screen as extra segment
- MOV DX,SCREEN
- MOV ES,DX
- MOV DI,SCREEN_SEG_OFFSET ;DI will be pointer to screen position
- ADD DI,FIRST_POSITION ;Add to point to desired area on screen
- CALL WRITE_TO_SCREEN ;This writes 12 characters from [SI] to [DI]
- MOV DH,80H ;Initialize for later comparisons
- MOV CX,7 ;Loop seven times
- E_LOOP: CMP AH,DH ;Are error code and DH the same?
- JE E_FOUND ;If yes, Error has been found
- ADD SI,12 ;Point to next error message
- SHR DH,1 ;Divide DH by 2
- LOOP E_LOOP ;Keep going until matched DH=0
- CMP AH,3 ;Error code not even number; 3 perhaps?
- JE E_FOUND ;If yes, have found the error
- ADD SI,12 ;Err unknown; unknown error returned
- E_FOUND:CALL WRITE_TO_SCREEN ;Write the error message to screen
- POP ES ;Having done Pushes, here are the Pops
- POP SI
- POP DI
- POP DX
- POP CX
- POP AX
- FIN: POP RET_ADDR_WORD ;Fooling with the stack. We want to
- POP RET_ADDR_WORD[2] ;preserve the flags but the old flags
- ADD SP,2 ;are still on the stack. First remove
- PUSH FLAGS ;return address, then flags. Fill flags
- POPF ;from "FLAGS", return to correct addr.
- JMP RET_ADDR
- DISK_WATCH ENDP
-
- WRITE_TO_SCREEN PROC NEAR ;Puts 12 characters on the screen
- MOV CX,12 ;Loop 12 times
- W_LOOP: MOVS ES:BYTE PTR[DI],CS:[SI] ;Move to the screen
- MOV AL,7 ;Move screen attribute into screen buffer
- MOV ES:[DI],AL
- INC DI ;Point to next byte in screenbuffer
- LOOP W_LOOP ;Keep going until done
- RET ;Exeunt
- WRITE_TO_SCREEN ENDP
-
- LOAD_WATCH PROC NEAR ;This procedure initializes everything
- ASSUME DS:INTERRUPTS ;The data segment will be the Interrupt area
- MOV AX,INTERRUPTS
- MOV DS,AX
-
- MOV AX,DISK_INT ;Get the old interrupt service routine
- MOV OLD_DISK_INT,AX ;address and put it into our location
- MOV AX,DISK_INT[2] ;OLD_DISK_INT so we can call it.
- MOV OLD_DISK_INT[2],AX
-
- MOV DISK_INT,OFFSET DISK_WATCH ;Now load the address of Dsk Watch
- MOV DISK_INT[2],CS ; routine into the Disk interrupt
-
- MOV AH,15 ;Ask for service 15 of INT 10H
- INT 10H ;This tells us how display is set
- SUB AH,25 ;Move to twenty-five placed before edge
- SHL AH,1 ;Mult by two (char & attribute bytes)
- MOV BYTE PTR FIRST_POSITION,AH ;Set screen cursor
- TEST AL,4 ;Is it a monochrome display?
- JNZ EXIT ;Yes - jump out
- MOV SCREEN_SEG_OFFSET,8000H ;No - set up for graphics display
- EXIT: MOV DX,OFFSET LOAD_WATCH ;Set up everything but this program to
- INT 27H ;stay resident and attach itself to DOS
- LOAD_WATCH ENDP
- CODE_SEG ENDS
- END FIRST ;END "FIRST" so 8088 will go to FIRST first
-