Import 2.3.9pre5
[davej-history.git] / drivers / block / xd.c
blob04c88fb08a1e442279fc9378db1298d1ba5c2668
1 /*
2 * This file contains the driver for an XT hard disk controller
3 * (at least the DTC 5150X) for Linux.
5 * Author: Pat Mackinlay, pat@it.com.au
6 * Date: 29/09/92
7 *
8 * Revised: 01/01/93, ...
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.
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.
21 * Modularized: 04/10/96 by Todd Fries, tfries@umr.edu
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.
33 #include <linux/module.h>
34 #include <linux/errno.h>
35 #include <linux/sched.h>
36 #include <linux/mm.h>
37 #include <linux/fs.h>
38 #include <linux/kernel.h>
39 #include <linux/timer.h>
40 #include <linux/genhd.h>
41 #include <linux/hdreg.h>
42 #include <linux/ioport.h>
43 #include <linux/init.h>
45 #include <asm/system.h>
46 #include <asm/io.h>
47 #include <asm/uaccess.h>
48 #include <asm/dma.h>
50 #define MAJOR_NR XT_DISK_MAJOR
51 #include <linux/blk.h>
52 #include <linux/blkpg.h>
54 #include "xd.h"
56 #define XD_DONT_USE_DMA 0 /* Initial value. may be overriden using
57 "nodma" module option */
58 #define XD_INIT_DISK_DELAY 3 /* 30 ms delay during disk initialization */
60 /* Above may need to be increased if a problem with the 2nd drive detection
61 (ST11M controller) or resetting a controler (WD) appears */
63 XD_INFO xd_info[XD_MAXDRIVES];
65 /* If you try this driver and find that your card is not detected by the driver at bootup, you need to add your BIOS
66 signature and details to the following list of signatures. A BIOS signature is a string embedded into the first
67 few bytes of your controller's on-board ROM BIOS. To find out what yours is, use something like MS-DOS's DEBUG
68 command. Run DEBUG, and then you can examine your BIOS signature with:
70 d xxxx:0000
72 where xxxx is the segment of your controller (like C800 or D000 or something). On the ASCII dump at the right, you should
73 be able to see a string mentioning the manufacturer's copyright etc. Add this string into the table below. The parameters
74 in the table are, in order:
76 offset ; this is the offset (in bytes) from the start of your ROM where the signature starts
77 signature ; this is the actual text of the signature
78 xd_?_init_controller ; this is the controller init routine used by your controller
79 xd_?_init_drive ; this is the drive init routine used by your controller
81 The controllers directly supported at the moment are: DTC 5150x, WD 1004A27X, ST11M/R and override. If your controller is
82 made by the same manufacturer as one of these, try using the same init routines as they do. If that doesn't work, your
83 best bet is to use the "override" routines. These routines use a "portable" method of getting the disk's geometry, and
84 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>.
86 NOTE: You can now specify your XT controller's parameters from the command line in the form xd=TYPE,IRQ,IO,DMA. The driver
87 should be able to detect your drive's geometry from this info. (eg: xd=0,5,0x320,3 is the "standard"). */
89 #include <asm/page.h>
90 /* coppied from floppy.c */
91 static inline int __get_order(unsigned long size)
93 int order;
95 size = (size-1) >> (PAGE_SHIFT-1);
96 order = -1;
97 do {
98 size >>= 1;
99 order++;
100 } while (size);
101 return order;
103 #define xd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,__get_order(size))
104 #define xd_dma_mem_free(addr, size) free_pages(addr, __get_order(size))
105 static char *xd_dma_buffer = 0;
107 static XD_SIGNATURE xd_sigs[] __initdata = {
108 { 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, pat@it.com.au */
109 { 0x0008,"[BXD06 (C) DTC 17-MAY-1985]",xd_dtc_init_controller,xd_dtc5150cx_init_drive," DTC 5150CX" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
110 { 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 */
111 { 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 */
112 { 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 */
113 { 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 */
114 { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
115 { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
116 { 0x0010,"ST11 BIOS v1.7",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11R" }, /* Alan Hourihane, alanh@fairlite.demon.co.uk */
117 { 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
118 { 0x0006,"COPYRIGHT XEBEC (C) 1984",xd_xebec_init_controller,xd_xebec_init_drive," XEBEC" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
121 static unsigned int xd_bases[] __initdata =
123 0xC8000, 0xCA000, 0xCC000,
124 0xCE000, 0xD0000, 0xD2000,
125 0xD4000, 0xD6000, 0xD8000,
126 0xDA000, 0xDC000, 0xDE000,
127 0xE0000
130 static struct hd_struct xd_struct[XD_MAXDRIVES << 6];
131 static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES] = { 0, 0 };
132 static int xd_blocksizes[XD_MAXDRIVES << 6];
133 static struct gendisk xd_gendisk = {
134 MAJOR_NR, /* Major number */
135 "xd", /* Major name */
136 6, /* Bits to shift to get real from partition */
137 1 << 6, /* Number of partitions per real */
138 XD_MAXDRIVES, /* maximum number of real */
139 #ifdef MODULE
140 NULL, /* called from init_module */
141 #else
142 xd_geninit, /* init function */
143 #endif
144 xd_struct, /* hd struct */
145 xd_sizes, /* block sizes */
146 0, /* number */
147 (void *) xd_info, /* internal */
148 NULL /* next */
150 static struct file_operations xd_fops = {
151 NULL, /* lseek - default */
152 block_read, /* read - general block-dev read */
153 block_write, /* write - general block-dev write */
154 NULL, /* readdir - bad */
155 NULL, /* poll */
156 xd_ioctl, /* ioctl */
157 NULL, /* mmap */
158 xd_open, /* open */
159 NULL, /* flush */
160 xd_release, /* release */
161 block_fsync /* fsync */
163 static DECLARE_WAIT_QUEUE_HEAD(xd_wait_int);
164 static DECLARE_WAIT_QUEUE_HEAD(xd_wait_open);
165 static u_char xd_valid[XD_MAXDRIVES] = { 0,0 };
166 static u_char xd_drives = 0, xd_irq = 5, xd_dma = 3, xd_maxsectors;
167 static u_char xd_override __initdata = 0, xd_type = 0;
168 static u_short xd_iobase = 0x320;
169 static int xd_geo[XD_MAXDRIVES*3] __initdata = { 0,0,0,0,0,0 };
171 static volatile int xdc_busy = 0;
172 static DECLARE_WAIT_QUEUE_HEAD(xdc_wait);
174 typedef void (*timeout_fn)(unsigned long);
175 static struct timer_list xd_timer = { NULL, NULL, 0, 0, (timeout_fn) xd_wakeup },
176 xd_watchdog_int = { NULL, NULL, 0, 0, (timeout_fn) xd_watchdog };
178 static volatile u_char xd_error;
179 static int nodma = XD_DONT_USE_DMA;
181 /* xd_init: register the block device number and set up pointer tables */
182 __initfunc(int xd_init (void))
184 if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
185 printk("xd: Unable to get major number %d\n",MAJOR_NR);
186 return -1;
188 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
189 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
190 xd_gendisk.next = gendisk_head;
191 gendisk_head = &xd_gendisk;
193 return 0;
196 /* xd_detect: scan the possible BIOS ROM locations for the signature strings */
197 __initfunc(static u_char xd_detect (u_char *controller, unsigned int *address))
199 u_char i,j,found = 0;
201 if (xd_override)
203 *controller = xd_type;
204 *address = 0;
205 return(1);
208 for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])) && !found; i++)
209 for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++)
210 if (check_signature(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) {
211 *controller = j;
212 xd_type = j;
213 *address = xd_bases[i];
214 found++;
216 return (found);
219 /* xd_geninit: grab the IRQ and DMA channel, initialise the drives */
220 /* and set up the "raw" device entries in the table */
221 __initfunc(static void xd_geninit (struct gendisk *ignored))
223 u_char i,controller;
224 unsigned int address;
226 if (xd_detect(&controller,&address)) {
228 printk("Detected a%s controller (type %d) at address %06x\n",xd_sigs[controller].name,controller,address);
229 if (check_region(xd_iobase,4)) {
230 printk("xd: Ports at 0x%x are not available\n",xd_iobase);
231 return;
233 request_region(xd_iobase,4,"xd");
234 if (controller)
235 xd_sigs[controller].init_controller(address);
236 xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
238 printk("Detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
239 for (i = 0; i < xd_drives; i++)
240 printk(" xd%c: CHS=%d/%d/%d\n",'a'+i,xd_info[i].cylinders,xd_info[i].heads,xd_info[i].sectors);
243 if (xd_drives) {
244 if (!request_irq(xd_irq,xd_interrupt_handler, 0, "XT hard disk", NULL)) {
245 if (request_dma(xd_dma,"xd")) {
246 printk("xd: unable to get DMA%d\n",xd_dma);
247 free_irq(xd_irq, NULL);
250 else
251 printk("xd: unable to get IRQ%d\n",xd_irq);
254 for (i = 0; i < xd_drives; i++) {
255 xd_struct[i << 6].nr_sects = xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors;
256 xd_valid[i] = 1;
259 xd_gendisk.nr_real = xd_drives;
261 for(i=0;i<(XD_MAXDRIVES << 6);i++) xd_blocksizes[i] = 1024;
262 blksize_size[MAJOR_NR] = xd_blocksizes;
265 /* xd_open: open a device */
266 static int xd_open (struct inode *inode,struct file *file)
268 int dev = DEVICE_NR(inode->i_rdev);
270 if (dev < xd_drives) {
271 while (!xd_valid[dev])
272 sleep_on(&xd_wait_open);
274 #ifdef MODULE
275 MOD_INC_USE_COUNT;
276 #endif /* MODULE */
278 xd_access[dev]++;
280 return (0);
282 else
283 return -ENXIO;
286 /* do_xd_request: handle an incoming request */
287 static void do_xd_request (void)
289 u_int block,count,retry;
290 int code;
292 sti();
293 if (xdc_busy)
294 return;
295 while (code = 0, CURRENT) {
296 INIT_REQUEST; /* do some checking on the request structure */
298 if (CURRENT_DEV < xd_drives
299 && CURRENT->sector + CURRENT->nr_sectors
300 <= xd_struct[MINOR(CURRENT->rq_dev)].nr_sects) {
301 block = CURRENT->sector + xd_struct[MINOR(CURRENT->rq_dev)].start_sect;
302 count = CURRENT->nr_sectors;
304 switch (CURRENT->cmd) {
305 case READ:
306 case WRITE:
307 for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
308 code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
309 break;
310 default:
311 printk("do_xd_request: unknown request\n");
312 break;
315 end_request(code); /* wrap up, 0 = fail, 1 = success */
319 /* xd_ioctl: handle device ioctl's */
320 static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
322 int dev;
324 if ((!inode) || !(inode->i_rdev))
325 return -EINVAL;
326 dev = DEVICE_NR(inode->i_rdev);
328 if (dev >= xd_drives) return -EINVAL;
329 switch (cmd) {
330 case HDIO_GETGEO:
332 struct hd_geometry g;
333 struct hd_geometry *geometry = (struct hd_geometry *) arg;
334 if (!geometry) return -EINVAL;
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;
341 case BLKGETSIZE:
342 if (!arg) return -EINVAL;
343 return put_user(xd_struct[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
344 case HDIO_SET_DMA:
345 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
346 if (xdc_busy) return -EBUSY;
347 nodma = !arg;
348 if (nodma && xd_dma_buffer) {
349 xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
350 xd_dma_buffer = 0;
352 return 0;
353 case HDIO_GET_DMA:
354 return put_user(!nodma, (long *) arg);
355 case HDIO_GET_MULTCOUNT:
356 return put_user(xd_maxsectors, (long *) arg);
357 case BLKRRPART:
358 if (!capable(CAP_SYS_ADMIN))
359 return -EACCES;
360 return xd_reread_partitions(inode->i_rdev);
362 case BLKFLSBUF:
363 case BLKROSET:
364 case BLKROGET:
365 case BLKRASET:
366 case BLKRAGET:
367 case BLKPG:
368 return blk_ioctl(inode->i_rdev, cmd, arg);
370 default:
371 return -EINVAL;
375 /* xd_release: release the device */
376 static int xd_release (struct inode *inode, struct file *file)
378 int target;
380 target= DEVICE_NR(inode->i_rdev);
381 if (target < xd_drives) {
382 sync_dev(inode->i_rdev);
383 xd_access[target]--;
385 #ifdef MODULE
386 MOD_DEC_USE_COUNT;
387 #endif /* MODULE */
390 return 0;
393 /* xd_reread_partitions: rereads the partition table from a drive */
394 static int xd_reread_partitions(kdev_t dev)
396 int target;
397 int start;
398 int partition;
400 target = DEVICE_NR(dev);
401 start = target << xd_gendisk.minor_shift;
403 cli();
404 xd_valid[target] = (xd_access[target] != 1);
405 sti();
406 if (xd_valid[target])
407 return -EBUSY;
409 for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
410 int minor = (start | partition);
411 kdev_t devp = MKDEV(MAJOR_NR, minor);
412 struct super_block * sb = get_super(devp);
414 sync_dev(devp);
415 if (sb)
416 invalidate_inodes(sb);
417 invalidate_buffers(devp);
418 xd_gendisk.part[minor].start_sect = 0;
419 xd_gendisk.part[minor].nr_sects = 0;
422 xd_gendisk.part[start].nr_sects = xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors;
423 resetup_one_dev(&xd_gendisk,target);
425 xd_valid[target] = 1;
426 wake_up(&xd_wait_open);
428 return 0;
431 /* xd_readwrite: handle a read/write request */
432 static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count)
434 u_char cmdblk[6],sense[4];
435 u_short track,cylinder;
436 u_char head,sector,control,mode = PIO_MODE,temp;
437 char **real_buffer;
438 register int i;
440 #ifdef DEBUG_READWRITE
441 printk("xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation == READ ? "read" : "write",drive,buffer,block,count);
442 #endif /* DEBUG_READWRITE */
444 control = xd_info[drive].control;
445 if (!xd_dma_buffer)
446 xd_dma_buffer = (char *)xd_dma_mem_alloc(xd_maxsectors * 0x200);
447 while (count) {
448 temp = count < xd_maxsectors ? count : xd_maxsectors;
450 track = block / xd_info[drive].sectors;
451 head = track % xd_info[drive].heads;
452 cylinder = track / xd_info[drive].heads;
453 sector = block % xd_info[drive].sectors;
455 #ifdef DEBUG_READWRITE
456 printk("xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive,head,cylinder,sector,temp);
457 #endif /* DEBUG_READWRITE */
459 if (xd_dma_buffer) {
460 mode = xd_setup_dma(operation == READ ? DMA_MODE_READ : DMA_MODE_WRITE,(u_char *)(xd_dma_buffer),temp * 0x200);
461 real_buffer = &xd_dma_buffer;
462 for (i=0; i < (temp * 0x200); i++)
463 xd_dma_buffer[i] = buffer[i];
465 else
466 real_buffer = &buffer;
468 xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
470 switch (xd_command(cmdblk,mode,(u_char *)(*real_buffer),(u_char *)(*real_buffer),sense,XD_TIMEOUT)) {
471 case 1:
472 printk("xd%c: %s timeout, recalibrating drive\n",'a'+drive,(operation == READ ? "read" : "write"));
473 xd_recalibrate(drive);
474 return (0);
475 case 2:
476 if (sense[0] & 0x30) {
477 printk("xd%c: %s - ",'a'+drive,(operation == READ ? "reading" : "writing"));
478 switch ((sense[0] & 0x30) >> 4) {
479 case 0: printk("drive error, code = 0x%X",sense[0] & 0x0F);
480 break;
481 case 1: printk("controller error, code = 0x%X",sense[0] & 0x0F);
482 break;
483 case 2: printk("command error, code = 0x%X",sense[0] & 0x0F);
484 break;
485 case 3: printk("miscellaneous error, code = 0x%X",sense[0] & 0x0F);
486 break;
489 if (sense[0] & 0x80)
490 printk(" - CHS = %d/%d/%d\n",((sense[2] & 0xC0) << 2) | sense[3],sense[1] & 0x1F,sense[2] & 0x3F);
491 /* reported drive number = (sense[1] & 0xE0) >> 5 */
492 else
493 printk(" - no valid disk address\n");
494 return (0);
496 if (xd_dma_buffer)
497 for (i=0; i < (temp * 0x200); i++)
498 buffer[i] = xd_dma_buffer[i];
500 count -= temp, buffer += temp * 0x200, block += temp;
502 return (1);
505 /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */
506 static void xd_recalibrate (u_char drive)
508 u_char cmdblk[6];
510 xd_build(cmdblk,CMD_RECALIBRATE,drive,0,0,0,0,0);
511 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8))
512 printk("xd%c: warning! error recalibrating, controller may be unstable\n", 'a'+drive);
515 /* xd_interrupt_handler: interrupt service routine */
516 static void xd_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs)
518 if (inb(XD_STATUS) & STAT_INTERRUPT) { /* check if it was our device */
519 #ifdef DEBUG_OTHER
520 printk("xd_interrupt_handler: interrupt detected\n");
521 #endif /* DEBUG_OTHER */
522 outb(0,XD_CONTROL); /* acknowledge interrupt */
523 wake_up(&xd_wait_int); /* and wake up sleeping processes */
525 else
526 printk("xd: unexpected interrupt\n");
529 /* xd_setup_dma: set up the DMA controller for a data transfer */
530 static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
532 unsigned long f;
534 if (nodma)
535 return (PIO_MODE);
536 if (((u_int) buffer & 0xFFFF0000) != (((u_int) buffer + count) & 0xFFFF0000)) {
537 #ifdef DEBUG_OTHER
538 printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");
539 #endif /* DEBUG_OTHER */
540 return (PIO_MODE);
543 f=claim_dma_lock();
544 disable_dma(xd_dma);
545 clear_dma_ff(xd_dma);
546 set_dma_mode(xd_dma,mode);
547 set_dma_addr(xd_dma,(u_int) buffer);
548 set_dma_count(xd_dma,count);
550 release_dma_lock(f);
552 return (DMA_MODE); /* use DMA and INT */
555 /* xd_build: put stuff into an array in a format suitable for the controller */
556 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)
558 cmdblk[0] = command;
559 cmdblk[1] = ((drive & 0x07) << 5) | (head & 0x1F);
560 cmdblk[2] = ((cylinder & 0x300) >> 2) | (sector & 0x3F);
561 cmdblk[3] = cylinder & 0xFF;
562 cmdblk[4] = count;
563 cmdblk[5] = control;
565 return (cmdblk);
568 /* xd_wakeup is called from timer interrupt */
569 static void xd_wakeup (void)
571 wake_up(&xdc_wait);
574 /* xd_wakeup is called from timer interrupt */
575 static void xd_watchdog (void)
577 xd_error = 1;
578 wake_up(&xd_wait_int);
581 /* xd_waitport: waits until port & mask == flags or a timeout occurs. return 1 for a timeout */
582 static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout)
584 u_long expiry = jiffies + timeout;
585 int success;
587 xdc_busy = 1;
588 while ((success = ((inb(port) & mask) != flags)) && time_before(jiffies, expiry)) {
589 xd_timer.expires = jiffies;
590 cli();
591 add_timer(&xd_timer);
592 sleep_on(&xdc_wait);
593 del_timer(&xd_timer);
594 sti();
596 xdc_busy = 0;
597 return (success);
600 static inline u_int xd_wait_for_IRQ (void)
602 unsigned long flags;
603 xd_watchdog_int.expires = jiffies + 8 * HZ;
604 add_timer(&xd_watchdog_int);
606 flags=claim_dma_lock();
607 enable_dma(xd_dma);
608 release_dma_lock(flags);
610 sleep_on(&xd_wait_int);
611 del_timer(&xd_watchdog_int);
612 xdc_busy = 0;
614 flags=claim_dma_lock();
615 disable_dma(xd_dma);
616 release_dma_lock(flags);
618 if (xd_error) {
619 printk("xd: missed IRQ - command aborted\n");
620 xd_error = 0;
621 return (1);
623 return (0);
626 /* xd_command: handle all data transfers necessary for a single command */
627 static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout)
629 u_char cmdblk[6],csb,complete = 0;
631 #ifdef DEBUG_COMMAND
632 printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);
633 #endif /* DEBUG_COMMAND */
635 outb(0,XD_SELECT);
636 outb(mode,XD_CONTROL);
638 if (xd_waitport(XD_STATUS,STAT_SELECT,STAT_SELECT,timeout))
639 return (1);
641 while (!complete) {
642 if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
643 return (1);
645 switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
646 case 0:
647 if (mode == DMA_MODE) {
648 if (xd_wait_for_IRQ())
649 return (1);
650 } else
651 outb(outdata ? *outdata++ : 0,XD_DATA);
652 break;
653 case STAT_INPUT:
654 if (mode == DMA_MODE) {
655 if (xd_wait_for_IRQ())
656 return (1);
657 } else
658 if (indata)
659 *indata++ = inb(XD_DATA);
660 else
661 inb(XD_DATA);
662 break;
663 case STAT_COMMAND:
664 outb(command ? *command++ : 0,XD_DATA);
665 break;
666 case STAT_COMMAND | STAT_INPUT:
667 complete = 1;
668 break;
671 csb = inb(XD_DATA);
673 if (xd_waitport(XD_STATUS,0,STAT_SELECT,timeout)) /* wait until deselected */
674 return (1);
676 if (csb & CSB_ERROR) { /* read sense data if error */
677 xd_build(cmdblk,CMD_SENSE,(csb & CSB_LUN) >> 5,0,0,0,0,0);
678 if (xd_command(cmdblk,0,sense,0,0,XD_TIMEOUT))
679 printk("xd: warning! sense command failed!\n");
682 #ifdef DEBUG_COMMAND
683 printk("xd_command: completed with csb = 0x%X\n",csb);
684 #endif /* DEBUG_COMMAND */
686 return (csb & CSB_ERROR);
689 __initfunc(static u_char xd_initdrives (void (*init_drive)(u_char drive)))
691 u_char cmdblk[6],i,count = 0;
693 for (i = 0; i < XD_MAXDRIVES; i++) {
694 xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
695 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8)) {
696 xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
697 add_timer(&xd_timer);
698 sleep_on(&xdc_wait);
700 init_drive(count);
701 count++;
703 xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
704 add_timer(&xd_timer);
705 sleep_on(&xdc_wait);
708 return (count);
711 __initfunc(static void xd_manual_geo_set (u_char drive))
713 xd_info[drive].heads = (u_char)(xd_geo[3 * drive + 1]);
714 xd_info[drive].cylinders = (u_short)(xd_geo[3 * drive]);
715 xd_info[drive].sectors = (u_char)(xd_geo[3 * drive + 2]);
718 __initfunc(static void xd_dtc_init_controller (unsigned int address))
720 switch (address) {
721 case 0x00000:
722 case 0xC8000: break; /*initial: 0x320 */
723 case 0xCA000: xd_iobase = 0x324;
724 case 0xD0000: /*5150CX*/
725 case 0xD8000: break; /*5150CX & 5150XL*/
726 default: printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address);
727 break;
729 xd_maxsectors = 0x01; /* my card seems to have trouble doing multi-block transfers? */
731 outb(0,XD_RESET); /* reset the controller */
735 __initfunc(static void xd_dtc5150cx_init_drive (u_char drive))
737 /* values from controller's BIOS - BIOS chip may be removed */
738 static u_short geometry_table[][4] = {
739 {0x200,8,0x200,0x100},
740 {0x267,2,0x267,0x267},
741 {0x264,4,0x264,0x80},
742 {0x132,4,0x132,0x0},
743 {0x132,2,0x80, 0x132},
744 {0x177,8,0x177,0x0},
745 {0x132,8,0x84, 0x0},
746 {}, /* not used */
747 {0x132,6,0x80, 0x100},
748 {0x200,6,0x100,0x100},
749 {0x264,2,0x264,0x80},
750 {0x280,4,0x280,0x100},
751 {0x2B9,3,0x2B9,0x2B9},
752 {0x2B9,5,0x2B9,0x2B9},
753 {0x280,6,0x280,0x100},
754 {0x132,4,0x132,0x0}};
755 u_char n;
757 n = inb(XD_JUMPER);
758 n = (drive ? n : (n >> 2)) & 0x33;
759 n = (n | (n >> 2)) & 0x0F;
760 if (xd_geo[3*drive])
761 xd_manual_geo_set(drive);
762 else
763 if (n != 7) {
764 xd_info[drive].heads = (u_char)(geometry_table[n][1]); /* heads */
765 xd_info[drive].cylinders = geometry_table[n][0]; /* cylinders */
766 xd_info[drive].sectors = 17; /* sectors */
767 #if 0
768 xd_info[drive].rwrite = geometry_table[n][2]; /* reduced write */
769 xd_info[drive].precomp = geometry_table[n][3] /* write precomp */
770 xd_info[drive].ecc = 0x0B; /* ecc length */
771 #endif /* 0 */
773 else {
774 printk("xd%c: undetermined drive geometry\n",'a'+drive);
775 return;
777 xd_info[drive].control = 5; /* control byte */
778 xd_setparam(CMD_DTCSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);
779 xd_recalibrate(drive);
782 __initfunc(static void xd_dtc_init_drive (u_char drive))
784 u_char cmdblk[6],buf[64];
786 xd_build(cmdblk,CMD_DTCGETGEOM,drive,0,0,0,0,0);
787 if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
788 xd_info[drive].heads = buf[0x0A]; /* heads */
789 xd_info[drive].cylinders = ((u_short *) (buf))[0x04]; /* cylinders */
790 xd_info[drive].sectors = 17; /* sectors */
791 if (xd_geo[3*drive])
792 xd_manual_geo_set(drive);
793 #if 0
794 xd_info[drive].rwrite = ((u_short *) (buf + 1))[0x05]; /* reduced write */
795 xd_info[drive].precomp = ((u_short *) (buf + 1))[0x06]; /* write precomp */
796 xd_info[drive].ecc = buf[0x0F]; /* ecc length */
797 #endif /* 0 */
798 xd_info[drive].control = 0; /* control byte */
800 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]);
801 xd_build(cmdblk,CMD_DTCSETSTEP,drive,0,0,0,0,7);
802 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
803 printk("xd_dtc_init_drive: error setting step rate for xd%c\n", 'a'+drive);
805 else
806 printk("xd_dtc_init_drive: error reading geometry for xd%c\n", 'a'+drive);
809 __initfunc(static void xd_wd_init_controller (unsigned int address))
811 switch (address) {
812 case 0x00000:
813 case 0xC8000: break; /*initial: 0x320 */
814 case 0xCA000: xd_iobase = 0x324; break;
815 case 0xCC000: xd_iobase = 0x328; break;
816 case 0xCE000: xd_iobase = 0x32C; break;
817 case 0xD0000: xd_iobase = 0x328; break; /* ? */
818 case 0xD8000: xd_iobase = 0x32C; break; /* ? */
819 default: printk("xd_wd_init_controller: unsupported BIOS address %06x\n",address);
820 break;
822 xd_maxsectors = 0x01; /* this one doesn't wrap properly either... */
824 outb(0,XD_RESET); /* reset the controller */
826 xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
827 add_timer(&xd_timer);
828 sleep_on(&xdc_wait);
831 __initfunc(static void xd_wd_init_drive (u_char drive))
833 /* values from controller's BIOS - BIOS may be disabled */
834 static u_short geometry_table[][4] = {
835 {0x264,4,0x1C2,0x1C2}, /* common part */
836 {0x132,4,0x099,0x0},
837 {0x267,2,0x1C2,0x1C2},
838 {0x267,4,0x1C2,0x1C2},
840 {0x334,6,0x335,0x335}, /* 1004 series RLL */
841 {0x30E,4,0x30F,0x3DC},
842 {0x30E,2,0x30F,0x30F},
843 {0x267,4,0x268,0x268},
845 {0x3D5,5,0x3D6,0x3D6}, /* 1002 series RLL */
846 {0x3DB,7,0x3DC,0x3DC},
847 {0x264,4,0x265,0x265},
848 {0x267,4,0x268,0x268}};
850 u_char cmdblk[6],buf[0x200];
851 u_char n = 0,rll,jumper_state,use_jumper_geo;
852 u_char wd_1002 = (xd_sigs[xd_type].string[7] == '6');
854 jumper_state = ~(inb(0x322));
855 if (jumper_state & 0x40)
856 xd_irq = 9;
857 rll = (jumper_state & 0x30) ? (0x04 << wd_1002) : 0;
858 xd_build(cmdblk,CMD_READ,drive,0,0,0,1,0);
859 if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
860 xd_info[drive].heads = buf[0x1AF]; /* heads */
861 xd_info[drive].cylinders = ((u_short *) (buf + 1))[0xD6]; /* cylinders */
862 xd_info[drive].sectors = 17; /* sectors */
863 if (xd_geo[3*drive])
864 xd_manual_geo_set(drive);
865 #if 0
866 xd_info[drive].rwrite = ((u_short *) (buf))[0xD8]; /* reduced write */
867 xd_info[drive].wprecomp = ((u_short *) (buf))[0xDA]; /* write precomp */
868 xd_info[drive].ecc = buf[0x1B4]; /* ecc length */
869 #endif /* 0 */
870 xd_info[drive].control = buf[0x1B5]; /* control byte */
871 use_jumper_geo = !(xd_info[drive].heads) || !(xd_info[drive].cylinders);
872 if (xd_geo[3*drive]) {
873 xd_manual_geo_set(drive);
874 xd_info[drive].control = rll ? 7 : 5;
876 else if (use_jumper_geo) {
877 n = (((jumper_state & 0x0F) >> (drive << 1)) & 0x03) | rll;
878 xd_info[drive].cylinders = geometry_table[n][0];
879 xd_info[drive].heads = (u_char)(geometry_table[n][1]);
880 xd_info[drive].control = rll ? 7 : 5;
881 #if 0
882 xd_info[drive].rwrite = geometry_table[n][2];
883 xd_info[drive].wprecomp = geometry_table[n][3];
884 xd_info[drive].ecc = 0x0B;
885 #endif /* 0 */
887 if (!wd_1002) {
888 if (use_jumper_geo)
889 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
890 geometry_table[n][2],geometry_table[n][3],0x0B);
891 else
892 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
893 ((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
895 /* 1002 based RLL controler requests converted addressing, but reports physical
896 (physical 26 sec., logical 17 sec.)
897 1004 based ???? */
898 if (rll & wd_1002) {
899 if ((xd_info[drive].cylinders *= 26,
900 xd_info[drive].cylinders /= 17) > 1023)
901 xd_info[drive].cylinders = 1023; /* 1024 ? */
902 #if 0
903 xd_info[drive].rwrite *= 26;
904 xd_info[drive].rwrite /= 17;
905 xd_info[drive].wprecomp *= 26
906 xd_info[drive].wprecomp /= 17;
907 #endif /* 0 */
910 else
911 printk("xd_wd_init_drive: error reading geometry for xd%c\n",'a'+drive);
915 __initfunc(static void xd_seagate_init_controller (unsigned int address))
917 switch (address) {
918 case 0x00000:
919 case 0xC8000: break; /*initial: 0x320 */
920 case 0xD0000: xd_iobase = 0x324; break;
921 case 0xD8000: xd_iobase = 0x328; break;
922 case 0xE0000: xd_iobase = 0x32C; break;
923 default: printk("xd_seagate_init_controller: unsupported BIOS address %06x\n",address);
924 break;
926 xd_maxsectors = 0x40;
928 outb(0,XD_RESET); /* reset the controller */
931 __initfunc(static void xd_seagate_init_drive (u_char drive))
933 u_char cmdblk[6],buf[0x200];
935 xd_build(cmdblk,CMD_ST11GETGEOM,drive,0,0,0,1,0);
936 if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
937 xd_info[drive].heads = buf[0x04]; /* heads */
938 xd_info[drive].cylinders = (buf[0x02] << 8) | buf[0x03]; /* cylinders */
939 xd_info[drive].sectors = buf[0x05]; /* sectors */
940 xd_info[drive].control = 0; /* control byte */
942 else
943 printk("xd_seagate_init_drive: error reading geometry from xd%c\n", 'a'+drive);
946 /* Omti support courtesy Dirk Melchers */
947 __initfunc(static void xd_omti_init_controller (unsigned int address))
949 switch (address) {
950 case 0x00000:
951 case 0xC8000: break; /*initial: 0x320 */
952 case 0xD0000: xd_iobase = 0x324; break;
953 case 0xD8000: xd_iobase = 0x328; break;
954 case 0xE0000: xd_iobase = 0x32C; break;
955 default: printk("xd_omti_init_controller: unsupported BIOS address %06x\n",address);
956 break;
959 xd_maxsectors = 0x40;
961 outb(0,XD_RESET); /* reset the controller */
964 __initfunc(static void xd_omti_init_drive (u_char drive))
966 /* gets infos from drive */
967 xd_override_init_drive(drive);
969 /* set other parameters, Hardcoded, not that nice :-) */
970 xd_info[drive].control = 2;
973 /* Xebec support (AK) */
974 __initfunc(static void xd_xebec_init_controller (unsigned int address))
976 /* iobase may be set manually in range 0x300 - 0x33C
977 irq may be set manually to 2(9),3,4,5,6,7
978 dma may be set manually to 1,2,3
979 (How to detect them ???)
980 BIOS address may be set manually in range 0x0 - 0xF8000
981 If you need non-standard settings use the xd=... command */
983 switch (address) {
984 case 0x00000:
985 case 0xC8000: /* initially: xd_iobase==0x320 */
986 case 0xD0000:
987 case 0xD2000:
988 case 0xD4000:
989 case 0xD6000:
990 case 0xD8000:
991 case 0xDA000:
992 case 0xDC000:
993 case 0xDE000:
994 case 0xE0000: break;
995 default: printk("xd_xebec_init_controller: unsupported BIOS address %06x\n",address);
996 break;
999 xd_maxsectors = 0x01;
1000 outb(0,XD_RESET); /* reset the controller */
1002 xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
1003 add_timer(&xd_timer);
1004 sleep_on(&xdc_wait);
1007 __initfunc(static void xd_xebec_init_drive (u_char drive))
1009 /* values from controller's BIOS - BIOS chip may be removed */
1010 static u_short geometry_table[][5] = {
1011 {0x132,4,0x080,0x080,0x7},
1012 {0x132,4,0x080,0x080,0x17},
1013 {0x264,2,0x100,0x100,0x7},
1014 {0x264,2,0x100,0x100,0x17},
1015 {0x132,8,0x080,0x080,0x7},
1016 {0x132,8,0x080,0x080,0x17},
1017 {0x264,4,0x100,0x100,0x6},
1018 {0x264,4,0x100,0x100,0x17},
1019 {0x2BC,5,0x2BC,0x12C,0x6},
1020 {0x3A5,4,0x3A5,0x3A5,0x7},
1021 {0x26C,6,0x26C,0x26C,0x7},
1022 {0x200,8,0x200,0x100,0x17},
1023 {0x400,5,0x400,0x400,0x7},
1024 {0x400,6,0x400,0x400,0x7},
1025 {0x264,8,0x264,0x200,0x17},
1026 {0x33E,7,0x33E,0x200,0x7}};
1027 u_char n;
1029 n = inb(XD_JUMPER) & 0x0F; /* BIOS's drive number: same geometry
1030 is assumed for BOTH drives */
1031 if (xd_geo[3*drive])
1032 xd_manual_geo_set(drive);
1033 else {
1034 xd_info[drive].heads = (u_char)(geometry_table[n][1]); /* heads */
1035 xd_info[drive].cylinders = geometry_table[n][0]; /* cylinders */
1036 xd_info[drive].sectors = 17; /* sectors */
1037 #if 0
1038 xd_info[drive].rwrite = geometry_table[n][2]; /* reduced write */
1039 xd_info[drive].precomp = geometry_table[n][3] /* write precomp */
1040 xd_info[drive].ecc = 0x0B; /* ecc length */
1041 #endif /* 0 */
1043 xd_info[drive].control = geometry_table[n][4]; /* control byte */
1044 xd_setparam(CMD_XBSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);
1045 xd_recalibrate(drive);
1048 /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
1049 etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
1050 __initfunc(static void xd_override_init_drive (u_char drive))
1052 u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };
1053 u_char cmdblk[6],i;
1055 if (xd_geo[3*drive])
1056 xd_manual_geo_set(drive);
1057 else {
1058 for (i = 0; i < 3; i++) {
1059 while (min[i] != max[i] - 1) {
1060 test[i] = (min[i] + max[i]) / 2;
1061 xd_build(cmdblk,CMD_SEEK,drive,(u_char) test[0],(u_short) test[1],(u_char) test[2],0,0);
1062 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
1063 min[i] = test[i];
1064 else
1065 max[i] = test[i];
1067 test[i] = min[i];
1069 xd_info[drive].heads = (u_char) min[0] + 1;
1070 xd_info[drive].cylinders = (u_short) min[1] + 1;
1071 xd_info[drive].sectors = (u_char) min[2] + 1;
1073 xd_info[drive].control = 0;
1076 /* xd_setup: initialise controler from command line parameters */
1077 __initfunc(void xd_setup (char *command,int *integers))
1079 switch (integers[0]) {
1080 case 4: if (integers[4] < 0)
1081 nodma = 1;
1082 else if (integers[4] < 8)
1083 xd_dma = integers[4];
1084 case 3: if ((integers[3] > 0) && (integers[3] <= 0x3FC))
1085 xd_iobase = integers[3];
1086 case 2: if ((integers[2] > 0) && (integers[2] < 16))
1087 xd_irq = integers[2];
1088 case 1: xd_override = 1;
1089 if ((integers[1] >= 0) && (integers[1] < (sizeof(xd_sigs) / sizeof(xd_sigs[0]))))
1090 xd_type = integers[1];
1091 case 0: break;
1092 default:printk("xd: too many parameters for xd\n");
1094 xd_maxsectors = 0x01;
1097 #ifndef MODULE
1098 /* xd_manual_geo_init: initialise drive geometry from command line parameters
1099 (used only for WD drives) */
1100 __initfunc(void xd_manual_geo_init (char *command,int *integers))
1102 int i;
1103 if (integers[0]%3 != 0) {
1104 printk("xd: incorrect number of parameters for xd_geo\n");
1105 return;
1107 for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++)
1108 xd_geo[i] = integers[i+1];
1110 #endif /* MODULE */
1112 /* xd_setparam: set the drive characteristics */
1113 __initfunc(static void xd_setparam (u_char command,u_char drive,u_char heads,u_short cylinders,u_short rwrite,u_short wprecomp,u_char ecc))
1115 u_char cmdblk[14];
1117 xd_build(cmdblk,command,drive,0,0,0,0,0);
1118 cmdblk[6] = (u_char) (cylinders >> 8) & 0x03;
1119 cmdblk[7] = (u_char) (cylinders & 0xFF);
1120 cmdblk[8] = heads & 0x1F;
1121 cmdblk[9] = (u_char) (rwrite >> 8) & 0x03;
1122 cmdblk[10] = (u_char) (rwrite & 0xFF);
1123 cmdblk[11] = (u_char) (wprecomp >> 8) & 0x03;
1124 cmdblk[12] = (u_char) (wprecomp & 0xFF);
1125 cmdblk[13] = ecc;
1127 /* Some controllers require geometry info as data, not command */
1129 if (xd_command(cmdblk,PIO_MODE,0,&cmdblk[6],0,XD_TIMEOUT * 2))
1130 printk("xd: error setting characteristics for xd%c\n", 'a'+drive);
1134 #ifdef MODULE
1135 static int xd[5] = { -1,-1,-1,-1, };
1137 MODULE_PARM(xd, "1-4i");
1138 MODULE_PARM(xd_geo, "3-6i");
1139 MODULE_PARM(nodma, "i");
1141 static void xd_done (void)
1143 struct gendisk ** gdp;
1145 blksize_size[MAJOR_NR] = NULL;
1146 blk_dev[MAJOR_NR].request_fn = NULL;
1147 blk_size[MAJOR_NR] = NULL;
1148 hardsect_size[MAJOR_NR] = NULL;
1149 read_ahead[MAJOR_NR] = 0;
1150 for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
1151 if (*gdp == &xd_gendisk)
1152 break;
1153 if (*gdp)
1154 *gdp = (*gdp)->next;
1155 release_region(xd_iobase,4);
1158 int init_module(void)
1160 int i,count = 0;
1161 int error = xd_init();
1162 if (!error)
1164 printk(KERN_INFO "XD: Loaded as a module.\n");
1165 for (i = 4; i > 0; i--)
1166 if(((xd[i] = xd[i-1]) >= 0) && !count)
1167 count = i;
1168 if((xd[0] = count))
1169 xd_setup(NULL, xd);
1170 xd_geninit(&(struct gendisk) { 0,0,0,0,0,0,0,0,0,0,0 });
1171 if (!xd_drives) {
1172 /* no drives detected - unload module */
1173 unregister_blkdev(MAJOR_NR, "xd");
1174 xd_done();
1175 return (-1);
1177 for (i = 0; i < xd_drives; i++)
1178 resetup_one_dev(&xd_gendisk, i);
1181 return error;
1184 void cleanup_module(void)
1186 int partition,dev,start;
1188 unregister_blkdev(MAJOR_NR, "xd");
1189 for (dev = 0; dev < xd_drives; dev++) {
1190 start = dev << xd_gendisk.minor_shift;
1191 for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
1192 int minor = (start | partition);
1193 kdev_t devp = MKDEV(MAJOR_NR, minor);
1194 start = dev << xd_gendisk.minor_shift;
1195 sync_dev(devp);
1196 invalidate_buffers(devp);
1199 xd_done();
1200 if (xd_drives) {
1201 free_irq(xd_irq, NULL);
1202 free_dma(xd_dma);
1203 if (xd_dma_buffer)
1204 xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
1207 #endif /* MODULE */