Implemented alias reading/writing via sysfs.

This commit is contained in:
Florian Pose 2007-03-02 15:43:45 +00:00
parent 94866f4bca
commit d8d30c4a1f
4 changed files with 114 additions and 33 deletions

1
NEWS
View File

@ -21,6 +21,7 @@ Changes in version 1.3.0:
devices to the master, which decides, which ones to register.
* All EEPROM write operations from user space are now blocking until
completion and returning appropriate error codes.
* Implemented setting of secondary slave address (alias) via sysfs.
* Removed annoying eeprom_write_enable file. EEPROM writing always enabled.
* Removed EtherCAT line comments from 8139too drivers.

1
TODO
View File

@ -16,6 +16,7 @@ $Id$
- SDO dictionary and -access in operation mode.
- SDO write access in sysfs.
- Speed up IDLE-FSM through fast mode with schedule().
- Evaluate EEPROM contents after writing.
* Future features:
- Distributed clocks.

View File

@ -311,7 +311,9 @@ int ec_fsm_master_action_process_eeprom(
}
// found pending EEPROM write operation. execute it!
EC_INFO("Writing EEPROM of slave %i...\n", slave->ring_position);
if (master->debug_level)
EC_DBG("Writing EEPROM data to slave %i...\n",
slave->ring_position);
fsm->eeprom_request = request;
fsm->eeprom_index = 0;
ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->offset,
@ -782,7 +784,8 @@ void ec_fsm_master_state_configure_slave(ec_fsm_master_t *fsm
Master state: WRITE EEPROM.
*/
void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *fsm /**< master state machine */)
void ec_fsm_master_state_write_eeprom(
ec_fsm_master_t *fsm /**< master state machine */)
{
ec_master_t *master = fsm->master;
ec_eeprom_write_request_t *request = fsm->eeprom_request;
@ -792,8 +795,8 @@ void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *fsm /**< master state mac
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
slave->error_flag = 1;
EC_ERR("Failed to write EEPROM contents to slave %i.\n",
slave->ring_position);
EC_ERR("Failed to write EEPROM data to slave %i.\n",
slave->ring_position);
request->state = EC_EEPROM_REQ_ERROR;
wake_up(&master->eeprom_queue);
fsm->state = ec_fsm_master_state_error;
@ -811,7 +814,9 @@ void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *fsm /**< master state mac
}
// finished writing EEPROM
EC_INFO("Finished writing EEPROM of slave %i.\n", slave->ring_position);
if (master->debug_level)
EC_DBG("Finished writing EEPROM data to slave %i.\n",
slave->ring_position);
request->state = EC_EEPROM_REQ_COMPLETED;
wake_up(&master->eeprom_queue);

View File

@ -65,11 +65,13 @@ ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *,
EC_SYSFS_READ_ATTR(info);
EC_SYSFS_READ_WRITE_ATTR(state);
EC_SYSFS_READ_WRITE_ATTR(eeprom);
EC_SYSFS_READ_WRITE_ATTR(alias);
static struct attribute *def_attrs[] = {
&attr_info,
&attr_state,
&attr_eeprom,
&attr_alias,
NULL,
};
@ -773,19 +775,57 @@ size_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */
/*****************************************************************************/
/**
Schedules an EEPROM write operation.
\return 0 in case of success, else < 0
*/
* Schedules an EEPROM write request.
* \return 0 case of success, otherwise error code.
*/
int ec_slave_schedule_eeprom_writing(ec_eeprom_write_request_t *request)
{
ec_master_t *master = request->slave->master;
request->state = EC_EEPROM_REQ_QUEUED;
// schedule EEPROM write request.
down(&master->eeprom_sem);
list_add_tail(&request->list, &master->eeprom_requests);
up(&master->eeprom_sem);
// wait for processing through FSM
if (wait_event_interruptible(master->eeprom_queue,
request->state != EC_EEPROM_REQ_QUEUED)) {
// interrupted by signal
down(&master->eeprom_sem);
if (request->state == EC_EEPROM_REQ_QUEUED) {
list_del(&request->list);
up(&master->eeprom_sem);
return -EINTR;
}
// request already processing: interrupt not possible.
up(&master->eeprom_sem);
}
// wait until master FSM has finished processing
wait_event(master->eeprom_queue, request->state != EC_EEPROM_REQ_BUSY);
return request->state == EC_EEPROM_REQ_COMPLETED ? 0 : -EIO;
}
/*****************************************************************************/
/**
* Writes complete EEPROM contents to a slave.
* \return data size written in case of success, otherwise error code.
*/
ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
const uint8_t *data, /**< new EEPROM data */
size_t size /**< size of data in bytes */
)
const uint8_t *data, /**< new EEPROM data */
size_t size /**< size of data in bytes */
)
{
ec_eeprom_write_request_t request;
const uint16_t *cat_header;
uint16_t cat_type, cat_size;
ec_master_t *master = slave->master;
int ret;
if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
@ -803,7 +843,6 @@ ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
request.words = (const uint16_t *) data;
request.offset = 0;
request.size = size / 2;
request.state = EC_EEPROM_REQ_QUEUED;
if (request.size < 0x0041) {
EC_ERR("EEPROM data too short! Dropping.\n");
@ -826,31 +865,60 @@ ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
cat_type = EC_READ_U16(cat_header);
}
// data ok: schedule EEPROM write request.
down(&master->eeprom_sem);
list_add_tail(&request.list, &master->eeprom_requests);
up(&master->eeprom_sem);
// EEPROM data ok. schedule writing.
if ((ret = ec_slave_schedule_eeprom_writing(&request)))
return ret; // error code
// wait for processing through FSM
if (wait_event_interruptible(master->eeprom_queue,
request.state != EC_EEPROM_REQ_QUEUED)) {
// interrupted by signal
down(&master->eeprom_sem);
if (request.state == EC_EEPROM_REQ_QUEUED) {
list_del(&request.list);
up(&master->eeprom_sem);
return -EINTR;
}
// request already processing: interrupt not possible.
up(&master->eeprom_sem);
return size; // success
}
/*****************************************************************************/
/**
* Writes the Secondary slave address (alias) to the slave's EEPROM.
* \return data size written in case of success, otherwise error code.
*/
ssize_t ec_slave_write_alias(ec_slave_t *slave, /**< EtherCAT slave */
const uint8_t *data, /**< alias string */
size_t size /**< size of data in bytes */
)
{
ec_eeprom_write_request_t request;
char *remainder;
uint16_t alias, word;
int ret;
if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
return -EBUSY;
}
// wait until master FSM has finished processing
wait_event(master->eeprom_queue, request.state != EC_EEPROM_REQ_BUSY);
alias = simple_strtoul(data, &remainder, 0);
if (remainder == (char *) data || (*remainder && *remainder != '\n')) {
EC_ERR("Invalid alias value! Dropping.\n");
return -EINVAL;
}
// correct endianess
EC_WRITE_U16(&word, alias);
return request.state == EC_EEPROM_REQ_COMPLETED ? size : -EIO;
// init EEPROM write request
INIT_LIST_HEAD(&request.list);
request.slave = slave;
request.words = &word;
request.offset = 0x0004;
request.size = 1;
if ((ret = ec_slave_schedule_eeprom_writing(&request)))
return ret; // error code
slave->sii_alias = alias; // FIXME: do this in state machine
return size; // success
}
/*****************************************************************************/
/**
@ -895,6 +963,9 @@ ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */
}
}
}
else if (attr == &attr_alias) {
return sprintf(buffer, "%u\n", slave->sii_alias);
}
return 0;
}
@ -937,8 +1008,11 @@ ssize_t ec_store_slave_attribute(struct kobject *kobj, /**< slave's kobject */
else if (attr == &attr_eeprom) {
return ec_slave_write_eeprom(slave, buffer, size);
}
else if (attr == &attr_alias) {
return ec_slave_write_alias(slave, buffer, size);
}
return -EINVAL;
return -EIO;
}
/*****************************************************************************/