mirror of
https://github.com/dingusdev/dingusppc.git
synced 2025-01-11 20:29:46 +00:00
Further ATA cmd work
This commit is contained in:
parent
86b0174b13
commit
0dd9a3d9b1
@ -50,30 +50,30 @@ void AtaBaseDevice::device_reset()
|
||||
this->r_cylinder_lo = 0;
|
||||
this->r_cylinder_hi = 0;
|
||||
this->r_dev_head = 0; // TODO: ATAPI devices shouldn't change this reg!
|
||||
this->r_status = IDE_Status::DRDY | IDE_Status::DSC;
|
||||
this->r_status = DRDY | DSC;
|
||||
}
|
||||
|
||||
uint16_t AtaBaseDevice::read(const uint8_t reg_addr) {
|
||||
switch (reg_addr) {
|
||||
case IDE_Reg::DATA:
|
||||
case ATA_Reg::DATA:
|
||||
LOG_F(WARNING, "Retrieving data from %s", this->name.c_str());
|
||||
return 0xFFFFU;
|
||||
case IDE_Reg::ERROR:
|
||||
case ATA_Reg::ERROR:
|
||||
return this->r_error;
|
||||
case IDE_Reg::SEC_COUNT:
|
||||
case ATA_Reg::SEC_COUNT:
|
||||
return this->r_sect_count;
|
||||
case IDE_Reg::SEC_NUM:
|
||||
case ATA_Reg::SEC_NUM:
|
||||
return this->r_sect_num;
|
||||
case IDE_Reg::CYL_LOW:
|
||||
case ATA_Reg::CYL_LOW:
|
||||
return this->r_cylinder_lo;
|
||||
case IDE_Reg::CYL_HIGH:
|
||||
case ATA_Reg::CYL_HIGH:
|
||||
return this->r_cylinder_hi;
|
||||
case IDE_Reg::DEVICE_HEAD:
|
||||
case ATA_Reg::DEVICE_HEAD:
|
||||
return this->r_dev_head;
|
||||
case IDE_Reg::STATUS:
|
||||
case ATA_Reg::STATUS:
|
||||
// TODO: clear pending interrupt
|
||||
return this->r_status;
|
||||
case IDE_Reg::ALT_STATUS:
|
||||
case ATA_Reg::ALT_STATUS:
|
||||
return this->r_status;
|
||||
default:
|
||||
LOG_F(WARNING, "Attempted to read unknown IDE register: %x", reg_addr);
|
||||
@ -83,37 +83,37 @@ uint16_t AtaBaseDevice::read(const uint8_t reg_addr) {
|
||||
|
||||
void AtaBaseDevice::write(const uint8_t reg_addr, const uint16_t value) {
|
||||
switch (reg_addr) {
|
||||
case IDE_Reg::DATA:
|
||||
case ATA_Reg::DATA:
|
||||
LOG_F(WARNING, "Pushing data to %s", this->name.c_str());
|
||||
break;
|
||||
case IDE_Reg::FEATURES:
|
||||
case ATA_Reg::FEATURES:
|
||||
this->r_features = value;
|
||||
break;
|
||||
case IDE_Reg::SEC_COUNT:
|
||||
case ATA_Reg::SEC_COUNT:
|
||||
this->r_sect_count = value;
|
||||
break;
|
||||
case IDE_Reg::SEC_NUM:
|
||||
case ATA_Reg::SEC_NUM:
|
||||
this->r_sect_num = value;
|
||||
break;
|
||||
case IDE_Reg::CYL_LOW:
|
||||
case ATA_Reg::CYL_LOW:
|
||||
this->r_cylinder_lo = value;
|
||||
break;
|
||||
case IDE_Reg::CYL_HIGH:
|
||||
case ATA_Reg::CYL_HIGH:
|
||||
this->r_cylinder_hi = value;
|
||||
break;
|
||||
case IDE_Reg::DEVICE_HEAD:
|
||||
case ATA_Reg::DEVICE_HEAD:
|
||||
this->r_dev_head = value;
|
||||
break;
|
||||
case IDE_Reg::COMMAND:
|
||||
case ATA_Reg::COMMAND:
|
||||
this->r_command = value;
|
||||
if (is_selected() || this->r_command == IDE_Cmd::DIAGNOSTICS) {
|
||||
if (is_selected() || this->r_command == DIAGNOSTICS) {
|
||||
perform_command();
|
||||
}
|
||||
break;
|
||||
case IDE_Reg::DEV_CTRL:
|
||||
if (!(this->r_dev_ctrl & ATA_CTRL_SRST) && (value & ATA_CTRL_SRST)) {
|
||||
case ATA_Reg::DEV_CTRL:
|
||||
if (!(this->r_dev_ctrl & SRST) && (value & SRST)) {
|
||||
LOG_F(INFO, "%s: soft reset triggered", this->name.c_str());
|
||||
this->r_status |= IDE_Status::BSY;
|
||||
this->r_status |= BSY;
|
||||
}
|
||||
this->r_dev_ctrl = value;
|
||||
break;
|
||||
|
@ -29,7 +29,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
namespace ata_interface {
|
||||
|
||||
/** ATA register offsets. */
|
||||
enum IDE_Reg : int {
|
||||
enum ATA_Reg : int {
|
||||
DATA = 0x0,
|
||||
ERROR = 0x1, // error (read)
|
||||
FEATURES = 0x1, // features (write)
|
||||
@ -46,7 +46,7 @@ enum IDE_Reg : int {
|
||||
};
|
||||
|
||||
/** Status register bits. */
|
||||
enum IDE_Status : int {
|
||||
enum ATA_Status : int {
|
||||
ERR = 0x1,
|
||||
IDX = 0x2,
|
||||
CORR = 0x4,
|
||||
@ -58,25 +58,26 @@ enum IDE_Status : int {
|
||||
};
|
||||
|
||||
/** Error register bits. */
|
||||
enum IDE_Error : int {
|
||||
ANMF = 0x1,
|
||||
TK0NF = 0x2,
|
||||
ABRT = 0x4,
|
||||
enum ATA_Error : int {
|
||||
ANMF = 0x1, //no address mark
|
||||
TK0NF = 0x2, //track 0 not found
|
||||
ABRT = 0x4, //abort command
|
||||
MCR = 0x8,
|
||||
IDNF = 0x10,
|
||||
MC = 0x20,
|
||||
IDNF = 0x10, //id mark not found
|
||||
MC = 0x20, //media change request
|
||||
UNC = 0x40,
|
||||
BBK = 0x80
|
||||
BBK = 0x80 //bad block
|
||||
};
|
||||
|
||||
/** Bit definition for the device control register. */
|
||||
enum {
|
||||
ATA_CTRL_nIEN = 1 << 1,
|
||||
ATA_CTRL_SRST = 1 << 2,
|
||||
enum ATA_CTRL : int{
|
||||
IEN = 0x2,
|
||||
SRST = 0x4,
|
||||
HOB = 0x80,
|
||||
};
|
||||
|
||||
/* ATA commands. */
|
||||
enum IDE_Cmd : int {
|
||||
enum ATA_Cmd : int {
|
||||
NOP = 0x00,
|
||||
RESET_ATAPI = 0x08,
|
||||
RECALIBRATE = 0x10,
|
||||
@ -85,7 +86,7 @@ enum IDE_Cmd : int {
|
||||
READ_LONG = 0x22,
|
||||
READ_SECTOR_EXT = 0x24,
|
||||
WRITE_SECTOR = 0x30,
|
||||
WRITE_SECTOR_NR = 0x21,
|
||||
WRITE_SECTOR_NR = 0x31,
|
||||
WRITE_LONG = 0x32,
|
||||
READ_VERIFY = 0x40,
|
||||
FORMAT_TRACKS = 0x50,
|
||||
|
@ -50,6 +50,7 @@ int AtaHardDisk::perform_command()
|
||||
{
|
||||
LOG_F(INFO, "%s: command 0x%x requested", this->name.c_str(), this->r_command);
|
||||
this->r_status |= BSY;
|
||||
this->r_status &= ~(DRDY);
|
||||
switch (this->r_command) {
|
||||
case NOP:
|
||||
break;
|
||||
@ -57,23 +58,58 @@ int AtaHardDisk::perform_command()
|
||||
device_reset();
|
||||
break;
|
||||
}
|
||||
case RECALIBRATE:
|
||||
hdd_img.seekg(0, std::ios::beg);
|
||||
this->r_error = 0;
|
||||
this->r_cylinder_lo = 0;
|
||||
this->r_cylinder_hi = 0;
|
||||
break;
|
||||
case READ_SECTOR:
|
||||
case READ_SECTOR_NR: {
|
||||
this->r_status |= DRQ;
|
||||
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);
|
||||
this->r_status &= ~(DRQ);
|
||||
break;
|
||||
}
|
||||
case DIAGNOSTICS:
|
||||
case WRITE_SECTOR:
|
||||
case WRITE_SECTOR_NR: {
|
||||
this->r_status |= DRQ;
|
||||
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.write(buffer, sec_count * 512);
|
||||
this->r_status &= ~(DRQ);
|
||||
break;
|
||||
}
|
||||
case INIT_DEV_PARAM:
|
||||
break;
|
||||
case DIAGNOSTICS: {
|
||||
this->r_status |= DRQ;
|
||||
int ret_code = this->r_error;
|
||||
this->r_status &= ~(DRQ);
|
||||
return ret_code;
|
||||
break;
|
||||
}
|
||||
case IDENTIFY_DEVICE: {
|
||||
this->r_status |= DRQ;
|
||||
memcpy(buffer, ide_hd_id, 512);
|
||||
this->r_status &= ~(DRQ);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_F(INFO, "Unknown ATA command 0x%x", this->r_command);
|
||||
this->r_status &= ~(BSY);
|
||||
this->r_status |= ERR;
|
||||
return -1;
|
||||
}
|
||||
this->r_status &= ~(BSY);
|
||||
this->r_status |= DRDY;
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,6 +41,10 @@ private:
|
||||
std::fstream hdd_img;
|
||||
uint64_t img_size;
|
||||
char * buffer = new char[1 <<17];
|
||||
|
||||
char* ide_hd_id = {
|
||||
0x0
|
||||
};
|
||||
};
|
||||
|
||||
#endif // ATA_HARD_DISK_H
|
||||
|
@ -48,7 +48,7 @@ IdeChannel::IdeChannel(const std::string name)
|
||||
|
||||
uint32_t IdeChannel::read(const uint8_t reg_addr, const int size)
|
||||
{
|
||||
if (reg_addr == IDE_Reg::TIME_CONFIG) {
|
||||
if (reg_addr == TIME_CONFIG) {
|
||||
if (size != 4) {
|
||||
LOG_F(WARNING, "%s: non-DWORD read from the channel config", this->name.c_str());
|
||||
}
|
||||
@ -60,14 +60,14 @@ uint32_t IdeChannel::read(const uint8_t reg_addr, const int size)
|
||||
|
||||
void IdeChannel::write(const uint8_t reg_addr, const uint32_t val, const int size)
|
||||
{
|
||||
if (reg_addr == IDE_Reg::TIME_CONFIG) {
|
||||
if (reg_addr == TIME_CONFIG) {
|
||||
if (size != 4) {
|
||||
LOG_F(WARNING, "%s: non-DWORD write to the channel config", this->name.c_str());
|
||||
}
|
||||
this->ch_config = val;
|
||||
} else {
|
||||
// keep track of the currently selected device
|
||||
if (reg_addr == IDE_Reg::DEVICE_HEAD) {
|
||||
if (reg_addr == DEVICE_HEAD) {
|
||||
this->cur_dev = (val >> 4) & 1;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user