HDDSuperTool
1 Introduction
2 WARNING
3 How to Hide a Drive from the OS
4 USB Drives
5 Important Notes
6 Installing
7 Usage
8 Tips and Tricks
9 Reporting Bugs
10 Default Variables
11 Script Examples
12 Script Commands
13 Scripts
Index
HDDSuperTool
************

This manual is for HDDSuperTool (version 1.10-1.8, 29 January 2017).

1 Introduction
**************

Hddsupertool is an advanced disk tool for Linux.  It is used to run a
script to send SCSI and ATA commands directly to a disk.  It performs a
pre-check on the script before running it.  The pre-check is a basic
syntax and sanity check.  If the script fails the pre-check, the program
will exit without executing the script.  To stop the program at any time
hit ctrl-c.

2 WARNING
*********

DIRECT IO WARNING!

   This program has two modes, passthrough and direct IO (either IDE or
AHCI). Passthrough expects the drive is recognized by the Linux OS. When
using passthrough you are using the Linux driver, so the driver will be
aware of the activity and there should be no conflicts.  However, if you
choose to use direct IO mode, you are bypassing all Linux OS drivers!
This could lead to conflicts, and undesired results if the drive was
visible to the OS. HDDSuperTool will not let you select a drive from the
menu that is visible to the OS. You must follow the method described in
the section on how to hide a drive from the OS.

   In IDE mode it is also possible to work with a drive on the same
controller as another (possibly a CD/DVD drive you are booting from).
This is an extremely bad idea!  There is a safety warning if this
condition is detected.  Look at the port information in the drive list
to see if the drive may be sharing the same controller.  At this time
CD/DVD drives are not listed by model and serial, but will show up as
patapi device.  So if you see another device that has the same port info
except the last number (device select, either 0 or 1 ), then there is
another device on the same controller.

   Also with IDE, if the device is a slave (device select is 1), there
may be unexpected results with return status in the event of an error,
or other unknown issues (safety warning in place for this also).  It is
highly recommended that the device be a master on the controller.

   The warnings will make you type the word DANGEROUS to continue for
each condition.  If you do choose to continue, you are on your own for
any bad things that may happen!  If you have to type it more than once
for multiple conditions, you are really pushing your luck!

   It should be noted that if you manually select the device by setting
all of the port information on the command line, none of the safety
checks are performed, and you are on your own.

   If you do not fully understand these potential issues, then you
should not use direct IO!

   YOU HAVE BEEN WARNED!

3 How to Hide a Drive from the OS
*********************************

When using direct IDE mode (-direct) or direct AHCI mode (-ahci), the
drive must be hidden from the OS for proper operation.  The method below
requires the Linux kernel to be 3.13 or newer.  Ubuntu 14.04 has kernel
3.13, so it or any newer version of Ubuntu should work.  If you are
using a Linux distribution other than an Ubuntu flavor, you are
responsible for knowing the kernel version.

   Note that when using direct IDE mode with either actual IDE drives or
SATA drives with the bios set for IDE, if you boot the OS without the
drive plugged in / powered up, then Linux will not see it.  This is an
alternative method that seems to work the same, but it is still
recommended to hide the drive.

   The first thing you need to know is that this is based on the
physical port that the drive is connected to.  So once you disable that
port you can plug any drive into it and Linux will not see it (this
might not be entirely true for AHCI, as it would appear that Linux can
tell when a device is plugged in and sends at least one command to it,
likely an identify device command, but after that it leaves it alone).
This is true for both IDE and AHCI. However, when working with SATA
drives, switching between IDE and AHCI modes in the BIOS will change the
port numbers and you would need to adjust accordingly.  I have also once
experienced the port numbers being different on one boot up, but it
looked like something did not load properly on that boot, and a reboot
put things back to normal.

   The second thing you need is the number related to that port.  To get
this you need to plug in a good drive to that port and run HDDSuperTool
with the proper option to list the drives.  Below is a sample output
from hddsupertool -ahci:

     1) ata5.00 sda e02a5000 0 e02a5100 ST3120213AS 5LS3NJ70
     2) ata6.00 sdb e02a5000 1 e02a5180 Hitachi HDS723020BLA642 MN3220F30JKX9E
     3) ata7    --- e02a5000 2 e02a5200 no device
     4) ata8    --- e02a5000 3 e02a5280 no device
     5) ata9.00 sdg e02a5000 4 e02a5300 WDC WD2500BEAS-00URT0 WD-WXHY07017481
     6) ata10    --- e02a5000 5 e02a5380 no device

   Selection number 5 is the drive/port we wish to hide.  You can see
that the OS sees it as /dev/sdg.  What we want is the number after the
ata, which is 9.00.  You must use that number to add a kernel boot
option to grub, which in this case would be:

     libata.force=9.00:disable

   IMPORTANT NOTE: Don't disable the primary hard drive you are booting
from!  If you did that to your Linux installation you could very well
nuke your OS and have to repair it.

   To add a boot parameter in an Ubuntu live CD:

   To get to the grub menu on an Ubuntu live CD you need to press any
key as soon as the first small logo appears at the bottom of the screen
during boot up.  If the language selection comes up select your language
and hit enter.  Then hit F6 for Other Options, and when the options box
pops up hit ESC. Now you should see a line on the bottom of the screen,
just above the F-key options.  Use the right arrow key to get a cursor
flashing and make sure you are at the end of that line.  Also make sure
that Try Ubuntu without installing is highlighted above (up and down
arrow keys to change).  Add the boot parameter (such as
libata.force=9.00:disable) to the end of the line, and hit enter.  Wait
for it to boot up.

   To temporarily add a boot parameter to a kernel of a Linux
installation:

   1) Start your system and wait for the GRUB menu to show (if you don't
see a GRUB menu, press and hold the left Shift key right after starting
the system).

   2) Now highlight the kernel you want to use, and press the e key.
You should be able to see and edit the commands associated with the
highlighted kernel.

   3) Go down to the line starting with linux and add your parameter
libata.force=9.00:disable to its end.

   4) Now press Ctrl + x to boot.

   To make this change permanent:

   1) From a terminal run: sudo gedit /etc/default/grub and enter your
password.

   2) Find the line starting with GRUB_CMDLINE_LINUX_DEFAULT and append
libata.force=9.00:disable to its end.  For example:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash libata.force=9.00:disable"

   3) Save the file and close the editor.

   4) Finally, start a terminal and run: sudo update-grub to update
GRUB's configuration file (you probably need to enter your password).

   On the next reboot, the kernel should be started with the boot
parameter.  To permanently remove it, simply remove the parameter from
GRUB_CMDLINE_LINUX_DEFAULT and run sudo update-grub again.

   After disabling the drive/port you should get a result like this:

     1) ata5.00 sda e02a5000 0 e02a5100 ST3120213AS 5LS3NJ70
     2) ata6.00 sdb e02a5000 1 e02a5180 Hitachi HDS723020BLA642 MN3220F30JKX9E
     3) ata7    --- e02a5000 2 e02a5200 no device
     4) ata8    --- e02a5000 3 e02a5280 no device
     5) ata9    --- e02a5000 4 e02a5300 WDC WD2500BEAS-00URT0 WD-WXHY07017481
     6) ata10    --- e02a5000 5 e02a5380 no device

   Notice that there is no longer a decimal place after ata9, and there
are dashes in place of sdg, but the drive is seen by HDDSuperTool as it
is listed with model and serial.  This drive/port is now hidden from the
OS, and you may use HDDSuperTool to access it.

4 USB Drives
************

When in normal passthrough mode, it may be possible to send ATA commands
to USB attached ATA drives.  However, what commands are supported and
how the drive reacts to certain commands is entirely up to the USB
adapter interface that is attached to (or built into) the drive.  This
means that some commands may not be supported by the drive, and some
commands may give odd results.  This is not the fault of HDDSuperTool.
For instance, there are some scripts for Western Digital that use vendor
specific commands to read modules.  These scripts will not work on all
USB drives!  There is nothing I can do about that.  If other commands
seem to work fine, but the vendor specific commands do not then the USB
adapter interface likely does not support those commands.

5 Important Notes
*****************

This is an advanced utility, and it is very possible to send destructive
commands to a drive.  Please make sure you know what you are doing
before using this software.  I am in no way responsible for any data
loss or damage caused by using this software.  Use it at your own risk!

   While I do my best to ensure that this software does what it is
supposed to without flaw, there is always the possibility of a
programming error on my part.  If an error is found, I will fix it as
soon as possible.  However, I assume no responsibility for any data loss
or damage caused by any programming error.  You are responsible for
testing any commands and scripts before using them on critical data.

   Note that when using passthrough mode that there is normally a buffer
limit of 524288.  There is a limit stored at
/sys/block/DEVICE/queue/max_sectors_kb, where "DEVICE" is the device you
are reading (example "/sys/block/sda/queue/max_sectors_kb").  The number
stored here is referenced in KB, and the default for a hard drive is
usually 512 (meaning 512KB). This number is smaller for a USB connected
drive.  If you attempt a command with a buffer size greater than this
you will get an I/O error.  This limitation can be overcome by using the
generic scsi name for the device (example: /dev/sg1).  This mapping can
be found using the command "lsscsi -g".

6 Installing
************

Hddsupertool is supplied as an executable, with separate ones for 32bit
and 64bit.  You cannot run the 32bit on a 64 bit system and vice versa
(you may get an odd file not found error if you try).

   Hddsupertool now has DEB (Debian/Ubuntu) and RPM (RedHat/Fedora)
installers available.  If you have downloaded the appropriate installer
then you should just be able to double click on it to start the
installation process.  This method should even work on many live CDs,
but not all.  If you are unable to use one of the installers, then you
will need to follow the instructions below to install from the tar.gz
file or to run without installing.

   If you have downloaded the tar.gz file, then the easiest way to get
