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