From 974be9dda6a0b3ebc1cb775146b9d143a93becfc Mon Sep 17 00:00:00 2001 From: minjaesong Date: Thu, 15 Jun 2023 23:30:57 +0900 Subject: [PATCH] distinguishing zero-byte write from full-block write --- terranmon.txt | 4 +- .../src/net/torvald/tsvm/SerialHelper.kt | 10 +++-- .../net/torvald/tsvm/peripheral/IOSpace.kt | 16 +++---- .../torvald/tsvm/peripheral/TevdDiskDrive.kt | 43 +++++++++++++------ 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/terranmon.txt b/terranmon.txt index b54bfdd..db0b5d3 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -110,15 +110,17 @@ MMIO 4080..4083 RO: 8-bit status code for connected device 4084..4091 RO: Block transfer status - 0b nnnnnnnn a000 mmmm + 0b nnnnnnnn a00z mmmm n-read: size of the block from the other device, LSB (4096-full block size is zero) m-read: size of the block from the other device, MSB (4096-full block size is zero) a-read: if the other device hasNext (doYouHaveNext), false if device not present + z-read: set if the size is actually 0 instead of 4096 n-write: size of the block I'm sending, LSB (4096-full block size is zero) m-write: size of the block I'm sending, MSB (4096-full block size is zero) a-write: if there's more to send (hasNext) + z-write: set if the size is actually 0 instead of 4096 4092..4095 RW: Block transfer control for Port 1 through 4 0b 00ms abcd diff --git a/tsvm_core/src/net/torvald/tsvm/SerialHelper.kt b/tsvm_core/src/net/torvald/tsvm/SerialHelper.kt index 30c541c..f94add2 100644 --- a/tsvm_core/src/net/torvald/tsvm/SerialHelper.kt +++ b/tsvm_core/src/net/torvald/tsvm/SerialHelper.kt @@ -119,16 +119,18 @@ object SerialHelper { 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), - ((blockSize ushr 8).and(15) or (moreToSend.toInt(7))).toByte() + ((blockSize ushr 8).and(15) or (moreToSend.toInt(7)) or (blockSize == 0).toInt(4)).toByte() ) } private fun getBlockTransferStatus(vm: VM, portNo: Int): Pair { - val bits = vm.getIO().mmio_read(4084L + (portNo * 2))!!.toUint() or - (vm.getIO().mmio_read(4085L + (portNo * 2))!!.toUint() shl 8) + val lb = vm.getIO().mmio_read(4084L + (portNo * 2))!!.toUint() + val hb = vm.getIO().mmio_read(4085L + (portNo * 2))!!.toUint() + val bits = lb or (hb shl 8) val rawcnt = bits.and(4095) val gotMore = bits.and(0x8000) != 0 - return (if (rawcnt == 0) BLOCK_SIZE else rawcnt) to gotMore + val actuallyZero = (hb and 0x10 != 0) + return (if (rawcnt == 0 && !actuallyZero) BLOCK_SIZE else rawcnt) to gotMore } data class DeviceStatus(val code: Int, val message: String) diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/IOSpace.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/IOSpace.kt index 514ef99..ca96050 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/IOSpace.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/IOSpace.kt @@ -129,13 +129,13 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor { 4083L -> blockTransferPorts[3].getYourStatusCode().toByte() 4084L -> (blockTransferPorts[0].yourBlockSize().toByte()) - 4085L -> (blockTransferPorts[0].doYouHaveNext().toInt(7) or blockTransferPorts[0].yourBlockSize().ushr(8).and(15)).toByte() + 4085L -> (blockTransferPorts[0].doYouHaveNext().toInt(7) or (blockTransferPorts[0].yourBlockSize() == 0).toInt(4) or blockTransferPorts[0].yourBlockSize().ushr(8).and(15)).toByte() 4086L -> (blockTransferPorts[1].yourBlockSize().toByte()) - 4087L -> (blockTransferPorts[1].doYouHaveNext().toInt(7) or blockTransferPorts[1].yourBlockSize().ushr(8).and(15)).toByte() + 4087L -> (blockTransferPorts[1].doYouHaveNext().toInt(7) or (blockTransferPorts[1].yourBlockSize() == 0).toInt(4) or blockTransferPorts[1].yourBlockSize().ushr(8).and(15)).toByte() 4088L -> (blockTransferPorts[2].yourBlockSize().toByte()) - 4089L -> (blockTransferPorts[2].doYouHaveNext().toInt(7) or blockTransferPorts[2].yourBlockSize().ushr(8).and(15)).toByte() + 4089L -> (blockTransferPorts[2].doYouHaveNext().toInt(7) or (blockTransferPorts[2].yourBlockSize() == 0).toInt(4) or blockTransferPorts[2].yourBlockSize().ushr(8).and(15)).toByte() 4090L -> (blockTransferPorts[3].yourBlockSize().toByte()) - 4091L -> (blockTransferPorts[3].doYouHaveNext().toInt(7) or blockTransferPorts[3].yourBlockSize().ushr(8).and(15)).toByte() + 4091L -> (blockTransferPorts[3].doYouHaveNext().toInt(7) or (blockTransferPorts[3].yourBlockSize() == 0).toInt(4) or blockTransferPorts[3].yourBlockSize().ushr(8).and(15)).toByte() in 4092..4095 -> composeBlockTransferStatus(adi - 4092).toByte() @@ -196,7 +196,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor { 4085L -> { blockTransferPorts[0].hasNext.set(byte < 0) blockTransferPorts[0].blockSize.getAcquire().let { - blockTransferPorts[0].blockSize.setRelease(it.and(0x00FF) or byte.toInt().and(15)) + blockTransferPorts[0].blockSize.setRelease(it.and(0x00FF) or byte.toInt().and(15) or (it == 0).toInt(4)) } } @@ -207,7 +207,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor { 4087L -> { blockTransferPorts[1].hasNext.set(byte < 0) blockTransferPorts[1].blockSize.getAcquire().let { - blockTransferPorts[1].blockSize.setRelease(it.and(0x00FF) or byte.toInt().and(15)) + blockTransferPorts[1].blockSize.setRelease(it.and(0x00FF) or byte.toInt().and(15) or (it == 0).toInt(4)) } } @@ -218,7 +218,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor { 4089L -> { blockTransferPorts[2].hasNext.set(byte < 0) blockTransferPorts[2].blockSize.getAcquire().let { - blockTransferPorts[2].blockSize.setRelease(it.and(0x00FF) or byte.toInt().and(15)) + blockTransferPorts[2].blockSize.setRelease(it.and(0x00FF) or byte.toInt().and(15) or (it == 0).toInt(4)) } } @@ -229,7 +229,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor { 4091L -> { blockTransferPorts[3].hasNext.set(byte < 0) blockTransferPorts[3].blockSize.getAcquire().let { - blockTransferPorts[3].blockSize.setRelease(it.and(0x00FF) or byte.toInt().and(15)) + blockTransferPorts[3].blockSize.setRelease(it.and(0x00FF) or byte.toInt().and(15) or (it == 0).toInt(4)) } } diff --git a/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt b/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt index 0aa4310..88e62cc 100644 --- a/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt +++ b/tsvm_core/src/net/torvald/tsvm/peripheral/TevdDiskDrive.kt @@ -143,23 +143,38 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, theTevdPath: //println("[DiskDrive] writeout with inputdata length of ${inputData.size}") //println("[DiskDriveMsg] ${inputData.toString(Charsets.UTF_8)}") + println("[TevDiskDrive] write-payload (${inputData.size} bytes)") + + if (!fileOpen) throw InternalError("File is not open but the drive is in write mode") - System.arraycopy(inputData, 0, writeBuffer, writeBufferUsage, minOf(writeModeLength - writeBufferUsage, inputData.size, BLOCK_SIZE)) - writeBufferUsage += inputData.size - - if (writeBufferUsage >= writeModeLength) { - // commit to the disk - if (appendMode) { - val filesize = file.length() - file.pwrite(writeBuffer, 0, writeBuffer.size, filesize) - } - else if (writeMode) - file.overwrite(writeBuffer) - + if (writeBuffer.isEmpty()) { writeMode = false appendMode = false } + else { + System.arraycopy( + inputData, + 0, + writeBuffer, + writeBufferUsage, + minOf(writeModeLength - writeBufferUsage, inputData.size, BLOCK_SIZE) + ) + writeBufferUsage += inputData.size + + if (writeBufferUsage >= writeModeLength) { + // commit to the disk + if (appendMode) { + val filesize = file.length() + file.pwrite(writeBuffer, 0, writeBuffer.size, filesize) + } + else if (writeMode) + file.overwrite(writeBuffer) + + writeMode = false + appendMode = false + } + } } else if (fileOpenMode == 17) { if (!fileOpen) throw InternalError("Bootloader file is not open but the drive is in boot write mode") @@ -175,7 +190,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, theTevdPath: else { val inputString = inputData.trimNull().toString(VM.CHARSET) -// println("[TevDiskDrive] $inputString") + println("[TevDiskDrive] $inputString") if (inputString.startsWith("DEVRST\u0017")) { printdbg("Device Reset") @@ -430,6 +445,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, theTevdPath: } } else if (inputString.startsWith("WRITE")) { + writeModeLength = inputString.substring(5, inputString.length).toInt() if (!fileOpen) { statusCode.set(STATE_CODE_NO_FILE_OPENED) return @@ -440,7 +456,6 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, theTevdPath: } if (fileOpenMode == 1) { writeMode = true; appendMode = false } else if (fileOpenMode == 2) { writeMode = false; appendMode = true } - writeModeLength = inputString.substring(5, inputString.length).toInt() writeBuffer = ByteArray(writeModeLength) writeBufferUsage = 0 statusCode.set(STATE_CODE_STANDBY)