xref: /original-bsd/sys/pmax/dev/sii.c (revision fac0c393)
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.4 (Berkeley) 11/30/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 #ifdef DEBUG
718 				sii_DumpLog();
719 #endif
720 				panic("sc_target 2");
721 			}
722 		}
723 		state = &sc->sc_st[sc->sc_target];
724 		switch (dstat & SII_PHASE_MSK) {
725 		case SII_CMD_PHASE:
726 			if (state->dmaPrevPhase >= 0) {
727 				/* restart DMA after disconnect/reconnect */
728 				if (state->dmaPrevPhase != SII_CMD_PHASE) {
729 					printf("sii%d: device %d: dma reselect phase doesn't match\n",
730 						sc - sii_softc, sc->sc_target);
731 					goto abort;
732 				}
733 				state->dmaCurPhase = SII_CMD_PHASE;
734 				state->dmaPrevPhase = -1;
735 				regs->dmaddrl = state->dmaAddrL;
736 				regs->dmaddrh = state->dmaAddrH;
737 				regs->dmlotc = state->dmaCnt;
738 				if (state->dmaCnt & 1)
739 					regs->dmabyte = state->dmaByte;
740 				regs->comm = SII_DMA | SII_INXFER |
741 					(comm & SII_STATE_MSK) | SII_CMD_PHASE;
742 				MachEmptyWriteBuffer();
743 #ifdef DEBUG
744 				if (sii_debug > 4)
745 					printf("Cmd dcnt %d dadr %x ",
746 						state->dmaCnt,
747 						(state->dmaAddrH << 16) |
748 							state->dmaAddrL);
749 #endif
750 			} else {
751 				/* send command data */
752 				i = state->cmdlen;
753 				if (i == 0) {
754 					printf("sii%d: device %d: cmd count exceeded\n",
755 						sc - sii_softc, sc->sc_target);
756 					goto abort;
757 				}
758 				CopyToBuffer((u_short *)state->cmd,
759 					(volatile u_short *)state->dmaAddr[0],
760 					i);
761 				sii_StartDMA(regs, state->dmaCurPhase =
762 					SII_CMD_PHASE, state->dmaAddr[0],
763 					state->dmalen = i);
764 			}
765 			/* wait a short time for XFER complete */
766 			SII_WAIT_UNTIL(dstat, regs->dstat,
767 				dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
768 			if (dstat & (SII_CI | SII_DI)) {
769 #ifdef DEBUG
770 				if (sii_debug > 4)
771 					printf("cnt %d\n", i);
772 				else if (sii_debug > 0)
773 					printf("sii_DoIntr: cmd wait ds %x cnt %d\n",
774 						dstat, i);
775 #endif
776 				goto again;
777 			}
778 			break;
779 
780 		case SII_DATA_IN_PHASE:
781 		case SII_DATA_OUT_PHASE:
782 			if (state->cmdlen > 0) {
783 				printf("sii%d: device %d: cmd %x: command data not all sent (%d) 1\n",
784 					sc - sii_softc, sc->sc_target,
785 					sc->sc_cmd[sc->sc_target]->cmd[0],
786 					state->cmdlen);
787 				state->cmdlen = 0;
788 #ifdef DEBUG
789 				sii_DumpLog();
790 #endif
791 			}
792 			if (state->dmaPrevPhase >= 0) {
793 				/* restart DMA after disconnect/reconnect */
794 				if (state->dmaPrevPhase !=
795 				    (dstat & SII_PHASE_MSK)) {
796 					printf("sii%d: device %d: dma reselect phase doesn't match\n",
797 						sc - sii_softc, sc->sc_target);
798 					goto abort;
799 				}
800 				state->dmaCurPhase = state->dmaPrevPhase;
801 				state->dmaPrevPhase = -1;
802 				regs->dmaddrl = state->dmaAddrL;
803 				regs->dmaddrh = state->dmaAddrH;
804 				regs->dmlotc = state->dmaCnt;
805 				if (state->dmaCnt & 1)
806 					regs->dmabyte = state->dmaByte;
807 				regs->comm = SII_DMA | SII_INXFER |
808 					(comm & SII_STATE_MSK) |
809 					state->dmaCurPhase;
810 				MachEmptyWriteBuffer();
811 #ifdef DEBUG
812 				if (sii_debug > 4)
813 					printf("Data %d dcnt %d dadr %x ",
814 						state->dmaDataPhase,
815 						state->dmaCnt,
816 						(state->dmaAddrH << 16) |
817 							state->dmaAddrL);
818 #endif
819 				break;
820 			}
821 			if (state->dmaDataPhase != (dstat & SII_PHASE_MSK)) {
822 				printf("sii%d: device %d: cmd %x: dma phase doesn't match\n",
823 					sc - sii_softc, sc->sc_target,
824 					sc->sc_cmd[sc->sc_target]->cmd[0]);
825 				goto abort;
826 			}
827 #ifdef DEBUG
828 			if (sii_debug > 4) {
829 				printf("Data %d ", state->dmaDataPhase);
830 				if (sii_debug > 5)
831 					printf("\n");
832 			}
833 #endif
834 			i = state->buflen;
835 			if (i == 0) {
836 				printf("sii%d: device %d: data count exceeded\n",
837 					sc - sii_softc, sc->sc_target);
838 				goto abort;
839 			}
840 			if (i > SII_MAX_DMA_XFER_LENGTH)
841 				i = SII_MAX_DMA_XFER_LENGTH;
842 			if ((dstat & SII_PHASE_MSK) == SII_DATA_IN_PHASE) {
843 				sii_StartDMA(regs,
844 					state->dmaCurPhase = SII_DATA_IN_PHASE,
845 					state->dmaAddr[state->dmaBufIndex],
846 					state->dmalen = i);
847 				break;
848 			}
849 			/* start first chunk */
850 			if (state->flags & FIRST_DMA) {
851 				state->flags &= ~FIRST_DMA;
852 				CopyToBuffer((u_short *)state->buf,
853 					(volatile u_short *)
854 					state->dmaAddr[state->dmaBufIndex], i);
855 			}
856 			sii_StartDMA(regs,
857 				state->dmaCurPhase = SII_DATA_OUT_PHASE,
858 				state->dmaAddr[state->dmaBufIndex],
859 				state->dmalen = i);
860 			i = state->buflen - SII_MAX_DMA_XFER_LENGTH;
861 			if (i > 0) {
862 				/* prepare for next chunk */
863 				if (i > SII_MAX_DMA_XFER_LENGTH)
864 					i = SII_MAX_DMA_XFER_LENGTH;
865 				CopyToBuffer((u_short *)(state->buf +
866 					SII_MAX_DMA_XFER_LENGTH),
867 					(volatile u_short *)
868 					state->dmaAddr[!state->dmaBufIndex], i);
869 			}
870 			break;
871 
872 		case SII_STATUS_PHASE:
873 			if (state->cmdlen > 0) {
874 				printf("sii%d: device %d: cmd %x: command data not all sent (%d) 2\n",
875 					sc - sii_softc, sc->sc_target,
876 					sc->sc_cmd[sc->sc_target]->cmd[0],
877 					state->cmdlen);
878 				state->cmdlen = 0;
879 #ifdef DEBUG
880 				sii_DumpLog();
881 #endif
882 			}
883 
884 			/* read amount transfered if DMA didn't finish */
885 			if (state->dmalen > 0) {
886 				i = state->dmalen - regs->dmlotc;
887 				state->dmalen = 0;
888 				state->dmaCurPhase = -1;
889 				regs->dmlotc = 0;
890 				regs->comm = comm &
891 					(SII_STATE_MSK | SII_PHASE_MSK);
892 				MachEmptyWriteBuffer();
893 				regs->dstat = SII_DNE;
894 				MachEmptyWriteBuffer();
895 #ifdef DEBUG
896 				if (sii_debug > 4)
897 					printf("DMA amt %d ", i);
898 #endif
899 				switch (comm & SII_PHASE_MSK) {
900 				case SII_DATA_IN_PHASE:
901 					/* copy in the data */
902 					CopyFromBuffer((volatile u_short *)
903 					    state->dmaAddr[state->dmaBufIndex],
904 					    state->buf, i);
905 
906 				case SII_CMD_PHASE:
907 				case SII_DATA_OUT_PHASE:
908 					state->buflen -= i;
909 				}
910 			}
911 
912 			/* read a one byte status message */
913 			state->statusByte = msg =
914 				sii_GetByte(regs, SII_STATUS_PHASE, 1);
915 			if (msg < 0) {
916 				dstat = regs->dstat;
917 				goto again;
918 			}
919 #ifdef DEBUG
920 			if (sii_debug > 4)
921 				printf("Status %x ", msg);
922 			if (sii_logp > sii_log)
923 				sii_logp[-1].msg = msg;
924 			else
925 				sii_log[NLOG - 1].msg = msg;
926 #endif
927 
928 			/* do a quick wait for COMMAND_COMPLETE */
929 			SII_WAIT_UNTIL(dstat, regs->dstat,
930 				dstat & (SII_CI | SII_DI), SII_WAIT_COUNT, i);
931 			if (dstat & (SII_CI | SII_DI)) {
932 #ifdef DEBUG
933 				if (sii_debug > 4)
934 					printf("cnt2 %d\n", i);
935 #endif
936 				goto again;
937 			}
938 			break;
939 
940 		case SII_MSG_IN_PHASE:
941 			/*
942 			 * Save DMA state if DMA didn't finish.
943 			 * Be careful not to save state again after reconnect
944 			 * and see RESTORE_POINTER message.
945 			 * Note that the SII DMA address is not incremented
946 			 * as DMA proceeds.
947 			 */
948 			if (state->dmaCurPhase > 0) {
949 				/* save dma registers */
950 				state->dmaPrevPhase = state->dmaCurPhase;
951 				state->dmaCurPhase = -1;
952 				state->dmaCnt = i = regs->dmlotc;
953 				if (dstat & SII_OBB)
954 					state->dmaByte = regs->dmabyte;
955 				if (i == 0)
956 					i = SII_MAX_DMA_XFER_LENGTH;
957 				i = state->dmalen - i;
958 				/* note: no carry from dmaddrl to dmaddrh */
959 				state->dmaAddrL = regs->dmaddrl + i;
960 				state->dmaAddrH = regs->dmaddrh;
961 				regs->comm = comm &
962 					(SII_STATE_MSK | SII_PHASE_MSK);
963 				MachEmptyWriteBuffer();
964 				regs->dstat = SII_DNE;
965 				MachEmptyWriteBuffer();
966 #ifdef DEBUG
967 				if (sii_debug > 4) {
968 					printf("SavP dcnt %d dadr %x ",
969 						state->dmaCnt,
970 						(state->dmaAddrH << 16) |
971 						state->dmaAddrL);
972 					if (((dstat & SII_OBB) != 0) ^
973 					    (state->dmaCnt & 1))
974 						printf("OBB??? ");
975 				} else if (sii_debug > 0) {
976 					if (((dstat & SII_OBB) != 0) ^
977 					    (state->dmaCnt & 1)) {
978 						printf("sii_DoIntr: OBB??? ds %x cnt %d\n",
979 							dstat, state->dmaCnt);
980 						sii_DumpLog();
981 					}
982 				}
983 #endif
984 			}
985 
986 			/* read a one byte message */
987 			msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 0);
988 			if (msg < 0) {
989 				dstat = regs->dstat;
990 				goto again;
991 			}
992 #ifdef DEBUG
993 			if (sii_debug > 4)
994 				printf("MsgIn %x ", msg);
995 			if (sii_logp > sii_log)
996 				sii_logp[-1].msg = msg;
997 			else
998 				sii_log[NLOG - 1].msg = msg;
999 #endif
1000 
1001 			/* process message */
1002 			switch (msg) {
1003 			case SCSI_COMMAND_COMPLETE:
1004 				/* acknowledge last byte */
1005 				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1006 					(comm & SII_STATE_MSK);
1007 				SII_WAIT_UNTIL(dstat, regs->dstat,
1008 					dstat & SII_DNE, SII_WAIT_COUNT, i);
1009 				regs->dstat = SII_DNE;
1010 				MachEmptyWriteBuffer();
1011 				msg = sc->sc_target;
1012 				sc->sc_target = -1;
1013 				/*
1014 				 * Wait a short time for disconnect.
1015 				 * Don't be fooled if SII_BER happens first.
1016 				 * Note: a reselect may happen here.
1017 				 */
1018 				SII_WAIT_UNTIL(cstat, regs->cstat,
1019 					cstat & (SII_RST | SII_SCH),
1020 					SII_WAIT_COUNT, i);
1021 				if ((cstat & (SII_RST | SII_SCH |
1022 				    SII_STATE_MSK)) == SII_SCH) {
1023 					regs->cstat = SII_SCH | SII_BER;
1024 					regs->comm = 0;
1025 					MachEmptyWriteBuffer();
1026 					/*
1027 					 * Double check that we didn't miss a
1028 					 * state change between seeing it and
1029 					 * clearing the SII_SCH bit.
1030 					 */
1031 					i = regs->cstat;
1032 					if (!(i & SII_SCH) &&
1033 					    (i & SII_STATE_MSK) !=
1034 					    (cstat & SII_STATE_MSK))
1035 						sii_StateChg(sc, i);
1036 				}
1037 #ifdef DEBUG
1038 				if (sii_debug > 4)
1039 					printf("cs %x\n", cstat);
1040 #endif
1041 				sii_CmdDone(sc, msg, 0);
1042 				break;
1043 
1044 			case SCSI_EXTENDED_MSG:
1045 				/* acknowledge last byte */
1046 				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1047 					(comm & SII_STATE_MSK);
1048 				SII_WAIT_UNTIL(dstat, regs->dstat,
1049 					dstat & SII_DNE, SII_WAIT_COUNT, i);
1050 				regs->dstat = SII_DNE;
1051 				MachEmptyWriteBuffer();
1052 				/* read the message length */
1053 				msg = sii_GetByte(regs, SII_MSG_IN_PHASE, 1);
1054 				if (msg < 0) {
1055 					dstat = regs->dstat;
1056 					goto again;
1057 				}
1058 				sii_buf[1] = msg;	/* message length */
1059 				if (msg == 0)
1060 					msg = 256;
1061 				/*
1062 				 * We read and acknowlege all the bytes
1063 				 * except the last so we can assert ATN
1064 				 * if needed before acknowledging the last.
1065 				 */
1066 				for (i = 0; i < msg; i++) {
1067 					dstat = sii_GetByte(regs,
1068 						SII_MSG_IN_PHASE, i < msg - 1);
1069 					if ((int)dstat < 0) {
1070 						dstat = regs->dstat;
1071 						goto again;
1072 					}
1073 					sii_buf[i + 2] = dstat;
1074 				}
1075 
1076 				switch (sii_buf[2]) {
1077 				case SCSI_MODIFY_DATA_PTR:
1078 					/* acknowledge last byte */
1079 					regs->comm = SII_INXFER |
1080 						SII_MSG_IN_PHASE |
1081 						(comm & SII_STATE_MSK);
1082 					SII_WAIT_UNTIL(dstat, regs->dstat,
1083 						dstat & SII_DNE,
1084 						SII_WAIT_COUNT, i);
1085 					regs->dstat = SII_DNE;
1086 					MachEmptyWriteBuffer();
1087 					i = (sii_buf[3] << 24) |
1088 						(sii_buf[4] << 16) |
1089 						(sii_buf[5] << 8) |
1090 						sii_buf[6];
1091 					if (state->dmaPrevPhase >= 0) {
1092 						state->dmaAddrL += i;
1093 						state->dmaCnt -= i;
1094 					}
1095 					break;
1096 
1097 				case SCSI_SYNCHRONOUS_XFER:
1098 					/*
1099 					 * Acknowledge last byte and
1100 					 * signal a request for MSG_OUT.
1101 					 */
1102 					regs->comm = SII_INXFER | SII_ATN |
1103 						SII_MSG_IN_PHASE |
1104 						(comm & SII_STATE_MSK);
1105 					SII_WAIT_UNTIL(dstat, regs->dstat,
1106 						dstat & SII_DNE,
1107 						SII_WAIT_COUNT, i);
1108 					regs->dstat = SII_DNE;
1109 					MachEmptyWriteBuffer();
1110 					sii_DoSync(regs, state);
1111 					break;
1112 
1113 				default:
1114 				reject:
1115 					/*
1116 					 * Acknowledge last byte and
1117 					 * signal a request for MSG_OUT.
1118 					 */
1119 					regs->comm = SII_INXFER | SII_ATN |
1120 						SII_MSG_IN_PHASE |
1121 						(comm & SII_STATE_MSK);
1122 					SII_WAIT_UNTIL(dstat, regs->dstat,
1123 						dstat & SII_DNE,
1124 						SII_WAIT_COUNT, i);
1125 					regs->dstat = SII_DNE;
1126 					MachEmptyWriteBuffer();
1127 
1128 					/* wait for MSG_OUT phase */
1129 					SII_WAIT_UNTIL(dstat, regs->dstat,
1130 						dstat & SII_TBE,
1131 						SII_WAIT_COUNT, i);
1132 
1133 					/* send a reject message */
1134 					regs->data = SCSI_MESSAGE_REJECT;
1135 					regs->comm = SII_INXFER |
1136 						(regs->cstat & SII_STATE_MSK) |
1137 						SII_MSG_OUT_PHASE;
1138 					SII_WAIT_UNTIL(dstat, regs->dstat,
1139 						dstat & SII_DNE,
1140 						SII_WAIT_COUNT, i);
1141 					regs->dstat = SII_DNE;
1142 					MachEmptyWriteBuffer();
1143 				}
1144 				break;
1145 
1146 			case SCSI_SAVE_DATA_POINTER:
1147 			case SCSI_RESTORE_POINTERS:
1148 				/* acknowledge last byte */
1149 				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1150 					(comm & SII_STATE_MSK);
1151 				SII_WAIT_UNTIL(dstat, regs->dstat,
1152 					dstat & SII_DNE, SII_WAIT_COUNT, i);
1153 				regs->dstat = SII_DNE;
1154 				MachEmptyWriteBuffer();
1155 				/* wait a short time for another msg */
1156 				SII_WAIT_UNTIL(dstat, regs->dstat,
1157 					dstat & (SII_CI | SII_DI),
1158 					SII_WAIT_COUNT, i);
1159 				if (dstat & (SII_CI | SII_DI)) {
1160 #ifdef DEBUG
1161 					if (sii_debug > 4)
1162 						printf("cnt %d\n", i);
1163 #endif
1164 					goto again;
1165 				}
1166 				break;
1167 
1168 			case SCSI_DISCONNECT:
1169 				/* acknowledge last byte */
1170 				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1171 					(comm & SII_STATE_MSK);
1172 				SII_WAIT_UNTIL(dstat, regs->dstat,
1173 					dstat & SII_DNE, SII_WAIT_COUNT, i);
1174 				regs->dstat = SII_DNE;
1175 				MachEmptyWriteBuffer();
1176 				state->prevComm = comm;
1177 #ifdef DEBUG
1178 				if (sii_debug > 4)
1179 					printf("disconn %d ", sc->sc_target);
1180 #endif
1181 				/*
1182 				 * Wait a short time for disconnect.
1183 				 * Don't be fooled if SII_BER happens first.
1184 				 * Note: a reselect may happen here.
1185 				 */
1186 				SII_WAIT_UNTIL(cstat, regs->cstat,
1187 					cstat & (SII_RST | SII_SCH),
1188 					SII_WAIT_COUNT, i);
1189 				if ((cstat & (SII_RST | SII_SCH |
1190 				    SII_STATE_MSK)) != SII_SCH) {
1191 #ifdef DEBUG
1192 					if (sii_debug > 4)
1193 						printf("cnt %d\n", i);
1194 #endif
1195 					dstat = regs->dstat;
1196 					goto again;
1197 				}
1198 				regs->cstat = SII_SCH | SII_BER;
1199 				regs->comm = 0;
1200 				MachEmptyWriteBuffer();
1201 				sc->sc_target = -1;
1202 				/*
1203 				 * Double check that we didn't miss a state
1204 				 * change between seeing it and clearing
1205 				 * the SII_SCH bit.
1206 				 */
1207 				i = regs->cstat;
1208 				if (!(i & SII_SCH) && (i & SII_STATE_MSK) !=
1209 				    (cstat & SII_STATE_MSK))
1210 					sii_StateChg(sc, i);
1211 				break;
1212 
1213 			case SCSI_MESSAGE_REJECT:
1214 				/* acknowledge last byte */
1215 				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1216 					(comm & SII_STATE_MSK);
1217 				SII_WAIT_UNTIL(dstat, regs->dstat,
1218 					dstat & SII_DNE, SII_WAIT_COUNT, i);
1219 				regs->dstat = SII_DNE;
1220 				MachEmptyWriteBuffer();
1221 				printf("sii%d: device %d: message reject.\n",
1222 					sc - sii_softc, sc->sc_target);
1223 				break;
1224 
1225 			default:
1226 				if (!(msg & SCSI_IDENTIFY)) {
1227 					printf("sii%d: device %d: couldn't handle message 0x%x... rejecting.\n",
1228 						sc - sii_softc, sc->sc_target,
1229 						msg);
1230 #ifdef DEBUG
1231 					sii_DumpLog();
1232 #endif
1233 					goto reject;
1234 				}
1235 				/* acknowledge last byte */
1236 				regs->comm = SII_INXFER | SII_MSG_IN_PHASE |
1237 					(comm & SII_STATE_MSK);
1238 				SII_WAIT_UNTIL(dstat, regs->dstat,
1239 					dstat & SII_DNE, SII_WAIT_COUNT, i);
1240 				regs->dstat = SII_DNE;
1241 				MachEmptyWriteBuffer();
1242 				/* may want to check LUN some day */
1243 				/* wait a short time for another msg */
1244 				SII_WAIT_UNTIL(dstat, regs->dstat,
1245 					dstat & (SII_CI | SII_DI),
1246 					SII_WAIT_COUNT, i);
1247 				if (dstat & (SII_CI | SII_DI)) {
1248 #ifdef DEBUG
1249 					if (sii_debug > 4)
1250 						printf("cnt %d\n", i);
1251 #endif
1252 					goto again;
1253 				}
1254 			}
1255 			break;
1256 
1257 		case SII_MSG_OUT_PHASE:
1258 #ifdef DEBUG
1259 			if (sii_debug > 4)
1260 				printf("MsgOut\n");
1261 #endif
1262 			printf("MsgOut %x\n", state->flags); /* XXX */
1263 
1264 			/*
1265 			 * Check for parity error.
1266 			 * Hardware will automatically set ATN
1267 			 * to request the device for a MSG_OUT phase.
1268 			 */
1269 			if (state->flags & PARITY_ERR) {
1270 				state->flags &= ~PARITY_ERR;
1271 				regs->data = SCSI_MESSAGE_PARITY_ERROR;
1272 			} else
1273 				regs->data = SCSI_NO_OP;
1274 			regs->comm = SII_INXFER | (comm & SII_STATE_MSK) |
1275 				SII_MSG_OUT_PHASE;
1276 			MachEmptyWriteBuffer();
1277 
1278 			/* wait a short time for XFER complete */
1279 			SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
1280 				SII_WAIT_COUNT, i);
1281 #ifdef DEBUG
1282 			if (sii_debug > 4)
1283 				printf("ds %x i %d\n", dstat, i);
1284 #endif
1285 			/* just clear the DNE bit and check errors later */
1286 			if (dstat & SII_DNE) {
1287 				regs->dstat = SII_DNE;
1288 				MachEmptyWriteBuffer();
1289 			}
1290 			break;
1291 
1292 		default:
1293 			printf("sii%d: Couldn't handle phase %d... ignoring.\n",
1294 				   sc - sii_softc, dstat & SII_PHASE_MSK);
1295 		}
1296 	}
1297 
1298 #ifdef DEBUG
1299 	if (sii_debug > 3)
1300 		printf("\n");
1301 #endif
1302 	/*
1303 	 * Check to make sure we won't be interrupted again.
1304 	 * Deglitch dstat register.
1305 	 */
1306 	msg = regs->dstat;
1307 	while (msg != (dstat = regs->dstat))
1308 		msg = dstat;
1309 	if (dstat & (SII_CI | SII_DI))
1310 		goto again;
1311 
1312 	if (sc->sc_target < 0) {
1313 		/* look for another device that is ready */
1314 		for (i = 0; i < SII_NCMD; i++) {
1315 			/* don't restart a disconnected command */
1316 			if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
1317 				continue;
1318 			sii_StartCmd(sc, i);
1319 			break;
1320 		}
1321 	}
1322 	return;
1323 
1324 abort:
1325 	/* jump here to abort the current command */
1326 	printf("sii%d: device %d: current command terminated\n",
1327 		sc - sii_softc, sc->sc_target);
1328 #ifdef DEBUG
1329 	sii_DumpLog();
1330 #endif
1331 
1332 	if ((cstat = regs->cstat) & SII_CON) {
1333 		/* try to send an abort msg for awhile */
1334 		regs->dstat = SII_DNE;
1335 		regs->data = SCSI_ABORT;
1336 		regs->comm = SII_INXFER | SII_ATN | (cstat & SII_STATE_MSK) |
1337 			SII_MSG_OUT_PHASE;
1338 		MachEmptyWriteBuffer();
1339 		SII_WAIT_UNTIL(dstat, regs->dstat,
1340 			(dstat & (SII_DNE | SII_PHASE_MSK)) ==
1341 			(SII_DNE | SII_MSG_OUT_PHASE),
1342 			2 * SII_WAIT_COUNT, i);
1343 #ifdef DEBUG
1344 		if (sii_debug > 0)
1345 			printf("Abort: cs %x ds %x i %d\n", cstat, dstat, i);
1346 #endif
1347 		if (dstat & (SII_DNE | SII_PHASE_MSK) ==
1348 		    (SII_DNE | SII_MSG_OUT_PHASE)) {
1349 			/* disconnect if command in progress */
1350 			regs->comm = SII_DISCON;
1351 			MachEmptyWriteBuffer();
1352 			SII_WAIT_UNTIL(cstat, regs->cstat,
1353 				!(cstat & SII_CON), SII_WAIT_COUNT, i);
1354 		}
1355 	} else {
1356 #ifdef DEBUG
1357 		if (sii_debug > 0)
1358 			printf("Abort: cs %x\n", cstat);
1359 #endif
1360 	}
1361 	regs->cstat = 0xffff;
1362 	regs->dstat = 0xffff;
1363 	regs->comm = 0;
1364 	MachEmptyWriteBuffer();
1365 
1366 	i = sc->sc_target;
1367 	sc->sc_target = -1;
1368 	sii_CmdDone(sc, i, EIO);
1369 #ifdef DEBUG
1370 	if (sii_debug > 4)
1371 		printf("sii_DoIntr: after CmdDone target %d\n", sc->sc_target);
1372 #endif
1373 }
1374 
1375 static void
1376 sii_StateChg(sc, cstat)
1377 	register struct siisoftc *sc;
1378 	register u_int cstat;
1379 {
1380 	register SIIRegs *regs = sc->sc_regs;
1381 	register State *state;
1382 	register int i;
1383 
1384 #ifdef DEBUG
1385 	if (sii_debug > 4)
1386 		printf("SCH: ");
1387 #endif
1388 
1389 	switch (cstat & SII_STATE_MSK) {
1390 	case 0:
1391 		/* disconnect */
1392 		i = sc->sc_target;
1393 		sc->sc_target = -1;
1394 #ifdef DEBUG
1395 		if (sii_debug > 4)
1396 			printf("disconn %d ", i);
1397 #endif
1398 		if (i >= 0 && !sc->sc_st[i].prevComm) {
1399 			printf("sii%d: device %d: spurrious disconnect (%d)\n",
1400 				sc - sii_softc, i, regs->slcsr);
1401 			sc->sc_st[i].prevComm = 0;
1402 		}
1403 		break;
1404 
1405 	case SII_CON:
1406 		/* connected as initiator */
1407 		i = regs->slcsr;
1408 		if (sc->sc_target == i)
1409 			break;
1410 		printf("sii%d: device %d: connect to device %d??\n",
1411 			sc - sii_softc, sc->sc_target, i);
1412 		sc->sc_target = i;
1413 		break;
1414 
1415 	case SII_DST:
1416 		/*
1417 		 * Wait for CON to become valid,
1418 		 * chip is slow sometimes.
1419 		 */
1420 		SII_WAIT_UNTIL(cstat, regs->cstat,
1421 			cstat & SII_CON, SII_WAIT_COUNT, i);
1422 		if (!(cstat & SII_CON))
1423 			panic("sii resel");
1424 		/* FALLTHROUGH */
1425 
1426 	case SII_CON | SII_DST:
1427 		/*
1428 		 * Its a reselection. Save the ID and wait for
1429 		 * interrupts to tell us what to do next
1430 		 * (should be MSG_IN of IDENTIFY).
1431 		 * NOTE: sc_target may be >= 0 if we were in
1432 		 * the process of trying to start a command
1433 		 * and were reselected before the select
1434 		 * command finished.
1435 		 */
1436 		sc->sc_target = i = regs->destat;
1437 		state = &sc->sc_st[i];
1438 		regs->comm = SII_CON | SII_DST | SII_MSG_IN_PHASE;
1439 		regs->dmctrl = state->dmaReqAck;
1440 		MachEmptyWriteBuffer();
1441 		if (!state->prevComm) {
1442 			printf("sii%d: device %d: spurrious reselection\n",
1443 				sc - sii_softc, i);
1444 			break;
1445 		}
1446 		state->prevComm = 0;
1447 #ifdef DEBUG
1448 		if (sii_debug > 4)
1449 			printf("resel %d ", sc->sc_target);
1450 #endif
1451 		break;
1452 
1453 #ifdef notyet
1454 	case SII_DST | SII_TGT:
1455 	case SII_CON | SII_DST | SII_TGT:
1456 		/* connected as target */
1457 		printf("sii%d: Selected by device %d as target!!\n",
1458 			sc - sii_softc, regs->destat);
1459 		regs->comm = SII_DISCON;
1460 		MachEmptyWriteBuffer();
1461 		SII_WAIT_UNTIL(!(regs->cstat & SII_CON),
1462 			SII_WAIT_COUNT, i);
1463 		regs->cstat = 0xffff;
1464 		regs->dstat = 0xffff;
1465 		regs->comm = 0;
1466 		break;
1467 #endif
1468 
1469 	default:
1470 		printf("sii%d: Unknown state change (cs %x)!!\n",
1471 			sc - sii_softc, cstat);
1472 #ifdef DEBUG
1473 		sii_DumpLog();
1474 #endif
1475 	}
1476 }
1477 
1478 /*
1479  * Read one byte of data.
1480  * If 'ack' is true, acknowledge the byte.
1481  */
1482 static int
1483 sii_GetByte(regs, phase, ack)
1484 	register SIIRegs *regs;
1485 	int phase, ack;
1486 {
1487 	register u_int dstat;
1488 	register u_int state;
1489 	register int i;
1490 	register int data;
1491 
1492 	dstat = regs->dstat;
1493 	state = regs->cstat & SII_STATE_MSK;
1494 	if (!(dstat & SII_IBF) || (dstat & SII_MIS)) {
1495 		regs->comm = state | phase;
1496 		MachEmptyWriteBuffer();
1497 		/* wait a short time for IBF */
1498 		SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_IBF,
1499 			SII_WAIT_COUNT, i);
1500 #ifdef DEBUG
1501 		if (!(dstat & SII_IBF))
1502 			printf("status no IBF\n");
1503 #endif
1504 	}
1505 	if (dstat & SII_DNE) { /* XXX */
1506 		printf("sii_GetByte: DNE set 5\n");
1507 #ifdef DEBUG
1508 		sii_DumpLog();
1509 #endif
1510 		regs->dstat = SII_DNE;
1511 	}
1512 	data = regs->data;
1513 	/* check for parity error */
1514 	if (dstat & SII_IPE) {
1515 #ifdef DEBUG
1516 		if (sii_debug > 4)
1517 			printf("cnt0 %d\n", i);
1518 #endif
1519 		printf("sii_GetByte: data %x ?? ds %x cm %x i %d\n",
1520 			data, dstat, regs->comm, i); /* XXX */
1521 		data = -1;
1522 		ack = 1;
1523 	}
1524 
1525 	if (ack) {
1526 		regs->comm = SII_INXFER | state | phase;
1527 		MachEmptyWriteBuffer();
1528 
1529 		/* wait a short time for XFER complete */
1530 		SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
1531 			SII_WAIT_COUNT, i);
1532 
1533 		/* clear the DNE */
1534 		if (dstat & SII_DNE) {
1535 			regs->dstat = SII_DNE;
1536 			MachEmptyWriteBuffer();
1537 		}
1538 	}
1539 
1540 	return (data);
1541 }
1542 
1543 /*
1544  * Exchange messages to initiate synchronous data transfers.
1545  */
1546 static void
1547 sii_DoSync(regs, state)
1548 	register SIIRegs *regs;
1549 	register State *state;
1550 {
1551 	register u_int dstat, comm;
1552 	register int i, j;
1553 	u_int len;
1554 
1555 #ifdef DEBUG
1556 	if (sii_debug)
1557 		printf("sii_DoSync: len %d per %d req/ack %d\n",
1558 			sii_buf[1], sii_buf[3], sii_buf[4]);
1559 #endif
1560 
1561 	/* SII chip can only handle a minimum transfer period of ??? */
1562 	if (sii_buf[3] < 64)
1563 		sii_buf[3] = 64;
1564 	/* SII chip can only handle a maximum REQ/ACK offset of 3 */
1565 	len = sii_buf[4];
1566 	if (len > 3)
1567 		len = 3;
1568 
1569 	sii_buf[0] = SCSI_EXTENDED_MSG;
1570 	sii_buf[1] = 3;		/* message length */
1571 	sii_buf[2] = SCSI_SYNCHRONOUS_XFER;
1572 	sii_buf[4] = len;
1573 #if 1
1574 	comm = SII_INXFER | SII_ATN | SII_MSG_OUT_PHASE |
1575 		(regs->cstat & SII_STATE_MSK);
1576 	regs->comm = comm & ~SII_INXFER;
1577 	for (j = 0; j < 5; j++) {
1578 		/* wait for target to request the next byte */
1579 		SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_TBE,
1580 			SII_WAIT_COUNT, i);
1581 		if (!(dstat & SII_TBE) ||
1582 		    (dstat & SII_PHASE_MSK) != SII_MSG_OUT_PHASE) {
1583 			printf("sii_DoSync: TBE? ds %x cm %x i %d\n",
1584 				dstat, comm, i); /* XXX */
1585 			return;
1586 		}
1587 
1588 		/* the last message byte should have ATN off */
1589 		if (j == 4)
1590 			comm &= ~SII_ATN;
1591 
1592 		regs->data = sii_buf[j];
1593 		regs->comm = comm;
1594 		MachEmptyWriteBuffer();
1595 
1596 		/* wait a short time for XFER complete */
1597 		SII_WAIT_UNTIL(dstat, regs->dstat, dstat & SII_DNE,
1598 			SII_WAIT_COUNT, i);
1599 
1600 		if (!(dstat & SII_DNE)) {
1601 			printf("sii_DoSync: DNE? ds %x cm %x i %d\n",
1602 				dstat, comm, i); /* XXX */
1603 			return;
1604 		}
1605 
1606 		/* clear the DNE, other errors handled later */
1607 		regs->dstat = SII_DNE;
1608 		MachEmptyWriteBuffer();
1609 	}
1610 #else
1611 	CopyToBuffer((u_short *)sii_buf, (volatile u_short *)SII_BUF_ADDR, 5);
1612 	printf("sii_DoSync: %x %x %x ds %x\n",
1613 		((volatile u_short *)SII_BUF_ADDR)[0],
1614 		((volatile u_short *)SII_BUF_ADDR)[2],
1615 		((volatile u_short *)SII_BUF_ADDR)[4],
1616 		regs->dstat); /* XXX */
1617 	regs->dmaddrl = (u_short)(SII_BUF_ADDR >> 1);
1618 	regs->dmaddrh = (u_short)(SII_BUF_ADDR >> 17) & 03;
1619 	regs->dmlotc = 5;
1620 	regs->comm = SII_DMA | SII_INXFER | SII_ATN |
1621 		(regs->cstat & SII_STATE_MSK) | SII_MSG_OUT_PHASE;
1622 	MachEmptyWriteBuffer();
1623 
1624 	/* wait a short time for XFER complete */
1625 	SII_WAIT_UNTIL(dstat, regs->dstat,
1626 		(dstat & (SII_DNE | SII_TCZ)) == (SII_DNE | SII_TCZ),
1627 		SII_WAIT_COUNT, i);
1628 
1629 	if ((dstat & (SII_DNE | SII_TCZ)) != (SII_DNE | SII_TCZ)) {
1630 		printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
1631 			dstat, regs->comm, i, regs->dmlotc); /* XXX */
1632 #ifdef DEBUG
1633 		sii_DumpLog(); /* XXX */
1634 #endif
1635 		return;
1636 	}
1637 	/* clear the DNE, other errors handled later */
1638 	regs->dstat = SII_DNE;
1639 	MachEmptyWriteBuffer();
1640 #endif
1641 
1642 #if 0
1643 	SII_WAIT_UNTIL(dstat, regs->dstat, dstat & (SII_CI | SII_DI),
1644 		SII_WAIT_COUNT, i);
1645 	printf("sii_DoSync: ds %x cm %x i %d lotc %d\n",
1646 		dstat, regs->comm, i, regs->dmlotc); /* XXX */
1647 #endif
1648 
1649 	state->dmaReqAck = len;
1650 }
1651 
1652 /*
1653  * Issue the sequence of commands to the controller to start DMA.
1654  * NOTE: the data buffer should be word-aligned for DMA out.
1655  */
1656 static void
1657 sii_StartDMA(regs, phase, dmaAddr, size)
1658 	register SIIRegs *regs;	/* which SII to use */
1659 	int phase;		/* phase to send/receive data */
1660 	u_short *dmaAddr;	/* DMA buffer address */
1661 	int size;		/* # of bytes to transfer */
1662 {
1663 
1664 	if (regs->dstat & SII_DNE) { /* XXX */
1665 		regs->dstat = SII_DNE;
1666 		printf("sii_StartDMA: DNE set\n");
1667 #ifdef DEBUG
1668 		sii_DumpLog();
1669 #endif
1670 	}
1671 	regs->dmaddrl = ((u_long)dmaAddr >> 1);
1672 	regs->dmaddrh = ((u_long)dmaAddr >> 17) & 03;
1673 	regs->dmlotc = size;
1674 	regs->comm = SII_DMA | SII_INXFER | (regs->cstat & SII_STATE_MSK) |
1675 		phase;
1676 	MachEmptyWriteBuffer();
1677 
1678 #ifdef DEBUG
1679 	if (sii_debug > 5) {
1680 		printf("sii_StartDMA: cs 0x%x, ds 0x%x, cm 0x%x, size %d\n",
1681 			regs->cstat, regs->dstat, regs->comm, size);
1682 	}
1683 #endif
1684 }
1685 
1686 /*
1687  * Call the device driver's 'done' routine to let it know the command is done.
1688  * The 'done' routine may try to start another command.
1689  * To be fair, we should start pending commands for other devices
1690  * before allowing the same device to start another command.
1691  */
1692 static void
1693 sii_CmdDone(sc, target, error)
1694 	register struct siisoftc *sc;	/* which SII to use */
1695 	int target;			/* which device is done */
1696 	int error;			/* error code if any errors */
1697 {
1698 	register ScsiCmd *scsicmd;
1699 	register int i;
1700 
1701 	scsicmd = sc->sc_cmd[target];
1702 #ifdef DIAGNOSTIC
1703 	if (target < 0 || !scsicmd)
1704 		panic("sii_CmdDone");
1705 #endif
1706 	sc->sc_cmd[target] = (ScsiCmd *)0;
1707 #ifdef DEBUG
1708 	if (sii_debug > 1) {
1709 		printf("sii_CmdDone: %s target %d cmd %x err %d resid %d\n",
1710 			scsicmd->sd->sd_driver->d_name, target,
1711 			scsicmd->cmd[0], error, sc->sc_st[target].buflen);
1712 	}
1713 #endif
1714 
1715 	/* look for another device that is ready */
1716 	for (i = 0; i < SII_NCMD; i++) {
1717 		/* don't restart a disconnected command */
1718 		if (!sc->sc_cmd[i] || sc->sc_st[i].prevComm)
1719 			continue;
1720 		sii_StartCmd(sc, i);
1721 		break;
1722 	}
1723 
1724 	(*scsicmd->sd->sd_driver->d_done)(scsicmd->unit, error,
1725 		sc->sc_st[target].buflen, sc->sc_st[target].statusByte);
1726 }
1727 
1728 #ifdef DEBUG
1729 sii_DumpLog()
1730 {
1731 	register struct sii_log *lp;
1732 
1733 	printf("sii: cmd %x bn %d cnt %d\n", sii_debug_cmd, sii_debug_bn,
1734 		sii_debug_sz);
1735 	lp = sii_logp;
1736 	do {
1737 		printf("target %d cs %x ds %x cm %x msg %x rlen %x dlen %x\n",
1738 			lp->target, lp->cstat, lp->dstat, lp->comm, lp->msg,
1739 			lp->rlen, lp->dlen);
1740 		if (++lp >= &sii_log[NLOG])
1741 			lp = sii_log;
1742 	} while (lp != sii_logp);
1743 }
1744 #endif
1745 #endif
1746