Implemented emergency register requests to analyze a broken bus. stable-1.5
authorFlorian Pose <fp@igh-essen.com>
Mon, 13 May 2013 20:21:19 +0200
branchstable-1.5
changeset 2529 c7e1f2616a9d
parent 2528 8bb574da5da2
child 2530 f8b779c9794e
Implemented emergency register requests to analyze a broken bus.
master/fsm_master.c
master/ioctl.c
master/ioctl.h
master/master.c
master/master.h
master/reg_request.c
master/reg_request.h
tool/Command.cpp
tool/Command.h
tool/CommandRegRead.cpp
tool/CommandRegWrite.cpp
tool/main.cpp
--- a/master/fsm_master.c	Thu Feb 14 11:17:33 2013 +0100
+++ b/master/fsm_master.c	Mon May 13 20:21:19 2013 +0200
@@ -198,7 +198,47 @@
         ec_fsm_master_t *fsm /**< Master state machine. */
         )
 {
+    ec_master_t *master = fsm->master;
+
     fsm->idle = 1;
+
+    // check for emergency requests
+    if (!list_empty(&master->emerg_reg_requests)) {
+        ec_reg_request_t *request;
+
+        // get first request
+        request = list_entry(master->emerg_reg_requests.next,
+                ec_reg_request_t, list);
+        list_del_init(&request->list); // dequeue
+        request->state = EC_INT_REQUEST_BUSY;
+
+        if (request->transfer_size > fsm->datagram->mem_size) {
+            EC_MASTER_ERR(master, "Emergency request data too large!\n");
+            request->state = EC_INT_REQUEST_FAILURE;
+            wake_up_all(&master->request_queue);
+            fsm->state(fsm); // continue
+            return;
+        }
+
+        if (request->dir != EC_DIR_OUTPUT) {
+            EC_MASTER_ERR(master, "Emergency requests must be"
+                    " write requests!\n");
+            request->state = EC_INT_REQUEST_FAILURE;
+            wake_up_all(&master->request_queue);
+            fsm->state(fsm); // continue
+            return;
+        }
+
+        EC_MASTER_DBG(master, 1, "Writing emergency register request...\n");
+        ec_datagram_apwr(fsm->datagram, request->ring_position,
+                request->address, request->transfer_size);
+        memcpy(fsm->datagram->data, request->data, request->transfer_size);
+        fsm->datagram->device_index = EC_DEVICE_MAIN;
+        request->state = EC_INT_REQUEST_SUCCESS;
+        wake_up_all(&master->request_queue);
+        return;
+    }
+
     ec_datagram_brd(fsm->datagram, 0x0130, 2);
     ec_datagram_zero(fsm->datagram);
     fsm->datagram->device_index = fsm->dev_idx;
--- a/master/ioctl.c	Thu Feb 14 11:17:33 2013 +0100
+++ b/master/ioctl.c	Mon May 13 20:21:19 2013 +0200
@@ -1144,16 +1144,23 @@
         return -EINTR;
     }
 
-    if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
-        up(&master->master_sem);
-        ec_reg_request_clear(&request);
-        EC_MASTER_ERR(master, "Slave %u does not exist!\n",
-                io.slave_position);
-        return -EINVAL;
-    }
-
-    // schedule request.
-    list_add_tail(&request.list, &slave->reg_requests);
+    if (io.emergency) {
+        request.ring_position = io.slave_position;
+        // schedule request.
+        list_add_tail(&request.list, &master->emerg_reg_requests);
+    }
+    else {
+        if (!(slave = ec_master_find_slave(master, 0, io.slave_position))) {
+            up(&master->master_sem);
+            ec_reg_request_clear(&request);
+            EC_MASTER_ERR(master, "Slave %u does not exist!\n",
+                    io.slave_position);
+            return -EINVAL;
+        }
+
+        // schedule request.
+        list_add_tail(&request.list, &slave->reg_requests);
+    }
 
     up(&master->master_sem);
 
--- a/master/ioctl.h	Thu Feb 14 11:17:33 2013 +0100
+++ b/master/ioctl.h	Mon May 13 20:21:19 2013 +0200
@@ -56,7 +56,7 @@
  *
  * Increment this when changing the ioctl interface!
  */
