Linear Always-Mapped Extents

LAMEbus is a simple no-fuss system bus architecture. There are 32 slots, each of which is associated with a fixed-size addressable region. These regions are mapped in order into the system physical memory space. There is no DMA; data transfers are done by the CPU using transfer buffers appearing within a device's address space. (However, DMA may be added in a future version.)

Structure of the Bus Region

There are 32 slots, and each slot has a 64K address space. Thus, the whole bus region takes 64K*32 = 2MB. The base physical address of this region is called LAMEBASE; because different processor types impose different restrictions on the organization of physical memory, its value depends on the processor architecture.

The bus controller always appears in slot 31; its 64K address space is divided in two. The lower half is divided into 32 1K config regions, one per slot. The upper half is divided into 32 1K control regions, one per CPU. In addition to configuration, the config region of the bus controller's config region contains the bus controller's own registers, described below.

Addressing the Bus

Thus, the physical address for slot N, holding the registers and other material for the device placed the slot, is given by

	LAMEBASE + (0x10000*N)
The physical address for slot N's config region is given by
	LAMEBASE + (0x10000*31) + (0x400*N)
The physical address for CPU N's control region is given by
	LAMEBASE + (0x10000*31) + 0x8000 + (0x400*N)
Virtual addresses will of course vary depending on processor architecture and MMU state.

Physical Memory Layout


On 32-bit MIPS processors, the first 512 megabytes of the physical address space is hardwired to appear at kernel virtual addresses 0x8000 0000 (cached) and 0xA000 0000 (uncached). Also, several virtual addresses starting at 0xbfc0 0000 are hardwired into the architecture and must point into the firmware ROM.

For this reason, LAMEBASE is set to 0x1fe0 0000, so the LAMEbus mapping area appears at the top end of these regions. The physical memory map is as follows:
0xffff ffff Upper physical RAM (above 508 MB)
0x2000 0000
0x1fff ffffLAMEbus devices
0x1fe0 0000
0x1fdf ffffBoot ROM area
0x1fc0 0000
0x1fbf ffff First 508 MB of physical RAM
0x0000 0000

Virtual memory map:
Address MIPS
Region MIPS hardwired address
0xffff ffff kseg2 TLB-mappable
kernel space
0xbfffffff kseg1 LAMEbus mapping area  
0xbfdfffff Boot ROM area
0xbfc00180 Exception address if "boot" flag is set
0xbfc00100 UTLB exception address if "boot" flag is set
0xbfc00000 Execution begins here after processor reset.
0xbfbfffff First 508 MB of RAM
0x9fffffff kseg0 Cached LAMEbus
(not useful)
0x9fdfffff Boot ROM area
0x9fbfffff First 508 MB of RAM
0x80000080 Exception address if "boot" flag not set.
0x80000000 UTLB exception address if "boot" flag not set.
0x7fffffff kuseg User space  

Because the MIPS has a 32-bit memory bus, all registers (all LAMEbus device registers are 32-bit) can be read or written atomically in a single instruction.


The experimental Ant-32 build of System/161 is deprecated.


LAMEbus for i386 has not been implemented, and probably will not be; however, if it is, the projected layout is with LAMEBASE at 0xffe0 0000, a boot ROM area below that, and all the rest of the physical address space potentially used by RAM:
0xffff ffffLAMEbus devices
0xffe0 0000
0xffdf ffffBoot ROM area
0xffc0 0000
0xffbf ffff Physical RAM (up to 4092 MB)
0x0000 0000
Note that this is not compatible with the traditional ISA-derived mess found on stock i386-based machines.

Also note that on i386 the virtual memory map can be arranged however desired.

Bus Configuration

Because the bus is always mapped, and interrupt lines are always connected, no explicit configuration of system resources is required. However, it is still necessary for system software to inspect the bus to find what devices are connected, and to perform certain control operations. For that reason, as mentioned above, a 1K config region is associated with each slot. Each such config region contains the following registers:
Name Offset Description
VID0x00-0x03Vendor ID
DID0x04-0x07Device ID
DRL0x08-0x0bDevice Revision Level
The Vendor ID, Device ID, and Device Revision Level in combination uniquely identify the hardware device present in the slot.

Vendor IDs defined are as follows:

Value Organization
0 No card present
1 System/161 Development Team
0xffff ffff Private experimental or research use
Other Reserved
If no card is present in a given slot, the other config registers may contain invalid values, and references to that slot's mapping area will (normally) cause memory bus errors.

The Device ID and Device Revision Level values are defined by the vendors. The System/161 Development Team devices are documented in an accompanying document.

Bus Controller

Offsets 512-1023 (0x200-0x3ff) of the bus controller's own configuration region are mapped to the bus controller's own registers.

The System/161 2.x multiprocessor bus controller (VID 1, DID 10) has the following registers:

NameOffset Description
RAMSZ0x200-0x203 Size of physical RAM in bytes
IRQS0x204-0x207 Mask of slots presently interrupting
PWR0x208-0x20b Power enable register
IRQE0x20c-0x20f Global interrupt enable register
CPUS0x210-0x213 Mask of CPUs present in the system
CPUE0x214-0x217 Mask of CPUs powered up and executing
SELF0x218-0x21b Bit corresponding to reading CPU

RAMSZ reports the system main board configuration. Writes are rejected. Where the physical RAM appears in the physical address space, and whether it is contiguous (and if not, where the gaps are) depends on the processor type.

The IRQS register holds a 1 for each slot that is presently asserting its IRQ line. Writes to IRQS are rejected; interrupts should be cleared on the devices generating them. Bit 0 represents slot 0, etc. Thus bit 31 is the bus controller's bit.

