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>
37 static struct raid_device_operations
*ataraid_ops
[16];
39 static int ataraid_ioctl(struct inode
*inode
, struct file
*file
,
40 unsigned int cmd
, unsigned long arg
);
41 static int ataraid_open(struct inode
*inode
, struct file
*filp
);
42 static int ataraid_release(struct inode
*inode
, struct file
*filp
);
43 static void ataraid_split_request(request_queue_t
* q
, int rw
,
44 struct buffer_head
*bh
);
47 struct gendisk ataraid_gendisk
;
48 static int ataraid_readahead
[256];
50 static struct block_device_operations ataraid_fops
= {
53 .release
= ataraid_release
,
54 .ioctl
= ataraid_ioctl
,
59 static DECLARE_MUTEX(ataraid_sem
);
61 /* Bitmap for the devices currently in use */
62 static unsigned int ataraiduse
;
65 /* stub fops functions */
67 static int ataraid_ioctl(struct inode
*inode
, struct file
*file
,
68 unsigned int cmd
, unsigned long arg
)
71 minor
= minor(inode
->i_rdev
) >> SHIFT
;
73 if ((ataraid_ops
[minor
]) && (ataraid_ops
[minor
]->ioctl
))
74 return (ataraid_ops
[minor
]->ioctl
) (inode
, file
, cmd
, arg
);
78 static int ataraid_open(struct inode
*inode
, struct file
*filp
)
81 minor
= minor(inode
->i_rdev
) >> SHIFT
;
83 if ((ataraid_ops
[minor
]) && (ataraid_ops
[minor
]->open
))
84 return (ataraid_ops
[minor
]->open
) (inode
, filp
);
89 static int ataraid_release(struct inode
*inode
, struct file
*filp
)
92 minor
= minor(inode
->i_rdev
) >> SHIFT
;
94 if ((ataraid_ops
[minor
]) && (ataraid_ops
[minor
]->release
))
95 return (ataraid_ops
[minor
]->release
) (inode
, filp
);
99 static int ataraid_make_request(request_queue_t
* q
, int rw
,
100 struct buffer_head
*bh
)
104 minor
= minor(bh
->b_rdev
) >> SHIFT
;
106 if ((ataraid_ops
[minor
]) && (ataraid_ops
[minor
]->make_request
)) {
108 retval
= (ataraid_ops
[minor
]->make_request
) (q
, rw
, bh
);
110 ataraid_split_request(q
, rw
, bh
);
118 struct buffer_head
*ataraid_get_bhead(void)
122 ptr
= kmalloc(sizeof(struct buffer_head
), GFP_NOIO
);
129 EXPORT_SYMBOL(ataraid_get_bhead
);
131 struct ataraid_bh_private
*ataraid_get_private(void)
135 ptr
= kmalloc(sizeof(struct ataraid_bh_private
), GFP_NOIO
);
142 EXPORT_SYMBOL(ataraid_get_private
);
144 void ataraid_end_request(struct buffer_head
*bh
, int uptodate
)
146 struct ataraid_bh_private
*private = bh
->b_private
;
151 if (atomic_dec_and_test(&private->count
)) {
152 private->parent
->b_end_io(private->parent
, uptodate
);
153 private->parent
= NULL
;
159 EXPORT_SYMBOL(ataraid_end_request
);
161 static void ataraid_split_request(request_queue_t
* q
, int rw
,
162 struct buffer_head
*bh
)
164 struct buffer_head
*bh1
, *bh2
;
165 struct ataraid_bh_private
*private;
166 bh1
= ataraid_get_bhead();
167 bh2
= ataraid_get_bhead();
169 /* If either of those ever fails we're doomed */
170 if ((!bh1
) || (!bh2
))
172 private = ataraid_get_private();
176 memcpy(bh1
, bh
, sizeof(*bh
));
177 memcpy(bh2
, bh
, sizeof(*bh
));
179 bh1
->b_end_io
= ataraid_end_request
;
180 bh2
->b_end_io
= ataraid_end_request
;
182 bh2
->b_rsector
+= bh
->b_size
>> 10;
185 private->parent
= bh
;
187 bh1
->b_private
= private;
188 bh2
->b_private
= private;
189 atomic_set(&private->count
, 2);
191 bh2
->b_data
+= bh
->b_size
/ 2;
193 generic_make_request(rw
, bh1
);
194 generic_make_request(rw
, bh2
);
200 /* device register / release functions */
203 int ataraid_get_device(struct raid_device_operations
*fops
)
207 if (ataraiduse
== ~0U) {
211 bit
= ffz(ataraiduse
);
212 ataraiduse
|= 1 << bit
;
213 ataraid_ops
[bit
] = fops
;
218 void ataraid_release_device(int device
)
222 if ((ataraiduse
& (1 << device
)) == 0)
223 BUG(); /* device wasn't registered at all */
225 ataraiduse
&= ~(1 << device
);
226 ataraid_ops
[device
] = NULL
;
230 void ataraid_register_disk(int device
, long size
)
232 register_disk(&ataraid_gendisk
, mk_kdev(ATAMAJOR
, 16 * device
), 16,
233 &ataraid_fops
, size
);
237 static __init
int ataraid_init(void)
240 for (i
= 0; i
< 256; i
++)
241 ataraid_readahead
[i
] = 1023;
243 /* setup the gendisk structure */
244 ataraid_gendisk
.part
=
245 kmalloc(256 * sizeof(struct hd_struct
), GFP_KERNEL
);
246 if (ataraid_gendisk
.part
== NULL
) {
248 "ataraid: Couldn't allocate memory, aborting \n");
252 memset(&ataraid_gendisk
.part
[0], 0,
253 256 * sizeof(struct hd_struct
));
256 ataraid_gendisk
.major
= ATAMAJOR
;
257 ataraid_gendisk
.major_name
= "ataraid";
258 ataraid_gendisk
.minor_shift
= 4;
259 ataraid_gendisk
.nr_real
= 16;
260 ataraid_gendisk
.fops
= &ataraid_fops
;
263 add_gendisk(&ataraid_gendisk
);
265 if (register_blkdev(ATAMAJOR
, "ataraid", &ataraid_fops
)) {
266 printk(KERN_ERR
"ataraid: Could not get major %d \n",
273 blk_queue_make_request(BLK_DEFAULT_QUEUE(ATAMAJOR
),
274 ataraid_make_request
);
280 static void __exit
ataraid_exit(void)
282 unregister_blkdev(ATAMAJOR
, "ataraid");
284 del_gendisk(&ataraid_gendisk
);
286 if (ataraid_gendisk
.part
) {
287 kfree(ataraid_gendisk
.part
);
288 ataraid_gendisk
.part
= NULL
;
292 module_init(ataraid_init
);
293 module_exit(ataraid_exit
);
297 EXPORT_SYMBOL(ataraid_get_device
);
298 EXPORT_SYMBOL(ataraid_release_device
);
299 EXPORT_SYMBOL(ataraid_gendisk
);
300 EXPORT_SYMBOL(ataraid_register_disk
);
301 MODULE_LICENSE("GPL");