Close

Whispering in host mode

A project log for THE PERTEC WHISPERER-MAINFRAME TAPE DRIVE EMULATOR

A.K.A. THE 9 TRACK TAPE DRIVE COMMUNICATOR Talking to Mainframes Era Reel to Reel 9 track tape drives

skaarj[skaarj] 06/14/2019 at 15:370 Comments






















This one was a little tricky to develop so it took some more time than expected. 

Here is what had to be done:

1. Establish communication with the tape drive. For this to happen, the following steps are required:

   - select the tape drive using /ITAD lines (transport address 0 and 1);

   - issue a short /IFAD pulse of a few uSecs in order to abort any current interruptible operation the tape drive is performing;

   - issue a short /IREW pulse to make sure the drive stays at BOT;

   - select the data density - 1600 bytes per inch for now: /IWFM+/IEDIT+/IERASE down at the same time,  pulse  /IGO and those three up.

   The tape drive should now issue the following status lines active:

/IONL  (online)    /IRDY  (ready)   /ILDP  (BOT, begin of tape or load point),  /IFPT (file protect) if manually selected on the drive.

2. Start the data transfer:

The data transfer starts when the drive receives a /IGO pulse and the rest is described in the previous chapter - catch /IRSTR, /IDBY, /IFBY and /IFMK using prioritized interrupt lines, fill a 32kB buffer (max buffer size as specified in most of the MsDos pertec drivers), dump it into the SPI RAM Buffer via DMA channel.  Each time the entire 2 MBytes RAM Buffer is filled, the operations are paused, the drive waits for a new /IGO while rewinding at the end of the last read block, in the mean time the entire 2 MBytes RAM Buffer is dumped on the microSD card, cleared and the transfer resumes until 2 x /IFMK or /EOT (end of tape) are signaled.

3. Store the data either for fun/inspection/museum purpose or for usage in a physical mainframe environment:

  So I have this big chunk of a 40MB 9-track tape drive data dumped inside a microSD card describing some eastern block communist old plans for building the most reliable agricultural tractor in the world. I can either stare at the data - nobody has it in the original format anymore - or I can move things further and load it into a mainframe in order to get access to the top secret development plans.

For the first variant there is no need to replicate the separation into distinct blocks and filemarks. 

However if I really want to build my own tractor and take over the fields  in my area, I have to push the things a little further and acquire the blocks and filemarks displacement scheme into a map and replicate them by pulsing the corresponding PERTEC lines on the interface while playing in the DRIVE championship.  

For various reasons the fatfs library is not capable to handle two distinct files - to store the "map" contents separately. Also the uSD transfer does not work in 4-bit wide bus mode (STM32CubeMX bug) to be able to get things done quickly enough while talking to the drive - good thing I chose to work with a Ram Buffer. 

And I am not going to sacrifice an 128k RAM bank just for generating a separate map file and get tons of headaches for not being able to store it separately on the SD card.

4. Welcome to Wonderland:   SIMH Emulator has its own format for handling tape images - thank you Chuck for the tip with SIMH .TAP Format which says each block is preceded and followed by descriptors telling details about the current and previous block. 

The implemented format looks like this:

---------|--------|---------------|--------|---------------|--------|---------------|--------|---------------|--------|
         |        |               |        |               |        |               |        |               |        |
DATA/BOT | BLKINF |     DATA      | BLKINF |     DATA      | BLKINF |     DATA      | BLKINF |     DATA      | BLKINF |
         |64 bits |               |64 bits |               |64 bits |               |64 bits |               |64 bits | 
---------|--------|---------------|--------|---------------|--------|---------------|--------|---------------|--------|

BLKINF (again shorted from Vampires and Warriors tongue ) - block with information.  It is inserted before and after each data block.

The format looks like this:

|-------------|------------|
|             |            |
| info prev   |  info next |
|     block   |   block    |
|   32 bits   |   32 bits  |
|-------------|------------|

 Each 64-bit block is split into two parts describing what came before and what will come to pass:

- Is there any END OF FILE?  (FMK = 1, bit 31)

- Is there any error inside the block which was caused by the tape cloning process? (ERR = 1, bit 30)

- Is this the final data block on the tape?  (EOD = 1, bit 29)

- zero bits reserved for future need (bits 28..24)

- How many bytes are there to be read?  (BLK LEN, bits 23->0)

I also need information inside "previous record" describing what was before - because tape sequential i/o operations sometimes happen in reverse mode.

          FMK    ERR   EOD    ZERO     BLK_LEN
           31     30    29    28->24    23->0
