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
*/
#include "viacuda.h"
#include "adb.h"
#include "memaccess.h"
#include "viacuda.h"
#include <cinttypes>
#include <loguru.hpp>
#include <memory>
using namespace std;
@ -43,19 +45,14 @@ ViaCuda::ViaCuda() {
this->via_regs[VIA_T1LH] = 0xFF;
this->via_regs[VIA_IER] = 0x7F;
// PRAM Pre-Initialization
this->pram_obj = new NVram("pram.bin", 256);
// PRAM is part of Cuda
this->pram_obj = std::unique_ptr<NVram> (new NVram("pram.bin", 256));
this->adb_obj = new ADB_Bus();
this->init();
}
ViaCuda::~ViaCuda() {
if (this->pram_obj)
delete (this->pram_obj);
}
void ViaCuda::init() {
this->old_tip = 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() {
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 */
void ViaCuda::out_buf_handler() {
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) {
uint16_t addr;
switch (cmd) {
case CUDA_START_STOP_AUTOPOLL:
if (this->in_buf[2]) {
@ -317,12 +322,26 @@ void ViaCuda::pseudo_command(int cmd, int data_count) {
response_header(CUDA_PKT_PSEUDO, 0);
break;
case CUDA_READ_PRAM:
response_header(CUDA_PKT_PSEUDO, 0);
this->pram_obj->read_byte(this->in_buf[2]);
addr = READ_WORD_BE_A(&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;
case CUDA_WRITE_PRAM:
response_header(CUDA_PKT_PSEUDO, 0);
this->pram_obj->write_byte(this->in_buf[2], this->in_buf[3]);
addr = READ_WORD_BE_A(&this->in_buf[2]);
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;
case CUDA_SET_AUTOPOLL_RATE:
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 "i2c.h"
#include "nvram.h"
#include <memory>
/** VIA register offsets. */
enum {
@ -103,6 +104,7 @@ enum {
CUDA_ERR_BAD_PKT = 1, /* invalid packet type */
CUDA_ERR_BAD_CMD = 2, /* invalid pseudo command */
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 */
};
@ -110,7 +112,7 @@ enum {
class ViaCuda : public HWComponent, public I2CBus {
public:
ViaCuda();
~ViaCuda();
~ViaCuda() = default;
bool supports_type(HWCompType type) {
return (type == HWCompType::ADB_HOST || type == HWCompType::I2C_HOST);
@ -135,11 +137,12 @@ private:
bool is_open_ended;
uint8_t curr_i2c_addr;
uint8_t cur_pram_addr;
void (ViaCuda::*out_handler)(void);
void (ViaCuda::*next_out_handler)(void);
NVram* pram_obj;
std::unique_ptr<NVram> pram_obj;
ADB_Bus* adb_obj;
void print_enabled_ints(); /* print enabled VIA interrupts and their sources */
@ -149,13 +152,13 @@ private:
void assert_sr_int();
void write(uint8_t new_state);
void response_header(uint32_t pkt_type, uint32_t pkt_flag);
// void cuda_response_packet();
void error_response(uint32_t error);
void process_packet();
void process_adb_command(uint8_t cmd_byte, int data_count);
void pseudo_command(int cmd, int data_count);
void null_out_handler(void);
void pram_out_handler(void);
void out_buf_handler(void);
void i2c_handler(void);