37 #include <linux/version.h> 38 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) 39 #include <linux/export.h> 42 #include <linux/file.h> 43 #include <linux/firmware.h> 44 #include <asm/processor.h> 52 #ifdef EC_SII_OVERRIDE 61 static int request_firmware_direct(
64 struct firmware **out_firmware
69 const int permreqd = S_IROTH;
70 const int permforbid = S_IFDIR | S_ISVTX | S_IXOTH | S_IXGRP | S_IXUSR;
74 struct firmware *firmware;
78 char pathname[strlen(filename) +
sizeof(EC_SII_DIR)];
82 if (strlen(filename) + 14 >= 256)
85 EC_SLAVE_DBG(slave, 1,
"request_firmware_direct: %s.\n", filename);
86 sprintf(pathname, EC_SII_DIR
"/%s", filename);
89 filp = filp_open(pathname, 0, O_RDONLY);
90 if ((IS_ERR(filp)) || (filp == NULL) || (filp->f_dentry == NULL)) {
96 permission = filp->f_dentry->d_inode->i_mode;
97 if ((permission & permreqd) != permreqd) {
98 EC_SLAVE_WARN(slave,
"Firmware %s not readable.\n", filename);
102 if ((permission & permforbid) != 0) {
103 EC_SLAVE_WARN(slave,
"Firmware %s incorrect perms.\n", filename);
108 *out_firmware = firmware = kzalloc(
sizeof(*firmware), GFP_KERNEL);
110 EC_SLAVE_ERR(slave,
"Failed to allocate memory (struct firmware).\n");
114 firmware->size = filp->f_dentry->d_inode->i_size;
116 if (!(firmware->data = kmalloc(firmware->size, GFP_KERNEL))) {
117 EC_SLAVE_ERR(slave,
"Failed to allocate memory (firmware data).\n");
127 while (pos < firmware->size) {
128 retval = vfs_read(filp, (
char __user *) firmware->data + pos,
129 firmware->size - pos, &pos);
132 EC_SLAVE_ERR(slave,
"Failed to read firmware (%d).\n", retval);
133 goto error_firmware_data;
139 EC_SLAVE_INFO(slave,
"SII firmware loaded from file %s.\n", filename);
140 filp_close(filp, NULL);
144 kfree(firmware->data);
147 *out_firmware = NULL;
149 filp_close(filp, NULL);
157 struct firmware_request_context
160 struct work_struct work;
161 const char *filename;
163 struct device fw_device;
167 void (*cont)(
const struct firmware *,
void *);
169 char filename_vendor_product[48];
170 char filename_vendor_product_revision[48];
174 static void firmware_request_complete(
const struct firmware *,
void *);
179 static int request_firmware_direct_work_func(
void *arg)
181 struct firmware_request_context *ctx = arg;
182 struct firmware *fw = NULL;
184 if (request_firmware_direct(ctx->slave, ctx->filename, &fw) == 0) {
185 firmware_request_complete(fw, ctx);
187 firmware_request_complete(NULL, ctx);
194 static int start_request(
195 struct firmware_request_context *ctx,
199 struct task_struct *task;
201 ctx->filename = filename;
202 task = kthread_run(request_firmware_direct_work_func, ctx,
203 "firmware/%s", filename);
205 firmware_request_complete(NULL, ctx);
206 return PTR_ERR(task);
211 static void clear_request(
212 struct firmware_request_context *ctx
221 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33) 222 #error "SII override requires kernel 2.6.33 or later; use --disable-sii-override instead." 225 static void fw_device_release(
struct device *dev)
227 struct firmware_request_context *ctx =
228 container_of(dev,
struct firmware_request_context, fw_device);
232 static int start_request(
233 struct firmware_request_context *ctx,
237 if (!ctx->device_inited) {
242 device_initialize(&ctx->fw_device);
243 dev_set_name(&ctx->fw_device,
"addr%u", ctx->slave->station_address);
244 dev_set_uevent_suppress(&ctx->fw_device,
true);
245 ctx->fw_device.parent = ctx->slave->master->class_device;
246 ctx->fw_device.release = fw_device_release;
248 error = device_add(&ctx->fw_device);
250 EC_SLAVE_ERR(ctx->slave,
"Unable to register child device for firmware.\n");
251 put_device(&ctx->fw_device);
254 ctx->device_inited =
true;
257 return request_firmware_nowait(THIS_MODULE, 1, filename,
258 &ctx->fw_device, GFP_KERNEL, ctx, firmware_request_complete);
261 static void clear_request(
262 struct firmware_request_context *ctx
265 if (ctx->device_inited) {
266 device_del(&ctx->fw_device);
267 put_device(&ctx->fw_device);
278 static void firmware_request_complete(
279 const struct firmware *firmware,
283 struct firmware_request_context *ctx = context;
285 if (!firmware && !ctx->fallback) {
286 ctx->fallback =
true;
287 if (start_request(ctx, ctx->filename_vendor_product) == 0) {
292 ctx->cont(firmware, ctx->context);
302 void ec_request_sii_firmware(
305 void (*cont)(
const struct firmware *,
void *)
308 struct firmware_request_context *ctx;
310 if (!(ctx = kzalloc(
sizeof(*ctx), GFP_KERNEL))) {
311 EC_SLAVE_ERR(slave,
"Unable to allocate firmware request context.\n");
315 sprintf(ctx->filename_vendor_product,
"ethercat/ec_%08x_%08x.bin",
318 sprintf(ctx->filename_vendor_product_revision,
"ethercat/ec_%08x_%08x_%08x.bin",
324 ctx->context = context;
328 EC_SLAVE_DBG(slave, 1,
"Trying to load SII firmware: %s\n", ctx->filename_vendor_product_revision);
329 EC_SLAVE_DBG(slave, 1,
" then: %s\n", ctx->filename_vendor_product);
331 if (start_request(ctx, ctx->filename_vendor_product_revision) == 0) {
345 void ec_release_sii_firmware(
const struct firmware *firmware )
349 kfree(firmware->data);
353 release_firmware(firmware);
358 #endif //EC_SII_OVERRIDE uint32_t revision_number
Revision number.
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
EtherCAT slave structure.
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
EtherCAT master structure.
ec_sii_image_t * sii_image
Current complete SII image.
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
#define EC_SLAVE_INFO(slave, fmt, args...)
Convenience macro for printing slave-specific information to syslog.
ec_sii_t sii
Extracted SII data.
uint32_t product_code
Vendor-specific product code.
uint32_t vendor_id
Vendor ID.