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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269#include <linux/module.h>
270#include <linux/init.h>
271#include <linux/interrupt.h>
272#include <linux/blkdev.h>
273#include <linux/spinlock.h>
274#include <linux/errno.h>
275#include <linux/string.h>
276#include <linux/ioport.h>
277#include <linux/proc_fs.h>
278#include <linux/pci.h>
279#include <linux/stat.h>
280#include <linux/delay.h>
281#include <linux/io.h>
282#include <linux/slab.h>
283#include <scsi/scsicam.h>
284
285
286#include <scsi/scsi.h>
287#include <scsi/scsi_cmnd.h>
288#include <scsi/scsi_device.h>
289#include <scsi/scsi_host.h>
290#include <scsi/scsi_ioctl.h>
291#include "fdomain.h"
292
293#ifndef PCMCIA
294MODULE_AUTHOR("Rickard E. Faith");
295MODULE_DESCRIPTION("Future domain SCSI driver");
296MODULE_LICENSE("GPL");
297#endif
298
299
300#define VERSION "$Revision: 5.51 $"
301
302
303
304#define DEBUG 0
305#define ENABLE_PARITY 1
306#define FIFO_COUNT 2
307
308
309
310#if DEBUG
311#define EVERY_ACCESS 0
312#define ERRORS_ONLY 1
313#define DEBUG_DETECT 0
314#define DEBUG_MESSAGES 1
315#define DEBUG_ABORT 1
316#define DEBUG_RESET 1
317#define DEBUG_RACE 1
318#else
319#define EVERY_ACCESS 0
320#define ERRORS_ONLY 0
321#define DEBUG_DETECT 0
322#define DEBUG_MESSAGES 0
323#define DEBUG_ABORT 0
324#define DEBUG_RESET 0
325#define DEBUG_RACE 0
326#endif
327
328
329#if EVERY_ACCESS
330#undef ERRORS_ONLY
331#define ERRORS_ONLY 0
332#endif
333
334#if ENABLE_PARITY
335#define PARITY_MASK 0x08
336#else
337#define PARITY_MASK 0x00
338#endif
339
340enum chip_type {
341 unknown = 0x00,
342 tmc1800 = 0x01,
343 tmc18c50 = 0x02,
344 tmc18c30 = 0x03,
345};
346
347enum {
348 in_arbitration = 0x02,
349 in_selection = 0x04,
350 in_other = 0x08,
351 disconnect = 0x10,
352 aborted = 0x20,
353 sent_ident = 0x40,
354};
355
356enum in_port_type {
357 Read_SCSI_Data = 0,
358 SCSI_Status = 1,
359 TMC_Status = 2,
360 FIFO_Status = 3,
361 Interrupt_Cond = 4,
362 LSB_ID_Code = 5,
363 MSB_ID_Code = 6,
364 Read_Loopback = 7,
365 SCSI_Data_NoACK = 8,
366 Interrupt_Status = 9,
367 Configuration1 = 10,
368 Configuration2 = 11,
369 Read_FIFO = 12,
370 FIFO_Data_Count = 14
371};
372
373enum out_port_type {
374 Write_SCSI_Data = 0,
375 SCSI_Cntl = 1,
376 Interrupt_Cntl = 2,
377 SCSI_Mode_Cntl = 3,
378 TMC_Cntl = 4,
379 Memory_Cntl = 5,
380 Write_Loopback = 7,
381 IO_Control = 11,
382 Write_FIFO = 12
383};
384
385
386static int port_base;
387static unsigned long bios_base;
388static void __iomem * bios_mem;
389static int bios_major;
390static int bios_minor;
391static int PCI_bus;
392#ifdef CONFIG_PCI
393static struct pci_dev *PCI_dev;
394#endif
395static int Quantum;
396static int interrupt_level;
397static volatile int in_command;
398static struct scsi_cmnd *current_SC;
399static enum chip_type chip = unknown;
400static int adapter_mask;
401static int this_id;
402static int setup_called;
403
404#if DEBUG_RACE
405static volatile int in_interrupt_flag;
406#endif
407
408static int FIFO_Size = 0x2000;
409
410
411static irqreturn_t do_fdomain_16x0_intr( int irq, void *dev_id );
412
413
414static char * fdomain = NULL;
415module_param(fdomain, charp, 0);
416
417#ifndef PCMCIA
418
419static unsigned long addresses[] = {
420 0xc8000,
421 0xca000,
422 0xce000,
423 0xde000,
424 0xcc000,
425 0xd0000,
426 0xe0000,
427};
428#define ADDRESS_COUNT ARRAY_SIZE(addresses)
429
430static unsigned short ports[] = { 0x140, 0x150, 0x160, 0x170 };
431#define PORT_COUNT ARRAY_SIZE(ports)
432
433static unsigned short ints[] = { 3, 5, 10, 11, 12, 14, 15, 0 };
434
435#endif
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469#ifndef PCMCIA
470
471static struct signature {
472 const char *signature;
473 int sig_offset;
474 int sig_length;
475 int major_bios_version;
476 int minor_bios_version;
477 int flag;
478} signatures[] = {
479
480
481 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 5, 50, 2, 0, 0 },
482 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V1.07/28/89", 5, 50, 2, 0, 0 },
483 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.07/28/89", 72, 50, 2, 0, 2 },
484 { "FUTURE DOMAIN CORP. (C) 1986-1990 1800-V2.0", 73, 43, 2, 0, 3 },
485 { "FUTURE DOMAIN CORP. (C) 1991 1800-V2.0.", 72, 39, 2, 0, 4 },
486 { "FUTURE DOMAIN CORP. (C) 1992 V3.00.004/02/92", 5, 44, 3, 0, 0 },
487 { "FUTURE DOMAIN TMC-18XX (C) 1993 V3.203/12/93", 5, 44, 3, 2, 0 },
488 { "IBM F1 P2 BIOS v1.0104/29/93", 5, 28, 3, -1, 0 },
489 { "Future Domain Corp. V1.0008/18/93", 5, 33, 3, 4, 0 },
490 { "Future Domain Corp. V1.0008/18/93", 26, 33, 3, 4, 1 },
491 { "Adaptec AHA-2920 PCI-SCSI Card", 42, 31, 3, -1, 1 },
492 { "IBM F1 P264/32", 5, 14, 3, -1, 1 },
493
494 { "Future Domain Corp. V2.0108/18/93", 5, 33, 3, 5, 0 },
495 { "FUTURE DOMAIN CORP. V3.5008/18/93", 5, 34, 3, 5, 0 },
496 { "FUTURE DOMAIN 18c30/18c50/1800 (C) 1994 V3.5", 5, 44, 3, 5, 0 },
497 { "FUTURE DOMAIN CORP. V3.6008/18/93", 5, 34, 3, 6, 0 },
498 { "FUTURE DOMAIN CORP. V3.6108/18/93", 5, 34, 3, 6, 0 },
499 { "FUTURE DOMAIN TMC-18XX", 5, 22, -1, -1, 0 },
500
501
502
503
504
505
506
507
508
509
510
511
512};
513
514#define SIGNATURE_COUNT ARRAY_SIZE(signatures)
515
516#endif
517
518static void print_banner( struct Scsi_Host *shpnt )
519{
520 if (!shpnt) return;
521
522 if (bios_major < 0 && bios_minor < 0) {
523 printk(KERN_INFO "scsi%d: <fdomain> No BIOS; using scsi id %d\n",
524 shpnt->host_no, shpnt->this_id);
525 } else {
526 printk(KERN_INFO "scsi%d: <fdomain> BIOS version ", shpnt->host_no);
527
528 if (bios_major >= 0) printk("%d.", bios_major);
529 else printk("?.");
530
531 if (bios_minor >= 0) printk("%d", bios_minor);
532 else printk("?.");
533
534 printk( " at 0x%lx using scsi id %d\n",
535 bios_base, shpnt->this_id );
536 }
537
538
539
540
541
542 printk(KERN_INFO "scsi%d: <fdomain> %s chip at 0x%x irq ",
543 shpnt->host_no,
544 chip == tmc1800 ? "TMC-1800" : (chip == tmc18c50 ? "TMC-18C50" : (chip == tmc18c30 ? (PCI_bus ? "TMC-36C70 (PCI bus)" : "TMC-18C30") : "Unknown")),
545 port_base);
546
547 if (interrupt_level)
548 printk("%d", interrupt_level);
549 else
550 printk("<none>");
551
552 printk( "\n" );
553}
554
555int fdomain_setup(char *str)
556{
557 int ints[4];
558
559 (void)get_options(str, ARRAY_SIZE(ints), ints);
560
561 if (setup_called++ || ints[0] < 2 || ints[0] > 3) {
562 printk(KERN_INFO "scsi: <fdomain> Usage: fdomain=<PORT_BASE>,<IRQ>[,<ADAPTER_ID>]\n");
563 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
564 return 0;
565 }
566
567 port_base = ints[0] >= 1 ? ints[1] : 0;
568 interrupt_level = ints[0] >= 2 ? ints[2] : 0;
569 this_id = ints[0] >= 3 ? ints[3] : 0;
570
571 bios_major = bios_minor = -1;
572 ++setup_called;
573 return 1;
574}
575
576__setup("fdomain=", fdomain_setup);
577
578
579static void do_pause(unsigned amount)
580{
581 mdelay(10*amount);
582}
583
584static inline void fdomain_make_bus_idle( void )
585{
586 outb(0, port_base + SCSI_Cntl);
587 outb(0, port_base + SCSI_Mode_Cntl);
588 if (chip == tmc18c50 || chip == tmc18c30)
589 outb(0x21 | PARITY_MASK, port_base + TMC_Cntl);
590 else
591 outb(0x01 | PARITY_MASK, port_base + TMC_Cntl);
592}
593
594static int fdomain_is_valid_port( int port )
595{
596#if DEBUG_DETECT
597 printk( " (%x%x),",
598 inb( port + MSB_ID_Code ), inb( port + LSB_ID_Code ) );
599#endif
600
601
602
603
604
605
606
607 if (inb( port + LSB_ID_Code ) != 0xe9) {
608 if (inb( port + LSB_ID_Code ) != 0x27) return 0;
609 if (inb( port + MSB_ID_Code ) != 0x61) return 0;
610 chip = tmc1800;
611 } else {
612 if (inb( port + MSB_ID_Code ) != 0x60) return 0;
613 chip = tmc18c50;
614
615
616
617
618
619
620 outb( 0x80, port + IO_Control );
621 if ((inb( port + Configuration2 ) & 0x80) == 0x80) {
622 outb( 0x00, port + IO_Control );
623 if ((inb( port + Configuration2 ) & 0x80) == 0x00) {
624 chip = tmc18c30;
625 FIFO_Size = 0x800;
626 }
627 }
628
629 }
630
631 return 1;
632}
633
634static int fdomain_test_loopback( void )
635{
636 int i;
637 int result;
638
639 for (i = 0; i < 255; i++) {
640 outb( i, port_base + Write_Loopback );
641 result = inb( port_base + Read_Loopback );
642 if (i != result)
643 return 1;
644 }
645 return 0;
646}
647
648#ifndef PCMCIA
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664static int fdomain_get_irq( int base )
665{
666 int options = inb(base + Configuration1);
667
668#if DEBUG_DETECT
669 printk("scsi: <fdomain> Options = %x\n", options);
670#endif
671
672
673
674
675
676
677 if (chip != tmc18c30 && !PCI_bus && addresses[(options & 0xc0) >> 6 ] != bios_base)
678 return 0;
679 return ints[(options & 0x0e) >> 1];
680}
681
682static int fdomain_isa_detect( int *irq, int *iobase )
683{
684 int i, j;
685 int base = 0xdeadbeef;
686 int flag = 0;
687
688#if DEBUG_DETECT
689 printk( "scsi: <fdomain> fdomain_isa_detect:" );
690#endif
691
692 for (i = 0; i < ADDRESS_COUNT; i++) {
693 void __iomem *p = ioremap(addresses[i], 0x2000);
694 if (!p)
695 continue;
696#if DEBUG_DETECT
697 printk( " %lx(%lx),", addresses[i], bios_base );
698#endif
699 for (j = 0; j < SIGNATURE_COUNT; j++) {
700 if (check_signature(p + signatures[j].sig_offset,
701 signatures[j].signature,
702 signatures[j].sig_length )) {
703 bios_major = signatures[j].major_bios_version;
704 bios_minor = signatures[j].minor_bios_version;
705 PCI_bus = (signatures[j].flag == 1);
706 Quantum = (signatures[j].flag > 1) ? signatures[j].flag : 0;
707 bios_base = addresses[i];
708 bios_mem = p;
709 goto found;
710 }
711 }
712 iounmap(p);
713 }
714
715found:
716 if (bios_major == 2) {
717
718
719
720
721
722
723
724
725 switch (Quantum) {
726 case 2:
727 case 3:
728 base = readb(bios_mem + 0x1fa2) + (readb(bios_mem + 0x1fa3) << 8);
729 break;
730 case 4:
731 base = readb(bios_mem + 0x1fa3) + (readb(bios_mem + 0x1fa4) << 8);
732 break;
733 default:
734 base = readb(bios_mem + 0x1fcc) + (readb(bios_mem + 0x1fcd) << 8);
735 break;
736 }
737
738#if DEBUG_DETECT
739 printk( " %x,", base );
740#endif
741
742 for (i = 0; i < PORT_COUNT; i++) {
743 if (base == ports[i]) {
744 if (!request_region(base, 0x10, "fdomain"))
745 break;
746 if (!fdomain_is_valid_port(base)) {
747 release_region(base, 0x10);
748 break;
749 }
750 *irq = fdomain_get_irq( base );
751 *iobase = base;
752 return 1;
753 }
754 }
755
756
757
758
759
760#if DEBUG_DETECT
761 printk( " RAM FAILED, " );
762#endif
763 }
764
765
766
767
768
769
770
771
772
773
774 for (i = 0; i < PORT_COUNT; i++) {
775 base = ports[i];
776 if (!request_region(base, 0x10, "fdomain")) {
777#if DEBUG_DETECT
778 printk( " (%x inuse),", base );
779#endif
780 continue;
781 }
782#if DEBUG_DETECT
783 printk( " %x,", base );
784#endif
785 flag = fdomain_is_valid_port(base);
786 if (flag)
787 break;
788 release_region(base, 0x10);
789 }
790
791#if DEBUG_DETECT
792 if (flag) printk( " SUCCESS\n" );
793 else printk( " FAILURE\n" );
794#endif
795
796 if (!flag) return 0;
797
798 *irq = fdomain_get_irq( base );
799 *iobase = base;
800
801 return 1;
802}
803
804#else
805
806static int fdomain_isa_detect( int *irq, int *iobase )
807{
808 if (irq)
809 *irq = 0;
810 if (iobase)
811 *iobase = 0;
812 return 0;
813}
814
815#endif
816
817
818
819
820
821
822#ifdef CONFIG_PCI
823static int fdomain_pci_bios_detect( int *irq, int *iobase, struct pci_dev **ret_pdev )
824{
825 unsigned int pci_irq;
826 unsigned long pci_base;
827 struct pci_dev *pdev = NULL;
828
829#if DEBUG_DETECT
830
831
832
833 printk( "scsi: <fdomain> INFO: use lspci -v to see list of PCI devices\n" );
834 printk( "scsi: <fdomain> TMC-3260 detect:"
835 " Using Vendor ID: 0x%x and Device ID: 0x%x\n",
836 PCI_VENDOR_ID_FD,
837 PCI_DEVICE_ID_FD_36C70 );
838#endif
839
840 if ((pdev = pci_get_device(PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, pdev)) == NULL)
841 return 0;
842 if (pci_enable_device(pdev))
843 goto fail;
844
845#if DEBUG_DETECT
846 printk( "scsi: <fdomain> TMC-3260 detect:"
847 " PCI bus %u, device %u, function %u\n",
848 pdev->bus->number,
849 PCI_SLOT(pdev->devfn),
850 PCI_FUNC(pdev->devfn));
851#endif
852
853
854
855
856 pci_base = pci_resource_start(pdev, 0);
857 pci_irq = pdev->irq;
858
859 if (!request_region( pci_base, 0x10, "fdomain" ))
860 goto fail;
861
862
863
864
865 *irq = pci_irq;
866 *iobase = pci_base;
867 *ret_pdev = pdev;
868
869#if DEBUG_DETECT
870 printk( "scsi: <fdomain> TMC-3260 detect:"
871 " IRQ = %d, I/O base = 0x%x [0x%lx]\n", *irq, *iobase, pci_base );
872#endif
873
874 if (!fdomain_is_valid_port(pci_base)) {
875 printk(KERN_ERR "scsi: <fdomain> PCI card detected, but driver not loaded (invalid port)\n" );
876 release_region(pci_base, 0x10);
877 goto fail;
878 }
879
880
881 bios_major = bios_minor = -1;
882 PCI_bus = 1;
883 PCI_dev = pdev;
884 Quantum = 0;
885 bios_base = 0;
886
887 return 1;
888fail:
889 pci_dev_put(pdev);
890 return 0;
891}
892
893#endif
894
895struct Scsi_Host *__fdomain_16x0_detect(struct scsi_host_template *tpnt )
896{
897 int retcode;
898 struct Scsi_Host *shpnt;
899 struct pci_dev *pdev = NULL;
900
901 if (setup_called) {
902#if DEBUG_DETECT
903 printk( "scsi: <fdomain> No BIOS, using port_base = 0x%x, irq = %d\n",
904 port_base, interrupt_level );
905#endif
906 if (!request_region(port_base, 0x10, "fdomain")) {
907 printk( "scsi: <fdomain> port 0x%x is busy\n", port_base );
908 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
909 return NULL;
910 }
911 if (!fdomain_is_valid_port( port_base )) {
912 printk( "scsi: <fdomain> Cannot locate chip at port base 0x%x\n",
913 port_base );
914 printk( "scsi: <fdomain> Bad LILO/INSMOD parameters?\n" );
915 release_region(port_base, 0x10);
916 return NULL;
917 }
918 } else {
919 int flag = 0;
920
921#ifdef CONFIG_PCI
922
923 flag = fdomain_pci_bios_detect( &interrupt_level, &port_base, &pdev );
924#endif
925 if (!flag) {
926
927 flag = fdomain_isa_detect( &interrupt_level, &port_base );
928
929 if (!flag) {
930 printk( "scsi: <fdomain> Detection failed (no card)\n" );
931 return NULL;
932 }
933 }
934 }
935
936 fdomain_16x0_bus_reset(NULL);
937
938 if (fdomain_test_loopback()) {
939 printk(KERN_ERR "scsi: <fdomain> Detection failed (loopback test failed at port base 0x%x)\n", port_base);
940 if (setup_called) {
941 printk(KERN_ERR "scsi: <fdomain> Bad LILO/INSMOD parameters?\n");
942 }
943 goto fail;
944 }
945
946 if (this_id) {
947 tpnt->this_id = (this_id & 0x07);
948 adapter_mask = (1 << tpnt->this_id);
949 } else {
950 if (PCI_bus || (bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
951 tpnt->this_id = 7;
952 adapter_mask = 0x80;
953 } else {
954 tpnt->this_id = 6;
955 adapter_mask = 0x40;
956 }
957 }
958
959
960
961
962 shpnt = scsi_register( tpnt, 0 );
963 if(shpnt == NULL) {
964 release_region(port_base, 0x10);
965 return NULL;
966 }
967 shpnt->irq = interrupt_level;
968 shpnt->io_port = port_base;
969 shpnt->n_io_port = 0x10;
970 print_banner( shpnt );
971
972
973 if (!interrupt_level) {
974 printk(KERN_ERR "scsi: <fdomain> Card Detected, but driver not loaded (no IRQ)\n" );
975 goto fail;
976 } else {
977
978
979 retcode = request_irq( interrupt_level,
980 do_fdomain_16x0_intr, pdev?IRQF_SHARED:0, "fdomain", shpnt);
981
982 if (retcode < 0) {
983 if (retcode == -EINVAL) {
984 printk(KERN_ERR "scsi: <fdomain> IRQ %d is bad!\n", interrupt_level );
985 printk(KERN_ERR " This shouldn't happen!\n" );
986 printk(KERN_ERR " Send mail to faith@acm.org\n" );
987 } else if (retcode == -EBUSY) {
988 printk(KERN_ERR "scsi: <fdomain> IRQ %d is already in use!\n", interrupt_level );
989 printk(KERN_ERR " Please use another IRQ!\n" );
990 } else {
991 printk(KERN_ERR "scsi: <fdomain> Error getting IRQ %d\n", interrupt_level );
992 printk(KERN_ERR " This shouldn't happen!\n" );
993 printk(KERN_ERR " Send mail to faith@acm.org\n" );
994 }
995 printk(KERN_ERR "scsi: <fdomain> Detected, but driver not loaded (IRQ)\n" );
996 goto fail;
997 }
998 }
999 return shpnt;
1000fail:
1001 pci_dev_put(pdev);
1002 release_region(port_base, 0x10);
1003 return NULL;
1004}
1005
1006static int fdomain_16x0_detect(struct scsi_host_template *tpnt)
1007{
1008 if (fdomain)
1009 fdomain_setup(fdomain);
1010 return (__fdomain_16x0_detect(tpnt) != NULL);
1011}
1012
1013static const char *fdomain_16x0_info( struct Scsi_Host *ignore )
1014{
1015 static char buffer[128];
1016 char *pt;
1017
1018 strcpy( buffer, "Future Domain 16-bit SCSI Driver Version" );
1019 if (strchr( VERSION, ':')) {
1020 strcat( buffer, strchr( VERSION, ':' ) + 1 );
1021 pt = strrchr( buffer, '$') - 1;
1022 if (!pt)
1023 pt = buffer + strlen( buffer ) - 1;
1024 if (*pt != ' ')
1025 ++pt;
1026 *pt = '\0';
1027 } else {
1028 strcat( buffer, " " VERSION );
1029 }
1030
1031 return buffer;
1032}
1033
1034#if 0
1035static int fdomain_arbitrate( void )
1036{
1037 int status = 0;
1038 unsigned long timeout;
1039
1040#if EVERY_ACCESS
1041 printk( "fdomain_arbitrate()\n" );
1042#endif
1043
1044 outb(0x00, port_base + SCSI_Cntl);
1045 outb(adapter_mask, port_base + SCSI_Data_NoACK);
1046 outb(0x04 | PARITY_MASK, port_base + TMC_Cntl);
1047
1048 timeout = 500;
1049 do {
1050 status = inb(port_base + TMC_Status);
1051 if (status & 0x02)
1052 return 0;
1053 mdelay(1);
1054 } while (--timeout);
1055
1056
1057 fdomain_make_bus_idle();
1058
1059#if EVERY_ACCESS
1060 printk( "Arbitration failed, status = %x\n", status );
1061#endif
1062#if ERRORS_ONLY
1063 printk( "scsi: <fdomain> Arbitration failed, status = %x\n", status );
1064#endif
1065 return 1;
1066}
1067#endif
1068
1069static int fdomain_select( int target )
1070{
1071 int status;
1072 unsigned long timeout;
1073#if ERRORS_ONLY
1074 static int flag = 0;
1075#endif
1076
1077 outb(0x82, port_base + SCSI_Cntl);
1078 outb(adapter_mask | (1 << target), port_base + SCSI_Data_NoACK);
1079
1080
1081 outb(PARITY_MASK, port_base + TMC_Cntl);
1082
1083 timeout = 350;
1084
1085 do {
1086 status = inb(port_base + SCSI_Status);
1087 if (status & 1) {
1088
1089 outb(0x80, port_base + SCSI_Cntl);
1090 return 0;
1091 }
1092 mdelay(1);
1093 } while (--timeout);
1094
1095 fdomain_make_bus_idle();
1096#if EVERY_ACCESS
1097 if (!target) printk( "Selection failed\n" );
1098#endif
1099#if ERRORS_ONLY
1100 if (!target) {
1101 if (!flag)
1102 ++flag;
1103 else
1104 printk( "scsi: <fdomain> Selection failed\n" );
1105 }
1106#endif
1107 return 1;
1108}
1109
1110static void my_done(int error)
1111{
1112 if (in_command) {
1113 in_command = 0;
1114 outb(0x00, port_base + Interrupt_Cntl);
1115 fdomain_make_bus_idle();
1116 current_SC->result = error;
1117 if (current_SC->scsi_done)
1118 current_SC->scsi_done( current_SC );
1119 else panic( "scsi: <fdomain> current_SC->scsi_done() == NULL" );
1120 } else {
1121 panic( "scsi: <fdomain> my_done() called outside of command\n" );
1122 }
1123#if DEBUG_RACE
1124 in_interrupt_flag = 0;
1125#endif
1126}
1127
1128static irqreturn_t do_fdomain_16x0_intr(int irq, void *dev_id)
1129{
1130 unsigned long flags;
1131 int status;
1132 int done = 0;
1133 unsigned data_count;
1134
1135
1136
1137
1138
1139
1140
1141
1142 if ((inb(port_base + TMC_Status) & 0x01) == 0)
1143 return IRQ_NONE;
1144
1145
1146 outb(0x00, port_base + Interrupt_Cntl);
1147
1148
1149 if (!in_command || !current_SC) {
1150#if EVERY_ACCESS
1151 printk( "Spurious interrupt, in_command = %d, current_SC = %x\n",
1152 in_command, current_SC );
1153#endif
1154 return IRQ_NONE;
1155 }
1156
1157
1158 if (current_SC->SCp.phase & aborted) {
1159#if DEBUG_ABORT
1160 printk( "scsi: <fdomain> Interrupt after abort, ignoring\n" );
1161#endif
1162
1163
1164 }
1165
1166#if DEBUG_RACE
1167 ++in_interrupt_flag;
1168#endif
1169
1170 if (current_SC->SCp.phase & in_arbitration) {
1171 status = inb(port_base + TMC_Status);
1172 if (!(status & 0x02)) {
1173#if EVERY_ACCESS
1174 printk( " AFAIL " );
1175#endif
1176 spin_lock_irqsave(current_SC->device->host->host_lock, flags);
1177 my_done( DID_BUS_BUSY << 16 );
1178 spin_unlock_irqrestore(current_SC->device->host->host_lock, flags);
1179 return IRQ_HANDLED;
1180 }
1181 current_SC->SCp.phase = in_selection;
1182
1183 outb(0x40 | FIFO_COUNT, port_base + Interrupt_Cntl);
1184
1185 outb(0x82, port_base + SCSI_Cntl);
1186 outb(adapter_mask | (1 << scmd_id(current_SC)), port_base + SCSI_Data_NoACK);
1187
1188
1189 outb(0x10 | PARITY_MASK, port_base + TMC_Cntl);
1190#if DEBUG_RACE
1191 in_interrupt_flag = 0;
1192#endif
1193 return IRQ_HANDLED;
1194 } else if (current_SC->SCp.phase & in_selection) {
1195 status = inb(port_base + SCSI_Status);
1196 if (!(status & 0x01)) {
1197
1198 if (fdomain_select( scmd_id(current_SC) )) {
1199#if EVERY_ACCESS
1200 printk( " SFAIL " );
1201#endif
1202 spin_lock_irqsave(current_SC->device->host->host_lock, flags);
1203 my_done( DID_NO_CONNECT << 16 );
1204 spin_unlock_irqrestore(current_SC->device->host->host_lock, flags);
1205 return IRQ_HANDLED;
1206 } else {
1207#if EVERY_ACCESS
1208 printk( " AltSel " );
1209#endif
1210
1211 outb(0x10 | PARITY_MASK, port_base + TMC_Cntl);
1212 }
1213 }
1214 current_SC->SCp.phase = in_other;
1215 outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl);
1216 outb(0x80, port_base + SCSI_Cntl);
1217#if DEBUG_RACE
1218 in_interrupt_flag = 0;
1219#endif
1220 return IRQ_HANDLED;
1221 }
1222
1223
1224
1225 status = inb(port_base + SCSI_Status);
1226
1227 if (status & 0x10) {
1228
1229 switch (status & 0x0e) {
1230
1231 case 0x08:
1232 outb(current_SC->cmnd[current_SC->SCp.sent_command++],
1233 port_base + Write_SCSI_Data);
1234#if EVERY_ACCESS
1235 printk( "CMD = %x,",
1236 current_SC->cmnd[ current_SC->SCp.sent_command - 1] );
1237#endif
1238 break;
1239 case 0x00:
1240 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
1241 current_SC->SCp.have_data_in = -1;
1242 outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl);
1243 }
1244 break;
1245 case 0x04:
1246 if (chip != tmc1800 && !current_SC->SCp.have_data_in) {
1247 current_SC->SCp.have_data_in = 1;
1248 outb(0x90 | PARITY_MASK, port_base + TMC_Cntl);
1249 }
1250 break;
1251 case 0x0c:
1252 current_SC->SCp.Status = inb(port_base + Read_SCSI_Data);
1253#if EVERY_ACCESS
1254 printk( "Status = %x, ", current_SC->SCp.Status );
1255#endif
1256#if ERRORS_ONLY
1257 if (current_SC->SCp.Status
1258 && current_SC->SCp.Status != 2
1259 && current_SC->SCp.Status != 8) {
1260 printk( "scsi: <fdomain> target = %d, command = %x, status = %x\n",
1261 current_SC->device->id,
1262 current_SC->cmnd[0],
1263 current_SC->SCp.Status );
1264 }
1265#endif
1266 break;
1267 case 0x0a:
1268 outb(MESSAGE_REJECT, port_base + Write_SCSI_Data);
1269 break;
1270 case 0x0e:
1271 current_SC->SCp.Message = inb(port_base + Read_SCSI_Data);
1272#if EVERY_ACCESS
1273 printk( "Message = %x, ", current_SC->SCp.Message );
1274#endif
1275 if (!current_SC->SCp.Message) ++done;
1276#if DEBUG_MESSAGES || EVERY_ACCESS
1277 if (current_SC->SCp.Message) {
1278 printk( "scsi: <fdomain> message = %x\n",
1279 current_SC->SCp.Message );
1280 }
1281#endif
1282 break;
1283 }
1284 }
1285
1286 if (chip == tmc1800 && !current_SC->SCp.have_data_in
1287 && (current_SC->SCp.sent_command >= current_SC->cmd_len)) {
1288
1289 if(current_SC->sc_data_direction == DMA_TO_DEVICE)
1290 {
1291 current_SC->SCp.have_data_in = -1;
1292 outb(0xd0 | PARITY_MASK, port_base + TMC_Cntl);
1293 }
1294 else
1295 {
1296 current_SC->SCp.have_data_in = 1;
1297 outb(0x90 | PARITY_MASK, port_base + TMC_Cntl);
1298 }
1299 }
1300
1301 if (current_SC->SCp.have_data_in == -1) {
1302 while ((data_count = FIFO_Size - inw(port_base + FIFO_Data_Count)) > 512) {
1303#if EVERY_ACCESS
1304 printk( "DC=%d, ", data_count ) ;
1305#endif
1306 if (data_count > current_SC->SCp.this_residual)
1307 data_count = current_SC->SCp.this_residual;
1308 if (data_count > 0) {
1309#if EVERY_ACCESS
1310 printk( "%d OUT, ", data_count );
1311#endif
1312 if (data_count == 1) {
1313 outb(*current_SC->SCp.ptr++, port_base + Write_FIFO);
1314 --current_SC->SCp.this_residual;
1315 } else {
1316 data_count >>= 1;
1317 outsw(port_base + Write_FIFO, current_SC->SCp.ptr, data_count);
1318 current_SC->SCp.ptr += 2 * data_count;
1319 current_SC->SCp.this_residual -= 2 * data_count;
1320 }
1321 }
1322 if (!current_SC->SCp.this_residual) {
1323 if (current_SC->SCp.buffers_residual) {
1324 --current_SC->SCp.buffers_residual;
1325 ++current_SC->SCp.buffer;
1326 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1327 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1328 } else
1329 break;
1330 }
1331 }
1332 }
1333
1334 if (current_SC->SCp.have_data_in == 1) {
1335 while ((data_count = inw(port_base + FIFO_Data_Count)) > 0) {
1336#if EVERY_ACCESS
1337 printk( "DC=%d, ", data_count );
1338#endif
1339 if (data_count > current_SC->SCp.this_residual)
1340 data_count = current_SC->SCp.this_residual;
1341 if (data_count) {
1342#if EVERY_ACCESS
1343 printk( "%d IN, ", data_count );
1344#endif
1345 if (data_count == 1) {
1346 *current_SC->SCp.ptr++ = inb(port_base + Read_FIFO);
1347 --current_SC->SCp.this_residual;
1348 } else {
1349 data_count >>= 1;
1350 insw(port_base + Read_FIFO, current_SC->SCp.ptr, data_count);
1351 current_SC->SCp.ptr += 2 * data_count;
1352 current_SC->SCp.this_residual -= 2 * data_count;
1353 }
1354 }
1355 if (!current_SC->SCp.this_residual
1356 && current_SC->SCp.buffers_residual) {
1357 --current_SC->SCp.buffers_residual;
1358 ++current_SC->SCp.buffer;
1359 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1360 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1361 }
1362 }
1363 }
1364
1365 if (done) {
1366#if EVERY_ACCESS
1367 printk( " ** IN DONE %d ** ", current_SC->SCp.have_data_in );
1368#endif
1369
1370#if ERRORS_ONLY
1371 if (current_SC->cmnd[0] == REQUEST_SENSE && !current_SC->SCp.Status) {
1372 char *buf = scsi_sglist(current_SC);
1373 if ((unsigned char)(*(buf + 2)) & 0x0f) {
1374 unsigned char key;
1375 unsigned char code;
1376 unsigned char qualifier;
1377
1378 key = (unsigned char)(*(buf + 2)) & 0x0f;
1379 code = (unsigned char)(*(buf + 12));
1380 qualifier = (unsigned char)(*(buf + 13));
1381
1382 if (key != UNIT_ATTENTION
1383 && !(key == NOT_READY
1384 && code == 0x04
1385 && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
1386 && !(key == ILLEGAL_REQUEST && (code == 0x25
1387 || code == 0x24
1388 || !code)))
1389
1390 printk( "scsi: <fdomain> REQUEST SENSE"
1391 " Key = %x, Code = %x, Qualifier = %x\n",
1392 key, code, qualifier );
1393 }
1394 }
1395#endif
1396#if EVERY_ACCESS
1397 printk( "BEFORE MY_DONE. . ." );
1398#endif
1399 spin_lock_irqsave(current_SC->device->host->host_lock, flags);
1400 my_done( (current_SC->SCp.Status & 0xff)
1401 | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16) );
1402 spin_unlock_irqrestore(current_SC->device->host->host_lock, flags);
1403#if EVERY_ACCESS
1404 printk( "RETURNING.\n" );
1405#endif
1406
1407 } else {
1408 if (current_SC->SCp.phase & disconnect) {
1409 outb(0xd0 | FIFO_COUNT, port_base + Interrupt_Cntl);
1410 outb(0x00, port_base + SCSI_Cntl);
1411 } else {
1412 outb(0x90 | FIFO_COUNT, port_base + Interrupt_Cntl);
1413 }
1414 }
1415#if DEBUG_RACE
1416 in_interrupt_flag = 0;
1417#endif
1418 return IRQ_HANDLED;
1419}
1420
1421static int fdomain_16x0_queue_lck(struct scsi_cmnd *SCpnt,
1422 void (*done)(struct scsi_cmnd *))
1423{
1424 if (in_command) {
1425 panic( "scsi: <fdomain> fdomain_16x0_queue() NOT REENTRANT!\n" );
1426 }
1427#if EVERY_ACCESS
1428 printk( "queue: target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1429 SCpnt->target,
1430 *(unsigned char *)SCpnt->cmnd,
1431 scsi_sg_count(SCpnt),
1432 scsi_bufflen(SCpnt));
1433#endif
1434
1435 fdomain_make_bus_idle();
1436
1437 current_SC = SCpnt;
1438 current_SC->scsi_done = done;
1439
1440
1441
1442 if (scsi_sg_count(current_SC)) {
1443 current_SC->SCp.buffer = scsi_sglist(current_SC);
1444 current_SC->SCp.ptr = sg_virt(current_SC->SCp.buffer);
1445 current_SC->SCp.this_residual = current_SC->SCp.buffer->length;
1446 current_SC->SCp.buffers_residual = scsi_sg_count(current_SC) - 1;
1447 } else {
1448 current_SC->SCp.ptr = NULL;
1449 current_SC->SCp.this_residual = 0;
1450 current_SC->SCp.buffer = NULL;
1451 current_SC->SCp.buffers_residual = 0;
1452 }
1453
1454 current_SC->SCp.Status = 0;
1455 current_SC->SCp.Message = 0;
1456 current_SC->SCp.have_data_in = 0;
1457 current_SC->SCp.sent_command = 0;
1458 current_SC->SCp.phase = in_arbitration;
1459
1460
1461 outb(0x00, port_base + Interrupt_Cntl);
1462 outb(0x00, port_base + SCSI_Cntl);
1463 outb(adapter_mask, port_base + SCSI_Data_NoACK);
1464 ++in_command;
1465 outb(0x20, port_base + Interrupt_Cntl);
1466 outb(0x14 | PARITY_MASK, port_base + TMC_Cntl);
1467
1468 return 0;
1469}
1470
1471static DEF_SCSI_QCMD(fdomain_16x0_queue)
1472
1473#if DEBUG_ABORT
1474static void print_info(struct scsi_cmnd *SCpnt)
1475{
1476 unsigned int imr;
1477 unsigned int irr;
1478 unsigned int isr;
1479
1480 if (!SCpnt || !SCpnt->device || !SCpnt->device->host) {
1481 printk(KERN_WARNING "scsi: <fdomain> Cannot provide detailed information\n");
1482 return;
1483 }
1484
1485 printk(KERN_INFO "%s\n", fdomain_16x0_info( SCpnt->device->host ) );
1486 print_banner(SCpnt->device->host);
1487 switch (SCpnt->SCp.phase) {
1488 case in_arbitration: printk("arbitration"); break;
1489 case in_selection: printk("selection"); break;
1490 case in_other: printk("other"); break;
1491 default: printk("unknown"); break;
1492 }
1493
1494 printk( " (%d), target = %d cmnd = 0x%02x pieces = %d size = %u\n",
1495 SCpnt->SCp.phase,
1496 SCpnt->device->id,
1497 *(unsigned char *)SCpnt->cmnd,
1498 scsi_sg_count(SCpnt),
1499 scsi_bufflen(SCpnt));
1500 printk( "sent_command = %d, have_data_in = %d, timeout = %d\n",
1501 SCpnt->SCp.sent_command,
1502 SCpnt->SCp.have_data_in,
1503 SCpnt->timeout );
1504#if DEBUG_RACE
1505 printk( "in_interrupt_flag = %d\n", in_interrupt_flag );
1506#endif
1507
1508 imr = (inb( 0x0a1 ) << 8) + inb( 0x21 );
1509 outb( 0x0a, 0xa0 );
1510 irr = inb( 0xa0 ) << 8;
1511 outb( 0x0a, 0x20 );
1512 irr += inb( 0x20 );
1513 outb( 0x0b, 0xa0 );
1514 isr = inb( 0xa0 ) << 8;
1515 outb( 0x0b, 0x20 );
1516 isr += inb( 0x20 );
1517
1518
1519 printk( "IMR = 0x%04x", imr );
1520 if (imr & (1 << interrupt_level))
1521 printk( " (masked)" );
1522 printk( ", IRR = 0x%04x, ISR = 0x%04x\n", irr, isr );
1523
1524 printk( "SCSI Status = 0x%02x\n", inb(port_base + SCSI_Status));
1525 printk( "TMC Status = 0x%02x", inb(port_base + TMC_Status));
1526 if (inb((port_base + TMC_Status) & 1))
1527 printk( " (interrupt)" );
1528 printk( "\n" );
1529 printk("Interrupt Status = 0x%02x", inb(port_base + Interrupt_Status));
1530 if (inb(port_base + Interrupt_Status) & 0x08)
1531 printk( " (enabled)" );
1532 printk( "\n" );
1533 if (chip == tmc18c50 || chip == tmc18c30) {
1534 printk("FIFO Status = 0x%02x\n", inb(port_base + FIFO_Status));
1535 printk( "Int. Condition = 0x%02x\n",
1536 inb( port_base + Interrupt_Cond ) );
1537 }
1538 printk( "Configuration 1 = 0x%02x\n", inb( port_base + Configuration1 ) );
1539 if (chip == tmc18c50 || chip == tmc18c30)
1540 printk( "Configuration 2 = 0x%02x\n",
1541 inb( port_base + Configuration2 ) );
1542}
1543#endif
1544
1545static int fdomain_16x0_abort(struct scsi_cmnd *SCpnt)
1546{
1547#if EVERY_ACCESS || ERRORS_ONLY || DEBUG_ABORT
1548 printk( "scsi: <fdomain> abort " );
1549#endif
1550
1551 if (!in_command) {
1552#if EVERY_ACCESS || ERRORS_ONLY
1553 printk( " (not in command)\n" );
1554#endif
1555 return FAILED;
1556 } else printk( "\n" );
1557
1558#if DEBUG_ABORT
1559 print_info( SCpnt );
1560#endif
1561
1562 fdomain_make_bus_idle();
1563 current_SC->SCp.phase |= aborted;
1564 current_SC->result = DID_ABORT << 16;
1565
1566
1567 my_done(DID_ABORT << 16);
1568 return SUCCESS;
1569}
1570
1571int fdomain_16x0_bus_reset(struct scsi_cmnd *SCpnt)
1572{
1573 unsigned long flags;
1574
1575 local_irq_save(flags);
1576
1577 outb(1, port_base + SCSI_Cntl);
1578 do_pause( 2 );
1579 outb(0, port_base + SCSI_Cntl);
1580 do_pause( 115 );
1581 outb(0, port_base + SCSI_Mode_Cntl);
1582 outb(PARITY_MASK, port_base + TMC_Cntl);
1583
1584 local_irq_restore(flags);
1585 return SUCCESS;
1586}
1587
1588static int fdomain_16x0_biosparam(struct scsi_device *sdev,
1589 struct block_device *bdev,
1590 sector_t capacity, int *info_array)
1591{
1592 int drive;
1593 int size = capacity;
1594 unsigned long offset;
1595 struct drive_info {
1596 unsigned short cylinders;
1597 unsigned char heads;
1598 unsigned char sectors;
1599 } i;
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644 if (MAJOR(bdev->bd_dev) != SCSI_DISK0_MAJOR) {
1645 printk("scsi: <fdomain> fdomain_16x0_biosparam: too many disks");
1646 return 0;
1647 }
1648 drive = MINOR(bdev->bd_dev) >> 4;
1649
1650 if (bios_major == 2) {
1651 switch (Quantum) {
1652 case 2:
1653
1654
1655 offset = 0x1f33 + drive * 25;
1656 break;
1657 case 3:
1658 offset = 0x1f36 + drive * 15;
1659 break;
1660 case 4:
1661 offset = 0x1f34 + drive * 15;
1662 break;
1663 default:
1664 offset = 0x1f31 + drive * 25;
1665 break;
1666 }
1667 memcpy_fromio( &i, bios_mem + offset, sizeof( struct drive_info ) );
1668 info_array[0] = i.heads;
1669 info_array[1] = i.sectors;
1670 info_array[2] = i.cylinders;
1671 } else if (bios_major == 3
1672 && bios_minor >= 0
1673 && bios_minor < 4) {
1674 memcpy_fromio( &i, bios_mem + 0x1f71 + drive * 10,
1675 sizeof( struct drive_info ) );
1676 info_array[0] = i.heads + 1;
1677 info_array[1] = i.sectors;
1678 info_array[2] = i.cylinders;
1679 } else {
1680
1681 unsigned char *p = scsi_bios_ptable(bdev);
1682
1683 if (p && p[65] == 0xaa && p[64] == 0x55
1684 && p[4]) {
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715 info_array[0] = p[5] + 1;
1716 info_array[1] = p[6] & 0x3f;
1717 } else {
1718
1719
1720
1721
1722
1723 if ((unsigned int)size >= 0x7e0000U) {
1724 info_array[0] = 0xff;
1725 info_array[1] = 0x3f;
1726 } else if ((unsigned int)size >= 0x200000U) {
1727 info_array[0] = 0x80;
1728 info_array[1] = 0x3f;
1729 } else {
1730 info_array[0] = 0x40;
1731 info_array[1] = 0x20;
1732 }
1733 }
1734
1735 info_array[2] = (unsigned int)size / (info_array[0] * info_array[1] );
1736 kfree(p);
1737 }
1738
1739 return 0;
1740}
1741
1742static int fdomain_16x0_release(struct Scsi_Host *shpnt)
1743{
1744 if (shpnt->irq)
1745 free_irq(shpnt->irq, shpnt);
1746 if (shpnt->io_port && shpnt->n_io_port)
1747 release_region(shpnt->io_port, shpnt->n_io_port);
1748 if (PCI_bus)
1749 pci_dev_put(PCI_dev);
1750 return 0;
1751}
1752
1753struct scsi_host_template fdomain_driver_template = {
1754 .module = THIS_MODULE,
1755 .name = "fdomain",
1756 .proc_name = "fdomain",
1757 .detect = fdomain_16x0_detect,
1758 .info = fdomain_16x0_info,
1759 .queuecommand = fdomain_16x0_queue,
1760 .eh_abort_handler = fdomain_16x0_abort,
1761 .eh_bus_reset_handler = fdomain_16x0_bus_reset,
1762 .bios_param = fdomain_16x0_biosparam,
1763 .release = fdomain_16x0_release,
1764 .can_queue = 1,
1765 .this_id = 6,
1766 .sg_tablesize = 64,
1767 .cmd_per_lun = 1,
1768 .use_clustering = DISABLE_CLUSTERING,
1769};
1770
1771#ifndef PCMCIA
1772#ifdef CONFIG_PCI
1773
1774static struct pci_device_id fdomain_pci_tbl[] = {
1775 { PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70,
1776 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
1777 { }
1778};
1779MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl);
1780#endif
1781#define driver_template fdomain_driver_template
1782#include "scsi_module.c"
1783
1784#endif
1785