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