mirror of
https://github.com/StrikerX3/StrikeBox.git
synced 2024-06-23 14:53:22 -04:00
Make ATA commands use shared memory instead of allocating/deallocating objects every time
This commit is contained in:
parent
c5f0363c61
commit
23d81bce64
74
src/common/vixen/shared_memory.h
Normal file
74
src/common/vixen/shared_memory.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace vixen {
|
||||
|
||||
/*!
|
||||
* A reusable block of memory that dynamically resizes to accomodate the
|
||||
* largest data structure written to it.
|
||||
*
|
||||
* Constructors and destructors are automatically invoked.
|
||||
*/
|
||||
class SharedMemory {
|
||||
public:
|
||||
SharedMemory() {}
|
||||
~SharedMemory() {
|
||||
if (m_dtor != nullptr) {
|
||||
m_dtor(*this);
|
||||
}
|
||||
if (m_memory != nullptr) {
|
||||
free(m_memory);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Reserves memory for the given data structure, invoking the constructor
|
||||
* with the given arguments. Placement new is used to initialize the object
|
||||
* or value directly into the allocated memory block.
|
||||
*
|
||||
* If another data structure is currently occupying the shared memory, it
|
||||
* will be destructed before reserving memory for the new data structure.
|
||||
*
|
||||
* If the new data structure is larger than the currently allocated memory
|
||||
* block, a new block will be allocated with the new data structure size,
|
||||
* otherwise the existing memory block is reused.
|
||||
*/
|
||||
template<class T, typename... Args>
|
||||
T* Allocate(Args... args) {
|
||||
// Invoke destructor from previous data structure
|
||||
if (m_dtor != nullptr) {
|
||||
m_dtor(*this);
|
||||
}
|
||||
|
||||
// Reallocate memory if new data structure is larger than the current buffer
|
||||
if (m_size < sizeof(T)) {
|
||||
if (m_memory != nullptr) {
|
||||
free(m_memory);
|
||||
}
|
||||
m_memory = malloc(sizeof(T));
|
||||
m_size = sizeof(T);
|
||||
}
|
||||
|
||||
// Update destructor to new data structure and call constructor
|
||||
m_dtor = [](SharedMemory& u) { ((T*)u.m_memory)->~T(); };
|
||||
return new(m_memory) T(args...);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Destructs the data structure present in the shared memory, if any.
|
||||
*/
|
||||
void Free() {
|
||||
if (m_dtor != nullptr) {
|
||||
m_dtor(*this);
|
||||
m_dtor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void *m_memory = nullptr;
|
||||
size_t m_size = 0;
|
||||
void (*m_dtor)(SharedMemory&) = nullptr;
|
||||
};
|
||||
|
||||
}
|
|
@ -137,7 +137,7 @@ bool ATAChannel::WriteControlPort(uint32_t value, uint8_t size) {
|
|||
log_debug("ATAChannel::WriteControlPort: Software reset triggered on channel %d\n", m_channel);
|
||||
// TODO: implement [9.3.1] for device 0 and [9.3.2] for device 1
|
||||
if (m_currentCommand != nullptr) {
|
||||
delete m_currentCommand;
|
||||
m_currentCommandMem.Free();
|
||||
m_currentCommand = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ void ATAChannel::ReadData(uint32_t *value, uint8_t size) {
|
|||
m_currentCommand->ReadData((uint8_t*)value, size);
|
||||
if (m_currentCommand->IsFinished()) {
|
||||
//log_spew("ATAChannel::ReadData: Finished processing command for channel %d\n", m_channel);
|
||||
delete m_currentCommand;
|
||||
m_currentCommandMem.Free();
|
||||
m_currentCommand = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ void ATAChannel::WriteData(uint32_t value, uint8_t size) {
|
|||
m_currentCommand->WriteData((uint8_t*)&value, size);
|
||||
if (m_currentCommand->IsFinished()) {
|
||||
//log_spew("ATAChannel::WriteData: Finished processing command for channel %d\n", m_channel);
|
||||
delete m_currentCommand;
|
||||
m_currentCommandMem.Free();
|
||||
m_currentCommand = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ void ATAChannel::WriteCommand(uint8_t value) {
|
|||
|
||||
// Instantiate the command
|
||||
auto factory = kCmdFactories.at(cmd);
|
||||
m_currentCommand = factory(*dev);
|
||||
m_currentCommand = factory(m_currentCommandMem, *dev);
|
||||
|
||||
// Every protocol starts by setting BSY=1
|
||||
m_regs.status |= StBusy;
|
||||
|
@ -227,7 +227,7 @@ void ATAChannel::WriteCommand(uint8_t value) {
|
|||
m_currentCommand->Execute();
|
||||
if (m_currentCommand->IsFinished()) {
|
||||
//log_spew("ATAChannel::WriteCommand: Finished processing command 0x%x for channel %d, device %d\n", cmd, m_channel, devIndex);
|
||||
delete m_currentCommand;
|
||||
m_currentCommandMem.Free();
|
||||
m_currentCommand = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -246,7 +246,7 @@ DMATransferResult ATAChannel::ReadDMA(uint8_t *dstBuffer, uint32_t readLen) {
|
|||
m_currentCommand->ReadData(dstBuffer, readLen);
|
||||
if (m_currentCommand->IsFinished()) {
|
||||
//log_spew("ATAChannel::ReadDMA: Finished processing command for channel %d\n", m_channel);
|
||||
delete m_currentCommand;
|
||||
m_currentCommandMem.Free();
|
||||
m_currentCommand = nullptr;
|
||||
return DMATransferEnd;
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ DMATransferResult ATAChannel::WriteDMA(uint8_t *srcBuffer, uint32_t writeLen) {
|
|||
m_currentCommand->WriteData(srcBuffer, writeLen);
|
||||
if (m_currentCommand->IsFinished()) {
|
||||
//log_spew("ATAChannel::WriteDMA: Finished processing command for channel %d\n", m_channel);
|
||||
delete m_currentCommand;
|
||||
m_currentCommandMem.Free();
|
||||
m_currentCommand = nullptr;
|
||||
return DMATransferEnd;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <mutex>
|
||||
|
||||
#include "vixen/cpu.h"
|
||||
#include "vixen/shared_memory.h"
|
||||
#include "../basic/irq.h"
|
||||
#include "../basic/interrupt.h"
|
||||
#include "ata_device.h"
|
||||
|
@ -106,6 +107,7 @@ private:
|
|||
|
||||
bool m_interrupt = false; // [5.2.9] INTRQ (Device Interrupt)
|
||||
|
||||
SharedMemory m_currentCommandMem;
|
||||
cmd::IATACommand *m_currentCommand;
|
||||
std::mutex m_commandMutex;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
#include "vixen/shared_memory.h"
|
||||
#include "../ata_device.h"
|
||||
|
||||
namespace vixen {
|
||||
|
@ -62,7 +63,7 @@ public:
|
|||
/*!
|
||||
* Defines the factory function type used to build a factory table.
|
||||
*/
|
||||
typedef IATACommand* (*Factory)(ATADevice& device);
|
||||
typedef IATACommand* (*Factory)(SharedMemory& sharedMemory, ATADevice& device);
|
||||
|
||||
protected:
|
||||
ATADevice& m_device;
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
IdentifyDevice(ATADevice& device);
|
||||
virtual ~IdentifyDevice() override;
|
||||
|
||||
static IATACommand *Factory(ATADevice& device) { return new IdentifyDevice(device); }
|
||||
static IATACommand *Factory(SharedMemory& sharedMemory, ATADevice& device) { return sharedMemory.Allocate<IdentifyDevice, ATADevice&>(device); }
|
||||
|
||||
protected:
|
||||
bool HasMoreData() override;
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
IdentifyPacketDevice(ATADevice& device);
|
||||
virtual ~IdentifyPacketDevice() override;
|
||||
|
||||
static IATACommand *Factory(ATADevice& device) { return new IdentifyPacketDevice(device); }
|
||||
static IATACommand *Factory(SharedMemory& sharedMemory, ATADevice& device) { return sharedMemory.Allocate<IdentifyPacketDevice, ATADevice&>(device); }
|
||||
|
||||
protected:
|
||||
bool HasMoreData() override;
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
InitializeDeviceParameters(ATADevice& device);
|
||||
virtual ~InitializeDeviceParameters() override;
|
||||
|
||||
static IATACommand *Factory(ATADevice& device) { return new InitializeDeviceParameters(device); }
|
||||
static IATACommand *Factory(SharedMemory& sharedMemory, ATADevice& device) { return sharedMemory.Allocate<InitializeDeviceParameters, ATADevice&>(device); }
|
||||
|
||||
protected:
|
||||
bool ExecuteImpl() override;
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
Packet(ATADevice& device);
|
||||
virtual ~Packet() override;
|
||||
|
||||
static IATACommand *Factory(ATADevice& device) { return new Packet(device); }
|
||||
static IATACommand *Factory(SharedMemory& sharedMemory, ATADevice& device) { return sharedMemory.Allocate<Packet, ATADevice&>(device); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
ReadDMA(ATADevice& device);
|
||||
virtual ~ReadDMA() override;
|
||||
|
||||
static IATACommand *Factory(ATADevice& device) { return new ReadDMA(device); }
|
||||
static IATACommand *Factory(SharedMemory& sharedMemory, ATADevice& device) { return sharedMemory.Allocate<ReadDMA, ATADevice&>(device); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
SecurityUnlock(ATADevice& device);
|
||||
virtual ~SecurityUnlock() override;
|
||||
|
||||
static IATACommand *Factory(ATADevice& device) { return new SecurityUnlock(device); }
|
||||
static IATACommand *Factory(SharedMemory& sharedMemory, ATADevice& device) { return sharedMemory.Allocate<SecurityUnlock, ATADevice&>(device); }
|
||||
|
||||
protected:
|
||||
bool Initialize() override;
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
SetFeatures(ATADevice& device);
|
||||
virtual ~SetFeatures() override;
|
||||
|
||||
static IATACommand *Factory(ATADevice& device) { return new SetFeatures(device); }
|
||||
static IATACommand *Factory(SharedMemory& sharedMemory, ATADevice& device) { return sharedMemory.Allocate<SetFeatures, ATADevice&>(device); }
|
||||
|
||||
protected:
|
||||
bool ExecuteImpl() override;
|
||||
|
|
|
@ -28,7 +28,7 @@ public:
|
|||
WriteDMA(ATADevice& device);
|
||||
virtual ~WriteDMA() override;
|
||||
|
||||
static IATACommand *Factory(ATADevice& device) { return new WriteDMA(device); }
|
||||
static IATACommand *Factory(SharedMemory& sharedMemory, ATADevice& device) { return sharedMemory.Allocate<WriteDMA, ATADevice&>(device); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -28,12 +28,11 @@ NonDataProtocolCommand::~NonDataProtocolCommand() {
|
|||
void NonDataProtocolCommand::Execute() {
|
||||
bool successful = ExecuteImpl();
|
||||
|
||||
auto& regs = m_device.GetRegisters();
|
||||
if (!successful) {
|
||||
regs.status |= StError;
|
||||
m_regs.status |= StError;
|
||||
}
|
||||
|
||||
regs.status &= ~StBusy;
|
||||
m_regs.status &= ~StBusy;
|
||||
m_interrupt.Assert();
|
||||
|
||||
Finish();
|
||||
|
|
Loading…
Reference in a new issue