



seti $printhelp = $printhelp
seti $help = $help
if $help = 1
  echo 'WD read ABA'

  if $printhelp = 1
    exit 0
  endif
  echo 'Hit ENTER to continue...'
  userinput $choicestring
  previousscript
endif
echo ""

include good_subroutines

# set a blank string variable to compare with user input
# make sure not to set this anyplace else
sets $null = ""

# set this to itself for use with the menu system
# make sure not to set this anyplace else
# if it was not previously set it will = 0
seti $using_menu = $using_menu

# set the file name to be read from
while 1 = 1
  variablecheck $file
  if $error_level < 16
    seti $ask = 1
  elseif $using_menu = 1
    seti $ask = 1
  endif
  if $ask = 1
    echo "Enter file name:"
    userinput $choicestring
    if $choicestring != $null
      sets $file = $choicestring
      break
    else
      echo "Choice cannot be blank!"
    endif
  else
    break
  endif
done

sets $base_file_name = $file
deletefile $file

while 1 = 1
  echo "Enter ABA in decimal (0x for hex):"
  userinput $choicestring
  if $choicestring != $null
    seti $aba_to_translate = $choicestring 0
    break
  else
    echo "Choice cannot be blank!"
  endif
done

while 1 = 1
  echo "Enter sector count in decimal (0x for hex):"
  userinput $choicestring
  if $choicestring != $null
    seti $sector_count_to_read = $choicestring 0
    if $sector_count_to_read = 0
      echo "Choice cannot be zero!"
    else
      break
    endif
  else
    echo "Choice cannot be blank!"
  endif
done

while 1 = 1
  echo "Enter head in decimal (0x for hex):"
  userinput $choicestring
  if $choicestring != $null
    seti $head_start = $choicestring 0
    break
  else
    echo "Choice cannot be blank!"
  endif
done



seti $read_block_size = 512 * 128
seti $initial_read_size = 512 * 16


seti $negative_cylinders = 0
seti $sectors_per_cylinder = 0
gosub find_sectors_per_track
seti $total_aba = $negative_cylinders * $sectors_per_cylinder
hex
sets $lstring = "0x" $total_aba
decimal
echo "Total ABA = " $total_aba " (" $lstring ")"

seti $aba_start = $aba_to_translate
gosub translate_aba_to_chs
seti $cylinder_start = $cylinder
seti $sector_start = $sector

seti $aba_end = $aba_start + $sector_count_to_read
seti $aba_to_translate = $aba_end
gosub translate_aba_to_chs
seti $cylinder_end = $cylinder
seti $sector_end = $sector
if $aba_end >= $total_aba
  echo "Read size is beyond end of ABA"
  previousscript
endif

gosub read_aba_section


previousscript
end





subroutine find_sectors_per_track
  seti $command_failed = 0
  seti $total_heads = 0
  seti $head_bitmap = 0
  seti $negative_cylinders = 0
  gosub read_data_table
  if $head_start >= $total_heads
    echo "Head chosen is greater than available heads"
    previousscript
  endif

  seti $bitmap = $head_bitmap > $head_start
  seti $bitmap = $bitmap & 1
  if $bitmap < 1
    echo "Head chosen is not active"
    previousscript
  endif

  seti $cylinder_start = 0 - $negative_cylinders
  seti $cylinder_start = $cylinder_start + 1
  seti $found_aba = 0

  seti $cylinder = $cylinder_start
  seti $head = $head_start
  seti $sector = 1
  gosub translate_chs_to_lba
  echo "Sectors per cylinder = " $found_aba
  seti $sectors_per_cylinder = $found_aba
endsubroutine





