From 5f8d97edcfdcfa8ef7263b9f6a6875322615bd6f Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Thu, 8 Feb 2024 12:05:29 +0100 Subject: [PATCH] Assigned ioctl calls to RT, nRT or both; documented that in header. --- include/ecrt.h | 254 +++++++++++++++++++++++++++++-------- master/ioctl.c | 295 ++++++++++++++++++++++--------------------- master/soe_request.c | 2 +- 3 files changed, 355 insertions(+), 196 deletions(-) diff --git a/include/ecrt.h b/include/ecrt.h index eb99f659..1ffda2db 100644 --- a/include/ecrt.h +++ b/include/ecrt.h @@ -27,20 +27,16 @@ * \defgroup ApplicationInterface EtherCAT Configuration Interface * * Interface for configuring the EtherCAT master for realtime applications. - * There are functions to request a master, to map process data, - * to communicate with slaves via CoE - * and to configure and activate the bus. - * All methods in this group should be used before the - * application switches to operational (real-time) mode - * by calling ecrt_master_activate(). - * After that, only calls to the functions in \ref ApplicationInterfaceRT - * are allowed. - * The real-time operational mode finishes by calling ecrt_master_deactivate(). - * Many functions in this group are blocking and/or they - * acquire locks. - * Do not use these functions in non-Userspace contexts, - * e.g. in RTAI/Xenomai Real-Time tasks or in atomic/softirq/tasklet - * context in kernel modules. You have been warned. + * There are functions to request a master, to map process data, to + * communicate with slaves via CoE and to configure and activate the network. + * All methods in this group should be used before the application switches to + * operational (real-time) mode by calling ecrt_master_activate(). After + * that, only calls to the functions in \ref ApplicationInterfaceRT are + * allowed. The real-time operational mode finishes by calling + * ecrt_master_deactivate(). Many functions in this group are blocking and/or + * they acquire locks. Do not use these functions in non-userspace contexts, + * e. g. in RTAI/Xenomai Real-Time tasks or in atomic/softirq/tasklet context + * in kernel modules. You have been warned. * * Changes in version 1.6.0: * @@ -109,10 +105,10 @@ * ecrt_slave_config_sync_manager()). * - Added ecrt_slave_config_complete_sdo() method to download an SDO during * configuration via CompleteAccess. - * - Added ecrt_master_deactivate() to remove the bus configuration. + * - Added ecrt_master_deactivate() to remove the master configuration. * - Added ecrt_open_master() and ecrt_master_reserve() separation for * userspace. - * - Added bus information interface (methods ecrt_master(), + * - Added master information interface (methods ecrt_master(), * ecrt_master_get_slave(), ecrt_master_get_sync_manager(), * ecrt_master_get_pdo() and ecrt_master_get_pdo_entry()) to get information * about the currently connected slaves and the PDO entries provided. @@ -332,7 +328,7 @@ typedef struct { unsigned int al_states : 4; /**< Application-layer states of all slaves. The states are coded in the lower 4 bits. If a bit is set, it means that at least one - slave in the bus is in the corresponding + slave in the network is in the corresponding state: - Bit 0: \a INIT - Bit 1: \a PREOP @@ -354,10 +350,10 @@ typedef struct { unsigned int slaves_responding; /**< Sum of responding slaves on the given link. */ unsigned int al_states : 4; /**< Application-layer states of the slaves on - the given link. The states are coded in the - lower 4 bits. If a bit is set, it means - that at least one slave in the bus is in the - corresponding state: + the given link. The states are coded in the + lower 4 bits. If a bit is set, it means + that at least one slave in the network is in + the corresponding state: - Bit 0: \a INIT - Bit 1: \a PREOP - Bit 2: \a SAFEOP @@ -397,9 +393,10 @@ typedef struct { * \see ecrt_master(). */ typedef struct { - unsigned int slave_count; /**< Number of slaves in the bus. */ + unsigned int slave_count; /**< Number of slaves in the network. */ 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 */ + uint8_t scan_busy; /**< \a true, while the master is scanning the network. + */ uint64_t app_time; /**< Application time. */ } ec_master_info_t; @@ -547,7 +544,7 @@ typedef struct { unsigned int n_entries; /**< Number of PDO entries in \a entries to map. Zero means, that the default mapping shall be used (this can only be done if the slave is - present at bus configuration time). */ + present at configuration time). */ ec_pdo_entry_info_t const *entries; /**< Array of PDO entries to map. Can either be \a NULL, or must contain at least \a n_entries values. */ @@ -709,14 +706,14 @@ EC_PUBLIC_API int ecrt_master_reserve( /** Sets the locking callbacks. * * For concurrent master access, i. e. if other instances than the application - * want to send and receive datagrams on the bus, the application has to + * want to send and receive datagrams on the network, the application has to * provide a callback mechanism. This method takes two function pointers as * its parameters. Asynchronous master access (like EoE processing) is only * possible if the callbacks have been set. * - * The task of the send callback (\a send_cb) is to decide, if the bus is - * currently accessible and whether or not to call the ecrt_master_send_ext() - * method. + * The task of the send callback (\a send_cb) is to decide, if the network + * hardware is currently accessible and whether or not to call the + * ecrt_master_send_ext() method. * * The task of the receive callback (\a receive_cb) is to decide, if a call to * ecrt_master_receive() is allowed and to execute it respectively. @@ -765,11 +762,11 @@ EC_PUBLIC_API ec_domain_t *ecrt_master_create_domain( * aliased slave, so a position of zero means the aliased slave itself and a * positive value matches the n-th slave behind the aliased one. * - * If the slave with the given address is found during the bus configuration, + * If the slave with the given address is found during the configuration, * its vendor ID and product code are matched against the given value. On * mismatch, the slave is not configured and an error message is raised. * - * If different slave configurations are pointing to the same slave during bus + * If different slave configurations are pointing to the same slave during * configuration, a warning is raised and only the first configuration is * applied. * @@ -1005,12 +1002,12 @@ EC_PUBLIC_API int ecrt_master_read_idn( * This function tells the master that the configuration phase is finished and * the realtime operation will begin. The function allocates internal memory * for the domains and calculates the logical FMMU addresses for domain - * members. It tells the master state machine that the bus configuration is - * now to be applied. + * members. It tells the master state machine that the configuration is + * now to be applied to the network. * * \attention After this function has been called, the realtime application is * in charge of cyclically calling ecrt_master_send() and - * ecrt_master_receive() to ensure bus communication. Before calling this + * ecrt_master_receive() to ensure network communication. Before calling this * function, the master thread is responsible for that, so these functions may * not be called! The method itself allocates memory and should not be called * in realtime context. @@ -1023,7 +1020,7 @@ EC_PUBLIC_API int ecrt_master_activate( /** Deactivates the master. * - * Removes the bus configuration. All objects created by + * Removes the master configuration. All objects created by * ecrt_master_create_domain(), ecrt_master_slave_config(), ecrt_domain_data() * ecrt_slave_config_create_sdo_request() and * ecrt_slave_config_create_voe_handler() are freed, so pointers to them @@ -1094,7 +1091,7 @@ EC_PUBLIC_API void ecrt_master_send_ext( * Stores the master state information in the given \a state structure. * * This method returns a global state. For the link-specific states in a - * redundant bus topology, use the ecrt_master_link_state() method. + * redundant network topology, use the ecrt_master_link_state() method. */ EC_PUBLIC_API void ecrt_master_state( const ec_master_t *master, /**< EtherCAT master. */ @@ -1193,6 +1190,10 @@ EC_PUBLIC_API void ecrt_master_sync_slave_clocks( * \attention The returned time is the system time of the reference clock * minus the transmission delay of the reference clock. * + * Calling this method makes only sense in realtime context (after master + * activation), when the ecrt_master_sync_slave_clocks() method is called + * cyclically. + * * \retval 0 success, system time was written into \a time. * \retval -ENXIO No reference clock found. * \retval -EIO Slave synchronization datagram was not received. @@ -1235,6 +1236,9 @@ EC_PUBLIC_API uint32_t ecrt_master_sync_monitor_process( * done by the master. But with special slaves, that can be reconfigured by * the vendor during runtime, it can be useful. * + * Calling this method only makes sense in realtime context (after + * activation), because slaves will not be configured before. + * * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_master_reset( @@ -1625,8 +1629,13 @@ EC_PUBLIC_API int ecrt_slave_config_emerg_size( * Byte 2: Error register * Byte 3-7: Data * + * Calling this method makes only sense in realtime context (after master + * activation). + * * \return 0 on success (record popped), or negative error code (i. e. * -ENOENT, if ring is empty). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API int ecrt_slave_config_emerg_pop( ec_slave_config_t *sc, /**< Slave configuration. */ @@ -1635,8 +1644,13 @@ EC_PUBLIC_API int ecrt_slave_config_emerg_pop( ); /** Clears CoE emergency ring buffer and the overrun counter. + * + * Calling this method makes only sense in realtime context (after master + * activation). * * \return 0 on success, or negative error code. + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API int ecrt_slave_config_emerg_clear( ec_slave_config_t *sc /**< Slave configuration. */ @@ -1648,7 +1662,12 @@ EC_PUBLIC_API int ecrt_slave_config_emerg_clear( * not be stored in the ring buffer and had to be dropped. Call * ecrt_slave_config_emerg_clear() to reset the counter. * + * Calling this method makes only sense in realtime context (after master + * activation). + * * \return Number of overruns since last clear, or negative error code. + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API int ecrt_slave_config_emerg_overruns( const ec_slave_config_t *sc /**< Slave configuration. */ @@ -1735,6 +1754,11 @@ EC_PUBLIC_API ec_reg_request_t *ecrt_slave_config_create_reg_request( * * \attention If the state of process data exchange shall be monitored in * realtime, ecrt_domain_state() should be used. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_slave_config_state( const ec_slave_config_t *sc, /**< Slave configuration */ @@ -1916,6 +1940,12 @@ EC_PUBLIC_API void ecrt_domain_state( * \attention If the SDO index and/or subindex is changed while * ecrt_sdo_request_state() returns EC_REQUEST_BUSY, this may lead to * unexpected results. + * + * This method is meant to be called in realtime context (after master + * activation). To initialize the SDO request, the index and subindex can be + * set via ecrt_slave_config_create_sdo_request(). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_sdo_request_index( ec_sdo_request_t *req, /**< SDO request. */ @@ -1930,6 +1960,9 @@ EC_PUBLIC_API void ecrt_sdo_request_index( * * The timeout is permanently stored in the request object and is valid until * the next call of this method. + * + * The timeout should be defined in non-realtime context, but can also be + * changed afterwards. */ EC_PUBLIC_API void ecrt_sdo_request_timeout( ec_sdo_request_t *req, /**< SDO request. */ @@ -1958,7 +1991,12 @@ EC_PUBLIC_API void ecrt_sdo_request_timeout( * the internal SDO data memory could be re-allocated if the read SDO data do * not fit inside. * + * This method is meant to be called in realtime context (after master + * activation), but can also be used to initialize data before. + * * \return Pointer to the internal SDO data memory. + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API uint8_t *ecrt_sdo_request_data( const ec_sdo_request_t *req /**< SDO request. */ @@ -1970,30 +2008,45 @@ EC_PUBLIC_API uint8_t *ecrt_sdo_request_data( * reserved memory. After a read operation the size is set to the size of the * read data. The size is not modified in any other situation. * + * This method is meant to be called in realtime context (after master + * activation). + * * \return SDO data size in bytes. + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API size_t ecrt_sdo_request_data_size( const ec_sdo_request_t *req /**< SDO request. */ ); /** Get the current state of the SDO request. + * + * The user-space implementation fetches incoming data and stores the received + * data size in the request object, so the request is not const. + * + * This method is meant to be called in realtime context (after master + * activation). * * \return Request state. + * + * \ingroup ApplicationInterfaceRT */ -#ifdef __KERNEL__ ec_request_state_t ecrt_sdo_request_state( - const ec_sdo_request_t *req /**< SDO request. */ - ); -#else -EC_PUBLIC_API ec_request_state_t ecrt_sdo_request_state( - ec_sdo_request_t *req /**< SDO request. */ - ); +#ifdef __KERNEL__ + const #endif + ec_sdo_request_t *req /**< SDO request. */ + ); /** Schedule an SDO write operation. * * \attention This method may not be called while ecrt_sdo_request_state() * returns EC_REQUEST_BUSY. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_sdo_request_write( ec_sdo_request_t *req /**< SDO request. */ @@ -2007,6 +2060,11 @@ EC_PUBLIC_API void ecrt_sdo_request_write( * \attention After calling this function, the return value of * ecrt_sdo_request_data() must be considered as invalid while * ecrt_sdo_request_state() returns EC_REQUEST_BUSY. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_sdo_request_read( ec_sdo_request_t *req /**< SDO request. */ @@ -2021,6 +2079,12 @@ EC_PUBLIC_API void ecrt_sdo_request_read( * \attention If the drive number and/or IDN is changed while * ecrt_soe_request_state() returns EC_REQUEST_BUSY, this may lead to * unexpected results. + * + * This method is meant to be called in realtime context (after master + * activation). To initialize the SoE request, the drive_no and IDN can be + * set via ecrt_slave_config_create_soe_request(). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_soe_request_idn( ec_soe_request_t *req, /**< IDN request. */ @@ -2035,6 +2099,9 @@ EC_PUBLIC_API void ecrt_soe_request_idn( * * The timeout is permanently stored in the request object and is valid until * the next call of this method. + * + * The timeout should be defined in non-realtime context, but can also be + * changed afterwards. */ EC_PUBLIC_API void ecrt_soe_request_timeout( ec_soe_request_t *req, /**< SoE request. */ @@ -2063,7 +2130,12 @@ EC_PUBLIC_API void ecrt_soe_request_timeout( * because the internal IDN data memory could be re-allocated if the read IDN * data do not fit inside. * + * This method is meant to be called in realtime context (after master + * activation), but can also be used to initialize data before. + * * \return Pointer to the internal IDN data memory. + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API uint8_t *ecrt_soe_request_data( const ec_soe_request_t *req /**< SoE request. */ @@ -2084,16 +2156,31 @@ EC_PUBLIC_API size_t ecrt_soe_request_data_size( /** Get the current state of the SoE request. * * \return Request state. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * In the user-space implementation, the method fetches the size of the + * incoming data, so the request object is not const. + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API ec_request_state_t ecrt_soe_request_state( - ec_soe_request_t *req /**< SoE request. Not const, because the - internal data size may be updated. */ - ); +#ifdef __KERNEL__ + const +#endif + ec_soe_request_t *req /**< SoE request. */ + ); /** Schedule an SoE IDN write operation. * * \attention This method may not be called while ecrt_soe_request_state() * returns EC_REQUEST_BUSY. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_soe_request_write( ec_soe_request_t *req /**< SoE request. */ @@ -2107,6 +2194,11 @@ EC_PUBLIC_API void ecrt_soe_request_write( * \attention After calling this function, the return value of * ecrt_soe_request_data() must be considered as invalid while * ecrt_soe_request_state() returns EC_REQUEST_BUSY. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_soe_request_read( ec_soe_request_t *req /**< SoE request. */ @@ -2122,6 +2214,12 @@ EC_PUBLIC_API void ecrt_soe_request_read( * type at as header. These numbers can be set with this function. The values * are valid and will be used for future send operations until the next call * of this method. + * + * This method is meant to be called in non-realtime context (before master + * activation) to initialize the header data, but it is also safe to + * change the header later on in realtime context. + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_voe_handler_send_header( ec_voe_handler_t *voe, /**< VoE handler. */ @@ -2136,6 +2234,11 @@ EC_PUBLIC_API void ecrt_voe_handler_send_header( * * The header information is stored at the memory given by the pointer * parameters. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_voe_handler_received_header( const ec_voe_handler_t *voe, /**< VoE handler. */ @@ -2186,8 +2289,14 @@ EC_PUBLIC_API size_t ecrt_voe_handler_data_size( /** Start a VoE write operation. * * After this function has been called, the ecrt_voe_handler_execute() method - * must be called in every bus cycle as long as it returns EC_REQUEST_BUSY. No - * other operation may be started while the handler is busy. + * must be called in every realtime cycle as long as it returns + * EC_REQUEST_BUSY. No other operation may be started while the handler is + * busy. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_voe_handler_write( ec_voe_handler_t *voe, /**< VoE handler. */ @@ -2197,8 +2306,9 @@ EC_PUBLIC_API void ecrt_voe_handler_write( /** Start a VoE read operation. * * After this function has been called, the ecrt_voe_handler_execute() method - * must be called in every bus cycle as long as it returns EC_REQUEST_BUSY. No - * other operation may be started while the handler is busy. + * must be called in every realtime cycle as long as it returns + * EC_REQUEST_BUSY. No other operation may be started while the handler is + * busy. * * The state machine queries the slave's send mailbox for new data to be send * to the master. If no data appear within the EC_VOE_RESPONSE_TIMEOUT @@ -2207,6 +2317,11 @@ EC_PUBLIC_API void ecrt_voe_handler_write( * On success, the size of the read data can be determined via * ecrt_voe_handler_data_size(), while the VoE header of the received data * can be retrieved with ecrt_voe_handler_received_header(). + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_voe_handler_read( ec_voe_handler_t *voe /**< VoE handler. */ @@ -2215,8 +2330,9 @@ EC_PUBLIC_API void ecrt_voe_handler_read( /** Start a VoE read operation without querying the sync manager status. * * After this function has been called, the ecrt_voe_handler_execute() method - * must be called in every bus cycle as long as it returns EC_REQUEST_BUSY. No - * other operation may be started while the handler is busy. + * must be called in every realtime cycle as long as it returns + * EC_REQUEST_BUSY. No other operation may be started while the handler is + * busy. * * The state machine queries the slave by sending an empty mailbox. The slave * fills its data to the master in this mailbox. If no data appear within the @@ -2226,6 +2342,11 @@ EC_PUBLIC_API void ecrt_voe_handler_read( * On success, the size of the read data can be determined via * ecrt_voe_handler_data_size(), while the VoE header of the received data * can be retrieved with ecrt_voe_handler_received_header(). + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_voe_handler_read_nosync( ec_voe_handler_t *voe /**< VoE handler. */ @@ -2233,14 +2354,19 @@ EC_PUBLIC_API void ecrt_voe_handler_read_nosync( /** Execute the handler. * - * This method executes the VoE handler. It has to be called in every bus + * This method executes the VoE handler. It has to be called in every realtime * cycle as long as it returns EC_REQUEST_BUSY. * * \return Handler state. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API ec_request_state_t ecrt_voe_handler_execute( - ec_voe_handler_t *voe /**< VoE handler. */ - ); + ec_voe_handler_t *voe /**< VoE handler. */ + ); /***************************************************************************** * Register request methods. @@ -2263,15 +2389,25 @@ EC_PUBLIC_API ec_request_state_t ecrt_voe_handler_execute( * EC_WRITE_U16(ecrt_reg_request_data(reg_request), 0xFFFF); * \endcode * + * This method is meant to be called in realtime context (after master + * activation), but can also be used to initialize data before. + * * \return Pointer to the internal memory. + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API uint8_t *ecrt_reg_request_data( const ec_reg_request_t *req /**< Register request. */ ); /** Get the current state of the register request. + * + * This method is meant to be called in realtime context (after master + * activation). * * \return Request state. + * + * \ingroup ApplicationInterfaceRT */ ec_request_state_t ecrt_reg_request_state( const ec_reg_request_t *req /**< Register request. */ @@ -2284,6 +2420,11 @@ ec_request_state_t ecrt_reg_request_state( * * \attention The \a size parameter is truncated to the size given at request * creation. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_reg_request_write( ec_reg_request_t *req, /**< Register request. */ @@ -2298,6 +2439,11 @@ EC_PUBLIC_API void ecrt_reg_request_write( * * \attention The \a size parameter is truncated to the size given at request * creation. + * + * This method is meant to be called in realtime context (after master + * activation). + * + * \ingroup ApplicationInterfaceRT */ EC_PUBLIC_API void ecrt_reg_request_read( ec_reg_request_t *req, /**< Register request. */ diff --git a/master/ioctl.c b/master/ioctl.c index 892e6a36..1a1c97b6 100644 --- a/master/ioctl.c +++ b/master/ioctl.c @@ -3486,6 +3486,8 @@ static ATTRIBUTES int ec_ioctl_sdo_request_timeout( /****************************************************************************/ /** Gets an SDO request's state. + * + * Also pre-fetches the size of incoming data. * * \return Zero on success, otherwise a negative error code. */ @@ -4670,7 +4672,9 @@ static ATTRIBUTES int ec_ioctl_slave_soe_write( return retval; } -/****************************************************************************/ +/***************************************************************************** + * ioctl() file operation functions + ****************************************************************************/ /** ioctl() function to use. * @@ -4685,6 +4689,8 @@ static long ec_ioctl_nrt( void *arg /**< ioctl() argument. */); #endif +/****************************************************************************/ + /** Called when an ioctl() command is issued. * Both RT and nRT context. * @@ -4703,13 +4709,6 @@ static long ec_ioctl_both( case EC_IOCTL_MODULE: ret = ec_ioctl_module(arg, ctx); break; - case EC_IOCTL_MASTER_DEBUG: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_master_debug(master, arg); - break; case EC_IOCTL_MASTER_RESCAN: if (!ctx->writable) { ret = -EPERM; @@ -4723,50 +4722,6 @@ static long ec_ioctl_both( case EC_IOCTL_MASTER_LINK_STATE: ret = ec_ioctl_master_link_state(master, arg, ctx); break; - case EC_IOCTL_RESET: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_reset(master, arg, ctx); - break; - case EC_IOCTL_REF_CLOCK_TIME: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_ref_clock_time(master, arg, ctx); - break; - case EC_IOCTL_SC_EMERG_POP: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sc_emerg_pop(master, arg, ctx); - break; - case EC_IOCTL_SC_EMERG_CLEAR: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sc_emerg_clear(master, arg, ctx); - break; - case EC_IOCTL_SC_EMERG_OVERRUNS: - ret = ec_ioctl_sc_emerg_overruns(master, arg, ctx); - break; - case EC_IOCTL_SC_STATE: - ret = ec_ioctl_sc_state(master, arg, ctx); - break; - case EC_IOCTL_DOMAIN_STATE: - ret = ec_ioctl_domain_state(master, arg, ctx); - break; - case EC_IOCTL_SDO_REQUEST_INDEX: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sdo_request_index(master, arg, ctx); - break; case EC_IOCTL_SDO_REQUEST_TIMEOUT: if (!ctx->writable) { ret = -EPERM; @@ -4774,33 +4729,9 @@ static long ec_ioctl_both( } ret = ec_ioctl_sdo_request_timeout(master, arg, ctx); break; - case EC_IOCTL_SDO_REQUEST_STATE: - ret = ec_ioctl_sdo_request_state(master, arg, ctx); - break; - case EC_IOCTL_SDO_REQUEST_READ: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sdo_request_read(master, arg, ctx); - break; - case EC_IOCTL_SDO_REQUEST_WRITE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_sdo_request_write(master, arg, ctx); - break; case EC_IOCTL_SDO_REQUEST_DATA: ret = ec_ioctl_sdo_request_data(master, arg, ctx); break; - case EC_IOCTL_SOE_REQUEST_IDN: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_soe_request_index(master, arg, ctx); - break; case EC_IOCTL_SOE_REQUEST_TIMEOUT: if (!ctx->writable) { ret = -EPERM; @@ -4808,46 +4739,12 @@ static long ec_ioctl_both( } ret = ec_ioctl_soe_request_timeout(master, arg, ctx); break; - case EC_IOCTL_SOE_REQUEST_STATE: - ret = ec_ioctl_soe_request_state(master, arg, ctx); - break; - case EC_IOCTL_SOE_REQUEST_READ: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_soe_request_read(master, arg, ctx); - break; - case EC_IOCTL_SOE_REQUEST_WRITE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_soe_request_write(master, arg, ctx); - break; case EC_IOCTL_SOE_REQUEST_DATA: ret = ec_ioctl_soe_request_data(master, arg, ctx); break; case EC_IOCTL_REG_REQUEST_DATA: ret = ec_ioctl_reg_request_data(master, arg, ctx); break; - case EC_IOCTL_REG_REQUEST_STATE: - ret = ec_ioctl_reg_request_state(master, arg, ctx); - break; - case EC_IOCTL_REG_REQUEST_WRITE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_reg_request_write(master, arg, ctx); - break; - case EC_IOCTL_REG_REQUEST_READ: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_reg_request_read(master, arg, ctx); - break; case EC_IOCTL_VOE_SEND_HEADER: if (!ctx->writable) { ret = -EPERM; @@ -4855,30 +4752,6 @@ static long ec_ioctl_both( } ret = ec_ioctl_voe_send_header(master, arg, ctx); break; - case EC_IOCTL_VOE_REC_HEADER: - ret = ec_ioctl_voe_rec_header(master, arg, ctx); - break; - case EC_IOCTL_VOE_READ: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_voe_read(master, arg, ctx); - break; - case EC_IOCTL_VOE_READ_NOSYNC: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_voe_read_nosync(master, arg, ctx); - break; - case EC_IOCTL_VOE_WRITE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_voe_write(master, arg, ctx); - break; case EC_IOCTL_VOE_DATA: ret = ec_ioctl_voe_data(master, arg, ctx); break; @@ -4895,6 +4768,8 @@ static long ec_ioctl_both( return ret; } +/****************************************************************************/ + /** Called when an ioctl() command is issued. * RTDM: RT only. * @@ -4961,6 +4836,13 @@ long ec_ioctl } ret = ec_ioctl_sync_slaves(master, arg, ctx); break; + case EC_IOCTL_REF_CLOCK_TIME: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_ref_clock_time(master, arg, ctx); + break; case EC_IOCTL_SYNC_MON_QUEUE: if (!ctx->writable) { ret = -EPERM; @@ -4975,6 +4857,33 @@ long ec_ioctl } ret = ec_ioctl_sync_mon_process(master, arg, ctx); break; + case EC_IOCTL_RESET: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_reset(master, arg, ctx); + break; + case EC_IOCTL_SC_EMERG_POP: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_emerg_pop(master, arg, ctx); + break; + case EC_IOCTL_SC_EMERG_CLEAR: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_emerg_clear(master, arg, ctx); + break; + case EC_IOCTL_SC_EMERG_OVERRUNS: + ret = ec_ioctl_sc_emerg_overruns(master, arg, ctx); + break; + case EC_IOCTL_SC_STATE: + ret = ec_ioctl_sc_state(master, arg, ctx); + break; case EC_IOCTL_DOMAIN_PROCESS: if (!ctx->writable) { ret = -EPERM; @@ -4989,6 +4898,98 @@ long ec_ioctl } ret = ec_ioctl_domain_queue(master, arg, ctx); break; + case EC_IOCTL_DOMAIN_STATE: + ret = ec_ioctl_domain_state(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_INDEX: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sdo_request_index(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_STATE: + ret = ec_ioctl_sdo_request_state(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_READ: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sdo_request_read(master, arg, ctx); + break; + case EC_IOCTL_SDO_REQUEST_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sdo_request_write(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_IDN: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_index(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_STATE: + ret = ec_ioctl_soe_request_state(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_READ: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_read(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_write(master, arg, ctx); + break; + case EC_IOCTL_REG_REQUEST_STATE: + ret = ec_ioctl_reg_request_state(master, arg, ctx); + break; + case EC_IOCTL_REG_REQUEST_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_reg_request_write(master, arg, ctx); + break; + case EC_IOCTL_REG_REQUEST_READ: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_reg_request_read(master, arg, ctx); + break; + case EC_IOCTL_VOE_REC_HEADER: + ret = ec_ioctl_voe_rec_header(master, arg, ctx); + break; + case EC_IOCTL_VOE_READ: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_voe_read(master, arg, ctx); + break; + case EC_IOCTL_VOE_READ_NOSYNC: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_voe_read_nosync(master, arg, ctx); + break; + case EC_IOCTL_VOE_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_voe_write(master, arg, ctx); + break; case EC_IOCTL_VOE_EXEC: if (!ctx->writable) { ret = -EPERM; @@ -5013,6 +5014,8 @@ long ec_ioctl return ret; } +/****************************************************************************/ + /** Called when an ioctl() command is issued. * nRT context only. * @@ -5061,6 +5064,13 @@ static long ec_ioctl_nrt case EC_IOCTL_DOMAIN_DATA: ret = ec_ioctl_domain_data(master, arg); break; + case EC_IOCTL_MASTER_DEBUG: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_master_debug(master, arg); + break; case EC_IOCTL_SLAVE_STATE: if (!ctx->writable) { ret = -EPERM; @@ -5133,6 +5143,13 @@ static long ec_ioctl_nrt } ret = ec_ioctl_slave_soe_read(master, arg); break; + case EC_IOCTL_SLAVE_SOE_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_slave_soe_write(master, arg); + break; #ifdef EC_EOE case EC_IOCTL_SLAVE_EOE_IP_PARAM: if (!ctx->writable) { @@ -5142,13 +5159,6 @@ static long ec_ioctl_nrt ret = ec_ioctl_slave_eoe_ip_param(master, arg); break; #endif - case EC_IOCTL_SLAVE_SOE_WRITE: - if (!ctx->writable) { - ret = -EPERM; - break; - } - ret = ec_ioctl_slave_soe_write(master, arg); - break; case EC_IOCTL_CONFIG: ret = ec_ioctl_config(master, arg); break; @@ -5172,6 +5182,9 @@ static long ec_ioctl_nrt ret = ec_ioctl_eoe_handler(master, arg); break; #endif + + /* Application interface */ + case EC_IOCTL_REQUEST: if (!ctx->writable) { ret = -EPERM; diff --git a/master/soe_request.c b/master/soe_request.c index 20aa231a..3960d2b4 100644 --- a/master/soe_request.c +++ b/master/soe_request.c @@ -293,7 +293,7 @@ size_t ecrt_soe_request_data_size(const ec_soe_request_t *req) /****************************************************************************/ -ec_request_state_t ecrt_soe_request_state(ec_soe_request_t *req) +ec_request_state_t ecrt_soe_request_state(const ec_soe_request_t *req) { return ec_request_state_translation_table[req->state]; }