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

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [drivers/] [block/] [xd.c] - Blame information for rev 901

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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