This source file includes following definitions.
- read_wd33c93
- write_wd33c93
- write_wd33c93_cmd
- read_1_byte
- write_wd33c93_count
- read_wd33c93_count
- round_period
- calc_sync_xfer
- wd33c93_queuecommand
- wd33c93_execute
- transfer_pio
- transfer_bytes
- wd33c93_intr
- reset_wd33c93
- wd33c93_reset
- wd33c93_abort
- wd33c93_setup
- check_setup_strings
- wd33c93_init
- wd33c93_proc_info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 #include <asm/system.h>
72 #include <linux/sched.h>
73 #include <linux/string.h>
74 #include <linux/delay.h>
75 #include <linux/version.h>
76
77 #if LINUX_VERSION_CODE >= 0x010300
78 #include <linux/blk.h>
79 #else
80 #include "../block/blk.h"
81 #endif
82
83 #include "scsi.h"
84 #include "hosts.h"
85 #include "wd33c93.h"
86
87 #ifdef MODULE
88 #include <linux/module.h>
89 #endif
90
91
92
93
94
95
96 #define SYNC_DEBUG
97 #define DEBUGGING_ON
98 #define DEBUG_DEFAULTS 0
99
100 #define WD33C93_VERSION "1.21"
101 #define WD33C93_DATE "20/Apr/1996"
102
103 #ifdef DEBUGGING_ON
104 #define DB(f,a) if (hostdata->args & (f)) a;
105 #else
106 #define DB(f,a)
107 #endif
108
109 #define IS_DIR_OUT(cmd) ((cmd)->cmnd[0] == WRITE_6 || \
110 (cmd)->cmnd[0] == WRITE_10 || \
111 (cmd)->cmnd[0] == WRITE_12)
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161 static char *setup_strings[] =
162 {"","","","","","","","","","","",""};
163
164 #ifdef PROC_INTERFACE
165 unsigned long disc_allowed_total;
166 unsigned long disc_taken_total;
167 #endif
168
169
170 inline uchar read_wd33c93(wd33c93_regs *regp,uchar reg_num)
171 {
172 regp->SASR = reg_num;
173 return(regp->SCMD);
174 }
175
176
177 #define READ_AUX_STAT() (regp->SASR)
178
179
180 inline void write_wd33c93(wd33c93_regs *regp,uchar reg_num, uchar value)
181 {
182 regp->SASR = reg_num;
183 regp->SCMD = value;
184 }
185
186
187 inline void write_wd33c93_cmd(wd33c93_regs *regp, uchar cmd)
188 {
189 regp->SASR = WD_COMMAND;
190 regp->SCMD = cmd;
191 }
192
193
194 inline uchar read_1_byte(wd33c93_regs *regp)
195 {
196 uchar asr;
197 uchar x = 0;
198
199 write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
200 write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO|0x80);
201 do {
202 asr = READ_AUX_STAT();
203 if (asr & ASR_DBR)
204 x = read_wd33c93(regp, WD_DATA);
205 } while (!(asr & ASR_INT));
206 return x;
207 }
208
209
210 void write_wd33c93_count(wd33c93_regs *regp,unsigned long value)
211 {
212 regp->SASR = WD_TRANSFER_COUNT_MSB;
213 regp->SCMD = value >> 16;
214 regp->SCMD = value >> 8;
215 regp->SCMD = value;
216 }
217
218
219 unsigned long read_wd33c93_count(wd33c93_regs *regp)
220 {
221 unsigned long value;
222
223 regp->SASR = WD_TRANSFER_COUNT_MSB;
224 value = regp->SCMD << 16;
225 value |= regp->SCMD << 8;
226 value |= regp->SCMD;
227 return value;
228 }
229
230
231
232 static struct sx_period sx_table[] = {
233 { 1, 0x20},
234 {252, 0x20},
235 {376, 0x30},
236 {500, 0x40},
237 {624, 0x50},
238 {752, 0x60},
239 {876, 0x70},
240 {1000,0x00},
241 {0, 0} };
242
243 int round_period(unsigned int period)
244 {
245 int x;
246
247 for (x=1; sx_table[x].period_ns; x++) {
248 if ((period <= sx_table[x-0].period_ns) &&
249 (period > sx_table[x-1].period_ns)) {
250 return x;
251 }
252 }
253 return 7;
254 }
255
256 uchar calc_sync_xfer(unsigned int period, unsigned int offset)
257 {
258 uchar result;
259
260 period *= 4;
261 result = sx_table[round_period(period)].reg_value;
262 result |= (offset < OPTIMUM_SX_OFF)?offset:OPTIMUM_SX_OFF;
263 return result;
264 }
265
266
267
268 void wd33c93_execute(struct Scsi_Host *instance);
269
270 int wd33c93_queuecommand (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
271 {
272 struct WD33C93_hostdata *hostdata;
273 Scsi_Cmnd *tmp;
274 unsigned long flags;
275
276
277 save_flags(flags);
278 cli();
279 hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
280
281 DB(DB_QUEUE_COMMAND,printk("Q-%d-%02x-%ld( ",cmd->target,cmd->cmnd[0],cmd->pid))
282
283
284
285
286
287
288
289 cmd->host_scribble = NULL;
290 cmd->scsi_done = done;
291 cmd->result = 0;
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308 if (cmd->use_sg) {
309 cmd->SCp.buffer = (struct scatterlist *)cmd->buffer;
310 cmd->SCp.buffers_residual = cmd->use_sg - 1;
311 cmd->SCp.ptr = (char *)cmd->SCp.buffer->address;
312 cmd->SCp.this_residual = cmd->SCp.buffer->length;
313 }
314 else {
315 cmd->SCp.buffer = NULL;
316 cmd->SCp.buffers_residual = 0;
317 cmd->SCp.ptr = (char *)cmd->request_buffer;
318 cmd->SCp.this_residual = cmd->request_bufflen;
319 }
320
321
322
323 cmd->SCp.Status = GOOD;
324
325
326
327
328
329
330
331 if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
332 cmd->host_scribble = (uchar *)hostdata->input_Q;
333 hostdata->input_Q = cmd;
334 }
335 else {
336 for (tmp=(Scsi_Cmnd *)hostdata->input_Q; tmp->host_scribble;
337 tmp=(Scsi_Cmnd *)tmp->host_scribble)
338 ;
339 tmp->host_scribble = (uchar *)cmd;
340 }
341
342
343
344
345
346 wd33c93_execute(cmd->host);
347
348 DB(DB_QUEUE_COMMAND,printk(")Q-%ld ",cmd->pid))
349
350 restore_flags(flags);
351 return 0;
352 }
353
354
355
356
357
358
359
360
361
362 void wd33c93_execute (struct Scsi_Host *instance)
363 {
364 struct WD33C93_hostdata *hostdata;
365 wd33c93_regs *regp;
366 Scsi_Cmnd *cmd, *prev;
367 unsigned long flags;
368 int i;
369
370
371 save_flags(flags);
372 cli();
373 hostdata = (struct WD33C93_hostdata *)instance->hostdata;
374 regp = hostdata->regp;
375
376 DB(DB_EXECUTE,printk("EX("))
377
378 if (hostdata->selecting || hostdata->connected) {
379
380 DB(DB_EXECUTE,printk(")EX-0 "))
381
382 restore_flags(flags);
383 return;
384 }
385
386
387
388
389
390
391 cmd = (Scsi_Cmnd *)hostdata->input_Q;
392 prev = 0;
393 while (cmd) {
394 if (!(hostdata->busy[cmd->target] & (1 << cmd->lun)))
395 break;
396 prev = cmd;
397 cmd = (Scsi_Cmnd *)cmd->host_scribble;
398 }
399
400
401
402 if (!cmd) {
403
404 DB(DB_EXECUTE,printk(")EX-1 "))
405
406 restore_flags(flags);
407 return;
408 }
409
410
411
412 if (prev)
413 prev->host_scribble = cmd->host_scribble;
414 else
415 hostdata->input_Q = (Scsi_Cmnd *)cmd->host_scribble;
416
417
418
419
420
421 if (IS_DIR_OUT(cmd))
422 write_wd33c93(regp, WD_DESTINATION_ID, cmd->target);
423 else
424 write_wd33c93(regp, WD_DESTINATION_ID, cmd->target | DSTID_DPD);
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449 cmd->SCp.phase = 0;
450 if (hostdata->disconnect == DIS_NEVER)
451 goto no;
452 if (hostdata->disconnect == DIS_ALWAYS)
453 goto yes;
454 if (cmd->device->type == 1)
455 goto yes;
456 if (hostdata->disconnected_Q)
457 goto yes;
458 if (!(hostdata->input_Q))
459 goto no;
460 for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
461 prev=(Scsi_Cmnd *)prev->host_scribble) {
462 if ((prev->target != cmd->target) || (prev->lun != cmd->lun)) {
463 for (prev=(Scsi_Cmnd *)hostdata->input_Q; prev;
464 prev=(Scsi_Cmnd *)prev->host_scribble)
465 prev->SCp.phase = 1;
466 goto yes;
467 }
468 }
469 goto no;
470
471 yes:
472 cmd->SCp.phase = 1;
473
474 #ifdef PROC_INTERFACE
475 disc_allowed_total++;
476 #endif
477
478 no:
479 write_wd33c93(regp, WD_SOURCE_ID, ((cmd->SCp.phase)?SRCID_ER:0));
480
481 write_wd33c93(regp, WD_TARGET_LUN, cmd->lun);
482 write_wd33c93(regp,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]);
483 hostdata->busy[cmd->target] |= (1 << cmd->lun);
484
485 if ((hostdata->level2 == L2_NONE) ||
486 (hostdata->sync_stat[cmd->target] == SS_UNSET)) {
487
488
489
490
491
492
493
494
495
496 hostdata->selecting = cmd;
497
498
499
500
501
502
503
504
505
506
507
508
509 if (hostdata->sync_stat[cmd->target] == SS_UNSET) {
510 if (hostdata->no_sync & (1 << cmd->target))
511 hostdata->sync_stat[cmd->target] = SS_SET;
512 else
513 hostdata->sync_stat[cmd->target] = SS_FIRST;
514 }
515 hostdata->state = S_SELECTING;
516 write_wd33c93_count(regp,0);
517 write_wd33c93_cmd(regp, WD_CMD_SEL_ATN);
518 }
519
520 else {
521
522
523
524
525
526
527
528
529
530 hostdata->connected = cmd;
531 write_wd33c93(regp, WD_COMMAND_PHASE, 0);
532
533
534
535
536
537 regp->SASR = WD_CDB_1;
538 for (i=0; i<cmd->cmd_len; i++)
539 regp->SCMD = cmd->cmnd[i];
540
541
542
543
544
545
546
547 write_wd33c93(regp, WD_OWN_ID, cmd->cmd_len);
548
549
550
551
552
553 if (cmd->SCp.phase == 0) {
554 if (hostdata->dma_setup(cmd,
555 (IS_DIR_OUT(cmd))?DATA_OUT_DIR:DATA_IN_DIR))
556 write_wd33c93_count(regp,0);
557 else {
558 write_wd33c93_count(regp, cmd->SCp.this_residual);
559 write_wd33c93(regp,WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
560 hostdata->dma = D_DMA_RUNNING;
561 }
562 }
563 else
564 write_wd33c93_count(regp,0);
565
566 hostdata->state = S_RUNNING_LEVEL2;
567 write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
568 }
569
570
571
572
573
574
575
576
577 DB(DB_EXECUTE,printk("%s%ld)EX-2 ",(cmd->SCp.phase)?"d:":"",cmd->pid))
578
579 restore_flags(flags);
580 }
581
582
583
584 void transfer_pio(wd33c93_regs *regp, uchar *buf, int cnt,
585 int data_in_dir, struct WD33C93_hostdata *hostdata)
586 {
587 uchar asr;
588
589 DB(DB_TRANSFER,printk("(%p,%d,%s)",buf,cnt,data_in_dir?"in":"out"))
590
591 write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
592 write_wd33c93_count(regp,cnt);
593 write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO);
594 if (data_in_dir) {
595 do {
596 asr = READ_AUX_STAT();
597 if (asr & ASR_DBR)
598 *buf++ = read_wd33c93(regp, WD_DATA);
599 } while (!(asr & ASR_INT));
600 }
601 else {
602 do {
603 asr = READ_AUX_STAT();
604 if (asr & ASR_DBR)
605 write_wd33c93(regp, WD_DATA, *buf++);
606 } while (!(asr & ASR_INT));
607 }
608
609
610
611
612
613
614
615
616 }
617
618
619
620 void transfer_bytes(wd33c93_regs *regp, Scsi_Cmnd *cmd, int data_in_dir)
621 {
622 struct WD33C93_hostdata *hostdata;
623
624 hostdata = (struct WD33C93_hostdata *)cmd->host->hostdata;
625
626
627
628
629
630
631
632
633
634 if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
635 ++cmd->SCp.buffer;
636 --cmd->SCp.buffers_residual;
637 cmd->SCp.this_residual = cmd->SCp.buffer->length;
638 cmd->SCp.ptr = cmd->SCp.buffer->address;
639 }
640
641 write_wd33c93(regp,WD_SYNCHRONOUS_TRANSFER,hostdata->sync_xfer[cmd->target]);
642
643
644
645 if (hostdata->dma_setup(cmd, data_in_dir)) {
646 transfer_pio(regp, (uchar *)&cmd->SCp.ptr, cmd->SCp.this_residual,
647 data_in_dir, hostdata);
648 }
649
650
651
652
653
654
655
656
657
658
659 else {
660 write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_DMA);
661 write_wd33c93_count(regp,cmd->SCp.this_residual);
662
663 if ((hostdata->level2 >= L2_DATA) || (cmd->SCp.phase == 0)) {
664 write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
665 write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
666 hostdata->state = S_RUNNING_LEVEL2;
667 }
668 else
669 write_wd33c93_cmd(regp, WD_CMD_TRANS_INFO);
670
671 hostdata->dma = D_DMA_RUNNING;
672 }
673 }
674
675
676
677 void wd33c93_intr (struct Scsi_Host *instance)
678 {
679 struct WD33C93_hostdata *hostdata;
680 Scsi_Cmnd *patch, *cmd;
681 wd33c93_regs *regp;
682 unsigned long flags;
683 uchar asr, sr, phs, id, lun, *ucp, msg;
684 unsigned long length;
685
686
687 hostdata = (struct WD33C93_hostdata *)instance->hostdata;
688 regp = hostdata->regp;
689
690 asr = READ_AUX_STAT();
691 if (!(asr & ASR_INT) || (asr & ASR_BSY))
692 return;
693
694
695
696 save_flags(flags);
697 sti();
698
699 cmd = (Scsi_Cmnd *)hostdata->connected;
700 sr = read_wd33c93(regp, WD_SCSI_STATUS);
701 phs = read_wd33c93(regp, WD_COMMAND_PHASE);
702
703 DB(DB_INTR,printk("{%02x:%02x-",asr,sr))
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720 if (hostdata->dma == D_DMA_RUNNING) {
721 DB(DB_TRANSFER,printk("[%p/%d:",cmd->SCp.ptr,cmd->SCp.this_residual))
722 hostdata->dma_stop(cmd->host, cmd, 1);
723 hostdata->dma = D_DMA_OFF;
724 length = cmd->SCp.this_residual;
725 cmd->SCp.this_residual = read_wd33c93_count(regp);
726 cmd->SCp.ptr += (length - cmd->SCp.this_residual);
727 DB(DB_TRANSFER,printk("%p/%d]",cmd->SCp.ptr,cmd->SCp.this_residual))
728 }
729
730
731
732 switch (sr) {
733
734 case CSR_TIMEOUT:
735 DB(DB_INTR,printk("TIMEOUT"))
736
737 cli();
738 if (hostdata->state == S_RUNNING_LEVEL2)
739 hostdata->connected = NULL;
740 else {
741 cmd = (Scsi_Cmnd *)hostdata->selecting;
742 hostdata->selecting = NULL;
743 }
744
745 cmd->result = DID_NO_CONNECT << 16;
746 hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
747 hostdata->state = S_UNCONNECTED;
748 cmd->scsi_done(cmd);
749
750
751
752
753
754 sti();
755 wd33c93_execute(instance);
756 break;
757
758
759
760
761 case CSR_SELECT:
762 cli();
763 DB(DB_INTR,printk("SELECT"))
764 hostdata->connected = cmd = (Scsi_Cmnd *)hostdata->selecting;
765 hostdata->selecting = NULL;
766
767
768
769 hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->lun);
770 if (cmd->SCp.phase)
771 hostdata->outgoing_msg[0] |= 0x40;
772
773 if (hostdata->sync_stat[cmd->target] == SS_FIRST) {
774 #ifdef SYNC_DEBUG
775 printk(" sending SDTR ");
776 #endif
777
778 hostdata->sync_stat[cmd->target] = SS_WAITING;
779
780
781
782 hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
783 hostdata->outgoing_msg[2] = 3;
784 hostdata->outgoing_msg[3] = EXTENDED_SDTR;
785 hostdata->outgoing_msg[4] = OPTIMUM_SX_PER/4;
786 hostdata->outgoing_msg[5] = OPTIMUM_SX_OFF;
787 hostdata->outgoing_len = 6;
788 }
789 else
790 hostdata->outgoing_len = 1;
791
792 hostdata->state = S_CONNECTED;
793 break;
794
795
796 case CSR_XFER_DONE|PHS_DATA_IN:
797 case CSR_UNEXP |PHS_DATA_IN:
798 case CSR_SRV_REQ |PHS_DATA_IN:
799 DB(DB_INTR,printk("IN-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
800 transfer_bytes(regp, cmd, DATA_IN_DIR);
801 if (hostdata->state != S_RUNNING_LEVEL2)
802 hostdata->state = S_CONNECTED;
803 break;
804
805
806 case CSR_XFER_DONE|PHS_DATA_OUT:
807 case CSR_UNEXP |PHS_DATA_OUT:
808 case CSR_SRV_REQ |PHS_DATA_OUT:
809 DB(DB_INTR,printk("OUT-%d.%d",cmd->SCp.this_residual,cmd->SCp.buffers_residual))
810 transfer_bytes(regp, cmd, DATA_OUT_DIR);
811 if (hostdata->state != S_RUNNING_LEVEL2)
812 hostdata->state = S_CONNECTED;
813 break;
814
815
816
817
818 case CSR_XFER_DONE|PHS_COMMAND:
819 case CSR_UNEXP |PHS_COMMAND:
820 case CSR_SRV_REQ |PHS_COMMAND:
821 DB(DB_INTR,printk("CMND-%02x,%ld",cmd->cmnd[0],cmd->pid))
822 transfer_pio(regp, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata);
823 hostdata->state = S_CONNECTED;
824 break;
825
826
827 case CSR_XFER_DONE|PHS_STATUS:
828 case CSR_UNEXP |PHS_STATUS:
829 case CSR_SRV_REQ |PHS_STATUS:
830 DB(DB_INTR,printk("STATUS"))
831
832 cmd->SCp.Status = read_1_byte(regp);
833 if (hostdata->level2 >= L2_BASIC) {
834 sr = read_wd33c93(regp, WD_SCSI_STATUS);
835 hostdata->state = S_RUNNING_LEVEL2;
836 write_wd33c93(regp, WD_COMMAND_PHASE, 0x50);
837 write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
838 }
839 else {
840 DB(DB_INTR,printk("=%02x",cmd->SCp.Status))
841 hostdata->state = S_CONNECTED;
842 }
843 break;
844
845
846 case CSR_XFER_DONE|PHS_MESS_IN:
847 case CSR_UNEXP |PHS_MESS_IN:
848 case CSR_SRV_REQ |PHS_MESS_IN:
849 DB(DB_INTR,printk("MSG_IN="))
850
851 cli();
852 msg = read_1_byte(regp);
853 sr = read_wd33c93(regp, WD_SCSI_STATUS);
854
855 hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
856 if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
857 msg = EXTENDED_MESSAGE;
858 else
859 hostdata->incoming_ptr = 0;
860
861 cmd->SCp.Message = msg;
862 switch (msg) {
863
864 case COMMAND_COMPLETE:
865 DB(DB_INTR,printk("CCMP-%ld",cmd->pid))
866 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
867 hostdata->state = S_PRE_CMP_DISC;
868 break;
869
870 case SAVE_POINTERS:
871 DB(DB_INTR,printk("SDP"))
872 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
873 hostdata->state = S_CONNECTED;
874 break;
875
876 case RESTORE_POINTERS:
877 DB(DB_INTR,printk("RDP"))
878 if (hostdata->level2 >= L2_BASIC) {
879 write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
880 write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
881 hostdata->state = S_RUNNING_LEVEL2;
882 }
883 else {
884 write_wd33c93_cmd(regp, WD_CMD_NEGATE_ACK);
885 hostdata->state = S_CONNECTED;
886 }
887 break;
888
889 case DISCONNECT:
890 DB(DB_INTR,printk("DIS"))
891 cmd->device->disconnect = 1;
892 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
893 hostdata->state = S_PRE_TMP_DISC;
894 break;
895
896 case MESSAGE_REJECT:
897 DB(DB_INTR,printk("REJ"))
898 #ifdef SYNC_DEBUG
899 printk("-REJ-");
900 #endif
901 if (hostdata->sync_stat[cmd->target] == SS_WAITING)
902 hostdata->sync_stat[cmd->target] = SS_SET;
903 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
904 hostdata->state = S_CONNECTED;
905 break;
906
907 case EXTENDED_MESSAGE:
908 DB(DB_INTR,printk("EXT"))
909
910 ucp = hostdata->incoming_msg;
911
912 #ifdef SYNC_DEBUG
913 printk("%02x",ucp[hostdata->incoming_ptr]);
914 #endif
915
916
917 if ((hostdata->incoming_ptr >= 2) &&
918 (hostdata->incoming_ptr == (ucp[1] + 1))) {
919
920 switch (ucp[2]) {
921 case EXTENDED_SDTR:
922 id = calc_sync_xfer(ucp[3],ucp[4]);
923 if (hostdata->sync_stat[cmd->target] != SS_WAITING) {
924
925
926
927
928
929
930
931
932
933
934 write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN);
935 hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
936 hostdata->outgoing_msg[1] = 3;
937 hostdata->outgoing_msg[2] = EXTENDED_SDTR;
938 hostdata->outgoing_msg[3] = hostdata->default_sx_per/4;
939 hostdata->outgoing_msg[4] = 0;
940 hostdata->outgoing_len = 5;
941 hostdata->sync_xfer[cmd->target] =
942 calc_sync_xfer(hostdata->default_sx_per/4,0);
943 }
944 else {
945 hostdata->sync_xfer[cmd->target] = id;
946 }
947 #ifdef SYNC_DEBUG
948 printk("sync_xfer=%02x",hostdata->sync_xfer[cmd->target]);
949 #endif
950 hostdata->sync_stat[cmd->target] = SS_SET;
951 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
952 hostdata->state = S_CONNECTED;
953 break;
954 case EXTENDED_WDTR:
955 write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN);
956 printk("sending WDTR ");
957 hostdata->outgoing_msg[0] = EXTENDED_MESSAGE;
958 hostdata->outgoing_msg[1] = 2;
959 hostdata->outgoing_msg[2] = EXTENDED_WDTR;
960 hostdata->outgoing_msg[3] = 0;
961 hostdata->outgoing_len = 4;
962 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
963 hostdata->state = S_CONNECTED;
964 break;
965 default:
966 write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN);
967 printk("Rejecting Unknown Extended Message(%02x). ",ucp[2]);
968 hostdata->outgoing_msg[0] = MESSAGE_REJECT;
969 hostdata->outgoing_len = 1;
970 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
971 hostdata->state = S_CONNECTED;
972 break;
973 }
974 hostdata->incoming_ptr = 0;
975 }
976
977
978
979 else {
980 hostdata->incoming_ptr++;
981 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
982 hostdata->state = S_CONNECTED;
983 }
984 break;
985
986 default:
987 printk("Rejecting Unknown Message(%02x) ",msg);
988 write_wd33c93_cmd(regp,WD_CMD_ASSERT_ATN);
989 hostdata->outgoing_msg[0] = MESSAGE_REJECT;
990 hostdata->outgoing_len = 1;
991 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
992 hostdata->state = S_CONNECTED;
993 }
994 break;
995
996
997
998
999 case CSR_SEL_XFER_DONE:
1000 cli();
1001
1002
1003
1004
1005
1006 write_wd33c93(regp,WD_SOURCE_ID, SRCID_ER);
1007 if (phs == 0x60) {
1008 DB(DB_INTR,printk("SX-DONE-%ld",cmd->pid))
1009 cmd->SCp.Message = COMMAND_COMPLETE;
1010 lun = read_wd33c93(regp, WD_TARGET_LUN);
1011 if (cmd->SCp.Status == GOOD)
1012 cmd->SCp.Status = lun;
1013 hostdata->connected = NULL;
1014 if (cmd->cmnd[0] != REQUEST_SENSE)
1015 cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
1016 else if (cmd->SCp.Status != GOOD)
1017 cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
1018 hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
1019 hostdata->state = S_UNCONNECTED;
1020 cmd->scsi_done(cmd);
1021
1022
1023
1024
1025
1026 wd33c93_execute(instance);
1027 }
1028 else {
1029 printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---",asr,sr,phs,cmd->pid);
1030 }
1031 break;
1032
1033
1034
1035
1036 case CSR_SDP:
1037 DB(DB_INTR,printk("SDP"))
1038 hostdata->state = S_RUNNING_LEVEL2;
1039 write_wd33c93(regp, WD_COMMAND_PHASE, 0x41);
1040 write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
1041 break;
1042
1043
1044 case CSR_XFER_DONE|PHS_MESS_OUT:
1045 case CSR_UNEXP |PHS_MESS_OUT:
1046 case CSR_SRV_REQ |PHS_MESS_OUT:
1047 DB(DB_INTR,printk("MSG_OUT="))
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062 if (hostdata->outgoing_len == 0) {
1063 hostdata->outgoing_len = 1;
1064 hostdata->outgoing_msg[0] = NOP;
1065 }
1066 transfer_pio(regp, hostdata->outgoing_msg, hostdata->outgoing_len,
1067 DATA_OUT_DIR, hostdata);
1068 DB(DB_INTR,printk("%02x",hostdata->outgoing_msg[0]))
1069 hostdata->outgoing_len = 0;
1070 hostdata->state = S_CONNECTED;
1071 break;
1072
1073
1074 case CSR_UNEXP_DISC:
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084 cli();
1085
1086
1087
1088
1089
1090 write_wd33c93(regp,WD_SOURCE_ID, SRCID_ER);
1091 if (cmd == NULL) {
1092 printk(" - Already disconnected! ");
1093 hostdata->state = S_UNCONNECTED;
1094 return;
1095 }
1096 DB(DB_INTR,printk("UNEXP_DISC-%ld",cmd->pid))
1097 hostdata->connected = NULL;
1098 hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
1099 hostdata->state = S_UNCONNECTED;
1100 if (cmd->cmnd[0] != REQUEST_SENSE)
1101 cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
1102 else if (cmd->SCp.Status != GOOD)
1103 cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
1104 cmd->scsi_done(cmd);
1105
1106
1107
1108
1109
1110 wd33c93_execute(instance);
1111 break;
1112
1113
1114 case CSR_DISC:
1115 cli();
1116
1117
1118
1119
1120
1121 write_wd33c93(regp,WD_SOURCE_ID, SRCID_ER);
1122 DB(DB_INTR,printk("DISC-%ld",cmd->pid))
1123 if (cmd == NULL) {
1124 printk(" - Already disconnected! ");
1125 hostdata->state = S_UNCONNECTED;
1126 }
1127 switch (hostdata->state) {
1128 case S_PRE_CMP_DISC:
1129 hostdata->connected = NULL;
1130 hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
1131 hostdata->state = S_UNCONNECTED;
1132 if (cmd->cmnd[0] != REQUEST_SENSE)
1133 cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
1134 else if (cmd->SCp.Status != GOOD)
1135 cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);
1136 cmd->scsi_done(cmd);
1137 break;
1138 case S_PRE_TMP_DISC:
1139 case S_RUNNING_LEVEL2:
1140 cmd->host_scribble = (uchar *)hostdata->disconnected_Q;
1141 hostdata->disconnected_Q = cmd;
1142 hostdata->connected = NULL;
1143 hostdata->state = S_UNCONNECTED;
1144
1145 #ifdef PROC_INTERFACE
1146 disc_taken_total++;
1147 #endif
1148
1149 break;
1150 default:
1151 printk("*** Unexpected DISCONNECT interrupt! ***");
1152 hostdata->state = S_UNCONNECTED;
1153 }
1154
1155
1156
1157
1158
1159 wd33c93_execute(instance);
1160 break;
1161
1162
1163 case CSR_RESEL_AM:
1164 DB(DB_INTR,printk("RESEL"))
1165
1166 cli();
1167
1168
1169
1170
1171
1172 if (hostdata->level2 <= L2_NONE) {
1173
1174 if (hostdata->selecting) {
1175 cmd = (Scsi_Cmnd *)hostdata->selecting;
1176 hostdata->selecting = NULL;
1177 hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
1178 cmd->host_scribble = (uchar *)hostdata->input_Q;
1179 hostdata->input_Q = cmd;
1180 }
1181 }
1182
1183 else {
1184
1185 if (cmd) {
1186 if (phs == 0x00) {
1187 hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
1188 cmd->host_scribble = (uchar *)hostdata->input_Q;
1189 hostdata->input_Q = cmd;
1190 }
1191 else {
1192 printk("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",asr,sr,phs);
1193 while (1)
1194 printk("\r");
1195 }
1196 }
1197
1198 }
1199
1200
1201
1202 id = read_wd33c93(regp, WD_SOURCE_ID);
1203 id &= SRCID_MASK;
1204
1205
1206
1207
1208
1209
1210 lun = read_wd33c93(regp, WD_DATA);
1211 if (hostdata->level2 < L2_RESELECT)
1212 write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK);
1213 lun &= 7;
1214
1215
1216
1217 cmd = (Scsi_Cmnd *)hostdata->disconnected_Q;
1218 patch = NULL;
1219 while (cmd) {
1220 if (id == cmd->target && lun == cmd->lun)
1221 break;
1222 patch = cmd;
1223 cmd = (Scsi_Cmnd *)cmd->host_scribble;
1224 }
1225
1226
1227
1228 if (!cmd) {
1229 printk("---TROUBLE: target %d.%d not in disconnect queue---",id,lun);
1230 return;
1231 }
1232
1233
1234
1235 if (patch)
1236 patch->host_scribble = cmd->host_scribble;
1237 else
1238 hostdata->disconnected_Q = (Scsi_Cmnd *)cmd->host_scribble;
1239 hostdata->connected = cmd;
1240
1241
1242
1243
1244
1245
1246 if (IS_DIR_OUT(cmd))
1247 write_wd33c93(regp, WD_DESTINATION_ID, cmd->target);
1248 else
1249 write_wd33c93(regp, WD_DESTINATION_ID, cmd->target | DSTID_DPD);
1250 if (hostdata->level2 >= L2_RESELECT) {
1251 write_wd33c93_count(regp, 0);
1252 write_wd33c93(regp, WD_COMMAND_PHASE, 0x45);
1253 write_wd33c93_cmd(regp, WD_CMD_SEL_ATN_XFER);
1254 hostdata->state = S_RUNNING_LEVEL2;
1255 }
1256 else
1257 hostdata->state = S_CONNECTED;
1258
1259 DB(DB_INTR,printk("-%ld",cmd->pid))
1260 break;
1261
1262 default:
1263 printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--",asr,sr,phs);
1264 }
1265
1266 restore_flags(flags);
1267
1268 DB(DB_INTR,printk("} "))
1269
1270 }
1271
1272
1273
1274 void reset_wd33c93(struct Scsi_Host *instance)
1275 {
1276 struct WD33C93_hostdata *hostdata;
1277 wd33c93_regs *regp;
1278 uchar sr;
1279
1280 hostdata = (struct WD33C93_hostdata *)instance->hostdata;
1281 regp = hostdata->regp;
1282
1283 write_wd33c93(regp, WD_OWN_ID, OWNID_EAF | OWNID_RAF |
1284 instance->this_id | hostdata->clock_freq);
1285 write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1286 write_wd33c93(regp, WD_SYNCHRONOUS_TRANSFER,
1287 calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF));
1288 write_wd33c93(regp, WD_COMMAND, WD_CMD_RESET);
1289
1290 while (!(READ_AUX_STAT() & ASR_INT))
1291 ;
1292 sr = read_wd33c93(regp, WD_SCSI_STATUS);
1293
1294 hostdata->microcode = read_wd33c93(regp, WD_CDB_1);
1295 if (sr == 0x00)
1296 hostdata->chip = C_WD33C93;
1297 else if (sr == 0x01) {
1298 write_wd33c93(regp, WD_QUEUE_TAG, 0xa5);
1299 sr = read_wd33c93(regp, WD_QUEUE_TAG);
1300 if (sr == 0xa5) {
1301 hostdata->chip = C_WD33C93B;
1302 write_wd33c93(regp, WD_QUEUE_TAG, 0);
1303 }
1304 else
1305 hostdata->chip = C_WD33C93A;
1306 }
1307 else
1308 hostdata->chip = C_UNKNOWN_CHIP;
1309
1310 write_wd33c93(regp, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
1311 write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1312 }
1313
1314
1315
1316 #if LINUX_VERSION_CODE >= 0x010300
1317 int wd33c93_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags)
1318 #else
1319 int wd33c93_reset(Scsi_Cmnd *SCpnt)
1320 #endif
1321 {
1322 unsigned long flags;
1323 struct Scsi_Host *instance;
1324 struct WD33C93_hostdata *hostdata;
1325 int i;
1326
1327 instance = SCpnt->host;
1328 hostdata = (struct WD33C93_hostdata *)instance->hostdata;
1329
1330 printk("scsi%d: reset. ", instance->host_no);
1331 save_flags(flags);
1332 cli();
1333
1334 ((struct WD33C93_hostdata *)instance->hostdata)->dma_stop(instance,NULL,0);
1335 for (i = 0; i < 8; i++) {
1336 hostdata->busy[i] = 0;
1337 hostdata->sync_xfer[i] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);
1338 hostdata->sync_stat[i] = SS_UNSET;
1339 }
1340 hostdata->input_Q = NULL;
1341 hostdata->selecting = NULL;
1342 hostdata->connected = NULL;
1343 hostdata->disconnected_Q = NULL;
1344 hostdata->state = S_UNCONNECTED;
1345 hostdata->dma = D_DMA_OFF;
1346 hostdata->incoming_ptr = 0;
1347 hostdata->outgoing_len = 0;
1348
1349 reset_wd33c93(instance);
1350 SCpnt->result = DID_RESET << 16;
1351 restore_flags(flags);
1352 return 0;
1353 }
1354
1355
1356
1357 int wd33c93_abort (Scsi_Cmnd *cmd)
1358 {
1359 struct Scsi_Host *instance;
1360 struct WD33C93_hostdata *hostdata;
1361 wd33c93_regs *regp;
1362 Scsi_Cmnd *tmp, *prev;
1363 unsigned long flags;
1364
1365 save_flags (flags);
1366 cli();
1367
1368 instance = cmd->host;
1369 hostdata = (struct WD33C93_hostdata *)instance->hostdata;
1370 regp = hostdata->regp;
1371
1372
1373
1374
1375
1376
1377 tmp = (Scsi_Cmnd *)hostdata->input_Q;
1378 prev = 0;
1379 while (tmp) {
1380 if (tmp == cmd) {
1381 if (prev)
1382 prev->host_scribble = cmd->host_scribble;
1383 cmd->host_scribble = NULL;
1384 cmd->result = DID_ABORT << 16;
1385 printk("scsi%d: Abort - removing command %ld from input_Q. ",
1386 instance->host_no, cmd->pid);
1387 cmd->scsi_done(cmd);
1388 restore_flags(flags);
1389 return SCSI_ABORT_SUCCESS;
1390 }
1391 prev = tmp;
1392 tmp = (Scsi_Cmnd *)tmp->host_scribble;
1393 }
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406 if (hostdata->connected == cmd) {
1407 uchar sr, asr;
1408 unsigned long timeout;
1409
1410 printk("scsi%d: Aborting connected command %ld - ",
1411 instance->host_no, cmd->pid);
1412
1413 printk("stopping DMA - ");
1414 if (hostdata->dma == D_DMA_RUNNING) {
1415 hostdata->dma_stop(instance, cmd, 0);
1416 hostdata->dma = D_DMA_OFF;
1417 }
1418
1419 printk("sending wd33c93 ABORT command - ");
1420 write_wd33c93(regp, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
1421 write_wd33c93_cmd(regp, WD_CMD_ABORT);
1422
1423
1424
1425 printk("flushing fifo - ");
1426 timeout = 1000000;
1427 do {
1428 asr = READ_AUX_STAT();
1429 if (asr & ASR_DBR)
1430 read_wd33c93(regp, WD_DATA);
1431 } while (!(asr & ASR_INT) && timeout-- > 0);
1432 sr = read_wd33c93(regp, WD_SCSI_STATUS);
1433 printk("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",
1434 asr, sr, read_wd33c93_count(regp), timeout);
1435
1436
1437
1438
1439
1440
1441
1442 printk("sending wd33c93 DISCONNECT command - ");
1443 write_wd33c93_cmd(regp, WD_CMD_DISCONNECT);
1444
1445 timeout = 1000000;
1446 asr = READ_AUX_STAT();
1447 while ((asr & ASR_CIP) && timeout-- > 0)
1448 asr = READ_AUX_STAT();
1449 sr = read_wd33c93(regp, WD_SCSI_STATUS);
1450 printk("asr=%02x, sr=%02x.",asr,sr);
1451
1452 hostdata->busy[cmd->target] &= ~(1 << cmd->lun);
1453 hostdata->connected = NULL;
1454 hostdata->state = S_UNCONNECTED;
1455 cmd->result = DID_ABORT << 16;
1456 cmd->scsi_done(cmd);
1457
1458
1459 wd33c93_execute (instance);
1460
1461 restore_flags(flags);
1462 return SCSI_ABORT_SUCCESS;
1463 }
1464
1465
1466
1467
1468
1469
1470
1471 tmp = (Scsi_Cmnd *)hostdata->disconnected_Q;
1472 while (tmp) {
1473 if (tmp == cmd) {
1474 printk("scsi%d: Abort - command %ld found on disconnected_Q - ",
1475 instance->host_no, cmd->pid);
1476 printk("returning ABORT_SNOOZE. ");
1477 restore_flags(flags);
1478 return SCSI_ABORT_SNOOZE;
1479 }
1480 tmp = (Scsi_Cmnd *)tmp->host_scribble;
1481 }
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494 wd33c93_execute (instance);
1495
1496 restore_flags(flags);
1497 printk("scsi%d: warning : SCSI command probably completed successfully"
1498 " before abortion. ", instance->host_no);
1499 return SCSI_ABORT_NOT_RUNNING;
1500 }
1501
1502
1503
1504 #define MAX_WD33C93_HOSTS 4
1505 #define MAX_SETUP_STRINGS (sizeof(setup_strings) / sizeof(char *))
1506 #define SETUP_BUFFER_SIZE 200
1507 static char setup_buffer[SETUP_BUFFER_SIZE];
1508 static char setup_used[MAX_SETUP_STRINGS];
1509
1510 void wd33c93_setup (char *str, int *ints)
1511 {
1512 int i,x;
1513 char *p1,*p2;
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524 p1 = setup_buffer;
1525 *p1 = '\0';
1526 if (ints[0]) {
1527 for (i=0; i<ints[0]; i++) {
1528 x = vsprintf(p1,"nosync:0x%02x,",&(ints[i+1]));
1529 p1 += x;
1530 }
1531 }
1532 if (str)
1533 strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
1534 setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
1535 p1 = setup_buffer;
1536 i = 0;
1537 while (*p1 && (i < MAX_SETUP_STRINGS)) {
1538 p2 = strchr(p1, ',');
1539 if (p2) {
1540 *p2 = '\0';
1541 if (p1 != p2)
1542 setup_strings[i] = p1;
1543 p1 = p2 + 1;
1544 i++;
1545 }
1546 else {
1547 setup_strings[i] = p1;
1548 break;
1549 }
1550 }
1551 for (i=0; i<MAX_SETUP_STRINGS; i++)
1552 setup_used[i] = 0;
1553 }
1554
1555
1556
1557
1558
1559 int check_setup_strings(char *key, int *flags, int *val, char *buf)
1560 {
1561 int x;
1562 char *cp;
1563
1564 for (x=0; x<MAX_SETUP_STRINGS; x++) {
1565 if (setup_used[x])
1566 continue;
1567 if (!strncmp(setup_strings[x], key, strlen(key)))
1568 break;
1569 if (!strncmp(setup_strings[x], "next", strlen("next")))
1570 return 0;
1571 }
1572 if (x == MAX_SETUP_STRINGS)
1573 return 0;
1574 setup_used[x] = 1;
1575 cp = setup_strings[x] + strlen(key);
1576 *val = -1;
1577 if (*cp != ':')
1578 return ++x;
1579 cp++;
1580 if ((*cp >= '0') && (*cp <= '9')) {
1581 *val = simple_strtoul(cp,NULL,0);
1582 }
1583 return ++x;
1584 }
1585
1586
1587
1588 void wd33c93_init (struct Scsi_Host *instance, wd33c93_regs *regs,
1589 dma_setup_t setup, dma_stop_t stop, int clock_freq)
1590 {
1591 struct WD33C93_hostdata *hostdata;
1592 int i;
1593 int flags;
1594 int val;
1595 char buf[32];
1596
1597 hostdata = (struct WD33C93_hostdata *)instance->hostdata;
1598
1599 hostdata->regp = regs;
1600 hostdata->clock_freq = clock_freq;
1601 hostdata->dma_setup = setup;
1602 hostdata->dma_stop = stop;
1603 hostdata->dma_bounce_buffer = NULL;
1604 hostdata->dma_bounce_len = 0;
1605 for (i = 0; i < 8; i++) {
1606 hostdata->busy[i] = 0;
1607 hostdata->sync_xfer[i] = calc_sync_xfer(DEFAULT_SX_PER/4,DEFAULT_SX_OFF);
1608 hostdata->sync_stat[i] = SS_UNSET;
1609 }
1610 hostdata->input_Q = NULL;
1611 hostdata->selecting = NULL;
1612 hostdata->connected = NULL;
1613 hostdata->disconnected_Q = NULL;
1614 hostdata->state = S_UNCONNECTED;
1615 hostdata->dma = D_DMA_OFF;
1616 hostdata->level2 = L2_BASIC;
1617 hostdata->disconnect = DIS_ADAPTIVE;
1618 hostdata->args = DEBUG_DEFAULTS;
1619 hostdata->incoming_ptr = 0;
1620 hostdata->outgoing_len = 0;
1621 hostdata->default_sx_per = DEFAULT_SX_PER;
1622 hostdata->no_sync = 0xff;
1623
1624 #ifdef PROC_INTERFACE
1625 hostdata->proc = PR_VERSION|PR_INFO|PR_TOTALS|
1626 PR_CONNECTED|PR_INPUTQ|PR_DISCQ|
1627 PR_STOP;
1628
1629 disc_allowed_total = 0;
1630 disc_taken_total = 0;
1631 #endif
1632
1633
1634 if (check_setup_strings("nosync",&flags,&val,buf))
1635 hostdata->no_sync = val;
1636
1637 if (check_setup_strings("period",&flags,&val,buf))
1638 hostdata->default_sx_per = sx_table[round_period((unsigned int)val)].period_ns;
1639
1640 if (check_setup_strings("disconnect",&flags,&val,buf)) {
1641 if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
1642 hostdata->disconnect = val;
1643 else
1644 hostdata->disconnect = DIS_ADAPTIVE;
1645 }
1646
1647 if (check_setup_strings("debug",&flags,&val,buf))
1648 hostdata->args = val & DB_MASK;
1649
1650 if (check_setup_strings("clock",&flags,&val,buf)) {
1651 if (val>7 && val<11)
1652 val = WD33C93_FS_8_10;
1653 else if (val>11 && val<16)
1654 val = WD33C93_FS_12_15;
1655 else if (val>15 && val<21)
1656 val = WD33C93_FS_16_20;
1657 else
1658 val = WD33C93_FS_8_10;
1659 hostdata->clock_freq = val;
1660 }
1661
1662 if ((i = check_setup_strings("next",&flags,&val,buf))) {
1663 while (i)
1664 setup_used[--i] = 1;
1665 }
1666
1667 #ifdef PROC_INTERFACE
1668 if (check_setup_strings("proc",&flags,&val,buf))
1669 hostdata->proc = val;
1670 #endif
1671
1672
1673 cli();
1674 reset_wd33c93(instance);
1675 sti();
1676
1677 printk("wd33c93-%d: chip=%s microcode=%02x\n",instance->host_no,
1678 (hostdata->chip==C_WD33C93)?"WD33c93":
1679 (hostdata->chip==C_WD33C93A)?"WD33c93A":
1680 (hostdata->chip==C_WD33C93B)?"WD33c93B":"unknown",
1681 hostdata->microcode);
1682
1683 #ifdef DEBUGGING_ON
1684 printk("wd33c93-%d: setup_strings=",instance->host_no);
1685 for (i=0; i<MAX_SETUP_STRINGS; i++)
1686 printk("%s,",setup_strings[i]);
1687 printk("\n");
1688 printk("wd33c93-%d: debug_flags = %04x\n",instance->host_no,hostdata->args);
1689 #endif
1690 printk("wd33c93-%d: driver version %s - %s\n",instance->host_no,
1691 WD33C93_VERSION,WD33C93_DATE);
1692 printk("wd33c93-%d: compiled on %s at %s\n",instance->host_no,
1693 __DATE__,__TIME__);
1694 }
1695
1696
1697 int wd33c93_proc_info(char *buf, char **start, off_t off, int len, int hn, int in)
1698 {
1699
1700 #ifdef PROC_INTERFACE
1701
1702 char *bp;
1703 char tbuf[128];
1704 unsigned long flags;
1705 struct Scsi_Host *instance;
1706 struct WD33C93_hostdata *hd;
1707 Scsi_Cmnd *cmd;
1708 int x,i;
1709 static int stop = 0;
1710
1711 for (instance=instance_list; instance; instance=instance->next) {
1712 if (instance->host_no == hn)
1713 break;
1714 }
1715 if (!instance) {
1716 printk("*** Hmm... Can't find host #%d!\n",hn);
1717 return (-ESRCH);
1718 }
1719 hd = (struct WD33C93_hostdata *)instance->hostdata;
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730 if (in) {
1731 buf[len] = '\0';
1732 bp = buf;
1733 if (!strncmp(bp,"debug:",6)) {
1734 bp += 6;
1735 hd->args = simple_strtoul(bp,NULL,0) & DB_MASK;
1736 }
1737 else if (!strncmp(bp,"disconnect:",11)) {
1738 bp += 11;
1739 x = simple_strtoul(bp,NULL,0);
1740 if (x < DIS_NEVER || x > DIS_ALWAYS)
1741 x = DIS_ADAPTIVE;
1742 hd->disconnect = x;
1743 }
1744 else if (!strncmp(bp,"period:",7)) {
1745 bp += 7;
1746 x = simple_strtoul(bp,NULL,0);
1747 hd->default_sx_per = sx_table[round_period((unsigned int)x)].period_ns;
1748 }
1749 else if (!strncmp(bp,"resync:",7)) {
1750 bp += 7;
1751 x = simple_strtoul(bp,NULL,0);
1752 for (i=0; i<7; i++)
1753 if (x & (1<<i))
1754 hd->sync_stat[i] = SS_UNSET;
1755 }
1756 else if (!strncmp(bp,"proc:",5)) {
1757 bp += 5;
1758 hd->proc = simple_strtoul(bp,NULL,0);
1759 }
1760 return len;
1761 }
1762
1763 save_flags(flags);
1764 cli();
1765 bp = buf;
1766 *bp = '\0';
1767 if (hd->proc & PR_VERSION) {
1768 sprintf(tbuf,"\nVersion %s - %s. Compiled %s %s",
1769 WD33C93_VERSION,WD33C93_DATE,__DATE__,__TIME__);
1770 strcat(bp,tbuf);
1771 }
1772 if (hd->proc & PR_INFO) {
1773 ;
1774 }
1775 if (hd->proc & PR_TOTALS) {
1776 sprintf(tbuf,"\n%ld disc_allowed, %ld disc_taken",
1777 disc_allowed_total,disc_taken_total);
1778 strcat(bp,tbuf);
1779 }
1780 if (hd->proc & PR_CONNECTED) {
1781 strcat(bp,"\nconnected: ");
1782 if (hd->connected) {
1783 cmd = (Scsi_Cmnd *)hd->connected;
1784 sprintf(tbuf," %ld-%d:%d(%02x)",
1785 cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
1786 strcat(bp,tbuf);
1787 }
1788 }
1789 if (hd->proc & PR_INPUTQ) {
1790 strcat(bp,"\ninput_Q: ");
1791 cmd = (Scsi_Cmnd *)hd->input_Q;
1792 while (cmd) {
1793 sprintf(tbuf," %ld-%d:%d(%02x)",
1794 cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
1795 strcat(bp,tbuf);
1796 cmd = (Scsi_Cmnd *)cmd->host_scribble;
1797 }
1798 }
1799 if (hd->proc & PR_DISCQ) {
1800 strcat(bp,"\ndisconnected_Q:");
1801 cmd = (Scsi_Cmnd *)hd->disconnected_Q;
1802 while (cmd) {
1803 sprintf(tbuf," %ld-%d:%d(%02x)",
1804 cmd->pid, cmd->target, cmd->lun, cmd->cmnd[0]);
1805 strcat(bp,tbuf);
1806 cmd = (Scsi_Cmnd *)cmd->host_scribble;
1807 }
1808 }
1809 strcat(bp,"\n");
1810 restore_flags(flags);
1811 *start = buf;
1812 if (stop) {
1813 stop = 0;
1814 return 0;
1815 }
1816 if (off > 0x40000)
1817 stop = 1;;
1818 if (hd->proc & PR_STOP)
1819 stop = 1;
1820 return strlen(bp);
1821
1822 #else
1823
1824 return 0;
1825
1826 #endif
1827
1828 }
1829
1830
1831 #ifdef MODULE
1832
1833 Scsi_Host_Template driver_template = WD33C93;
1834
1835 #include "scsi_module.c"
1836
1837 #endif
1838