2 * vdi.h - The driver for virtual disks of VirtualBox
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 //TODO: Remove? #include <linux/config.h>
26 #include <linux/module.h>
27 #include <linux/init.h>
30 #include <linux/blkdev.h>
31 #include <linux/cdev.h>
32 #include <linux/errno.h>
34 #include <linux/genhd.h>
35 #include <linux/hdreg.h>
36 #include <linux/kernel.h>
37 #include <linux/types.h>
44 #define VDIS_BUF_SIZE 80
49 static int vdi_major
= VDI_MAJOR
;
50 static int vdis_major
= VDIS_MAJOR
;
54 * Some disk parameters
56 static int major
= VDI_MAJOR
;
60 static struct request_queue
*Queue
;
62 // Used to prevent multiple access do vdis
63 static int is_vdis_open
= 0;
64 static char vdis_buf
[VDIS_BUF_SIZE
];
65 static struct cdev vdis_cdev
;
66 dev_t vdis_dev_t
= MKDEV(VDIS_MAJOR
, VDIS_MINOR
);
68 //TODO: static char *vdis_buf
75 // Open the char device to communicate with daemon
76 static int vdis_open(struct inode
*, struct file
*);
77 static int vdis_release(struct inode
*, struct file
*);
78 static ssize_t
vdis_read(struct file
*, char *, size_t, loff_t
*);
79 static ssize_t
vdis_write(struct file
*, const char *, size_t, loff_t
*);
86 static int vdis_open(struct inode
*inode
, struct file
*file
)
92 try_module_get(THIS_MODULE
);
98 static int vdis_release(struct inode
* inode
, struct file
* file
)
105 static ssize_t
vdis_read(struct file
* file
, char * response
, size_t length
, loff_t
* offset
)
110 while ( (vdis_buf
[i
] != '\0') && length
) {
111 put_user(vdis_buf
[i
], response
++);
120 static ssize_t
vdis_write(struct file
*file
, const char *message
, size_t length
, loff_t
*offset
)
126 void vdi_request(request_queue_t
*q
)
130 while ( (req
= elv_next_request(q
)) != NULL
) {
131 if (!blk_fs_request(req
)) {
136 printk("vdi request: sec %lu (nr, %u)\n", req
->nr_sectors
,
137 req
->current_nr_sectors
);
138 // TODO: send data to the daemon
140 // Verify data direction
141 if (rq_data_dir(req
)) {
143 //sprintf(vdis_buf, "write %lu %lu\n", req->sector, req->nr_sectors);
146 //sprintf(vdis_buf, "read %lu %lu\n", req->sector, req->nr_sectors);
154 int vdi_ioctl (struct inode
*inode
, struct file
*filp
, unsigned int cmd
,
162 * Operations with the block driver
164 static struct block_device_operations vdi_oper
= {
165 .owner
= THIS_MODULE
,
171 * Operations with the char driver
173 struct file_operations vdis_oper
= {
177 .release
= vdis_release
181 static int __init
vdi_init(void)
187 vdis_major
= alloc_chrdev_region(&vdis_dev_t
, 0, 1, "vdis");
188 if (vdis_major
< 0) {
189 printk(KERN_WARNING
"vdi: Unable to create the char device\n");
192 vdis_major
= MAJOR(vdis_dev_t
);
194 printk(KERN_WARNING
"vdi: vdis major = %d\n", vdis_major
);
196 cdev_init(&vdis_cdev
, &vdis_oper
);
197 vdis_cdev
.owner
= THIS_MODULE
;
198 vdis_cdev
.ops
= &vdis_oper
;
199 err
= cdev_add(&vdis_cdev
, vdis_dev_t
, 1);
201 printk(KERN_NOTICE
"vdi: Error while adding char device\n");
208 vdi
.size
= VDI_SECTORS
* VDI_HARDSECT_SIZE
;
210 spin_lock_init(&vdi
.lock
);
212 Queue
= blk_init_queue(vdi_request
, &vdi
.lock
);
214 printk(KERN_WARNING
"vdi: Unable to create request queue.\n");
217 blk_queue_hardsect_size(Queue
, VDI_HARDSECT_SIZE
);
221 * Register your major, and accept a dynamic number
223 vdi_major
= register_blkdev(vdi_major
, "vdi");
225 printk(KERN_WARNING
"vdi: Unable to create block device major %d\n", vdi_major
);
229 // Create the gendisk structure
230 vdi
.gd
= alloc_disk(16);
232 // TODO: Unregister it
233 unregister_blkdev(major
, "vdi");
236 // Set gendisk fields
237 vdi
.gd
->major
= vdi_major
;
238 vdi
.gd
->first_minor
= 0;
239 vdi
.gd
->fops
= &vdi_oper
;
240 vdi
.gd
->private_data
= &vdi
;
241 strcpy(vdi
.gd
->disk_name
, "vdi0");
242 set_capacity(vdi
.gd
, VDI_SECTORS
*(VDI_HARDSECT_SIZE
/KERNEL_SECTOR_SIZE
));
243 vdi
.gd
->queue
= Queue
;
246 printk("vdi: init complete\n");
247 return 0; /* succeed */
250 static void __exit
vdi_exit(void)
252 cdev_del(&vdis_cdev
);
253 unregister_chrdev_region(vdis_dev_t
, 1);
256 unregister_blkdev(vdi_major
, "vdi");
257 blk_cleanup_queue(Queue
);
258 printk("vdi: exit complete\n");
261 MODULE_LICENSE("GPL");
263 module_init(vdi_init
);
264 module_exit(vdi_exit
);