HP Forums
(71B) 82161A Low Level Tape Dump - Printable Version

+- HP Forums (https://www.hpmuseum.org/forum)
+-- Forum: HP Software Libraries (/forum-10.html)
+--- Forum: General Software Library (/forum-13.html)
+--- Thread: (71B) 82161A Low Level Tape Dump (/thread-16513.html)



(71B) 82161A Low Level Tape Dump - Sylvain Cote - 03-22-2021 10:29 PM

Hello all,
Mark Power from HPCC asked me to help him do a raw dump of some of his verbatim MI tapes. (MI-50 & MI-80)
The verbatim MI cassettes are compatible with HP-82176A mini data cassette. (both seems to be made by Verbatim)
His cassettes was formatted and used on a non HP drive unit but used the same drive mechanism that HP used for his 82161A.
I cannot use any high level functions because they all assumed that the data cassette are LIF formatted.
So I wrote this program that uses low level DDL/DDT commands to do the tape dump and to manually control the interface loop.
Sylvain

Summary

The program read the tape starting from the first sector of the first track to last sector of the same track, rewind the tape and then do the same for each other tracks.
The current configuration of the program target the HP-82161A unit who has two tracks (0 & 1) of 256 sectors each (0 to 255).
The program handle drive readiness and drive errors.
The unrecoverable errors end the program while a retry loop has been implemented for recoverable errors.
Status messages are displayed for each steps.
Because the tape content is saved in a file in main memory, you need at least 140KB of free main RAM to run this program.
Two files are generated, the first one (TD for TapeDump) contains the file sectors while the second one (TE for TapeErrors) contains the errors.

Constants
  • A : hold drive loop address, currently set to 1.
  • R1 : number of retries for recoverable errors, currently set to 3 times.
  • T1 : number tracks, currently set to 2 tracks.
  • S1 : number of sectors, currently set to 256 sectors.
  • S2 : size of a sector, currently set to 256 bytes. (if you change that value, line 105 and 110 must also be changed)
Note 1: these constants are defined at line 115, adjust the values to match your setup or preference
Note 2: if you choose another drive type, uncomment line 510 and comment line 515

Code:
 10 ! TAPEDUMP by Sylvain Cote
 11 ! last updated on: 2021-03-20 21h10 EDT
 12 ! Desc: do a sector by sector tape dump to a file in main memory
 13 ! Need: 71B, 82401A, ~140KB of main RAM

 30 ! A   : DriveAddress       (constant)
 31 ! B   : DriveBusyFlag
 32 ! C   : DriveErrorCode
 33 ! D   : DeviceAccessoryID
 34 ! E   : DriveErrorFlag
 35 ! L   : DriveErrorLevel
 36 ! L0  : InputBufferLength
 37 ! L2  : LogDriveError
 38 ! R0  : ActiveReadTimes
 39 ! R1  : MaxReadTimes       (constant)
 40 ! S   : DriveStatus
 41 ! S0  : TapeSectorActive
 42 ! S1  : TapeSectorNumbers  (constant)
 43 ! S2  : TapeSectorSize     (constant)
 44 ! S3  : TapeSeekFlag       : tell the drive to do a tape seek if set to 1
 45 ! T1  : TapeTrackNumbers   (constant)
 50 ! B0$ : InputBuffer
 51 ! M$  : DriveErrorLevel

100 OPTION BASE 0                                                                         ! array index start at 0
105 DIM B0$[256]                                                                          ! input buffer creation
110 IMAGE #,256A                                                                          ! input format
115 A=1 @ R1=3 @ T1=2 @ S1=256 @ S2=256                                                   ! app constants
120 S=0 @ B=0 @ E=0 @ C=0 @ L=0 @ M$=""                                                   ! init values
125 B0$="" @ L0=0 @ D=0 @ L2=0 @ R0=0                                                     ! init values
130 SFLAG -1 @ PURGE TD @ PURGE TE @ CFLAG -1                                             ! delete old files, disregard error if files are missing
135 CREATE TEXT TD @ CREATE TEXT TE                                                       ! create TapeDump and TapeError files
140 ASSIGN #1 TO TD @ ASSIGN #2 TO TE                                                     ! open TapeDump and TapeError files
145 SFLAG -23                                                                             ! use variable size as tape read length
150 DELAY 0,0                                                                             ! set display and scrolling delays
155 RESET HPIL @ RESTORE IO                                                               ! reset loop
160 GOSUB 'AIDCHECK'                                                                      ! verify that we have a tape drive at specified loop address
165 GOSUB 'REWIND'                                                                        ! rewind tape
170 S3=1                                                                                  ! seek tape to track 0 sector 0
175 FOR T0=0 TO T1-1                                                                      ! track outer loop
180   FOR S0=0 TO S1-1                                                                    !   sector inner loop
185     GOSUB 'READSEC'                                                                   !     read sector from tape
190   NEXT S0                                                                             !   sector inner loop end
195 NEXT T0                                                                               ! track outer loop end
200 GOSUB 'REWIND'                                                                        ! rewind tape
205 ASSIGN #1 TO * @ ASSIGN #2 TO *                                                       ! close files
210 CFLAG -23 @ DELAY 1,1/8                                                               ! restore environment
215 DISP "DUMP DONE"                                                                      ! warn
220 END                                                                                   ! end of program

500 ! device accessory id check                                                           !
505 'AIDCHECK': ! IN: A / UPD: D / OUT: -                                                 ! sub check device type at loop address
510 ! D=DEVAID(A) @ IF D DIV 16#1 THEN DISP "Err: Invalid Device" @ STOP                  !   get accessory id and if device type is a mass storage then stop the program
515   D=DEVAID(A) @ IF D#16       THEN DISP "Err: Invalid Device" @ STOP                  !   get accessory id and if device is not a 82161A then stop the program
520 RETURN                                                                                ! end sub

525 ! loop until drive is ready                                                           !
530 'BUSYWAIT': ! IN: A / UPD: S / OUT: -                                                 ! sub wait until drive is ready
535   'BW': S=SPOLL(A) @ IF BIT(S,5)=1 THEN GOTO 'BW'                                     !   loop until drive is no longer busy
540 RETURN                                                                                ! end sub

545 ! reset drive status variables                                                        !
550 'RSETSTAT': ! IN: A / UPD: S,B,E,C,L / OUT: -                                         ! sub reset status variables
555   S=0 @ B=0 @ E=0 @ C=0 @ L=0                                                         !   set drive status related variables to 0
560 RETURN                                                                                ! end sub

565 ! read & decode drive status byte                                                     !
570 'READSTAT': ! IN: A / UPD: - / OUT: S,B,E,C,L                                         ! sub read and decode drive status
575   S=SPOLL(A) @ B=BIT(S,5) @ E=BIT(S,4) @ C=BINAND(S,15)                               !   read drive status and get busy flag, error flag and error code
580   IF E=0 AND B=0 THEN L=0 @ RETURN                                                    !   if drive not in error and not busy -> set error level to normal  and return
585   IF E=0 AND B=1 THEN L=1 @ RETURN                                                    !   if drive not in error but is busy  -> set error level to warning and return
590   IF C=9 OR C=10 THEN L=1 ELSE L=2                                                    !   if drive error is recoverable      -> set error level to warning otherwise set error level to
595 RETURN                                                                                ! end sub

600 ! build status message                                                                !
605 'BUILDMSG': ! IN: B,E,C,L / UPD: - / OUT: M$                                          ! sub build drive status message
610   IF E=0 AND B=0 THEN M$=""             @ RETURN                                      !   drive is normal, return
615   IF E=0 AND B=1 THEN M$="Drive Busy"   @ GOTO 'BM'                                   !   drive is busy
620   IF C=9         THEN M$="Rec Number"   @ GOTO 'BM'                                   !   unexpected record number, tape read failed, try to re-read the sector
625   IF C=10        THEN M$="Rec Checksum" @ GOTO 'BM'                                   !   invalid record checksum, tape read failed, try to re-read the sector
630   IF C=7         THEN M$="New Tape"     @ GOTO 'BM'                                   !   new tape has been inserted in the drive and need to be seeked
635   IF C=4         THEN M$="No Tape"      @ GOTO 'BM'                                   !   there is no tape in drive
640   IF C=8         THEN M$="Time Out"     @ GOTO 'BM'                                   !   no data record has been found on the tape
645   IF C=3         THEN M$="Tape:EOT+TS"  @ GOTO 'BM'                                   !   unexpected end of tape has been reached AND tape has stalled
650   IF C=1         THEN M$="End of Tape"  @ GOTO 'BM'                                   !   unexpected end of tape has been reached
655   IF C=2         THEN M$="Tape Stalled" @ GOTO 'BM'                                   !   tape has stalled
660   IF C=5 OR C=6  THEN M$="Device"       @ GOTO 'BM'                                   !   generic device error
665   IF C=12        THEN M$="Tape Size"    @ GOTO 'BM'                                   !   track number greather than 1 has been requested
670                       M$="Unknown"                                                    !   unknown error (covers code=0, 11, 13, 14 & 15)
675   'BM': ! build message                                                               !   build message
680   IF L=1 THEN M$="Wrn:"&STR$(C)&":"&M$                                                !   warning message
685   IF L=2 THEN M$="Err:"&STR$(C)&":"&M$                                                !   error message
690 RETURN                                                                                ! end sub

695 ! verify that drive is ready and not in error                                         !
700 'PRECHECK': ! IN: A / UPD: S,B,E,C,L,M$ / OUT: -                                      ! sub pre-check before doing a drive operation
705   GOSUB 'BUSYWAIT' @ GOSUB 'READSTAT' @ M$=""                                         !   wait for drive to be ready, then read current status and decode it
710   IF L=2 THEN GOSUB 'BUILDMSG' @ DISP M$ @ STOP                                       !   if error level is error then display error message then stop the program
715 RETURN                                                                                ! end sub

720 ! rewind drive tape                                                                   !
725 'REWIND': ! IN: A / UPD: S,B,E,C,L,M$ / OUT: -                                        ! sub rewind tape
730   GOSUB 'PRECHECK'                                                                    !   pre-check drive for readyness
735   DISP "Rewinding Tape ..."                                                           !   tell user the action to be taken
740   SEND UNT UNL LISTEN A DDL 7                                                         !   rewind tape
745   GOSUB 'BUSYWAIT'                                                                    !   wait for drive to be ready
750 RETURN                                                                                ! end sub

755 ! position drive head to the specified track & sector                                 !
760 'SEEK': ! IN: A,T0,S0 / UPD: S,B,E,C,L,M$ / OUT: -                                    ! sub seek track:record
765   GOSUB 'PRECHECK'                                                                    !   pre-check drive for readyness
770   DISP "Seek: T="&STR$(T0)&" S="&STR$(S0)                                             !   tell user the action to be taken
775   SEND UNT UNL MTA LISTEN A DDL 4 DATA T0 DATA S0                                     !   seek tape and wait for drive to be ready
780   GOSUB 'BUSYWAIT'                                                                    !   wait for drive to be ready
785 RETURN                                                                                ! end sub

790 ! Set Drive in Read Mode - Drive Fill Buffer 0 with Current Sector                    !
795 'READMODE': ! IN: A / UPD: - / OUT: -                                                 ! sub activate data transfert mode
800   DISP "Read mode activated"                                                          !   tell user the action to be taken
805   SEND UNT UNL TALK A DDT 2                                                           !   drive set in read mode, trigger the drive to fill buffer 0 with current sector
810 RETURN                                                                                ! end sub

815 ! Read Sector                                                                         !
820 'READSEC': ! IN: A,R1,T0,S0,S2,S3,#1,#2 / UPD: R0,S,B,E,C,L,M$,B0$,L0,S3 / OUT: -     ! sub read sector
825   FOR R0=1 TO R1                                                                      !   read times loop
830     IF S3=1 THEN GOSUB 'SEEK' @ GOSUB 'READMODE' @ S3=0                               !     activate data transfer from tape drive
835     DISP "Read T:"&STR$(T0)&" S:"&STR$(S0)&" #"&STR$(R0)                              !     tell user the action to be taken
840     ENTER :A USING 110;B0$ @ L0=LEN(B0$)                                              !     get drive buffer 0, trigger the drive to fill buffer 0 with next sector
845     GOSUB 'BUSYWAIT' @ GOSUB 'READSTAT'                                               !     wait for drive to be ready & get drive status
850     IF L=0 AND L0=S2 THEN PRINT #1;B0$ @ RETURN                                       !     if no error and record length is valid then save record and return
855     IF L=0 THEN DISP "Wrn: Inv.Rec.Length" @ PRINT #2;B0$ @ BEEP 440,1 @ RETURN       !     if no error and record length is invalid then log data and return
860     IF L=1 THEN GOSUB 'BUILDMSG' @ DISP M$ @ BEEP 523,1 @ S3=1                        !     there was an problem reading the tape, warn user
865     IF L=2 THEN GOSUB 'BUILDMSG' @ DISP M$ @ STOP                                     !     if error level is error then display error message then stop the program
870   NEXT R0                                                                             !   end loop
875   PRINT #2;":T="&DTH$(T0)[5]&":S="&DTH$(S0)[4,5]&":E="&DTH$(S)[5]&":"                 !   too many retry, log error (ex.: ":T=1:S=A8:E=A:")
880   DISP "Wrn: Skipped Bad Rec." @ BEEP 440,1 @ S3=1                                    !   warn user, next record will be seeked
885 RETURN                                                                                ! end sub

Note 3: click on the "View a Printable Version" URL at the bottom of this page to see the complete listing.
Note 4: if you want to run this program, do a block copy without the rightmost comments in order to fit within the 96 characters line limit.