diff --git a/devices/common/scsi/scsi.h b/devices/common/scsi/scsi.h index 56f6af0..9c864d0 100644 --- a/devices/common/scsi/scsi.h +++ b/devices/common/scsi/scsi.h @@ -58,6 +58,42 @@ enum ScsiMsg : int { BUS_PHASE_CHANGE, }; +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, +}; + +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, + +}; + /** Standard SCSI bus timing values measured in ns. */ #define BUS_SETTLE_DELAY 400 #define BUS_FREE_DELAY 800 diff --git a/devices/harddrive/ata_hd.cpp b/devices/harddrive/ata_hd.cpp new file mode 100644 index 0000000..2cd2732 --- /dev/null +++ b/devices/harddrive/ata_hd.cpp @@ -0,0 +1,19 @@ +#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 new file mode 100644 index 0000000..3aa41a6 --- /dev/null +++ b/devices/harddrive/ata_hd.h @@ -0,0 +1,17 @@ + +/** @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 new file mode 100644 index 0000000..e7da541 --- /dev/null +++ b/devices/harddrive/scsi_hd.cpp @@ -0,0 +1,72 @@ +#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/harddrive/scsi_hd.h b/devices/harddrive/scsi_hd.h new file mode 100644 index 0000000..3cc6163 --- /dev/null +++ b/devices/harddrive/scsi_hd.h @@ -0,0 +1,62 @@ +/* +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 SCSI hard drive support */ + +#ifndef SCSI_HD_H +#define SCSI_HD_H + +#include +#include +#include +#include + +class HardDrive : public ScsiDevice { +public: + HardDrive(std::string filename); + ~HardDrive() = default; + + virtual void notify(ScsiMsg msg_type, int param){ + return param; + }; + + int test_unit_ready(); + int req_sense(uint8_t alloc_len); + int read_capacity_10(); + int inquiry(); + int send_diagnostic(); + + void format(); + void read(uint32_t lba, uint16_t transfer_len); + void write(uint32_t lba, uint16_t transfer_len); + void seek(uint32_t lba); + void rewind(); + +protected: + std::string img_path; + fstream hdd_img; + uint64_t img_size; + char img_buffer[1 << 17]; + uint8_t scsi_command[12]; + uint64_t file_offset = 0; +} + +#endif \ No newline at end of file