mirror of
https://github.com/dingusdev/dingusppc.git
synced 2024-06-10 13:29:42 +00:00
Improve ScsiDevice class.
This commit is contained in:
parent
3af9729e5b
commit
eeb576a927
|
@ -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, {}, {}
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
57
devices/common/scsi/scsidevice.cpp
Normal file
57
devices/common/scsi/scsidevice.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user