^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) }