started is to copy the tar.gz file to a flash drive, and then use simple
copy and paste to put it in the Home folder that can be found on the
desktop of the Linux install.  When you open a terminal it should
default to the same Home folder that is on the desktop.

   To extract hddsupertool, open a terminal and use the following
commands (replacing the -x.x-x.x.-xxx with proper version number and
architecture):
     gunzip hddsupertool-x.x-x.x.-xxx-free.tar.gz
     tar xf hddsupertool-x.x-x.x.-xxx-free.tar

   Then navigate to the proper directory:
     cd hddsupertool-x.x-x.x.-xxx-free

   The following method to install HDDSuperTool will not only work on a
Linux installation, but you can use the same method when booting from a
live CD. The only difference is that every time you use a live CD, you
will need to perform these steps after each boot.

   To install hddsupertool, use the following command:
     sudo make install

   The "make install" command needs to be run as root, which is why
"sudo" is included in this example.  Your sysem may use a different
command, or you may already be root.  If it is not ran as root, then you
will likely get permission errors and the install will not be complete.
Note that you can also uninstall it with the command "sudo make
uninstall".  There is now also an uninstaller script that can be ran by
typing "sudo hddsupertool-uninstall.sh".

   You must run hddsupertool as root.  For Ubuntu you would use "sudo"
in front of the command:
     sudo hddsupertool
   Please consult the documentation for your version of Linux for
information on how to run as root.

   To run it without installing, you must be in the same directory as
hddsupertool.  Note that some versions of Linux will not allow you to
run a program from certain external devices (such as a FAT32 USB drive).
Example to run it from the current directory:
     sudo ./hddsupertool

   You may need to change the permissions on the file so that you have
the rights to run it.  The following command should do that:
     sudo chmod a+x hddsupertool

   If you are booted from a live CD that does not allow installing with
make (maybe make does not exist) and you are trying to run it from a USB
drive and are getting a permission error, you can copy the executable to
the home folder and run it from there.  Note that if using a live CD the
home folder exists in ram and will be cleared on a reboot.  The
following example assumes you are in the folder on the USB drive that
contains hddsupertool.  The first command copies it to the home folder,
the second command gives permission to execute, and the third command
runs it:
     sudo cp hddsupertool /home
     sudo chmod a+x /home/hddsupertool
     sudo /home/hddsupertool

   You may notice that examples did not include a drive or script.  As
long as the hddscripts folder is either in the current working
directory, or has been copied to /usr/local/bin/hddscripts, hddsupertool
will start with a menu driven system.  You can still run hddsupertool
with manual options to declare which drive and script with a command
such as the following:
     sudo hddsupertool -t /dev/sdb -f ata_identify_device

7 Usage
*******

Hddsupertool must be run as root.  If no arguments are present on the
command line, it will start the passthrough menu mode.

   If no drive is chosen, then all possible available drives will be
listed with model and serial numbers.  In passthrough mode, the drives
will have the form of /dev/sdx, followed by model and serial.  If the
drive is not ATA (did not respond to identify device command), then the
returned sense code will be shown instead of model/serial.

   In direct mode, it will show driver and port information.  From left
to right: Driver, PCI bus ID, Registers port, Control port, Bus port,
Device select, Model, Serial.  If there was not a proper response from
the identify device command, then there will be other information in
place of the model and serial.  "Busy or drq" will be followed by the
status and error register values, and usually means there are no drives
connected to that controller.  "No drq" will be followed by the status
register, lba mid, lba high, and either "no device" or "patapi device".
Patapi indicates there is a CD/DVD drive attached.  At this time
hddsupertool does not list CD/DVD drives by model and serial.

   If you would like to see more information about the ports on your
system, try the command "lspci -v".  Note that for SATA drives, the BIOS
must be in IDE mode for direct IO to work.  AHCI mode is not supported
for direct IO.

   Note that in direct IO mode, DMA access is not available in the free
version.

   The format for running hddsupertool is:

     hddsupertool [OPTIONS] OPTIONAL_VARIABLES

   Where:
OPTIONAL_VARIABLES
     Optional variables to be passed to the script from the command
     line.  Both number and string variables can be passed, with a total
     limit of 16 variables that can be passed.  A number variable is
     passed using a single equal sign, and a string variable is passed
     using a double equal sign.  There must be NO SPACES BETWEEN THE
     VARIABLE NAME, EQUALS SIGN, AND VALUE. In the command line you also
     DO NOT START THE VARIABLE NAME WITH "$" as you would inside the
     script.  Number variables will be treated as decimal unless
     preceeded by 0x in which case they will be treated as hex.  String
     variables that contain text with spaces must be enclosed in quotes.
     The following example will set a number variable "number" to a
     value of 255 and a string variable "string" to a line of text.
          hddsupertool -t /dev/sda -f script.txt number=0xff string=="line of text"

   Hddsupertool supports the following options:

'-h'
'--help'
     Print an informative help message describing the options and exit.

'-v'
'--version'
     Print the version number and exit.

'-V'
'--verbose'
     Show additional information.  It is multi-level, meaning -V is
     level 1, -VV is level 2 and so on.

'-c'
'--check'
     Perform the normal pre-check on the script, but do not execute it.

'-C'
'--command'
     Use a command prompt to enter commands instead of reading from a
     script.  Note that some commands will not work on the command line,
     and will report a generic error with the command (you can't do
     conditional statements, loops, or subroutines).  When ran with this
     option you will get a command prompt of ">".  To exit the command
     line mode type "end".  The following example performs a simple
     identify device command and displays the raw results.
          hddsupertool /dev/sda --command
          hddsupertool 1.5-1.4 20160101

          > buffersize 512
          > setreadpio
          > ata28cmd 0 0 0 0 0 0xa0 0xec
          > printbuffer 0 0 512
          0: 7a 42 20 08 00 00 10 00 00 00 00 00 3f 00 00 00    zB .........?...
          10: 00 00 00 00 30 30 30 30 30 30 30 30 30 30 30 30    ....000000000000
          20: 30 30 30 30 30 30 31 30 00 00 40 00 00 00 30 30    00000010.....00
          30: 30 30 30 30 31 30 4d 56 61 77 65 72 56 20 72 69    000010MVawerV ri
          40: 75 74 6c 61 49 20 45 44 48 20 72 61 20 64 72 44    utlaI EDH ra drD
          50: 76 69 20 65 20 20 20 20 20 20 20 20 20 20 40 80    vi e          .
          60: 00 00 00 2f 00 00 00 02 00 00 07 00 20 08 10 00    .../........ ...
          70: 3f 00 00 fe 1f 00 10 01 00 00 20 00 00 00 07 00    ?......... .....
          80: 03 00 78 00 78 00 a0 00 78 00 00 00 00 00 00 00    ..x.x...x.......
          90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          a0: 1e 00 17 00 08 40 08 40 00 41 08 40 08 00 00 41    .......A....A
          b0: 07 04 00 00 00 00 fe 40 00 00 00 00 00 00 00 00    ...............
          c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          d0: 00 00 00 00 00 40 00 00 00 50 90 c2 9e fe 59 18    ........P....Y.
          e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          1a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          1b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          1c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          1d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          1e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
          1f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a5 a4    ................
          > end

          Total program run time = 80 seconds


'-d'
'--direct'
     Enable and use direct IO mode.  For SATA drives, the BIOS must be
     in IDE mode for this to work.  It will not work in AHCI mode.  Note
     that for some unknown reason, on some models of computers Linux may
     still use the AHCI driver even with the BIOS set to IDE. You are
     stuck using passthrough mode in this case.

'-f SCRIPT'
'--file SCRIPT'
     The script file that contains the commands to be sent to the drive.
     If this is not set, then it will look for a file named "hddmenu"
     first in the current directory, then in the sub directory
     "hddscripts/", and then in "/usr/local/bin/hddscripts/".  All
     subscripts will be loaded from the directory where hddmenu was
     found.  If no script file is found then the program will exit.

'-i SPACES'
'--indent SPACES'
     Performs an indentation cleanup on the script.  This will indent
     certain commands by the number of spaces specified.
          hddsupertool -i 2 -f script.txt

'-t DISK'
'--target DISK'
     The drive to which the commands are to be sent.  This must be a
     whole drive and not a partition.  If you do specify a partition,
     all commands will still reference the drive from the beginning and
     ignore the partition offset.  If this is not set, then a list of
     possible devices will be presented to choose from.
          hddsupertool -t /dev/sda -f script.txt

'-L SERIAL'
'--license SERIAL'
     Enter license number to install license.
          hddsupertool -L 11111-22222-33333-44444-55555

'--regaddress REG PORT ADDRESS'
     Only for direct IO. The address in hex for the registers port.
     This is set for you if the device is chosen from the menu list at
     startup.

'--conaddress CONTROL PORT ADDRESS'
     Only for direct IO. The address in hex for the control port.  This
     is set for you if the device is chosen from the menu list at
     startup.

'--busaddress BUS PORT ADDRESS'
     Only for direct IO. The address in hex for the bus port.  This is
     set for you if the device is chosen from the menu list at startup.

'--device DEVICE'
     Only for direct IO. This is either 0 or 1, to choose device 0 or 1.
     The default is 0.  This is set for you if the device is chosen from
     the menu list at startup.  This will set the proper bit in the
     device field when performing ATA commands.

's DRIVE SERIAL'
'--serial DRIVE SERIAL'
     This will choose the device by serial number.  This is useful for
     repeating a script run where the device may have been power cycled
     and may come back with a different listing, or the device was moved
     to a different port.  If the serial number cannot be matched, then
     no device is chosen and the program will exit.
          hddsupertool -f script.txt -s WD12345678

