Documentation

Sources

Where every constant comes from, what has been checked against a real pack, and two traps worth knowing about before reading the ITS sources yourself.

Sources

Where every constant comes from, what has been checked against a real pack, and two traps worth knowing about before reading the ITS sources yourself.

The primary source

Every on-disk offset, width and opcode in src/its.h is transcribed from one file:

SYSTEM;FSDEFS 43     the file system parameters, "APPLIES TO ALL ITS MACHINES"

read in the PDP-10/its repository, at src/system/fsdefs.43.

How far the transcription reaches

FSDEFS 43 is one version of one file, and ITS ran for twenty-three years, so "which ITS releases does this reader cover?" is a real question. It used to be answered here with a shrug. It has a better answer now, because the same repository preserves an earlier version of the same fileSYSENG;FSDEFS 40, three file-versions back, imported in 2016 and deleted a month later, still in the history.

$ make version-diff
1. every symbol, both versions
  ok   IDENTICAL: all 71 definitions, same names and same values

2. the symbols src/its.h actually cites
  ok   all 43 symbols its.h cites are defined in FSDEFS 43
  ok   ...and 2 constants that cite ITS code instead, and say so

All 71 DEFSYMs are identical — every name, every value. The 65 lines that differ are entirely prose: version 43 replaced a terse descriptor comment with a long one and added a dated note. And that note makes the claim this comparison checks:

; 8/19/90 Due to the larger size of RP07s it was necessary to officially ; flush the DM "funny" bit. This change only changes the comments in this ; file, but any program that interprets UFD descriptors needs to be fixed ; to not mask that bit out (as most of them currently do).

The file says its own change was comment-only; the symbol comparison is what holds it to that.

One semantic difference survives, with no symbol attached to it. FSDEFS 40 documents the 020 bit of a load address as a "FUNNY" BLOCK IF DMDSK; 43 says it is flushed, so 17 bits are block number. This reader does not mask it, which is correct for 43 and for any pack FSDEFS calls known — but it is the one place where reading version 40 instead would have produced different code, and no diff of symbols would have shown it.

What this does NOT establish. A file version is ITS's own numbering, not a release number, and nothing here maps 40 or 43 onto an ITS distribution. The comparison establishes that the format did not move between two points; it does not establish where those points are. Both versions carry ;9/5/79 - tut format changed!, so the three-bit TUT entry this reads is the post-1979 one in both — which puts a floor under the span and no ceiling.

tests/version-diff.sh also checks the citation column: every symbol its.h names must actually be defined in FSDEFS. That is the one kind of wrong citation a machine can catch, and it found one — two constants whose comments began with SIXBIT and looked like citations to a symbol of that name. They cite ITS's own code instead now, and say so.

Its own header reads:

;;; Copyright (c) 1999 Massachusetts Institute of Technology
;;; See the COPYING file at the top-level directory of this project.

Two other files in the same tree supplied facts that FSDEFS does not carry:

file what it settled
src/system/disk.1228 that a "track" is a block (line 48); QFL2, the MFD-slot arithmetic; that UNDATE's right half is TIMOFF (HRR TT,TIMOFF, lines 190 and 505) ; and that QLGLK's name comparison is UNSIGNED — it complements bit 0 with TLC A,(SETZ) before a signed CAML, which is the standard unsigned-compare idiom (line 2381 on)
src/system/time.953 that TIMOFF is "the re-calculated number of HALF-SECONDS SINCE MIDNIGHT" (line 346), which settles UNTIM
src/system/sysjob.119 the same field again, from the other side: "TIME OF DAY IN .5 SEC UNITS" (line 1165)
src/system/rp06.defs1 and the four beside it the drive geometry table, per drive

one is not a source but a second opinion, and it is now used:

file what it settled
src/kshack/nsalv.261 ITS's own salvager. Run against a pack rather than read for constants — see validation. Its LTYPE also settled the SIXBIT trap below.
src/midas/midas.458 that MIDAS's 'X is SIXBIT, which is what makes LTYPE mean what it means

and one is named on the roadmap rather than used yet:

file what it is for
src/system/dskdmp.217 the standalone dumper and bootstrap: how a pack is written from outside the monitor

The licensing line, and where it sits

The ITS tree is GPL and is never vendored, copied or committed here. No line of ITS code and no line of anybody else's C appears in this project.

What is taken is what a file format is: word offsets, field widths, opcode values, and the arithmetic that turns a block number into a disk address. That is the same thing t10fs takes from DEC's COMMOD.MAC and s5fs from the 2.9BSD headers, and it is why each constant is cited: a citation is what distinguishes transcribing a fact from copying an implementation.

The same line applies to two other programs in that tree that read this format, both of which were read for what they say and neither of which contributed code:

  • tools/dasm/libword/ (GPL) — the container formats a 36-bit word is stored in, which is where the name data8 for what this project calls le64 comes from.
  • tools/mldev/ — a FUSE client for the ITS network file protocol, not the disk format. Different problem, listed here so nobody goes looking for disk layout in it.

itsfs is clean, original C. Disk images and the ITS source tree are usable locally for validation and are never committed. Test fixtures are built by the test suite.

Two traps

1. MIDAS numbers are octal unless they carry a trailing dot.

DEFSYM	LTIBLK==20		;BYTES MAPPING THE DISK START HERE      <- 16 decimal
DEFSYM	UDDESC==11.	;FIRST LOC AVAIL FOR DESC                   <- 11 decimal

