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