'Q'
'--quiet'
     Surpress some of the output.  This is mostly for my use to be able
     to extract the help from the individual scripts to include in this
     documentation.

   Example usage:
     hddsupertool -t /dev/sda -f script.txt

8 Tips and Tricks
*****************

Here are a few tips and tricks to help you along.

   HDDSuperTool needs to be run as root.  By doing so any files or
folders that it creates will be owned by root.  This can make it
difficult to edit or delete files as a user (you will get permission
errors).  The terminal command "chmod" will help you with this.  It is
recommended that you read up on this command and learn how to use it.

   There may be times when it would be nice to log all screen output to
a file.  Someone just recently pointed me to the "script" function.  If
you type "script -help" on the command line it will show the possible
options.  By default it will save the log to the file "typescript".

   The following example would probably be the best way to use the
function.  This will log all screen output for that run of hddsupertool
to the file named hddsupertool.log, and stop logging when hddsupertool
exits.  If the file exists it will be overwritten.
     script -c "sudo hddsupertool" hddsupertool.log

   HDDSuperTool can be run from a live CD. When running from a live CD
it runs in ram, and all data is lost when you reboot!  You are
responsible for making sure that you copy any data you wish to keep to
an external drive when running from a live CD.

9 Reporting Bugs
****************

It is always possible that there are programming errors in this
software.  It is also possible that there are errors and omissions in
this documentation.  If you report them, they will get fixed.  If you
don't report them, they will just stay the way they are and will not get
fixed.

   Report bugs to (<sdcomputingservice@gmail.com>)

   Please include the version number of hddsupertool.  You can find the
version by running hddsupertool with the '--version' option.

10 Default Variables
********************

There are several variables that are automatically created and used by
the program.  You should not use these variables to store data as they
will get overwritten by the program during operation.
'error_level'
     Some commands will return data in this variable.  The data is
     command specific.
'io_sense_key'
     sense key - part of the key code qualifier.  Only for passthrough.
'io_asc'
     additional sense code - part of the key code qualifier.  Only for
     passthrough.
'io_ascq'
     additional sense code qualifier - part of the key code qualifier.
     Only for passthrough.
'io_status'
     This is the SCSI status byte as defined by the SCSI standard.  Only
     for passthrough.
'io_masked_status'
     Refer to "The Linux SCSI Generic (sg) HOWTO". Only for passthrough.
'io_msg_status'
     Refer to "The Linux SCSI Generic (sg) HOWTO". Only for passthrough.
'io_sb_len_wr'
     Number of bytes in the sense buffer.  Only for passthrough.
'io_host_status'
     Refer to "The Linux SCSI Generic (sg) HOWTO". Only for passthrough.
'io_driver_status'
     Refer to "The Linux SCSI Generic (sg) HOWTO". Only for passthrough.
'io_resid'
     Refer to "The Linux SCSI Generic (sg) HOWTO". Only for passthrough.
'io_duration'
     Number of milliseconds the SCSI command took to complete.  Only for
     passthrough.
'io_info'
     Refer to "The Linux SCSI Generic (sg) HOWTO". Only for passthrough.
'ata_return_error'
     ATA error register data.
'ata_return_count'
     ATA count register data.
'ata_return_lba'
     ATA LBA register data combined into one value.
'ata_return_device'
     ATA device register data.
'ata_return_status'
     ATA status register data.
'time'
     Value returned from GETTIME command.
'date'
     Value returned from GETTIME command.
'data_transferred'
     Returns the number of bytes transferred.  This can be an indication
     if data was transferred or not, but is not a guarantee that data
     was actually transferred.
'command_status'
     Return value from a command.  Any value other than 0 indicates the
     command failed to complete at the driver level, and any sense key
     or register data may not be present or useful.  1 is for
     passthrough only.  0x20 and up are for direct IO only.  There are
     major and minor values that are combined to form the full value.
     Values are listed in hex.
          Major values:
          1 = Passthrough error (ioctl driver reported an error)
          2x = Busy or DRQ timeout while waiting to send the command
          3x = Soft reset timeout, command did not complete in time
          4x = Soft reset timeout, drive is not ready after reset
          5x = General timeout, command did not complete in time
          6x = No DRQ, drq was not set when it was expected
          7x = Wrong device detected, something switched the device
          8x or higher = Something bad went wrong when processing
          Minor values:
          x1 = Exceeded reset timeout
          x2 = Exceeded general timeout
'bus_master_status'
     Bus master status.  Only for direct mode when performing DMA
     commands.
'direct_mode'
     A way for scripts to tell if using direct(value=1) or
     passthrough(value=0) mode.
'ahci_mode'
     A way for scripts to tell if using AHCI mode.

11 Script Examples
******************

The scripting can be a bit overwhelming to even those that are used to
some sort of programming.  This section is an attempt to demonstrate the
basics.

   The following is a commented script to perform a simple identify
device command and display the raw data.
     # first we must set the buffer size
     buffersize 512

     # now we must specify that this is a PIO read command
     setreadpio

     # now we send the command
     ata28cmd 0 0 0 0 0 0xa0 0xec

     # show the data on the screen
     printbuffer 0 512

     # write the data to the file "indentify.bin"
     writebuffer "indentify.bin" 0 0 512

     # the data returned from this command is in words in litte endian format,
     # and can be flipped for easier viewing of the information
     # note that this is optional and not normally used for other commands
     wordflipbuffer 0 512

     # show the flipped data on the screen
     printbuffer 0 512

   MHDD has several scripts available for different things.  Here is an
example of translating a MHDD script to HDDSuperTool.  First here is a
MHDD script to dump 2 sectors of module 02 from a WD Marvel drive
(popular as the drive passwords are usually stored there).
     ;script name: read md
     ;reads md 02 on WD marwell drives
     ;
     reset
     waitnbsy

     regs = $45 $0b $00 $44 $57 $a0 $80
     waitnbsy

     regs = $d6 $01 $be $4f $c2 $a0 $b0
     waitnbsy
     checkdrq
     sectorsfrom = cs.bin

     regs = $d5 $01 $bf $4f $c2 $a0 $b0
     waitnbsy
     checkdrq
     sectorsto = 21.bin

     regs = $d5 $01 $bf $4f $c2 $a0 $b0
     waitnbsy
     checkdrq
     sectorsto = 22.bin

     ; end
   This also requires the 512 byte file cs.bin to have been created by
the user with the following data.  Note that only the first line has
data, the rest of the file is 0 filled.
     0x000  08 00 01 00 02 00 00 00 00 00 00 00 00 00 00 00
     ......................................................
     0x1f0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

   Here is the HDDSuperTool version.
     # the first command is non-data, so set the buffersize to 0
     buffersize 0

     # this is a PIO command so this must be set
     setreadpio

     # send the first command
     ata28cmd 0x45 0x0b 0x00 0x44 0x57 0xa0 0x80

     # optionally show the returned values of the error and status registers
     echo "error=0x" $ata_return_error " status=0x" $ata_return_status

     # the next command sends 512 bytes (the file) so set the buffer size
     buffersize 0x200

     # clear the buffer to 0s so there is no other data
     clearbuffer

     # put data in the buffer
     # note that this is the file data from cs.bin
     # as you can see it can be directly entered with HDDSuperTool
     setbuffer 0
       08 00 01 00 02
     endbuffer

     # this is a write command so set accordingly
     setwritepio

     # send the command
     ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0

     # optionally show the returned values of the error and status registers
     echo "error=0x" $ata_return_error " status=0x" $ata_return_status

     # the next commands are read commands
     setreadpio

     # clear the buffer to 0s so we know the data received is good
     clearbuffer

     # send the command
     ata28cmd 0xd5 0x01 0xbf 0x4f 0xc2 0xa0 0xb0

     # optionally show the returned values of the error and status registers
     echo "error=0x" $ata_return_error " status=0x" $ata_return_status

     # write the sector to a file
     writebuffer "21.bin" 0 0 0x200

     # clear the buffer to 0s so we know the data received is good
     clearbuffer

     # send the command
     ata28cmd 0xd5 0x01 0xbf 0x4f 0xc2 0xa0 0xb0

     # optionally show the returned values of the error and status registers
     echo "error=0x" $ata_return_error " status=0x" $ata_return_status

     # write the sector to a file
     writebuffer "22.bin" 0 0 0x200

     # this command is not listed in the MHDD script above
     # it is the counterpart to the first command
     # the first command turned on a special VSC mode
     # this command turns it back off, otherwise it would need to be reset
     buffersize 0
     setreadpio
     ata28cmd 0x44 0x0b 0x00 0x44 0x57 0xa0 0x80

     # we are done
     end

12 Script Commands
******************

Note that all commands, operators, operands, and variables in the script
MUST BE SEPARATED BY A SPACE. For example, "SETI $a=1" is not correct
and will be rejected.  The proper command would be "SETI $a = 1".  This
is the syntax that I used as it allows for less complicated programming
code.  Items can be separated by more than one space with no issues, it
just has to be a minimum of one space.

   Note that all numbers written in the script are assumed to be in
decimal format, unless specified as hex by a proceeding "0x".  The
exeption is when setting the buffer all numbers are assumed in hex
format.

   All commands are available in all small letters or all capital
letters, but they cannot be mixed small and capital letters.  Commands
are in all caps in this documentation for viewing purposes.

   Most if not all commands will accept variables in place of actual
numbers or text.  If you find a command that does not properly accept
variables when you think is should, please report it.

   The available commands and syntax are as follows:

'#'
     Comment line.  Anything following the # will not be processed.  It
     must be the first non-space character in the line.  You cannot add
     a comment to the end of a line.

