scsi_1185.c revision 1.3 1 /* $NetBSD: scsi_1185.c,v 1.3 1998/06/05 12:34:06 tsubai Exp $ */
2
3 /*
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: $Hdr: scsi_1185.c,v 4.300 91/06/09 06:22:20 root Rel41 $ SONY
39 *
40 * @(#)scsi_1185.c 8.1 (Berkeley) 6/11/93
41 */
42
43 /*
44 * Copyright (c) 1989- by SONY Corporation.
45 */
46 /*
47 * scsi_1185.c
48 *
49 * CXD1185Q
50 * SCSI bus low level common routines
51 * for one cpu machine
52 */
53 /*
54 * MODIFY HISTORY:
55 *
56 * DMAC_WAIT --- DMAC_0266 wo tukau-baai, DMAC mata-wa SCSI-chip ni
57 * tuzukete access suru-baai,
58 * kanarazu wait wo ireru-beshi !
59 *
60 */
61
62 #include <sys/types.h>
63 #include <sys/param.h>
64 #include <sys/systm.h>
65 #include <sys/map.h>
66 #include <sys/buf.h>
67 #include <vm/vm.h>
68 #include <sys/proc.h>
69 #include <sys/user.h>
70 #include <sys/conf.h>
71 #include <sys/dkstat.h>
72 #include <sys/kernel.h>
73
74 #include <machine/pte.h>
75 #include <machine/cpu.h>
76
77 #include <newsmips/dev/screg_1185.h>
78 #include <newsmips/dev/scsic.h>
79
80 #ifdef news3400
81 # include <newsmips/dev/dmac_0448.h>
82 # ifndef NDMACMAP
83 # define NDMACMAP 144
84 # endif
85 #endif
86
87 #include <newsmips/dev/scsireg.h>
88
89 #include <machine/locore.h>
90 #include <machine/machConst.h>
91
92 #ifdef mips
93 #define VOLATILE volatile
94 #else
95 #define VOLATILE
96 #endif
97
98 #define ABORT_SYNCTR_MES_FROM_TARGET
99 #define SCSI_1185AQ
100 #define RESET_RECOVER
101
102 #define DMAC_MAP_INIT /* for nws-3700 parity error */
103
104 #define APAD_ALWAYS_ON
105
106 # define CHECK_LOOP_CNT 60
107 # define RSL_LOOP_CNT 60
108
109 #ifndef DMAC_MAP_INIT
110 # define MAP_OVER_ACCESS /* for nws-3700 parity error */
111 #endif
112
113 #undef CHECK_MRQ
114
115 #ifdef NOT_SUPPORT_SYNCTR
116 # define MAX_OFFSET_BYTES 0
117 #else
118 # define MAX_OFFSET_BYTES MAX_OFFSET
119 #endif
120
121 #define NTARGET 8
122
123 #define act_point spoint
124 #define act_trcnt stcnt
125 #define act_tag stag
126 #define act_offset soffset
127
128 #define splscsi splsc
129
130 #if defined(mips) && defined(CPU_SINGLE)
131 #define nops(x) { int i; for (i = 0; i < (x); i++) ; }
132 #define vtophys(v) kvtophys((vm_offset_t)(v))
133 #define DMAC_WAIT0 ;
134 #else
135 #define DMAC_WAIT0 DMAC_WAIT
136 #endif
137
138 int perr_flag[NTARGET];
139
140 #ifndef NOT_SUPPORT_SYNCTR
141 VOLATILE char sync_tr[NTARGET];
142 #endif
143
144 #ifdef DMAC_MAP_INIT
145 int dmac_map_init = 0;
146 #endif
147
148 #ifdef SCSI_1185AQ
149 int scsi_1185AQ = 0;
150 #endif
151
152 struct sc_chan_stat chan_stat[NTARGET]; /* SCSI channel status */
153 int sel_stat[NTARGET]; /* target select status */
154 #define SEL_WAIT 0
155 #define SEL_START 1
156 #define SEL_TIMEOUT 2
157 #define SEL_ARBF 3
158 #define SEL_SUCCESS 4
159 #define SEL_RSLD 5
160 #define SEL_RSL_WAIT 6
161
162 /*
163 * command flag status
164 */
165 #define CF_SET 1
166 #define CF_SEND 2
167 #define CF_ENOUGH 3
168 #define CF_EXEC 4
169
170 #define SEL_TIMEOUT_VALUE 0x7a
171
172 VOLATILE int int_stat1;
173 VOLATILE int int_stat2;
174
175 VOLATILE int min_flag;
176
177 VOLATILE char mout_flag[NTARGET];
178 #define MOUT_IDENTIFY 1
179 #define MOUT_SYNC_TR 2
180
181 VOLATILE int last_cmd;
182 VOLATILE char min_cnt[NTARGET];
183 VOLATILE u_char *min_point[NTARGET];
184 VOLATILE int pad_cnt[NTARGET];
185
186 VOLATILE static u_char *act_cmd_pointer;
187 static VOLATILE struct sc_chan_stat *wbq_actf = 0; /* forword active pointer */
188 static VOLATILE struct sc_chan_stat *wbq_actl = 0; /* last active pointer */
189 static char ScsiSoftError[] = "SCSI soft error";
190 static struct scsi_stat scsi_stat;
191
192 static int pad_start;
193
194 static int WAIT_STATR_BITCLR __P((int));
195 static int WAIT_STATR_BITSET __P((int));
196 static void SET_CMD __P((int));
197 static void SET_CNT __P((int));
198 static int GET_CNT __P((void));
199 static void GET_INTR __P((VOLATILE int *, VOLATILE int *));
200 void sc_send __P((int, int, struct scsi *));
201 static void sc_start __P((void));
202 int scintr __P((void));
203 void scsi_hardreset __P((void));
204 void scsi_chipreset __P((void));
205 void scsi_softreset __P((void));
206 static void sc_resel __P((void));
207 static void sc_discon __P((void));
208 static void sc_pmatch __P((void));
209 static void flush_fifo __P((void));
210 static void sc_cout __P((struct sc_chan_stat *));
211 static void sc_min __P((struct sc_chan_stat *));
212 static void sc_mout __P((struct sc_chan_stat *));
213 static void sc_sin __P((VOLATILE struct sc_chan_stat *));
214 static void sc_dio __P((VOLATILE struct sc_chan_stat *));
215 static void sc_dio_pad __P((VOLATILE struct sc_chan_stat *));
216 static void print_scsi_stat __P((void));
217 int sc_busy __P((int));
218 static void append_wb __P((VOLATILE struct sc_chan_stat *));
219 static int get_wb_chan __P((void));
220 static int release_wb __P((void));
221 static void adjust_transfer __P((struct sc_chan_stat *));
222 static void clean_k2dcache __P((struct scsi *));
223
224 extern void sc_done __P((struct scsi *));
225 extern vm_offset_t kvtophys __P((vm_offset_t));
226
227 #if defined(mips) && defined(CPU_SINGLE)
228 #define dma_reset(x) { \
229 int s = splscsi(); \
230 dmac_gsel = (x); dmac_cctl = DM_RST; dmac_cctl = 0; \
231 splx(s); \
232 }
233 #endif
234
235 int
236 WAIT_STATR_BITCLR(bitmask)
237 register int bitmask;
238 {
239 register int iloop;
240 register VOLATILE int dummy;
241
242 iloop = 0;
243 do {
244 dummy = sc_statr;
245 DMAC_WAIT0;
246 if (iloop++ > CHECK_LOOP_CNT)
247 return (-1);
248 } while (dummy & bitmask);
249 return (0);
250 }
251
252 int
253 WAIT_STATR_BITSET(bitmask)
254 register int bitmask;
255 {
256 register int iloop;
257 register VOLATILE int dummy;
258
259 iloop = 0;
260 do {
261 dummy = sc_statr;
262 DMAC_WAIT0;
263 if (iloop++ > CHECK_LOOP_CNT)
264 return (-1);
265 } while ((dummy & bitmask) == 0);
266 return (0);
267 }
268
269 void
270 SET_CMD(CMD)
271 register int CMD;
272 {
273
274 (void) WAIT_STATR_BITCLR(R0_CIP);
275 last_cmd = (CMD);
276 sc_comr = (CMD);
277 DMAC_WAIT0;
278 }
279
280 void
281 SET_CNT(COUNT)
282 register int COUNT;
283 {
284
285 sc_tclow = (COUNT) & 0xff;
286 DMAC_WAIT0;
287 sc_tcmid = ((COUNT) >> 8) & 0xff;
288 DMAC_WAIT0;
289 sc_tchi = ((COUNT) >> 16) & 0xff;
290 DMAC_WAIT0;
291 }
292
293 int
294 GET_CNT()
295 {
296 register VOLATILE int COUNT;
297
298 COUNT = sc_tclow;
299 DMAC_WAIT0;
300 COUNT += (sc_tcmid << 8) & 0xff00;
301 DMAC_WAIT0;
302 COUNT += (sc_tchi << 16) & 0xff0000;
303 DMAC_WAIT0;
304 return (COUNT);
305 }
306
307 void
308 GET_INTR(DATA1, DATA2)
309 register VOLATILE int *DATA1;
310 register VOLATILE int *DATA2;
311 {
312 (void) WAIT_STATR_BITCLR(R0_CIP);
313 while (sc_statr & R0_MIRQ) {
314 DMAC_WAIT0;
315 *DATA1 |= sc_intrq1;
316 DMAC_WAIT0;
317 *DATA2 |= sc_intrq2;
318 DMAC_WAIT0;
319 }
320 }
321
322
323 void
324 sc_send(chan, ie, sc)
325 register int chan;
326 register int ie;
327 register struct scsi *sc;
328 {
329 register VOLATILE struct sc_chan_stat *cs;
330 register struct scsi_stat *ss;
331 register int i;
332
333 cs = &chan_stat[chan];
334 ss = &scsi_stat;
335
336 if (sc == NULL || cs->sc != NULL) {
337 printf("SCSI%d:sc_send() NULL sc or NOT NULL cs->sc\n", chan);
338 printf("ie=0x%x sc=0x%p cs->sc=0x%p\n", ie, sc, cs->sc);
339 if (sc) {
340 printf("cdb=");
341 for (i = 0; i < 6; i++)
342 printf("0x%x ", sc->sc_cdb.un_reserved[i]);
343 printf("\n");
344 }
345 panic(ScsiSoftError);
346 /*NOTREACHED*/
347 }
348
349 if ((sc->sc_cdb.un_reserved[0] == SCOP_RESET)
350 && (sc->sc_cdb.un_reserved[1] == SCOP_RESET)) {
351 /*
352 * SCSI bus reset command procedure
353 * (vender unique by Sony Corp.)
354 */
355 #ifdef SCSI_1185AQ
356 if (sc_idenr & 0x08) {
357 scsi_1185AQ = 1;
358 }
359 #endif
360 cs->sc = sc;
361 scsi_hardreset();
362 sc->sc_istatus = INST_EP;
363 cs->sc = NULL;
364 sc_done(sc);
365 return;
366 }
367
368 if (sc->sc_map && (sc->sc_map->mp_pages > 0)) {
369 /*
370 * use map table
371 */
372 sc->sc_coffset = sc->sc_map->mp_offset & PGOFSET;
373 if (sc->sc_map->mp_pages > NSCMAP) {
374 printf("SCSI%d: map table overflow\n", chan);
375 sc->sc_istatus = INST_EP|INST_LB|INST_PRE;
376 return;
377 }
378 } else {
379 /*
380 * no use map table
381 */
382 sc->sc_coffset = (u_int)sc->sc_cpoint & PGOFSET;
383 }
384 sc->sc_ctag = 0;
385
386 cs->sc = sc;
387 cs->comflg = OFF;
388
389 cs->intr_flg = ie;
390 cs->chan_num = chan;
391 perr_flag[chan] = 0;
392 mout_flag[chan] = 0;
393 min_cnt[chan] = 0;
394
395 sel_stat[chan] = SEL_WAIT;
396 append_wb(cs);
397 sc_start();
398 }
399
400 /*
401 * SCSI start up routine
402 */
403 void
404 sc_start()
405 {
406 register VOLATILE struct sc_chan_stat *cs;
407 register struct scsi_stat *ss;
408 register int s;
409 register VOLATILE int chan;
410 register VOLATILE int dummy;
411
412 ss = &scsi_stat;
413
414 s = splclock();
415 chan = get_wb_chan();
416 if ((chan < 0) || (ss->ipc >= 0))
417 goto sc_start_exit;
418 if (sel_stat[chan] != SEL_WAIT) {
419 /*
420 * already started
421 */
422 goto sc_start_exit;
423 }
424 sel_stat[chan] = SEL_START;
425 (void) splscsi();
426
427 cs = &chan_stat[chan];
428
429 dummy = sc_cmonr;
430 DMAC_WAIT0;
431 if (dummy & (R4_MBSY|R4_MSEL)) {
432 sel_stat[chan] = SEL_WAIT;
433 goto sc_start_exit;
434 }
435
436 /*
437 * send SELECT with ATN command
438 */
439 ss->dma_stat = OFF;
440 pad_start = 0;
441 dummy = sc_statr;
442 DMAC_WAIT0;
443 if (dummy & R0_CIP) {
444 sel_stat[chan] = SEL_WAIT;
445 goto sc_start_exit;
446 }
447 sc_idenr = (chan << SC_TG_SHIFT) | SC_OWNID;
448 DMAC_WAIT0;
449 #ifdef SCSI_1185AQ
450 if (scsi_1185AQ)
451 sc_intok1 = Ra_STO|Ra_ARBF;
452 else
453 sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;
454 #else
455 sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;
456 #endif
457 DMAC_WAIT0;
458 /*
459 * BUGFIX for signal reflection on BSY
460 * !Rb_DCNT
461 */
462 sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE;
463 DMAC_WAIT0;
464
465 dummy = sc_cmonr;
466 DMAC_WAIT0;
467 if (dummy & (R4_MBSY|R4_MSEL)) {
468 sel_stat[chan] = SEL_WAIT;
469 goto sc_start_exit;
470 }
471 SET_CMD(SCMD_SEL_ATN);
472
473 sc_start_exit:
474 splx(s);
475 }
476
477 /*
478 * SCSI interrupt service routine
479 */
480 int
481 scintr()
482 {
483 register struct scsi_stat *ss;
484 register int iloop;
485 register VOLATILE int chan;
486 register VOLATILE int dummy;
487 int s_int1, s_int2;
488
489 scintr_loop:
490
491 #if defined(CHECK_MRQ) && defined(news3400)
492 while (dmac_gstat & CH_MRQ(CH_SCSI))
493 DMAC_WAIT;
494 #endif
495
496 for (iloop = 0; iloop < 100; iloop++) {
497 dummy = sc_statr;
498 DMAC_WAIT;
499 if ((dummy & R0_CIP) == 0)
500 break;
501 }
502
503 /*
504 * get SCSI interrupt request
505 */
506 while (sc_statr & R0_MIRQ) {
507 DMAC_WAIT0;
508 s_int1 = sc_intrq1;
509 DMAC_WAIT0;
510 s_int2 = sc_intrq2;
511 DMAC_WAIT0;
512 int_stat1 |= s_int1;
513 int_stat2 |= s_int2;
514 }
515
516 if (int_stat2 & R3_SRST) {
517 /*
518 * RST signal is drived
519 */
520 int_stat2 &= ~R3_SRST;
521 scsi_softreset();
522 goto scintr_exit;
523 }
524
525 ss = &scsi_stat;
526 if ((ss->ipc < 0) && (ss->wrc <= 0) && (ss->wbc <= 0)) {
527 int_stat1 = 0;
528 int_stat2 = 0;
529 goto scintr_exit;
530 }
531
532 chan = get_wb_chan();
533 if ((chan >= 0) && (sel_stat[chan] == SEL_START) &&
534 (last_cmd == SCMD_SEL_ATN)) {
535 /*
536 * Check the result of SELECTION command
537 */
538 if (int_stat1 & R2_RSL) {
539 /*
540 * RESELECTION occur
541 */
542 if (ss->wrc > 0) {
543 sel_stat[chan] = SEL_RSLD;
544 } else {
545 /*
546 * Ghost RESELECTION ???
547 */
548 int_stat1 &= ~R2_RSL;
549 }
550 }
551 if (int_stat1 & R2_ARBF) {
552 /*
553 * ARBITRATION fault
554 */
555 int_stat1 &= ~R2_ARBF;
556 sel_stat[chan] = SEL_ARBF;
557 }
558 if (int_stat1 & R2_STO) {
559 /*
560 * SELECTION timeout
561 */
562 int_stat1 &= ~R2_STO;
563 if ((int_stat2&(R3_PHC|R3_RMSG)) != (R3_PHC|R3_RMSG)) {
564 ss->ipc = chan;
565 ss->ip = &chan_stat[chan];
566 sel_stat[chan] = SEL_TIMEOUT;
567 chan_stat[chan].sc->sc_istatus
568 = INST_EP|INST_TO;
569 release_wb();
570 }
571 }
572
573 /*
574 * SELECTION command done
575 */
576 switch (sel_stat[chan]) {
577
578 case SEL_START:
579 if ((int_stat2 & R3_FNC) == 0)
580 break;
581 /*
582 * SELECTION success
583 */
584 sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;
585 ss->ipc = chan;
586 ss->ip = &chan_stat[chan];
587 ss->ip->sc->sc_istatus |= INST_IP;
588 ss->dma_stat = OFF;
589 pad_start = 0;
590 sel_stat[chan] = SEL_SUCCESS;
591 release_wb();
592 #ifndef NOT_SUPPORT_SYNCTR
593 sc_syncr = sync_tr[chan];
594 DMAC_WAIT0;
595 #endif
596 DMAC_WAIT0;
597 break;
598
599 case SEL_TIMEOUT:
600 /*
601 * SELECTION time out
602 */
603 sc_discon();
604 goto scintr_exit;
605
606 /* case SEL_RSLD: */
607 /* case SEL_ARBF: */
608 default:
609 /*
610 * SELECTION failed
611 */
612 sel_stat[chan] = SEL_WAIT;
613 break;
614 }
615 if ((int_stat1 & R2_RSL) == 0)
616 int_stat2 &= ~R3_FNC;
617 }
618
619 if (ss->ip != NULL) {
620 /*
621 * check In Process channel's request
622 */
623 if (ss->dma_stat != OFF) {
624 /*
625 * adjust pointer & counter
626 */
627 adjust_transfer(ss->ip);
628 }
629 if (int_stat2 & R3_SPE) {
630 register int VOLATILE statr;
631 register int VOLATILE cmonr;
632
633 statr = sc_statr;
634 DMAC_WAIT0;
635 cmonr = sc_cmonr;
636 int_stat2 &= ~R3_SPE;
637 perr_flag[ss->ip->chan_num] = 1;
638 }
639 }
640
641 if (int_stat2 & R3_DCNT) {
642 /*
643 * Bus Free
644 */
645 sc_discon();
646 int_stat2 &= ~R3_DCNT;
647 }
648
649 if ((ss->ipc >= 0) && (sel_stat[ss->ipc] == SEL_RSL_WAIT)) {
650 sel_stat[ss->ipc] = SEL_RSLD;
651 ss->ipc = -1;
652 int_stat1 |= R2_RSL;
653 }
654 if (int_stat1 & R2_RSL) {
655 /*
656 * Reselection
657 */
658 sc_resel();
659 int_stat1 &= ~R2_RSL;
660 if (sel_stat[ss->ipc] == SEL_RSL_WAIT)
661 goto scintr_exit;
662 }
663
664
665 if ((ss->ipc >= 0) && (ss->ipc != SC_OWNID) &&
666 (sel_stat[ss->ipc] == SEL_SUCCESS)) {
667 if (int_stat2 & R3_PHC) {
668 /*
669 * Phase change
670 */
671 int_stat2 &= ~(R3_PHC|R3_RMSG);
672 sc_pmatch();
673 } else if (int_stat2 & R3_RMSG) {
674 /*
675 * message Phase
676 */
677 if (min_flag > 0) {
678 int_stat2 &= ~(R3_PHC|R3_RMSG);
679 sc_pmatch();
680 }
681 }
682 else if (ss->dma_stat != OFF) {
683 dummy = sc_cmonr;
684 DMAC_WAIT0;
685 if ((dummy & (R4_MMSG|R4_MCD|R4_MREQ)) == R4_MREQ) {
686 /*
687 * still DATA transfer phase
688 */
689 sc_dio_pad(ss->ip);
690 }
691 }
692 else if (ss->ip->comflg == CF_SEND) {
693 dummy = sc_cmonr;
694 DMAC_WAIT0;
695 if ((dummy & SC_PMASK) == COM_OUT) {
696 /*
697 * command out phase
698 */
699 sc_cout(ss->ip);
700 }
701 }
702 } else {
703 if (int_stat2 & (R3_PHC|R3_RMSG))
704 goto scintr_exit;
705 }
706
707 if ((int_stat1 & (R2_STO|R2_RSL|R2_ARBF))
708 || (int_stat2 & (R3_DCNT|R3_SRST|R3_PHC|R3_SPE))) {
709 /*
710 * still remain intrq
711 */
712 goto scintr_loop;
713 }
714
715 scintr_exit:
716 return (1);
717 }
718
719 /*
720 * SCSI bus reset routine
721 * scsi_hardreset() is occered a reset interrupt.
722 * And call scsi_softreset().
723 */
724 void
725 scsi_hardreset()
726 {
727 register int s;
728 #ifdef DMAC_MAP_INIT
729 register int i;
730 #endif
731
732 s = splscsi();
733
734 scsi_chipreset();
735 DMAC_WAIT0;
736 int_stat1 = 0;
737 int_stat2 = 0;
738 SET_CMD(SCMD_AST_RST); /* assert RST signal */
739
740 #ifdef DMAC_MAP_INIT
741 if (dmac_map_init == 0) {
742 dmac_map_init++;
743 for (i = 0; i < NDMACMAP; i++) {
744 # if defined(mips) && defined(CPU_SINGLE)
745 dmac_gsel = CH_SCSI;
746 dmac_ctag = (u_char)i;
747 dmac_cmap = (u_short)0;
748 # endif
749 }
750 }
751 #endif
752 /*cxd1185_init();*/
753 splx(s);
754 }
755
756 /*
757 * I/O port (sc_ioptr) bit assign
758 *
759 * Rf_PRT3 - <reserved>
760 * Rf_PRT2 - <reserved>
761 * Rf_PRT1 out Floppy Disk Density control
762 * Rf_PRT0 out Floppy Disk Eject control
763 */
764
765 void
766 scsi_chipreset()
767 {
768 register int s;
769 register VOLATILE int save_ioptr;
770
771 s = splscsi();
772
773 #if defined(mips) && defined(CPU_SINGLE)
774 dmac_gsel = CH_SCSI;
775 dmac_cwid = 4; /* initialize DMAC SCSI chan */
776 *(unsigned VOLATILE char *)PINTEN |= DMA_INTEN;
777 dma_reset(CH_SCSI);
778 #endif
779 sc_envir = 0; /* 1/4 clock */
780 DMAC_WAIT0;
781 save_ioptr = sc_ioptr;
782 DMAC_WAIT0;
783 last_cmd = SCMD_CHIP_RST;
784 sc_comr = SCMD_CHIP_RST; /* reset chip */
785 DMAC_WAIT;
786 (void) WAIT_STATR_BITCLR(R0_CIP);
787 /*
788 * SCMD_CHIP_RST command reset all register
789 * except sc_statr<7:6> & sc_cmonr.
790 * So, bit R0_MIRQ & R3_FNC will be not set.
791 */
792 sc_idenr = SC_OWNID;
793 DMAC_WAIT0;
794
795 sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;
796 DMAC_WAIT0;
797 sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
798 DMAC_WAIT0;
799
800 sc_ioptr = save_ioptr;
801 DMAC_WAIT;
802
803 sc_moder = Rc_TMSL; /* RST drive time = 25.5 us */
804 DMAC_WAIT0;
805 sc_timer = 0x2;
806 DMAC_WAIT0;
807
808 sc_moder = Rc_SPHI; /* selection timeout = 252 ms */
809 DMAC_WAIT0;
810 sc_timer = SEL_TIMEOUT_VALUE;
811 DMAC_WAIT0;
812
813 #ifdef SCSI_1185AQ
814 if (scsi_1185AQ)
815 SET_CMD(SCMD_ENB_SEL); /* enable reselection */
816 #endif
817
818 int_stat1 &= ~R2_RSL; /* ignore RSL inter request */
819
820 splx(s);
821 }
822
823 void
824 scsi_softreset()
825 {
826 register VOLATILE struct sc_chan_stat *cs;
827 register struct scsi_stat *ss;
828 /* register int (*handler)(); */
829 register int i;
830 #ifdef mips
831 extern struct sc_data sc_data[];
832 register struct sc_data *scdp;
833 #endif
834
835 wbq_actf = NULL;
836 wbq_actl = NULL;
837 ss = &scsi_stat;
838 ss->wbc = 0;
839 ss->wrc = 0;
840 ss->ip = NULL;
841 ss->ipc = -1;
842 ss->dma_stat = OFF;
843 pad_start = 0;
844
845 for (i = 0; i < NTARGET; ++i) {
846 if (i == SC_OWNID)
847 continue;
848 cs = &chan_stat[i];
849 cs->wb_next = NULL;
850 #ifndef NOT_SUPPORT_SYNCTR
851 sync_tr[i] = 0; /* asynchronous mode */
852 #endif
853 sel_stat[i] = SEL_WAIT;
854 if (cs->sc != NULL) {
855 struct scsi *sc = cs->sc;
856
857 if ((cs->sc->sc_istatus & INST_EP) == 0)
858 cs->sc->sc_istatus = (INST_EP|INST_HE);
859 cs->sc = NULL;
860 #ifdef mips
861 scdp = &sc_data[cs->chan_num];
862 MachFlushDCache((vm_offset_t)scdp->scd_scaddr, sizeof(struct scsi));
863
864 if (MACH_IS_USPACE(scdp->scd_vaddr))
865 panic("scsi_softreset: user address is not supported");
866
867 if (MACH_IS_CACHED(scdp->scd_vaddr))
868 MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);
869 else
870 clean_k2dcache(sc);
871 #endif /* mips */
872 #if 0
873 if ((cs->intr_flg == SCSI_INTEN)
874 && (handler = scintsw[i].sci_inthandler)) {
875 #ifdef noyet /* KU:XXX */
876 intrcnt[INTR_SCSI00 + i]++;
877 #endif
878 (*handler)(scintsw[i].sci_ctlr);
879 }
880 #endif
881 sc_done(sc);
882 }
883 }
884 }
885
886 /*
887 * RESELECTION interrupt service routine
888 * ( RESELECTION phase )
889 */
890 void
891 sc_resel()
892 {
893 register struct sc_chan_stat *cs;
894 register struct scsi_stat *ss;
895 register VOLATILE int chan;
896 register VOLATILE int statr;
897 register int iloop;
898
899 min_flag = 0;
900 chan = (sc_idenr & R6_SID_MASK) >> SC_TG_SHIFT;
901
902 if (chan == SC_OWNID)
903 return;
904
905 statr = sc_statr;
906 DMAC_WAIT0;
907 if (statr & R0_CIP) {
908 if (last_cmd == SCMD_SEL_ATN) {
909 /*
910 * SELECTION command dead lock ?
911 * save interrupt request
912 */
913 while (sc_statr & R0_MIRQ) {
914 DMAC_WAIT0;
915 int_stat1 |= sc_intrq1;
916 DMAC_WAIT0;
917 int_stat2 |= sc_intrq2;
918 DMAC_WAIT0;
919 }
920 scsi_chipreset();
921 }
922 }
923
924 cs = &chan_stat[chan];
925 if (cs->sc == NULL) {
926 scsi_hardreset();
927 return;
928 }
929 if ((cs->sc->sc_istatus & INST_WR) == 0) {
930 scsi_hardreset();
931 return;
932 }
933
934 ss = &scsi_stat;
935 if (ss->ipc >= 0) {
936 scsi_hardreset();
937 return;
938 }
939
940 ss->ip = cs;
941 ss->ipc = chan;
942
943 sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;
944 DMAC_WAIT0;
945
946 iloop = 0;
947 while ((int_stat2 & R3_FNC) == 0) {
948 /*
949 * Max 6 usec wait
950 */
951 if (iloop++ > RSL_LOOP_CNT) {
952 sel_stat[chan] = SEL_RSL_WAIT;
953 return;
954 }
955 GET_INTR(&int_stat1, &int_stat2);
956 }
957 int_stat2 &= ~R3_FNC;
958
959 sel_stat[chan] = SEL_SUCCESS;
960
961 ss->wrc--;
962 ss->dma_stat = OFF;
963 pad_start = 0;
964 cs->sc->sc_istatus |= INST_IP;
965 cs->sc->sc_istatus &= ~INST_WR;
966
967 #ifndef NOT_SUPPORT_SYNCTR
968 sc_syncr = sync_tr[chan];
969 DMAC_WAIT0;
970 #endif
971 }
972
973 /*
974 * DISCONNECT interrupt service routine
975 * ( Target disconnect / job done )
976 */
977 void
978 sc_discon()
979 {
980 register VOLATILE struct sc_chan_stat *cs;
981 register struct scsi_stat *ss;
982 /* register int (*handler)(); */
983 register VOLATILE int dummy;
984 #ifdef mips
985 extern struct sc_data sc_data[];
986 register struct sc_data *scdp;
987 #endif
988
989 /*
990 * Signal reflection on BSY is occured.
991 * Not Bus Free Phase, ignore.
992 *
993 * But, CXD1185Q reset INIT bit of sc_statr.
994 * So, can't issue Transfer Information command.
995 *
996 * What shall we do ? Bus reset ?
997 */
998 if ((int_stat2 & R3_DCNT) && ((sc_intok2 & Rb_DCNT) == 0))
999 return;
1000
1001 sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE;
1002 DMAC_WAIT0;
1003
1004 min_flag = 0;
1005 dummy = sc_cmonr;
1006 DMAC_WAIT0;
1007 if (dummy & R4_MATN) {
1008 SET_CMD(SCMD_NGT_ATN);
1009 (void) WAIT_STATR_BITSET(R0_MIRQ);
1010 GET_INTR(&int_stat1, &int_stat2); /* clear interrupt */
1011 }
1012
1013 if ((int_stat1 & R2_RSL) == 0)
1014 int_stat2 &= ~R3_FNC;
1015
1016 ss = &scsi_stat;
1017 cs = ss->ip;
1018 if ((cs == NULL) || (ss->ipc < 0))
1019 goto sc_discon_exit;
1020
1021 if ((sel_stat[cs->chan_num] != SEL_SUCCESS)
1022 && (sel_stat[cs->chan_num] != SEL_TIMEOUT))
1023 printf("sc_discon: eh!\n");
1024
1025 /*
1026 * indicate abnormal terminate
1027 */
1028 if ((cs->sc->sc_istatus & (INST_EP|INST_WR)) == 0)
1029 cs->sc->sc_istatus |= (INST_EP|INST_PRE|INST_LB);
1030
1031 cs->sc->sc_istatus &= ~INST_IP;
1032 ss->dma_stat = OFF;
1033 pad_start = 0;
1034 ss->ip = NULL;
1035 ss->ipc = -1;
1036
1037 if ((cs->sc->sc_istatus & INST_WR) == 0) {
1038 struct scsi *sc = cs->sc;
1039
1040 if (perr_flag[cs->chan_num] > 0)
1041 cs->sc->sc_istatus |= INST_EP|INST_PRE;
1042 cs->sc = NULL;
1043 #ifdef mips
1044 scdp = &sc_data[cs->chan_num];
1045 MachFlushDCache((vm_offset_t)scdp->scd_scaddr, sizeof(struct scsi));
1046
1047 if (MACH_IS_USPACE(scdp->scd_vaddr))
1048 panic("sc_discon: user address is not supported");
1049
1050 if (MACH_IS_CACHED(scdp->scd_vaddr))
1051 MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);
1052 else
1053 clean_k2dcache(sc);
1054
1055 #endif /* mips */
1056 #if 0
1057 if ((cs->intr_flg == SCSI_INTEN)
1058 && (handler = scintsw[cs->chan_num].sci_inthandler)) {
1059 #ifdef notyet /* KU:XXX */
1060 intrcnt[INTR_SCSI00 + cs->chan_num]++;
1061 #endif
1062 (*handler)(scintsw[cs->chan_num].sci_ctlr);
1063 }
1064 #endif
1065 sc_done(sc);
1066 }
1067
1068 sc_discon_exit:
1069 sc_start();
1070 }
1071
1072 /*
1073 * SCSI phase match interrupt service routine
1074 */
1075 void
1076 sc_pmatch()
1077 {
1078 register /*VOLATILE*/ struct sc_chan_stat *cs; /* XXX Is this volatile? */
1079 register VOLATILE int phase;
1080 register VOLATILE int phase2;
1081 register VOLATILE int cmonr;
1082
1083 int_stat2 &= ~R3_FNC; /* XXXXXXXX */
1084
1085 cs = scsi_stat.ip;
1086 if (cs == NULL)
1087 return;
1088
1089 # if defined(mips) && defined(CPU_SINGLE)
1090 dma_reset(CH_SCSI);
1091 # endif
1092 phase = sc_cmonr & SC_PMASK;
1093 DMAC_WAIT0;
1094 for (;;) {
1095 phase2 = phase;
1096 cmonr = sc_cmonr;
1097 DMAC_WAIT0;
1098 phase = cmonr & SC_PMASK;
1099 if (phase == phase2) {
1100 if ((phase == DAT_IN) || (phase == DAT_OUT))
1101 break;
1102 else if (cmonr & R4_MREQ)
1103 break;
1104 }
1105 }
1106
1107
1108 scsi_stat.dma_stat = OFF;
1109 pad_start = 0;
1110
1111 if (phase == COM_OUT) {
1112 min_flag = 0;
1113 if (cs->comflg != CF_SEND)
1114 cs->comflg = CF_SET;
1115 sc_cout(cs);
1116 } else {
1117 cs->comflg = CF_ENOUGH;
1118 sc_intok2 &= ~Rb_FNC;
1119 if (phase == MES_IN) {
1120 min_flag++;
1121 sc_min(cs);
1122 } else {
1123 min_flag = 0;
1124
1125 switch (phase) {
1126
1127 case MES_OUT:
1128 sc_mout(cs);
1129 break;
1130
1131 case DAT_IN:
1132 case DAT_OUT:
1133 sc_dio(cs);
1134 break;
1135
1136 case STAT_IN:
1137 sc_sin(cs);
1138 break;
1139
1140 default:
1141 printf("SCSI%d: unknown phase\n", cs->chan_num);
1142 break;
1143 }
1144 }
1145 }
1146 }
1147
1148
1149 void
1150 flush_fifo()
1151 {
1152 register VOLATILE int dummy;
1153 VOLATILE int tmp;
1154 VOLATILE int tmp0;
1155
1156 dummy = sc_ffstr;
1157 DMAC_WAIT0;
1158 if (dummy & R5_FIFOREM) {
1159 /*
1160 * flush FIFO
1161 */
1162 SET_CMD(SCMD_FLSH_FIFO);
1163 tmp = 0;
1164 do {
1165 do {
1166 dummy = sc_statr;
1167 DMAC_WAIT0;
1168 } while (dummy & R0_CIP);
1169 GET_INTR(&tmp0, &tmp); /* clear interrupt */
1170 } while ((tmp & R3_FNC) == 0);
1171 }
1172 }
1173
1174 /*
1175 * SCSI command send routine
1176 */
1177 void
1178 sc_cout(cs)
1179 register struct sc_chan_stat *cs;
1180 {
1181 register struct scsi *sc;
1182 register int iloop;
1183 register int cdb_bytes;
1184 register VOLATILE int dummy;
1185 register VOLATILE int statr;
1186
1187 if (cs->comflg == CF_SET) {
1188 cs->comflg = CF_SEND;
1189
1190 flush_fifo();
1191
1192 sc = cs->sc;
1193 switch (sc->sc_opcode & CMD_TYPEMASK) {
1194 case CMD_T0:
1195 cdb_bytes = 6;
1196 break;
1197
1198 case CMD_T1:
1199 cdb_bytes = 10;
1200 break;
1201
1202 case CMD_T5:
1203 cdb_bytes = 12;
1204 break;
1205
1206 default:
1207 cdb_bytes = 6;
1208 sc_intok2 |= Rb_FNC;
1209 break;
1210 }
1211
1212 /*
1213 * set Active pointers
1214 */
1215 act_cmd_pointer = sc->sc_cdb.un_reserved;
1216 cs->act_trcnt = sc->sc_ctrnscnt;
1217 cs->act_point = sc->sc_cpoint;
1218 cs->act_tag = sc->sc_ctag;
1219 cs->act_offset = sc->sc_coffset;
1220
1221 } else {
1222 cdb_bytes = 1;
1223 iloop = 0;
1224 do {
1225 dummy = sc_cmonr;
1226 DMAC_WAIT0;
1227 if ((dummy & SC_PMASK) != COM_OUT)
1228 return;
1229 statr = sc_statr;
1230 DMAC_WAIT0;
1231 if (statr & R0_MIRQ)
1232 return;
1233 } while ((dummy & R4_MREQ) == 0);
1234 statr = sc_statr;
1235 DMAC_WAIT0;
1236 if (statr & R0_MIRQ)
1237 return;
1238 }
1239
1240
1241 SET_CNT(cdb_bytes);
1242 SET_CMD(SCMD_TR_INFO|R0_TRBE);
1243
1244 for (iloop = 0; iloop < cdb_bytes; iloop++) {
1245 do {
1246 dummy = sc_cmonr;
1247 DMAC_WAIT0;
1248 if ((dummy & SC_PMASK) != COM_OUT)
1249 return;
1250 } while ((dummy & R4_MREQ) == 0);
1251 statr = sc_statr;
1252 DMAC_WAIT0;
1253 if (statr & R0_MIRQ)
1254 return;
1255 sc_datr = *act_cmd_pointer++;
1256 do {
1257 dummy = sc_cmonr;
1258 DMAC_WAIT0;
1259 } while ((dummy & R4_MACK) != 0);
1260 }
1261 }
1262
1263 #define GET_MIN_COUNT 127
1264
1265 /*
1266 * SCSI message accept routine
1267 */
1268 void
1269 sc_min(cs)
1270 register struct sc_chan_stat *cs;
1271 {
1272 register struct scsi *sc;
1273 register struct scsi_stat *ss;
1274 register VOLATILE int dummy;
1275
1276 sc = cs->sc;
1277 ss = &scsi_stat;
1278
1279 sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
1280 DMAC_WAIT0;
1281
1282 if (min_flag == 1)
1283 flush_fifo();
1284
1285 dummy = sc_cmonr;
1286 DMAC_WAIT0;
1287 if ((dummy & R4_MREQ) == 0) {
1288 printf("sc_min: !REQ cmonr=%x\n", dummy);
1289 print_scsi_stat();
1290 scsi_hardreset();
1291 return;
1292 }
1293
1294 /* retry_cmd_issue: */
1295 int_stat2 &= ~R3_FNC;
1296 SET_CMD(SCMD_TR_INFO);
1297 do {
1298 do {
1299 dummy = sc_statr;
1300 DMAC_WAIT0;
1301 } while (dummy & R0_CIP);
1302 GET_INTR(&int_stat1, &int_stat2); /* clear interrupt */
1303 } while ((int_stat2 & R3_FNC) == 0);
1304 int_stat2 &= ~R3_FNC;
1305
1306 dummy = sc_ffstr;
1307 if (dummy & R5_FIE) {
1308 DMAC_WAIT;
1309 dummy = sc_ffstr;
1310 DMAC_WAIT0;
1311 if (dummy & R5_FIE) {
1312 dummy = sc_statr;
1313 DMAC_WAIT0;
1314 if ((dummy & R0_INIT) == 0) {
1315 /*
1316 * CXD1185 detect BSY false
1317 */
1318 scsi_hardreset();
1319 return;
1320 }
1321 }
1322 }
1323 dummy = sc_datr; /* get message byte */
1324 DMAC_WAIT0;
1325
1326 if (min_cnt[cs->chan_num] == 0) {
1327 sc->sc_message = sc->sc_identify;
1328 if (dummy == MSG_EXTND) {
1329 /* Extended Message */
1330 min_cnt[cs->chan_num] = GET_MIN_COUNT;
1331 min_point[cs->chan_num] = sc->sc_param;
1332 bzero((caddr_t)sc->sc_param, 8);
1333 *min_point[cs->chan_num]++ = dummy;
1334 } else {
1335 switch ((dummy & MSG_IDENT)? MSG_IDENT : dummy) {
1336
1337 case MSG_CCOMP:
1338 sc->sc_istatus |= INST_EP;
1339 break;
1340
1341 case MSG_MREJ:
1342 #ifndef NOT_SUPPORT_SYNCTR
1343 if (mout_flag[cs->chan_num] == MOUT_SYNC_TR)
1344 sync_tr[cs->chan_num] = 0;
1345 #endif
1346 break;
1347
1348 case MSG_IDENT:
1349 case MSG_RDP:
1350 ss->dma_stat = OFF;
1351 pad_start = 0;
1352 cs->comflg = OFF;
1353 /*
1354 * restore the saved value to Active pointers
1355 */
1356 act_cmd_pointer = sc->sc_cdb.un_reserved;
1357 cs->act_trcnt = sc->sc_ctrnscnt;
1358 cs->act_point = sc->sc_cpoint;
1359 cs->act_tag = sc->sc_ctag;
1360 cs->act_offset = sc->sc_coffset;
1361 break;
1362
1363 case MSG_SDP:
1364 /*
1365 * save Active pointers
1366 */
1367 sc->sc_ctrnscnt = cs->act_trcnt;
1368 sc->sc_ctag = cs->act_tag;
1369 sc->sc_coffset = cs->act_offset;
1370 sc->sc_cpoint = cs->act_point;
1371 break;
1372
1373 case MSG_DCNT:
1374 sc->sc_istatus |= INST_WR;
1375 ss->wrc++;
1376 break;
1377
1378 default:
1379 sc->sc_message = MSG_MREJ;
1380 SET_CMD(SCMD_AST_ATN);
1381 printf("SCSI%d:sc_min() Unknown mes=0x%x, \n",
1382 cs->chan_num, dummy);
1383 }
1384 }
1385 } else {
1386 *min_point[cs->chan_num]++ = dummy;
1387 if (min_cnt[cs->chan_num] == GET_MIN_COUNT)
1388 min_cnt[cs->chan_num] = dummy;
1389 else
1390 min_cnt[cs->chan_num]--;
1391 if (min_cnt[cs->chan_num] <= 0) {
1392 #ifdef ABORT_SYNCTR_MES_FROM_TARGET
1393 if ((sc->sc_param[2] == 0x01)
1394 && (mout_flag[cs->chan_num] == MOUT_SYNC_TR)) {
1395 #else
1396 if (sc->sc_param[2] == 0x01) { /*}*/
1397 #endif
1398 register int i;
1399 /*
1400 * receive Synchronous transfer message reply
1401 * calculate transfer period val
1402 * tpm * 4/1000 us = 4/16 * (tpv + 1)
1403 */
1404 #define TPM2TPV(tpm) (((tpm)*16 + 999) / 1000 - 1)
1405 #ifndef NOT_SUPPORT_SYNCTR
1406 i = sc->sc_param[3]; /* get tpm */
1407 i = TPM2TPV(i) << 4;
1408 if (sc->sc_param[4] == 0)
1409 sync_tr[cs->chan_num] = 0;
1410 else
1411 sync_tr[cs->chan_num] = i | sc->sc_param[4];
1412 #endif /* !NOT_SUPPORT_SYNCTR */
1413 } else {
1414 sc->sc_message = MSG_MREJ;
1415 SET_CMD(SCMD_AST_ATN); /* assert ATN */
1416 }
1417 }
1418 }
1419 SET_CMD(SCMD_NGT_ACK);
1420 }
1421
1422 /*
1423 * SCSI message send routine
1424 */
1425 void
1426 sc_mout(cs)
1427 register struct sc_chan_stat *cs;
1428 {
1429 register struct scsi *sc = cs->sc;
1430 register u_char *mp;
1431 register int cnt;
1432 register int iloop;
1433 register VOLATILE int dummy;
1434 VOLATILE int tmp;
1435 VOLATILE int tmp0;
1436
1437 flush_fifo();
1438
1439 if (mout_flag[cs->chan_num] == 0) {
1440 mout_flag[cs->chan_num] = MOUT_IDENTIFY;
1441 if (sc->sc_message != 0) {
1442 sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
1443 DMAC_WAIT0;
1444 if ((sc->sc_message == MSG_EXTND)
1445 && (sc->sc_param[2] == 0x01)) {
1446 cnt = 5;
1447 mp = sc->sc_param;
1448 sc->sc_param[3] = MIN_TP;
1449 if (sc->sc_param[4] > MAX_OFFSET_BYTES)
1450 sc->sc_param[4] = MAX_OFFSET_BYTES;
1451 mout_flag[cs->chan_num] = MOUT_SYNC_TR;
1452 } else {
1453 cnt = 1;
1454 mp = &sc->sc_message;
1455 }
1456
1457 SET_CNT(cnt);
1458 SET_CMD(SCMD_TR_INFO|R0_TRBE);
1459 sc_datr = sc->sc_identify;
1460 DMAC_WAIT0;
1461 for (iloop = 1; iloop < cnt; iloop++) {
1462 sc_datr = *mp++;
1463 DMAC_WAIT;
1464 }
1465 do {
1466 dummy = sc_cmonr;
1467 DMAC_WAIT0;
1468 if ((dummy & R4_MBSY) == 0)
1469 return;
1470 dummy = sc_statr;
1471 DMAC_WAIT0;
1472 } while (dummy & R0_CIP);
1473
1474 tmp = 0;
1475 GET_INTR(&tmp0, &tmp); /* clear interrupt */
1476 if ((tmp & R3_FNC) == 0) {
1477 (void) WAIT_STATR_BITSET(R0_MIRQ);
1478 GET_INTR(&tmp0, &tmp); /* clear interrupt */
1479 }
1480
1481 do {
1482 dummy = sc_cmonr;
1483 DMAC_WAIT0;
1484 if ((dummy & R4_MBSY) == 0)
1485 return;
1486 } while ((dummy & R4_MREQ) == 0);
1487 SET_CMD(SCMD_NGT_ATN);
1488 (void) WAIT_STATR_BITCLR(R0_CIP);
1489 GET_INTR(&tmp0, &tmp); /* clear interrupt */
1490
1491 dummy = sc_cmonr;
1492 DMAC_WAIT0;
1493 if ((dummy & R4_MREQ) == 0) {
1494 printf("sc_mout: !REQ cmonr=%x\n", dummy);
1495 print_scsi_stat();
1496 scsi_hardreset();
1497 return;
1498 }
1499
1500 SET_CMD(SCMD_TR_INFO);
1501 sc_datr = *mp++;
1502 DMAC_WAIT0;
1503 } else {
1504 dummy = sc_cmonr;
1505 DMAC_WAIT0;
1506 if (dummy & R4_MATN) {
1507 SET_CMD(SCMD_NGT_ATN);
1508 (void) WAIT_STATR_BITCLR(R0_CIP);
1509 GET_INTR(&tmp0, &tmp); /* clear interrupt */
1510 }
1511
1512 iloop = 0;
1513 do {
1514 dummy = sc_cmonr;
1515 DMAC_WAIT0;
1516 if (iloop++ > CHECK_LOOP_CNT)
1517 break;
1518 } while ((dummy & R4_MREQ) == 0);
1519 SET_CMD(SCMD_TR_INFO);
1520 sc_datr = sc->sc_identify;
1521 DMAC_WAIT0;
1522 }
1523 } else {
1524 dummy = sc_cmonr;
1525 DMAC_WAIT0;
1526 if (dummy & R4_MATN) {
1527 SET_CMD(SCMD_NGT_ATN);
1528 (void) WAIT_STATR_BITCLR(R0_CIP);
1529 GET_INTR(&tmp0, &tmp); /* clear interrupt */
1530 }
1531
1532 dummy = sc_cmonr;
1533 DMAC_WAIT0;
1534 if ((dummy & R4_MREQ) == 0) {
1535 printf("sc_mout: !REQ cmonr=%x\n", dummy);
1536 print_scsi_stat();
1537 scsi_hardreset();
1538 return;
1539 }
1540
1541 SET_CMD(SCMD_TR_INFO);
1542 sc_datr = sc->sc_message;
1543 DMAC_WAIT0;
1544 }
1545 }
1546
1547 /*
1548 * SCSI status accept routine
1549 */
1550 void
1551 sc_sin(cs)
1552 register VOLATILE struct sc_chan_stat *cs;
1553 {
1554 register VOLATILE int dummy;
1555 register int iloop;
1556
1557 flush_fifo();
1558
1559 dummy = sc_cmonr;
1560 DMAC_WAIT0;
1561 if ((dummy & R4_MREQ) == 0) {
1562 printf("sc_sin: !REQ cmonr=%x\n", dummy);
1563 print_scsi_stat();
1564 scsi_hardreset();
1565 return;
1566 }
1567
1568 sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
1569 DMAC_WAIT0;
1570
1571 SET_CMD(SCMD_TR_INFO);
1572
1573 (void) WAIT_STATR_BITCLR(R0_CIP);
1574
1575 int_stat2 &= ~R3_FNC;
1576 iloop = 0;
1577 do {
1578 if (iloop++ > CHECK_LOOP_CNT)
1579 break;
1580 GET_INTR(&int_stat1, &int_stat2); /* clear interrupt */
1581 } while ((int_stat2 & R3_FNC) == 0);
1582 int_stat2 &= ~R3_FNC;
1583
1584 cs->sc->sc_tstatus = sc_datr; /* get status byte */
1585 DMAC_WAIT0;
1586 }
1587
1588 /*
1589 * SCSI data in/out routine
1590 */
1591 void
1592 sc_dio(cs)
1593 register VOLATILE struct sc_chan_stat *cs;
1594 {
1595 register VOLATILE struct scsi *sc;
1596 register struct scsi_stat *ss;
1597 register int i;
1598 register int pages;
1599 register u_int tag;
1600 register u_int pfn;
1601 VOLATILE int phase;
1602
1603 sc = cs->sc;
1604 ss = &scsi_stat;
1605
1606 sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;
1607 DMAC_WAIT0;
1608
1609 if (cs->act_trcnt <= 0) {
1610 sc_dio_pad(cs);
1611 return;
1612 }
1613
1614 switch (sc->sc_opcode) {
1615
1616 case SCOP_READ:
1617 case SCOP_WRITE:
1618 case SCOP_EREAD:
1619 case SCOP_EWRITE:
1620 i = (cs->act_trcnt + sc->sc_bytesec -1) / sc->sc_bytesec;
1621 i *= sc->sc_bytesec;
1622 break;
1623
1624 default:
1625 i = cs->act_trcnt;
1626 break;
1627 }
1628
1629 SET_CNT(i);
1630 pad_cnt[cs->chan_num] = i - cs->act_trcnt;
1631
1632 phase = sc_cmonr & SC_PMASK;
1633 DMAC_WAIT0;
1634 if (phase == DAT_IN) {
1635 if (sc_syncr == OFF) {
1636 DMAC_WAIT0;
1637 flush_fifo();
1638 }
1639 }
1640
1641 #if defined(mips) && defined(CPU_SINGLE)
1642 SET_CMD(SCMD_TR_INFO|R0_DMA|R0_TRBE);
1643 #endif
1644
1645 #if defined(mips) && defined(CPU_SINGLE)
1646 dmac_gsel = CH_SCSI;
1647 dmac_ctrcl = (u_char)(cs->act_trcnt & 0xff);
1648 dmac_ctrcm = (u_char)((cs->act_trcnt >> 8) & 0xff);
1649 dmac_ctrch = (u_char)((cs->act_trcnt >> 16) & 0x0f);
1650 dmac_cofsh = (u_char)((cs->act_offset >> 8) & 0xf);
1651 dmac_cofsl = (u_char)(cs->act_offset & 0xff);
1652 #endif
1653 tag = 0;
1654
1655 if (sc->sc_map && (sc->sc_map->mp_pages > 0)) {
1656 /*
1657 * Set DMAC map entry from map table
1658 */
1659 pages = sc->sc_map->mp_pages;
1660 for (i = cs->act_tag; i < pages; i++) {
1661 if ((pfn = sc->sc_map->mp_addr[i]) == 0)
1662 panic("SCSI:sc_dma() zero entry");
1663 #if defined(mips) && defined(CPU_SINGLE)
1664 dmac_gsel = CH_SCSI;
1665 dmac_ctag = (u_char)tag++;
1666 dmac_cmap = (u_short)pfn;
1667 #endif
1668 }
1669 #ifdef MAP_OVER_ACCESS
1670 # if defined(mips) && defined(CPU_SINGLE)
1671 dmac_gsel = CH_SCSI;
1672 dmac_ctag = (u_char)tag++;
1673 dmac_cmap = (u_short)pfn;
1674 # endif
1675 #endif
1676 } else {
1677 /*
1678 * Set DMAC map entry from logical address
1679 */
1680 pfn = (u_int)vtophys(cs->act_point) >> PGSHIFT;
1681 pages = (cs->act_trcnt >> PGSHIFT) + 2;
1682 for (i = 0; i < pages; i++) {
1683 #if defined(mips) && defined(CPU_SINGLE)
1684 dmac_gsel = CH_SCSI;
1685 dmac_ctag = (u_char)tag++;
1686 dmac_cmap = (u_short)pfn + i;
1687 #endif
1688 }
1689 }
1690
1691 #if defined(mips) && defined(CPU_SINGLE)
1692 dmac_gsel = CH_SCSI;
1693 dmac_ctag = 0;
1694 #endif
1695
1696 if (phase == DAT_IN) {
1697 ss->dma_stat = SC_DMAC_RD;
1698 #if defined(mips) && defined(CPU_SINGLE)
1699 /*
1700 * auto pad flag is always on
1701 */
1702 dmac_gsel = CH_SCSI;
1703 dmac_cctl = DM_MODE|DM_APAD;
1704 DMAC_WAIT;
1705 dmac_cctl = DM_MODE|DM_APAD|DM_ENABLE;
1706 DMAC_WAIT0;
1707 #endif
1708 }
1709 else if (phase == DAT_OUT) {
1710 ss->dma_stat = SC_DMAC_WR;
1711 #if defined(mips) && defined(CPU_SINGLE)
1712 dmac_gsel = CH_SCSI;
1713 dmac_cctl = DM_APAD;
1714 DMAC_WAIT;
1715 dmac_cctl = DM_APAD|DM_ENABLE;
1716 DMAC_WAIT0;
1717 #endif
1718 /* DMAC start on mem->I/O */
1719 }
1720 }
1721
1722 #define MAX_TR_CNT24 ((1 << 24) -1)
1723 void
1724 sc_dio_pad(cs)
1725 register VOLATILE struct sc_chan_stat *cs;
1726 {
1727 register int dummy;
1728
1729 if (cs->act_trcnt >= 0)
1730 return;
1731 pad_start = 1;
1732
1733 SET_CNT(MAX_TR_CNT24);
1734 SET_CMD(SCMD_TR_PAD|R0_TRBE);
1735 dummy = sc_cmonr & SC_PMASK;
1736 DMAC_WAIT0;
1737 if (dummy == DAT_IN)
1738 dummy = sc_datr; /* get data */
1739 else
1740 sc_datr = 0; /* send data */
1741 }
1742
1743 void
1744 print_scsi_stat()
1745 {
1746 register struct scsi_stat *ss;
1747
1748 ss = &scsi_stat;
1749 printf("ipc=%d wrc=%d wbc=%d\n", ss->ipc, ss->wrc, ss->wbc);
1750 }
1751
1752 /*
1753 * return 0 if it was done. Or retun TRUE if it is busy.
1754 */
1755 int
1756 sc_busy(chan)
1757 register int chan;
1758 {
1759 return ((int)chan_stat[chan].sc);
1760 }
1761
1762
1763 /*
1764 * append channel into Waiting Bus_free queue
1765 */
1766 void
1767 append_wb(cs)
1768 register VOLATILE struct sc_chan_stat *cs;
1769 {
1770 register int s;
1771
1772 s = splclock(); /* inhibit process switch */
1773 if (wbq_actf == NULL)
1774 wbq_actf = cs;
1775 else
1776 wbq_actl->wb_next = cs;
1777 wbq_actl = cs;
1778 cs->sc->sc_istatus = INST_WAIT;
1779 scsi_stat.wbc++;
1780 splx(s);
1781 }
1782
1783 /*
1784 * get channel from Waiting Bus_free queue
1785 */
1786 int
1787 get_wb_chan()
1788 {
1789 register int s;
1790 register int chan;
1791
1792 s = splclock(); /* inhibit process switch */
1793 if (wbq_actf == NULL) {
1794 chan = -1;
1795 } else {
1796 chan = wbq_actf->chan_num;
1797 if ((chan < 0) || (chan >= NTARGET) || (chan == SC_OWNID))
1798 chan = -1;
1799 }
1800 splx(s);
1801 return (chan);
1802 }
1803
1804 /*
1805 * release channel from Waiting Bus_free queue
1806 */
1807 int
1808 release_wb()
1809 {
1810 register VOLATILE struct sc_chan_stat *cs;
1811 register int s;
1812 int error;
1813
1814 s = splclock(); /* inhibit process switch */
1815 error = 0;
1816 if (wbq_actf == NULL) {
1817 error = -1;
1818 } else {
1819 cs = wbq_actf;
1820 wbq_actf = cs->wb_next;
1821 cs->wb_next = NULL;
1822 if (wbq_actl == cs)
1823 wbq_actl = NULL;
1824 cs->sc->sc_istatus &= ~INST_WAIT;
1825 scsi_stat.wbc--;
1826 }
1827 splx(s);
1828 return (error);
1829 }
1830
1831 void
1832 adjust_transfer(cs)
1833 register struct sc_chan_stat *cs;
1834 {
1835 register struct scsi *sc;
1836 register struct scsi_stat *ss;
1837 register VOLATILE u_int remain_cnt;
1838 register u_int offset;
1839 u_int sent_byte;
1840
1841 sc = cs->sc;
1842 ss = &scsi_stat;
1843
1844 if (pad_start) {
1845 pad_start = 0;
1846 remain_cnt = 0;
1847 } else {
1848 # if defined(mips) && defined(CPU_SINGLE)
1849 remain_cnt = GET_CNT();
1850 remain_cnt -= pad_cnt[cs->chan_num];
1851 if (ss->dma_stat == SC_DMAC_WR) {
1852 /*
1853 * adjust counter in the FIFO
1854 */
1855 remain_cnt += sc_ffstr & R5_FIFOREM;
1856 }
1857 # endif
1858 }
1859
1860 sent_byte = sc->sc_ctrnscnt - remain_cnt;
1861 cs->act_trcnt = remain_cnt;
1862
1863 offset = sc->sc_coffset + sent_byte;
1864 cs->act_tag += (offset >> PGSHIFT);
1865 cs->act_offset = offset & PGOFSET;
1866 if ((sc->sc_map == NULL) || (sc->sc_map->mp_pages <= 0))
1867 cs->act_point += sent_byte;
1868 }
1869
1870 #ifdef mips
1871 static void
1872 clean_k2dcache(sc)
1873 struct scsi *sc;
1874 {
1875 struct sc_map *sc_map = sc->sc_map;
1876 vm_offset_t pa;
1877 int i, pages;
1878
1879 if (sc_map == NULL)
1880 return;
1881
1882 pages = sc_map->mp_pages;
1883 for (i = 0; i < pages; i++) {
1884 pa = sc_map->mp_addr[i] << PGSHIFT;
1885 MachFlushDCache(MIPS_PHYS_TO_KSEG0(pa), NBPG);
1886 }
1887 }
1888 #endif
1889