From d0ef473adcf15b887eeb090cfc55d826c0fea993 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Thu, 22 Oct 2020 14:16:36 +0900 Subject: [PATCH] SerialHelper would work as intended MINUS the wait function --- assets/serialtest.js | 14 +++++ assets/tvdos/fsh.js | 5 +- src/net/torvald/tsvm/SerialHelper.kt | 54 ++++++++++++++++--- src/net/torvald/tsvm/VMGUI.kt | 3 +- src/net/torvald/tsvm/VMJSR223Delegate.kt | 1 + src/net/torvald/tsvm/VMRunnerFactory.kt | 1 + .../tsvm/peripheral/BlockTransferInterface.kt | 11 ++-- .../tsvm/peripheral/BlockTransferPort.kt | 19 +++++-- src/net/torvald/tsvm/peripheral/IOSpace.kt | 12 +++-- .../tsvm/peripheral/TestFunctionGenerator.kt | 15 +++--- terranmon.txt | 2 +- 11 files changed, 110 insertions(+), 27 deletions(-) create mode 100644 assets/serialtest.js diff --git a/assets/serialtest.js b/assets/serialtest.js new file mode 100644 index 0000000..70dfff8 --- /dev/null +++ b/assets/serialtest.js @@ -0,0 +1,14 @@ +var ba = com.sendMessageGetBytes(0, [0x44,0x45,0x56,0x4e,0x41,0x4d,0x17]); +serial.println(ba); +for (let k = 0; k < 4096; k++) { + serial.print(String.fromCharCode(ba[k])); +} +serial.print("\n"); + +ba = com.pullMessage(0) +for (let k = 0; k < 4096; k++) { + serial.print(String.fromCharCode(ba[k])); +} +serial.print("\n"); + +serial.println("\nk bye") \ No newline at end of file diff --git a/assets/tvdos/fsh.js b/assets/tvdos/fsh.js index 67f8d8e..9b19eba 100644 --- a/assets/tvdos/fsh.js +++ b/assets/tvdos/fsh.js @@ -125,4 +125,7 @@ con.color_pair(201,255); print("cya!"); let konsht = 3412341241; -print(konsht); \ No newline at end of file +println(konsht); + +let pppp = graphics.getCursorYX(); +println(pppp.toString()); \ No newline at end of file diff --git a/src/net/torvald/tsvm/SerialHelper.kt b/src/net/torvald/tsvm/SerialHelper.kt index 51bb8bd..22e8e7a 100644 --- a/src/net/torvald/tsvm/SerialHelper.kt +++ b/src/net/torvald/tsvm/SerialHelper.kt @@ -15,28 +15,50 @@ object SerialHelper { fun sendMessageGetBytes(vm: VM, portNo: Int, message: ByteArray): ByteArray { sendMessage(vm, portNo, message) waitUntilReady(vm, portNo) - return getMessage(vm, portNo) + return fetchResponse(vm, portNo) } fun sendMessage(vm: VM, portNo: Int, message: ByteArray) { if (!checkIfDeviceIsThere(vm, portNo)) throw IllegalStateException("Device not connected") if (message.size > BLOCK_SIZE) throw NotImplementedError("sending message greater than 4096 is a future work :p") - UnsafeHelper.memcpyRaw( + /*UnsafeHelper.memcpyRaw( message, UnsafeHelper.getArrayOffset(message), null, vm.getIO().blockTransferTx[portNo].ptr, minOf(BLOCK_SIZE, message.size).toLong() - ) + )*/ + + for (k in 0 until BLOCK_SIZE) { + vm.getIO().blockTransferTx[portNo][k.toLong()] = if (k >= message.size) 0 else message[k] + } + initiateWriting(vm, portNo) + + // TODO assuming the write operation is finished... (wait for something?) + getReady(vm, portNo) } - fun getMessage(vm: VM, portNo: Int): ByteArray { + // Returns what's on the RX buffer after sendMessage() + fun fetchResponse(vm: VM, portNo: Int): ByteArray { + val incomingMsg = ByteArray(BLOCK_SIZE) + + UnsafeHelper.memcpyRaw( + null, vm.getIO().blockTransferRx[portNo].ptr, + incomingMsg, UnsafeHelper.getArrayOffset(incomingMsg), + BLOCK_SIZE.toLong() + ) + + return incomingMsg + } + + // Initiates startSend() function from the connected device + fun pullMessage(vm: VM, portNo: Int): ByteArray { val msgBuffer = ByteArrayOutputStream(BLOCK_SIZE) // pull all the blocks of messages do { initiateReading(vm, portNo) - while (!checkIfDeviceIsReady(vm, portNo)) { Thread.sleep(SLEEP_TIME) } + waitUntilReady(vm, portNo) val transStat = getBlockTransferStatus(vm, portNo) val incomingMsg = ByteArray(transStat.first) @@ -48,7 +70,9 @@ object SerialHelper { ) msgBuffer.write(incomingMsg) - } while (getBlockTransferStatus(vm, portNo).second) + } while (transStat.second) + + getReady(vm, portNo) return msgBuffer.toByteArray() } @@ -63,7 +87,8 @@ object SerialHelper { } fun waitUntilReady(vm: VM, portNo: Int) { - while (!checkIfDeviceIsReady(vm, portNo)) { Thread.sleep(SLEEP_TIME) } + Thread.sleep(SLEEP_TIME) + //while (!checkIfDeviceIsReady(vm, portNo)) { Thread.sleep(SLEEP_TIME) } } @@ -81,6 +106,12 @@ object SerialHelper { vm.getIO().mmio_write(4092L + portNo, 0b0110) } + private fun getReady(vm: VM, portNo: Int) { + val flags = vm.getIO().mmio_read(4092L + portNo)!! + val newFlags = flags.and(0b1111_1001.toByte()).or(0b0000_0010) + vm.getIO().mmio_write(4092L + portNo, newFlags) + } + private fun setBlockTransferStatus(vm: VM, portNo: Int, blockSize: Int, moreToSend: Boolean = false) { vm.getIO().mmio_write(4084L + (portNo * 2), (blockSize and 255).toByte()) vm.getIO().mmio_write(4085L + (portNo * 2), @@ -99,4 +130,13 @@ object SerialHelper { private fun Boolean.toInt() = if (this) 1 else 0 data class DeviceStatus(val isError: Boolean, val code: Int, val message: String) +} + +class SerialHelperDelegate(val vm: VM) { + fun sendMessage(portNo: Int, message: ByteArray) = SerialHelper.sendMessage(vm, portNo, message) + fun pullMessage(portNo: Int) = SerialHelper.pullMessage(vm, portNo) + fun sendMessageGetBytes(portNo: Int, message: ByteArray) = SerialHelper.sendMessageGetBytes(vm, portNo, message) + fun fetchResponse(portNo: Int) = SerialHelper.fetchResponse(vm, portNo) + fun getDeviceStatus(portNo: Int) = SerialHelper.getDeviceStatus(vm, portNo) + fun waitUntilReady(portNo: Int) = SerialHelper.waitUntilReady(vm, portNo) } \ No newline at end of file diff --git a/src/net/torvald/tsvm/VMGUI.kt b/src/net/torvald/tsvm/VMGUI.kt index 307dd9b..eb42325 100644 --- a/src/net/torvald/tsvm/VMGUI.kt +++ b/src/net/torvald/tsvm/VMGUI.kt @@ -66,7 +66,8 @@ class VMGUI(val appConfig: LwjglApplicationConfiguration) : ApplicationAdapter() //val fr = FileReader("./assets/tvdos/command.js") //val fr = FileReader("./assets/zippytest.js") - val fr = FileReader("./assets/tvdos/fsh.js") + val fr = FileReader("./assets/serialtest.js") + //val fr = FileReader("./assets/tvdos/fsh.js") //val fr = FileReader("./assets/tbas/basic.js") //val fr = FileReader("./assets/jscon.js") val prg = fr.readText() diff --git a/src/net/torvald/tsvm/VMJSR223Delegate.kt b/src/net/torvald/tsvm/VMJSR223Delegate.kt index 9148ef2..2bab09a 100644 --- a/src/net/torvald/tsvm/VMJSR223Delegate.kt +++ b/src/net/torvald/tsvm/VMJSR223Delegate.kt @@ -100,6 +100,7 @@ class VMJSR223Delegate(val vm: VM) { } class VMSerialDebugger(val vm: VM) { + fun print(s: String) = System.out.print(s) fun println(s: String) = System.out.println(s) fun printerr(s: String) = System.err.println(s) } \ No newline at end of file diff --git a/src/net/torvald/tsvm/VMRunnerFactory.kt b/src/net/torvald/tsvm/VMRunnerFactory.kt index 5233f94..310c5e7 100644 --- a/src/net/torvald/tsvm/VMRunnerFactory.kt +++ b/src/net/torvald/tsvm/VMRunnerFactory.kt @@ -79,6 +79,7 @@ object VMRunnerFactory { bind.put("serial", VMSerialDebugger(vm)) bind.put("gzip", CompressorDelegate()) bind.put("base64", Base64Delegate()) + bind.put("com", SerialHelperDelegate(vm)) if (extension == "js") { val fr = FileReader("./assets/JS_INIT.js") diff --git a/src/net/torvald/tsvm/peripheral/BlockTransferInterface.kt b/src/net/torvald/tsvm/peripheral/BlockTransferInterface.kt index 2ddc77c..0ac6736 100644 --- a/src/net/torvald/tsvm/peripheral/BlockTransferInterface.kt +++ b/src/net/torvald/tsvm/peripheral/BlockTransferInterface.kt @@ -1,5 +1,7 @@ package net.torvald.tsvm.peripheral +import java.io.IOException + abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolean) { protected var recipient: BlockTransferInterface? = null @@ -23,7 +25,7 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea abstract fun startSend() /** The actual implementation */ protected fun startSend(sendfun: ((BlockTransferInterface) -> Unit)? = null) { - if (areYouReady()) { + //if (areYouReady()) { busy = true ready = false @@ -33,13 +35,16 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea busy = false ready = true - } + //} + //else { + // throw IOException("${this.javaClass.canonicalName}: Device '${recipient?.javaClass?.canonicalName}' is not ready to receive") + //} } /** Ask the recipient to start send its thing to me so that I can 'read' */ open fun startRead() { - recipient?.startSend(null) + recipient?.startSend() } /** A method called by the sender so it can ACTUALLY write its thing onto me. */ diff --git a/src/net/torvald/tsvm/peripheral/BlockTransferPort.kt b/src/net/torvald/tsvm/peripheral/BlockTransferPort.kt index 8f6af80..4ccdb57 100644 --- a/src/net/torvald/tsvm/peripheral/BlockTransferPort.kt +++ b/src/net/torvald/tsvm/peripheral/BlockTransferPort.kt @@ -12,19 +12,30 @@ class BlockTransferPort(val vm: VM, val portno: Int) : BlockTransferInterface(tr override fun startSend() { startSend { recipient -> - val ba = ByteArray(BLOCK_SIZE) { vm.getIO().blockTransferRx[portno][it.toLong()] } + val ba = ByteArray(BLOCK_SIZE) { vm.getIO().blockTransferTx[portno][it.toLong()] } recipient.writeout(ba) } + + this.ready = true + this.busy = false } override fun hasNext(): Boolean = hasNext override fun writeout(inputData: ByteArray) { writeout(inputData) { - val copySize = minOf(BLOCK_SIZE, inputData.size).toLong() - val arrayOffset = UnsafeHelper.getArrayOffset(inputData) - UnsafeHelper.memcpyRaw(inputData, arrayOffset, null, vm.getIO().blockTransferRx[portno].ptr, copySize) + //val copySize = minOf(BLOCK_SIZE, inputData.size).toLong() + //val arrayOffset = UnsafeHelper.getArrayOffset(inputData) + //UnsafeHelper.memcpyRaw(inputData, arrayOffset, null, vm.getIO().blockTransferRx[portno].ptr, copySize) + + // not exposing raw memory to block probable security hole + for (k in 0 until BLOCK_SIZE) { + vm.getIO().blockTransferRx[portno][k.toLong()] = if (k >= inputData.size) 0 else inputData[k] + } } + + this.ready = true + this.busy = false } diff --git a/src/net/torvald/tsvm/peripheral/IOSpace.kt b/src/net/torvald/tsvm/peripheral/IOSpace.kt index a51555c..4b6778a 100644 --- a/src/net/torvald/tsvm/peripheral/IOSpace.kt +++ b/src/net/torvald/tsvm/peripheral/IOSpace.kt @@ -38,8 +38,8 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor { private val keyEventBuffers = ByteArray(8) init { - //blockTransferPorts[0].attachDevice(TestFunctionGenerator()) - blockTransferPorts[0].attachDevice(TestDiskDrive(0)) + blockTransferPorts[0].attachDevice(TestFunctionGenerator()) + blockTransferPorts[1].attachDevice(TestDiskDrive(0)) } private fun composeBlockTransferStatus(portno: Int): Int { @@ -55,10 +55,14 @@ class IOSpace(val vm: VM) : PeriBase, InputProcessor { blockTransferPorts[portno].setMode(bits.and(0b0000_1000) != 0.toByte()) blockTransferPorts[portno].ready = bits.and(0b0000_0010) != 0.toByte() if (bits.and(0b0000_0100) != 0.toByte()) { - if (blockTransferPorts[portno].getMode()) + if (blockTransferPorts[portno].getMode()) { + println("[IOSpace] startSend()") blockTransferPorts[portno].startSend() - else + } + else { + println("[IOSpace] startRead()") blockTransferPorts[portno].startRead() + } } } diff --git a/src/net/torvald/tsvm/peripheral/TestFunctionGenerator.kt b/src/net/torvald/tsvm/peripheral/TestFunctionGenerator.kt index 19a2421..49bb5e4 100644 --- a/src/net/torvald/tsvm/peripheral/TestFunctionGenerator.kt +++ b/src/net/torvald/tsvm/peripheral/TestFunctionGenerator.kt @@ -1,5 +1,6 @@ package net.torvald.tsvm.peripheral +import net.torvald.tsvm.VM import java.util.ArrayList class TestFunctionGenerator : BlockTransferInterface(true, false) { @@ -33,16 +34,16 @@ Nunc mollis nibh vitae sapien consequat, ut vestibulum sem pharetra. Aliquam iac } override fun startSend() { - if (readModeLength > 0) { - readModeLength = 0 - startSend { it.writeout(filecontent_lorem) } - } + println("[TestFunctionGenerator] startSend()") + startSend { it.writeout(filecontent_lorem) } } override fun hasNext(): Boolean = false override fun writeout(inputData: ByteArray) { - val inputString = inputData.toString() + val inputString = inputData.toString(VM.CHARSET) + + println("InputString: $inputString") if (inputString.startsWith("DEVRST\u0017")) { readModeLength = -1 @@ -50,8 +51,10 @@ Nunc mollis nibh vitae sapien consequat, ut vestibulum sem pharetra. Aliquam iac } else if (inputString.startsWith("DEVTYP\u0017")) startSend { it.writeout(composeSerialAns("STOR")) } - else if (inputString.startsWith("DEVNAM\u0017")) + else if (inputString.startsWith("DEVNAM\u0017")) { + println("Device name?") startSend { it.writeout(composeSerialAns("Testtec Virtual Disk Drive")) } + } else if (inputString.startsWith("OPENR\"")) fileOpen = true else if (inputString.startsWith("CLOSE")) diff --git a/terranmon.txt b/terranmon.txt index 8e7bf7d..17af7ef 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -101,7 +101,7 @@ MMIO a: 1 for send, 0 for receive - b-write: 1 to start sending if a-bit is set; if f-bit is unset, make other device to start sending + b-write: 1 to start sending if a-bit is set; if a-bit is unset, make other device to start sending b-read: if this bit is set, you're currently receiving something (aka busy) c-write: I'm ready to receive