mirror of
https://github.com/ISpillMyDrink/OpenSuperClone.git
synced 2026-05-04 14:00:54 +00:00
548 lines
14 KiB
Plaintext
548 lines
14 KiB
Plaintext
seti $printhelp = $printhelp
|
|
seti $help = $help
|
|
if $help != 0
|
|
echo 'This will scan the drive using the read verify command.'
|
|
echo 'Reads are done in blocks (clusters) of 256 sectors.'
|
|
echo 'This means that all warnings and errors show the position'
|
|
echo ' of the first sector of the block, NOT the actual problem sector.'
|
|
echo 'If the required variables below are not set on the command line,'
|
|
echo ' then you will be propted to enter them.'
|
|
echo 'This requires the number variable startsector to be set.'
|
|
echo 'This requires the number variable endsector to be set.'
|
|
echo 'If endsector is set to 0, it will default to the last addressable sector.'
|
|
echo 'This uses the identify device command to determine the last sector.'
|
|
echo 'This requires the number variable threshold to be set.'
|
|
echo 'Threshold is time in milliseconds.'
|
|
echo 'If a read exceeds the threshold, a warning will be given.'
|
|
echo 'If threshold is set to 0, it will default to 150ms.'
|
|
echo 'This requires the number variable softtimeout to be set.'
|
|
echo 'Softtimeout is the time in milliseconds to wait before giving up on a command.'
|
|
echo 'If softtimeout is set to 0, it will default to 10000ms.'
|
|
echo 'This requires the number variable hardtimeout to be set.'
|
|
echo 'Hardtimeout is the time to wait after a softreset before doing a hardreset.'
|
|
echo 'If hardtimeout is set to 0, it will default to 10000ms.'
|
|
echo 'This requires the string variable logfile to be set.'
|
|
echo 'Logfile will capture all the warnings and errors.'
|
|
echo 'This requires the string variable rateslog to be set.'
|
|
echo 'Rateslog will capture timing info that can be ploted.'
|
|
echo 'Rateslog captures the low, high, and average over 256 block reads.'
|
|
echo 'If logfile and/or ratesfile are blank no log will be produced.'
|
|
|
|
echo 'Example using defaults:'
|
|
echo 'hddsupertool -t /dev/sda -f ata_scan_device threshold=0 softtimeout=0 startsector=0 endsector=0 logfile=="" rateslog==""'
|
|
if $printhelp = 1
|
|
exit 0
|
|
endif
|
|
echo 'Hit ENTER to continue...'
|
|
userinput $choicestring
|
|
previousscript
|
|
endif
|
|
|
|
include good_subroutines
|
|
|
|
sets $null = ""
|
|
seti $using_menu = $using_menu
|
|
|
|
|
|
seti $ask = 0
|
|
while 1 = 1
|
|
variablecheck $startsector
|
|
if $error_level < 16
|
|
seti $ask = 1
|
|
elseif $using_menu = 1
|
|
seti $ask = 1
|
|
endif
|
|
if $ask = 1
|
|
echo "Enter start sector, or leave blank for first:"
|
|
userinput $choicestring
|
|
if $choicestring != $null
|
|
seti $startsector = $choicestring 0
|
|
break
|
|
else
|
|
seti $startsector = 0
|
|
break
|
|
endif
|
|
else
|
|
break
|
|
endif
|
|
done
|
|
|
|
seti $ask = 0
|
|
while 1 = 1
|
|
variablecheck $endsector
|
|
if $error_level < 16
|
|
seti $ask = 1
|
|
elseif $using_menu = 1
|
|
seti $ask = 1
|
|
endif
|
|
if $ask = 1
|
|
echo "Enter end sector, or leave blank for last:"
|
|
userinput $choicestring
|
|
if $choicestring != $null
|
|
seti $endsector = $choicestring 0
|
|
break
|
|
else
|
|
seti $endsector = 0
|
|
break
|
|
endif
|
|
else
|
|
break
|
|
endif
|
|
done
|
|
|
|
seti $ask = 0
|
|
while 1 = 1
|
|
variablecheck $threshold
|
|
if $error_level < 16
|
|
seti $ask = 1
|
|
elseif $using_menu = 1
|
|
seti $ask = 1
|
|
endif
|
|
if $ask = 1
|
|
echo "Enter warning threshold in ms, or leave blank for default(150):"
|
|
userinput $choicestring
|
|
if $choicestring != $null
|
|
seti $threshold = $choicestring 0
|
|
break
|
|
else
|
|
seti $threshold = 150
|
|
break
|
|
endif
|
|
else
|
|
break
|
|
endif
|
|
done
|
|
if $threshold = 0
|
|
seti $threshold = 150
|
|
endif
|
|
seti $threshold = $threshold * 1000
|
|
|
|
seti $ask = 0
|
|
while 1 = 1
|
|
variablecheck $softtimeout
|
|
if $error_level < 16
|
|
seti $ask = 1
|
|
elseif $using_menu = 1
|
|
seti $ask = 1
|
|
endif
|
|
if $ask = 1
|
|
echo "Enter softtimeout in ms, or leave blank for default(10000ms):"
|
|
userinput $choicestring
|
|
if $choicestring != $null
|
|
seti $softtimeout = $choicestring 0
|
|
break
|
|
else
|
|
seti $softtimeout = 10000
|
|
break
|
|
endif
|
|
else
|
|
break
|
|
endif
|
|
done
|
|
if $softtimeout = 0
|
|
seti $softtimeout = 10000
|
|
endif
|
|
seti $softtimeout = $softtimeout * 1000
|
|
softtimeout $softtimeout
|
|
|
|
seti $ask = 0
|
|
while 1 = 1
|
|
variablecheck $hardtimeout
|
|
if $error_level < 16
|
|
seti $ask = 1
|
|
elseif $using_menu = 1
|
|
seti $ask = 1
|
|
endif
|
|
if $ask = 1
|
|
echo "Enter hardtimeout in ms, or leave blank for default(10000ms):"
|
|
userinput $choicestring
|
|
if $choicestring != $null
|
|
seti $hardtimeout = $choicestring 0
|
|
break
|
|
else
|
|
seti $hardtimeout = 10000
|
|
break
|
|
endif
|
|
else
|
|
break
|
|
endif
|
|
done
|
|
if $hardtimeout = 0
|
|
seti $hardtimeout = 10000
|
|
endif
|
|
seti $hardtimeout = $hardtimeout * 1000
|
|
hardtimeout $hardtimeout
|
|
|
|
seti $ask = 0
|
|
variablecheck $logfile
|
|
if $error_level < 16
|
|
seti $ask = 1
|
|
elseif $using_menu = 1
|
|
seti $ask = 1
|
|
endif
|
|
if $ask = 1
|
|
echo "Enter logfile name, or leave blank for no log:"
|
|
userinput $choicestring
|
|
sets $logfile = $choicestring
|
|
endif
|
|
|
|
seti $ask = 0
|
|
variablecheck $rateslog
|
|
if $error_level < 16
|
|
seti $ask = 1
|
|
elseif $using_menu = 1
|
|
seti $ask = 1
|
|
endif
|
|
if $ask = 1
|
|
echo "Enter optional rates logfile name, or leave blank for no log:"
|
|
userinput $choicestring
|
|
sets $rateslog = $choicestring
|
|
endif
|
|
|
|
# get the size of the drive using identify device command
|
|
buffersize 512
|
|
setreadpio
|
|
ata28cmd 0 0 0 0 0 0xa0 0xec
|
|
# check if command failed
|
|
seti $command_failed = 0
|
|
gosub check_command_status
|
|
if $command_failed = 1
|
|
echo "Identify device command failed!"
|
|
gosub show_sense_data
|
|
gosub show_ata_return_status
|
|
previousscript
|
|
endif
|
|
# check if drive supports extended commands
|
|
seti $tempnum = buffer 167
|
|
seti $extended = $tempnum & 4
|
|
# total addressable sectors
|
|
if $extended > 0
|
|
seti $addressable = buffer 200 qw
|
|
else
|
|
seti $addressable = buffer 120 dw
|
|
endif
|
|
|
|
if $endsector = 0
|
|
seti $endsector = $addressable
|
|
endif
|
|
|
|
|
|
buffersize 0
|
|
setreadpio
|
|
seti $blocksize = 256
|
|
seti $logchunk = 256
|
|
seti $currentposition = $startsector
|
|
seti $previousposition = $currentposition
|
|
seti $blockposition = $currentposition
|
|
seti $processedsectors = 0
|
|
seti $totalsectors = $endsector - $startsector
|
|
seti $logcounter = 0
|
|
seti $accumulatedtime = 0
|
|
seti $1ms = 0
|
|
seti $3ms = 0
|
|
seti $10ms = 0
|
|
seti $30ms = 0
|
|
seti $100ms = 0
|
|
seti $300ms = 0
|
|
seti $over300ms = 0
|
|
seti $errorcount = 0
|
|
seti $highvalue = 0
|
|
seti $lowvalue = 1000000000
|
|
|
|
if $logfile != $null
|
|
deletefile $logfile
|
|
sets $line = "# warning log " $date
|
|
writelog $logfile $line
|
|
sets $line = "# cluster size is " $blocksize
|
|
writelog $logfile $line
|
|
endif
|
|
|
|
if $rateslog != $null
|
|
deletefile $rateslog
|
|
sets $line = "# position low high avg"
|
|
writelog $rateslog $line
|
|
endif
|
|
|
|
gettime
|
|
seti $displaytime = $time
|
|
seti $redodisplay = 1
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
echo " "
|
|
gettime
|
|
seti $programstart = $time
|
|
while $currentposition < $endsector
|
|
seti $sector = $currentposition
|
|
|
|
if $extended > 0
|
|
seti $features = 0
|
|
seti $count = $blocksize
|
|
seti $LBAlow = $sector & 0xffff
|
|
seti $temp = $sector > 16
|
|
seti $LBAmid = $temp & 0xffff
|
|
seti $temp = $sector > 32
|
|
seti $LBAhigh = $temp & 0xffff
|
|
seti $device = 0xe0
|
|
seti $command = 0x42
|
|
gettime
|
|
seti $startreadtime = $time
|
|
ata48cmd $features $count $LBAhigh $LBAmid $LBAlow $device $command
|
|
gettime
|
|
seti $endreadtime = $time
|
|
|
|
else
|
|
seti $features = 0
|
|
seti $count = $blocksize & 0xff
|
|
seti $LBAlow = $sector & 0xff
|
|
seti $temp = $sector > 8
|
|
seti $LBAmid = $temp & 0xff
|
|
seti $temp = $sector > 16
|
|
seti $LBAhigh = $temp & 0xff
|
|
seti $temp = $sector > 24
|
|
seti $LBAdevice = $temp & 0x0f
|
|
seti $device = 0xe0
|
|
seti $device = $device | $LBAdevice
|
|
seti $command = 0x40
|
|
gettime
|
|
seti $startreadtime = $time
|
|
ata28cmd $features $count $LBAlow $LBAmid $LBAhigh $device $command
|
|
gettime
|
|
seti $endreadtime = $time
|
|
endif
|
|
|
|
# check if command failed
|
|
seti $command_failed = 0
|
|
gosub check_command_status
|
|
if $command_failed = 1
|
|
seti $devicefault = $ata_return_status & 0x20
|
|
endif
|
|
|
|
seti $readtime = $endreadtime - $startreadtime
|
|
if $command_failed = 1
|
|
seti $errorcount = $errorcount + 1
|
|
elseif $readtime > 300000
|
|
seti $over300ms = $over300ms + 1
|
|
elseif $readtime > 100000
|
|
seti $300ms = $300ms + 1
|
|
elseif $readtime > 30000
|
|
seti $100ms = $100ms + 1
|
|
elseif $readtime > 10000
|
|
seti $30ms = $30ms + 1
|
|
elseif $readtime > 3000
|
|
seti $10ms = $10ms + 1
|
|
elseif $readtime > 1000
|
|
seti $3ms = $3ms + 1
|
|
else
|
|
seti $1ms = $1ms + 1
|
|
endif
|
|
|
|
|
|
if $readtime < $lowvalue
|
|
seti $lowvalue = $readtime
|
|
endif
|
|
if $readtime > $highvalue
|
|
seti $highvalue = $readtime
|
|
endif
|
|
|
|
seti $showerror = 0
|
|
if $command_failed = 1
|
|
seti $showerror = 1
|
|
elseif $readtime > $threshold
|
|
seti $showerror = 1
|
|
endif
|
|
|
|
if $showerror > 0
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
seti $adjustedtime = $readtime / 1000
|
|
if $command_failed = 1
|
|
hex
|
|
sets $errorstring = "e=0x" $ata_return_error " s=0x" $ata_return_status
|
|
decimal
|
|
if $direct_mode = 1
|
|
seti $command_status = $command_status & 0xfff0
|
|
if $command_status = 0x20
|
|
sets $status = "BUSY"
|
|
elseif $command_status = 0x30
|
|
sets $status = "TIMEOUT/RESET"
|
|
elseif $command_status = 0x40
|
|
sets $status = "TIMEOUT/RESET/BUSY"
|
|
elseif $command_status = 0x50
|
|
sets $status = "TIMEOUT"
|
|
elseif $command_status = 0x60
|
|
sets $status = "NO DRQ"
|
|
elseif $command_status = 0x70
|
|
sets $status = "WRONG DEVICE"
|
|
elseif $command_status > 0x7f
|
|
hex
|
|
sets $status = "OTHER/0x" $command_status
|
|
decimal
|
|
else
|
|
sets $status = ""
|
|
endif
|
|
else
|
|
sets $status = ""
|
|
endif
|
|
sets $outputline = "ERROR " $status " " $currentposition " " $adjustedtime "ms " $errorstring
|
|
else
|
|
sets $outputline = "WARNING " $currentposition " " $adjustedtime "ms "
|
|
endif
|
|
echo $outputline
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
echo $null
|
|
seti $redodisplay = 1
|
|
if $logfile != $null
|
|
writelog $logfile $outputline
|
|
endif
|
|
endif
|
|
|
|
|
|
seti $elapsedtime = $endreadtime - $displaytime
|
|
if $elapsedtime > 1000000
|
|
seti $redodisplay = 1
|
|
endif
|
|
if $redodisplay = 1
|
|
seti $sectorstransferred = $currentposition - $previousposition
|
|
seti $previousposition = $currentposition
|
|
seti $bytestransferred = $sectorstransferred * 512
|
|
seti $adjustedbytes = $bytestransferred * 1000000
|
|
seti $currentspeed = $adjustedbytes / $elapsedtime
|
|
seti $currentspeed = $currentspeed / 1000
|
|
gosub displayoutput
|
|
seti $displaytime = $endreadtime
|
|
endif
|
|
seti $redodisplay = 0
|
|
|
|
|
|
seti $accumulatedtime = $accumulatedtime + $readtime
|
|
seti $logcounter = $logcounter + 1
|
|
if $logcounter = $logchunk
|
|
seti $average = $accumulatedtime / $logchunk
|
|
|
|
if $rateslog != $null
|
|
sets $line = $blockposition " " $lowvalue " " $highvalue " " $average
|
|
writelog $rateslog $line
|
|
else
|
|
#echo "low=" $lowvalue " high=" $highvalue " average=" $average
|
|
endif
|
|
|
|
seti $highvalue = 0
|
|
seti $lowvalue = 1000000000
|
|
seti $accumulatedtime = 0
|
|
seti $logcounter = 0
|
|
seti $blockposition = $currentposition + $blocksize
|
|
endif
|
|
|
|
if $devicefault > 0
|
|
echo "Device fault detected!"
|
|
echo "Current position= " $currentposition
|
|
gosub show_ata_return_status
|
|
seti $devicefault = 0
|
|
echo "Power cycle the drive and hit enter to continue"
|
|
userinput $dummy
|
|
# do a hard reset to set the drive back up for access
|
|
hardreset
|
|
endif
|
|
|
|
seti $currentposition = $currentposition + $blocksize
|
|
seti $processedsectors = $processedsectors + $blocksize
|
|
# check if last read is less than blocksize
|
|
seti $partial = $currentposition + $blocksize
|
|
if $partial > $endsector
|
|
if $currentposition < $endsector
|
|
seti $blocksize = $endsector - $currentposition
|
|
endif
|
|
endif
|
|
done
|
|
|
|
if $devicefault = 0
|
|
gosub displayoutput
|
|
endif
|
|
|
|
|
|
previousscript
|
|
end
|
|
|
|
|
|
|
|
subroutine displayoutput
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
upline
|
|
echo " "
|
|
gettime
|
|
seti $totaltime = $time - $programstart
|
|
seti $totalseconds = $totaltime / 1000000
|
|
seti $remainder = $totaltime % 1000000
|
|
seti $totalminutes = $totalseconds / 60
|
|
seti $seconds = $totalseconds % 60
|
|
seti $hours = $totalminutes / 60
|
|
seti $minutes = $totalminutes % 60
|
|
echo "scantime h:m:s = " $hours ":" $minutes ":" $seconds "." $remainder
|
|
seti $positionpercent = $processedsectors * 100
|
|
seti $percentcomplete = $positionpercent / $totalsectors
|
|
seti $remainder = $positionpercent % $totalsectors
|
|
seti $remainder = $remainder * 100
|
|
seti $percentremainder = $remainder / $totalsectors
|
|
if $percentremainder < 10
|
|
echo $percentcomplete ".0" $percentremainder "% complete "
|
|
else
|
|
echo $percentcomplete "." $percentremainder "% complete "
|
|
endif
|
|
echo "position= " $currentposition " "
|
|
echo "speed= " $currentspeed " kB/s "
|
|
echo "<1ms=" $1ms " "
|
|
echo "1-3ms=" $3ms " "
|
|
echo "3-10ms=" $10ms " "
|
|
echo "10-30ms=" $30ms " "
|
|
echo "30-100ms=" $100ms " "
|
|
echo "100-300ms=" $300ms " "
|
|
echo ">300ms=" $over300ms " "
|
|
echo "errors=" $errorcount " "
|
|
endsubroutine
|
|
|
|
|