36 #include <linux/module.h>
37 #include <linux/errno.h>
41 #include <linux/kernel.h>
47 #include <linux/wait.h>
55 #include <asm/uaccess.h>
61 static void __init do_xd_setup (
int *integers);
63 static int xd[5] = { -1,-1,-1,-1, };
66 #define XD_DONT_USE_DMA 0
68 #define XD_INIT_DISK_DELAY (30)
100 #define xd_dma_mem_alloc(size) __get_dma_pages(GFP_KERNEL,get_order(size))
101 #define xd_dma_mem_free(addr, size) free_pages(addr, get_order(size))
102 static char *xd_dma_buffer;
105 { 0x0000,
"Override geometry handler",
NULL,xd_override_init_drive,
"n unknown" },
106 { 0x0008,
"[BXD06 (C) DTC 17-MAY-1985]",xd_dtc_init_controller,xd_dtc5150cx_init_drive,
" DTC 5150CX" },
107 { 0x000B,
"CRD18A Not an IBM rom. (C) Copyright Data Technology Corp. 05/31/88",xd_dtc_init_controller,xd_dtc_init_drive,
" DTC 5150X" },
108 { 0x000B,
"CXD23A Not an IBM ROM (C)Copyright Data Technology Corp 12/03/88",xd_dtc_init_controller,xd_dtc_init_drive,
" DTC 5150X" },
109 { 0x0008,
"07/15/86(C) Copyright 1986 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive,
" Western Dig. 1002-27X" },
110 { 0x0008,
"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive,
" Western Dig. WDXT-GEN2" },
111 { 0x0015,
"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive,
" Seagate ST11M/R" },
112 { 0x0010,
"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive,
" Seagate ST11M/R" },
113 { 0x0010,
"ST11 BIOS v1.7",xd_seagate_init_controller,xd_seagate_init_drive,
" Seagate ST11R" },
114 { 0x1000,
"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,
"n OMTI 5520" },
115 { 0x0006,
"COPYRIGHT XEBEC (C) 1984",xd_xebec_init_controller,xd_xebec_init_drive,
" XEBEC" },
116 { 0x0008,
"(C) Copyright 1984 Western Digital Corp", xd_wd_init_controller, xd_wd_init_drive,
" Western Dig. 1002s-wx2" },
117 { 0x0008,
"(C) Copyright 1986 Western Digital Corporation", xd_wd_init_controller, xd_wd_init_drive,
" 1986 Western Digital" },
122 0xC8000, 0xCA000, 0xCC000,
123 0xCE000, 0xD0000, 0xD2000,
124 0xD4000, 0xD6000, 0xD8000,
125 0xDA000, 0xDC000, 0xDE000,
131 static struct gendisk *xd_gendisk[2];
135 static const struct block_device_operations xd_fops = {
141 static u_char xd_drives, xd_irq = 5, xd_dma = 3, xd_maxsectors;
143 static u_short xd_iobase = 0x320;
146 static volatile int xdc_busy;
149 static volatile u_char xd_error;
155 static int __init xd_init(
void)
164 for (i = 4; i > 0; i--)
165 if (((xd[i] = xd[i-1]) >= 0) && !count)
172 init_timer (&xd_watchdog_int); xd_watchdog_int.function = xd_watchdog;
183 if (xd_detect(&controller,&address)) {
185 printk(
"Detected a%s controller (type %d) at address %06x\n",
186 xd_sigs[controller].
name,controller,address);
188 printk(
"xd: Ports at 0x%x are not available\n",
194 xd_drives = xd_initdrives(xd_sigs[controller].init_drive);
196 printk(
"Detected %d hard drive%s (using IRQ%d & DMA%d)\n",
197 xd_drives,xd_drives == 1 ?
"" :
"s",xd_irq,xd_dma);
205 if (!xd_dma_buffer && xd_maxsectors) {
207 if (!xd_dma_buffer) {
217 for (i = 0; i < xd_drives; i++) {
224 disk->first_minor = i<<6;
225 sprintf(disk->disk_name,
"xd%c", i+
'a');
226 disk->fops = &xd_fops;
227 disk->private_data =
p;
228 disk->queue = xd_queue;
230 printk(
" %s: CHS=%d/%d/%d\n", disk->disk_name,
232 xd_gendisk[
i] = disk;
236 if (
request_irq(xd_irq,xd_interrupt_handler, 0,
"XT hard disk",
NULL)) {
237 printk(
"xd: unable to get IRQ%d\n",xd_irq);
242 printk(
"xd: unable to get DMA%d\n",xd_dma);
249 for (i = 0; i < xd_drives; i++)
257 for (i = 0; i < xd_drives; i++)
265 xd_maxsectors * 0x200);
286 *controller = xd_type;
296 const char *
s = xd_sigs[
j].string;
300 *address = xd_bases[
i];
320 unsigned block = blk_rq_pos(req);
321 unsigned count = blk_rq_cur_sectors(req);
322 XD_INFO *disk = req->rq_disk->private_data;
326 if (req->cmd_type != REQ_TYPE_FS)
328 if (block + count > get_capacity(req->rq_disk))
330 for (retry = 0; (retry <
XD_RETRIES) && !res; retry++)
331 res = xd_readwrite(rq_data_dir(req), disk, req->buffer,
356 if (xdc_busy)
return -
EBUSY;
358 if (nodma && xd_dma_buffer) {
360 xd_maxsectors * 0x200);
361 xd_dma_buffer =
NULL;
362 }
else if (!nodma && !xd_dma_buffer) {
364 if (!xd_dma_buffer) {
371 return put_user(!nodma, (
long __user *) arg);
373 return put_user(xd_maxsectors, (
long __user *) arg);
380 unsigned int cmd,
unsigned long param)
385 ret = xd_locked_ioctl(bdev, mode, cmd, param);
401 #ifdef DEBUG_READWRITE
402 printk(
"xd_readwrite: operation = %s, drive = %d, buffer = 0x%X, block = %d, count = %d\n",operation ==
READ ?
"read" :
"write",drive,buffer,block,count);
405 spin_unlock_irq(&xd_lock);
411 temp = count < xd_maxsectors ? count : xd_maxsectors;
414 head = track % p->
heads;
415 cylinder = track / p->
heads;
418 #ifdef DEBUG_READWRITE
419 printk(
"xd_readwrite: drive = %d, head = %d, cylinder = %d, sector = %d, count = %d\n",drive,head,cylinder,sector,temp);
424 real_buffer = &xd_dma_buffer;
425 for (i=0; i < (temp * 0x200); i++)
426 xd_dma_buffer[i] = buffer[i];
431 xd_build(cmdblk,operation ==
READ ?
CMD_READ :
CMD_WRITE,drive,head,cylinder,sector,temp & 0xFF,control);
435 printk(
"xd%c: %s timeout, recalibrating drive\n",
'a'+drive,(operation ==
READ ?
"read" :
"write"));
436 xd_recalibrate(drive);
437 spin_lock_irq(&xd_lock);
440 if (sense[0] & 0x30) {
441 printk(
"xd%c: %s - ",
'a'+drive,(operation ==
READ ?
"reading" :
"writing"));
442 switch ((sense[0] & 0x30) >> 4) {
443 case 0:
printk(
"drive error, code = 0x%X",sense[0] & 0x0F);
445 case 1:
printk(
"controller error, code = 0x%X",sense[0] & 0x0F);
447 case 2:
printk(
"command error, code = 0x%X",sense[0] & 0x0F);
449 case 3:
printk(
"miscellaneous error, code = 0x%X",sense[0] & 0x0F);
454 printk(
" - CHS = %d/%d/%d\n",((sense[2] & 0xC0) << 2) | sense[3],sense[1] & 0x1F,sense[2] & 0x3F);
457 printk(
" - no valid disk address\n");
458 spin_lock_irq(&xd_lock);
462 for (i=0; i < (temp * 0x200); i++)
463 buffer[i] = xd_dma_buffer[i];
465 count -=
temp, buffer += temp * 0x200, block +=
temp;
467 spin_lock_irq(&xd_lock);
472 static void xd_recalibrate (
u_char drive)
478 printk(
"xd%c: warning! error recalibrating, controller may be unstable\n",
'a'+drive);
486 printk(
"xd_interrupt_handler: interrupt detected\n");
493 printk(
"xd: unexpected interrupt\n");
504 if (((
unsigned long) buffer & 0xFFFF0000) != (((
unsigned long) buffer + count) & 0xFFFF0000)) {
506 printk(
"xd_setup_dma: using PIO, transfer overlaps 64k boundary\n");
513 clear_dma_ff(xd_dma);
515 set_dma_addr(xd_dma, (
unsigned long) buffer);
527 cmdblk[1] = ((drive & 0x07) << 5) | (head & 0x1F);
528 cmdblk[2] = ((cylinder & 0x300) >> 2) | (sector & 0x3F);
529 cmdblk[3] = cylinder & 0xFF;
536 static void xd_watchdog (
unsigned long unused)
549 while ((success = ((
inb(port) & mask) != flags)) &&
time_before(jiffies, expiry))
555 static inline u_int xd_wait_for_IRQ (
void)
558 xd_watchdog_int.expires =
jiffies + 8 *
HZ;
574 printk(
"xd: missed IRQ - command aborted\n");
587 printk(
"xd_command: command = 0x%X, mode = 0x%X, indata = 0x%X, outdata = 0x%X, sense = 0x%X\n",command,mode,indata,outdata,sense);
603 if (xd_wait_for_IRQ())
610 if (xd_wait_for_IRQ())
634 printk(
"xd: warning! sense command failed!\n");
638 printk(
"xd_command: completed with csb = 0x%X\n",csb);
641 return (csb & CSB_ERROR);
664 xd_info[drive].
heads = (
u_char)(xd_geo[3 * drive + 1]);
669 static void __init xd_dtc_init_controller (
unsigned int address)
674 case 0xCA000: xd_iobase = 0x324;
677 default:
printk(
"xd_dtc_init_controller: unsupported BIOS address %06x\n",address);
680 xd_maxsectors = 0x01;
686 static void __init xd_dtc5150cx_init_drive (
u_char drive)
689 static u_short geometry_table[][4] = {
690 {0x200,8,0x200,0x100},
691 {0x267,2,0x267,0x267},
692 {0x264,4,0x264,0x80},
694 {0x132,2,0x80, 0x132},
698 {0x132,6,0x80, 0x100},
699 {0x200,6,0x100,0x100},
700 {0x264,2,0x264,0x80},
701 {0x280,4,0x280,0x100},
702 {0x2B9,3,0x2B9,0x2B9},
703 {0x2B9,5,0x2B9,0x2B9},
704 {0x280,6,0x280,0x100},
705 {0x132,4,0x132,0x0}};
709 n = (drive ? n : (n >> 2)) & 0x33;
710 n = (n | (n >> 2)) & 0x0F;
712 xd_manual_geo_set(drive);
715 xd_info[drive].
heads = (
u_char)(geometry_table[n][1]);
716 xd_info[drive].
cylinders = geometry_table[
n][0];
719 xd_info[drive].rwrite = geometry_table[
n][2];
720 xd_info[drive].precomp = geometry_table[
n][3]
721 xd_info[drive].ecc = 0x0B;
725 printk(
"xd%c: undetermined drive geometry\n",
'a'+drive);
730 xd_recalibrate(drive);
739 xd_info[drive].
heads = buf[0x0A];
743 xd_manual_geo_set(drive);
745 xd_info[drive].rwrite = ((
u_short *) (buf + 1))[0x05];
746 xd_info[drive].precomp = ((
u_short *) (buf + 1))[0x06];
747 xd_info[drive].ecc = buf[0x0F];
754 printk(
"xd_dtc_init_drive: error setting step rate for xd%c\n",
'a'+drive);
757 printk(
"xd_dtc_init_drive: error reading geometry for xd%c\n",
'a'+drive);
760 static void __init xd_wd_init_controller (
unsigned int address)
765 case 0xCA000: xd_iobase = 0x324;
break;
766 case 0xCC000: xd_iobase = 0x328;
break;
767 case 0xCE000: xd_iobase = 0x32C;
break;
768 case 0xD0000: xd_iobase = 0x328;
break;
769 case 0xD8000: xd_iobase = 0x32C;
break;
770 default:
printk(
"xd_wd_init_controller: unsupported BIOS address %06x\n",address);
773 xd_maxsectors = 0x01;
783 static u_short geometry_table[][4] = {
784 {0x264,4,0x1C2,0x1C2},
786 {0x267,2,0x1C2,0x1C2},
787 {0x267,4,0x1C2,0x1C2},
789 {0x334,6,0x335,0x335},
790 {0x30E,4,0x30F,0x3DC},
791 {0x30E,2,0x30F,0x30F},
792 {0x267,4,0x268,0x268},
794 {0x3D5,5,0x3D6,0x3D6},
795 {0x3DB,7,0x3DC,0x3DC},
796 {0x264,4,0x265,0x265},
797 {0x267,4,0x268,0x268}};
799 u_char cmdblk[6],buf[0x200];
800 u_char n = 0,rll,jumper_state,use_jumper_geo;
801 u_char wd_1002 = (xd_sigs[xd_type].string[7] ==
'6');
803 jumper_state = ~(
inb(0x322));
804 if (jumper_state & 0x40)
806 rll = (jumper_state & 0x30) ? (0x04 << wd_1002) : 0;
807 xd_build(cmdblk,
CMD_READ,drive,0,0,0,1,0);
809 xd_info[drive].
heads = buf[0x1AF];
813 xd_manual_geo_set(drive);
815 xd_info[drive].rwrite = ((
u_short *) (buf))[0xD8];
816 xd_info[drive].wprecomp = ((
u_short *) (buf))[0xDA];
817 xd_info[drive].ecc = buf[0x1B4];
819 xd_info[drive].
control = buf[0x1B5];
820 use_jumper_geo = !(xd_info[drive].
heads) || !(xd_info[drive].cylinders);
821 if (xd_geo[3*drive]) {
822 xd_manual_geo_set(drive);
823 xd_info[drive].
control = rll ? 7 : 5;
825 else if (use_jumper_geo) {
826 n = (((jumper_state & 0x0F) >> (drive << 1)) & 0x03) | rll;
827 xd_info[drive].
cylinders = geometry_table[
n][0];
828 xd_info[drive].
heads = (
u_char)(geometry_table[n][1]);
829 xd_info[drive].
control = rll ? 7 : 5;
831 xd_info[drive].rwrite = geometry_table[
n][2];
832 xd_info[drive].wprecomp = geometry_table[
n][3];
833 xd_info[drive].ecc = 0x0B;
838 xd_setparam(
CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
839 geometry_table[n][2],geometry_table[n][3],0x0B);
841 xd_setparam(
CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
848 if ((xd_info[drive].cylinders *= 26,
849 xd_info[drive].cylinders /= 17) > 1023)
852 xd_info[drive].rwrite *= 26;
853 xd_info[drive].rwrite /= 17;
854 xd_info[drive].wprecomp *= 26
855 xd_info[drive].wprecomp /= 17;
860 printk(
"xd_wd_init_drive: error reading geometry for xd%c\n",
'a'+drive);
864 static void __init xd_seagate_init_controller (
unsigned int address)
869 case 0xD0000: xd_iobase = 0x324;
break;
870 case 0xD8000: xd_iobase = 0x328;
break;
871 case 0xE0000: xd_iobase = 0x32C;
break;
872 default:
printk(
"xd_seagate_init_controller: unsupported BIOS address %06x\n",address);
875 xd_maxsectors = 0x40;
882 u_char cmdblk[6],buf[0x200];
886 xd_info[drive].
heads = buf[0x04];
887 xd_info[drive].
cylinders = (buf[0x02] << 8) | buf[0x03];
888 xd_info[drive].
sectors = buf[0x05];
892 printk(
"xd_seagate_init_drive: error reading geometry from xd%c\n",
'a'+drive);
896 static void __init xd_omti_init_controller (
unsigned int address)
901 case 0xD0000: xd_iobase = 0x324;
break;
902 case 0xD8000: xd_iobase = 0x328;
break;
903 case 0xE0000: xd_iobase = 0x32C;
break;
904 default:
printk(
"xd_omti_init_controller: unsupported BIOS address %06x\n",address);
908 xd_maxsectors = 0x40;
916 xd_override_init_drive(drive);
923 static void __init xd_xebec_init_controller (
unsigned int address)
944 default:
printk(
"xd_xebec_init_controller: unsupported BIOS address %06x\n",address);
948 xd_maxsectors = 0x01;
957 static u_short geometry_table[][5] = {
958 {0x132,4,0x080,0x080,0x7},
959 {0x132,4,0x080,0x080,0x17},
960 {0x264,2,0x100,0x100,0x7},
961 {0x264,2,0x100,0x100,0x17},
962 {0x132,8,0x080,0x080,0x7},
963 {0x132,8,0x080,0x080,0x17},
964 {0x264,4,0x100,0x100,0x6},
965 {0x264,4,0x100,0x100,0x17},
966 {0x2BC,5,0x2BC,0x12C,0x6},
967 {0x3A5,4,0x3A5,0x3A5,0x7},
968 {0x26C,6,0x26C,0x26C,0x7},
969 {0x200,8,0x200,0x100,0x17},
970 {0x400,5,0x400,0x400,0x7},
971 {0x400,6,0x400,0x400,0x7},
972 {0x264,8,0x264,0x200,0x17},
973 {0x33E,7,0x33E,0x200,0x7}};
979 xd_manual_geo_set(drive);
981 xd_info[drive].
heads = (
u_char)(geometry_table[n][1]);
982 xd_info[drive].
cylinders = geometry_table[
n][0];
985 xd_info[drive].rwrite = geometry_table[
n][2];
986 xd_info[drive].precomp = geometry_table[
n][3]
987 xd_info[drive].ecc = 0x0B;
990 xd_info[drive].
control = geometry_table[
n][4];
991 xd_setparam(
CMD_XBSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,geometry_table[n][2],geometry_table[n][3],0x0B);
992 xd_recalibrate(drive);
997 static void __init xd_override_init_drive (
u_char drive)
1002 if (xd_geo[3*drive])
1003 xd_manual_geo_set(drive);
1005 for (i = 0; i < 3; i++) {
1006 while (min[i] !=
max[i] - 1) {
1024 static void __init do_xd_setup (
int *integers)
1026 switch (integers[0]) {
1027 case 4:
if (integers[4] < 0)
1029 else if (integers[4] < 8)
1030 xd_dma = integers[4];
1031 case 3:
if ((integers[3] > 0) && (integers[3] <= 0x3FC))
1032 xd_iobase = integers[3];
1033 case 2:
if ((integers[2] > 0) && (integers[2] < 16))
1034 xd_irq = integers[2];
1035 case 1: xd_override = 1;
1036 if ((integers[1] >= 0) && (integers[1] <
ARRAY_SIZE(xd_sigs)))
1037 xd_type = integers[1];
1039 default:
printk(
"xd: too many parameters for xd\n");
1041 xd_maxsectors = 0x01;
1049 xd_build(cmdblk,command,drive,0,0,0,0,0);
1050 cmdblk[6] = (
u_char) (cylinders >> 8) & 0x03;
1051 cmdblk[7] = (
u_char) (cylinders & 0xFF);
1052 cmdblk[8] = heads & 0x1F;
1053 cmdblk[9] = (
u_char) (rwrite >> 8) & 0x03;
1054 cmdblk[10] = (
u_char) (rwrite & 0xFF);
1055 cmdblk[11] = (
u_char) (wprecomp >> 8) & 0x03;
1056 cmdblk[12] = (
u_char) (wprecomp & 0xFF);
1062 printk(
"xd: error setting characteristics for xd%c\n",
'a'+drive);
1078 for (i = 0; i < xd_drives; i++) {
1103 static int __init xd_manual_geo_init (
char *str)
1108 if (integers[0]%3 != 0) {
1109 printk(
"xd: incorrect number of parameters for xd_geo\n");
1112 for (i = 0; (i < integers[0]) && (i < 3*XD_MAXDRIVES); i++)
1113 xd_geo[i] = integers[i+1];
1118 __setup (
"xd_geo=", xd_manual_geo_init);