The PWR register holds a 1 for each slot that is currently powered. Writing to this register powers devices on and off. Powering off the system mainboard switches the system off. Note: if the mainboard is powered off, all other slots should be powered off as well. At startup, slots with devices in them are powered; others are unpowered.

The IRQE register holds a 1 for each slot that is allowed to generate interrupts. Slots whose bit in IRQE is zero may assert their IRQ line (and thus appear in IRQS) but will not generate a processor interrupt by doing so.

The CPUS register holds a 1 for each CPU that is present on the system board. These are not necessarily contiguous in the word; in a two-CPU configuration the CPUs present may be e.g. 0 and 16, leading to a value of 0x0001 0001 in this register.

The CPUE register holds a 1 for each CPU that is enabled, that is, powered up and executing. Upon board reset only one CPU (the boot CPU) will be enabled; this will normally be CPU 0. Others that are present may be activated by writing 1s into this register. Enabling a CPU that is not present has undefined results.

The SELF register holds a 1 in the bit position corresponding to the currently executing CPU that is reading the register. This allows distinguishing CPUs from one another. (Note that the system board cannot distinguish among cores on the same CPU; that requires additional on-chip facilities.)

Device Revision Level. The device revision level of the multiprocessor system board is 1.

Old Bus Controller

The older System/161 1.x uniprocessor bus controller (VID 1, DID 1), which is still supported and may be configured as "oldmainboard", has the following registers:

NameOffset Description
RAMSZ0x200-0x203 Size of physical RAM in bytes
IRQS0x204-0x207 Mask of slots presently interrupting
PWR0x208-0x20b Power enable register
IRQE0x20c-0x20f Interrupt enable register

RAMSZ, IRQS, and IRQE are the same as in the multiprocessor bus controller.

The PWR register switches the system off if the value 0 is written into it. Other writes have no effect, and reading produces undefined results.

Device Revision Levels. Two levels of the bus controller device are defined.

The IRQE register is defined so as to be backwards compatible; that is, software that works with the DRL 1 device will work with the DRL 2 device without modification.

CPU Control Area

Each CPU control area contains the following:

NameOffset Description
CIRQE0x000-0x003 Per-CPU interrupt enable register
CIPI0x004-0x007 Per-CPU inter-processor interrupt register
CRAM0x300-0x3ffPer-CPU scratch buffer

CIRQE is the same as IRQE, but per-processor. This allows interrupts to be routed to one or more processors as desired. CIRQE is applied downstream of IRQE; that is, an interrupt disabled in IRQE will never be delivered regardless of the setting of CIRQE on any CPU. Note: there is no hardware support for dispatching interrupts to multiple CPUs round-robin fashion.

CIPI allows sending inter-processor interrupts. The inter-processor interrupt pin of each CPU is asserted if its CIPI register contains a nonzero value.

CRAM is a 128-byte scratch area used for system startup, as described below. After startup it can be used as desired by the OS.

On the old uniprocessor motherboard, the entire CPU control area is reserved and accesses yield undefined behavior.

Supporting Both Controllers

A kernel that supports both mainboard types (uniprocessor and multiprocessor) requires abstraction of the mainboard functions in software. Having accomplished that, the uniprocessor mainboard can be made to mimic a multiprocessor mainboard with one CPU as follows:

Additionally, to be able to run on DRL 1 of the old mainboard such a kernel must not rely on individual interrupt masking via CIRQE or IRQE being available at all.

Bus Power-Up

At power-up time, the devices present are automatically probed and the VID, DID, and DRL values become available in the configuration registers. The CPUS register, if present, is loaded. The amount of RAM present is probed and the RAMSZ register is loaded. The IRQE and CIRQE registers, if present, are loaded with 0xffff ffff. All devices are reset to a state such that they will not generate interrupts until otherwise programmed.

At this point, the boot CPU is started. On the multiprocessor board the CPUE register is loaded so as to enable the boot CPU, usually CPU 0. On the uniprocessor board, the one CPU is simply released from reset. Control is transferred to the boot ROM.

The boot ROM has no published entry points and supplies no services besides system startup. In fact, it may or may not actually be present, as in the System/161 environment system startup can be effected without it, inside the simulator.

Boot ROM

The boot ROM loads an ELF kernel image in a suitable processor-dependent way, and jumps to the image's entry point. A bootup stack is established. A single null-terminated string (generated from the kernel arguments passed on the System/161 command line) is passed as a function argument to the entry point.

On the multiprocessor system board, the boot string is placed in a suitable but unspecified location in main memory. The boot stack is established at the top of the CRAM area.

For secondary CPUs and secondary cores on the boot CPU, which are not normally started until the kernel has taken control of the system, the boot stack is established at the top of the CRAM area, and the contents of the lowest word in the CRAM area are read and used as an entry point to begin execution within the kernel.

On the old uniprocessor system board, the boot string and the boot stack are placed in a suitable but unspecified location in main memory.


The kernel should be linked to run at or near virtual address 0x8000 0000. The kernel is loaded into the corresponding physical memory at or near physical address 0. The boot string (and, if appropriate, the boot stack) are placed at or near the high end of memory, to avoid conflicting with the kernel. The kernel should as soon as possible copy the boot string and establish its own stack in a known location. Then all memory may be used safely.

The address of the boot string is passed in the a0 ($4) register. The sp register points to the top of a stack region as previously defined. However, the startup code should not assume that a proper caller stack frame already exists on the stack. (That is, writing a0 back to its argument slot through the stack pointer may produce undefined behavior.) The contents of other registers, including the CPU configuration registers, are unspecified. The TLB state is unspecified. The CPU cache is in a state suitable for routine operation.


The experimental Ant-32 build of System/161 is deprecated.


Not yet specified.