'ECHO'
     Print to screen output.  Text can be output using quotes, either
     single or double.  Quotes of the opposite type inside the original
     quotes will be output to the screen.  Both string and number
     variables can also be output.  There must be a space between quotes
     and variables, and variables must be outside the quotes.  The
     following is a proper example:
          ECHO "This will print the variable a=" $a " and then the variable b=" $b
          ECHO "This will print single 'quotes' within the line"

'SETI'
     Set a number variable.  All variables must start with "$".  All
     number variables are integers of type long long.  That means they
     can be a value from -9,223,372,036,854,775,808 to
     9,223,372,036,854,775,807.  You can also set it to another
     variable, and also do simple math with two operands and one
     operator.

     Available operands are:
          +  addition
          -  subtraction
          *  multiplication
          /  division (no remainder)
          %  division (result is the remainder)
          &  bitwise and
          |  bitwise or
          ^  bitwise exclusive or
          <  bitwise shift left
          >  bitwise shift right

     Usage examples:
          SETI $a = 3
          SETI $b = $a + 0x10
          SETI $c = $a * $b
          SETI $count = $count + 1

     There are a couple special cases for the SETI command.  The first
     is the ability to extract a number from a string variable.  The
     format is "SETI $number = $string location", where $string is the
     string variable containing the number to be extracted, and location
     is the placement of the number inside the string, starting with 0
     as the first location.  The location is based on spaces or tabs
     between the numbers.  The location can be a number variable itself.
     If the number to be extracted starts with 0x it will be processed
     as hex, otherwise it will be processed as decimal unless forced
     using the "HEX" command.  The following example will extract the
     number 3 from the string 1 2 3 4 5.
          sets $string = "1 2 3 4 5"
          SETI $number = $string 2

     The second special case is extracting a number from the buffer or
     scratchpad (or sensebuffer, but words are not supported for
     sensebuffer).  You can only extract a byte, word, double word, or
     quad word.  The format is "SETI $number = BUFFER location type",
     where location is the starting byte location in the buffer, and
     type is either b, w, dw, qw.  If no type is specified it will
     assume the type is byte.  Note that the words are little endian, so
     a buffer value of 11 22 33 44 would be double word value
     0x44332211.  This can be useful for extracting information from the
     identify device results.
          #extract byte 234 from the buffer
          SETI $number = BUFFER 234

          #extract double word from the buffer starting at byte 234
          SETI $number = BUFFER 234 dw

'SETS'
     Set a string variable.  All variables must start with "$".  The
     format is the similar to the ECHO command, except instead of screen
     output the string ends up in the variable.
          SETS $string = "This will put the variable a=" $a " and then the variable b="
          $b " along with this message into a string variable"

     There is one exception, where a part of the buffer can be extracted
     into the string variable.  The format for that is "SETS $string =
     BUFFER location length", where location is the byte position in the
     buffer and length is the number of bytes to copy.  The following
     example will put 40 characters from the buffer starting at byte 54
     into a string variable:
          SETS $string = BUFFER 54 40

'EXIT'
     The script will terminate with an exit code.  The format is "EXIT
     number", where number is a value from 0-255.  Note that the program
     already uses some of the lower numbers for program error codes, so
     it is advised you use numbers 16-255.

'END'
     The script will terminate with a normal exit code of 0.

'HEX'
     This forces many commands to default to processing numbers as hex
     instead of decimal.  It will affect the output of the ECHO command
     and also the SETS command.  Be very careful using the HEX command,
     as it can cause undesired results if left turned on.  It is
     recommended to only use it before a command such as ECHO to get the
     desired results from the command, and then use the DECIMAL command
     to turn it back off.
          SETI $number = 0x7f
          ECHO "The number in decimal is " $number
          HEX
          ECHO "The number in hex is 0x" $number
          DECIMAL

'DECIMAL'
     This turns off the HEX command and puts the default number
     processing back to decimal.  It does not force numbers to be
     processed as decimal, if they are proceeded by 0x they are still
     processed as hex.

'SETBUFFER'
     Manually set the buffer contents.  The buffer contains the data
     that is either sent to or received from the drive.  The format is
     "SETBUFFER offset", where offset is a number (can be a variable)
     that is the location in the buffer to start.  The lines following
     the SETBUFFER command are the actual data, to be ended by the
     ENDBUFFER command.  The data must be in the format of
     byte-space-byte-space-byte, and the data is always processed as
     hex.  There is no set number of bytes per row, the next row will
     just pick up where the last row left off.  A row can start with an
     additional offset (which will be an additional offset to the
     supplied buffer offset).  To use the additional offset start the
     line with a hex number followed by a colon.
          # start setting the buffer at offset 128(0x80)
          SETBUFFER 0x80
            0 1 2 3 4 5 6 7
            8 9 a b c d e f
            10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
            # the next line will jump to buffer offset 256(0x100)
            80: 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
          ENDBUFFER

'ENDBUFFER'
     Required for ending the SETBUFFER command.

'PRINTBUFFER'
     Prints the buffer to the screen.  The format is "PRINTBUFFER offset
     size", where offset is the starting buffer offset, and size is the
     number of bytes to be printed.  You cannot print past the end of
     the current buffer size.
          # show the first 256 bytes of the buffer
          PRINTBUFFER 0 256

'STRINGTOBUFFER'
     Puts a string into the buffer contents.  The format is
     "STRINGTOBUFFER offset size $string", where offset is the buffer
     offset, size is the maximum copy size, and $string is the string
     variable name.  If size is greater than the length of the string
     then the whole string will be copied into the buffer, and the copy
     will stop at the end of the string.  If size is smaller than the
     length of the string then it will only copy up to the size limit
     and the rest of the string is ignored.
          SETS $string1 = "this is a string"
          # copy the whole string (up to 64 bytes) to the buffer starting at offset 0x10
          STRINGTOBUFFER 0x10 64 $string1
          # copy only the first two words to the beginning of the buffer
          STRINGTOBUFFER 0 7 $string1

'CLEARBUFFER'
     Clears (erases) the entire buffer contents to zeros.

'BUFFERSIZE'
     Sets a new buffer size.  This erases (destroys) the current buffer
     contents.  The format is "BUFFERSIZE size", where size is the new
     size of the buffer in bytes.  The default starting buffer size is
     512.  The maximum buffer size is 33554432 (512 * 65536).
          # increase the buffer size to 4096
          BUFFERSIZE 4096

'WRITEBUFFER'
     Write the buffer or part of the buffer to a file.  The format is
     "WRITEBUFFER filename bufferoffset fileoffset size", where filename
     is the name of the file to write to, bufferoffset is the byte
     offset of the starting point in the buffer, fileoffset is the byte
     offset of the write point in the file, and size is the size in
     bytes to be written.  If the file does not exist it will be
     created.  This will overwrite the designated data in the file, but
     will not erase any other data in the file, meaning you can keep
     adding data to the file at different offsets.
          # write the first 512 bytes of the buffer to the file named image.bin
          WRITEBUFFER image.bin 0 0 512
          # write 512 bytes to the second sector of the file
          WRITEBUFFER image.bin 0 512 512

'READBUFFER'
     Read a part of a file to the buffer.  The format is "READBUFFER
     filename bufferoffset fileoffset size", where filename is the name
     of the file to read from, bufferoffset is the byte offset of the
     starting point in the buffer, fileoffset is the byte offset of the
     read point in the file, and size is the size in bytes to be read.
          # read the first 512 bytes of the file named image.bin to the start of the
          buffer
          READBUFFER image.bin 0 0 512
          # read the second 512 bytes of the file to the buffer
          READBUFFER image.bin 0 512 512

'DIRECTION'
     Set the direction of the data transfer to either NONE, TO, FROM, or
     TOFROM. This is often required for proper processing of both SCSI
     and ATA passthrough commands by the Linux kernel.  The proper
     direction needed for a command can be found in the SCSI or ATA
     documentation respectively.  Note that for ATA commands this is set
     by the SETREADPIO, SETREADDMA, SETWRITEPIO, and SETWRITEDMA
     commands respectively, so you do not need to set it directly.  You
     do need to set it with SCSI commands.
          # set the direction to read data from the drive
          DIRECTION FROM

'SCSI6CMD'
     Perform an scsi 6 command.  Format is "SCSI6CMD b0 b1 b2 b3 b4 b5",
     where b0-b5 are the actual bytes of the command.

'SCSI10CMD'
     Perform an scsi 10 command.  Format is "SCSI10CMD b0 b1 b2 b3 b4 b5
     b6 b7 b8 b9", where b0-b9 are the actual bytes of the command.
          # perform scsi capacity 10 command
          DIRECTION FROM
          SCSI10CMD 0x25 0 0 0 0 0 0 0 0 0

'SCSI12CMD'
     Perform an scsi 12 command.  Format is "SCSI12CMD b0 b1 b2 b3 b4 b5
     b6 b7 b8 b9 b10 b11", where b0-b11 are the actual bytes of the
     command.

'SCSI16CMD'
     Perform an scsi 16 command.  Format is "SCSI16CMD b0 b1 b2 b3 b4 b5
     b6 b7 b8 b9 b10 b11 b12 b13 b14 b15", where b0-b15 are the actual
     bytes of the command.
          # perform scsi capacity 16 command
          DIRECTION FROM
          SCSI16CMD 0x9e 0x10 0 0 0 0 0 0 0 0 0 0 0 0x12 0 0

'PRINTSENSEBUFFER'
     Prints the SCSI return sense buffer to the screen so that advanced
     users can decode the results.  The format is "PRINTSENSEBUFFER
     offset size", where offset is the sense buffer offset, and size is
     the number of bytes to be printed.  The maximum sense buffer size
     is 256.
          # display the contents of the sense buffer that was returned, if any
          PRINTSENSEBUFFER 0 $io_sb_len_wr

