2022-10-08 23:51:54 +00:00
|
|
|
/*
|
|
|
|
DingusPPC - The Experimental PowerPC Macintosh emulator
|
2023-12-19 13:49:54 +00:00
|
|
|
Copyright (C) 2018-23 divingkatae and maximum
|
2022-10-08 23:51:54 +00:00
|
|
|
(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 <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2022-12-07 21:36:25 +00:00
|
|
|
/** @file ATA interface definitions. */
|
2022-10-08 23:51:54 +00:00
|
|
|
|
2022-12-07 21:36:25 +00:00
|
|
|
#ifndef ATA_INTERFACE_H
|
|
|
|
#define ATA_INTERFACE_H
|
2022-10-08 23:51:54 +00:00
|
|
|
|
|
|
|
#include <cinttypes>
|
2022-10-22 18:41:52 +00:00
|
|
|
|
2022-12-08 07:04:09 +00:00
|
|
|
namespace ata_interface {
|
|
|
|
|
2022-12-12 01:36:45 +00:00
|
|
|
/** Device IDs according with the Apple ATA zero/one specification. */
|
|
|
|
enum {
|
|
|
|
DEVICE_ID_INVALID = -1,
|
|
|
|
DEVICE_ID_ZERO = 0,
|
|
|
|
DEVICE_ID_ONE = 1
|
|
|
|
};
|
|
|
|
|
2022-12-12 14:07:19 +00:00
|
|
|
/** Device types. */
|
|
|
|
enum {
|
|
|
|
DEVICE_TYPE_UNKNOWN = -1,
|
|
|
|
DEVICE_TYPE_ATA = 0,
|
|
|
|
DEVICE_TYPE_ATAPI = 1,
|
|
|
|
};
|
|
|
|
|
2022-12-08 07:04:09 +00:00
|
|
|
/** ATA register offsets. */
|
2022-12-11 23:08:43 +00:00
|
|
|
enum ATA_Reg : int {
|
2023-05-15 15:53:00 +00:00
|
|
|
DATA = 0x00, // 16-bit data (read & write)
|
|
|
|
ERROR = 0x01, // error (read)
|
|
|
|
FEATURES = 0x01, // features (write)
|
|
|
|
SEC_COUNT = 0x02, // sector count
|
|
|
|
SEC_NUM = 0x03, // sector number
|
|
|
|
CYL_LOW = 0x04, // cylinder low
|
|
|
|
CYL_HIGH = 0x05, // cylinder high
|
|
|
|
DEVICE_HEAD = 0x06, // device/head
|
|
|
|
STATUS = 0x07, // status (read)
|
|
|
|
COMMAND = 0x07, // command (write)
|
|
|
|
ALT_STATUS = 0x16, // alt status (read)
|
|
|
|
DEV_CTRL = 0x16, // device control (write)
|
|
|
|
TIME_CONFIG = 0x20 // Apple ASIC specific timing configuration
|
|
|
|
};
|
|
|
|
|
|
|
|
/** ATAPI specific register offsets. */
|
|
|
|
enum ATAPI_Reg : int {
|
|
|
|
INT_REASON = 0x2, // interrupt reason (read-only)
|
|
|
|
BYTE_COUNT_LO = 0x4, // byte count (bits 0-7)
|
|
|
|
BYTE_COUNT_HI = 0x5, // byte count (bits 8-15)
|
|
|
|
};
|
|
|
|
|
|
|
|
/** ATAPI Interrupt Reason bits. */
|
|
|
|
enum ATAPI_Int_Reason : uint8_t {
|
|
|
|
CoD = 1 << 0,
|
|
|
|
IO = 1 << 1,
|
|
|
|
RELEASE = 1 << 2,
|
2022-10-08 23:51:54 +00:00
|
|
|
};
|
|
|
|
|
2023-06-18 21:06:04 +00:00
|
|
|
/** ATAPI Features bits. */
|
|
|
|
enum ATAPI_Features : uint8_t {
|
|
|
|
DMA = 1 << 0,
|
|
|
|
OVERLAP = 1 << 1
|
|
|
|
};
|
|
|
|
|
2023-11-22 16:03:37 +00:00
|
|
|
/** Device/Head register bits. */
|
|
|
|
enum ATA_Dev_Head : uint8_t {
|
|
|
|
LBA = 1 << 6,
|
|
|
|
};
|
|
|
|
|
2022-12-08 23:52:39 +00:00
|
|
|
/** Status register bits. */
|
2023-05-15 15:53:00 +00:00
|
|
|
enum ATA_Status : uint8_t {
|
|
|
|
ERR = 0x01,
|
|
|
|
IDX = 0x02,
|
|
|
|
CORR = 0x04,
|
|
|
|
DRQ = 0x08,
|
2022-10-08 23:51:54 +00:00
|
|
|
DSC = 0x10,
|
|
|
|
DWF = 0x20,
|
|
|
|
DRDY = 0x40,
|
|
|
|
BSY = 0x80
|
|
|
|
};
|
|
|
|
|
2022-12-08 23:52:39 +00:00
|
|
|
/** Error register bits. */
|
2023-05-15 15:53:00 +00:00
|
|
|
enum ATA_Error : uint8_t {
|
|
|
|
ANMF = 0x01, //no address mark
|
|
|
|
TK0NF = 0x02, //track 0 not found
|
|
|
|
ABRT = 0x04, //abort command
|
|
|
|
MCR = 0x08,
|
2022-12-11 23:08:43 +00:00
|
|
|
IDNF = 0x10, //id mark not found
|
|
|
|
MC = 0x20, //media change request
|
2022-12-05 15:42:51 +00:00
|
|
|
UNC = 0x40,
|
2023-05-15 15:53:00 +00:00
|
|
|
BBK = 0x80, //bad block
|
2022-12-05 15:42:51 +00:00
|
|
|
};
|
|
|
|
|
2022-12-08 23:52:39 +00:00
|
|
|
/** Bit definition for the device control register. */
|
2023-05-15 15:53:00 +00:00
|
|
|
enum ATA_CTRL : uint8_t {
|
|
|
|
IEN = 0x02,
|
|
|
|
SRST = 0x04,
|
2022-12-11 23:08:43 +00:00
|
|
|
HOB = 0x80,
|
2022-12-08 23:52:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* ATA commands. */
|
2023-05-15 15:53:00 +00:00
|
|
|
enum ATA_Cmd : uint8_t {
|
2024-03-30 03:47:25 +00:00
|
|
|
NOP = 0x00,
|
|
|
|
ATAPI_SOFT_RESET = 0x08,
|
|
|
|
RECALIBRATE = 0x10,
|
|
|
|
READ_SECTOR = 0x20,
|
|
|
|
READ_SECTOR_NR = 0x21,
|
|
|
|
READ_LONG = 0x22,
|
|
|
|
READ_SECTOR_EXT = 0x24,
|
|
|
|
WRITE_SECTOR = 0x30,
|
|
|
|
WRITE_SECTOR_NR = 0x31,
|
|
|
|
WRITE_LONG = 0x32,
|
|
|
|
READ_VERIFY = 0x40,
|
|
|
|
FORMAT_TRACKS = 0x50,
|
|
|
|
IDE_SEEK = 0x70,
|
|
|
|
DIAGNOSTICS = 0x90,
|
|
|
|
INIT_DEV_PARAM = 0x91,
|
|
|
|
ATAPI_PACKET = 0xA0,
|
|
|
|
ATAPI_IDFY_DEV = 0xA1,
|
|
|
|
ATAPI_SERVICE = 0xA2,
|
|
|
|
READ_MULTIPLE = 0xC4,
|
|
|
|
WRITE_MULTIPLE = 0xC5,
|
|
|
|
READ_DMA = 0xC8,
|
|
|
|
WRITE_DMA = 0xCA,
|
|
|
|
STANDBY_IMMEDIATE_E0 = 0xE0,
|
|
|
|
FLUSH_CACHE = 0xE7, // ATA-5
|
|
|
|
WRITE_BUFFER_DMA = 0xE9,
|
|
|
|
READ_BUFFER_DMA = 0xEB,
|
|
|
|
IDENTIFY_DEVICE = 0xEC,
|
|
|
|
SET_FEATURES = 0xEF,
|
2022-10-08 23:51:54 +00:00
|
|
|
};
|
|
|
|
|
2022-12-08 07:04:09 +00:00
|
|
|
}; // namespace ata_interface
|
|
|
|
|
2022-12-07 21:36:25 +00:00
|
|
|
/** Interface for ATA devices. */
|
|
|
|
class AtaInterface {
|
2022-10-08 23:51:54 +00:00
|
|
|
public:
|
2022-12-07 21:36:25 +00:00
|
|
|
AtaInterface() = default;
|
|
|
|
virtual ~AtaInterface() = default;
|
|
|
|
virtual uint16_t read(const uint8_t reg_addr) = 0;
|
|
|
|
virtual void write(const uint8_t reg_addr, const uint16_t val) = 0;
|
2022-12-08 23:52:39 +00:00
|
|
|
|
2023-04-24 21:02:32 +00:00
|
|
|
virtual int get_device_id() = 0;
|
|
|
|
virtual void pdiag_callback() {};
|
2022-12-07 21:36:25 +00:00
|
|
|
};
|
2022-12-05 15:42:51 +00:00
|
|
|
|
2022-12-07 21:36:25 +00:00
|
|
|
/** Dummy ATA device. */
|
|
|
|
class AtaNullDevice : public AtaInterface {
|
|
|
|
public:
|
|
|
|
AtaNullDevice() = default;
|
|
|
|
~AtaNullDevice() = default;
|
|
|
|
|
2023-04-24 21:02:32 +00:00
|
|
|
uint16_t read(const uint8_t reg_addr) override {
|
2022-12-07 21:36:25 +00:00
|
|
|
// return all one's except DD7 if no device is present
|
|
|
|
// DD7 corresponds to the BSY bit of the status register
|
|
|
|
// The host should have a pull-down resistor on DD7
|
|
|
|
// to prevent the software from waiting for a long time
|
|
|
|
// for empty slots
|
|
|
|
return 0xFF7FU;
|
|
|
|
};
|
|
|
|
|
2023-04-24 21:02:32 +00:00
|
|
|
void write(const uint8_t reg_addr, const uint16_t val) override {};
|
2022-12-08 23:52:39 +00:00
|
|
|
|
|
|
|
// invalid device ID means no real device is present
|
2023-04-24 21:02:32 +00:00
|
|
|
int get_device_id() override { return ata_interface::DEVICE_ID_INVALID; };
|
2022-10-08 23:51:54 +00:00
|
|
|
};
|
|
|
|
|
2022-12-07 21:36:25 +00:00
|
|
|
#endif // ATA_INTERFACE_H
|