Two lines, two bases, and the only difference is a full stop. its.h writes each constant in the base FSDEFS writes it in and says so, so a line can be checked against the source by eye without converting anything.

2. FSDEFS's prose gives ASCII codes for characters it stores as SIXBIT.

The link-target encoding is described as quoting ";" (73) and ":" (72). Those are the ASCII codes. The bytes on the disk are SIXBIT — 033 and 032 — and taking the numbers at face value finds no separator anywhere, rendering every link as one run-on string. The same sentence gives space as (0), which is the SIXBIT value. One sentence, two encodings.

Found by dumping the bytes of a link that was already "working", and settled empirically. ITS's own code then confirmed it, which is worth more than the measurement: NSALV's link parser compares against character constants —

LTYPE:	MOVEI B,6
LTYPE2:	IDPB Z,E		;Z accumulates the link.
	ILDB A,N		;Get a byte.
	JUMPE A,CPOPJ		;Not expecting zeros in the link.
	CAIN A,':		;Quoting character?

— and MIDAS assembles 'X as SIXBIT, not ASCII. From MIDAS's own source, src/midas/midas.458:

SQUOT9:	JSP F,QOTCON	;SIXBIT SYL
	CAIGE A,40
	 ETR ERRN6B	;NOT SIXBIT
	CAIL A,140
	 SUBI A,40	;CONVERT TO UPPER CASE
	LSH T,6		;SHIFT OVER ACCUMULATED VALUE
	ADDI T,-40(A)	;ADD IN SIXBIT FOR CHARACTER IN A

'; is therefore 073 − 040 = 033, and ': is 072 − 040 = 032: exactly the bytes on the disk. So FSDEFS's comment and ITS's own code disagree about this encoding, and the code is right — which is the general lesson worth taking, not just this instance.

This cost an afternoon here and is written up in its.h beside the constants, in the file system, and in validation.

Evidence markers

its.h marks every field:

[v]   read in FSDEFS and seen to decode correctly on a real ITS pack
[s]   read in FSDEFS, not yet exercised against a pack

A [s] field is not less trustworthy as a transcription — it is less trustworthy as an understanding, and a reader should not lean on one. The gap register in the file system lists every one that matters and says what is missing.

What "a real pack" means here is stated plainly because it bounds every [v]: an RP06 image built by the PDP-10/its Makefile, booted, and run — out/simh/rp0.dsk, SHA-256 27d980f2…. It is not an artifact recovered from MIT. A pack built from source in 2026 exercises the format that ITS writes today; a 1980s pack could exercise fields that nothing has written since. Finding one is on the roadmap.

Corroborating implementations

Not sources — second opinions, and named as such:

  • SIMH (PDP10/pdp10_rp.c, sim_disk.c) — the disk container is little-endian per 8-byte word, on any host, because the byte swap is conditional on the host being big-endian.
  • KLH10 — defines dbd9, two words in nine bytes. DEC never had such a format, so KLH10's source is that format's specification rather than a second opinion on it.
  • TM03 Magnetic Tape Formatter User Guide, EK-OTM03-UG-003, table 2-12 — the core-dump frame layout, from the hardware that does the packing. The formatter splits the word; the operating system only hands it over.

The last two are why core and dbd9 are implemented at all. Both are now confirmed, and neither on the strength of the documents above alone: core by finding three strings ITS prints inside the tape it loads them from, and dbd9 by agreeing byte for byte with a pack written by KLH10's own vdkfmt — see word packing.

ITS's own prose documentation

Found after the format had been implemented and measured, which is the only order in which it is worth anything: read first it would simply have been believed.

  • doc/sysdoc/magtap.101 — ITS's .OPEN bits for magtape, copied from a 1972 memo. Bit 3.9 selects "Core dump mode, 36 bit words" against "IBM Character Mode, 32 bit words", and core dump is the zero case. That is the one thing the TM03 manual cannot say: which mode ITS actually asks for.
  • doc/sysdoc/adding.packs — nine lines on multi-pack, and they settle what it would take: FIRSPK/LASTPK in the salvager and NQS in ITS, both assembly-time, then MARK and UCOP. Also says UCOP propagates the MFD and UFDs to a fresh pack rather than sharing them, which is a structural fact worth having before writing any multi-pack support.
  • doc/sysdoc/ufd.100 — the directory in English. Confirms the three header words, the five-word name block, the semicolon/colon link rule, and — the one that matters — that the descriptor pointer is "a byte address relative to a point 11. words from the beginning of the directory", which is the origin this project got wrong once and found by arithmetic rather than by reading.

The DUMP tape format

  • doc/sysdoc/dump.format, in the PDP-10/its tree — ITS's own description of the save-set layout: the four-word tape header, the file header, and what a link looks like. Read after the format had been measured against a tape ITS wrote and transcribed from syseng/dump.449, which is the right order: it turned out to describe the six-word header, from before HRDATE and HLEN were added in July 1989, and so corroborates both the layout and the date of the change rather than merely repeating one of them.
  • syseng/dump.449 — the program itself, and the only place the link constants are stated outright (;CREATION DATE OF LINK IS 400000,,0, ; Length of link is always 3) rather than deduced from bytes.
  • kshack/nsalv.261 — for FESET, which writes the KS10 home block, and for the IFCE MCHN blocks that fix a salvager's drive at assembly time.