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