Merge /spare/repo/netdev-2.6/ branch 'ieee80211'
[linux-2.6] / drivers / block / xd.c
1 /*
2  * This file contains the driver for an XT hard disk controller
3  * (at least the DTC 5150X) for Linux.
4  *
5  * Author: Pat Mackinlay, pat@it.com.au
6  * Date: 29/09/92
7  * 
8  * Revised: 01/01/93, ...
9  *
10  * Ref: DTC 5150X Controller Specification (thanks to Kevin Fowler,
11  *   kevinf@agora.rain.com)
12  * Also thanks to: Salvador Abreu, Dave Thaler, Risto Kankkunen and
13  *   Wim Van Dorst.
14  *
15  * Revised: 04/04/94 by Risto Kankkunen
16  *   Moved the detection code from xd_init() to xd_geninit() as it needed
17  *   interrupts enabled and Linus didn't want to enable them in that first
18  *   phase. xd_geninit() is the place to do these kinds of things anyway,
19  *   he says.
20  *
21  * Modularized: 04/10/96 by Todd Fries, tfries@umr.edu
22  *
23  * Revised: 13/12/97 by Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl
24  *   Fixed some problems with disk initialization and module initiation.
25  *   Added support for manual geometry setting (except Seagate controllers)
26  *   in form:
27  *      xd_geo=<cyl_xda>,<head_xda>,<sec_xda>[,<cyl_xdb>,<head_xdb>,<sec_xdb>]
28  *   Recovered DMA access. Abridged messages. Added support for DTC5051CX,
29  *   WD1002-27X & XEBEC controllers. Driver uses now some jumper settings.
30  *   Extended ioctl() support.
31  *
32  * Bugfix: 15/02/01, Paul G. - inform queue layer of tiny xd_maxsect.
33  *
34  */
35
36 #include <linux/module.h>
37 #include <linux/errno.h>
38 #include <linux/interrupt.h>
39 #include <linux/mm.h>
40 #include <linux/fs.h>
41 #include <linux/kernel.h>
42 #include <linux/timer.h>
43 #include <linux/genhd.h>
44 #include <linux/hdreg.h>
45 #include <linux/ioport.h>
46 #include <linux/init.h>
47 #include <linux/wait.h>
48 #include <linux/blkdev.h>
49 #include <linux/blkpg.h>
50
51 #include <asm/system.h>
52 #include <asm/io.h>
53 #include <asm/uaccess.h>
54 #include <asm/dma.h>
55
56 #include "xd.h"
57
58 static void __init do_xd_setup (int *integers);
59 #ifdef MODULE
60 static int xd[5] = { -1,-1,-1,-1, };
61 #endif
62
63 #define XD_DONT_USE_DMA         0  /* Initial value. may be overriden using
64                                       "nodma" module option */
65 #define XD_INIT_DISK_DELAY      (30*HZ/1000)  /* 30 ms delay during disk initialization */
66
67 /* Above may need to be increased if a problem with the 2nd drive detection
68    (ST11M controller) or resetting a controller (WD) appears */
69
70 static XD_INFO xd_info[XD_MAXDRIVES];
71
72 /* If you try this driver and find that your card is not detected by the driver at bootup, you need to add your BIOS
73    signature and details to the following list of signatures. A BIOS signature is a string embedded into the first
74    few bytes of your controller's on-board ROM BIOS. To find out what yours is, use something like MS-DOS's DEBUG
75    command. Run DEBUG, and then you can examine your BIOS signature with:
76
77         d xxxx:0000
78
79    where xxxx is the segment of your controller (like C800 or D000 or something). On the ASCII dump at the right, you should
80    be able to see a string mentioning the manufacturer's copyright etc. Add this string into the table below. The parameters
81    in the table are, in order:
82
83         offset                  ; this is the offset (in bytes) from the start of your ROM where the signature starts
84         signature               ; this is the actual text of the signature
85         xd_?_init_controller    ; this is the controller init routine used by your controller
86         xd_?_init_drive         ; this is the drive init routine used by your controller
87
88    The controllers directly supported at the moment are: DTC 5150x, WD 1004A27X, ST11M/R and override. If your controller is
89    made by the same manufacturer as one of these, try using the same init routines as they do. If that doesn't work, your
90    best bet is to use the "override" routines. These routines use a "portable" method of getting the disk's geometry, and
91    may work with your card. If none of these seem to work, try sending me some email and I'll see what I can do <grin>.
92
93    NOTE: You can now specify your XT controller's parameters from the command line in the form xd=TYPE,IRQ,IO,DMA. The driver
94    should be able to detect your drive's geometry from this info. (eg: xd=0,5,0x320,3 is the "standard"). */
95
96 #include <asm/page.h>
97 #define xd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size))
98 #define xd_dma_mem_free(addr, size) free_pages(addr, get_order(size))
99 static char *xd_dma_buffer;
100
101 static XD_SIGNATURE xd_sigs[] __initdata = {
102         { 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, pat@it.com.au */
103         { 0x0008,"[BXD06 (C) DTC 17-MAY-1985]",xd_dtc_init_controller,xd_dtc5150cx_init_drive," DTC 5150CX" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
104         { 0x000B,"CRD18A   Not an IBM rom. (C) Copyright Data Technology Corp. 05/31/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Todd Fries, tfries@umr.edu */
105         { 0x000B,"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive," DTC 5150X" }, /* Pat Mackinlay, pat@it.com.au */
106         { 0x0008,"07/15/86(C) Copyright 1986 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002-27X" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
107         { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Dig. WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
108         { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
109         { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
110         { 0x0010,"ST11 BIOS v1.7",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11R" }, /* Alan Hourihane, alanh@fairlite.demon.co.uk */
111         { 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
112         { 0x0006,"COPYRIGHT XEBEC (C) 1984",xd_xebec_init_controller,xd_xebec_init_drive," XEBEC" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
113         { 0x0008,"(C) Copyright 1984 Western Digital Corp", xd_wd_init_controller, xd_wd_init_drive," Western Dig. 1002s-wx2" },
114         { 0x0008,"(C) Copyright 1986 Western Digital Corporation", xd_wd_init_controller, xd_wd_init_drive," 1986 Western Digital" }, /* jfree@sovereign.org */
115 };
116
117 static unsigned int xd_bases[] __initdata =
118 {
119         0xC8000, 0xCA000, 0xCC000,
120         0xCE000, 0xD0000, 0xD2000,
121         0xD4000, 0xD6000, 0xD8000,
122         0xDA000, 0xDC000, 0xDE000,
123         0xE0000
124 };
125
126 static DEFINE_SPINLOCK(xd_lock);
127
128 static struct gendisk *xd_gendisk[2];
129
130 static struct block_device_operations xd_fops = {
131         .owner  = THIS_MODULE,
132         .ioctl  = xd_ioctl,
133 };
134 static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
135 static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors;
136 static u_char xd_override __initdata = 0, xd_type __initdata = 0;
137 static u_short xd_iobase = 0x320;
138 static int xd_geo[XD_MAXDRIVES*3] __initdata = { 0, };
139
140 static volatile int xdc_busy;
141 static struct timer_list xd_watchdog_int;
142
143 static volatile u_char xd_error;
144 static int nodma = XD_DONT_USE_DMA;
145
146 static struct request_queue *xd_queue;
147
148 /* xd_init: register the block device number and set up pointer tables */
149 static int __init xd_init(void)
150 {
151         u_char i,controller;
152         unsigned int address;
153         int err;
154
155 #ifdef MODULE
156         {
157                 u_char count = 0;
158                 for (i = 4; i > 0; i--)
159                         if (((xd[i] = xd[i-1]) >= 0) && !count)
160                                 count = i;
161                 if ((xd[0] = count))
162                         do_xd_setup(xd);
163         }
164 #endif
165
166         init_timer (&xd_watchdog_int); xd_watchdog_int.function = xd_watchdog;
167
168         if (!xd_dma_buffer)
169                 xd_dma_buffer = (char *)xd_dma_mem_alloc(xd_maxsectors * 0x200);
170         if (!xd_dma_buffer) {
171                 printk(KERN_ERR "xd: Out of memory.\n");
172                 return -ENOMEM;
173         }
174
175         err = -EBUSY;
176         if (register_blkdev(XT_DISK_MAJOR, "xd"))
177                 goto out1;
178
179         err = -ENOMEM;
180         xd_queue = blk_init_queue(do_xd_request, &xd_lock);
181         if (!xd_queue)
182                 goto out1a;
183
184         if (xd_detect(&controller,&address)) {
185
186                 printk("Detected a%s controller (type %d) at address %06x\n",
187                         xd_sigs[controller].name,controller,address);
188                 if (!request_region(xd_iobase,4,"xd")) {
189                         printk("xd: Ports at 0x%x are not available\n",
190                                 xd_iobase);
191                         goto out2;
192                 }
193                 if (controller)
194                         xd_sigs[controller].init_controller(address);
195                 xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
196                 
197                 printk("Detected %d hard drive%s (using IRQ%d & DMA%d)\n",
198                         xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
199         }
200
201         err = -ENODEV;
202         if (!xd_drives)
203                 goto out3;
204
205         for (i = 0; i < xd_drives; i++) {
206                 XD_INFO *p = &xd_info[i];
207                 struct gendisk *disk = alloc_disk(64);
208                 if (!disk)
209                         goto Enomem;
210                 p->unit = i;
211                 disk->major = XT_DISK_MAJOR;
212                 disk->first_minor = i<<6;
213                 sprintf(disk->disk_name, "xd%c", i+'a');
214                 sprintf(disk->devfs_name, "xd/target%d", i);
215                 disk->fops = &xd_fops;
216                 disk->private_data = p;
217                 disk->queue = xd_queue;
218                 set_capacity(disk, p->heads * p->cylinders * p->sectors);
219                 printk(" %s: CHS=%d/%d/%d\n", disk->disk_name,
220                         p->cylinders, p->heads, p->sectors);
221                 xd_gendisk[i] = disk;
222         }
223
224         err = -EBUSY;
225         if (request_irq(xd_irq,xd_interrupt_handler, 0, "XT hard disk", NULL)) {
226                 printk("xd: unable to get IRQ%d\n",xd_irq);
227                 goto out4;
228         }
229
230         if (request_dma(xd_dma,"xd")) {
231                 printk("xd: unable to get DMA%d\n",xd_dma);
232                 goto out5;
233         }
234
235         /* xd_maxsectors depends on controller - so set after detection */
236         blk_queue_max_sectors(xd_queue, xd_maxsectors);
237
238         for (i = 0; i < xd_drives; i++)
239                 add_disk(xd_gendisk[i]);
240
241         return 0;
242
243 out5:
244         free_irq(xd_irq, NULL);
245 out4:
246         for (i = 0; i < xd_drives; i++)
247                 put_disk(xd_gendisk[i]);
248 out3:
249         release_region(xd_iobase,4);
250 out2:
251         blk_cleanup_queue(xd_queue);
252 out1a:
253         unregister_blkdev(XT_DISK_MAJOR, "xd");
254 out1:
255         if (xd_dma_buffer)
256                 xd_dma_mem_free((unsigned long)xd_dma_buffer,
257                                 xd_maxsectors * 0x200);
258         return err;
259 Enomem:
260         err = -ENOMEM;
261         while (i--)
262                 put_disk(xd_gendisk[i]);
263         goto out3;
264 }
265
266 /* xd_detect: scan the possible BIOS ROM locations for the signature strings */
267 static u_char __init xd_detect (u_char *controller, unsigned int *address)
268 {
269         int i, j;
270
271         if (xd_override)
272         {
273                 *controller = xd_type;
274                 *address = 0;
275                 return(1);
276         }
277
278         for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])); i++) {
279                 void __iomem *p = ioremap(xd_bases[i], 0x2000);
280                 if (!p)
281                         continue;
282                 for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])); j++) {
283                         const char *s = xd_sigs[j].string;
284                         if (check_signature(p + xd_sigs[j].offset, s, strlen(s))) {
285                                 *controller = j;
286                                 xd_type = j;
287                                 *address = xd_bases[i];
288                                 iounmap(p);
289                                 return 1;
290                         }
291                 }
292                 iounmap(p);
293         }
294         return 0;
295 }
296
297 /* do_xd_request: handle an incoming request */
298 static void do_xd_request (request_queue_t * q)
299 {
300         struct request *req;
301
302         if (xdc_busy)
303                 return;
304
305         while ((req = elv_next_request(q)) != NULL) {
306                 unsigned block = req->sector;
307                 unsigned count = req->nr_sectors;
308                 int rw = rq_data_dir(req);
309                 XD_INFO *disk = req->rq_disk->private_data;
310                 int res = 0;
311                 int retry;
312
313                 if (!(req->flags & REQ_CMD)) {
314                         end_request(req, 0);
315                         continue;
316                 }
317                 if (block + count > get_capacity(req->rq_disk)) {
318                         end_request(req, 0);
319                         continue;
320                 }
321                 if (rw != READ && rw != WRITE) {
322                         printk("do_xd_request: unknown request\n");
323                         end_request(req, 0);
324                         continue;
325                 }
326                 for (retry = 0; (retry < XD_RETRIES) && !res; retry++)
327                         res = xd_readwrite(rw, disk, req->buffer, block, count);
328                 end_request(req, res);  /* wrap up, 0 = fail, 1 = success */
329         }
330 }
331
332 /* xd_ioctl: handle device ioctl's */
333 static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
334 {
335         XD_INFO *p = inode->i_bdev->bd_disk->private_data;
336
337         switch (cmd) {
338                 case HDIO_GETGEO:
339                 {
340                         struct hd_geometry g;
341                         struct hd_geometry __user *geom= (void __user *)arg;
342                         g.heads = p->heads;
343                         g.sectors = p->sectors;
344                         g.cylinders = p->cylinders;
345                         g.start = get_start_sect(inode->i_bdev);
346                         return copy_to_user(geom, &g, sizeof(g)) ? -EFAULT : 0;
347                 }
348                 case HDIO_SET_DMA:
349                         if (!capable(CAP_SYS_ADMIN)) return -EACCES;
350                         if (xdc_busy) return -EBUSY;
351                         nodma = !arg;
352                         if (nodma && xd_dma_buffer) {
353                                 xd_dma_mem_free((unsigned long)xd_dma_buffer,
354                                                 xd_maxsectors * 0x200);
355                                 xd_dma_buffer = NULL;
356                         } else if (!nodma && !xd_dma_buffer) {
357                                 xd_dma_buffer = (char *)xd_dma_mem_alloc(xd_maxsectors * 0x200);
358                                 if (!xd_dma_buffer) {
359                                         nodma = XD_DONT_USE_DMA;
360                                         return -ENOMEM;
361                                 }
362                         }
363                         return 0;
364                 case HDIO_GET_DMA:
365                         return put_user(!nodma, (long __user *) arg);
366                 case HDIO_GET_MULTCOUNT:
367                         return put_user(xd_maxsectors, (long __user *) arg);
368                 default:
369                         return -EINVAL;
370         }
371 }
372
373 /* xd_readwrite: handle a read/write request */
374 static int xd_readwrite (u_char operation,XD_INFO *p,char *buffer,u_int block,u_int count)
375 {
376         int drive = p->unit;
377         u_char cmdblk[6],sense[4];
378         u_short track,cylinder;
379         u_char head,sector,control,mode = PIO_MODE,temp;
380         char **real_buffer;
381         register int i;
382         
383 #ifdef DEBUG_READWRITE
384         printk("xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation == READ ? "read" : "write",drive,buffer,block,count);
385 #endif /* DEBUG_READWRITE */
386
387         spin_unlock_irq(&xd_lock);
388
389         control = p->control;
390         if (!xd_dma_buffer)
391                 xd_dma_buffer = (char *)xd_dma_mem_alloc(xd_maxsectors * 0x200);
392         while (count) {
393                 temp = count < xd_maxsectors ? count : xd_maxsectors;
394
395                 track = block / p->sectors;
396                 head = track % p->heads;
397                 cylinder = track / p->heads;
398                 sector = block % p->sectors;
399
400 #ifdef DEBUG_READWRITE
401                 printk("xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive,head,cylinder,sector,temp);
402 #endif /* DEBUG_READWRITE */
403
404                 if (xd_dma_buffer) {
405                         mode = xd_setup_dma(operation == READ ? DMA_MODE_READ : DMA_MODE_WRITE,(u_char *)(xd_dma_buffer),temp * 0x200);
406                         real_buffer = &xd_dma_buffer;
407                         for (i=0; i < (temp * 0x200); i++)
408                                 xd_dma_buffer[i] = buffer[i];
409                 }
410                 else
411                         real_buffer = &buffer;
412
413                 xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
414
415                 switch (xd_command(cmdblk,mode,(u_char *)(*real_buffer),(u_char *)(*real_buffer),sense,XD_TIMEOUT)) {
416                         case 1:
417                                 printk("xd%c: %s timeout, recalibrating drive\n",'a'+drive,(operation == READ ? "read" : "write"));
418                                 xd_recalibrate(drive);
419                                 spin_lock_irq(&xd_lock);
420                                 return (0);
421                         case 2:
422                                 if (sense[0] & 0x30) {
423                                         printk("xd%c: %s - ",'a'+drive,(operation == READ ? "reading" : "writing"));
424                                         switch ((sense[0] & 0x30) >> 4) {
425                                         case 0: printk("drive error, code = 0x%X",sense[0] & 0x0F);
426                                                 break;
427                                         case 1: printk("controller error, code = 0x%X",sense[0] & 0x0F);
428                                                 break;
429                                         case 2: printk("command error, code = 0x%X",sense[0] & 0x0F);
430                                                 break;
431                                         case 3: printk("miscellaneous error, code = 0x%X",sense[0] & 0x0F);
432                                                 break;
433                                         }
434                                 }
435                                 if (sense[0] & 0x80)
436                                         printk(" - CHS = %d/%d/%d\n",((sense[2] & 0xC0) << 2) | sense[3],sense[1] & 0x1F,sense[2] & 0x3F);
437                                 /*      reported drive number = (sense[1] & 0xE0) >> 5 */
438                                 else
439                                         printk(" - no valid disk address\n");
440                                 spin_lock_irq(&xd_lock);
441                                 return (0);
442                 }
443                 if (xd_dma_buffer)
444                         for (i=0; i < (temp * 0x200); i++)
445                                 buffer[i] = xd_dma_buffer[i];
446
447                 count -= temp, buffer += temp * 0x200, block += temp;
448         }
449         spin_lock_irq(&xd_lock);
450         return (1);
451 }
452
453 /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */
454 static void xd_recalibrate (u_char drive)
455 {
456         u_char cmdblk[6];
457         
458         xd_build(cmdblk,CMD_RECALIBRATE,drive,0,0,0,0,0);
459         if (xd_command(cmdblk,PIO_MODE,NULL,NULL,NULL,XD_TIMEOUT * 8))
460                 printk("xd%c: warning! error recalibrating, controller may be unstable\n", 'a'+drive);
461 }
462
463 /* xd_interrupt_handler: interrupt service routine */
464 static irqreturn_t xd_interrupt_handler(int irq, void *dev_id,
465                                         struct pt_regs *regs)
466 {
467         if (inb(XD_STATUS) & STAT_INTERRUPT) {                                                  /* check if it was our device */
468 #ifdef DEBUG_OTHER
469                 printk("xd_interrupt_handler: interrupt detected\n");
470 #endif /* DEBUG_OTHER */
471                 outb(0,XD_CONTROL);                                                             /* acknowledge interrupt */
472                 wake_up(&xd_wait_int);  /* and wake up sleeping processes */
473                 return IRQ_HANDLED;
474         }
475         else
476                 printk("xd: unexpected interrupt\n");
477         return IRQ_NONE;
478 }
479
480 /* xd_setup_dma: set up the DMA controller for a data transfer */
481 static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
482 {
483         unsigned long f;
484         
485         if (nodma)
486                 return (PIO_MODE);
487         if (((unsigned long) buffer & 0xFFFF0000) != (((unsigned long) buffer + count) & 0xFFFF0000)) {
488 #ifdef DEBUG_OTHER
489                 printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");
490 #endif /* DEBUG_OTHER */
491                 return (PIO_MODE);
492         }
493         
494         f=claim_dma_lock();
495         disable_dma(xd_dma);
496         clear_dma_ff(xd_dma);
497         set_dma_mode(xd_dma,mode);
498         set_dma_addr(xd_dma, (unsigned long) buffer);
499         set_dma_count(xd_dma,count);
500         
501         release_dma_lock(f);
502
503         return (DMA_MODE);                      /* use DMA and INT */
504 }
505
506 /* xd_build: put stuff into an array in a format suitable for the controller */
507 static u_char *xd_build (u_char *cmdblk,u_char command,u_char drive,u_char head,u_short cylinder,u_char sector,u_char count,u_char control)
508 {
509         cmdblk[0] = command;
510         cmdblk[1] = ((drive & 0x07) << 5) | (head & 0x1F);
511         cmdblk[2] = ((cylinder & 0x300) >> 2) | (sector & 0x3F);
512         cmdblk[3] = cylinder & 0xFF;
513         cmdblk[4] = count;
514         cmdblk[5] = control;
515         
516         return (cmdblk);
517 }
518
519 static void xd_watchdog (unsigned long unused)
520 {
521         xd_error = 1;
522         wake_up(&xd_wait_int);
523 }
524
525 /* xd_waitport: waits until port & mask == flags or a timeout occurs. return 1 for a timeout */
526 static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout)
527 {
528         u_long expiry = jiffies + timeout;
529         int success;
530
531         xdc_busy = 1;
532         while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) {
533                 set_current_state(TASK_UNINTERRUPTIBLE);
534                 schedule_timeout(1);
535         }
536         xdc_busy = 0;
537         return (success);
538 }
539
540 static inline u_int xd_wait_for_IRQ (void)
541 {
542         unsigned long flags;
543         xd_watchdog_int.expires = jiffies + 8 * HZ;
544         add_timer(&xd_watchdog_int);
545         
546         flags=claim_dma_lock();
547         enable_dma(xd_dma);
548         release_dma_lock(flags);
549         
550         sleep_on(&xd_wait_int);
551         del_timer(&xd_watchdog_int);
552         xdc_busy = 0;
553         
554         flags=claim_dma_lock();
555         disable_dma(xd_dma);
556         release_dma_lock(flags);
557         
558         if (xd_error) {
559                 printk("xd: missed IRQ - command aborted\n");
560                 xd_error = 0;
561                 return (1);
562         }
563         return (0);
564 }
565
566 /* xd_command: handle all data transfers necessary for a single command */
567 static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout)
568 {
569         u_char cmdblk[6],csb,complete = 0;
570
571 #ifdef DEBUG_COMMAND
572         printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);
573 #endif /* DEBUG_COMMAND */
574
575         outb(0,XD_SELECT);
576         outb(mode,XD_CONTROL);
577
578         if (xd_waitport(XD_STATUS,STAT_SELECT,STAT_SELECT,timeout))
579                 return (1);
580
581         while (!complete) {
582                 if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
583                         return (1);
584
585                 switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
586                         case 0:
587                                 if (mode == DMA_MODE) {
588                                         if (xd_wait_for_IRQ())
589                                                 return (1);
590                                 } else
591                                         outb(outdata ? *outdata++ : 0,XD_DATA);
592                                 break;
593                         case STAT_INPUT:
594                                 if (mode == DMA_MODE) {
595                                         if (xd_wait_for_IRQ())
596                                                 return (1);
597                                 } else
598                                         if (indata)
599                                                 *indata++ = inb(XD_DATA);
600                                         else
601                                                 inb(XD_DATA);
602                                 break;
603                         case STAT_COMMAND:
604                                 outb(command ? *command++ : 0,XD_DATA);
605                                 break;
606                         case STAT_COMMAND | STAT_INPUT:
607                                 complete = 1;
608                                 break;
609                 }
610         }
611         csb = inb(XD_DATA);
612
613         if (xd_waitport(XD_STATUS,0,STAT_SELECT,timeout))                                       /* wait until deselected */
614                 return (1);
615
616         if (csb & CSB_ERROR) {                                                                  /* read sense data if error */
617                 xd_build(cmdblk,CMD_SENSE,(csb & CSB_LUN) >> 5,0,0,0,0,0);
618                 if (xd_command(cmdblk,0,sense,NULL,NULL,XD_TIMEOUT))
619                         printk("xd: warning! sense command failed!\n");
620         }
621
622 #ifdef DEBUG_COMMAND
623         printk("xd_command: completed with csb = 0x%X\n",csb);
624 #endif /* DEBUG_COMMAND */
625
626         return (csb & CSB_ERROR);
627 }
628
629 static u_char __init xd_initdrives (void (*init_drive)(u_char drive))
630 {
631         u_char cmdblk[6],i,count = 0;
632
633         for (i = 0; i < XD_MAXDRIVES; i++) {
634                 xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
635                 if (!xd_command(cmdblk,PIO_MODE,NULL,NULL,NULL,XD_TIMEOUT*8)) {
636                         set_current_state(TASK_INTERRUPTIBLE);
637                         schedule_timeout(XD_INIT_DISK_DELAY);
638
639                         init_drive(count);
640                         count++;
641
642                         set_current_state(TASK_INTERRUPTIBLE);
643                         schedule_timeout(XD_INIT_DISK_DELAY);
644                 }
645         }
646         return (count);
647 }
648
649 static void __init xd_manual_geo_set (u_char drive)
650 {
651         xd_info[drive].heads = (u_char)(xd_geo[3 * drive + 1]);
652         xd_info[drive].cylinders = (u_short)(xd_geo[3 * drive]);
653         xd_info[drive].sectors = (u_char)(xd_geo[3 * drive + 2]);
654 }
655
656 static void __init xd_dtc_init_controller (unsigned int address)
657 {
658         switch (address) {
659                 case 0x00000:
660                 case 0xC8000:   break;                  /*initial: 0x320 */
661                 case 0xCA000:   xd_iobase = 0x324; 
662                 case 0xD0000:                           /*5150CX*/
663                 case 0xD8000:   break;                  /*5150CX & 5150XL*/
664                 default:        printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address);
665                                 break;
666         }
667         xd_maxsectors = 0x01;           /* my card seems to have trouble doing multi-block transfers? */
668
669         outb(0,XD_RESET);               /* reset the controller */
670 }
671
672
673 static void __init xd_dtc5150cx_init_drive (u_char drive)
674 {
675         /* values from controller's BIOS - BIOS chip may be removed */
676         static u_short geometry_table[][4] = {
677                 {0x200,8,0x200,0x100},
678                 {0x267,2,0x267,0x267},
679                 {0x264,4,0x264,0x80},
680                 {0x132,4,0x132,0x0},
681                 {0x132,2,0x80, 0x132},
682                 {0x177,8,0x177,0x0},
683                 {0x132,8,0x84, 0x0},
684                 {},  /* not used */
685                 {0x132,6,0x80, 0x100},
686                 {0x200,6,0x100,0x100},
687                 {0x264,2,0x264,0x80},
688                 {0x280,4,0x280,0x100},
689                 {0x2B9,3,0x2B9,0x2B9},
690                 {0x2B9,5,0x2B9,0x2B9},
691                 {0x280,6,0x280,0x100},
692                 {0x132,4,0x132,0x0}};
693         u_char n;
694
695         n = inb(XD_JUMPER);
696         n = (drive ? n : (n >> 2)) & 0x33;
697         n = (n | (n >> 2)) & 0x0F;
698         if (xd_geo[3*drive])
699                 xd_manual_geo_set(drive);
700         else
701                 if (n != 7) {   
702                         xd_info[drive].heads = (u_char)(geometry_table[n][1]);                  /* heads */
703                         xd_info[drive].cylinders = geometry_table[n][0];        /* cylinders */
704                         xd_info[drive].sectors = 17;                            /* sectors */
705 #if 0
706                         xd_info[drive].rwrite = geometry_table[n][2];   /* reduced write */
707                         xd_info[drive].precomp = geometry_table[n][3]           /* write precomp */
708                         xd_info[drive].ecc = 0x0B;                              /* ecc length */
709 #endif /* 0 */
710                 }
711                 else {
712                         printk("xd%c: undetermined drive geometry\n",'a'+drive);
713                         return;
714                 }
715         xd_info[drive].control = 5;                             /* control byte */
716         xd_setparam(CMD_DTCSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);
717         xd_recalibrate(drive);
718 }
719
720 static void __init xd_dtc_init_drive (u_char drive)
721 {
722         u_char cmdblk[6],buf[64];
723
724         xd_build(cmdblk,CMD_DTCGETGEOM,drive,0,0,0,0,0);
725         if (!xd_command(cmdblk,PIO_MODE,buf,NULL,NULL,XD_TIMEOUT * 2)) {
726                 xd_info[drive].heads = buf[0x0A];                       /* heads */
727                 xd_info[drive].cylinders = ((u_short *) (buf))[0x04];   /* cylinders */
728                 xd_info[drive].sectors = 17;                            /* sectors */
729                 if (xd_geo[3*drive])
730                         xd_manual_geo_set(drive);
731 #if 0
732                 xd_info[drive].rwrite = ((u_short *) (buf + 1))[0x05];  /* reduced write */
733                 xd_info[drive].precomp = ((u_short *) (buf + 1))[0x06]; /* write precomp */
734                 xd_info[drive].ecc = buf[0x0F];                         /* ecc length */
735 #endif /* 0 */
736                 xd_info[drive].control = 0;                             /* control byte */
737
738                 xd_setparam(CMD_DTCSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,((u_short *) (buf + 1))[0x05],((u_short *) (buf + 1))[0x06],buf[0x0F]);
739                 xd_build(cmdblk,CMD_DTCSETSTEP,drive,0,0,0,0,7);
740                 if (xd_command(cmdblk,PIO_MODE,NULL,NULL,NULL,XD_TIMEOUT * 2))
741                         printk("xd_dtc_init_drive: error setting step rate for xd%c\n", 'a'+drive);
742         }
743         else
744                 printk("xd_dtc_init_drive: error reading geometry for xd%c\n", 'a'+drive);
745 }
746
747 static void __init xd_wd_init_controller (unsigned int address)
748 {
749         switch (address) {
750                 case 0x00000:
751                 case 0xC8000:   break;                  /*initial: 0x320 */
752                 case 0xCA000:   xd_iobase = 0x324; break;
753                 case 0xCC000:   xd_iobase = 0x328; break;
754                 case 0xCE000:   xd_iobase = 0x32C; break;
755                 case 0xD0000:   xd_iobase = 0x328; break; /* ? */
756                 case 0xD8000:   xd_iobase = 0x32C; break; /* ? */
757                 default:        printk("xd_wd_init_controller: unsupported BIOS address %06x\n",address);
758                                 break;
759         }
760         xd_maxsectors = 0x01;           /* this one doesn't wrap properly either... */
761
762         outb(0,XD_RESET);               /* reset the controller */
763
764         set_current_state(TASK_UNINTERRUPTIBLE);
765         schedule_timeout(XD_INIT_DISK_DELAY);
766 }
767
768 static void __init xd_wd_init_drive (u_char drive)
769 {
770         /* values from controller's BIOS - BIOS may be disabled */
771         static u_short geometry_table[][4] = {
772                 {0x264,4,0x1C2,0x1C2},   /* common part */
773                 {0x132,4,0x099,0x0},
774                 {0x267,2,0x1C2,0x1C2},
775                 {0x267,4,0x1C2,0x1C2},
776
777                 {0x334,6,0x335,0x335},   /* 1004 series RLL */
778                 {0x30E,4,0x30F,0x3DC},
779                 {0x30E,2,0x30F,0x30F},
780                 {0x267,4,0x268,0x268},
781
782                 {0x3D5,5,0x3D6,0x3D6},   /* 1002 series RLL */
783                 {0x3DB,7,0x3DC,0x3DC},
784                 {0x264,4,0x265,0x265},
785                 {0x267,4,0x268,0x268}};
786
787         u_char cmdblk[6],buf[0x200];
788         u_char n = 0,rll,jumper_state,use_jumper_geo;
789         u_char wd_1002 = (xd_sigs[xd_type].string[7] == '6');
790         
791         jumper_state = ~(inb(0x322));
792         if (jumper_state & 0x40)
793                 xd_irq = 9;
794         rll = (jumper_state & 0x30) ? (0x04 << wd_1002) : 0;
795         xd_build(cmdblk,CMD_READ,drive,0,0,0,1,0);
796         if (!xd_command(cmdblk,PIO_MODE,buf,NULL,NULL,XD_TIMEOUT * 2)) {
797                 xd_info[drive].heads = buf[0x1AF];                              /* heads */
798                 xd_info[drive].cylinders = ((u_short *) (buf + 1))[0xD6];       /* cylinders */
799                 xd_info[drive].sectors = 17;                                    /* sectors */
800                 if (xd_geo[3*drive])
801                         xd_manual_geo_set(drive);
802 #if 0
803                 xd_info[drive].rwrite = ((u_short *) (buf))[0xD8];              /* reduced write */
804                 xd_info[drive].wprecomp = ((u_short *) (buf))[0xDA];            /* write precomp */
805                 xd_info[drive].ecc = buf[0x1B4];                                /* ecc length */
806 #endif /* 0 */
807                 xd_info[drive].control = buf[0x1B5];                            /* control byte */
808                 use_jumper_geo = !(xd_info[drive].heads) || !(xd_info[drive].cylinders);
809                 if (xd_geo[3*drive]) {
810                         xd_manual_geo_set(drive);
811                         xd_info[drive].control = rll ? 7 : 5;
812                 }
813                 else if (use_jumper_geo) {
814                         n = (((jumper_state & 0x0F) >> (drive << 1)) & 0x03) | rll;
815                         xd_info[drive].cylinders = geometry_table[n][0];
816                         xd_info[drive].heads = (u_char)(geometry_table[n][1]);
817                         xd_info[drive].control = rll ? 7 : 5;
818 #if 0
819                         xd_info[drive].rwrite = geometry_table[n][2];
820                         xd_info[drive].wprecomp = geometry_table[n][3];
821                         xd_info[drive].ecc = 0x0B;
822 #endif /* 0 */
823                 }
824                 if (!wd_1002) {
825                         if (use_jumper_geo)
826                                 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
827                                         geometry_table[n][2],geometry_table[n][3],0x0B);
828                         else
829                                 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
830                                         ((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
831                 }
832         /* 1002 based RLL controller requests converted addressing, but reports physical 
833            (physical 26 sec., logical 17 sec.) 
834            1004 based ???? */
835                 if (rll & wd_1002) {
836                         if ((xd_info[drive].cylinders *= 26,
837                              xd_info[drive].cylinders /= 17) > 1023)
838                                 xd_info[drive].cylinders = 1023;  /* 1024 ? */
839 #if 0
840                         xd_info[drive].rwrite *= 26; 
841                         xd_info[drive].rwrite /= 17;
842                         xd_info[drive].wprecomp *= 26
843                         xd_info[drive].wprecomp /= 17;
844 #endif /* 0 */
845                 }
846         }
847         else
848                 printk("xd_wd_init_drive: error reading geometry for xd%c\n",'a'+drive);        
849
850 }
851
852 static void __init xd_seagate_init_controller (unsigned int address)
853 {
854         switch (address) {
855                 case 0x00000:
856                 case 0xC8000:   break;                  /*initial: 0x320 */
857                 case 0xD0000:   xd_iobase = 0x324; break;
858                 case 0xD8000:   xd_iobase = 0x328; break;
859                 case 0xE0000:   xd_iobase = 0x32C; break;
860                 default:        printk("xd_seagate_init_controller: unsupported BIOS address %06x\n",address);
861                                 break;
862         }
863         xd_maxsectors = 0x40;
864
865         outb(0,XD_RESET);               /* reset the controller */
866 }
867
868 static void __init xd_seagate_init_drive (u_char drive)
869 {
870         u_char cmdblk[6],buf[0x200];
871
872         xd_build(cmdblk,CMD_ST11GETGEOM,drive,0,0,0,1,0);
873         if (!xd_command(cmdblk,PIO_MODE,buf,NULL,NULL,XD_TIMEOUT * 2)) {
874                 xd_info[drive].heads = buf[0x04];                               /* heads */
875                 xd_info[drive].cylinders = (buf[0x02] << 8) | buf[0x03];        /* cylinders */
876                 xd_info[drive].sectors = buf[0x05];                             /* sectors */
877                 xd_info[drive].control = 0;                                     /* control byte */
878         }
879         else
880                 printk("xd_seagate_init_drive: error reading geometry from xd%c\n", 'a'+drive);
881 }
882
883 /* Omti support courtesy Dirk Melchers */
884 static void __init xd_omti_init_controller (unsigned int address)
885 {
886         switch (address) {
887                 case 0x00000:
888                 case 0xC8000:   break;                  /*initial: 0x320 */
889                 case 0xD0000:   xd_iobase = 0x324; break;
890                 case 0xD8000:   xd_iobase = 0x328; break;
891                 case 0xE0000:   xd_iobase = 0x32C; break;
892                 default:        printk("xd_omti_init_controller: unsupported BIOS address %06x\n",address);
893                                 break;
894         }
895         
896         xd_maxsectors = 0x40;
897
898         outb(0,XD_RESET);               /* reset the controller */
899 }
900
901 static void __init xd_omti_init_drive (u_char drive)
902 {
903         /* gets infos from drive */
904         xd_override_init_drive(drive);
905
906         /* set other parameters, Hardcoded, not that nice :-) */
907         xd_info[drive].control = 2;
908 }
909
910 /* Xebec support (AK) */
911 static void __init xd_xebec_init_controller (unsigned int address)
912 {
913 /* iobase may be set manually in range 0x300 - 0x33C
914       irq may be set manually to 2(9),3,4,5,6,7
915       dma may be set manually to 1,2,3
916         (How to detect them ???)
917 BIOS address may be set manually in range 0x0 - 0xF8000
918 If you need non-standard settings use the xd=... command */
919
920         switch (address) {
921                 case 0x00000:
922                 case 0xC8000:   /* initially: xd_iobase==0x320 */
923                 case 0xD0000:
924                 case 0xD2000:
925                 case 0xD4000:
926                 case 0xD6000:
927                 case 0xD8000:
928                 case 0xDA000:
929                 case 0xDC000:
930                 case 0xDE000:
931                 case 0xE0000:   break;
932                 default:        printk("xd_xebec_init_controller: unsupported BIOS address %06x\n",address);
933                                 break;
934                 }
935
936         xd_maxsectors = 0x01;
937         outb(0,XD_RESET);               /* reset the controller */
938
939         set_current_state(TASK_UNINTERRUPTIBLE);
940         schedule_timeout(XD_INIT_DISK_DELAY);
941 }
942
943 static void __init xd_xebec_init_drive (u_char drive)
944 {
945         /* values from controller's BIOS - BIOS chip may be removed */
946         static u_short geometry_table[][5] = {
947                 {0x132,4,0x080,0x080,0x7},
948                 {0x132,4,0x080,0x080,0x17},
949                 {0x264,2,0x100,0x100,0x7},
950                 {0x264,2,0x100,0x100,0x17},
951                 {0x132,8,0x080,0x080,0x7},
952                 {0x132,8,0x080,0x080,0x17},
953                 {0x264,4,0x100,0x100,0x6},
954                 {0x264,4,0x100,0x100,0x17},
955                 {0x2BC,5,0x2BC,0x12C,0x6},
956                 {0x3A5,4,0x3A5,0x3A5,0x7},
957                 {0x26C,6,0x26C,0x26C,0x7},
958                 {0x200,8,0x200,0x100,0x17},
959                 {0x400,5,0x400,0x400,0x7},
960                 {0x400,6,0x400,0x400,0x7},
961                 {0x264,8,0x264,0x200,0x17},
962                 {0x33E,7,0x33E,0x200,0x7}};
963         u_char n;
964
965         n = inb(XD_JUMPER) & 0x0F; /* BIOS's drive number: same geometry 
966                                         is assumed for BOTH drives */
967         if (xd_geo[3*drive])
968                 xd_manual_geo_set(drive);
969         else {
970                 xd_info[drive].heads = (u_char)(geometry_table[n][1]);                  /* heads */
971                 xd_info[drive].cylinders = geometry_table[n][0];        /* cylinders */
972                 xd_info[drive].sectors = 17;                            /* sectors */
973 #if 0
974                 xd_info[drive].rwrite = geometry_table[n][2];   /* reduced write */
975                 xd_info[drive].precomp = geometry_table[n][3]           /* write precomp */
976                 xd_info[drive].ecc = 0x0B;                              /* ecc length */
977 #endif /* 0 */
978         }
979         xd_info[drive].control = geometry_table[n][4];                  /* control byte */
980         xd_setparam(CMD_XBSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);
981         xd_recalibrate(drive);
982 }
983
984 /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
985    etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
986 static void __init xd_override_init_drive (u_char drive)
987 {
988         u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };
989         u_char cmdblk[6],i;
990
991         if (xd_geo[3*drive])
992                 xd_manual_geo_set(drive);
993         else {
994                 for (i = 0; i < 3; i++) {
995                         while (min[i] != max[i] - 1) {
996                                 test[i] = (min[i] + max[i]) / 2;
997                                 xd_build(cmdblk,CMD_SEEK,drive,(u_char) test[0],(u_short) test[1],(u_char) test[2],0,0);
998                                 if (!xd_command(cmdblk,PIO_MODE,NULL,NULL,NULL,XD_TIMEOUT * 2))
999                                         min[i] = test[i];
1000                                 else
1001                                         max[i] = test[i];
1002                         }
1003                         test[i] = min[i];
1004                 }
1005                 xd_info[drive].heads = (u_char) min[0] + 1;
1006                 xd_info[drive].cylinders = (u_short) min[1] + 1;
1007                 xd_info[drive].sectors = (u_char) min[2] + 1;
1008         }
1009         xd_info[drive].control = 0;
1010 }
1011
1012 /* xd_setup: initialise controller from command line parameters */
1013 static void __init do_xd_setup (int *integers)
1014 {
1015         switch (integers[0]) {
1016                 case 4: if (integers[4] < 0)
1017                                 nodma = 1;
1018                         else if (integers[4] < 8)
1019                                 xd_dma = integers[4];
1020                 case 3: if ((integers[3] > 0) && (integers[3] <= 0x3FC))
1021                                 xd_iobase = integers[3];
1022                 case 2: if ((integers[2] > 0) && (integers[2] < 16))
1023                                 xd_irq = integers[2];
1024                 case 1: xd_override = 1;
1025                         if ((integers[1] >= 0) && (integers[1] < (sizeof(xd_sigs) / sizeof(xd_sigs[0]))))
1026                                 xd_type = integers[1];
1027                 case 0: break;
1028                 default:printk("xd: too many parameters for xd\n");
1029         }
1030         xd_maxsectors = 0x01;
1031 }
1032
1033 /* xd_setparam: set the drive characteristics */
1034 static void __init xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc)
1035 {
1036         u_char cmdblk[14];
1037
1038         xd_build(cmdblk,command,drive,0,0,0,0,0);
1039         cmdblk[6] = (u_char) (cylinders >> 8) & 0x03;
1040         cmdblk[7] = (u_char) (cylinders & 0xFF);
1041         cmdblk[8] = heads & 0x1F;
1042         cmdblk[9] = (u_char) (rwrite >> 8) & 0x03;
1043         cmdblk[10] = (u_char) (rwrite & 0xFF);
1044         cmdblk[11] = (u_char) (wprecomp >> 8) & 0x03;
1045         cmdblk[12] = (u_char) (wprecomp & 0xFF);
1046         cmdblk[13] = ecc;
1047
1048         /* Some controllers require geometry info as data, not command */
1049
1050         if (xd_command(cmdblk,PIO_MODE,NULL,&cmdblk[6],NULL,XD_TIMEOUT * 2))
1051                 printk("xd: error setting characteristics for xd%c\n", 'a'+drive);
1052 }
1053
1054
1055 #ifdef MODULE
1056
1057 module_param_array(xd, int, NULL, 0);
1058 module_param_array(xd_geo, int, NULL, 0);
1059 module_param(nodma, bool, 0);
1060
1061 MODULE_LICENSE("GPL");
1062
1063 void cleanup_module(void)
1064 {
1065         int i;
1066         unregister_blkdev(XT_DISK_MAJOR, "xd");
1067         for (i = 0; i < xd_drives; i++) {
1068                 del_gendisk(xd_gendisk[i]);
1069                 put_disk(xd_gendisk[i]);
1070         }
1071         blk_cleanup_queue(xd_queue);
1072         release_region(xd_iobase,4);
1073         if (xd_drives) {
1074                 free_irq(xd_irq, NULL);
1075                 free_dma(xd_dma);
1076                 if (xd_dma_buffer)
1077                         xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
1078         }
1079 }
1080 #else
1081
1082 static int __init xd_setup (char *str)
1083 {
1084         int ints[5];
1085         get_options (str, ARRAY_SIZE (ints), ints);
1086         do_xd_setup (ints);
1087         return 1;
1088 }
1089
1090 /* xd_manual_geo_init: initialise drive geometry from command line parameters
1091    (used only for WD drives) */
1092 static int __init xd_manual_geo_init (char *str)
1093 {
1094         int i, integers[1 + 3*XD_MAXDRIVES];
1095
1096         get_options (str, ARRAY_SIZE (integers), integers);
1097         if (integers[0]%3 != 0) {
1098                 printk("xd: incorrect number of parameters for xd_geo\n");
1099                 return 1;
1100         }
1101         for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++)
1102                 xd_geo[i] = integers[i+1];
1103         return 1;
1104 }
1105
1106 __setup ("xd=", xd_setup);
1107 __setup ("xd_geo=", xd_manual_geo_init);
1108
1109 #endif /* MODULE */
1110
1111 module_init(xd_init);
1112 MODULE_ALIAS_BLOCKDEV_MAJOR(XT_DISK_MAJOR);