2388 if (copy_to_user((void __user *) data.data, ecrt_voe_handler_data(voe), |
2388 if (copy_to_user((void __user *) data.data, ecrt_voe_handler_data(voe), |
2389 ecrt_voe_handler_data_size(voe))) |
2389 ecrt_voe_handler_data_size(voe))) |
2390 return -EFAULT; |
2390 return -EFAULT; |
2391 |
2391 |
2392 return 0; |
2392 return 0; |
|
2393 } |
|
2394 |
|
2395 /*****************************************************************************/ |
|
2396 |
|
2397 /** Read a file from a slave via FoE. |
|
2398 */ |
|
2399 int ec_cdev_ioctl_slave_foe_read( |
|
2400 ec_master_t *master, /**< EtherCAT master. */ |
|
2401 unsigned long arg /**< ioctl() argument. */ |
|
2402 ) |
|
2403 { |
|
2404 ec_ioctl_slave_foe_t data; |
|
2405 ec_master_foe_request_t request; |
|
2406 int retval; |
|
2407 |
|
2408 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
|
2409 return -EFAULT; |
|
2410 } |
|
2411 |
|
2412 ec_foe_request_init(&request.req, data.file_name); |
|
2413 ec_foe_request_read(&request.req); |
|
2414 ec_foe_request_alloc(&request.req, 10000); // FIXME |
|
2415 |
|
2416 if (down_interruptible(&master->master_sem)) |
|
2417 return -EINTR; |
|
2418 |
|
2419 if (!(request.slave = ec_master_find_slave( |
|
2420 master, 0, data.slave_position))) { |
|
2421 up(&master->master_sem); |
|
2422 ec_foe_request_clear(&request.req); |
|
2423 EC_ERR("Slave %u does not exist!\n", data.slave_position); |
|
2424 return -EINVAL; |
|
2425 } |
|
2426 |
|
2427 // schedule request. |
|
2428 list_add_tail(&request.list, &master->foe_requests); |
|
2429 |
|
2430 up(&master->master_sem); |
|
2431 |
|
2432 // wait for processing through FSM |
|
2433 if (wait_event_interruptible(master->foe_queue, |
|
2434 request.req.state != EC_INT_REQUEST_QUEUED)) { |
|
2435 // interrupted by signal |
|
2436 down(&master->master_sem); |
|
2437 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
|
2438 list_del(&request.list); |
|
2439 up(&master->master_sem); |
|
2440 ec_foe_request_clear(&request.req); |
|
2441 return -EINTR; |
|
2442 } |
|
2443 // request already processing: interrupt not possible. |
|
2444 up(&master->master_sem); |
|
2445 } |
|
2446 |
|
2447 // wait until master FSM has finished processing |
|
2448 wait_event(master->foe_queue, request.req.state != EC_REQUEST_BUSY); |
|
2449 |
|
2450 data.abort_code = request.req.abort_code; |
|
2451 |
|
2452 if (master->debug_level) { |
|
2453 EC_DBG("%d bytes read via FoE (abort_code = 0x%x).\n", |
|
2454 request.req.data_size, request.req.abort_code); |
|
2455 } |
|
2456 |
|
2457 if (request.req.state != EC_REQUEST_SUCCESS) { |
|
2458 data.data_size = 0; |
|
2459 retval = -EIO; |
|
2460 } else { |
|
2461 if (request.req.data_size > data.buffer_size) { |
|
2462 EC_ERR("Buffer too small.\n"); |
|
2463 ec_foe_request_clear(&request.req); |
|
2464 return -EOVERFLOW; |
|
2465 } |
|
2466 data.data_size = request.req.data_size; |
|
2467 if (copy_to_user((void __user *) data.buffer, |
|
2468 request.req.buffer, data.data_size)) { |
|
2469 ec_foe_request_clear(&request.req); |
|
2470 return -EFAULT; |
|
2471 } |
|
2472 retval = 0; |
|
2473 } |
|
2474 |
|
2475 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
|
2476 retval = -EFAULT; |
|
2477 } |
|
2478 |
|
2479 ec_foe_request_clear(&request.req); |
|
2480 return retval; |
|
2481 } |
|
2482 |
|
2483 /*****************************************************************************/ |
|
2484 |
|
2485 /** Write a file to a slave via FoE |
|
2486 */ |
|
2487 int ec_cdev_ioctl_slave_foe_write( |
|
2488 ec_master_t *master, /**< EtherCAT master. */ |
|
2489 unsigned long arg /**< ioctl() argument. */ |
|
2490 ) |
|
2491 { |
|
2492 ec_ioctl_slave_foe_t data; |
|
2493 ec_master_foe_request_t request; |
|
2494 int retval; |
|
2495 |
|
2496 if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { |
|
2497 return -EFAULT; |
|
2498 } |
|
2499 |
|
2500 INIT_LIST_HEAD(&request.list); |
|
2501 |
|
2502 ec_foe_request_init(&request.req, data.file_name); |
|
2503 |
|
2504 if (ec_foe_request_alloc(&request.req, data.buffer_size)) { |
|
2505 ec_foe_request_clear(&request.req); |
|
2506 return -ENOMEM; |
|
2507 } |
|
2508 if (copy_from_user(request.req.buffer, |
|
2509 (void __user *) data.buffer, data.buffer_size)) { |
|
2510 ec_foe_request_clear(&request.req); |
|
2511 return -EFAULT; |
|
2512 } |
|
2513 request.req.data_size = data.buffer_size; |
|
2514 ec_foe_request_write(&request.req); |
|
2515 |
|
2516 if (down_interruptible(&master->master_sem)) |
|
2517 return -EINTR; |
|
2518 |
|
2519 if (!(request.slave = ec_master_find_slave( |
|
2520 master, 0, data.slave_position))) { |
|
2521 up(&master->master_sem); |
|
2522 EC_ERR("Slave %u does not exist!\n", data.slave_position); |
|
2523 ec_foe_request_clear(&request.req); |
|
2524 return -EINVAL; |
|
2525 } |
|
2526 |
|
2527 if (master->debug_level) { |
|
2528 EC_DBG("Scheduling FoE write request.\n"); |
|
2529 } |
|
2530 |
|
2531 // schedule FoE write request. |
|
2532 list_add_tail(&request.list, &master->foe_requests); |
|
2533 |
|
2534 up(&master->master_sem); |
|
2535 |
|
2536 // wait for processing through FSM |
|
2537 if (wait_event_interruptible(master->foe_queue, |
|
2538 request.req.state != EC_INT_REQUEST_QUEUED)) { |
|
2539 // interrupted by signal |
|
2540 down(&master->master_sem); |
|
2541 if (request.req.state == EC_INT_REQUEST_QUEUED) { |
|
2542 // abort request |
|
2543 list_del(&request.list); |
|
2544 up(&master->master_sem); |
|
2545 ec_foe_request_clear(&request.req); |
|
2546 return -EINTR; |
|
2547 } |
|
2548 up(&master->master_sem); |
|
2549 } |
|
2550 |
|
2551 // wait until master FSM has finished processing |
|
2552 wait_event(master->foe_queue, request.req.state != EC_REQUEST_BUSY); |
|
2553 |
|
2554 data.abort_code = request.req.abort_code; |
|
2555 |
|
2556 retval = request.req.state == EC_REQUEST_SUCCESS ? 0 : -EIO; |
|
2557 |
|
2558 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) { |
|
2559 retval = -EFAULT; |
|
2560 } |
|
2561 |
|
2562 ec_foe_request_clear(&request.req); |
|
2563 |
|
2564 if (master->debug_level) { |
|
2565 printk ("Finished FoE writing.\n"); |
|
2566 } |
|
2567 |
|
2568 return retval; |
2393 } |
2569 } |
2394 |
2570 |
2395 /****************************************************************************** |
2571 /****************************************************************************** |
2396 * File operations |
2572 * File operations |
2397 *****************************************************************************/ |
2573 *****************************************************************************/ |
2500 return ec_cdev_ioctl_slave_phy_read(master, arg); |
2676 return ec_cdev_ioctl_slave_phy_read(master, arg); |
2501 case EC_IOCTL_SLAVE_PHY_WRITE: |
2677 case EC_IOCTL_SLAVE_PHY_WRITE: |
2502 if (!(filp->f_mode & FMODE_WRITE)) |
2678 if (!(filp->f_mode & FMODE_WRITE)) |
2503 return -EPERM; |
2679 return -EPERM; |
2504 return ec_cdev_ioctl_slave_phy_write(master, arg); |
2680 return ec_cdev_ioctl_slave_phy_write(master, arg); |
|
2681 case EC_IOCTL_SLAVE_FOE_READ: |
|
2682 return ec_cdev_ioctl_slave_foe_read(master, arg); |
|
2683 case EC_IOCTL_SLAVE_FOE_WRITE: |
|
2684 if (!(filp->f_mode & FMODE_WRITE)) |
|
2685 return -EPERM; |
|
2686 return ec_cdev_ioctl_slave_foe_write(master, arg); |
2505 case EC_IOCTL_CONFIG: |
2687 case EC_IOCTL_CONFIG: |
2506 return ec_cdev_ioctl_config(master, arg); |
2688 return ec_cdev_ioctl_config(master, arg); |
2507 case EC_IOCTL_CONFIG_PDO: |
2689 case EC_IOCTL_CONFIG_PDO: |
2508 return ec_cdev_ioctl_config_pdo(master, arg); |
2690 return ec_cdev_ioctl_config_pdo(master, arg); |
2509 case EC_IOCTL_CONFIG_PDO_ENTRY: |
2691 case EC_IOCTL_CONFIG_PDO_ENTRY: |