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