-#define EC_IOCTL_VERSION_MAGIC 27
+#define EC_IOCTL_VERSION_MAGIC 28
 
 // Command-line tool
 #define EC_IOCTL_MODULE                EC_IOR(0x00, ec_ioctl_module_t)
@@ -419,6 +419,7 @@
 typedef struct {
     // inputs
     uint16_t slave_position;
+    uint8_t emergency;
     uint16_t address;
     size_t size;
     uint8_t *data;
--- a/master/master.c	Thu Feb 14 11:17:33 2013 +0100
+++ b/master/master.c	Mon May 13 20:21:19 2013 +0200
@@ -232,6 +232,7 @@
     master->app_cb_data = NULL;
 
     INIT_LIST_HEAD(&master->sii_requests);
+    INIT_LIST_HEAD(&master->emerg_reg_requests);
 
     init_waitqueue_head(&master->request_queue);
 
--- a/master/master.h	Thu Feb 14 11:17:33 2013 +0100
+++ b/master/master.h	Mon May 13 20:21:19 2013 +0200
@@ -305,6 +305,8 @@
     void *app_cb_data; /**< Application callback data. */
 
     struct list_head sii_requests; /**< SII write requests. */
+    struct list_head emerg_reg_requests; /**< Emergency register access
+                                           requests. */
 
     wait_queue_head_t request_queue; /**< Wait queue for external requests
                                        from user space. */
--- a/master/reg_request.c	Thu Feb 14 11:17:33 2013 +0100
+++ b/master/reg_request.c	Mon May 13 20:21:19 2013 +0200
@@ -62,6 +62,7 @@
     reg->address = 0;
     reg->transfer_size = 0;
     reg->state = EC_INT_REQUEST_INIT;
+    reg->ring_position = 0;
     return 0;
 }
 
--- a/master/reg_request.h	Thu Feb 14 11:17:33 2013 +0100
+++ b/master/reg_request.h	Mon May 13 20:21:19 2013 +0200
@@ -54,6 +54,7 @@
     uint16_t address; /**< Register address. */
     size_t transfer_size; /**< Size of the data to transfer. */
     ec_internal_request_state_t state; /**< Request state. */
+    uint16_t ring_position; /**< Ring position for emergency requests. */
 };
 
 /*****************************************************************************/
--- a/tool/Command.cpp	Thu Feb 14 11:17:33 2013 +0100
+++ b/tool/Command.cpp	Mon May 13 20:21:19 2013 +0200
@@ -150,7 +150,9 @@
 Command::Command(const string &name, const string &briefDesc):
     name(name),
     briefDesc(briefDesc),
-    verbosity(Normal)
+    verbosity(Normal),
+    emergency(false),
+    force(false)
 {
 }
 
@@ -204,6 +206,13 @@
 
 /*****************************************************************************/
 
