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