From 4477c392b87bdaaae6780ccadc9a4f4923f2b344 Mon Sep 17 00:00:00 2001 From: root Date: Mon, 16 Jan 2017 12:16:27 +0000 Subject: add source --- src/Makefile.am | 53 +++++++++++++++++ src/hexdump.c | 87 ++++++++++++++++++++++++++++ src/project.h | 76 +++++++++++++++++++++++++ src/prototypes.h | 12 ++++ src/twa.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/twa.h | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/twa_t.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.c | 23 ++++++++ src/version.c | 15 +++++ 9 files changed, 754 insertions(+) create mode 100644 src/Makefile.am create mode 100644 src/hexdump.c create mode 100644 src/project.h create mode 100644 src/prototypes.h create mode 100644 src/twa.c create mode 100644 src/twa.h create mode 100644 src/twa_t.c create mode 100644 src/util.c create mode 100644 src/version.c diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..85bb6b0 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,53 @@ +# +# +# Makefile.am: +# +# Copyright (c) 2017 James McKenzie , +# All rights reserved. +# +# +# + +CPROTO=cproto +AM_CPPFLAGS = + +noinst_HEADERS=project.h prototypes.h + +bin_PROGRAMS = twa_t + +SRCS=twa_t.c twa.c version.c util.c hexdump.c +twa_t_SOURCES = ${SRCS} +twa_t_LDADD = + +AM_CFLAGS=-g + +twa_t_LDFLAGS = + +BUILT_SOURCES = version.h + + +VFD=${srcdir}/.. +VF=${shell cat ${VFD}/version-files} +VFS=${VF:%=${VFD}/%} +VCHK=${shell cat ${VFS} | @MD5SUM@ | @AWK@ '{print $$1 }' } +VNUM=${shell @GREP@ ${VCHK} ${VFD}/version-md5sums | @AWK@ '{ print $$2 }' } +VDEF=${shell echo `cat ${VFD}/version-major`.`cat ${VFD}/version-minor`.`cat ${VFD}/version-micro` } + +protos: + echo > prototypes.h + ${CPROTO} -v ${INCLUDES} ${SRCS} > prototypes.tmp + mv -f prototypes.tmp prototypes.h + + + +version.h: $(VFD)/version-files $(VFD)/version-major \ + $(VFD)/version-minor $(VFD)/version-micro \ + $(VFD)/version-md5sums ${VFS} Makefile + if [ .${VNUM} = . ]; then \ + echo "#define VERSION \"twa_t Version ${VDEF} + Edits\"" > version.h; \ + echo ${VDEF}-E > version-num; \ + else \ + echo "#define VERSION \"twa_t Version ${VNUM}\"" > version.h; \ + echo ${VNUM} > version-num; \ + fi + diff --git a/src/hexdump.c b/src/hexdump.c new file mode 100644 index 0000000..1d51d99 --- /dev/null +++ b/src/hexdump.c @@ -0,0 +1,87 @@ +/* + * hexdump.c: + * + * Copyright (c) 2017 James McKenzie , + * All rights reserved. + * + */ + +#include "project.h" + + +static unsigned char +printable (unsigned char c) +{ + + if (c < ' ') + c = '.'; + if (c > 126) + c = '.'; + + return c; +} + + + +void +hexdump (char *prefix, void *_d, size_t os, size_t oe) +{ + unsigned char *d = (unsigned char *) _d; + static unsigned char zero[0x10]; + + size_t s, e; + size_t i, j; + int gap = 0; + + s = os & ~15; + e = (oe - 1) | 15; + e++; + + for (i = s; i < e; i += 0x10) + { + + if (((i > s) && ((i + 0x10) < oe)) && !memcmp (&d[i], zero, 0x10)) + { + gap = 1; + continue; + } + if (gap) + { + printf ("%s ...\n", prefix); + gap = 0; + } + + + printf ("%s %06lx:", prefix, i); + + for (j = i; j < (i + 0x10); ++j) + { + + if (j == 8) + printf (" "); + + if ((j < os) || (j >= oe)) + printf (" "); + else + printf (" %02x", d[j]); + } + + printf (" "); + + for (j = i; j < (i + 0x10); ++j) + { + + if (j == 8) + printf (" "); + + if ((j < os) || (j >= oe)) + printf (" "); + else + printf ("%c", printable (d[j])); + } + + + + printf ("\n"); + } +} diff --git a/src/project.h b/src/project.h new file mode 100644 index 0000000..9126217 --- /dev/null +++ b/src/project.h @@ -0,0 +1,76 @@ +/* + * project.h: + * + * Copyright (c) 2017 James McKenzie , + * All rights reserved. + * + */ + +#ifndef __PROJECT_H__ +#define __PROJECT_H__ + + +#include "config.h" + +#ifdef TM_IN_SYS_TIME +#include +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#else +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#include +#endif + +#include +#include + +#ifdef HAVE_MALLOC_H +#include +#endif + +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_STRINGS_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#if defined(HAVE_STDINT_H) +#include +#elif defined(HAVE_SYS_INT_TYPES_H) +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include + +#define cpu_to_le32(a) htole32(a) +#define cpu_to_le16(a) htole16(a) +#define le16_to_cpu(a) le16toh(a) +#define le32_to_cpu(a) le32toh(a) + +#include "twa.h" + + +#include "prototypes.h" + +#endif /* __PROJECT_H__ */ diff --git a/src/prototypes.h b/src/prototypes.h new file mode 100644 index 0000000..2a749a2 --- /dev/null +++ b/src/prototypes.h @@ -0,0 +1,12 @@ +/* hexdump.c */ +void hexdump(char *prefix, void *_d, size_t os, size_t oe); +/* twa.c */ +ssize_t twa_get_parameter(int fd, int table_id, int parameter_id, void *data, size_t data_len); +int twa_set_parameter(int fd, int table_id, int parameter_id, void *data, size_t data_len); +/* twa_t.c */ +void tw_dt_to_tm(TW_DateTime *tw_dt, struct tm *tm); +void tm_to_tw_dt(struct tm *tm, TW_DateTime *tw_dt); +int main(int argc, char *argv[]); +/* util.c */ +void *xmalloc(size_t s); +/* version.c */ diff --git a/src/twa.c b/src/twa.c new file mode 100644 index 0000000..9cd89b2 --- /dev/null +++ b/src/twa.c @@ -0,0 +1,157 @@ +/* + * twa.c: + * + * Copyright (c) 2017 James McKenzie , + * All rights reserved. + * + */ + +#include "project.h" + +ssize_t +twa_get_parameter (int fd, int table_id, int parameter_id, void *data, + size_t data_len) +{ + + TW_Command *command; + TW_Param_Apache *param; + TW_Command_Apache_Header *header; + TW_Ioctl_Buf_Apache *tw_ioctl_apache; + int rc; + size_t buffer_len, ret_len; + char error[512]; + + buffer_len = data_len + sizeof (TW_Param_Apache); + + tw_ioctl_apache = xmalloc (sizeof (TW_Ioctl_Buf_Apache) + buffer_len); + + memset (tw_ioctl_apache, 0, sizeof (TW_Ioctl_Buf_Apache) + buffer_len); + + tw_ioctl_apache->driver_command.control_code = + TW_IOCTL_FIRMWARE_PASS_THROUGH; + tw_ioctl_apache->driver_command.buffer_length = buffer_len; + + header = + (TW_Command_Apache_Header *) & (tw_ioctl_apache->firmware_command.header); + header->header_desc.size_header = sizeof (*header); + + command = + (TW_Command *) & (tw_ioctl_apache->firmware_command.command.oldcommand); + + command->byte0.opcode = TW_OP_GET_PARAM; + command->byte0.sgl_offset = 0x2; + + command->size = TW_COMMAND_SIZE; + + command->byte6.parameter_count = cpu_to_le16 (1); + + param = (TW_Param_Apache *) tw_ioctl_apache->data_buffer; + + param->table_id = cpu_to_le16 (table_id | 0x8000); + param->parameter_id = cpu_to_le16 (parameter_id); + param->parameter_size_bytes = cpu_to_le16 (data_len); + + rc = ioctl (fd, TW_IOCTL_FIRMWARE_PASS_THROUGH, tw_ioctl_apache); + + if (rc) + { + fprintf (stderr, + "twa_get_parameter: ioctl TW_IOCTL_FIRMWARE_PASS_THROUGH failed: %m\n"); + return -1; + } + + if (header->status_block.error) + { + memset (error, 0, sizeof (error)); + memcpy (error, header->err_specific_desc, + sizeof (header->err_specific_desc)); + + fprintf (stderr, + "twa_get_parameter: controller returns error: (0x%x) %s\n", + le16_to_cpu (header->status_block.error), error + 1); + return -1; + } + + ret_len = le16_to_cpu (param->actual_parameter_size_bytes); + + if (ret_len > data_len) + { + fprintf (stderr, + "twa_get_parameter: buffer passed for table 0x%x, parameter 0x%x too short: given %d bytes need %d\n", + table_id, parameter_id, data_len, ret_len); + return -1; + } + + memcpy (data, param->data, ret_len); + + return ret_len; +} + +int +twa_set_parameter (int fd, int table_id, int parameter_id, void *data, + size_t data_len) +{ + + TW_Command *command; + TW_Param_Apache *param; + TW_Command_Apache_Header *header; + TW_Ioctl_Buf_Apache *tw_ioctl_apache; + int rc; + size_t buffer_len, ret_len; + char error[512]; + + buffer_len = data_len + sizeof (TW_Param_Apache); + + tw_ioctl_apache = xmalloc (sizeof (TW_Ioctl_Buf_Apache) + buffer_len); + + memset (tw_ioctl_apache, 0, sizeof (TW_Ioctl_Buf_Apache) + buffer_len); + + tw_ioctl_apache->driver_command.control_code = + TW_IOCTL_FIRMWARE_PASS_THROUGH; + tw_ioctl_apache->driver_command.buffer_length = buffer_len; + + header = + (TW_Command_Apache_Header *) & (tw_ioctl_apache->firmware_command.header); + header->header_desc.size_header = sizeof (*header); + + command = + (TW_Command *) & (tw_ioctl_apache->firmware_command.command.oldcommand); + + command->byte0.opcode = TW_OP_SET_PARAM; + command->byte0.sgl_offset = 0x2; + + command->size = TW_COMMAND_SIZE; + + command->byte6.parameter_count = cpu_to_le16 (1); + + param = (TW_Param_Apache *) tw_ioctl_apache->data_buffer; + + param->table_id = cpu_to_le16 (table_id | 0x8000); + param->parameter_id = cpu_to_le16 (parameter_id); + param->parameter_size_bytes = cpu_to_le16 (data_len); + + memcpy (param->data, data, data_len); + + rc = ioctl (fd, TW_IOCTL_FIRMWARE_PASS_THROUGH, tw_ioctl_apache); + + if (rc) + { + fprintf (stderr, + "twa_get_parameter: ioctl TW_IOCTL_FIRMWARE_PASS_THROUGH failed: %m\n"); + return -1; + } + + if (header->status_block.error) + { + memset (error, 0, sizeof (error)); + memcpy (error, header->err_specific_desc, + sizeof (header->err_specific_desc)); + + fprintf (stderr, + "twa_get_parameter: controller returns error: (0x%x) %s\n", + le16_to_cpu (header->status_block.error), error + 1); + return -1; + } + + return 0; +} diff --git a/src/twa.h b/src/twa.h new file mode 100644 index 0000000..413e70b --- /dev/null +++ b/src/twa.h @@ -0,0 +1,169 @@ +/* + * twa.h: + * + * Copyright (c) 2017 James McKenzie , + * All rights reserved. + * + */ + +#ifndef _TWA_H_ +#define _TWA_H_ + +#define TWA_PACKED __attribute__ (( packed )) + +typedef uint64_t dma_addr_t; + + +#define TW_SENSE_DATA_LENGTH 18 + +#define TW_COMMAND_SIZE (sizeof(dma_addr_t) > 4 ? 5 : 4) +#define TW_APACHE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 72 : 109) +#define TW_ESCALADE_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 41 : 62) +#define TW_PADDING_LENGTH (sizeof(dma_addr_t) > 4 ? 8 : 0) + +typedef struct TWA_PACKED TAG_TW_SG_Entry +{ + dma_addr_t address; + uint32_t length; +} TW_SG_Entry; + + +typedef struct TWA_PACKED TAG_TW_Command_Apache_Header +{ + unsigned char sense_data[TW_SENSE_DATA_LENGTH]; + struct TWA_PACKED + { + char reserved[4]; + unsigned short error; + unsigned char padding; + unsigned char severity__reserved; + } status_block; + unsigned char err_specific_desc[98]; + struct TWA_PACKED + { + unsigned char size_header; + unsigned short reserved; + unsigned char size_sense; + } header_desc; +} TW_Command_Apache_Header; + + +/* Command Packet */ +typedef struct TWA_PACKED TW_Command +{ + /* First DWORD */ + struct TWA_PACKED + { + unsigned char opcode:5; + unsigned char sgl_offset:3; + } byte0; + unsigned char size; + unsigned char request_id; + struct TWA_PACKED + { + unsigned char unit:4; + unsigned char host_id:4; + } byte3; + /* Second DWORD */ + unsigned char status; + unsigned char flags; + + union + { + unsigned short block_count; + unsigned short parameter_count; + unsigned short message_credits; + } byte6; + union + { + struct TWA_PACKED + { + uint32_t lba; + TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH]; + dma_addr_t padding; + } io; + struct + { + TW_SG_Entry sgl[TW_ESCALADE_MAX_SGL_LENGTH]; + uint32_t padding; + dma_addr_t padding2; + } param; + } byte8_offset; +} TW_Command; + +typedef struct TWA_PACKED TAG_TW_Command_Apache +{ + unsigned char opcode__reserved; + unsigned char unit; + unsigned short request_id__lunl; + unsigned char status; + unsigned char sgl_offset; + unsigned short sgl_entries__lunh; + unsigned char cdb[16]; + TW_SG_Entry sg_list[TW_APACHE_MAX_SGL_LENGTH]; + unsigned char padding[TW_PADDING_LENGTH]; +} TW_Command_Apache; + + +typedef struct TWA_PACKED TAG_TW_Command_Full +{ + TW_Command_Apache_Header header; + union + { + TW_Command oldcommand; + TW_Command_Apache newcommand; + } command; +} TW_Command_Full; + + + +typedef struct TWA_PACKED TAG_TW_Ioctl_Driver_Command +{ + unsigned int control_code; + unsigned int status; + unsigned int unique_id; + unsigned int sequence_id; + unsigned int os_specific; + unsigned int buffer_length; +} TW_Ioctl_Driver_Command; + + + +typedef struct TWA_PACKED TAG_TW_Ioctl_Apache +{ + TW_Ioctl_Driver_Command driver_command; + char padding[488]; + TW_Command_Full firmware_command; + char data_buffer[0]; +} TW_Ioctl_Buf_Apache; + +typedef struct TWA_PACKED +{ + unsigned short table_id; + unsigned short parameter_id; + unsigned short parameter_size_bytes; + unsigned short actual_parameter_size_bytes; + unsigned char data[0]; +} TW_Param_Apache, *PTW_Param_Apache; + +typedef struct +{ + uint8_t resv; + uint8_t tw_sec; + uint8_t tw_min; + uint8_t tw_hour; + uint8_t tw_day; + uint8_t tw_month; + uint16_t tw_year; +} TW_DateTime; + +#define TW_IOCTL_FIRMWARE_PASS_THROUGH 0x108 + +#define TW_OP_GET_PARAM 0x12 +#define TW_OP_SET_PARAM 0x13 + +#define TW_TIMEKEEP_TABLE 0x040A +#define TW_TIMEKEEP_DATETIME 0x4 + + +#endif /* _TWA_H_ */ diff --git a/src/twa_t.c b/src/twa_t.c new file mode 100644 index 0000000..cfebb96 --- /dev/null +++ b/src/twa_t.c @@ -0,0 +1,162 @@ +/* + * twa_t.c: + * + * Copyright (c) 2017 James McKenzie , + * All rights reserved. + * + */ + +#include "project.h" + +void +tw_dt_to_tm (TW_DateTime * tw_dt, struct tm *tm) +{ + memset (tm, 0, sizeof (*tm)); + + tm->tm_sec = tw_dt->tw_sec; + tm->tm_min = tw_dt->tw_min; + tm->tm_hour = tw_dt->tw_hour; + tm->tm_mday = tw_dt->tw_day; + tm->tm_mon = tw_dt->tw_month - 1; + tm->tm_year = tw_dt->tw_year - 1900; +} + + + +void +tm_to_tw_dt (struct tm *tm, TW_DateTime * tw_dt) +{ + memset (tw_dt, 0, sizeof (*tw_dt)); + + tw_dt->tw_sec = tm->tm_sec; + tw_dt->tw_min = tm->tm_min; + tw_dt->tw_hour = tm->tm_hour; + tw_dt->tw_day = tm->tm_mday; + tw_dt->tw_month = tm->tm_mon + 1; + tw_dt->tw_year = tm->tm_year + 1900; +} + + +static int +show_ctrl_time (int fd) +{ + TW_DateTime dt; + ssize_t ret; + struct tm tm; + + + ret = + twa_get_parameter (fd, TW_TIMEKEEP_TABLE, TW_TIMEKEEP_DATETIME, &dt, + sizeof (dt)); + + if (ret != sizeof (dt)) + { + fprintf (stderr, "Failed to get controller time\n"); + return -1; + } + + tw_dt_to_tm (&dt, &tm); + + printf ("Controller time is: %s", asctime (&tm)); + + return 0; +} + + + +static int +set_ctrl_time (int fd) +{ + TW_DateTime dt; + int ret; + struct tm tm; + time_t t; + + + time (&t); + + localtime_r (&t, &tm); + + tm_to_tw_dt (&tm, &dt); + + ret = + twa_set_parameter (fd, TW_TIMEKEEP_TABLE, TW_TIMEKEEP_DATETIME, &dt, + sizeof (dt)); + + if (ret) + { + fprintf (stderr, "Failed to set controller time\n"); + return -1; + } + return 0; +} + + +static int +check_ctrl_time (int fd) +{ + TW_DateTime dt; + ssize_t ret; + struct tm tm; + time_t ctrl_time, local_time; + double d; + int rc = 0; + + ret = + twa_get_parameter (fd, TW_TIMEKEEP_TABLE, TW_TIMEKEEP_DATETIME, &dt, + sizeof (dt)); + + if (ret != sizeof (dt)) + { + fprintf (stderr, "Failed to get controller time\n"); + rc |= -1; + return rc; + } + + tw_dt_to_tm (&dt, &tm); + + printf ("Controller time is: %s", asctime (&tm)); + + ctrl_time = mktime (&tm); + + time (&local_time); + localtime_r (&local_time, &tm); + local_time = mktime (&tm); + + d = difftime (local_time, ctrl_time); + + printf ("Controller time difference is %.1lf seconds\n", d); + + if ((d > 15.0) || (d < -15.0)) + { + printf ("Setting controller time\n"); + rc |= set_ctrl_time (fd); + rc |= show_ctrl_time (fd); + } + + return rc; +} + + +int +main (int argc, char *argv[]) +{ + char *dev = "/dev/twa0"; + int fd; + int ret = 0; + + if (argc == 2) + dev = argv[1]; + + fd = open (dev, O_RDWR); + + if (fd < 0) + { + fprintf (stderr, "Failed to open %s: %m\n", dev); + ret |= -1; + return ret; + } + + + return check_ctrl_time (fd); +} diff --git a/src/util.c b/src/util.c new file mode 100644 index 0000000..022e04b --- /dev/null +++ b/src/util.c @@ -0,0 +1,23 @@ +/* + * util.c: + * + * Copyright (c) 2017 James McKenzie , + * All rights reserved. + * + */ + +#include "project.h" + +void * +xmalloc (size_t s) +{ + void *ret = malloc (s); + + if (!ret) + { + fprintf (stderr, "malloc(%lu) failed - aborting\n", s); + exit (1); + } + + return ret; +} diff --git a/src/version.c b/src/version.c new file mode 100644 index 0000000..e13290c --- /dev/null +++ b/src/version.c @@ -0,0 +1,15 @@ +/* + * version.c: + * + * Copyright (c) 2017 James McKenzie , + * All rights reserved. + * + */ + +#include "version.h" + +static char * +GetVersion (void) +{ + return VERSION; +} -- cgit v1.2.3