'SETREADPIO'
     Prepare for PIO read.  Required before performing this type of ATA
     command.  If the buffer size is set to zero prior to this command,
     then it will setup for a non-data command.  If you wish to perform
     a non-data command you should set the buffer size to zero before
     performing this command.

'SETWRITEPIO'
     Prepare for PIO write.  Required before performing this type of ATA
     command.  If the buffer size is set to zero prior to this command,
     then it will setup for a non-data command.  If you wish to perform
     a non-data command you should set the buffer size to zero before
     performing this command.  The non-data command is the same as when
     performing a non-data SETREADPIO command.

'SETREADDMA'
     Prepare for DMA read.  Required before performing this type of ATA
     command.

'SETWRITEDMA'
     Prepare for DMA write.  Required before performing this type of ATA
     command.

'ATA28CMD'
     ATA 28 bit command.  The format is "ATA28CMD b0 b1 b2 b3 b4 b5 b6",
     where b0-b6 are the actual bytes of the command according to ATA
     documentation.  Note that the device bit of the device field will
     be set for you according to the device being accessed, in either
     passthrough or direct IO modes.  b0 = features b1 = count b2 = lba
     low b3 = lba mid b4 = lba high b5 = device b6 = command
          # perform ata_identify_device command
          buffersize 512
          setreadpio
          ATA28CMD 0 0 0 0 0 0xa0 0xec
          echo "Raw buffer:"
          printbuffer 0 512

'ATA48CMD'
     ATA 48 bit command.  The format is "ATA48CMD w0 w1 w2 w3 w4 b5 b6",
     where w0-w4 are the actual words of the command according to ATA
     documentation, and b5-b6 are the device and commands bytes.  The
     words are in standard format and not flipped (not little endian),
     meaning that 0x0001 has a value of 1.  Note that the device bit of
     the device field will be set for you according to the device being
     accessed, in either passthrough or direct IO modes, so it does not
     matter what value you give that bit.  Also remember that the LBA
     order is reversed from the 28 bit command.  w0 = features w1 =
     count w2 = lba high w3 = lba mid w4 = lba low b5 = device b6 =
     command
          # perform ata_identify_device command
          buffersize 512
          setreadpio
          ATA48CMD 0 0 0 0 0 0xa0 0xec
          echo "Raw buffer:"
          printbuffer 0 512

'WRITELOG'
     Write a string variable to a text file as a line.  This will append
     the string to the end of the existing file.  The format is
     "WRITELOG filename string", where filename is the name of the file
     to be written to, and string is the variable to be written.  If the
     file does not exist it will be created.
          # write text lines to the file named logfile.txt
          sets $line1 = "This is the first line"
          sets $line2 = "This is the second line"
          WRITELOG logfile.txt $line1
          WRITELOG logfile.txt $line2

'GETTIME'
     This gets the current time and date and sets two variables.  Number
     variable $time will have the time in microseconds since the Epoch
     (1970-01-01 00:00:00 +0000 (UTC)). String variable $date will
     contain the current date and time.
          # display the time since Epoch and the current date
          GETTIME
          echo "time since Epoch usec: " $time
          echo "todays date: " $date

          # display the time elapsed
          GETTIME
          seti $start_time = $time
          # do some program stuff here that takes time
          GETTIME
          seti $elapsed_time = $time - start_time
          echo "time elapsed usec: " $elapsed_time

'REOPENDISK'
     Only for passthrough, has no effect with direct IO. Closes and
     reopens the current disk.  This seems to perform a soft reset on
     the drive, which can be helpful in certain cases where it may not
     respond properly after performing certain commands.

'IF'
     Conditional if statement.  The format is "IF value1 condition
     value2", where value1 and value2 are number or string variables and
     condition is the comparison to be made.  The values can be actual
     numbers (or strings) or variables.  If using an actual string
     (word), do not use quotes, and there cannot be spaces in the
     string.  To compare strings with spaces in them you must set and
     compare string variables.  Complex statements are not allowed (more
     than one condition).  Math is also not allowed within the
     statement.  Multiple IF statements can be nested.  Each IF
     statement must be ended with the ENDIF command.  Everything in
     between the IF and ENDIF is executed if the condition is true.

     Available conditions are:
          <  less than
          >  greater than
          =  equal
          !=  not equal
          <=  less than or equal
          >=  greater than or equal
          Note that only equal and not equal are allowed when comparing strings

     Example:
          seti $high = 100
          if $a > 1
            echo "a is greater than 1"
            if $a > 10
              echo "a is greater than 10"
              if $a > $high
                echo "a is greater than " $high
              endif
            endif
          endif

'ENDIF'
     Marks the end of an IF statement.

'ELSE'
     Statement to be processed when the IF and any ELSEIF statements are
     false.

     Example:
          if $a > 0
            echo "a is greater than 0"
          else
            echo "a is less than or equal to 0"
          endif

'ELSEIF'
     Conditional statement to be processed when the IF or preceeding
     ELSEIF statements are false.  The format is the same as the IF
     statement.

     Example:
          if $a > 10
            echo "a is greater than 10"
          elseif $a < 0
            echo "a is less than 0"
          elseif $a = 5
            echo "a is equal to 5"
          else
            echo "a is between 0 and 10 but is not 5"
          endif

'SUBROUTINE'
     Marks the start of a subroutine.  The format is "SUBROUTINE name",
     where name is the name of the subroutine.  The subroutine must be
     ended with the ENDSUBROUTINE command.
          subroutine show_ata_return
            echo "ATA return data:
            hex
            echo "error=0x" $ata_return_error " count=0x" $ata_return_count " lba=0x"
          $ata_return_lba " device=0x" $ata_return_device " status=0x" $ata_return_status
            decimal
          endsubroutine

'ENDSUBROUTINE'
     Marks the end of a subroutine.

'GOSUB'
     Calls a subroutine.  The format is "GOSUB name", where name is the
     name of the subroutine.  When the subroutine ends by either the
     ENDSUBROUTINE or RETURNSUB command, program execution will resume
     on the line followin the GOSUB command.
          ata28cmd 0 0 0 0 0 0xa0 0xec
          gosub show_ata_return
          printbuffer 0 512

'RETURNSUB'
     Returns from the current subroutine.  This is meant to be used with
     conditional statements, to be able to exit the subroutine before
     reaching the ENDSUBROUTINE command.
          subroutine do_something
            if $error_level != 0
              returnsub
            endif
            printbuffer 0 512
          endsubroutine

'WHILE'
     Conditional loop.  The format is the same as the IF command.  The
     WHILE command must be ended with the DONE command.  If the WHILE
     condition is true then the code between the WHILE and DONE commands
     is executed.  When the DONE command is reached, the WHILE condition
     is checked again to see if it is true or false.  When the condition
     is false the code continues on after the DONE command, otherwise it
     loops back to the beginning of the WHILE command.

     Example:
          # count from 1 to 10
          seti $count = 1
          while $count <= 10
            echo "The count is " $count
            seti $count = $count + 1
          done

'DONE'
     Marks the end of the WHILE command.

'BREAK'
     Breaks out of the current WHILE command.  This is meant to be used
     with conditional statements, to be able to exit the loop without
     having to get all the way to the DONE command, or to exit when the
     condition is still true.  Example:
          # count from 1 to 10
          seti $count = 1
          # this while statement is always true so would loop forever without break
          while 1 = 1
            echo "The count is " $count
            seti $count = $count + 1
            if $count > 10
              break
            endif
          done

'SETSCRATCHPAD'
     Manually set the scratchpad contents.  The format and use is the
     same as the SETBUFFER command.  The scratchpad is a second buffer
     that you can use.  The difference between the buffer and scratchpad
     is that the scratchpad is not used for direct disk command data
     transfers.  It is just for storing and manipulating any data you
     wish.

     There is one important difference from the SETBUFFER command.  The
     SETSCRATCHPAD command will allow for values greater than 255.  When
     this happens, it sets a quad word in the scratchpad, instead of
     just one byte.  This is in place to make it easier to write
     variable values to a file.  So be careful with this!

'ENDSCRATCHPAD'
     Required for ending the SETSCRATCHPAD command.

'PRINTSCRATCHPAD'
     Print the scratchpad to the screen.  The format and use is the same
     as the PRINTBUFFER command.

'STRINGTOSCRATCHPAD'
     Puts a string into the scratchpad contents.  The format and use is
     the same as the STRINGTOBUFFER command.

'CLEARSCRATCHPAD'
     Clears (erases) the entire scratchpad contents to zeros.

'SCRATCHPADSIZE'
     Sets a new scratchpad size.  The format and use is the same as the
     BUFFERSIZE command.

'WRITESCRATCHPAD'
     Write the scratchpad to a file.  The format is and use is the same
     as the WRITEBUFFER command.

'READSCRATCHPAD'
     Read a part of a file to the scratchpad.  The format and use is the
     same as the READBUFFER command.

'COPYSCATCHPADTOBUFFER'
     Copies a part of the scatchpad to the buffer.  The format is
     "COPYSCATCHPADTOBUFFER scratchoffset bufferoffset size", where
     scratchoffset is the starting offset of the scratchpad,
     bufferoffset is the starting offset of the buffer, and size is the
     number of bytes to copy.
          # copy 512 bytes from scratchpad to buffer
          copyscratchpadtobuffer 0 0 512

'COPYBUFFERTOSCRATCHPAD'
     Copies a part of the buffer to the scratchpad.  The format is
     "COPYBUFFERTOSCRATCHPAD bufferoffset scratchoffset size", where
     bufferoffset is the starting offset of the buffer, scratchoffset is
     the starting offset of the scratchpad, and size is the number of
     bytes to copy.
          # copy 512 bytes from buffer to scratchpad
          copybuffertoscratchpad 0 0 512

