diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/firewire/nosy-dump.c | 245 |
1 files changed, 132 insertions, 113 deletions
diff --git a/tools/firewire/nosy-dump.c b/tools/firewire/nosy-dump.c index 5d1e89233738..32c48556170b 100644 --- a/tools/firewire/nosy-dump.c +++ b/tools/firewire/nosy-dump.c @@ -487,138 +487,157 @@ static const struct packet_info packet_info[] = { }; static int -handle_packet(uint32_t *data, size_t length) +handle_request_packet(uint32_t *data, size_t length) { - if (length == 0) { - printf("bus reset\r\n"); - clear_pending_transaction_list(); - } else if (length > sizeof(struct phy_packet)) { - struct link_packet *p = (struct link_packet *) data; - struct subaction *sa, *prev; - struct link_transaction *t; + struct link_packet *p = (struct link_packet *) data; + struct subaction *sa, *prev; + struct link_transaction *t; - switch (packet_info[p->common.tcode].type) { - case PACKET_REQUEST: - t = link_transaction_lookup(p->common.source, p->common.destination, - p->common.tlabel); - sa = subaction_create(data, length); - t->request = sa; - - if (!list_empty(&t->request_list)) { - prev = list_tail(&t->request_list, - struct subaction, link); - - if (!ACK_BUSY(prev->ack)) { - /* - * error, we should only see ack_busy_* before the - * ack_pending/ack_complete -- this is an ack_pending - * instead (ack_complete would have finished the - * transaction). - */ - } + t = link_transaction_lookup(p->common.source, p->common.destination, + p->common.tlabel); + sa = subaction_create(data, length); + t->request = sa; + + if (!list_empty(&t->request_list)) { + prev = list_tail(&t->request_list, + struct subaction, link); + + if (!ACK_BUSY(prev->ack)) { + /* + * error, we should only see ack_busy_* before the + * ack_pending/ack_complete -- this is an ack_pending + * instead (ack_complete would have finished the + * transaction). + */ + } - if (prev->packet.common.tcode != sa->packet.common.tcode || - prev->packet.common.tlabel != sa->packet.common.tlabel) { - /* memcmp() ? */ - /* error, these should match for retries. */ - } - } + if (prev->packet.common.tcode != sa->packet.common.tcode || + prev->packet.common.tlabel != sa->packet.common.tlabel) { + /* memcmp() ? */ + /* error, these should match for retries. */ + } + } - list_append(&t->request_list, &sa->link); + list_append(&t->request_list, &sa->link); - switch (sa->ack) { - case ACK_COMPLETE: - if (p->common.tcode != TCODE_WRITE_QUADLET && - p->common.tcode != TCODE_WRITE_BLOCK) - /* error, unified transactions only allowed for write */; - list_remove(&t->link); - handle_transaction(t); - break; + switch (sa->ack) { + case ACK_COMPLETE: + if (p->common.tcode != TCODE_WRITE_QUADLET && + p->common.tcode != TCODE_WRITE_BLOCK) + /* error, unified transactions only allowed for write */; + list_remove(&t->link); + handle_transaction(t); + break; - case ACK_NO_ACK: - case ACK_DATA_ERROR: - case ACK_TYPE_ERROR: - list_remove(&t->link); - handle_transaction(t); - break; + case ACK_NO_ACK: + case ACK_DATA_ERROR: + case ACK_TYPE_ERROR: + list_remove(&t->link); + handle_transaction(t); + break; + + case ACK_PENDING: + /* request subaction phase over, wait for response. */ + break; + + case ACK_BUSY_X: + case ACK_BUSY_A: + case ACK_BUSY_B: + /* ok, wait for retry. */ + /* check that retry protocol is respected. */ + break; + } - case ACK_PENDING: - /* request subaction phase over, wait for response. */ - break; + return 1; +} - case ACK_BUSY_X: - case ACK_BUSY_A: - case ACK_BUSY_B: - /* ok, wait for retry. */ - /* check that retry protocol is respected. */ - break; - } - break; +static int +handle_response_packet(uint32_t *data, size_t length) +{ + struct link_packet *p = (struct link_packet *) data; + struct subaction *sa, *prev; + struct link_transaction *t; - case PACKET_RESPONSE: - t = link_transaction_lookup(p->common.destination, p->common.source, - p->common.tlabel); - if (list_empty(&t->request_list)) { - /* unsolicited response */ - } + t = link_transaction_lookup(p->common.destination, p->common.source, + p->common.tlabel); + if (list_empty(&t->request_list)) { + /* unsolicited response */ + } - sa = subaction_create(data, length); - t->response = sa; + sa = subaction_create(data, length); + t->response = sa; - if (!list_empty(&t->response_list)) { - prev = list_tail(&t->response_list, struct subaction, link); + if (!list_empty(&t->response_list)) { + prev = list_tail(&t->response_list, struct subaction, link); - if (!ACK_BUSY(prev->ack)) { - /* - * error, we should only see ack_busy_* before the - * ack_pending/ack_complete - */ - } + if (!ACK_BUSY(prev->ack)) { + /* + * error, we should only see ack_busy_* before the + * ack_pending/ack_complete + */ + } - if (prev->packet.common.tcode != sa->packet.common.tcode || - prev->packet.common.tlabel != sa->packet.common.tlabel) { - /* use memcmp() instead? */ - /* error, these should match for retries. */ - } - } else { - prev = list_tail(&t->request_list, struct subaction, link); - if (prev->ack != ACK_PENDING) { - /* - * error, should not get response unless last request got - * ack_pending. - */ - } + if (prev->packet.common.tcode != sa->packet.common.tcode || + prev->packet.common.tlabel != sa->packet.common.tlabel) { + /* use memcmp() instead? */ + /* error, these should match for retries. */ + } + } else { + prev = list_tail(&t->request_list, struct subaction, link); + if (prev->ack != ACK_PENDING) { + /* + * error, should not get response unless last request got + * ack_pending. + */ + } - if (packet_info[prev->packet.common.tcode].response_tcode != - sa->packet.common.tcode) { - /* error, tcode mismatch */ - } - } + if (packet_info[prev->packet.common.tcode].response_tcode != + sa->packet.common.tcode) { + /* error, tcode mismatch */ + } + } - list_append(&t->response_list, &sa->link); + list_append(&t->response_list, &sa->link); - switch (sa->ack) { - case ACK_COMPLETE: - case ACK_NO_ACK: - case ACK_DATA_ERROR: - case ACK_TYPE_ERROR: - list_remove(&t->link); - handle_transaction(t); - /* transaction complete, remove t from pending list. */ - break; + switch (sa->ack) { + case ACK_COMPLETE: + case ACK_NO_ACK: + case ACK_DATA_ERROR: + case ACK_TYPE_ERROR: + list_remove(&t->link); + handle_transaction(t); + /* transaction complete, remove t from pending list. */ + break; + + case ACK_PENDING: + /* error for responses. */ + break; + + case ACK_BUSY_X: + case ACK_BUSY_A: + case ACK_BUSY_B: + /* no problem, wait for next retry */ + break; + } - case ACK_PENDING: - /* error for responses. */ - break; + return 1; +} - case ACK_BUSY_X: - case ACK_BUSY_A: - case ACK_BUSY_B: - /* no problem, wait for next retry */ - break; - } +static int +handle_packet(uint32_t *data, size_t length) +{ + if (length == 0) { + printf("bus reset\r\n"); + clear_pending_transaction_list(); + } else if (length > sizeof(struct phy_packet)) { + struct link_packet *p = (struct link_packet *) data; - break; + switch (packet_info[p->common.tcode].type) { + case PACKET_REQUEST: + return handle_request_packet(data, length); + + case PACKET_RESPONSE: + return handle_response_packet(data, length); case PACKET_OTHER: case PACKET_RESERVED: |