Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * nosy-dump - Interface to snoop mode driver for TI PCILynx 1394 controllers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  * Copyright (C) 2002-2006 Kristian Høgsberg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7) #include <byteswap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8) #include <endian.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9) #include <fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) #include <linux/firewire-constants.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <poll.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <popt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <stdio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <sys/ioctl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <sys/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) #include <termios.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include "list.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include "nosy-dump.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) #include "nosy-user.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) 	PACKET_FIELD_DETAIL		= 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) 	PACKET_FIELD_DATA_LENGTH	= 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) 	/* Marks the fields we print in transaction view. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) 	PACKET_FIELD_TRANSACTION	= 0x04,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) static void print_packet(uint32_t *data, size_t length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) static void decode_link_packet(struct link_packet *packet, size_t length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) 			       int include_flags, int exclude_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) static int run = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) sig_t sys_sigint_handler;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) static char *option_nosy_device = "/dev/nosy";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) static char *option_view = "packet";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) static char *option_output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) static char *option_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) static int option_hex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) static int option_iso;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) static int option_cycle_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) static int option_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) static int option_verbose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	VIEW_TRANSACTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 	VIEW_PACKET,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	VIEW_STATS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) static const struct poptOption options[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) 		.longName	= "device",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 		.shortName	= 'd',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) 		.argInfo	= POPT_ARG_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) 		.arg		= &option_nosy_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 		.descrip	= "Path to nosy device.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 		.argDescrip	= "DEVICE"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 		.longName	= "view",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) 		.argInfo	= POPT_ARG_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 		.arg		= &option_view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) 		.descrip	= "Specify view of bus traffic: packet, transaction or stats.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) 		.argDescrip	= "VIEW"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) 		.longName	= "hex",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 		.shortName	= 'x',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 		.argInfo	= POPT_ARG_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 		.arg		= &option_hex,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) 		.descrip	= "Print each packet in hex.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) 		.longName	= "iso",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) 		.argInfo	= POPT_ARG_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) 		.arg		= &option_iso,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) 		.descrip	= "Print iso packets.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) 		.longName	= "cycle-start",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) 		.argInfo	= POPT_ARG_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) 		.arg		= &option_cycle_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 		.descrip	= "Print cycle start packets.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) 		.longName	= "verbose",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) 		.shortName	= 'v',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 		.argInfo	= POPT_ARG_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) 		.arg		= &option_verbose,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 		.descrip	= "Verbose packet view.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) 		.longName	= "output",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) 		.shortName	= 'o',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 		.argInfo	= POPT_ARG_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 		.arg		= &option_output,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 		.descrip	= "Log to output file.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 		.argDescrip	= "FILENAME"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 		.longName	= "input",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 		.shortName	= 'i',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) 		.argInfo	= POPT_ARG_STRING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 		.arg		= &option_input,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 		.descrip	= "Decode log from file.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) 		.argDescrip	= "FILENAME"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 		.longName	= "version",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) 		.argInfo	= POPT_ARG_NONE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) 		.arg		= &option_version,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 		.descrip	= "Specify print version info.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) 	POPT_AUTOHELP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 	POPT_TABLEEND
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) /* Allow all ^C except the first to interrupt the program in the usual way. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) sigint_handler(int signal_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 	if (run == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 		run = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 		signal(SIGINT, SIG_DFL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) static struct subaction *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) subaction_create(uint32_t *data, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) 	struct subaction *sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) 	/* we put the ack in the subaction struct for easy access. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	sa = malloc(sizeof *sa - sizeof sa->packet + length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 	if (!sa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	sa->ack = data[length / 4 - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	sa->length = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 	memcpy(&sa->packet, data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	return sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) subaction_destroy(struct subaction *sa)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	free(sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) static struct list pending_transaction_list = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 	&pending_transaction_list, &pending_transaction_list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) static struct link_transaction *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) link_transaction_lookup(int request_node, int response_node, int tlabel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 	struct link_transaction *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) 	list_for_each_entry(t, &pending_transaction_list, link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 		if (t->request_node == request_node &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) 		    t->response_node == response_node &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) 		    t->tlabel == tlabel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) 			return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) 	t = malloc(sizeof *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	if (!t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 	t->request_node = request_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 	t->response_node = response_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) 	t->tlabel = tlabel;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177) 	list_init(&t->request_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178) 	list_init(&t->response_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) 	list_append(&pending_transaction_list, &t->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	return t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) link_transaction_destroy(struct link_transaction *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	struct subaction *sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 	while (!list_empty(&t->request_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 		sa = list_head(&t->request_list, struct subaction, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) 		list_remove(&sa->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193) 		subaction_destroy(sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) 	while (!list_empty(&t->response_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 		sa = list_head(&t->response_list, struct subaction, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 		list_remove(&sa->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) 		subaction_destroy(sa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) 	free(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) struct protocol_decoder {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) 	const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) 	int (*decode)(struct link_transaction *t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) static const struct protocol_decoder protocol_decoders[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	{ "FCP", decode_fcp }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) handle_transaction(struct link_transaction *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) 	struct subaction *sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) 	if (!t->request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 		printf("BUG in handle_transaction\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	for (i = 0; i < array_length(protocol_decoders); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 		if (protocol_decoders[i].decode(t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	/* HACK: decode only fcp right now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	decode_link_packet(&t->request->packet, t->request->length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 			   PACKET_FIELD_TRANSACTION, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) 	if (t->response)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 		decode_link_packet(&t->response->packet, t->request->length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) 				   PACKET_FIELD_TRANSACTION, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 		printf("[no response]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	if (option_verbose) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 		list_for_each_entry(sa, &t->request_list, link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 			print_packet((uint32_t *) &sa->packet, sa->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) 		list_for_each_entry(sa, &t->response_list, link)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 			print_packet((uint32_t *) &sa->packet, sa->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	printf("\r\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 	link_transaction_destroy(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) clear_pending_transaction_list(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 	struct link_transaction *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	while (!list_empty(&pending_transaction_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 		t = list_head(&pending_transaction_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 			      struct link_transaction, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 		list_remove(&t->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) 		link_transaction_destroy(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) 		/* print unfinished transactions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) static const char * const tcode_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 	[0x0] = "write_quadlet_request",	[0x6] = "read_quadlet_response",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) 	[0x1] = "write_block_request",		[0x7] = "read_block_response",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 	[0x2] = "write_response",		[0x8] = "cycle_start",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) 	[0x3] = "reserved",			[0x9] = "lock_request",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) 	[0x4] = "read_quadlet_request",		[0xa] = "iso_data",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) 	[0x5] = "read_block_request",		[0xb] = "lock_response",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) static const char * const ack_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 	[0x0] = "no ack",			[0x8] = "reserved (0x08)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	[0x1] = "ack_complete",			[0x9] = "reserved (0x09)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	[0x2] = "ack_pending",			[0xa] = "reserved (0x0a)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	[0x3] = "reserved (0x03)",		[0xb] = "reserved (0x0b)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	[0x4] = "ack_busy_x",			[0xc] = "reserved (0x0c)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 	[0x5] = "ack_busy_a",			[0xd] = "ack_data_error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	[0x6] = "ack_busy_b",			[0xe] = "ack_type_error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 	[0x7] = "reserved (0x07)",		[0xf] = "reserved (0x0f)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) static const char * const rcode_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	[0x0] = "complete",			[0x4] = "conflict_error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) 	[0x1] = "reserved (0x01)",		[0x5] = "data_error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 	[0x2] = "reserved (0x02)",		[0x6] = "type_error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) 	[0x3] = "reserved (0x03)",		[0x7] = "address_error",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) static const char * const retry_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	[0x0] = "retry_1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 	[0x1] = "retry_x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	[0x2] = "retry_a",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	[0x3] = "retry_b",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 	PACKET_RESERVED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	PACKET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 	PACKET_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	PACKET_OTHER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) struct packet_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) 	const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) 	int type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	int response_tcode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 	const struct packet_field *fields;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	int field_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) struct packet_field {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	const char *name; /* Short name for field. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) 	int offset;	/* Location of field, specified in bits; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 			/* negative means from end of packet.    */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) 	int width;	/* Width of field, 0 means use data_length. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317) 	int flags;	/* Show options. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	const char * const *value_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) #define COMMON_REQUEST_FIELDS						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	{ "dest", 0, 16, PACKET_FIELD_TRANSACTION },			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	{ "tl", 16, 6 },						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	{ "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names },		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 	{ "tcode", 24, 4, PACKET_FIELD_TRANSACTION, tcode_names },	\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	{ "pri", 28, 4, PACKET_FIELD_DETAIL },				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	{ "src", 32, 16, PACKET_FIELD_TRANSACTION },			\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 	{ "offs", 48, 48, PACKET_FIELD_TRANSACTION }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) #define COMMON_RESPONSE_FIELDS						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 	{ "dest", 0, 16 },						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	{ "tl", 16, 6 },						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 	{ "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names },		\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	{ "tcode", 24, 4, 0, tcode_names },				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 	{ "pri", 28, 4, PACKET_FIELD_DETAIL },				\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	{ "src", 32, 16 },						\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 	{ "rcode", 48, 4, PACKET_FIELD_TRANSACTION, rcode_names }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) static const struct packet_field read_quadlet_request_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	COMMON_REQUEST_FIELDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 	{ "crc", 96, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	{ "ack", 156, 4, 0, ack_names },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) static const struct packet_field read_quadlet_response_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	COMMON_RESPONSE_FIELDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	{ "data", 96, 32, PACKET_FIELD_TRANSACTION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 	{ "crc", 128, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 	{ "ack", 188, 4, 0, ack_names },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) static const struct packet_field read_block_request_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	COMMON_REQUEST_FIELDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	{ "data_length", 96, 16, PACKET_FIELD_TRANSACTION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	{ "extended_tcode", 112, 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	{ "crc", 128, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	{ "ack", 188, 4, 0, ack_names },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) static const struct packet_field block_response_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	COMMON_RESPONSE_FIELDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	{ "data_length", 96, 16, PACKET_FIELD_DATA_LENGTH },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	{ "extended_tcode", 112, 16 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	{ "crc", 128, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	{ "data", 160, 0, PACKET_FIELD_TRANSACTION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	{ "crc", -64, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	{ "ack", -4, 4, 0, ack_names },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) static const struct packet_field write_quadlet_request_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 	COMMON_REQUEST_FIELDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 	{ "data", 96, 32, PACKET_FIELD_TRANSACTION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 	{ "ack", -4, 4, 0, ack_names },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) static const struct packet_field block_request_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 	COMMON_REQUEST_FIELDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 	{ "data_length", 96, 16, PACKET_FIELD_DATA_LENGTH | PACKET_FIELD_TRANSACTION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 	{ "extended_tcode", 112, 16, PACKET_FIELD_TRANSACTION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 	{ "crc", 128, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	{ "data", 160, 0, PACKET_FIELD_TRANSACTION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) 	{ "crc", -64, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	{ "ack", -4, 4, 0, ack_names },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) static const struct packet_field write_response_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) 	COMMON_RESPONSE_FIELDS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388) 	{ "reserved", 64, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389) 	{ "ack", -4, 4, 0, ack_names },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) static const struct packet_field iso_data_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 	{ "data_length", 0, 16, PACKET_FIELD_DATA_LENGTH },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	{ "tag", 16, 2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 	{ "channel", 18, 6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 	{ "tcode", 24, 4, 0, tcode_names },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 	{ "sy", 28, 4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 	{ "crc", 32, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 	{ "data", 64, 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 	{ "crc", -64, 32, PACKET_FIELD_DETAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	{ "ack", -4, 4, 0, ack_names },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) static const struct packet_info packet_info[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 		.name		= "write_quadlet_request",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 		.type		= PACKET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 		.response_tcode	= TCODE_WRITE_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 		.fields		= write_quadlet_request_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		.field_count	= array_length(write_quadlet_request_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 		.name		= "write_block_request",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 		.type		= PACKET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		.response_tcode	= TCODE_WRITE_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		.fields		= block_request_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		.field_count	= array_length(block_request_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 		.name		= "write_response",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 		.type		= PACKET_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 		.fields		= write_response_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 		.field_count	= array_length(write_response_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) 		.name		= "reserved",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 		.type		= PACKET_RESERVED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) 		.name		= "read_quadlet_request",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 		.type		= PACKET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 		.response_tcode	= TCODE_READ_QUADLET_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 		.fields		= read_quadlet_request_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 		.field_count	= array_length(read_quadlet_request_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 		.name		= "read_block_request",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 		.type		= PACKET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 		.response_tcode	= TCODE_READ_BLOCK_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 		.fields		= read_block_request_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 		.field_count	= array_length(read_block_request_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 		.name		= "read_quadlet_response",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 		.type		= PACKET_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		.fields		= read_quadlet_response_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		.field_count	= array_length(read_quadlet_response_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 		.name		= "read_block_response",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		.type		= PACKET_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		.fields		= block_response_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		.field_count	= array_length(block_response_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		.name		= "cycle_start",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		.type		= PACKET_OTHER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		.fields		= write_quadlet_request_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 		.field_count	= array_length(write_quadlet_request_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		.name		= "lock_request",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		.type		= PACKET_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 		.fields		= block_request_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 		.field_count	= array_length(block_request_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) 		.name		= "iso_data",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) 		.type		= PACKET_OTHER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 		.fields		= iso_data_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 		.field_count	= array_length(iso_data_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 		.name		= "lock_response",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 		.type		= PACKET_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 		.fields		= block_response_fields,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		.field_count	= array_length(block_response_fields)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) handle_request_packet(uint32_t *data, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	struct link_packet *p = (struct link_packet *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	struct subaction *sa, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	struct link_transaction *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 	t = link_transaction_lookup(p->common.source, p->common.destination,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 			p->common.tlabel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	sa = subaction_create(data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	t->request = sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 	if (!list_empty(&t->request_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 		prev = list_tail(&t->request_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 				 struct subaction, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 		if (!ACK_BUSY(prev->ack)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 			 * error, we should only see ack_busy_* before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 			 * ack_pending/ack_complete -- this is an ack_pending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 			 * instead (ack_complete would have finished the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 			 * transaction).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 		if (prev->packet.common.tcode != sa->packet.common.tcode ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 		    prev->packet.common.tlabel != sa->packet.common.tlabel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) 			/* memcmp() ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 			/* error, these should match for retries. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	list_append(&t->request_list, &sa->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	switch (sa->ack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 	case ACK_COMPLETE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 		if (p->common.tcode != TCODE_WRITE_QUADLET_REQUEST &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 		    p->common.tcode != TCODE_WRITE_BLOCK_REQUEST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 			/* error, unified transactions only allowed for write */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 		list_remove(&t->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 		handle_transaction(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	case ACK_NO_ACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) 	case ACK_DATA_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 	case ACK_TYPE_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) 		list_remove(&t->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) 		handle_transaction(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	case ACK_PENDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 		/* request subaction phase over, wait for response. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	case ACK_BUSY_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 	case ACK_BUSY_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) 	case ACK_BUSY_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) 		/* ok, wait for retry. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 		/* check that retry protocol is respected. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) handle_response_packet(uint32_t *data, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	struct link_packet *p = (struct link_packet *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	struct subaction *sa, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) 	struct link_transaction *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) 	t = link_transaction_lookup(p->common.destination, p->common.source,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 			p->common.tlabel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	if (list_empty(&t->request_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 		/* unsolicited response */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	sa = subaction_create(data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	t->response = sa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	if (!list_empty(&t->response_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 		prev = list_tail(&t->response_list, struct subaction, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 		if (!ACK_BUSY(prev->ack)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 			 * error, we should only see ack_busy_* before the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 			 * ack_pending/ack_complete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) 		if (prev->packet.common.tcode != sa->packet.common.tcode ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) 		    prev->packet.common.tlabel != sa->packet.common.tlabel) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) 			/* use memcmp() instead? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) 			/* error, these should match for retries. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 		prev = list_tail(&t->request_list, struct subaction, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 		if (prev->ack != ACK_PENDING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 			 * error, should not get response unless last request got
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 			 * ack_pending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		if (packet_info[prev->packet.common.tcode].response_tcode !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 		    sa->packet.common.tcode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 			/* error, tcode mismatch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	list_append(&t->response_list, &sa->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	switch (sa->ack) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	case ACK_COMPLETE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	case ACK_NO_ACK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	case ACK_DATA_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 	case ACK_TYPE_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 		list_remove(&t->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 		handle_transaction(t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 		/* transaction complete, remove t from pending list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	case ACK_PENDING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 		/* error for responses. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	case ACK_BUSY_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 	case ACK_BUSY_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	case ACK_BUSY_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) 		/* no problem, wait for next retry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) handle_packet(uint32_t *data, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	if (length == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 		printf("bus reset\r\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 		clear_pending_transaction_list();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	} else if (length > sizeof(struct phy_packet)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 		struct link_packet *p = (struct link_packet *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) 		switch (packet_info[p->common.tcode].type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 		case PACKET_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 			return handle_request_packet(data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 		case PACKET_RESPONSE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 			return handle_response_packet(data, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 		case PACKET_OTHER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 		case PACKET_RESERVED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 			return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) static unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) get_bits(struct link_packet *packet, int offset, int width)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	uint32_t *data = (uint32_t *) packet;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 	uint32_t index, shift, mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	index = offset / 32 + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	shift = 32 - (offset & 31) - width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	mask = width == 32 ? ~0 : (1 << width) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	return (data[index] >> shift) & mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) #if __BYTE_ORDER == __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) #define byte_index(i) ((i) ^ 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) #elif __BYTE_ORDER == __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) #define byte_index(i) (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) #error unsupported byte order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) dump_data(unsigned char *data, int length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) 	int i, print_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	if (length > 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 		print_length = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 		print_length = length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 	for (i = 0; i < print_length; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 		printf("%s%02hhx",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		       (i % 4 == 0 && i != 0) ? " " : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 		       data[byte_index(i)]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 	if (print_length < length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 		printf(" (%d more bytes)", length - print_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) decode_link_packet(struct link_packet *packet, size_t length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 		   int include_flags, int exclude_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) 	const struct packet_info *pi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	int data_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	pi = &packet_info[packet->common.tcode];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) 	for (i = 0; i < pi->field_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) 		const struct packet_field *f = &pi->fields[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 		int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 		if (f->flags & exclude_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 		if (include_flags && !(f->flags & include_flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 		if (f->offset < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 			offset = length * 8 + f->offset - 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 			offset = f->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 		if (f->value_names != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 			uint32_t bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 			bits = get_bits(packet, offset, f->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 			printf("%s", f->value_names[bits]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 		} else if (f->width == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 			printf("%s=[", f->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 			dump_data((unsigned char *) packet + (offset / 8 + 4), data_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 			printf("]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 			unsigned long long bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 			int high_width, low_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 			if ((offset & ~31) != ((offset + f->width - 1) & ~31)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 				/* Bit field spans quadlet boundary. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 				high_width = ((offset + 31) & ~31) - offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 				low_width = f->width - high_width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 				bits = get_bits(packet, offset, high_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 				bits = (bits << low_width) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 					get_bits(packet, offset + high_width, low_width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 				bits = get_bits(packet, offset, f->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 			printf("%s=0x%0*llx", f->name, (f->width + 3) / 4, bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 			if (f->flags & PACKET_FIELD_DATA_LENGTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 				data_length = bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 		if (i < pi->field_count - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 			printf(", ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) print_packet(uint32_t *data, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	printf("%6u  ", data[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	if (length == 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) 		printf("bus reset");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 	} else if (length < sizeof(struct phy_packet)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) 		printf("short packet: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) 		for (i = 1; i < length / 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) 			printf("%s%08x", i == 0 ? "[" : " ", data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 		printf("]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758) 	} else if (length == sizeof(struct phy_packet) && data[1] == ~data[2]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759) 		struct phy_packet *pp = (struct phy_packet *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) 		/* phy packet are 3 quadlets: the 1 quadlet payload,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 		 * the bitwise inverse of the payload and the snoop
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 		 * mode ack */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 		switch (pp->common.identifier) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 		case PHY_PACKET_CONFIGURATION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 			if (!pp->phy_config.set_root && !pp->phy_config.set_gap_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 				printf("ext phy config: phy_id=%02x", pp->phy_config.root_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 				printf("phy config:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 				if (pp->phy_config.set_root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 					printf(" set_root_id=%02x", pp->phy_config.root_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 				if (pp->phy_config.set_gap_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 					printf(" set_gap_count=%d", pp->phy_config.gap_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 		case PHY_PACKET_LINK_ON:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 			printf("link-on packet, phy_id=%02x", pp->link_on.phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		case PHY_PACKET_SELF_ID:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 			if (pp->self_id.extended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 				printf("extended self id: phy_id=%02x, seq=%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 				       pp->ext_self_id.phy_id, pp->ext_self_id.sequence);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 				static const char * const speed_names[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 					"S100", "S200", "S400", "BETA"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 				};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 				printf("self id: phy_id=%02x, link %s, gap_count=%d, speed=%s%s%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 				       pp->self_id.phy_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 				       (pp->self_id.link_active ? "active" : "not active"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 				       pp->self_id.gap_count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 				       speed_names[pp->self_id.phy_speed],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 				       (pp->self_id.contender ? ", irm contender" : ""),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 				       (pp->self_id.initiated_reset ? ", initiator" : ""));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 			printf("unknown phy packet: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 			for (i = 1; i < length / 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 				printf("%s%08x", i == 0 ? "[" : " ", data[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 			printf("]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 		struct link_packet *packet = (struct link_packet *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 		decode_link_packet(packet, length, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 				   option_verbose ? 0 : PACKET_FIELD_DETAIL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 	if (option_hex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		printf("  [");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 		dump_data((unsigned char *) data + 4, length - 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		printf("]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	printf("\r\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) #define HIDE_CURSOR	"\033[?25l"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) #define SHOW_CURSOR	"\033[?25h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) #define CLEAR		"\033[H\033[2J"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) print_stats(uint32_t *data, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 	static int bus_reset_count, short_packet_count, phy_packet_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 	static int tcode_count[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 	static struct timeval last_update;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	struct timeval now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	if (length == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) 		bus_reset_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 	else if (length < sizeof(struct phy_packet))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) 		short_packet_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 	else if (length == sizeof(struct phy_packet) && data[1] == ~data[2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840) 		phy_packet_count++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 		struct link_packet *packet = (struct link_packet *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 		tcode_count[packet->common.tcode]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	gettimeofday(&now, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	if (now.tv_sec <= last_update.tv_sec &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	    now.tv_usec < last_update.tv_usec + 500000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	last_update = now;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	printf(CLEAR HIDE_CURSOR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	       "  bus resets              : %8d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	       "  short packets           : %8d\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	       "  phy packets             : %8d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	       bus_reset_count, short_packet_count, phy_packet_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 	for (i = 0; i < array_length(packet_info); i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 		if (packet_info[i].type != PACKET_RESERVED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 			printf("  %-24s: %8d\n", packet_info[i].name, tcode_count[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	printf(SHOW_CURSOR "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) static struct termios saved_attributes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) reset_input_mode(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	tcsetattr(STDIN_FILENO, TCSANOW, &saved_attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) set_input_mode(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 	struct termios tattr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 	/* Make sure stdin is a terminal. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 	if (!isatty(STDIN_FILENO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 		fprintf(stderr, "Not a terminal.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		exit(EXIT_FAILURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	/* Save the terminal attributes so we can restore them later. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 	tcgetattr(STDIN_FILENO, &saved_attributes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 	atexit(reset_input_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) 	/* Set the funny terminal modes. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) 	tcgetattr(STDIN_FILENO, &tattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) 	tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) 	tattr.c_cc[VMIN] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) 	tattr.c_cc[VTIME] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	tcsetattr(STDIN_FILENO, TCSAFLUSH, &tattr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) int main(int argc, const char *argv[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 	uint32_t buf[128 * 1024];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	uint32_t filter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	int length, retval, view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 	int fd = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 	FILE *output = NULL, *input = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 	poptContext con;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 	char c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 	struct pollfd pollfds[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	sys_sigint_handler = signal(SIGINT, sigint_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	con = poptGetContext(NULL, argc, argv, options, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	retval = poptGetNextOpt(con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	if (retval < -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 		poptPrintUsage(con, stdout, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	if (option_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 		printf("dump tool for nosy sniffer, version %s\n", VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) 	if (__BYTE_ORDER != __LITTLE_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 		fprintf(stderr, "warning: nosy has only been tested on little "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) 			"endian machines\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) 	if (option_input != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 		input = fopen(option_input, "r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 		if (input == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 			fprintf(stderr, "Could not open %s, %m\n", option_input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 		fd = open(option_nosy_device, O_RDWR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 		if (fd < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 			fprintf(stderr, "Could not open %s, %m\n", option_nosy_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		set_input_mode();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 	if (strcmp(option_view, "transaction") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 		view = VIEW_TRANSACTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 	else if (strcmp(option_view, "stats") == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 		view = VIEW_STATS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 		view = VIEW_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	if (option_output) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		output = fopen(option_output, "w");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		if (output == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 			fprintf(stderr, "Could not open %s, %m\n", option_output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 			return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 	filter = ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	if (!option_iso)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		filter &= ~(1 << TCODE_STREAM_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	if (!option_cycle_start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 		filter &= ~(1 << TCODE_CYCLE_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	if (view == VIEW_STATS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 		filter = ~(1 << TCODE_CYCLE_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 	ioctl(fd, NOSY_IOC_FILTER, filter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	ioctl(fd, NOSY_IOC_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	pollfds[0].fd = fd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	pollfds[0].events = POLLIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	pollfds[1].fd = STDIN_FILENO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	pollfds[1].events = POLLIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	while (run) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		if (input != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 			if (fread(&length, sizeof length, 1, input) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 			fread(buf, 1, length, input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 			poll(pollfds, 2, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 			if (pollfds[1].revents) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 				read(STDIN_FILENO, &c, sizeof c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 				switch (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 				case 'q':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 					if (output != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 						fclose(output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 					return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) 			if (pollfds[0].revents)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 				length = read(fd, buf, sizeof buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 		if (output != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 			fwrite(&length, sizeof length, 1, output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 			fwrite(buf, 1, length, output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 		switch (view) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 		case VIEW_TRANSACTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 			handle_packet(buf, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 		case VIEW_PACKET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 			print_packet(buf, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 		case VIEW_STATS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 			print_stats(buf, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	if (output != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 		fclose(output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 	close(fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 	poptFreeContext(con);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }