viacuda: fix PRAM reading and writing.

This commit is contained in:
Maxim Poliakovski 2021-10-14 00:01:30 +02:00
parent e53296f7a9
commit 2f725fe3e4
2 changed files with 38 additions and 16 deletions

View File

@ -24,10 +24,12 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
Author: Max Poliakovski 2019 Author: Max Poliakovski 2019
*/ */
#include "viacuda.h"
#include "adb.h" #include "adb.h"
#include "memaccess.h"
#include "viacuda.h"
#include <cinttypes> #include <cinttypes>
#include <loguru.hpp> #include <loguru.hpp>
#include <memory>
using namespace std; using namespace std;
@ -43,19 +45,14 @@ ViaCuda::ViaCuda() {
this->via_regs[VIA_T1LH] = 0xFF; this->via_regs[VIA_T1LH] = 0xFF;
this->via_regs[VIA_IER] = 0x7F; this->via_regs[VIA_IER] = 0x7F;
// PRAM Pre-Initialization // PRAM is part of Cuda
this->pram_obj = new NVram("pram.bin", 256); this->pram_obj = std::unique_ptr<NVram> (new NVram("pram.bin", 256));
this->adb_obj = new ADB_Bus(); this->adb_obj = new ADB_Bus();
this->init(); this->init();
} }
ViaCuda::~ViaCuda() {
if (this->pram_obj)
delete (this->pram_obj);
}
void ViaCuda::init() { void ViaCuda::init() {
this->old_tip = 0; this->old_tip = 0;
this->old_byteack = 0; this->old_byteack = 0;
@ -197,11 +194,17 @@ void ViaCuda::write(uint8_t new_state) {
} }
} }
/* sends zeros to host at infinitum */ /* sends zeros to host ad infinitum */
void ViaCuda::null_out_handler() { void ViaCuda::null_out_handler() {
this->via_regs[VIA_SR] = 0; this->via_regs[VIA_SR] = 0;
} }
/* sends PRAM content to host ad infinitum */
void ViaCuda::pram_out_handler()
{
this->via_regs[VIA_SR] = this->pram_obj->read_byte(this->cur_pram_addr++);
}
/* sends data from out_buf until exhausted, then switches to next_out_handler */ /* sends data from out_buf until exhausted, then switches to next_out_handler */
void ViaCuda::out_buf_handler() { void ViaCuda::out_buf_handler() {
if (this->out_pos < this->out_count) { if (this->out_pos < this->out_count) {
@ -307,6 +310,8 @@ void ViaCuda::process_adb_command(uint8_t cmd_byte, int data_count) {
} }
void ViaCuda::pseudo_command(int cmd, int data_count) { void ViaCuda::pseudo_command(int cmd, int data_count) {
uint16_t addr;
switch (cmd) { switch (cmd) {
case CUDA_START_STOP_AUTOPOLL: case CUDA_START_STOP_AUTOPOLL:
if (this->in_buf[2]) { if (this->in_buf[2]) {
@ -317,12 +322,26 @@ void ViaCuda::pseudo_command(int cmd, int data_count) {
response_header(CUDA_PKT_PSEUDO, 0); response_header(CUDA_PKT_PSEUDO, 0);
break; break;
case CUDA_READ_PRAM: case CUDA_READ_PRAM:
response_header(CUDA_PKT_PSEUDO, 0); addr = READ_WORD_BE_A(&this->in_buf[2]);
this->pram_obj->read_byte(this->in_buf[2]); if (addr <= 0xFF) {
response_header(CUDA_PKT_PSEUDO, 0);
// this command is open-ended so set up the corresponding context
this->cur_pram_addr = addr;
this->next_out_handler = &ViaCuda::pram_out_handler;
this->is_open_ended = true;
} else {
error_response(CUDA_ERR_BAD_PAR);
}
break; break;
case CUDA_WRITE_PRAM: case CUDA_WRITE_PRAM:
response_header(CUDA_PKT_PSEUDO, 0); addr = READ_WORD_BE_A(&this->in_buf[2]);
this->pram_obj->write_byte(this->in_buf[2], this->in_buf[3]); if (addr <= 0xFF) {
// TODO: implement open-ended write transaction properly
response_header(CUDA_PKT_PSEUDO, 0);
this->pram_obj->write_byte(addr, this->in_buf[4]);
} else {
error_response(CUDA_ERR_BAD_PAR);
}
break; break;
case CUDA_SET_AUTOPOLL_RATE: case CUDA_SET_AUTOPOLL_RATE:
this->poll_rate = this->in_buf[2]; this->poll_rate = this->in_buf[2];

View File

@ -49,6 +49,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "hwcomponent.h" #include "hwcomponent.h"
#include "i2c.h" #include "i2c.h"
#include "nvram.h" #include "nvram.h"
#include <memory>
/** VIA register offsets. */ /** VIA register offsets. */
enum { enum {
@ -103,6 +104,7 @@ enum {
CUDA_ERR_BAD_PKT = 1, /* invalid packet type */ CUDA_ERR_BAD_PKT = 1, /* invalid packet type */
CUDA_ERR_BAD_CMD = 2, /* invalid pseudo command */ CUDA_ERR_BAD_CMD = 2, /* invalid pseudo command */
CUDA_ERR_BAD_SIZE = 3, /* invalid packet size */ CUDA_ERR_BAD_SIZE = 3, /* invalid packet size */
CUDA_ERR_BAD_PAR = 4, /* invalid parameter */
CUDA_ERR_I2C = 5 /* invalid I2C data or no acknowledge */ CUDA_ERR_I2C = 5 /* invalid I2C data or no acknowledge */
}; };
@ -110,7 +112,7 @@ enum {
class ViaCuda : public HWComponent, public I2CBus { class ViaCuda : public HWComponent, public I2CBus {
public: public:
ViaCuda(); ViaCuda();
~ViaCuda(); ~ViaCuda() = default;
bool supports_type(HWCompType type) { bool supports_type(HWCompType type) {
return (type == HWCompType::ADB_HOST || type == HWCompType::I2C_HOST); return (type == HWCompType::ADB_HOST || type == HWCompType::I2C_HOST);
@ -135,11 +137,12 @@ private:
bool is_open_ended; bool is_open_ended;
uint8_t curr_i2c_addr; uint8_t curr_i2c_addr;
uint8_t cur_pram_addr;
void (ViaCuda::*out_handler)(void); void (ViaCuda::*out_handler)(void);
void (ViaCuda::*next_out_handler)(void); void (ViaCuda::*next_out_handler)(void);
NVram* pram_obj; std::unique_ptr<NVram> pram_obj;
ADB_Bus* adb_obj; ADB_Bus* adb_obj;
void print_enabled_ints(); /* print enabled VIA interrupts and their sources */ void print_enabled_ints(); /* print enabled VIA interrupts and their sources */
@ -149,13 +152,13 @@ private:
void assert_sr_int(); void assert_sr_int();
void write(uint8_t new_state); void write(uint8_t new_state);
void response_header(uint32_t pkt_type, uint32_t pkt_flag); void response_header(uint32_t pkt_type, uint32_t pkt_flag);
// void cuda_response_packet();
void error_response(uint32_t error); void error_response(uint32_t error);
void process_packet(); void process_packet();
void process_adb_command(uint8_t cmd_byte, int data_count); void process_adb_command(uint8_t cmd_byte, int data_count);
void pseudo_command(int cmd, int data_count); void pseudo_command(int cmd, int data_count);
void null_out_handler(void); void null_out_handler(void);
void pram_out_handler(void);
void out_buf_handler(void); void out_buf_handler(void);
void i2c_handler(void); void i2c_handler(void);