#include <linux/cdev.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
-#include <linux/devfs_fs_kernel.h>
+#include <linux/compat.h>
#include "csr1212.h"
#include "ieee1394.h"
queue_complete_req(req);
}
+#ifdef CONFIG_COMPAT
+struct compat_raw1394_req {
+ __u32 type;
+ __s32 error;
+ __u32 misc;
+
+ __u32 generation;
+ __u32 length;
+
+ __u64 address;
+
+ __u64 tag;
+
+ __u64 sendb;
+ __u64 recvb;
+} __attribute__((packed));
+
+static const char __user *raw1394_compat_write(const char __user *buf)
+{
+ struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
+ struct raw1394_request __user *r;
+ r = compat_alloc_user_space(sizeof(struct raw1394_request));
+
+#define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x))
+
+ if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) ||
+ C(address) ||
+ C(tag) ||
+ C(sendb) ||
+ C(recvb))
+ return ERR_PTR(-EFAULT);
+ return (const char __user *)r;
+}
+#undef C
+
+#define P(x) __put_user(r->x, &cr->x)
+
+static int
+raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
+{
+ struct compat_raw1394_req __user *cr = (typeof(cr)) r;
+ if (!access_ok(VERIFY_WRITE,cr,sizeof(struct compat_raw1394_req)) ||
+ P(type) ||
+ P(error) ||
+ P(misc) ||
+ P(generation) ||
+ P(length) ||
+ P(address) ||
+ P(tag) ||
+ P(sendb) ||
+ P(recvb))
+ return -EFAULT;
+ return sizeof(struct compat_raw1394_req);
+}
+#undef P
+
+#endif
+
+
static ssize_t raw1394_read(struct file *file, char __user * buffer,
size_t count, loff_t * offset_is_ignored)
{
struct pending_request *req;
ssize_t ret;
+#ifdef CONFIG_COMPAT
+ if (count == sizeof(struct compat_raw1394_req)) {
+ /* ok */
+ } else
+#endif
if (count != sizeof(struct raw1394_request)) {
return -EINVAL;
}
req->req.error = RAW1394_ERROR_MEMFAULT;
}
}
- if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
- ret = -EFAULT;
- goto out;
- }
- ret = (ssize_t) sizeof(struct raw1394_request);
+#ifdef CONFIG_COMPAT
+ if (count == sizeof(struct compat_raw1394_req) &&
+ sizeof(struct compat_raw1394_req) !=
+ sizeof(struct raw1394_request)) {
+ ret = raw1394_compat_read(buffer, &req->req);
+
+ } else
+#endif
+ {
+ if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
+ ret = -EFAULT;
+ goto out;
+ }
+ ret = (ssize_t) sizeof(struct raw1394_request);
+ }
out:
free_pending_request(req);
return ret;
req->req.length)) {
csr1212_release_keyval(fi->csr1212_dirs[dr]);
fi->csr1212_dirs[dr] = NULL;
- CSR1212_FREE(cache);
ret = -EFAULT;
} else {
cache->len = req->req.length;
}
}
kfree(cache->filled_head);
- kfree(cache);
+ CSR1212_FREE(cache);
if (ret >= 0) {
/* we have to free the request, because we queue no response,
return handle_async_request(fi, req, node);
}
+
static ssize_t raw1394_write(struct file *file, const char __user * buffer,
size_t count, loff_t * offset_is_ignored)
{
struct pending_request *req;
ssize_t retval = 0;
+#ifdef CONFIG_COMPAT
+ if (count == sizeof(struct compat_raw1394_req) &&
+ sizeof(struct compat_raw1394_req) !=
+ sizeof(struct raw1394_request)) {
+ buffer = raw1394_compat_write(buffer);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+ } else
+#endif
if (count != sizeof(struct raw1394_request)) {
return -EINVAL;
}
/* ensure user-supplied buffer is accessible and big enough */
if (!access_ok(VERIFY_WRITE, upackets.infos,
- upackets.n_packets *
- sizeof(struct raw1394_iso_packet_info)))
+ upackets.n_packets *
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
/* copy the packet_infos out */
/* ensure user-supplied buffer is accessible and big enough */
if (!access_ok(VERIFY_READ, upackets.infos,
- upackets.n_packets *
- sizeof(struct raw1394_iso_packet_info)))
+ upackets.n_packets *
+ sizeof(struct raw1394_iso_packet_info)))
return -EFAULT;
/* copy the infos structs in and queue the packets */
list) {
entry = fi_hlp->addr_list.next;
while (entry != &(fi_hlp->addr_list)) {
- arm_addr = list_entry(entry,
- struct
+ arm_addr = list_entry(entry, struct
arm_addr,
addr_list);
if (arm_addr->start ==
.write = raw1394_write,
.mmap = raw1394_mmap,
.ioctl = raw1394_ioctl,
+ // .compat_ioctl = ... someone needs to do this
.poll = raw1394_poll,
.open = raw1394_open,
.release = raw1394_release,
hpsb_register_highlevel(&raw1394_highlevel);
- if (IS_ERR(class_device_create(hpsb_protocol_class, NULL, MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- NULL, RAW1394_DEVICE_NAME))) {
+ if (IS_ERR
+ (class_device_create
+ (hpsb_protocol_class, NULL,
+ MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16), NULL,
+ RAW1394_DEVICE_NAME))) {
ret = -EFAULT;
goto out_unreg;
}
-
- devfs_mk_cdev(MKDEV(
- IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
- S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
cdev_init(&raw1394_cdev, &raw1394_fops);
raw1394_cdev.owner = THIS_MODULE;
goto out;
-out_dev:
- devfs_remove(RAW1394_DEVICE_NAME);
+ out_dev:
class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
-out_unreg:
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ out_unreg:
hpsb_unregister_highlevel(&raw1394_highlevel);
-out:
+ out:
return ret;
}
static void __exit cleanup_raw1394(void)
{
class_device_destroy(hpsb_protocol_class,
- MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+ MKDEV(IEEE1394_MAJOR,
+ IEEE1394_MINOR_BLOCK_RAW1394 * 16));
cdev_del(&raw1394_cdev);
- devfs_remove(RAW1394_DEVICE_NAME);
hpsb_unregister_highlevel(&raw1394_highlevel);
hpsb_unregister_protocol(&raw1394_driver);
}