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#include <linux/module.h>
117#include <linux/blkdev.h>
118#include <linux/interrupt.h>
119#include <linux/string.h>
120#include <linux/delay.h>
121#include <linux/proc_fs.h>
122#include <linux/ioport.h>
123#include <linux/stat.h>
124
125#include <asm/io.h>
126
127#include "scsi.h"
128#include <scsi/scsi_host.h>
129
130#define IN2000_VERSION "1.33-2.5"
131#define IN2000_DATE "2002/11/03"
132
133#include "in2000.h"
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
183static char *setup_args[] = { "", "", "", "", "", "", "", "", "" };
184
185
186static char *setup_strings;
187
188module_param(setup_strings, charp, 0);
189
190static inline uchar read_3393(struct IN2000_hostdata *hostdata, uchar reg_num)
191{
192 write1_io(reg_num, IO_WD_ADDR);
193 return read1_io(IO_WD_DATA);
194}
195
196
197#define READ_AUX_STAT() read1_io(IO_WD_ASR)
198
199
200static inline void write_3393(struct IN2000_hostdata *hostdata, uchar reg_num, uchar value)
201{
202 write1_io(reg_num, IO_WD_ADDR);
203 write1_io(value, IO_WD_DATA);
204}
205
206
207static inline void write_3393_cmd(struct IN2000_hostdata *hostdata, uchar cmd)
208{
209
210
211 write1_io(WD_COMMAND, IO_WD_ADDR);
212 write1_io(cmd, IO_WD_DATA);
213}
214
215
216static uchar read_1_byte(struct IN2000_hostdata *hostdata)
217{
218 uchar asr, x = 0;
219
220 write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
221 write_3393_cmd(hostdata, WD_CMD_TRANS_INFO | 0x80);
222 do {
223 asr = READ_AUX_STAT();
224 if (asr & ASR_DBR)
225 x = read_3393(hostdata, WD_DATA);
226 } while (!(asr & ASR_INT));
227 return x;
228}
229
230
231static void write_3393_count(struct IN2000_hostdata *hostdata, unsigned long value)
232{
233 write1_io(WD_TRANSFER_COUNT_MSB, IO_WD_ADDR);
234 write1_io((value >> 16), IO_WD_DATA);
235 write1_io((value >> 8), IO_WD_DATA);
236 write1_io(value, IO_WD_DATA);
237}
238
239
240static unsigned long read_3393_count(struct IN2000_hostdata *hostdata)
241{
242 unsigned long value;
243
244 write1_io(WD_TRANSFER_COUNT_MSB, IO_WD_ADDR);
245 value = read1_io(IO_WD_DATA) << 16;
246 value |= read1_io(IO_WD_DATA) << 8;
247 value |= read1_io(IO_WD_DATA);
248 return value;
249}
250
251
252
253
254
255
256
257static int is_dir_out(Scsi_Cmnd * cmd)
258{
259 switch (cmd->cmnd[0]) {
260 case WRITE_6:
261 case WRITE_10:
262 case WRITE_12:
263 case WRITE_LONG:
264 case WRITE_SAME:
265 case WRITE_BUFFER:
266 case WRITE_VERIFY:
267 case WRITE_VERIFY_12:
268 case COMPARE:
269 case COPY:
270 case COPY_VERIFY:
271 case SEARCH_EQUAL:
272 case SEARCH_HIGH:
273 case SEARCH_LOW:
274 case SEARCH_EQUAL_12:
275 case SEARCH_HIGH_12:
276 case SEARCH_LOW_12:
277 case FORMAT_UNIT:
278 case REASSIGN_BLOCKS:
279 case RESERVE:
280 case MODE_SELECT:
281 case MODE_SELECT_10:
282 case LOG_SELECT:
283 case SEND_DIAGNOSTIC:
284 case CHANGE_DEFINITION:
285 case UPDATE_BLOCK:
286 case SET_WINDOW:
287 case MEDIUM_SCAN:
288 case SEND_VOLUME_TAG:
289 case 0xea:
290 return 1;
291 default:
292 return 0;
293 }
294}
295
296
297
298static struct sx_period sx_table[] = {
299 {1, 0x20},
300 {252, 0x20},
301 {376, 0x30},
302 {500, 0x40},
303 {624, 0x50},
304 {752, 0x60},
305 {876, 0x70},
306 {1000, 0x00},
307 {0, 0}
308};
309
310static int round_period(unsigned int period)
311{
312 int x;
313
314 for (x = 1; sx_table[x].period_ns; x++) {
315 if ((period <= sx_table[x - 0].period_ns) && (period > sx_table[x - 1].period_ns)) {
316 return x;
317 }
318 }
319 return 7;
320}
321
322static uchar calc_sync_xfer(unsigned int period, unsigned int offset)
323{
324 uchar result;
325
326 period *= 4;
327 result = sx_table[round_period(period)].reg_value;
328 result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF;
329 return result;
330}
331
332
333
334static void in2000_execute(struct Scsi_Host *instance);
335
336static int in2000_queuecommand_lck(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
337{
338 struct Scsi_Host *instance;
339 struct IN2000_hostdata *hostdata;
340 Scsi_Cmnd *tmp;
341
342 instance = cmd->device->host;
343 hostdata = (struct IN2000_hostdata *) instance->hostdata;
344
345 DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x(", cmd->cmnd[0]))
346
347
348
349
350
351
352 cmd->host_scribble = NULL;
353 cmd->scsi_done = done;
354 cmd->result = 0;
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371 if (scsi_bufflen(cmd)) {
372 cmd->SCp.buffer = scsi_sglist(cmd);
373 cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
374 cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
375 cmd->SCp.this_residual = cmd->SCp.buffer->length;
376 } else {
377 cmd->SCp.buffer = NULL;
378 cmd->SCp.buffers_residual = 0;
379 cmd->SCp.ptr = NULL;
380 cmd->SCp.this_residual = 0;
381 }
382 cmd->SCp.have_data_in = 0;
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403 cmd->SCp.Status = ILLEGAL_STATUS_BYTE;
404
405
406
407
408
409
410
411
412
413
414
415 if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
416 cmd->host_scribble = (uchar *) hostdata->input_Q;
417 hostdata->input_Q = cmd;
418 } else {
419 for (tmp = (Scsi_Cmnd *) hostdata->input_Q; tmp->host_scribble; tmp = (Scsi_Cmnd *) tmp->host_scribble);
420 tmp->host_scribble = (uchar *) cmd;
421 }
422
423
424
425
426
427 in2000_execute(cmd->device->host);
428
429 DB(DB_QUEUE_COMMAND, printk(")Q "))
430 return 0;
431}
432
433static DEF_SCSI_QCMD(in2000_queuecommand)
434
435
436
437
438
439
440
441
442
443
444
445static void in2000_execute(struct Scsi_Host *instance)
446{
447 struct IN2000_hostdata *hostdata;
448 Scsi_Cmnd *cmd, *prev;
449 int i;
450 unsigned short *sp;
451 unsigned short f;
452 unsigned short flushbuf[16];
453
454
455 hostdata = (struct IN2000_hostdata *) instance->hostdata;
456
457 DB(DB_EXECUTE, printk("EX("))
458
459 if (hostdata->selecting || hostdata->connected) {
460
461 DB(DB_EXECUTE, printk(")EX-0 "))
462
463 return;
464 }
465
466
467
468
469
470
471 cmd = (Scsi_Cmnd *) hostdata->input_Q;
472 prev = NULL;
473 while (cmd) {
474 if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)))
475 break;
476 prev = cmd;
477 cmd = (Scsi_Cmnd *) cmd->host_scribble;
478 }
479
480
481
482 if (!cmd) {
483
484 DB(DB_EXECUTE, printk(")EX-1 "))
485
486 return;
487 }
488
489
490
491 if (prev)
492 prev->host_scribble = cmd->host_scribble;
493 else
494 hostdata->input_Q = (Scsi_Cmnd *) cmd->host_scribble;
495
496#ifdef PROC_STATISTICS
497 hostdata->cmd_cnt[cmd->device->id]++;
498#endif
499
500
501
502
503
504 if (is_dir_out(cmd))
505 write_3393(hostdata, WD_DESTINATION_ID, cmd->device->id);
506 else
507 write_3393(hostdata, WD_DESTINATION_ID, cmd->device->id | DSTID_DPD);
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532 cmd->SCp.phase = 0;
533 if (hostdata->disconnect == DIS_NEVER)
534 goto no;
535 if (hostdata->disconnect == DIS_ALWAYS)
536 goto yes;
537 if (cmd->device->type == 1)
538 goto yes;
539 if (hostdata->disconnected_Q)
540 goto yes;
541 if (!(hostdata->input_Q))
542 goto no;
543 for (prev = (Scsi_Cmnd *) hostdata->input_Q; prev; prev = (Scsi_Cmnd *) prev->host_scribble) {
544 if ((prev->device->id != cmd->device->id) || (prev->device->lun != cmd->device->lun)) {
545 for (prev = (Scsi_Cmnd *) hostdata->input_Q; prev; prev = (Scsi_Cmnd *) prev->host_scribble)
546 prev->SCp.phase = 1;
547 goto yes;
548 }
549 }
550 goto no;
551
552 yes:
553 cmd->SCp.phase = 1;
554
555#ifdef PROC_STATISTICS
556 hostdata->disc_allowed_cnt[cmd->device->id]++;
557#endif
558
559 no:
560 write_3393(hostdata, WD_SOURCE_ID, ((cmd->SCp.phase) ? SRCID_ER : 0));
561
562 write_3393(hostdata, WD_TARGET_LUN, cmd->device->lun);
563 write_3393(hostdata, WD_SYNCHRONOUS_TRANSFER, hostdata->sync_xfer[cmd->device->id]);
564 hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun);
565
566 if ((hostdata->level2 <= L2_NONE) || (hostdata->sync_stat[cmd->device->id] == SS_UNSET)) {
567
568
569
570
571
572
573
574
575
576 hostdata->selecting = cmd;
577
578
579
580
581
582
583
584
585
586
587
588 if (hostdata->sync_stat[cmd->device->id] == SS_UNSET) {
589 if (hostdata->sync_off & (1 << cmd->device->id))
590 hostdata->sync_stat[cmd->device->id] = SS_SET;
591 else
592 hostdata->sync_stat[cmd->device->id] = SS_FIRST;
593 }
594 hostdata->state = S_SELECTING;
595 write_3393_count(hostdata, 0);
596 write_3393_cmd(hostdata, WD_CMD_SEL_ATN);
597 }
598
599 else {
600
601
602
603
604
605
606
607
608
609 hostdata->connected = cmd;
610 write_3393(hostdata, WD_COMMAND_PHASE, 0);
611
612
613
614
615
616 write1_io(WD_CDB_1, IO_WD_ADDR);
617 for (i = 0; i < cmd->cmd_len; i++)
618 write1_io(cmd->cmnd[i], IO_WD_DATA);
619
620
621
622
623
624
625
626 write_3393(hostdata, WD_OWN_ID, cmd->cmd_len);
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646 if (!(cmd->SCp.phase)) {
647 write_3393_count(hostdata, cmd->SCp.this_residual);
648 write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS);
649 write1_io(0, IO_FIFO_WRITE);
650
651 if (is_dir_out(cmd)) {
652 hostdata->fifo = FI_FIFO_WRITING;
653 if ((i = cmd->SCp.this_residual) > (IN2000_FIFO_SIZE - 16))
654 i = IN2000_FIFO_SIZE - 16;
655 cmd->SCp.have_data_in = i;
656 i >>= 1;
657 sp = (unsigned short *) cmd->SCp.ptr;
658 f = hostdata->io_base + IO_FIFO;
659
660#ifdef FAST_WRITE_IO
661
662 FAST_WRITE2_IO();
663#else
664 while (i--)
665 write2_io(*sp++, IO_FIFO);
666
667#endif
668
669
670
671 if (cmd->SCp.have_data_in <= ((IN2000_FIFO_SIZE - 16) - 32)) {
672 sp = flushbuf;
673 i = 16;
674
675#ifdef FAST_WRITE_IO
676
677 FAST_WRITE2_IO();
678#else
679 while (i--)
680 write2_io(0, IO_FIFO);
681
682#endif
683
684 }
685 }
686
687 else {
688 write1_io(0, IO_FIFO_READ);
689 hostdata->fifo = FI_FIFO_READING;
690 cmd->SCp.have_data_in = 0;
691 }
692
693 } else {
694 write_3393_count(hostdata, 0);
695 }
696 hostdata->state = S_RUNNING_LEVEL2;
697 write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER);
698 }
699
700
701
702
703
704
705
706
707 DB(DB_EXECUTE, printk("%s)EX-2 ", (cmd->SCp.phase) ? "d:" : ""))
708
709}
710
711
712
713static void transfer_pio(uchar * buf, int cnt, int data_in_dir, struct IN2000_hostdata *hostdata)
714{
715 uchar asr;
716
717 DB(DB_TRANSFER, printk("(%p,%d,%s)", buf, cnt, data_in_dir ? "in" : "out"))
718
719 write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
720 write_3393_count(hostdata, cnt);
721 write_3393_cmd(hostdata, WD_CMD_TRANS_INFO);
722 if (data_in_dir) {
723 do {
724 asr = READ_AUX_STAT();
725 if (asr & ASR_DBR)
726 *buf++ = read_3393(hostdata, WD_DATA);
727 } while (!(asr & ASR_INT));
728 } else {
729 do {
730 asr = READ_AUX_STAT();
731 if (asr & ASR_DBR)
732 write_3393(hostdata, WD_DATA, *buf++);
733 } while (!(asr & ASR_INT));
734 }
735
736
737
738
739
740
741
742
743}
744
745
746
747static void transfer_bytes(Scsi_Cmnd * cmd, int data_in_dir)
748{
749 struct IN2000_hostdata *hostdata;
750 unsigned short *sp;
751 unsigned short f;
752 int i;
753
754 hostdata = (struct IN2000_hostdata *) cmd->device->host->hostdata;
755
756
757
758
759
760
761
762
763
764 if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
765 ++cmd->SCp.buffer;
766 --cmd->SCp.buffers_residual;
767 cmd->SCp.this_residual = cmd->SCp.buffer->length;
768 cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
769 }
770
771
772
773 write_3393(hostdata, WD_SYNCHRONOUS_TRANSFER, hostdata->sync_xfer[cmd->device->id]);
774 write_3393_count(hostdata, cmd->SCp.this_residual);
775 write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_BUS);
776 write1_io(0, IO_FIFO_WRITE);
777
778
779
780
781
782 if (data_in_dir) {
783 write1_io(0, IO_FIFO_READ);
784 if ((hostdata->level2 >= L2_DATA) || (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) {
785 write_3393(hostdata, WD_COMMAND_PHASE, 0x45);
786 write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER);
787 hostdata->state = S_RUNNING_LEVEL2;
788 } else
789 write_3393_cmd(hostdata, WD_CMD_TRANS_INFO);
790 hostdata->fifo = FI_FIFO_READING;
791 cmd->SCp.have_data_in = 0;
792 return;
793 }
794
795
796
797
798
799
800 if ((hostdata->level2 >= L2_DATA) || (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) {
801 write_3393(hostdata, WD_COMMAND_PHASE, 0x45);
802 write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER);
803 hostdata->state = S_RUNNING_LEVEL2;
804 } else
805 write_3393_cmd(hostdata, WD_CMD_TRANS_INFO);
806 hostdata->fifo = FI_FIFO_WRITING;
807 sp = (unsigned short *) cmd->SCp.ptr;
808
809 if ((i = cmd->SCp.this_residual) > IN2000_FIFO_SIZE)
810 i = IN2000_FIFO_SIZE;
811 cmd->SCp.have_data_in = i;
812 i >>= 1;
813 f = hostdata->io_base + IO_FIFO;
814
815#ifdef FAST_WRITE_IO
816
817 FAST_WRITE2_IO();
818#else
819 while (i--)
820 write2_io(*sp++, IO_FIFO);
821
822#endif
823
824}
825
826
827
828
829
830
831
832
833static irqreturn_t in2000_intr(int irqnum, void *dev_id)
834{
835 struct Scsi_Host *instance = dev_id;
836 struct IN2000_hostdata *hostdata;
837 Scsi_Cmnd *patch, *cmd;
838 uchar asr, sr, phs, id, lun, *ucp, msg;
839 int i, j;
840 unsigned long length;
841 unsigned short *sp;
842 unsigned short f;
843 unsigned long flags;
844
845 hostdata = (struct IN2000_hostdata *) instance->hostdata;
846
847
848
849 spin_lock_irqsave(instance->host_lock, flags);
850
851#ifdef PROC_STATISTICS
852 hostdata->int_cnt++;
853#endif
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890 write1_io(0, IO_LED_ON);
891 asr = READ_AUX_STAT();
892 if (!(asr & ASR_INT)) {
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913 cmd = (Scsi_Cmnd *) hostdata->connected;
914 CHECK_NULL(cmd, "fifo_int")
915
916 if (hostdata->fifo == FI_FIFO_READING) {
917
918 DB(DB_FIFO, printk("{R:%02x} ", read1_io(IO_FIFO_COUNT)))
919
920 sp = (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in);
921 i = read1_io(IO_FIFO_COUNT) & 0xfe;
922 i <<= 2;
923 f = hostdata->io_base + IO_FIFO;
924
925#ifdef FAST_READ_IO
926
927 FAST_READ2_IO();
928#else
929 while (i--)
930 *sp++ = read2_io(IO_FIFO);
931
932#endif
933
934 i = sp - (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in);
935 i <<= 1;
936 cmd->SCp.have_data_in += i;
937 }
938
939 else if (hostdata->fifo == FI_FIFO_WRITING) {
940
941 DB(DB_FIFO, printk("{W:%02x} ", read1_io(IO_FIFO_COUNT)))
942
943
944
945
946
947
948
949
950
951
952
953 if (cmd->SCp.this_residual == cmd->SCp.have_data_in) {
954 i = 16;
955 while (i--)
956 write2_io(0, IO_FIFO);
957 }
958
959
960
961
962
963 else {
964 sp = (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in);
965 i = cmd->SCp.this_residual - cmd->SCp.have_data_in;
966 j = read1_io(IO_FIFO_COUNT) & 0xfe;
967 j <<= 2;
968 if ((j << 1) > i)
969 j = (i >> 1);
970 while (j--)
971 write2_io(*sp++, IO_FIFO);
972
973 i = sp - (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in);
974 i <<= 1;
975 cmd->SCp.have_data_in += i;
976 }
977 }
978
979 else {
980 printk("*** Spurious FIFO interrupt ***");
981 }
982
983 write1_io(0, IO_LED_OFF);
984
985
986 spin_unlock_irqrestore(instance->host_lock, flags);
987 return IRQ_HANDLED;
988 }
989
990
991
992
993
994
995 cmd = (Scsi_Cmnd *) hostdata->connected;
996 sr = read_3393(hostdata, WD_SCSI_STATUS);
997 phs = read_3393(hostdata, WD_COMMAND_PHASE);
998
999 if (!cmd && (sr != CSR_RESEL_AM && sr != CSR_TIMEOUT && sr != CSR_SELECT)) {
1000 printk("\nNR:wd-intr-1\n");
1001 write1_io(0, IO_LED_OFF);
1002
1003
1004 spin_unlock_irqrestore(instance->host_lock, flags);
1005 return IRQ_HANDLED;
1006 }
1007
1008 DB(DB_INTR, printk("{%02x:%02x-", asr, sr))
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022 if (hostdata->fifo == FI_FIFO_READING) {
1023
1024
1025
1026 sp = (unsigned short *) (cmd->SCp.ptr + cmd->SCp.have_data_in);
1027
1028
1029
1030 i = (cmd->SCp.this_residual - read_3393_count(hostdata)) - cmd->SCp.have_data_in;
1031 i >>= 1;
1032 f = hostdata->io_base + IO_FIFO;
1033
1034#ifdef FAST_READ_IO
1035
1036 FAST_READ2_IO();
1037#else
1038 while (i--)
1039 *sp++ = read2_io(IO_FIFO);
1040
1041#endif
1042
1043 hostdata->fifo = FI_FIFO_UNUSED;
1044 length = cmd->SCp.this_residual;
1045 cmd->SCp.this_residual = read_3393_count(hostdata);
1046 cmd->SCp.ptr += (length - cmd->SCp.this_residual);
1047
1048 DB(DB_TRANSFER, printk("(%p,%d)", cmd->SCp.ptr, cmd->SCp.this_residual))
1049
1050 }
1051
1052 else if (hostdata->fifo == FI_FIFO_WRITING) {
1053 hostdata->fifo = FI_FIFO_UNUSED;
1054 length = cmd->SCp.this_residual;
1055 cmd->SCp.this_residual = read_3393_count(hostdata);
1056 cmd->SCp.ptr += (length - cmd->SCp.this_residual);
1057
1058 DB(DB_TRANSFER, printk("(%p,%d)", cmd->SCp.ptr, cmd->SCp.this_residual))
1059
1060 }
1061
1062
1063
1064 switch (sr) {
1065
1066 case CSR_TIMEOUT:
1067 DB(DB_INTR, printk("TIMEOUT"))
1068
1069 if (hostdata->state == S_RUNNING_LEVEL2)
1070 hostdata->connected = NULL;
1071 else {
1072 cmd = (Scsi_Cmnd *) hostdata->selecting;
1073 CHECK_NULL(cmd, "csr_timeout")
1074 hostdata->selecting = NULL;
1075 }
1076
1077 cmd->result = DID_NO_CONNECT << 16;
1078 hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
1079 hostdata->state = S_UNCONNECTED;
1080 cmd->scsi_done(cmd);
1081
1082
1083
1084
1085
1086 in2000_execute(instance);
1087 break;
1088
1089
1090
1091
1092 case CSR_SELECT:
1093 DB(DB_INTR, printk("SELECT"))
1094 hostdata->connected = cmd = (Scsi_Cmnd *) hostdata->selecting;
1095 CHECK_NULL(cmd, "csr_select")
1096 hostdata->selecting = NULL;
1097
1098
1099
1100 hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->device->lun);
1101 if (cmd->SCp.phase)
1102 hostdata->outgoing_msg[0] |= 0x40;
1103
1104 if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) {
1105#ifdef SYNC_DEBUG
1106 printk(" sending SDTR ");
1107#endif
1108
1109 hostdata->sync_stat[cmd->device->id] = SS_WAITING;
1110
1111
1112
1113 hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
1114 hostdata->outgoing_msg[2] = 3;
1115 hostdata->outgoing_msg[3] = EXTENDED_SDTR;
1116 hostdata->outgoing_msg[4] = OPTIMUM_SX_PER / 4;
1117 hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
1118 hostdata->outgoing_len = 6;
1119 } else
1120 hostdata->outgoing_len = 1;
1121
1122 hostdata->state = S_CONNECTED;
1123 break;
1124
1125
1126 case CSR_XFER_DONE | PHS_DATA_IN:
1127 case CSR_UNEXP | PHS_DATA_IN:
1128 case CSR_SRV_REQ | PHS_DATA_IN:
1129 DB(DB_INTR, printk("IN-%d.%d", cmd->SCp.this_residual, cmd->SCp.buffers_residual))
1130 transfer_bytes(cmd, DATA_IN_DIR);
1131 if (hostdata->state != S_RUNNING_LEVEL2)
1132 hostdata->state = S_CONNECTED;
1133 break;
1134
1135
1136 case CSR_XFER_DONE | PHS_DATA_OUT:
1137 case CSR_UNEXP | PHS_DATA_OUT:
1138 case CSR_SRV_REQ | PHS_DATA_OUT:
1139 DB(DB_INTR, printk("OUT-%d.%d", cmd->SCp.this_residual, cmd->SCp.buffers_residual))
1140 transfer_bytes(cmd, DATA_OUT_DIR);
1141 if (hostdata->state != S_RUNNING_LEVEL2)
1142 hostdata->state = S_CONNECTED;
1143 break;
1144
1145
1146
1147
1148 case CSR_XFER_DONE | PHS_COMMAND:
1149 case CSR_UNEXP | PHS_COMMAND:
1150 case CSR_SRV_REQ | PHS_COMMAND:
1151 DB(DB_INTR, printk("CMND-%02x", cmd->cmnd[0]))
1152 transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
1153 hostdata->state = S_CONNECTED;
1154 break;
1155
1156
1157 case CSR_XFER_DONE | PHS_STATUS:
1158 case CSR_UNEXP | PHS_STATUS:
1159 case CSR_SRV_REQ | PHS_STATUS:
1160 DB(DB_INTR, printk("STATUS="))
1161
1162 cmd->SCp.Status = read_1_byte(hostdata);
1163 DB(DB_INTR, printk("%02x", cmd->SCp.Status))
1164 if (hostdata->level2 >= L2_BASIC) {
1165 sr = read_3393(hostdata, WD_SCSI_STATUS);
1166 hostdata->state = S_RUNNING_LEVEL2;
1167 write_3393(hostdata, WD_COMMAND_PHASE, 0x50);
1168 write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER);
1169 } else {
1170 hostdata->state = S_CONNECTED;
1171 }
1172 break;
1173
1174
1175 case CSR_XFER_DONE | PHS_MESS_IN:
1176 case CSR_UNEXP | PHS_MESS_IN:
1177 case CSR_SRV_REQ | PHS_MESS_IN:
1178 DB(DB_INTR, printk("MSG_IN="))
1179
1180 msg = read_1_byte(hostdata);
1181 sr = read_3393(hostdata, WD_SCSI_STATUS);
1182
1183 hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
1184 if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
1185 msg = EXTENDED_MESSAGE;
1186 else
1187 hostdata->incoming_ptr = 0;
1188
1189 cmd->SCp.Message = msg;
1190 switch (msg) {
1191
1192 case COMMAND_COMPLETE:
1193 DB(DB_INTR, printk("CCMP"))
1194 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1195 hostdata->state = S_PRE_CMP_DISC;
1196 break;
1197
1198 case SAVE_POINTERS:
1199 DB(DB_INTR, printk("SDP"))
1200 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1201 hostdata->state = S_CONNECTED;
1202 break;
1203
1204 case RESTORE_POINTERS:
1205 DB(DB_INTR, printk("RDP"))
1206 if (hostdata->level2 >= L2_BASIC) {
1207 write_3393(hostdata, WD_COMMAND_PHASE, 0x45);
1208 write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER);
1209 hostdata->state = S_RUNNING_LEVEL2;
1210 } else {
1211 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1212 hostdata->state = S_CONNECTED;
1213 }
1214 break;
1215
1216 case DISCONNECT:
1217 DB(DB_INTR, printk("DIS"))
1218 cmd->device->disconnect = 1;
1219 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1220 hostdata->state = S_PRE_TMP_DISC;
1221 break;
1222
1223 case MESSAGE_REJECT:
1224 DB(DB_INTR, printk("REJ"))
1225#ifdef SYNC_DEBUG
1226 printk("-REJ-");
1227#endif
1228 if (hostdata->sync_stat[cmd->device->id] == SS_WAITING)
1229 hostdata->sync_stat[cmd->device->id] = SS_SET;
1230 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1231 hostdata->state = S_CONNECTED;
1232 break;
1233
1234 case EXTENDED_MESSAGE:
1235 DB(DB_INTR, printk("EXT"))
1236
1237 ucp = hostdata->incoming_msg;
1238
1239#ifdef SYNC_DEBUG
1240 printk("%02x", ucp[hostdata->incoming_ptr]);
1241#endif
1242
1243
1244 if ((hostdata->incoming_ptr >= 2) && (hostdata->incoming_ptr == (ucp[1] + 1))) {
1245
1246 switch (ucp[2]) {
1247 case EXTENDED_SDTR:
1248 id = calc_sync_xfer(ucp[3], ucp[4]);
1249 if (hostdata->sync_stat[cmd->device->id] != SS_WAITING) {
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260 write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN);
1261 hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
1262 hostdata->outgoing_msg[1] = 3;
1263 hostdata->outgoing_msg[2] = EXTENDED_SDTR;
1264 hostdata->outgoing_msg[3] = hostdata->default_sx_per / 4;
1265 hostdata->outgoing_msg[4] = 0;
1266 hostdata->outgoing_len = 5;
1267 hostdata->sync_xfer[cmd->device->id] = calc_sync_xfer(hostdata->default_sx_per / 4, 0);
1268 } else {
1269 hostdata->sync_xfer[cmd->device->id] = id;
1270 }
1271#ifdef SYNC_DEBUG
1272 printk("sync_xfer=%02x", hostdata->sync_xfer[cmd->device->id]);
1273#endif
1274 hostdata->sync_stat[cmd->device->id] = SS_SET;
1275 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1276 hostdata->state = S_CONNECTED;
1277 break;
1278 case EXTENDED_WDTR:
1279 write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN);
1280 printk("sending WDTR ");
1281 hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
1282 hostdata->outgoing_msg[1] = 2;
1283 hostdata->outgoing_msg[2] = EXTENDED_WDTR;
1284 hostdata->outgoing_msg[3] = 0;
1285 hostdata->outgoing_len = 4;
1286 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1287 hostdata->state = S_CONNECTED;
1288 break;
1289 default:
1290 write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN);
1291 printk("Rejecting Unknown Extended Message(%02x). ", ucp[2]);
1292 hostdata->outgoing_msg[0] = MESSAGE_REJECT;
1293 hostdata->outgoing_len = 1;
1294 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1295 hostdata->state = S_CONNECTED;
1296 break;
1297 }
1298 hostdata->incoming_ptr = 0;
1299 }
1300
1301
1302
1303 else {
1304 hostdata->incoming_ptr++;
1305 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1306 hostdata->state = S_CONNECTED;
1307 }
1308 break;
1309
1310 default:
1311 printk("Rejecting Unknown Message(%02x) ", msg);
1312 write_3393_cmd(hostdata, WD_CMD_ASSERT_ATN);
1313 hostdata->outgoing_msg[0] = MESSAGE_REJECT;
1314 hostdata->outgoing_len = 1;
1315 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1316 hostdata->state = S_CONNECTED;
1317 }
1318 break;
1319
1320
1321
1322
1323 case CSR_SEL_XFER_DONE:
1324
1325
1326
1327
1328
1329 write_3393(hostdata, WD_SOURCE_ID, SRCID_ER);
1330 if (phs == 0x60) {
1331 DB(DB_INTR, printk("SX-DONE"))
1332 cmd->SCp.Message = COMMAND_COMPLETE;
1333 lun = read_3393(hostdata, WD_TARGET_LUN);
1334 DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun))
1335 hostdata->connected = NULL;
1336 hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
1337 hostdata->state = S_UNCONNECTED;
1338 if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE)
1339 cmd->SCp.Status = lun;
1340 if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
1341 cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
1342 else
1343 cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
1344 cmd->scsi_done(cmd);
1345
1346
1347
1348
1349
1350 in2000_execute(instance);
1351 } else {
1352 printk("%02x:%02x:%02x: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs);
1353 }
1354 break;
1355
1356
1357
1358
1359 case CSR_SDP:
1360 DB(DB_INTR, printk("SDP"))
1361 hostdata->state = S_RUNNING_LEVEL2;
1362 write_3393(hostdata, WD_COMMAND_PHASE, 0x41);
1363 write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER);
1364 break;
1365
1366
1367 case CSR_XFER_DONE | PHS_MESS_OUT:
1368 case CSR_UNEXP | PHS_MESS_OUT:
1369 case CSR_SRV_REQ | PHS_MESS_OUT:
1370 DB(DB_INTR, printk("MSG_OUT="))
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384 if (hostdata->outgoing_len == 0) {
1385 hostdata->outgoing_len = 1;
1386 hostdata->outgoing_msg[0] = NOP;
1387 }
1388 transfer_pio(hostdata->outgoing_msg, hostdata->outgoing_len, DATA_OUT_DIR, hostdata);
1389 DB(DB_INTR, printk("%02x", hostdata->outgoing_msg[0]))
1390 hostdata->outgoing_len = 0;
1391 hostdata->state = S_CONNECTED;
1392 break;
1393
1394
1395 case CSR_UNEXP_DISC:
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410 write_3393(hostdata, WD_SOURCE_ID, SRCID_ER);
1411 if (cmd == NULL) {
1412 printk(" - Already disconnected! ");
1413 hostdata->state = S_UNCONNECTED;
1414
1415
1416 spin_unlock_irqrestore(instance->host_lock, flags);
1417 return IRQ_HANDLED;
1418 }
1419 DB(DB_INTR, printk("UNEXP_DISC"))
1420 hostdata->connected = NULL;
1421 hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
1422 hostdata->state = S_UNCONNECTED;
1423 if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
1424 cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
1425 else
1426 cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
1427 cmd->scsi_done(cmd);
1428
1429
1430
1431
1432
1433 in2000_execute(instance);
1434 break;
1435
1436
1437 case CSR_DISC:
1438
1439
1440
1441
1442
1443 write_3393(hostdata, WD_SOURCE_ID, SRCID_ER);
1444 DB(DB_INTR, printk("DISC"))
1445 if (cmd == NULL) {
1446 printk(" - Already disconnected! ");
1447 hostdata->state = S_UNCONNECTED;
1448 }
1449 switch (hostdata->state) {
1450 case S_PRE_CMP_DISC:
1451 hostdata->connected = NULL;
1452 hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
1453 hostdata->state = S_UNCONNECTED;
1454 DB(DB_INTR, printk(":%d", cmd->SCp.Status))
1455 if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
1456 cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
1457 else
1458 cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
1459 cmd->scsi_done(cmd);
1460 break;
1461 case S_PRE_TMP_DISC:
1462 case S_RUNNING_LEVEL2:
1463 cmd->host_scribble = (uchar *) hostdata->disconnected_Q;
1464 hostdata->disconnected_Q = cmd;
1465 hostdata->connected = NULL;
1466 hostdata->state = S_UNCONNECTED;
1467
1468#ifdef PROC_STATISTICS
1469 hostdata->disc_done_cnt[cmd->device->id]++;
1470#endif
1471
1472 break;
1473 default:
1474 printk("*** Unexpected DISCONNECT interrupt! ***");
1475 hostdata->state = S_UNCONNECTED;
1476 }
1477
1478
1479
1480
1481
1482 in2000_execute(instance);
1483 break;
1484
1485
1486 case CSR_RESEL_AM:
1487 DB(DB_INTR, printk("RESEL"))
1488
1489
1490
1491
1492 if (hostdata->level2 <= L2_NONE) {
1493
1494 if (hostdata->selecting) {
1495 cmd = (Scsi_Cmnd *) hostdata->selecting;
1496 hostdata->selecting = NULL;
1497 hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
1498 cmd->host_scribble = (uchar *) hostdata->input_Q;
1499 hostdata->input_Q = cmd;
1500 }
1501 }
1502
1503 else {
1504
1505 if (cmd) {
1506 if (phs == 0x00) {
1507 hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
1508 cmd->host_scribble = (uchar *) hostdata->input_Q;
1509 hostdata->input_Q = cmd;
1510 } else {
1511 printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---", asr, sr, phs);
1512 while (1)
1513 printk("\r");
1514 }
1515 }
1516
1517 }
1518
1519
1520
1521 id = read_3393(hostdata, WD_SOURCE_ID);
1522 id &= SRCID_MASK;
1523
1524
1525
1526
1527
1528
1529 lun = read_3393(hostdata, WD_DATA);
1530 if (hostdata->level2 < L2_RESELECT)
1531 write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK);
1532 lun &= 7;
1533
1534
1535
1536 cmd = (Scsi_Cmnd *) hostdata->disconnected_Q;
1537 patch = NULL;
1538 while (cmd) {
1539 if (id == cmd->device->id && lun == cmd->device->lun)
1540 break;
1541 patch = cmd;
1542 cmd = (Scsi_Cmnd *) cmd->host_scribble;
1543 }
1544
1545
1546
1547 if (!cmd) {
1548 printk("---TROUBLE: target %d.%d not in disconnect queue---", id, lun);
1549 break;
1550 }
1551
1552
1553
1554 if (patch)
1555 patch->host_scribble = cmd->host_scribble;
1556 else
1557 hostdata->disconnected_Q = (Scsi_Cmnd *) cmd->host_scribble;
1558 hostdata->connected = cmd;
1559
1560
1561
1562
1563
1564
1565 if (is_dir_out(cmd))
1566 write_3393(hostdata, WD_DESTINATION_ID, cmd->device->id);
1567 else
1568 write_3393(hostdata, WD_DESTINATION_ID, cmd->device->id | DSTID_DPD);
1569 if (hostdata->level2 >= L2_RESELECT) {
1570 write_3393_count(hostdata, 0);
1571 write_3393(hostdata, WD_COMMAND_PHASE, 0x45);
1572 write_3393_cmd(hostdata, WD_CMD_SEL_ATN_XFER);
1573 hostdata->state = S_RUNNING_LEVEL2;
1574 } else
1575 hostdata->state = S_CONNECTED;
1576
1577 break;
1578
1579 default:
1580 printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--", asr, sr, phs);
1581 }
1582
1583 write1_io(0, IO_LED_OFF);
1584
1585 DB(DB_INTR, printk("} "))
1586
1587
1588 spin_unlock_irqrestore(instance->host_lock, flags);
1589 return IRQ_HANDLED;
1590}
1591
1592
1593
1594#define RESET_CARD 0
1595#define RESET_CARD_AND_BUS 1
1596#define B_FLAG 0x80
1597
1598
1599
1600
1601
1602static int reset_hardware(struct Scsi_Host *instance, int type)
1603{
1604 struct IN2000_hostdata *hostdata;
1605 int qt, x;
1606
1607 hostdata = (struct IN2000_hostdata *) instance->hostdata;
1608
1609 write1_io(0, IO_LED_ON);
1610 if (type == RESET_CARD_AND_BUS) {
1611 write1_io(0, IO_CARD_RESET);
1612 x = read1_io(IO_HARDWARE);
1613 }
1614 x = read_3393(hostdata, WD_SCSI_STATUS);
1615 write_3393(hostdata, WD_OWN_ID, instance->this_id | OWNID_EAF | OWNID_RAF | OWNID_FS_8);
1616 write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1617 write_3393(hostdata, WD_SYNCHRONOUS_TRANSFER, calc_sync_xfer(hostdata->default_sx_per / 4, DEFAULT_SX_OFF));
1618
1619 write1_io(0, IO_FIFO_WRITE);
1620 write1_io(0, IO_FIFO_READ);
1621 write_3393(hostdata, WD_COMMAND, WD_CMD_RESET);
1622
1623 while (!(READ_AUX_STAT() & ASR_INT))
1624 cpu_relax();
1625
1626 x = read_3393(hostdata, WD_SCSI_STATUS);
1627
1628 write_3393(hostdata, WD_QUEUE_TAG, 0xa5);
1629 qt = read_3393(hostdata, WD_QUEUE_TAG);
1630 if (qt == 0xa5) {
1631 x |= B_FLAG;
1632 write_3393(hostdata, WD_QUEUE_TAG, 0);
1633 }
1634 write_3393(hostdata, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
1635 write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1636 write1_io(0, IO_LED_OFF);
1637 return x;
1638}
1639
1640
1641
1642static int in2000_bus_reset(Scsi_Cmnd * cmd)
1643{
1644 struct Scsi_Host *instance;
1645 struct IN2000_hostdata *hostdata;
1646 int x;
1647 unsigned long flags;
1648
1649 instance = cmd->device->host;
1650 hostdata = (struct IN2000_hostdata *) instance->hostdata;
1651
1652 printk(KERN_WARNING "scsi%d: Reset. ", instance->host_no);
1653
1654 spin_lock_irqsave(instance->host_lock, flags);
1655
1656
1657 reset_hardware(instance, RESET_CARD_AND_BUS);
1658 for (x = 0; x < 8; x++) {
1659 hostdata->busy[x] = 0;
1660 hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF);
1661 hostdata->sync_stat[x] = SS_UNSET;
1662 }
1663 hostdata->input_Q = NULL;
1664 hostdata->selecting = NULL;
1665 hostdata->connected = NULL;
1666 hostdata->disconnected_Q = NULL;
1667 hostdata->state = S_UNCONNECTED;
1668 hostdata->fifo = FI_FIFO_UNUSED;
1669 hostdata->incoming_ptr = 0;
1670 hostdata->outgoing_len = 0;
1671
1672 cmd->result = DID_RESET << 16;
1673
1674 spin_unlock_irqrestore(instance->host_lock, flags);
1675 return SUCCESS;
1676}
1677
1678static int __in2000_abort(Scsi_Cmnd * cmd)
1679{
1680 struct Scsi_Host *instance;
1681 struct IN2000_hostdata *hostdata;
1682 Scsi_Cmnd *tmp, *prev;
1683 uchar sr, asr;
1684 unsigned long timeout;
1685
1686 instance = cmd->device->host;
1687 hostdata = (struct IN2000_hostdata *) instance->hostdata;
1688
1689 printk(KERN_DEBUG "scsi%d: Abort-", instance->host_no);
1690 printk("(asr=%02x,count=%ld,resid=%d,buf_resid=%d,have_data=%d,FC=%02x)- ", READ_AUX_STAT(), read_3393_count(hostdata), cmd->SCp.this_residual, cmd->SCp.buffers_residual, cmd->SCp.have_data_in, read1_io(IO_FIFO_COUNT));
1691
1692
1693
1694
1695
1696
1697 tmp = (Scsi_Cmnd *) hostdata->input_Q;
1698 prev = NULL;
1699 while (tmp) {
1700 if (tmp == cmd) {
1701 if (prev)
1702 prev->host_scribble = cmd->host_scribble;
1703 cmd->host_scribble = NULL;
1704 cmd->result = DID_ABORT << 16;
1705 printk(KERN_WARNING "scsi%d: Abort - removing command from input_Q. ", instance->host_no);
1706 cmd->scsi_done(cmd);
1707 return SUCCESS;
1708 }
1709 prev = tmp;
1710 tmp = (Scsi_Cmnd *) tmp->host_scribble;
1711 }
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724 if (hostdata->connected == cmd) {
1725
1726 printk(KERN_WARNING "scsi%d: Aborting connected command - ", instance->host_no);
1727
1728 printk("sending wd33c93 ABORT command - ");
1729 write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1730 write_3393_cmd(hostdata, WD_CMD_ABORT);
1731
1732
1733
1734 printk("flushing fifo - ");
1735 timeout = 1000000;
1736 do {
1737 asr = READ_AUX_STAT();
1738 if (asr & ASR_DBR)
1739 read_3393(hostdata, WD_DATA);
1740 } while (!(asr & ASR_INT) && timeout-- > 0);
1741 sr = read_3393(hostdata, WD_SCSI_STATUS);
1742 printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ", asr, sr, read_3393_count(hostdata), timeout);
1743
1744
1745
1746
1747
1748
1749
1750 printk("sending wd33c93 DISCONNECT command - ");
1751 write_3393_cmd(hostdata, WD_CMD_DISCONNECT);
1752
1753 timeout = 1000000;
1754 asr = READ_AUX_STAT();
1755 while ((asr & ASR_CIP) && timeout-- > 0)
1756 asr = READ_AUX_STAT();
1757 sr = read_3393(hostdata, WD_SCSI_STATUS);
1758 printk("asr=%02x, sr=%02x.", asr, sr);
1759
1760 hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun);
1761 hostdata->connected = NULL;
1762 hostdata->state = S_UNCONNECTED;
1763 cmd->result = DID_ABORT << 16;
1764 cmd->scsi_done(cmd);
1765
1766 in2000_execute(instance);
1767
1768 return SUCCESS;
1769 }
1770
1771
1772
1773
1774
1775
1776
1777 for (tmp = (Scsi_Cmnd *) hostdata->disconnected_Q; tmp; tmp = (Scsi_Cmnd *) tmp->host_scribble)
1778 if (cmd == tmp) {
1779 printk(KERN_DEBUG "scsi%d: unable to abort disconnected command.\n", instance->host_no);
1780 return FAILED;
1781 }
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793 in2000_execute(instance);
1794
1795 printk("scsi%d: warning : SCSI command probably completed successfully" " before abortion. ", instance->host_no);
1796 return SUCCESS;
1797}
1798
1799static int in2000_abort(Scsi_Cmnd * cmd)
1800{
1801 int rc;
1802
1803 spin_lock_irq(cmd->device->host->host_lock);
1804 rc = __in2000_abort(cmd);
1805 spin_unlock_irq(cmd->device->host->host_lock);
1806
1807 return rc;
1808}
1809
1810
1811#define MAX_IN2000_HOSTS 3
1812#define MAX_SETUP_ARGS ARRAY_SIZE(setup_args)
1813#define SETUP_BUFFER_SIZE 200
1814static char setup_buffer[SETUP_BUFFER_SIZE];
1815static char setup_used[MAX_SETUP_ARGS];
1816static int done_setup = 0;
1817
1818static void __init in2000_setup(char *str, int *ints)
1819{
1820 int i;
1821 char *p1, *p2;
1822
1823 strlcpy(setup_buffer, str, SETUP_BUFFER_SIZE);
1824 p1 = setup_buffer;
1825 i = 0;
1826 while (*p1 && (i < MAX_SETUP_ARGS)) {
1827 p2 = strchr(p1, ',');
1828 if (p2) {
1829 *p2 = '\0';
1830 if (p1 != p2)
1831 setup_args[i] = p1;
1832 p1 = p2 + 1;
1833 i++;
1834 } else {
1835 setup_args[i] = p1;
1836 break;
1837 }
1838 }
1839 for (i = 0; i < MAX_SETUP_ARGS; i++)
1840 setup_used[i] = 0;
1841 done_setup = 1;
1842}
1843
1844
1845
1846
1847
1848static int __init check_setup_args(char *key, int *val, char *buf)
1849{
1850 int x;
1851 char *cp;
1852
1853 for (x = 0; x < MAX_SETUP_ARGS; x++) {
1854 if (setup_used[x])
1855 continue;
1856 if (!strncmp(setup_args[x], key, strlen(key)))
1857 break;
1858 }
1859 if (x == MAX_SETUP_ARGS)
1860 return 0;
1861 setup_used[x] = 1;
1862 cp = setup_args[x] + strlen(key);
1863 *val = -1;
1864 if (*cp != ':')
1865 return ++x;
1866 cp++;
1867 if ((*cp >= '0') && (*cp <= '9')) {
1868 *val = simple_strtoul(cp, NULL, 0);
1869 }
1870 return ++x;
1871}
1872
1873
1874
1875
1876
1877
1878
1879
1880static u32 bios_tab[] in2000__INITDATA = {
1881 0xc8000,
1882 0xd0000,
1883 0xd8000,
1884 0
1885};
1886
1887static unsigned short base_tab[] in2000__INITDATA = {
1888 0x220,
1889 0x200,
1890 0x110,
1891 0x100,
1892};
1893
1894static int int_tab[] in2000__INITDATA = {
1895 15,
1896 14,
1897 11,
1898 10
1899};
1900
1901static int probe_bios(u32 addr, u32 *s1, uchar *switches)
1902{
1903 void __iomem *p = ioremap(addr, 0x34);
1904 if (!p)
1905 return 0;
1906 *s1 = readl(p + 0x10);
1907 if (*s1 == 0x41564f4e || readl(p + 0x30) == 0x61776c41) {
1908
1909 *switches = ~readb(p + 0x20);
1910 iounmap(p);
1911 return 1;
1912 }
1913 iounmap(p);
1914 return 0;
1915}
1916
1917static int __init in2000_detect(struct scsi_host_template * tpnt)
1918{
1919 struct Scsi_Host *instance;
1920 struct IN2000_hostdata *hostdata;
1921 int detect_count;
1922 int bios;
1923 int x;
1924 unsigned short base;
1925 uchar switches;
1926 uchar hrev;
1927 unsigned long flags;
1928 int val;
1929 char buf[32];
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943 if (!done_setup && setup_strings)
1944 in2000_setup(setup_strings, NULL);
1945
1946 detect_count = 0;
1947 for (bios = 0; bios_tab[bios]; bios++) {
1948 u32 s1 = 0;
1949 if (check_setup_args("ioport", &val, buf)) {
1950 base = val;
1951 switches = ~inb(base + IO_SWITCHES) & 0xff;
1952 printk("Forcing IN2000 detection at IOport 0x%x ", base);
1953 bios = 2;
1954 }
1955
1956
1957
1958
1959
1960 else if (probe_bios(bios_tab[bios], &s1, &switches)) {
1961 printk("Found IN2000 BIOS at 0x%x ", (unsigned int) bios_tab[bios]);
1962
1963
1964
1965 x = switches & (SW_ADDR0 | SW_ADDR1);
1966 base = base_tab[x];
1967
1968
1969
1970 x = ~inb(base + IO_SWITCHES) & 0xff;
1971 if (x != switches) {
1972 printk("Bad IO signature: %02x vs %02x.\n", x, switches);
1973 continue;
1974 }
1975 } else
1976 continue;
1977
1978
1979
1980 if (!(switches & SW_BIT7)) {
1981 printk("There is no IN-2000 SCSI card at IOport 0x%03x!\n", base);
1982 continue;
1983 }
1984
1985
1986
1987
1988
1989
1990 hrev = inb(base + IO_HARDWARE);
1991
1992
1993 if (switches & SW_DISINT) {
1994 printk("The IN-2000 SCSI card at IOport 0x%03x ", base);
1995 printk("is not configured for interrupt operation!\n");
1996 printk("This driver requires an interrupt: cancelling detection.\n");
1997 continue;
1998 }
1999
2000
2001
2002
2003
2004 tpnt->proc_name = "in2000";
2005 instance = scsi_register(tpnt, sizeof(struct IN2000_hostdata));
2006 if (instance == NULL)
2007 continue;
2008 detect_count++;
2009 hostdata = (struct IN2000_hostdata *) instance->hostdata;
2010 instance->io_port = hostdata->io_base = base;
2011 hostdata->dip_switch = switches;
2012 hostdata->hrev = hrev;
2013
2014 write1_io(0, IO_FIFO_WRITE);
2015 write1_io(0, IO_FIFO_READ);
2016 write1_io(0, IO_INTR_MASK);
2017 x = int_tab[(switches & (SW_INT0 | SW_INT1)) >> SW_INT_SHIFT];
2018 if (request_irq(x, in2000_intr, IRQF_DISABLED, "in2000", instance)) {
2019 printk("in2000_detect: Unable to allocate IRQ.\n");
2020 detect_count--;
2021 continue;
2022 }
2023 instance->irq = x;
2024 instance->n_io_port = 13;
2025 request_region(base, 13, "in2000");
2026
2027 for (x = 0; x < 8; x++) {
2028 hostdata->busy[x] = 0;
2029 hostdata->sync_xfer[x] = calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF);
2030 hostdata->sync_stat[x] = SS_UNSET;
2031#ifdef PROC_STATISTICS
2032 hostdata->cmd_cnt[x] = 0;
2033 hostdata->disc_allowed_cnt[x] = 0;
2034 hostdata->disc_done_cnt[x] = 0;
2035#endif
2036 }
2037 hostdata->input_Q = NULL;
2038 hostdata->selecting = NULL;
2039 hostdata->connected = NULL;
2040 hostdata->disconnected_Q = NULL;
2041 hostdata->state = S_UNCONNECTED;
2042 hostdata->fifo = FI_FIFO_UNUSED;
2043 hostdata->level2 = L2_BASIC;
2044 hostdata->disconnect = DIS_ADAPTIVE;
2045 hostdata->args = DEBUG_DEFAULTS;
2046 hostdata->incoming_ptr = 0;
2047 hostdata->outgoing_len = 0;
2048 hostdata->default_sx_per = DEFAULT_SX_PER;
2049
2050
2051
2052 if (s1 == 0x41564f4e && (switches & SW_SYNC_DOS5))
2053 hostdata->sync_off = 0x00;
2054 else
2055 hostdata->sync_off = 0xff;
2056
2057#ifdef PROC_INTERFACE
2058 hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS | PR_CONNECTED | PR_INPUTQ | PR_DISCQ | PR_STOP;
2059#ifdef PROC_STATISTICS
2060 hostdata->int_cnt = 0;
2061#endif
2062#endif
2063
2064 if (check_setup_args("nosync", &val, buf))
2065 hostdata->sync_off = val;
2066
2067 if (check_setup_args("period", &val, buf))
2068 hostdata->default_sx_per = sx_table[round_period((unsigned int) val)].period_ns;
2069
2070 if (check_setup_args("disconnect", &val, buf)) {
2071 if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
2072 hostdata->disconnect = val;
2073 else
2074 hostdata->disconnect = DIS_ADAPTIVE;
2075 }
2076
2077 if (check_setup_args("noreset", &val, buf))
2078 hostdata->args ^= A_NO_SCSI_RESET;
2079
2080 if (check_setup_args("level2", &val, buf))
2081 hostdata->level2 = val;
2082
2083 if (check_setup_args("debug", &val, buf))
2084 hostdata->args = (val & DB_MASK);
2085
2086#ifdef PROC_INTERFACE
2087 if (check_setup_args("proc", &val, buf))
2088 hostdata->proc = val;
2089#endif
2090
2091
2092
2093
2094 spin_lock_irqsave(instance->host_lock, flags);
2095 x = reset_hardware(instance, (hostdata->args & A_NO_SCSI_RESET) ? RESET_CARD : RESET_CARD_AND_BUS);
2096 spin_unlock_irqrestore(instance->host_lock, flags);
2097
2098 hostdata->microcode = read_3393(hostdata, WD_CDB_1);
2099 if (x & 0x01) {
2100 if (x & B_FLAG)
2101 hostdata->chip = C_WD33C93B;
2102 else
2103 hostdata->chip = C_WD33C93A;
2104 } else
2105 hostdata->chip = C_WD33C93;
2106
2107 printk("dip_switch=%02x irq=%d ioport=%02x floppy=%s sync/DOS5=%s ", (switches & 0x7f), instance->irq, hostdata->io_base, (switches & SW_FLOPPY) ? "Yes" : "No", (switches & SW_SYNC_DOS5) ? "Yes" : "No");
2108 printk("hardware_ver=%02x chip=%s microcode=%02x\n", hrev, (hostdata->chip == C_WD33C93) ? "WD33c93" : (hostdata->chip == C_WD33C93A) ? "WD33c93A" : (hostdata->chip == C_WD33C93B) ? "WD33c93B" : "unknown", hostdata->microcode);
2109#ifdef DEBUGGING_ON
2110 printk("setup_args = ");
2111 for (x = 0; x < MAX_SETUP_ARGS; x++)
2112 printk("%s,", setup_args[x]);
2113 printk("\n");
2114#endif
2115 if (hostdata->sync_off == 0xff)
2116 printk("Sync-transfer DISABLED on all devices: ENABLE from command-line\n");
2117 printk("IN2000 driver version %s - %s\n", IN2000_VERSION, IN2000_DATE);
2118 }
2119
2120 return detect_count;
2121}
2122
2123static int in2000_release(struct Scsi_Host *shost)
2124{
2125 if (shost->irq)
2126 free_irq(shost->irq, shost);
2127 if (shost->io_port && shost->n_io_port)
2128 release_region(shost->io_port, shost->n_io_port);
2129 return 0;
2130}
2131
2132
2133
2134
2135
2136
2137static int in2000_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int *iinfo)
2138{
2139 int size;
2140
2141 size = capacity;
2142 iinfo[0] = 64;
2143 iinfo[1] = 32;
2144 iinfo[2] = size >> 11;
2145
2146
2147
2148
2149
2150 if (iinfo[2] > 1024) {
2151 iinfo[0] = 64;
2152 iinfo[1] = 63;
2153 iinfo[2] = (unsigned long) capacity / (iinfo[0] * iinfo[1]);
2154 }
2155 if (iinfo[2] > 1024) {
2156 iinfo[0] = 128;
2157 iinfo[1] = 63;
2158 iinfo[2] = (unsigned long) capacity / (iinfo[0] * iinfo[1]);
2159 }
2160 if (iinfo[2] > 1024) {
2161 iinfo[0] = 255;
2162 iinfo[1] = 63;
2163 iinfo[2] = (unsigned long) capacity / (iinfo[0] * iinfo[1]);
2164 }
2165 return 0;
2166}
2167
2168
2169static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in)
2170{
2171
2172#ifdef PROC_INTERFACE
2173
2174 char *bp;
2175 char tbuf[128];
2176 unsigned long flags;
2177 struct IN2000_hostdata *hd;
2178 Scsi_Cmnd *cmd;
2179 int x, i;
2180 static int stop = 0;
2181
2182 hd = (struct IN2000_hostdata *) instance->hostdata;
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193 if (in) {
2194 buf[len] = '\0';
2195 bp = buf;
2196 if (!strncmp(bp, "debug:", 6)) {
2197 bp += 6;
2198 hd->args = simple_strtoul(bp, NULL, 0) & DB_MASK;
2199 } else if (!strncmp(bp, "disconnect:", 11)) {
2200 bp += 11;
2201 x = simple_strtoul(bp, NULL, 0);
2202 if (x < DIS_NEVER || x > DIS_ALWAYS)
2203 x = DIS_ADAPTIVE;
2204 hd->disconnect = x;
2205 } else if (!strncmp(bp, "period:", 7)) {
2206 bp += 7;
2207 x = simple_strtoul(bp, NULL, 0);
2208 hd->default_sx_per = sx_table[round_period((unsigned int) x)].period_ns;
2209 } else if (!strncmp(bp, "resync:", 7)) {
2210 bp += 7;
2211 x = simple_strtoul(bp, NULL, 0);
2212 for (i = 0; i < 7; i++)
2213 if (x & (1 << i))
2214 hd->sync_stat[i] = SS_UNSET;
2215 } else if (!strncmp(bp, "proc:", 5)) {
2216 bp += 5;
2217 hd->proc = simple_strtoul(bp, NULL, 0);
2218 } else if (!strncmp(bp, "level2:", 7)) {
2219 bp += 7;
2220 hd->level2 = simple_strtoul(bp, NULL, 0);
2221 }
2222 return len;
2223 }
2224
2225 spin_lock_irqsave(instance->host_lock, flags);
2226 bp = buf;
2227 *bp = '\0';
2228 if (hd->proc & PR_VERSION) {
2229 sprintf(tbuf, "\nVersion %s - %s.", IN2000_VERSION, IN2000_DATE);
2230 strcat(bp, tbuf);
2231 }
2232 if (hd->proc & PR_INFO) {
2233 sprintf(tbuf, "\ndip_switch=%02x: irq=%d io=%02x floppy=%s sync/DOS5=%s", (hd->dip_switch & 0x7f), instance->irq, hd->io_base, (hd->dip_switch & 0x40) ? "Yes" : "No", (hd->dip_switch & 0x20) ? "Yes" : "No");
2234 strcat(bp, tbuf);
2235 strcat(bp, "\nsync_xfer[] = ");
2236 for (x = 0; x < 7; x++) {
2237 sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);
2238 strcat(bp, tbuf);
2239 }
2240 strcat(bp, "\nsync_stat[] = ");
2241 for (x = 0; x < 7; x++) {
2242 sprintf(tbuf, "\t%02x", hd->sync_stat[x]);
2243 strcat(bp, tbuf);
2244 }
2245 }
2246#ifdef PROC_STATISTICS
2247 if (hd->proc & PR_STATISTICS) {
2248 strcat(bp, "\ncommands issued: ");
2249 for (x = 0; x < 7; x++) {
2250 sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);
2251 strcat(bp, tbuf);
2252 }
2253 strcat(bp, "\ndisconnects allowed:");
2254 for (x = 0; x < 7; x++) {
2255 sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);
2256 strcat(bp, tbuf);
2257 }
2258 strcat(bp, "\ndisconnects done: ");
2259 for (x = 0; x < 7; x++) {
2260 sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);
2261 strcat(bp, tbuf);
2262 }
2263 sprintf(tbuf, "\ninterrupts: \t%ld", hd->int_cnt);
2264 strcat(bp, tbuf);
2265 }
2266#endif
2267 if (hd->proc & PR_CONNECTED) {
2268 strcat(bp, "\nconnected: ");
2269 if (hd->connected) {
2270 cmd = (Scsi_Cmnd *) hd->connected;
2271 sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2272 strcat(bp, tbuf);
2273 }
2274 }
2275 if (hd->proc & PR_INPUTQ) {
2276 strcat(bp, "\ninput_Q: ");
2277 cmd = (Scsi_Cmnd *) hd->input_Q;
2278 while (cmd) {
2279 sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2280 strcat(bp, tbuf);
2281 cmd = (Scsi_Cmnd *) cmd->host_scribble;
2282 }
2283 }
2284 if (hd->proc & PR_DISCQ) {
2285 strcat(bp, "\ndisconnected_Q:");
2286 cmd = (Scsi_Cmnd *) hd->disconnected_Q;
2287 while (cmd) {
2288 sprintf(tbuf, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2289 strcat(bp, tbuf);
2290 cmd = (Scsi_Cmnd *) cmd->host_scribble;
2291 }
2292 }
2293 if (hd->proc & PR_TEST) {
2294 ;
2295 }
2296 strcat(bp, "\n");
2297 spin_unlock_irqrestore(instance->host_lock, flags);
2298 *start = buf;
2299 if (stop) {
2300 stop = 0;
2301 return 0;
2302 }
2303 if (off > 0x40000)
2304 stop = 1;
2305 if (hd->proc & PR_STOP)
2306 stop = 1;
2307 return strlen(bp);
2308
2309#else
2310
2311 return 0;
2312
2313#endif
2314
2315}
2316
2317MODULE_LICENSE("GPL");
2318
2319
2320static struct scsi_host_template driver_template = {
2321 .proc_name = "in2000",
2322 .proc_info = in2000_proc_info,
2323 .name = "Always IN2000",
2324 .detect = in2000_detect,
2325 .release = in2000_release,
2326 .queuecommand = in2000_queuecommand,
2327 .eh_abort_handler = in2000_abort,
2328 .eh_bus_reset_handler = in2000_bus_reset,
2329 .bios_param = in2000_biosparam,
2330 .can_queue = IN2000_CAN_Q,
2331 .this_id = IN2000_HOST_ID,
2332 .sg_tablesize = IN2000_SG,
2333 .cmd_per_lun = IN2000_CPL,
2334 .use_clustering = DISABLE_CLUSTERING,
2335};
2336#include "scsi_module.c"
2337