MON 144B DeviceFunction (MAGTP) - emulation notes¶
Behaviour-focused model for an emulator author. Handler entry MAGTP = 26354B in
006-S3FS.bin (byte-verified, 144B-MAGTP.ASM). The function-code list is taken
from the SINTRAN source IP-P2-SCSI-MAGTP.NPL (function-code header block) and the
DeviceFunction parameter contract from ND-860228 (Monitor Calls).
Parameters¶
param 1 : function code INT (in)
param 2 : buffer used for data transfer ARR (in; used for READ/WRITE record ops)
param 3 : logical device number INT (in; the tape/streamer LDN)
param 4 : 1st device-dependent param INT (in)
param 5 : 2nd device-dependent param INT (in)
Return: status in A (device/driver status word; 0 = OK, non-zero = device error code / status bits). For READ-type functions the data lands in the caller's buffer (param 2); READ STATUS / READ ERROR COUNTERS return their values through the buffer and/or the device-dependent parameters.
Function codes (octal) - from IP-P2-SCSI-MAGTP.NPL¶
| Code | Function |
|---|---|
| 0 | READ (one record into buffer) |
| 1 | WRITE (one record from buffer) |
| 2 | READ PARITY |
| 7 | ERASE |
| 12 | WRITE EOF (tape mark) |
| 13 | REWIND |
| 14 | WRITE SKIP |
| 20 | READ STATUS (TEST UNIT READY) |
| 24 | READ LAST STATUS |
| 25 | READ ERROR COUNTERS |
| 26 | READ BYTE RECORD |
| 27 | WRITE BYTE RECORD |
| 37 | READ EXTENDED STATUS |
| 42 | READ FORMAT |
| 50 | READ MULTIPLE RECORDS |
| 51 | WRITE MULTIPLE RECORDS |
| 60 | READ WITH DOUBLE AMOUNT |
| 61 | WRITE WITH DOUBLE AMOUNT |
| 62 | READ DOUBLE AMOUNT BYTE RECORD |
| 63 | WRITE DOUBLE AMOUNT BYTE RECORD |
| 66 | READ WITH DOUBLE AMOUNT, DON'T CLEAR CACHE |
| 73 | TEST UNIT READY |
| 75 | INQUIRY (READ DEVICE TYPE) |
The handler at 26446B..26467B bounds-checks the code (SAT 100, SAT 177) and
masks with AND 66 to pick a device-function group before indexing the driver's
jump table (LDT I 62). Codes >= 100B are an extended/aliased range.
What the linker needs¶
The ND linker touches MON 144B but it is genuinely unimplemented in the emulator.
For a first pass the emulator can:
- Accept the 5-parameter block, read function code (param 1) and LDN (param 3).
- If the emulated "device" is not a tape/streamer, return a device-error status in
A (non-zero) rather than crashing - the linker's normal path does not depend on a
real tape, it just probes the device.
- If it must appear to succeed, implement the harmless status functions:
20B/73B TEST UNIT READY -> return "ready" status (0), and
75B INQUIRY -> return a device-type word in the buffer.
- READ/WRITE record functions (0/1/26/27/50/51/60/61) move param 4/5 bytes
between the caller's buffer (param 2) and the device.
Pseudocode¶
function MAGTP(func, buf, ldn, p1, p2) -> A:
if not device_is_tape_like(ldn):
return DEVICE_ERROR_STATUS
group = func & 0o66 # handler masks the code
switch func:
0, 26, 50, 60, 62, 66: return tape_read(ldn, buf, p1, p2)
1, 27, 51, 61, 63: return tape_write(ldn, buf, p1, p2)
12: return tape_write_eof(ldn)
13: return tape_rewind(ldn)
7: return tape_erase(ldn)
14: return tape_write_skip(ldn)
20, 73: return tape_test_unit_ready(ldn) # status in A
24: return tape_last_status(ldn, buf)
25: return tape_error_counters(ldn, buf)
37: return tape_extended_status(ldn, buf)
42: return tape_read_format(ldn, buf)
75: return tape_inquiry(ldn, buf) # device type into buf
default: return DEVICE_ERROR_STATUS
C sketch¶
/* Returns device status word (0 = OK). buf is the caller's transfer buffer. */
int sintran_magtp(int func, uint8_t *buf, size_t bufbytes,
int ldn, int p1, int p2)
{
if (!device_is_tape_like(ldn))
return DEV_NOT_RESERVED; /* non-zero status; do not crash */
switch (func) {
case 000: case 026: case 050:
case 060: case 062: case 066:
return tape_read(ldn, buf, bufbytes, p1, p2);
case 001: case 027: case 051:
case 061: case 063:
return tape_write(ldn, buf, bufbytes, p1, p2);
case 012: return tape_write_eof(ldn);
case 013: return tape_rewind(ldn);
case 007: return tape_erase(ldn);
case 014: return tape_write_skip(ldn);
case 020: case 073: return tape_test_unit_ready(ldn);
case 024: return tape_last_status(ldn, buf, bufbytes);
case 025: return tape_error_counters(ldn, buf, bufbytes);
case 037: return tape_extended_status(ldn, buf, bufbytes);
case 042: return tape_read_format(ldn, buf, bufbytes);
case 075: return tape_inquiry(ldn, buf, bufbytes);
default: return DEV_ILLEGAL_FUNCTION; /* non-zero status */
}
}
Not verified / open items¶
- The exact per-function jump-table offsets and each function's buffer layout live
in the device driver (
IP-P2-SCSI-MAGTP.NPLand the tape/streamer drivers), outside the 96-word MAGTP dispatch window; only the dispatch/validation was byte-traced here. - The precise meaning of the
AND 66mask and the100B..177Bextended range was not decoded to individual functions.