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