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