dingusppc/devices/common/ata/atadefs.h

156 lines
4.2 KiB
C
Raw Normal View History

/*
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 <https://www.gnu.org/licenses/>.
*/
2022-12-07 21:36:25 +00:00
/** @file ATA interface definitions. */
2022-12-07 21:36:25 +00:00
#ifndef ATA_INTERFACE_H
#define ATA_INTERFACE_H
#include <cinttypes>
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
};
/** 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 {
2022-12-08 07:04:09 +00:00
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
DEVICE_HEAD = 0x6, // device/head
STATUS = 0x7, // status (read)
COMMAND = 0x7, // command (write)
ALT_STATUS = 0x16, // alt status (read)
DEV_CTRL = 0x16, // device control (write)
TIME_CONFIG = 0x20 // Apple ASIC specific timing configuration
};
2022-12-08 23:52:39 +00:00
/** Status register bits. */
2022-12-11 23:08:43 +00:00
enum ATA_Status : int {
2022-12-07 21:36:25 +00:00
ERR = 0x1,
IDX = 0x2,
CORR = 0x4,
DRQ = 0x8,
DSC = 0x10,
DWF = 0x20,
DRDY = 0x40,
BSY = 0x80
};
2022-12-08 23:52:39 +00:00
/** Error register bits. */
2022-12-11 23:08:43 +00:00
enum ATA_Error : int {
ANMF = 0x1, //no address mark
TK0NF = 0x2, //track 0 not found
ABRT = 0x4, //abort command
2022-12-05 15:42:51 +00:00
MCR = 0x8,
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,
2022-12-11 23:08:43 +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. */
2022-12-11 23:08:43 +00:00
enum ATA_CTRL : int{
IEN = 0x2,
SRST = 0x4,
HOB = 0x80,
2022-12-08 23:52:39 +00:00
};
/* ATA commands. */
2022-12-11 23:08:43 +00:00
enum ATA_Cmd : int {
2022-12-08 23:52:39 +00:00
NOP = 0x00,
RESET_ATAPI = 0x08,
RECALIBRATE = 0x10,
READ_SECTOR = 0x20,
READ_SECTOR_NR = 0x21,
READ_LONG = 0x22,
READ_SECTOR_EXT = 0x24,
WRITE_SECTOR = 0x30,
2022-12-11 23:08:43 +00:00
WRITE_SECTOR_NR = 0x31,
2022-12-08 23:52:39 +00:00
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,
};
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 {
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
virtual int get_device_id() = 0;
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;
uint16_t read(const uint8_t reg_addr) {
// 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;
};
void write(const uint8_t reg_addr, const uint16_t val) {};
2022-12-08 23:52:39 +00:00
// invalid device ID means no real device is present
2022-12-12 01:36:45 +00:00
int get_device_id() { return ata_interface::DEVICE_ID_INVALID; };
};
2022-12-07 21:36:25 +00:00
#endif // ATA_INTERFACE_H