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