Use a global context for registering "hardwired" devices for consistency.
This commit is contained in:
@@ -5,6 +5,7 @@ import li.cil.ceres.api.Serialized;
|
||||
import li.cil.oc2.OpenComputers;
|
||||
import li.cil.oc2.api.bus.DeviceBusElement;
|
||||
import li.cil.oc2.api.bus.device.Device;
|
||||
import li.cil.oc2.api.bus.device.vm.VMContext;
|
||||
import li.cil.oc2.api.bus.device.vm.VMDeviceLifecycleEventType;
|
||||
import li.cil.oc2.common.block.ComputerBlock;
|
||||
import li.cil.oc2.common.bus.AbstractDeviceBusController;
|
||||
@@ -69,6 +70,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
|
||||
private static final String ITEMS_NBT_TAG_NAME = "items";
|
||||
|
||||
private static final int DEVICE_LOAD_RETRY_INTERVAL = 10 * 20; // In ticks.
|
||||
private static final int VFS_INTERRUPT = 0x5;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -94,7 +96,7 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
|
||||
private final VirtIOFileSystemDevice vfs;
|
||||
private ConsoleRunner runner;
|
||||
|
||||
private final DeviceItemStackHandler itemHandler = new DeviceItemStackHandler(4);
|
||||
private final DeviceItemStackHandler itemHandler = new DeviceItemStackHandler(8);
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -109,9 +111,11 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
|
||||
terminal = new Terminal();
|
||||
virtualMachine = new VirtualMachine(busController);
|
||||
|
||||
vfs = new VirtIOFileSystemDevice(virtualMachine.board.getMemoryMap(), "scripts", new HostFileSystem());
|
||||
vfs.getInterrupt().set(virtualMachine.vmAdapter.claimInterrupt(), virtualMachine.board.getInterruptController());
|
||||
virtualMachine.board.addDevice(vfs);
|
||||
final VMContext context = virtualMachine.vmAdapter.getGlobalContext();
|
||||
vfs = new VirtIOFileSystemDevice(context.getMemoryMap(), "scripts", new HostFileSystem());
|
||||
context.getInterruptAllocator().claimInterrupt(VFS_INTERRUPT).ifPresent(interrupt ->
|
||||
vfs.getInterrupt().set(interrupt, context.getInterruptController()));
|
||||
context.getMemoryRangeAllocator().claimMemoryRange(vfs);
|
||||
|
||||
setCapabilityIfAbsent(Capabilities.DEVICE_BUS_ELEMENT_CAPABILITY, busElement);
|
||||
setCapabilityIfAbsent(Capabilities.DEVICE_BUS_CONTROLLER_CAPABILITY, busController);
|
||||
@@ -336,9 +340,9 @@ public final class ComputerTileEntity extends AbstractTileEntity implements ITic
|
||||
}
|
||||
|
||||
if (compound.contains(ITEMS_NBT_TAG_NAME, NBTTagIds.TAG_COMPOUND)) {
|
||||
itemHandler.setStackInSlot(0, ItemStack.EMPTY);
|
||||
itemHandler.setStackInSlot(1, ItemStack.EMPTY);
|
||||
itemHandler.setStackInSlot(2, ItemStack.EMPTY);
|
||||
for (int i = 0; i < itemHandler.getSlots(); i++) {
|
||||
itemHandler.setStackInSlot(i, ItemStack.EMPTY);
|
||||
}
|
||||
itemHandler.deserializeNBT(compound.getCompound(ITEMS_NBT_TAG_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,12 @@ public final class ManagedInterruptAllocator implements InterruptAllocator {
|
||||
}
|
||||
|
||||
public void freeze() {
|
||||
final long[] words = managedInterrupts.toLongArray();
|
||||
managedMask = words.length > 0 ? (int) words[0] : 0;
|
||||
isFrozen = true;
|
||||
}
|
||||
|
||||
public void invalidate() {
|
||||
claimedInterrupts.andNot(managedInterrupts);
|
||||
managedInterrupts.clear();
|
||||
managedMask = 0;
|
||||
}
|
||||
|
||||
@@ -54,6 +53,7 @@ public final class ManagedInterruptAllocator implements InterruptAllocator {
|
||||
claimedInterrupts.set(interrupt);
|
||||
reservedInterrupts.set(interrupt);
|
||||
managedInterrupts.set(interrupt);
|
||||
managedMask |= (1 << interrupt);
|
||||
return OptionalInt.of(interrupt);
|
||||
}
|
||||
}
|
||||
@@ -76,6 +76,7 @@ public final class ManagedInterruptAllocator implements InterruptAllocator {
|
||||
claimedInterrupts.set(interrupt);
|
||||
reservedInterrupts.set(interrupt);
|
||||
managedInterrupts.set(interrupt);
|
||||
managedMask |= (1 << interrupt);
|
||||
|
||||
return OptionalInt.of(interrupt);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@ package li.cil.oc2.common.vm;
|
||||
|
||||
import li.cil.ceres.api.Serialized;
|
||||
import li.cil.oc2.api.bus.DeviceBusController;
|
||||
import li.cil.oc2.api.bus.device.vm.InterruptAllocator;
|
||||
import li.cil.oc2.api.bus.device.vm.MemoryRangeAllocator;
|
||||
import li.cil.oc2.api.bus.device.vm.VMContext;
|
||||
import li.cil.oc2.common.bus.RPCAdapter;
|
||||
import li.cil.sedna.api.device.InterruptController;
|
||||
import li.cil.sedna.buildroot.Buildroot;
|
||||
import li.cil.sedna.device.block.ByteBufferBlockDevice;
|
||||
import li.cil.sedna.device.rtc.GoldfishRTC;
|
||||
@@ -25,6 +29,24 @@ public final class VirtualMachine {
|
||||
public static final int REPORTED_CPU_FREQUENCY = 700_000;
|
||||
public static final int ACTUAL_CPU_FREQUENCY = REPORTED_CPU_FREQUENCY * 72;
|
||||
|
||||
private static final int UART_INTERRUPT = 0x1;
|
||||
private static final int HDD_INTERRUPT = 0x2;
|
||||
private static final int RTC_INTERRUPT = 0x3;
|
||||
private static final int RPC_INTERRUPT = 0x4;
|
||||
|
||||
private static final ByteBufferBlockDevice ROOT_FS;
|
||||
|
||||
static {
|
||||
ByteBufferBlockDevice rootfs;
|
||||
try {
|
||||
rootfs = ByteBufferBlockDevice.createFromStream(Buildroot.getRootFilesystem(), true);
|
||||
} catch (final IOException e) {
|
||||
LOGGER.error(e);
|
||||
rootfs = ByteBufferBlockDevice.create(0, true);
|
||||
}
|
||||
ROOT_FS = rootfs;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
public final MinecraftRealTimeCounter rtc = new MinecraftRealTimeCounter();
|
||||
@@ -46,30 +68,31 @@ public final class VirtualMachine {
|
||||
board.getCpu().setFrequency(REPORTED_CPU_FREQUENCY);
|
||||
|
||||
vmAdapter = new VirtualMachineDeviceBusAdapter(board);
|
||||
final VMContext context = vmAdapter.getGlobalContext();
|
||||
|
||||
final MemoryRangeAllocator memoryRangeAllocator = context.getMemoryRangeAllocator();
|
||||
final InterruptAllocator interruptAllocator = context.getInterruptAllocator();
|
||||
final InterruptController interruptController = context.getInterruptController();
|
||||
|
||||
uart = new UART16550A();
|
||||
uart.getInterrupt().set(vmAdapter.claimInterrupt(), board.getInterruptController());
|
||||
board.addDevice(uart);
|
||||
interruptAllocator.claimInterrupt(UART_INTERRUPT).ifPresent(interrupt ->
|
||||
uart.getInterrupt().set(interrupt, interruptController));
|
||||
memoryRangeAllocator.claimMemoryRange(uart);
|
||||
|
||||
hdd = new VirtIOBlockDevice(board.getMemoryMap());
|
||||
hdd.getInterrupt().set(vmAdapter.claimInterrupt(), board.getInterruptController());
|
||||
board.addDevice(hdd);
|
||||
|
||||
final ByteBufferBlockDevice blockDevice;
|
||||
try {
|
||||
blockDevice = ByteBufferBlockDevice.createFromStream(Buildroot.getRootFilesystem(), true);
|
||||
hdd.setBlockDevice(blockDevice);
|
||||
} catch (final IOException e) {
|
||||
LOGGER.error(e);
|
||||
}
|
||||
hdd = new VirtIOBlockDevice(board.getMemoryMap(), ROOT_FS);
|
||||
interruptAllocator.claimInterrupt(HDD_INTERRUPT).ifPresent(interrupt ->
|
||||
hdd.getInterrupt().set(interrupt, interruptController));
|
||||
memoryRangeAllocator.claimMemoryRange(hdd);
|
||||
|
||||
final GoldfishRTC rtc = new GoldfishRTC(this.rtc);
|
||||
rtc.getInterrupt().set(vmAdapter.claimInterrupt(), board.getInterruptController());
|
||||
board.addDevice(rtc);
|
||||
interruptAllocator.claimInterrupt(RTC_INTERRUPT).ifPresent(interrupt ->
|
||||
rtc.getInterrupt().set(interrupt, interruptController));
|
||||
memoryRangeAllocator.claimMemoryRange(rtc);
|
||||
|
||||
deviceBusSerialDevice = new VirtIOConsoleDevice(board.getMemoryMap());
|
||||
deviceBusSerialDevice.getInterrupt().set(vmAdapter.claimInterrupt(), board.getInterruptController());
|
||||
board.addDevice(deviceBusSerialDevice);
|
||||
interruptAllocator.claimInterrupt(RPC_INTERRUPT).ifPresent(interrupt ->
|
||||
deviceBusSerialDevice.getInterrupt().set(interrupt, interruptController));
|
||||
memoryRangeAllocator.claimMemoryRange(deviceBusSerialDevice);
|
||||
|
||||
rpcAdapter = new RPCAdapter(busController, deviceBusSerialDevice);
|
||||
|
||||
|
||||
@@ -2,18 +2,15 @@ package li.cil.oc2.common.vm;
|
||||
|
||||
import li.cil.ceres.api.Serialized;
|
||||
import li.cil.oc2.api.bus.device.Device;
|
||||
import li.cil.oc2.api.bus.device.vm.VMDevice;
|
||||
import li.cil.oc2.api.bus.device.vm.VMDeviceLifecycleEventType;
|
||||
import li.cil.oc2.api.bus.device.vm.VMDeviceLifecycleListener;
|
||||
import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult;
|
||||
import li.cil.oc2.api.bus.device.vm.*;
|
||||
import li.cil.sedna.api.Board;
|
||||
import li.cil.sedna.riscv.device.R5PlatformLevelInterruptController;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public final class VirtualMachineDeviceBusAdapter {
|
||||
private final Board board;
|
||||
|
||||
private final ManagedVMContext globalContext;
|
||||
private final BitSet claimedInterrupts = new BitSet();
|
||||
private final HashMap<VMDevice, ManagedVMContext> deviceContexts = new HashMap<>();
|
||||
private final ArrayList<VMDevice> incompleteLoads = new ArrayList<>();
|
||||
@@ -32,20 +29,12 @@ public final class VirtualMachineDeviceBusAdapter {
|
||||
|
||||
public VirtualMachineDeviceBusAdapter(final Board board) {
|
||||
this.board = board;
|
||||
this.globalContext = new ManagedVMContext(board, claimedInterrupts, reservedInterrupts);
|
||||
this.claimedInterrupts.set(0);
|
||||
}
|
||||
|
||||
public int claimInterrupt() {
|
||||
return claimInterrupt(claimedInterrupts.nextClearBit(0));
|
||||
}
|
||||
|
||||
public int claimInterrupt(final int interrupt) {
|
||||
if (interrupt < 1 || interrupt >= R5PlatformLevelInterruptController.INTERRUPT_COUNT) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
claimedInterrupts.set(interrupt);
|
||||
return interrupt;
|
||||
public VMContext getGlobalContext() {
|
||||
return globalContext;
|
||||
}
|
||||
|
||||
public boolean load() {
|
||||
|
||||
@@ -138,7 +138,7 @@ public final class VMDeviceTests {
|
||||
return VMDeviceLoadResult.success();
|
||||
});
|
||||
|
||||
adapter.claimInterrupt(claimedInterrupt);
|
||||
adapter.getGlobalContext().getInterruptAllocator().claimInterrupt(claimedInterrupt);
|
||||
|
||||
adapter.addDevices(Collections.singleton(device));
|
||||
assertTrue(adapter.load());
|
||||
|
||||
Reference in New Issue
Block a user