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.)
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.
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.
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:
Virtual memory map:
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:
Also note that on i386 the virtual memory map can be arranged however desired.
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:
Vendor IDs defined are as follows:
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.
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:
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.
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:
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.
Each CPU control area contains the following:
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.
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:
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.
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.