OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [block/] [xd.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.