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