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