From 58908621e6fbe87b1e2f7d29bf24590080b77e83 Mon Sep 17 00:00:00 2001 From: dingusdev <52434309+dingusdev@users.noreply.github.com> Date: Mon, 5 Dec 2022 08:42:51 -0700 Subject: [PATCH] IDE refinements --- devices/CMakeLists.txt | 2 +- devices/common/ata/ata_bus.cpp | 37 +++++++++++ .../common/{ide/ide_hd.h => ata/ata_bus.h} | 40 ++++++------ .../{ide/ide_hd.cpp => ata/ata_full.cpp} | 44 +++++++------ devices/common/ata/ata_full.h | 55 ++++++++++++++++ devices/common/ata/ata_null.cpp | 64 +++++++++++++++++++ devices/common/ata/ata_null.h | 50 +++++++++++++++ devices/ioctrl/heathrow.cpp | 24 +++++-- devices/ioctrl/macio.h | 9 ++- machines/machinegossamer.cpp | 2 +- 10 files changed, 276 insertions(+), 51 deletions(-) create mode 100644 devices/common/ata/ata_bus.cpp rename devices/common/{ide/ide_hd.h => ata/ata_bus.h} (80%) rename devices/common/{ide/ide_hd.cpp => ata/ata_full.cpp} (78%) create mode 100644 devices/common/ata/ata_full.h create mode 100644 devices/common/ata/ata_null.cpp create mode 100644 devices/common/ata/ata_null.h diff --git a/devices/CMakeLists.txt b/devices/CMakeLists.txt index a4b05f8..4261c99 100644 --- a/devices/CMakeLists.txt +++ b/devices/CMakeLists.txt @@ -6,7 +6,7 @@ file(GLOB SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/common/adb/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/common/i2c/*.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/common/ide/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/common/ata/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/common/pci/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/common/scsi/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/ethernet/*.cpp" diff --git a/devices/common/ata/ata_bus.cpp b/devices/common/ata/ata_bus.cpp new file mode 100644 index 0000000..22a0afa --- /dev/null +++ b/devices/common/ata/ata_bus.cpp @@ -0,0 +1,37 @@ +/* +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 . +*/ + +/** @file Heathrow hard drive controller */ + +#include +#include +#include +#include +#include +#include + +#define sector_size 512 + +using namespace std; + +AtaBus::AtaBus() { + supports_types(HWCompType::IDE_BUS); +} \ No newline at end of file diff --git a/devices/common/ide/ide_hd.h b/devices/common/ata/ata_bus.h similarity index 80% rename from devices/common/ide/ide_hd.h rename to devices/common/ata/ata_bus.h index 2120909..e988e85 100644 --- a/devices/common/ide/ide_hd.h +++ b/devices/common/ata/ata_bus.h @@ -21,8 +21,8 @@ along with this program. If not, see . /** @file ATA hard drive support */ -#ifndef IDE_HD_H -#define IDE_HD_H +#ifndef IDEDEVICE_H +#define IDEDEVICE_H #include #include @@ -52,6 +52,7 @@ enum IDE_Reg : int { TIME_CONFIG = 0x20 }; +/** Status Register Bits */ enum IDE_Status : int { ERR = 0x1, IDX = 0x2, @@ -63,6 +64,18 @@ enum IDE_Status : int { BSY = 0x80 }; +/** Error Register Bits */ +enum IDE_Error : int { + ANMF = 0x1, + TK0NF = 0x2, + ABRT = 0x4, + MCR = 0x8, + IDNF = 0x10, + MC = 0x20, + UNC = 0x40, + BBK = 0x80 +}; + /** Heath IDE commands. */ enum IDE_Cmd : int { IDE_NOP = 0x00, @@ -79,26 +92,13 @@ enum IDE_Cmd : int { WRITE_DMA = 0xCA, }; -class IdeHardDisk : public HWComponent { +class AtaBus : public HWComponent { public: - IdeHardDisk(); - ~IdeHardDisk() = default; - - static std::unique_ptr create() { - return std::unique_ptr(new IdeHardDisk()); - } + AtaBus(); + ~AtaBus() = default; - void insert_image(std::string filename); - uint32_t read(int reg); - void write(int reg, uint32_t value); - - void perform_command(uint32_t command); - -private: - std::fstream hdd_img; - uint64_t img_size; - uint32_t regs[33]; - uint8_t buffer[SEC_SIZE]; + void connect_msg(); + void pass_msg(); }; #endif \ No newline at end of file diff --git a/devices/common/ide/ide_hd.cpp b/devices/common/ata/ata_full.cpp similarity index 78% rename from devices/common/ide/ide_hd.cpp rename to devices/common/ata/ata_full.cpp index 085d990..7b43b9d 100644 --- a/devices/common/ide/ide_hd.cpp +++ b/devices/common/ata/ata_full.cpp @@ -21,35 +21,40 @@ along with this program. If not, see . /** @file Heathrow hard drive controller */ +#include #include -#include #include #include -#include #include +#include #define sector_size 512 using namespace std; -IdeHardDisk::IdeHardDisk() { - this->name = "IdeHardDisk"; +AtaFullDevice::AtaFullDevice() { supports_types(HWCompType::IDE_DEV); + + regs[IDE_Reg::ERROR] = IDE_Error::ANMF; + regs[IDE_Reg::SEC_COUNT] = 0x1; + regs[IDE_Reg::SEC_NUM] = 0x1; + regs[IDE_Reg::STATUS] = IDE_Status::DRDY | IDE_Status::DSC; + regs[IDE_Reg::ALT_STATUS] = IDE_Status::DRDY | IDE_Status::DSC; } -void IdeHardDisk::insert_image(std::string filename) { - this->hdd_img.open(filename, ios::out | ios::in | ios::binary); +void AtaFullDevice::insert_image(std::string filename) { + this->ide_img.open(filename, ios::out | ios::in | ios::binary); // Taken from: // https://stackoverflow.com/questions/22984956/tellg-function-give-wrong-size-of-file/22986486 - hdd_img.ignore(std::numeric_limits::max()); - img_size = this->hdd_img.gcount(); - hdd_img.clear(); // Since ignore will have set eof. - hdd_img.seekg(0, std::ios_base::beg); + ide_img.ignore(std::numeric_limits::max()); + img_size = this->ide_img.gcount(); + ide_img.clear(); // Since ignore will have set eof. + ide_img.seekg(0, std::ios_base::beg); } -uint32_t IdeHardDisk::read(int reg) { - switch (reg) { +uint32_t AtaFullDevice::read(int reg) { + switch (reg) { case IDE_Reg::IDE_DATA: LOG_F(0, "Retrieving DATA from IDE: %x", regs[IDE_Reg::IDE_DATA]); return regs[IDE_Reg::IDE_DATA]; @@ -75,15 +80,13 @@ uint32_t IdeHardDisk::read(int reg) { LOG_F(WARNING, "Attempted to read unknown IDE register: %x", reg); return 0x0; } - } -void IdeHardDisk::write(int reg, uint32_t value) { +void AtaFullDevice::write(int reg, uint32_t value) { switch (reg) { case IDE_Reg::IDE_DATA: regs[IDE_Reg::IDE_DATA] = value; break; - break; case IDE_Reg::FEATURES: regs[IDE_Reg::FEATURES] = value; break; @@ -118,7 +121,7 @@ void IdeHardDisk::write(int reg, uint32_t value) { } } -void IdeHardDisk::perform_command(uint32_t command) { +int AtaFullDevice::perform_command(uint32_t command) { switch (command) { case IDE_Cmd::READ_SECTOR: LOG_F(WARNING, "Trying to read sector with: %x", command); @@ -129,10 +132,13 @@ void IdeHardDisk::perform_command(uint32_t command) { default: LOG_F(WARNING, "Attempted to execute IDE command: %x", command); } + + return 0; } -static const DeviceDescription IDE_Descriptor = { - IdeHardDisk::create, {}, {} + +static const DeviceDescription ATA_Full_Descriptor = { + AtaFullDevice::create, {}, {} }; -REGISTER_DEVICE(IdeHardDisk, IDE_Descriptor); \ No newline at end of file +REGISTER_DEVICE(AtaFullDevice, ATA_Full_Descriptor); \ No newline at end of file diff --git a/devices/common/ata/ata_full.h b/devices/common/ata/ata_full.h new file mode 100644 index 0000000..58c2adb --- /dev/null +++ b/devices/common/ata/ata_full.h @@ -0,0 +1,55 @@ +/* +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 . +*/ + +/** @file Full ATA device */ + +#include + +#define SEC_SIZE 512 + +#ifndef ATA_FULL_H +#define ATA_FULL_H + +class AtaFullDevice : public AtaBus { + public: + AtaFullDevice(); + ~AtaFullDevice() = default; + + static std::unique_ptr create() { + return std::unique_ptr(new AtaFullDevice()); + } + + void insert_image(std::string filename); + uint32_t read(int reg); + void write(int reg, uint32_t value); + + int perform_command(uint32_t command); + void get_status(); + + private: + uint32_t regs[33] = {0x0}; + uint8_t buffer[SEC_SIZE]; + std::fstream ide_img; + uint64_t img_size; +}; + + +#endif \ No newline at end of file diff --git a/devices/common/ata/ata_null.cpp b/devices/common/ata/ata_null.cpp new file mode 100644 index 0000000..6862a0f --- /dev/null +++ b/devices/common/ata/ata_null.cpp @@ -0,0 +1,64 @@ +/* +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 . +*/ + +/** @file Null ATA device */ + +#include +#include +#include +#include +#include + +AtaNullDevice::AtaNullDevice() { + supports_types(HWCompType::IDE_DEV); + + regs[IDE_Reg::STATUS] = IDE_Status::DRDY | IDE_Status::DSC; + regs[IDE_Reg::ALT_STATUS] = IDE_Status::DRDY | IDE_Status::DSC; +} + +uint32_t AtaNullDevice::read(int reg) { + if (reg == IDE_Reg::ERROR) { + return IDE_Error::TK0NF; + } + else if (reg == IDE_Reg::STATUS) { + return IDE_Status::ERR; + } + LOG_F(WARNING, "Dummy read for IDE register 0x%x", reg); + return 0x0; +} + +void AtaNullDevice::write(int reg, uint32_t value) { + if (reg == IDE_Reg::COMMAND) { + process_command(value); + } + LOG_F(WARNING, "Dummy write for IDE register 0x%x with value 0x%x", reg, value); +} + +int AtaNullDevice::process_command(uint32_t cmd) { + LOG_F(ERROR, "Attempted to execute command %x", cmd); + return 0; +} + +static const DeviceDescription ATA_Null_Descriptor = { + AtaNullDevice::create, {}, {} +}; + +REGISTER_DEVICE(AtaNullDevice, ATA_Null_Descriptor); \ No newline at end of file diff --git a/devices/common/ata/ata_null.h b/devices/common/ata/ata_null.h new file mode 100644 index 0000000..22982d8 --- /dev/null +++ b/devices/common/ata/ata_null.h @@ -0,0 +1,50 @@ +/* +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 . +*/ + +/** @file Null ATA device */ + +#include + +#define SEC_SIZE 512 + +#ifndef ATA_NULL_H +#define ATA_NULL_H + +class AtaNullDevice : public AtaBus { +public: + AtaNullDevice(); + ~AtaNullDevice() = default; + + static std::unique_ptr create() { + return std::unique_ptr(new AtaNullDevice()); + } + + int process_command(uint32_t cmd); + + uint32_t read(int reg); + void write(int reg, uint32_t value); + +private: + uint32_t regs[33] = {0x0}; + uint8_t buffer[SEC_SIZE]; +}; + +#endif \ No newline at end of file diff --git a/devices/ioctrl/heathrow.cpp b/devices/ioctrl/heathrow.cpp index 67aa241..7edb011 100644 --- a/devices/ioctrl/heathrow.cpp +++ b/devices/ioctrl/heathrow.cpp @@ -24,7 +24,8 @@ along with this program. If not, see . #include #include #include -#include +#include +#include #include #include #include @@ -80,7 +81,8 @@ HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow"), InterruptCtrl() this->mesh = dynamic_cast(gMachineObj->get_comp_by_name("Mesh")); // connect IDE HW - this->ide_1 = dynamic_cast(gMachineObj->get_comp_by_name("IdeHardDisk")); + this->ide_0 = dynamic_cast(gMachineObj->get_comp_by_name("AtaNullDevice")); + this->ide_1 = dynamic_cast(gMachineObj->get_comp_by_name("AtaNullDevice")); //std::string hd_image_path = GET_STR_PROP("hdd_img"); //if (!hd_image_path.empty()) { @@ -170,9 +172,13 @@ uint32_t HeathrowIC::read(uint32_t rgn_start, uint32_t offset, int size) { case 0x17: res = this->viacuda->read((offset - 0x16000) >> 9); break; + case 0x20: // IDE 0 + LOG_F(0, "Read IDE 0 - offset=0x%X", offset); + res = this->ide_0->read((offset >> 4) & 0x1F); + break; case 0x21: //IDE 1 - LOG_F(0, "Read IDE offset=0x%X", offset); - res = this->ide_1->read((offset - 0x21000) >> 4); + LOG_F(0, "Read IDE 1 - offset=0x%X", offset); + res = this->ide_1->read((offset >> 4) & 0x1F); break; default: if (sub_addr >= 0x60) { @@ -219,9 +225,13 @@ void HeathrowIC::write(uint32_t rgn_start, uint32_t offset, uint32_t value, int case 0x17: this->viacuda->write((offset - 0x16000) >> 9, value); break; + case 0x20: + LOG_F(0, "Write IDE 0 - offset=0x%X", offset); + this->ide_0->write((offset >> 4) & 0x1F, value); + break; case 0x21: - LOG_F(0, "Write IDE offset=0x%X", offset); - this->ide_1->write(((offset - 0x21000) >> 4), value); + LOG_F(0, "Write IDE 1 - offset=0x%X", offset); + this->ide_1->write((offset >> 4) & 0x1F, value); break; default: if (sub_addr >= 0x60) { @@ -399,7 +409,7 @@ void HeathrowIC::clear_cpu_int() } static const vector Heathrow_Subdevices = { - "NVRAM", "ViaCuda", "Mesh", "Escc", "Swim3", "IdeHardDisk"}; + "NVRAM", "ViaCuda", "Mesh", "Escc", "Swim3", "AtaNullDevice"}; static const DeviceDescription Heathrow_Descriptor = { HeathrowIC::create, Heathrow_Subdevices, {} diff --git a/devices/ioctrl/macio.h b/devices/ioctrl/macio.h index fc91e79..f528bfa 100644 --- a/devices/ioctrl/macio.h +++ b/devices/ioctrl/macio.h @@ -54,7 +54,8 @@ along with this program. If not, see . #include #include #include -#include +#include +#include #include #include #include @@ -138,7 +139,8 @@ private: MaceController* mace; ViaCuda* viacuda; // VIA cell with Cuda MCU attached to it EsccController* escc; // ESCC serial controller - IdeHardDisk* ide_0; // Internal ATA + AtaNullDevice* ide_0; // Internal ATA + AtaNullDevice* ide_1; // Media Bay ATA Sc53C94* scsi_0; // external SCSI Swim3::Swim3Ctrl* swim3; // floppy disk controller @@ -231,7 +233,8 @@ private: ViaCuda* viacuda; // VIA cell with Cuda MCU attached to it MESHController* mesh; // MESH SCSI cell instance EsccController* escc; // ESCC serial controller - IdeHardDisk* ide_1; // Internal ATA + AtaNullDevice* ide_0; // Internal ATA + AtaNullDevice* ide_1; // Media Bay ATA Swim3::Swim3Ctrl* swim3; // floppy disk controller std::unique_ptr snd_out_dma; diff --git a/machines/machinegossamer.cpp b/machines/machinegossamer.cpp index 9ba593d..1e8e0db 100644 --- a/machines/machinegossamer.cpp +++ b/machines/machinegossamer.cpp @@ -164,7 +164,7 @@ static const PropMap gossamer_settings = { }; static vector pmg3_devices = { - "Grackle", "Heathrow", "AtiRageGT", "IdeHardDisk" + "Grackle", "Heathrow", "AtiRageGT" }; static const MachineDescription pmg3dt_descriptor = {