special usb hub handling, IDE disks, and retries all over the place
[linux-2.4.git] / drivers / ide / raid / ataraid.c
1 /*
2    ataraid.c  Copyright (C) 2001 Red Hat, Inc. All rights reserved.
3
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.
8    
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.  
12    
13    Authors:     Arjan van de Ven <arjanv@redhat.com>
14                 
15    
16 */
17
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>
31
32 #include <linux/ide.h>
33 #include <asm/uaccess.h>
34
35 #include "ataraid.h"
36
37                                         
38 static int ataraid_hardsect_size[256];
39 static int ataraid_blksize_size[256];
40
41 static struct raid_device_operations* ataraid_ops[16];
42
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);
47
48
49 struct gendisk ataraid_gendisk;
50 static int ataraid_gendisk_sizes[256];
51 static int ataraid_readahead[256];
52
53 static struct block_device_operations ataraid_fops = {
54         owner:                  THIS_MODULE,
55         open:                   ataraid_open,
56         release:                ataraid_release,
57         ioctl:                  ataraid_ioctl,
58 };
59                 
60
61
62 static DECLARE_MUTEX(ataraid_sem);
63
64 /* Bitmap for the devices currently in use */
65 static unsigned int ataraiduse;
66
67
68 /* stub fops functions */
69
70 static int ataraid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)  
71 {
72         int minor;
73         minor = MINOR(inode->i_rdev)>>SHIFT;
74         
75         if ((ataraid_ops[minor])&&(ataraid_ops[minor]->ioctl))
76                 return (ataraid_ops[minor]->ioctl)(inode,file,cmd,arg);
77         return -EINVAL;
78 }
79
80 static int ataraid_open(struct inode * inode, struct file * filp)
81 {
82         int minor;
83         minor = MINOR(inode->i_rdev)>>SHIFT;
84
85         if ((ataraid_ops[minor])&&(ataraid_ops[minor]->open))
86                 return (ataraid_ops[minor]->open)(inode,filp);
87         return -EINVAL;
88 }
89
90
91 static int ataraid_release(struct inode * inode, struct file * filp)
92 {
93         int minor;
94         minor = MINOR(inode->i_rdev)>>SHIFT;
95
96         if ((ataraid_ops[minor])&&(ataraid_ops[minor]->release))
97                 return (ataraid_ops[minor]->release)(inode,filp);
98         return -EINVAL;
99 }
100
101 static int ataraid_make_request (request_queue_t *q, int rw, struct buffer_head * bh)
102 {
103         int minor;
104         int retval;
105         minor = MINOR(bh->b_rdev)>>SHIFT;
106
107         if ((ataraid_ops[minor])&&(ataraid_ops[minor]->make_request)) {
108                 
109                 retval= (ataraid_ops[minor]->make_request)(q,rw,bh);
110                 if (retval == -1) {
111                         ataraid_split_request(q,rw,bh);         
112                         return 0;
113                 } else
114                         return retval;
115         }
116         return -EINVAL;
117 }
118
119 struct buffer_head *ataraid_get_bhead(void)
120 {
121         void *ptr = NULL;
122         while (!ptr) {
123                 ptr=kmalloc(sizeof(struct buffer_head),GFP_NOIO);
124                 if (!ptr) {
125                         __set_current_state(TASK_RUNNING);
126                         yield();
127                 }
128         }
129         return ptr;
130 }
131
132 EXPORT_SYMBOL(ataraid_get_bhead);
133
134 struct ataraid_bh_private *ataraid_get_private(void)
135 {
136         void *ptr = NULL;
137         while (!ptr) {
138                 ptr=kmalloc(sizeof(struct ataraid_bh_private),GFP_NOIO);
139                 if (!ptr) {
140                         __set_current_state(TASK_RUNNING);
141                         yield();
142                 }
143         }
144         return ptr;
145 }
146
147 EXPORT_SYMBOL(ataraid_get_private);
148
149 void ataraid_end_request(struct buffer_head *bh, int uptodate)
150 {
151         struct ataraid_bh_private *private = bh->b_private;
152
153         if (private==NULL)
154                 BUG();
155
156         if (atomic_dec_and_test(&private->count)) {
157                 private->parent->b_end_io(private->parent,uptodate);
158                 private->parent = NULL;
159                 kfree(private);
160         }
161         kfree(bh);
162 }
163
164 EXPORT_SYMBOL(ataraid_end_request);
165
166 static void ataraid_split_request(request_queue_t *q, int rw, struct buffer_head * bh)
167 {
168         struct buffer_head *bh1,*bh2;
169         struct ataraid_bh_private *private;
170         bh1=ataraid_get_bhead();
171         bh2=ataraid_get_bhead();
172
173         /* If either of those ever fails we're doomed */
174         if ((!bh1)||(!bh2))
175                 BUG();
176         private = ataraid_get_private();
177         if (private==NULL)
178                 BUG();
179         
180         memcpy(bh1, bh, sizeof(*bh));
181         memcpy(bh2, bh, sizeof(*bh));
182         
183         bh1->b_end_io = ataraid_end_request;
184         bh2->b_end_io = ataraid_end_request;
185
186         bh2->b_rsector += bh->b_size >> 10;
187         bh1->b_size /= 2;
188         bh2->b_size /= 2;
189         private->parent = bh;
190
191         bh1->b_private = private;
192         bh2->b_private = private;
193         atomic_set(&private->count,2);
194
195         bh2->b_data +=  bh->b_size/2;
196
197         generic_make_request(rw,bh1);
198         generic_make_request(rw,bh2);
199 }
200
201
202
203
204 /* device register / release functions */
205
206
207 int ataraid_get_device(struct raid_device_operations *fops)
208 {
209         int bit;
210         down(&ataraid_sem);
211         if (ataraiduse==~0U) {
212                 up(&ataraid_sem);
213                 return -ENODEV;
214         }
215         bit=ffz(ataraiduse); 
216         ataraiduse |= 1<<bit;
217         ataraid_ops[bit] = fops;
218         up(&ataraid_sem);
219         return bit;
220 }
221
222 void ataraid_release_device(int device)
223 {
224         down(&ataraid_sem);
225         
226         if ((ataraiduse & (1<<device))==0)
227                 BUG();  /* device wasn't registered at all */
228         
229         ataraiduse &= ~(1<<device);
230         ataraid_ops[device] = NULL;
231         up(&ataraid_sem);
232 }
233
234 void ataraid_register_disk(int device,long size)
235 {
236         register_disk(&ataraid_gendisk, MKDEV(ATAMAJOR,16*device),16,
237                 &ataraid_fops,size);
238
239 }
240
241 static __init int ataraid_init(void) 
242 {
243         int i;
244         for(i=0;i<256;i++)
245         {
246                 ataraid_hardsect_size[i] = 512;
247                 ataraid_blksize_size[i] = 1024;  
248                 ataraid_readahead[i] = 1023;
249         }
250         
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;
255         
256         
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");
261                 return -1;
262         }
263         
264         memset(&ataraid_gendisk.part[0],0,256*sizeof(struct hd_struct));
265         
266         
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;
274         
275         
276         add_gendisk(&ataraid_gendisk);
277                         
278         if (register_blkdev(ATAMAJOR, "ataraid", &ataraid_fops)) {
279                 printk(KERN_ERR "ataraid: Could not get major %d \n",ATAMAJOR);
280                 return -1;
281         }
282         
283                         
284         
285         blk_queue_make_request(BLK_DEFAULT_QUEUE(ATAMAJOR),ataraid_make_request);
286                                                                                         
287         return 0;                                                               
288 }
289
290
291 static void __exit ataraid_exit(void)
292 {
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;
298
299         del_gendisk(&ataraid_gendisk);
300         
301         if (ataraid_gendisk.part) {
302                 kfree(ataraid_gendisk.part);
303                 ataraid_gendisk.part = NULL;
304         }
305 }
306
307 module_init(ataraid_init);
308 module_exit(ataraid_exit);
309
310
311
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");
317