aboutsummaryrefslogtreecommitdiffstats
path: root/tools/firewire/nosy-dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/firewire/nosy-dump.c')
-rw-r--r--tools/firewire/nosy-dump.c245
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[] = {
487}; 487};
488 488
489static int 489static int
490handle_packet(uint32_t *data, size_t length) 490handle_request_packet(uint32_t *data, size_t length)
491{ 491{
492 if (length == 0) { 492 struct link_packet *p = (struct link_packet *) data;
493 printf("bus reset\r\n"); 493 struct subaction *sa, *prev;
494 clear_pending_transaction_list(); 494 struct link_transaction *t;
495 } else if (length > sizeof(struct phy_packet)) {
496 struct link_packet *p = (struct link_packet *) data;
497 struct subaction *sa, *prev;
498 struct link_transaction *t;
499 495
500 switch (packet_info[p->common.tcode].type) { 496 t = link_transaction_lookup(p->common.source, p->common.destination,
501 case PACKET_REQUEST: 497 p->common.tlabel);
502 t = link_transaction_lookup(p->common.source, p->common.destination, 498 sa = subaction_create(data, length);
503 p->common.tlabel); 499 t->request = sa;
504 sa = subaction_create(data, length); 500
505 t->request = sa; 501 if (!list_empty(&t->request_list)) {
506 502 prev = list_tail(&t->request_list,
507 if (!list_empty(&t->request_list)) { 503 struct subaction, link);
508 prev = list_tail(&t->request_list, 504
509 struct subaction, link); 505 if (!ACK_BUSY(prev->ack)) {
510 506 /*
511 if (!ACK_BUSY(prev->ack)) { 507 * error, we should only see ack_busy_* before the
512 /* 508 * ack_pending/ack_complete -- this is an ack_pending
513 * error, we should only see ack_busy_* before the 509 * instead (ack_complete would have finished the
514 * ack_pending/ack_complete -- this is an ack_pending 510 * transaction).
515 * instead (ack_complete would have finished the 511 */
516 * transaction). 512 }
517 */
518 }
519 513
520 if (prev->packet.common.tcode != sa->packet.common.tcode || 514 if (prev->packet.common.tcode != sa->packet.common.tcode ||
521 prev->packet.common.tlabel != sa->packet.common.tlabel) { 515 prev->packet.common.tlabel != sa->packet.common.tlabel) {
522 /* memcmp() ? */ 516 /* memcmp() ? */
523 /* error, these should match for retries. */ 517 /* error, these should match for retries. */
524 } 518 }
525 } 519 }
526 520
527 list_append(&t->request_list, &sa->link); 521 list_append(&t->request_list, &sa->link);
528 522
529 switch (sa->ack) { 523 switch (sa->ack) {
530 case ACK_COMPLETE: 524 case ACK_COMPLETE:
531 if (p->common.tcode != TCODE_WRITE_QUADLET && 525 if (p->common.tcode != TCODE_WRITE_QUADLET &&
532 p->common.tcode != TCODE_WRITE_BLOCK) 526 p->common.tcode != TCODE_WRITE_BLOCK)
533 /* error, unified transactions only allowed for write */; 527 /* error, unified transactions only allowed for write */;
534 list_remove(&t->link); 528 list_remove(&t->link);
535 handle_transaction(t); 529 handle_transaction(t);
536 break; 530 break;
537 531
538 case ACK_NO_ACK: 532 case ACK_NO_ACK:
539 case ACK_DATA_ERROR: 533 case ACK_DATA_ERROR:
540 case ACK_TYPE_ERROR: 534 case ACK_TYPE_ERROR:
541 list_remove(&t->link); 535 list_remove(&t->link);
542 handle_transaction(t); 536 handle_transaction(t);
543 break; 537 break;
538
539 case ACK_PENDING:
540 /* request subaction phase over, wait for response. */
541 break;
542
543 case ACK_BUSY_X:
544 case ACK_BUSY_A:
545 case ACK_BUSY_B:
546 /* ok, wait for retry. */
547 /* check that retry protocol is respected. */
548 break;
549 }
544 550
545 case ACK_PENDING: 551 return 1;
546 /* request subaction phase over, wait for response. */ 552}
547 break;
548 553
549 case ACK_BUSY_X: 554static int
550 case ACK_BUSY_A: 555handle_response_packet(uint32_t *data, size_t length)
551 case ACK_BUSY_B: 556{
552 /* ok, wait for retry. */ 557 struct link_packet *p = (struct link_packet *) data;
553 /* check that retry protocol is respected. */ 558 struct subaction *sa, *prev;
554 break; 559 struct link_transaction *t;
555 }
556 break;
557 560
558 case PACKET_RESPONSE: 561 t = link_transaction_lookup(p->common.destination, p->common.source,
559 t = link_transaction_lookup(p->common.destination, p->common.source, 562 p->common.tlabel);
560 p->common.tlabel); 563 if (list_empty(&t->request_list)) {
561 if (list_empty(&t->request_list)) { 564 /* unsolicited response */
562 /* unsolicited response */ 565 }
563 }
564 566
565 sa = subaction_create(data, length); 567 sa = subaction_create(data, length);
566 t->response = sa; 568 t->response = sa;
567 569
568 if (!list_empty(&t->response_list)) { 570 if (!list_empty(&t->response_list)) {
569 prev = list_tail(&t->response_list, struct subaction, link); 571 prev = list_tail(&t->response_list, struct subaction, link);
570 572
571 if (!ACK_BUSY(prev->ack)) { 573 if (!ACK_BUSY(prev->ack)) {
572 /* 574 /*
573 * error, we should only see ack_busy_* before the 575 * error, we should only see ack_busy_* before the
574 * ack_pending/ack_complete 576 * ack_pending/ack_complete
575 */ 577 */
576 } 578 }
577 579
578 if (prev->packet.common.tcode != sa->packet.common.tcode || 580 if (prev->packet.common.tcode != sa->packet.common.tcode ||
579 prev->packet.common.tlabel != sa->packet.common.tlabel) { 581 prev->packet.common.tlabel != sa->packet.common.tlabel) {
580 /* use memcmp() instead? */ 582 /* use memcmp() instead? */
581 /* error, these should match for retries. */ 583 /* error, these should match for retries. */
582 } 584 }
583 } else { 585 } else {
584 prev = list_tail(&t->request_list, struct subaction, link); 586 prev = list_tail(&t->request_list, struct subaction, link);
585 if (prev->ack != ACK_PENDING) { 587 if (prev->ack != ACK_PENDING) {
586 /* 588 /*
587 * error, should not get response unless last request got 589 * error, should not get response unless last request got
588 * ack_pending. 590 * ack_pending.
589 */ 591 */
590 } 592 }
591 593
592 if (packet_info[prev->packet.common.tcode].response_tcode != 594 if (packet_info[prev->packet.common.tcode].response_tcode !=
593 sa->packet.common.tcode) { 595 sa->packet.common.tcode) {
594 /* error, tcode mismatch */ 596 /* error, tcode mismatch */
595 } 597 }
596 } 598 }
597 599
598 list_append(&t->response_list, &sa->link); 600 list_append(&t->response_list, &sa->link);
599 601
600 switch (sa->ack) { 602 switch (sa->ack) {
601 case ACK_COMPLETE: 603 case ACK_COMPLETE:
602 case ACK_NO_ACK: 604 case ACK_NO_ACK:
603 case ACK_DATA_ERROR: 605 case ACK_DATA_ERROR:
604 case ACK_TYPE_ERROR: 606 case ACK_TYPE_ERROR:
605 list_remove(&t->link); 607 list_remove(&t->link);
606 handle_transaction(t); 608 handle_transaction(t);
607 /* transaction complete, remove t from pending list. */ 609 /* transaction complete, remove t from pending list. */
608 break; 610 break;
611
612 case ACK_PENDING:
613 /* error for responses. */
614 break;
615
616 case ACK_BUSY_X:
617 case ACK_BUSY_A:
618 case ACK_BUSY_B:
619 /* no problem, wait for next retry */
620 break;
621 }
609 622
610 case ACK_PENDING: 623 return 1;
611 /* error for responses. */ 624}
612 break;
613 625
614 case ACK_BUSY_X: 626static int
615 case ACK_BUSY_A: 627handle_packet(uint32_t *data, size_t length)
616 case ACK_BUSY_B: 628{
617 /* no problem, wait for next retry */ 629 if (length == 0) {
618 break; 630 printf("bus reset\r\n");
619 } 631 clear_pending_transaction_list();
632 } else if (length > sizeof(struct phy_packet)) {
633 struct link_packet *p = (struct link_packet *) data;
620 634
621 break; 635 switch (packet_info[p->common.tcode].type) {
636 case PACKET_REQUEST:
637 return handle_request_packet(data, length);
638
639 case PACKET_RESPONSE:
640 return handle_response_packet(data, length);
622 641
623 case PACKET_OTHER: 642 case PACKET_OTHER:
624 case PACKET_RESERVED: 643 case PACKET_RESERVED: