Import 2.1.118
[davej-history.git] / drivers / block / xd.c
blobccbcc0a97a959363f08e00de771e96f6f1ba7fac
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>
53 #include "xd.h"
55 #define XD_DONT_USE_DMA 0 /* Initial value. may be overriden using
56 "nodma" module option */
57 #define XD_INIT_DISK_DELAY 3 /* 30 ms delay during disk initialization */
59 /* Above may need to be increased if a problem with the 2nd drive detection
60 (ST11M controller) or resetting a controler (WD) appears */
62 XD_INFO xd_info[XD_MAXDRIVES];
64 /* If you try this driver and find that your card is not detected by the driver at bootup, you need to add your BIOS
65 signature and details to the following list of signatures. A BIOS signature is a string embedded into the first
66 few bytes of your controller's on-board ROM BIOS. To find out what yours is, use something like MS-DOS's DEBUG
67 command. Run DEBUG, and then you can examine your BIOS signature with:
69 d xxxx:0000
71 where xxxx is the segment of your controller (like C800 or D000 or something). On the ASCII dump at the right, you should
72 be able to see a string mentioning the manufacturer's copyright etc. Add this string into the table below. The parameters
73 in the table are, in order:
75 offset ; this is the offset (in bytes) from the start of your ROM where the signature starts
76 signature ; this is the actual text of the signature
77 xd_?_init_controller ; this is the controller init routine used by your controller
78 xd_?_init_drive ; this is the drive init routine used by your controller
80 The controllers directly supported at the moment are: DTC 5150x, WD 1004A27X, ST11M/R and override. If your controller is
81 made by the same manufacturer as one of these, try using the same init routines as they do. If that doesn't work, your
82 best bet is to use the "override" routines. These routines use a "portable" method of getting the disk's geometry, and
83 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>.
85 NOTE: You can now specify your XT controller's parameters from the command line in the form xd=TYPE,IRQ,IO,DMA. The driver
86 should be able to detect your drive's geometry from this info. (eg: xd=0,5,0x320,3 is the "standard"). */
88 #include <asm/page.h>
89 /* coppied from floppy.c */
90 static inline int __get_order(unsigned long size)
92 int order;
94 size = (size-1) >> (PAGE_SHIFT-1);
95 order = -1;
96 do {
97 size >>= 1;
98 order++;
99 } while (size);
100 return order;
102 #define xd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,__get_order(size))
103 #define xd_dma_mem_free(addr, size) free_pages(addr, __get_order(size))
104 static char *xd_dma_buffer = 0;
106 static XD_SIGNATURE xd_sigs[] __initdata = {
107 { 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, pat@it.com.au */
108 { 0x0008,"[BXD06 (C) DTC 17-MAY-1985]",xd_dtc_init_controller,xd_dtc5150cx_init_drive," DTC 5150CX" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
109 { 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 */
110 { 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 */
111 { 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Dig. 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */
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. 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */
114 { 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 */
115 { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
116 { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
117 { 0x0010,"ST11 BIOS v1.7",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11R" }, /* Alan Hourihane, alanh@fairlite.demon.co.uk */
118 { 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
119 { 0x0006,"COPYRIGHT XEBEC (C) 1984",xd_xebec_init_controller,xd_xebec_init_drive," XEBEC" }, /* Andrzej Krzysztofowicz, ankry@mif.pg.gda.pl */
122 static unsigned int xd_bases[] __initdata =
124 0xC8000, 0xCA000, 0xCC000,
125 0xCE000, 0xD0000, 0xD2000,
126 0xD4000, 0xD6000, 0xD8000,
127 0xDA000, 0xDC000, 0xDE000,
128 0xE0000
131 static struct hd_struct xd_struct[XD_MAXDRIVES << 6];
132 static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES] = { 0, 0 };
133 static int xd_blocksizes[XD_MAXDRIVES << 6];
134 static struct gendisk xd_gendisk = {
135 MAJOR_NR, /* Major number */
136 "xd", /* Major name */
137 6, /* Bits to shift to get real from partition */
138 1 << 6, /* Number of partitions per real */
139 XD_MAXDRIVES, /* maximum number of real */
140 #ifdef MODULE
141 NULL, /* called from init_module */
142 #else
143 xd_geninit, /* init function */
144 #endif
145 xd_struct, /* hd struct */
146 xd_sizes, /* block sizes */
147 0, /* number */
148 (void *) xd_info, /* internal */
149 NULL /* next */
151 static struct file_operations xd_fops = {
152 NULL, /* lseek - default */
153 block_read, /* read - general block-dev read */
154 block_write, /* write - general block-dev write */
155 NULL, /* readdir - bad */
156 NULL, /* poll */
157 xd_ioctl, /* ioctl */
158 NULL, /* mmap */
159 xd_open, /* open */
160 NULL, /* flush */
161 xd_release, /* release */
162 block_fsync /* fsync */
164 static struct wait_queue *xd_wait_int = NULL, *xd_wait_open = NULL;
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 struct wait_queue *xdc_wait = NULL;
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 BLKRASET:
342 if(!capable(CAP_SYS_ADMIN)) return -EACCES;
343 if(arg > 0xff) return -EINVAL;
344 read_ahead[MAJOR(inode->i_rdev)] = arg;
345 return 0;
346 case BLKRAGET:
347 return put_user(read_ahead[MAJOR(inode->i_rdev)], (long*) arg);
348 case BLKGETSIZE:
349 if (!arg) return -EINVAL;
350 return put_user(xd_struct[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
351 case BLKFLSBUF: /* Return devices size */
352 if(!capable(CAP_SYS_ADMIN)) return -EACCES;
353 fsync_dev(inode->i_rdev);
354 invalidate_buffers(inode->i_rdev);
355 return 0;
356 case HDIO_SET_DMA:
357 if (!capable(CAP_SYS_ADMIN)) return -EACCES;
358 if (xdc_busy) return -EBUSY;
359 nodma = !arg;
360 if (nodma && xd_dma_buffer) {
361 xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
362 xd_dma_buffer = 0;
364 return 0;
365 case HDIO_GET_DMA:
366 return put_user(!nodma, (long *) arg);
367 case HDIO_GET_MULTCOUNT:
368 return put_user(xd_maxsectors, (long *) arg);
369 case BLKRRPART:
370 if (!capable(CAP_SYS_ADMIN))
371 return -EACCES;
372 return xd_reread_partitions(inode->i_rdev);
373 RO_IOCTLS(inode->i_rdev,arg);
374 default:
375 return -EINVAL;
379 /* xd_release: release the device */
380 static int xd_release (struct inode *inode, struct file *file)
382 int target;
384 target= DEVICE_NR(inode->i_rdev);
385 if (target < xd_drives) {
386 sync_dev(inode->i_rdev);
387 xd_access[target]--;
389 #ifdef MODULE
390 MOD_DEC_USE_COUNT;
391 #endif /* MODULE */
394 return 0;
397 /* xd_reread_partitions: rereads the partition table from a drive */
398 static int xd_reread_partitions(kdev_t dev)
400 int target;
401 int start;
402 int partition;
404 target = DEVICE_NR(dev);
405 start = target << xd_gendisk.minor_shift;
407 cli();
408 xd_valid[target] = (xd_access[target] != 1);
409 sti();
410 if (xd_valid[target])
411 return -EBUSY;
413 for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
414 int minor = (start | partition);
415 kdev_t devp = MKDEV(MAJOR_NR, minor);
416 struct super_block * sb = get_super(devp);
418 sync_dev(devp);
419 if (sb)
420 invalidate_inodes(sb);
421 invalidate_buffers(devp);
422 xd_gendisk.part[minor].start_sect = 0;
423 xd_gendisk.part[minor].nr_sects = 0;
426 xd_gendisk.part[start].nr_sects = xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors;
427 resetup_one_dev(&xd_gendisk,target);
429 xd_valid[target] = 1;
430 wake_up(&xd_wait_open);
432 return 0;
435 /* xd_readwrite: handle a read/write request */
436 static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count)
438 u_char cmdblk[6],sense[4];
439 u_short track,cylinder;
440 u_char head,sector,control,mode = PIO_MODE,temp;
441 char **real_buffer;
442 register int i;
444 #ifdef DEBUG_READWRITE
445 printk("xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation == READ ? "read" : "write",drive,buffer,block,count);
446 #endif /* DEBUG_READWRITE */
448 control = xd_info[drive].control;
449 if (!xd_dma_buffer)
450 xd_dma_buffer = (char *)xd_dma_mem_alloc(xd_maxsectors * 0x200);
451 while (count) {
452 temp = count < xd_maxsectors ? count : xd_maxsectors;
454 track = block / xd_info[drive].sectors;
455 head = track % xd_info[drive].heads;
456 cylinder = track / xd_info[drive].heads;
457 sector = block % xd_info[drive].sectors;
459 #ifdef DEBUG_READWRITE
460 printk("xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive,head,cylinder,sector,temp);
461 #endif /* DEBUG_READWRITE */
463 if (xd_dma_buffer) {
464 mode = xd_setup_dma(operation == READ ? DMA_MODE_READ : DMA_MODE_WRITE,(u_char *)(xd_dma_buffer),temp * 0x200);
465 real_buffer = &xd_dma_buffer;
466 for (i=0; i < (temp * 0x200); i++)
467 xd_dma_buffer[i] = buffer[i];
469 else
470 real_buffer = &buffer;
472 xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
474 switch (xd_command(cmdblk,mode,(u_char *)(*real_buffer),(u_char *)(*real_buffer),sense,XD_TIMEOUT)) {
475 case 1:
476 printk("xd%c: %s timeout, recalibrating drive\n",'a'+drive,(operation == READ ? "read" : "write"));
477 xd_recalibrate(drive);
478 return (0);
479 case 2:
480 if (sense[0] & 0x30) {
481 printk("xd%c: %s - ",'a'+drive,(operation == READ ? "reading" : "writing"));
482 switch ((sense[0] & 0x30) >> 4) {
483 case 0: printk("drive error, code = 0x%X",sense[0] & 0x0F);
484 break;
485 case 1: printk("controller error, code = 0x%X",sense[0] & 0x0F);
486 break;
487 case 2: printk("command error, code = 0x%X",sense[0] & 0x0F);
488 break;
489 case 3: printk("miscellaneous error, code = 0x%X",sense[0] & 0x0F);
490 break;
493 if (sense[0] & 0x80)
494 printk(" - CHS = %d/%d/%d\n",((sense[2] & 0xC0) << 2) | sense[3],sense[1] & 0x1F,sense[2] & 0x3F);
495 /* reported drive number = (sense[1] & 0xE0) >> 5 */
496 else
497 printk(" - no valid disk address\n");
498 return (0);
500 if (xd_dma_buffer)
501 for (i=0; i < (temp * 0x200); i++)
502 buffer[i] = xd_dma_buffer[i];
504 count -= temp, buffer += temp * 0x200, block += temp;
506 return (1);
509 /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */
510 static void xd_recalibrate (u_char drive)
512 u_char cmdblk[6];
514 xd_build(cmdblk,CMD_RECALIBRATE,drive,0,0,0,0,0);
515 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8))
516 printk("xd%c: warning! error recalibrating, controller may be unstable\n", 'a'+drive);
519 /* xd_interrupt_handler: interrupt service routine */
520 static void xd_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs)
522 if (inb(XD_STATUS) & STAT_INTERRUPT) { /* check if it was our device */
523 #ifdef DEBUG_OTHER
524 printk("xd_interrupt_handler: interrupt detected\n");
525 #endif /* DEBUG_OTHER */
526 outb(0,XD_CONTROL); /* acknowledge interrupt */
527 wake_up(&xd_wait_int); /* and wake up sleeping processes */
529 else
530 printk("xd: unexpected interrupt\n");
533 /* xd_setup_dma: set up the DMA controller for a data transfer */
534 static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
536 if (nodma)
537 return (PIO_MODE);
538 if (((u_int) buffer & 0xFFFF0000) != (((u_int) buffer + count) & 0xFFFF0000)) {
539 #ifdef DEBUG_OTHER
540 printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");
541 #endif /* DEBUG_OTHER */
542 return (PIO_MODE);
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 return (DMA_MODE); /* use DMA and INT */
553 /* xd_build: put stuff into an array in a format suitable for the controller */
554 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)
556 cmdblk[0] = command;
557 cmdblk[1] = ((drive & 0x07) << 5) | (head & 0x1F);
558 cmdblk[2] = ((cylinder & 0x300) >> 2) | (sector & 0x3F);
559 cmdblk[3] = cylinder & 0xFF;
560 cmdblk[4] = count;
561 cmdblk[5] = control;
563 return (cmdblk);
566 /* xd_wakeup is called from timer interrupt */
567 static void xd_wakeup (void)
569 wake_up(&xdc_wait);
572 /* xd_wakeup is called from timer interrupt */
573 static void xd_watchdog (void)
575 xd_error = 1;
576 wake_up(&xd_wait_int);
579 /* xd_waitport: waits until port & mask == flags or a timeout occurs. return 1 for a timeout */
580 static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout)
582 u_long expiry = jiffies + timeout;
583 int success;
585 xdc_busy = 1;
586 while ((success = ((inb(port) & mask) != flags)) && (jiffies < expiry)) {
587 xd_timer.expires = jiffies;
588 cli();
589 add_timer(&xd_timer);
590 sleep_on(&xdc_wait);
591 del_timer(&xd_timer);
592 sti();
594 xdc_busy = 0;
595 return (success);
598 static inline u_int xd_wait_for_IRQ (void)
600 xd_watchdog_int.expires = jiffies + 8 * HZ;
601 add_timer(&xd_watchdog_int);
602 enable_dma(xd_dma);
603 sleep_on(&xd_wait_int);
604 del_timer(&xd_watchdog_int);
605 xdc_busy = 0;
606 disable_dma(xd_dma);
607 if (xd_error) {
608 printk("xd: missed IRQ - command aborted\n");
609 xd_error = 0;
610 return (1);
612 return (0);
615 /* xd_command: handle all data transfers necessary for a single command */
616 static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout)
618 u_char cmdblk[6],csb,complete = 0;
620 #ifdef DEBUG_COMMAND
621 printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);
622 #endif /* DEBUG_COMMAND */
624 outb(0,XD_SELECT);
625 outb(mode,XD_CONTROL);
627 if (xd_waitport(XD_STATUS,STAT_SELECT,STAT_SELECT,timeout))
628 return (1);
630 while (!complete) {
631 if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
632 return (1);
634 switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
635 case 0:
636 if (mode == DMA_MODE) {
637 if (xd_wait_for_IRQ())
638 return (1);
639 } else
640 outb(outdata ? *outdata++ : 0,XD_DATA);
641 break;
642 case STAT_INPUT:
643 if (mode == DMA_MODE) {
644 if (xd_wait_for_IRQ())
645 return (1);
646 } else
647 if (indata)
648 *indata++ = inb(XD_DATA);
649 else
650 inb(XD_DATA);
651 break;
652 case STAT_COMMAND:
653 outb(command ? *command++ : 0,XD_DATA);
654 break;
655 case STAT_COMMAND | STAT_INPUT:
656 complete = 1;
657 break;
660 csb = inb(XD_DATA);
662 if (xd_waitport(XD_STATUS,0,STAT_SELECT,timeout)) /* wait until deselected */
663 return (1);
665 if (csb & CSB_ERROR) { /* read sense data if error */
666 xd_build(cmdblk,CMD_SENSE,(csb & CSB_LUN) >> 5,0,0,0,0,0);
667 if (xd_command(cmdblk,0,sense,0,0,XD_TIMEOUT))
668 printk("xd: warning! sense command failed!\n");
671 #ifdef DEBUG_COMMAND
672 printk("xd_command: completed with csb = 0x%X\n",csb);
673 #endif /* DEBUG_COMMAND */
675 return (csb & CSB_ERROR);
678 __initfunc(static u_char xd_initdrives (void (*init_drive)(u_char drive)))
680 u_char cmdblk[6],i,count = 0;
682 for (i = 0; i < XD_MAXDRIVES; i++) {
683 xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
684 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8)) {
685 xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
686 add_timer(&xd_timer);
687 sleep_on(&xdc_wait);
689 init_drive(count);
690 count++;
692 xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
693 add_timer(&xd_timer);
694 sleep_on(&xdc_wait);
697 return (count);
700 __initfunc(static void xd_manual_geo_set (u_char drive))
702 xd_info[drive].heads = (u_char)(xd_geo[3 * drive + 1]);
703 xd_info[drive].cylinders = (u_short)(xd_geo[3 * drive]);
704 xd_info[drive].sectors = (u_char)(xd_geo[3 * drive + 2]);
707 __initfunc(static void xd_dtc_init_controller (unsigned int address))
709 switch (address) {
710 case 0x00000:
711 case 0xC8000: break; /*initial: 0x320 */
712 case 0xCA000: xd_iobase = 0x324;
713 case 0xD0000: /*5150CX*/
714 case 0xD8000: break; /*5150CX & 5150XL*/
715 default: printk("xd_dtc_init_controller: unsupported BIOS address %06x\n",address);
716 break;
718 xd_maxsectors = 0x01; /* my card seems to have trouble doing multi-block transfers? */
720 outb(0,XD_RESET); /* reset the controller */
724 __initfunc(static void xd_dtc5150cx_init_drive (u_char drive))
726 /* values from controller's BIOS - BIOS chip may be removed */
727 static u_short geometry_table[][4] = {
728 {0x200,8,0x200,0x100},
729 {0x267,2,0x267,0x267},
730 {0x264,4,0x264,0x80},
731 {0x132,4,0x132,0x0},
732 {0x132,2,0x80, 0x132},
733 {0x177,8,0x177,0x0},
734 {0x132,8,0x84, 0x0},
735 {}, /* not used */
736 {0x132,6,0x80, 0x100},
737 {0x200,6,0x100,0x100},
738 {0x264,2,0x264,0x80},
739 {0x280,4,0x280,0x100},
740 {0x2B9,3,0x2B9,0x2B9},
741 {0x2B9,5,0x2B9,0x2B9},
742 {0x280,6,0x280,0x100},
743 {0x132,4,0x132,0x0}};
744 u_char n;
746 n = inb(XD_JUMPER);
747 n = (drive ? n : (n >> 2)) & 0x33;
748 n = (n | (n >> 2)) & 0x0F;
749 if (xd_geo[3*drive])
750 xd_manual_geo_set(drive);
751 else
752 if (n != 7) {
753 xd_info[drive].heads = (u_char)(geometry_table[n][1]); /* heads */
754 xd_info[drive].cylinders = geometry_table[n][0]; /* cylinders */
755 xd_info[drive].sectors = 17; /* sectors */
756 #if 0
757 xd_info[drive].rwrite = geometry_table[n][2]; /* reduced write */
758 xd_info[drive].precomp = geometry_table[n][3] /* write precomp */
759 xd_info[drive].ecc = 0x0B; /* ecc length */
760 #endif /* 0 */
762 else {
763 printk("xd%c: undetermined drive geometry\n",'a'+drive);
764 return;
766 xd_info[drive].control = 5; /* control byte */
767 xd_setparam(CMD_DTCSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);
768 xd_recalibrate(drive);
771 __initfunc(static void xd_dtc_init_drive (u_char drive))
773 u_char cmdblk[6],buf[64];
775 xd_build(cmdblk,CMD_DTCGETGEOM,drive,0,0,0,0,0);
776 if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
777 xd_info[drive].heads = buf[0x0A]; /* heads */
778 xd_info[drive].cylinders = ((u_short *) (buf))[0x04]; /* cylinders */
779 xd_info[drive].sectors = 17; /* sectors */
780 if (xd_geo[3*drive])
781 xd_manual_geo_set(drive);
782 #if 0
783 xd_info[drive].rwrite = ((u_short *) (buf + 1))[0x05]; /* reduced write */
784 xd_info[drive].precomp = ((u_short *) (buf + 1))[0x06]; /* write precomp */
785 xd_info[drive].ecc = buf[0x0F]; /* ecc length */
786 #endif /* 0 */
787 xd_info[drive].control = 0; /* control byte */
789 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]);
790 xd_build(cmdblk,CMD_DTCSETSTEP,drive,0,0,0,0,7);
791 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
792 printk("xd_dtc_init_drive: error setting step rate for xd%c\n", 'a'+drive);
794 else
795 printk("xd_dtc_init_drive: error reading geometry for xd%c\n", 'a'+drive);
798 __initfunc(static void xd_wd_init_controller (unsigned int address))
800 switch (address) {
801 case 0x00000:
802 case 0xC8000: break; /*initial: 0x320 */
803 case 0xCA000: xd_iobase = 0x324; break;
804 case 0xCC000: xd_iobase = 0x328; break;
805 case 0xCE000: xd_iobase = 0x32C; break;
806 case 0xD0000: xd_iobase = 0x328; break; /* ? */
807 case 0xD8000: xd_iobase = 0x32C; break; /* ? */
808 default: printk("xd_wd_init_controller: unsupported BIOS address %06x\n",address);
809 break;
811 xd_maxsectors = 0x01; /* this one doesn't wrap properly either... */
813 outb(0,XD_RESET); /* reset the controller */
815 xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
816 add_timer(&xd_timer);
817 sleep_on(&xdc_wait);
820 __initfunc(static void xd_wd_init_drive (u_char drive))
822 /* values from controller's BIOS - BIOS may be disabled */
823 static u_short geometry_table[][4] = {
824 {0x264,4,0x1C2,0x1C2}, /* common part */
825 {0x132,4,0x099,0x0},
826 {0x267,2,0x1C2,0x1C2},
827 {0x267,4,0x1C2,0x1C2},
829 {0x334,6,0x335,0x335}, /* 1004 series RLL */
830 {0x30E,4,0x30F,0x3DC},
831 {0x30E,2,0x30F,0x30F},
832 {0x267,4,0x268,0x268},
834 {0x3D5,5,0x3D6,0x3D6}, /* 1002 series RLL */
835 {0x3DB,7,0x3DC,0x3DC},
836 {0x264,4,0x265,0x265},
837 {0x267,4,0x268,0x268}};
839 u_char cmdblk[6],buf[0x200];
840 u_char n = 0,rll,jumper_state,use_jumper_geo;
841 u_char wd_1002 = (xd_sigs[xd_type].string[7] == '6');
843 jumper_state = ~(inb(0x322));
844 if (jumper_state & 0x40)
845 xd_irq = 9;
846 rll = (jumper_state & 0x30) ? (0x04 << wd_1002) : 0;
847 xd_build(cmdblk,CMD_READ,drive,0,0,0,1,0);
848 if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
849 xd_info[drive].heads = buf[0x1AF]; /* heads */
850 xd_info[drive].cylinders = ((u_short *) (buf + 1))[0xD6]; /* cylinders */
851 xd_info[drive].sectors = 17; /* sectors */
852 if (xd_geo[3*drive])
853 xd_manual_geo_set(drive);
854 #if 0
855 xd_info[drive].rwrite = ((u_short *) (buf))[0xD8]; /* reduced write */
856 xd_info[drive].wprecomp = ((u_short *) (buf))[0xDA]; /* write precomp */
857 xd_info[drive].ecc = buf[0x1B4]; /* ecc length */
858 #endif /* 0 */
859 xd_info[drive].control = buf[0x1B5]; /* control byte */
860 use_jumper_geo = !(xd_info[drive].heads) || !(xd_info[drive].cylinders);
861 if (xd_geo[3*drive]) {
862 xd_manual_geo_set(drive);
863 xd_info[drive].control = rll ? 7 : 5;
865 else if (use_jumper_geo) {
866 n = (((jumper_state & 0x0F) >> (drive << 1)) & 0x03) | rll;
867 xd_info[drive].cylinders = geometry_table[n][0];
868 xd_info[drive].heads = (u_char)(geometry_table[n][1]);
869 xd_info[drive].control = rll ? 7 : 5;
870 #if 0
871 xd_info[drive].rwrite = geometry_table[n][2];
872 xd_info[drive].wprecomp = geometry_table[n][3];
873 xd_info[drive].ecc = 0x0B;
874 #endif /* 0 */
876 if (!wd_1002) {
877 if (use_jumper_geo)
878 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
879 geometry_table[n][2],geometry_table[n][3],0x0B);
880 else
881 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
882 ((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
884 /* 1002 based RLL controler requests converted adressing, but reports physical
885 (physical 26 sec., logical 17 sec.)
886 1004 based ???? */
887 if (rll & wd_1002) {
888 if ((xd_info[drive].cylinders *= 26,
889 xd_info[drive].cylinders /= 17) > 1023)
890 xd_info[drive].cylinders = 1023; /* 1024 ? */
891 #if 0
892 xd_info[drive].rwrite *= 26;
893 xd_info[drive].rwrite /= 17;
894 xd_info[drive].wprecomp *= 26
895 xd_info[drive].wprecomp /= 17;
896 #endif /* 0 */
899 else
900 printk("xd_wd_init_drive: error reading geometry for xd%c\n",'a'+drive);
904 __initfunc(static void xd_seagate_init_controller (unsigned int address))
906 switch (address) {
907 case 0x00000:
908 case 0xC8000: break; /*initial: 0x320 */
909 case 0xD0000: xd_iobase = 0x324; break;
910 case 0xD8000: xd_iobase = 0x328; break;
911 case 0xE0000: xd_iobase = 0x32C; break;
912 default: printk("xd_seagate_init_controller: unsupported BIOS address %06x\n",address);
913 break;
915 xd_maxsectors = 0x40;
917 outb(0,XD_RESET); /* reset the controller */
920 __initfunc(static void xd_seagate_init_drive (u_char drive))
922 u_char cmdblk[6],buf[0x200];
924 xd_build(cmdblk,CMD_ST11GETGEOM,drive,0,0,0,1,0);
925 if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
926 xd_info[drive].heads = buf[0x04]; /* heads */
927 xd_info[drive].cylinders = (buf[0x02] << 8) | buf[0x03]; /* cylinders */
928 xd_info[drive].sectors = buf[0x05]; /* sectors */
929 xd_info[drive].control = 0; /* control byte */
931 else
932 printk("xd_seagate_init_drive: error reading geometry from xd%c\n", 'a'+drive);
935 /* Omti support courtesy Dirk Melchers */
936 __initfunc(static void xd_omti_init_controller (unsigned int address))
938 switch (address) {
939 case 0x00000:
940 case 0xC8000: break; /*initial: 0x320 */
941 case 0xD0000: xd_iobase = 0x324; break;
942 case 0xD8000: xd_iobase = 0x328; break;
943 case 0xE0000: xd_iobase = 0x32C; break;
944 default: printk("xd_omti_init_controller: unsupported BIOS address %06x\n",address);
945 break;
948 xd_maxsectors = 0x40;
950 outb(0,XD_RESET); /* reset the controller */
953 __initfunc(static void xd_omti_init_drive (u_char drive))
955 /* gets infos from drive */
956 xd_override_init_drive(drive);
958 /* set other parameters, Hardcoded, not that nice :-) */
959 xd_info[drive].control = 2;
962 /* Xebec support (AK) */
963 __initfunc(static void xd_xebec_init_controller (unsigned int address))
965 /* iobase may be set manually in range 0x300 - 0x33C
966 irq may be set manually to 2(9),3,4,5,6,7
967 dma may be set manually to 1,2,3
968 (How to detect them ???)
969 BIOS address may be set manually in range 0x0 - 0xF8000
970 If you need non-standard settings use the xd=... command */
972 switch (address) {
973 case 0x00000:
974 case 0xC8000: /* initially: xd_iobase==0x320 */
975 case 0xD0000:
976 case 0xD2000:
977 case 0xD4000:
978 case 0xD6000:
979 case 0xD8000:
980 case 0xDA000:
981 case 0xDC000:
982 case 0xDE000:
983 case 0xE0000: break;
984 default: printk("xd_xebec_init_controller: unsupported BIOS address %06x\n",address);
985 break;
988 xd_maxsectors = 0x01;
989 outb(0,XD_RESET); /* reset the controller */
991 xd_timer.expires = jiffies + XD_INIT_DISK_DELAY;
992 add_timer(&xd_timer);
993 sleep_on(&xdc_wait);
996 __initfunc(static void xd_xebec_init_drive (u_char drive))
998 /* values from controller's BIOS - BIOS chip may be removed */
999 static u_short geometry_table[][5] = {
1000 {0x132,4,0x080,0x080,0x7},
1001 {0x132,4,0x080,0x080,0x17},
1002 {0x264,2,0x100,0x100,0x7},
1003 {0x264,2,0x100,0x100,0x17},
1004 {0x132,8,0x080,0x080,0x7},
1005 {0x132,8,0x080,0x080,0x17},
1006 {0x264,4,0x100,0x100,0x6},
1007 {0x264,4,0x100,0x100,0x17},
1008 {0x2BC,5,0x2BC,0x12C,0x6},
1009 {0x3A5,4,0x3A5,0x3A5,0x7},
1010 {0x26C,6,0x26C,0x26C,0x7},
1011 {0x200,8,0x200,0x100,0x17},
1012 {0x400,5,0x400,0x400,0x7},
1013 {0x400,6,0x400,0x400,0x7},
1014 {0x264,8,0x264,0x200,0x17},
1015 {0x33E,7,0x33E,0x200,0x7}};
1016 u_char n;
1018 n = inb(XD_JUMPER) & 0x0F; /* BIOS's drive number: same geometry
1019 is assumed for BOTH drives */
1020 if (xd_geo[3*drive])
1021 xd_manual_geo_set(drive);
1022 else {
1023 xd_info[drive].heads = (u_char)(geometry_table[n][1]); /* heads */
1024 xd_info[drive].cylinders = geometry_table[n][0]; /* cylinders */
1025 xd_info[drive].sectors = 17; /* sectors */
1026 #if 0
1027 xd_info[drive].rwrite = geometry_table[n][2]; /* reduced write */
1028 xd_info[drive].precomp = geometry_table[n][3] /* write precomp */
1029 xd_info[drive].ecc = 0x0B; /* ecc length */
1030 #endif /* 0 */
1032 xd_info[drive].control = geometry_table[n][4]; /* control byte */
1033 xd_setparam(CMD_XBSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);
1034 xd_recalibrate(drive);
1037 /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
1038 etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
1039 __initfunc(static void xd_override_init_drive (u_char drive))
1041 u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };
1042 u_char cmdblk[6],i;
1044 if (xd_geo[3*drive])
1045 xd_manual_geo_set(drive);
1046 else {
1047 for (i = 0; i < 3; i++) {
1048 while (min[i] != max[i] - 1) {
1049 test[i] = (min[i] + max[i]) / 2;
1050 xd_build(cmdblk,CMD_SEEK,drive,(u_char) test[0],(u_short) test[1],(u_char) test[2],0,0);
1051 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
1052 min[i] = test[i];
1053 else
1054 max[i] = test[i];
1056 test[i] = min[i];
1058 xd_info[drive].heads = (u_char) min[0] + 1;
1059 xd_info[drive].cylinders = (u_short) min[1] + 1;
1060 xd_info[drive].sectors = (u_char) min[2] + 1;
1062 xd_info[drive].control = 0;
1065 /* xd_setup: initialise controler from command line parameters */
1066 __initfunc(void xd_setup (char *command,int *integers))
1068 switch (integers[0]) {
1069 case 4: if (integers[4] < 0)
1070 nodma = 1;
1071 else if (integers[4] < 8)
1072 xd_dma = integers[4];
1073 case 3: if ((integers[3] > 0) && (integers[3] <= 0x3FC))
1074 xd_iobase = integers[3];
1075 case 2: if ((integers[2] > 0) && (integers[2] < 16))
1076 xd_irq = integers[2];
1077 case 1: xd_override = 1;
1078 if ((integers[1] >= 0) && (integers[1] < (sizeof(xd_sigs) / sizeof(xd_sigs[0]))))
1079 xd_type = integers[1];
1080 case 0: break;
1081 default:printk("xd: too many parameters for xd\n");
1083 xd_maxsectors = 0x01;
1086 #ifndef MODULE
1087 /* xd_manual_geo_init: initialise drive geometry from command line parameters
1088 (used only for WD drives) */
1089 __initfunc(void xd_manual_geo_init (char *command,int *integers))
1091 int i;
1092 if (integers[0]%3 != 0) {
1093 printk("xd: incorrect number of parameters for xd_geo\n");
1094 return;
1096 for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++)
1097 xd_geo[i] = integers[i+1];
1099 #endif /* MODULE */
1101 /* xd_setparam: set the drive characteristics */
1102 __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))
1104 u_char cmdblk[14];
1106 xd_build(cmdblk,command,drive,0,0,0,0,0);
1107 cmdblk[6] = (u_char) (cylinders >> 8) & 0x03;
1108 cmdblk[7] = (u_char) (cylinders & 0xFF);
1109 cmdblk[8] = heads & 0x1F;
1110 cmdblk[9] = (u_char) (rwrite >> 8) & 0x03;
1111 cmdblk[10] = (u_char) (rwrite & 0xFF);
1112 cmdblk[11] = (u_char) (wprecomp >> 8) & 0x03;
1113 cmdblk[12] = (u_char) (wprecomp & 0xFF);
1114 cmdblk[13] = ecc;
1116 /* Some controllers require geometry info as data, not command */
1118 if (xd_command(cmdblk,PIO_MODE,0,&cmdblk[6],0,XD_TIMEOUT * 2))
1119 printk("xd: error setting characteristics for xd%c\n", 'a'+drive);
1123 #ifdef MODULE
1124 static int xd[5] = { -1,-1,-1,-1, };
1126 MODULE_PARM(xd, "1-4i");
1127 MODULE_PARM(xd_geo, "3-6i");
1128 MODULE_PARM(nodma, "i");
1130 static void xd_done (void)
1132 struct gendisk ** gdp;
1134 blksize_size[MAJOR_NR] = NULL;
1135 blk_dev[MAJOR_NR].request_fn = NULL;
1136 blk_size[MAJOR_NR] = NULL;
1137 hardsect_size[MAJOR_NR] = NULL;
1138 read_ahead[MAJOR_NR] = 0;
1139 for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
1140 if (*gdp == &xd_gendisk)
1141 break;
1142 if (*gdp)
1143 *gdp = (*gdp)->next;
1144 release_region(xd_iobase,4);
1147 int init_module(void)
1149 int i,count = 0;
1150 int error = xd_init();
1151 if (!error)
1153 printk(KERN_INFO "XD: Loaded as a module.\n");
1154 for (i = 4; i > 0; i--)
1155 if(((xd[i] = xd[i-1]) >= 0) && !count)
1156 count = i;
1157 if((xd[0] = count));
1158 xd_setup(NULL, xd);
1159 xd_geninit(&(struct gendisk) { 0,0,0,0,0,0,0,0,0,0,0 });
1160 if (!xd_drives) {
1161 /* no drives detected - unload module */
1162 unregister_blkdev(MAJOR_NR, "xd");
1163 xd_done();
1164 return (-1);
1166 for (i = 0; i < xd_drives; i++)
1167 resetup_one_dev(&xd_gendisk, i);
1170 return error;
1173 void cleanup_module(void)
1175 int partition,dev,start;
1177 unregister_blkdev(MAJOR_NR, "xd");
1178 for (dev = 0; dev < xd_drives; dev++) {
1179 start = dev << xd_gendisk.minor_shift;
1180 for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
1181 int minor = (start | partition);
1182 kdev_t devp = MKDEV(MAJOR_NR, minor);
1183 start = dev << xd_gendisk.minor_shift;
1184 sync_dev(devp);
1185 invalidate_buffers(devp);
1188 xd_done();
1189 if (xd_drives) {
1190 free_irq(xd_irq, NULL);
1191 free_dma(xd_dma);
1192 if (xd_dma_buffer)
1193 xd_dma_mem_free((unsigned long)xd_dma_buffer, xd_maxsectors * 0x200);
1196 #endif /* MODULE */