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