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