Upon entry to this procedure:
the processor is running at priority zero, in kernel mode and with the previous mode shown as user mode;
the kernel mode segmentation registers have been set and the memory management unit has been enabled;
all the data areas used by the operating system have been initialised;
the stack pointer (SP or r6) points to a word which contains a return address in “start”.
The first action of “main” would appear to be redundant, since “updlock” should have already been set to zero as part of the initialisation performed by “start”;
“i” is initialised to the ordinal of the first 32 word block beyond the “per process data area” for process #0;
The first pair of user mode segmentation registers are used to provide a “moving window” into higher areas of the physical memory.
At each position of the window an attempt is made (using “fuibyte”) to read the first accessible word in the window. If this is not successful, it is assumed that the end of the physical memory has been reached. Otherwise the next 32 word block is initialised to zero (using “clearseg” (0676)) and added to the list of available memory, and the window is advanced by 32 words.
“fuibyte” and “clearseg” are both to be found in “m40.s”, “fuibyte” will normally return a positive value in the range 0 to 255. However, in the exceptional case where the memory location referenced does not respond, the value –1 is returned. The way this is brought about is a little obscure, and will be explained later in Chapter Ten.)
“maxmem” defines the maximum amount of main memory which may be used by a user program. This is the minimum of:
the physically available memory (“maxmem”);
an installation definable parameter (“MAXMEM”) (0135);
the ultimate limit imposed by the PDP11 architecture;
“swapmap” defines available space on the swapping disk which may be used when user programs are swapped out of main memory. It is initialised to a single area of size “nswap”, starting at relative address “swplo”. Note that “nswap” and “swplo” are initialised in “conf.c” (lines 4697, 4698);
The significance of this and the next four lines will be discussed shortly;
The design of UNIX assumes the existence of a system clock which interrupts the processor at line frequency (i.e 50 Hz or 60 Hz).
There are two possible clock types available: a line frequency clock (KW11-L) which has a control register on the Unibus at address 777546, or a programmable, real-time clock (KW11-P) located at address 777540 (lines 1509, 1510).
UNIX does not presume which clock will be present. It attempts to read the status word for the line frequency clock first. If successful, that clock is initialised and the other (if present) remains unused. If the first attempt is unsuccessful, then the other clock is tried. If both attempts are unsuccessful, there is a call on “panic” which effectively halts the system with an error message to the operator.
Since the absence of a clock will be indicated by a bus timeout error, it is convenient to make the reference via “fuiword”, preceded by the setting of a user mode segmentation register pair (1599, 1600).
Either type of clock is initialised by the statement
*lks = 0115;
As a consequence of this action, the clock will interrupt the processor within the next 20 milliseconds. This interrupt may occur at any time, but it will be convenient for this discussion to assume that no interrupt will occur before initialisation is complete;
“cinit” (82l4) initialises the pool of character buffers. See Chapter 23;
“binit” (5055) initialises the pool of large buffers. See Chapter 17;
“iinit” (6922) initialises table entries for the root device. See Chapter Twenty.