applied komax patch to version r1822

- adapted to 2.6.31 (-rt): init_MUTEX -> sema_init, net_device_ops (Matthias Lüscher)
- 8139too eth driver for 2.6.31 (Matthias Lüscher)
- scan_busy queryable in user mode (ec_master_info_t) (Martin Troxler)
- read alias from register 0x0012 (TODO: reread alias after sii write) (Martin Troxler)
- cancel external SDO/FOE,Reg&SII requests (Martin Troxler)
This commit is contained in:
Martin Troxler 2009-11-19 14:39:10 +01:00
parent fb69f56152
commit dfeb99b1cb
11 changed files with 5605 additions and 18 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -391,7 +391,8 @@ int __init init_mini_module(void)
goto out_return;
}
init_MUTEX(&master_sem);
sema_init(&master_sem, 1);
ecrt_master_callbacks(master, send_callback, receive_callback);
printk(KERN_INFO PFX "Registering domain...\n");

View File

@ -214,6 +214,7 @@ typedef struct {
typedef struct {
unsigned int slave_count; /**< Number of slaves in the bus. */
unsigned int link_up : 1; /**< \a true, if the network link is up. */
uint8_t scan_busy; /**< \a true, while the master is scanning the bus */
uint64_t app_time; /**< Application time. */
} ec_master_info_t;

View File

@ -125,6 +125,7 @@ int ecrt_master(ec_master_t* master, ec_master_info_t *master_info)
master_info->slave_count = data.slave_count;
master_info->link_up = data.devices[0].link_state;
master_info->scan_busy = data.scan_busy;
master_info->app_time = data.app_time;
return 0;
}

View File

