More meth updates.
[linux-2.6/linux-mips.git] / drivers / ide / ataraid.c
blob0a6b6ec91baa6463f0e2be42736f7dd29c51dbfa
1 /*
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)
7 any later version.
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>
21 #include <linux/mm.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>
35 #include "ataraid.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 = {
51 .owner = THIS_MODULE,
52 .open = ataraid_open,
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)
70 int minor;
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);
75 return -EINVAL;
78 static int ataraid_open(struct inode *inode, struct file *filp)
80 int minor;
81 minor = minor(inode->i_rdev) >> SHIFT;
83 if ((ataraid_ops[minor]) && (ataraid_ops[minor]->open))
84 return (ataraid_ops[minor]->open) (inode, filp);
85 return -EINVAL;
89 static int ataraid_release(struct inode *inode, struct file *filp)
91 int minor;
92 minor = minor(inode->i_rdev) >> SHIFT;
94 if ((ataraid_ops[minor]) && (ataraid_ops[minor]->release))
95 return (ataraid_ops[minor]->release) (inode, filp);
96 return -EINVAL;
99 static int ataraid_make_request(request_queue_t * q, int rw,
100 struct buffer_head *bh)
102 int minor;
103 int retval;
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);
109 if (retval == -1) {
110 ataraid_split_request(q, rw, bh);
111 return 0;
112 } else
113 return retval;
115 return -EINVAL;
118 struct buffer_head *ataraid_get_bhead(void)
120 void *ptr = NULL;
121 while (!ptr) {
122 ptr = kmalloc(sizeof(struct buffer_head), GFP_NOIO);
123 if (!ptr)
124 yield();
126 return ptr;
129 EXPORT_SYMBOL(ataraid_get_bhead);
131 struct ataraid_bh_private *ataraid_get_private(void)
133 void *ptr = NULL;
134 while (!ptr) {
135 ptr = kmalloc(sizeof(struct ataraid_bh_private), GFP_NOIO);
136 if (!ptr)
137 yield();
139 return ptr;
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;
148 if (private == NULL)
149 BUG();
151 if (atomic_dec_and_test(&private->count)) {
152 private->parent->b_end_io(private->parent, uptodate);
153 private->parent = NULL;
154 kfree(private);
156 kfree(bh);
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))
171 BUG();
172 private = ataraid_get_private();
173 if (private == NULL)
174 BUG();
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;
183 bh1->b_size /= 2;
184 bh2->b_size /= 2;
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)
205 int bit;
206 down(&ataraid_sem);
207 if (ataraiduse == ~0U) {
208 up(&ataraid_sem);
209 return -ENODEV;
211 bit = ffz(ataraiduse);
212 ataraiduse |= 1 << bit;
213 ataraid_ops[bit] = fops;
214 up(&ataraid_sem);
215 return bit;
218 void ataraid_release_device(int device)
220 down(&ataraid_sem);
222 if ((ataraiduse & (1 << device)) == 0)
223 BUG(); /* device wasn't registered at all */
225 ataraiduse &= ~(1 << device);
226 ataraid_ops[device] = NULL;
227 up(&ataraid_sem);
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)
239 int i;
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) {
247 printk(KERN_ERR
248 "ataraid: Couldn't allocate memory, aborting \n");
249 return -1;
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",
267 ATAMAJOR);
268 return -1;
273 blk_queue_make_request(BLK_DEFAULT_QUEUE(ATAMAJOR),
274 ataraid_make_request);
276 return 0;
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");