+void Command::setEmergency(bool e)
+{
+    emergency = e;
+};
+
+/*****************************************************************************/
+
 void Command::setForce(bool f)
 {
     force = f;
@@ -489,6 +498,19 @@
 
 /****************************************************************************/
 
+int Command::emergencySlave() const
+{
+    unsigned int ret;
+
+    stringstream str;
+    str << positions;
+    str >> ret;
+
+    return ret;
+}
+
+/****************************************************************************/
+
 string Command::alStateString(uint8_t state)
 {
     string ret;
--- a/tool/Command.h	Thu Feb 14 11:17:33 2013 +0100
+++ b/tool/Command.h	Mon May 13 20:21:19 2013 +0200
@@ -107,6 +107,9 @@
         void setDataType(const string &);
         const string &getDataType() const;
 
+        void setEmergency(bool);
+        bool getEmergency() const;
+
         void setForce(bool);
         bool getForce() const;
 
@@ -140,6 +143,7 @@
         ConfigList selectedConfigs(MasterDevice &);
         typedef list<ec_ioctl_domain_t> DomainList;
         DomainList selectedDomains(MasterDevice &, const ec_ioctl_master_t &);
+        int emergencySlave() const;
 
         static string alStateString(uint8_t);
 
@@ -152,6 +156,7 @@
         string positions;
         string domains;
         string dataType;
+        bool emergency;
         bool force;
         string outputFile;
         string skin;
@@ -189,6 +194,13 @@
 
 /****************************************************************************/
 
+inline bool Command::getEmergency() const
+{
+    return emergency;
+}
+
+/****************************************************************************/
+
 inline bool Command::getForce() const
 {
     return force;
--- a/tool/CommandRegRead.cpp	Thu Feb 14 11:17:33 2013 +0100
+++ b/tool/CommandRegRead.cpp	Mon May 13 20:21:19 2013 +0200
@@ -149,6 +149,7 @@
         throwSingleSlaveRequired(slaves.size());
     }
     io.slave_position = slaves.front().position;
+    io.emergency = false;
 
     io.data = new uint8_t[io.size];
 
--- a/tool/CommandRegWrite.cpp	Thu Feb 14 11:17:33 2013 +0100
+++ b/tool/CommandRegWrite.cpp	Mon May 13 20:21:19 2013 +0200
@@ -68,10 +68,12 @@
         << typeInfo()
         << endl
         << "Command-specific options:" << endl
-        << "  --alias    -a <alias>" << endl
-        << "  --position -p <pos>    Slave selection. See the help of" << endl
-        << "                         the 'slaves' command." << endl
-        << "  --type     -t <type>   Data type (see above)." << endl
+        << "  --alias     -a <alias>" << endl
+        << "  --position  -p <pos>    Slave selection. See the help of"
+        << endl
+        << "                          the 'slaves' command." << endl
+        << "  --type      -t <type>   Data type (see above)." << endl
+        << "  --emergency -e          Send as emergency request." << endl
         << endl
         << numericInfo();
 
@@ -85,7 +87,6 @@
     stringstream strOffset, err;
     ec_ioctl_slave_reg_t io;
     ifstream file;
-    SlaveList slaves;
 
     if (args.size() != 2) {
         err << "'" << getName() << "' takes exactly two arguments!";
@@ -158,12 +159,19 @@
         throw e;
     }
 
-    slaves = selectedSlaves(m);
-    if (slaves.size() != 1) {
-        delete [] io.data;
-        throwSingleSlaveRequired(slaves.size());
-    }
-    io.slave_position = slaves.front().position;
+    if (getEmergency()) {
+        io.slave_position = emergencySlave();
+        io.emergency = true;
+    }
+    else {
+        SlaveList slaves = selectedSlaves(m);
+        if (slaves.size() != 1) {
+            delete [] io.data;
+            throwSingleSlaveRequired(slaves.size());
+        }
+        io.slave_position = slaves.front().position;
+        io.emergency = false;
+    }
 
     // send data to master
     try {
--- a/tool/main.cpp	Thu Feb 14 11:17:33 2013 +0100
+++ b/tool/main.cpp	Mon May 13 20:21:19 2013 +0200
@@ -83,6 +83,7 @@
 string dataTypeStr;
 Command::Verbosity verbosity = Command::Normal;
 bool force = false;
+bool emergency = false;
 bool helpRequested = false;
 string outputFile;
 string skin;
@@ -149,6 +150,7 @@
         {"type",        required_argument, NULL, 't'},
         {"output-file", required_argument, NULL, 'o'},
         {"skin",        required_argument, NULL, 's'},
+        {"emergency",   no_argument,       NULL, 'e'},
         {"force",       no_argument,       NULL, 'f'},
         {"quiet",       no_argument,       NULL, 'q'},
         {"verbose",     no_argument,       NULL, 'v'},
@@ -157,7 +159,7 @@
     };
 
     do {
-        c = getopt_long(argc, argv, "m:a:p:d:t:o:s:fqvh", longOptions, NULL);
+        c = getopt_long(argc, argv, "m:a:p:d:t:o:s:efqvh", longOptions, NULL);
 
         switch (c) {
             case 'm':
@@ -188,6 +190,10 @@
                 skin = optarg;
                 break;
 
+            case 'e':
+                emergency = true;
+                break;
+
             case 'f':
                 force = true;
                 break;
@@ -315,6 +321,7 @@
                     cmd->setDataType(dataTypeStr);
                     cmd->setOutputFile(outputFile);
                     cmd->setSkin(skin);
+                    cmd->setEmergency(emergency);
                     cmd->setForce(force);
                     cmd->execute(commandArgs);
                 } catch (InvalidUsageException &e) {