Improve ScsiDevice class.

This commit is contained in:
Maxim Poliakovski 2022-10-25 02:10:54 +02:00
parent 3af9729e5b
commit eeb576a927
8 changed files with 89 additions and 12 deletions

View File

@ -31,7 +31,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <cinttypes>
Sc53C94::Sc53C94(uint8_t chip_id, uint8_t my_id)
Sc53C94::Sc53C94(uint8_t chip_id, uint8_t my_id) : ScsiDevice(my_id)
{
this->chip_id = chip_id;
this->my_bus_id = my_id;
@ -342,7 +342,7 @@ void Sc53C94::update_irq()
}
}
void Sc53C94::notify(ScsiMsg msg_type, int param)
void Sc53C94::notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param)
{
switch (msg_type) {
case ScsiMsg::CONFIRM_SEL:
@ -360,6 +360,16 @@ void Sc53C94::notify(ScsiMsg msg_type, int param)
}
}
bool Sc53C94::send_bytes(uint8_t* dst_ptr, int count)
{
if ((this->data_fifo_pos - this->data_fifo_read_pos) < count) {
return false;
}
std::memcpy(dst_ptr, &this->data_fifo[this->data_fifo_read_pos], count);
return true;
}
static const DeviceDescription Sc53C94_Descriptor = {
Sc53C94::create, {}, {}
};

View File

@ -141,7 +141,8 @@ public:
void write(uint8_t reg_offset, uint8_t value);
// ScsiDevice methods
void notify(ScsiMsg msg_type, int param);
void notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param);
bool send_bytes(uint8_t* dst_ptr, int count);
protected:
void reset_device();

View File

@ -119,15 +119,22 @@ enum ScsiError : int {
#define SCSI_MAX_DEVS 8
class ScsiBus;
class ScsiDevice : public HWComponent {
public:
ScsiDevice() = default;
ScsiDevice(int my_id) {
this->scsi_id = my_id;
};
~ScsiDevice() = default;
virtual void notify(ScsiMsg msg_type, int param) = 0;
virtual void notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param);
virtual bool send_bytes(uint8_t* dst_ptr, int count) = 0;
private:
int scsi_id;
int scsi_id;
uint8_t cmd_buf[16] = {};
};
/** This class provides a higher level abstraction for the SCSI bus. */

View File

@ -58,7 +58,7 @@ void ScsiBus::change_bus_phase(int initiator_id)
if (i == initiator_id)
continue; // don't notify the initiator
if (this->devices[i] != nullptr) {
this->devices[i]->notify(ScsiMsg::BUS_PHASE_CHANGE, this->cur_phase);
this->devices[i]->notify(this, ScsiMsg::BUS_PHASE_CHANGE, this->cur_phase);
}
}
}
@ -161,7 +161,7 @@ void ScsiBus::confirm_selection(int target_id)
// notify initiator about selection confirmation from target
if (this->initiator_id >= 0) {
this->devices[this->initiator_id]->notify(ScsiMsg::CONFIRM_SEL, target_id);
this->devices[this->initiator_id]->notify(this, ScsiMsg::CONFIRM_SEL, target_id);
}
}

View File

@ -22,6 +22,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
/** @file Generic SCSI Hard Disk emulation. */
#include <devices/deviceregistry.h>
#include <devices/common/scsi/scsi.h>
#include <devices/common/scsi/scsi_hd.h>
#include <machines/machinebase.h>
#include <machines/machineproperties.h>
@ -35,7 +36,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
using namespace std;
ScsiHardDisk::ScsiHardDisk() {
ScsiHardDisk::ScsiHardDisk(int my_id) : ScsiDevice(my_id)
{
supports_types(HWCompType::SCSI_DEV);
std::string hd_image_path = GET_STR_PROP("hdd_img");

View File

@ -32,10 +32,10 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
class ScsiHardDisk : public ScsiDevice {
public:
ScsiHardDisk();
ScsiHardDisk(int my_id);
~ScsiHardDisk() = default;
void notify(ScsiMsg msg_type, int param);
bool send_bytes(uint8_t* dst_ptr, int count) { return true; };
int test_unit_ready();
int req_sense(uint8_t alloc_len);

View File

@ -0,0 +1,57 @@
/*
DingusPPC - The Experimental PowerPC Macintosh emulator
Copyright (C) 2018-22 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <core/timermanager.h>
#include <devices/common/scsi/scsi.h>
#include <loguru.hpp>
#include <cinttypes>
void ScsiDevice::notify(ScsiBus* bus_obj, ScsiMsg msg_type, int param)
{
if (msg_type == ScsiMsg::BUS_PHASE_CHANGE) {
switch (param) {
case ScsiPhase::RESET:
LOG_F(INFO, "ScsiDevice %d: bus reset aknowledged", this->scsi_id);
break;
case ScsiPhase::SELECTION:
// check if something tries to select us
if (bus_obj->get_data_lines() & (1 << scsi_id)) {
LOG_F(INFO, "ScsiDevice %d selected", this->scsi_id);
TimerManager::get_instance()->add_oneshot_timer(
BUS_SETTLE_DELAY,
[this, bus_obj]() {
// don't confirm selection if BSY or I/O are asserted
if (bus_obj->test_ctrl_lines(SCSI_CTRL_BSY | SCSI_CTRL_IO))
return;
bus_obj->assert_ctrl_line(this->scsi_id, SCSI_CTRL_BSY);
bus_obj->confirm_selection(this->scsi_id);
if (bus_obj->test_ctrl_lines(SCSI_CTRL_ATN)) {
LOG_F(WARNING, "ScsiDevice: MESSAGE_OUT isn't supported yet");
}
bus_obj->transfer_command(this->cmd_buf);
//this->process_command();
});
}
break;
}
}
}

View File

@ -84,7 +84,7 @@ int initialize_pdm(std::string& id)
auto scsi_bus = dynamic_cast<ScsiBus*>(gMachineObj->get_comp_by_name("SCSI0"));
// attach SCSI HD to the main bus, ID #0
gMachineObj->add_device("SCSI_HD", std::unique_ptr<ScsiHardDisk>(new ScsiHardDisk()));
gMachineObj->add_device("SCSI_HD", std::unique_ptr<ScsiHardDisk>(new ScsiHardDisk(0)));
scsi_bus->register_device(0, dynamic_cast<ScsiDevice*>(gMachineObj->get_comp_by_name("SCSI_HD")));
// Init virtual CPU and request MPC601