master/rtdm.c
branchstable-1.5
changeset 2707 245d8592cfdc
parent 2706 43f8e40a183d
child 2712 5d21d80777a6
equal deleted inserted replaced
2706:43f8e40a183d 2707:245d8592cfdc
    42 
    42 
    43 /** Set to 1 to enable device operations debugging.
    43 /** Set to 1 to enable device operations debugging.
    44  */
    44  */
    45 #define DEBUG 0
    45 #define DEBUG 0
    46 
    46 
    47 /****************************************************************************/
    47 
    48 
    48 /****************************************************************************/
    49 /** Context structure for an open RTDM file handle.
    49 
    50  */
    50 int ec_rtdm_open(struct rtdm_fd *, int);
    51 typedef struct {
    51 void ec_rtdm_close(struct rtdm_fd *);
    52     struct rtdm_fd *fd; /**< RTDM user data. */
    52 int ec_rtdm_ioctl(struct rtdm_fd *,
    53     ec_ioctl_context_t ioctl_ctx; /**< Context structure. */
       
    54 } ec_rtdm_context_t;
       
    55 
       
    56 /****************************************************************************/
       
    57 
       
    58 int ec_rtdm_open(struct rtdm_dev_context *, struct rtdm_fd *, int);
       
    59 int ec_rtdm_close(struct rtdm_dev_context *, struct rtdm_fd *);
       
    60 int ec_rtdm_ioctl(struct rtdm_dev_context *, struct rtdm_fd *,
       
    61         unsigned int, void __user *);
    53         unsigned int, void __user *);
    62 
    54 
    63 /****************************************************************************/
    55 /****************************************************************************/
    64 
    56 
    65 static struct rtdm_driver ec_rtdm_driver = {
    57 static struct rtdm_driver ec_rtdm_driver = {
    67 							  RTDM_CLASS_EXPERIMENTAL,
    59 							  RTDM_CLASS_EXPERIMENTAL,
    68 							  222,
    60 							  222,
    69 							  1),
    61 							  1),
    70 	.device_flags		=	RTDM_NAMED_DEVICE,
    62 	.device_flags		=	RTDM_NAMED_DEVICE,
    71 	.device_count		=	1,
    63 	.device_count		=	1,
    72 	.context_size		=	sizeof(ec_rtdm_context_t),
    64 	.context_size		=	sizeof(ec_ioctl_context_t),
    73 	.ops = {
    65 	.ops = {
    74         .open      = ec_rtdm_open;
    66         .open      = ec_rtdm_open,
    75         .close_nrt = ec_rtdm_close,
    67         .close     = ec_rtdm_close,
    76         .ioctl_rt  = ec_rtdm_ioctl,
    68         .ioctl_rt  = ec_rtdm_ioctl,
    77         .ioctl_nrt = ec_rtdm_ioctl
    69         .ioctl_nrt = ec_rtdm_ioctl
    78 	},
    70 	},
    79 };
    71 };
    80 
    72 
    86         ec_rtdm_dev_t *rtdm_dev, /**< EtherCAT RTDM device. */
    78         ec_rtdm_dev_t *rtdm_dev, /**< EtherCAT RTDM device. */
    87         ec_master_t *master /**< EtherCAT master. */
    79         ec_master_t *master /**< EtherCAT master. */
    88         )
    80         )
    89 {
    81 {
    90     int ret;
    82     int ret;
    91 
    83     char* devlabel;
    92     MODULE_VERSION
       
    93 
    84 
    94     rtdm_dev->master = master;
    85     rtdm_dev->master = master;
    95 
    86 
    96     rtdm_dev->dev = kzalloc(sizeof(struct rtdm_device), GFP_KERNEL);
    87     rtdm_dev->dev = kzalloc(sizeof(struct rtdm_device), GFP_KERNEL);
    97     if (!rtdm_dev->dev) {
    88     if (!rtdm_dev->dev) {
    98         EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device.\n");
    89         EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device.\n");
    99         return -ENOMEM;
    90         return -ENOMEM;
   100     }
    91     }
   101     
    92     
   102     rtdm_dev->dev->label = kzalloc(RTDM_MAX_DEVNAME_LEN+1, GFP_KERNEL);
    93     devlabel = kzalloc(RTDM_MAX_DEVNAME_LEN+1, GFP_KERNEL);
   103     if (!rtdm_dev->dev->label) {
    94     if (!devlabel) {
   104         EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device name.\n");
    95         EC_MASTER_ERR(master, "Failed to reserve memory for RTDM device name.\n");
   105         return -ENOMEM;
    96         return -ENOMEM;
   106         kfree(rtdm_dev->dev);
    97         kfree(rtdm_dev->dev);
   107     }
    98     }
   108     
    99     snprintf(devlabel, RTDM_MAX_DEVNAME_LEN,
   109 
   100             "EtherCAT%u", master->index);
       
   101 
       
   102     rtdm_dev->dev->label = devlabel;
   110     rtdm_dev->dev->driver = &ec_rtdm_driver;
   103     rtdm_dev->dev->driver = &ec_rtdm_driver;
   111     snprintf(rtdm_dev->dev->label, RTDM_MAX_DEVNAME_LEN,
       
   112             "EtherCAT%u", master->index);
       
   113     rtdm_dev->dev->device_data = rtdm_dev; /* pointer to parent */
   104     rtdm_dev->dev->device_data = rtdm_dev; /* pointer to parent */
   114 
   105 
   115 
   106 
   116     EC_MASTER_INFO(master, "Registering RTDM device %s.\n",
   107     EC_MASTER_INFO(master, "Registering RTDM device %s.\n",
   117             rtdm_dev->dev->driver_name);
   108             devlabel);
   118     ret = rtdm_dev_register(rtdm_dev->dev);
   109     ret = rtdm_dev_register(rtdm_dev->dev);
   119     if (ret) {
   110     if (ret) {
   120         EC_MASTER_ERR(master, "Initialization of RTDM interface failed"
   111         EC_MASTER_ERR(master, "Initialization of RTDM interface failed"
   121                 " (return value %i).\n", ret);
   112                 " (return value %i).\n", ret);
   122         kfree(rtdm_dev->dev->label);
   113         kfree(rtdm_dev->dev->label);
   132  */
   123  */
   133 void ec_rtdm_dev_clear(
   124 void ec_rtdm_dev_clear(
   134         ec_rtdm_dev_t *rtdm_dev /**< EtherCAT RTDM device. */
   125         ec_rtdm_dev_t *rtdm_dev /**< EtherCAT RTDM device. */
   135         )
   126         )
   136 {
   127 {
   137     int ret;
       
   138 
       
   139     EC_MASTER_INFO(rtdm_dev->master, "Unregistering RTDM device %s.\n",
   128     EC_MASTER_INFO(rtdm_dev->master, "Unregistering RTDM device %s.\n",
   140             rtdm_dev->dev->label);
   129             rtdm_dev->dev->label);
   141     ret = rtdm_dev_unregister(rtdm_dev->dev, 1000 /* poll delay [ms] */);
   130     rtdm_dev_unregister(rtdm_dev->dev);
   142     if (ret < 0) {
       
   143         EC_MASTER_WARN(rtdm_dev->master,
       
   144                 "Failed to unregister RTDM device (code %i).\n", ret);
       
   145     }
       
   146 
   131 
   147     kfree(rtdm_dev->dev->label);
   132     kfree(rtdm_dev->dev->label);
   148     kfree(rtdm_dev->dev);
   133     kfree(rtdm_dev->dev);
   149 }
   134 }
   150 
   135 
   153 /** Driver open.
   138 /** Driver open.
   154  *
   139  *
   155  * \return Always zero (success).
   140  * \return Always zero (success).
   156  */
   141  */
   157 int ec_rtdm_open(
   142 int ec_rtdm_open(
   158         struct rtdm_dev_context *context, /**< Context. */
       
   159         struct rtdm_fd *fd, /**< User data. */
   143         struct rtdm_fd *fd, /**< User data. */
   160         int oflags /**< Open flags. */
   144         int oflags /**< Open flags. */
   161         )
   145         )
   162 {
   146 {
   163     ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
   147     ec_ioctl_context_t *ctx = (ec_ioctl_context_t *) rtdm_fd_to_private(fd);
   164 #if DEBUG
   148 #if DEBUG
   165     ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data;
   149     ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) rtdm_fd_device(fd)->device_data;
   166 #endif
   150 #endif
   167 
   151 
   168     ctx->fd = fd;
   152     ctx->writable = oflags & O_WRONLY || oflags & O_RDWR;
   169     ctx->ioctl_ctx.writable = oflags & O_WRONLY || oflags & O_RDWR;
   153     ctx->requested = 0;
   170     ctx->ioctl_ctx.requested = 0;
   154     ctx->process_data = NULL;
   171     ctx->ioctl_ctx.process_data = NULL;
   155     ctx->process_data_size = 0;
   172     ctx->ioctl_ctx.process_data_size = 0;
       
   173 
   156 
   174 #if DEBUG
   157 #if DEBUG
   175     EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s opened.\n",
   158     EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s opened.\n",
   176             context->device->device_name);
   159             context->device->device_name);
   177 #endif
   160 #endif
   182 
   165 
   183 /** Driver close.
   166 /** Driver close.
   184  *
   167  *
   185  * \return Always zero (success).
   168  * \return Always zero (success).
   186  */
   169  */
   187 int ec_rtdm_close(
   170 void ec_rtdm_close(
   188         struct rtdm_dev_context *context, /**< Context. */
       
   189         struct rtdm_fd *fd /**< User data. */
   171         struct rtdm_fd *fd /**< User data. */
   190         )
   172         )
   191 {
   173 {
   192     ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
   174     ec_ioctl_context_t *ctx = (ec_ioctl_context_t *) rtdm_fd_to_private(fd);
   193     ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data;
   175     ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) rtdm_fd_device(fd)->device_data;
   194 
   176 
   195     if (ctx->ioctl_ctx.requested) {
   177     if (ctx->requested) {
   196         ecrt_release_master(rtdm_dev->master);
   178         ecrt_release_master(rtdm_dev->master);
   197 	}
   179 	}
   198 
   180 
   199 #if DEBUG
   181 #if DEBUG
   200     EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s closed.\n",
   182     EC_MASTER_INFO(rtdm_dev->master, "RTDM device %s closed.\n",
   201             context->device->device_name);
   183             context->device->device_name);
   202 #endif
   184 #endif
   203     return 0;
       
   204 }
   185 }
   205 
   186 
   206 /****************************************************************************/
   187 /****************************************************************************/
   207 
   188 
   208 /** Driver ioctl.
   189 /** Driver ioctl.
   209  *
   190  *
   210  * \return ioctl() return code.
   191  * \return ioctl() return code.
   211  */
   192  */
   212 int ec_rtdm_ioctl(
   193 int ec_rtdm_ioctl(
   213         struct rtdm_dev_context *context, /**< Context. */
       
   214         struct rtdm_fd *fd, /**< User data. */
   194         struct rtdm_fd *fd, /**< User data. */
   215         unsigned int request, /**< Request. */
   195         unsigned int request, /**< Request. */
   216         void __user *arg /**< Argument. */
   196         void __user *arg /**< Argument. */
   217         )
   197         )
   218 {
   198 {
   219     ec_rtdm_context_t *ctx = (ec_rtdm_context_t *) context->dev_private;
   199     ec_ioctl_context_t *ctx = (ec_ioctl_context_t *) rtdm_fd_to_private(fd);
   220     ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) context->device->device_data;
   200     ec_rtdm_dev_t *rtdm_dev = (ec_rtdm_dev_t *) rtdm_fd_device(fd)->device_data;
   221 
   201 
   222 #if DEBUG
   202 #if DEBUG
   223     EC_MASTER_INFO(rtdm_dev->master, "ioctl(request = %u, ctl = %02x)"
   203     EC_MASTER_INFO(rtdm_dev->master, "ioctl(request = %u, ctl = %02x)"
   224             " on RTDM device %s.\n", request, _IOC_NR(request),
   204             " on RTDM device %s.\n", request, _IOC_NR(request),
   225             context->device->device_name);
   205             context->device->device_name);
   226 #endif
   206 #endif
   227     return ec_ioctl_rtdm(rtdm_dev->master, &ctx->ioctl_ctx, request, arg);
   207     return ec_ioctl_rtdm(rtdm_dev->master, ctx, request, arg);
   228 }
   208 }
   229 
   209 
   230 /****************************************************************************/
   210 /****************************************************************************/
   231 
   211 
   232 /** Memory-map process data to user space.
   212 /** Memory-map process data to user space.
   233  *
   213  *
   234  * \return Zero on success, otherwise a negative error code.
   214  * \return Zero on success, otherwise a negative error code.
   235  */
   215  */
   236 int ec_rtdm_mmap(
   216 int ec_rtdm_mmap(
   237         ec_ioctl_context_t *ioctl_ctx, /**< Context. */
   217         ec_ioctl_context_t *ctx, /**< Context. */
   238         void **user_address /**< Userspace address. */
   218         void **user_address /**< Userspace address. */
   239         )
   219         )
   240 {
   220 {
   241     ec_rtdm_context_t *ctx =
       
   242         container_of(ioctl_ctx, ec_rtdm_context_t, ioctl_ctx);
       
   243     int ret;
   221     int ret;
   244 
   222 
   245     ret = rtdm_mmap_to_user(ctx->fd,
   223     ret = rtdm_mmap_to_user(rtdm_private_to_fd(ctx),
   246             ioctl_ctx->process_data, ioctl_ctx->process_data_size,
   224             ctx->process_data, ctx->process_data_size,
   247             PROT_READ | PROT_WRITE,
   225             PROT_READ | PROT_WRITE,
   248             user_address,
   226             user_address,
   249             NULL, NULL);
   227             NULL, NULL);
   250     if (ret < 0) {
   228     if (ret < 0) {
   251         return ret;
   229         return ret;