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