From 1e9ec5d7ae771ec7e4312920b5110c9bf9e32181 Mon Sep 17 00:00:00 2001 From: dingusdev <52434309+dingusdev@users.noreply.github.com> Date: Thu, 8 Dec 2022 15:29:04 -0700 Subject: [PATCH] Start ATA command support --- devices/common/ata/atadefs.h | 44 +++++++++++++++++++++++---------- devices/common/ata/atahd.cpp | 44 +++++++++++++++++++++++++++++++++ devices/common/ata/atahd.h | 8 ++++++ devices/common/ata/idechannel.h | 1 + 4 files changed, 84 insertions(+), 13 deletions(-) diff --git a/devices/common/ata/atadefs.h b/devices/common/ata/atadefs.h index 2529fd8..97f599d 100644 --- a/devices/common/ata/atadefs.h +++ b/devices/common/ata/atadefs.h @@ -69,20 +69,38 @@ enum IDE_Error : int { BBK = 0x80 }; -/** ATA commands. */ +/* ATA Signals */ +enum IDE_Signal : int { + PDIAG = 0x22, + DASP = 0x27 +}; + +/* ATA commands. */ enum IDE_Cmd : int { - NOP = 0x00, - RESET_ATAPI = 0x08, - RECALIBRATE = 0x10, - READ_SECTOR = 0x20, - READ_LONG = 0x22, - WRITE_SECTOR = 0x30, - WRITE_LONG = 0x32, - WRITE_VERIFY = 0x40, - FORMAT_TRACKS = 0x50, - DIAGNOSTICS = 0x90, - READ_DMA = 0xC8, - WRITE_DMA = 0xCA, + NOP = 0x00, + RESET_ATAPI = 0x08, + RECALIBRATE = 0x10, + READ_SECTOR = 0x20, + READ_SECTOR_NR = 0x21, + READ_LONG = 0x22, + READ_SECTOR_EXT = 0x24, + WRITE_SECTOR = 0x30, + WRITE_SECTOR_NR = 0x21, + WRITE_LONG = 0x32, + READ_VERIFY = 0x40, + FORMAT_TRACKS = 0x50, + IDE_SEEK = 0x70, + DIAGNOSTICS = 0x90, + INIT_DEV_PARAM = 0x91, + PACKET = 0xA0, + IDFY_PKT_DEV = 0xA1, + READ_MULTIPLE = 0xC4, + WRITE_MULTIPLE = 0xC5, + READ_DMA = 0xC8, + WRITE_DMA = 0xCA, + WRITE_BUFFER_DMA = 0xE9, + READ_BUFFER_DMA = 0xEB, + IDENTIFY_DEVICE = 0xEC, }; }; // namespace ata_interface diff --git a/devices/common/ata/atahd.cpp b/devices/common/ata/atahd.cpp index 7056f9e..855915d 100644 --- a/devices/common/ata/atahd.cpp +++ b/devices/common/ata/atahd.cpp @@ -22,14 +22,58 @@ along with this program. If not, see . /** @file ATA hard disk emulation. */ #include +#include +#include +#include #include +using namespace ata_interface; + AtaHardDisk::AtaHardDisk() : AtaBaseDevice("ATA-HD") { } +void AtaHardDisk::insert_image(std::string filename) { + this->hdd_img.open(filename, std::fstream::out | std::fstream::in | std::fstream::binary); + + struct stat stat_buf; + int rc = stat(filename.c_str(), &stat_buf); + if (!rc) { + this->img_size = stat_buf.st_size; + } else { + ABORT_F("ScsiHardDisk: could not determine file size using stat()"); + } + this->hdd_img.seekg(0, std::ios_base::beg); +} + int AtaHardDisk::perform_command() { LOG_F(INFO, "%s: command 0x%x requested", this->name.c_str(), this->r_command); + this->r_status |= BSY; + switch (this->r_command) { + case NOP: + break; + case RESET_ATAPI: { + device_reset(); + break; + } + case READ_SECTOR: + case READ_SECTOR_NR: { + uint16_t sec_count = (this->r_sect_count == 0) ? 256 : this->r_sect_count; + uint32_t sector = (r_sect_num << 16); + sector |= ((this->r_cylinder_lo) << 8) + (this->r_cylinder_hi); + uint64_t offset = sector * 512; + hdd_img.seekg(offset, std::ios::beg); + hdd_img.read(buffer, sec_count * 512); + break; + } + case DIAGNOSTICS: + break; + default: + LOG_F(INFO, "Unknown ATA command 0x%x", this->r_command); + this->r_status |= ERR; + } + this->r_status &= ~(BSY); + this->r_status |= DRDY; return -1; } diff --git a/devices/common/ata/atahd.h b/devices/common/ata/atahd.h index c6319f2..d9dfaf2 100644 --- a/devices/common/ata/atahd.h +++ b/devices/common/ata/atahd.h @@ -25,6 +25,8 @@ along with this program. If not, see . #define ATA_HARD_DISK_H #include +#include +#include class AtaHardDisk : public AtaBaseDevice { @@ -32,7 +34,13 @@ public: AtaHardDisk(); ~AtaHardDisk() = default; + void insert_image(std::string filename); int perform_command(); + +private: + std::fstream hdd_img; + uint64_t img_size; + char * buffer = new char[1 <<17]; }; #endif // ATA_HARD_DISK_H diff --git a/devices/common/ata/idechannel.h b/devices/common/ata/idechannel.h index 427ea02..0ab145b 100644 --- a/devices/common/ata/idechannel.h +++ b/devices/common/ata/idechannel.h @@ -47,6 +47,7 @@ public: uint16_t read(const uint8_t reg_addr, const int size); void write(const uint8_t reg_addr, const uint16_t val, const int size); + //void talk_to_channel(std::string name) private: int cur_dev = 0;