Skip to content
Snippets Groups Projects
Commit 002a96fe authored by Florian Pose's avatar Florian Pose
Browse files

Implemented SoE fragmented reading.

parent 7d8a15ad
No related branches found
No related tags found
No related merge requests found
......@@ -110,6 +110,7 @@ void ec_fsm_soe_transfer(
if (request->dir == EC_DIR_OUTPUT) {
fsm->state = ec_fsm_soe_write_start;
} else {
fsm->request->data_size = 0;
fsm->state = ec_fsm_soe_read_start;
}
}
......@@ -225,7 +226,6 @@ void ec_fsm_soe_read_request(ec_fsm_soe_t *fsm /**< finite state machine */)
}
fsm->jiffies_start = datagram->jiffies_sent;
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_soe_read_check;
......@@ -290,7 +290,8 @@ void ec_fsm_soe_read_response(ec_fsm_soe_t *fsm /**< finite state machine */)
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
ec_master_t *master = slave->master;
uint8_t *data, mbox_prot, opcode, error_flag, value_included;
uint8_t *data, mbox_prot, header, opcode, incomplete, error_flag,
value_included;
size_t rec_size, data_size;
ec_soe_request_t *req = fsm->request;
......@@ -338,7 +339,11 @@ void ec_fsm_soe_read_response(ec_fsm_soe_t *fsm /**< finite state machine */)
return;
}
opcode = EC_READ_U8(data) & 0x7;
header = EC_READ_U8(data);
opcode = header & 0x7;
incomplete = (header >> 3) & 1;
error_flag = (header >> 4) & 1;
if (opcode != EC_SOE_OPCODE_READ_RESPONSE) {
EC_ERR("Received no read response (opcode %x).\n", opcode);
ec_print_data(data, rec_size);
......@@ -346,7 +351,6 @@ void ec_fsm_soe_read_response(ec_fsm_soe_t *fsm /**< finite state machine */)
return;
}
error_flag = (EC_READ_U8(data) >> 4) & 1;
if (error_flag) {
req->error_code = EC_READ_U16(data + rec_size - 2);
EC_ERR("Received error response: 0x%04x.\n",
......@@ -365,18 +369,29 @@ void ec_fsm_soe_read_response(ec_fsm_soe_t *fsm /**< finite state machine */)
}
data_size = rec_size - EC_SOE_READ_RESPONSE_SIZE;
if (ec_soe_request_copy_data(req,
data + EC_SOE_READ_RESPONSE_SIZE, data_size)) {
if (ec_soe_request_append_data(req,
data + EC_SOE_READ_RESPONSE_SIZE, data_size)) {
fsm->state = ec_fsm_soe_error;
return;
}
if (master->debug_level) {
EC_DBG("IDN data:\n");
ec_print_data(req->data, req->data_size);
}
if (incomplete) {
if (master->debug_level) {
EC_DBG("SoE data incomplete. Waiting for fragment"
" at offset %zu.\n", req->data_size);
}
fsm->jiffies_start = datagram->jiffies_sent;
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_soe_read_check;
} else {
if (master->debug_level) {
EC_DBG("IDN data:\n");
ec_print_data(req->data, req->data_size);
}
fsm->state = ec_fsm_soe_end; // success
fsm->state = ec_fsm_soe_end; // success
}
}
/******************************************************************************
......
......@@ -172,6 +172,40 @@ int ec_soe_request_copy_data(
/*****************************************************************************/
/** Copies SoE data from an external source.
*
* If the \a mem_size is to small, new memory is allocated.
*
* \retval 0 Success.
* \retval <0 Error code.
*/
int ec_soe_request_append_data(
ec_soe_request_t *req, /**< SoE request. */
const uint8_t *source, /**< Source data. */
size_t size /**< Number of bytes in \a source. */
)
{
if (req->data_size + size > req->mem_size) {
size_t new_size = req->mem_size ? req->mem_size * 2 : size;
uint8_t *new_data = (uint8_t *) kmalloc(new_size, GFP_KERNEL);
if (!new_data) {
EC_ERR("Failed to allocate %zu bytes of SoE memory.\n",
new_size);
return -ENOMEM;
}
memcpy(new_data, req->data, req->data_size);
kfree(req->data);
req->data = new_data;
req->mem_size = new_size;
}
memcpy(req->data + req->data_size, source, size);
req->data_size += size;
return 0;
}
/*****************************************************************************/
void ec_soe_request_read(ec_soe_request_t *req)
{
req->dir = EC_DIR_INPUT;
......
......@@ -68,6 +68,7 @@ int ec_soe_request_copy(ec_soe_request_t *, const ec_soe_request_t *);
void ec_soe_request_set_idn(ec_soe_request_t *, uint16_t);
int ec_soe_request_alloc(ec_soe_request_t *, size_t);
int ec_soe_request_copy_data(ec_soe_request_t *, const uint8_t *, size_t);
int ec_soe_request_append_data(ec_soe_request_t *, const uint8_t *, size_t);
void ec_soe_request_read(ec_soe_request_t *);
void ec_soe_request_write(ec_soe_request_t *);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment