1f08c3bdfSopenharmony_ci 2f08c3bdfSopenharmony_ci/* 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines Corp., 2001 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 7f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 8f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 9f08c3bdfSopenharmony_ci * (at your option) any later version. 10f08c3bdfSopenharmony_ci * 11f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 12f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 14f08c3bdfSopenharmony_ci * the GNU General Public License for more details. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 17f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 18f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19f08c3bdfSopenharmony_ci */ 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci/* 22f08c3bdfSopenharmony_ci * Legacy Power Management (PM) was removed from the kernel, removed it from 23f08c3bdfSopenharmony_ci * here also. ( http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6afe1a1fe8ff83f6ac2726b04665e76ba7b14f3e ) 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci */ 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci#include <linux/types.h> 28f08c3bdfSopenharmony_ci#include <linux/kernel.h> 29f08c3bdfSopenharmony_ci#include <linux/fs.h> 30f08c3bdfSopenharmony_ci#include <linux/ioctl.h> 31f08c3bdfSopenharmony_ci#include <linux/module.h> 32f08c3bdfSopenharmony_ci#include <linux/init.h> 33f08c3bdfSopenharmony_ci#include <linux/pm.h> 34f08c3bdfSopenharmony_ci#include <linux/genhd.h> 35f08c3bdfSopenharmony_ci#include <linux/version.h> 36f08c3bdfSopenharmony_ci#include <linux/string.h> 37f08c3bdfSopenharmony_ci#include <linux/autoconf.h> 38f08c3bdfSopenharmony_ci#include <linux/nls.h> 39f08c3bdfSopenharmony_ci#include <linux/blkdev.h> 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ci#ifdef CONFIG_KMOD 42f08c3bdfSopenharmony_ci#include <linux/kmod.h> 43f08c3bdfSopenharmony_ci#endif 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci#include <linux/errno.h> 46f08c3bdfSopenharmony_ci#include <linux/spinlock.h> 47f08c3bdfSopenharmony_ci#include <linux/uaccess.h> 48f08c3bdfSopenharmony_ci 49f08c3bdfSopenharmony_ci#include "nlsTest.h" 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ciMODULE_AUTHOR("David Cruz <cruzd@us.ibm.com>"); 52f08c3bdfSopenharmony_ciMODULE_AUTHOR("Márton Németh <nm127@freemail.hu>"); 53f08c3bdfSopenharmony_ciMODULE_DESCRIPTION(TEST_DRIVER_NAME); 54f08c3bdfSopenharmony_ciMODULE_LICENSE("GPL"); 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci/* Struct block_device_operations changed: 57f08c3bdfSopenharmony_ci * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=d4430d62fa77208824a37fe6f85ab2831d274769 58f08c3bdfSopenharmony_ci */ 59f08c3bdfSopenharmony_ci#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) 60f08c3bdfSopenharmony_cistatic int test_open(struct inode *, struct file *); 61f08c3bdfSopenharmony_cistatic int test_release(struct inode *, struct file *); 62f08c3bdfSopenharmony_cistatic int test_ioctl(struct inode *, struct file *, 63f08c3bdfSopenharmony_ci unsigned int cmd, unsigned long l); 64f08c3bdfSopenharmony_ci#else 65f08c3bdfSopenharmony_cistatic int test_open(struct block_device *bdev, fmode_t mode); 66f08c3bdfSopenharmony_cistatic int test_release(struct gendisk *disk, fmode_t mode); 67f08c3bdfSopenharmony_cistatic int test_ioctl(struct block_device *bdev, fmode_t mode, 68f08c3bdfSopenharmony_ci unsigned int cmd, unsigned long l); 69f08c3bdfSopenharmony_ci#endif 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_cistatic void test_nls_base(void); 72f08c3bdfSopenharmony_cistatic void option1(void); 73f08c3bdfSopenharmony_ci 74f08c3bdfSopenharmony_cistruct test_block_device { 75f08c3bdfSopenharmony_ci spinlock_t queue_lock; 76f08c3bdfSopenharmony_ci}; 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_cistatic struct block_device_operations bdops = { 79f08c3bdfSopenharmony_ci .open = test_open, 80f08c3bdfSopenharmony_ci .release = test_release, 81f08c3bdfSopenharmony_ci .ioctl = test_ioctl, 82f08c3bdfSopenharmony_ci}; 83f08c3bdfSopenharmony_ci 84f08c3bdfSopenharmony_cistatic struct gendisk *gd_ptr; 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) 87f08c3bdfSopenharmony_cistatic int test_open(struct inode *inode, struct file *f) 88f08c3bdfSopenharmony_ci#else 89f08c3bdfSopenharmony_cistatic int test_open(struct block_device *bdev, fmode_t mode) 90f08c3bdfSopenharmony_ci#endif 91f08c3bdfSopenharmony_ci{ 92f08c3bdfSopenharmony_ci printk(KERN_DEBUG "device opened\n"); 93f08c3bdfSopenharmony_ci return 0; 94f08c3bdfSopenharmony_ci} 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) 97f08c3bdfSopenharmony_cistatic int test_release(struct inode *ino, struct file *f) 98f08c3bdfSopenharmony_ci#else 99f08c3bdfSopenharmony_cistatic int test_release(struct gendisk *disk, fmode_t mode) 100f08c3bdfSopenharmony_ci#endif 101f08c3bdfSopenharmony_ci{ 102f08c3bdfSopenharmony_ci printk(KERN_DEBUG "device released\n"); 103f08c3bdfSopenharmony_ci return 0; 104f08c3bdfSopenharmony_ci} 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28) 107f08c3bdfSopenharmony_cistatic int test_ioctl(struct inode *ino, struct file *f, 108f08c3bdfSopenharmony_ci unsigned int cmd, unsigned long l) 109f08c3bdfSopenharmony_ci#else 110f08c3bdfSopenharmony_cistatic int test_ioctl(struct block_device *bdev, fmode_t mode, 111f08c3bdfSopenharmony_ci unsigned int cmd, unsigned long l) 112f08c3bdfSopenharmony_ci#endif 113f08c3bdfSopenharmony_ci{ 114f08c3bdfSopenharmony_ci int rc = 0; /* return code */ 115f08c3bdfSopenharmony_ci int arg; 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Entered the ioctl call.\n"); 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci if (copy_from_user(&arg, (void *)l, sizeof(int))) { 120f08c3bdfSopenharmony_ci /* bad address */ 121f08c3bdfSopenharmony_ci return -EFAULT; 122f08c3bdfSopenharmony_ci } 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_ci switch (cmd) { 125f08c3bdfSopenharmony_ci case OPTION1: 126f08c3bdfSopenharmony_ci option1(); 127f08c3bdfSopenharmony_ci break; 128f08c3bdfSopenharmony_ci default: 129f08c3bdfSopenharmony_ci printk(KERN_ERR "Mismatching ioctl command\n"); 130f08c3bdfSopenharmony_ci } 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci return rc; 133f08c3bdfSopenharmony_ci} 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_cistatic void option1(void) 136f08c3bdfSopenharmony_ci{ 137f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Module option 1 chosen\n"); 138f08c3bdfSopenharmony_ci} 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_cistatic void test_request(struct request_queue *q) 141f08c3bdfSopenharmony_ci{ 142f08c3bdfSopenharmony_ci printk(KERN_DEBUG "test_request() called\n"); 143f08c3bdfSopenharmony_ci}; 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_cistatic int test_init_module(void) 146f08c3bdfSopenharmony_ci{ 147f08c3bdfSopenharmony_ci struct test_block_device *dev; 148f08c3bdfSopenharmony_ci struct request_queue *queue; 149f08c3bdfSopenharmony_ci int rc; 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_ci printk(KERN_DEBUG "starting module\n"); 152f08c3bdfSopenharmony_ci 153f08c3bdfSopenharmony_ci dev = kzalloc(sizeof(*dev), GFP_KERNEL); 154f08c3bdfSopenharmony_ci if (!dev) 155f08c3bdfSopenharmony_ci return -ENOMEM; 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci rc = register_blkdev(NLSMAJOR, DEVICE_NAME); 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci printk(KERN_DEBUG "BLK INC - result=%d, major=%d\n", rc, NLSMAJOR); 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci if (rc < 0) { 162f08c3bdfSopenharmony_ci printk(KERN_ERR "Failed to register device.\n"); 163f08c3bdfSopenharmony_ci kfree(dev); 164f08c3bdfSopenharmony_ci return rc; 165f08c3bdfSopenharmony_ci } 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_ci spin_lock_init(&dev->queue_lock); 168f08c3bdfSopenharmony_ci 169f08c3bdfSopenharmony_ci gd_ptr = alloc_disk(1); 170f08c3bdfSopenharmony_ci if (!gd_ptr) { 171f08c3bdfSopenharmony_ci unregister_blkdev(NLSMAJOR, DEVICE_NAME); 172f08c3bdfSopenharmony_ci kfree(dev); 173f08c3bdfSopenharmony_ci return -ENOMEM; 174f08c3bdfSopenharmony_ci } 175f08c3bdfSopenharmony_ci 176f08c3bdfSopenharmony_ci printk(KERN_ALERT "gd_ptr after alloc=%p\n", gd_ptr); 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_ci queue = blk_init_queue(test_request, &dev->queue_lock); 179f08c3bdfSopenharmony_ci if (!queue) { 180f08c3bdfSopenharmony_ci del_gendisk(gd_ptr); 181f08c3bdfSopenharmony_ci unregister_blkdev(NLSMAJOR, DEVICE_NAME); 182f08c3bdfSopenharmony_ci kfree(dev); 183f08c3bdfSopenharmony_ci return -ENOMEM; 184f08c3bdfSopenharmony_ci } 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci gd_ptr->major = NLSMAJOR; 187f08c3bdfSopenharmony_ci gd_ptr->first_minor = 0; 188f08c3bdfSopenharmony_ci gd_ptr->fops = &bdops; 189f08c3bdfSopenharmony_ci gd_ptr->queue = queue; 190f08c3bdfSopenharmony_ci gd_ptr->private_data = dev; 191f08c3bdfSopenharmony_ci snprintf(gd_ptr->disk_name, sizeof(gd_ptr->disk_name), DEVICE_NAME); 192f08c3bdfSopenharmony_ci add_disk(gd_ptr); 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci printk(KERN_DEBUG "block device %s added\n", DEVICE_NAME); 195f08c3bdfSopenharmony_ci 196f08c3bdfSopenharmony_ci test_nls_base(); 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci return 0; 199f08c3bdfSopenharmony_ci} 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_cistatic void test_exit_module(void) 202f08c3bdfSopenharmony_ci{ 203f08c3bdfSopenharmony_ci printk(KERN_DEBUG "unloading module\n"); 204f08c3bdfSopenharmony_ci 205f08c3bdfSopenharmony_ci del_gendisk(gd_ptr); 206f08c3bdfSopenharmony_ci unregister_blkdev(NLSMAJOR, DEVICE_NAME); 207f08c3bdfSopenharmony_ci} 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_cistatic void test_nls_base(void) 210f08c3bdfSopenharmony_ci{ 211f08c3bdfSopenharmony_ci wchar_t p = 0x20; 212f08c3bdfSopenharmony_ci __u8 s = 0x01; 213f08c3bdfSopenharmony_ci int n = 2; 214f08c3bdfSopenharmony_ci struct nls_table nls; 215f08c3bdfSopenharmony_ci struct nls_table *nls_ptr; 216f08c3bdfSopenharmony_ci int ret; 217f08c3bdfSopenharmony_ci char charset[20] = "David"; 218f08c3bdfSopenharmony_ci 219f08c3bdfSopenharmony_ci memset(&nls, 0, sizeof(nls)); 220f08c3bdfSopenharmony_ci 221f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Calling load_nls_default()\n"); 222f08c3bdfSopenharmony_ci nls_ptr = load_nls_default(); 223f08c3bdfSopenharmony_ci printk(KERN_DEBUG "load_nls_default() returns %p\n", nls_ptr); 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Calling register_nls(%p)\n", &nls); 226f08c3bdfSopenharmony_ci ret = register_nls(&nls); 227f08c3bdfSopenharmony_ci printk(KERN_DEBUG "register_nls() returns %i\n", ret); 228f08c3bdfSopenharmony_ci 229f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Calling unload_nls(%p)\n", &nls); 230f08c3bdfSopenharmony_ci unload_nls(&nls); 231f08c3bdfSopenharmony_ci 232f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Calling load_nls(\"%s\")\n", charset); 233f08c3bdfSopenharmony_ci nls_ptr = load_nls(charset); 234f08c3bdfSopenharmony_ci printk(KERN_DEBUG "load_nls() returns %p\n", nls_ptr); 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Calling unregister_nls(%p)\n", &nls); 237f08c3bdfSopenharmony_ci unregister_nls(&nls); 238f08c3bdfSopenharmony_ci 239f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Calling utf8_mbtowc(%p, %p, %i);\n", &p, &s, n); 240f08c3bdfSopenharmony_ci ret = utf8_mbtowc(&p, &s, n); 241f08c3bdfSopenharmony_ci printk(KERN_DEBUG "utf8_mbtowc() returns %i\n", ret); 242f08c3bdfSopenharmony_ci 243f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Calling utf8_mbstowcs(%p, %p, %i);\n", &p, &s, n); 244f08c3bdfSopenharmony_ci ret = utf8_mbstowcs(&p, &s, n); 245f08c3bdfSopenharmony_ci printk(KERN_DEBUG "utf8_mbstowcs() returns %i\n", ret); 246f08c3bdfSopenharmony_ci 247f08c3bdfSopenharmony_ci n = 20; 248f08c3bdfSopenharmony_ci 249f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Calling utf8_wctomb(%p, 0x%X, %i);\n", &s, p, n); 250f08c3bdfSopenharmony_ci ret = utf8_wctomb(&s, p, n); 251f08c3bdfSopenharmony_ci printk(KERN_DEBUG "utf8_wctomb() returns %i\n", ret); 252f08c3bdfSopenharmony_ci 253f08c3bdfSopenharmony_ci printk(KERN_DEBUG "Calling utf8_wcstombs(%p, %p, %i);\n", &s, &p, n); 254f08c3bdfSopenharmony_ci ret = utf8_wcstombs(&s, &p, n); 255f08c3bdfSopenharmony_ci printk(KERN_DEBUG "utf8_wcstombs() returns %i\n", ret); 256f08c3bdfSopenharmony_ci 257f08c3bdfSopenharmony_ci} 258f08c3bdfSopenharmony_ci 259f08c3bdfSopenharmony_cimodule_init(test_init_module); 260f08c3bdfSopenharmony_cimodule_exit(test_exit_module); 261