System/161 LAMEbus Devices

These devices have LAMEbus vendor id 1 (System/161 Development Team).

11 Old uniprocessor bus controller -- see LAMEbus spec
21Timer/clock card
32Fixed disk
41Serial console
51Text screen
62Network interface
71Emulator filesystem
82Hardware trace control
91Random number generator
101 Multiprocessor bus controller -- see LAMEbus spec

Timer/clock card

Device id: 2
Oldest revision: 1
Current revision: 1
0-3Current time (seconds)
4-7Current time (nanoseconds)
8-11Restart-on-expiry flag
12-15True if interrupt (reading clears)
16-19Countdown time (usec) (writing starts timer)
20-23Speaker (write any value to beep)
An interrupt is generated when the countdown time reaches 0. The countdown timer is automatically restarted if the restart-on-expiry register has a nonzero value.

Reading from the speaker produces undefined behavior.

The current time registers represent UTC, where the epoch is midnight on January 1, 1970, as per the Unix time call. (In 2038 this will break. Oh no.)

Fixed disk

Device id: 3
Oldest revision: 2
Current revision: 2
0-3Number of sectors (total)
8-11Sector number
12-15Rotation speed (RPM)
A 512-byte sector transfer buffer is mapped at offset 32768.

The disk can do one operation at a time. To perform an operation, store the sector number into the sector register, and then write either the read-in-progress or write-in-progress values into the status register. Changing the sector number register while an operation is in progress produces undefined results.

The status register reports the present state of the disk. When it is reporting a completed operation, the IRQ line is raised. Writing zero back (or starting another operation) clears the interrupt condition. Writing zero back when an operation is in progress aborts the operation. Writing values other than zero or the values that start operations into the status register produces undefined results.

The disk is assumed to never need low-level formatting. The sector size is 512 bytes. Note that the 32-bit linear sector addressing limits disk size to 2^32 * 512 = 2^41 bytes, or 2 TB. In practice implementations may have lower limits.

The status register bits are as follows:

1 Operation in progress
2 Operation is write
4 Operation completed
8 Invalid sector number
16 Media error
This results in the following values being meaningful in the status register:
0 Device idle
1 Read operation in progress
3 Write operation in progress
4 Read operation succeeded
6 Write operation succeeded
12 Invalid sector number on read
14 Invalid sector number on write
20 Media error on read
22 Media error on write
Once a write operation has reported successful completion, the disk guarantees that the complete sector written will in fact make it to stable storage.

Serial console

Device id: 4
Oldest revision: 1
Current revision: 1
0-3Character buffer
4-7Write IRQ register
8-11Read IRQ register
This is a very, very simple console interface. Writing to the first register causes a character to be printed. Reading from it returns the last character typed.

You must wait until one write has completed before starting another one, or the output may be garbled.

The two IRQ registers have three bits each. Bit 0 (IRQEN) controls whether interrupts are generated; if bit 0 is clear, interrupts for writes or reads (respectively) will not be generated at all.

Bit 1 (CMPL) is latched on when the device completes a (write or read, respectively) operation. It can be cleared by software. Bit 2 (FORCE) is controlled only by software. The device's IRQ line is asserted if either the write or read IRQ register is in an asserting state; an IRQ register is in an asserting state if bit 0 is set and either bit 1 or bit 2 is set.

The FORCE bit can be used to perform polled I/O without causing the IRQ line to flap, which can cause problems in multiprocessor configurations. The basic approach is to set FORCE during the polled I/O if an IRQ was already pending, to keep it pending until the polled I/O is complete, and to clear IRQEN during the polled I/O if an IRQ was not already pending, to avoid triggering a spurious interrupt. See the OS/161 2.x driver (1.99.06 or higher) for example code.

NOTE: Bit 2 is only supported in System/161 versions 1.99.05 and up. The device revision is 1 regardless; if necessary the feature can be probed by writing FORCE (without IRQEN) to one of the IRQ registers and then reading the register back. If FORCE is read back, the feature is present; if 0 is read back, the feature is not available. Note that drivers written for prior versions of System/161 without the FORCE bit will continue to work as before.

The characters read from the device are 8-bit ASCII and control characters in the range 0-255. Non-ASCII keys, such as cursor keys or function keys, may appear as strings beginning with an escape sequence, or as values greater than 255. Unfortunately, in practice such characters may come from any of a number of sources and it is not practical to attempt to document their values or even map them into a single consistent set.

Screen console

Device id: 5
Oldest revision: 1
Current revision: 1
0-3Cursor position
4-7Display size
8-11Character input buffer
12-15Read IRQ register
Memory mapped screen interface. 32k of screen memory is mapped at offset 32768. The cursor position and display size registers are encoded with the X value in the most significant 16 bits and the Y value in the least significant 16 bits, with a zero base.

