MON 144B MAGTP -- DeviceFunction¶
Device-dependent function call: parameter 1 is a function code interpreted by
the addressed device's driver (magnetic tape, SCSI streamer, floppy-with-volume,
Versatec). The handler MAGTP sets up a per-call frame, range-checks the
function code, and dispatches into a per-device function group. It is the "monster"
call that accreted new sub-functions across SINTRAN versions.
All addresses and values in this document are octal unless a decimal suffix is
given. This analysis is written against the real SINTRAN L bytes carved from
006-S3FS.bin; the L07 symbol tables under
../../../../../../SINTRAN/NPL-SOURCE/SYMBOLS/L07/ are used only for symbol names.
Dispatch (byte-verified)¶
prove-mon.py 144 output (ground truth):
GOTAB base = 071233 octal in tools/sintran-segment-carver/versions/L-VSX-500/resident/SINTRAN-DATA_commoncode.bin
MON 144B:
GOTAB[144] : file byte 0xe5fe of commoncode.bin, raw = 00 00 -> 000000 octal
= 000000 -> FALL-THROUGH (no direct handler; dispatched via MFELL/CALLPROC)
So GOTAB[144B] = 000000. This is a FALL-THROUGH monitor call: the level-14
dispatcher finds a zero in the GOTAB word (at commoncode virtual 71377B =
71233B + 144B) and routes the call through MFELL -> CALLPROC to a
second-level monitor process. The overlay named by prove-mon.py
(025-S3IRPIT.bin) is the tool's default overlay guess and is not the
MAGTP body; the real body lives in the file-system segment.
Handler location (VERIFIED against FILSYS-SYMBOLS.SYMB.TXT, L07):
| Item | Value |
|---|---|
| Segment file | ../../../segments/006-S3FS.bin (load base 26000B) |
| Entry symbol | MAGTP = 26354B |
| Entry bytes on disk | 04 17 4C 0F big-endian = 002027 046017 octal (STZ ,X 27 / LDA ,X 17) |
| Carve window in this folder | 26354B .. 27037B (307 words = 614 bytes) |
File offset of entry in 006-S3FS.bin |
word 26354B - 26000B = 354B |
The first two entry words disassemble exactly as the .bin head bytes
(0417 4c0f), confirming the slice is aligned to MAGTP and byte-honest.
Sub-entry symbols that fall inside the window (from FILSYS-SYMBOLS, L07):
| Symbol | Address | Length to next |
|---|---|---|
MAGTP |
26354B |
21B words to 500RF |
500RF |
26375B |
2B words to 500WF |
500WF |
26401B |
4B words to XRFIL |
XRFIL |
26405B |
2B words to XWFIL |
XWFIL |
26407B |
-- |
These are the "how did I enter" prologue variants (read-file / write-file /
500-side read / 500-side write) that all merge into the common body at 26411B.
Instruction walkthrough¶
The .ASM in this folder (144B-MAGTP.ASM) is the byte-honest
disassembly of the 307-word closure. Register conventions: B = current
monitor-process frame pointer, X = a secondary/parameter block pointer, A/T
scratch. Frame slots are referenced as ,B nn (displacement into the process
frame) and ,X nn. Key blocks by address:
Entry prologue / sub-entry fan-in (26354B .. 26410B)
Five distinct entry points set an operation selector in frame slot ,X 27 and a
sub-selector in A, then converge:
- MAGTP 26354B: STZ ,X 27 (selector 0), snapshots ,X 17 into ,X 31, calls
a shared worker via JPL I 63 (-> pointer word, target 26442B), then a second
JPL I 61 (-> 26443B). It seeds ,B 17/21/23/27 and jumps JMP I 50
(-> 26444B) into the common setup.
- 500RF 26375B / 500WF 26401B / XRFIL 26405B / XWFIL 26407B: each loads a
small immediate (SAA 0/1/2) into A and/or ,X 27 to distinguish read vs
write and 500-side vs file, then falls into the merge at 26411B.
Common setup (26411B .. 26445B)
STA ,X 25 stores the sub-selector; re-snapshots ,X 17->,X 31; two indirect
worker calls JPL I 26 (-> 26442B and 26445B); tests ,B 21 (a flag) with
JAZ/JAF and sets it to 0 or 1. JMP I 12 (-> 26444B) rejoins.
Note words 26433B..26445B are the pointer/indirect-address words those
JPL I / JMP I instructions point at (they disassemble as spurious
instructions but are actually address constants -- e.g. 26442B: 004141,
26444B: 026446). Treat 26433B..26445B as data, not code.
Function-code range check (26446B .. 26467B) -- the heart of the dispatch:
026446 LDA ,B 20 ; A = function code (parameter 1)
026447 SAT 100 ; T = 100B
026450 SKP IF DA GRE ST ; skip if code >= 100B
026451 JMP 026470 ; code < 100B -> "high/standard" path
026452 SAT 177 ; T = 177B
026453 SKP IF DT GRE SA ; skip if 177B >= code (i.e. code <= 177B)
026454 JMP 026470 ; code > 177B -> also to 026470
026455 LDA ,B 25 ; (in-range 100B..177B branch) reload sub-selector
026456 JAF ... ; ... choose default function slot (100B / 74B)
026461 SAT 1 / EQL ; special-case code 1
026463 JMP 026554 ; -> error/soft-exit path
026464 LDA 74
026465 STA ,B 30 ; store resolved function index in ,B 30
026466 LDA ,B 20
026467 JMP 026607 ; dispatch tail for the 100B..177B group
26470B.
Standard-function masking + table index (26470B .. 26506B)
026470 LDT 71 ; T = default index
026471 STT ,B 30
026473 LDA ,B 25 ; sub-selector
026474 AND 66 ; mask -> select a device-function *group*
026475 AAA -77 ; bias
026476 SKP IF 0 GRE SA
026477 JMP 026554 ; out of range -> soft exit
026500 RADD CLD SX DA
026501 LDT I 62 ; index a per-device function pointer table
026502 SKP IF DT UEQ 0 ; is the slot non-zero?
026503 JMP 026507
026504 LDA 60 / STZ I 60
026506 JMP 026553
LDT I 62 is the indirect index into the addressed device's function table. When
the selected slot is zero the code takes the "unsupported function" exit.
Device-status decode blocks (26507B .. 26652B)
Two near-identical blocks (26507B..26567B and 26615B..26653B) call a shared
worker (JPL I 57 -> 26566B; JPL I 35 -> 26652B), then use BSKP ONE/ZRO
bit-skip instructions on ,X 3 / ,X 7 (device status words) to translate
hardware status bits into SINTRAN error codes: SAA 132 (26513B/26621B),
SAA 174 (26530B/26551B), SAA 133 (26636B). These are the
tape/streamer status-to-errorcode maps. 26554B..26556B is the common soft-error
exit: LDA 14 / STA ,B 12 / JPL I 13 (report code in ,B 12).
Buffer transfer tail (26737B .. 27036B) -- two MOVEW blocks:
026741 SAA 22 ; build source/dest descriptors
026742 RADD CLD SA DL
026743 SAX 7
026744 LDD I 101 ; load a 32-bit pointer (double)
026745 RADD SX DD
026750 MOVEW ; block move (buffer <-> device frame)
026751 LDX I 72
026752 LDA ,X 34 / STA ,B 46
...
026776 JPL I 56 ; -> 027054 (finalize / STATX device status latch)
STATX at 26774B latches device status; MOVEW at 26750B and 27031B
perform the actual buffer copy described by parameter 2. The routine ends at the
closure boundary 27036B (SUB I ,B 42) with control returning via the
JPL I workers into the monitor-process framework rather than a classic MON
skip-return in this window.
Parameter / register contract¶
Frame-relative, from the code (VERIFIED unless marked):
| Item | Location | Notes |
|---|---|---|
| Function code (param 1) | ,B 20 |
VERIFIED: loaded at 26446B, range-checked 100B/177B, masked AND 66 |
| Sub-selector / device group | ,B 25 |
VERIFIED: LDA ,B 25 at 26455B/26473B, drives table index |
| Resolved function index | ,B 30 |
VERIFIED: STA ,B 30 at 26465B/26471B |
| In/out flag | ,B 21 |
VERIFIED: set 0/1 at 26426B..26431B, tested at 26762B |
| Buffer (param 2) | via ,X/pointer words at 26744B (LDD I 101) and 27025B |
VERIFIED that a double-word pointer is loaded for MOVEW; exact param->slot binding UNVERIFIED (set up by the fall-through/CALLPROC prologue outside this window) |
| Logical device number (param 3) | UNVERIFIED in this slice | driver selection happens before entry |
| Device-dependent params 4/5 | UNVERIFIED in this slice | consumed by the per-device table target |
| Error code out | ,B 12 |
VERIFIED: STA ,B 12 at 26555B before JPL I 13 (error reporter) |
| Device status | ,X 3, ,X 7 |
VERIFIED: BSKP bit tests decode these |
Skip-return / A-register result convention: UNVERIFIED here. The classic MON
skip-return and the "bytes transferred in A" result are established by the
MFELL/CALLPROC wrapper and the calling monitor entry, neither of which is in
this 307-word window. Do not assert a specific A/skip contract from this slice
alone.
Cross-reference¶
- Manual: ND-860228 SINTRAN III Monitor Calls, DeviceFunction (144B / 100
decimal). Parameter list (function code, buffer, logical device number, two
device-dependent parameters) matches
README.mdand theLDA ,B 20function-code usage seen in the code. - Function-code table and driver-side behaviour:
MAGTP-emulation.md. - Per-device driver body (jump-table targets, actual buffer handling): lives in
the device driver source (e.g.
IP-P2-SCSI-MAGTP.NPL), outside this window. - NPL caveat: the L07 NPL source under
../../../../../../SINTRAN/NPL-SOURCE/is a different revision than the carved L image; NPL addresses are NOT byte truth for this handler. Only the symbol names (MAGTP/500RF/500WF/XRFIL/XWFIL) were used, and their addresses were re-confirmed against the carved bytes on disk.
Integrity¶
Validator (validate-mon-carves.py), exact result line:
ok mon-emulation/144B-MAGTP/144B-MAGTP.ASM [26354..27036, 307w]
1/1 checked passed; 0 FAILED; 0 skipped (ND-500)
Zero direct branches escape the file: control-flow closure holds over
26354B..27036B (307 words). The .bin is 614 bytes = 307 words, big-endian, and
its first four bytes (0417 4c0f) equal the disassembled entry
002027 046017 -- the slice is aligned to MAGTP and byte-honest.
Confidence and open questions¶
- HIGH confidence: GOTAB[144B]=000000 fall-through; handler =
MAGTP=26354Bin006-S3FS.bin; function-code range check (100B/177B,AND 66); error code in,B 12; twoMOVEWbuffer-transfer tails; closure integrity. - MEDIUM confidence: slot bindings for
,B 20/21/25/30-- named from their usage in the code, not from an external frame map. - LOW / UNVERIFIED: exact parameter-to-frame-slot binding for buffer / LDN /
device params (established by the
MFELL/CALLPROCprologue, not in this window); the A-register / skip-return output convention; the concrete contents and target routines of the per-device pointer table indexed byLDT I 62.
Anomalies:
1. README.md still describes the carve as "192 bytes = 96 words,
slice 26354B..26513B". That is STALE: the actual .bin on disk is 614
bytes = 307 words, window 26354B..27036B, which is what the validator
passes on. The README's 96-word figure predates the control-flow-closure
re-carve and should be updated.
2. prove-mon.py prints overlay 025-S3IRPIT.bin as its default guess; the real
MAGTP body is in 006-S3FS.bin. The overlay line is a tool default, not a
finding.
3. Words 26433B..26445B, 26557B..26565B, 26642B..26652B disassemble as
instructions but are pointer/address constants consumed by the neighbouring
JPL I / JMP I / worker calls. They are data embedded in the code stream
(normal ND-100 PLANC layout) and must not be read as executable.