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
51MODULE_AUTHOR("David Cruz <cruzd@us.ibm.com>");
52MODULE_AUTHOR("Márton Németh <nm127@freemail.hu>");
53MODULE_DESCRIPTION(TEST_DRIVER_NAME);
54MODULE_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)
60static int test_open(struct inode *, struct file *);
61static int test_release(struct inode *, struct file *);
62static int test_ioctl(struct inode *, struct file *,
63		      unsigned int cmd, unsigned long l);
64#else
65static int test_open(struct block_device *bdev, fmode_t mode);
66static int test_release(struct gendisk *disk, fmode_t mode);
67static int test_ioctl(struct block_device *bdev, fmode_t mode,
68		      unsigned int cmd, unsigned long l);
69#endif
70
71static void test_nls_base(void);
72static void option1(void);
73
74struct test_block_device {
75	spinlock_t queue_lock;
76};
77
78static struct block_device_operations bdops = {
79	.open = test_open,
80	.release = test_release,
81	.ioctl = test_ioctl,
82};
83
84static struct gendisk *gd_ptr;
85
86#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 28)
87static int test_open(struct inode *inode, struct file *f)
88#else
89static 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)
97static int test_release(struct inode *ino, struct file *f)
98#else
99static 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)
107static int test_ioctl(struct inode *ino, struct file *f,
108		      unsigned int cmd, unsigned long l)
109#else
110static 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
135static void option1(void)
136{
137	printk(KERN_DEBUG "Module option 1 chosen\n");
138}
139
140static void test_request(struct request_queue *q)
141{
142	printk(KERN_DEBUG "test_request() called\n");
143};
144
145static 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
201static 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
209static 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
259module_init(test_init_module);
260module_exit(test_exit_module);
261