#include <linux/hdreg.h> /* HDIO_GETGEO */
#include <linux/sysdev.h>
#include <linux/bio.h>
+#include <linux/devfs_fs_kernel.h>
#include <asm/uaccess.h>
#define XPRAM_NAME "xpram"
#define PRINT_ERR(x...) printk(KERN_ERR XPRAM_NAME " error:" x)
+static struct sysdev_class xpram_sysclass = {
+ set_kset_name("xpram"),
+};
+
+static struct sys_device xpram_sys_device = {
+ .id = 0,
+ .cls = &xpram_sysclass,
+};
+
typedef struct {
unsigned int size; /* size of xpram segment in pages */
unsigned int offset; /* start page of xpram segment */
/*
* Parameter parsing functions.
*/
-static int __initdata devs = XPRAM_DEVS;
-static char __initdata *sizes[XPRAM_MAX_DEVS];
+static int devs = XPRAM_DEVS;
+static unsigned int sizes[XPRAM_MAX_DEVS];
module_param(devs, int, 0);
-module_param_array(sizes, charp, NULL, 0);
+module_param_array(sizes, int, NULL, 0);
MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \
"the default is " __MODULE_STRING(XPRAM_DEVS) "\n");
"claimed by explicit sizes\n");
MODULE_LICENSE("GPL");
+#ifndef MODULE
+/*
+ * Parses the kernel parameters given in the kernel parameter line.
+ * The expected format is
+ * <number_of_partitions>[","<partition_size>]*
+ * where
+ * devices is a positive integer that initializes xpram_devs
+ * each size is a non-negative integer possibly followed by a
+ * magnitude (k,K,m,M,g,G), the list of sizes initialises
+ * xpram_sizes
+ *
+ * Arguments
+ * str: substring of kernel parameter line that contains xprams
+ * kernel parameters.
+ *
+ * Result 0 on success, -EINVAL else -- only for Version > 2.3
+ *
+ * Side effects
+ * the global variabls devs is set to the value of
+ * <number_of_partitions> and sizes[i] is set to the i-th
+ * partition size (if provided). A parsing error of a value
+ * results in this value being set to -EINVAL.
+ */
+static int __init xpram_setup (char *str)
+{
+ char *cp;
+ int i;
+
+ devs = simple_strtoul(str, &cp, 10);
+ if (cp <= str || devs > XPRAM_MAX_DEVS)
+ return 0;
+ for (i = 0; (i < devs) && (*cp++ == ','); i++) {
+ sizes[i] = simple_strtoul(cp, &cp, 10);
+ if (*cp == 'g' || *cp == 'G') {
+ sizes[i] <<= 20;
+ cp++;
+ } else if (*cp == 'm' || *cp == 'M') {
+ sizes[i] <<= 10;
+ cp++;
+ } else if (*cp == 'k' || *cp == 'K')
+ cp++;
+ while (isspace(*cp)) cp++;
+ }
+ if (*cp == ',' && i >= devs)
+ PRINT_WARN("partition sizes list has too many entries.\n");
+ else if (*cp != 0)
+ PRINT_WARN("ignored '%s' at end of parameter string.\n", cp);
+ return 1;
+}
+
+__setup("xpram_parts=", xpram_setup);
+#endif
+
/*
* Copy expanded memory page (4kB) into main memory
* Arguments
{
unsigned long mem_needed;
unsigned long mem_auto;
- unsigned long long size;
int mem_auto_no;
int i;
mem_needed = 0;
mem_auto_no = 0;
for (i = 0; i < xpram_devs; i++) {
- if (sizes[i]) {
- size = simple_strtoull(sizes[i], &sizes[i], 0);
- switch (sizes[i][0]) {
- case 'g':
- case 'G':
- size <<= 20;
- break;
- case 'm':
- case 'M':
- size <<= 10;
- }
- xpram_sizes[i] = (size + 3) & -4UL;
- }
+ xpram_sizes[i] = (sizes[i] + 3) & -4UL;
if (xpram_sizes[i])
mem_needed += xpram_sizes[i];
else
if (rc < 0)
goto out;
+ devfs_mk_dir("slram");
+
/*
* Assign the other needed values: make request function, sizes and
* hardsect size. All the minor devices feature the same value.
disk->private_data = &xpram_devices[i];
disk->queue = xpram_queue;
sprintf(disk->disk_name, "slram%d", i);
+ sprintf(disk->devfs_name, "slram/%d", i);
set_capacity(disk, xpram_sizes[i] << 1);
add_disk(disk);
}
return 0;
out_unreg:
+ devfs_remove("slram");
unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
out:
while (i--)
put_disk(xpram_disks[i]);
}
unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
+ devfs_remove("slram");
blk_cleanup_queue(xpram_queue);
+ sysdev_unregister(&xpram_sys_device);
+ sysdev_class_unregister(&xpram_sysclass);
}
static int __init xpram_init(void)
rc = xpram_setup_sizes(xpram_pages);
if (rc)
return rc;
- return xpram_setup_blkdev();
+ rc = sysdev_class_register(&xpram_sysclass);
+ if (rc)
+ return rc;
+
+ rc = sysdev_register(&xpram_sys_device);
+ if (rc) {
+ sysdev_class_unregister(&xpram_sysclass);
+ return rc;
+ }
+ rc = xpram_setup_blkdev();
+ if (rc)
+ sysdev_unregister(&xpram_sys_device);
+ return rc;
}
module_init(xpram_init);