Implemented emergency register requests to analyze a broken bus.
--- 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) {