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 != GOOD)
1180 cmd->result =
1181 (cmd->
1182 result & 0x00ffff) | (DID_ERROR << 16);
1183 else
1184 cmd->result =
1185 cmd->SCp.Status | (cmd->SCp.Message << 8);
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 && cmd->SCp.Status != GOOD)
1266 cmd->result =
1267 (cmd->result & 0x00ffff) | (DID_ERROR << 16);
1268 else
1269 cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
1270 cmd->scsi_done(cmd);
1271
1272
1273
1274
1275
1276 spin_unlock_irqrestore(&hostdata->lock, flags);
1277 wd33c93_execute(instance);
1278 break;
1279
1280 case CSR_DISC:
1281
1282
1283
1284
1285
1286 write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
1287 DB(DB_INTR, printk("DISC"))
1288 if (cmd == NULL) {
1289 printk(" - Already disconnected! ");
1290 hostdata->state = S_UNCONNECTED;
1291 }
1292 switch (hostdata->state) {
1293 case S_PRE_CMP_DISC:
1294 hostdata->connected = NULL;
1295 hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
1296 hostdata->state = S_UNCONNECTED;
1297 DB(DB_INTR, printk(":%d", cmd->SCp.Status))
1298 if (cmd->cmnd[0] == REQUEST_SENSE
1299 && cmd->SCp.Status != GOOD)
1300 cmd->result =
1301 (cmd->
1302 result & 0x00ffff) | (DID_ERROR << 16);
1303 else
1304 cmd->result =
1305 cmd->SCp.Status | (cmd->SCp.Message << 8);
1306 cmd->scsi_done(cmd);
1307 break;
1308 case S_PRE_TMP_DISC:
1309 case S_RUNNING_LEVEL2:
1310 cmd->host_scribble = (uchar *) hostdata->disconnected_Q;
1311 hostdata->disconnected_Q = cmd;
1312 hostdata->connected = NULL;
1313 hostdata->state = S_UNCONNECTED;
1314
1315#ifdef PROC_STATISTICS
1316 hostdata->disc_done_cnt[cmd->device->id]++;
1317#endif
1318
1319 break;
1320 default:
1321 printk("*** Unexpected DISCONNECT interrupt! ***");
1322 hostdata->state = S_UNCONNECTED;
1323 }
1324
1325
1326
1327
1328 spin_unlock_irqrestore(&hostdata->lock, flags);
1329 wd33c93_execute(instance);
1330 break;
1331
1332 case CSR_RESEL_AM:
1333 case CSR_RESEL:
1334 DB(DB_INTR, printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
1335
1336
1337
1338
1339
1340
1341
1342
1343 if (hostdata->level2 <= L2_NONE) {
1344
1345 if (hostdata->selecting) {
1346 cmd = (struct scsi_cmnd *) hostdata->selecting;
1347 hostdata->selecting = NULL;
1348 hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
1349 cmd->host_scribble =
1350 (uchar *) hostdata->input_Q;
1351 hostdata->input_Q = cmd;
1352 }
1353 }
1354
1355 else {
1356
1357 if (cmd) {
1358 if (phs == 0x00) {
1359 hostdata->busy[cmd->device->id] &=
1360 ~(1 << (cmd->device->lun & 0xff));
1361 cmd->host_scribble =
1362 (uchar *) hostdata->input_Q;
1363 hostdata->input_Q = cmd;
1364 } else {
1365 printk
1366 ("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",
1367 asr, sr, phs);
1368 while (1)
1369 printk("\r");
1370 }
1371 }
1372
1373 }
1374
1375
1376
1377 id = read_wd33c93(regs, WD_SOURCE_ID);
1378 id &= SRCID_MASK;
1379
1380
1381
1382
1383
1384
1385 if (sr == CSR_RESEL_AM) {
1386 lun = read_wd33c93(regs, WD_DATA);
1387 if (hostdata->level2 < L2_RESELECT)
1388 write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
1389 lun &= 7;
1390 } else {
1391
1392 for (lun = 255; lun; lun--) {
1393 if ((asr = read_aux_stat(regs)) & ASR_INT)
1394 break;
1395 udelay(10);
1396 }
1397 if (!(asr & ASR_INT)) {
1398 printk
1399 ("wd33c93: Reselected without IDENTIFY\n");
1400 lun = 0;
1401 } else {
1402
1403 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1404 udelay(7);
1405 if (sr == (CSR_ABORT | PHS_MESS_IN) ||
1406 sr == (CSR_UNEXP | PHS_MESS_IN) ||
1407 sr == (CSR_SRV_REQ | PHS_MESS_IN)) {
1408
1409 lun = read_1_byte(regs);
1410
1411 asr = read_aux_stat(regs);
1412 if (!(asr & ASR_INT)) {
1413 udelay(10);
1414 asr = read_aux_stat(regs);
1415 if (!(asr & ASR_INT))
1416 printk
1417 ("wd33c93: No int after LUN on RESEL (%02x)\n",
1418 asr);
1419 }
1420 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1421 udelay(7);
1422 if (sr != CSR_MSGIN)
1423 printk
1424 ("wd33c93: Not paused with ACK on RESEL (%02x)\n",
1425 sr);
1426 lun &= 7;
1427 write_wd33c93_cmd(regs,
1428 WD_CMD_NEGATE_ACK);
1429 } else {
1430 printk
1431 ("wd33c93: Not MSG_IN on reselect (%02x)\n",
1432 sr);
1433 lun = 0;
1434 }
1435 }
1436 }
1437
1438
1439
1440 cmd = (struct scsi_cmnd *) hostdata->disconnected_Q;
1441 patch = NULL;
1442 while (cmd) {
1443 if (id == cmd->device->id && lun == (u8)cmd->device->lun)
1444 break;
1445 patch = cmd;
1446 cmd = (struct scsi_cmnd *) cmd->host_scribble;
1447 }
1448
1449
1450
1451 if (!cmd) {
1452 printk
1453 ("---TROUBLE: target %d.%d not in disconnect queue---",
1454 id, (u8)lun);
1455 spin_unlock_irqrestore(&hostdata->lock, flags);
1456 return;
1457 }
1458
1459
1460
1461 if (patch)
1462 patch->host_scribble = cmd->host_scribble;
1463 else
1464 hostdata->disconnected_Q =
1465 (struct scsi_cmnd *) cmd->host_scribble;
1466 hostdata->connected = cmd;
1467
1468
1469
1470
1471
1472
1473 if (cmd->sc_data_direction == DMA_TO_DEVICE)
1474 write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id);
1475 else
1476 write_wd33c93(regs, WD_DESTINATION_ID,
1477 cmd->device->id | DSTID_DPD);
1478 if (hostdata->level2 >= L2_RESELECT) {
1479 write_wd33c93_count(regs, 0);
1480 write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
1481 write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
1482 hostdata->state = S_RUNNING_LEVEL2;
1483 } else
1484 hostdata->state = S_CONNECTED;
1485
1486 spin_unlock_irqrestore(&hostdata->lock, flags);
1487 break;
1488
1489 default:
1490 printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--", asr, sr, phs);
1491 spin_unlock_irqrestore(&hostdata->lock, flags);
1492 }
1493
1494 DB(DB_INTR, printk("} "))
1495
1496}
1497
1498static void
1499reset_wd33c93(struct Scsi_Host *instance)
1500{
1501 struct WD33C93_hostdata *hostdata =
1502 (struct WD33C93_hostdata *) instance->hostdata;
1503 const wd33c93_regs regs = hostdata->regs;
1504 uchar sr;
1505
1506#ifdef CONFIG_SGI_IP22
1507 {
1508 int busycount = 0;
1509 extern void sgiwd93_reset(unsigned long);
1510
1511 while ((read_aux_stat(regs) & ASR_BSY) && busycount++ < 100)
1512 udelay (10);
1513
1514
1515
1516
1517
1518
1519
1520
1521 if (read_aux_stat(regs) & ASR_BSY)
1522 sgiwd93_reset(instance->base);
1523 }
1524#endif
1525
1526 write_wd33c93(regs, WD_OWN_ID, OWNID_EAF | OWNID_RAF |
1527 instance->this_id | hostdata->clock_freq);
1528 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1529 write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
1530 calc_sync_xfer(hostdata->default_sx_per / 4,
1531 DEFAULT_SX_OFF, 0, hostdata->sx_table));
1532 write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET);
1533
1534
1535#ifdef CONFIG_MVME147_SCSI
1536 udelay(25);
1537#endif
1538
1539 while (!(read_aux_stat(regs) & ASR_INT))
1540 ;
1541 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1542
1543 hostdata->microcode = read_wd33c93(regs, WD_CDB_1);
1544 if (sr == 0x00)
1545 hostdata->chip = C_WD33C93;
1546 else if (sr == 0x01) {
1547 write_wd33c93(regs, WD_QUEUE_TAG, 0xa5);
1548 sr = read_wd33c93(regs, WD_QUEUE_TAG);
1549 if (sr == 0xa5) {
1550 hostdata->chip = C_WD33C93B;
1551 write_wd33c93(regs, WD_QUEUE_TAG, 0);
1552 } else
1553 hostdata->chip = C_WD33C93A;
1554 } else
1555 hostdata->chip = C_UNKNOWN_CHIP;
1556
1557 if (hostdata->chip != C_WD33C93B)
1558 hostdata->fast = 0;
1559
1560 write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
1561 write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1562}
1563
1564int
1565wd33c93_host_reset(struct scsi_cmnd * SCpnt)
1566{
1567 struct Scsi_Host *instance;
1568 struct WD33C93_hostdata *hostdata;
1569 int i;
1570
1571 instance = SCpnt->device->host;
1572 spin_lock_irq(instance->host_lock);
1573 hostdata = (struct WD33C93_hostdata *) instance->hostdata;
1574
1575 printk("scsi%d: reset. ", instance->host_no);
1576 disable_irq(instance->irq);
1577
1578 hostdata->dma_stop(instance, NULL, 0);
1579 for (i = 0; i < 8; i++) {
1580 hostdata->busy[i] = 0;
1581 hostdata->sync_xfer[i] =
1582 calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
1583 0, hostdata->sx_table);
1584 hostdata->sync_stat[i] = SS_UNSET;
1585 }
1586 hostdata->input_Q = NULL;
1587 hostdata->selecting = NULL;
1588 hostdata->connected = NULL;
1589 hostdata->disconnected_Q = NULL;
1590 hostdata->state = S_UNCONNECTED;
1591 hostdata->dma = D_DMA_OFF;
1592 hostdata->incoming_ptr = 0;
1593 hostdata->outgoing_len = 0;
1594
1595 reset_wd33c93(instance);
1596 SCpnt->result = DID_RESET << 16;
1597 enable_irq(instance->irq);
1598 spin_unlock_irq(instance->host_lock);
1599 return SUCCESS;
1600}
1601
1602int
1603wd33c93_abort(struct scsi_cmnd * cmd)
1604{
1605 struct Scsi_Host *instance;
1606 struct WD33C93_hostdata *hostdata;
1607 wd33c93_regs regs;
1608 struct scsi_cmnd *tmp, *prev;
1609
1610 disable_irq(cmd->device->host->irq);
1611
1612 instance = cmd->device->host;
1613 hostdata = (struct WD33C93_hostdata *) instance->hostdata;
1614 regs = hostdata->regs;
1615
1616
1617
1618
1619
1620
1621 tmp = (struct scsi_cmnd *) hostdata->input_Q;
1622 prev = NULL;
1623 while (tmp) {
1624 if (tmp == cmd) {
1625 if (prev)
1626 prev->host_scribble = cmd->host_scribble;
1627 else
1628 hostdata->input_Q =
1629 (struct scsi_cmnd *) cmd->host_scribble;
1630 cmd->host_scribble = NULL;
1631 cmd->result = DID_ABORT << 16;
1632 printk
1633 ("scsi%d: Abort - removing command from input_Q. ",
1634 instance->host_no);
1635 enable_irq(cmd->device->host->irq);
1636 cmd->scsi_done(cmd);
1637 return SUCCESS;
1638 }
1639 prev = tmp;
1640 tmp = (struct scsi_cmnd *) tmp->host_scribble;
1641 }
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654 if (hostdata->connected == cmd) {
1655 uchar sr, asr;
1656 unsigned long timeout;
1657
1658 printk("scsi%d: Aborting connected command - ",
1659 instance->host_no);
1660
1661 printk("stopping DMA - ");
1662 if (hostdata->dma == D_DMA_RUNNING) {
1663 hostdata->dma_stop(instance, cmd, 0);
1664 hostdata->dma = D_DMA_OFF;
1665 }
1666
1667 printk("sending wd33c93 ABORT command - ");
1668 write_wd33c93(regs, WD_CONTROL,
1669 CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1670 write_wd33c93_cmd(regs, WD_CMD_ABORT);
1671
1672
1673
1674 printk("flushing fifo - ");
1675 timeout = 1000000;
1676 do {
1677 asr = read_aux_stat(regs);
1678 if (asr & ASR_DBR)
1679 read_wd33c93(regs, WD_DATA);
1680 } while (!(asr & ASR_INT) && timeout-- > 0);
1681 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1682 printk
1683 ("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",
1684 asr, sr, read_wd33c93_count(regs), timeout);
1685
1686
1687
1688
1689
1690
1691
1692 printk("sending wd33c93 DISCONNECT command - ");
1693 write_wd33c93_cmd(regs, WD_CMD_DISCONNECT);
1694
1695 timeout = 1000000;
1696 asr = read_aux_stat(regs);
1697 while ((asr & ASR_CIP) && timeout-- > 0)
1698 asr = read_aux_stat(regs);
1699 sr = read_wd33c93(regs, WD_SCSI_STATUS);
1700 printk("asr=%02x, sr=%02x.", asr, sr);
1701
1702 hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
1703 hostdata->connected = NULL;
1704 hostdata->state = S_UNCONNECTED;
1705 cmd->result = DID_ABORT << 16;
1706
1707
1708 wd33c93_execute(instance);
1709
1710 enable_irq(cmd->device->host->irq);
1711 cmd->scsi_done(cmd);
1712 return SUCCESS;
1713 }
1714
1715
1716
1717
1718
1719
1720
1721 tmp = (struct scsi_cmnd *) hostdata->disconnected_Q;
1722 while (tmp) {
1723 if (tmp == cmd) {
1724 printk
1725 ("scsi%d: Abort - command found on disconnected_Q - ",
1726 instance->host_no);
1727 printk("Abort SNOOZE. ");
1728 enable_irq(cmd->device->host->irq);
1729 return FAILED;
1730 }
1731 tmp = (struct scsi_cmnd *) tmp->host_scribble;
1732 }
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745 wd33c93_execute(instance);
1746
1747 enable_irq(cmd->device->host->irq);
1748 printk("scsi%d: warning : SCSI command probably completed successfully"
1749 " before abortion. ", instance->host_no);
1750 return FAILED;
1751}
1752
1753#define MAX_WD33C93_HOSTS 4
1754#define MAX_SETUP_ARGS ARRAY_SIZE(setup_args)
1755#define SETUP_BUFFER_SIZE 200
1756static char setup_buffer[SETUP_BUFFER_SIZE];
1757static char setup_used[MAX_SETUP_ARGS];
1758static int done_setup = 0;
1759
1760static int
1761wd33c93_setup(char *str)
1762{
1763 int i;
1764 char *p1, *p2;
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775 p1 = setup_buffer;
1776 *p1 = '\0';
1777 if (str)
1778 strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
1779 setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
1780 p1 = setup_buffer;
1781 i = 0;
1782 while (*p1 && (i < MAX_SETUP_ARGS)) {
1783 p2 = strchr(p1, ',');
1784 if (p2) {
1785 *p2 = '\0';
1786 if (p1 != p2)
1787 setup_args[i] = p1;
1788 p1 = p2 + 1;
1789 i++;
1790 } else {
1791 setup_args[i] = p1;
1792 break;
1793 }
1794 }
1795 for (i = 0; i < MAX_SETUP_ARGS; i++)
1796 setup_used[i] = 0;
1797 done_setup = 1;
1798
1799 return 1;
1800}
1801__setup("wd33c93=", wd33c93_setup);
1802
1803
1804
1805static int
1806check_setup_args(char *key, int *flags, int *val, char *buf)
1807{
1808 int x;
1809 char *cp;
1810
1811 for (x = 0; x < MAX_SETUP_ARGS; x++) {
1812 if (setup_used[x])
1813 continue;
1814 if (!strncmp(setup_args[x], key, strlen(key)))
1815 break;
1816 if (!strncmp(setup_args[x], "next", strlen("next")))
1817 return 0;
1818 }
1819 if (x == MAX_SETUP_ARGS)
1820 return 0;
1821 setup_used[x] = 1;
1822 cp = setup_args[x] + strlen(key);
1823 *val = -1;
1824 if (*cp != ':')
1825 return ++x;
1826 cp++;
1827 if ((*cp >= '0') && (*cp <= '9')) {
1828 *val = simple_strtoul(cp, NULL, 0);
1829 }
1830 return ++x;
1831}
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850static inline unsigned int
1851round_4(unsigned int x)
1852{
1853 switch (x & 3) {
1854 case 1: --x;
1855 break;
1856 case 2: ++x;
1857
1858 case 3: ++x;
1859 }
1860 return x;
1861}
1862
1863static void
1864calc_sx_table(unsigned int mhz, struct sx_period sx_table[9])
1865{
1866 unsigned int d, i;
1867 if (mhz < 11)
1868 d = 2;
1869 else if (mhz < 16)
1870 d = 3;
1871 else
1872 d = 4;
1873
1874 d = (100000 * d) / 2 / mhz;
1875
1876 sx_table[0].period_ns = 1;
1877 sx_table[0].reg_value = 0x20;
1878 for (i = 1; i < 8; i++) {
1879 sx_table[i].period_ns = round_4((i+1)*d / 100);
1880 sx_table[i].reg_value = (i+1)*0x10;
1881 }
1882 sx_table[7].reg_value = 0;
1883 sx_table[8].period_ns = 0;
1884 sx_table[8].reg_value = 0;
1885}
1886
1887
1888
1889
1890static uchar
1891set_clk_freq(int freq, int *mhz)
1892{
1893 int x = freq;
1894 if (WD33C93_FS_8_10 == freq)
1895 freq = 8;
1896 else if (WD33C93_FS_12_15 == freq)
1897 freq = 12;
1898 else if (WD33C93_FS_16_20 == freq)
1899 freq = 16;
1900 else if (freq > 7 && freq < 11)
1901 x = WD33C93_FS_8_10;
1902 else if (freq > 11 && freq < 16)
1903 x = WD33C93_FS_12_15;
1904 else if (freq > 15 && freq < 21)
1905 x = WD33C93_FS_16_20;
1906 else {
1907
1908 x = WD33C93_FS_8_10;
1909 freq = 8;
1910 }
1911 *mhz = freq;
1912 return x;
1913}
1914
1915
1916
1917
1918static inline void set_resync ( struct WD33C93_hostdata *hd, int mask )
1919{
1920 int i;
1921 for (i = 0; i < 8; i++)
1922 if (mask & (1 << i))
1923 hd->sync_stat[i] = SS_UNSET;
1924}
1925
1926void
1927wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
1928 dma_setup_t setup, dma_stop_t stop, int clock_freq)
1929{
1930 struct WD33C93_hostdata *hostdata;
1931 int i;
1932 int flags;
1933 int val;
1934 char buf[32];
1935
1936 if (!done_setup && setup_strings)
1937 wd33c93_setup(setup_strings);
1938
1939 hostdata = (struct WD33C93_hostdata *) instance->hostdata;
1940
1941 hostdata->regs = regs;
1942 hostdata->clock_freq = set_clk_freq(clock_freq, &i);
1943 calc_sx_table(i, hostdata->sx_table);
1944 hostdata->dma_setup = setup;
1945 hostdata->dma_stop = stop;
1946 hostdata->dma_bounce_buffer = NULL;
1947 hostdata->dma_bounce_len = 0;
1948 for (i = 0; i < 8; i++) {
1949 hostdata->busy[i] = 0;
1950 hostdata->sync_xfer[i] =
1951 calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
1952 0, hostdata->sx_table);
1953 hostdata->sync_stat[i] = SS_UNSET;
1954#ifdef PROC_STATISTICS
1955 hostdata->cmd_cnt[i] = 0;
1956 hostdata->disc_allowed_cnt[i] = 0;
1957 hostdata->disc_done_cnt[i] = 0;
1958#endif
1959 }
1960 hostdata->input_Q = NULL;
1961 hostdata->selecting = NULL;
1962 hostdata->connected = NULL;
1963 hostdata->disconnected_Q = NULL;
1964 hostdata->state = S_UNCONNECTED;
1965 hostdata->dma = D_DMA_OFF;
1966 hostdata->level2 = L2_BASIC;
1967 hostdata->disconnect = DIS_ADAPTIVE;
1968 hostdata->args = DEBUG_DEFAULTS;
1969 hostdata->incoming_ptr = 0;
1970 hostdata->outgoing_len = 0;
1971 hostdata->default_sx_per = DEFAULT_SX_PER;
1972 hostdata->no_dma = 0;
1973
1974#ifdef PROC_INTERFACE
1975 hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
1976 PR_CONNECTED | PR_INPUTQ | PR_DISCQ | PR_STOP;
1977#ifdef PROC_STATISTICS
1978 hostdata->dma_cnt = 0;
1979 hostdata->pio_cnt = 0;
1980 hostdata->int_cnt = 0;
1981#endif
1982#endif
1983
1984 if (check_setup_args("clock", &flags, &val, buf)) {
1985 hostdata->clock_freq = set_clk_freq(val, &val);
1986 calc_sx_table(val, hostdata->sx_table);
1987 }
1988
1989 if (check_setup_args("nosync", &flags, &val, buf))
1990 hostdata->no_sync = val;
1991
1992 if (check_setup_args("nodma", &flags, &val, buf))
1993 hostdata->no_dma = (val == -1) ? 1 : val;
1994
1995 if (check_setup_args("period", &flags, &val, buf))
1996 hostdata->default_sx_per =
1997 hostdata->sx_table[round_period((unsigned int) val,
1998 hostdata->sx_table)].period_ns;
1999
2000 if (check_setup_args("disconnect", &flags, &val, buf)) {
2001 if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
2002 hostdata->disconnect = val;
2003 else
2004 hostdata->disconnect = DIS_ADAPTIVE;
2005 }
2006
2007 if (check_setup_args("level2", &flags, &val, buf))
2008 hostdata->level2 = val;
2009
2010 if (check_setup_args("debug", &flags, &val, buf))
2011 hostdata->args = val & DB_MASK;
2012
2013 if (check_setup_args("burst", &flags, &val, buf))
2014 hostdata->dma_mode = val ? CTRL_BURST:CTRL_DMA;
2015
2016 if (WD33C93_FS_16_20 == hostdata->clock_freq
2017 && check_setup_args("fast", &flags, &val, buf))
2018 hostdata->fast = !!val;
2019
2020 if ((i = check_setup_args("next", &flags, &val, buf))) {
2021 while (i)
2022 setup_used[--i] = 1;
2023 }
2024#ifdef PROC_INTERFACE
2025 if (check_setup_args("proc", &flags, &val, buf))
2026 hostdata->proc = val;
2027#endif
2028
2029 spin_lock_irq(&hostdata->lock);
2030 reset_wd33c93(instance);
2031 spin_unlock_irq(&hostdata->lock);
2032
2033 printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",
2034 instance->host_no,
2035 (hostdata->chip == C_WD33C93) ? "WD33c93" : (hostdata->chip ==
2036 C_WD33C93A) ?
2037 "WD33c93A" : (hostdata->chip ==
2038 C_WD33C93B) ? "WD33c93B" : "unknown",
2039 hostdata->microcode, hostdata->no_sync, hostdata->no_dma);
2040#ifdef DEBUGGING_ON
2041 printk(" debug_flags=0x%02x\n", hostdata->args);
2042#else
2043 printk(" debugging=OFF\n");
2044#endif
2045 printk(" setup_args=");
2046 for (i = 0; i < MAX_SETUP_ARGS; i++)
2047 printk("%s,", setup_args[i]);
2048 printk("\n");
2049 printk(" Version %s - %s\n", WD33C93_VERSION, WD33C93_DATE);
2050}
2051
2052int wd33c93_write_info(struct Scsi_Host *instance, char *buf, int len)
2053{
2054#ifdef PROC_INTERFACE
2055 char *bp;
2056 struct WD33C93_hostdata *hd;
2057 int x;
2058
2059 hd = (struct WD33C93_hostdata *) instance->hostdata;
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075 buf[len] = '\0';
2076 for (bp = buf; *bp; ) {
2077 while (',' == *bp || ' ' == *bp)
2078 ++bp;
2079 if (!strncmp(bp, "debug:", 6)) {
2080 hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
2081 } else if (!strncmp(bp, "disconnect:", 11)) {
2082 x = simple_strtoul(bp+11, &bp, 0);
2083 if (x < DIS_NEVER || x > DIS_ALWAYS)
2084 x = DIS_ADAPTIVE;
2085 hd->disconnect = x;
2086 } else if (!strncmp(bp, "period:", 7)) {
2087 x = simple_strtoul(bp+7, &bp, 0);
2088 hd->default_sx_per =
2089 hd->sx_table[round_period((unsigned int) x,
2090 hd->sx_table)].period_ns;
2091 } else if (!strncmp(bp, "resync:", 7)) {
2092 set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
2093 } else if (!strncmp(bp, "proc:", 5)) {
2094 hd->proc = simple_strtoul(bp+5, &bp, 0);
2095 } else if (!strncmp(bp, "nodma:", 6)) {
2096 hd->no_dma = simple_strtoul(bp+6, &bp, 0);
2097 } else if (!strncmp(bp, "level2:", 7)) {
2098 hd->level2 = simple_strtoul(bp+7, &bp, 0);
2099 } else if (!strncmp(bp, "burst:", 6)) {
2100 hd->dma_mode =
2101 simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
2102 } else if (!strncmp(bp, "fast:", 5)) {
2103 x = !!simple_strtol(bp+5, &bp, 0);
2104 if (x != hd->fast)
2105 set_resync(hd, 0xff);
2106 hd->fast = x;
2107 } else if (!strncmp(bp, "nosync:", 7)) {
2108 x = simple_strtoul(bp+7, &bp, 0);
2109 set_resync(hd, x ^ hd->no_sync);
2110 hd->no_sync = x;
2111 } else {
2112 break;
2113 }
2114 }
2115 return len;
2116#else
2117 return 0;
2118#endif
2119}
2120
2121int
2122wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance)
2123{
2124#ifdef PROC_INTERFACE
2125 struct WD33C93_hostdata *hd;
2126 struct scsi_cmnd *cmd;
2127 int x;
2128
2129 hd = (struct WD33C93_hostdata *) instance->hostdata;
2130
2131 spin_lock_irq(&hd->lock);
2132 if (hd->proc & PR_VERSION)
2133 seq_printf(m, "\nVersion %s - %s.",
2134 WD33C93_VERSION, WD33C93_DATE);
2135
2136 if (hd->proc & PR_INFO) {
2137 seq_printf(m, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
2138 " dma_mode=%02x fast=%d",
2139 hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
2140 seq_puts(m, "\nsync_xfer[] = ");
2141 for (x = 0; x < 7; x++)
2142 seq_printf(m, "\t%02x", hd->sync_xfer[x]);
2143 seq_puts(m, "\nsync_stat[] = ");
2144 for (x = 0; x < 7; x++)
2145 seq_printf(m, "\t%02x", hd->sync_stat[x]);
2146 }
2147#ifdef PROC_STATISTICS
2148 if (hd->proc & PR_STATISTICS) {
2149 seq_puts(m, "\ncommands issued: ");
2150 for (x = 0; x < 7; x++)
2151 seq_printf(m, "\t%ld", hd->cmd_cnt[x]);
2152 seq_puts(m, "\ndisconnects allowed:");
2153 for (x = 0; x < 7; x++)
2154 seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]);
2155 seq_puts(m, "\ndisconnects done: ");
2156 for (x = 0; x < 7; x++)
2157 seq_printf(m, "\t%ld", hd->disc_done_cnt[x]);
2158 seq_printf(m,
2159 "\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",
2160 hd->int_cnt, hd->dma_cnt, hd->pio_cnt);
2161 }
2162#endif
2163 if (hd->proc & PR_CONNECTED) {
2164 seq_puts(m, "\nconnected: ");
2165 if (hd->connected) {
2166 cmd = (struct scsi_cmnd *) hd->connected;
2167 seq_printf(m, " %d:%llu(%02x)",
2168 cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2169 }
2170 }
2171 if (hd->proc & PR_INPUTQ) {
2172 seq_puts(m, "\ninput_Q: ");
2173 cmd = (struct scsi_cmnd *) hd->input_Q;
2174 while (cmd) {
2175 seq_printf(m, " %d:%llu(%02x)",
2176 cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2177 cmd = (struct scsi_cmnd *) cmd->host_scribble;
2178 }
2179 }
2180 if (hd->proc & PR_DISCQ) {
2181 seq_puts(m, "\ndisconnected_Q:");
2182 cmd = (struct scsi_cmnd *) hd->disconnected_Q;
2183 while (cmd) {
2184 seq_printf(m, " %d:%llu(%02x)",
2185 cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
2186 cmd = (struct scsi_cmnd *) cmd->host_scribble;
2187 }
2188 }
2189 seq_putc(m, '\n');
2190 spin_unlock_irq(&hd->lock);
2191#endif
2192 return 0;
2193}
2194
2195EXPORT_SYMBOL(wd33c93_host_reset);
2196EXPORT_SYMBOL(wd33c93_init);
2197EXPORT_SYMBOL(wd33c93_abort);
2198EXPORT_SYMBOL(wd33c93_queuecommand);
2199EXPORT_SYMBOL(wd33c93_intr);
2200EXPORT_SYMBOL(wd33c93_show_info);
2201EXPORT_SYMBOL(wd33c93_write_info);
2202