Disk: NeoMemory: Implement writing
parent
f05fd5e201
commit
f367fcecca
|
|
@ -152,7 +152,7 @@ set(SRC_FILES
|
||||||
disk/diskreaddriver.cpp
|
disk/diskreaddriver.cpp
|
||||||
disk/diskwritedriver.cpp
|
disk/diskwritedriver.cpp
|
||||||
disk/nulldiskdriver.cpp
|
disk/nulldiskdriver.cpp
|
||||||
disk/neomemorydiskreaddriver.cpp
|
disk/neomemorydiskdriver.cpp
|
||||||
disk/plasiondiskreaddriver.cpp
|
disk/plasiondiskreaddriver.cpp
|
||||||
disk/extextractordiskreaddriver.cpp
|
disk/extextractordiskreaddriver.cpp
|
||||||
disk/fat.cpp
|
disk/fat.cpp
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include "icsneo/disk/neomemorydiskdriver.h"
|
||||||
|
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
using namespace icsneo;
|
||||||
|
using namespace icsneo::Disk;
|
||||||
|
|
||||||
|
optional<uint64_t> NeoMemoryDiskDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report,
|
||||||
|
uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) {
|
||||||
|
static std::shared_ptr<MessageFilter> NeoMemorySDRead = std::make_shared<MessageFilter>(Network::NetID::NeoMemorySDRead);
|
||||||
|
|
||||||
|
if(pos % SectorSize != 0)
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
if(amount != SectorSize)
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
if(cachePos != pos || std::chrono::steady_clock::now() > cachedAt + CacheTime) {
|
||||||
|
// The cache does not have this data, go get it
|
||||||
|
const uint64_t currentSector = pos / SectorSize;
|
||||||
|
auto msg = com.waitForMessageSync([¤tSector, &com] {
|
||||||
|
return com.sendCommand(Command::NeoReadMemory, {
|
||||||
|
MemoryTypeSD,
|
||||||
|
uint8_t(currentSector & 0xFF),
|
||||||
|
uint8_t((currentSector >> 8) & 0xFF),
|
||||||
|
uint8_t((currentSector >> 16) & 0xFF),
|
||||||
|
uint8_t((currentSector >> 24) & 0xFF),
|
||||||
|
uint8_t(SectorSize & 0xFF),
|
||||||
|
uint8_t((SectorSize >> 8) & 0xFF),
|
||||||
|
uint8_t((SectorSize >> 16) & 0xFF),
|
||||||
|
uint8_t((SectorSize >> 24) & 0xFF)
|
||||||
|
});
|
||||||
|
}, NeoMemorySDRead, timeout);
|
||||||
|
|
||||||
|
if(!msg)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const auto sdmsg = std::dynamic_pointer_cast<NeoReadMemorySDMessage>(msg);
|
||||||
|
if(!sdmsg || sdmsg->data.size() != SectorSize) {
|
||||||
|
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
||||||
|
return nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(cache.data(), sdmsg->data.data(), SectorSize);
|
||||||
|
cachedAt = std::chrono::steady_clock::now();
|
||||||
|
cachePos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(into, cache.data(), SectorSize);
|
||||||
|
return SectorSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<uint64_t> NeoMemoryDiskDriver::writeLogicalDiskAligned(Communication& com, device_eventhandler_t report,
|
||||||
|
uint64_t pos, const uint8_t* atomicBuf, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) {
|
||||||
|
|
||||||
|
static std::shared_ptr<MessageFilter> NeoMemoryDone = std::make_shared<MessageFilter>(Network::NetID::NeoMemoryWriteDone);
|
||||||
|
|
||||||
|
if(pos % SectorSize != 0)
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
if(amount != SectorSize)
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
// Clear the cache if we're writing to the cached sector
|
||||||
|
if(pos == cachePos)
|
||||||
|
cachedAt = std::chrono::time_point<std::chrono::steady_clock>();
|
||||||
|
|
||||||
|
// Requesting an atomic operation, but neoMemory does not support it
|
||||||
|
// Continue on anyway but warn the caller
|
||||||
|
if(atomicBuf != nullptr)
|
||||||
|
report(APIEvent::Type::AtomicOperationCompletedNonatomically, NonatomicSeverity);
|
||||||
|
|
||||||
|
const uint64_t currentSector = pos / SectorSize;
|
||||||
|
auto msg = com.waitForMessageSync([¤tSector, &com, from, amount] {
|
||||||
|
std::vector<uint8_t> command = {
|
||||||
|
MemoryTypeSD,
|
||||||
|
uint8_t(currentSector & 0xFF),
|
||||||
|
uint8_t((currentSector >> 8) & 0xFF),
|
||||||
|
uint8_t((currentSector >> 16) & 0xFF),
|
||||||
|
uint8_t((currentSector >> 24) & 0xFF),
|
||||||
|
uint8_t(SectorSize & 0xFF),
|
||||||
|
uint8_t((SectorSize >> 8) & 0xFF),
|
||||||
|
};
|
||||||
|
command.insert(command.end(), from, from + amount);
|
||||||
|
return com.sendCommand(Command::NeoWriteMemory, command);
|
||||||
|
}, NeoMemoryDone, timeout);
|
||||||
|
|
||||||
|
if(!msg)
|
||||||
|
return nullopt;
|
||||||
|
|
||||||
|
return SectorSize;
|
||||||
|
}
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
#include "icsneo/disk/neomemorydiskreaddriver.h"
|
|
||||||
#include "icsneo/communication/message/neoreadmemorysdmessage.h"
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
using namespace icsneo;
|
|
||||||
using namespace icsneo::Disk;
|
|
||||||
|
|
||||||
optional<uint64_t> NeoMemoryDiskReadDriver::readLogicalDiskAligned(Communication& com, device_eventhandler_t report,
|
|
||||||
uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) {
|
|
||||||
static std::shared_ptr<MessageFilter> NeoMemorySDRead = std::make_shared<MessageFilter>(Network::NetID::NeoMemorySDRead);
|
|
||||||
|
|
||||||
if(amount != SectorSize)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if(cachePos != pos || std::chrono::steady_clock::now() > cachedAt + CacheTime) {
|
|
||||||
// The cache does not have this data, go get it
|
|
||||||
const uint64_t currentSector = pos / SectorSize;
|
|
||||||
auto msg = com.waitForMessageSync([¤tSector, &com] {
|
|
||||||
return com.sendCommand(Command::NeoReadMemory, {
|
|
||||||
MemoryTypeSD,
|
|
||||||
uint8_t(currentSector & 0xFF),
|
|
||||||
uint8_t((currentSector >> 8) & 0xFF),
|
|
||||||
uint8_t((currentSector >> 16) & 0xFF),
|
|
||||||
uint8_t((currentSector >> 24) & 0xFF),
|
|
||||||
uint8_t(SectorSize & 0xFF),
|
|
||||||
uint8_t((SectorSize >> 8) & 0xFF),
|
|
||||||
uint8_t((SectorSize >> 16) & 0xFF),
|
|
||||||
uint8_t((SectorSize >> 24) & 0xFF)
|
|
||||||
});
|
|
||||||
}, NeoMemorySDRead, timeout);
|
|
||||||
|
|
||||||
if(!msg)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const auto sdmsg = std::dynamic_pointer_cast<NeoReadMemorySDMessage>(msg);
|
|
||||||
if(!sdmsg || sdmsg->data.size() != SectorSize) {
|
|
||||||
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
|
|
||||||
return nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(cache.data(), sdmsg->data.data(), SectorSize);
|
|
||||||
cachedAt = std::chrono::steady_clock::now();
|
|
||||||
cachePos = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(into, cache.data(), SectorSize);
|
|
||||||
return SectorSize;
|
|
||||||
}
|
|
||||||
|
|
@ -9,6 +9,7 @@ enum class Command : uint8_t {
|
||||||
EnableNetworkCommunication = 0x07,
|
EnableNetworkCommunication = 0x07,
|
||||||
EnableNetworkCommunicationEx = 0x08,
|
EnableNetworkCommunicationEx = 0x08,
|
||||||
NeoReadMemory = 0x40,
|
NeoReadMemory = 0x40,
|
||||||
|
NeoWriteMemory = 0x41,
|
||||||
RequestSerialNumber = 0xA1,
|
RequestSerialNumber = 0xA1,
|
||||||
GetMainVersion = 0xA3, // Previously known as RED_CMD_APP_VERSION_REQ
|
GetMainVersion = 0xA3, // Previously known as RED_CMD_APP_VERSION_REQ
|
||||||
SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM
|
SetSettings = 0xA4, // Previously known as RED_CMD_SET_BAUD_REQ, follow up with SaveSettings to write to EEPROM
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ public:
|
||||||
RED_DFLASH_READ = 22,
|
RED_DFLASH_READ = 22,
|
||||||
NeoMemorySDRead = 23, // Response from NeoMemory (MemoryTypeSD)
|
NeoMemorySDRead = 23, // Response from NeoMemory (MemoryTypeSD)
|
||||||
CAN_ERRBITS = 24,
|
CAN_ERRBITS = 24,
|
||||||
RED_DFLASH_WRITE_DONE = 25,
|
NeoMemoryWriteDone = 25,
|
||||||
RED_WAVE_CAN1_LOGICAL = 26,
|
RED_WAVE_CAN1_LOGICAL = 26,
|
||||||
RED_WAVE_CAN2_LOGICAL = 27,
|
RED_WAVE_CAN2_LOGICAL = 27,
|
||||||
RED_WAVE_LIN1_LOGICAL = 28,
|
RED_WAVE_LIN1_LOGICAL = 28,
|
||||||
|
|
@ -275,6 +275,7 @@ public:
|
||||||
case NetID::LogicalDiskInfo:
|
case NetID::LogicalDiskInfo:
|
||||||
case NetID::EthPHYControl:
|
case NetID::EthPHYControl:
|
||||||
case NetID::NeoMemorySDRead:
|
case NetID::NeoMemorySDRead:
|
||||||
|
case NetID::NeoMemoryWriteDone:
|
||||||
return Type::Internal;
|
return Type::Internal;
|
||||||
case NetID::Invalid:
|
case NetID::Invalid:
|
||||||
case NetID::Any:
|
case NetID::Any:
|
||||||
|
|
@ -367,8 +368,8 @@ public:
|
||||||
return "NeoMemorySDRead";
|
return "NeoMemorySDRead";
|
||||||
case NetID::CAN_ERRBITS:
|
case NetID::CAN_ERRBITS:
|
||||||
return "CAN_ERRBITS";
|
return "CAN_ERRBITS";
|
||||||
case NetID::RED_DFLASH_WRITE_DONE:
|
case NetID::NeoMemoryWriteDone:
|
||||||
return "RED_DFLASH_WRITE_DONE";
|
return "NeoMemoryWriteDone";
|
||||||
case NetID::RED_WAVE_CAN1_LOGICAL:
|
case NetID::RED_WAVE_CAN1_LOGICAL:
|
||||||
return "RED_WAVE_CAN1_LOGICAL";
|
return "RED_WAVE_CAN1_LOGICAL";
|
||||||
case NetID::RED_WAVE_CAN2_LOGICAL:
|
case NetID::RED_WAVE_CAN2_LOGICAL:
|
||||||
|
|
@ -835,9 +836,9 @@ private:
|
||||||
#define ICSNEO_NETID_RED_EXT_MEMORYREAD 20
|
#define ICSNEO_NETID_RED_EXT_MEMORYREAD 20
|
||||||
#define ICSNEO_NETID_RED_INT_MEMORYREAD 21
|
#define ICSNEO_NETID_RED_INT_MEMORYREAD 21
|
||||||
#define ICSNEO_NETID_RED_DFLASH_READ 22
|
#define ICSNEO_NETID_RED_DFLASH_READ 22
|
||||||
#define ICSNEO_NETID_RED_SDCARD_READ 23
|
#define ICSNEO_NETID_NEOMEMORY_SD_READ 23
|
||||||
#define ICSNEO_NETID_CAN_ERRBITS 24
|
#define ICSNEO_NETID_CAN_ERRBITS 24
|
||||||
#define ICSNEO_NETID_RED_DFLASH_WRITE_DONE 25
|
#define ICSNEO_NETID_NEOMEMORY_WRITE_DONE 25
|
||||||
#define ICSNEO_NETID_RED_WAVE_CAN1_LOGICAL 26
|
#define ICSNEO_NETID_RED_WAVE_CAN1_LOGICAL 26
|
||||||
#define ICSNEO_NETID_RED_WAVE_CAN2_LOGICAL 27
|
#define ICSNEO_NETID_RED_WAVE_CAN2_LOGICAL 27
|
||||||
#define ICSNEO_NETID_RED_WAVE_LIN1_LOGICAL 28
|
#define ICSNEO_NETID_RED_WAVE_LIN1_LOGICAL 28
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include "icsneo/device/devicetype.h"
|
#include "icsneo/device/devicetype.h"
|
||||||
#include "icsneo/platform/pcap.h"
|
#include "icsneo/platform/pcap.h"
|
||||||
#include "icsneo/disk/extextractordiskreaddriver.h"
|
#include "icsneo/disk/extextractordiskreaddriver.h"
|
||||||
|
#include "icsneo/disk/neomemorydiskdriver.h"
|
||||||
#include "icsneo/device/tree/neovired2/neovired2settings.h"
|
#include "icsneo/device/tree/neovired2/neovired2settings.h"
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
@ -68,7 +69,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NeoVIRED2(neodevice_t neodevice) : Device(neodevice) {
|
NeoVIRED2(neodevice_t neodevice) : Device(neodevice) {
|
||||||
initialize<PCAP, NeoVIRED2Settings, Disk::ExtExtractorDiskReadDriver>();
|
initialize<PCAP, NeoVIRED2Settings, Disk::ExtExtractorDiskReadDriver, Disk::NeoMemoryDiskDriver>();
|
||||||
getWritableNeoDevice().type = DEVICE_TYPE;
|
getWritableNeoDevice().type = DEVICE_TYPE;
|
||||||
productId = PRODUCT_ID;
|
productId = PRODUCT_ID;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "icsneo/device/devicetype.h"
|
#include "icsneo/device/devicetype.h"
|
||||||
#include "icsneo/platform/ftdi.h"
|
#include "icsneo/platform/ftdi.h"
|
||||||
#include "icsneo/disk/plasiondiskreaddriver.h"
|
#include "icsneo/disk/plasiondiskreaddriver.h"
|
||||||
|
#include "icsneo/disk/neomemorydiskdriver.h"
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
|
|
@ -25,7 +26,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NeoVIION(neodevice_t neodevice) : Plasion(neodevice) {
|
NeoVIION(neodevice_t neodevice) : Plasion(neodevice) {
|
||||||
initialize<FTDI, NullSettings, Disk::PlasionDiskReadDriver>();
|
initialize<FTDI, NullSettings, Disk::PlasionDiskReadDriver, Disk::NeoMemoryDiskDriver>();
|
||||||
getWritableNeoDevice().type = DEVICE_TYPE;
|
getWritableNeoDevice().type = DEVICE_TYPE;
|
||||||
productId = PRODUCT_ID;
|
productId = PRODUCT_ID;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
#ifndef __NEOMEMORYDISKREADDRIVER_H__
|
#ifndef __NEOMEMORYDISKDRIVER_H__
|
||||||
#define __NEOMEMORYDISKREADDRIVER_H__
|
#define __NEOMEMORYDISKDRIVER_H__
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
||||||
#include "icsneo/disk/diskreaddriver.h"
|
#include "icsneo/disk/diskreaddriver.h"
|
||||||
|
#include "icsneo/disk/diskwritedriver.h"
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
|
@ -12,11 +13,11 @@ namespace icsneo {
|
||||||
namespace Disk {
|
namespace Disk {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A disk read driver which uses the neoMemory command to read from the disk
|
* A disk driver which uses the neoMemory command to read from or write to the disk
|
||||||
*
|
*
|
||||||
* This can only request reads by sector, so it will be very slow, but is likely supported by any device with a disk
|
* This can only make requests per sector, so it will be very slow, but is likely supported by any device with a disk
|
||||||
*/
|
*/
|
||||||
class NeoMemoryDiskReadDriver : public ReadDriver {
|
class NeoMemoryDiskDriver : public ReadDriver, public WriteDriver {
|
||||||
public:
|
public:
|
||||||
std::pair<uint32_t, uint32_t> getBlockSizeBounds() const override {
|
std::pair<uint32_t, uint32_t> getBlockSizeBounds() const override {
|
||||||
static_assert(SectorSize <= std::numeric_limits<uint32_t>::max(), "Incorrect sector size");
|
static_assert(SectorSize <= std::numeric_limits<uint32_t>::max(), "Incorrect sector size");
|
||||||
|
|
@ -36,6 +37,9 @@ private:
|
||||||
|
|
||||||
optional<uint64_t> readLogicalDiskAligned(Communication& com, device_eventhandler_t report,
|
optional<uint64_t> readLogicalDiskAligned(Communication& com, device_eventhandler_t report,
|
||||||
uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) override;
|
uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout) override;
|
||||||
|
|
||||||
|
optional<uint64_t> writeLogicalDiskAligned(Communication& com, device_eventhandler_t report,
|
||||||
|
uint64_t pos, const uint8_t* atomicBuf, const uint8_t* from, uint64_t amount, std::chrono::milliseconds timeout) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Disk
|
} // namespace Disk
|
||||||
|
|
@ -43,4 +47,4 @@ private:
|
||||||
} // namespace icsneo
|
} // namespace icsneo
|
||||||
|
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
#endif // __NEOMEMORYDISKREADDRIVER_H__
|
#endif // __NEOMEMORYDISKDRIVER_H__
|
||||||
Loading…
Reference in New Issue