subroutine translate_chs_to_lba

  gosub enable_vsc

  # vsc to prepare for translate
  echo "prepare to translate chs to lba"
  buffersize 0x200
  clearbuffer
  seti $offsetl = $cylinder & 0xff
  seti $offsetm1 = $cylinder > 8
  seti $offsetm1 = $offsetm1 & 0xff
  seti $offsetm2 = $cylinder > 16
  seti $offsetm2 = $offsetm2 & 0xff
  seti $offseth = $cylinder > 24
  seti $offseth = $offseth & 0xff

  seti $sectorl = $sector & 0xff
  seti $sectorh = $sector > 8
  seti $sectorh = $sectorh & 0xff

  seti $head = $head & 0xff
  setbuffer 0
    16 00  $offsetl $offsetm1  $offsetm2 $offseth  $head 00  $sectorl $sectorh
  endbuffer
  hex
  #echo "keysector= 16 00  " $offsetl " " $offsetm1 "  "  $offsetm2  " " $offseth "  " $head " 0  "  $sectorl " " $sectorh
  setwritepio
  ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
  #echo "command= d6 01 be 4f c2 a0 b0"
  decimal
  # check if command failed
  gosub status_check
  # vsc to read result
  buffersize 0x200
  clearbuffer
  setreadpio
  echo "reading result"
  ata28cmd 0xd5 0x01 0xbf 0x4f 0xc2 0xa0 0xb0
  hex
  #echo "command= d5 01 bf 4f c2 a0 b0"
  decimal
  # check if command failed
  gosub status_check
  scratchpadsize 0x200
  copybuffertoscratchpad 0 0 512

  gosub disable_vsc

  #printscratchpad 0 32

  seti $lba = scratchpad 2 qw
  seti $lba = $lba & 0xffffffffffff
  hex
  sets $lstring = "0x" $lba
  decimal
  #echo "lba = " $lba " (" $lstring ")"
  seti $found_aba = $lba

endsubroutine





subroutine translate_aba_to_chs
  seti $cylinder = $aba_to_translate / $sectors_per_cylinder
  seti $cylinder = $cylinder - $negative_cylinders
  seti $sector = $aba_to_translate % $sectors_per_cylinder
  seti $sector = $sector + 1
  echo "cylinder=" $cylinder
  echo "sector=" $sector
  echo "head=" $head_start

  # verify result
  gosub translate_chs_to_lba
  echo "translated back to aba = " $found_aba
  if $found_aba != $aba_to_translate
    echo "Reverse translation did not match!"
    echo "ABA requested = " $aba_to_translate
    echo "Translated back = " $found_aba
    previousscript
  endif
endsubroutine





subroutine read_aba_section
  seti $cylinder = $cylinder_start
  seti $sector = $sector_start
  seti $data_count = 0
  while $data_count < $sector_count_to_read
    seti $data_remaining = $sector_count_to_read - $data_count
    seti $blocks = $read_block_size / 512
    if $blocks > $data_remaining
      seti $blocks = $data_remaining
    endif
    seti $remaining_sectors_in_track = $sectors_per_cylinder - $sector
    seti $remaining_sectors_in_track = $remaining_sectors_in_track + 1
    if $blocks > $remaining_sectors_in_track
      seti $blocks = $remaining_sectors_in_track
    endif
    seti $read_size = $blocks * 512
    gosub read_chs
    seti $sector = $sector + $blocks
    if $sector > $sectors_per_cylinder
      seti $sector = 1
      seti $cylinder = $cylinder + 1
    endif

    seti $data_count = $data_count + $blocks
  done
endsubroutine





