summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sys/file.h4
-rw-r--r--include/sys/sunddi.h179
-rw-r--r--include/sys/sunldi.h27
-rw-r--r--include/sys/types.h2
-rw-r--r--include/sys/vnode.h1
-rw-r--r--modules/spl/Makefile.in1
-rw-r--r--modules/spl/spl-module.c297
-rw-r--r--modules/spl/spl-vnode.c1
-rw-r--r--modules/splat/splat-vnode.c4
9 files changed, 508 insertions, 8 deletions
diff --git a/include/sys/file.h b/include/sys/file.h
new file mode 100644
index 000000000..63d662237
--- /dev/null
+++ b/include/sys/file.h
@@ -0,0 +1,4 @@
+#ifndef _SPL_FILE_H
+#define _SPL_FILE_H
+
+#endif /* SPL_FILE_H */
diff --git a/include/sys/sunddi.h b/include/sys/sunddi.h
index 541102556..888b84451 100644
--- a/include/sys/sunddi.h
+++ b/include/sys/sunddi.h
@@ -1,4 +1,183 @@
#ifndef _SPL_SUNDDI_H
#define _SPL_SUNDDI_H
+#include <sys/cred.h>
+#include <sys/uio.h>
+#include <sys/sunldi.h>
+#include <sys/mutex.h>
+#include <linux/kdev_t.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/list.h>
+#include <linux/device.h>
+
+typedef int ddi_devid_t;
+
+typedef enum {
+ DDI_INFO_DEVT2DEVINFO = 0,
+ DDI_INFO_DEVT2INSTANCE = 1
+} ddi_info_cmd_t;
+
+typedef enum {
+ DDI_ATTACH = 0,
+ DDI_RESUME = 1,
+ DDI_PM_RESUME = 2
+} ddi_attach_cmd_t;
+
+typedef enum {
+ DDI_DETACH = 0,
+ DDI_SUSPEND = 1,
+ DDI_PM_SUSPEND = 2,
+ DDI_HOTPLUG_DETACH = 3
+} ddi_detach_cmd_t;
+
+typedef enum {
+ DDI_RESET_FORCE = 0
+} ddi_reset_cmd_t;
+
+typedef enum {
+ PROP_LEN = 0,
+ PROP_LEN_AND_VAL_BUF = 1,
+ PROP_LEN_AND_VAL_ALLOC = 2,
+ PROP_EXISTS = 3
+} ddi_prop_op_t;
+
+typedef void *devmap_cookie_t;
+typedef struct as {
+ uchar_t a_flags;
+} as_t;
+
+typedef struct pollhead {
+ struct polldat *ph_list;
+} pollhead_t;
+
+typedef struct dev_info {
+ kmutex_t di_lock;
+ struct dev_ops *di_ops;
+ struct cdev *di_cdev;
+ struct class *di_class;
+ major_t di_major;
+ minor_t di_minor;
+ dev_t di_dev;
+ unsigned di_minors;
+ struct list_head di_list;
+} dev_info_t;
+
+typedef struct cb_ops {
+ int (*cb_open)(dev_t *devp, int flag, int otyp, cred_t *credp);
+ int (*cb_close)(dev_t dev, int flag, int otyp, cred_t *credp);
+ int (*cb_strategy)(void *bp);
+ int (*cb_print)(dev_t dev, char *str);
+ int (*cb_dump)(dev_t dev, caddr_t addr, daddr_t blkno, int nblk);
+ int (*cb_read)(dev_t dev, struct uio *uiop, cred_t *credp);
+ int (*cb_write)(dev_t dev, struct uio *uiop, cred_t *credp);
+ int (*cb_ioctl)(dev_t dev, int cmd, intptr_t arg, int mode,
+ cred_t *credp, int *rvalp);
+ int (*cb_devmap)(dev_t dev, devmap_cookie_t dhp, offset_t off,
+ size_t len, size_t *maplen, uint_t model);
+ int (*cb_mmap)(dev_t dev, off_t off, int prot);
+ int (*cb_segmap)(dev_t dev, off_t off, struct as *asp,
+ caddr_t *addrp, off_t len, unsigned int prot,
+ unsigned int maxprot, unsigned int flags,
+ cred_t *credp);
+ int (*cb_chpoll)(dev_t dev, short events, int anyyet,
+ short *reventsp, struct pollhead **phpp);
+ int (*cb_prop_op)(dev_t dev, dev_info_t *dip,
+ ddi_prop_op_t prop_op, int mod_flags,
+ char *name, caddr_t valuep, int *length);
+ struct streamtab *cb_str;
+ int cb_flag;
+ int cb_rev;
+ int (*cb_aread)(dev_t dev, struct aio_req *aio, cred_t *credp);
+ int (*cb_awrite)(dev_t dev, struct aio_req *aio, cred_t *credp);
+} cb_ops_t;
+
+typedef struct dev_ops {
+ int devo_rev;
+ int devo_refcnt;
+
+ int (*devo_getinfo)(dev_info_t *dip,
+ ddi_info_cmd_t infocmd, void *arg, void **result);
+ int (*devo_identify)(dev_info_t *dip);
+ int (*devo_probe)(dev_info_t *dip);
+ int (*devo_attach)(dev_info_t *dip, ddi_attach_cmd_t cmd);
+ int (*devo_detach)(dev_info_t *dip, ddi_detach_cmd_t cmd);
+ int (*devo_reset)(dev_info_t *dip, ddi_reset_cmd_t cmd);
+
+ struct cb_ops *devo_cb_ops;
+ struct bus_ops *devo_bus_ops;
+ int (*devo_power)(dev_info_t *dip, int component, int level);
+} dev_ops_t;
+
+typedef struct mod_ops {
+ int (*modm_install)(void);
+ int (*modm_remove)(void);
+ int (*modm_info)(void);
+} mod_ops_t;
+
+typedef struct modldrv {
+ struct mod_ops *drv_modops;
+ char *drv_linkinfo;
+ struct dev_ops *drv_dev_ops;
+ struct dev_info *drv_dev_info;
+} modldrv_t;
+
+#define MODREV_1 1
+
+#define D_NEW 0x000
+#define D_MP 0x020
+#define D_64BIT 0x200
+
+#define DEVO_REV 3
+#define CB_REV 1
+
+#define DDI_SUCCESS 0
+#define DDI_FAILURE -1
+
+#define DDI_PSEUDO "ddi_pseudo"
+
+#define nodev NULL
+#define nochpoll NULL
+#define nulldev NULL
+#define mod_driverops NULL
+#define ddi_prop_op NULL
+
+#define getminor MINOR
+#define getmajor MAJOR
+
+#define mod_install(x) 0
+#define mod_remove(x) 0
+
+extern int __ddi_create_minor_node(dev_info_t *dip, char *name, int spec_type,
+ minor_t minor_num, char *node_type,
+ int flag, struct module *mod);
+extern void __ddi_remove_minor_node(dev_info_t *dip, char *name);
+extern int __mod_install(struct modlinkage *modlp);
+extern int __mod_remove(struct modlinkage *modlp);
+
+static __inline__ void ddi_report_dev(dev_info_t *d) { }
+static __inline__ void ddi_prop_remove_all(dev_info_t *dip) { }
+
+static __inline__ major_t
+ddi_driver_major(dev_info_t *di)
+{
+ return getminor(di->di_dev);
+}
+
+static __inline__ int
+ddi_create_minor_node(dev_info_t *di, char *name, int spec_type,
+ minor_t minor_num, char *node_type, int flag)
+{
+ return __ddi_create_minor_node(di, name, spec_type, minor_num,
+ node_type, flag, THIS_MODULE);
+
+}
+
+#undef mod_install
+#undef mod_remove
+
+#define ddi_remove_minor_node __ddi_remove_minor_node
+#define mod_install __mod_install
+#define mod_remove __mod_remove
+
#endif /* SPL_SUNDDI_H */
diff --git a/include/sys/sunldi.h b/include/sys/sunldi.h
index 01e80b54f..f473350be 100644
--- a/include/sys/sunldi.h
+++ b/include/sys/sunldi.h
@@ -1,9 +1,28 @@
#ifndef _SPL_SUNLDI_H
#define _SPL_SUNLDI_H
-/* XXX: ALL TOTALLY BOGUS, JUST PLACE HOLDERS */
-typedef int ddi_devid_t;
-typedef int ldi_handle_t;
-typedef int ldi_ident_t;
+#include <sys/types.h>
+
+typedef struct modlinkage {
+ int ml_rev;
+ struct modlfs *ml_modlfs;
+ struct modldrv *ml_modldrv;
+ major_t ml_major;
+ unsigned ml_minors;
+ void *pad1;
+} modlinkage_t;
+
+typedef struct ldi_ident {
+ char li_modname[MAXNAMELEN];
+ dev_t li_dev;
+} *ldi_ident_t;
+
+typedef struct ldi_handle {
+ uint_t lh_type;
+ struct ldi_ident *lh_ident;
+} ldi_handle_t;
+
+extern int ldi_ident_from_mod(struct modlinkage *modlp, ldi_ident_t *lip);
+extern void ldi_ident_release(ldi_ident_t li);
#endif /* SPL_SUNLDI_H */
diff --git a/include/sys/types.h b/include/sys/types.h
index 0d6a71ca0..dc660a761 100644
--- a/include/sys/types.h
+++ b/include/sys/types.h
@@ -31,7 +31,5 @@ typedef longlong_t diskaddr_t;
typedef ushort_t o_mode_t;
typedef uint_t major_t;
typedef uint_t minor_t;
-typedef uint_t ldi_ident_t;
-typedef dev_t dev_info_t;
#endif /* _SPL_TYPES_H */
diff --git a/include/sys/vnode.h b/include/sys/vnode.h
index 1b9c3b671..4ee7e7895 100644
--- a/include/sys/vnode.h
+++ b/include/sys/vnode.h
@@ -19,6 +19,7 @@ extern "C" {
#include <sys/types.h>
#include <sys/time.h>
#include <sys/uio.h>
+#include <sys/sunldi.h>
#define XVA_MAPSIZE 3
#define XVA_MAGIC 0x78766174
diff --git a/modules/spl/Makefile.in b/modules/spl/Makefile.in
index 1005d100b..bcc25be97 100644
--- a/modules/spl/Makefile.in
+++ b/modules/spl/Makefile.in
@@ -17,6 +17,7 @@ spl-objs += spl-vnode.o
spl-objs += spl-err.o
spl-objs += spl-time.o
spl-objs += spl-kobj.o
+spl-objs += spl-module.o
spl-objs += spl-generic.o
splmodule := spl.ko
diff --git a/modules/spl/spl-module.c b/modules/spl/spl-module.c
new file mode 100644
index 000000000..efe516adb
--- /dev/null
+++ b/modules/spl/spl-module.c
@@ -0,0 +1,297 @@
+#include <sys/sysmacros.h>
+#include <sys/sunddi.h>
+#include "config.h"
+
+static spinlock_t dev_info_lock = SPIN_LOCK_UNLOCKED;
+static LIST_HEAD(dev_info_list);
+
+static struct dev_info *
+get_dev_info(dev_t dev)
+{
+ struct dev_info *di;
+
+ spin_lock(&dev_info_lock);
+
+ list_for_each_entry(di, &dev_info_list, di_list)
+ if (di->di_dev == dev)
+ goto out;
+
+ di = NULL;
+out:
+ spin_unlock(&dev_info_lock);
+ return di;
+}
+
+static int
+mod_generic_ioctl(struct inode *ino, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ struct dev_info *di;
+ int rc, flag = 0, rvalp = 0;
+ cred_t *cr = NULL;
+
+ di = get_dev_info(MKDEV(imajor(ino), iminor(ino)));
+ if (di == NULL)
+ return EINVAL;
+
+ rc = di->di_ops->devo_cb_ops->cb_ioctl(di->di_dev,
+ (int)cmd,(intptr_t)arg,
+ flag, cr, &rvalp);
+ return rc;
+}
+
+int
+__ddi_create_minor_node(dev_info_t *di, char *name, int spec_type,
+ minor_t minor_num, char *node_type,
+ int flag, struct module *mod)
+{
+ struct cdev *cdev;
+ struct dev_ops *dev_ops;
+ struct cb_ops *cb_ops;
+ struct file_operations *fops;
+ int rc;
+
+ BUG_ON(spec_type != S_IFCHR);
+ BUG_ON(minor_num < di->di_minors);
+ BUG_ON(strcmp(node_type, DDI_PSEUDO));
+ BUG_ON(flag != 0);
+
+ fops = kmalloc(sizeof(struct file_operations), GFP_KERNEL);
+ if (fops == NULL)
+ return DDI_FAILURE;
+
+ cdev = cdev_alloc();
+ if (cdev == NULL) {
+ kfree(fops);
+ return DDI_FAILURE;
+ }
+
+ cdev->ops = fops;
+
+ mutex_enter(&di->di_lock);
+ dev_ops = di->di_ops;
+ BUG_ON(dev_ops == NULL);
+ cb_ops = di->di_ops->devo_cb_ops;
+ BUG_ON(cb_ops == NULL);
+
+ /* Setup the fops to cb_ops mapping */
+ fops->owner = mod;
+ if (cb_ops->cb_ioctl)
+ fops->ioctl = mod_generic_ioctl;
+
+#if 0
+ if (cb_ops->cb_open)
+ fops->open = mod_generic_open;
+
+ if (cb_ops->cb_close)
+ fops->release = mod_generic_close;
+
+ if (cb_ops->cb_read)
+ fops->read = mod_generic_read;
+
+ if (cb_ops->cb_write)
+ fops->write = mod_generic_write;
+#endif
+ /* XXX: Currently unsupported operations */
+ BUG_ON(cb_ops->cb_open != NULL);
+ BUG_ON(cb_ops->cb_close != NULL);
+ BUG_ON(cb_ops->cb_read != NULL);
+ BUG_ON(cb_ops->cb_write != NULL);
+ BUG_ON(cb_ops->cb_strategy != NULL);
+ BUG_ON(cb_ops->cb_print != NULL);
+ BUG_ON(cb_ops->cb_dump != NULL);
+ BUG_ON(cb_ops->cb_devmap != NULL);
+ BUG_ON(cb_ops->cb_mmap != NULL);
+ BUG_ON(cb_ops->cb_segmap != NULL);
+ BUG_ON(cb_ops->cb_chpoll != NULL);
+ BUG_ON(cb_ops->cb_prop_op != NULL);
+ BUG_ON(cb_ops->cb_str != NULL);
+ BUG_ON(cb_ops->cb_aread != NULL);
+ BUG_ON(cb_ops->cb_awrite != NULL);
+
+ di->di_minor = minor_num;
+ di->di_dev = MKDEV(di->di_major, di->di_minor);
+
+ rc = cdev_add(cdev, di->di_dev, 1);
+ if (rc) {
+ printk("spl: Error adding cdev, %d\n", rc);
+ kfree(fops);
+ cdev_del(cdev);
+ mutex_exit(&di->di_lock);
+ return DDI_FAILURE;
+ }
+
+ di->di_class = class_create(THIS_MODULE, name);
+ if (IS_ERR(di->di_class)) {
+ rc = PTR_ERR(di->di_class);
+ printk("spl: Error creating %s class, %d\n", name, rc);
+ kfree(fops);
+ cdev_del(di->di_cdev);
+ mutex_exit(&di->di_lock);
+ return DDI_FAILURE;
+ }
+
+ class_device_create(di->di_class, NULL, di->di_dev,
+ NULL, "%s%d", name, di->di_minor);
+
+ di->di_cdev = cdev;
+
+ spin_lock(&dev_info_lock);
+ list_add(&di->di_list, &dev_info_list);
+ spin_unlock(&dev_info_lock);
+
+ mutex_exit(&di->di_lock);
+
+ return DDI_SUCCESS;
+}
+EXPORT_SYMBOL(__ddi_create_minor_node);
+
+static void
+___ddi_remove_minor_node(dev_info_t *di, char *name)
+{
+ class_device_destroy(di->di_class, di->di_dev);
+ class_destroy(di->di_class);
+ cdev_del(di->di_cdev);
+
+ spin_lock(&dev_info_lock);
+ list_del(&di->di_list);
+ spin_unlock(&dev_info_lock);
+}
+
+void
+__ddi_remove_minor_node(dev_info_t *di, char *name)
+{
+ mutex_enter(&di->di_lock);
+ ___ddi_remove_minor_node(di, name);
+ mutex_exit(&di->di_lock);
+}
+EXPORT_SYMBOL(ddi_remove_minor_node);
+
+#if 0
+static int
+mod_generic_open(struct inode *, struct file *)
+{
+ open(dev_t *devp, int flag, int otyp, cred_t *credp);
+}
+
+static int
+mod_generic_close(struct inode *, struct file *)
+{
+ close(dev_t dev, int flag, int otyp, cred_t *credp);
+}
+
+static ssize_t
+mod_generic_read(struct file *, char __user *, size_t, loff_t *)
+{
+ read(dev_t dev, struct uio *uiop, cred_t *credp);
+}
+
+static ssize_t
+mod_generic_write(struct file *, const char __user *, size_t, loff_t *)
+{
+ write(dev_t dev, struct uio *uiop, cred_t *credp);
+}
+#endif
+
+static struct dev_info *
+dev_info_alloc(major_t major, minor_t minors, struct dev_ops *ops) {
+ struct dev_info *di;
+
+ di = kmalloc(sizeof(struct dev_info), GFP_KERNEL);
+ if (di == NULL)
+ return NULL;
+
+ mutex_init(&di->di_lock, NULL, MUTEX_DEFAULT, NULL);
+ INIT_LIST_HEAD(&di->di_list);
+ di->di_ops = ops;
+ di->di_class = NULL;
+ di->di_cdev = NULL;
+ di->di_major = major;
+ di->di_minor = 0;
+ di->di_minors = minors;
+ di->di_dev = 0;
+
+ return di;
+}
+
+static void
+dev_info_free(struct dev_info *di)
+{
+ mutex_enter(&di->di_lock);
+ __ddi_remove_minor_node(di, NULL);
+ mutex_exit(&di->di_lock);
+ mutex_destroy(&di->di_lock);
+ kfree(di);
+}
+
+int
+__mod_install(struct modlinkage *modlp)
+{
+ struct modldrv *drv = modlp->ml_modldrv;
+ struct dev_info *di;
+ int rc;
+
+ di = dev_info_alloc(modlp->ml_major, modlp->ml_minors,
+ drv->drv_dev_ops);
+ if (di == NULL)
+ return ENOMEM;
+
+ /* XXX: Really we need to be calling devo_probe if it's available
+ * and then calling devo_attach for each device discovered. However
+ * for now we just call it once and let the app sort it out.
+ */
+ rc = drv->drv_dev_ops->devo_attach(di, DDI_ATTACH);
+ if (rc != DDI_SUCCESS) {
+ dev_info_free(di);
+ return rc;
+ }
+
+ drv->drv_dev_info = di;
+
+ return DDI_SUCCESS;
+}
+EXPORT_SYMBOL(__mod_install);
+
+int
+__mod_remove(struct modlinkage *modlp)
+{
+ struct modldrv *drv = modlp->ml_modldrv;
+ struct dev_info *di = drv->drv_dev_info;
+ int rc;
+
+ rc = drv->drv_dev_ops->devo_detach(di, DDI_DETACH);
+ if (rc != DDI_SUCCESS)
+ return rc;
+
+ dev_info_free(di);
+ drv->drv_dev_info = NULL;
+
+ return DDI_SUCCESS;
+}
+EXPORT_SYMBOL(__mod_remove);
+
+int
+ldi_ident_from_mod(struct modlinkage *modlp, ldi_ident_t *lip)
+{
+ ldi_ident_t li;
+
+ BUG_ON(modlp == NULL || lip == NULL);
+
+ li = kmalloc(sizeof(struct ldi_ident), GFP_KERNEL);
+ if (li == NULL)
+ return ENOMEM;
+
+ li->li_dev = MKDEV(modlp->ml_major, 0);
+ *lip = li;
+
+ return 0;
+}
+EXPORT_SYMBOL(ldi_ident_from_mod);
+
+void
+ldi_ident_release(ldi_ident_t lip)
+{
+ BUG_ON(lip == NULL);
+ kfree(lip);
+}
+EXPORT_SYMBOL(ldi_ident_release);
diff --git a/modules/spl/spl-vnode.c b/modules/spl/spl-vnode.c
index 4ed59d32e..24ee71293 100644
--- a/modules/spl/spl-vnode.c
+++ b/modules/spl/spl-vnode.c
@@ -548,6 +548,7 @@ vn_file_cache_constructor(void *buf, void *cdrarg, int kmflags)
atomic_set(&fp->f_ref, 0);
mutex_init(&fp->f_lock, NULL, MUTEX_DEFAULT, NULL);
+ INIT_LIST_HEAD(&fp->f_list);
return (0);
} /* file_cache_constructor() */
diff --git a/modules/splat/splat-vnode.c b/modules/splat/splat-vnode.c
index 92bbbfc74..8578ea20a 100644
--- a/modules/splat/splat-vnode.c
+++ b/modules/splat/splat-vnode.c
@@ -30,8 +30,8 @@
#define SPLAT_VNODE_TEST6_DESC "Vn_sync Test"
#define SPLAT_VNODE_TEST7_ID 0x0907
-#define SPLAT_VNODE_TEST7_NAME "getf"
-#define SPLAT_VNODE_TEST7_DESC "getf/releasef Test"
+#define SPLAT_VNODE_TEST7_NAME "vn_getf"
+#define SPLAT_VNODE_TEST7_DESC "vn_getf/vn_releasef Test"
#define SPLAT_VNODE_TEST_FILE "/etc/fstab"
#define SPLAT_VNODE_TEST_FILE_AT "etc/fstab"