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