From 8fabbb008c1a31c809a3d97f22351f141a2bd02d Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Thu, 4 Aug 2016 17:06:11 +0100 Subject: hwstub: add support for coprocessor operations At the moment the stub only implement them for MIPS. Change-Id: Ica835a0e9c70fa5675c3d655eae986e812a47de8 --- utils/hwstub/lib/hwstub.cpp | 46 ++++++++++++++++++++++++++++++++ utils/hwstub/lib/hwstub_net.cpp | 12 +++++++++ utils/hwstub/lib/hwstub_usb.cpp | 52 +++++++++++++++++++++++++++++++++++++ utils/hwstub/lib/hwstub_virtual.cpp | 12 +++++++++ 4 files changed, 122 insertions(+) (limited to 'utils/hwstub/lib') diff --git a/utils/hwstub/lib/hwstub.cpp b/utils/hwstub/lib/hwstub.cpp index 9dd2915903..5e708c3bb8 100644 --- a/utils/hwstub/lib/hwstub.cpp +++ b/utils/hwstub/lib/hwstub.cpp @@ -45,6 +45,8 @@ std::string error_string(error err) case error::PROTOCOL_ERROR: return "network protocol error"; case error::TIMEOUT: return "timeout"; case error::OVERFLW: return "overflow"; + case error::UNIMPLEMENTED: return "operation is not implemented"; + case error::UNSUPPORTED: return "operation unsupported"; default: return "unknown error"; } } @@ -457,6 +459,38 @@ error handle::write(uint32_t addr, const void *buf, size_t& sz, bool atomic) return error::SUCCESS; } +error handle::cop_op(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], const void *out_data, + size_t out_size, void *in_data, size_t *in_size) +{ + std::unique_lock lock(m_mutex); + /* get a pointer so that it's not destroyed during the runtime of the function, + * the pointer will be released at the end of the function */ + std::shared_ptr ctx = m_dev->get_context(); + if(!ctx) + return error::NO_CONTEXT; + /* ensure valid status */ + error err = status(); + if(err != error::SUCCESS) + return err; + return cop_dev(op, args, out_data, out_size, in_data, in_size); +} + +error handle::read32_cop(uint8_t args[HWSTUB_COP_ARGS], uint32_t& value) +{ + size_t sz = sizeof(value); + error err = cop_op(HWSTUB_COP_READ, args, nullptr, 0, &value, &sz); + if(err != error::SUCCESS) + return err; + if(sz != sizeof(value)) + return error::ERROR; + return error::SUCCESS; +} + +error handle::write32_cop(uint8_t args[HWSTUB_COP_ARGS], uint32_t value) +{ + return cop_op(HWSTUB_COP_WRITE, args, &value, sizeof(value), nullptr, nullptr); +} + error handle::status() const { /* check context */ @@ -616,6 +650,18 @@ error dummy_handle::exec_dev(uint32_t addr, uint16_t flags) return error::DUMMY; } +error dummy_handle::cop_dev(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], + const void *out_data, size_t out_size, void *in_data, size_t *in_size) +{ + (void) op; + (void) args; + (void) out_data; + (void) out_size; + (void) in_data; + (void) in_size; + return error::DUMMY; +} + error dummy_handle::status() const { error err = handle::status(); diff --git a/utils/hwstub/lib/hwstub_net.cpp b/utils/hwstub/lib/hwstub_net.cpp index ddafea6351..c9d201a761 100644 --- a/utils/hwstub/lib/hwstub_net.cpp +++ b/utils/hwstub/lib/hwstub_net.cpp @@ -735,6 +735,18 @@ error handle::exec_dev(uint32_t addr, uint16_t flags) return error::SUCCESS; } +error handle::cop_dev(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], + const void *out_data, size_t out_size, void *in_data, size_t *in_size) +{ + (void) op; + (void) args; + (void) out_data; + (void) out_size; + (void) in_data; + (void) in_size; + return error::UNIMPLEMENTED; +} + error handle::status() const { return hwstub::handle::status(); diff --git a/utils/hwstub/lib/hwstub_usb.cpp b/utils/hwstub/lib/hwstub_usb.cpp index 6bb1cfa049..37249f5812 100644 --- a/utils/hwstub/lib/hwstub_usb.cpp +++ b/utils/hwstub/lib/hwstub_usb.cpp @@ -399,6 +399,46 @@ error rb_handle::write_dev(uint32_t addr, const void *buf, size_t& sz, bool atom return ret; } +error rb_handle::cop_dev(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], + const void *out_data, size_t out_size, void *in_data, size_t *in_size) +{ + (void) op; + (void) args; + (void) out_data; + (void) out_size; + (void) in_data; + (void) in_size; + std::shared_ptr hctx = get_device()->get_context(); + if(!hctx) + return error::NO_CONTEXT; + + /* construct out request: header followed by (optional) data */ + size_t hdr_sz = sizeof(struct hwstub_cop_req_t); + uint8_t *tmp_buf = new uint8_t[out_size + hdr_sz]; + struct hwstub_cop_req_t *req = reinterpret_cast(tmp_buf); + req->bOp = op; + for(int i = 0; i < HWSTUB_COP_ARGS; i++) + req->bArgs[i] = args[i]; + if(out_size > 0) + memcpy(tmp_buf + hdr_sz, out_data, out_size); + error ret = interpret_libusb_error(libusb_control_transfer(m_handle, + LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT, + HWSTUB_COPROCESSOR_OP, m_transac_id++, m_intf, + (unsigned char *)req, out_size + hdr_sz, m_timeout), out_size + hdr_sz); + delete[] tmp_buf; + /* return errors if any */ + if(ret != error::SUCCESS) + return ret; + /* return now if there is no read stage */ + if(in_data == nullptr) + return error::SUCCESS; + /* perform read stage (use the same transaction ID) */ + return interpret_libusb_size(libusb_control_transfer(m_handle, + LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN, + HWSTUB_READ2, m_transac_id - 1, m_intf, + (unsigned char *)in_data, *in_size, m_timeout), *in_size); +} + bool rb_handle::find_intf(struct libusb_device_descriptor *dev, struct libusb_config_descriptor *config, int& intf_idx) { @@ -674,6 +714,18 @@ error jz_handle::write_dev(uint32_t addr, const void *buf, size_t& sz, bool atom return ret; } +error jz_handle::cop_dev(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], + const void *out_data, size_t out_size, void *in_data, size_t *in_size) +{ + (void) op; + (void) args; + (void) out_data; + (void) out_size; + (void) in_data; + (void) in_size; + return error::UNSUPPORTED; +} + bool jz_handle::is_boot_dev(struct libusb_device_descriptor *dev, struct libusb_config_descriptor *config) { diff --git a/utils/hwstub/lib/hwstub_virtual.cpp b/utils/hwstub/lib/hwstub_virtual.cpp index fada56fb83..5c9e79e5a1 100644 --- a/utils/hwstub/lib/hwstub_virtual.cpp +++ b/utils/hwstub/lib/hwstub_virtual.cpp @@ -221,6 +221,18 @@ error handle::exec_dev(uint32_t addr, uint16_t flags) return p ? p->exec_dev(addr, flags) : error::DISCONNECTED; } +error handle::cop_dev(uint8_t op, uint8_t args[HWSTUB_COP_ARGS], + const void *out_data, size_t out_size, void *in_data, size_t *in_size) +{ + (void) op; + (void) args; + (void) out_data; + (void) out_size; + (void) in_data; + (void) in_size; + return error::UNSUPPORTED; +} + error handle::status() const { return hwstub::handle::status(); -- cgit v1.2.3