distinguishing zero-byte write from full-block write

This commit is contained in:
minjaesong
2023-06-15 23:30:57 +09:00
parent 445c1a873f
commit 974be9dda6
4 changed files with 46 additions and 27 deletions

View File

@@ -110,15 +110,17 @@ MMIO
4080..4083 RO: 8-bit status code for connected device 4080..4083 RO: 8-bit status code for connected device
4084..4091 RO: Block transfer status 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) 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) 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 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) 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) 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) 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 4092..4095 RW: Block transfer control for Port 1 through 4
0b 00ms abcd 0b 00ms abcd

View File

@@ -119,16 +119,18 @@ object SerialHelper {
private fun setBlockTransferStatus(vm: VM, portNo: Int, blockSize: Int, moreToSend: Boolean = false) { 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(4084L + (portNo * 2), (blockSize and 255).toByte())
vm.getIO().mmio_write(4085L + (portNo * 2), 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<Int, Boolean> { private fun getBlockTransferStatus(vm: VM, portNo: Int): Pair<Int, Boolean> {
val bits = vm.getIO().mmio_read(4084L + (portNo * 2))!!.toUint() or val lb = vm.getIO().mmio_read(4084L + (portNo * 2))!!.toUint()
(vm.getIO().mmio_read(4085L + (portNo * 2))!!.toUint() shl 8) val hb = vm.getIO().mmio_read(4085L + (portNo * 2))!!.toUint()
val bits = lb or (hb shl 8)
val rawcnt = bits.and(4095) val rawcnt = bits.and(4095)
val gotMore = bits.and(0x8000) != 0 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) data class DeviceStatus(val code: Int, val message: String)

View File

@@ -129,13 +129,13 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
4083L -> blockTransferPorts[3].getYourStatusCode().toByte() 4083L -> blockTransferPorts[3].getYourStatusCode().toByte()
4084L -> (blockTransferPorts[0].yourBlockSize().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()) 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()) 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()) 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() in 4092..4095 -> composeBlockTransferStatus(adi - 4092).toByte()
@@ -196,7 +196,7 @@ class IOSpace(val vm: VM) : PeriBase("io"), InputProcessor {
4085L -> { 4085L -> {
blockTransferPorts[0].hasNext.set(byte < 0) blockTransferPorts[0].hasNext.set(byte < 0)
blockTransferPorts[0].blockSize.getAcquire().let { 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 -> { 4087L -> {
blockTransferPorts[1].hasNext.set(byte < 0) blockTransferPorts[1].hasNext.set(byte < 0)
blockTransferPorts[1].blockSize.getAcquire().let { 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 -> { 4089L -> {
blockTransferPorts[2].hasNext.set(byte < 0) blockTransferPorts[2].hasNext.set(byte < 0)
blockTransferPorts[2].blockSize.getAcquire().let { 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 -> { 4091L -> {
blockTransferPorts[3].hasNext.set(byte < 0) blockTransferPorts[3].hasNext.set(byte < 0)
blockTransferPorts[3].blockSize.getAcquire().let { 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))
} }
} }

View File

@@ -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("[DiskDrive] writeout with inputdata length of ${inputData.size}")
//println("[DiskDriveMsg] ${inputData.toString(Charsets.UTF_8)}") //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") 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)) if (writeBuffer.isEmpty()) {
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 writeMode = false
appendMode = 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) { else if (fileOpenMode == 17) {
if (!fileOpen) throw InternalError("Bootloader file is not open but the drive is in boot write mode") 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 { else {
val inputString = inputData.trimNull().toString(VM.CHARSET) val inputString = inputData.trimNull().toString(VM.CHARSET)
// println("[TevDiskDrive] $inputString") println("[TevDiskDrive] $inputString")
if (inputString.startsWith("DEVRST\u0017")) { if (inputString.startsWith("DEVRST\u0017")) {
printdbg("Device Reset") printdbg("Device Reset")
@@ -430,6 +445,7 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, theTevdPath:
} }
} }
else if (inputString.startsWith("WRITE")) { else if (inputString.startsWith("WRITE")) {
writeModeLength = inputString.substring(5, inputString.length).toInt()
if (!fileOpen) { if (!fileOpen) {
statusCode.set(STATE_CODE_NO_FILE_OPENED) statusCode.set(STATE_CODE_NO_FILE_OPENED)
return return
@@ -440,7 +456,6 @@ class TevdDiskDrive(private val vm: VM, private val driveNum: Int, theTevdPath:
} }
if (fileOpenMode == 1) { writeMode = true; appendMode = false } if (fileOpenMode == 1) { writeMode = true; appendMode = false }
else if (fileOpenMode == 2) { writeMode = false; appendMode = true } else if (fileOpenMode == 2) { writeMode = false; appendMode = true }
writeModeLength = inputString.substring(5, inputString.length).toInt()
writeBuffer = ByteArray(writeModeLength) writeBuffer = ByteArray(writeModeLength)
writeBufferUsage = 0 writeBufferUsage = 0
statusCode.set(STATE_CODE_STANDBY) statusCode.set(STATE_CODE_STANDBY)