'VARIABLECHECK'
     Check if a variable has been set and what type it is.  The format
     is "VARIABLECHECK variable", where variable is the name of the
     variable to be checked.  The purpose of this is to check if a
     varaible was set properly on the command line.  The result is
     returned in $error_level.  A value of 0 = variable not set.  A
     value of 1 = variable is of number type but only set in script.  A
     value of 2 = varaible is of string type but only set in script.  A
     value of 17 = variable is of number type and is set on the command
     line.  A value of 18 = variable is of string type and is set on the
     command line.
          # check variable type for $input
          variablecheck $input
          if $error_level = 0
            echo "variable not set"
          elseif $error_level = 1
            echo "variable is number but not set on command line"
          elseif $error_level = 2
            echo "variable is string but not set on command line"
          elseif $error_level = 17
            echo "variable is number and was set on command line"
          elseif $error_level = 18
            echo "variable is string and was set on command line"
          endif

'GETFILESIZE'
     Get the size of a file.  The format is "GETFILESIZE filename",
     where filename is the name (with optional path) of the file.
     Filename can be the raw file name or a string that contains the
     file name.  The raw file name cannnot contain spaces.  If there are
     spaces, the file name must be in a string.  The size of the file in
     bytes is returned in $error_level.  If the file does not exist or
     there is some other error then $error_level will contain -1.
          # get the file size of the file "test.txt"
          getfilesize test.txt
          # get the file size of the file "the test.txt"
          sets $filename = "the test.txt"
          getfilesize $filename
          if error_level = -1
            echo "File not found"
          endif

'DELETEFILE'
     Delete a file.  The format is "DELETEFILE filename", where filename
     is the name (with optional path) of the file.  Filename can be the
     raw file name or a string that contains the file name.  The raw
     file name cannnot contain spaces.  If there are spaces, the file
     name must be in a string.
          # delete the file "test.txt"
          deletefile test.txt
          # delete the file "the test.txt"
          sets $filename = "the test.txt"
          deletefile $filename

'CALLCOMMAND'
     Perform a command line command.  The format is "CALLCOMMAND
     command", where command is the command line command to be
     performed.  The command can be a string varaible, or a single word
     command.  For commands that contain multiple words, you must use a
     string variable.
          # perform the command "ls -a"
          sets $command = "ls -a"
          callcommand $command

'USERINPUT'
     Get user input from keyboard.  The format is "USERINPUT variable",
     where variable is the string variable where the user input is
     placed.  This will pause the program waiting for the user to type
     something and then press enter.

     Example:
          echo "What would you like to do?"
          echo "1) Perform action 1"
          echo "2) Perform action 2"
          echo "3) Perform action 3"
          echo "Enter your choice:
          userinput $choicestring
          # extract the first number from the string
          seti $choice = $choicestring 0
          if $choice = 1
            echo "your choice was 1"
          elseif $choice = 2
            echo "your choice was 2"
          elseif $choice = 3
            echo "your choice was 3"
          else
            echo "invalid choice"
          endif

'WORDFLIPBUFFER'
     Flip the bytes within words from little endian to normal.  The
     format is "WORDFLIPBUFFER offset size", where offset is the offset
     in the buffer to start the flip and size is how many bytes to flip.
     If the size is an odd number the last byte will not be flipped.
     This command is useful for getting some proper readable information
     from the identify device command, such as the model and serial
     number.
          # show the model and serial number of a drive
          buffersize 512
          protocol pio-data-in
          direction from
          ata28cmd 0 0 0 0 0 0xa0 0xec
          wordflipbuffer 0 512
          sets $model = buffer 54 40
          echo "Model= " $model
          sets $serial = buffer 20 20
          echo "Serial= " $serial

'WORDFLIPSCRATCHPAD'
     Flip the bytes within words from little endian to normal.  The
     format and use is the same as the WORDFLIPBUFFER command.

'GETSTATUS'
     This will update the status and error registers ($ata_return_error,
     $ata_return_status, and $ata_alternate_status).  This only works
     for direct IO. For passthrough it attempts to send the proper
     protocol, but it would appear that Linux does not support that
     protocol and returns sense data of "invalid field in CDB".

'SOFTRESET'
     This performs a soft reset of the device.  Note that this will
     reset both devices on the controller.  This only works for direct
     IO. For passthrough it attempts to send the proper protocol, but it
     would appear that Linux does not support that protocol and returns
     sense data of "invalid field in CDB". To perform a soft reset using
     passthrough, use the REOPENDISK command.

'USLEEP'
     Sleep for x amount of microseconds.  The format is "USLEEP
     microseconds".  This is a way to make the program sleep without
     using CPU, perhaps waiting for a drive to become ready.
          echo "Sleeping for 5 seconds"
          USLEEP 5000000
          echo "Done sleeping"

'SOFTTIMEOUT'
     Only for direct IO, has no effect with passthrough.  When
     performing an ATA command, the time to wait before sending a soft
     reset.  The format is "SOFTTIMEOUT microseconds".  The default is
     15000000 (15s).  This is used to automatically perform a soft reset
     if a command times out, so that it does not have to be done
     manually.  If this happens, the register status will reflect the
     status after the soft reset.  The soft reset waits for the drive to
     be ready up to the value of RESETTIMEOUT after performing the reset
     before returning.  If you don't want to perform a soft reset when
     it times out, set the SOFTTIMEOUT value greater than the value of
     GENERALTIMEOUT.

'RESETTIMEOUT'
     Only for direct IO, has no effect with passthrough.  When
     performing an ATA command, the time to wait for the drive to be
     ready after a soft reset before returning.  The format is
     "RESETTIMEOUT microseconds".  The default is 15000000 (15s).

'BUSYTIMEOUT'
     Only for direct IO, has no effect with passthrough.  When
     performing an ATA command, the time to wait before giving up if the
     device is busy prior to issuing the command.  The format is
     "BUSYTIMEOUT microseconds".  The default is 15000000 (15s).  If you
     don't want the device to time out for being busy, set this value
     greater than the value of GENERALTIMEOUT.

'GENERALTIMEOUT'
     This timer is mostly for direct IO, but can also influence
     passthrough in some circumstances.  When performing a command, the
     time to wait before giving up if the command has not finished.  The
     format is "GENERALTIMEOUT microseconds".  The default is 30000000
     (30s).

'LOADSCRIPT'
     Loads a different script into memory.  The format is "LOADSCRIPT
     script", where script is the script file to be loaded.  This is
     mostly designed for a menu driven system.  All current variables
     will be passed on to the new script.  The new script will start
     from the beginning.

'PREVIOUSSCRIPT'
     Loads the previous script into memory, if there was one.  This is
     designed for a menu driven system.  When returning to the previous
     script, the previous script will start from the beginning.  All
     current varaibles will be passed on to the previous script.

'INCLUDE'
     This will append another script file to the end (bottom) the
     current one in memory.  The format is "INCLUDE script", where
     script is the script file to be loaded.  This is useful for
     including common subroutines without having to copy them into every
     script.

'UPLINE'
     Used for display purposes.  Moves the cursor up one line.  This is
     useful for repeating data on the screen without scrolling.

13 Scripts
**********

