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"},