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