This section contains all the help available for the individual scripts.

   ata28_erase_sectors_pio
     Erase sector(s) from the disk using 28 bit write pio data-out command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to write.
     "count" is the number of sectors to write (max 256).
     Example: hddsupertool -t /dev/sda -f ata28_write_sectors_pio sector=0 count=1

   ata28_makebad
     Make a bad sector using the old 28 bit writelong command.
     This command is obsolete and not supported on all drives.
     This requires number variable "sector" to be set.
     "sector" is the starting sector to write.
     Example: hddsupertool -t /dev/sda -f ata28_makebad sector=0

   ata28_read_sectors_dma
     Read sector(s) from the disk using 28 bit read dma data-in command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to read.
     "count" is the number of sectors to read (max 256).
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be written to.
     Example: hddsupertool -t /dev/sda -f ata28_read_sectors_dma sector=0 count=1 file=="sector0.bin"
     Example: hddsupertool -t /dev/sda -f ata28_read_sectors_dma sector=2048 count=16 file=="sectors2048-2053.bin"

   ata28_read_sectors_pio
     Read sector(s) from the disk using 28 bit read pio data-in command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to read.
     "count" is the number of sectors to read (max 256).
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be written to.
     Example: hddsupertool -t /dev/sda -f ata28_read_sectors_pio sector=0 count=1 file=="sector0.bin"
     Example: hddsupertool -t /dev/sda -f ata28_read_sectors_pio sector=2048 count=16 file=="sectors2048-2053.bin"

   ata28_readlong
     Perform the old 28 bit readlong command.
     This command is obsolete and not supported on all drives.
     This requires number variables "sector" to be set.
     "sector" is the sector to read.
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be written to.
     Example: hddsupertool -t /dev/sda -f ata28_readlong sector=0 file=="longsector0.bin"

   ata28_write_sectors_dma
     Write sector(s) to the disk using 28 bit write dma data-out command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to write.
     "count" is the number of sectors to write (max 256).
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be read from.
     Example: hddsupertool -t /dev/sda -f ata28_write_sectors_dma sector=0 count=1 file=="sector0.bin"
     Example: hddsupertool -t /dev/sda -f ata28_write_sectors_dma sector=2048 count=16 file=="sectors2048-2053.bin"

   ata28_write_sectors_pio
     Write sector(s) to the disk using 28 bit write pio data-out command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to write.
     "count" is the number of sectors to write (max 256).
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be read from.
     Example: hddsupertool -t /dev/sda -f ata28_write_sectors_pio sector=0 count=1 file=="sector0.bin"
     Example: hddsupertool -t /dev/sda -f ata28_write_sectors_pio sector=2048 count=16 file=="sectors2048-2053.bin"

   ata48_erase_sectors_pio
     Erase sector(s) from the disk using 48 bit write pio data-out command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to write.
     "count" is the number of sectors to write (max 65536).
     Example: hddsupertool -t /dev/sda -f ata48_write_sectors_pio sector=0 count=1

   ata48_read_sectors_dma
     Read sector(s) from the disk using 48 bit read dma data-in command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to read.
     "count" is the number of sectors to read (max 65536).
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be written to.
     Example: hddsupertool -t /dev/sda -f ata48_read_sectors_dma sector=0 count=1 file=="sector0.bin"
     Example: hddsupertool -t /dev/sda -f ata48_read_sectors_dma sector=2048 count=16 file=="sectors2048-2053.bin"

   ata48_read_sectors_pio
     Read sector(s) from the disk using 48 bit read pio data-in command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to read.
     "count" is the number of sectors to read (max 65536).
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be written to.
     Example: hddsupertool -t /dev/sda -f ata48_read_sectors_pio sector=0 count=1 file=="sector0.bin"
     Example: hddsupertool -t /dev/sda -f ata28_read_sectors_pio sector=2048 count=16 file=="sectors2048-2053.bin"

   ata48_write_sectors_dma
     Write sector(s) to the disk using 48 bit write dma data-out command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to write.
     "count" is the number of sectors to write (max 65536).
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be read from.
     Example: hddsupertool -t /dev/sda -f ata48_write_sectors_dma sector=0 count=1 file=="sector0.bin"
     Example: hddsupertool -t /dev/sda -f ata48_write_sectors_dma sector=2048 count=16 file=="sectors2048-2053.bin"

   ata48_write_sectors_pio
     Write sector(s) to the disk using 48 bit write pio data-out command.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to write.
     "count" is the number of sectors to write (max 65536).
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be read from.
     Example: hddsupertool -t /dev/sda -f ata48_write_sectors_pio sector=0 count=1 file=="sector0.bin"
     Example: hddsupertool -t /dev/sda -f ata48_write_sectors_pio sector=2048 count=16 file=="sectors2048-2053.bin"

   ata48_write_uncorrectable
     Make bad sector(s) from the disk using 48 bit write uncorrectable non-data command.
     This creates a pseudo-uncorrectable error with logging.
     This requires number variables "sector" and "count" to be set.
     "sector" is the starting sector to write.
     "count" is the number of sectors to write (max 65536).
     Example: hddsupertool -t /dev/sda -f ata48_write_uncorrectable sector=0 count=1

   ata_disable_look_ahead
     Disable read look ahead.
     Example: hddsupertool -t /dev/sda -f ata_disable_look_ahead

   ata_enable_look_ahead
     Enable read look ahead.
     Example: hddsupertool -t /dev/sda -f ata_enable_look_ahead

   ata_identify_device
     This will send the identify device command to the drive and display the raw results.
     It will also display some of the drive capabilities and status.
     A value of 0 = not supported or not enabled.
     A value of 1 = supported or enabled.
     Example: hddsupertool -t /dev/sda -f ata_identify_device

   ata_scan_device
     This will scan the drive using the read verify command.
     Reads are done in blocks (clusters) of 256 sectors.
     This means that all warnings and errors show the position
      of the first sector of the block, NOT the actual problem sector.
     If the required variables below are not set on the command line,
      then you will be propted to enter them.
     This requires the number variable startsector to be set.
     This requires the number variable endsector to be set.
     If endsector is set to 0, it will default to the last addressable sector.
     This uses the identify device command to determine the last sector.
     This requires the number variable threshold to be set.
     Threshold is time in milliseconds.
     If a read exceeds the threshold, a warning will be given.
     If threshold is set to 0, it will default to 150ms.
     This requires the number variable softtimeout to be set.
     Softtimeout is the time in milliseconds to wait before giving up on a command.
     If softtimeout is set to 0, it will default to 10000ms.
     This requires the number variable hardtimeout to be set.
     Hardtimeout is the time to wait after a softreset before doing a hardreset.
     If hardtimeout is set to 0, it will default to 10000ms.
     This requires the string variable logfile to be set.
     Logfile will capture all the warnings and errors.
     This requires the string variable rateslog to be set.
     Rateslog will capture timing info that can be ploted.
     Rateslog captures the low, high, and average over 256 block reads.
     If logfile and/or ratesfile are blank no log will be produced.
     Example using defaults:
     hddsupertool -t /dev/sda -f ata_scan_device threshold=0 softtimeout=0 startsector=0 endsector=0 logfile=="" rateslog==""

   ata_sct_error_control_timer
     This command is not supported by all drives.
     View the results of the identify device command to check support.
     Get the value of the read error control timer.
     Optionally set the value of the read error control timer.
     This command uses the number variable "timer".
     Timer can be a value from 0-65535.
     The timer controls how much time before giving up on a read error.
     Normally this is in 100ms increments (value of 5 would be 500ms),
      but this is drive specific (try different values to see what happens).
     The default value is 0 (unlimited, all recovery proceedures are tried).
     This value is not permenant, it resets with a power cycle.
     If timer is not set it will only show the current value.
     Example to show current error timer:
       hddsupertool -t /dev/sda -f ata_sct_error_control_timer
     Example to set the error control timer to 1:
       hddsupertool -t /dev/sda -f ata_sct_error_control_timer timer=1

   ata_sct_readlong
     Perform an SCT read long command if supported.
     This command requires the number variable "sector" to be set on the command line.
     This also requires the string variable "file" to be set.
     "file" is the name of the file the data will be written to.
     Note that even if this command is supported, it may still be of no value.
     The ATA documentation states that the data returned may be encoded.
     And my experience so far is that the data is usually encoded and totally useless.
     So don't get your hopes up about using this command to get any worthwhile data.
     It is mainly a demonstration of using the SCT commands.
     Example: hddsupertool -t /dev/sdb -f ata48_sct_readlong sector=100 file=="sector100.bin

   ata_security_remove_password
     Remove the password from the disk using 28 bit security disable password command.
     This requires either the string variable "password" or "hex" to be set.
     Password is the password in plain text.
     Hex is the password in hex. It does not require 0x to proceed numbers.
     If neither password or hex is set then the password will be blank (all 0s).
     DO NOT SET BOTH or you could end up with undesired results!
     This requires the number variable "type" to be set on the command line.
     Type is either 0 for user password or 1 for master password.
     If type is not set it will default to 0.
     Example: hddsupertool -t /dev/sdb -f ata_security_remove_password password=="abcd" type=0
     Example: hddsupertool -t /dev/sdb -f ata_security_remove_password hex=="0a 0b 0c 0d" type=0

   ata_security_set_password
     Set the password from the disk using 28 bit security disable password command.
     This requires either the string variable "password" or "hex" to be set.
     Password is the password in plain text.
     Hex is the password in hex. It does not require 0x to proceed numbers.
     If neither password or hex is set then the password will be blank (all 0s).
     DO NOT SET BOTH or you could end up with undesired results!
     This requires the number variable "type" to be set on the command line.
     Type is either 0 for user password or 1 for master password.
     If type is not set it will default to 0.
     This requires the number variable "level" to be set on the command line.
     Level is either 0 for high security or 1 for maximum security.
     If level is not set it will default to 0.
     Example: hddsupertool -t /dev/sdb -f ata_security_set_password password=="abcd" type=0 level=0
     Example: hddsupertool -t /dev/sdb -f ata_security_set_password hex=="0a 0b 0c 0d" type=0 level=0

   ata_security_unlock
     Unlock the disk using 28 bit security unlock pio data-out command.
     This requires either the string variable "password" or "hex" to be set.
     Password is the password in plain text.
     Hex is the password in hex. It does not require 0x to proceed numbers.
     If neither password or hex is set then the password will be blank (all 0s).
     DO NOT SET BOTH or you could end up with undesired results!
     This requires the number variable "type" to be set on the command line.
     Type is either 0 for user password or 1 for master password.
     If type is not set it will default to 0.
     Example: hddsupertool -t /dev/sdb -f ata_security_unlock password=="abcd" type=0
     Example: hddsupertool -t /dev/sdb -f ata_security_unlock hex=="0a 0b 0c 0d" type=0

   ata_smart_data
     This will read the smart data from the drive and display the results.
     Example: hddsupertool -t /dev/sda -f ata_smart_data

   ata_status
     This will get the current drive status registers if direct IO.
     This does not work with passthrough.

   good_subroutines
     This contains common subroutines that are used by other scripts.
     This file is required by most scripts.

   hddmenu

     Main menu
     q) Quit
     h) Toggle script help
     1) Device information
     2) Read sectors
     3) Write sectors
     4) Erase sectors
     5) Tools
     6) Security
     7) VSC
     8) Custom

   hddsubmenu_custom

     Custom menu
     q) Quit
     p) Previous menu
     h) Toggle script help
     1) Custom message
     8) my scripts tech
     9) my scripts test

   hddsubmenu_erase

     Erase menu
     q) Quit
     p) Previous menu
     h) Toggle script help
     1) Erase sectors 28 PIO
     2) Erase sectors 48 PIO

   hddsubmenu_info

     Device information menu
     q) Quit
     p) Previous menu
     h) Toggle script help
     1) Identify device
     2) Smart info

   hddsubmenu_read

     Read sectors menu
     q) Quit
     p) Previous menu
     h) Toggle script help
     1) Read sectors PIO 28
     2) Read sectors PIO 48
     3) Read sectors DMA 28
     4) Read sectors DMA 48
     5) Readlong (old 28 bit)
     6) Readlong (48 bit SCT)

   hddsubmenu_security

     Security menu
     q) Quit
     p) Previous menu
     h) Toggle script help
     1) Security remove password
     2) Security set password
     3) Security unlock

   hddsubmenu_tools

     Tools menu
     q) Quit
     p) Previous menu
     h) Toggle script help
     1) Scan device
     2) Make a bad sector
     3) Write uncorrectable
     4) Disable read look ahead
     5) Enable read look ahead
     6) Error Control Timer (SCT)
     7) Reset Device
     8) Get device status
     9) Hard Reset

   hddsubmenu_vsc

     VSC menu
     q) Quit
     p) Previous menu
     h) Toggle script help
     1) WD dump mod 42 (older Caviar drives)
     2) WD royl (Marvel) dump mod 02
     3) WD royl (Marvel) dump mod 32
     4) WD royl (Marvel) patch mod 02 (slow fix)
     5) WD royl (Marvel) patch mod 32 (slow fix additional)
     6) WD royl (Marvel) dump all modules
     7) WD royl (Marvel) dump selected module
     8) WD royl (Marvel) read rom
     9) WD royl (Marvel) check rom file
     10) WD royl (Marvel) write rom (dangerous)
     11) WD royl (Marvel) write module (dangerous)

   hddsubmenu_write

     Write sectors menu
     q) Quit
     p) Previous menu
     h) Toggle script help
     1) Write sectors PIO 28
     2) Write sectors PIO 48
     3) Write sectors DMA 28
     4) Write sectors DMA 48

   reset
     This will soft reset the device if direct IO.
     If passthrough it will reopen the device.

   reset_hard
     This will hard reset the device if direct IO.
     If passthrough it will reopen the device.

   wd_dump_mod42
     Western Digital (older) dump module 42 to file using vendor specific commands.
     This will dump the first 3 sectors of the module to the file "mod42.bin".
     It will also show it on the screen.

   wd_royl_check_rom
     Western Digital ROYL check ROM file.
     This script performs some checks on a ROM file.
     This requires the text variable "file" to be set.
     "file" is the name of the file containing the ROM.
     This scipt does not perform any disk IO,
     so it can be ran with any target, even /dev/zero.

   wd_royl_dump_mod02
     Western Digital ROYL dump module 02 to file using vendor specific commands.
     By default this will dump the sectors of the module to the file "mod02.bin".
     It will also display the data on the screen.
     Note that some USB drives do not support these vendor specific commands.

   wd_royl_dump_mod32
     Western Digital ROYL dump module 32 to file using vendor specific commands.
     By default this will dump the sectors of the module to the file "mod32.bin".
     It will also display the data on the screen.
     Note that some USB drives do not support these vendor specific commands.

   wd_royl_dump_mod_all
     Western Digital ROYL dump all modules using vendor specific commands.
     This will dump the sectors of the modules to the files "modulexxxx.bin".
     Note that some USB drives do not support these vendor specific commands.

   wd_royl_dump_mod_select
     Western Digital ROYL dump a module to file using vendor specific commands.
     By default this will dump the sectors of the module to the file "mod0x(select).bin".
     It will also display the data on the screen.
     This requires the number variable "mod" to be set in DECIMAL.
     To enter a hex number preceed it with "0x".
     mod is the SA module to be read.

   wd_royl_patch_mod02
     Western Digital ROYL patch module 0x02 using vendor specific commands.
     This is to resolve a common WD slow issue, where the drive reads slow.
     Definition of the "slow responding issue":
      - The drive is reading very slow, but all reads are GOOD.
     This may not help any if the reads are bad due to a weak or bad head.
     WARNING: THIS IS DANGEROUS AND COULD KILL THE DRIVE!!!
     USE AT YOUR OWN RISK!!!
     Western Digital ROYL patch module 02 to file using vendor specific commands.
     Note that some USB drives do not support these vendor specific commands.
     This patch is meant for drives that suffer from the "slow" issue.
     This patch disables the background scanning on the drive.
     This patch is based on data from the following forum thread:
       WD - Fixing the "Slow Issue" manually :
       http://www.hddoracle.com/viewtopic.php?f=86&t=848
     This will dump the sectors to the file "<serial>_mod02orig.bin".
     And it will create the file "<serial>_mod02patched.bin".
     It will also create a folder using the model and serial as the folder name,
      and create a backup dump file with the date and time as part of the name.
     It will create a backup dump every time a read or write is attempted.
     The drive must be power cycled for the changes to take effect.
     You have three options:
     1) Read the module to a file and create the patch.
     2) Write the patched data back to the disk.
     3) Restore the original dump.

   wd_royl_patch_mod32
     Western Digital ROYL patch module 0x32 using vendor specific commands.
     This is to resolve a common WD slow issue, where the drive reads slow.
     Definition of the "slow responding issue":
      - The drive is reading very slow, but all reads are GOOD.
     This may not help any if the reads are bad due to a weak or bad head.
     WARNING: THIS IS DANGEROUS AND COULD KILL THE DRIVE!!!
     USE AT YOUR OWN RISK!!!
     This patch may not be needed if the module 0x02 patch fixes the slow issue.
     You should perform the module 0x02 patch first and power cycle the drive.
     If the module 0x02 patch works, then do not bother with this patch.
     Western Digital ROYL patch module 32 to file using vendor specific commands.
     Note that some USB drives do not support these vendor specific commands.
     This patch is meant for drives that suffer from the "slow" issue.
     This patch clears some data in the RE-LO list.
     However, it may not clear everything that is needed, and is a bit of a hack.
     It is intended be used along with the module 02 patch.
     However, it is normally not needed if the module 02 patch solves the slow issue.
     This patch is based on data from the following forum thread:
       WD - Fixing the "Slow Issue" manually :
       http://www.hddoracle.com/viewtopic.php?f=86&t=848
     This will dump the sectors to the file "<serial>_mod32orig.bin".
     And it will create the file "<serial>_mod32patched.bin".
     It will also create a folder using the model and serial as the folder name,
      and create a backup dump file with the date and time as part of the name.
     It will create a backup dump every time a read or write is attempted.
     The drive must be power cycled for the changes to take effect.
     You have three options:
     1) Read the module to a file and create the patch.
     2) Write the patched data back to the disk.
     3) Restore the original dump.

   wd_royl_read_rom
     Western Digital ROYL read ROM to file using vendor specific commands.
     Note that some USB drives do not support these vendor specific commands.
     This requires the text variable "file" to be set.
     "file" is the name of the file to dump the ROM.

   wd_royl_write_mod
     Western Digital ROYL write module from file using vendor specific commands.
     WARNING: THIS IS DANGEROUS AND COULD KILL THE DRIVE!!!
     USE AT YOUR OWN RISK!!!
     It is IMPORTANT to use 0x to select the module number in HEX!
     The difference between decimal and hex COULD KILL THE DRIVE!!!
     This modifies data in the service area of the drive!
     If you don't know what you are doing, then don't do it!
     Western Digital ROYL write module from file using vendor specific commands.
     Note that some USB drives do not support these vendor specific commands.
     WARNING! THIS SCRIPT COULD BE DANGEROUS IF YOU DO NOT KNOW WHAT YOU ARE DOING!
     It will create a folder using the model and serial as the folder name,
      and create a backup dump file with the date and time as part of the name.
     It will create a backup dump every time a read or write is attempted.
     The checksum will be recalculated if it not correct.
     This requires the number variable "mod" to be set in DECIMAL.
     To enter a HEX number preceed it with "0x" (IMPORTANT TO SELECT CORRECT MODULE).
     "mod" is the SA module to be written.
     This requires the text variable "file" to be set.
     "file" is the file which is to be written to the module.

   wd_royl_write_rom
     Western Digital ROYL write rom from file using vendor specific commands.
     WARNING: THIS IS DANGEROUS AND COULD KILL THE DRIVE!!!
     THIS IS EVEN MORE DANGEROUS OVER USB!!!
     DO NOT STOP THIS PROCESS OR REMOVE POWER FROM THE DRIVE!!!
     IF THE ROM GETS ERASED BUT NOT WRITTEN, DO NOT REMOVE POWER!!!
     USE AT YOUR OWN RISK!!!
     If you write an incompatible ROM you could kill the drive!
     If the erase works but the write fails, you could kill the drive!
     In this emergency case, use slow and stupid mode to attempt to write.
     Do not use slow and stupid mode unless you erased the rom and are stuck.
     It is recommended to perform another ROM dump and check after writing
       to be sure it worked. Use the other scripts for these functions.
     If the script fails for any reason, it is recommended to do another dump
       and check to make sure ROM is still in good condition.
     This requires the text variable "file" to be set.
     "file" is the name of the file to dump the rom.
     This requires the number variable "slow_and_stupid" to be set.
     "slow_and_stupid" is an emergency mode if the flash is erased but not written.
     A value of 0 is off, any other value is on.
     It is not recommended to use slow_and_stupid unless needed.

Index
*****

* Menu:

* Default Variables:                     Default Variables.  (line  554)
* How to Hide a Drive from the OS:       How to Hide a Drive from the OS.
                                                             (line   77)
* Important Notes:                       Important Notes.    (line  206)
* Installing:                            Installing.         (line  232)
* introduction:                          Introduction.       (line   23)
* Reporting Bugs:                        Reporting Bugs.     (line  540)
* Script Commands:                       Script Commands.    (line  778)
* Script Examples:                       Script Examples.    (line  637)
* Scripts:                               Scripts.            (line 1527)
* Tips and Tricks:                       Tips and Tricks.    (line  513)
* Usage:                                 Usage.              (line  315)
* USB Drives:                            USB Drives.         (line  191)
* WARNING:                               WARNING.            (line   33)

