From ee9573327c627b5b10bbb750b66482d7837e68f0 Mon Sep 17 00:00:00 2001 From: dingusdev <52434309+dingusdev@users.noreply.github.com> Date: Sat, 8 Oct 2022 16:51:54 -0700 Subject: [PATCH] Reorganized hard disk code Not compiling yet. --- devices/common/ide/heath_ide.cpp | 77 +++++++++++++ devices/common/ide/heath_ide.h | 84 ++++++++++++++ devices/common/scsi/scsi.h | 63 ++++++----- devices/common/scsi/scsi_hd.cpp | 109 +++++++++++++++++++ devices/{harddrive => common/scsi}/scsi_hd.h | 16 +-- devices/harddrive/ata_hd.cpp | 19 ---- devices/harddrive/ata_hd.h | 17 --- devices/harddrive/scsi_hd.cpp | 72 ------------ devices/ioctrl/amic.h | 4 + devices/ioctrl/heathrow.cpp | 10 ++ devices/ioctrl/macio.h | 3 + machines/machinefactory.cpp | 2 + 12 files changed, 331 insertions(+), 145 deletions(-) create mode 100644 devices/common/ide/heath_ide.cpp create mode 100644 devices/common/ide/heath_ide.h create mode 100644 devices/common/scsi/scsi_hd.cpp rename devices/{harddrive => common/scsi}/scsi_hd.h (87%) delete mode 100644 devices/harddrive/ata_hd.cpp delete mode 100644 devices/harddrive/ata_hd.h delete mode 100644 devices/harddrive/scsi_hd.cpp diff --git a/devices/common/ide/heath_ide.cpp b/devices/common/ide/heath_ide.cpp new file mode 100644 index 0000000..74286fc --- /dev/null +++ b/devices/common/ide/heath_ide.cpp @@ -0,0 +1,77 @@ +/* +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 "heath_ide.h" +#include +#include +#include +#include + +#define sector_size 512 + +using namespace std; + +HeathIDE::HeathIDE(std::string filename) { + this->hdd_img; + + // Taken from: + // https://stackoverflow.com/questions/22984956/tellg-function-give-wrong-size-of-file/22986486 + this->hdd_img.ignore(std::numeric_limits::max()); + this->img_size = this->hdd_img.gcount(); + this->hdd_img.clear(); // Since ignore will have set eof. + this->hdd_img.seekg(0, std::ios_base::beg); +} + + +uint32_t HeathIDE::read(int reg) { + uint32_t res = 0; + switch (reg) { + case HEATH_DATA: + res = heath_regs[HEATH_DATA]; + case HEATH_ERROR: + res = heath_regs[HEATH_ERROR]; + case HEATH_SEC_COUNT: + res = heath_regs[HEATH_SEC_COUNT]; + case HEATH_SEC_NUM: + res = heath_regs[HEATH_SEC_NUM]; + default: + LOG_F(WARNING, "Attempted to read unknown IDE register: %x", reg); + } + + return res; +} + + +void HeathIDE::write(int reg, uint32_t value) { + switch (reg) { + case HEATH_DATA: + res = heath_regs[HEATH_DATA]; + case HEATH_CMD: + perform_command(value); + default: + LOG_F(WARNING, "Attempted to write unknown IDE register: %x", reg); + } + +void HeathIDE::perform_command(uint32_t command) { + LOG_F(WARNING, "Attempted to execute IDE command: %x", command); +} \ No newline at end of file diff --git a/devices/common/ide/heath_ide.h b/devices/common/ide/heath_ide.h new file mode 100644 index 0000000..e0d65cd --- /dev/null +++ b/devices/common/ide/heath_ide.h @@ -0,0 +1,84 @@ +/* +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 ATA hard drive support */ + +#ifndef ATA_HD_H +#define ATA_HD_H + +#include +#include +#include + +#define SEC_SIZE 512 + +/** Heath IDE register offsets. */ +enum IDE_Reg : int { + IDE_DATA = 0x0, + ERROR = 0x1, // error (read) + FEATURES = 0x1, // features (write) + SEC_COUNT = 0x2, // sector count + SEC_NUM = 0x3, // sector number + CYL_LOW = 0x4, // cylinder low + CYL_HIGH = 0x5, // cylinder high + DRIVE_HEAD = 0x6, // drive/head + STATUS = 0x7, // status (read) + CMD = 0x7, // command (write) + ALT_STATUS = 0x16, // alt status (read) + DEV_CTRL = 0x16, // device control (write) + TIME_CONFIG = 0x20, +}; + +enum IDE_Status { + ERR = 0x1, + IDX = 0x2, + CORR = 0x4, + DRQ = 0x8, + DSC = 0x10, + DWF = 0x20, + DRDY = 0x40, + BSY = 0x80 +}; + +/** Heath IDE commands. */ +enum IDE_Cmd { + RESET_ATAPI = 0x08, + RECALIBRATE = 0x10, + READ_SECTOR = 0x20, + WRITE_SECTOR = 0x30, + FORMAT_TRACKS = 0x50, + DIAGNOSTICS = 0x90, +}; + +class HeathIDE : public HWComponent { +public: + HeathIDE(std::string filename); + uint32_t read(int reg); + void write(int reg, uint32_t value); + + void perform_command(uint32_t command); + +private: + uint32_t regs[33]; + uint8_t buffer[SEC_SIZE]; +}; + +#endif \ No newline at end of file diff --git a/devices/common/scsi/scsi.h b/devices/common/scsi/scsi.h index 9c864d0..9198483 100644 --- a/devices/common/scsi/scsi.h +++ b/devices/common/scsi/scsi.h @@ -59,38 +59,42 @@ enum ScsiMsg : int { }; enum ScsiCommamd : int { - SCSI_TEST_UNITY_READY = 0x0, - SCSI_REWIND = 0x1, - SCSI_REQ_SENSE = 0x3, - SCSI_FORMAT = 0x4, - SCSI_READ_BLK_LIMITS = 0x5, - SCSI_READ_6 = 0x8, - SCSI_WRITE_6 = 0xA, - SCSI_SEEK_6 = 0xB, - SCSI_VERIFY_6 = 0x13, - SCSI_MODE_SELECT_6 = 0x15, - SCSI_ERASE_6 = 0x19, - SCSI_MODE_SENSE_6 = 0x1A, - SCSI_DIAG_RESULTS = 0x1C, - SCSI_READ_CAPAC_10 = 0x25, - SCSI_READ_10 = 0x28, - SCSI_WRITE_10 = 0x2A, - SCSI_VERIFY_10 = 0x2F, - SCSI_READ_LONG_10 = 0x35, + TEST_UNITY_READY = 0x0, + REWIND = 0x1, + REQ_SENSE = 0x3, + FORMAT = 0x4, + READ_BLK_LIMITS = 0x5, + READ_6 = 0x8, + WRITE_6 = 0xA, + SEEK_6 = 0xB, + INQUIRY = 0x12, + VERIFY_6 = 0x13, + MODE_SELECT_6 = 0x15, + RELEASE_UNIT = 0x17, + ERASE_6 = 0x19, + MODE_SENSE_6 = 0x1A, + DIAG_RESULTS = 0x1C, + SEND_DIAGS = 0x1D, + READ_CAPAC_10 = 0x25, + READ_10 = 0x28, + WRITE_10 = 0x2A, + VERIFY_10 = 0x2F, + READ_LONG_10 = 0x35, }; enum ScsiSense : int { - SCSI_NO_SENSE = 0x0, - SCSI_RECOVERED = 0x1, - SCSI_NOT_READY = 0x2, - SCSI_MEDIA_ERR = 0x3, - SCSI_HW_ERROR = 0x4, - SCSI_ILLEGAL_REQ = 0x5, - SCSI_UNIT_ATTENTION = 0x6, - SCSI_DATA_PROTECT = 0x7, - SCSI_BLANK_CHECK = 0x8, - SCSI_MISCOMPARE = 0xE, - SCSI_COMPLETED = 0xF, + NO_SENSE = 0x0, + RECOVERED = 0x1, + NOT_READY = 0x2, + MEDIUM_ERR = 0x3, + HW_ERROR = 0x4, + ILLEGAL_REQ = 0x5, + UNIT_ATTENTION = 0x6, + DATA_PROTECT = 0x7, + BLANK_CHECK = 0x8, + VOL_OVERFLOW = 0xD, + MISCOMPARE = 0xE, + COMPLETED = 0xF, }; @@ -110,6 +114,7 @@ public: ~ScsiDevice() = default; virtual void notify(ScsiMsg msg_type, int param) = 0; + virtual void select() = 0; private: int scsi_id; diff --git a/devices/common/scsi/scsi_hd.cpp b/devices/common/scsi/scsi_hd.cpp new file mode 100644 index 0000000..ac7b8db --- /dev/null +++ b/devices/common/scsi/scsi_hd.cpp @@ -0,0 +1,109 @@ +/* +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 Sander-Wozniak Machine 3 (SWIM3) emulation. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define sector_size 512 + +using namespace std; + +SCSI_HD::SCSI_HD() { + supports_types(HWCompType::SCSI_DEV); + + std::string hd_image_path = GET_STR_PROP("hdd_img"); + + //We don't want to store everything in memory, but + //we want to keep the hard disk available. + this->hdd_img.open(hd_image_path, ios::out | ios::in | ios::binary); + + // Taken from: + // https://stackoverflow.com/questions/22984956/tellg-function-give-wrong-size-of-file/22986486 + this->hdd_img.ignore(std::numeric_limits::max()); + this->img_size = this->hdd_img.gcount(); + this->hdd_img.clear(); // Since ignore will have set eof. + this->hdd_img.seekg(0, std::ios_base::beg); +} + +int SCSI_HD::test_unit_ready() { + return 0x0; +} + +int SCSI_HD::req_sense(uint8_t alloc_len) { + if (alloc_len != 252) { + LOG_F(WARNING, "Inappropriate Allocation Length: %%d", alloc_len); + } + return 0x0; //placeholder - no sense +} + +int SCSI_HD::inquiry() { + return 0x1000000F; +} + +int SCSI_HD::send_diagnostic() { + return 0x0; +} + +int SCSI_HD::read_capacity_10() { + return this->img_size; +} + +void SCSI_HD::format() {} + +void SCSI_HD::read(uint32_t lba, uint16_t transfer_len) { + uint32_t transfer_size = (transfer_len == 0) ? 256 : transfer_len; + transfer_size *= sector_size; + uint32_t device_offset = lba * sector_size; + + this->hdd_img.seekg(device_offset, this->hdd_img.beg); + this->hdd_img.read(img_buffer, transfer_size); +} + +void SCSI_HD::write(uint32_t lba, uint16_t transfer_len) { + uint32_t transfer_size = (transfer_len == 0) ? 256 : transfer_len; + transfer_size *= sector_size; + uint32_t device_offset = lba * sector_size; + + this->hdd_img.seekg(device_offset, this->hdd_img.beg); + this->hdd_img.write((char*)&img_buffer, transfer_size); + +} + +void SCSI_HD::seek(uint32_t lba) { + this->hdd_img.seekg(0, this->hdd_img.beg); +} + +void SCSI_HD::rewind() { + this->hdd_img.seekg(0, this->hdd_img.beg); +} + +static const PropMap SCSI_HD_Properties = { + {"hdd_img", new StrProperty("")}, + {"hdd_wr_prot", new BinProperty(0)}, +}; \ No newline at end of file diff --git a/devices/harddrive/scsi_hd.h b/devices/common/scsi/scsi_hd.h similarity index 87% rename from devices/harddrive/scsi_hd.h rename to devices/common/scsi/scsi_hd.h index 3cc6163..0f0a5b8 100644 --- a/devices/harddrive/scsi_hd.h +++ b/devices/common/scsi/scsi_hd.h @@ -26,17 +26,16 @@ along with this program. If not, see . #include #include +#include #include #include -class HardDrive : public ScsiDevice { +class SCSI_HD : public ScsiDevice { public: - HardDrive(std::string filename); - ~HardDrive() = default; + SCSI_HD(); + ~SCSI_HD() = default; - virtual void notify(ScsiMsg msg_type, int param){ - return param; - }; + virtual void notify(ScsiMsg msg_type, int param) = 0; int test_unit_ready(); int req_sense(uint8_t alloc_len); @@ -52,11 +51,12 @@ public: protected: std::string img_path; - fstream hdd_img; + std::fstream hdd_img; uint64_t img_size; char img_buffer[1 << 17]; uint8_t scsi_command[12]; uint64_t file_offset = 0; -} + uint8_t status; +}; #endif \ No newline at end of file diff --git a/devices/harddrive/ata_hd.cpp b/devices/harddrive/ata_hd.cpp deleted file mode 100644 index 2cd2732..0000000 --- a/devices/harddrive/ata_hd.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "ata_hd.h" -#include -#include -#include - -#define sector_size 512 - -using namespace std; - -HardDrive::HardDrive(std::string filename) { - this->hdd_img; - - // Taken from: - // https://stackoverflow.com/questions/22984956/tellg-function-give-wrong-size-of-file/22986486 - this->hdd_img.ignore(std::numeric_limits::max()); - this->img_size = this->hdd_img.gcount(); - this->hdd_img.clear(); // Since ignore will have set eof. - this->hdd_img.seekg(0, std::ios_base::beg); -} diff --git a/devices/harddrive/ata_hd.h b/devices/harddrive/ata_hd.h deleted file mode 100644 index 3aa41a6..0000000 --- a/devices/harddrive/ata_hd.h +++ /dev/null @@ -1,17 +0,0 @@ - -/** @file ATA hard drive support */ - -#ifndef SCSI_HD_H -#define SCSI_HD_H - -#include -#include -#include - - -class ATAHardDrive { -public: - ATAHardDrive(std::string filename); -} - -#endif \ No newline at end of file diff --git a/devices/harddrive/scsi_hd.cpp b/devices/harddrive/scsi_hd.cpp deleted file mode 100644 index e7da541..0000000 --- a/devices/harddrive/scsi_hd.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "scsi_hd.h" -#include -#include -#include - -#define sector_size 512 - -using namespace std; - -HardDrive::HardDrive(std::string filename) { - supports_types(HWCompType::SCSI_DEV); - - this->hdd_img.open(filename, ios::out | ios::in | ios::binary); - - // Taken from: - // https://stackoverflow.com/questions/22984956/tellg-function-give-wrong-size-of-file/22986486 - this->hdd_img.ignore(std::numeric_limits::max()); - this->img_size = this->hdd_img.gcount(); - this->hdd_img.clear(); // Since ignore will have set eof. - this->hdd_img.seekg(0, std::ios_base::beg); -} - -int HardDrive::test_unit_ready(){ - return 0x0; -} - -int HardDrive::req_sense(uint8_t alloc_len) { - if (alloc_len != 252) { - LOG_F(WARNING, "Inappropriate Allocation Length: %%d", alloc_len); - } - return 0x0; //placeholder - no sense -} - -int HardDrive::inquiry() { - return 0x1000000F; -} - -int HardDrive::send_diagnostic() { - return 0x0; -} - -int HardDrive::read_capacity_10() { - return this->img_size; -} - -void HardDrive::format() { -} - -void HardDrive::read(uint32_t lba, uint16_t transfer_len) { - uint32_t final_transfer = (transfer_len == 0) ? 256 : transfer_len; - final_transfer = transfer_len * sector_size; - - this->hdd_img.seekg(lba * sector_size); - img_buffer = this->hdd_img.read(memblock, size); -} - -void HardDrive::write(uint32_t lba, uint16_t transfer_len) { - uint32_t final_transfer = (transfer_len == 0) ? 256 : transfer_len; - final_transfer = transfer_len * sector_size; - - this->hdd_img.seekg(device_offset, this->hdd_img.beg); - this->hdd_img.write((char*)&read_buffer, sector_size); - -} - -void HardDrive::seek(uint32_t lba) { -} - - -void HardDrive::rewind() { - this->hdd_img.seekg(0, disk_image.beg); -} diff --git a/devices/ioctrl/amic.h b/devices/ioctrl/amic.h index ff46dd4..fb91587 100644 --- a/devices/ioctrl/amic.h +++ b/devices/ioctrl/amic.h @@ -150,6 +150,10 @@ enum AMICReg : uint32_t { // Interrupt registers Int_Ctrl = 0x2A000, + DMA_Int_0 = 0x2A008, + Bus_Err_Int_0 = 0x2A009, + DMA_Int_1 = 0x2A00A, + Bus_Err_Int_1 = 0x2A00B, // Undocumented diagnostics register Diag_Reg = 0x2C000, diff --git a/devices/ioctrl/heathrow.cpp b/devices/ioctrl/heathrow.cpp index 078388c..5b88d0c 100644 --- a/devices/ioctrl/heathrow.cpp +++ b/devices/ioctrl/heathrow.cpp @@ -24,6 +24,7 @@ along with this program. If not, see . #include #include #include +#include #include #include #include @@ -78,6 +79,9 @@ HeathrowIC::HeathrowIC() : PCIDevice("mac-io/heathrow"), InterruptCtrl() // connect SCSI HW this->mesh = dynamic_cast(gMachineObj->get_comp_by_name("Mesh")); + // connect IDE HW + this->ide_0 = dynamic_cast(gMachineObj->get_comp_by_name("IDE0")); + // connect serial HW this->escc = dynamic_cast(gMachineObj->get_comp_by_name("Escc")); @@ -161,6 +165,9 @@ 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: + res = this->ide_0->read((offset - 0x20000) >> 4); + break; default: if (sub_addr >= 0x60) { res = this->nvram->read_byte((offset - 0x60000) >> 4); @@ -206,6 +213,9 @@ 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: + this->ide_0->write((offset - 0x20000) >> 9, value); + break; default: if (sub_addr >= 0x60) { this->nvram->write_byte((offset - 0x60000) >> 4, value); diff --git a/devices/ioctrl/macio.h b/devices/ioctrl/macio.h index 6c81152..3dd3962 100644 --- a/devices/ioctrl/macio.h +++ b/devices/ioctrl/macio.h @@ -54,6 +54,7 @@ along with this program. If not, see . #include #include #include +#include #include #include #include @@ -137,6 +138,7 @@ private: MaceController* mace; ViaCuda* viacuda; // VIA cell with Cuda MCU attached to it EsccController* escc; // ESCC serial controller + HeathIDE* ide_0; // Internal ATA Sc53C94* scsi_0; // external SCSI Swim3::Swim3Ctrl* swim3; // floppy disk controller @@ -229,6 +231,7 @@ private: ViaCuda* viacuda; // VIA cell with Cuda MCU attached to it MESHController* mesh; // MESH SCSI cell instance EsccController* escc; // ESCC serial controller + HeathIDE* ide_0; // Internal ATA Swim3::Swim3Ctrl* swim3; // floppy disk controller std::unique_ptr snd_out_dma; diff --git a/machines/machinefactory.cpp b/machines/machinefactory.cpp index ac2553b..0b5d15b 100644 --- a/machines/machinefactory.cpp +++ b/machines/machinefactory.cpp @@ -78,6 +78,8 @@ static const map PropHelp = { {"gfxmem_size", "specifies video memory size in MB"}, {"fdd_img", "specifies path to floppy disk image"}, {"fdd_wr_prot", "toggles floppy disk's write protection"}, + {"hdd_img", "specifies path to hard disk image"}, + {"hdd_wr_prot", "toggles hard disk's write protection"}, {"mon_id", "specifies which monitor to emulate"}, {"pci_A1", "insert a PCI device into A1 slot"}, {"pci_B1", "insert a PCI device into B1 slot"},