To make the cursor invisible, move it off the screen. This may or may not work depending on the display.

Reading is the same as with the serial console device. Writing is accomplished by scribbling in screen memory, one byte per character, increasing addresses moving first to the right then down across the screen.

Writing to the display size register should, in principle, work, but in practice will not.

Network interface

Device id: 6
Oldest revision: 2
Current revision: 2
0-3Receive interrupt register
4-7Transmit interrupt register
8-11Control register
12-15Status register
A 4k read buffer followed by a 4k write buffer is mapped at offset 32768. Packets may not exceed 4k.

Simple network interface.

Bit 0 of each interrupt register is set when a receive (or transmit) is complete. These bits may be cleared by writing 0 back. If either interrupt register is nonzero, the card's IRQ line is asserted.

The control register contains two bits: bit 0 controls promiscuous mode, and bit 1 controls packet sending. If the promiscuous mode bit is set, all packets seen will be received, even those whose destination is elsewhere. Setting bit 1 starts a packet transmit. Do not set bit 1 while a transmit is already in progress; undefined behavior may result. The rest of the control register is reserved and should be set to 0.

The lower 16 bits of the status register report the device hardware address. The rest is reserved. The status register is read-only.

To transmit, a packet should first be assembled in the send buffer. The destination and length fields in the link-level header must be set correctly. (The source and frame fields will be set by the card during transmit. However, the entire link-level header should be placed in the send buffer.) Then bit 1 of the control register should be set to 1 to start transmission. An interrupt will occur when transmission is complete.

To receive, merely copy each packet out of the receive buffer as receive interrupts occur. Further packets arriving are discarded while the receive interrupt register is nonzero, so packets may be copied without being corrupted by further input.

The link-level packet header is 8 bytes long and has the following fields (always in network byte order):

OffsetSize Description
0 2 Framing word (0xa4b3)
2 2 Hardware from-address
4 2 Total packet length
6 2 Hardware to-address
The length field should hold the entire packet length, including the space taken by the header.

The hardware address 0xffff is the broadcast address; the hardware address 0x0000 is reserved for sending keepalives to the network hub. Software should not send packets to hardware address 0x0000.

Emulator passthrough filesystem

Device id: 7
Oldest revision: 1
Current revision: 1
0-3Handle number to do I/O with
4-7File offset for read/readdir/write
8-11Length of I/O
12-15Operation code
16-19Result code
A 16384-byte I/O buffer is mapped at offset 32768.

The operation codes are:

1 Open a file
2 Create a file
3 Create a file exclusively (O_EXCL)
4 Close a file
5 Read from a file
6 Read one filename from a directory
7 Write to a file
8 Get size of a file
9 Truncate a file
The result codes are:
0 Operation in progress or device idle
1 Success
2 Bad handle
3 Bad operation code
4 Bad pathname
5 Bad I/O size
6 File exists
7 File is a directory
8 Media error
9 Out of handles
10 Out of disk space
11 File is not a directory
12 Unknown other error
13 Unsupported operation
The rest of the documentation for this device is reserved, on the grounds that it is complicated, messy, unclean, and may be subject to frequent change.

Hardware trace controller

Device id: 8
Oldest revision: 1
Current revision: 2
0-3Trace-on register
4-7Trace-off register
8-11Debugging printout register
12-15System state dump register
16-19Software debugger request
This device controls trace161's trace flags, allowing them to be set or cleared on the fly. To set a trace flag, write the letter of its trace option to the trace-on register; to clear it, use the trace-off register. The letters are the same as those used on the trace161 command line. If running sys161 rather than trace161, this device may exist and be used, but the trace registers have no effect.

The debugging printout register, if written to, causes trace161 or sys161 to print a debug message, which includes the value written to the register.

The system state dump register, if written to, will cause a complete dump of the simulation state, tagged with the value written to the register. This feature is primarily intended for testing and debugging System/161 itself.

The software debugger request register, if written to, will cause System/161 to drop to the debugger. This is preferable to explicitly inserting a breakpoint instruction, because debuggers don't cope very well with hitting breakpoint instructions they didn't insert themselves.

The software debugger request register was introduced in DRL 2. (This appeared in the System/161 2.0 release, after 1.99.10.) A device that reports DRL 1 does not have this register and attempts to write to it will fault.

All these registers are write-only.

Random number generator

Device id: 9
Oldest revision: 1
Current revision: 1
0-3Random value
Reading the register returns a 32-bit random value. In the simulated version, this value is generated by a pseudo-random generator whose seed can be specified explicitly. This allows for repeatable results, which can be helpful in some contexts.