serial_transfer: implement "maple_raw" command
This commit is contained in:
parent
66f8eeeda2
commit
c713a084d8
@ -2,7 +2,7 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
|
||||
DIR := $(dir $(MAKEFILE_PATH))
|
||||
|
||||
LIB ?= .
|
||||
OPT ?= -O2
|
||||
OPT ?= -Og
|
||||
GENERATED ?=
|
||||
|
||||
AARCH = --isa=sh4 --little
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#include "crc32.h"
|
||||
|
||||
static struct serial_load::maple_poll_state poll_state __attribute__((aligned(32)));
|
||||
|
||||
extern uint32_t _binary_font_portfolio_6x8 __asm("_binary_font_portfolio_6x8_portfolio_6x8_data_start");
|
||||
|
||||
template <typename T>
|
||||
@ -43,22 +45,7 @@ struct serial_error_counter {
|
||||
|
||||
struct serial_error_counter error_counter;
|
||||
|
||||
enum struct step {
|
||||
IDLE = 0,
|
||||
DEVICE_STATUS,
|
||||
EXTENSION_DEVICE_STATUS,
|
||||
EXTENSION_DEVICE_REPLY,
|
||||
};
|
||||
|
||||
struct maple_display_poll_state {
|
||||
bool want_start;
|
||||
enum step step;
|
||||
struct {
|
||||
uint8_t ap__lm;
|
||||
} port[4];
|
||||
};
|
||||
|
||||
void send_vmu_framebuffer(maple::host_command_writer& writer, uint8_t port, uint8_t lm)
|
||||
void send_vmu_framebuffer(maple::host_command_writer<>& writer, uint8_t port, uint8_t lm)
|
||||
{
|
||||
using command_type = maple::block_write<uint8_t[0]>;
|
||||
using response_type = maple::device_reply;
|
||||
@ -88,9 +75,9 @@ void send_vmu_framebuffer(maple::host_command_writer& writer, uint8_t port, uint
|
||||
copy<uint8_t>(data_fields.written_data, fb, maple::display::vmu::framebuffer_size);
|
||||
}
|
||||
|
||||
void recv_extension_device_status(struct maple_display_poll_state &state)
|
||||
void recv_extension_device_status(struct serial_load::maple_poll_state &state)
|
||||
{
|
||||
auto writer = maple::host_command_writer(send_buf, recv_buf);
|
||||
auto writer = maple::host_command_writer<>(send_buf, recv_buf);
|
||||
|
||||
using response_type = maple::host_response<maple::device_status::data_fields>;
|
||||
auto host_response = reinterpret_cast<response_type *>(recv_buf);
|
||||
@ -112,20 +99,25 @@ void recv_extension_device_status(struct maple_display_poll_state &state)
|
||||
|
||||
auto& bus_data = host_response[response_index++].bus_data;
|
||||
auto& data_fields = bus_data.data_fields;
|
||||
if ((bus_data.command_code == maple::device_status::command_code) &&
|
||||
(std::byteswap(data_fields.device_id.ft) & function_type::bw_lcd)) {
|
||||
|
||||
last_send_offset = writer.send_offset;
|
||||
send_vmu_framebuffer(writer, port, bit);
|
||||
if (bus_data.command_code != maple::device_status::command_code) {
|
||||
state.port[port].lm[i].device_id.ft = 0;
|
||||
} else {
|
||||
// this extension device is not a bw_lcd; remove it
|
||||
state.port[port].ap__lm &= ~bit;
|
||||
state.port[port].lm[i].device_id.ft = std::byteswap(data_fields.device_id.ft);
|
||||
state.port[port].lm[i].device_id.fd[0] = std::byteswap(data_fields.device_id.fd[0]);
|
||||
state.port[port].lm[i].device_id.fd[1] = std::byteswap(data_fields.device_id.fd[1]);
|
||||
state.port[port].lm[i].device_id.fd[2] = std::byteswap(data_fields.device_id.fd[2]);
|
||||
|
||||
if (state.port[port].lm[i].device_id.ft & function_type::bw_lcd) {
|
||||
last_send_offset = writer.send_offset;
|
||||
send_vmu_framebuffer(writer, port, bit);
|
||||
}
|
||||
}
|
||||
bit <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// change the last command from
|
||||
using command_type = maple::host_command<maple::block_write<uint8_t[0]>::data_fields>;
|
||||
auto host_command = reinterpret_cast<command_type *>(&send_buf[last_send_offset / 4]);
|
||||
host_command->host_instruction |= host_instruction::end_flag;
|
||||
@ -135,7 +127,7 @@ void recv_extension_device_status(struct maple_display_poll_state &state)
|
||||
}
|
||||
}
|
||||
|
||||
void send_extension_device_request(maple::host_command_writer& writer, uint8_t port, uint8_t lm)
|
||||
void send_extension_device_request(maple::host_command_writer<>& writer, uint8_t port, uint8_t lm)
|
||||
{
|
||||
uint32_t host_port_select = host_instruction_port_select(port);
|
||||
uint32_t destination_ap = ap_port_select(port) | ap::de::expansion_device | lm;
|
||||
@ -148,20 +140,19 @@ void send_extension_device_request(maple::host_command_writer& writer, uint8_t p
|
||||
false); // end_flag
|
||||
}
|
||||
|
||||
typedef void (* func_t)(maple::host_command_writer& writer, uint8_t port, uint8_t lm);
|
||||
void do_lm_requests(maple::host_command_writer& writer, uint8_t port, uint8_t lm, func_t func)
|
||||
typedef void (* func_t)(maple::host_command_writer<>& writer, uint8_t port, uint8_t lm);
|
||||
void do_lm_requests(maple::host_command_writer<>& writer, uint8_t port, uint8_t lm, func_t func)
|
||||
{
|
||||
uint32_t bit = ap::lm_bus::_0;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
if (lm & bit) {
|
||||
lm &= ~bit;
|
||||
func(writer, port, bit);
|
||||
}
|
||||
bit <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
void recv_device_status(struct maple_display_poll_state &state)
|
||||
void recv_device_status(struct serial_load::maple_poll_state &state)
|
||||
{
|
||||
auto writer = maple::host_command_writer(send_buf, recv_buf);
|
||||
|
||||
@ -170,13 +161,17 @@ void recv_device_status(struct maple_display_poll_state &state)
|
||||
|
||||
for (int port = 0; port < 4; port++) {
|
||||
auto& bus_data = host_response[port].bus_data;
|
||||
auto& data_fields = bus_data.data_fields;
|
||||
if (bus_data.command_code != maple::device_status::command_code) {
|
||||
state.port[port].ap__lm = 0;
|
||||
state.port[port].device_id.ft = 0;
|
||||
} else {
|
||||
//auto& data_fields = bus_data.data_fields;
|
||||
|
||||
uint8_t lm = bus_data.source_ap & ap::lm_bus::bit_mask;
|
||||
state.port[port].ap__lm = lm;
|
||||
state.port[port].device_id.ft = std::byteswap(data_fields.device_id.ft);
|
||||
state.port[port].device_id.fd[0] = std::byteswap(data_fields.device_id.fd[0]);
|
||||
state.port[port].device_id.fd[1] = std::byteswap(data_fields.device_id.fd[1]);
|
||||
state.port[port].device_id.fd[2] = std::byteswap(data_fields.device_id.fd[2]);
|
||||
do_lm_requests(writer, port, lm, &send_extension_device_request);
|
||||
}
|
||||
}
|
||||
@ -198,11 +193,26 @@ void send_device_request()
|
||||
recv_buf, writer.recv_offset);
|
||||
}
|
||||
|
||||
void handle_maple(struct maple_display_poll_state& state)
|
||||
void send_raw(struct serial_load::maple_poll_state& state)
|
||||
{
|
||||
maple::dma_start(&__send_buf, state.send_length,
|
||||
&__recv_buf, state.recv_length);
|
||||
/*
|
||||
maple::dma_start((uint32_t*)0xac000020, state.send_length,
|
||||
(uint32_t*)0xac002020, state.recv_length);
|
||||
*/
|
||||
}
|
||||
|
||||
void handle_maple(struct serial_load::maple_poll_state& state)
|
||||
{
|
||||
using namespace serial_load;
|
||||
|
||||
switch (state.step) {
|
||||
case step::IDLE:
|
||||
if (state.want_start) {
|
||||
if (state.want_raw) {
|
||||
send_raw(state);
|
||||
state.step = step::RAW;
|
||||
} else if (state.want_start) {
|
||||
// always send to all ports
|
||||
send_device_request();
|
||||
state.step = step::DEVICE_STATUS;
|
||||
@ -212,20 +222,25 @@ void handle_maple(struct maple_display_poll_state& state)
|
||||
case step::DEVICE_STATUS:
|
||||
if (maple::dma_poll_complete()) {
|
||||
recv_device_status(state);
|
||||
state.step = step::EXTENSION_DEVICE_STATUS;
|
||||
state.step = step::EXTENSION__DEVICE_STATUS;
|
||||
}
|
||||
break;
|
||||
case step::EXTENSION_DEVICE_STATUS:
|
||||
case step::EXTENSION__DEVICE_STATUS:
|
||||
if (maple::dma_poll_complete()) {
|
||||
recv_extension_device_status(state);
|
||||
state.step = step::EXTENSION_DEVICE_REPLY;
|
||||
state.step = step::EXTENSION__DEVICE_STATUS__DEVICE_REPLY;
|
||||
}
|
||||
break;
|
||||
case step::EXTENSION_DEVICE_REPLY:
|
||||
case step::EXTENSION__DEVICE_STATUS__DEVICE_REPLY:
|
||||
if (maple::dma_poll_complete()) {
|
||||
state.step = step::IDLE;
|
||||
}
|
||||
break;
|
||||
case step::RAW:
|
||||
if (maple::dma_poll_complete()) {
|
||||
state.want_raw = 0;
|
||||
state.step = step::IDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,13 +296,16 @@ void render_u8(uint32_t src, char * dst)
|
||||
for (int i = 0; i < 2; i++) dst[i] = num_buf[i];
|
||||
}
|
||||
|
||||
static int count = 0;
|
||||
|
||||
void render_idle_state(char * dst)
|
||||
{
|
||||
render_line("idle", &dst[0]);
|
||||
render_line("idle3", &dst[0]);
|
||||
|
||||
render_u32(serial_load::state.buf.u32[0], &dst[8]);
|
||||
render_u32(serial_load::state.buf.u32[1], &dst[16]);
|
||||
render_u8(serial_load::state.len, &dst[24]);
|
||||
render_clear(&dst[26], 6);
|
||||
render_u8(serial_load::state.len, &dst[16]);
|
||||
render_clear(&dst[18], 6);
|
||||
render_u32(count++, &dst[24]);
|
||||
}
|
||||
|
||||
void render_write_state(char * dst)
|
||||
@ -295,7 +313,7 @@ void render_write_state(char * dst)
|
||||
render_line("write", &dst[0]);
|
||||
render_u32(sh7091.DMAC.DMATCR1, &dst[8]);
|
||||
render_u32(sh7091.DMAC.DAR1, &dst[16]);
|
||||
render_u32(serial_load::state.write_crc.value, &dst[24]);
|
||||
render_u32(serial_load::state.reply_crc.value, &dst[24]);
|
||||
}
|
||||
|
||||
void render_read_state(char * dst)
|
||||
@ -303,7 +321,7 @@ void render_read_state(char * dst)
|
||||
render_line("read", &dst[0]);
|
||||
render_u32(sh7091.DMAC.DMATCR1, &dst[8]);
|
||||
render_u32(sh7091.DMAC.SAR1, &dst[16]);
|
||||
render_u32(serial_load::state.read_crc.value, &dst[24]);
|
||||
render_u32(serial_load::state.reply_crc.value, &dst[24]);
|
||||
}
|
||||
|
||||
void render_fsm_state(char * dst)
|
||||
@ -327,8 +345,25 @@ void render_fsm_state(char * dst)
|
||||
render_line("speed", &dst[0]);
|
||||
render_clear(&dst[8], 24);
|
||||
break;
|
||||
case fsm_state::maple_raw__command:
|
||||
render_line("mr__cmd", &dst[0]);
|
||||
render_u32(sh7091.DMAC.DAR1, &dst[8]);
|
||||
render_u32(sh7091.DMAC.SAR1, &dst[16]);
|
||||
render_clear(&dst[24], 8);
|
||||
break;
|
||||
case fsm_state::maple_raw__maple_dma:
|
||||
render_line("mr__dma", &dst[0]);
|
||||
render_u32(poll_state.send_length, &dst[8]);
|
||||
render_u32(poll_state.recv_length, &dst[16]);
|
||||
render_u8(poll_state.want_raw, &dst[24]);
|
||||
render_clear(&dst[26], 6);
|
||||
break;
|
||||
case fsm_state::maple_raw__response:
|
||||
render_line("mr__resp", &dst[0]);
|
||||
render_clear(&dst[8], 24);
|
||||
break;
|
||||
default:
|
||||
render_line("invalid", &dst[0]);
|
||||
render_line("unknown", &dst[0]);
|
||||
render_clear(&dst[8], 24);
|
||||
break;
|
||||
}
|
||||
@ -362,10 +397,13 @@ void main() __attribute__((section(".text.main")));
|
||||
|
||||
void main()
|
||||
{
|
||||
poll_state.want_start = 0;
|
||||
poll_state.want_raw = 0;
|
||||
poll_state.step = serial_load::step::IDLE;
|
||||
|
||||
constexpr uint32_t serial_speed = 0;
|
||||
serial_load::init(serial_speed);
|
||||
|
||||
struct maple_display_poll_state state = {0};
|
||||
const uint8_t * font = reinterpret_cast<const uint8_t *>(&_binary_font_portfolio_6x8);
|
||||
auto renderer0 = maple::display::font_renderer(font);
|
||||
framebuffer[0] = renderer0.fb;
|
||||
@ -384,6 +422,13 @@ void main()
|
||||
error_counter.dr = 0;
|
||||
error_counter.orer = 0;
|
||||
|
||||
/*
|
||||
const uint8_t m[] = {0xe0, 0x22, 0x24, 0xb6, 0x30, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xa5, 0xce, 0x18, 0xda};
|
||||
for (uint32_t i = 0; i < (sizeof (m)); i++) {
|
||||
serial_load::recv(state, m[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
while (1) {
|
||||
using namespace scif;
|
||||
|
||||
@ -411,16 +456,16 @@ void main()
|
||||
if (serial_load::state.fsm_state == serial_load::fsm_state::idle) {
|
||||
while (sh7091.SCIF.SCFSR2 & scfsr2::rdf::bit_mask) {
|
||||
const uint8_t c = sh7091.SCIF.SCFRDR2;
|
||||
serial_load::recv(c);
|
||||
serial_load::recv(poll_state, c);
|
||||
sh7091.SCIF.SCFSR2 = scfsr2 & ~scfsr2::rdf::bit_mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
serial_load::tick();
|
||||
serial_load::tick(poll_state);
|
||||
render(renderer0, renderer1);
|
||||
|
||||
state.want_start = 1;
|
||||
handle_maple(state);
|
||||
poll_state.want_start = 1;
|
||||
handle_maple(poll_state);
|
||||
}
|
||||
}
|
||||
|
7
ip.lds
7
ip.lds
@ -71,8 +71,8 @@ SECTIONS
|
||||
|
||||
INCLUDE "debug.lds"
|
||||
}
|
||||
__stack_reservation = 0x1000;
|
||||
__stack_end = ORIGIN(p1ram) + LENGTH(p1ram) - __stack_reservation;
|
||||
|
||||
__stack_end = ORIGIN(p1ram) + LENGTH(p1ram);
|
||||
|
||||
__text_link_start = 0;
|
||||
__text_link_end = 0;
|
||||
@ -97,3 +97,6 @@ __vbr_link_end = 0;
|
||||
__vbr_load_end = 0;
|
||||
|
||||
INCLUDE "addresses.lds"
|
||||
|
||||
__send_buf = 0xac000020;
|
||||
__recv_buf = 0xac002020;
|
||||
|
@ -3,7 +3,7 @@ MEMORY
|
||||
{
|
||||
p1ram : ORIGIN = 0xac005000, LENGTH = 0x0000
|
||||
p2ram : ORIGIN = 0xac010000, LENGTH = 0xff0000
|
||||
ldram : ORIGIN = 0xacffd000, LENGTH = 0x3000
|
||||
ldram : ORIGIN = 0xacffd000, LENGTH = 0x4000
|
||||
}
|
||||
SECTIONS
|
||||
{
|
||||
@ -72,4 +72,7 @@ SECTIONS
|
||||
INCLUDE "symbols.lds"
|
||||
INCLUDE "addresses.lds"
|
||||
|
||||
__stack_end = 0x8c008000;
|
||||
__stack_end = 0x8c00f000;
|
||||
|
||||
__send_buf = 0xac000020;
|
||||
__recv_buf = 0xac002020;
|
||||
|
2
main.lds
2
main.lds
@ -7,4 +7,4 @@ MEMORY
|
||||
|
||||
INCLUDE "common.lds"
|
||||
|
||||
__stack_end = ORIGIN(p1ram) + LENGTH(p1ram) - 0x3000;
|
||||
__stack_end = ORIGIN(p1ram) + LENGTH(p1ram) - 0x4000;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <tuple>
|
||||
|
||||
#include "maple/maple.hpp"
|
||||
@ -9,6 +10,7 @@
|
||||
|
||||
namespace maple {
|
||||
|
||||
template <uint32_t base_address = 0>
|
||||
struct host_command_writer {
|
||||
uint32_t * const send_buf;
|
||||
uint32_t * const recv_buf;
|
||||
@ -43,7 +45,13 @@ struct host_command_writer {
|
||||
| (host_port_select & host_instruction::port_select::bit_mask)
|
||||
| host_instruction::transfer_length(data_size / 4);
|
||||
|
||||
host_command->receive_data_storage_address = receive_data_storage_address::address(reinterpret_cast<uint32_t>(host_response));
|
||||
uint32_t host_response_address;
|
||||
if constexpr (base_address != 0) {
|
||||
host_response_address = base_address + recv_offset;
|
||||
} else {
|
||||
host_response_address = reinterpret_cast<uint32_t>(host_response);
|
||||
}
|
||||
host_command->receive_data_storage_address = receive_data_storage_address::address(host_response_address);
|
||||
|
||||
host_command->bus_data.command_code = C::command_code;
|
||||
host_command->bus_data.destination_ap = destination_ap;
|
||||
|
@ -23,3 +23,15 @@ constexpr inline uint32_t host_instruction_port_select(const uint32_t port)
|
||||
case 3: return host_instruction::port_select::d;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline uint32_t ap_lm_bus(const uint32_t lm)
|
||||
{
|
||||
switch (lm) {
|
||||
default: [[fallthrough]];
|
||||
case 0: return ap::lm_bus::_0;
|
||||
case 1: return ap::lm_bus::_1;
|
||||
case 2: return ap::lm_bus::_2;
|
||||
case 3: return ap::lm_bus::_3;
|
||||
case 4: return ap::lm_bus::_4;
|
||||
}
|
||||
}
|
||||
|
180
serial_load.cpp
180
serial_load.cpp
@ -51,33 +51,106 @@ void jump_to_func(const uint32_t addr)
|
||||
// restore our stack
|
||||
}
|
||||
|
||||
static inline void prestart_write()
|
||||
static void prestart_write()
|
||||
{
|
||||
uint32_t dest = state.buf.arg[0];
|
||||
uint32_t size = state.buf.arg[1];
|
||||
serial::recv_dma(dest - 1, size + 1);
|
||||
state.write_crc.value = 0xffffffff;
|
||||
state.write_crc.offset = dest;
|
||||
state.reply_crc.value = 0xffffffff;
|
||||
state.reply_crc.offset = dest;
|
||||
}
|
||||
|
||||
static inline void prestart_read()
|
||||
static void poststart_read()
|
||||
{
|
||||
uint32_t src = state.buf.arg[0];
|
||||
uint32_t size = state.buf.arg[1];
|
||||
serial::send_dma(src, size);
|
||||
state.read_crc.value = 0xffffffff;
|
||||
state.read_crc.offset = src;
|
||||
state.reply_crc.value = 0xffffffff;
|
||||
state.reply_crc.offset = src;
|
||||
}
|
||||
|
||||
static void prestart_maple_raw__command()
|
||||
{
|
||||
uint32_t dest = reinterpret_cast<uint32_t>(&__send_buf);
|
||||
//uint32_t dest = 0xac000020;
|
||||
uint32_t size = state.buf.arg[0];
|
||||
serial::recv_dma(dest - 1, size + 1);
|
||||
state.reply_crc.value = 0xffffffff;
|
||||
state.reply_crc.offset = dest;
|
||||
}
|
||||
|
||||
static void prestart_maple_raw__response()
|
||||
{
|
||||
uint32_t src = reinterpret_cast<uint32_t>(&__recv_buf);
|
||||
//uint32_t src = 0xac002020;
|
||||
uint32_t size = state.buf.arg[1];
|
||||
serial::send_dma(src, size);
|
||||
state.reply_crc.value = 0xffffffff;
|
||||
state.reply_crc.offset = src;
|
||||
}
|
||||
|
||||
/*
|
||||
static reply::maple_list_entry maple_list[4 + 4 * 5];
|
||||
|
||||
static void prestart_maple_list(struct maple_port * port)
|
||||
{
|
||||
uint32_t function_type = state.buf.arg[0];
|
||||
uint32_t list_ix = 0;
|
||||
|
||||
for (int port_ix = 0; port_ix < 4; port_ix++) {
|
||||
|
||||
if ((port[port_ix].device_id.ft & function_type) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
maple_list[list_ix].port = port_ix;
|
||||
maple_list[list_ix].lm = 0;
|
||||
maple_list[list_ix]._res = 0;
|
||||
maple_list[list_ix].device_id.ft = port[port_ix].device_id.ft;
|
||||
maple_list[list_ix].device_id.fd[0] = port[port_ix].device_id.fd[0];
|
||||
maple_list[list_ix].device_id.fd[1] = port[port_ix].device_id.fd[1];
|
||||
maple_list[list_ix].device_id.fd[2] = port[port_ix].device_id.fd[2];
|
||||
list_ix++;
|
||||
|
||||
int bit = 1;
|
||||
for (int lm_ix = 0; lm_ix < 5; lm_ix++) {
|
||||
if ((port[port_ix].ap__lm & bit) != 0) {
|
||||
maple_list[list_ix].port = port_ix;
|
||||
maple_list[list_ix].lm = bit;
|
||||
maple_list[list_ix]._res = 0;
|
||||
maple_list[list_ix].device_id.ft = port[port_ix].lm[lm_ix].device_id.ft;
|
||||
maple_list[list_ix].device_id.fd[0] = port[port_ix].lm[lm_ix].device_id.fd[0];
|
||||
maple_list[list_ix].device_id.fd[1] = port[port_ix].lm[lm_ix].device_id.fd[1];
|
||||
maple_list[list_ix].device_id.fd[2] = port[port_ix].lm[lm_ix].device_id.fd[2];
|
||||
list_ix++;
|
||||
}
|
||||
bit <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
state.buf.arg[1] = list_ix * (sizeof (struct reply::maple_list_entry));
|
||||
}
|
||||
|
||||
static void poststart_maple_list()
|
||||
{
|
||||
uint32_t src = reinterpret_cast<uint32_t>(maple_list);
|
||||
uint32_t size = state.buf.arg[1];
|
||||
serial::send_dma(src, size);
|
||||
state.reply_crc.value = 0xffffffff;
|
||||
state.reply_crc.offset = src;
|
||||
}
|
||||
*/
|
||||
|
||||
struct state_arglen_reply command_list[] = {
|
||||
{command::_write, reply::_write, fsm_state::write},
|
||||
{command::_read , reply::_read , fsm_state::read },
|
||||
{command::_jump , reply::_jump , fsm_state::jump },
|
||||
{command::_speed, reply::_speed, fsm_state::speed},
|
||||
{command::_write , reply::_write , fsm_state::write },
|
||||
{command::_read , reply::_read , fsm_state::read },
|
||||
{command::_jump , reply::_jump , fsm_state::jump },
|
||||
{command::_speed , reply::_speed , fsm_state::speed },
|
||||
{command::_maple_raw , reply::_maple_raw , fsm_state::maple_raw__command },
|
||||
};
|
||||
constexpr uint32_t command_list_length = (sizeof (command_list)) / (sizeof (command_list[0]));
|
||||
|
||||
void recv(uint8_t c)
|
||||
void recv(struct maple_poll_state& poll_state, uint8_t c)
|
||||
{
|
||||
state.buf.u8[state.len++] = c;
|
||||
switch (state.fsm_state) {
|
||||
@ -90,12 +163,13 @@ void recv(uint8_t c)
|
||||
if (crc == state.buf.crc) {
|
||||
// valid command, do the transition
|
||||
if (state.buf.cmd == command::_write) prestart_write();
|
||||
if (state.buf.cmd == command::_maple_raw) prestart_maple_raw__command();
|
||||
state.fsm_state = sar.fsm_state;
|
||||
state.len = 0;
|
||||
union command_reply reply = command_reply(sar.reply, state.buf.arg[0], state.buf.arg[1]);
|
||||
union command_reply reply = command_reply(sar.reply, state.buf.arg[0], state.buf.arg[1]);
|
||||
serial::string(reply.u8, 16);
|
||||
|
||||
if (state.buf.cmd == command::_read) prestart_read();
|
||||
if (state.buf.cmd == command::_read) poststart_read();
|
||||
return;
|
||||
} else {
|
||||
// do nothing
|
||||
@ -112,25 +186,66 @@ void recv(uint8_t c)
|
||||
}
|
||||
}
|
||||
|
||||
void tick()
|
||||
void tick(struct maple_poll_state& poll_state)
|
||||
{
|
||||
switch (state.fsm_state) {
|
||||
case fsm_state::idle:
|
||||
break;
|
||||
case fsm_state::maple_raw__command: [[fallthrough]];
|
||||
case fsm_state::write:
|
||||
{
|
||||
// read chcr1 before dar1 to avoid race
|
||||
uint32_t chcr1 = sh7091.DMAC.CHCR1;
|
||||
uint32_t dar1 = sh7091.DMAC.DAR1;
|
||||
if (dar1 > state.write_crc.offset) {
|
||||
uint32_t len = dar1 - state.write_crc.offset;
|
||||
const uint8_t * buf = reinterpret_cast<const uint8_t *>(state.write_crc.offset);
|
||||
state.write_crc.value = crc32_update(state.write_crc.value, buf, len);
|
||||
state.write_crc.offset += len;
|
||||
if (dar1 > state.reply_crc.offset) {
|
||||
uint32_t len = dar1 - state.reply_crc.offset;
|
||||
const uint8_t * buf = reinterpret_cast<const uint8_t *>(state.reply_crc.offset);
|
||||
state.reply_crc.value = crc32_update(state.reply_crc.value, buf, len);
|
||||
state.reply_crc.offset += len;
|
||||
}
|
||||
if (chcr1 & dmac::chcr::te::transfers_completed) {
|
||||
state.write_crc.value ^= 0xffffffff;
|
||||
union command_reply reply = reply::write_crc(state.write_crc.value);
|
||||
state.reply_crc.value ^= 0xffffffff;
|
||||
union command_reply reply = reply::crc(state.reply_crc.value);
|
||||
serial::string(reply.u8, 16);
|
||||
|
||||
sh7091.DMAC.CHCR1 = 0;
|
||||
|
||||
// transition to next state
|
||||
if (state.fsm_state == fsm_state::maple_raw__command) {
|
||||
poll_state.send_length = state.buf.arg[0];
|
||||
poll_state.recv_length = state.buf.arg[1];
|
||||
poll_state.want_raw = 1;
|
||||
state.fsm_state = fsm_state::maple_raw__maple_dma;
|
||||
} else
|
||||
state.fsm_state = fsm_state::idle;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case fsm_state::maple_raw__maple_dma:
|
||||
{
|
||||
// transition to next state
|
||||
if (poll_state.want_raw == 0) {
|
||||
prestart_maple_raw__response();
|
||||
state.fsm_state = fsm_state::maple_raw__response;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case fsm_state::maple_raw__response: [[fallthrough]];
|
||||
case fsm_state::read:
|
||||
{
|
||||
// read chcr1 before sar1 to avoid race
|
||||
uint32_t chcr1 = sh7091.DMAC.CHCR1;
|
||||
uint32_t sar1 = sh7091.DMAC.SAR1;
|
||||
if (sar1 > state.reply_crc.offset) {
|
||||
uint32_t len = sar1 - state.reply_crc.offset;
|
||||
const uint8_t * buf = reinterpret_cast<const uint8_t *>(state.reply_crc.offset);
|
||||
state.reply_crc.value = crc32_update(state.reply_crc.value, buf, len);
|
||||
state.reply_crc.offset += len;
|
||||
}
|
||||
|
||||
if (chcr1 & dmac::chcr::te::transfers_completed) {
|
||||
state.reply_crc.value ^= 0xffffffff;
|
||||
union command_reply reply = reply::crc(state.reply_crc.value);
|
||||
serial::string(reply.u8, 16);
|
||||
|
||||
sh7091.DMAC.CHCR1 = 0;
|
||||
@ -140,29 +255,6 @@ void tick()
|
||||
}
|
||||
}
|
||||
break;
|
||||
case fsm_state::read:
|
||||
{
|
||||
uint32_t chcr1 = sh7091.DMAC.CHCR1;
|
||||
uint32_t sar1 = sh7091.DMAC.SAR1;
|
||||
if (sar1 > state.read_crc.offset) {
|
||||
uint32_t len = sar1 - state.read_crc.offset;
|
||||
const uint8_t * buf = reinterpret_cast<const uint8_t *>(state.read_crc.offset);
|
||||
state.read_crc.value = crc32_update(state.read_crc.value, buf, len);
|
||||
state.read_crc.offset += len;
|
||||
}
|
||||
|
||||
if (chcr1 & dmac::chcr::te::transfers_completed) {
|
||||
state.read_crc.value ^= 0xffffffff;
|
||||
union command_reply reply = reply::read_crc(state.read_crc.value);
|
||||
serial::string(reply.u8, 16);
|
||||
|
||||
sh7091.DMAC.CHCR1 = 0;
|
||||
|
||||
// transition to next state
|
||||
//state.fsm_state = fsm_state::idle;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case fsm_state::jump:
|
||||
{
|
||||
using namespace scif;
|
||||
|
@ -2,13 +2,14 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "maple/maple_bus_commands.hpp"
|
||||
#include "serial_protocol.hpp"
|
||||
|
||||
namespace serial_load {
|
||||
|
||||
void init(uint32_t speed);
|
||||
void recv(uint8_t c);
|
||||
void tick();
|
||||
void recv(struct maple_poll_state& poll_state, uint8_t c);
|
||||
void tick(struct maple_poll_state& poll_state);
|
||||
|
||||
enum struct fsm_state {
|
||||
idle,
|
||||
@ -16,6 +17,9 @@ enum struct fsm_state {
|
||||
read,
|
||||
jump,
|
||||
speed,
|
||||
maple_raw__command,
|
||||
maple_raw__maple_dma,
|
||||
maple_raw__response,
|
||||
};
|
||||
|
||||
struct state_arglen_reply {
|
||||
@ -33,11 +37,47 @@ struct state {
|
||||
union command_reply buf;
|
||||
uint32_t len;
|
||||
enum fsm_state fsm_state;
|
||||
struct incremental_crc write_crc;
|
||||
struct incremental_crc read_crc;
|
||||
struct incremental_crc reply_crc;
|
||||
uint32_t speed;
|
||||
};
|
||||
|
||||
extern struct state state;
|
||||
|
||||
struct lm {
|
||||
struct maple::device_id device_id;
|
||||
};
|
||||
|
||||
struct maple_port {
|
||||
struct maple::device_id device_id;
|
||||
uint8_t ap__lm;
|
||||
struct lm lm[5];
|
||||
};
|
||||
|
||||
enum struct step {
|
||||
IDLE = 0,
|
||||
DEVICE_STATUS,
|
||||
EXTENSION__DEVICE_STATUS,
|
||||
EXTENSION__DEVICE_STATUS__DEVICE_REPLY,
|
||||
RAW,
|
||||
};
|
||||
|
||||
struct maple_command_parameters {
|
||||
uint8_t port;
|
||||
uint8_t lm;
|
||||
};
|
||||
|
||||
struct maple_poll_state {
|
||||
uint32_t send_length;
|
||||
uint32_t recv_length;
|
||||
|
||||
bool want_start;
|
||||
bool want_raw;
|
||||
enum step step;
|
||||
struct serial_load::maple_port port[4];
|
||||
struct maple_command_parameters command_parameters;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
extern "C" uint32_t __send_buf __asm("__send_buf");
|
||||
extern "C" uint32_t __recv_buf __asm("__recv_buf");
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "maple/maple_bus_commands.hpp"
|
||||
|
||||
#include "crc32.h"
|
||||
|
||||
namespace serial_load {
|
||||
@ -56,13 +58,15 @@ namespace command {
|
||||
constexpr uint32_t _jump = gen_cmd("JUMP");
|
||||
constexpr uint32_t _speed = gen_cmd("SPED");
|
||||
|
||||
constexpr uint32_t _maple_list = gen_cmd("MPLS");
|
||||
constexpr uint32_t _maple_raw = gen_cmd("MPRW");
|
||||
|
||||
static_assert(_write == 0x2cc46ed8);
|
||||
static_assert(_read == 0xf18d57c7);
|
||||
static_assert(_jump == 0xa6696f38);
|
||||
static_assert(_read == 0xf18d57c7);
|
||||
static_assert(_jump == 0xa6696f38);
|
||||
static_assert(_speed == 0x27a7a9f4);
|
||||
|
||||
static_assert(_maple_raw == 0xb62422e0);
|
||||
|
||||
constexpr union command_reply write(uint32_t dest, uint32_t size)
|
||||
{
|
||||
return command_reply(_write, dest, size);
|
||||
@ -83,9 +87,9 @@ namespace command {
|
||||
return command_reply(_speed, speed, 0);
|
||||
}
|
||||
|
||||
constexpr union command_reply maple_list(uint32_t function_type)
|
||||
constexpr union command_reply maple_raw(uint32_t send_size, uint32_t recv_size)
|
||||
{
|
||||
return command_reply(_maple_list, function_type, 0);
|
||||
return command_reply(_maple_raw, send_size, recv_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,18 +98,19 @@ namespace reply {
|
||||
constexpr uint32_t _read = gen_cmd("read");
|
||||
constexpr uint32_t _jump = gen_cmd("jump");
|
||||
constexpr uint32_t _speed = gen_cmd("sped");
|
||||
constexpr uint32_t _write_crc = gen_cmd("crcw");
|
||||
constexpr uint32_t _read_crc = gen_cmd("crcr");
|
||||
|
||||
constexpr uint32_t _maple_list = gen_cmd("mpls");
|
||||
constexpr uint32_t _maple_list_crc = gen_cmd("mlcs");
|
||||
constexpr uint32_t _maple_raw = gen_cmd("mprw");
|
||||
|
||||
constexpr uint32_t _crc = gen_cmd("rcrc");
|
||||
|
||||
static_assert(_write == 0x8c661aaa);
|
||||
static_assert(_read == 0x512f23b5);
|
||||
static_assert(_jump == 0x06cb1b4a);
|
||||
static_assert(_speed == 0x8705dd86);
|
||||
static_assert(_write_crc == 0x3cccc074);
|
||||
static_assert(_read_crc == 0x99cc92f4);
|
||||
|
||||
static_assert(_maple_raw == 0x16865692);
|
||||
|
||||
static_assert(_crc == 0xcc9aab7c);
|
||||
|
||||
constexpr union command_reply write(uint32_t dest, uint32_t size)
|
||||
{
|
||||
@ -127,14 +132,14 @@ namespace reply {
|
||||
return command_reply(_speed, speed, 0);
|
||||
}
|
||||
|
||||
constexpr union command_reply write_crc(uint32_t crc)
|
||||
constexpr union command_reply crc(uint32_t crc)
|
||||
{
|
||||
return command_reply(_write_crc, crc, 0);
|
||||
return command_reply(_crc, crc, 0);
|
||||
}
|
||||
|
||||
constexpr union command_reply read_crc(uint32_t crc)
|
||||
constexpr union command_reply maple_raw(uint32_t send_size, uint32_t recv_size)
|
||||
{
|
||||
return command_reply(_read_crc, crc, 0);
|
||||
return command_reply(_maple_raw, send_size, recv_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +99,8 @@ void string(const char * s)
|
||||
void string(const uint8_t * s, uint32_t len)
|
||||
{
|
||||
while (len > 0) {
|
||||
//hexlify(*s++);
|
||||
//character(' ');
|
||||
character(*s++);
|
||||
len--;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ commands = [
|
||||
"SPED",
|
||||
|
||||
"MPLS",
|
||||
"MPRW",
|
||||
]
|
||||
|
||||
replies = [
|
||||
@ -26,11 +27,11 @@ replies = [
|
||||
"read",
|
||||
"jump",
|
||||
"sped",
|
||||
"crcw",
|
||||
"crcr",
|
||||
|
||||
"mpls",
|
||||
"mlcs",
|
||||
"mprw",
|
||||
|
||||
"rcrc"
|
||||
]
|
||||
|
||||
seen = set()
|
||||
|
@ -15,6 +15,11 @@
|
||||
#include "crc32.h"
|
||||
#include "serial_protocol.hpp"
|
||||
|
||||
#include "maple/maple_bus_bits.hpp"
|
||||
#include "maple/maple.hpp"
|
||||
#include "maple/maple_host_command_writer.hpp"
|
||||
#include "maple/maple_bus_commands.hpp"
|
||||
|
||||
extern "C" int convert_baudrate_UT_export(int baudrate, struct ftdi_context *ftdi,
|
||||
unsigned short *value, unsigned short *index);
|
||||
|
||||
@ -190,6 +195,10 @@ void dump_command_reply(union serial_load::command_reply& cr)
|
||||
for (uint32_t i = 0; i < (sizeof (union serial_load::command_reply)) / (sizeof (uint32_t)); i++) {
|
||||
fprintf(stderr, " %08x\n", serial_load::le_bswap(cr.u32[i]));
|
||||
}
|
||||
for (uint32_t i = 0; i < (sizeof (union serial_load::command_reply)); i++) {
|
||||
fprintf(stderr, "%02x ", cr.u8[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
int read_reply(struct ftdi_context * ftdi, uint32_t expected_cmd, union serial_load::command_reply& reply)
|
||||
@ -200,7 +209,7 @@ int read_reply(struct ftdi_context * ftdi, uint32_t expected_cmd, union serial_l
|
||||
|
||||
long length = read_with_timeout(ftdi, reply.u8, read_length);
|
||||
if (length != read_length) {
|
||||
fprintf(stderr, "short read; want %ld bytes; received: %ld\n", read_length, length);
|
||||
fprintf(stderr, "read_reply: short read; want %ld bytes; received: %ld\n", read_length, length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -273,7 +282,7 @@ int do_write(struct ftdi_context * ftdi, const uint32_t dest, const uint8_t * bu
|
||||
uint32_t buf_crc = crc32(buf, size);
|
||||
|
||||
union serial_load::command_reply crc_reply;
|
||||
res = read_reply(ftdi, serial_load::reply::_write_crc, crc_reply);
|
||||
res = read_reply(ftdi, serial_load::reply::_crc, crc_reply);
|
||||
clock_res = clock_gettime(CLOCK_MONOTONIC, &end2);
|
||||
assert(clock_res == 0);
|
||||
if (res != 0) {
|
||||
@ -300,6 +309,10 @@ int do_write(struct ftdi_context * ftdi, const uint32_t dest, const uint8_t * bu
|
||||
fprintf(stderr, " idealized write time : %.03f seconds\n", idealized_time);
|
||||
fprintf(stderr, " measured write time : %.03f seconds\n", measured_time2);
|
||||
|
||||
if (crc_reply.arg[0] != buf_crc) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -471,22 +484,25 @@ int do_read(struct ftdi_context * ftdi, const uint32_t src, uint8_t * buf, const
|
||||
|
||||
uint32_t read_length = 0;
|
||||
while (read_length < size) {
|
||||
res = ftdi_read_data(ftdi, (uint8_t *)buf, size - read_length);
|
||||
res = ftdi_read_data(ftdi, (uint8_t *)&buf[read_length], size - read_length);
|
||||
assert(res >= 0);
|
||||
read_length += res;
|
||||
if (read_length < size)
|
||||
fprintf(stderr, "short read; want %x out of %x\n", size - read_length, size);
|
||||
fprintf(stderr, "read: short read; want %x out of %x\n", size - read_length, size);
|
||||
}
|
||||
|
||||
uint32_t buf_crc = crc32((uint8_t*)buf, size);
|
||||
|
||||
union serial_load::command_reply crc_reply;
|
||||
res = read_reply(ftdi, serial_load::reply::_read_crc, crc_reply);
|
||||
res = read_reply(ftdi, serial_load::reply::_crc, crc_reply);
|
||||
if (res != 0) {
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "remote crc: %08x; local crc %08x\n", crc_reply.arg[0], buf_crc);
|
||||
|
||||
fprintf(stderr, "remote crc: %08x; local crc %08x\n", crc_reply.arg[0], buf_crc);
|
||||
if (crc_reply.arg[0] != buf_crc) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -562,6 +578,214 @@ void do_console(struct ftdi_context * ftdi)
|
||||
}
|
||||
}
|
||||
|
||||
int lm_bit_to_int(uint8_t bit)
|
||||
{
|
||||
switch (bit) {
|
||||
case 0b00001:
|
||||
return 0;
|
||||
case 0b00010:
|
||||
return 1;
|
||||
case 0b00100:
|
||||
return 2;
|
||||
case 0b01000:
|
||||
return 3;
|
||||
case 0b10000:
|
||||
return 4;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int count_left_set_bits(uint32_t n, int stop_bit)
|
||||
{
|
||||
int bit_ix = 31;
|
||||
int count = 0;
|
||||
while (bit_ix != stop_bit) {
|
||||
if (n & (1 << 31)) {
|
||||
count += 1;
|
||||
}
|
||||
n <<= 1;
|
||||
bit_ix -= 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
static_assert(count_left_set_bits(0xe, 1) == 2);
|
||||
static_assert(count_left_set_bits(0x2, 1) == 0);
|
||||
|
||||
consteval int count_trailing_zeros(uint32_t n)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if ((n & 1) != 0)
|
||||
break;
|
||||
count += 1;
|
||||
n >>= 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
static_assert(count_trailing_zeros(0x80) == 7);
|
||||
static_assert(count_trailing_zeros(0x2) == 1);
|
||||
|
||||
void print_storage_function_definition(const uint32_t fd)
|
||||
{
|
||||
int partitions = ((fd >> 24) & 0xff) + 1;
|
||||
int bytes_per_block = (((fd >> 16) & 0xff) + 1) * 32;
|
||||
int write_accesses = (fd >> 12) & 0xf;
|
||||
int read_accesses = (fd >> 8) & 0xf;
|
||||
|
||||
fprintf(stderr, " storage function definition:\n");
|
||||
fprintf(stderr, " partitions: %d\n", partitions);
|
||||
fprintf(stderr, " bytes_per_block: %d\n", bytes_per_block);
|
||||
fprintf(stderr, " write_accesses: %d\n", write_accesses);
|
||||
fprintf(stderr, " read_accesses: %d\n", read_accesses);
|
||||
}
|
||||
|
||||
void print_device_id(struct maple::device_id& device_id)
|
||||
{
|
||||
fprintf(stderr, " ft: %08x\n", device_id.ft);
|
||||
fprintf(stderr, " fd[0]: %08x\n", device_id.fd[0]);
|
||||
fprintf(stderr, " fd[1]: %08x\n", device_id.fd[1]);
|
||||
fprintf(stderr, " fd[2]: %08x\n", device_id.fd[2]);
|
||||
|
||||
if (device_id.ft & function_type::storage) {
|
||||
int fd_ix = count_left_set_bits(device_id.ft, count_trailing_zeros(function_type::storage));
|
||||
print_storage_function_definition(device_id.fd[fd_ix]);
|
||||
}
|
||||
}
|
||||
|
||||
int do_maple_raw(struct ftdi_context * ftdi,
|
||||
uint8_t * send_buf,
|
||||
uint32_t send_size,
|
||||
uint8_t * recv_buf,
|
||||
uint32_t recv_size)
|
||||
{
|
||||
int res;
|
||||
|
||||
union serial_load::command_reply command = serial_load::command::maple_raw(send_size, recv_size);
|
||||
dump_command_reply(command);
|
||||
res = ftdi_write_data(ftdi, command.u8, (sizeof (command)));
|
||||
assert(res == (sizeof (command)));
|
||||
union serial_load::command_reply reply;
|
||||
fprintf(stderr, "maple_raw: wait maple_raw reply\n");
|
||||
res = read_reply(ftdi, serial_load::reply::_maple_raw, reply);
|
||||
if (res != 0) {
|
||||
return -2;
|
||||
}
|
||||
if (reply.arg[0] != command.arg[0] || reply.arg[1] != command.arg[1]) {
|
||||
fprintf(stderr, "maple_raw: argument mismatch: (%08x, %08x) != (%08x, %08x)\n",
|
||||
reply.arg[0], reply.arg[1],
|
||||
command.arg[0], command.arg[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
res = ftdi_write_data(ftdi, send_buf, send_size);
|
||||
assert(res >= 0);
|
||||
assert((uint32_t)res == send_size);
|
||||
|
||||
uint32_t send_buf_crc = crc32(send_buf, send_size);
|
||||
fprintf(stderr, "send_size: %d\n", send_size);
|
||||
for (uint32_t i = 0; i < send_size; i++) {
|
||||
fprintf(stderr, "%02x ", send_buf[i]);
|
||||
if (i % 4 == 3)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
union serial_load::command_reply send_crc_reply;
|
||||
fprintf(stderr, "maple_raw: send: wait crc reply\n");
|
||||
res = read_reply(ftdi, serial_load::reply::_crc, send_crc_reply);
|
||||
if (res != 0) {
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "maple_raw: send: remote crc: %08x; local crc %08x\n", send_crc_reply.arg[0], send_buf_crc);
|
||||
if (send_crc_reply.arg[0] != send_buf_crc) {
|
||||
dump_command_reply(send_crc_reply);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t read_length = 0;
|
||||
while (read_length < recv_size) {
|
||||
res = ftdi_read_data(ftdi, &recv_buf[read_length], recv_size - read_length);
|
||||
assert(res >= 0);
|
||||
read_length += res;
|
||||
if (read_length < recv_size)
|
||||
fprintf(stderr, "maple raw: short read; want %x out of %x\n", recv_size - read_length, recv_size);
|
||||
}
|
||||
|
||||
uint32_t recv_buf_crc = crc32(recv_buf, recv_size);
|
||||
|
||||
union serial_load::command_reply recv_crc_reply;
|
||||
fprintf(stderr, "maple_raw: recv: wait crc reply\n");
|
||||
res = read_reply(ftdi, serial_load::reply::_crc, recv_crc_reply);
|
||||
if (res != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "maple_raw: recv: remote crc: %08x; local crc %08x\n", recv_crc_reply.arg[0], recv_buf_crc);
|
||||
if (recv_crc_reply.arg[0] != recv_buf_crc) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_maple_list(struct ftdi_context * ftdi)
|
||||
{
|
||||
uint8_t send_buf[1024] = {0};
|
||||
uint8_t recv_buf[1024] = {0};
|
||||
|
||||
using command_type = maple::device_request;
|
||||
using response_type = maple::device_status;
|
||||
|
||||
auto writer = maple::host_command_writer<0xac002020>(reinterpret_cast<uint32_t *>(send_buf), reinterpret_cast<uint32_t *>(recv_buf));
|
||||
auto [host_command, host_response]
|
||||
= writer.append_command_all_ports<command_type, response_type>();
|
||||
|
||||
for (uint32_t i = 0; i < writer.send_offset; i++) {
|
||||
fprintf(stderr, "%02x ", send_buf[i]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
int res = do_maple_raw(ftdi,
|
||||
send_buf, writer.send_offset,
|
||||
recv_buf, writer.recv_offset);
|
||||
if (res != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < writer.recv_offset; i++) {
|
||||
fprintf(stderr, "%02x ", recv_buf[i]);
|
||||
if (i % 4 == 3)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "%d\n", response_type::command_code);
|
||||
fprintf(stderr, "%p\n", host_response);
|
||||
fprintf(stderr, "%p\n", recv_buf);
|
||||
|
||||
for (uint8_t port = 0; port < 4; port++) {
|
||||
auto& bus_data = host_response[port].bus_data;
|
||||
auto& data_fields = bus_data.data_fields;
|
||||
fprintf(stderr, "port: %d\n", port);
|
||||
if (bus_data.command_code != response_type::command_code) {
|
||||
fprintf(stderr, " disconnected %02x %02x %02x %02x\n",
|
||||
bus_data.command_code,
|
||||
bus_data.destination_ap,
|
||||
bus_data.source_ap,
|
||||
bus_data.data_size);
|
||||
} else {
|
||||
fprintf(stderr, " ft: %08x\n", std::byteswap(data_fields.device_id.ft));
|
||||
fprintf(stderr, " fd[0]: %08x\n", std::byteswap(data_fields.device_id.fd[0]));
|
||||
fprintf(stderr, " fd[1]: %08x\n", std::byteswap(data_fields.device_id.fd[1]));
|
||||
fprintf(stderr, " fd[2]: %08x\n", std::byteswap(data_fields.device_id.fd[2]));
|
||||
fprintf(stderr, " source_ap.lm_bus: %d\n", bus_data.source_ap & ap::lm_bus::bit_mask);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum struct argument_type {
|
||||
string,
|
||||
integer
|
||||
@ -581,6 +805,7 @@ struct cli_command commands[] = {
|
||||
{ "list_baudrates" , 1, (void *)&do_list_baudrates },
|
||||
{ "show_baudrate_error", 1, (void *)&do_show_baudrate_error },
|
||||
{ "console" , 0, (void *)&do_console },
|
||||
{ "maple_list" , 0, (void *)&do_maple_list },
|
||||
};
|
||||
|
||||
constexpr int commands_length = (sizeof (commands)) / (sizeof (commands[0]));
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
filename="$1"
|
||||
|
||||
if [ -z "$filename" ]; then
|
||||
@ -9,7 +11,7 @@ fi
|
||||
|
||||
set -ex
|
||||
|
||||
./ftdi_transfer \
|
||||
${SCRIPT_DIR}/ftdi_transfer \
|
||||
write 0xac010000 "$filename" \
|
||||
jump 0xac010000 \
|
||||
console
|
||||
jump 0xac010000
|
||||
# console
|
||||
|
Loading…
x
Reference in New Issue
Block a user