153895Smckusick /*
2*63304Sbostic * Copyright (c) 1992, 1993
3*63304Sbostic * The Regents of the University of California. All rights reserved.
453895Smckusick *
553895Smckusick * This code is derived from software contributed to Berkeley by
653895Smckusick * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
753895Smckusick *
853895Smckusick * %sccs.include.redist.c%
953895Smckusick *
1053895Smckusick * from: $Hdr: scsi_1185.c,v 4.300 91/06/09 06:22:20 root Rel41 $ SONY
1153895Smckusick *
12*63304Sbostic * @(#)scsi_1185.c 8.1 (Berkeley) 06/11/93
1353895Smckusick */
1453895Smckusick
1553895Smckusick /*
1653895Smckusick * Copyright (c) 1989- by SONY Corporation.
1753895Smckusick */
1853895Smckusick /*
1953895Smckusick * scsi_1185.c
2053895Smckusick *
2153895Smckusick * CXD1185Q
2253895Smckusick * SCSI bus low level common routines
2353895Smckusick * for one cpu machine
2453895Smckusick */
2553895Smckusick /*
2653895Smckusick * MODIFY HISTORY:
2753895Smckusick *
2853895Smckusick * DMAC_WAIT --- DMAC_0266 wo tukau-baai, DMAC mata-wa SCSI-chip ni
2953895Smckusick * tuzukete access suru-baai,
3053895Smckusick * kanarazu wait wo ireru-beshi !
3153895Smckusick *
3253895Smckusick */
3353895Smckusick
3457179Sutashiro #include <sys/types.h>
3557179Sutashiro #include <machine/pte.h>
3657179Sutashiro #include <machine/cpu.h>
3753895Smckusick
3857179Sutashiro #include <sys/param.h>
3957179Sutashiro #include <sys/systm.h>
4057179Sutashiro #include <sys/map.h>
4157179Sutashiro #include <sys/buf.h>
4257179Sutashiro #include <vm/vm.h>
4357179Sutashiro #include <sys/proc.h>
4457179Sutashiro #include <sys/user.h>
4557179Sutashiro #include <sys/conf.h>
4657179Sutashiro #include <sys/dkstat.h>
4757179Sutashiro #include <sys/kernel.h>
4853895Smckusick
4957179Sutashiro #include <news3400/hbdev/hbvar.h>
5057179Sutashiro #include <news3400/hbdev/screg_1185.h>
5157179Sutashiro #include <news3400/hbdev/scsic.h>
5253895Smckusick
5353895Smckusick #ifdef news3400
5457179Sutashiro # include <news3400/hbdev/dmac_0448.h>
5553895Smckusick # ifndef NDMACMAP
5653895Smckusick # define NDMACMAP 144
5753895Smckusick # endif
5853895Smckusick #endif
5953895Smckusick
6057179Sutashiro #include <news3400/iodev/scsireg.h>
6153895Smckusick
6253895Smckusick #ifdef mips
6353895Smckusick #define VOLATILE volatile
6453895Smckusick #else
6553895Smckusick #define VOLATILE
6653895Smckusick #endif
6753895Smckusick
6853895Smckusick #define ABORT_SYNCTR_MES_FROM_TARGET
6953895Smckusick #define SCSI_1185AQ
7053895Smckusick #define RESET_RECOVER
7153895Smckusick
7253895Smckusick #define DMAC_MAP_INIT /* for nws-3700 parity error */
7353895Smckusick
7453895Smckusick #define APAD_ALWAYS_ON
7553895Smckusick
7653895Smckusick # define CHECK_LOOP_CNT 60
7753895Smckusick # define RSL_LOOP_CNT 60
7853895Smckusick
7953895Smckusick #ifndef DMAC_MAP_INIT
8053895Smckusick # define MAP_OVER_ACCESS /* for nws-3700 parity error */
8153895Smckusick #endif
8253895Smckusick
8353895Smckusick #undef CHECK_MRQ
8453895Smckusick
8553895Smckusick #ifdef NOT_SUPPORT_SYNCTR
8653895Smckusick # define MAX_OFFSET_BYTES 0
8753895Smckusick #else
8853895Smckusick # define MAX_OFFSET_BYTES MAX_OFFSET
8953895Smckusick #endif
9053895Smckusick
9153895Smckusick #define NTARGET 8
9253895Smckusick
9353895Smckusick #define act_point spoint
9453895Smckusick #define act_trcnt stcnt
9553895Smckusick #define act_tag stag
9653895Smckusick #define act_offset soffset
9753895Smckusick
9853895Smckusick #define splscsi splsc
9953895Smckusick
10053895Smckusick #if defined(mips) && defined(CPU_SINGLE)
10153895Smckusick #define nops(x) { int i; for (i = 0; i < (x); i++) ; }
10253895Smckusick #define vtophys(v) MACH_UNMAPPED_TO_PHYS(v)
10353895Smckusick #define DMAC_WAIT0 ;
10453895Smckusick #else
10553895Smckusick #define DMAC_WAIT0 DMAC_WAIT
10653895Smckusick #endif
10753895Smckusick
10853895Smckusick int perr_flag[NTARGET];
10953895Smckusick
11053895Smckusick #ifndef NOT_SUPPORT_SYNCTR
11153895Smckusick VOLATILE char sync_tr[NTARGET];
11253895Smckusick #endif
11353895Smckusick
11453895Smckusick #ifdef DMAC_MAP_INIT
11553895Smckusick int dmac_map_init = 0;
11653895Smckusick #endif
11753895Smckusick
11853895Smckusick #ifdef SCSI_1185AQ
11953895Smckusick int scsi_1185AQ = 0;
12053895Smckusick #endif
12153895Smckusick
12253895Smckusick struct sc_chan_stat chan_stat[NTARGET]; /* SCSI channel status */
12353895Smckusick int sel_stat[NTARGET]; /* target select status */
12453895Smckusick #define SEL_WAIT 0
12553895Smckusick #define SEL_START 1
12653895Smckusick #define SEL_TIMEOUT 2
12753895Smckusick #define SEL_ARBF 3
12853895Smckusick #define SEL_SUCCESS 4
12953895Smckusick #define SEL_RSLD 5
13053895Smckusick #define SEL_RSL_WAIT 6
13153895Smckusick
13253895Smckusick /*
13353895Smckusick * command flag status
13453895Smckusick */
13553895Smckusick #define CF_SET 1
13653895Smckusick #define CF_SEND 2
13753895Smckusick #define CF_ENOUGH 3
13853895Smckusick #define CF_EXEC 4
13953895Smckusick
14053895Smckusick #define SEL_TIMEOUT_VALUE 0x7a
14153895Smckusick
14253895Smckusick VOLATILE int int_stat1;
14353895Smckusick VOLATILE int int_stat2;
14453895Smckusick
14553895Smckusick VOLATILE int min_flag;
14653895Smckusick
14753895Smckusick VOLATILE char mout_flag[NTARGET];
14853895Smckusick #define MOUT_IDENTIFY 1
14953895Smckusick #define MOUT_SYNC_TR 2
15053895Smckusick
15153895Smckusick VOLATILE int last_cmd;
15253895Smckusick VOLATILE char min_cnt[NTARGET];
15353895Smckusick VOLATILE u_char *min_point[NTARGET];
15453895Smckusick VOLATILE int pad_cnt[NTARGET];
15553895Smckusick
15653895Smckusick VOLATILE static u_char *act_cmd_pointer;
15753895Smckusick static VOLATILE struct sc_chan_stat *wbq_actf = 0; /* forword active pointer */
15853895Smckusick static VOLATILE struct sc_chan_stat *wbq_actl = 0; /* last active pointer */
15953895Smckusick static char ScsiSoftError[] = "SCSI soft error";
16053895Smckusick
16153895Smckusick static int pad_start;
16253895Smckusick
16353895Smckusick #if defined(mips) && defined(CPU_SINGLE)
16453895Smckusick #define dma_reset(x) { \
16553895Smckusick int s = splscsi(); \
16653895Smckusick dmac_gsel = (x); dmac_cctl = DM_RST; dmac_cctl = 0; \
16753895Smckusick splx(s); \
16853895Smckusick }
16953895Smckusick #endif
17053895Smckusick
WAIT_STATR_BITCLR(bitmask)17153895Smckusick WAIT_STATR_BITCLR(bitmask)
17253895Smckusick register int bitmask;
17353895Smckusick {
17453895Smckusick register int iloop;
17553895Smckusick register VOLATILE int dummy;
17653895Smckusick
17753895Smckusick iloop = 0;
17853895Smckusick do {
17953895Smckusick dummy = sc_statr;
18053895Smckusick DMAC_WAIT0;
18153895Smckusick if (iloop++ > CHECK_LOOP_CNT)
18253895Smckusick return (-1);
18353895Smckusick } while (dummy & bitmask);
18453895Smckusick return (0);
18553895Smckusick }
18653895Smckusick
WAIT_STATR_BITSET(bitmask)18753895Smckusick WAIT_STATR_BITSET(bitmask)
18853895Smckusick register int bitmask;
18953895Smckusick {
19053895Smckusick register int iloop;
19153895Smckusick register VOLATILE int dummy;
19253895Smckusick
19353895Smckusick iloop = 0;
19453895Smckusick do {
19553895Smckusick dummy = sc_statr;
19653895Smckusick DMAC_WAIT0;
19753895Smckusick if (iloop++ > CHECK_LOOP_CNT)
19853895Smckusick return (-1);
19953895Smckusick } while ((dummy & bitmask) == 0);
20053895Smckusick return (0);
20153895Smckusick }
20253895Smckusick
SET_CMD(CMD)20353895Smckusick SET_CMD(CMD)
20453895Smckusick register int CMD;
20553895Smckusick {
20653895Smckusick
20753895Smckusick (void) WAIT_STATR_BITCLR(R0_CIP);
20853895Smckusick last_cmd = (CMD);
20953895Smckusick sc_comr = (CMD);
21053895Smckusick DMAC_WAIT0;
21153895Smckusick }
21253895Smckusick
SET_CNT(COUNT)21353895Smckusick SET_CNT(COUNT)
21453895Smckusick register int COUNT;
21553895Smckusick {
21653895Smckusick
21753895Smckusick sc_tclow = (COUNT) & 0xff;
21853895Smckusick DMAC_WAIT0;
21953895Smckusick sc_tcmid = ((COUNT) >> 8) & 0xff;
22053895Smckusick DMAC_WAIT0;
22153895Smckusick sc_tchi = ((COUNT) >> 16) & 0xff;
22253895Smckusick DMAC_WAIT0;
22353895Smckusick }
22453895Smckusick
GET_CNT()22553895Smckusick GET_CNT()
22653895Smckusick {
22753895Smckusick register VOLATILE int COUNT;
22853895Smckusick
22953895Smckusick COUNT = sc_tclow;
23053895Smckusick DMAC_WAIT0;
23153895Smckusick COUNT += (sc_tcmid << 8) & 0xff00;
23253895Smckusick DMAC_WAIT0;
23353895Smckusick COUNT += (sc_tchi << 16) & 0xff0000;
23453895Smckusick DMAC_WAIT0;
23553895Smckusick return (COUNT);
23653895Smckusick }
23753895Smckusick
GET_INTR(DATA1,DATA2)23853895Smckusick GET_INTR(DATA1, DATA2)
23953895Smckusick register VOLATILE int *DATA1;
24053895Smckusick register VOLATILE int *DATA2;
24153895Smckusick {
24253895Smckusick register VOLATILE int dummy;
24353895Smckusick
24453895Smckusick (void) WAIT_STATR_BITCLR(R0_CIP);
24553895Smckusick while (sc_statr & R0_MIRQ) {
24653895Smckusick DMAC_WAIT0;
24753895Smckusick *DATA1 |= sc_intrq1;
24853895Smckusick DMAC_WAIT0;
24953895Smckusick *DATA2 |= sc_intrq2;
25053895Smckusick DMAC_WAIT0;
25153895Smckusick }
25253895Smckusick }
25353895Smckusick
25453895Smckusick
sc_send(chan,ie,sc)25553895Smckusick sc_send(chan, ie, sc)
25653895Smckusick register int chan;
25753895Smckusick register int ie;
25853895Smckusick register struct scsi *sc;
25953895Smckusick {
26053895Smckusick register VOLATILE struct sc_chan_stat *cs;
26153895Smckusick register struct scsi_stat *ss;
26253895Smckusick register int i;
26353895Smckusick
26453895Smckusick cs = &chan_stat[chan];
26553895Smckusick ss = &scsi_stat;
26653895Smckusick
26753895Smckusick if (sc == NULL || cs->sc != NULL) {
26853895Smckusick printf("SCSI%d:sc_send() NULL sc or NOT NULL cs->sc\n", chan);
26953895Smckusick printf("ie=0x%x sc=0x%x cs->sc=0x%x\n", ie, sc, cs->sc);
27053895Smckusick if (sc) {
27153895Smckusick printf("cdb=");
27253895Smckusick for (i = 0; i < 6; i++)
27353895Smckusick printf("0x%x ", sc->sc_cdb.un_reserved[i]);
27453895Smckusick printf("\n");
27553895Smckusick }
27653895Smckusick panic(ScsiSoftError);
27753895Smckusick /*NOTREACHED*/
27853895Smckusick }
27953895Smckusick
28053895Smckusick if ((sc->sc_cdb.un_reserved[0] == SCOP_RESET)
28153895Smckusick && (sc->sc_cdb.un_reserved[1] == SCOP_RESET)) {
28253895Smckusick /*
28353895Smckusick * SCSI bus reset command procedure
28453895Smckusick * (vender unique by Sony Corp.)
28553895Smckusick */
28653895Smckusick #ifdef SCSI_1185AQ
28753895Smckusick if (sc_idenr & 0x08) {
28853895Smckusick scsi_1185AQ = 1;
28953895Smckusick }
29053895Smckusick #endif
29153895Smckusick cs->sc = sc;
29253895Smckusick scsi_hardreset();
29353895Smckusick sc->sc_istatus = INST_EP;
29453895Smckusick cs->sc = NULL;
29553895Smckusick return;
29653895Smckusick }
29753895Smckusick
29853895Smckusick if (sc->sc_map && (sc->sc_map->mp_pages > 0)) {
29953895Smckusick /*
30053895Smckusick * use map table
30153895Smckusick */
30253895Smckusick sc->sc_coffset = sc->sc_map->mp_offset & PGOFSET;
30353895Smckusick if (sc->sc_map->mp_pages > NSCMAP) {
30453895Smckusick printf("SCSI%d: map table overflow\n", chan);
30553895Smckusick sc->sc_istatus = INST_EP|INST_LB|INST_PRE;
30653895Smckusick return;
30753895Smckusick }
30853895Smckusick } else {
30953895Smckusick /*
31053895Smckusick * no use map table
31153895Smckusick */
31253895Smckusick sc->sc_coffset = (u_int)sc->sc_cpoint & PGOFSET;
31353895Smckusick }
31453895Smckusick sc->sc_ctag = 0;
31553895Smckusick
31653895Smckusick cs->sc = sc;
31753895Smckusick cs->comflg = OFF;
31853895Smckusick
31953895Smckusick cs->intr_flg = ie;
32053895Smckusick cs->chan_num = chan;
32153895Smckusick perr_flag[chan] = 0;
32253895Smckusick mout_flag[chan] = 0;
32353895Smckusick min_cnt[chan] = 0;
32453895Smckusick
32553895Smckusick sel_stat[chan] = SEL_WAIT;
32653895Smckusick append_wb(cs);
32753895Smckusick sc_start();
32853895Smckusick }
32953895Smckusick
33053895Smckusick /*
33153895Smckusick * SCSI start up routine
33253895Smckusick */
sc_start()33353895Smckusick sc_start()
33453895Smckusick {
33553895Smckusick register VOLATILE struct sc_chan_stat *cs;
33653895Smckusick register struct scsi_stat *ss;
33753895Smckusick register int s;
33853895Smckusick register VOLATILE int chan;
33953895Smckusick register VOLATILE int dummy;
34053895Smckusick
34153895Smckusick ss = &scsi_stat;
34253895Smckusick
34353895Smckusick s = splclock();
34453895Smckusick chan = get_wb_chan();
34553895Smckusick if ((chan < 0) || (ss->ipc >= 0))
34653895Smckusick goto sc_start_exit;
34753895Smckusick if (sel_stat[chan] != SEL_WAIT) {
34853895Smckusick /*
34953895Smckusick * already started
35053895Smckusick */
35153895Smckusick goto sc_start_exit;
35253895Smckusick }
35353895Smckusick sel_stat[chan] = SEL_START;
35453895Smckusick (void) splscsi();
35553895Smckusick
35653895Smckusick cs = &chan_stat[chan];
35753895Smckusick
35853895Smckusick dummy = sc_cmonr;
35953895Smckusick DMAC_WAIT0;
36053895Smckusick if (dummy & (R4_MBSY|R4_MSEL)) {
36153895Smckusick sel_stat[chan] = SEL_WAIT;
36253895Smckusick goto sc_start_exit;
36353895Smckusick }
36453895Smckusick
36553895Smckusick /*
36653895Smckusick * send SELECT with ATN command
36753895Smckusick */
36853895Smckusick ss->dma_stat = OFF;
36953895Smckusick pad_start = 0;
37053895Smckusick dummy = sc_statr;
37153895Smckusick DMAC_WAIT0;
37253895Smckusick if (dummy & R0_CIP) {
37353895Smckusick sel_stat[chan] = SEL_WAIT;
37453895Smckusick goto sc_start_exit;
37553895Smckusick }
37653895Smckusick sc_idenr = (chan << SC_TG_SHIFT) | SC_OWNID;
37753895Smckusick DMAC_WAIT0;
37853895Smckusick #ifdef SCSI_1185AQ
37953895Smckusick if (scsi_1185AQ)
38053895Smckusick sc_intok1 = Ra_STO|Ra_ARBF;
38153895Smckusick else
38253895Smckusick sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;
38353895Smckusick #else
38453895Smckusick sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;
38553895Smckusick #endif
38653895Smckusick DMAC_WAIT0;
38753895Smckusick /*
38853895Smckusick * BUGFIX for signal reflection on BSY
38953895Smckusick * !Rb_DCNT
39053895Smckusick */
39153895Smckusick sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE;
39253895Smckusick DMAC_WAIT0;
39353895Smckusick
39453895Smckusick dummy = sc_cmonr;
39553895Smckusick DMAC_WAIT0;
39653895Smckusick if (dummy & (R4_MBSY|R4_MSEL)) {
39753895Smckusick sel_stat[chan] = SEL_WAIT;
39853895Smckusick goto sc_start_exit;
39953895Smckusick }
40053895Smckusick SET_CMD(SCMD_SEL_ATN);
40153895Smckusick
40253895Smckusick sc_start_exit:
40353895Smckusick splx(s);
40453895Smckusick }
40553895Smckusick
40653895Smckusick /*
40753895Smckusick * SCSI interrupt service routine
40853895Smckusick */
scintr()40953895Smckusick scintr()
41053895Smckusick {
41153895Smckusick register struct scsi_stat *ss;
41253895Smckusick register int iloop;
41353895Smckusick register VOLATILE int chan;
41453895Smckusick register VOLATILE int dummy;
41553895Smckusick int s_int1, s_int2;
41653895Smckusick
41753895Smckusick scintr_loop:
41853895Smckusick
41953895Smckusick #if defined(CHECK_MRQ) && defined(news3400)
42053895Smckusick while (dmac_gstat & CH_MRQ(CH_SCSI))
42153895Smckusick DMAC_WAIT;
42253895Smckusick #endif
42353895Smckusick
42453895Smckusick for (iloop = 0; iloop < 100; iloop++) {
42553895Smckusick dummy = sc_statr;
42653895Smckusick DMAC_WAIT;
42753895Smckusick if ((dummy & R0_CIP) == 0)
42853895Smckusick break;
42953895Smckusick }
43053895Smckusick
43153895Smckusick /*
43253895Smckusick * get SCSI interrupt request
43353895Smckusick */
43453895Smckusick while (sc_statr & R0_MIRQ) {
43553895Smckusick DMAC_WAIT0;
43653895Smckusick s_int1 = sc_intrq1;
43753895Smckusick DMAC_WAIT0;
43853895Smckusick s_int2 = sc_intrq2;
43953895Smckusick DMAC_WAIT0;
44053895Smckusick int_stat1 |= s_int1;
44153895Smckusick int_stat2 |= s_int2;
44253895Smckusick }
44353895Smckusick
44453895Smckusick if (int_stat2 & R3_SRST) {
44553895Smckusick /*
44653895Smckusick * RST signal is drived
44753895Smckusick */
44853895Smckusick int_stat2 &= ~R3_SRST;
44953895Smckusick scsi_softreset();
45053895Smckusick goto scintr_exit;
45153895Smckusick }
45253895Smckusick
45353895Smckusick ss = &scsi_stat;
45453895Smckusick if ((ss->ipc < 0) && (ss->wrc <= 0) && (ss->wbc <= 0)) {
45553895Smckusick int_stat1 = 0;
45653895Smckusick int_stat2 = 0;
45753895Smckusick goto scintr_exit;
45853895Smckusick }
45953895Smckusick
46053895Smckusick chan = get_wb_chan();
46153895Smckusick if ((chan >= 0) && (sel_stat[chan] == SEL_START) &&
46253895Smckusick (last_cmd == SCMD_SEL_ATN)) {
46353895Smckusick /*
46453895Smckusick * Check the result of SELECTION command
46553895Smckusick */
46653895Smckusick if (int_stat1 & R2_RSL) {
46753895Smckusick /*
46853895Smckusick * RESELECTION occur
46953895Smckusick */
47053895Smckusick if (ss->wrc > 0) {
47153895Smckusick sel_stat[chan] = SEL_RSLD;
47253895Smckusick } else {
47353895Smckusick /*
47453895Smckusick * Ghost RESELECTION ???
47553895Smckusick */
47653895Smckusick int_stat1 &= ~R2_RSL;
47753895Smckusick }
47853895Smckusick }
47953895Smckusick if (int_stat1 & R2_ARBF) {
48053895Smckusick /*
48153895Smckusick * ARBITRATION fault
48253895Smckusick */
48353895Smckusick int_stat1 &= ~R2_ARBF;
48453895Smckusick sel_stat[chan] = SEL_ARBF;
48553895Smckusick }
48653895Smckusick if (int_stat1 & R2_STO) {
48753895Smckusick /*
48853895Smckusick * SELECTION timeout
48953895Smckusick */
49053895Smckusick int_stat1 &= ~R2_STO;
49153895Smckusick if ((int_stat2&(R3_PHC|R3_RMSG)) != (R3_PHC|R3_RMSG)) {
49253895Smckusick ss->ipc = chan;
49353895Smckusick ss->ip = &chan_stat[chan];
49453895Smckusick sel_stat[chan] = SEL_TIMEOUT;
49553895Smckusick chan_stat[chan].sc->sc_istatus
49653895Smckusick = INST_EP|INST_TO;
49753895Smckusick release_wb();
49853895Smckusick }
49953895Smckusick }
50053895Smckusick
50153895Smckusick /*
50253895Smckusick * SELECTION command done
50353895Smckusick */
50453895Smckusick switch (sel_stat[chan]) {
50553895Smckusick
50653895Smckusick case SEL_START:
50753895Smckusick if ((int_stat2 & R3_FNC) == 0)
50853895Smckusick break;
50953895Smckusick /*
51053895Smckusick * SELECTION success
51153895Smckusick */
51253895Smckusick sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;
51353895Smckusick ss->ipc = chan;
51453895Smckusick ss->ip = &chan_stat[chan];
51553895Smckusick ss->ip->sc->sc_istatus |= INST_IP;
51653895Smckusick ss->dma_stat = OFF;
51753895Smckusick pad_start = 0;
51853895Smckusick sel_stat[chan] = SEL_SUCCESS;
51953895Smckusick release_wb();
52053895Smckusick #ifndef NOT_SUPPORT_SYNCTR
52153895Smckusick sc_syncr = sync_tr[chan];
52253895Smckusick DMAC_WAIT0;
52353895Smckusick #endif
52453895Smckusick DMAC_WAIT0;
52553895Smckusick break;
52653895Smckusick
52753895Smckusick case SEL_TIMEOUT:
52853895Smckusick /*
52953895Smckusick * SELECTION time out
53053895Smckusick */
53153895Smckusick sc_discon();
53253895Smckusick goto scintr_exit;
53353895Smckusick
53453895Smckusick /* case SEL_RSLD: */
53553895Smckusick /* case SEL_ARBF: */
53653895Smckusick default:
53753895Smckusick /*
53853895Smckusick * SELECTION failed
53953895Smckusick */
54053895Smckusick sel_stat[chan] = SEL_WAIT;
54153895Smckusick break;
54253895Smckusick }
54353895Smckusick if ((int_stat1 & R2_RSL) == 0)
54453895Smckusick int_stat2 &= ~R3_FNC;
54553895Smckusick }
54653895Smckusick
54753895Smckusick if (ss->ip != NULL) {
54853895Smckusick /*
54953895Smckusick * check In Process channel's request
55053895Smckusick */
55153895Smckusick if (ss->dma_stat != OFF) {
55253895Smckusick /*
55353895Smckusick * adjust pointer & counter
55453895Smckusick */
55553895Smckusick adjust_transfer(ss->ip);
55653895Smckusick }
55753895Smckusick if (int_stat2 & R3_SPE) {
55853895Smckusick register int VOLATILE statr;
55953895Smckusick register int VOLATILE cmonr;
56053895Smckusick
56153895Smckusick statr = sc_statr;
56253895Smckusick DMAC_WAIT0;
56353895Smckusick cmonr = sc_cmonr;
56453895Smckusick int_stat2 &= ~R3_SPE;
56553895Smckusick perr_flag[ss->ip->chan_num] = 1;
56653895Smckusick }
56753895Smckusick }
56853895Smckusick
56953895Smckusick if (int_stat2 & R3_DCNT) {
57053895Smckusick /*
57153895Smckusick * Bus Free
57253895Smckusick */
57353895Smckusick sc_discon();
57453895Smckusick int_stat2 &= ~R3_DCNT;
57553895Smckusick }
57653895Smckusick
57753895Smckusick if ((ss->ipc >= 0) && (sel_stat[ss->ipc] == SEL_RSL_WAIT)) {
57853895Smckusick sel_stat[ss->ipc] = SEL_RSLD;
57953895Smckusick ss->ipc = -1;
58053895Smckusick int_stat1 |= R2_RSL;
58153895Smckusick }
58253895Smckusick if (int_stat1 & R2_RSL) {
58353895Smckusick /*
58453895Smckusick * Reselection
58553895Smckusick */
58653895Smckusick sc_resel();
58753895Smckusick int_stat1 &= ~R2_RSL;
58853895Smckusick if (sel_stat[ss->ipc] == SEL_RSL_WAIT)
58953895Smckusick goto scintr_exit;
59053895Smckusick }
59153895Smckusick
59253895Smckusick
59353895Smckusick if ((ss->ipc >= 0) && (ss->ipc != SC_OWNID) &&
59453895Smckusick (sel_stat[ss->ipc] == SEL_SUCCESS)) {
59553895Smckusick if (int_stat2 & R3_PHC) {
59653895Smckusick /*
59753895Smckusick * Phase change
59853895Smckusick */
59953895Smckusick int_stat2 &= ~(R3_PHC|R3_RMSG);
60053895Smckusick sc_pmatch();
60153895Smckusick } else if (int_stat2 & R3_RMSG) {
60253895Smckusick /*
60353895Smckusick * message Phase
60453895Smckusick */
60553895Smckusick if (min_flag > 0) {
60653895Smckusick int_stat2 &= ~(R3_PHC|R3_RMSG);
60753895Smckusick sc_pmatch();
60853895Smckusick }
60953895Smckusick }
61053895Smckusick else if (ss->dma_stat != OFF) {
61153895Smckusick dummy = sc_cmonr;
61253895Smckusick DMAC_WAIT0;
61353895Smckusick if ((dummy & (R4_MMSG|R4_MCD|R4_MREQ)) == R4_MREQ) {
61453895Smckusick /*
61553895Smckusick * still DATA transfer phase
61653895Smckusick */
61753895Smckusick sc_dio_pad(ss->ip);
61853895Smckusick }
61953895Smckusick }
62053895Smckusick else if (ss->ip->comflg == CF_SEND) {
62153895Smckusick dummy = sc_cmonr;
62253895Smckusick DMAC_WAIT0;
62353895Smckusick if ((dummy & SC_PMASK) == COM_OUT) {
62453895Smckusick /*
62553895Smckusick * command out phase
62653895Smckusick */
62753895Smckusick sc_cout(ss->ip);
62853895Smckusick }
62953895Smckusick }
63053895Smckusick } else {
63153895Smckusick if (int_stat2 & (R3_PHC|R3_RMSG))
63253895Smckusick goto scintr_exit;
63353895Smckusick }
63453895Smckusick
63553895Smckusick if ((int_stat1 & (R2_STO|R2_RSL|R2_ARBF))
63653895Smckusick || (int_stat2 & (R3_DCNT|R3_SRST|R3_PHC|R3_SPE))) {
63753895Smckusick /*
63853895Smckusick * still remain intrq
63953895Smckusick */
64053895Smckusick goto scintr_loop;
64153895Smckusick }
64253895Smckusick
64353895Smckusick scintr_exit:
64453895Smckusick return (1);
64553895Smckusick }
64653895Smckusick
64753895Smckusick /*
64853895Smckusick * SCSI bus reset routine
64953895Smckusick * scsi_hardreset() is occered a reset interrupt.
65053895Smckusick * And call scsi_softreset().
65153895Smckusick */
scsi_hardreset()65253895Smckusick scsi_hardreset()
65353895Smckusick {
65453895Smckusick register int s;
65553895Smckusick #ifdef DMAC_MAP_INIT
65653895Smckusick register int i;
65753895Smckusick #endif
65853895Smckusick
65953895Smckusick s = splscsi();
66053895Smckusick
66153895Smckusick scsi_chipreset();
66253895Smckusick DMAC_WAIT0;
66353895Smckusick int_stat1 = 0;
66453895Smckusick int_stat2 = 0;
66553895Smckusick SET_CMD(SCMD_AST_RST); /* assert RST signal */
66653895Smckusick
66753895Smckusick #ifdef DMAC_MAP_INIT
66853895Smckusick if (dmac_map_init == 0) {
66953895Smckusick dmac_map_init++;
67053895Smckusick for (i = 0; i < NDMACMAP; i++) {
67153895Smckusick # if defined(mips) && defined(CPU_SINGLE)
67253895Smckusick dmac_gsel = CH_SCSI;
67353895Smckusick dmac_ctag = (u_char)i;
67453895Smckusick dmac_cmap = (u_short)0;
67553895Smckusick # endif
67653895Smckusick }
67753895Smckusick }
67853895Smckusick #endif
67953895Smckusick splx(s);
68053895Smckusick }
68153895Smckusick
68253895Smckusick /*
68353895Smckusick * I/O port (sc_ioptr) bit assign
68453895Smckusick *
68553895Smckusick * Rf_PRT3 - <reserved>
68653895Smckusick * Rf_PRT2 - <reserved>
68753895Smckusick * Rf_PRT1 out Floppy Disk Density control
68853895Smckusick * Rf_PRT0 out Floppy Disk Eject control
68953895Smckusick */
69053895Smckusick
scsi_chipreset()69153895Smckusick scsi_chipreset()
69253895Smckusick {
69353895Smckusick register int s;
69453895Smckusick register int iloop;
69553895Smckusick register VOLATILE int save_ioptr;
69653895Smckusick register VOLATILE int dummy;
69753895Smckusick int s_int1, s_int2;
69853895Smckusick
69953895Smckusick s = splscsi();
70053895Smckusick
70153895Smckusick #if defined(mips) && defined(CPU_SINGLE)
70253895Smckusick dmac_gsel = CH_SCSI;
70353895Smckusick dmac_cwid = 4; /* initialize DMAC SCSI chan */
70453895Smckusick *(unsigned VOLATILE char *)PINTEN |= DMA_INTEN;
70553895Smckusick dma_reset(CH_SCSI);
70653895Smckusick #endif
70753895Smckusick sc_envir = 0; /* 1/4 clock */
70853895Smckusick DMAC_WAIT0;
70953895Smckusick save_ioptr = sc_ioptr;
71053895Smckusick DMAC_WAIT0;
71153895Smckusick last_cmd = SCMD_CHIP_RST;
71253895Smckusick sc_comr = SCMD_CHIP_RST; /* reset chip */
71353895Smckusick DMAC_WAIT;
71453895Smckusick (void) WAIT_STATR_BITCLR(R0_CIP);
71553895Smckusick /*
71653895Smckusick * SCMD_CHIP_RST command reset all register
71753895Smckusick * except sc_statr<7:6> & sc_cmonr.
71853895Smckusick * So, bit R0_MIRQ & R3_FNC will be not set.
71953895Smckusick */
72053895Smckusick sc_idenr = SC_OWNID;
72153895Smckusick DMAC_WAIT0;
72253895Smckusick
72353895Smckusick sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;
72453895Smckusick DMAC_WAIT0;
72553895Smckusick sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
72653895Smckusick DMAC_WAIT0;
72753895Smckusick
72853895Smckusick sc_ioptr = save_ioptr;
72953895Smckusick DMAC_WAIT;
73053895Smckusick
73153895Smckusick sc_moder = Rc_TMSL; /* RST drive time = 25.5 us */
73253895Smckusick DMAC_WAIT0;
73353895Smckusick sc_timer = 0x2;
73453895Smckusick DMAC_WAIT0;
73553895Smckusick
73653895Smckusick sc_moder = Rc_SPHI; /* selection timeout = 252 ms */
73753895Smckusick DMAC_WAIT0;
73853895Smckusick sc_timer = SEL_TIMEOUT_VALUE;
73953895Smckusick DMAC_WAIT0;
74053895Smckusick
74153895Smckusick #ifdef SCSI_1185AQ
74253895Smckusick if (scsi_1185AQ)
74353895Smckusick SET_CMD(SCMD_ENB_SEL); /* enable reselection */
74453895Smckusick #endif
74553895Smckusick
74653895Smckusick int_stat1 &= ~R2_RSL; /* ignore RSL inter request */
74753895Smckusick
74853895Smckusick splx(s);
74953895Smckusick }
75053895Smckusick
scsi_softreset()75153895Smckusick scsi_softreset()
75253895Smckusick {
75353895Smckusick register VOLATILE struct sc_chan_stat *cs;
75453895Smckusick register struct scsi_stat *ss;
75553895Smckusick register int (*handler)();
75653895Smckusick register int i;
75753895Smckusick #ifdef mips
75853895Smckusick extern struct sc_data sc_data[];
75953895Smckusick register struct sc_data *scdp;
76053895Smckusick #endif
76153895Smckusick
76253895Smckusick wbq_actf = NULL;
76353895Smckusick wbq_actl = NULL;
76453895Smckusick ss = &scsi_stat;
76553895Smckusick ss->wbc = 0;
76653895Smckusick ss->wrc = 0;
76753895Smckusick ss->ip = NULL;
76853895Smckusick ss->ipc = -1;
76953895Smckusick ss->dma_stat = OFF;
77053895Smckusick pad_start = 0;
77153895Smckusick
77253895Smckusick for (i = 0; i < NTARGET; ++i) {
77353895Smckusick if (i == SC_OWNID)
77453895Smckusick continue;
77553895Smckusick cs = &chan_stat[i];
77653895Smckusick cs->wb_next = NULL;
77753895Smckusick #ifndef NOT_SUPPORT_SYNCTR
77853895Smckusick sync_tr[i] = 0; /* asynchronous mode */
77953895Smckusick #endif
78053895Smckusick sel_stat[i] = SEL_WAIT;
78153895Smckusick if (cs->sc != NULL) {
78253895Smckusick if ((cs->sc->sc_istatus & INST_EP) == 0)
78353895Smckusick cs->sc->sc_istatus = (INST_EP|INST_HE);
78453895Smckusick cs->sc = NULL;
78553895Smckusick #ifdef mips
78653895Smckusick scdp = &sc_data[cs->chan_num];
78753895Smckusick MachFlushDCache(scdp->scd_scaddr, sizeof(struct scsi));
78853895Smckusick
78953895Smckusick if (MACH_IS_USPACE(scdp->scd_vaddr)) {
79053895Smckusick panic("scsi_softreset: user address is not supported");
79153895Smckusick } else if (MACH_IS_CACHED(scdp->scd_vaddr)) {
79253895Smckusick MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);
79353895Smckusick } else if (MACH_IS_MAPPED(scdp->scd_vaddr)) {
79453895Smckusick #ifdef notyet /* KU:XXX */
79553895Smckusick clean_k2dcache(scdp->scd_vaddr, scdp->scd_count);
79653895Smckusick #else
79753895Smckusick MachFlushCache();
79853895Smckusick #endif
79953895Smckusick }
80053895Smckusick #endif /* mips */
80153895Smckusick if ((cs->intr_flg == SCSI_INTEN)
80253895Smckusick && (handler = scintsw[i].sci_inthandler)) {
80353895Smckusick #ifdef noyet /* KU:XXX */
80453895Smckusick intrcnt[INTR_SCSI00 + i]++;
80553895Smckusick #endif
80653895Smckusick (*handler)(scintsw[i].sci_ctlr);
80753895Smckusick }
80853895Smckusick }
80953895Smckusick }
81053895Smckusick }
81153895Smckusick
81253895Smckusick /*
81353895Smckusick * RESELECTION interrupt service routine
81453895Smckusick * ( RESELECTION phase )
81553895Smckusick */
sc_resel()81653895Smckusick sc_resel()
81753895Smckusick {
81853895Smckusick register struct sc_chan_stat *cs;
81953895Smckusick register struct scsi_stat *ss;
82053895Smckusick register VOLATILE int chan;
82153895Smckusick register VOLATILE int statr;
82253895Smckusick register int iloop;
82353895Smckusick
82453895Smckusick min_flag = 0;
82553895Smckusick chan = (sc_idenr & R6_SID_MASK) >> SC_TG_SHIFT;
82653895Smckusick
82753895Smckusick if (chan == SC_OWNID)
82853895Smckusick return;
82953895Smckusick
83053895Smckusick statr = sc_statr;
83153895Smckusick DMAC_WAIT0;
83253895Smckusick if (statr & R0_CIP) {
83353895Smckusick if (last_cmd == SCMD_SEL_ATN) {
83453895Smckusick /*
83553895Smckusick * SELECTION command dead lock ?
83653895Smckusick * save interrupt request
83753895Smckusick */
83853895Smckusick while (sc_statr & R0_MIRQ) {
83953895Smckusick DMAC_WAIT0;
84053895Smckusick int_stat1 |= sc_intrq1;
84153895Smckusick DMAC_WAIT0;
84253895Smckusick int_stat2 |= sc_intrq2;
84353895Smckusick DMAC_WAIT0;
84453895Smckusick }
84553895Smckusick scsi_chipreset();
84653895Smckusick }
84753895Smckusick }
84853895Smckusick
84953895Smckusick cs = &chan_stat[chan];
85053895Smckusick if (cs->sc == NULL) {
85153895Smckusick scsi_hardreset();
85253895Smckusick return;
85353895Smckusick }
85453895Smckusick if ((cs->sc->sc_istatus & INST_WR) == 0) {
85553895Smckusick scsi_hardreset();
85653895Smckusick return;
85753895Smckusick }
85853895Smckusick
85953895Smckusick ss = &scsi_stat;
86053895Smckusick if (ss->ipc >= 0) {
86153895Smckusick scsi_hardreset();
86253895Smckusick return;
86353895Smckusick }
86453895Smckusick
86553895Smckusick ss->ip = cs;
86653895Smckusick ss->ipc = chan;
86753895Smckusick
86853895Smckusick sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;
86953895Smckusick DMAC_WAIT0;
87053895Smckusick
87153895Smckusick iloop = 0;
87253895Smckusick while ((int_stat2 & R3_FNC) == 0) {
87353895Smckusick /*
87453895Smckusick * Max 6 usec wait
87553895Smckusick */
87653895Smckusick if (iloop++ > RSL_LOOP_CNT) {
87753895Smckusick sel_stat[chan] = SEL_RSL_WAIT;
87853895Smckusick return;
87953895Smckusick }
88053895Smckusick GET_INTR(&int_stat1, &int_stat2);
88153895Smckusick }
88253895Smckusick int_stat2 &= ~R3_FNC;
88353895Smckusick
88453895Smckusick sel_stat[chan] = SEL_SUCCESS;
88553895Smckusick
88653895Smckusick ss->wrc--;
88753895Smckusick ss->dma_stat = OFF;
88853895Smckusick pad_start = 0;
88953895Smckusick cs->sc->sc_istatus |= INST_IP;
89053895Smckusick cs->sc->sc_istatus &= ~INST_WR;
89153895Smckusick
89253895Smckusick #ifndef NOT_SUPPORT_SYNCTR
89353895Smckusick sc_syncr = sync_tr[chan];
89453895Smckusick DMAC_WAIT0;
89553895Smckusick #endif
89653895Smckusick }
89753895Smckusick
89853895Smckusick /*
89953895Smckusick * DISCONNECT interrupt service routine
90053895Smckusick * ( Target disconnect / job done )
90153895Smckusick */
sc_discon()90253895Smckusick sc_discon()
90353895Smckusick {
90453895Smckusick register VOLATILE struct sc_chan_stat *cs;
90553895Smckusick register struct scsi_stat *ss;
90653895Smckusick register int (*handler)();
90753895Smckusick register VOLATILE int dummy;
90853895Smckusick #ifdef mips
90953895Smckusick extern struct sc_data sc_data[];
91053895Smckusick register struct sc_data *scdp;
91153895Smckusick #endif
91253895Smckusick
91353895Smckusick /*
91453895Smckusick * Signal reflection on BSY is occured.
91553895Smckusick * Not Bus Free Phase, ignore.
91653895Smckusick *
91753895Smckusick * But, CXD1185Q reset INIT bit of sc_statr.
91853895Smckusick * So, can't issue Transfer Information command.
91953895Smckusick *
92053895Smckusick * What shall we do ? Bus reset ?
92153895Smckusick */
92253895Smckusick if ((int_stat2 & R3_DCNT) && ((sc_intok2 & Rb_DCNT) == 0))
92353895Smckusick return;
92453895Smckusick
92553895Smckusick sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE;
92653895Smckusick DMAC_WAIT0;
92753895Smckusick
92853895Smckusick min_flag = 0;
92953895Smckusick dummy = sc_cmonr;
93053895Smckusick DMAC_WAIT0;
93153895Smckusick if (dummy & R4_MATN) {
93253895Smckusick SET_CMD(SCMD_NGT_ATN);
93353895Smckusick (void) WAIT_STATR_BITSET(R0_MIRQ);
93453895Smckusick GET_INTR(&int_stat1, &int_stat2); /* clear interrupt */
93553895Smckusick }
93653895Smckusick
93753895Smckusick if ((int_stat1 & R2_RSL) == 0)
93853895Smckusick int_stat2 &= ~R3_FNC;
93953895Smckusick
94053895Smckusick ss = &scsi_stat;
94153895Smckusick cs = ss->ip;
94253895Smckusick if ((cs == NULL) || (ss->ipc < 0))
94353895Smckusick goto sc_discon_exit;
94453895Smckusick
94553895Smckusick if ((sel_stat[cs->chan_num] != SEL_SUCCESS)
94653895Smckusick && (sel_stat[cs->chan_num] != SEL_TIMEOUT))
94753895Smckusick printf("sc_discon: eh!\n");
94853895Smckusick
94953895Smckusick /*
95053895Smckusick * indicate abnormal terminate
95153895Smckusick */
95253895Smckusick if ((cs->sc->sc_istatus & (INST_EP|INST_WR)) == 0)
95353895Smckusick cs->sc->sc_istatus |= (INST_EP|INST_PRE|INST_LB);
95453895Smckusick
95553895Smckusick cs->sc->sc_istatus &= ~INST_IP;
95653895Smckusick ss->dma_stat = OFF;
95753895Smckusick pad_start = 0;
95853895Smckusick ss->ip = NULL;
95953895Smckusick ss->ipc = -1;
96053895Smckusick
96153895Smckusick if ((cs->sc->sc_istatus & INST_WR) == 0) {
96253895Smckusick if (perr_flag[cs->chan_num] > 0)
96353895Smckusick cs->sc->sc_istatus |= INST_EP|INST_PRE;
96453895Smckusick cs->sc = NULL;
96553895Smckusick #ifdef mips
96653895Smckusick scdp = &sc_data[cs->chan_num];
96753895Smckusick MachFlushDCache(scdp->scd_scaddr, sizeof(struct scsi));
96853895Smckusick
96953895Smckusick if (MACH_IS_USPACE(scdp->scd_vaddr)) {
97053895Smckusick panic("sc_discon: user address is not supported");
97153895Smckusick } else if (MACH_IS_CACHED(scdp->scd_vaddr)) {
97253895Smckusick MachFlushDCache(scdp->scd_vaddr, scdp->scd_count);
97353895Smckusick } else if (MACH_IS_MAPPED(scdp->scd_vaddr)) {
97453895Smckusick #ifdef notyet /* KU:XXX */
97553895Smckusick clean_k2dcache(scdp->scd_vaddr, scdp->scd_count);
97653895Smckusick #else
97753895Smckusick MachFlushCache();
97853895Smckusick #endif
97953895Smckusick }
98053895Smckusick #endif /* mips */
98153895Smckusick if ((cs->intr_flg == SCSI_INTEN)
98253895Smckusick && (handler = scintsw[cs->chan_num].sci_inthandler)) {
98353895Smckusick #ifdef notyet /* KU:XXX */
98453895Smckusick intrcnt[INTR_SCSI00 + cs->chan_num]++;
98553895Smckusick #endif
98653895Smckusick (*handler)(scintsw[cs->chan_num].sci_ctlr);
98753895Smckusick }
98853895Smckusick }
98953895Smckusick
99053895Smckusick sc_discon_exit:
99153895Smckusick sc_start();
99253895Smckusick }
99353895Smckusick
99453895Smckusick /*
99553895Smckusick * SCSI phase match interrupt service routine
99653895Smckusick */
sc_pmatch()99753895Smckusick sc_pmatch()
99853895Smckusick {
99953895Smckusick register VOLATILE struct sc_chan_stat *cs;
100053895Smckusick register VOLATILE int phase;
100153895Smckusick register VOLATILE int phase2;
100253895Smckusick register VOLATILE int cmonr;
100353895Smckusick
100453895Smckusick int_stat2 &= ~R3_FNC; /* XXXXXXXX */
100553895Smckusick
100653895Smckusick cs = scsi_stat.ip;
100753895Smckusick if (cs == NULL)
100853895Smckusick return;
100953895Smckusick
101053895Smckusick # if defined(mips) && defined(CPU_SINGLE)
101153895Smckusick dma_reset(CH_SCSI);
101253895Smckusick # endif
101353895Smckusick phase = sc_cmonr & SC_PMASK;
101453895Smckusick DMAC_WAIT0;
101553895Smckusick for (;;) {
101653895Smckusick phase2 = phase;
101753895Smckusick cmonr = sc_cmonr;
101853895Smckusick DMAC_WAIT0;
101953895Smckusick phase = cmonr & SC_PMASK;
102053895Smckusick if (phase == phase2) {
102153895Smckusick if ((phase == DAT_IN) || (phase == DAT_OUT))
102253895Smckusick break;
102353895Smckusick else if (cmonr & R4_MREQ)
102453895Smckusick break;
102553895Smckusick }
102653895Smckusick }
102753895Smckusick
102853895Smckusick
102953895Smckusick scsi_stat.dma_stat = OFF;
103053895Smckusick pad_start = 0;
103153895Smckusick
103253895Smckusick if (phase == COM_OUT) {
103353895Smckusick min_flag = 0;
103453895Smckusick if (cs->comflg != CF_SEND)
103553895Smckusick cs->comflg = CF_SET;
103653895Smckusick sc_cout(cs);
103753895Smckusick } else {
103853895Smckusick cs->comflg = CF_ENOUGH;
103953895Smckusick sc_intok2 &= ~Rb_FNC;
104053895Smckusick if (phase == MES_IN) {
104153895Smckusick min_flag++;
104253895Smckusick sc_min(cs);
104353895Smckusick } else {
104453895Smckusick min_flag = 0;
104553895Smckusick
104653895Smckusick switch (phase) {
104753895Smckusick
104853895Smckusick case MES_OUT:
104953895Smckusick sc_mout(cs);
105053895Smckusick break;
105153895Smckusick
105253895Smckusick case DAT_IN:
105353895Smckusick case DAT_OUT:
105453895Smckusick sc_dio(cs);
105553895Smckusick break;
105653895Smckusick
105753895Smckusick case STAT_IN:
105853895Smckusick sc_sin(cs);
105953895Smckusick break;
106053895Smckusick
106153895Smckusick default:
106253895Smckusick printf("SCSI%d: unknown phase\n", cs->chan_num);
106353895Smckusick break;
106453895Smckusick }
106553895Smckusick }
106653895Smckusick }
106753895Smckusick }
106853895Smckusick
106953895Smckusick
flush_fifo()107053895Smckusick flush_fifo()
107153895Smckusick {
107253895Smckusick register VOLATILE int dummy;
107353895Smckusick VOLATILE int tmp;
107453895Smckusick VOLATILE int tmp0;
107553895Smckusick
107653895Smckusick dummy = sc_ffstr;
107753895Smckusick DMAC_WAIT0;
107853895Smckusick if (dummy & R5_FIFOREM) {
107953895Smckusick /*
108053895Smckusick * flush FIFO
108153895Smckusick */
108253895Smckusick SET_CMD(SCMD_FLSH_FIFO);
108353895Smckusick tmp = 0;
108453895Smckusick do {
108553895Smckusick do {
108653895Smckusick dummy = sc_statr;
108753895Smckusick DMAC_WAIT0;
108853895Smckusick } while (dummy & R0_CIP);
108953895Smckusick GET_INTR(&tmp0, &tmp); /* clear interrupt */
109053895Smckusick } while ((tmp & R3_FNC) == 0);
109153895Smckusick }
109253895Smckusick }
109353895Smckusick
109453895Smckusick /*
109553895Smckusick * SCSI command send routine
109653895Smckusick */
109753895Smckusick int
sc_cout(cs)109853895Smckusick sc_cout(cs)
109953895Smckusick register struct sc_chan_stat *cs;
110053895Smckusick {
110153895Smckusick register struct scsi *sc;
110253895Smckusick register int iloop;
110353895Smckusick register int cdb_bytes;
110453895Smckusick register VOLATILE int dummy;
110553895Smckusick register VOLATILE int statr;
110653895Smckusick
110753895Smckusick if (cs->comflg == CF_SET) {
110853895Smckusick cs->comflg = CF_SEND;
110953895Smckusick
111053895Smckusick flush_fifo();
111153895Smckusick
111253895Smckusick sc = cs->sc;
111353895Smckusick switch (sc->sc_opcode & CMD_TYPEMASK) {
111453895Smckusick case CMD_T0:
111553895Smckusick cdb_bytes = 6;
111653895Smckusick break;
111753895Smckusick
111853895Smckusick case CMD_T1:
111953895Smckusick cdb_bytes = 10;
112053895Smckusick break;
112153895Smckusick
112253895Smckusick case CMD_T5:
112353895Smckusick cdb_bytes = 12;
112453895Smckusick break;
112553895Smckusick
112653895Smckusick default:
112753895Smckusick cdb_bytes = 6;
112853895Smckusick sc_intok2 |= Rb_FNC;
112953895Smckusick break;
113053895Smckusick }
113153895Smckusick
113253895Smckusick /*
113353895Smckusick * set Active pointers
113453895Smckusick */
113553895Smckusick act_cmd_pointer = sc->sc_cdb.un_reserved;
113653895Smckusick cs->act_trcnt = sc->sc_ctrnscnt;
113753895Smckusick cs->act_point = sc->sc_cpoint;
113853895Smckusick cs->act_tag = sc->sc_ctag;
113953895Smckusick cs->act_offset = sc->sc_coffset;
114053895Smckusick
114153895Smckusick } else {
114253895Smckusick cdb_bytes = 1;
114353895Smckusick iloop = 0;
114453895Smckusick do {
114553895Smckusick dummy = sc_cmonr;
114653895Smckusick DMAC_WAIT0;
114753895Smckusick if ((dummy & SC_PMASK) != COM_OUT)
114853895Smckusick return;
114953895Smckusick statr = sc_statr;
115053895Smckusick DMAC_WAIT0;
115153895Smckusick if (statr & R0_MIRQ)
115253895Smckusick return;
115353895Smckusick } while ((dummy & R4_MREQ) == 0);
115453895Smckusick statr = sc_statr;
115553895Smckusick DMAC_WAIT0;
115653895Smckusick if (statr & R0_MIRQ)
115753895Smckusick return;
115853895Smckusick }
115953895Smckusick
116053895Smckusick
116153895Smckusick SET_CNT(cdb_bytes);
116253895Smckusick SET_CMD(SCMD_TR_INFO|R0_TRBE);
116353895Smckusick
116453895Smckusick for (iloop = 0; iloop < cdb_bytes; iloop++) {
116553895Smckusick do {
116653895Smckusick dummy = sc_cmonr;
116753895Smckusick DMAC_WAIT0;
116853895Smckusick if ((dummy & SC_PMASK) != COM_OUT)
116953895Smckusick return;
117053895Smckusick } while ((dummy & R4_MREQ) == 0);
117153895Smckusick statr = sc_statr;
117253895Smckusick DMAC_WAIT0;
117353895Smckusick if (statr & R0_MIRQ)
117453895Smckusick return;
117553895Smckusick sc_datr = *act_cmd_pointer++;
117653895Smckusick do {
117753895Smckusick dummy = sc_cmonr;
117853895Smckusick DMAC_WAIT0;
117953895Smckusick } while ((dummy & R4_MACK) != 0);
118053895Smckusick }
118153895Smckusick }
118253895Smckusick
118353895Smckusick #define GET_MIN_COUNT 127
118453895Smckusick
118553895Smckusick /*
118653895Smckusick * SCSI message accept routine
118753895Smckusick */
sc_min(cs)118853895Smckusick sc_min(cs)
118953895Smckusick register struct sc_chan_stat *cs;
119053895Smckusick {
119153895Smckusick register struct scsi *sc;
119253895Smckusick register struct scsi_stat *ss;
119353895Smckusick register VOLATILE int dummy;
119453895Smckusick
119553895Smckusick sc = cs->sc;
119653895Smckusick ss = &scsi_stat;
119753895Smckusick
119853895Smckusick sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
119953895Smckusick DMAC_WAIT0;
120053895Smckusick
120153895Smckusick if (min_flag == 1)
120253895Smckusick flush_fifo();
120353895Smckusick
120453895Smckusick dummy = sc_cmonr;
120553895Smckusick DMAC_WAIT0;
120653895Smckusick if ((dummy & R4_MREQ) == 0) {
120753895Smckusick printf("sc_min: !REQ cmonr=%x\n", dummy);
120853895Smckusick print_scsi_stat();
120953895Smckusick scsi_hardreset();
121053895Smckusick return;
121153895Smckusick }
121253895Smckusick
121353895Smckusick retry_cmd_issue:
121453895Smckusick int_stat2 &= ~R3_FNC;
121553895Smckusick SET_CMD(SCMD_TR_INFO);
121653895Smckusick do {
121753895Smckusick do {
121853895Smckusick dummy = sc_statr;
121953895Smckusick DMAC_WAIT0;
122053895Smckusick } while (dummy & R0_CIP);
122153895Smckusick GET_INTR(&int_stat1, &int_stat2); /* clear interrupt */
122253895Smckusick } while ((int_stat2 & R3_FNC) == 0);
122353895Smckusick int_stat2 &= ~R3_FNC;
122453895Smckusick
122553895Smckusick dummy = sc_ffstr;
122653895Smckusick if (dummy & R5_FIE) {
122753895Smckusick DMAC_WAIT;
122853895Smckusick dummy = sc_ffstr;
122953895Smckusick DMAC_WAIT0;
123053895Smckusick if (dummy & R5_FIE) {
123153895Smckusick dummy = sc_statr;
123253895Smckusick DMAC_WAIT0;
123353895Smckusick if ((dummy & R0_INIT) == 0) {
123453895Smckusick /*
123553895Smckusick * CXD1185 detect BSY false
123653895Smckusick */
123753895Smckusick scsi_hardreset();
123853895Smckusick return;
123953895Smckusick }
124053895Smckusick }
124153895Smckusick }
124253895Smckusick dummy = sc_datr; /* get message byte */
124353895Smckusick DMAC_WAIT0;
124453895Smckusick
124553895Smckusick if (min_cnt[cs->chan_num] == 0) {
124653895Smckusick sc->sc_message = sc->sc_identify;
124753895Smckusick if (dummy == MSG_EXTND) {
124853895Smckusick /* Extended Message */
124953895Smckusick min_cnt[cs->chan_num] = GET_MIN_COUNT;
125053895Smckusick min_point[cs->chan_num] = sc->sc_param;
125153895Smckusick bzero((caddr_t)sc->sc_param, 8);
125253895Smckusick *min_point[cs->chan_num]++ = dummy;
125353895Smckusick } else {
125453895Smckusick switch ((dummy & MSG_IDENT)? MSG_IDENT : dummy) {
125553895Smckusick
125653895Smckusick case MSG_CCOMP:
125753895Smckusick sc->sc_istatus |= INST_EP;
125853895Smckusick break;
125953895Smckusick
126053895Smckusick case MSG_MREJ:
126153895Smckusick #ifndef NOT_SUPPORT_SYNCTR
126253895Smckusick if (mout_flag[cs->chan_num] == MOUT_SYNC_TR)
126353895Smckusick sync_tr[cs->chan_num] = 0;
126453895Smckusick #endif
126553895Smckusick break;
126653895Smckusick
126753895Smckusick case MSG_IDENT:
126853895Smckusick case MSG_RDP:
126953895Smckusick ss->dma_stat = OFF;
127053895Smckusick pad_start = 0;
127153895Smckusick cs->comflg = OFF;
127253895Smckusick /*
127353895Smckusick * restore the saved value to Active pointers
127453895Smckusick */
127553895Smckusick act_cmd_pointer = sc->sc_cdb.un_reserved;
127653895Smckusick cs->act_trcnt = sc->sc_ctrnscnt;
127753895Smckusick cs->act_point = sc->sc_cpoint;
127853895Smckusick cs->act_tag = sc->sc_ctag;
127953895Smckusick cs->act_offset = sc->sc_coffset;
128053895Smckusick break;
128153895Smckusick
128253895Smckusick case MSG_SDP:
128353895Smckusick /*
128453895Smckusick * save Active pointers
128553895Smckusick */
128653895Smckusick sc->sc_ctrnscnt = cs->act_trcnt;
128753895Smckusick sc->sc_ctag = cs->act_tag;
128853895Smckusick sc->sc_coffset = cs->act_offset;
128953895Smckusick sc->sc_cpoint = cs->act_point;
129053895Smckusick break;
129153895Smckusick
129253895Smckusick case MSG_DCNT:
129353895Smckusick sc->sc_istatus |= INST_WR;
129453895Smckusick ss->wrc++;
129553895Smckusick break;
129653895Smckusick
129753895Smckusick default:
129853895Smckusick sc->sc_message = MSG_MREJ;
129953895Smckusick SET_CMD(SCMD_AST_ATN);
130053895Smckusick printf("SCSI%d:sc_min() Unknown mes=0x%x, \n",
130153895Smckusick cs->chan_num, dummy);
130253895Smckusick }
130353895Smckusick }
130453895Smckusick } else {
130553895Smckusick *min_point[cs->chan_num]++ = dummy;
130653895Smckusick if (min_cnt[cs->chan_num] == GET_MIN_COUNT)
130753895Smckusick min_cnt[cs->chan_num] = dummy;
130853895Smckusick else
130953895Smckusick min_cnt[cs->chan_num]--;
131053895Smckusick if (min_cnt[cs->chan_num] <= 0) {
131153895Smckusick #ifdef ABORT_SYNCTR_MES_FROM_TARGET
131253895Smckusick if ((sc->sc_param[2] == 0x01)
131353895Smckusick && (mout_flag[cs->chan_num] == MOUT_SYNC_TR)) {
131453895Smckusick #else
131553895Smckusick if (sc->sc_param[2] == 0x01) { /*}*/
131653895Smckusick #endif
131753895Smckusick register int i;
131853895Smckusick /*
131953895Smckusick * receive Synchronous transfer message reply
132053895Smckusick * calculate transfer period val
132153895Smckusick * tpm * 4/1000 us = 4/16 * (tpv + 1)
132253895Smckusick */
132353895Smckusick #define TPM2TPV(tpm) (((tpm)*16 + 999) / 1000 - 1)
132453895Smckusick #ifndef NOT_SUPPORT_SYNCTR
132553895Smckusick i = sc->sc_param[3]; /* get tpm */
132653895Smckusick i = TPM2TPV(i) << 4;
132753895Smckusick if (sc->sc_param[4] == 0)
132853895Smckusick sync_tr[cs->chan_num] = 0;
132953895Smckusick else
133053895Smckusick sync_tr[cs->chan_num] = i | sc->sc_param[4];
133153895Smckusick #endif /* !NOT_SUPPORT_SYNCTR */
133253895Smckusick } else {
133353895Smckusick sc->sc_message = MSG_MREJ;
133453895Smckusick SET_CMD(SCMD_AST_ATN); /* assert ATN */
133553895Smckusick }
133653895Smckusick }
133753895Smckusick }
133853895Smckusick SET_CMD(SCMD_NGT_ACK);
133953895Smckusick }
134053895Smckusick
134153895Smckusick /*
134253895Smckusick * SCSI message send routine
134353895Smckusick */
134453895Smckusick int
sc_mout(cs)134553895Smckusick sc_mout(cs)
134653895Smckusick register struct sc_chan_stat *cs;
134753895Smckusick {
134853895Smckusick register struct scsi *sc = cs->sc;
134953895Smckusick register u_char *mp;
135053895Smckusick register int cnt;
135153895Smckusick register int iloop;
135253895Smckusick register VOLATILE int dummy;
135353895Smckusick VOLATILE int tmp;
135453895Smckusick VOLATILE int tmp0;
135553895Smckusick
135653895Smckusick flush_fifo();
135753895Smckusick
135853895Smckusick if (mout_flag[cs->chan_num] == 0) {
135953895Smckusick mout_flag[cs->chan_num] = MOUT_IDENTIFY;
136053895Smckusick if (sc->sc_message != 0) {
136153895Smckusick sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
136253895Smckusick DMAC_WAIT0;
136353895Smckusick if ((sc->sc_message == MSG_EXTND)
136453895Smckusick && (sc->sc_param[2] == 0x01)) {
136553895Smckusick cnt = 5;
136653895Smckusick mp = sc->sc_param;
136753895Smckusick sc->sc_param[3] = MIN_TP;
136853895Smckusick if (sc->sc_param[4] > MAX_OFFSET_BYTES)
136953895Smckusick sc->sc_param[4] = MAX_OFFSET_BYTES;
137053895Smckusick mout_flag[cs->chan_num] = MOUT_SYNC_TR;
137153895Smckusick } else {
137253895Smckusick cnt = 1;
137353895Smckusick mp = &sc->sc_message;
137453895Smckusick }
137553895Smckusick
137653895Smckusick SET_CNT(cnt);
137753895Smckusick SET_CMD(SCMD_TR_INFO|R0_TRBE);
137853895Smckusick sc_datr = sc->sc_identify;
137953895Smckusick DMAC_WAIT0;
138053895Smckusick for (iloop = 1; iloop < cnt; iloop++) {
138153895Smckusick sc_datr = *mp++;
138253895Smckusick DMAC_WAIT;
138353895Smckusick }
138453895Smckusick do {
138553895Smckusick dummy = sc_cmonr;
138653895Smckusick DMAC_WAIT0;
138753895Smckusick if ((dummy & R4_MBSY) == 0)
138853895Smckusick return;
138953895Smckusick dummy = sc_statr;
139053895Smckusick DMAC_WAIT0;
139153895Smckusick } while (dummy & R0_CIP);
139253895Smckusick
139353895Smckusick tmp = 0;
139453895Smckusick GET_INTR(&tmp0, &tmp); /* clear interrupt */
139553895Smckusick if ((tmp & R3_FNC) == 0) {
139653895Smckusick (void) WAIT_STATR_BITSET(R0_MIRQ);
139753895Smckusick GET_INTR(&tmp0, &tmp); /* clear interrupt */
139853895Smckusick }
139953895Smckusick
140053895Smckusick do {
140153895Smckusick dummy = sc_cmonr;
140253895Smckusick DMAC_WAIT0;
140353895Smckusick if ((dummy & R4_MBSY) == 0)
140453895Smckusick return;
140553895Smckusick } while ((dummy & R4_MREQ) == 0);
140653895Smckusick SET_CMD(SCMD_NGT_ATN);
140753895Smckusick (void) WAIT_STATR_BITCLR(R0_CIP);
140853895Smckusick GET_INTR(&tmp0, &tmp); /* clear interrupt */
140953895Smckusick
141053895Smckusick dummy = sc_cmonr;
141153895Smckusick DMAC_WAIT0;
141253895Smckusick if ((dummy & R4_MREQ) == 0) {
141353895Smckusick printf("sc_mout: !REQ cmonr=%x\n", dummy);
141453895Smckusick print_scsi_stat();
141553895Smckusick scsi_hardreset();
141653895Smckusick return;
141753895Smckusick }
141853895Smckusick
141953895Smckusick SET_CMD(SCMD_TR_INFO);
142053895Smckusick sc_datr = *mp++;
142153895Smckusick DMAC_WAIT0;
142253895Smckusick } else {
142353895Smckusick dummy = sc_cmonr;
142453895Smckusick DMAC_WAIT0;
142553895Smckusick if (dummy & R4_MATN) {
142653895Smckusick SET_CMD(SCMD_NGT_ATN);
142753895Smckusick (void) WAIT_STATR_BITCLR(R0_CIP);
142853895Smckusick GET_INTR(&tmp0, &tmp); /* clear interrupt */
142953895Smckusick }
143053895Smckusick
143153895Smckusick iloop = 0;
143253895Smckusick do {
143353895Smckusick dummy = sc_cmonr;
143453895Smckusick DMAC_WAIT0;
143553895Smckusick if (iloop++ > CHECK_LOOP_CNT)
143653895Smckusick break;
143753895Smckusick } while ((dummy & R4_MREQ) == 0);
143853895Smckusick SET_CMD(SCMD_TR_INFO);
143953895Smckusick sc_datr = sc->sc_identify;
144053895Smckusick DMAC_WAIT0;
144153895Smckusick }
144253895Smckusick } else {
144353895Smckusick dummy = sc_cmonr;
144453895Smckusick DMAC_WAIT0;
144553895Smckusick if (dummy & R4_MATN) {
144653895Smckusick SET_CMD(SCMD_NGT_ATN);
144753895Smckusick (void) WAIT_STATR_BITCLR(R0_CIP);
144853895Smckusick GET_INTR(&tmp0, &tmp); /* clear interrupt */
144953895Smckusick }
145053895Smckusick
145153895Smckusick dummy = sc_cmonr;
145253895Smckusick DMAC_WAIT0;
145353895Smckusick if ((dummy & R4_MREQ) == 0) {
145453895Smckusick printf("sc_mout: !REQ cmonr=%x\n", dummy);
145553895Smckusick print_scsi_stat();
145653895Smckusick scsi_hardreset();
145753895Smckusick return;
145853895Smckusick }
145953895Smckusick
146053895Smckusick SET_CMD(SCMD_TR_INFO);
146153895Smckusick sc_datr = sc->sc_message;
146253895Smckusick DMAC_WAIT0;
146353895Smckusick }
146453895Smckusick }
146553895Smckusick
146653895Smckusick /*
146753895Smckusick * SCSI status accept routine
146853895Smckusick */
sc_sin(cs)146953895Smckusick sc_sin(cs)
147053895Smckusick register VOLATILE struct sc_chan_stat *cs;
147153895Smckusick {
147253895Smckusick register VOLATILE int dummy;
147353895Smckusick register int iloop;
147453895Smckusick
147553895Smckusick flush_fifo();
147653895Smckusick
147753895Smckusick dummy = sc_cmonr;
147853895Smckusick DMAC_WAIT0;
147953895Smckusick if ((dummy & R4_MREQ) == 0) {
148053895Smckusick printf("sc_sin: !REQ cmonr=%x\n", dummy);
148153895Smckusick print_scsi_stat();
148253895Smckusick scsi_hardreset();
148353895Smckusick return;
148453895Smckusick }
148553895Smckusick
148653895Smckusick sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE|Rb_RMSG;
148753895Smckusick DMAC_WAIT0;
148853895Smckusick
148953895Smckusick SET_CMD(SCMD_TR_INFO);
149053895Smckusick
149153895Smckusick (void) WAIT_STATR_BITCLR(R0_CIP);
149253895Smckusick
149353895Smckusick int_stat2 &= ~R3_FNC;
149453895Smckusick iloop = 0;
149553895Smckusick do {
149653895Smckusick if (iloop++ > CHECK_LOOP_CNT)
149753895Smckusick break;
149853895Smckusick GET_INTR(&int_stat1, &int_stat2); /* clear interrupt */
149953895Smckusick } while ((int_stat2 & R3_FNC) == 0);
150053895Smckusick int_stat2 &= ~R3_FNC;
150153895Smckusick
150253895Smckusick cs->sc->sc_tstatus = sc_datr; /* get status byte */
150353895Smckusick DMAC_WAIT0;
150453895Smckusick }
150553895Smckusick
150653895Smckusick /*
150753895Smckusick * SCSI data in/out routine
150853895Smckusick */
sc_dio(cs)150953895Smckusick sc_dio(cs)
151053895Smckusick register VOLATILE struct sc_chan_stat *cs;
151153895Smckusick {
151253895Smckusick register VOLATILE struct scsi *sc;
151353895Smckusick register struct scsi_stat *ss;
151453895Smckusick register int i;
151553895Smckusick register int pages;
151653895Smckusick register u_int tag;
151753895Smckusick register u_int pfn;
151853895Smckusick VOLATILE int phase;
151953895Smckusick
152053895Smckusick sc = cs->sc;
152153895Smckusick ss = &scsi_stat;
152253895Smckusick
152353895Smckusick sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE;
152453895Smckusick DMAC_WAIT0;
152553895Smckusick
152653895Smckusick if (cs->act_trcnt <= 0) {
152753895Smckusick sc_dio_pad(cs);
152853895Smckusick return;
152953895Smckusick }
153053895Smckusick
153153895Smckusick switch (sc->sc_opcode) {
153253895Smckusick
153353895Smckusick case SCOP_READ:
153453895Smckusick case SCOP_WRITE:
153553895Smckusick case SCOP_EREAD:
153653895Smckusick case SCOP_EWRITE:
153753895Smckusick i = (cs->act_trcnt + sc->sc_bytesec -1) / sc->sc_bytesec;
153853895Smckusick i *= sc->sc_bytesec;
153953895Smckusick break;
154053895Smckusick
154153895Smckusick default:
154253895Smckusick i = cs->act_trcnt;
154353895Smckusick break;
154453895Smckusick }
154553895Smckusick
154653895Smckusick SET_CNT(i);
154753895Smckusick pad_cnt[cs->chan_num] = i - cs->act_trcnt;
154853895Smckusick
154953895Smckusick phase = sc_cmonr & SC_PMASK;
155053895Smckusick DMAC_WAIT0;
155153895Smckusick if (phase == DAT_IN) {
155253895Smckusick if (sc_syncr == OFF) {
155353895Smckusick DMAC_WAIT0;
155453895Smckusick flush_fifo();
155553895Smckusick }
155653895Smckusick }
155753895Smckusick
155853895Smckusick #if defined(mips) && defined(CPU_SINGLE)
155953895Smckusick SET_CMD(SCMD_TR_INFO|R0_DMA|R0_TRBE);
156053895Smckusick #endif
156153895Smckusick
156253895Smckusick #if defined(mips) && defined(CPU_SINGLE)
156353895Smckusick dmac_gsel = CH_SCSI;
156453895Smckusick dmac_ctrcl = (u_char)(cs->act_trcnt & 0xff);
156553895Smckusick dmac_ctrcm = (u_char)((cs->act_trcnt >> 8) & 0xff);
156653895Smckusick dmac_ctrch = (u_char)((cs->act_trcnt >> 16) & 0x0f);
156753895Smckusick dmac_cofsh = (u_char)((cs->act_offset >> 8) & 0xf);
156853895Smckusick dmac_cofsl = (u_char)(cs->act_offset & 0xff);
156953895Smckusick #endif
157053895Smckusick tag = 0;
157153895Smckusick
157253895Smckusick if (sc->sc_map && (sc->sc_map->mp_pages > 0)) {
157353895Smckusick /*
157453895Smckusick * Set DMAC map entry from map table
157553895Smckusick */
157653895Smckusick pages = sc->sc_map->mp_pages;
157753895Smckusick for (i = cs->act_tag; i < pages; i++) {
157853895Smckusick if ((pfn = sc->sc_map->mp_addr[i]) == 0)
157953895Smckusick panic("SCSI:sc_dma() zero entry");
158053895Smckusick #if defined(mips) && defined(CPU_SINGLE)
158153895Smckusick dmac_gsel = CH_SCSI;
158253895Smckusick dmac_ctag = (u_char)tag++;
158353895Smckusick dmac_cmap = (u_short)pfn;
158453895Smckusick #endif
158553895Smckusick }
158653895Smckusick #ifdef MAP_OVER_ACCESS
158753895Smckusick # if defined(mips) && defined(CPU_SINGLE)
158853895Smckusick dmac_gsel = CH_SCSI;
158953895Smckusick dmac_ctag = (u_char)tag++;
159053895Smckusick dmac_cmap = (u_short)pfn;
159153895Smckusick # endif
159253895Smckusick #endif
159353895Smckusick } else {
159453895Smckusick /*
159553895Smckusick * Set DMAC map entry from logical address
159653895Smckusick */
159753895Smckusick pfn = (u_int)vtophys(cs->act_point) >> PGSHIFT;
159853895Smckusick pages = (cs->act_trcnt >> PGSHIFT) + 2;
159953895Smckusick for (i = 0; i < pages; i++) {
160053895Smckusick #if defined(mips) && defined(CPU_SINGLE)
160153895Smckusick dmac_gsel = CH_SCSI;
160253895Smckusick dmac_ctag = (u_char)tag++;
160353895Smckusick dmac_cmap = (u_short)pfn + i;
160453895Smckusick #endif
160553895Smckusick }
160653895Smckusick }
160753895Smckusick
160853895Smckusick #if defined(mips) && defined(CPU_SINGLE)
160953895Smckusick dmac_gsel = CH_SCSI;
161053895Smckusick dmac_ctag = 0;
161153895Smckusick #endif
161253895Smckusick
161353895Smckusick if (phase == DAT_IN) {
161453895Smckusick ss->dma_stat = SC_DMAC_RD;
161553895Smckusick #if defined(mips) && defined(CPU_SINGLE)
161653895Smckusick /*
161753895Smckusick * auto pad flag is always on
161853895Smckusick */
161953895Smckusick dmac_gsel = CH_SCSI;
162053895Smckusick dmac_cctl = DM_MODE|DM_APAD;
162153895Smckusick DMAC_WAIT;
162253895Smckusick dmac_cctl = DM_MODE|DM_APAD|DM_ENABLE;
162353895Smckusick DMAC_WAIT0;
162453895Smckusick #endif
162553895Smckusick }
162653895Smckusick else if (phase == DAT_OUT) {
162753895Smckusick ss->dma_stat = SC_DMAC_WR;
162853895Smckusick #if defined(mips) && defined(CPU_SINGLE)
162953895Smckusick dmac_gsel = CH_SCSI;
163053895Smckusick dmac_cctl = DM_APAD;
163153895Smckusick DMAC_WAIT;
163253895Smckusick dmac_cctl = DM_APAD|DM_ENABLE;
163353895Smckusick DMAC_WAIT0;
163453895Smckusick #endif
163553895Smckusick /* DMAC start on mem->I/O */
163653895Smckusick }
163753895Smckusick }
163853895Smckusick
163953895Smckusick #define MAX_TR_CNT24 ((1 << 24) -1)
sc_dio_pad(cs)164053895Smckusick sc_dio_pad(cs)
164153895Smckusick register VOLATILE struct sc_chan_stat *cs;
164253895Smckusick {
164353895Smckusick register VOLATILE int phase;
164453895Smckusick register int dummy;
164553895Smckusick
164653895Smckusick if (cs->act_trcnt >= 0)
164753895Smckusick return;
164853895Smckusick pad_start = 1;
164953895Smckusick
165053895Smckusick SET_CNT(MAX_TR_CNT24);
165153895Smckusick SET_CMD(SCMD_TR_PAD|R0_TRBE);
165253895Smckusick dummy = sc_cmonr & SC_PMASK;
165353895Smckusick DMAC_WAIT0;
165453895Smckusick if (dummy == DAT_IN)
165553895Smckusick dummy = sc_datr; /* get data */
165653895Smckusick else
165753895Smckusick sc_datr = 0; /* send data */
165853895Smckusick }
165953895Smckusick
print_scsi_stat()166053895Smckusick print_scsi_stat()
166153895Smckusick {
166253895Smckusick register struct scsi_stat *ss;
166353895Smckusick register VOLATILE int i;
166453895Smckusick int dummy;
166553895Smckusick
166653895Smckusick ss = &scsi_stat;
166753895Smckusick printf("ipc=%d wrc=%d wbc=%d\n", ss->ipc, ss->wrc, ss->wbc);
166853895Smckusick }
166953895Smckusick
167053895Smckusick /*
167153895Smckusick * return 0 if it was done. Or retun TRUE if it is busy.
167253895Smckusick */
sc_busy(chan)167353895Smckusick sc_busy(chan)
167453895Smckusick register int chan;
167553895Smckusick {
167653895Smckusick return ((int)chan_stat[chan].sc);
167753895Smckusick }
167853895Smckusick
167953895Smckusick
168053895Smckusick /*
168153895Smckusick * append channel into Waiting Bus_free queue
168253895Smckusick */
append_wb(cs)168353895Smckusick append_wb(cs)
168453895Smckusick register VOLATILE struct sc_chan_stat *cs;
168553895Smckusick {
168653895Smckusick register int s;
168753895Smckusick
168853895Smckusick s = splclock(); /* inhibit process switch */
168953895Smckusick if (wbq_actf == NULL)
169053895Smckusick wbq_actf = cs;
169153895Smckusick else
169253895Smckusick wbq_actl->wb_next = cs;
169353895Smckusick wbq_actl = cs;
169453895Smckusick cs->sc->sc_istatus = INST_WAIT;
169553895Smckusick scsi_stat.wbc++;
169653895Smckusick splx(s);
169753895Smckusick }
169853895Smckusick
169953895Smckusick /*
170053895Smckusick * get channel from Waiting Bus_free queue
170153895Smckusick */
get_wb_chan()170253895Smckusick get_wb_chan()
170353895Smckusick {
170453895Smckusick register int s;
170553895Smckusick register int chan;
170653895Smckusick
170753895Smckusick s = splclock(); /* inhibit process switch */
170853895Smckusick if (wbq_actf == NULL) {
170953895Smckusick chan = -1;
171053895Smckusick } else {
171153895Smckusick chan = wbq_actf->chan_num;
171253895Smckusick if ((chan < 0) || (chan >= NTARGET) || (chan == SC_OWNID))
171353895Smckusick chan = -1;
171453895Smckusick }
171553895Smckusick splx(s);
171653895Smckusick return (chan);
171753895Smckusick }
171853895Smckusick
171953895Smckusick /*
172053895Smckusick * release channel from Waiting Bus_free queue
172153895Smckusick */
release_wb()172253895Smckusick release_wb()
172353895Smckusick {
172453895Smckusick register VOLATILE struct sc_chan_stat *cs;
172553895Smckusick register int s;
172653895Smckusick int error;
172753895Smckusick
172853895Smckusick s = splclock(); /* inhibit process switch */
172953895Smckusick error = 0;
173053895Smckusick if (wbq_actf == NULL) {
173153895Smckusick error = -1;
173253895Smckusick } else {
173353895Smckusick cs = wbq_actf;
173453895Smckusick wbq_actf = cs->wb_next;
173553895Smckusick cs->wb_next = NULL;
173653895Smckusick if (wbq_actl == cs)
173753895Smckusick wbq_actl = NULL;
173853895Smckusick cs->sc->sc_istatus &= ~INST_WAIT;
173953895Smckusick scsi_stat.wbc--;
174053895Smckusick }
174153895Smckusick splx(s);
174253895Smckusick return (error);
174353895Smckusick }
174453895Smckusick
adjust_transfer(cs)174553895Smckusick adjust_transfer(cs)
174653895Smckusick register struct sc_chan_stat *cs;
174753895Smckusick {
174853895Smckusick register struct scsi *sc;
174953895Smckusick register struct scsi_stat *ss;
175053895Smckusick register VOLATILE u_int remain_cnt;
175153895Smckusick register u_int offset;
175253895Smckusick u_int sent_byte;
175353895Smckusick
175453895Smckusick sc = cs->sc;
175553895Smckusick ss = &scsi_stat;
175653895Smckusick
175753895Smckusick if (pad_start) {
175853895Smckusick pad_start = 0;
175953895Smckusick remain_cnt = 0;
176053895Smckusick } else {
176153895Smckusick # if defined(mips) && defined(CPU_SINGLE)
176253895Smckusick remain_cnt = GET_CNT();
176353895Smckusick remain_cnt -= pad_cnt[cs->chan_num];
176453895Smckusick if (ss->dma_stat == SC_DMAC_WR) {
176553895Smckusick /*
176653895Smckusick * adjust counter in the FIFO
176753895Smckusick */
176853895Smckusick remain_cnt += sc_ffstr & R5_FIFOREM;
176953895Smckusick }
177053895Smckusick # endif
177153895Smckusick }
177253895Smckusick
177353895Smckusick sent_byte = sc->sc_ctrnscnt - remain_cnt;
177453895Smckusick cs->act_trcnt = remain_cnt;
177553895Smckusick
177653895Smckusick offset = sc->sc_coffset + sent_byte;
177753895Smckusick cs->act_tag += (offset >> PGSHIFT);
177853895Smckusick cs->act_offset = offset & PGOFSET;
177953895Smckusick if ((sc->sc_map == NULL) || (sc->sc_map->mp_pages <= 0))
178053895Smckusick cs->act_point += sent_byte;
178153895Smckusick }
1782