FMKMASK    0       1    1     1 -> 1     1->1 FMKMASK = 0x7FFFFFFF
ERRMASK    1       0    1     1 -> 1     1->1 ERRMASK = 0xBFFFFFFF
EODMASK    1       1    0     1 -> 1     1->1 EODMASK = 0xDFFFFFFF
BLKMASK    1       1    1     1 -> 1     0->0 BLKMASK = 0xFF000000

 Some consideration should be taken regarding the transition between the RAM banks to keep the data integrity and not to lose any data during record transfer. There is no hardware addressing control so everything is at the software level. Special care must be taken at i/o operation for both data and descriptors.

The serial output debug log explains how these first descriptors are loaded from the SPI RAM Buffer into the STM32 memory space:

drive_rewind()@tape.c line3701: extract INIT PREVREC:
rambuf_rec_extract()@spiram.c line2851: extract RECORD

ram_extract(spiram.c@line2642): startaddr@0 cbank=0 cpos=0 length=4 free=131071, RAMPOS= 0, RAM_FULL = 0

ram_extract(read@spiram.c line2664): length(4) < free(131071) reading from memory bank 0x0, startaddr=0 cpos=0 length=4 free=131071, RAMPOS= 4
 0x0  0x0  0x0  0x0

rambuf_rec_extract()@spiram.c line2886: FMK=0x0; ERR=0x0; EOD=0x0; BLK=0x0; RECORD=0x0

drive_rewind()@tape.c line3704: init PREVREC:  fmk = 0, err = 0, eod = 0, blklen = 0
#####################################

drive_rewind()@tape.c line3710: extract INIT CUR_REC:
rambuf_rec_extract()@spiram.c line2851: extract RECORD

ram_extract(spiram.c@line2642): startaddr@4 cbank=0 cpos=4 length=4 free=131067, RAMPOS= 4, RAM_FULL = 0
▒)$▒

ram_extract(read@spiram.c line2664): length(4) < free(131067) reading from memory bank 0x0, startaddr=4 cpos=4 length=4 free=131067, RAMPOS= 8
 0xA0  0x16  0x29  0x24

rambuf_rec_extract()@spiram.c line2886: FMK=0x1; ERR=0x0; EOD=0x1; BLK=0x162924; RECORD=0xA0162924

drive_rewind()@tape.c line3713: init CURREC:  fmk = 1, err = 0, eod = 1, blklen = 0x162924, total_tape_length = 1,452,324 BYTES
##############################

drive_rewind()@tape.c line3718: extract 1st PREVREC:
rambuf_rec_extract()@spiram.c line2851: extract RECORD
ram_extract(spiram.c@line2642): startaddr@8 cbank=0 cpos=8 length=4 free=131063, RAMPOS= 8, RAM_FULL = 0
▒
ram_extract(read@spiram.c line2664): length(4) < free(131063) reading from memory bank 0x0, startaddr=8 cpos=8 length=4 free=131063, RAMPOS= 12
 0x80  0x0  0x0  0x0
rambuf_rec_extract()@spiram.c line2886: FMK=0x1; ERR=0x0; EOD=0x0; BLK=0x0; RECORD=0x80000000
drive_rewind()@tape.c line3724: virtual streamer RDY. @start_mainframe() the system waits for /IGO, reads CURREC, transmits the data block and reads PREVREC.

Here is a screenshot of two images of the same tape. Left side is the data alone, right side is the data and descriptors. We can notice the data is padded with spaces to fill the blocks.

Now let's see what that log and the first 128 bytes in the screen-shot above mean:

Starting at address 0x00000000 - begin of tape image in modified SIMH format:

                    HEX                     BIN                   Activated bits
Previous record: 00 00 00 00  00000000000000000000000000000000   NONE - initial prev record

Current record:  A0 16 29 24  10100000000101100010100100100100 FMK=1 EOD=1 BLKLEN = 0x162924 meaning 1,452,324 bytes or almost a 3.5", 1.44 MB Diskette

Previous record: 80 00 00 00  10000000000000000000000000000000 There was a FMK with zero-block length

Current record:  00 00 00 50  00000000000000000000000010100000 Here it comes an 80-bytes length block:
VOL1VOL0010 [22 x space] VASEA_____BURU [23 x space]   total = 80 bytes

By looking at the tape data header we now know that in the past someone called "Vasili the Weed" came to the factory computing center from the electronics department and wrote that tape containing some files in an old tape archive format, the data was valid for 1402 days (2022 - 620), version one, generation one of the documents and the operating system tape block length chosen at software level is 512-bytes long block split into two sectors of 256 bytes each. We also notice the tape contains an archive format defined by the POSIX.1-1988 specification called USTAR. Bring me some cold beer and I will tell you more.

[END OF TRANSMISSION]

Discussions