mirror of
https://github.com/akuker/RASCSI.git
synced 2024-12-30 05:29:47 +00:00
41bdcd4aed
* Update logging * Remove duplicate code * Update unit tests * Clean up includes * Merge ProtobufSerializer into protobuf_util namespace * Precompile regex * Add const * Add Split() convenience method, update log level/ID parsing * Move log.h to legacy folder * Elimininate gotos * Fixes for gcc 13 * Update compiler flags * Update default folder handling * Use references instead of pointers * Move code for better encapsulation * Move code * Remove unused method argument * Move device logger * Remove redundant to_string * Rename for consistency * Update handling of protobuf pointers * Simplify protobuf usage * Memory handling update * Add hasher
127 lines
2.8 KiB
C++
127 lines
2.8 KiB
C++
//---------------------------------------------------------------------------
|
|
//
|
|
// SCSI Target Emulator PiSCSI
|
|
// for Raspberry Pi
|
|
//
|
|
// Copyright (C) 2022-2023 Uwe Seimet
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include "shared/piscsi_exceptions.h"
|
|
#include "devices/primary_device.h"
|
|
#include "abstract_controller.h"
|
|
#include <ranges>
|
|
|
|
using namespace scsi_defs;
|
|
|
|
AbstractController::AbstractController(BUS& bus, int target_id, int max_luns) : bus(bus), target_id(target_id), max_luns(max_luns)
|
|
{
|
|
device_logger.SetIdAndLun(target_id, -1);
|
|
}
|
|
|
|
void AbstractController::AllocateCmd(size_t size)
|
|
{
|
|
if (size > ctrl.cmd.size()) {
|
|
ctrl.cmd.resize(size);
|
|
}
|
|
}
|
|
|
|
void AbstractController::AllocateBuffer(size_t size)
|
|
{
|
|
if (size > ctrl.buffer.size()) {
|
|
ctrl.buffer.resize(size);
|
|
}
|
|
}
|
|
|
|
void AbstractController::SetByteTransfer(bool b)
|
|
{
|
|
is_byte_transfer = b;
|
|
|
|
if (!is_byte_transfer) {
|
|
bytes_to_transfer = 0;
|
|
}
|
|
}
|
|
|
|
unordered_set<shared_ptr<PrimaryDevice>> AbstractController::GetDevices() const
|
|
{
|
|
unordered_set<shared_ptr<PrimaryDevice>> devices;
|
|
|
|
// "luns | views:values" is not supported by the bullseye compiler
|
|
ranges::transform(luns, inserter(devices, devices.begin()), [] (const auto& l) { return l.second; } );
|
|
|
|
return devices;
|
|
}
|
|
|
|
shared_ptr<PrimaryDevice> AbstractController::GetDeviceForLun(int lun) const {
|
|
const auto& it = luns.find(lun);
|
|
return it == luns.end() ? nullptr : it->second;
|
|
}
|
|
|
|
void AbstractController::Reset()
|
|
{
|
|
SetPhase(phase_t::busfree);
|
|
|
|
ctrl = {};
|
|
|
|
SetByteTransfer(false);
|
|
|
|
// Reset all LUNs
|
|
for (const auto& [_, device] : luns) {
|
|
device->Reset();
|
|
}
|
|
|
|
GetBus().Reset();
|
|
}
|
|
|
|
void AbstractController::ProcessOnController(int id_data)
|
|
{
|
|
device_logger.SetIdAndLun(GetTargetId(), -1);
|
|
|
|
const int initiator_id = ExtractInitiatorId(id_data);
|
|
if (initiator_id != UNKNOWN_INITIATOR_ID) {
|
|
LogTrace("++++ Starting processing for initiator ID " + to_string(initiator_id));
|
|
}
|
|
else {
|
|
LogTrace("++++ Starting processing for unknown initiator ID");
|
|
}
|
|
|
|
while (Process(initiator_id)) {
|
|
// Handle bus phases until the bus is free for the next command
|
|
}
|
|
}
|
|
|
|
bool AbstractController::AddDevice(shared_ptr<PrimaryDevice> device)
|
|
{
|
|
const int lun = device->GetLun();
|
|
|
|
if (lun < 0 || lun >= GetMaxLuns() || HasDeviceForLun(lun) || device->GetController()) {
|
|
return false;
|
|
}
|
|
|
|
luns[lun] = device;
|
|
device->SetController(this);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AbstractController::RemoveDevice(PrimaryDevice& device)
|
|
{
|
|
device.CleanUp();
|
|
|
|
return luns.erase(device.GetLun()) == 1;
|
|
}
|
|
|
|
bool AbstractController::HasDeviceForLun(int lun) const
|
|
{
|
|
return luns.contains(lun);
|
|
}
|
|
|
|
int AbstractController::ExtractInitiatorId(int id_data) const
|
|
{
|
|
if (const int id_data_without_target = id_data - (1 << target_id); id_data_without_target) {
|
|
return static_cast<int>(log2(id_data_without_target & -id_data_without_target));
|
|
}
|
|
|
|
return UNKNOWN_INITIATOR_ID;
|
|
}
|