CAC 2015-10-22

Cleaning up status_service

the 'eo' bit

/* This function figures out the number of bytes which were transferred for a given I/O operation.  Note that
   these are 9-bit bytes.  If the I/O operation transferred 6-bit characters, our calculation may be a
   little off.  This is known as "too bad". */

get_io_byte_count:

...

/* The calculations have to be done differently depending on whether the operation was a read or a write,
   and on whether the channel was in ASCII mode or binary mode. */

          if writing () then do;                            /* either all was written, or none, we claim... */
               if status_ptr -> istat.er then
                    return (0);                             /* can't trust what's on the tape */
               else return (buffer_ptr -> tbi.data_len);
          end;
          else do;                                          /* reading, we'll trust the counts */
                if ascii_mode (buffer_ptr) then do;
                    buffer_ptr -> tbi.data_len =
                         word_count () * BYTES_PER_WORD - mod (BYTES_PER_WORD - status_tcp (), BYTES_PER_WORD);
                    buffer_ptr -> tbi.bit_len = (buffer_ptr -> tbi.data_len) * BITS_PER_BYTE;
               end;
               else do;
                    buffer_ptr -> tbi.bit_len =
                         BITS_PER_WORD * (word_count () - 1 - bin (status.eo))
                         + BITS_PER_CHAR * (BITS_PER_CHAR - mod (BITS_PER_CHAR - status_tcp (), BITS_PER_CHAR));
                    if (status.major = "0000"b) & ((status.sub & "001010"b) = "000000"b) then
                         buffer_ptr -> tbi.bit_len = buffer_ptr -> tbi.bit_len - bin (substr (status.sub, 1, 3));
                    buffer_ptr -> tbi.data_len = divide (buffer_ptr -> tbi.bit_len, BITS_PER_BYTE, 21);
               end;
               return (buffer_ptr -> tbi.data_len);
          end;

Reading ASCII:

                    buffer_ptr -> tbi.data_len =
                         word_count () * BYTES_PER_WORD - mod (BYTES_PER_WORD - status_tcp (), BYTES_PER_WORD);
                    buffer_ptr -> tbi.bit_len = (buffer_ptr -> tbi.data_len) * BITS_PER_BYTE;

(word_count is the sum of the tallies in the DCW list)
BYTES_PER_WORD is 4
BITS_PER_BYTE is 9
status_tcp is the character position (0-7) (for ASCII, only 0-3 should occur?)

data_len = word_count * 4 - (4 - cp) % 4 

So the word count includes partial words; ie 6 chars would be two words, so the result is 4 * count_count - unused.

bit_len *= 9

Convert from bytes to bits.

Reading binary:

                    buffer_ptr -> tbi.bit_len =
                         BITS_PER_WORD * (word_count () - 1 - bin (status.eo))
                         + BITS_PER_CHAR * (BITS_PER_CHAR - mod (BITS_PER_CHAR - status_tcp (), BITS_PER_CHAR));
                    if (status.major = "0000"b) & ((status.sub & "001010"b) = "000000"b) then
                         buffer_ptr -> tbi.bit_len = buffer_ptr -> tbi.bit_len - bin (substr (status.sub, 1, 3));
                    buffer_ptr -> tbi.data_len = divide (buffer_ptr -> tbi.bit_len, BITS_PER_BYTE, 21);

bit_len = 36 * (wc - 1 - eo) + 9 * (9 - tcp)
data_len = bit_len / 36;

Okay, lets assume that the controller was doing 72 bit xfers; so the tally would always be even (multiple of 2). For partial xfers,
eo indicates that the end of data is in the even or odd word, and cp where in the word.

If the driver returns odd tallies and never sets e/o, then the above math should be okay.

I cannot decipher the status check, no semantic correspondence with AN87; I am assuming that some particular tape drive will return cp in the
sub-status. Ignoring.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License