@ -34,6 +34,7 @@
/*****************************************************************************/
#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@ -48,6 +49,16 @@ int ec_dbgdev_stop(struct net_device *);
int ec_dbgdev_tx(struct sk_buff *, struct net_device *);
struct net_device_stats *ec_dbgdev_stats(struct net_device *);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
static const struct net_device_ops ec_dbg_netdev_ops =
{
.ndo_open = ec_dbgdev_open,
.ndo_stop = ec_dbgdev_stop,
.ndo_start_xmit = ec_dbgdev_tx,
.ndo_get_stats = ec_dbgdev_stats,
};
#endif
/*****************************************************************************/
/** Debug interface constructor.
@ -74,10 +85,14 @@ int ec_debug_init(
}
// initialize net_device
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
dbg->dev->netdev_ops = &ec_dbg_netdev_ops;
#else
dbg->dev->open = ec_dbgdev_open;
dbg->dev->stop = ec_dbgdev_stop;
dbg->dev->hard_start_xmit = ec_dbgdev_tx;
dbg->dev->get_stats = ec_dbgdev_stats;
#endif
// initialize private data
*((ec_debug_t **) netdev_priv(dbg->dev)) = dbg;

View File

@ -34,6 +34,7 @@
/*****************************************************************************/
#include <linux/version.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@ -79,6 +80,16 @@ int ec_eoedev_stop(struct net_device *);
int ec_eoedev_tx(struct sk_buff *, struct net_device *);
struct net_device_stats *ec_eoedev_stats(struct net_device *);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
static const struct net_device_ops ec_eoe_netdev_ops =
{
.ndo_open = ec_eoedev_open,
.ndo_stop = ec_eoedev_stop,
.ndo_start_xmit = ec_eoedev_tx,
.ndo_get_stats = ec_eoedev_stats,
};
#endif
/*****************************************************************************/
/** EoE constructor.
@ -107,7 +118,8 @@ int ec_eoe_init(
eoe->tx_queue_active = 0;
eoe->tx_queue_size = EC_EOE_TX_QUEUE_SIZE;
eoe->tx_queued_frames = 0;
init_MUTEX(&eoe->tx_queue_sem);
sema_init(&eoe->tx_queue_sem, 1);
eoe->tx_frame_number = 0xFF;
memset(&eoe->stats, 0, sizeof(struct net_device_stats));
@ -138,10 +150,14 @@ int ec_eoe_init(
}
// initialize net_device
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)
eoe->dev->netdev_ops = &ec_eoe_netdev_ops;
#else
eoe->dev->open = ec_eoedev_open;
eoe->dev->stop = ec_eoedev_stop;
eoe->dev->hard_start_xmit = ec_eoedev_tx;
eoe->dev->get_stats = ec_eoedev_stats;
#endif
for (i = 0; i < ETH_ALEN; i++)
eoe->dev->dev_addr[i] = i | (i << 4);

View File

@ -344,7 +344,7 @@ int ec_fsm_master_action_process_sii(
/*****************************************************************************/
/** Check for pending register requests and process one.
*
*
* \return non-zero, if a register request is processed.
*/
int ec_fsm_master_action_process_register(
@ -949,6 +949,7 @@ void ec_fsm_master_state_write_sii(
if (request->offset <= 4 && request->offset + request->nwords > 4) {
// alias was written
slave->sii.alias = EC_READ_U16(request->words + 4);
// TODO: read alias from register 0x0012
}
// TODO: Evaluate other SII contents!
@ -1089,7 +1090,7 @@ void ec_fsm_master_state_reg_request(
ec_fsm_master_restart(fsm);
return;
}
if (datagram->working_counter == 1) {
if (request->dir == EC_DIR_INPUT) { // read request
if (request->data)

View File

@ -52,6 +52,7 @@ void ec_fsm_slave_scan_state_dc_times(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_regalias(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_sync(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *);
@ -60,6 +61,7 @@ void ec_fsm_slave_scan_state_end(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_error(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_enter_datalink(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_enter_regalias(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_enter_preop(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_enter_pdos(ec_fsm_slave_scan_t *);
@ -313,7 +315,7 @@ void ec_fsm_slave_scan_state_base(
for (i = 0; i < EC_MAX_PORTS; i++) {
slave->ports[i].desc = (octet >> (2 * i)) & 0x03;
}
octet = EC_READ_U8(datagram->data + 8);
slave->base_fmmu_bit_operation = octet & 0x01;
slave->base_dc_supported = (octet >> 2) & 0x01;
@ -600,7 +602,7 @@ void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *fsm /**< slave state
}
// Evaluate SII contents
ec_slave_clear_sync_managers(slave);
slave->sii.alias =
@ -711,11 +713,7 @@ void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *fsm /**< slave state
}
}
if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
ec_fsm_slave_scan_enter_preop(fsm);
} else {
fsm->state = ec_fsm_slave_scan_state_end;
}
ec_fsm_slave_scan_enter_regalias(fsm);
return;
end:
@ -724,6 +722,74 @@ end:
fsm->state = ec_fsm_slave_scan_state_error;
}
/*****************************************************************************/
/**
Slave scan entry function: REGALIAS.
*/
void ec_fsm_slave_scan_enter_regalias(
ec_fsm_slave_scan_t *fsm /**< slave state machine */
)
{
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
// read alias from register 0x0012
if (slave->master->debug_level)
EC_DBG("Reading alias from register 0x0012 of slave %u.\n",
slave->ring_position);
ec_datagram_fprd(datagram, slave->station_address, 0x0012, 2);
ec_datagram_zero(datagram);
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_slave_scan_state_regalias;
}
/*****************************************************************************/
/**
Slave scan state: REGALIAS.
*/
void ec_fsm_slave_scan_state_regalias(
ec_fsm_slave_scan_t *fsm /**< slave state machine */
)
{
ec_datagram_t *datagram = fsm->datagram;
ec_slave_t *slave = fsm->slave;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
return;
if (datagram->state != EC_DATAGRAM_RECEIVED) {
fsm->state = ec_fsm_slave_scan_state_error;
EC_ERR("Failed to receive get reg alias datagram from slave %u"
" (datagram state %u).\n",
fsm->slave->ring_position, datagram->state);
return;
}
if (datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_scan_state_error;
EC_ERR("Failed to read reg alias of slave %u: ",
fsm->slave->ring_position);
ec_datagram_print_wc_error(datagram);
return;
}
slave->sii.alias = EC_READ_U16(datagram->data);
if (slave->master->debug_level)
EC_DBG("Alias of slave %u is %u.\n",
slave->ring_position,slave->sii.alias);
if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
ec_fsm_slave_scan_enter_preop(fsm);
} else {
fsm->state = ec_fsm_slave_scan_state_end;
}
}
/*****************************************************************************/
/** Enter slave scan state PREOP.

View File

@ -114,11 +114,12 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
master->index = index;
master->reserved = 0;
init_MUTEX(&master->master_sem);
sema_init(&master->master_sem, 1);
master->main_mac = main_mac;
master->backup_mac = backup_mac;
init_MUTEX(&master->device_sem);
sema_init(&master->device_sem, 1);
master->phase = EC_ORPHANED;
master->injection_seq_fsm = 0;
@ -135,19 +136,19 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
master->scan_busy = 0;
master->allow_scan = 1;
init_MUTEX(&master->scan_sem);
sema_init(&master->scan_sem, 1);
init_waitqueue_head(&master->scan_queue);
master->config_busy = 0;
master->allow_config = 1;
init_MUTEX(&master->config_sem);
sema_init(&master->config_sem, 1);
init_waitqueue_head(&master->config_queue);
INIT_LIST_HEAD(&master->datagram_queue);
master->datagram_index = 0;
INIT_LIST_HEAD(&master->ext_datagram_queue);
init_MUTEX(&master->ext_queue_sem);
sema_init(&master->ext_queue_sem, 1);
INIT_LIST_HEAD(&master->domains);
@ -165,7 +166,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
INIT_LIST_HEAD(&master->eoe_handlers);
#endif
init_MUTEX(&master->io_sem);
sema_init(&master->io_sem, 1);
master->send_cb = NULL;
master->receive_cb = NULL;
master->app_send_cb = NULL;
@ -348,6 +349,64 @@ void ec_master_clear_slaves(ec_master_t *master)
master->dc_ref_clock = NULL;
// external requests are obsolete, so we wake pending waiters and remove them from the list
// SII
while (1) {
ec_sii_write_request_t *request;
if (list_empty(&master->sii_requests))
break;
// get first request
request = list_entry(master->sii_requests.next, ec_sii_write_request_t,
list);
list_del_init(&request->list); // dequeue
EC_INFO("Discarding SII request, slave %u does not exist anymore.\n",
request->slave->ring_position);
request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->sii_queue);
}
// Reg
while (1) {
ec_reg_request_t *request;
if (list_empty(&master->reg_requests))
break;
// get first request
request = list_entry(master->reg_requests.next,
ec_reg_request_t, list);
list_del_init(&request->list); // dequeue
EC_INFO("Discarding Reg request, slave %u does not exist anymore.\n",
request->slave->ring_position);
request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->reg_queue);
}
// SDO
while (1) {
ec_master_sdo_request_t *request;
if (list_empty(&master->slave_sdo_requests))
break;
// get first request
request = list_entry(master->slave_sdo_requests.next,
ec_master_sdo_request_t, list);
list_del_init(&request->list); // dequeue
EC_INFO("Discarding SDO request, slave %u does not exist anymore.\n",
request->slave->ring_position);
request->req.state = EC_INT_REQUEST_FAILURE;
wake_up(&master->sdo_queue);
}
// FOE
while (1) {
ec_master_foe_request_t *request;
if (list_empty(&master->foe_requests))
break;
// get first request
request = list_entry(master->foe_requests.next,
ec_master_foe_request_t, list);
list_del_init(&request->list); // dequeue
EC_INFO("Discarding FOE request, slave %u does not exist anymore.\n",
request->slave->ring_position);
request->req.state = EC_INT_REQUEST_FAILURE;
wake_up(&master->foe_queue);
}
for (slave = master->slaves;
slave < master->slaves + master->slave_count;
slave++) {

View File

@ -101,7 +101,7 @@ int __init ec_init_module(void)
EC_INFO("Master driver %s\n", EC_MASTER_VERSION);
init_MUTEX(&master_sem);
sema_init(&master_sem, 1);
if (master_count) {
if (alloc_chrdev_region(&device_number, 0, master_count, "EtherCAT")) {