diff options
author | Kristian Høgsberg <krh@redhat.com> | 2006-11-30 18:10:10 -0500 |
---|---|---|
committer | Kristian Høgsberg <krh@redhat.com> | 2006-11-30 18:10:10 -0500 |
commit | 5d0148312b98d2dee399fa20f87f66190eeba51b (patch) | |
tree | 4410d4986ebba059dfd64b56c21094c8e38e0c87 | |
parent | e3e7c833dbf4300a5370c84c08ffd9e3e0e0fda4 (diff) |
Add simple AV/C decoder.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | decode-fcp.c | 239 | ||||
-rw-r--r-- | nosy-dump.c | 385 | ||||
-rw-r--r-- | nosy-dump.h | 292 | ||||
-rw-r--r-- | nosy-user.h | 32 | ||||
-rw-r--r-- | nosy.c | 1 |
6 files changed, 618 insertions, 333 deletions
@@ -26,7 +26,7 @@ nosy-dump : CPPFLAGS = -DVERSION=\"$(version)\" nosy-dump : LDFLAGS = -g nosy-dump : LDLIBS = -lpopt -nosy-dump : nosy-dump.o +nosy-dump : nosy-dump.o decode-fcp.o clean : rm -rf nosy.ko *.o *.mod.c nosy-dump .*.cmd diff --git a/decode-fcp.c b/decode-fcp.c new file mode 100644 index 0000000..cb9a31b --- /dev/null +++ b/decode-fcp.c @@ -0,0 +1,239 @@ +#include <stdlib.h> +#include <stdio.h> +#include "list.h" +#include "nosy-dump.h" + +#define CSR_FCP_COMMAND 0xfffff0000b00ull +#define CSR_FCP_RESPONSE 0xfffff0000d00ull + +static const char * const ctype_names[16] = { + "control", + "status", + "specific inquiry", + "notify", + "general inquiry", + "(reserved 0x05)", + "(reserved 0x06)", + "(reserved 0x07)", + "not implemented", + "accepted", + "rejected", + "in transition", + "stable", + "changed", + "(reserved 0x0e)", + "interim" +}; + +static const char * const subunit_type_names[32] = { + "monitor", + "audio", + "printer", + "disc", + "tape recorder/player", + "tuner", + "ca", + "camera", + "(reserved 0x08)", + "panel", + "bulletin board", + "camera storage", + "(reserved 0x0c)", + "(reserved 0x0d)", + "(reserved 0x0e)", + "(reserved 0x0f)", + "(reserved 0x10)", + "(reserved 0x11)", + "(reserved 0x12)", + "(reserved 0x13)", + "(reserved 0x14)", + "(reserved 0x15)", + "(reserved 0x16)", + "(reserved 0x17)", + "(reserved 0x18)", + "(reserved 0x19)", + "(reserved 0x1a)", + "(reserved 0x1b)", + "vendor unique", + "all subunit types", + "subunit_type extended to next byte", + "unit" +}; + +struct avc_enum { + int value; + const char *name; +}; + +struct avc_field { + const char *name; /* Short name for field. */ + int offset; /* Location of field, specified in bits. + * Negative means from end of packet */ + int width; /* Width of field, 0 means use data_length. */ + struct avc_enum *names; +}; + +struct avc_opcode_info { + const char *name; + struct avc_field fields[8]; +}; + +struct avc_enum power_field_names[] = { + { 0x70, "on" }, + { 0x60, "off" }, + { } +}; + +static const struct avc_opcode_info opcode_info[256] = { + + /* TA Document 1999026 + * AV/C Digital Interface Command Set General Specification + * Version 4.0 */ + [0xb2] = + { "power", { + { "state", 0, 8, power_field_names } + } + }, + [0x30] = + { "unit info", { + { "foo", 0, 8 }, + { "unit_type", 8, 5 }, + { "unit", 13, 3 }, + { "company id", 16, 24 }, + } + }, + [0x31] = { "subunit info" }, + [0x01] = { "reserve" }, + [0xb0] = { "version" }, + [0x00] = { "vendor dependent" }, + + [0x02] = { "plug info" }, + [0x12] = { "channel usage" }, + [0x24] = { "connect" }, + [0x20] = { "connect av" }, + [0x22] = { "connections" }, + [0x11] = { "digital input" }, + [0x10] = { "digital output" }, + [0x25] = { "disconnect" }, + [0x21] = { "disconnect av" }, + [0x19] = { "input plug signal format" }, + [0x18] = { "output plug signal format" }, + [0x1f] = { "general bus setup" }, + + /* TA Document 1999025 + * AV/C Descriptor Mechanism Specification Version 1.0 */ + [0x0c] = { "create descriptor" }, + [0x08] = { "open descriptor" }, + [0x09] = { "read descriptor" }, + [0x0a] = { "write descriptor" }, + [0x05] = { "open info block" }, + [0x06] = { "read info block" }, + [0x07] = { "write info block" }, + [0x0b] = { "search descriptor" }, + [0x0d] = { "object number select" }, + + /* TA Document 1999015 + * AV/C Command Set for Rate Control of Isochronous Data Flow 1.0 */ + [0xb3] = { "rate", { + { "subfunction", 0, 8 }, + { "result", 8, 8 }, + { "plug_type", 16, 8 }, + { "plug_id", 16, 8 }, + } + }, + + /* TA Document 1999008 + * AV/C Audio Subunit Specification 1.0 */ + [0xb8] = { "function block" }, + + /* TA Document 2001001 + * AV/C Panel Subunit Specification 1.1 */ + [0x7d] = { "gui update" }, + [0x7e] = { "push gui data" }, + [0x7f] = { "user action" }, + [0x7c] = { "pass through" }, + + /* */ + [0x26] = { "asynchronous connection" }, +}; + +struct avc_frame { + unsigned int operand0 : 8; + unsigned int opcode : 8; + unsigned int subunit_id : 3; + unsigned int subunit_type : 5; + unsigned int ctype : 4; + unsigned int cts : 4; +}; + +static void +decode_avc(struct link_transaction *t) +{ + struct avc_frame *frame = (struct avc_frame *) t->request->packet.write_block.data; + const struct avc_opcode_info *info; + const char *name; + char buffer[32]; + int i; + + info = &opcode_info[frame->opcode]; + if (info->name == NULL) { + snprintf(buffer, sizeof buffer, "(unknown opcode 0x%02x)", frame->opcode); + name = buffer; + } else { + name = info->name; + } + + printf("av/c %s, subunit_type=%s, subunit_id=%d, opcode=%s", + ctype_names[frame->ctype], subunit_type_names[frame->subunit_type], + frame->subunit_id, name); + + for (i = 0; info->fields[i].name != NULL; i++) { + printf(", %s", info->fields[i].name); + } + + printf("\n"); +} + + +int +decode_fcp(struct link_transaction *t) +{ + struct avc_frame *frame = (struct avc_frame *) t->request->packet.write_block.data; + unsigned long long offset; + + offset = ((unsigned long long) t->request->packet.common.offset_high << 32) | + t->request->packet.common.offset_low; + + if (t->request->packet.common.tcode != TCODE_WRITE_BLOCK) + return 0; + + if (offset == CSR_FCP_COMMAND || offset == CSR_FCP_RESPONSE) { + switch (frame->cts) { + case 0x00: + decode_avc(t); + break; + case 0x01: + printf("cal fcp frame (cts=0x01)\n"); + break; + case 0x02: + printf("ehs fcp frame (cts=0x02)\n"); + break; + case 0x03: + printf("havi fcp frame (cts=0x03)\n"); + break; + case 0x0e: + printf("vendor specific fcp frame (cts=0x0e)\n"); + break; + case 0x0f: + printf("extended cts\n"); + break; + default: + printf("reserved fcp frame (ctx=0x%02x)\n", frame->cts); + break; + } + return 1; + } + + return 0; +} + diff --git a/nosy-dump.c b/nosy-dump.c index 1f3f74d..993043f 100644 --- a/nosy-dump.c +++ b/nosy-dump.c @@ -13,14 +13,22 @@ #include <byteswap.h> #include <termios.h> -#include "nosy-user.h" #include "list.h" +#include "nosy-user.h" +#include "nosy-dump.h" -#define array_length(array) (sizeof(array) / sizeof(array[0])) - +enum { + PACKET_FIELD_DETAIL = 0x01, + PACKET_FIELD_DATA_LENGTH = 0x02, + /* Marks the fields we print in transaction view. */ + PACKET_FIELD_TRANSACTION = 0x04 +}; static void print_packet(unsigned long *data, size_t length); +static void +decode_link_packet(struct link_packet *packet, size_t length, + int include_flags, int exclude_flags); static char *option_nosy_device = "/dev/nosy"; static char *option_view = "packet"; @@ -32,10 +40,6 @@ static int option_cycle_start; static int option_version; static int option_verbose; -#define SPEED_100 0x0 -#define SPEED_200 0x1 -#define SPEED_400 0x2 - enum { VIEW_TRANSACTION, VIEW_PACKET, @@ -110,254 +114,6 @@ static const struct poptOption options[] = { POPT_TABLEEND }; -struct phy_packet { - unsigned long timestamp; - - union { - struct { - unsigned int zero : 24; - unsigned int phy_id : 6; - unsigned int identifier : 2; - } common, link_on; - struct { - unsigned int zero : 16; - unsigned int gap_count : 6; - unsigned int set_gap_count : 1; - unsigned int set_root : 1; - unsigned int root_id : 6; - unsigned int identifier : 2; - } phy_config; - struct { - unsigned int more_packets : 1; - unsigned int initiated_reset : 1; - unsigned int port2 : 2; - unsigned int port1 : 2; - unsigned int port0 : 2; - unsigned int power_class : 3; - unsigned int contender : 1; - unsigned int phy_delay : 2; - unsigned int phy_speed : 2; - unsigned int gap_count : 6; - unsigned int link_active : 1; - unsigned int extended : 1; - unsigned int phy_id : 6; - unsigned int identifier : 2; - } self_id; - - struct { - unsigned int more_packets : 1; - unsigned int reserved1 : 1; - unsigned int porth : 2; - unsigned int portg : 2; - unsigned int portf : 2; - unsigned int porte : 2; - unsigned int portd : 2; - unsigned int portc : 2; - unsigned int portb : 2; - unsigned int porta : 2; - unsigned int reserved0 : 2; - unsigned int sequence : 3; - unsigned int extended : 1; - unsigned int phy_id : 6; - unsigned int identifier : 2; - } ext_self_id; - }; - - unsigned long inverted; - unsigned long ack; -}; - -#define PHY_PACKET_CONFIGURATION 0x00 -#define PHY_PACKET_LINK_ON 0x01 -#define PHY_PACKET_SELF_ID 0x02 - -struct link_packet { - unsigned long timestamp; - - union { - struct { - unsigned int priority : 4; - unsigned int tcode : 4; - unsigned int rt : 2; - unsigned int tlabel : 6; - unsigned int destination : 16; - - unsigned int offset_high : 16; - unsigned int source : 16; - - unsigned long offset_low; - } common; - - struct { - unsigned int priority : 4; - unsigned int tcode : 4; - unsigned int rt : 2; - unsigned int tlabel : 6; - unsigned int destination : 16; - - unsigned int offset_high : 16; - unsigned int source : 16; - - unsigned long offset_low; - - unsigned long crc; - } read_quadlet; - - struct { - unsigned int priority : 4; - unsigned int tcode : 4; - unsigned int rt : 2; - unsigned int tlabel : 6; - unsigned int destination : 16; - - unsigned int reserved0 : 12; - unsigned int rcode : 4; - unsigned int source : 16; - - unsigned long reserved1; - - unsigned long data; - - unsigned long crc; - } read_quadlet_response; - - struct { - unsigned int priority : 4; - unsigned int tcode : 4; - unsigned int rt : 2; - unsigned int tlabel : 6; - unsigned int destination : 16; - - unsigned int offset_high : 16; - unsigned int source : 16; - - unsigned long offset_low; - - unsigned int extended_tcode : 16; - unsigned int data_length : 16; - - unsigned long crc; - } read_block; - - struct { - unsigned int priority : 4; - unsigned int tcode : 4; - unsigned int rt : 2; - unsigned int tlabel : 6; - unsigned int destination : 16; - - unsigned int reserved0 : 12; - unsigned int rcode : 4; - unsigned int source : 16; - - unsigned long reserved1; - - unsigned int extended_tcode : 16; - unsigned int data_length : 16; - - unsigned long crc; - - unsigned long data[0]; - - /* crc and ack follows. */ - - } read_block_response; - - struct { - unsigned int priority : 4; - unsigned int tcode : 4; - unsigned int rt : 2; - unsigned int tlabel : 6; - unsigned int destination : 16; - - unsigned int offset_high : 16; - unsigned int source : 16; - - unsigned long offset_low; - - unsigned long data; - - unsigned long crc; - - } write_quadlet; - - struct { - unsigned int priority : 4; - unsigned int tcode : 4; - unsigned int rt : 2; - unsigned int tlabel : 6; - unsigned int destination : 16; - - unsigned int offset_high : 16; - unsigned int source : 16; - - unsigned int offset_low : 32; - - unsigned int extended_tcode : 16; - unsigned int data_length : 16; - - unsigned long crc; - unsigned long data[0]; - - /* crc and ack follows. */ - - } write_block; - - struct { - unsigned int priority : 4; - unsigned int tcode : 4; - unsigned int rt : 2; - unsigned int tlabel : 6; - unsigned int destination : 16; - - unsigned int reserved0 : 12; - unsigned int rcode : 4; - unsigned int source : 16; - - unsigned long reserved1; - - unsigned long crc; - } write_response; - - struct { - unsigned int priority : 4; - unsigned int tcode : 4; - unsigned int rt : 2; - unsigned int tlabel : 6; - unsigned int destination : 16; - - unsigned int offset_high : 16; - unsigned int source : 16; - - unsigned long offset_low; - - unsigned long data; - - unsigned long crc; - } cycle_start; - - struct { - unsigned int sy : 4; - unsigned int tcode : 4; - unsigned int channel : 6; - unsigned int tag : 2; - unsigned int data_length : 16; - - unsigned long crc; - } iso_data; - - }; - -}; - -struct subaction { - unsigned long ack; - size_t length; - struct list link; - struct link_packet packet; -}; - - struct subaction * subaction_create(unsigned long *data, size_t length) { @@ -378,12 +134,6 @@ subaction_destroy(struct subaction *sa) free(sa); } -struct link_transaction { - int request_node, response_node, tlabel; - struct list request_list, response_list; - struct list link; -}; - struct list pending_transaction_list = { &pending_transaction_list, &pending_transaction_list }; @@ -429,17 +179,42 @@ link_transaction_destroy(struct link_transaction *t) free(t); } +struct protocol_decoder { + const char *name; + int (*decode)(struct link_transaction *t); +}; + +static struct protocol_decoder protocol_decoders[] = { + { "FCP", decode_fcp } +}; + void handle_transaction(struct link_transaction *t) { struct subaction *sa; - - printf("completed transaction (%04x->%04x, tlabel=%x)\r\n", - t->request_node, t->response_node, t->tlabel); - list_for_each_entry(sa, &t->request_list, link) - print_packet((unsigned long *) &sa->packet, sa->length); - list_for_each_entry(sa, &t->response_list, link) - print_packet((unsigned long *) &sa->packet, sa->length); + int i; + + for (i = 0; i < array_length(protocol_decoders); i++) + if (protocol_decoders[i].decode(t)) + break; + + /* HACK: decode only fcp right now. */ + return; + + decode_link_packet(&t->request->packet, t->request->length, + PACKET_FIELD_TRANSACTION, 0); + if (t->response) + decode_link_packet(&t->response->packet, t->request->length, + PACKET_FIELD_TRANSACTION, 0); + else + printf("[no response]"); + + if (option_verbose) { + list_for_each_entry(sa, &t->request_list, link) + print_packet((unsigned long *) &sa->packet, sa->length); + list_for_each_entry(sa, &t->response_list, link) + print_packet((unsigned long *) &sa->packet, sa->length); + } printf("\r\n"); link_transaction_destroy(t); @@ -525,11 +300,6 @@ struct packet_info { int field_count; }; -enum { - PACKET_FIELD_DETAIL = 0x01, - PACKET_FIELD_DATA_LENGTH = 0x02 -}; - struct packet_field { const char *name; /* Short name for field. */ int offset; /* Location of field, specified in bits. @@ -539,23 +309,23 @@ struct packet_field { const char * const *value_names; }; -#define COMMON_REQUEST_FIELDS \ - { "dest", 0, 16 }, \ - { "tl", 16, 6 }, \ - { "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names }, \ - { "tcode", 24, 4, 0, tcode_names }, \ - { "pri", 28, 4, PACKET_FIELD_DETAIL }, \ - { "src", 32, 16 }, \ - { "offs", 48, 48 } - -#define COMMON_RESPONSE_FIELDS \ - { "dest", 0, 16 }, \ - { "tl", 16, 6 }, \ - { "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names }, \ - { "tcode", 24, 4, 0, tcode_names }, \ - { "pri", 28, 4, PACKET_FIELD_DETAIL }, \ - { "src", 32, 16 }, \ - { "rcode", 48, 4, 0, rcode_names } +#define COMMON_REQUEST_FIELDS \ + { "dest", 0, 16, PACKET_FIELD_TRANSACTION }, \ + { "tl", 16, 6 }, \ + { "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names }, \ + { "tcode", 24, 4, PACKET_FIELD_TRANSACTION, tcode_names }, \ + { "pri", 28, 4, PACKET_FIELD_DETAIL }, \ + { "src", 32, 16, PACKET_FIELD_TRANSACTION }, \ + { "offs", 48, 48, PACKET_FIELD_TRANSACTION } + +#define COMMON_RESPONSE_FIELDS \ + { "dest", 0, 16 }, \ + { "tl", 16, 6 }, \ + { "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names }, \ + { "tcode", 24, 4, 0, tcode_names }, \ + { "pri", 28, 4, PACKET_FIELD_DETAIL }, \ + { "src", 32, 16 }, \ + { "rcode", 48, 4, PACKET_FIELD_TRANSACTION, rcode_names } struct packet_field read_quadlet_request_fields[] = { COMMON_REQUEST_FIELDS, @@ -565,14 +335,14 @@ struct packet_field read_quadlet_request_fields[] = { struct packet_field read_quadlet_response_fields[] = { COMMON_RESPONSE_FIELDS, - { "data", 96, 32 }, + { "data", 96, 32, PACKET_FIELD_TRANSACTION }, { "crc", 128, 32, PACKET_FIELD_DETAIL }, { "ack", 188, 4, 0, ack_names } }; struct packet_field read_block_request_fields[] = { COMMON_REQUEST_FIELDS, - { "data_length", 96, 16 }, + { "data_length", 96, 16, PACKET_FIELD_TRANSACTION }, { "extended_tcode", 112, 16 }, { "crc", 128, 32, PACKET_FIELD_DETAIL }, { "ack", 188, 4, 0, ack_names }, @@ -583,23 +353,23 @@ struct packet_field block_response_fields[] = { { "data_length", 96, 16, PACKET_FIELD_DATA_LENGTH }, { "extended_tcode", 112, 16 }, { "crc", 128, 32, PACKET_FIELD_DETAIL }, - { "data", 160, 0 }, + { "data", 160, 0, PACKET_FIELD_TRANSACTION }, { "crc", -64, 32, PACKET_FIELD_DETAIL }, { "ack", -4, 4, 0, ack_names } }; struct packet_field write_quadlet_request_fields[] = { COMMON_REQUEST_FIELDS, - { "data", 96, 32 }, + { "data", 96, 32, PACKET_FIELD_TRANSACTION }, { "ack", -4, 4, 0, ack_names } }; struct packet_field block_request_fields[] = { COMMON_REQUEST_FIELDS, - { "data_length", 96, 16, PACKET_FIELD_DATA_LENGTH }, - { "extended_tcode", 112, 16 }, + { "data_length", 96, 16, PACKET_FIELD_DATA_LENGTH | PACKET_FIELD_TRANSACTION }, + { "extended_tcode", 112, 16, PACKET_FIELD_TRANSACTION }, { "crc", 128, 32, PACKET_FIELD_DETAIL }, - { "data", 160, 0 }, + { "data", 160, 0, PACKET_FIELD_TRANSACTION }, { "crc", -64, 32, PACKET_FIELD_DETAIL }, { "ack", -4, 4, 0, ack_names } }; @@ -699,7 +469,7 @@ static struct packet_info packet_info[] = { } }; -void +int handle_packet(unsigned long *data, size_t length) { if (length == 0) { @@ -716,6 +486,7 @@ handle_packet(unsigned long *data, size_t length) t = link_transaction_lookup(p->common.source, p->common.destination, p->common.tlabel); sa = subaction_create(data, length); + t->request = sa; if (!list_empty(&t->request_list)) { prev = list_tail(&t->request_list, struct subaction, link); @@ -772,7 +543,8 @@ handle_packet(unsigned long *data, size_t length) } sa = subaction_create(data, length); - + t->response = sa; + if (!list_empty(&t->response_list)) { prev = list_tail(&t->response_list, struct subaction, link); @@ -825,9 +597,11 @@ handle_packet(unsigned long *data, size_t length) case PACKET_OTHER: case PACKET_RESERVED: - return; + return 0; } } + + return 1; } unsigned int get_bits(struct link_packet *packet, int offset, int width) @@ -860,7 +634,9 @@ void dump_data(unsigned char *data, int length) data[byte_index(i)]); } -void decode_link_packet(struct link_packet *packet, size_t length) +static void +decode_link_packet(struct link_packet *packet, size_t length, + int include_flags, int exclude_flags) { struct packet_info *pi; int data_length = 0; @@ -872,7 +648,9 @@ void decode_link_packet(struct link_packet *packet, size_t length) struct packet_field *f = &pi->fields[i]; int offset; - if ((f->flags & PACKET_FIELD_DETAIL) && !option_verbose) + if (f->flags & exclude_flags) + continue; + if (include_flags && !(f->flags & include_flags)) continue; if (f->offset < 0) @@ -989,7 +767,8 @@ print_packet(unsigned long *data, size_t length) else { struct link_packet *packet = (struct link_packet *) data; - decode_link_packet(packet, length); + decode_link_packet(packet, length, 0, + option_verbose ? 0 : PACKET_FIELD_DETAIL); } if (option_hex) { diff --git a/nosy-dump.h b/nosy-dump.h new file mode 100644 index 0000000..d8bcb61 --- /dev/null +++ b/nosy-dump.h @@ -0,0 +1,292 @@ +#ifndef __nosy_dump_h__ +#define __nosy_dump_h__ + +#define array_length(array) (sizeof(array) / sizeof(array[0])) + +#define TCODE_WRITE_QUADLET 0x0 +#define TCODE_WRITE_BLOCK 0x1 +#define TCODE_WRITE_RESPONSE 0x2 +#define TCODE_READ_QUADLET 0x4 +#define TCODE_READ_BLOCK 0x5 +#define TCODE_READ_QUADLET_RESPONSE 0x6 +#define TCODE_READ_BLOCK_RESPONSE 0x7 +#define TCODE_CYCLE_START 0x8 +#define TCODE_LOCK_REQUEST 0x9 +#define TCODE_ISO_DATA 0xa +#define TCODE_LOCK_RESPONSE 0xb +#define TCODE_PHY_PACKET 0x10 + +#define ACK_NO_ACK 0x0 +#define ACK_COMPLETE 0x1 +#define ACK_PENDING 0x2 +#define ACK_BUSY_X 0x4 +#define ACK_BUSY_A 0x5 +#define ACK_BUSY_B 0x6 +#define ACK_DATA_ERROR 0xd +#define ACK_TYPE_ERROR 0xe + +#define ACK_DONE(a) ((a >> 2) == 0) +#define ACK_BUSY(a) ((a >> 2) == 1) +#define ACK_ERROR(a) ((a >> 2) == 3) + +#define SPEED_100 0x0 +#define SPEED_200 0x1 +#define SPEED_400 0x2 + +struct phy_packet { + unsigned long timestamp; + + union { + struct { + unsigned int zero : 24; + unsigned int phy_id : 6; + unsigned int identifier : 2; + } common, link_on; + struct { + unsigned int zero : 16; + unsigned int gap_count : 6; + unsigned int set_gap_count : 1; + unsigned int set_root : 1; + unsigned int root_id : 6; + unsigned int identifier : 2; + } phy_config; + struct { + unsigned int more_packets : 1; + unsigned int initiated_reset : 1; + unsigned int port2 : 2; + unsigned int port1 : 2; + unsigned int port0 : 2; + unsigned int power_class : 3; + unsigned int contender : 1; + unsigned int phy_delay : 2; + unsigned int phy_speed : 2; + unsigned int gap_count : 6; + unsigned int link_active : 1; + unsigned int extended : 1; + unsigned int phy_id : 6; + unsigned int identifier : 2; + } self_id; + + struct { + unsigned int more_packets : 1; + unsigned int reserved1 : 1; + unsigned int porth : 2; + unsigned int portg : 2; + unsigned int portf : 2; + unsigned int porte : 2; + unsigned int portd : 2; + unsigned int portc : 2; + unsigned int portb : 2; + unsigned int porta : 2; + unsigned int reserved0 : 2; + unsigned int sequence : 3; + unsigned int extended : 1; + unsigned int phy_id : 6; + unsigned int identifier : 2; + } ext_self_id; + }; + + unsigned long inverted; + unsigned long ack; +}; + +#define PHY_PACKET_CONFIGURATION 0x00 +#define PHY_PACKET_LINK_ON 0x01 +#define PHY_PACKET_SELF_ID 0x02 + +struct link_packet { + unsigned long timestamp; + + union { + struct { + unsigned int priority : 4; + unsigned int tcode : 4; + unsigned int rt : 2; + unsigned int tlabel : 6; + unsigned int destination : 16; + + unsigned int offset_high : 16; + unsigned int source : 16; + + unsigned long offset_low; + } common; + + struct { + unsigned int priority : 4; + unsigned int tcode : 4; + unsigned int rt : 2; + unsigned int tlabel : 6; + unsigned int destination : 16; + + unsigned int offset_high : 16; + unsigned int source : 16; + + unsigned long offset_low; + + unsigned long crc; + } read_quadlet; + + struct { + unsigned int priority : 4; + unsigned int tcode : 4; + unsigned int rt : 2; + unsigned int tlabel : 6; + unsigned int destination : 16; + + unsigned int reserved0 : 12; + unsigned int rcode : 4; + unsigned int source : 16; + + unsigned long reserved1; + + unsigned long data; + + unsigned long crc; + } read_quadlet_response; + + struct { + unsigned int priority : 4; + unsigned int tcode : 4; + unsigned int rt : 2; + unsigned int tlabel : 6; + unsigned int destination : 16; + + unsigned int offset_high : 16; + unsigned int source : 16; + + unsigned long offset_low; + + unsigned int extended_tcode : 16; + unsigned int data_length : 16; + + unsigned long crc; + } read_block; + + struct { + unsigned int priority : 4; + unsigned int tcode : 4; + unsigned int rt : 2; + unsigned int tlabel : 6; + unsigned int destination : 16; + + unsigned int reserved0 : 12; + unsigned int rcode : 4; + unsigned int source : 16; + + unsigned long reserved1; + + unsigned int extended_tcode : 16; + unsigned int data_length : 16; + + unsigned long crc; + + unsigned long data[0]; + + /* crc and ack follows. */ + + } read_block_response; + + struct { + unsigned int priority : 4; + unsigned int tcode : 4; + unsigned int rt : 2; + unsigned int tlabel : 6; + unsigned int destination : 16; + + unsigned int offset_high : 16; + unsigned int source : 16; + + unsigned long offset_low; + + unsigned long data; + + unsigned long crc; + + } write_quadlet; + + struct { + unsigned int priority : 4; + unsigned int tcode : 4; + unsigned int rt : 2; + unsigned int tlabel : 6; + unsigned int destination : 16; + + unsigned int offset_high : 16; + unsigned int source : 16; + + unsigned int offset_low : 32; + + unsigned int extended_tcode : 16; + unsigned int data_length : 16; + + unsigned long crc; + unsigned long data[0]; + + /* crc and ack follows. */ + + } write_block; + + struct { + unsigned int priority : 4; + unsigned int tcode : 4; + unsigned int rt : 2; + unsigned int tlabel : 6; + unsigned int destination : 16; + + unsigned int reserved0 : 12; + unsigned int rcode : 4; + unsigned int source : 16; + + unsigned long reserved1; + + unsigned long crc; + } write_response; + + struct { + unsigned int priority : 4; + unsigned int tcode : 4; + unsigned int rt : 2; + unsigned int tlabel : 6; + unsigned int destination : 16; + + unsigned int offset_high : 16; + unsigned int source : 16; + + unsigned long offset_low; + + unsigned long data; + + unsigned long crc; + } cycle_start; + + struct { + unsigned int sy : 4; + unsigned int tcode : 4; + unsigned int channel : 6; + unsigned int tag : 2; + unsigned int data_length : 16; + + unsigned long crc; + } iso_data; + + }; + +}; + +struct subaction { + unsigned long ack; + size_t length; + struct list link; + struct link_packet packet; +}; + +struct link_transaction { + int request_node, response_node, tlabel; + struct subaction *request, *response; + struct list request_list, response_list; + struct list link; +}; + +int decode_fcp(struct link_transaction *t); + +#endif /* __nosy_dump_h__ */ diff --git a/nosy-user.h b/nosy-user.h index 4cfe49f..c9a1682 100644 --- a/nosy-user.h +++ b/nosy-user.h @@ -1,5 +1,5 @@ -#ifndef __pcilynx_user_h -#define __pcilynx_user_h +#ifndef __nosy_user_h +#define __nosy_user_h #include <asm/ioctl.h> #include <asm/types.h> @@ -9,32 +9,6 @@ #define NOSY_IOC_STOP _IO('&', 2) #define NOSY_IOC_FILTER _IOW('&', 2, __u32) -#define TCODE_WRITE_QUADLET 0x0 -#define TCODE_WRITE_BLOCK 0x1 -#define TCODE_WRITE_RESPONSE 0x2 -#define TCODE_READ_QUADLET 0x4 -#define TCODE_READ_BLOCK 0x5 -#define TCODE_READ_QUADLET_RESPONSE 0x6 -#define TCODE_READ_BLOCK_RESPONSE 0x7 -#define TCODE_CYCLE_START 0x8 -#define TCODE_LOCK_REQUEST 0x9 -#define TCODE_ISO_DATA 0xa -#define TCODE_LOCK_RESPONSE 0xb -#define TCODE_PHY_PACKET 0x10 - -#define ACK_NO_ACK 0x0 -#define ACK_COMPLETE 0x1 -#define ACK_PENDING 0x2 -#define ACK_BUSY_X 0x4 -#define ACK_BUSY_A 0x5 -#define ACK_BUSY_B 0x6 -#define ACK_DATA_ERROR 0xd -#define ACK_TYPE_ERROR 0xe - -#define ACK_DONE(a) ((a >> 2) == 0) -#define ACK_BUSY(a) ((a >> 2) == 1) -#define ACK_ERROR(a) ((a >> 2) == 3) - struct nosy_stats { __u32 total_packet_count; __u32 lost_packet_count; @@ -48,4 +22,4 @@ struct nosy_stats { * quadlet with ack */ -#endif /* __pcilynx_user_h */ +#endif /* __nosy_user_h */ @@ -38,6 +38,7 @@ #include "nosy.h" #include "nosy-user.h" +#define TCODE_PHY_PACKET 0x10 #define PCI_DEVICE_ID_TI_PCILYNX 0x8000 #define notify(s, args...) printk(KERN_NOTICE s, ## args) |