144B DeviceFunction¶
In progress MON 144B (100 decimal) · Mnemonic MAGTP · Group: Device Handling (manual section 2.11)
Available from: All programs (manual compatibility box)
Emulation source: src/handlers/mon_144B_DeviceFunction.c
Description¶
Performs various operations on floppy disks, magnetic tapes, Versatec plotters, and SCSI streamers.
- The parameter values depend on the device.
- If the function code is in the range 5B to 24B, except 23B, the parameter buffer and the two device dependent parameters are dummies.
- If the function code is in the range 20B to 24B, except 23B, the hardware status is returned.
Parameters¶
| Name | Type | Direction | Description |
|---|---|---|---|
FunctionCode |
INTEGER2 | In | Function code. See the following pages. |
Buffer |
INTEGER2[1024] | In/Out | Buffer used for data transfer to and from the device. |
DeviceNo |
INTEGER2 | In | Logical device number (or open-file number). See appendix B. |
DeviceParam1 |
INTEGER2 | In | First device dependent parameter. See the following pages. |
DeviceParam2 |
INTEGER2 | In | Second device dependent parameter. See the following pages. |
Direction: In = the program supplies the value, Out = the call returns it, In/Out = both.
See also¶
DeviceControl, @DEVICE-FUNCTION
Compatibility¶
| Machines | Users | Programs |
|---|---|---|
| ND-100 and ND-500 | All users | All programs |
The manual's compatibility box for this call, word for word.
Yes/no fields from the YAML extraction (not in the manual's words):
| ND-100 | ND-500 | User programs | RT programs | System programs |
|---|---|---|---|---|
| Yes | Yes | Yes | Yes | No |
Examples¶
From the manual (OCR text, not corrected).
INTEGER : DevNo, Func, Param1, Param2
BYTES : Buff(0:2047)
...
ON ROUTINEERROR DO
IF ErrCode >‹ 0 THEN ...
ENDON
Monitor_Call(‘DeviceFunction‘, Func, Buff(0), DevNo, Param1, Param2)
INTEGER DevNo, Func, Param1, Param2
INTEGER Buff(1024)
...
Monitor Call('DeviceFunction', Func, Buff(1), DevNo, Param1, Param2)
IF (ErrCode .NE. 0) THEN ...
DevNo, Func, Param1, Param2 : INTEGER2;
Buff : ARRAY [0..63] OF RECORD...END;
...
DeviceFunction(Func, Buff, DevNo, Param1, Param2);
IF ErrCode <> 0 THEN ...
01 DevNo COMP.
01 Func COMP.
01 Param1 COMP.
01 Param2 COMP.
01 Buff.
02 array COMP OCCURS 1024 TIMES.
01 ErrCode COMP.
...
MONITOR-CALL "DeviceFunction" USING Func, Buff, DevNo, Param1, Param2.
CALL "CbError" USING ErrCode.
IF ErrCode NOT = 0 GO ...
DevNo : W BLOCK 1
Func : W BLOCK 1
Param1 : W BLOCK 1
Param2 : W BLOCK 1
Buff : W BLOCK 1024
ErrCode : W BLOCK 1
DeviceFunction : EQU 3789 + 144B
...
CALLG DeviceFunction, 5, Func, Buff, DevNo, Param1, Param2
IF K GO ERROR
...
ERROR : W1 =: ErrCode %ErrorCode in W1 register.
LDA (PAR %Load register A with address of parameter list.
MON 144 %Monitor call DeviceFunction.
STA STAT %Store status returned.
...
STAT, 0
PAR, FUNC %Function to be performed.
BUFF %Address of buffer used for data transfer.
DEVNO %Logical device number.
PARA1 %Device dependent parameter.
PARA2 %Device dependent parameter.
...
FUNC, ...
BUFF, 0
**+120/ %Make a buffer of 80 words.
DEVNO, ...
PARA1, ...
PARA2, ...
ndmonlib implementation¶
In progress Registered MON_STATUS_IN_PROGRESS: partly implemented. The dispatcher calls the handler.
| Handler | mon_144B_DeviceFunction |
| Code lines | 79 (non-blank, non-comment lines in the file) |
Notes from the handler source¶
src/handlers/mon_144B_DeviceFunction.c line 49
Function 0B - Read-Record.
The ND linker uses this to load its DDB tables: it OPENs 'DDBTABLES-G':VTM,
SETBTs the byte pointer to 0, then issues MAGTP(0, buffer, <that file>, ...)
and immediately requires the first word of the buffer to be 1
(0xB004AFB8: "w comp2 r.0x0,$0x1", else error 0x106A). The real
DDBTABLES-G06:VTM begins with 0x00000001 and carries 0x40-byte records at
+0x78, which is exactly where the linker indexes - so the file image maps
directly onto the buffer.
src/handlers/mon_144B_DeviceFunction.c line 75
Resume at the position the caller established (the linker sets it with
74B SETBT before calling), matching how 117B RFILE streams.
src/handlers/mon_144B_DeviceFunction.c line 137
UNVERIFIED: which parameter carries the transfer size. Table 9.1 lists
param2 as "octal no. of words", but the linker passes param1=4096 and
param2=3, and 4096 is the only value that can span the table it then
indexes (count at +0x0, 0x40-byte records from +0x78). The manual's
"following pages" that would settle the ND-500 parameter convention
are not in the scanned set. Treating param1 as a BYTE count is
therefore INFERRED - it is what the linker's own usage demands, not
something read from a manual. Revisit if another caller disagrees.
src/handlers/mon_144B_DeviceFunction.c line 148
Every other function code is a real device operation (tape motion,
formatting, hardware status) against hardware we do not emulate.
Returning benign SUCCESS keeps callers moving; it is NOT correct, and
the true return convention (status word / IO buffer format) is
UNVERIFIED. Do not port as final.
Emulation research¶
Source
This section comes from the emulation: block of the call's YAML file in the NDInsight repo. It records what was learned while implementing the call in nd500x; its status is nd500x's, not ndmonlib's.
| Status (nd500x) | partial |
| nd500x handler | nd500x/src/libmon/handlers/mon_144B_DeviceFunction.c |
| Last updated | 2026-07-17 |
Function codes¶
- Radix: octal
- Note: The manual body says only "Function code. See the following pages." THIS is that table. It is OCTAL - it skips 8 and 9, which is the giveaway.
-
Source
- Doc: ND-60.050.06 SINTRAN III Users Guide
- Page: 232
- Table: 9.1
- Codes
1. 0
Field Value Name Read-Record Description Reads a record from the device, or from the open file given by DeviceNo, into Buffer. Param1 Octal addr. of data buf. for area users to read (manual) Param2 Octal no. of words (manual) Status implemented 2. 1
Field Value Name Write-Record Param2 Octal no. of words Status not_implemented 3. 5
Field Value Name Unlock-and-Stop Status not_implemented 4. 6
Field Value Name Lock-Cassette Status not_implemented 5. 7
Field Value Name Erase-EOF Status not_implemented 6. 10
Field Value Name Advance-to-EOF Status not_implemented 7. 11
Field Value Name Reverse-to-EOF Status not_implemented 8. 12
Field Value Name Write-EOF Status not_implemented 9. 13
Field Value Name Rewind Status not_implemented 10. 14
Field Value Name Write-Erase-Gap Status not_implemented 11. 15
Field Value Name Back-Space-Records Status not_implemented 12. 16
Field Value Name Advance-Records Status not_implemented 13. 17
Field Value Name Unload Status not_implemented 14. 20
Field Value Name Read Status Description Reads the device status register via an IOX instruction. Status not_implemented 15. 21
Field Value Name Clear Device Status not_implemented 16. 23
Field Value Name Select Density-and-Parity Param2 Density/parity value (Users Guide section 9.2.2.1) Status not_implemented 17. 24
Field Value Name Read Last Status Description Returns the status of the last operation, saved by the driver, without executing an IOX instruction. Status not_implemented
Observed calls¶
1. ND linker (linker-b01.dom) @0xB004E9BC, via wrapper @0xB004E98A
| Field | Value |
|---|---|
| Params | Functioncode: 0 Buffer: 0xB00530BC Deviceno: 65 Deviceparam1: 4096 Deviceparam2: 3 |
| Expectation | The linker OPENs 'DDBTABLES-G':VTM (abbreviation-resolves to DDBTABLES-G06:VTM), 74B SETBTs the byte pointer to 0, then issues this call, and IMMEDIATELY requires the first word of Buffer to be 1 (0xB004AFB8 "w comp2 r.0x0,$0x1"), else it raises error 0x106A. The real DDBTABLES-G06:VTM begins 00 00 00 01 and carries 0x40-byte records at +0x78 - exactly where the linker then indexes. The file image maps directly onto the buffer. |
| Note | If this call returns success WITHOUT filling Buffer, the linker's tables stay blank and it later walks blank memory as records, computes a bogus pointer 0x40404040 (0x20202020+0x20202020 - spaces read as a record), takes a protect violation, and aborts via its own trap handler. The failure surfaces ~83000 instructions later as a stack overflow, which is a symptom, NOT the bug. |
Return contract¶
- Success: K flag cleared; Buffer filled for transfer functions.
-
Errors
Code Octal Meaning 90 132B No file opened with this number (Read-Record on a non-open device) 3 003B End of file / seek failed 97 141B Transfer error
Verified¶
1. Function codes are octal, and this is the right table.
| Field | Value |
|---|---|
| Evidence | The table skips 8 and 9. Independently, the ND linker's own MAGTP wrapper at 0xB004E98A special-cases function codes 0x10 and 0x14 (16 and 20 decimal = 20B and 24B octal) = exactly Read Status / Read Last Status - the codes the manual says take dummy parameters ("in the range 5B to 24B, except 23B, the parameter buffer and the two device dependent parameters are dummies"). |
2. Function 0 reads the open file named by DeviceNo into Buffer.
| Field | Value |
|---|---|
| Evidence | Implemented and run: error 0x106A drops from 1 occurrence to 0, and the downstream protect violation and stack overflow disappear entirely. Log: "Read-Record 4096 bytes from device 101 into 0xB00530BC, pos=10000". |
3. DeviceNo may be an open-file number, not only a logical device.
| Field | Value |
|---|---|
| Evidence | Manual parameter text says "Logical device number (or open-file number)". Observed: DeviceNo=65, the file number returned by the preceding 50B OPEN. Corroborated by the access-code table entry for code 8: "Direct transfer for ReadFromFile, WriteToFile and DeviceFunction". |
Unverified¶
- WHICH parameter carries the transfer size. Table 9.1 lists param2 as "octal no. of words", but the linker passes param1=4096 and param2=3, and 4096 is the only value that can span the table it then indexes. nd500x treats param1 as a BYTE count. This is INFERRED from the caller's usage, not read from a manual - the pages that would settle the ND-500 parameter convention are not in the scanned set.
- The return convention for the status-reporting functions (20B-24B): the manual says "the hardware status is returned" but the format is not in the scanned pages.
- All function codes other than 0 are unimplemented in nd500x and currently return benign SUCCESS. That is NOT correct behaviour - they are real device operations against hardware not emulated.
Discrepancies¶
1. The carve of the ND-100 worker (L-VSX-500 segment 006-S3FS, MAGTP @026354B) validates the function code to the range 100B..177B, which would make function 0 out of range.
| Field | Value |
|---|---|
| Is | The ND linker passes function 0 and expects it to work. The carve itself notes GOTAB[144B] = 000000 is a fall-through and the real dispatch lives in an UNCARVED overlay, so that range check is not authoritative for the ND-500 path. |
| Evidence | NDInsight/tools/sintran-segment-carver/versions/L-VSX-500/re/mon-analysis/144B-DeviceFunction/144B-DeviceFunction.pseudo.c |
Sources¶
| Doc | Page | Table | Note |
|---|---|---|---|
| ND-60.050.06 SINTRAN III Users Guide | 232 | 9.1 | The function-code table. Concluded on page 233 (codes 20-24). |
| nd500x/docs/HANDOFF_CSHARP_STRING_WRITE_MMU.md | Section 7 item 3 - full port notes for the C# side. |
Source¶
SINTRAN III Monitor Calls (ND-860228.2 EN), page 143.