# HG changeset patch # User Florian Pose # Date 1368469279 -7200 # Node ID c7e1f2616a9d017e121de8b837537b34b3f3e81a # Parent 8bb574da5da24a77b310804940cde67b1283c2ab Implemented emergency register requests to analyze a broken bus. diff -r 8bb574da5da2 -r c7e1f2616a9d master/fsm_master.c --- 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; diff -r 8bb574da5da2 -r c7e1f2616a9d master/ioctl.c --- 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); diff -r 8bb574da5da2 -r c7e1f2616a9d master/ioctl.h --- 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; diff -r 8bb574da5da2 -r c7e1f2616a9d master/master.c --- 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); diff -r 8bb574da5da2 -r c7e1f2616a9d master/master.h --- 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. */ diff -r 8bb574da5da2 -r c7e1f2616a9d master/reg_request.c --- 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; } diff -r 8bb574da5da2 -r c7e1f2616a9d master/reg_request.h --- 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. */ }; /*****************************************************************************/ diff -r 8bb574da5da2 -r c7e1f2616a9d tool/Command.cpp --- 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; diff -r 8bb574da5da2 -r c7e1f2616a9d tool/Command.h --- 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 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; diff -r 8bb574da5da2 -r c7e1f2616a9d tool/CommandRegRead.cpp --- 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]; diff -r 8bb574da5da2 -r c7e1f2616a9d tool/CommandRegWrite.cpp --- 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 " << endl - << " --position -p Slave selection. See the help of" << endl - << " the 'slaves' command." << endl - << " --type -t Data type (see above)." << endl + << " --alias -a " << endl + << " --position -p Slave selection. See the help of" + << endl + << " the 'slaves' command." << endl + << " --type -t 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 { diff -r 8bb574da5da2 -r c7e1f2616a9d tool/main.cpp --- 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) {