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