Import 1.3.39
[davej-history.git] / drivers / block / xd.c
blobb0c08297683e9e530c71b45e814c61a59d9b1764
1 /*
2 * This file contains the driver for an XT hard disk controller
3 * (at least the DTC 5150X) for Linux.
5 * Author: Pat Mackinlay, pat@it.com.au
6 * Date: 29/09/92
7 *
8 * Revised: 01/01/93, ...
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.
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.
23 #include <linux/errno.h>
24 #include <linux/sched.h>
25 #include <linux/mm.h>
26 #include <linux/fs.h>
27 #include <linux/kernel.h>
28 #include <linux/genhd.h>
29 #include <linux/xd.h>
31 #include <asm/system.h>
32 #include <asm/io.h>
33 #include <asm/segment.h>
34 #include <asm/dma.h>
36 #define MAJOR_NR XT_DISK_MAJOR
37 #include <linux/blk.h>
39 XD_INFO xd_info[XD_MAXDRIVES];
41 /* If you try this driver and find that your card is not detected by the driver at bootup, you need to add your BIOS
42 signature and details to the following list of signatures. A BIOS signature is a string embedded into the first
43 few bytes of your controller's on-board ROM BIOS. To find out what yours is, use something like MS-DOS's DEBUG
44 command. Run DEBUG, and then you can examine your BIOS signature with:
46 d xxxx:0000
48 where xxxx is the segment of your controller (like C800 or D000 or something). On the ASCII dump at the right, you should
49 be able to see a string mentioning the manufacturer's copyright etc. Add this string into the table below. The parameters
50 in the table are, in order:
52 offset ; this is the offset (in bytes) from the start of your ROM where the signature starts
53 signature ; this is the actual text of the signature
54 xd_?_init_controller ; this is the controller init routine used by your controller
55 xd_?_init_drive ; this is the drive init routine used by your controller
57 The controllers directly supported at the moment are: DTC 5150x, WD 1004A27X, ST11M/R and override. If your controller is
58 made by the same manufacturer as one of these, try using the same init routines as they do. If that doesn't work, your
59 best bet is to use the "override" routines. These routines use a "portable" method of getting the disk's geometry, and
60 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>.
62 NOTE: You can now specify your XT controller's parameters from the command line in the form xd=TYPE,IRQ,IO,DMA. The driver
63 should be able to detect your drive's geometry from this info. (eg: xd=0,5,0x320,3 is the "standard"). */
65 static XD_SIGNATURE xd_sigs[] = {
66 { 0x0000,"Override geometry handler",NULL,xd_override_init_drive,"n unknown" }, /* Pat Mackinlay, pat@it.com.au */
67 { 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 */
68 { 0x0008,"07/15/86 (C) Copyright 1986 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1002AWX1" }, /* Ian Justman, citrus!ianj@csusac.ecs.csus.edu */
69 { 0x0008,"06/24/88 (C) Copyright 1988 Western Digital Corp",xd_wd_init_controller,xd_wd_init_drive," Western Digital 1004A27X" }, /* Dave Thaler, thalerd@engin.umich.edu */
70 { 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
71 { 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
72 { 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
73 { 0x0010,"ST11 BIOS V1.7",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11R" }, /* Alan Hourihane, alanh@fairlite.demon.co.uk */
74 { 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
76 static u_char *xd_bases[] =
78 (u_char *) 0xC8000,(u_char *) 0xCA000,(u_char *) 0xCC000,
79 (u_char *) 0xCE000,(u_char *) 0xD0000,(u_char *) 0xD8000,
80 (u_char *) 0xE0000
83 static struct hd_struct xd[XD_MAXDRIVES << 6];
84 static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES] = { 0, 0 };
85 static int xd_blocksizes[XD_MAXDRIVES << 6];
86 static struct gendisk xd_gendisk = {
87 MAJOR_NR, /* Major number */
88 "xd", /* Major name */
89 6, /* Bits to shift to get real from partition */
90 1 << 6, /* Number of partitions per real */
91 XD_MAXDRIVES, /* maximum number of real */
92 xd_geninit, /* init function */
93 xd, /* hd struct */
94 xd_sizes, /* block sizes */
95 0, /* number */
96 (void *) xd_info, /* internal */
97 NULL /* next */
99 static struct file_operations xd_fops = {
100 NULL, /* lseek - default */
101 block_read, /* read - general block-dev read */
102 block_write, /* write - general block-dev write */
103 NULL, /* readdir - bad */
104 NULL, /* select */
105 xd_ioctl, /* ioctl */
106 NULL, /* mmap */
107 xd_open, /* open */
108 xd_release, /* release */
109 block_fsync /* fsync */
111 static struct wait_queue *xd_wait_int = NULL, *xd_wait_open = NULL;
112 static u_char xd_valid[XD_MAXDRIVES] = { 0,0 };
113 static u_char xd_drives = 0, xd_irq = 0, xd_dma = 0, xd_maxsectors;
114 static u_char xd_override = 0, xd_type = 0;
115 static u_short xd_iobase = 0;
117 /* xd_init: register the block device number and set up pointer tables */
118 int xd_init (void)
120 if (register_blkdev(MAJOR_NR,"xd",&xd_fops)) {
121 printk("xd_init: unable to get major number %d\n",MAJOR_NR);
122 return -1;
124 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
125 read_ahead[MAJOR_NR] = 8; /* 8 sector (4kB) read ahead */
126 xd_gendisk.next = gendisk_head;
127 gendisk_head = &xd_gendisk;
129 return 0;
132 /* xd_detect: scan the possible BIOS ROM locations for the signature strings */
133 static u_char xd_detect (u_char *controller,u_char **address)
135 u_char i,j,found = 0;
137 if (xd_override)
139 *controller = xd_type;
140 *address = NULL;
141 return(1);
144 for (i = 0; i < (sizeof(xd_bases) / sizeof(xd_bases[0])) && !found; i++)
145 for (j = 1; j < (sizeof(xd_sigs) / sizeof(xd_sigs[0])) && !found; j++)
146 if (!memcmp(xd_bases[i] + xd_sigs[j].offset,xd_sigs[j].string,strlen(xd_sigs[j].string))) {
147 *controller = j;
148 *address = xd_bases[i];
149 found++;
151 return (found);
154 /* xd_geninit: grab the IRQ and DMA channel, initialise the drives */
155 /* and set up the "raw" device entries in the table */
156 static void xd_geninit (struct gendisk *ignored)
158 u_char i,controller,*address;
160 if (xd_detect(&controller,&address)) {
162 printk("xd_geninit: detected a%s controller (type %d) at address %p\n",xd_sigs[controller].name,controller,address);
163 if (controller)
164 xd_sigs[controller].init_controller(address);
165 xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
167 printk("xd_geninit: detected %d hard drive%s (using IRQ%d & DMA%d)\n",xd_drives,xd_drives == 1 ? "" : "s",xd_irq,xd_dma);
168 for (i = 0; i < xd_drives; i++)
169 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);
171 if (!request_irq(xd_irq,xd_interrupt_handler, 0, "XT harddisk")) {
172 if (request_dma(xd_dma,"xd")) {
173 printk("xd_geninit: unable to get DMA%d\n",xd_dma);
174 free_irq(xd_irq);
177 else
178 printk("xd_geninit: unable to get IRQ%d\n",xd_irq);
181 for (i = 0; i < xd_drives; i++) {
182 xd[i << 6].nr_sects = xd_info[i].heads * xd_info[i].cylinders * xd_info[i].sectors;
183 xd_valid[i] = 1;
186 xd_gendisk.nr_real = xd_drives;
188 for(i=0;i<(XD_MAXDRIVES << 6);i++) xd_blocksizes[i] = 1024;
189 blksize_size[MAJOR_NR] = xd_blocksizes;
192 /* xd_open: open a device */
193 static int xd_open (struct inode *inode,struct file *file)
195 int dev = DEVICE_NR(inode->i_rdev);
197 if (dev < xd_drives) {
198 while (!xd_valid[dev])
199 sleep_on(&xd_wait_open);
201 xd_access[dev]++;
203 return (0);
205 else
206 return (-ENODEV);
209 /* do_xd_request: handle an incoming request */
210 static void do_xd_request (void)
212 u_int block,count,retry;
213 int code;
215 sti();
216 while (code = 0, CURRENT) {
217 INIT_REQUEST; /* do some checking on the request structure */
219 if (CURRENT_DEV < xd_drives
220 && CURRENT->sector + CURRENT->nr_sectors
221 <= xd[MINOR(CURRENT->rq_dev)].nr_sects) {
222 block = CURRENT->sector + xd[MINOR(CURRENT->rq_dev)].start_sect;
223 count = CURRENT->nr_sectors;
225 switch (CURRENT->cmd) {
226 case READ:
227 case WRITE:
228 for (retry = 0; (retry < XD_RETRIES) && !code; retry++)
229 code = xd_readwrite(CURRENT->cmd,CURRENT_DEV,CURRENT->buffer,block,count);
230 break;
231 default:
232 printk("do_xd_request: unknown request\n"); break;
235 end_request(code); /* wrap up, 0 = fail, 1 = success */
239 /* xd_ioctl: handle device ioctl's */
240 static int xd_ioctl (struct inode *inode,struct file *file,u_int cmd,u_long arg)
242 XD_GEOMETRY *geometry = (XD_GEOMETRY *) arg;
243 int dev = DEVICE_NR(inode->i_rdev),err;
245 if (inode && (dev < xd_drives))
246 switch (cmd) {
247 case HDIO_GETGEO:
248 if (arg) {
249 if ((err = verify_area(VERIFY_WRITE,geometry,sizeof(*geometry))))
250 return (err);
251 put_user(xd_info[dev].heads, &geometry->heads);
252 put_user(xd_info[dev].sectors, &geometry->sectors);
253 put_user(xd_info[dev].cylinders, &geometry->cylinders);
254 put_user(xd[MINOR(inode->i_rdev)].start_sect,&geometry->start);
256 return (0);
258 break;
259 case BLKRASET:
260 if(!suser())
261 return -EACCES;
262 if(!(inode->i_rdev))
263 return -EINVAL;
264 if(arg > 0xff)
265 return -EINVAL;
266 read_ahead[MAJOR(inode->i_rdev)] = arg;
267 return 0;
268 case BLKGETSIZE:
269 if (arg) {
270 if ((err = verify_area(VERIFY_WRITE,(long *) arg,sizeof(long))))
271 return (err);
272 put_user(xd[MINOR(inode->i_rdev)].nr_sects,(long *) arg);
274 return (0);
276 break;
277 case BLKFLSBUF:
278 if(!suser()) return -EACCES;
279 if(!(inode->i_rdev))
280 return -EINVAL;
281 fsync_dev(inode->i_rdev);
282 invalidate_buffers(inode->i_rdev);
283 return 0;
285 case BLKRRPART:
286 return (xd_reread_partitions(inode->i_rdev));
287 RO_IOCTLS(inode->i_rdev,arg);
289 return (-EINVAL);
292 /* xd_release: release the device */
293 static void xd_release (struct inode *inode, struct file *file)
295 int dev = DEVICE_NR(inode->i_rdev);
297 if (dev < xd_drives) {
298 sync_dev(inode->i_rdev);
299 xd_access[dev]--;
303 /* xd_reread_partitions: rereads the partition table from a drive */
304 static int xd_reread_partitions(kdev_t dev)
306 int target = DEVICE_NR(dev);
307 int start = target << xd_gendisk.minor_shift;
308 int partition;
310 cli(); xd_valid[target] = (xd_access[target] != 1); sti();
311 if (xd_valid[target])
312 return (-EBUSY);
314 for (partition = xd_gendisk.max_p - 1; partition >= 0; partition--) {
315 int minor = (start | partition);
316 kdev_t devp = MKDEV(MAJOR_NR, minor);
317 sync_dev(devp);
318 invalidate_inodes(devp);
319 invalidate_buffers(devp);
320 xd_gendisk.part[minor].start_sect = 0;
321 xd_gendisk.part[minor].nr_sects = 0;
324 xd_gendisk.part[start].nr_sects = xd_info[target].heads * xd_info[target].cylinders * xd_info[target].sectors;
325 resetup_one_dev(&xd_gendisk,target);
327 xd_valid[target] = 1;
328 wake_up(&xd_wait_open);
330 return (0);
333 /* xd_readwrite: handle a read/write request */
334 static int xd_readwrite (u_char operation,u_char drive,char *buffer,u_int block,u_int count)
336 u_char cmdblk[6],sense[4];
337 u_short track,cylinder;
338 u_char head,sector,control,mode,temp;
340 #ifdef DEBUG_READWRITE
341 printk("xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation == READ ? "read" : "write",drive,buffer,block,count);
342 #endif /* DEBUG_READWRITE */
344 control = xd_info[drive].control;
345 while (count) {
346 temp = count < xd_maxsectors ? count : xd_maxsectors;
348 track = block / xd_info[drive].sectors;
349 head = track % xd_info[drive].heads;
350 cylinder = track / xd_info[drive].heads;
351 sector = block % xd_info[drive].sectors;
353 #ifdef DEBUG_READWRITE
354 printk("xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive,head,cylinder,sector,temp);
355 #endif /* DEBUG_READWRITE */
357 mode = xd_setup_dma(operation == READ ? DMA_MODE_READ : DMA_MODE_WRITE,(u_char *)buffer,temp * 0x200);
358 xd_build(cmdblk,operation == READ ? CMD_READ : CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
360 switch (xd_command(cmdblk,mode,(u_char *) buffer,(u_char *) buffer,sense,XD_TIMEOUT)) {
361 case 1:
362 printk("xd_readwrite: timeout, recalibrating drive\n");
363 xd_recalibrate(drive);
364 return (0);
365 case 2:
366 switch ((sense[0] & 0x30) >> 4) {
367 case 0: printk("xd_readwrite: drive error, code = 0x%X",sense[0] & 0x0F); break;
368 case 1: printk("xd_readwrite: controller error, code = 0x%X",sense[0] & 0x0F); break;
369 case 2: printk("xd_readwrite: command error, code = 0x%X",sense[0] & 0x0F); break;
370 case 3: printk("xd_readwrite: miscellaneous error, code = 0x%X",sense[0] & 0x0F); break;
372 if (sense[0] & 0x80)
373 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);
374 else
375 printk(" - no valid disk address\n");
376 return (0);
378 count -= temp, buffer += temp * 0x200, block += temp;
380 return (1);
383 /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */
384 static void xd_recalibrate (u_char drive)
386 u_char cmdblk[6];
388 xd_build(cmdblk,CMD_RECALIBRATE,drive,0,0,0,0,0);
389 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8))
390 printk("xd_recalibrate: warning! error recalibrating, controller may be unstable\n");
393 /* xd_interrupt_handler: interrupt service routine */
394 static void xd_interrupt_handler(int irq, struct pt_regs * regs)
396 if (inb(XD_STATUS) & STAT_INTERRUPT) { /* check if it was our device */
397 #ifdef DEBUG_OTHER
398 printk("xd_interrupt_handler: interrupt detected\n");
399 #endif /* DEBUG_OTHER */
400 outb(0,XD_CONTROL); /* acknowledge interrupt */
401 wake_up(&xd_wait_int); /* and wake up sleeping processes */
403 else
404 printk("xd_interrupt_handler: unexpected interrupt\n");
407 /* xd_dma: set up the DMA controller for a data transfer */
408 static u_char xd_setup_dma (u_char mode,u_char *buffer,u_int count)
410 if (buffer < ((u_char *) 0x1000000 - count)) { /* transfer to address < 16M? */
411 if (((u_int) buffer & 0xFFFF0000) != (((u_int) buffer + count) & 0xFFFF0000)) {
412 #ifdef DEBUG_OTHER
413 printk("xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");
414 #endif /* DEBUG_OTHER */
415 return (PIO_MODE);
417 disable_dma(xd_dma);
418 clear_dma_ff(xd_dma);
419 set_dma_mode(xd_dma,mode);
420 set_dma_addr(xd_dma,(u_int) buffer);
421 set_dma_count(xd_dma,count);
423 return (DMA_MODE); /* use DMA and INT */
425 #ifdef DEBUG_OTHER
426 printk("xd_setup_dma: using PIO, cannot DMA above 16 meg\n");
427 #endif /* DEBUG_OTHER */
428 return (PIO_MODE);
431 /* xd_build: put stuff into an array in a format suitable for the controller */
432 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)
434 cmdblk[0] = command;
435 cmdblk[1] = ((drive & 0x07) << 5) | (head & 0x1F);
436 cmdblk[2] = ((cylinder & 0x300) >> 2) | (sector & 0x3F);
437 cmdblk[3] = cylinder & 0xFF;
438 cmdblk[4] = count;
439 cmdblk[5] = control;
441 return (cmdblk);
444 /* xd_waitport: waits until port & mask == flags or a timeout occurs. return 1 for a timeout */
445 static inline u_char xd_waitport (u_short port,u_char flags,u_char mask,u_long timeout)
447 u_long expiry = jiffies + timeout;
449 while (((inb(port) & mask) != flags) && (jiffies < expiry))
452 return (jiffies >= expiry);
455 /* xd_command: handle all data transfers necessary for a single command */
456 static u_int xd_command (u_char *command,u_char mode,u_char *indata,u_char *outdata,u_char *sense,u_long timeout)
458 u_char cmdblk[6],csb,complete = 0;
460 #ifdef DEBUG_COMMAND
461 printk("xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);
462 #endif /* DEBUG_COMMAND */
464 outb(0,XD_SELECT);
465 outb(mode,XD_CONTROL);
467 if (xd_waitport(XD_STATUS,STAT_SELECT,STAT_SELECT,timeout))
468 return (1);
470 while (!complete) {
471 if (xd_waitport(XD_STATUS,STAT_READY,STAT_READY,timeout))
472 return (1);
473 switch (inb(XD_STATUS) & (STAT_COMMAND | STAT_INPUT)) {
474 case 0:
475 if (mode == DMA_MODE) {
476 enable_dma(xd_dma);
477 sleep_on(&xd_wait_int);
478 disable_dma(xd_dma);
479 } else
480 outb(outdata ? *outdata++ : 0,XD_DATA);
481 break;
482 case STAT_INPUT:
483 if (mode == DMA_MODE) {
484 enable_dma(xd_dma);
485 sleep_on(&xd_wait_int);
486 disable_dma(xd_dma);
487 } else
488 if (indata)
489 *indata++ = inb(XD_DATA);
490 else
491 inb(XD_DATA);
492 break;
493 case STAT_COMMAND:
494 outb(command ? *command++ : 0,XD_DATA);
495 break;
496 case STAT_COMMAND | STAT_INPUT:
497 complete = 1;
498 break;
501 csb = inb(XD_DATA);
503 if (xd_waitport(XD_STATUS,0,STAT_SELECT,timeout)) /* wait until deselected */
504 return (1);
506 if (csb & CSB_ERROR) { /* read sense data if error */
507 xd_build(cmdblk,CMD_SENSE,(csb & CSB_LUN) >> 5,0,0,0,0,0);
508 if (xd_command(cmdblk,0,sense,0,0,XD_TIMEOUT))
509 printk("xd_command: warning! sense command failed!\n");
512 #ifdef DEBUG_COMMAND
513 printk("xd_command: completed with csb = 0x%X\n",csb);
514 #endif /* DEBUG_COMMAND */
516 return (csb & CSB_ERROR);
519 static u_char xd_initdrives (void (*init_drive)(u_char drive))
521 u_char cmdblk[6],i,count = 0;
523 for (i = 0; i < XD_MAXDRIVES; i++) {
524 xd_build(cmdblk,CMD_TESTREADY,i,0,0,0,0,0);
525 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 8)) {
526 init_drive(count);
527 count++;
530 return (count);
533 static void xd_dtc_init_controller (u_char *address)
535 switch ((u_long) address) {
536 case 0xC8000: xd_iobase = 0x320; break;
537 case 0xCA000: xd_iobase = 0x324; break;
538 default: printk("xd_dtc_init_controller: unsupported BIOS address %p\n",address);
539 xd_iobase = 0x320; break;
541 xd_irq = 5; /* the IRQ _can_ be changed on this card, but requires a hardware mod */
542 xd_dma = 3;
543 xd_maxsectors = 0x01; /* my card seems to have trouble doing multi-block transfers? */
545 outb(0,XD_RESET); /* reset the controller */
548 static void xd_dtc_init_drive (u_char drive)
550 u_char cmdblk[6],buf[64];
552 xd_build(cmdblk,CMD_DTCGETGEOM,drive,0,0,0,0,0);
553 if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
554 xd_info[drive].heads = buf[0x0A]; /* heads */
555 xd_info[drive].cylinders = ((u_short *) (buf))[0x04]; /* cylinders */
556 xd_info[drive].sectors = 17; /* sectors */
557 #if 0
558 xd_info[drive].rwrite = ((u_short *) (buf + 1))[0x05]; /* reduced write */
559 xd_info[drive].precomp = ((u_short *) (buf + 1))[0x06]; /* write precomp */
560 xd_info[drive].ecc = buf[0x0F]; /* ecc length */
561 #endif /* 0 */
562 xd_info[drive].control = 0; /* control byte */
564 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]);
565 xd_build(cmdblk,CMD_DTCSETSTEP,drive,0,0,0,0,7);
566 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
567 printk("xd_dtc_init_drive: error setting step rate for drive %d\n",drive);
569 else
570 printk("xd_dtc_init_drive: error reading geometry for drive %d\n",drive);
573 static void xd_wd_init_controller (u_char *address)
575 switch ((u_long) address) {
576 case 0xC8000: xd_iobase = 0x320; break;
577 case 0xCA000: xd_iobase = 0x324; break;
578 case 0xCC000: xd_iobase = 0x328; break;
579 case 0xCE000: xd_iobase = 0x32C; break;
580 case 0xD0000: xd_iobase = 0x328; break;
581 case 0xD8000: xd_iobase = 0x32C; break;
582 default: printk("xd_wd_init_controller: unsupported BIOS address %p\n",address);
583 xd_iobase = 0x320; break;
585 xd_irq = 5; /* don't know how to auto-detect this yet */
586 xd_dma = 3;
587 xd_maxsectors = 0x01; /* this one doesn't wrap properly either... */
589 /* outb(0,XD_RESET); */ /* reset the controller */
592 static void xd_wd_init_drive (u_char drive)
594 u_char cmdblk[6],buf[0x200];
596 xd_build(cmdblk,CMD_READ,drive,0,0,0,1,0);
597 if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
598 xd_info[drive].heads = buf[0x1AF]; /* heads */
599 xd_info[drive].cylinders = ((u_short *) (buf + 1))[0xD6]; /* cylinders */
600 xd_info[drive].sectors = 17; /* sectors */
601 #if 0
602 xd_info[drive].rwrite = ((u_short *) (buf))[0xD8]; /* reduced write */
603 xd_info[drive].wprecomp = ((u_short *) (buf))[0xDA]; /* write precomp */
604 xd_info[drive].ecc = buf[0x1B4]; /* ecc length */
605 #endif /* 0 */
606 xd_info[drive].control = buf[0x1B5]; /* control byte */
608 xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
610 else
611 printk("xd_wd_init_drive: error reading geometry for drive %d\n",drive);
614 static void xd_seagate_init_controller (u_char *address)
616 switch ((u_long) address) {
617 case 0xC8000: xd_iobase = 0x320; break;
618 case 0xD0000: xd_iobase = 0x324; break;
619 case 0xD8000: xd_iobase = 0x328; break;
620 case 0xE0000: xd_iobase = 0x32C; break;
621 default: printk("xd_seagate_init_controller: unsupported BIOS address %p\n",address);
622 xd_iobase = 0x320; break;
624 xd_irq = 5; /* the IRQ and DMA channel are fixed on the Seagate controllers */
625 xd_dma = 3;
626 xd_maxsectors = 0x40;
628 outb(0,XD_RESET); /* reset the controller */
631 static void xd_seagate_init_drive (u_char drive)
633 u_char cmdblk[6],buf[0x200];
635 xd_build(cmdblk,CMD_ST11GETGEOM,drive,0,0,0,1,0);
636 if (!xd_command(cmdblk,PIO_MODE,buf,0,0,XD_TIMEOUT * 2)) {
637 xd_info[drive].heads = buf[0x04]; /* heads */
638 xd_info[drive].cylinders = (buf[0x02] << 8) | buf[0x03]; /* cylinders */
639 xd_info[drive].sectors = buf[0x05]; /* sectors */
640 xd_info[drive].control = 0; /* control byte */
642 else
643 printk("xd_seagate_init_drive: error reading geometry from drive %d\n",drive);
646 /* Omti support courtesy Dirk Melchers */
647 static void xd_omti_init_controller (u_char *address)
649 switch ((u_long) address) {
650 case 0xC8000: xd_iobase = 0x320; break;
651 case 0xD0000: xd_iobase = 0x324; break;
652 case 0xD8000: xd_iobase = 0x328; break;
653 case 0xE0000: xd_iobase = 0x32C; break;
654 default: printk("xd_omti_init_controller: unsupported BIOS address %p\n",address);
655 xd_iobase = 0x320; break;
658 xd_irq = 5; /* the IRQ and DMA channel are fixed on the Omti controllers */
659 xd_dma = 3;
660 xd_maxsectors = 0x40;
662 outb(0,XD_RESET); /* reset the controller */
665 static void xd_omti_init_drive (u_char drive)
667 /* gets infos from drive */
668 xd_override_init_drive(drive);
670 /* set other parameters, Hardcoded, not that nice :-) */
671 xd_info[drive].control = 2;
674 /* xd_override_init_drive: this finds disk geometry in a "binary search" style, narrowing in on the "correct" number of heads
675 etc. by trying values until it gets the highest successful value. Idea courtesy Salvador Abreu (spa@fct.unl.pt). */
676 static void xd_override_init_drive (u_char drive)
678 u_short min[] = { 0,0,0 },max[] = { 16,1024,64 },test[] = { 0,0,0 };
679 u_char cmdblk[6],i;
681 for (i = 0; i < 3; i++) {
682 while (min[i] != max[i] - 1) {
683 test[i] = (min[i] + max[i]) / 2;
684 xd_build(cmdblk,CMD_SEEK,drive,(u_char) test[0],(u_short) test[1],(u_char) test[2],0,0);
685 if (!xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
686 min[i] = test[i];
687 else
688 max[i] = test[i];
690 test[i] = min[i];
692 xd_info[drive].heads = (u_char) min[0] + 1;
693 xd_info[drive].cylinders = (u_short) min[1] + 1;
694 xd_info[drive].sectors = (u_char) min[2] + 1;
695 xd_info[drive].control = 0;
698 /* xd_setup: initialise from command line parameters */
699 void xd_setup (char *command,int *integers)
701 xd_override = 1;
703 xd_type = integers[1];
704 xd_irq = integers[2];
705 xd_iobase = integers[3];
706 xd_dma = integers[4];
708 xd_maxsectors = 0x01;
711 /* xd_setparam: set the drive characteristics */
712 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)
714 u_char cmdblk[14];
716 xd_build(cmdblk,command,drive,0,0,0,0,0);
717 cmdblk[6] = (u_char) (cylinders >> 8) & 0x03;
718 cmdblk[7] = (u_char) (cylinders & 0xFF);
719 cmdblk[8] = heads & 0x1F;
720 cmdblk[9] = (u_char) (rwrite >> 8) & 0x03;
721 cmdblk[10] = (u_char) (rwrite & 0xFF);
722 cmdblk[11] = (u_char) (wprecomp >> 8) & 0x03;
723 cmdblk[12] = (u_char) (wprecomp & 0xFF);
724 cmdblk[13] = ecc;
726 if (xd_command(cmdblk,PIO_MODE,0,0,0,XD_TIMEOUT * 2))
727 printk("xd_setparam: error setting characteristics for drive %d\n",drive);