2 ataraid.c Copyright (C) 2001 Red Hat, Inc. All rights reserved.
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 2, or (at your option)
9 You should have received a copy of the GNU General Public License
10 (for example /usr/src/linux/COPYING); if not, write to the Free
11 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13 Authors: Arjan van de Ven <arjanv@redhat.com>
18 #include <linux/module.h>
19 #include <linux/init.h>
20 #include <linux/kernel.h>
22 #include <asm/semaphore.h>
23 #include <linux/sched.h>
24 #include <linux/smp_lock.h>
25 #include <linux/blkdev.h>
26 #include <linux/blkpg.h>
27 #include <linux/genhd.h>
28 #include <linux/ioctl.h>
29 #include <linux/kdev_t.h>
30 #include <linux/swap.h>
32 #include <linux/ide.h>
33 #include <asm/uaccess.h>
38 static int ataraid_hardsect_size[256];
39 static int ataraid_blksize_size[256];
41 static struct raid_device_operations* ataraid_ops[16];
43 static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
44 static int ataraid_open(struct inode * inode, struct file * filp);
45 static int ataraid_release(struct inode * inode, struct file * filp);
46 static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh);
49 struct gendisk ataraid_gendisk;
50 static int ataraid_gendisk_sizes[256];
51 static int ataraid_readahead[256];
53 static struct block_device_operations ataraid_fops = {
56 release: ataraid_release,
62 static DECLARE_MUTEX(ataraid_sem);
64 /* Bitmap for the devices currently in use */
65 static unsigned int ataraiduse;
68 /* stub fops functions */
70 static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
73 minor = MINOR(inode->i_rdev)>>SHIFT;
75 if ((ataraid_ops[minor])&&(ataraid_ops[minor]->ioctl))
76 return (ataraid_ops[minor]->ioctl)(inode,file,cmd,arg);
80 static int ataraid_open(struct inode * inode, struct file * filp)
83 minor = MINOR(inode->i_rdev)>>SHIFT;
85 if ((ataraid_ops[minor])&&(ataraid_ops[minor]->open))
86 return (ataraid_ops[minor]->open)(inode,filp);
91 static int ataraid_release(struct inode * inode, struct file * filp)
94 minor = MINOR(inode->i_rdev)>>SHIFT;
96 if ((ataraid_ops[minor])&&(ataraid_ops[minor]->release))
97 return (ataraid_ops[minor]->release)(inode,filp);
101 static int ataraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
105 minor = MINOR(bh->b_rdev)>>SHIFT;
107 if ((ataraid_ops[minor])&&(ataraid_ops[minor]->make_request)) {
109 retval= (ataraid_ops[minor]->make_request)(q,rw,bh);
111 ataraid_split_request(q,rw,bh);
119 struct buffer_head *ataraid_get_bhead(void)
123 ptr=kmalloc(sizeof(struct buffer_head),GFP_NOIO);
125 __set_current_state(TASK_RUNNING);
132 EXPORT_SYMBOL(ataraid_get_bhead);
134 struct ataraid_bh_private *ataraid_get_private(void)
138 ptr=kmalloc(sizeof(struct ataraid_bh_private),GFP_NOIO);
140 __set_current_state(TASK_RUNNING);
147 EXPORT_SYMBOL(ataraid_get_private);
149 void ataraid_end_request(struct buffer_head *bh, int uptodate)
151 struct ataraid_bh_private *private = bh->b_private;
156 if (atomic_dec_and_test(&private->count)) {
157 private->parent->b_end_io(private->parent,uptodate);
158 private->parent = NULL;
164 EXPORT_SYMBOL(ataraid_end_request);
166 static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh)
168 struct buffer_head *bh1,*bh2;
169 struct ataraid_bh_private *private;
170 bh1=ataraid_get_bhead();
171 bh2=ataraid_get_bhead();
173 /* If either of those ever fails we're doomed */
176 private = ataraid_get_private();
180 memcpy(bh1, bh, sizeof(*bh));
181 memcpy(bh2, bh, sizeof(*bh));
183 bh1->b_end_io = ataraid_end_request;
184 bh2->b_end_io = ataraid_end_request;
186 bh2->b_rsector += bh->b_size >> 10;
189 private->parent = bh;
191 bh1->b_private = private;
192 bh2->b_private = private;
193 atomic_set(&private->count,2);
195 bh2->b_data += bh->b_size/2;
197 generic_make_request(rw,bh1);
198 generic_make_request(rw,bh2);
204 /* device register / release functions */
207 int ataraid_get_device(struct raid_device_operations *fops)
211 if (ataraiduse==~0U) {
216 ataraiduse |= 1<<bit;
217 ataraid_ops[bit] = fops;
222 void ataraid_release_device(int device)
226 if ((ataraiduse & (1<<device))==0)
227 BUG(); /* device wasn't registered at all */
229 ataraiduse &= ~(1<<device);
230 ataraid_ops[device] = NULL;
234 void ataraid_register_disk(int device,long size)
236 register_disk(&ataraid_gendisk, MKDEV(ATAMAJOR,16*device),16,
241 static __init int ataraid_init(void)
246 ataraid_hardsect_size[i] = 512;
247 ataraid_blksize_size[i] = 1024;
248 ataraid_readahead[i] = 1023;
251 if (blksize_size[ATAMAJOR]==NULL)
252 blksize_size[ATAMAJOR] = ataraid_blksize_size;
253 if (hardsect_size[ATAMAJOR]==NULL)
254 hardsect_size[ATAMAJOR] = ataraid_hardsect_size;
257 /* setup the gendisk structure */
258 ataraid_gendisk.part = kmalloc(256 * sizeof(struct hd_struct),GFP_KERNEL);
259 if (ataraid_gendisk.part==NULL) {
260 printk(KERN_ERR "ataraid: Couldn't allocate memory, aborting \n");
264 memset(&ataraid_gendisk.part[0],0,256*sizeof(struct hd_struct));
267 ataraid_gendisk.major = ATAMAJOR;
268 ataraid_gendisk.major_name = "ataraid";
269 ataraid_gendisk.minor_shift = 4;
270 ataraid_gendisk.max_p = 15;
271 ataraid_gendisk.sizes = &ataraid_gendisk_sizes[0];
272 ataraid_gendisk.nr_real = 16;
273 ataraid_gendisk.fops = &ataraid_fops;
276 add_gendisk(&ataraid_gendisk);
278 if (register_blkdev(ATAMAJOR, "ataraid", &ataraid_fops)) {
279 printk(KERN_ERR "ataraid: Could not get major %d \n",ATAMAJOR);
285 blk_queue_make_request(BLK_DEFAULT_QUEUE(ATAMAJOR),ataraid_make_request);
291 static void __exit ataraid_exit(void)
293 unregister_blkdev(ATAMAJOR, "ataraid");
294 hardsect_size[ATAMAJOR] = NULL;
295 blk_size[ATAMAJOR] = NULL;
296 blksize_size[ATAMAJOR] = NULL;
297 max_readahead[ATAMAJOR] = NULL;
299 del_gendisk(&ataraid_gendisk);
301 if (ataraid_gendisk.part) {
302 kfree(ataraid_gendisk.part);
303 ataraid_gendisk.part = NULL;
307 module_init(ataraid_init);
308 module_exit(ataraid_exit);
312 EXPORT_SYMBOL(ataraid_get_device);
313 EXPORT_SYMBOL(ataraid_release_device);
314 EXPORT_SYMBOL(ataraid_gendisk);
315 EXPORT_SYMBOL(ataraid_register_disk);
316 MODULE_LICENSE("GPL");