This source file includes following definitions.
- ncr5380_wait_req
- ncr5380_wait_not_req
- ncr_sched_msgout
- ncr5380_pio_out
- ncr5380_pio_in
- ncr5380_init
- ncr5380_reset_scsibus
- ncr5380_intr
- ncr5380_abort
- ncr5380_cmd_timeout
- ncr5380_scsi_cmd
- ncr5380_done
- ncr5380_sched
- ncr5380_reselect
- ncr5380_select
- ncr5380_msg_in
- ncr5380_msg_out
- ncr5380_command
- ncr5380_data_xfer
- ncr5380_status
- ncr5380_machine
- ncr5380_show_scsi_cmd
- ncr5380_show_sense
- ncr5380_trace
- ncr5380_clear_trace
- ncr5380_show_trace
- ncr5380_show_req
- ncr5380_show_state
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 <sys/types.h>
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/kernel.h>
74 #include <sys/errno.h>
75 #include <sys/device.h>
76 #include <sys/buf.h>
77 #include <sys/proc.h>
78 #include <sys/user.h>
79
80 #include <scsi/scsi_all.h>
81 #include <scsi/scsi_debug.h>
82 #include <scsi/scsi_message.h>
83 #include <scsi/scsiconf.h>
84
85 #ifdef DDB
86 #include <ddb/db_output.h>
87 #endif
88
89 #include <dev/ic/ncr5380reg.h>
90 #include <dev/ic/ncr5380var.h>
91
92 static void ncr5380_sched(struct ncr5380_softc *);
93 static void ncr5380_done(struct ncr5380_softc *);
94
95 static int ncr5380_select(struct ncr5380_softc *, struct sci_req *);
96 static void ncr5380_reselect(struct ncr5380_softc *);
97
98 static int ncr5380_msg_in(struct ncr5380_softc *);
99 static int ncr5380_msg_out(struct ncr5380_softc *);
100 static int ncr5380_data_xfer(struct ncr5380_softc *, int);
101 static int ncr5380_command(struct ncr5380_softc *);
102 static int ncr5380_status(struct ncr5380_softc *);
103 static void ncr5380_machine(struct ncr5380_softc *);
104
105 void ncr5380_abort(struct ncr5380_softc *);
106 void ncr5380_cmd_timeout(void *);
107
108
109
110
111 #define ACT_CONTINUE 0x00
112 #define ACT_DISCONNECT 0x01
113 #define ACT_CMD_DONE 0x02
114 #define ACT_RESET_BUS 0x04
115 #define ACT_WAIT_DMA 0x10
116
117
118
119
120
121 #ifndef DDB
122
123 #define Debugger() printf("Debug: ncr5380.c:%d\n", __LINE__)
124 #endif
125
126 #ifdef NCR5380_DEBUG
127
128 #define NCR_DBG_BREAK 1
129 #define NCR_DBG_CMDS 2
130 int ncr5380_debug = NCR_DBG_BREAK|NCR_DBG_CMDS;
131 struct ncr5380_softc *ncr5380_debug_sc;
132
133 #define NCR_BREAK() \
134 do { if (ncr5380_debug & NCR_DBG_BREAK) Debugger(); } while (0)
135
136 static void ncr5380_show_scsi_cmd(struct scsi_xfer *);
137 static void ncr5380_show_sense(struct scsi_xfer *);
138
139 #ifdef DDB
140 void ncr5380_trace(char *, long);
141 void ncr5380_clear_trace(void);
142 void ncr5380_show_trace(void);
143 void ncr5380_show_req(struct sci_req *);
144 void ncr5380_show_req(struct sci_req *);
145 void ncr5380_show_state(void);
146 #endif
147 #else
148
149 #define NCR_BREAK()
150 #define ncr5380_show_scsi_cmd(xs)
151 #define ncr5380_show_sense(xs)
152
153 #endif
154
155 static char *
156 phase_names[8] = {
157 "DATA_OUT",
158 "DATA_IN",
159 "COMMAND",
160 "STATUS",
161 "UNSPEC1",
162 "UNSPEC2",
163 "MSG_OUT",
164 "MSG_IN",
165 };
166
167
168
169
170
171
172
173
174
175
176 int ncr5380_wait_phase_timo = 1000 * 10 * 300;
177
178
179 int ncr5380_wait_req_timo = 1000 * 50;
180 int ncr5380_wait_nrq_timo = 1000 * 25;
181
182 static __inline int ncr5380_wait_req(struct ncr5380_softc *);
183 static __inline int ncr5380_wait_not_req(struct ncr5380_softc *);
184 static __inline void ncr_sched_msgout(struct ncr5380_softc *, int);
185
186
187 static __inline int ncr5380_wait_req(sc)
188 struct ncr5380_softc *sc;
189 {
190 register int timo = ncr5380_wait_req_timo;
191 for (;;) {
192 if (*sc->sci_bus_csr & SCI_BUS_REQ) {
193 timo = 0;
194 break;
195 }
196 if (--timo < 0)
197 break;
198 delay(2);
199 }
200 return (timo);
201 }
202
203
204 static __inline int ncr5380_wait_not_req(sc)
205 struct ncr5380_softc *sc;
206 {
207 register int timo = ncr5380_wait_nrq_timo;
208 for (;;) {
209 if ((*sc->sci_bus_csr & SCI_BUS_REQ) == 0) {
210 timo = 0;
211 break;
212 }
213 if (--timo < 0)
214 break;
215 delay(2);
216 }
217 return (timo);
218 }
219
220
221 static __inline void
222 ncr_sched_msgout(sc, msg_code)
223 struct ncr5380_softc *sc;
224 int msg_code;
225 {
226
227 if (sc->sc_msgpriq == 0) {
228 register u_char icmd;
229 icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
230 *sc->sci_icmd = icmd | SCI_ICMD_ATN;
231 delay(2);
232 }
233 sc->sc_msgpriq |= msg_code;
234 }
235
236
237 int
238 ncr5380_pio_out(sc, phase, count, data)
239 struct ncr5380_softc *sc;
240 int phase, count;
241 unsigned char *data;
242 {
243 register u_char icmd;
244 register int resid;
245 register int error;
246
247 icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
248
249 icmd |= SCI_ICMD_DATA;
250 *sc->sci_icmd = icmd;
251
252 resid = count;
253 while (resid > 0) {
254 if (!SCI_BUSY(sc)) {
255 NCR_TRACE("pio_out: lost BSY, resid=%d\n", resid);
256 break;
257 }
258 if (ncr5380_wait_req(sc)) {
259 NCR_TRACE("pio_out: no REQ, resid=%d\n", resid);
260 break;
261 }
262 if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
263 break;
264
265
266 if (data)
267 *sc->sci_odata = *data++;
268 else
269 *sc->sci_odata = 0;
270
271
272 icmd |= SCI_ICMD_ACK;
273 *sc->sci_icmd = icmd;
274
275
276 error = ncr5380_wait_not_req(sc);
277
278
279 icmd &= ~SCI_ICMD_ACK;
280 *sc->sci_icmd = icmd;
281
282 if (error) {
283 NCR_TRACE("pio_out: stuck REQ, resid=%d\n", resid);
284 break;
285 }
286
287 --resid;
288 }
289
290
291 icmd &= ~SCI_ICMD_DATA;
292 *sc->sci_icmd = icmd;
293
294 return (count - resid);
295 }
296
297
298 int
299 ncr5380_pio_in(sc, phase, count, data)
300 struct ncr5380_softc *sc;
301 int phase, count;
302 unsigned char *data;
303 {
304 register u_char icmd;
305 register int resid;
306 register int error;
307
308 icmd = *(sc->sci_icmd) & SCI_ICMD_RMASK;
309
310 resid = count;
311 while (resid > 0) {
312 if (!SCI_BUSY(sc)) {
313 NCR_TRACE("pio_in: lost BSY, resid=%d\n", resid);
314 break;
315 }
316 if (ncr5380_wait_req(sc)) {
317 NCR_TRACE("pio_in: no REQ, resid=%d\n", resid);
318 break;
319 }
320
321 if (SCI_BUS_PHASE(*sc->sci_bus_csr) != phase)
322 break;
323
324
325 if (data)
326 *data++ = *sc->sci_data;
327 else
328 (void) *sc->sci_data;
329
330
331 icmd |= SCI_ICMD_ACK;
332 *sc->sci_icmd = icmd;
333
334
335 error = ncr5380_wait_not_req(sc);
336
337
338 icmd &= ~SCI_ICMD_ACK;
339 *sc->sci_icmd = icmd;
340
341 if (error) {
342 NCR_TRACE("pio_in: stuck REQ, resid=%d\n", resid);
343 break;
344 }
345
346 --resid;
347 }
348
349 return (count - resid);
350 }
351
352
353 void
354 ncr5380_init(sc)
355 struct ncr5380_softc *sc;
356 {
357 int i, j;
358 struct sci_req *sr;
359
360 #ifdef NCR5380_DEBUG
361 ncr5380_debug_sc = sc;
362 #endif
363
364 for (i = 0; i < SCI_OPENINGS; i++) {
365 sr = &sc->sc_ring[i];
366 sr->sr_xs = NULL;
367 timeout_set(&sr->sr_timeout, ncr5380_cmd_timeout, sr);
368 }
369 for (i = 0; i < 8; i++)
370 for (j = 0; j < 8; j++)
371 sc->sc_matrix[i][j] = NULL;
372
373 sc->sc_link.openings = 2;
374 sc->sc_prevphase = PHASE_INVALID;
375 sc->sc_state = NCR_IDLE;
376
377 *sc->sci_tcmd = PHASE_INVALID;
378 *sc->sci_icmd = 0;
379 *sc->sci_mode = 0;
380 *sc->sci_sel_enb = 0;
381 SCI_CLR_INTR(sc);
382
383
384 *sc->sci_sel_enb = 0x80;
385
386
387 if (sc->sc_intr_on) {
388 NCR_TRACE("init: intr ON\n", 0);
389 sc->sc_intr_on(sc);
390 }
391 }
392
393
394 void
395 ncr5380_reset_scsibus(sc)
396 struct ncr5380_softc *sc;
397 {
398
399 NCR_TRACE("reset_scsibus, cur=0x%x\n",
400 (long) sc->sc_current);
401
402 *sc->sci_icmd = SCI_ICMD_RST;
403 delay(500);
404 *sc->sci_icmd = 0;
405
406 *sc->sci_mode = 0;
407 *sc->sci_tcmd = PHASE_INVALID;
408
409 SCI_CLR_INTR(sc);
410
411 delay(100000);
412
413
414 }
415
416
417
418
419
420
421 int
422 ncr5380_intr(sc)
423 struct ncr5380_softc *sc;
424 {
425 int claimed = 0;
426
427
428
429
430
431
432 NCR_TRACE("intr: top, state=%d\n", sc->sc_state);
433
434 if (sc->sc_state == NCR_IDLE) {
435
436
437
438
439
440
441
442 if (sc->sc_intr_off) {
443 NCR_TRACE("intr: for reselect, intr off\n", 0);
444 sc->sc_intr_off(sc);
445 }
446
447 ncr5380_reselect(sc);
448 }
449
450
451
452
453
454
455
456
457
458 if (sc->sc_state & NCR_WORKING) {
459 NCR_TRACE("intr: call machine, cur=0x%x\n",
460 (long) sc->sc_current);
461
462 ncr5380_machine(sc);
463 NCR_TRACE("intr: machine done, cur=0x%x\n",
464 (long) sc->sc_current);
465 claimed = 1;
466 }
467
468
469 if (sc->sc_state == NCR_IDLE) {
470 NCR_TRACE("intr: call sched, cur=0x%x\n",
471 (long) sc->sc_current);
472 ncr5380_sched(sc);
473 NCR_TRACE("intr: sched done, cur=0x%x\n",
474 (long) sc->sc_current);
475 }
476
477 return claimed;
478 }
479
480
481
482
483
484 void
485 ncr5380_abort(sc)
486 struct ncr5380_softc *sc;
487 {
488
489
490
491
492
493
494
495
496 if (sc->sc_intr_off) {
497 NCR_TRACE("abort: intr off\n", 0);
498 sc->sc_intr_off(sc);
499 }
500
501 sc->sc_state |= NCR_ABORTING;
502 if ((sc->sc_state & NCR_DOINGDMA) == 0) {
503 ncr_sched_msgout(sc, SEND_ABORT);
504 }
505 NCR_TRACE("abort: call machine, cur=0x%x\n",
506 (long) sc->sc_current);
507 ncr5380_machine(sc);
508 NCR_TRACE("abort: machine done, cur=0x%x\n",
509 (long) sc->sc_current);
510
511
512 if (sc->sc_intr_on) {
513 NCR_TRACE("abort: intr ON\n", 0);
514 sc->sc_intr_on(sc);
515 }
516 }
517
518
519
520
521 void
522 ncr5380_cmd_timeout(arg)
523 void *arg;
524 {
525 struct sci_req *sr = arg;
526 struct scsi_xfer *xs;
527 struct scsi_link *sc_link;
528 struct ncr5380_softc *sc;
529 int s;
530
531 s = splbio();
532
533
534 xs = sr->sr_xs;
535 if (xs == NULL) {
536 printf("ncr5380_cmd_timeout: no scsi_xfer\n");
537 goto out;
538 }
539 sc_link = xs->sc_link;
540 sc = sc_link->adapter_softc;
541
542 printf("%s: cmd timeout, targ=%d, lun=%d\n",
543 sc->sc_dev.dv_xname,
544 sr->sr_target, sr->sr_lun);
545
546
547
548
549
550
551
552 sr->sr_flags |= SR_OVERDUE;
553 if (sc->sc_current == sr) {
554 NCR_TRACE("cmd_tmo: call abort, sr=0x%x\n", (long) sr);
555 ncr5380_abort(sc);
556 } else {
557
558
559
560
561 NCR_TRACE("cmd_tmo: clear matrix, t/l=0x%02x\n",
562 (sr->sr_target << 4) | sr->sr_lun);
563 sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL;
564 }
565
566
567
568
569
570
571 if (sc->sc_state == NCR_IDLE) {
572 NCR_TRACE("cmd_tmo: call sched, cur=0x%x\n",
573 (long) sc->sc_current);
574 ncr5380_sched(sc);
575 NCR_TRACE("cmd_tmo: sched done, cur=0x%x\n",
576 (long) sc->sc_current);
577 }
578
579 out:
580 splx(s);
581 }
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596 int
597 ncr5380_scsi_cmd(xs)
598 struct scsi_xfer *xs;
599 {
600 struct ncr5380_softc *sc;
601 struct sci_req *sr;
602 int s, rv, i, flags;
603
604 sc = xs->sc_link->adapter_softc;
605 flags = xs->flags;
606
607 if (sc->sc_flags & NCR5380_FORCE_POLLING)
608 flags |= SCSI_POLL;
609
610 if (flags & SCSI_DATA_UIO)
611 panic("ncr5380: scsi data uio requested");
612
613 s = splbio();
614
615 if (flags & SCSI_POLL) {
616
617 sr = sc->sc_current;
618 if (sr) {
619 printf("%s: polled request aborting %d/%d\n",
620 sc->sc_dev.dv_xname,
621 sr->sr_target, sr->sr_lun);
622 ncr5380_abort(sc);
623 }
624 if (sc->sc_state != NCR_IDLE) {
625 panic("ncr5380_scsi_cmd: polled request, abort failed");
626 }
627 }
628
629
630
631
632
633 for (i = 0; i < SCI_OPENINGS; i++)
634 if (sc->sc_ring[i].sr_xs == NULL)
635 goto new;
636
637 rv = TRY_AGAIN_LATER;
638 NCR_TRACE("scsi_cmd: no openings, rv=%d\n", rv);
639 goto out;
640
641 new:
642
643 sr = &sc->sc_ring[i];
644 sr->sr_xs = xs;
645 sr->sr_target = xs->sc_link->target;
646 sr->sr_lun = xs->sc_link->lun;
647 sr->sr_dma_hand = NULL;
648 sr->sr_dataptr = xs->data;
649 sr->sr_datalen = xs->datalen;
650 sr->sr_flags = (flags & SCSI_POLL) ? SR_IMMED : 0;
651 sr->sr_status = -1;
652 sc->sc_ncmds++;
653 rv = SUCCESSFULLY_QUEUED;
654
655 NCR_TRACE("scsi_cmd: new sr=0x%x\n", (long)sr);
656
657 if (flags & SCSI_POLL) {
658
659 sc->sc_rr = i;
660 }
661
662
663
664
665 if (sc->sc_state == NCR_IDLE) {
666 NCR_TRACE("scsi_cmd: call sched, cur=0x%x\n",
667 (long) sc->sc_current);
668 ncr5380_sched(sc);
669 NCR_TRACE("scsi_cmd: sched done, cur=0x%x\n",
670 (long) sc->sc_current);
671 }
672
673 if (flags & SCSI_POLL) {
674 #ifdef DIAGNOSTIC
675
676 if (sc->sc_state != NCR_IDLE)
677 panic("ncr5380_scsi_cmd: poll didn't finish");
678 #endif
679 rv = COMPLETE;
680 }
681
682 out:
683 splx(s);
684 return (rv);
685 }
686
687
688
689
690
691
692 static void
693 ncr5380_done(sc)
694 struct ncr5380_softc *sc;
695 {
696 struct sci_req *sr;
697 struct scsi_xfer *xs;
698
699 #ifdef DIAGNOSTIC
700 if (sc->sc_state == NCR_IDLE)
701 panic("ncr5380_done: state=idle");
702 if (sc->sc_current == NULL)
703 panic("ncr5380_done: current=0");
704 #endif
705
706 sr = sc->sc_current;
707 xs = sr->sr_xs;
708
709 NCR_TRACE("done: top, cur=0x%x\n", (long) sc->sc_current);
710
711
712
713
714 if (sr->sr_dma_hand) {
715 NCR_TRACE("done: dma_free, dh=0x%x\n",
716 (long) sr->sr_dma_hand);
717 (*sc->sc_dma_free)(sc);
718 }
719 #ifdef DIAGNOSTIC
720 if (sr->sr_dma_hand)
721 panic("ncr5380_done: dma free did not");
722 #endif
723
724 if (sc->sc_state & NCR_ABORTING) {
725 NCR_TRACE("done: aborting, error=%d\n", xs->error);
726 if (xs->error == XS_NOERROR)
727 xs->error = XS_TIMEOUT;
728 }
729
730 NCR_TRACE("done: check error=%d\n", (long) xs->error);
731
732
733 if (xs->error != XS_NOERROR)
734 goto finish;
735
736 NCR_TRACE("done: check status=%d\n", sr->sr_status);
737
738 switch (sr->sr_status) {
739 case SCSI_OK:
740 if (sr->sr_flags & SR_SENSE) {
741 #ifdef NCR5380_DEBUG
742 if (ncr5380_debug & NCR_DBG_CMDS) {
743 ncr5380_show_sense(xs);
744 }
745 #endif
746 xs->error = XS_SENSE;
747 }
748 break;
749
750 case SCSI_CHECK:
751 if (sr->sr_flags & SR_SENSE) {
752
753 printf("ncr5380_done: sense asked for sense\n");
754 NCR_BREAK();
755 xs->error = XS_DRIVER_STUFFUP;
756 break;
757 }
758 sr->sr_flags |= SR_SENSE;
759 NCR_TRACE("done: get sense, sr=0x%x\n", (long) sr);
760
761
762
763
764 sc->sc_state = NCR_IDLE;
765 sc->sc_current = NULL;
766 sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL;
767 return;
768
769 case SCSI_BUSY:
770 xs->error = XS_BUSY;
771 break;
772
773 case -1:
774
775
776 default:
777 printf("%s: target %d, bad status=%d\n",
778 sc->sc_dev.dv_xname, sr->sr_target, sr->sr_status);
779 xs->error = XS_DRIVER_STUFFUP;
780 break;
781 }
782
783 finish:
784
785 NCR_TRACE("done: finish, error=%d\n", xs->error);
786
787
788
789
790
791
792
793
794 #ifdef DIAGNOSTIC
795 if ((sc->sc_state & NCR_WORKING) == 0)
796 panic("ncr5380_done: bad state");
797 #endif
798
799
800 sc->sc_current = NULL;
801 sc->sc_matrix[sr->sr_target][sr->sr_lun] = NULL;
802 timeout_del(&sr->sr_timeout);
803
804
805 sr->sr_xs = NULL;
806 sc->sc_ncmds--;
807
808
809 xs->flags |= ITSDONE;
810 scsi_done(xs);
811
812 sc->sc_state = NCR_IDLE;
813
814 }
815
816
817
818
819
820
821
822
823 static void
824 ncr5380_sched(sc)
825 struct ncr5380_softc *sc;
826 {
827 struct sci_req *sr;
828 struct scsi_xfer *xs;
829 int target = 0, lun = 0;
830 int error, i;
831
832
833 if (sc->sc_intr_off) {
834 NCR_TRACE("sched: top, intr off\n", 0);
835 sc->sc_intr_off(sc);
836 }
837
838 next_job:
839
840
841
842 #ifdef DIAGNOSTIC
843 if (sc->sc_state != NCR_IDLE)
844 panic("ncr5380_sched: not idle");
845 if (sc->sc_current)
846 panic("ncr5380_sched: current set");
847 #endif
848
849
850
851
852
853
854
855
856 i = sc->sc_rr;
857 sr = NULL;
858 do {
859 if (sc->sc_ring[i].sr_xs) {
860 target = sc->sc_ring[i].sr_target;
861 lun = sc->sc_ring[i].sr_lun;
862 if (sc->sc_matrix[target][lun] == NULL) {
863
864
865
866
867
868
869
870 sc->sc_rr = i;
871 sr = &sc->sc_ring[i];
872 break;
873 }
874 }
875 i++;
876 if (i == SCI_OPENINGS)
877 i = 0;
878 } while (i != sc->sc_rr);
879
880 if (sr == NULL) {
881 NCR_TRACE("sched: no work, cur=0x%x\n",
882 (long) sc->sc_current);
883
884
885 if (sc->sc_intr_on) {
886 NCR_TRACE("sched: ret, intr ON\n", 0);
887 sc->sc_intr_on(sc);
888 }
889
890 return;
891 }
892
893 NCR_TRACE("sched: select for t/l=0x%02x\n",
894 (sr->sr_target << 4) | sr->sr_lun);
895
896 sc->sc_state = NCR_WORKING;
897 error = ncr5380_select(sc, sr);
898 if (sc->sc_current) {
899
900
901 if (sr->sr_flags & SR_IMMED) {
902 printf("%s: reselected while polling (abort)\n",
903 sc->sc_dev.dv_xname);
904
905 sc->sc_state |= NCR_ABORTING;
906 sc->sc_msgpriq |= SEND_ABORT;
907 }
908 sr = sc->sc_current;
909 xs = sr->sr_xs;
910 NCR_TRACE("sched: reselect, new sr=0x%x\n", (long)sr);
911 goto have_nexus;
912 }
913
914
915 sc->sc_matrix[target][lun] = sr;
916 sc->sc_current = sr;
917 xs = sr->sr_xs;
918
919
920
921
922 sc->sc_dataptr = sr->sr_dataptr;
923 sc->sc_datalen = sr->sr_datalen;
924 sc->sc_prevphase = PHASE_INVALID;
925 sc->sc_msgpriq = SEND_IDENTIFY;
926 sc->sc_msgoutq = 0;
927 sc->sc_msgout = 0;
928
929 NCR_TRACE("sched: select rv=%d\n", error);
930
931 switch (error) {
932 case XS_NOERROR:
933 break;
934
935 case XS_BUSY:
936
937 printf("%s: select found SCSI bus busy, resetting...\n",
938 sc->sc_dev.dv_xname);
939 ncr5380_reset_scsibus(sc);
940
941 case XS_SELTIMEOUT:
942 default:
943 xs->error = error;
944 NCR_TRACE("sched: call done, sr=0x%x\n", (long)sr);
945 ncr5380_done(sc);
946
947
948 sc->sc_dataptr = NULL;
949 sc->sc_datalen = 0;
950 sc->sc_prevphase = PHASE_INVALID;
951 sc->sc_msgpriq = 0;
952 sc->sc_msgoutq = 0;
953 sc->sc_msgout = 0;
954
955 goto next_job;
956 }
957
958
959
960
961
962
963 if (sr->sr_flags & SR_OVERDUE) {
964 NCR_TRACE("sched: overdue, sr=0x%x\n", (long)sr);
965 sc->sc_state |= NCR_ABORTING;
966 sc->sc_msgpriq |= SEND_ABORT;
967 goto have_nexus;
968 }
969
970
971
972
973
974 if (sr->sr_flags & SR_SENSE) {
975 NCR_TRACE("sched: get sense, sr=0x%x\n", (long)sr);
976
977 goto have_nexus;
978 }
979
980
981
982
983
984
985
986
987 #ifdef NCR5380_DEBUG
988 if (ncr5380_debug & NCR_DBG_CMDS) {
989 printf("ncr5380_sched: begin, target=%d, LUN=%d\n",
990 xs->sc_link->target, xs->sc_link->lun);
991 ncr5380_show_scsi_cmd(xs);
992 }
993 #endif
994 if (xs->flags & SCSI_RESET) {
995 NCR_TRACE("sched: cmd=reset, sr=0x%x\n", (long)sr);
996
997 sc->sc_msgpriq |= SEND_DEV_RESET;
998 goto have_nexus;
999 }
1000
1001 #ifdef DIAGNOSTIC
1002 if ((xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) == 0) {
1003 if (sc->sc_dataptr) {
1004 printf("%s: ptr but no data in/out flags?\n",
1005 sc->sc_dev.dv_xname);
1006 NCR_BREAK();
1007 sc->sc_dataptr = NULL;
1008 }
1009 }
1010 #endif
1011
1012
1013 if (sc->sc_dataptr && sc->sc_dma_alloc &&
1014 (sc->sc_datalen >= sc->sc_min_dma_len))
1015 {
1016 NCR_TRACE("sched: dma_alloc, len=%d\n", sc->sc_datalen);
1017 (*sc->sc_dma_alloc)(sc);
1018 }
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029 if (sr->sr_dma_hand && sc->sc_dma_setup) {
1030 NCR_TRACE("sched: dma_setup, dh=0x%x\n",
1031 (long) sr->sr_dma_hand);
1032 sc->sc_dma_setup(sc);
1033 }
1034
1035
1036
1037
1038 if ((sr->sr_flags & SR_IMMED) == 0) {
1039 i = (xs->timeout * hz) / 1000;
1040 NCR_TRACE("sched: set timeout=%d\n", i);
1041 timeout_add(&sr->sr_timeout, i);
1042 }
1043
1044 have_nexus:
1045 NCR_TRACE("sched: call machine, cur=0x%x\n",
1046 (long) sc->sc_current);
1047 ncr5380_machine(sc);
1048 NCR_TRACE("sched: machine done, cur=0x%x\n",
1049 (long) sc->sc_current);
1050
1051
1052
1053
1054
1055 if (sc->sc_state == NCR_IDLE)
1056 goto next_job;
1057
1058 return;
1059 }
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071 void
1072 ncr5380_reselect(sc)
1073 struct ncr5380_softc *sc;
1074 {
1075 struct sci_req *sr;
1076 int target, lun, phase, timo;
1077 int target_mask;
1078 u_char bus, data, icmd, msg;
1079
1080 #ifdef DIAGNOSTIC
1081
1082
1083
1084
1085
1086 if (sc->sc_current)
1087 panic("ncr5380_reselect: current set");
1088 #endif
1089
1090
1091
1092
1093
1094 bus = *(sc->sci_bus_csr);
1095 if ((bus & SCI_BUS_SEL) == 0) {
1096
1097 return;
1098 }
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108 timo = ncr5380_wait_nrq_timo;
1109 for (;;) {
1110 if ((bus & SCI_BUS_BSY) == 0)
1111 break;
1112
1113 if (--timo <= 0) {
1114 printf("%s: reselect, BSY stuck, bus=0x%x\n",
1115 sc->sc_dev.dv_xname, bus);
1116
1117 ncr5380_reset_scsibus(sc);
1118 return;
1119 }
1120 delay(2);
1121 bus = *(sc->sci_bus_csr);
1122
1123 if ((bus & SCI_BUS_SEL) == 0)
1124 return;
1125
1126 }
1127 NCR_TRACE("reselect, valid data after %d loops\n",
1128 ncr5380_wait_nrq_timo - timo);
1129
1130
1131
1132
1133
1134 delay(2);
1135 data = *(sc->sci_data) & 0xFF;
1136
1137
1138
1139
1140
1141
1142 if ((bus & SCI_BUS_IO) == 0) {
1143 printf("%s: selected as target, data=0x%x\n",
1144 sc->sc_dev.dv_xname, data);
1145
1146
1147 ncr5380_reset_scsibus(sc);
1148 return;
1149 }
1150
1151
1152
1153
1154 for (target = 0; target < 7; target++) {
1155 target_mask = (1 << target);
1156 if (data & target_mask)
1157 break;
1158 }
1159 if ((data & 0x7F) != target_mask) {
1160
1161 printf("%s: bad reselect, data=0x%x\n",
1162 sc->sc_dev.dv_xname, data);
1163 return;
1164 }
1165
1166 NCR_TRACE("reselect: target=0x%x\n", target);
1167
1168
1169 *(sc->sci_icmd) = SCI_ICMD_BSY;
1170
1171
1172 timo = ncr5380_wait_nrq_timo;
1173 for (;;) {
1174 bus = *(sc->sci_bus_csr);
1175 if ((bus & SCI_BUS_SEL) == 0)
1176 break;
1177 if (--timo <= 0) {
1178 printf("%s: reselect, SEL stuck, bus=0x%x\n",
1179 sc->sc_dev.dv_xname, bus);
1180 NCR_BREAK();
1181
1182 break;
1183 }
1184 delay(2);
1185 }
1186
1187
1188 *(sc->sci_icmd) = 0;
1189 *sc->sci_sel_enb = 0;
1190 SCI_CLR_INTR(sc);
1191
1192
1193
1194
1195
1196
1197 lun = 0;
1198
1199 if (ncr5380_wait_req(sc)) {
1200 printf("%s: reselect, no REQ\n",
1201 sc->sc_dev.dv_xname);
1202
1203 goto abort;
1204 }
1205 phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
1206 if (phase != PHASE_MSG_IN) {
1207 printf("%s: reselect, phase=%d\n",
1208 sc->sc_dev.dv_xname, phase);
1209 goto abort;
1210 }
1211
1212
1213 *(sc->sci_tcmd) = PHASE_MSG_IN;
1214
1215
1216 msg = *(sc->sci_data);
1217 if ((msg & 0x80) == 0) {
1218 printf("%s: reselect, not identify, msg=%d\n",
1219 sc->sc_dev.dv_xname, msg);
1220 goto abort;
1221 }
1222 lun = msg & 7;
1223
1224
1225 sr = sc->sc_matrix[target][lun];
1226 if (sr) {
1227
1228 sc->sc_state |= NCR_WORKING;
1229 sc->sc_current = sr;
1230 NCR_TRACE("reselect: resume sr=0x%x\n", (long)sr);
1231
1232
1233 sc->sc_dataptr = sr->sr_dataptr;
1234 sc->sc_datalen = sr->sr_datalen;
1235
1236 sc->sc_prevphase = PHASE_INVALID;
1237 sc->sc_msgpriq = 0;
1238 sc->sc_msgoutq = 0;
1239 sc->sc_msgout = 0;
1240
1241
1242
1243 if (sc->sc_parity_disable & target_mask)
1244 *sc->sci_mode = (SCI_MODE_MONBSY);
1245 else
1246 *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK);
1247
1248
1249
1250
1251
1252
1253 if (sr->sr_dma_hand && sc->sc_dma_setup) {
1254 NCR_TRACE("reselect: call DMA setup, dh=0x%x\n",
1255 (long) sr->sr_dma_hand);
1256 sc->sc_dma_setup(sc);
1257 }
1258
1259
1260 ncr5380_pio_in(sc, PHASE_MSG_IN, 1, &msg);
1261 return;
1262 }
1263
1264 printf("%s: phantom reselect: target=%d, LUN=%d\n",
1265 sc->sc_dev.dv_xname, target, lun);
1266 abort:
1267
1268
1269
1270
1271 sc->sc_state |= NCR_ABORTING;
1272
1273
1274 icmd = SCI_ICMD_ATN;
1275 *sc->sci_icmd = icmd;
1276 delay(2);
1277
1278
1279 ncr5380_pio_in(sc, PHASE_MSG_IN, 1, &msg);
1280
1281
1282 sc->sc_prevphase = PHASE_INVALID;
1283 sc->sc_msgpriq = SEND_ABORT;
1284 ncr5380_msg_out(sc);
1285
1286 *(sc->sci_tcmd) = PHASE_INVALID;
1287 *sc->sci_sel_enb = 0;
1288 SCI_CLR_INTR(sc);
1289 *sc->sci_sel_enb = 0x80;
1290
1291 sc->sc_state &= ~NCR_ABORTING;
1292 }
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305 static int
1306 ncr5380_select(sc, sr)
1307 struct ncr5380_softc *sc;
1308 struct sci_req *sr;
1309 {
1310 int timo, s, target_mask;
1311 u_char data, icmd;
1312
1313
1314 ncr5380_reselect(sc);
1315 if (sc->sc_current) {
1316 NCR_TRACE("select: reselect, cur=0x%x\n",
1317 (long) sc->sc_current);
1318 return XS_BUSY;
1319 }
1320
1321
1322
1323
1324
1325 *sc->sci_tcmd = PHASE_DATA_OUT;
1326 *sc->sci_icmd = icmd = 0;
1327 *sc->sci_mode = 0;
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346 s = splvm();
1347
1348 *(sc->sci_odata) = 0x80;
1349 *(sc->sci_mode) = SCI_MODE_ARB;
1350
1351 #define WAIT_AIP_USEC 20
1352
1353 timo = WAIT_AIP_USEC;
1354 for (;;) {
1355 if (*(sc->sci_icmd) & SCI_ICMD_AIP)
1356 break;
1357 if (timo <= 0) {
1358
1359
1360
1361
1362
1363 NCR_TRACE("select: bus busy, rc=%d\n", XS_BUSY);
1364 goto lost_arb;
1365 }
1366 timo -= 2;
1367 delay(2);
1368 }
1369 NCR_TRACE("select: have AIP after %d uSec.\n",
1370 WAIT_AIP_USEC - timo);
1371
1372
1373 delay(3);
1374
1375
1376 if (*(sc->sci_icmd) & SCI_ICMD_LST) {
1377
1378 NCR_TRACE("select: lost one, rc=%d\n", XS_BUSY);
1379 goto lost_arb;
1380 }
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392 icmd = (SCI_ICMD_BSY | SCI_ICMD_SEL);
1393 *sc->sci_icmd = icmd;
1394
1395
1396
1397
1398
1399
1400
1401 delay(2);
1402
1403
1404
1405
1406
1407
1408
1409 if (*(sc->sci_icmd) & SCI_ICMD_LST) {
1410
1411 NCR_TRACE("select: lost two, rc=%d\n", XS_BUSY);
1412
1413 lost_arb:
1414 *sc->sci_icmd = 0;
1415 *sc->sci_mode = 0;
1416
1417 splx(s);
1418
1419
1420
1421
1422
1423 ncr5380_reselect(sc);
1424 return XS_BUSY;
1425 }
1426
1427
1428 *sc->sci_mode = 0;
1429 *sc->sci_sel_enb = 0;
1430
1431 splx(s);
1432
1433
1434
1435
1436
1437
1438
1439 target_mask = (1 << sr->sr_target);
1440 data = 0x80 | target_mask;
1441 *(sc->sci_odata) = data;
1442 icmd |= (SCI_ICMD_DATA | SCI_ICMD_ATN);
1443 *(sc->sci_icmd) = icmd;
1444 delay(2);
1445
1446
1447 icmd &= ~SCI_ICMD_BSY;
1448 *(sc->sci_icmd) = icmd;
1449 delay(3);
1450
1451
1452
1453
1454
1455 for (timo = 25000;;) {
1456 if (*sc->sci_bus_csr & SCI_BUS_BSY)
1457 goto success;
1458 if (--timo <= 0)
1459 break;
1460 delay(10);
1461 }
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471 icmd &= ~SCI_ICMD_DATA;
1472 *(sc->sci_icmd) = icmd;
1473 delay(201);
1474 if ((*sc->sci_bus_csr & SCI_BUS_BSY) == 0) {
1475
1476 *sc->sci_tcmd = PHASE_INVALID;
1477 *sc->sci_icmd = 0;
1478 *sc->sci_mode = 0;
1479 *sc->sci_sel_enb = 0;
1480 SCI_CLR_INTR(sc);
1481 *sc->sci_sel_enb = 0x80;
1482 NCR_TRACE("select: device down, rc=%d\n", XS_SELTIMEOUT);
1483 return XS_SELTIMEOUT;
1484 }
1485
1486 success:
1487
1488
1489
1490
1491
1492 icmd &= ~(SCI_ICMD_DATA | SCI_ICMD_SEL);
1493 *sc->sci_icmd = icmd;
1494
1495
1496 if (sc->sc_parity_disable & target_mask)
1497 *sc->sci_mode = (SCI_MODE_MONBSY);
1498 else
1499 *sc->sci_mode = (SCI_MODE_MONBSY | SCI_MODE_PAR_CHK);
1500
1501 return XS_NOERROR;
1502 }
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536 #define IS1BYTEMSG(m) (((m) != 0x01 && (m) < 0x20) || (m) >= 0x80)
1537 #define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
1538 #define ISEXTMSG(m) ((m) == 0x01)
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548 static int
1549 ncr5380_msg_in(sc)
1550 register struct ncr5380_softc *sc;
1551 {
1552 struct sci_req *sr = sc->sc_current;
1553 struct scsi_xfer *xs = sr->sr_xs;
1554 int n, phase;
1555 int act_flags;
1556 register u_char icmd;
1557
1558
1559 *sc->sci_tcmd = PHASE_MSG_IN;
1560
1561 act_flags = ACT_CONTINUE;
1562 icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
1563
1564 if (sc->sc_prevphase == PHASE_MSG_IN) {
1565
1566 n = sc->sc_imp - sc->sc_imess;
1567 NCR_TRACE("msg_in: continuation, n=%d\n", n);
1568 goto nextbyte;
1569 }
1570
1571
1572 sc->sc_state &= ~NCR_DROP_MSGIN;
1573
1574 nextmsg:
1575 n = 0;
1576 sc->sc_imp = &sc->sc_imess[n];
1577
1578 nextbyte:
1579
1580
1581
1582
1583
1584 for (;;) {
1585
1586
1587
1588
1589 if (!SCI_BUSY(sc)) {
1590 NCR_TRACE("msg_in: lost BSY, n=%d\n", n);
1591
1592 act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
1593 return (act_flags);
1594 }
1595 if (ncr5380_wait_req(sc)) {
1596 NCR_TRACE("msg_in: BSY but no REQ, n=%d\n", n);
1597
1598 return (act_flags);
1599 }
1600 phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
1601 if (phase != PHASE_MSG_IN) {
1602
1603
1604
1605
1606
1607 return (act_flags);
1608 }
1609
1610 if (*sc->sci_csr & SCI_CSR_PERR) {
1611 ncr_sched_msgout(sc, SEND_PARITY_ERROR);
1612 sc->sc_state |= NCR_DROP_MSGIN;
1613 }
1614
1615
1616 if ((sc->sc_state & NCR_DROP_MSGIN) == 0) {
1617 if (n >= NCR_MAX_MSG_LEN) {
1618 ncr_sched_msgout(sc, SEND_REJECT);
1619 sc->sc_state |= NCR_DROP_MSGIN;
1620 } else {
1621 *sc->sc_imp++ = *sc->sci_data;
1622 n++;
1623
1624
1625
1626
1627
1628
1629 if (n == 1 && IS1BYTEMSG(sc->sc_imess[0]))
1630 goto have_msg;
1631 if (n == 2 && IS2BYTEMSG(sc->sc_imess[0]))
1632 goto have_msg;
1633 if (n >= 3 && ISEXTMSG(sc->sc_imess[0]) &&
1634 n == sc->sc_imess[1] + 2)
1635 goto have_msg;
1636 }
1637 }
1638
1639
1640
1641
1642
1643
1644
1645
1646 icmd |= SCI_ICMD_ACK;
1647 *sc->sci_icmd = icmd;
1648
1649 if (ncr5380_wait_not_req(sc)) {
1650 NCR_TRACE("msg_in: drop, stuck REQ, n=%d\n", n);
1651 act_flags |= ACT_RESET_BUS;
1652 }
1653
1654 icmd &= ~SCI_ICMD_ACK;
1655 *sc->sci_icmd = icmd;
1656
1657 if (act_flags != ACT_CONTINUE)
1658 return (act_flags);
1659
1660
1661 }
1662
1663 have_msg:
1664
1665
1666 switch (sc->sc_imess[0]) {
1667 case MSG_CMDCOMPLETE:
1668 NCR_TRACE("msg_in: CMDCOMPLETE\n", 0);
1669
1670 act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
1671 break;
1672
1673 case MSG_PARITY_ERROR:
1674 NCR_TRACE("msg_in: PARITY_ERROR\n", 0);
1675
1676 ncr_sched_msgout(sc, sc->sc_msgout);
1677
1678 icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
1679 break;
1680
1681 case MSG_MESSAGE_REJECT:
1682
1683 NCR_TRACE("msg_in: got reject for 0x%x\n", sc->sc_msgout);
1684 switch (sc->sc_msgout) {
1685 case SEND_IDENTIFY:
1686
1687
1688 break;
1689 case SEND_INIT_DET_ERR:
1690 goto abort;
1691 }
1692 break;
1693
1694 case MSG_NOOP:
1695 NCR_TRACE("msg_in: NOOP\n", 0);
1696 break;
1697
1698 case MSG_DISCONNECT:
1699 NCR_TRACE("msg_in: DISCONNECT\n", 0);
1700
1701 act_flags |= ACT_DISCONNECT;
1702 if ((xs->sc_link->quirks & SDEV_AUTOSAVE) == 0)
1703 break;
1704
1705
1706 case MSG_SAVEDATAPOINTER:
1707 NCR_TRACE("msg_in: SAVE_PTRS\n", 0);
1708 sr->sr_dataptr = sc->sc_dataptr;
1709 sr->sr_datalen = sc->sc_datalen;
1710 break;
1711
1712 case MSG_RESTOREPOINTERS:
1713 NCR_TRACE("msg_in: RESTORE_PTRS\n", 0);
1714 sc->sc_dataptr = sr->sr_dataptr;
1715 sc->sc_datalen = sr->sr_datalen;
1716 break;
1717
1718 case MSG_EXTENDED:
1719 switch (sc->sc_imess[2]) {
1720 case MSG_EXT_SDTR:
1721 case MSG_EXT_WDTR:
1722
1723 goto reject;
1724 default:
1725 printf("%s: unrecognized MESSAGE EXTENDED; sending REJECT\n",
1726 sc->sc_dev.dv_xname);
1727 NCR_BREAK();
1728 goto reject;
1729 }
1730 break;
1731
1732 default:
1733 NCR_TRACE("msg_in: eh? imsg=0x%x\n", sc->sc_imess[0]);
1734 printf("%s: unrecognized MESSAGE; sending REJECT\n",
1735 sc->sc_dev.dv_xname);
1736 NCR_BREAK();
1737
1738 reject:
1739 ncr_sched_msgout(sc, SEND_REJECT);
1740
1741 icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
1742 break;
1743
1744 abort:
1745 sc->sc_state |= NCR_ABORTING;
1746 ncr_sched_msgout(sc, SEND_ABORT);
1747 break;
1748 }
1749
1750
1751 icmd |= SCI_ICMD_ACK;
1752 *sc->sci_icmd = icmd;
1753
1754 if (ncr5380_wait_not_req(sc)) {
1755 NCR_TRACE("msg_in: last, stuck REQ, n=%d\n", n);
1756 act_flags |= ACT_RESET_BUS;
1757 }
1758
1759 icmd &= ~SCI_ICMD_ACK;
1760 *sc->sci_icmd = icmd;
1761
1762
1763 if (act_flags == ACT_CONTINUE)
1764 goto nextmsg;
1765
1766 return (act_flags);
1767 }
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789 static int
1790 ncr5380_msg_out(sc)
1791 register struct ncr5380_softc *sc;
1792 {
1793 struct sci_req *sr = sc->sc_current;
1794 int act_flags, n, phase, progress;
1795 register u_char icmd, msg;
1796
1797
1798 *sc->sci_tcmd = PHASE_MSG_OUT;
1799
1800 progress = 0;
1801 act_flags = ACT_CONTINUE;
1802
1803
1804
1805
1806
1807 icmd = *sc->sci_icmd & SCI_ICMD_RMASK;
1808 icmd |= (SCI_ICMD_ATN | SCI_ICMD_DATA);
1809 *sc->sci_icmd = icmd;
1810
1811 if (sc->sc_prevphase == PHASE_MSG_OUT) {
1812 if (sc->sc_omp == sc->sc_omess) {
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824 sc->sc_msgpriq |= sc->sc_msgoutq;
1825 NCR_TRACE("msg_out: retrans priq=0x%x\n", sc->sc_msgpriq);
1826 } else {
1827
1828 n = sc->sc_omp - sc->sc_omess;
1829 NCR_TRACE("msg_out: continuation, n=%d\n", n);
1830 goto nextbyte;
1831 }
1832 }
1833
1834
1835 sc->sc_msgoutq = 0;
1836
1837 nextmsg:
1838
1839 sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq;
1840 sc->sc_msgpriq &= ~sc->sc_msgout;
1841 sc->sc_msgoutq |= sc->sc_msgout;
1842
1843
1844 switch (sc->sc_msgout) {
1845 case SEND_IDENTIFY:
1846 NCR_TRACE("msg_out: SEND_IDENTIFY\n", 0);
1847 if (sr == NULL) {
1848 printf("%s: SEND_IDENTIFY while not connected; sending NOOP\n",
1849 sc->sc_dev.dv_xname);
1850 NCR_BREAK();
1851 goto noop;
1852 }
1853
1854
1855
1856
1857
1858 msg = 0xc0;
1859 if (sc->sc_no_disconnect & (1 << sr->sr_target))
1860 msg = 0x80;
1861 if (sr->sr_flags & (SR_IMMED | SR_SENSE))
1862 msg = 0x80;
1863 sc->sc_omess[0] = msg | sr->sr_lun;
1864 n = 1;
1865 break;
1866
1867 case SEND_DEV_RESET:
1868 NCR_TRACE("msg_out: SEND_DEV_RESET\n", 0);
1869
1870
1871 act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
1872 sc->sc_omess[0] = MSG_BUS_DEV_RESET;
1873 n = 1;
1874 break;
1875
1876 case SEND_REJECT:
1877 NCR_TRACE("msg_out: SEND_REJECT\n", 0);
1878 sc->sc_omess[0] = MSG_MESSAGE_REJECT;
1879 n = 1;
1880 break;
1881
1882 case SEND_PARITY_ERROR:
1883 NCR_TRACE("msg_out: SEND_PARITY_ERROR\n", 0);
1884 sc->sc_omess[0] = MSG_PARITY_ERROR;
1885 n = 1;
1886 break;
1887
1888 case SEND_INIT_DET_ERR:
1889 NCR_TRACE("msg_out: SEND_INIT_DET_ERR\n", 0);
1890 sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
1891 n = 1;
1892 break;
1893
1894 case SEND_ABORT:
1895 NCR_TRACE("msg_out: SEND_ABORT\n", 0);
1896
1897
1898 act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
1899 sc->sc_omess[0] = MSG_ABORT;
1900 n = 1;
1901 break;
1902
1903 case 0:
1904 printf("%s: unexpected MESSAGE OUT; sending NOOP\n",
1905 sc->sc_dev.dv_xname);
1906 NCR_BREAK();
1907 noop:
1908 NCR_TRACE("msg_out: send NOOP\n", 0);
1909 sc->sc_omess[0] = MSG_NOOP;
1910 n = 1;
1911 break;
1912
1913 default:
1914 printf("%s: weird MESSAGE OUT; sending NOOP\n",
1915 sc->sc_dev.dv_xname);
1916 NCR_BREAK();
1917 goto noop;
1918 }
1919 sc->sc_omp = &sc->sc_omess[n];
1920
1921 nextbyte:
1922
1923 while (n > 0) {
1924
1925
1926
1927
1928 if (!SCI_BUSY(sc)) {
1929 NCR_TRACE("msg_out: lost BSY, n=%d\n", n);
1930 goto out;
1931 }
1932 if (ncr5380_wait_req(sc)) {
1933 NCR_TRACE("msg_out: no REQ, n=%d\n", n);
1934 goto out;
1935 }
1936 phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
1937 if (phase != PHASE_MSG_OUT) {
1938
1939
1940
1941
1942 NCR_TRACE("msg_out: new phase=%d\n", phase);
1943 goto out;
1944 }
1945
1946
1947 --n;
1948
1949
1950 if (n == 0 && sc->sc_msgpriq == 0) {
1951 icmd &= ~SCI_ICMD_ATN;
1952 *sc->sci_icmd = icmd;
1953
1954 delay(2);
1955 }
1956
1957
1958 *sc->sci_odata = *--sc->sc_omp;
1959
1960
1961 icmd |= SCI_ICMD_ACK;
1962 *sc->sci_icmd = icmd;
1963
1964
1965 if (ncr5380_wait_not_req(sc)) {
1966 NCR_TRACE("msg_out: stuck REQ, n=%d\n", n);
1967 act_flags |= ACT_RESET_BUS;
1968 }
1969
1970
1971 icmd &= ~SCI_ICMD_ACK;
1972 *sc->sci_icmd = icmd;
1973
1974
1975 if (act_flags & ACT_RESET_BUS)
1976 goto out;
1977
1978 }
1979 progress++;
1980
1981
1982 if (sc->sc_msgpriq != 0) {
1983
1984 goto nextmsg;
1985 }
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995 out:
1996
1997 icmd &= ~SCI_ICMD_DATA;
1998 *sc->sci_icmd = icmd;
1999
2000 if (!progress)
2001 act_flags |= ACT_RESET_BUS;
2002
2003 return (act_flags);
2004 }
2005
2006
2007
2008
2009
2010 static int
2011 ncr5380_command(sc)
2012 struct ncr5380_softc *sc;
2013 {
2014 struct sci_req *sr = sc->sc_current;
2015 struct scsi_xfer *xs = sr->sr_xs;
2016 struct scsi_sense rqs;
2017 int len;
2018
2019
2020 *sc->sci_tcmd = PHASE_COMMAND;
2021
2022 if (sr->sr_flags & SR_SENSE) {
2023 rqs.opcode = REQUEST_SENSE;
2024 rqs.byte2 = xs->sc_link->lun << 5;
2025 rqs.length = sizeof(xs->sense);
2026
2027 rqs.unused[0] = rqs.unused[1] = rqs.control = 0;
2028 len = ncr5380_pio_out(sc, PHASE_COMMAND, sizeof(rqs),
2029 (u_char *)&rqs);
2030 }
2031 else {
2032
2033
2034 len = ncr5380_pio_out(sc, PHASE_COMMAND, xs->cmdlen,
2035 (u_char *)xs->cmd);
2036 }
2037
2038 if (len != xs->cmdlen) {
2039 #ifdef NCR5380_DEBUG
2040 printf("ncr5380_command: short transfer: wanted %d got %d.\n",
2041 xs->cmdlen, len);
2042 ncr5380_show_scsi_cmd(xs);
2043 NCR_BREAK();
2044 #endif
2045 if (len < 6) {
2046 xs->error = XS_DRIVER_STUFFUP;
2047 sc->sc_state |= NCR_ABORTING;
2048 ncr_sched_msgout(sc, SEND_ABORT);
2049 }
2050
2051 }
2052
2053 return ACT_CONTINUE;
2054 }
2055
2056
2057
2058
2059
2060 static int
2061 ncr5380_data_xfer(sc, phase)
2062 struct ncr5380_softc *sc;
2063 int phase;
2064 {
2065 struct sci_req *sr = sc->sc_current;
2066 struct scsi_xfer *xs = sr->sr_xs;
2067 int expected_phase;
2068 int len;
2069
2070 if (sr->sr_flags & SR_SENSE) {
2071 NCR_TRACE("data_xfer: get sense, sr=0x%x\n", (long)sr);
2072 if (phase != PHASE_DATA_IN) {
2073 printf("%s: sense phase error\n", sc->sc_dev.dv_xname);
2074 goto abort;
2075 }
2076
2077 *sc->sci_tcmd = PHASE_DATA_IN;
2078 len = ncr5380_pio_in(sc, phase, sizeof(xs->sense),
2079 (u_char *)&xs->sense);
2080 return ACT_CONTINUE;
2081 }
2082
2083
2084
2085
2086 if (sc->sc_state & NCR_ABORTING) {
2087 printf("%s: aborting, but phase=%s (reset)\n",
2088 sc->sc_dev.dv_xname, phase_names[phase & 7]);
2089 return ACT_RESET_BUS;
2090 }
2091
2092
2093 expected_phase = (xs->flags & SCSI_DATA_OUT) ?
2094 PHASE_DATA_OUT : PHASE_DATA_IN;
2095 if (phase != expected_phase) {
2096 printf("%s: data phase error\n", sc->sc_dev.dv_xname);
2097 goto abort;
2098 }
2099
2100
2101 if (sc->sc_datalen <= 0) {
2102
2103 if (phase == PHASE_DATA_IN)
2104 ncr5380_pio_in(sc, phase, 4096, NULL);
2105 else
2106 ncr5380_pio_out(sc, phase, 4096, NULL);
2107
2108 if (SCI_BUS_PHASE(*sc->sci_bus_csr) == phase) {
2109
2110 printf("%s: too much data padding\n",
2111 sc->sc_dev.dv_xname);
2112 goto abort;
2113 }
2114 return ACT_CONTINUE;
2115 }
2116
2117
2118
2119
2120
2121 if (sr->sr_dma_hand &&
2122 (sc->sc_datalen >= sc->sc_min_dma_len))
2123 {
2124
2125
2126
2127
2128
2129 NCR_TRACE("data_xfer: dma_start, dh=0x%x\n",
2130 (long) sr->sr_dma_hand);
2131 (*sc->sc_dma_start)(sc);
2132 return ACT_WAIT_DMA;
2133 }
2134
2135
2136
2137
2138
2139 NCR_TRACE("data_xfer: doing PIO, len=%d\n", sc->sc_datalen);
2140
2141 *sc->sci_tcmd = phase;
2142 if (phase == PHASE_DATA_OUT) {
2143 len = (*sc->sc_pio_out)(sc, phase, sc->sc_datalen, sc->sc_dataptr);
2144 } else {
2145 len = (*sc->sc_pio_in) (sc, phase, sc->sc_datalen, sc->sc_dataptr);
2146 }
2147 sc->sc_dataptr += len;
2148 sc->sc_datalen -= len;
2149
2150 NCR_TRACE("data_xfer: did PIO, resid=%d\n", sc->sc_datalen);
2151 return (ACT_CONTINUE);
2152
2153 abort:
2154 sc->sc_state |= NCR_ABORTING;
2155 ncr_sched_msgout(sc, SEND_ABORT);
2156 return (ACT_CONTINUE);
2157 }
2158
2159
2160 static int
2161 ncr5380_status(sc)
2162 struct ncr5380_softc *sc;
2163 {
2164 int len;
2165 u_char status;
2166 struct sci_req *sr = sc->sc_current;
2167
2168
2169 *sc->sci_tcmd = PHASE_STATUS;
2170
2171 len = ncr5380_pio_in(sc, PHASE_STATUS, 1, &status);
2172 if (len) {
2173 sr->sr_status = status;
2174 } else {
2175 printf("ncr5380_status: none?\n");
2176 }
2177
2178 return ACT_CONTINUE;
2179 }
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191 static void
2192 ncr5380_machine(sc)
2193 struct ncr5380_softc *sc;
2194 {
2195 struct sci_req *sr;
2196 struct scsi_xfer *xs;
2197 int act_flags, phase, timo;
2198
2199 #ifdef DIAGNOSTIC
2200 if (sc->sc_state == NCR_IDLE)
2201 panic("ncr5380_machine: state=idle");
2202 if (sc->sc_current == NULL)
2203 panic("ncr5380_machine: no current cmd");
2204 #endif
2205
2206 sr = sc->sc_current;
2207 xs = sr->sr_xs;
2208 act_flags = ACT_CONTINUE;
2209
2210
2211
2212
2213
2214
2215 if (sc->sc_state & NCR_DOINGDMA) {
2216
2217 goto dma_done;
2218 }
2219
2220 next_phase:
2221
2222 if (!SCI_BUSY(sc)) {
2223
2224 printf("ncr5380_machine: unexpected disconnect.\n");
2225 xs->error = XS_DRIVER_STUFFUP;
2226 act_flags |= (ACT_DISCONNECT | ACT_CMD_DONE);
2227 goto do_actions;
2228 }
2229
2230
2231
2232
2233
2234
2235 timo = ncr5380_wait_phase_timo;
2236 for (;;) {
2237 if (*sc->sci_bus_csr & SCI_BUS_REQ)
2238 break;
2239 if (--timo <= 0) {
2240 if (sc->sc_state & NCR_ABORTING) {
2241 printf("%s: no REQ while aborting, reset\n",
2242 sc->sc_dev.dv_xname);
2243 act_flags |= ACT_RESET_BUS;
2244 goto do_actions;
2245 }
2246 printf("%s: no REQ for next phase, abort\n",
2247 sc->sc_dev.dv_xname);
2248 sc->sc_state |= NCR_ABORTING;
2249 ncr_sched_msgout(sc, SEND_ABORT);
2250 goto next_phase;
2251 }
2252 delay(100);
2253 }
2254
2255 phase = SCI_BUS_PHASE(*sc->sci_bus_csr);
2256 NCR_TRACE("machine: phase=%s\n",
2257 (long) phase_names[phase & 7]);
2258
2259
2260
2261
2262
2263
2264 #if 0
2265
2266
2267
2268
2269
2270 *sc->sci_tcmd = phase;
2271 #endif
2272
2273 switch (phase) {
2274
2275 case PHASE_DATA_OUT:
2276 case PHASE_DATA_IN:
2277 act_flags = ncr5380_data_xfer(sc, phase);
2278 break;
2279
2280 case PHASE_COMMAND:
2281 act_flags = ncr5380_command(sc);
2282 break;
2283
2284 case PHASE_STATUS:
2285 act_flags = ncr5380_status(sc);
2286 break;
2287
2288 case PHASE_MSG_OUT:
2289 act_flags = ncr5380_msg_out(sc);
2290 break;
2291
2292 case PHASE_MSG_IN:
2293 act_flags = ncr5380_msg_in(sc);
2294 break;
2295
2296 default:
2297 printf("ncr5380_machine: Unexpected phase 0x%x\n", phase);
2298 sc->sc_state |= NCR_ABORTING;
2299 ncr_sched_msgout(sc, SEND_ABORT);
2300 goto next_phase;
2301
2302 }
2303 sc->sc_prevphase = phase;
2304
2305 do_actions:
2306 __asm("_ncr5380_actions:");
2307
2308 if (act_flags & ACT_WAIT_DMA) {
2309 act_flags &= ~ACT_WAIT_DMA;
2310
2311 if ((sr->sr_flags & SR_IMMED) == 0) {
2312 NCR_TRACE("machine: wait for DMA intr.\n", 0);
2313 return;
2314 }
2315
2316 NCR_TRACE("machine: dma_poll, dh=0x%x\n",
2317 (long) sr->sr_dma_hand);
2318 (*sc->sc_dma_poll)(sc);
2319 dma_done:
2320
2321 if (sr->sr_flags & SR_OVERDUE)
2322 sc->sc_state |= NCR_ABORTING;
2323 NCR_TRACE("machine: dma_stop, dh=0x%x\n",
2324 (long) sr->sr_dma_hand);
2325 (*sc->sc_dma_stop)(sc);
2326 SCI_CLR_INTR(sc);
2327
2328
2329
2330
2331
2332 if (sc->sc_state & NCR_ABORTING) {
2333 ncr_sched_msgout(sc, SEND_ABORT);
2334 }
2335 }
2336
2337
2338
2339
2340
2341 if (*(sc->sci_csr) & SCI_CSR_PERR) {
2342 printf("%s: parity error!\n", sc->sc_dev.dv_xname);
2343
2344 ncr_sched_msgout(sc, SEND_PARITY_ERROR);
2345 }
2346
2347 if (act_flags == ACT_CONTINUE)
2348 goto next_phase;
2349
2350
2351 NCR_TRACE("machine: act_flags=0x%x\n", act_flags);
2352
2353 if (act_flags & ACT_RESET_BUS) {
2354 act_flags |= ACT_CMD_DONE;
2355
2356
2357
2358
2359 sc->sc_state |= NCR_ABORTING;
2360 printf("%s: reset SCSI bus for TID=%d LUN=%d\n",
2361 sc->sc_dev.dv_xname, sr->sr_target, sr->sr_lun);
2362 ncr5380_reset_scsibus(sc);
2363 }
2364
2365 if (act_flags & ACT_CMD_DONE) {
2366 act_flags |= ACT_DISCONNECT;
2367
2368
2369 if (sc->sc_datalen < 0) {
2370 printf("%s: %d extra bytes from %d:%d\n",
2371 sc->sc_dev.dv_xname, -sc->sc_datalen,
2372 sr->sr_target, sr->sr_lun);
2373 sc->sc_datalen = 0;
2374 }
2375 xs->resid = sc->sc_datalen;
2376
2377 NCR_TRACE("machine: call done, cur=0x%x\n", (long)sr);
2378 ncr5380_done(sc);
2379 }
2380
2381 if (act_flags & ACT_DISCONNECT) {
2382
2383
2384
2385
2386
2387 timo = ncr5380_wait_req_timo;
2388 for (;;) {
2389 if (!SCI_BUSY(sc))
2390 goto busfree;
2391 if (--timo <= 0)
2392 break;
2393 delay(2);
2394 }
2395
2396 printf("%s: Target %d LUN %d stuck busy, resetting...\n",
2397 sc->sc_dev.dv_xname, sr->sr_target, sr->sr_lun);
2398 ncr5380_reset_scsibus(sc);
2399 busfree:
2400 NCR_TRACE("machine: discon, waited %d\n",
2401 ncr5380_wait_req_timo - timo);
2402
2403 *sc->sci_icmd = 0;
2404 *sc->sci_mode = 0;
2405 *sc->sci_tcmd = PHASE_INVALID;
2406 *sc->sci_sel_enb = 0;
2407 SCI_CLR_INTR(sc);
2408 *sc->sci_sel_enb = 0x80;
2409
2410 if ((act_flags & ACT_CMD_DONE) == 0) {
2411 __asm("_ncr5380_disconnected:");
2412 NCR_TRACE("machine: discon, cur=0x%x\n", (long)sr);
2413 }
2414
2415
2416
2417
2418
2419
2420 sc->sc_state = NCR_IDLE;
2421 sc->sc_current = NULL;
2422
2423
2424 sc->sc_dataptr = NULL;
2425 sc->sc_datalen = 0;
2426 sc->sc_prevphase = PHASE_INVALID;
2427 sc->sc_msgpriq = 0;
2428 sc->sc_msgoutq = 0;
2429 sc->sc_msgout = 0;
2430
2431
2432 }
2433 }
2434
2435
2436 #ifdef NCR5380_DEBUG
2437
2438 static void
2439 ncr5380_show_scsi_cmd(xs)
2440 struct scsi_xfer *xs;
2441 {
2442 u_char *b = (u_char *) xs->cmd;
2443 int i = 0;
2444
2445 if ( ! ( xs->flags & SCSI_RESET ) ) {
2446 printf("si(%d:%d:%d)-",
2447 xs->sc_link->scsibus, xs->sc_link->target,
2448 xs->sc_link->lun);
2449 while (i < xs->cmdlen) {
2450 if (i) printf(",");
2451 printf("%x",b[i++]);
2452 }
2453 printf("-\n");
2454 } else {
2455 printf("si(%d:%d:%d)-RESET-\n",
2456 xs->sc_link->scsibus, xs->sc_link->target,
2457 xs->sc_link->lun);
2458 }
2459 }
2460
2461
2462 static void
2463 ncr5380_show_sense(xs)
2464 struct scsi_xfer *xs;
2465 {
2466 u_char *b = (u_char *)&xs->sense;
2467 int i;
2468
2469 printf("sense:");
2470 for (i = 0; i < sizeof(xs->sense); i++)
2471 printf(" %02x", b[i]);
2472 printf("\n");
2473 }
2474
2475 int ncr5380_traceidx = 0;
2476
2477 #define TRACE_MAX 1024
2478 struct trace_ent {
2479 char *msg;
2480 long val;
2481 } ncr5380_tracebuf[TRACE_MAX];
2482
2483 void
2484 ncr5380_trace(msg, val)
2485 char *msg;
2486 long val;
2487 {
2488 register struct trace_ent *tr;
2489 register int s;
2490
2491 s = splbio();
2492
2493 tr = &ncr5380_tracebuf[ncr5380_traceidx];
2494
2495 ncr5380_traceidx++;
2496 if (ncr5380_traceidx >= TRACE_MAX)
2497 ncr5380_traceidx = 0;
2498
2499 tr->msg = msg;
2500 tr->val = val;
2501
2502 splx(s);
2503 }
2504
2505 #ifdef DDB
2506 void
2507 ncr5380_clear_trace()
2508 {
2509 ncr5380_traceidx = 0;
2510 bzero((char *) ncr5380_tracebuf, sizeof(ncr5380_tracebuf));
2511 }
2512
2513 void
2514 ncr5380_show_trace()
2515 {
2516 struct trace_ent *tr;
2517 int idx;
2518
2519 idx = ncr5380_traceidx;
2520 do {
2521 tr = &ncr5380_tracebuf[idx];
2522 idx++;
2523 if (idx >= TRACE_MAX)
2524 idx = 0;
2525 if (tr->msg)
2526 db_printf(tr->msg, tr->val);
2527 } while (idx != ncr5380_traceidx);
2528 }
2529
2530 void
2531 ncr5380_show_req(sr)
2532 struct sci_req *sr;
2533 {
2534 struct scsi_xfer *xs = sr->sr_xs;
2535
2536 db_printf("TID=%d ", sr->sr_target);
2537 db_printf("LUN=%d ", sr->sr_lun);
2538 db_printf("dh=%p ", sr->sr_dma_hand);
2539 db_printf("dptr=%p ", sr->sr_dataptr);
2540 db_printf("dlen=0x%x ", sr->sr_datalen);
2541 db_printf("flags=%d ", sr->sr_flags);
2542 db_printf("stat=%d ", sr->sr_status);
2543
2544 if (xs == NULL) {
2545 db_printf("(xs=NULL)\n");
2546 return;
2547 }
2548 db_printf("\n");
2549 #ifdef SCSIDEBUG
2550 show_scsi_xs(xs);
2551 #else
2552 db_printf("xs=%p\n", xs);
2553 #endif
2554 }
2555
2556 void
2557 ncr5380_show_state()
2558 {
2559 struct ncr5380_softc *sc;
2560 struct sci_req *sr;
2561 int i, j, k;
2562
2563 sc = ncr5380_debug_sc;
2564
2565 if (sc == NULL) {
2566 db_printf("ncr5380_debug_sc == NULL\n");
2567 return;
2568 }
2569
2570 db_printf("sc_ncmds=%d\n", sc->sc_ncmds);
2571 k = -1;
2572 for (i = 0; i < SCI_OPENINGS; i++) {
2573 sr = &sc->sc_ring[i];
2574 if (sr->sr_xs) {
2575 if (sr == sc->sc_current)
2576 k = i;
2577 db_printf("req %d: (sr=%p)", i, (long)sr);
2578 ncr5380_show_req(sr);
2579 }
2580 }
2581 db_printf("sc_rr=%d, current=%d\n", sc->sc_rr, k);
2582
2583 db_printf("Active request matrix:\n");
2584 for(i = 0; i < 8; i++) {
2585 for (j = 0; j < 8; j++) {
2586 sr = sc->sc_matrix[i][j];
2587 if (sr) {
2588 db_printf("TID=%d LUN=%d sr=0x%x\n", i, j, (long)sr);
2589 }
2590 }
2591 }
2592
2593 db_printf("sc_state=0x%x\n", sc->sc_state);
2594 db_printf("sc_current=%p\n", sc->sc_current);
2595 db_printf("sc_dataptr=%p\n", sc->sc_dataptr);
2596 db_printf("sc_datalen=0x%x\n", sc->sc_datalen);
2597
2598 db_printf("sc_prevphase=%d\n", sc->sc_prevphase);
2599 db_printf("sc_msgpriq=0x%x\n", sc->sc_msgpriq);
2600 }
2601
2602 #endif
2603 #endif