1/*	$NetBSD: sii.c,v 1.9 2011/06/04 01:31:23 tsutsui Exp $	*/
2
3/*-
4 * Copyright (c) 1992, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell and Rick Macklem.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 *	@(#)sii.c	8.2 (Berkeley) 11/30/93
35 *
36 * from: Header: /sprite/src/kernel/dev/ds3100.md/RCS/devSII.c,
37 *	v 9.2 89/09/14 13:37:41 jhh Exp $ SPRITE (DECWRL)";
38 */
39
40#include <sys/cdefs.h>
41__KERNEL_RCSID(0, "$NetBSD: sii.c,v 1.9 2011/06/04 01:31:23 tsutsui Exp $");
42
43#include "sii.h"
44/*
45 * SCSI interface driver
46 */
47#include <sys/param.h>
48#include <sys/buf.h>
49#include <sys/conf.h>
50#include <sys/device.h>
51#include <sys/systm.h>
52
53#include <mips/locore.h>
54
55#include <dev/scsipi/scsi_all.h>
56#include <dev/scsipi/scsi_message.h>
57#include <dev/scsipi/scsipi_all.h>
58#include <dev/scsipi/scsipi_disk.h>
59#include <dev/scsipi/scsiconf.h>
60
61/* old 4.4BSD/pmax scsi drivers */
62#include <pmax/ibus/siireg.h>		/* device registers */
63#include <pmax/ibus/siivar.h>		/* softc and prototypes */
64
65#include <pmax/pmax/machdep.h>		/* prom_scsiid prototype */
66
67/* XXX not in dev/scsipi/scsi_message.h */
68#define	MSG_EXT_MODIFY_DATA_PTR		0x00
69
70extern struct cfdriver sii_cd;
71
72/*
73 * MACROS for timing out spin loops.
74 *
75 * Wait until expression is true.
76 *
77 * Control register bits can change at any time so when the CPU
78 * reads a register, the bits might change and
79 * invalidate the setup and hold times for the CPU.
80 * This macro reads the register twice to be sure the value is stable.
81 *
82 *	args:	var 		- variable to save control register contents
83 *		reg		- control register to read
84 *		expr 		- expression to spin on
85 *		spincount 	- maximum number of times through the loop
86 *		cntr		- variable for number of tries
87 */
88#define	SII_WAIT_UNTIL(var, reg, expr, spincount, cntr) {	\
89		u_int tmp = reg;				\
90		for (cntr = 0; cntr < spincount; cntr++) {	\
91			while (tmp != (var = reg))		\
92				tmp = var;			\
93			if (expr)				\
94				break;				\
95			if (cntr >= 100)			\
96				DELAY(100);			\
97		}						\
98	}
99
100#ifdef DEBUG
101int	sii_debug = 1;
102int	sii_debug_cmd;
103int	sii_debug_bn;
104int	sii_debug_sz;
105#define NLOG 16
106struct sii_log {
107	u_short	cstat;
108	u_short	dstat;
109	u_short	comm;
110	u_short	msg;
111	int	rlen;
112	int	dlen;
113	int	target;
114} sii_log[NLOG], *sii_logp = sii_log;
115#endif
116
117static u_char	sii_buf[256];	/* used for extended messages */
118
119#define NORESET	0
120#define RESET	1
121#define NOWAIT	0
122#define WAIT	1
123
124
125/*
126 * Define a safe address in the SCSI buffer for doing status & message DMA
127 * XXX why not add another field to softc?
128 */
129#define SII_BUF_ADDR(sc)	((sc)->sc_buf + SII_MAX_DMA_XFER_LENGTH * 14)
130
131/*
132 * Forward references
133 */
134
135static void	sii_Reset(struct siisoftc *sc, int resetbus);
136static void	sii_StartCmd(struct siisoftc *sc, int target);
137static void	sii_CmdDone(struct siisoftc *sc, int target, int error);
138static void	sii_DoIntr(struct siisoftc *sc, u_int dstat);
139static void	sii_StateChg(struct siisoftc *sc, u_int cstat);
140static int	sii_GetByte(SIIRegs *regs, int phase, int ack);
141static void	sii_DoSync(SIIRegs *regs, State *state);
142static void	sii_StartDMA(SIIRegs *regs, int phase, u_short *dmaAddr,
143				  int size);
144
145#ifdef DEBUG
146static void	sii_DumpLog(void);
147#endif
148
149
150/*
151 * Match driver based on name
152 */
153void
154siiattach(struct siisoftc *sc)
155{
156	int i;
157
158	sc->sc_target = -1;	/* no command active */
159
160	/*
161	 * Give each target its own DMA buffer region.
162	 * Make it big enough for 2 max transfers so we can ping pong buffers
163	 * while we copy the data.
164	 */
165	for (i = 0; i < SII_NCMD; i++) {
166		sc->sc_st[i].dmaAddr[0] = (u_short *)
167			sc->sc_buf + 2 * SII_MAX_DMA_XFER_LENGTH * i;
168		sc->sc_st[i].dmaAddr[1] = sc->sc_st[i].dmaAddr[0] +
169			SII_MAX_DMA_XFER_LENGTH;
170	}
171
172	sii_Reset(sc, RESET);
173	printf(": target %d\n", sc->sc_regs->id & SII_IDMSK);
174
175	sc->sc_adapter.adapt_dev = sc->sc_dev;
176	sc->sc_adapter.adapt_nchannels = 1;
177	sc->sc_adapter.adapt_openings = 7;
178	sc->sc_adapter.adapt_max_periph = 1;
179	sc->sc_adapter.adapt_ioctl = NULL;
180	sc->sc_adapter.adapt_minphys = minphys;
181	sc->sc_adapter.adapt_request = sii_scsi_request;
182
183	sc->sc_channel.chan_adapter = &sc->sc_adapter;
184	sc->sc_channel.chan_bustype = &scsi_bustype;
185	sc->sc_channel.chan_channel = 0;
186	sc->sc_channel.chan_ntargets = 8;
187	sc->sc_channel.chan_nluns = 8;
188	sc->sc_channel.chan_id = sc->sc_regs->id & SII_IDMSK;
189
190
191	/*
192	 * Now try to attach all the sub-devices
193	 */
194	config_found(sc->sc_dev, &sc->sc_channel, scsiprint);
195}
196
197/*
198 * Start activity on a SCSI device.
199 * We maintain information on each device separately since devices can
200 * connect/disconnect during an operation.
201 */
202
203void
204sii_scsi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, void *arg)
205{
206	struct scsipi_xfer *xs;
207	struct scsipi_periph *periph;
208	struct siisoftc *sc;
209	int target;
210	int s;
211	int count;
212
213	sc = device_private(chan->chan_adapter->adapt_dev);
214
215	switch (req) {
216	case ADAPTER_REQ_RUN_XFER:
217		xs = arg;
218		periph = xs->xs_periph;
219		target = periph->periph_target;
220		s = splbio();
221		if (sc->sc_cmd[target]) {
222			splx(s);
223			xs->error = XS_RESOURCE_SHORTAGE;
224			scsipi_done(xs);
225			printf("[busy at start]\n");
226			return;
227		}
228		/*
229		 * Build a ScsiCmd for this command and start it.
230		 */
231		sc->sc_xs[target] = xs;
232		sc->sc_cmd[target] = &sc->sc_cmd_fake[target];	/* XXX */
233		sc->sc_cmd[target]->unit = 0;
234		sc->sc_cmd[target]->flags = 0;
235		sc->sc_cmd[target]->buflen = xs->datalen;
236		sc->sc_cmd[target]->buf = xs->data;
237		sc->sc_cmd[target]->cmdlen = xs->cmdlen;
238		sc->sc_cmd[target]->cmd = (u_char *)xs->cmd;
239		sc->sc_cmd[target]->lun = xs->xs_periph->periph_lun;
240		sii_StartCmd(sc, target);
241		splx(s);
242		if ((xs->xs_control & XS_CTL_POLL) == 0)
243			return;
244		count = xs->timeout;
245		while (count) {
246			if ((xs->xs_status & XS_STS_DONE) != 0)
247				return;
248			siiintr(sc);
249			/* XXX schedule another command? */
250			DELAY(1000);
251			--count;
252		}
253		xs->error = XS_TIMEOUT;
254		scsipi_done(xs);
255		return;
256	case ADAPTER_REQ_GROW_RESOURCES:
257		/* XXX Not supported. */
258		return;
259
260	case ADAPTER_REQ_SET_XFER_MODE:
261		/* XXX Not supported. */
262		return;
263	}
264}
265
266/*
267 * Check to see if any SII chips have pending interrupts
268 * and process as appropriate.
269 */
270int
271siiintr(void *xxxsc)
272{
273	struct siisoftc *sc = xxxsc;
274	u_int dstat;
275
276	/*
277	 * Find which controller caused the interrupt.
278	 */
279	dstat = sc->sc_regs->dstat;
280	if (dstat & (SII_CI | SII_DI)) {
281		sii_DoIntr(sc, dstat);
282		return (0);	/* XXX */
283	}
284
285	return (1);		/* XXX spurious interrupt? */
286}
287
288/*
289 * Reset the SII chip and do a SCSI reset if 'reset' is true.
290 * NOTE: if !cold && reset, should probably probe for devices
291 * since a SCSI bus reset will set UNIT_ATTENTION.
292 */
293static void
294sii_Reset(struct siisoftc* sc, int reset)
295	/* reset:				 TRUE => reset SCSI bus */
296{
297	SIIRegs *regs = sc->sc_regs;
298
299#ifdef DEBUG
300	if (sii_debug > 1)
301		printf("sii: RESET\n");
302#endif
303	/*
304	 * Reset the SII chip.
305	 */
306	regs->comm = SII_CHRESET;
307	/*
308	 * Set arbitrated bus mode.
309	 */
310	regs->csr = SII_HPM;
311	/*
312	 * Set host adapter ID (from PROM sciiidN variable).
313	 */
314	/* XXX device_unit() abuse */
315	regs->id = SII_ID_IO | prom_scsiid(device_unit(sc->sc_dev));
316	/*
317	 * Enable SII to drive the SCSI bus.
318	 */
319	regs->dictrl = SII_PRE;
320	regs->dmctrl = 0;
321
322	if (reset) {
323		int i;
324
325		/*
326		 * Assert SCSI bus reset for at least 25 Usec to clear the
327		 * world. SII_DO_RST is self clearing.
328		 * Delay 250 ms before doing any commands.
329		 */
330		regs->comm = SII_DO_RST;
331		wbflush();
332		DELAY(250000);
333
334		/* rearbitrate synchronous offset */
335		for (i = 0; i < SII_NCMD; i++)
336			sc->sc_st[i].dmaReqAck = 0;
337	}
338
339	/*
340	 * Clear any pending interrupts from the reset.
341	 */
342	regs->cstat = regs->cstat;
343	regs->dstat = regs->dstat;
344	/*
345	 * Set up SII for arbitrated bus mode, SCSI parity checking,
346	 * Reselect Enable, and Interrupt Enable.
347	 */
348	regs->csr = SII_HPM | SII_RSE | SII_PCE | SII_IE;
349	wbflush();
350}
351
352/*
353 * Start a SCSI command by sending the cmd data
354 * to a SCSI controller via the SII.
355 * Call the device done proceedure if it can't be started.
356 * NOTE: we should be called with interrupts disabled.
357 */
358static void
359sii_StartCmd(struct siisoftc *sc, int target)
360	/* sc:	 which SII to use */
361	/* target:		 which command to start */
362{
363	SIIRegs *regs;
364	ScsiCmd *scsicmd;
365	State *state;
366	u_int status;
367	int error, retval;
368
369	/* if another command is currently in progress, just wait */
370	if (sc->sc_target >= 0)
371		return;
372
373	/* initialize state information for this command */
374	scsicmd = sc->sc_cmd[target];
375	state = &sc->sc_st[target];
376	state->flags = FIRST_DMA;
377	state->prevComm = 0;
378	state->dmalen = 0;
379	state->dmaCurPhase = -1;
380	state->dmaPrevPhase = -1;
381	state->dmaBufIndex = 0;
382	state->cmd = scsicmd->cmd;
383	state->cmdlen = scsicmd->cmdlen;
384	if ((state->buflen = scsicmd->buflen) == 0) {
385		state->dmaDataPhase = -1; /* illegal phase. shouldn't happen */
386		state->buf = (char *)0;
387	} else {
388		state->buf = scsicmd->buf;
389	}
390
391#ifdef DEBUG
392	if (sii_debug > 1) {
393		printf("sii_StartCmd: %s target %d cmd 0x%x addr %p size %d DMA %d\n",
394		    device_xname(sc->sc_dev),
395		    target, scsicmd->cmd[0], scsicmd->buf, scsicmd->buflen,
396		    state->dmaDataPhase);
397	}
398	sii_debug_cmd = scsicmd->cmd[0];
399	if (scsicmd->cmd[0] == READ_10 ||
400	    scsicmd->cmd[0] == WRITE_10) {
401		sii_debug_bn = (scsicmd->cmd[2] << 24) |
402			(scsicmd->cmd[3] << 16) |
403			(scsicmd->cmd[4] << 8) |
404			scsicmd->cmd[5];
405		sii_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8];
406	} else {
407		sii_debug_bn = 0;
408		sii_debug_sz = 0;
409	}
410#endif
411
412	/* try to select the target */
413	regs = sc->sc_regs;
414
415	/*
416	 * Another device may have selected us; in which case,
417	 * this command will be restarted later.
418	 */
419	if ((status = regs->dstat) & (SII_CI | SII_DI)) {
420		sii_DoIntr(sc, status);
421		return;
422	}
423
424	sc->sc_target = target;
425#if 0
426	/* seem to have problems with synchronous transfers */
427	if (scsicmd->flags & SCSICMD_USE_SYNC) {
428		printf("sii_StartCmd: doing extended msg\n"); /* XXX */
429		/*
430		 * Setup to send both the identify message and the synchronous
431		 * data transfer request.
432		 */
433		sii_buf[0] = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG;
434		sii_buf[1] = MSG_EXTENDED;
435		sii_buf[2] = MSG_EXT_SDTR_LEN;
436		sii_buf[3] = MSG_EXT_SDTR;
437		sii_buf[4] = 0;
438		sii_buf[5] = 3;		/* maximum SII chip supports */
439
440		state->dmaCurPhase = SII_MSG_OUT_PHASE,
441		state->dmalen = 6;
442		sc->sii_copytobuf((u_short *)sii_buf,
443			(volatile u_short *)SII_BUF_ADDR(sc), 6);
444		regs->slcsr = target;
445		regs->dmctrl = state->dmaReqAck;
446		regs->dmaddrl = (u_short)(SII_BUF_ADDR(sc) >> 1);
447		regs->dmaddrh = (u_short)(SII_BUF_ADDR(sc) >> 17) & 03;
448		regs->dmlotc = 6;
449		regs->comm = SII_DMA | SII_INXFER | SII_SELECT | SII_ATN |
450			SII_CON | SII_MSG_OUT_PHASE;
451	} else
452#endif
453	{
454		/* do a chained, select with ATN and programmed I/O command */
455		regs->data = MSG_IDENTIFYFLAG | MSG_IDENTIFY_DISCFLAG |
456		    scsicmd->lun;
457		regs->slcsr = target;
458		regs->dmctrl = state->dmaReqAck;
459		regs->comm = SII_INXFER | SII_SELECT | SII_ATN | SII_CON |
460			SII_MSG_OUT_PHASE;
461	}
462	wbflush();
463
464	/*
465	 * Wait for something to happen
466	 * (should happen soon or we would use interrupts).
467	 */
468	SII_WAIT_UNTIL(status, regs->cstat, status & (SII_CI | SII_DI),
469		SII_WAIT_COUNT/4, retval);
470
471	/* check to see if we are connected OK */
472	if ((status & (SII_RST | SII_SCH | SII_STATE_MSK)) ==
473	    (SII_SCH | SII_CON)) {
474		regs->cstat = status;
475		wbflush();
476
477#ifdef DEBUG
478		sii_logp->target = target;
479		sii_logp->cstat = status;
480		sii_logp->dstat = 0;
481		sii_logp->comm = regs->comm;
482		sii_logp->msg = -1;
483		sii_logp->rlen = state->buflen;
484		sii_logp->dlen = state->dmalen;
485		if (++sii_logp >= &sii_log[NLOG])
486			sii_logp = sii_log;
487#endif
488
489		/* wait a short time for command phase */
490		SII_WAIT_UNTIL(status, regs->dstat, status & SII_MIS,
491			SII_WAIT_COUNT, retval);
492#ifdef DEBUG
493		if (sii_debug > 2)
494			printf("sii_StartCmd: ds %x cnt %d\n", status, retval);
495#endif
496		if ((status & (SII_CI | SII_MIS | SII_PHASE_MSK)) !=
497		    (SII_MIS | SII_CMD_PHASE)) {
498			printf("sii_StartCmd: timeout cs %x ds %x cnt %d\n",
499				regs->cstat, status, retval); /* XXX */
500			/* process interrupt or continue until it happens */
501			if (status & (SII_CI | SII_DI))
502				sii_DoIntr(sc, status);
503			return;
504		}
505		regs->dstat = SII_DNE;	/* clear Msg Out DMA done */
506
507		/* send command data */
508		sc->sii_copytobuf((u_short *)state->cmd,
509			(volatile u_short *)state->dmaAddr[0], state->cmdlen);
510		sii_StartDMA(regs, state->dmaCurPhase = SII_CMD_PHASE,
511			state->dmaAddr[0], state->dmalen = scsicmd->cmdlen);
512
513		/* wait a little while for DMA to finish */
514		SII_WAIT_UNTIL(status, regs->dstat, status & (SII_CI | SII_DI),
515			SII_WAIT_COUNT, retval);
516#ifdef DEBUG
517		if (sii_debug > 2)
518			printf("sii_StartCmd: ds %x, cnt %d\n", status, retval);
519#endif
520		if (status & (SII_CI | SII_DI))
521			sii_DoIntr(sc, status);
522#ifdef DEBUG
523		if (sii_debug > 2)
524			printf("sii_StartCmd: DONE ds %x\n", regs->dstat);
525#endif
526		return;
527	}
528
529	/*
530	 * Another device may have selected us; in which case,
531	 * this command will be restarted later.
532	 */
533	if (status & (SII_CI | SII_DI)) {
534		sii_DoIntr(sc, regs->dstat);
535		return;
536	}
537
538	/*
539	 * Disconnect if selection command still in progress.
540	 */
541	if (status & SII_SIP) {
542		error = ENXIO;	/* device didn't respond */
543		regs->comm = SII_DISCON;
544		wbflush();
545		SII_WAIT_UNTIL(status, regs->cstat,
546			!(status & (SII_CON | SII_SIP)),
547			SII_WAIT_COUNT, retval);
548	} else
549		error = EBUSY;	/* couldn't get the bus */
550#ifdef DEBUG
551	if (sii_debug > 1)
552		printf("sii_StartCmd: Couldn't select target %d error %d\n",
553			target, error);
554#endif
555	sc->sc_target = -1;
556	regs->cstat = 0xffff;
557	regs->dstat = 0xffff;
558	regs->comm = 0;
559	wbflush();
560	sii_CmdDone(sc, target, error);
561}
562
563/*
564 * Process interrupt conditions.
565 */
566static void
567sii_DoIntr(struct siisoftc *sc, u_int dstat)
568{
569	SIIRegs *regs = sc->sc_regs;
570	State *state;
571	u_int cstat;
572	int i, msg;
573	u_int comm;
574
575again:
576	comm = regs->comm;
577
578#ifdef DEBUG
579	if (sii_debug > 3)
580		printf("sii_DoIntr: cs %x, ds %x cm %x ",
581			regs->cstat, dstat, comm);
582	sii_logp->target = sc->sc_target;
583	sii_logp->cstat = regs->cstat;
584	sii_logp->dstat = dstat;
585	sii_logp->comm = comm;
586	sii_logp->msg = -1;
587	if (sc->sc_target >= 0) {
588		sii_logp->rlen = sc->sc_st[sc->sc_target].buflen;
589		sii_logp->dlen = sc->sc_st[sc->sc_target].dmalen;
590	} else {
591		sii_logp->rlen = 0;
592		sii_logp->dlen = 0;
593	}
594	if (++sii_logp >= &sii_log[NLOG])
595		sii_logp = sii_log;
596#endif
597
598	regs->dstat = dstat;	/* acknowledge everything */
599	wbflush();
600
601	if (dstat & SII_CI) {
602		/* deglitch cstat register */
603		msg = regs->cstat;
604		while (msg != (cstat = regs->cstat))
605			msg = cstat;
606		regs->cstat = cstat;	/* acknowledge everything */
607		wbflush();
608#ifdef DEBUG
609		if (sii_logp > sii_log)
610			sii_logp[-1].cstat = cstat;
611		else
612			sii_log[NLOG - 1].cstat = cstat;
613#endif
614
615		/* check for a BUS RESET */
616		if (cstat & SII_RST) {
617			printf("%s: SCSI bus reset!!\n",
618			    device_xname(sc->sc_dev));
619			/* need to flush disconnected commands */
620			for (i = 0; i < SII_NCMD; i++) {
621				if (!sc->sc_cmd[i])
622					continue;
623				sii_CmdDone(sc, i, EIO);
624			}
625			/* rearbitrate synchronous offset */
626			for (i = 0; i < SII_NCMD; i++)
627				sc->sc_st[i].dmaReqAck = 0;
628			sc->sc_target = -1;
629			return;
630		}
631
632#ifdef notdef
633		/*
634		 * Check for a BUS ERROR.
635		 * According to DEC, this feature doesn't really work
636		 * and to just clear the bit if it's set.
637		 */
638		if (cstat & SII_BER) {
639			regs->cstat = SII_BER;
640			wbflush();
641		}
642#endif
643
644		/* check for state change */
645		if (cstat & SII_SCH) {
646			sii_StateChg(sc, cstat);
647			comm = regs->comm;
648		}
649	}
650
651	/* check for DMA completion */
652	if (dstat & SII_DNE) {
653		u_short *dma;
654		char *buf;
655
656		/*
657		 * There is a race condition with SII_SCH. There is a short
658		 * window between the time a SII_SCH is seen after a disconnect
659		 * and when the SII_SCH is cleared. A reselect can happen
660		 * in this window and we will clear the SII_SCH without
661		 * processing the reconnect.
662		 */
663		if (sc->sc_target < 0) {
664			cstat = regs->cstat;
665			printf("%s: target %d DNE?? dev %d,%d cs %x\n",
666			    device_xname(sc->sc_dev), sc->sc_target,
667			    regs->slcsr, regs->destat,
668			    cstat); /* XXX */
669			if (cstat & SII_DST) {
670				sc->sc_target = regs->destat;
671				state = &sc->sc_st[sc->sc_target];
672				state->prevComm = 0;
673			} else
674				panic("sc_target 1");
675		}
676		state = &sc->sc_st[sc->sc_target];
677		/* check for a PARITY ERROR */
678		if (dstat & SII_IPE) {
679			state->flags |= PARITY_ERR;
680			printf("%s: Parity error!!\n",
681			    device_xname(sc->sc_dev));
682			goto abort;
683		}
684		/* dmalen = amount left to transfer, i = amount transfered */
685		i = state->dmalen;
686		state->dmalen = 0;
687		state->dmaCurPhase = -1;
688#ifdef DEBUG
689		if (sii_debug > 4) {
690			printf("DNE: amt %d ", i);
691			if (!(dstat & SII_TCZ))
692				printf("no TCZ?? (%d) ", regs->dmlotc);
693		} else if (!(dstat & SII_TCZ)) {
694			printf("%s: device %d: no TCZ?? (%d)\n",
695			    device_xname(sc->sc_dev),
696			    sc->sc_target, regs->dmlotc);
697			sii_DumpLog(); /* XXX */
698		}
699#endif
700		switch (comm & SII_PHASE_MSK) {
701		case SII_CMD_PHASE:
702			state->cmdlen -= i;
703			break;
704
705		case SII_DATA_IN_PHASE:
706			/* check for more data for the same phase */
707			dma = state->dmaAddr[state->dmaBufIndex];
708			buf = state->buf;
709			state->buf += i;
710			state->buflen -= i;
711			if (state->buflen > 0 && !(dstat & SII_MIS)) {
712				int len;
713
714				/* start reading next chunk */
715				len = state->buflen;
716				if (len > SII_MAX_DMA_XFER_LENGTH)
717					len = SII_MAX_DMA_XFER_LENGTH;
718				state->dmaBufIndex = !state->dmaBufIndex;
719				sii_StartDMA(regs,
720					state->dmaCurPhase = SII_DATA_IN_PHASE,
721					state->dmaAddr[state->dmaBufIndex],
722					state->dmaCnt = state->dmalen = len);
723				dstat &= ~(SII_IBF | SII_TBE);
724			}
725			/* copy in the data */
726			sc->sii_copyfrombuf((volatile u_short *)dma, buf, i);
727			break;
728
729		case SII_DATA_OUT_PHASE:
730			state->dmaBufIndex = !state->dmaBufIndex;
731			state->buf += i;
732			state->buflen -= i;
733
734			/* check for more data for the same phase */
735			if (state->buflen <= 0 || (dstat & SII_MIS))
736				break;
737
738			/* start next chunk */
739			i = state->buflen;
740			if (i > SII_MAX_DMA_XFER_LENGTH) {
741				sii_StartDMA(regs, state->dmaCurPhase =
742					SII_DATA_OUT_PHASE,
743					state->dmaAddr[state->dmaBufIndex],
744					state->dmaCnt = state->dmalen =
745					SII_MAX_DMA_XFER_LENGTH);
746				/* prepare for next chunk */
747				i -= SII_MAX_DMA_XFER_LENGTH;
748				if (i > SII_MAX_DMA_XFER_LENGTH)
749					i = SII_MAX_DMA_XFER_LENGTH;
750				sc->sii_copytobuf((u_short *)(state->buf +
751					SII_MAX_DMA_XFER_LENGTH),
752					(volatile u_short *)
753					state->dmaAddr[!state->dmaBufIndex], i);
754			} else {
755				sii_StartDMA(regs, state->dmaCurPhase =
756					SII_DATA_OUT_PHASE,
757					state->dmaAddr[state->dmaBufIndex],
758					state->dmaCnt = state->dmalen = i);
759			}
760			dstat &= ~(SII_IBF | SII_TBE);
761		}
762	}
763
764	/* check for phase change or another MsgIn/Out */
765	if (dstat & (SII_MIS | SII_IBF | SII_TBE)) {
766		/*
767		 * There is a race condition with SII_SCH. There is a short
768		 * window between the time a SII_SCH is seen after a disconnect
769		 * and when the SII_SCH is cleared. A reselect can happen
770		 * in this window and we will clear the SII_SCH without
771		 * processing the reconnect.
772		 */
773		if (sc->sc_target < 0) {
774			cstat = regs->cstat;
775			printf("%s: target %d MIS?? dev %d,%d cs %x ds %x\n",
776			    device_xname(sc->sc_dev), sc->sc_target,
777			    regs->slcsr, regs->destat,
778			    cstat, dstat); /* XXX */
779			if (cstat & SII_DST) {
780				sc->sc_target = regs->destat;
781				state = &sc->sc_st[sc->sc_target];
782				state->prevComm = 0;
783			} else {
784#ifdef DEBUG
785				sii_DumpLog();
786#endif
787				panic("sc_target 2");
788			}
789		}
790		state = &sc->sc_st[sc->sc_target];
791		switch (dstat & SII_PHASE_MSK) {
792		case SII_CMD_PHASE:
793			if (state->dmaPrevPhase >= 0) {
794				/* restart DMA after disconnect/reconnect */
795				if (state->dmaPrevPhase != SII_CMD_PHASE) {
796					printf("%s: device %d: DMA reselect phase doesn't match\n",
797					    device_xname(sc->sc_dev),
798					    sc->sc_target);
799					goto abort;
800				}
801				state->dmaCurPhase = SII_CMD_PHASE;
802				state->dmaPrevPhase = -1;
803				regs->dmaddrl = state->dmaAddrL;
804				regs->dmaddrh = state->dmaAddrH;
805				regs->dmlotc = state->dmaCnt;
806				if (state->dmaCnt & 1)
807					regs->dmabyte = state->dmaByte;
808				regs->comm = SII_DMA | SII_INXFER |
809					(comm & SII_STATE_MSK) | SII_CMD_PHASE;
810				wbflush();
811#ifdef DEBUG
812				if (sii_debug > 4)
813					printf("Cmd dcnt %d dadr %x ",
814						state->dmaCnt,
815						(state->dmaAddrH << 16) |
816							state->dmaAddrL);
817#endif
818			} else {
819				/* send command data */
820				i = state->cmdlen;
821				if (i == 0) {
822					printf("%s: device %d: cmd count exceeded\n",
823					    device_xname(sc->sc_dev),
824					    sc->sc_target);
825					goto abort;
826				}
827				sc->sii_copytobuf((u_short *)state->cmd,
828					(volatile u_short *)state->dmaAddr[0],
829					i);
830				sii_StartDMA(regs, state->dmaCurPhase =
831					SII_CMD_PHASE, state->dmaAddr[0],
832					state->dmaCnt = state->dmalen = i);
833			}
834			/* wait a short time for XFER complete */
835			SII_WAIT_UNTIL(dstat, regs->dstat,
836				dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
837			if (dstat & (SII_CI | SII_DI)) {
838#ifdef DEBUG
839				if (sii_debug > 4)
840					printf("cnt %d\n", i);
841				else if (sii_debug > 0)
842					printf("sii_DoIntr: cmd wait ds %x cnt %d\n",
843						dstat, i);
844#endif
845				goto again;
846			}
847			break;
848
849		case SII_DATA_IN_PHASE:
850		case SII_DATA_OUT_PHASE:
851			if (state->cmdlen > 0) {
852				printf("%s: device %d: cmd %x: command data not all sent (%d) 1\n",
853				    device_xname(sc->sc_dev), sc->sc_target,
854				    sc->sc_cmd[sc->sc_target]->cmd[0],
855				    state->cmdlen);
856				state->cmdlen = 0;
857#ifdef DEBUG
858				sii_DumpLog();
859#endif
860			}
861			if (state->dmaPrevPhase >= 0) {
862				/* restart DMA after disconnect/reconnect */
863				if (state->dmaPrevPhase !=
864				    (dstat & SII_PHASE_MSK)) {
865					printf("%s: device %d: DMA reselect phase doesn't match\n",
866					    device_xname(sc->sc_dev),
867					    sc->sc_target);
868					goto abort;
869				}
870				state->dmaCurPhase = state->dmaPrevPhase;
871				state->dmaPrevPhase = -1;
872				regs->dmaddrl = state->dmaAddrL;
873				regs->dmaddrh = state->dmaAddrH;
874				regs->dmlotc = state->dmaCnt;
875				if (state->dmaCnt & 1)
876					regs->dmabyte = state->dmaByte;
877				regs->comm = SII_DMA | SII_INXFER |
878					(comm & SII_STATE_MSK) |
879					state->dmaCurPhase;
880				wbflush();
881#ifdef DEBUG
882				if (sii_debug > 4)
883					printf("Data %d dcnt %d dadr %x ",
884						state->dmaDataPhase,
885						state->dmaCnt,
886						(state->dmaAddrH << 16) |
887							state->dmaAddrL);
888#endif
889				break;
890			}
891#ifdef DEBUG
892			if (sii_debug > 4) {
893				printf("Data %d ", state->dmaDataPhase);
894				if (sii_debug > 5)
895					printf("\n");
896			}
897#endif
898			i = state->buflen;
899			if (i == 0) {
900				printf("%s: device %d: data count exceeded\n",
901				    device_xname(sc->sc_dev), sc->sc_target);
902				goto abort;
903			}
904			if (i > SII_MAX_DMA_XFER_LENGTH)
905				i = SII_MAX_DMA_XFER_LENGTH;
906			if ((dstat & SII_PHASE_MSK) == SII_DATA_IN_PHASE) {
907				sii_StartDMA(regs,
908					state->dmaCurPhase = SII_DATA_IN_PHASE,
909					state->dmaAddr[state->dmaBufIndex],
910					state->dmaCnt = state->dmalen = i);
911				break;
912			}
913			/* start first chunk */
914			if (state->flags & FIRST_DMA) {
915				state->flags &= ~FIRST_DMA;
916				sc->sii_copytobuf((u_short *)state->buf,
917					(volatile u_short *)
918					state->dmaAddr[state->dmaBufIndex], i);
919			}
920			sii_StartDMA(regs,
921				state->dmaCurPhase = SII_DATA_OUT_PHASE,
922				state->dmaAddr[state->dmaBufIndex],
923				state->dmaCnt = state->dmalen = i);
924			i = state->buflen - SII_MAX_DMA_XFER_LENGTH;
925			if (i > 0) {
926				/* prepare for next chunk */
927				if (i > SII_MAX_DMA_XFER_LENGTH)
928					i = SII_MAX_DMA_XFER_LENGTH;
929				sc->sii_copytobuf((u_short *)(state->buf +
930					SII_MAX_DMA_XFER_LENGTH),
931					(volatile u_short *)
932					state->dmaAddr[!state->dmaBufIndex], i);
933			}
934			break;
935
936		case SII_STATUS_PHASE:
937			if (state->cmdlen > 0) {
938				printf("%s: device %d: cmd %x: command data not all sent (%d) 2\n",
939				    device_xname(sc->sc_dev), sc->sc_target,
940				    sc->sc_cmd[sc->sc_target]->cmd[0],
941				    state->cmdlen);
942				state->cmdlen = 0;
943#ifdef DEBUG
944				sii_DumpLog();
945#endif
946			}
947
948			/* read amount transfered if DMA didn't finish */
949			if (state->dmalen > 0) {
950				i = state->dmalen - regs->dmlotc;
951				state->dmalen = 0;
952				state->dmaCurPhase = -1;
953				regs->dmlotc = 0;
954				regs->comm = comm &
955					(SII_STATE_MSK | SII_PHASE_MSK);
956				wbflush();
957				regs->dstat = SII_DNE;
958				wbflush();
959#ifdef DEBUG
960				if (sii_debug > 4)
961					printf("DMA amt %d ", i);
962#endif
963				switch (comm & SII_PHASE_MSK) {
964				case SII_DATA_IN_PHASE:
965					/* copy in the data */
966					sc->sii_copyfrombuf((volatile u_short*)
967					    state->dmaAddr[state->dmaBufIndex],
968					    state->buf, i);
969
970				case SII_CMD_PHASE:
971				case SII_DATA_OUT_PHASE:
972					state->buflen -= i;
973				}
974			}
975
976			/* read a one byte status message */
977			state->statusByte = msg =
978				sii_GetByte(regs, SII_STATUS_PHASE, 1);
979			if (msg < 0) {
980				dstat = regs->dstat;
981				goto again;
982			}
983#ifdef DEBUG
984			if (sii_debug > 4)
985				printf("Status %x ", msg);
986			if (sii_logp > sii_log)
987				sii_logp[-1].msg = msg;
988			else
989				sii_log[NLOG - 1].msg = msg;
990#endif
991
992			/* do a quick wait for COMMAND_COMPLETE */
993			SII_WAIT_UNTIL(dstat, regs->dstat,
994				dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
995			if (dstat & (SII_CI | SII_DI)) {
996#ifdef DEBUG
997				if (sii_debug > 4)
998					printf("cnt2 %d\n", i);
999#endif
1000				goto again;
1001			}
1002			break;
1003
1004		case SII_MSG_IN_PHASE:
1005			/*
1006			 * Save DMA state if DMA didn't finish.
1007			 * Be careful not to save state again after reconnect
1008			 * and see RESTORE_POINTER message.
1009			 * Note that the SII DMA address is not incremented
1010			 * as DMA proceeds.
1011			 */
1012			if (state->dmaCurPhase >= 0) {
1013				/* save DMA registers */
1014				state->dmaPrevPhase = state->dmaCurPhase;
1015				state->dmaCurPhase = -1;
1016				if (dstat & SII_OBB)
1017					state->dmaByte = regs->dmabyte;
1018				i = regs->dmlotc;
1019				if (i != 0)
1020					i = state->dmaCnt - i;
1021				/* note: no carry from dmaddrl to dmaddrh */
1022				state->dmaAddrL = regs->dmaddrl + i;
1023				state->dmaAddrH = regs->dmaddrh;
1024				state->dmaCnt = regs->dmlotc;
1025				if (state->dmaCnt == 0)
1026					state->dmaCnt = SII_MAX_DMA_XFER_LENGTH;
1027				regs->comm = comm &
1028					(SII_STATE_MSK | SII_PHASE_MSK);
1029				wbflush();
1030				regs->dstat = SII_DNE;
1031				wbflush();
1032#ifdef DEBUG
1033				if (sii_debug > 4) {
1034					printf("SavP dcnt %d dadr %x ",
1035						state->dmaCnt,
1036						(state->dmaAddrH << 16) |
1037						state->dmaAddrL);
1038					if (((dstat & SII_OBB) != 0) ^
1039					    (state->dmaCnt & 1))
1040						printf("OBB??? ");
1041				} else if (sii_debug > 0) {
1042					if (((dstat & SII_OBB) != 0) ^
1043					    (state->dmaCnt & 1)) {
1044						printf("sii_DoIntr: OBB??? ds %x cnt %d\n",
1045							dstat, state->dmaCnt);
1046						sii_DumpLog();
1047					}
1048				}
1049#endif
1050			}
1051
1052			/* read a one byte message */
1053			msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 0);
1054			if (msg < 0) {
1055				dstat = regs->dstat;
1056				goto again;
1057			}
1058#ifdef DEBUG
1059			if (sii_debug > 4)
1060				printf("MsgIn %x ", msg);
1061			if (sii_logp > sii_log)
1062				sii_logp[-1].msg = msg;
1063			else
1064				sii_log[NLOG - 1].msg = msg;
1065#endif
1066
1067			/* process message */
1068			switch (msg) {
1069			case MSG_CMDCOMPLETE:
1070				/* acknowledge last byte */
1071				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1072					(comm & SII_STATE_MSK);
1073				SII_WAIT_UNTIL(dstat, regs->dstat,
1074					dstat & SII_DNE, SII_WAIT_COUNT, i);
1075				regs->dstat = SII_DNE;
1076				wbflush();
1077				msg = sc->sc_target;
1078				sc->sc_target = -1;
1079				/*
1080				 * Wait a short time for disconnect.
1081				 * Don't be fooled if SII_BER happens first.
1082				 * Note: a reselect may happen here.
1083				 */
1084				SII_WAIT_UNTIL(cstat, regs->cstat,
1085					cstat & (SII_RST | SII_SCH),
1086					SII_WAIT_COUNT, i);
1087				if ((cstat & (SII_RST | SII_SCH |
1088				    SII_STATE_MSK)) == SII_SCH) {
1089					regs->cstat = SII_SCH | SII_BER;
1090					regs->comm = 0;
1091					wbflush();
1092					/*
1093					 * Double check that we didn't miss a
1094					 * state change between seeing it and
1095					 * clearing the SII_SCH bit.
1096					 */
1097					i = regs->cstat;
1098					if (!(i & SII_SCH) &&
1099					    (i & SII_STATE_MSK) !=
1100					    (cstat & SII_STATE_MSK))
1101						sii_StateChg(sc, i);
1102				}
1103#ifdef DEBUG
1104				if (sii_debug > 4)
1105					printf("cs %x\n", cstat);
1106#endif
1107				sii_CmdDone(sc, msg, 0);
1108				break;
1109
1110			case MSG_EXTENDED:
1111				/* acknowledge last byte */
1112				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1113					(comm & SII_STATE_MSK);
1114				SII_WAIT_UNTIL(dstat, regs->dstat,
1115					dstat & SII_DNE, SII_WAIT_COUNT, i);
1116				regs->dstat = SII_DNE;
1117				wbflush();
1118				/* read the message length */
1119				msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 1);
1120				if (msg < 0) {
1121					dstat = regs->dstat;
1122					goto again;
1123				}
1124				sii_buf[1] = msg;	/* message length */
1125				if (msg == 0)
1126					msg = 256;
1127				/*
1128				 * We read and acknowlege all the bytes
1129				 * except the last so we can assert ATN
1130				 * if needed before acknowledging the last.
1131				 */
1132				for (i = 0; i < msg; i++) {
1133					dstat = sii_GetByte(regs,
1134						SII_MSG_IN_PHASE, i < msg - 1);
1135					if ((int)dstat < 0) {
1136						dstat = regs->dstat;
1137						goto again;
1138					}
1139					sii_buf[i + 2] = dstat;
1140				}
1141
1142				switch (sii_buf[2]) {
1143				case MSG_EXT_MODIFY_DATA_PTR:
1144					/* acknowledge last byte */
1145					regs->comm = SII_INXFER |
1146						SII_MSG_IN_PHASE |
1147						(comm & SII_STATE_MSK);
1148					SII_WAIT_UNTIL(dstat, regs->dstat,
1149						dstat & SII_DNE,
1150						SII_WAIT_COUNT, i);
1151					regs->dstat = SII_DNE;
1152					wbflush();
1153					i = (sii_buf[3] << 24) |
1154						(sii_buf[4] << 16) |
1155						(sii_buf[5] << 8) |
1156						sii_buf[6];
1157					if (state->dmaPrevPhase >= 0) {
1158						state->dmaAddrL += i;
1159						state->dmaCnt -= i;
1160					}
1161					break;
1162
1163				case MSG_EXT_SDTR_LEN:
1164					/*
1165					 * Acknowledge last byte and
1166					 * signal a request for MSG_OUT.
1167					 */
1168					regs->comm = SII_INXFER | SII_ATN |
1169						SII_MSG_IN_PHASE |
1170						(comm & SII_STATE_MSK);
1171					SII_WAIT_UNTIL(dstat, regs->dstat,
1172						dstat & SII_DNE,
1173						SII_WAIT_COUNT, i);
1174					regs->dstat = SII_DNE;
1175					wbflush();
1176					sii_DoSync(regs, state);
1177					break;
1178
1179				default:
1180				reject:
1181					/*
1182					 * Acknowledge last byte and
1183					 * signal a request for MSG_OUT.
1184					 */
1185					regs->comm = SII_INXFER | SII_ATN |
1186						SII_MSG_IN_PHASE |
1187						(comm & SII_STATE_MSK);
1188					SII_WAIT_UNTIL(dstat, regs->dstat,
1189						dstat & SII_DNE,
1190						SII_WAIT_COUNT, i);
1191					regs->dstat = SII_DNE;
1192					wbflush();
1193
1194					/* wait for MSG_OUT phase */
1195					SII_WAIT_UNTIL(dstat, regs->dstat,
1196						dstat & SII_TBE,
1197						SII_WAIT_COUNT, i);
1198
1199					/* send a reject message */
1200					regs->data = MSG_MESSAGE_REJECT;
1201					regs->comm = SII_INXFER |
1202						(regs->cstat & SII_STATE_MSK) |
1203						SII_MSG_OUT_PHASE;
1204					SII_WAIT_UNTIL(dstat, regs->dstat,
1205						dstat & SII_DNE,
1206						SII_WAIT_COUNT, i);
1207					regs->dstat = SII_DNE;
1208					wbflush();
1209				}
1210				break;
1211
1212			case MSG_SAVEDATAPOINTER:
1213			case MSG_RESTOREPOINTERS:
1214				/* acknowledge last byte */
1215				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1216					(comm & SII_STATE_MSK);
1217				SII_WAIT_UNTIL(dstat, regs->dstat,
1218					dstat & SII_DNE, SII_WAIT_COUNT, i);
1219				regs->dstat = SII_DNE;
1220				wbflush();
1221				/* wait a short time for another msg */
1222				SII_WAIT_UNTIL(dstat, regs->dstat,
1223					dstat & (SII_CI | SII_DI),
1224					SII_WAIT_COUNT, i);
1225				if (dstat & (SII_CI | SII_DI)) {
1226#ifdef DEBUG
1227					if (sii_debug > 4)
1228						printf("cnt %d\n", i);
1229#endif
1230					goto again;
1231				}
1232				break;
1233
1234			case MSG_DISCONNECT:
1235				/* acknowledge last byte */
1236				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1237					(comm & SII_STATE_MSK);
1238				SII_WAIT_UNTIL(dstat, regs->dstat,
1239					dstat & SII_DNE, SII_WAIT_COUNT, i);
1240				regs->dstat = SII_DNE;
1241				wbflush();
1242				state->prevComm = comm;
1243#ifdef DEBUG
1244				if (sii_debug > 4)
1245					printf("disconn %d ", sc->sc_target);
1246#endif
1247				/*
1248				 * Wait a short time for disconnect.
1249				 * Don't be fooled if SII_BER happens first.
1250				 * Note: a reselect may happen here.
1251				 */
1252				SII_WAIT_UNTIL(cstat, regs->cstat,
1253					cstat & (SII_RST | SII_SCH),
1254					SII_WAIT_COUNT, i);
1255				if ((cstat & (SII_RST | SII_SCH |
1256				    SII_STATE_MSK)) != SII_SCH) {
1257#ifdef DEBUG
1258					if (sii_debug > 4)
1259						printf("cnt %d\n", i);
1260#endif
1261					dstat = regs->dstat;
1262					goto again;
1263				}
1264				regs->cstat = SII_SCH | SII_BER;
1265				regs->comm = 0;
1266				wbflush();
1267				sc->sc_target = -1;
1268				/*
1269				 * Double check that we didn't miss a state
1270				 * change between seeing it and clearing
1271				 * the SII_SCH bit.
1272				 */
1273				i = regs->cstat;
1274				if (!(i & SII_SCH) && (i & SII_STATE_MSK) !=
1275				    (cstat & SII_STATE_MSK))
1276					sii_StateChg(sc, i);
1277				break;
1278
1279			case MSG_MESSAGE_REJECT:
1280				/* acknowledge last byte */
1281				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1282					(comm & SII_STATE_MSK);
1283				SII_WAIT_UNTIL(dstat, regs->dstat,
1284					dstat & SII_DNE, SII_WAIT_COUNT, i);
1285				regs->dstat = SII_DNE;
1286				wbflush();
1287				printf("%s: device %d: message reject.\n",
1288				    device_xname(sc->sc_dev), sc->sc_target);
1289				break;
1290
1291			default:
1292				if (!(msg & MSG_IDENTIFYFLAG)) {
1293					printf("%s: device %d: couldn't handle "
1294					    "message 0x%x... rejecting.\n",
1295					    device_xname(sc->sc_dev),
1296					    sc->sc_target,
1297					    msg);
1298#ifdef DEBUG
1299					sii_DumpLog();
1300#endif
1301					goto reject;
1302				}
1303				/* acknowledge last byte */
1304				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1305					(comm & SII_STATE_MSK);
1306				SII_WAIT_UNTIL(dstat, regs->dstat,
1307					dstat & SII_DNE, SII_WAIT_COUNT, i);
1308				regs->dstat = SII_DNE;
1309				wbflush();
1310				/* may want to check LUN some day */
1311				/* wait a short time for another msg */
1312				SII_WAIT_UNTIL(dstat, regs->dstat,
1313					dstat & (SII_CI | SII_DI),
1314					SII_WAIT_COUNT, i);
1315				if (dstat & (SII_CI | SII_DI)) {
1316#ifdef DEBUG
1317					if (sii_debug > 4)
1318						printf("cnt %d\n", i);
1319#endif
1320					goto again;
1321				}
1322			}
1323			break;
1324
1325		case SII_MSG_OUT_PHASE:
1326#ifdef DEBUG
1327			if (sii_debug > 4)
1328				printf("MsgOut\n");
1329#endif
1330			printf("MsgOut %x\n", state->flags); /* XXX */
1331
1332			/*
1333			 * Check for parity error.
1334			 * Hardware will automatically set ATN
1335			 * to request the device for a MSG_OUT phase.
1336			 */
1337			if (state->flags & PARITY_ERR) {
1338				state->flags &= ~PARITY_ERR;
1339				regs->data = MSG_PARITY_ERROR;
1340			} else
1341				regs->data = MSG_NOOP;
1342			regs->comm = SII_INXFER | (comm & SII_STATE_MSK) |
1343				SII_MSG_OUT_PHASE;
1344			wbflush();
1345
1346			/* wait a short time for XFER complete */
1347			SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
1348				SII_WAIT_COUNT, i);
1349#ifdef DEBUG
1350			if (sii_debug > 4)
1351				printf("ds %x i %d\n", dstat, i);
1352#endif
1353			/* just clear the DNE bit and check errors later */
1354			if (dstat & SII_DNE) {
1355				regs->dstat = SII_DNE;
1356				wbflush();
1357			}
1358			break;
1359
1360		default:
1361			printf("%s: Couldn't handle phase %d... ignoring.\n",
1362			    device_xname(sc->sc_dev), dstat & SII_PHASE_MSK);
1363		}
1364	}
1365
1366#ifdef DEBUG
1367	if (sii_debug > 3)
1368		printf("\n");
1369#endif
1370	/*
1371	 * Check to make sure we won't be interrupted again.
1372	 * Deglitch dstat register.
1373	 */
1374	msg = regs->dstat;
1375	while (msg != (dstat = regs->dstat))
1376		msg = dstat;
1377	if (dstat & (SII_CI | SII_DI))
1378		goto again;
1379
1380	if (sc->sc_target < 0) {
1381		/* look for another device that is ready */
1382		for (i = 0; i < SII_NCMD; i++) {
1383			/* don't restart a disconnected command */
1384			if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
1385				continue;
1386			sii_StartCmd(sc, i);
1387			break;
1388		}
1389	}
1390	return;
1391
1392abort:
1393	/* jump here to abort the current command */
1394	printf("%s: device %d: current command terminated\n",
1395	    device_xname(sc->sc_dev), sc->sc_target);
1396#ifdef DEBUG
1397	sii_DumpLog();
1398#endif
1399
1400	if ((cstat = regs->cstat) & SII_CON) {
1401		/* try to send an abort msg for awhile */
1402		regs->dstat = SII_DNE;
1403		regs->data = MSG_ABORT;
1404		regs->comm = SII_INXFER | SII_ATN | (cstat & SII_STATE_MSK) |
1405			SII_MSG_OUT_PHASE;
1406		wbflush();
1407		SII_WAIT_UNTIL(dstat, regs->dstat,
1408			(dstat & (SII_DNE | SII_PHASE_MSK)) ==
1409			(SII_DNE | SII_MSG_OUT_PHASE),
1410			2 * SII_WAIT_COUNT, i);
1411#ifdef DEBUG
1412		if (sii_debug > 0)
1413			printf("Abort: cs %x ds %x i %d\n", cstat, dstat, i);
1414#endif
1415		if ((dstat & (SII_DNE | SII_PHASE_MSK)) ==
1416		    (SII_DNE | SII_MSG_OUT_PHASE)) {
1417			/* disconnect if command in progress */
1418			regs->comm = SII_DISCON;
1419			wbflush();
1420			SII_WAIT_UNTIL(cstat, regs->cstat,
1421				!(cstat & SII_CON), SII_WAIT_COUNT, i);
1422		}
1423	} else {
1424#ifdef DEBUG
1425		if (sii_debug > 0)
1426			printf("Abort: cs %x\n", cstat);
1427#endif
1428	}
1429	regs->cstat = 0xffff;
1430	regs->dstat = 0xffff;
1431	regs->comm = 0;
1432	wbflush();
1433
1434	i = sc->sc_target;
1435	sc->sc_target = -1;
1436	sii_CmdDone(sc, i, EIO);
1437#ifdef DEBUG
1438	if (sii_debug > 4)
1439		printf("sii_DoIntr: after CmdDone target %d\n", sc->sc_target);
1440#endif
1441}
1442
1443static void
1444sii_StateChg(struct siisoftc *sc, u_int cstat)
1445{
1446	SIIRegs *regs = sc->sc_regs;
1447	State *state;
1448	int i;
1449
1450#ifdef DEBUG
1451	if (sii_debug > 4)
1452		printf("SCH: ");
1453#endif
1454
1455	switch (cstat & SII_STATE_MSK) {
1456	case 0:
1457		/* disconnect */
1458		i = sc->sc_target;
1459		sc->sc_target = -1;
1460#ifdef DEBUG
1461		if (sii_debug > 4)
1462			printf("disconn %d ", i);
1463#endif
1464		if (i >= 0 && !sc->sc_st[i].prevComm) {
1465			printf("%s: device %d: spurrious disconnect (%d)\n",
1466			    device_xname(sc->sc_dev), i, regs->slcsr);
1467			sc->sc_st[i].prevComm = 0;
1468		}
1469		break;
1470
1471	case SII_CON:
1472		/* connected as initiator */
1473		i = regs->slcsr;
1474		if (sc->sc_target == i)
1475			break;
1476		printf("%s: device %d: connect to device %d??\n",
1477		    device_xname(sc->sc_dev), sc->sc_target, i);
1478		sc->sc_target = i;
1479		break;
1480
1481	case SII_DST:
1482		/*
1483		 * Wait for CON to become valid,
1484		 * chip is slow sometimes.
1485		 */
1486		SII_WAIT_UNTIL(cstat, regs->cstat,
1487			cstat & SII_CON, SII_WAIT_COUNT, i);
1488		if (!(cstat & SII_CON))
1489			panic("sii resel");
1490		/* FALLTHROUGH */
1491
1492	case SII_CON | SII_DST:
1493		/*
1494		 * Its a reselection. Save the ID and wait for
1495		 * interrupts to tell us what to do next
1496		 * (should be MSG_IN of IDENTIFY).
1497		 * NOTE: sc_target may be >= 0 if we were in
1498		 * the process of trying to start a command
1499		 * and were reselected before the select
1500		 * command finished.
1501		 */
1502		sc->sc_target = i = regs->destat;
1503		state = &sc->sc_st[i];
1504		regs->comm = SII_CON | SII_DST | SII_MSG_IN_PHASE;
1505		regs->dmctrl = state->dmaReqAck;
1506		wbflush();
1507		if (!state->prevComm) {
1508			printf("%s: device %d: spurious reselection\n",
1509			    device_xname(sc->sc_dev), i);
1510			break;
1511		}
1512		state->prevComm = 0;
1513#ifdef DEBUG
1514		if (sii_debug > 4)
1515			printf("resel %d ", sc->sc_target);
1516#endif
1517		break;
1518
1519#ifdef notyet
1520	case SII_DST | SII_TGT:
1521	case SII_CON | SII_DST | SII_TGT:
1522		/* connected as target */
1523		printf("%s: Selected by device %d as target!!\n",
1524		    device_xname(sc->sc_dev), regs->destat);
1525		regs->comm = SII_DISCON;
1526		wbflush();
1527		SII_WAIT_UNTIL(!(regs->cstat & SII_CON),
1528			SII_WAIT_COUNT, i);
1529		regs->cstat = 0xffff;
1530		regs->dstat = 0xffff;
1531		regs->comm = 0;
1532		break;
1533#endif
1534
1535	default:
1536		printf("%s: Unknown state change (cs %x)!!\n",
1537		    device_xname(sc->sc_dev), cstat);
1538#ifdef DEBUG
1539		sii_DumpLog();
1540#endif
1541	}
1542}
1543
1544/*
1545 * Read one byte of data.
1546 * If 'ack' is true, acknowledge the byte.
1547 */
1548static int
1549sii_GetByte(SIIRegs *regs, int phase, int ack)
1550{
1551	u_int dstat;
1552	u_int state;
1553	int i;
1554	int data;
1555
1556	dstat = regs->dstat;
1557	state = regs->cstat & SII_STATE_MSK;
1558	i = -1;
1559	if (!(dstat & SII_IBF) || (dstat & SII_MIS)) {
1560		regs->comm = state | phase;
1561		wbflush();
1562		/* wait a short time for IBF */
1563		SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_IBF,
1564			SII_WAIT_COUNT, i);
1565#ifdef DEBUG
1566		if (!(dstat & SII_IBF))
1567			printf("status no IBF\n");
1568#endif
1569	}
1570	if (dstat & SII_DNE) { /* XXX */
1571		printf("sii_GetByte: DNE set 5\n");
1572#ifdef DEBUG
1573		sii_DumpLog();
1574#endif
1575		regs->dstat = SII_DNE;
1576	}
1577	data = regs->data;
1578	/* check for parity error */
1579	if (dstat & SII_IPE) {
1580#ifdef DEBUG
1581		if (sii_debug > 4)
1582			printf("cnt0 %d\n", i);
1583#endif
1584		printf("sii_GetByte: data %x ?? ds %x cm %x i %d\n",
1585			data, dstat, regs->comm, i); /* XXX */
1586		data = -1;
1587		ack = 1;
1588	}
1589
1590	if (ack) {
1591		regs->comm = SII_INXFER | state | phase;
1592		wbflush();
1593
1594		/* wait a short time for XFER complete */
1595		SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
1596			SII_WAIT_COUNT, i);
1597
1598		/* clear the DNE */
1599		if (dstat & SII_DNE) {
1600			regs->dstat = SII_DNE;
1601			wbflush();
1602		}
1603	}
1604
1605	return (data);
1606}
1607
1608/*
1609 * Exchange messages to initiate synchronous data transfers.
1610 */
1611static void
1612sii_DoSync(SIIRegs *regs, State *state)
1613{
1614	u_int dstat, comm;
1615	int i, j;
1616	u_int len;
1617
1618#ifdef DEBUG
1619	if (sii_debug)
1620		printf("sii_DoSync: len %d per %d req/ack %d\n",
1621			sii_buf[1], sii_buf[3], sii_buf[4]);
1622#endif
1623
1624	/* SII chip can only handle a minimum transfer period of ??? */
1625	if (sii_buf[3] < 64)
1626		sii_buf[3] = 64;
1627	/* SII chip can only handle a maximum REQ/ACK offset of 3 */
1628	len = sii_buf[4];
1629	if (len > 3)
1630		len = 3;
1631
1632	sii_buf[0] = MSG_EXTENDED;
1633	sii_buf[1] = MSG_EXT_SDTR_LEN;
1634	sii_buf[2] = MSG_EXT_SDTR;
1635	sii_buf[4] = len;
1636#if 1
1637	comm = SII_INXFER | SII_ATN | SII_MSG_OUT_PHASE |
1638		(regs->cstat & SII_STATE_MSK);
1639	regs->comm = comm & ~SII_INXFER;
1640	for (j = 0; j < 5; j++) {
1641		/* wait for target to request the next byte */
1642		SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_TBE,
1643			SII_WAIT_COUNT, i);
1644		if (!(dstat & SII_TBE) ||
1645		    (dstat & SII_PHASE_MSK) != SII_MSG_OUT_PHASE) {
1646			printf("sii_DoSync: TBE? ds %x cm %x i %d\n",
1647				dstat, comm, i); /* XXX */
1648			return;
1649		}
1650
1651		/* the last message byte should have ATN off */
1652		if (j == 4)
1653			comm &= ~SII_ATN;
1654
1655		regs->data = sii_buf[j];
1656		regs->comm = comm;
1657		wbflush();
1658
1659		/* wait a short time for XFER complete */
1660		SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
1661			SII_WAIT_COUNT, i);
1662
1663		if (!(dstat & SII_DNE)) {
1664			printf("sii_DoSync: DNE? ds %x cm %x i %d\n",
1665				dstat, comm, i); /* XXX */
1666			return;
1667		}
1668
1669		/* clear the DNE, other errors handled later */
1670		regs->dstat = SII_DNE;
1671		wbflush();
1672	}
1673#else	/* 0 */
1674	sc->sii_copytobuf((u_short *)sii_buf,
1675		     (volatile u_short *)SII_BUF_ADDR(sc), 5);
1676	printf("sii_DoSync: %x %x %x ds %x\n",
1677		((volatile u_short *)SII_BUF_ADDR(sc))[0],
1678		((volatile u_short *)SII_BUF_ADDR(sc))[2],
1679		((volatile u_short *)SII_BUF_ADDR(sc))[4],
1680		regs->dstat); /* XXX */
1681	regs->dmaddrl = (u_short)(SII_BUF_ADDR(sc) >> 1);
1682	regs->dmaddrh = (u_short)(SII_BUF_ADDR(sc) >> 17) & 03;
1683	regs->dmlotc = 5;
1684	regs->comm = SII_DMA | SII_INXFER | SII_ATN |
1685		(regs->cstat & SII_STATE_MSK) | SII_MSG_OUT_PHASE;
1686	wbflush();
1687
1688	/* wait a short time for XFER complete */
1689	SII_WAIT_UNTIL(dstat, regs->dstat,
1690		(dstat & (SII_DNE | SII_TCZ)) == (SII_DNE | SII_TCZ),
1691		SII_WAIT_COUNT, i);
1692
1693	if ((dstat & (SII_DNE | SII_TCZ)) != (SII_DNE | SII_TCZ)) {
1694		printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
1695			dstat, regs->comm, i, regs->dmlotc); /* XXX */
1696		sii_DumpLog(); /* XXX */
1697		return;
1698	}
1699	/* clear the DNE, other errors handled later */
1700	regs->dstat = SII_DNE;
1701	wbflush();
1702#endif	/* 0 */
1703
1704#if 0
1705	SII_WAIT_UNTIL(dstat, regs->dstat, dstat & (SII_CI | SII_DI),
1706		SII_WAIT_COUNT, i);
1707	printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
1708		dstat, regs->comm, i, regs->dmlotc); /* XXX */
1709#endif
1710
1711	state->dmaReqAck = len;
1712}
1713
1714/*
1715 * Issue the sequence of commands to the controller to start DMA.
1716 * NOTE: the data buffer should be word-aligned for DMA out.
1717 */
1718static void
1719sii_StartDMA(SIIRegs *regs, int phase, u_short *dmaAddr, int size)
1720	/* regs:	 which SII to use */
1721	/* phase:		 phase to send/receive data */
1722	/* dmaAddr:	 DMA buffer address */
1723	/* size:		 # of bytes to transfer */
1724{
1725
1726	if (regs->dstat & SII_DNE) { /* XXX */
1727		regs->dstat = SII_DNE;
1728		printf("sii_StartDMA: DNE set\n");
1729#ifdef DEBUG
1730		sii_DumpLog();
1731#endif
1732	}
1733	regs->dmaddrl = ((u_long)dmaAddr >> 1);
1734	regs->dmaddrh = ((u_long)dmaAddr >> 17) & 03;
1735	regs->dmlotc = size;
1736	regs->comm = SII_DMA | SII_INXFER | (regs->cstat & SII_STATE_MSK) |
1737		phase;
1738	wbflush();
1739
1740#ifdef DEBUG
1741	if (sii_debug > 5) {
1742		printf("sii_StartDMA: cs 0x%x, ds 0x%x, cm 0x%x, size %d\n",
1743			regs->cstat, regs->dstat, regs->comm, size);
1744	}
1745#endif
1746}
1747
1748/*
1749 * Call the device driver's 'done' routine to let it know the command is done.
1750 * The 'done' routine may try to start another command.
1751 * To be fair, we should start pending commands for other devices
1752 * before allowing the same device to start another command.
1753 */
1754static void
1755sii_CmdDone(struct siisoftc *sc, int target, int error)
1756	/* sc:	 which SII to use */
1757	/* target:			 which device is done */
1758	/* error:			 error code if any errors */
1759{
1760	ScsiCmd *scsicmd;
1761	int i;
1762
1763	scsicmd = sc->sc_cmd[target];
1764#ifdef DIAGNOSTIC
1765	if (target < 0 || !scsicmd)
1766		panic("sii_CmdDone");
1767#endif
1768	sc->sc_cmd[target] = (ScsiCmd *)0;
1769#ifdef DEBUG
1770	if (sii_debug > 1) {
1771		printf("sii_CmdDone: %s target %d cmd %x err %d resid %d\n",
1772		    device_xname(sc->sc_dev),
1773		    target, scsicmd->cmd[0], error, sc->sc_st[target].buflen);
1774	}
1775#endif
1776
1777	/* look for another device that is ready */
1778	for (i = 0; i < SII_NCMD; i++) {
1779		/* don't restart a disconnected command */
1780		if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
1781			continue;
1782		sii_StartCmd(sc, i);
1783		break;
1784	}
1785
1786	sc->sc_xs[target]->status = sc->sc_st[target].statusByte;
1787	/*
1788	 * Convert SII driver error code to MI SCSI XS_*.
1789	 */
1790	switch (error) {
1791	case 0:
1792		sc->sc_xs[target]->error = XS_NOERROR;
1793		break;
1794	case ENXIO:
1795		sc->sc_xs[target]->error = XS_SELTIMEOUT;
1796		break;
1797	case EBUSY:
1798		sc->sc_xs[target]->error = XS_BUSY;
1799		break;
1800	case EIO:
1801		sc->sc_xs[target]->error = XS_DRIVER_STUFFUP;
1802		break;
1803	default:
1804		sc->sc_xs[target]->error = XS_DRIVER_STUFFUP;
1805	}
1806	sc->sc_xs[target]->resid = sc->sc_st[target].buflen;
1807	scsipi_done(sc->sc_xs[target]);
1808}
1809
1810#ifdef DEBUG
1811static void
1812sii_DumpLog(void)
1813{
1814	struct sii_log *lp;
1815
1816	printf("sii: cmd %x bn %d cnt %d\n", sii_debug_cmd, sii_debug_bn,
1817		sii_debug_sz);
1818	lp = sii_logp;
1819	do {
1820		printf("target %d cs %x ds %x cm %x msg %x rlen %x dlen %x\n",
1821			lp->target, lp->cstat, lp->dstat, lp->comm, lp->msg,
1822			lp->rlen, lp->dlen);
1823		if (++lp >= &sii_log[NLOG])
1824			lp = sii_log;
1825	} while (lp != sii_logp);
1826}
1827#endif
1828