subroutine read_chs
  gosub enable_vsc

    echo "head=" $head "  cylinder=" $cylinder "  sector=" $sector "  size=" $blocks
    # vsc to prepare for chs read
    #echo "prepare to read chs"
    buffersize 0x200
    clearbuffer
    seti $offsetl = $cylinder & 0xff
    seti $offsetm1 = $cylinder > 8
    seti $offsetm1 = $offsetm1 & 0xff
    seti $offsetm2 = $cylinder > 16
    seti $offsetm2 = $offsetm2 & 0xff
    seti $offseth = $cylinder > 24
    seti $offseth = $offseth & 0xff

    seti $sectorl = $sector & 0xff
    seti $sectorh = $sector > 8
    seti $sectorh = $sectorh & 0xff

    seti $sizel = $read_size & 0xff
    seti $sizem1 = $read_size > 8
    seti $sizem1 = $sizem1 & 0xff
    seti $sizem2 = $read_size > 16
    seti $sizem2 = $sizem2 & 0xff
    seti $sizeh = $read_size > 24
    seti $sizeh = $sizeh & 0xff

    seti $sizel = 0
    seti $sizem1 = 0
    seti $sizem2 = 0
    seti $sizeh = 0

    setbuffer 0
      0c 00  01 00  $offsetl $offsetm1  $offsetm2 $offseth  $head 00  $sectorl $sectorh  $sizel $sizem1 $sizem2 $sizeh
    endbuffer
    hex
    #echo "keysector= 0c 00  01 00  " $offsetl " " $offsetm1 " " $offsetm2 " " $offseth "  " $head " 00  " $sectorl " " $sectorh "  " $sizel " " $sizem1 " " $sizem2 " " $sizeh
    setwritepio
    ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
    #echo "command= d6 01 be 4f c2 a0 b0"
    decimal
    # check if command failed
    gosub status_check

    # vsc to read chs
    seti $sectors = $read_size / 512
    buffersize $read_size
    clearbuffer
    setreadpio
    #echo "reading chs"
    ata28cmd 0xd5 $sectors 0xbf 0x4f 0xc2 0xa0 0xb0
    hex
    #echo "command= d5 " $sectors " bf 4f c2 a0 b0"
    decimal
    # check if command failed
    gosub status_check

    seti $write_offset = $data_count * 512
    # write the buffer to file
    writebuffer $file 0 $write_offset $read_size

  gosub disable_vsc
  #echo "chs read done"
endsubroutine





subroutine read_data_table
  gosub enable_vsc

  # vsc to prepare to get drive data table
  echo "prepare to get data table"
  buffersize 0x200
  clearbuffer
  setbuffer 0
    0d 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00
  endbuffer
  setwritepio
  ata28cmd 0xd6 0x01 0xbe 0x4f 0xc2 0xa0 0xb0
  # check if command failed
  gosub status_check

  # vsc to get to get drive data table
  echo "getting data table"
  buffersize 0x200
  clearbuffer
  setreadpio
  ata28cmd 0xd5 0x01 0xbf 0x4f 0xc2 0xa0 0xb0
  # check if command failed
  gosub status_check
  copybuffertoscratchpad 0 0 512

  gosub disable_vsc

  echo "data table read done"

  #printscratchpad 0 512
  seti $value = 0

  seti $offset = 29
  seti $bytes = 1
  gosub process_offset
  seti $total_heads = $value

  seti $offset = 31
  seti $bytes = 1
  gosub process_offset
  seti $head_bitmap = $value

  seti $offset = 36
  seti $bytes = 2
  gosub process_offset
  seti $negative_cylinders = $value

endsubroutine





subroutine process_offset
  if $bytes = 1
    seti $value = scratchpad $offset b
  elseif $bytes = 2
    seti $value = scratchpad $offset w
  elseif $bytes = 4
    seti $value = scratchpad $offset dw
  elseif $bytes = 8
    seti $value = scratchpad $offset qw
  else
    seti $value = 0
    echo "BYTE COUNT OUT OF RANGE"
  endif
  hex
  sets $offset_string = "0x" $offset
  sets $value_string = "0x" $value
  sets $bytes_string = "0x" $bytes
  decimal
  #echo "offset=" $offset " (" $offset_string ")  value=" $value " (" $value_string ")(" $bytes " bytes)"
endsubroutine







subroutine status_check
  seti $command_failed = 0
  gosub check_command_status
  if $command_failed = 1
    echo "Command failed!"
    gosub show_sense_data
    gosub show_ata_return_status
    previousscript
  endif
endsubroutine



subroutine status_check_no_stop
  seti $command_failed = 0
  gosub check_command_status
  if $command_failed = 1
    echo "Command failed!"
    gosub show_sense_data
    gosub show_ata_return_status
  endif
endsubroutine



subroutine enable_vsc
  # enable vendor specific commands
  #echo "enable vsc"
  buffersize 0
  setreadpio
  ata28cmd 0x45 0x0b 0x00 0x44 0x57 0xa0 0x80
  # check if command failed
  gosub status_check
endsubroutine



subroutine disable_vsc
  # disable vendor specific commands
  #echo "disable vsc"
  buffersize 0
  setreadpio
  ata28cmd 0x44 0x0b 0x00 0x44 0x57 0xa0 0x80
  # check if command failed
  gosub status_check
endsubroutine



