diff --git a/devices/viacuda.cpp b/devices/viacuda.cpp index 0379e0c..ddc5145 100644 --- a/devices/viacuda.cpp +++ b/devices/viacuda.cpp @@ -11,14 +11,17 @@ */ #include +#include #include #include #include "viacuda.h" using namespace std; +/** the signature for PRAM backing file identification. */ +static char PRAM_FILE_ID[] = "DINGUSPPCP-RAM"; -ViaCuda::ViaCuda() +ViaCuda::ViaCuda(std::string pram_file, uint32_t pram_size) { /* FIXME: is this the correct VIA initialization? */ @@ -29,6 +32,12 @@ ViaCuda::ViaCuda() this->via_regs[VIA_T1LH] = 0xFF; this->via_regs[VIA_IER] = 0x7F; + //PRAM Pre-Initialization + this->pram_file = pram_file; + this->pram_size = pram_size; + + this->pram_storage = new uint8_t[pram_size]; + this->cuda_init(); } @@ -39,6 +48,31 @@ void ViaCuda::cuda_init() this->treq = 1; this->in_count = 0; this->out_count = 0; + + //PRAM Initialization + char sig[sizeof(PRAM_FILE_ID)]; + uint16_t data_size; + + ifstream f(this->pram_file, ios::in | ios::binary); + + if (f.fail() || !f.read(sig, sizeof(PRAM_FILE_ID)) || + !f.read((char*)&data_size, sizeof(data_size)) || + memcmp(sig, PRAM_FILE_ID, sizeof(PRAM_FILE_ID)) || + data_size != this->pram_size || + !f.read((char*)this->pram_storage, this->pram_size)) + { + cout << "WARN: Could not restore PRAM content from the given file." << endl; + memset(this->pram_storage, 0, sizeof(this->pram_size)); + } + + f.close(); +} + +ViaCuda::~ViaCuda() +{ + this->cuda_pram_save(); + if (this->pram_storage) + delete this->pram_storage; } uint8_t ViaCuda::read(int reg) @@ -239,6 +273,14 @@ void ViaCuda::cuda_process_packet() void ViaCuda::cuda_pseudo_command(int cmd, int data_count) { switch(cmd) { + case CUDA_READ_PRAM: + cuda_response_header(CUDA_PKT_PSEUDO, 0); + pram_read_value(this->in_buf[2]); + break; + case CUDA_WRITE_PRAM: + cuda_response_header(CUDA_PKT_PSEUDO, 0); + pram_write_value(this->in_buf[2], this->in_buf[3]); + break; case CUDA_READ_WRITE_I2C: cuda_response_header(CUDA_PKT_PSEUDO, 0); /* bit 0 of the I2C address byte indicates operation kind: @@ -271,6 +313,14 @@ void ViaCuda::cuda_pseudo_command(int cmd, int data_count) } } +uint8_t ViaCuda::pram_read_value(uint8_t offset) { + return pram_storage[offset]; +} + +void ViaCuda::pram_write_value(uint8_t offset, uint8_t new_state) { + pram_storage[offset] = new_state; +} + void ViaCuda::i2c_simple_transaction(uint8_t dev_addr, const uint8_t *in_buf, int in_bytes) { @@ -324,3 +374,17 @@ void ViaCuda::i2c_comb_transaction(uint8_t dev_addr, uint8_t sub_addr, cuda_error_response(CUDA_ERR_I2C); } } + +void ViaCuda::cuda_pram_save() +{ + ofstream f(this->pram_file, ios::out | ios::binary); + + /* write file identification */ + f.write(PRAM_FILE_ID, sizeof(PRAM_FILE_ID)); + f.write((char*)&this->pram_size, sizeof(this->pram_size)); + + /* write PRAM content */ + f.write((char*)this->pram_storage, this->pram_size); + + f.close(); +} \ No newline at end of file diff --git a/devices/viacuda.h b/devices/viacuda.h index f031370..5df968c 100644 --- a/devices/viacuda.h +++ b/devices/viacuda.h @@ -69,6 +69,8 @@ enum { /** Cuda pseudo commands. */ enum { + CUDA_READ_PRAM = 0x07, /* read parameter RAM*/ + CUDA_WRITE_PRAM = 0x0C, /* write parameter RAM*/ CUDA_READ_WRITE_I2C = 0x22, /* read/write I2C device */ CUDA_COMB_FMT_I2C = 0x25, /* combined format I2C transaction */ CUDA_OUT_PB0 = 0x26, /* output one bit to Cuda's PB0 line */ @@ -84,8 +86,8 @@ enum { class ViaCuda { public: - ViaCuda(); - ~ViaCuda() = default; + ViaCuda(std::string pram_file = "pram.bin", uint32_t pram_size = 256); + ~ViaCuda(); uint8_t read(int reg); void write(int reg, uint8_t value); @@ -103,6 +105,10 @@ private: int32_t out_count; int32_t out_pos; + std::string pram_file; /* file name for the PRAM file. */ + uint8_t pram_size; /* PRAM size. */ + uint8_t* pram_storage; + void print_enabled_ints(); /* print enabled VIA interrupts and their sources */ void cuda_init(); @@ -113,8 +119,11 @@ private: void cuda_error_response(uint32_t error); void cuda_process_packet(); void cuda_pseudo_command(int cmd, int data_count); + void cuda_pram_save(); /* I2C related methods */ + uint8_t pram_read_value(uint8_t offset); + void pram_write_value(uint8_t offset, uint8_t new_state); void i2c_simple_transaction(uint8_t dev_addr, const uint8_t *in_buf, int in_bytes); void i2c_comb_transaction(uint8_t dev_addr, uint8_t sub_addr, uint8_t dev_addr1, const uint8_t *in_buf, int in_bytes);