282 data.current_on_ebus = slave->sii.current_on_ebus; |
282 data.current_on_ebus = slave->sii.current_on_ebus; |
283 for (i = 0; i < EC_MAX_PORTS; i++) { |
283 for (i = 0; i < EC_MAX_PORTS; i++) { |
284 data.ports[i].desc = slave->ports[i].desc; |
284 data.ports[i].desc = slave->ports[i].desc; |
285 data.ports[i].link.link_up = slave->ports[i].link.link_up; |
285 data.ports[i].link.link_up = slave->ports[i].link.link_up; |
286 data.ports[i].link.loop_closed = slave->ports[i].link.loop_closed; |
286 data.ports[i].link.loop_closed = slave->ports[i].link.loop_closed; |
287 data.ports[i].link.signal_detected = slave->ports[i].link.signal_detected; |
287 data.ports[i].link.signal_detected = |
|
288 slave->ports[i].link.signal_detected; |
288 data.ports[i].receive_time = slave->ports[i].receive_time; |
289 data.ports[i].receive_time = slave->ports[i].receive_time; |
289 if (slave->ports[i].next_slave) { |
290 if (slave->ports[i].next_slave) { |
290 data.ports[i].next_slave = slave->ports[i].next_slave->ring_position; |
291 data.ports[i].next_slave = |
|
292 slave->ports[i].next_slave->ring_position; |
291 } else { |
293 } else { |
292 data.ports[i].next_slave = 0xffff; |
294 data.ports[i].next_slave = 0xffff; |
293 } |
295 } |
294 data.ports[i].delay_to_next_dc = slave->ports[i].delay_to_next_dc; |
296 data.ports[i].delay_to_next_dc = slave->ports[i].delay_to_next_dc; |
295 } |
297 } |
3224 } |
3237 } |
3225 |
3238 |
3226 ec_foe_request_clear(&request.req); |
3239 ec_foe_request_clear(&request.req); |
3227 |
3240 |
3228 if (master->debug_level) { |
3241 if (master->debug_level) { |
3229 printk("Finished FoE writing.\n"); |
3242 EC_DBG("Finished FoE writing.\n"); |
|
3243 } |
|
3244 |
|
3245 return retval; |
|
3246 } |
|
3247 |
|
3248 /*****************************************************************************/ |
|
3249 |
|
3250 /** Read an SoE IDN. |
|
3251 */ |
|
3252 int ec_cdev_ioctl_slave_soe_read( |
|
3253 ec_master_t *master, /**< EtherCAT master. */ |
|
3254 unsigned long arg /**< ioctl() argument. */ |
|
3255 ) |
|
3256 { |
|
3257 ec_ioctl_slave_soe_t data; |
|
3258 ec_master_soe_request_t request; |
|
3259 int retval; |
|
3260 |
|
3261 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
|
3262 return -EFAULT; |
|
3263 } |
|
3264 |
|
3265 ec_soe_request_init(&request.req); |
|
3266 ec_soe_request_set_idn(&request.req, data.idn); |
|
3267 ec_soe_request_read(&request.req); |
|
3268 |
|
3269 if (down_interruptible(&master->master_sem)) |
|
3270 return -EINTR; |
|
3271 |
|
3272 if (!(request.slave = ec_master_find_slave( |
|
3273 master, 0, data.slave_position))) { |
|
3274 up(&master->master_sem); |
|
3275 ec_soe_request_clear(&request.req); |
|
3276 EC_ERR("Slave %u does not exist!\n", data.slave_position); |
|
3277 return -EINVAL; |
|
3278 } |
|
3279 |
|
3280 // schedule request. |
|
3281 list_add_tail(&request.list, &request.slave->soe_requests); |
|
3282 |
|
3283 up(&master->master_sem); |
|
3284 |
|
3285 if (master->debug_level) { |
|
3286 EC_DBG("Scheduled SoE read request on slave %u.\n", |
|
3287 request.slave->ring_position); |
|
3288 } |
|
3289 |
|
3290 // wait for processing through FSM |
|
3291 if (wait_event_interruptible(request.slave->soe_queue, |
|
3292 request.req.state != EC_INT_REQUEST_QUEUED)) { |
|
3293 // interrupted by signal |
|
3294 down(&master->master_sem); |
|
3295 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
|
3296 list_del(&request.list); |
|
3297 up(&master->master_sem); |
|
3298 ec_soe_request_clear(&request.req); |
|
3299 return -EINTR; |
|
3300 } |
|
3301 // request already processing: interrupt not possible. |
|
3302 up(&master->master_sem); |
|
3303 } |
|
3304 |
|
3305 // wait until master FSM has finished processing |
|
3306 wait_event(request.slave->soe_queue, |
|
3307 request.req.state != EC_INT_REQUEST_BUSY); |
|
3308 |
|
3309 data.error_code = request.req.error_code; |
|
3310 |
|
3311 if (master->debug_level) { |
|
3312 EC_DBG("Read %zd bytes via SoE.\n", request.req.data_size); |
|
3313 } |
|
3314 |
|
3315 if (request.req.state != EC_INT_REQUEST_SUCCESS) { |
|
3316 data.data_size = 0; |
|
3317 retval = -EIO; |
|
3318 } else { |
|
3319 if (request.req.data_size > data.mem_size) { |
|
3320 EC_ERR("Buffer too small.\n"); |
|
3321 ec_soe_request_clear(&request.req); |
|
3322 return -EOVERFLOW; |
|
3323 } |
|
3324 data.data_size = request.req.data_size; |
|
3325 if (copy_to_user((void __user *) data.data, |
|
3326 request.req.data, data.data_size)) { |
|
3327 ec_soe_request_clear(&request.req); |
|
3328 return -EFAULT; |
|
3329 } |
|
3330 retval = 0; |
|
3331 } |
|
3332 |
|
3333 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
|
3334 retval = -EFAULT; |
|
3335 } |
|
3336 |
|
3337 if (master->debug_level) |
|
3338 EC_DBG("SoE read request finished on slave %u.\n", |
|
3339 request.slave->ring_position); |
|
3340 |
|
3341 ec_soe_request_clear(&request.req); |
|
3342 |
|
3343 return retval; |
|
3344 } |
|
3345 |
|
3346 /*****************************************************************************/ |
|
3347 |
|
3348 /** Write an IDN to a slave via SoE. |
|
3349 */ |
|
3350 int ec_cdev_ioctl_slave_soe_write( |
|
3351 ec_master_t *master, /**< EtherCAT master. */ |
|
3352 unsigned long arg /**< ioctl() argument. */ |
|
3353 ) |
|
3354 { |
|
3355 ec_ioctl_slave_soe_t data; |
|
3356 ec_master_soe_request_t request; |
|
3357 int retval; |
|
3358 |
|
3359 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
|
3360 return -EFAULT; |
|
3361 } |
|
3362 |
|
3363 INIT_LIST_HEAD(&request.list); |
|
3364 |
|
3365 ec_soe_request_init(&request.req); |
|
3366 ec_soe_request_set_idn(&request.req, data.idn); |
|
3367 |
|
3368 if (ec_soe_request_alloc(&request.req, data.mem_size)) { |
|
3369 ec_soe_request_clear(&request.req); |
|
3370 return -ENOMEM; |
|
3371 } |
|
3372 if (copy_from_user(request.req.data, |
|
3373 (void __user *) data.data, data.mem_size)) { |
|
3374 ec_soe_request_clear(&request.req); |
|
3375 return -EFAULT; |
|
3376 } |
|
3377 request.req.data_size = data.mem_size; |
|
3378 ec_soe_request_write(&request.req); |
|
3379 |
|
3380 if (down_interruptible(&master->master_sem)) |
|
3381 return -EINTR; |
|
3382 |
|
3383 if (!(request.slave = ec_master_find_slave( |
|
3384 master, 0, data.slave_position))) { |
|
3385 up(&master->master_sem); |
|
3386 EC_ERR("Slave %u does not exist!\n", data.slave_position); |
|
3387 ec_soe_request_clear(&request.req); |
|
3388 return -EINVAL; |
|
3389 } |
|
3390 |
|
3391 if (master->debug_level) { |
|
3392 EC_DBG("Scheduling SoE write request.\n"); |
|
3393 } |
|
3394 |
|
3395 // schedule SoE write request. |
|
3396 list_add_tail(&request.list, &request.slave->soe_requests); |
|
3397 |
|
3398 up(&master->master_sem); |
|
3399 |
|
3400 // wait for processing through FSM |
|
3401 if (wait_event_interruptible(request.slave->soe_queue, |
|
3402 request.req.state != EC_INT_REQUEST_QUEUED)) { |
|
3403 // interrupted by signal |
|
3404 down(&master->master_sem); |
|
3405 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
|
3406 // abort request |
|
3407 list_del(&request.list); |
|
3408 up(&master->master_sem); |
|
3409 ec_soe_request_clear(&request.req); |
|
3410 return -EINTR; |
|
3411 } |
|
3412 up(&master->master_sem); |
|
3413 } |
|
3414 |
|
3415 // wait until master FSM has finished processing |
|
3416 wait_event(request.slave->soe_queue, |
|
3417 request.req.state != EC_INT_REQUEST_BUSY); |
|
3418 |
|
3419 //data.result = request.req.result; |
|
3420 |
|
3421 retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO; |
|
3422 |
|
3423 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
|
3424 retval = -EFAULT; |
|
3425 } |
|
3426 |
|
3427 ec_soe_request_clear(&request.req); |
|
3428 |
|
3429 if (master->debug_level) { |
|
3430 EC_DBG("Finished SoE writing.\n"); |
3230 } |
3431 } |
3231 |
3432 |
3232 return retval; |
3433 return retval; |
3233 } |
3434 } |
3234 |
3435 |
3352 return ec_cdev_ioctl_slave_foe_read(master, arg); |
3553 return ec_cdev_ioctl_slave_foe_read(master, arg); |
3353 case EC_IOCTL_SLAVE_FOE_WRITE: |
3554 case EC_IOCTL_SLAVE_FOE_WRITE: |
3354 if (!(filp->f_mode & FMODE_WRITE)) |
3555 if (!(filp->f_mode & FMODE_WRITE)) |
3355 return -EPERM; |
3556 return -EPERM; |
3356 return ec_cdev_ioctl_slave_foe_write(master, arg); |
3557 return ec_cdev_ioctl_slave_foe_write(master, arg); |
|
3558 case EC_IOCTL_SLAVE_SOE_READ: |
|
3559 return ec_cdev_ioctl_slave_soe_read(master, arg); |
|
3560 case EC_IOCTL_SLAVE_SOE_WRITE: |
|
3561 if (!(filp->f_mode & FMODE_WRITE)) |
|
3562 return -EPERM; |
|
3563 return ec_cdev_ioctl_slave_soe_write(master, arg); |
3357 case EC_IOCTL_CONFIG: |
3564 case EC_IOCTL_CONFIG: |
3358 return ec_cdev_ioctl_config(master, arg); |
3565 return ec_cdev_ioctl_config(master, arg); |
3359 case EC_IOCTL_CONFIG_PDO: |
3566 case EC_IOCTL_CONFIG_PDO: |
3360 return ec_cdev_ioctl_config_pdo(master, arg); |
3567 return ec_cdev_ioctl_config_pdo(master, arg); |
3361 case EC_IOCTL_CONFIG_PDO_ENTRY: |
3568 case EC_IOCTL_CONFIG_PDO_ENTRY: |