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