| |
| /* |
| * |
| * Copyright (c) International Business Machines Corp., 2001 |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| * the GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| /* |
| * Legacy Power Management (PM) was removed from the kernel, removed it from |
| * here also. ( http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6afe1a1fe8ff83f6ac2726b04665e76ba7b14f3e ) |
| * |
| */ |
| |
| #include <linux/types.h> |
| #include <linux/kernel.h> |
| #include <linux/fs.h> |
| #include <linux/ioctl.h> |
| #include <linux/module.h> |
| #include <linux/init.h> |
| #include <linux/pm.h> |
| #include <linux/genhd.h> |
| #include <linux/version.h> |
| #include <linux/string.h> |
| #include <linux/autoconf.h> |
| #include <linux/nls.h> |
| #include <linux/blkdev.h> |
| |
| #ifdef CONFIG_KMOD |
| #include <linux/kmod.h> |
| #endif |
| |
| #include <linux/errno.h> |
| #include <linux/spinlock.h> |
| #include <linux/uaccess.h> |
| |
| #include "nlsTest.h" |
| |
| MODULE_AUTHOR("David Cruz <cruzd@us.ibm.com>"); |
| MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>"); |
| MODULE_DESCRIPTION(TEST_DRIVER_NAME); |
| MODULE_LICENSE("GPL"); |
| |
| /* Struct block_device_operations changed: |
| * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=d4430d62fa77208824a37fe6f85ab2831d274769 |
| */ |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) |
| static int test_open(struct inode *, struct file *); |
| static int test_release(struct inode *, struct file *); |
| static int test_ioctl(struct inode *, struct file *, |
| unsigned int cmd, unsigned long l); |
| #else |
| static int test_open(struct block_device *bdev, fmode_t mode); |
| static int test_release(struct gendisk *disk, fmode_t mode); |
| static int test_ioctl(struct block_device *bdev, fmode_t mode, |
| unsigned int cmd, unsigned long l); |
| #endif |
| |
| static void test_nls_base(void); |
| static void option1(void); |
| |
| struct test_block_device { |
| spinlock_t queue_lock; |
| }; |
| |
| static struct block_device_operations bdops = { |
| .open = test_open, |
| .release = test_release, |
| .ioctl = test_ioctl, |
| }; |
| |
| static struct gendisk *gd_ptr; |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) |
| static int test_open(struct inode *inode, struct file *f) |
| #else |
| static int test_open(struct block_device *bdev, fmode_t mode) |
| #endif |
| { |
| printk(KERN_DEBUG "device opened\n"); |
| return 0; |
| } |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) |
| static int test_release(struct inode *ino, struct file *f) |
| #else |
| static int test_release(struct gendisk *disk, fmode_t mode) |
| #endif |
| { |
| printk(KERN_DEBUG "device released\n"); |
| return 0; |
| } |
| |
| #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) |
| static int test_ioctl(struct inode *ino, struct file *f, |
| unsigned int cmd, unsigned long l) |
| #else |
| static int test_ioctl(struct block_device *bdev, fmode_t mode, |
| unsigned int cmd, unsigned long l) |
| #endif |
| { |
| int rc = 0; /* return code */ |
| int arg; |
| |
| printk(KERN_DEBUG "Entered the ioctl call.\n"); |
| |
| if (copy_from_user(&arg, (void *)l, sizeof(int))) { |
| /* bad address */ |
| return -EFAULT; |
| } |
| |
| switch (cmd) { |
| case OPTION1: |
| option1(); |
| break; |
| default: |
| printk(KERN_ERR "Mismatching ioctl command\n"); |
| } |
| |
| return rc; |
| } |
| |
| static void option1(void) |
| { |
| printk(KERN_DEBUG "Module option 1 chosen\n"); |
| } |
| |
| static void test_request(struct request_queue *q) |
| { |
| printk(KERN_DEBUG "test_request() called\n"); |
| }; |
| |
| static int test_init_module(void) |
| { |
| struct test_block_device *dev; |
| struct request_queue *queue; |
| int rc; |
| |
| printk(KERN_DEBUG "starting module\n"); |
| |
| dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
| if (!dev) |
| return -ENOMEM; |
| |
| rc = register_blkdev(NLSMAJOR, DEVICE_NAME); |
| |
| printk(KERN_DEBUG "BLK INC - result=%d, major=%d\n", rc, NLSMAJOR); |
| |
| if (rc < 0) { |
| printk(KERN_ERR "Failed to register device.\n"); |
| kfree(dev); |
| return rc; |
| } |
| |
| spin_lock_init(&dev->queue_lock); |
| |
| gd_ptr = alloc_disk(1); |
| if (!gd_ptr) { |
| unregister_blkdev(NLSMAJOR, DEVICE_NAME); |
| kfree(dev); |
| return -ENOMEM; |
| } |
| |
| printk(KERN_ALERT "gd_ptr after alloc=%p\n", gd_ptr); |
| |
| queue = blk_init_queue(test_request, &dev->queue_lock); |
| if (!queue) { |
| del_gendisk(gd_ptr); |
| unregister_blkdev(NLSMAJOR, DEVICE_NAME); |
| kfree(dev); |
| return -ENOMEM; |
| } |
| |
| gd_ptr->major = NLSMAJOR; |
| gd_ptr->first_minor = 0; |
| gd_ptr->fops = &bdops; |
| gd_ptr->queue = queue; |
| gd_ptr->private_data = dev; |
| snprintf(gd_ptr->disk_name, sizeof(gd_ptr->disk_name), DEVICE_NAME); |
| add_disk(gd_ptr); |
| |
| printk(KERN_DEBUG "block device %s added\n", DEVICE_NAME); |
| |
| test_nls_base(); |
| |
| return 0; |
| } |
| |
| static void test_exit_module(void) |
| { |
| printk(KERN_DEBUG "unloading module\n"); |
| |
| del_gendisk(gd_ptr); |
| unregister_blkdev(NLSMAJOR, DEVICE_NAME); |
| } |
| |
| static void test_nls_base(void) |
| { |
| wchar_t p = 0x20; |
| __u8 s = 0x01; |
| int n = 2; |
| struct nls_table nls; |
| struct nls_table *nls_ptr; |
| int ret; |
| char charset[20] = "David"; |
| |
| memset(&nls, 0, sizeof(nls)); |
| |
| printk(KERN_DEBUG "Calling load_nls_default()\n"); |
| nls_ptr = load_nls_default(); |
| printk(KERN_DEBUG "load_nls_default() returns %p\n", nls_ptr); |
| |
| printk(KERN_DEBUG "Calling register_nls(%p)\n", &nls); |
| ret = register_nls(&nls); |
| printk(KERN_DEBUG "register_nls() returns %i\n", ret); |
| |
| printk(KERN_DEBUG "Calling unload_nls(%p)\n", &nls); |
| unload_nls(&nls); |
| |
| printk(KERN_DEBUG "Calling load_nls(\"%s\")\n", charset); |
| nls_ptr = load_nls(charset); |
| printk(KERN_DEBUG "load_nls() returns %p\n", nls_ptr); |
| |
| printk(KERN_DEBUG "Calling unregister_nls(%p)\n", &nls); |
| unregister_nls(&nls); |
| |
| printk(KERN_DEBUG "Calling utf8_mbtowc(%p, %p, %i);\n", &p, &s, n); |
| ret = utf8_mbtowc(&p, &s, n); |
| printk(KERN_DEBUG "utf8_mbtowc() returns %i\n", ret); |
| |
| printk(KERN_DEBUG "Calling utf8_mbstowcs(%p, %p, %i);\n", &p, &s, n); |
| ret = utf8_mbstowcs(&p, &s, n); |
| printk(KERN_DEBUG "utf8_mbstowcs() returns %i\n", ret); |
| |
| n = 20; |
| |
| printk(KERN_DEBUG "Calling utf8_wctomb(%p, 0x%X, %i);\n", &s, p, n); |
| ret = utf8_wctomb(&s, p, n); |
| printk(KERN_DEBUG "utf8_wctomb() returns %i\n", ret); |
| |
| printk(KERN_DEBUG "Calling utf8_wcstombs(%p, %p, %i);\n", &s, &p, n); |
| ret = utf8_wcstombs(&s, &p, n); |
| printk(KERN_DEBUG "utf8_wcstombs() returns %i\n", ret); |
| |
| } |
| |
| module_init(test_init_module); |
| module_exit(test_exit_module); |