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-%ld( ", cmd->device->id, cmd->cmnd[0], cmd->serial_number))
385
386
387
388
389
390
391 cmd->host_scribble = NULL;
392 cmd->scsi_done = done;
393 cmd->result = 0;
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410 if (scsi_bufflen(cmd)) {
411 cmd->SCp.buffer = scsi_sglist(cmd);
412 cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
413 cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
414 cmd->SCp.this_residual = cmd->SCp.buffer->length;
415 } else {
416 cmd->SCp.buffer = NULL;
417 cmd->SCp.buffers_residual = 0;
418 cmd->SCp.ptr = NULL;
419 cmd->SCp.this_residual = 0;
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439 cmd->SCp.Status = ILLEGAL_STATUS_BYTE;
440
441
442
443
444
445
446
447 spin_lock_irq(&hostdata->lock);
448
449 if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
450 cmd->host_scribble = (uchar *) hostdata->input_Q;
451 hostdata->input_Q = cmd;
452 } else {
453 for (tmp = (struct scsi_cmnd *) hostdata->input_Q;
454 tmp->host_scribble;
455 tmp = (struct scsi_cmnd *) tmp->host_scribble) ;
456 tmp->host_scribble = (uchar *) cmd;
457 }
458
459
460
461
462
463 wd33c93_execute(cmd->device->host);
464
465 DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number))
466
467 spin_unlock_irq(&hostdata->lock);
468 return 0;
469}
470
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%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->serial_number))
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,%ld", cmd->cmnd[0], cmd->serial_number))
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-%ld", cmd->serial_number))
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-%ld", cmd->serial_number))
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-%ld: Unknown SEL_XFER_DONE phase!!---",
1204 asr, sr, phs, cmd->serial_number);
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-%ld", cmd->serial_number))
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-%ld", cmd->serial_number))
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 DB(DB_INTR, printk("-%ld", cmd->serial_number))
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 %ld from input_Q. ",
1641 instance->host_no, cmd->serial_number);
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 %ld - ",
1666 instance->host_no, cmd->serial_number);
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);
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 %ld found on disconnected_Q - ",
1733 instance->host_no, cmd->serial_number);
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, Compiled %s at %s\n",
2056 WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__);
2057}
2058
2059int
2060wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off, int len, int in)
2061{
2062
2063#ifdef PROC_INTERFACE
2064
2065 char *bp;
2066 char tbuf[128];
2067 struct WD33C93_hostdata *hd;
2068 struct scsi_cmnd *cmd;
2069 int x;
2070 static int stop = 0;
2071
2072 hd = (struct WD33C93_hostdata *) instance->hostdata;
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088 if (in) {
2089 buf[len] = '\0';
2090 for (bp = buf; *bp; ) {
2091 while (',' == *bp || ' ' == *bp)
2092 ++bp;
2093 if (!strncmp(bp, "debug:", 6)) {
2094 hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
2095 } else if (!strncmp(bp, "disconnect:", 11)) {
2096 x = simple_strtoul(bp+11, &bp, 0);
2097 if (x < DIS_NEVER || x > DIS_ALWAYS)
2098 x = DIS_ADAPTIVE;
2099 hd->disconnect = x;
2100 } else if (!strncmp(bp, "period:", 7)) {
2101 x = simple_strtoul(bp+7, &bp, 0);
2102 hd->default_sx_per =
2103 hd->sx_table[round_period((unsigned int) x,
2104 hd->sx_table)].period_ns;
2105 } else if (!strncmp(bp, "resync:", 7)) {
2106 set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
2107 } else if (!strncmp(bp, "proc:", 5)) {
2108 hd->proc = simple_strtoul(bp+5, &bp, 0);
2109 } else if (!strncmp(bp, "nodma:", 6)) {
2110 hd->no_dma = simple_strtoul(bp+6, &bp, 0);
2111 } else if (!strncmp(bp, "level2:", 7)) {
2112 hd->level2 = simple_strtoul(bp+7, &bp, 0);
2113 } else if (!strncmp(bp, "burst:", 6)) {
2114 hd->dma_mode =
2115 simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
2116 } else if (!strncmp(bp, "fast:", 5)) {
2117 x = !!simple_strtol(bp+5, &bp, 0);
2118 if (x != hd->fast)
2119 set_resync(hd, 0xff);
2120 hd->fast = x;
2121 } else if (!strncmp(bp, "nosync:", 7)) {
2122 x = simple_strtoul(bp+7, &bp, 0);
2123 set_resync(hd, x ^ hd->no_sync);
2124 hd->no_sync = x;
2125 } else {
2126 break;
2127 }
2128 }
2129 return len;
2130 }
2131
2132 spin_lock_irq(&hd->lock);
2133 bp = buf;
2134 *bp = '\0';
2135 if (hd->proc & PR_VERSION) {
2136 sprintf(tbuf, "\nVersion %s - %s. Compiled %s %s",
2137 WD33C93_VERSION, WD33C93_DATE, __DATE__, __TIME__);
2138 strcat(bp, tbuf);
2139 }
2140 if (hd->proc & PR_INFO) {
2141 sprintf(tbuf, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
2142 " dma_mode=%02x fast=%d",
2143 hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
2144 strcat(bp, tbuf);
2145 strcat(bp, "\nsync_xfer[] = ");
2146 for (x = 0; x < 7; x++) {
2147 sprintf(tbuf, "\t%02x", hd->sync_xfer[x]);
2148 strcat(bp, tbuf);
2149 }
2150 strcat(bp, "\nsync_stat[] = ");
2151 for (x = 0; x < 7; x++) {
2152 sprintf(tbuf, "\t%02x", hd->sync_stat[x]);
2153 strcat(bp, tbuf);
2154 }
2155 }
2156#ifdef PROC_STATISTICS
2157 if (hd->proc & PR_STATISTICS) {
2158 strcat(bp, "\ncommands issued: ");
2159 for (x = 0; x < 7; x++) {
2160 sprintf(tbuf, "\t%ld", hd->cmd_cnt[x]);
2161 strcat(bp, tbuf);
2162 }
2163 strcat(bp, "\ndisconnects allowed:");
2164 for (x = 0; x < 7; x++) {
2165 sprintf(tbuf, "\t%ld", hd->disc_allowed_cnt[x]);
2166 strcat(bp, tbuf);
2167 }
2168 strcat(bp, "\ndisconnects done: ");
2169 for (x = 0; x < 7; x++) {
2170 sprintf(tbuf, "\t%ld", hd->disc_done_cnt[x]);
2171 strcat(bp, tbuf);
2172 }
2173 sprintf(tbuf,
2174 "\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",
2175 hd->int_cnt, hd->dma_cnt, hd->pio_cnt);
2176 strcat(bp, tbuf);
2177 }
2178#endif
2179 if (hd->proc & PR_CONNECTED) {
2180 strcat(bp, "\nconnected: ");
2181 if (hd->connected) {
2182 cmd = (struct scsi_cmnd *) hd->connected;
2183 sprintf(tbuf, " %ld-%d:%d(%02x)",
2184 cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2185 strcat(bp, tbuf);
2186 }
2187 }
2188 if (hd->proc & PR_INPUTQ) {
2189 strcat(bp, "\ninput_Q: ");
2190 cmd = (struct scsi_cmnd *) hd->input_Q;
2191 while (cmd) {
2192 sprintf(tbuf, " %ld-%d:%d(%02x)",
2193 cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2194 strcat(bp, tbuf);
2195 cmd = (struct scsi_cmnd *) cmd->host_scribble;
2196 }
2197 }
2198 if (hd->proc & PR_DISCQ) {
2199 strcat(bp, "\ndisconnected_Q:");
2200 cmd = (struct scsi_cmnd *) hd->disconnected_Q;
2201 while (cmd) {
2202 sprintf(tbuf, " %ld-%d:%d(%02x)",
2203 cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2204 strcat(bp, tbuf);
2205 cmd = (struct scsi_cmnd *) cmd->host_scribble;
2206 }
2207 }
2208 strcat(bp, "\n");
2209 spin_unlock_irq(&hd->lock);
2210 *start = buf;
2211 if (stop) {
2212 stop = 0;
2213 return 0;
2214 }
2215 if (off > 0x40000)
2216 stop = 1;
2217 if (hd->proc & PR_STOP)
2218 stop = 1;
2219 return strlen(bp);
2220
2221#else
2222
2223 return 0;
2224
2225#endif
2226
2227}
2228
2229EXPORT_SYMBOL(wd33c93_host_reset);
2230EXPORT_SYMBOL(wd33c93_init);
2231EXPORT_SYMBOL(wd33c93_abort);
2232EXPORT_SYMBOL(wd33c93_queuecommand);
2233EXPORT_SYMBOL(wd33c93_intr);
2234EXPORT_SYMBOL(wd33c93_proc_info);
2235