xref: /netbsd-src/sys/arch/x68k/dev/mha.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: mha.c,v 1.46 2007/10/17 19:58:02 garbled Exp $	*/
2 
3 /*-
4  * Copyright (c) 1996-1999 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Charles M. Hannum, Masaru Oki, Takumi Nakamura, Masanobu Saitoh and
9  * Minoura Makoto.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *        This product includes software developed by the NetBSD
22  *        Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38 */
39 
40 /*-
41  * Copyright (c) 1994 Jarle Greipsland
42  * All rights reserved.
43  *
44  * Redistribution and use in source and binary forms, with or without
45  * modification, are permitted provided that the following conditions
46  * are met:
47  * 1. Redistributions of source code must retain the above copyright
48  *    notice, this list of conditions and the following disclaimer.
49  * 2. Redistributions in binary form must reproduce the above copyright
50  *    notice, this list of conditions and the following disclaimer in the
51  *    documentation and/or other materials provided with the distribution.
52  * 3. The name of the author may not be used to endorse or promote products
53  *    derived from this software without specific prior written permission.
54  *
55  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
56  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
57  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
58  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
59  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
60  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
61  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
63  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
64  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
65  * POSSIBILITY OF SUCH DAMAGE.
66  */
67 
68 #include <sys/cdefs.h>
69 __KERNEL_RCSID(0, "$NetBSD: mha.c,v 1.46 2007/10/17 19:58:02 garbled Exp $");
70 
71 #include "opt_ddb.h"
72 
73 /* Synchronous data transfers? */
74 #define SPC_USE_SYNCHRONOUS	0
75 #define SPC_SYNC_REQ_ACK_OFS 	8
76 
77 /* Default DMA mode? */
78 #define MHA_DMA_LIMIT_XFER	1
79 #define MHA_DMA_BURST_XFER	1
80 #define MHA_DMA_SHORT_BUS_CYCLE	1
81 
82 #define MHA_DMA_DATAIN	(0 | (MHA_DMA_LIMIT_XFER << 1)		\
83 			   | (MHA_DMA_BURST_XFER << 2)		\
84 			   | (MHA_DMA_SHORT_BUS_CYCLE << 3))
85 #define MHA_DMA_DATAOUT	(1 | (MHA_DMA_LIMIT_XFER << 1)		\
86 			   | (MHA_DMA_BURST_XFER << 2)		\
87 			   | (MHA_DMA_SHORT_BUS_CYCLE << 3))
88 
89 /* Include debug functions?  At the end of this file there are a bunch of
90  * functions that will print out various information regarding queued SCSI
91  * commands, driver state and chip contents.  You can call them from the
92  * kernel debugger.  If you set SPC_DEBUG to 0 they are not included (the
93  * kernel uses less memory) but you lose the debugging facilities.
94  */
95 #define SPC_DEBUG		0
96 
97 /* End of customizable parameters */
98 
99 /*
100  * MB86601A SCSI Protocol Controller (SPC) routines for MANKAI Mach-2
101  */
102 
103 #include <sys/types.h>
104 #include <sys/param.h>
105 #include <sys/systm.h>
106 #include <sys/kernel.h>
107 #include <sys/errno.h>
108 #include <sys/ioctl.h>
109 #include <sys/device.h>
110 #include <sys/buf.h>
111 #include <sys/proc.h>
112 #include <sys/user.h>
113 #include <sys/queue.h>
114 
115 #include <machine/bus.h>
116 
117 #include <dev/scsipi/scsi_spc.h>
118 #include <dev/scsipi/scsi_all.h>
119 #include <dev/scsipi/scsipi_all.h>
120 #include <dev/scsipi/scsi_message.h>
121 #include <dev/scsipi/scsiconf.h>
122 
123 #include <x68k/x68k/iodevice.h>
124 #include <x68k/dev/mb86601reg.h>
125 #include <x68k/dev/mhavar.h>
126 #include <x68k/dev/intiovar.h>
127 #include <x68k/dev/scsiromvar.h>
128 
129 #if 0
130 #define WAIT {if (sc->sc_pc[2]) {printf("[W_%d", __LINE__); while (sc->sc_pc[2] & 0x40);printf("]");}}
131 #else
132 #define WAIT {while (sc->sc_pc[2] & 0x40);}
133 #endif
134 
135 #define SSR	(sc->sc_pc[2])
136 #define	SS_IREQUEST	0x80
137 #define	SS_BUSY		0x40
138 #define	SS_DREG_FULL	0x02
139 
140 #define	NSR	(sc->sc_pc[3])
141 
142 #define	SIR	(sc->sc_pc[4])
143 
144 #define	CMR	(sc->sc_pc[5])
145 #define	CMD_SEL_AND_CMD	0x00
146 #define	CMD_SELECT	0x09
147 #define	CMD_SET_ATN	0x0a
148 #define	CMD_RESET_ATN	0x0b
149 #define	CMD_RESET_ACK	0x0d
150 #define	CMD_SEND_FROM_MPU	0x10
151 #define	CMD_SEND_FROM_DMA	0x11
152 #define	CMD_RECEIVE_TO_MPU	0x12
153 #define	CMD_RECEIVE_TO_DMA	0x13
154 #define	CMD_RECEIVE_MSG	0x1a
155 #define	CMD_RECEIVE_STS	0x1c
156 #define	CMD_SOFT_RESET	0x40
157 #define	CMD_SCSI_RESET	0x42
158 #define	CMD_SET_UP_REG	0x43
159 
160 #define	SCR	(sc->sc_pc[11])
161 
162 #define	TMR	(sc->sc_pc[12])
163 #define	TM_SYNC		0x80
164 #define	TM_ASYNC	0x00
165 
166 #define	WAR	(sc->sc_pc[15])
167 #define	WA_MCSBUFWIN	0x00
168 #define	WA_UPMWIN	0x80
169 #define	WA_INITWIN	0xc0
170 
171 #define	MBR	(sc->sc_pc[15])
172 
173 #define ISCSR	(sc->sc_ps[2])
174 
175 #define	CCR	(sc->sc_pcx[0])
176 #define	OIR	(sc->sc_pcx[1])
177 #define	AMR	(sc->sc_pcx[2])
178 #define	SMR	(sc->sc_pcx[3])
179 #define	SRR	(sc->sc_pcx[4])
180 #define	STR	(sc->sc_pcx[5])
181 #define	RTR	(sc->sc_pcx[6])
182 #define	ATR	(sc->sc_pcx[7])
183 #define	PER	(sc->sc_pcx[8])
184 #define	IER	(sc->sc_pcx[9])
185 #define	IE_ALL	0xBF
186 
187 #define	GLR	(sc->sc_pcx[10])
188 #define	DMR	(sc->sc_pcx[11])
189 #define	IMR	(sc->sc_pcx[12])
190 
191 #ifndef DDB
192 #define	Debugger() panic("should call debugger here (mha.c)")
193 #endif /* ! DDB */
194 
195 
196 #if SPC_DEBUG
197 #define SPC_SHOWACBS	0x01
198 #define SPC_SHOWINTS	0x02
199 #define SPC_SHOWCMDS	0x04
200 #define SPC_SHOWMISC	0x08
201 #define SPC_SHOWTRAC	0x10
202 #define SPC_SHOWSTART	0x20
203 #define SPC_SHOWPHASE	0x40
204 #define SPC_SHOWDMA	0x80
205 #define SPC_SHOWCCMDS	0x100
206 #define SPC_SHOWMSGS	0x200
207 #define SPC_DOBREAK	0x400
208 
209 int mha_debug =
210 #if 0
211 0x7FF;
212 #else
213 SPC_SHOWSTART|SPC_SHOWTRAC;
214 #endif
215 
216 
217 #define SPC_ACBS(str)  do {if (mha_debug & SPC_SHOWACBS) printf str;} while (0)
218 #define SPC_MISC(str)  do {if (mha_debug & SPC_SHOWMISC) printf str;} while (0)
219 #define SPC_INTS(str)  do {if (mha_debug & SPC_SHOWINTS) printf str;} while (0)
220 #define SPC_TRACE(str) do {if (mha_debug & SPC_SHOWTRAC) printf str;} while (0)
221 #define SPC_CMDS(str)  do {if (mha_debug & SPC_SHOWCMDS) printf str;} while (0)
222 #define SPC_START(str) do {if (mha_debug & SPC_SHOWSTART) printf str;}while (0)
223 #define SPC_PHASE(str) do {if (mha_debug & SPC_SHOWPHASE) printf str;}while (0)
224 #define SPC_DMA(str)   do {if (mha_debug & SPC_SHOWDMA) printf str;}while (0)
225 #define SPC_MSGS(str)  do {if (mha_debug & SPC_SHOWMSGS) printf str;}while (0)
226 #define	SPC_BREAK()    do {if ((mha_debug & SPC_DOBREAK) != 0) Debugger();} while (0)
227 #define	SPC_ASSERT(x)  do {if (x) {} else {printf("%s at line %d: assertion failed\n", sc->sc_dev.dv_xname, __LINE__); Debugger();}} while (0)
228 #else
229 #define SPC_ACBS(str)
230 #define SPC_MISC(str)
231 #define SPC_INTS(str)
232 #define SPC_TRACE(str)
233 #define SPC_CMDS(str)
234 #define SPC_START(str)
235 #define SPC_PHASE(str)
236 #define SPC_DMA(str)
237 #define SPC_MSGS(str)
238 #define	SPC_BREAK()
239 #define	SPC_ASSERT(x)
240 #endif
241 
242 int	mhamatch(struct device *, struct cfdata *, void *);
243 void	mhaattach(struct device *, struct device *, void *);
244 void	mhaselect(struct mha_softc *, u_char, u_char, u_char *, u_char);
245 void	mha_scsi_reset(struct mha_softc *);
246 void	mha_reset(struct mha_softc *);
247 void	mha_free_acb(struct mha_softc *, struct acb *, int);
248 void	mha_sense(struct mha_softc *, struct acb *);
249 void	mha_msgin(struct mha_softc *);
250 void	mha_msgout(struct mha_softc *);
251 int	mha_dataout_pio(struct mha_softc *, u_char *, int);
252 int	mha_datain_pio(struct mha_softc *, u_char *, int);
253 int	mha_dataout(struct mha_softc *, u_char *, int);
254 int	mha_datain(struct mha_softc *, u_char *, int);
255 void	mha_abort(struct mha_softc *, struct acb *);
256 void 	mha_init(struct mha_softc *);
257 void	mha_scsi_request(struct scsipi_channel *, scsipi_adapter_req_t, void *);
258 void	mha_poll(struct mha_softc *, struct acb *);
259 void	mha_sched(struct mha_softc *);
260 void	mha_done(struct mha_softc *, struct acb *);
261 int	mhaintr(void *);
262 void	mha_timeout(void *);
263 void	mha_minphys(struct buf *);
264 void	mha_dequeue(struct mha_softc *, struct acb *);
265 inline void	mha_setsync(struct mha_softc *, struct spc_tinfo *);
266 #if SPC_DEBUG
267 void	mha_print_acb(struct acb *);
268 void	mha_show_scsi_cmd(struct acb *);
269 void	mha_print_active_acb(void);
270 void	mha_dump_driver(struct mha_softc *);
271 #endif
272 
273 static int mha_dataio_dma(int, int, struct mha_softc *, u_char *, int);
274 
275 CFATTACH_DECL(mha, sizeof(struct mha_softc),
276     mhamatch, mhaattach, NULL, NULL);
277 
278 extern struct cfdriver mha_cd;
279 
280 /*
281  * returns non-zero value if a controller is found.
282  */
283 int
284 mhamatch(struct device *parent, struct cfdata *cf, void *aux)
285 {
286 	struct intio_attach_args *ia = aux;
287 	bus_space_tag_t iot = ia->ia_bst;
288 	bus_space_handle_t ioh;
289 
290 	ia->ia_size=0x20;
291 	if (ia->ia_addr != 0xea0000)
292 		return 0;
293 
294 	if (intio_map_allocate_region(device_parent(parent), ia,
295 				      INTIO_MAP_TESTONLY) < 0) /* FAKE */
296 		return 0;
297 
298 	if (bus_space_map(iot, ia->ia_addr, 0x20, BUS_SPACE_MAP_SHIFTED,
299 			  &ioh) < 0)
300 		return 0;
301 	if (!badaddr(INTIO_ADDR(ia->ia_addr + 0)))
302 		return 0;
303 	bus_space_unmap(iot, ioh, 0x20);
304 
305 	return 1;
306 }
307 
308 /*
309  */
310 
311 struct mha_softc *tmpsc;
312 
313 void
314 mhaattach(struct device *parent, struct device *self, void *aux)
315 {
316 	struct mha_softc *sc = (void *)self;
317 	struct intio_attach_args *ia = aux;
318 
319 	tmpsc = sc;	/* XXX */
320 
321 	printf(": Mankai Mach-2 Fast SCSI Host Adaptor\n");
322 
323 	SPC_TRACE(("mhaattach  "));
324 	sc->sc_state = SPC_INIT;
325 	sc->sc_iobase = INTIO_ADDR(ia->ia_addr + 0x80); /* XXX */
326 	intio_map_allocate_region(device_parent(parent), ia, INTIO_MAP_ALLOCATE);
327 				/* XXX: FAKE  */
328 	sc->sc_dmat = ia->ia_dmat;
329 
330 	sc->sc_pc = (volatile u_char *)sc->sc_iobase;
331 	sc->sc_ps = (volatile u_short *)sc->sc_iobase;
332 	sc->sc_pcx = &sc->sc_pc[0x10];
333 
334 	sc->sc_id = IODEVbase->io_sram[0x70] & 0x7; /* XXX */
335 
336 	intio_intr_establish(ia->ia_intr, "mha", mhaintr, sc);
337 
338 	mha_init(sc);	/* Init chip and driver */
339 
340 	mha_scsi_reset(sc);	/* XXX: some devices need this. */
341 
342 	sc->sc_phase  = BUSFREE_PHASE;
343 
344 	/*
345 	 * Fill in the adapter.
346 	 */
347 	sc->sc_adapter.adapt_dev = &sc->sc_dev;
348 	sc->sc_adapter.adapt_nchannels = 1;
349 	sc->sc_adapter.adapt_openings = 7;
350 	sc->sc_adapter.adapt_max_periph = 1;
351 	sc->sc_adapter.adapt_ioctl = NULL;
352 	sc->sc_adapter.adapt_minphys = mha_minphys;
353 	sc->sc_adapter.adapt_request = mha_scsi_request;
354 
355 	sc->sc_channel.chan_adapter = &sc->sc_adapter;
356 	sc->sc_channel.chan_bustype = &scsi_bustype;
357 	sc->sc_channel.chan_channel = 0;
358 	sc->sc_channel.chan_ntargets = 8;
359 	sc->sc_channel.chan_nluns = 8;
360 	sc->sc_channel.chan_id = sc->sc_id;
361 
362 	sc->sc_spcinitialized = 0;
363 	WAR = WA_INITWIN;
364 #if 1
365 	CCR = 0x14;
366 	OIR = sc->sc_id;
367 	AMR = 0x00;
368 	SMR = 0x00;
369 	SRR = 0x00;
370 	STR = 0x20;
371 	RTR = 0x40;
372 	ATR = 0x01;
373 	PER = 0xc9;
374 #endif
375 	IER = IE_ALL;	/* $B$9$Y$F$N3d$j9~$_$r5v2D(B */
376 #if 1
377 	GLR = 0x00;
378 	DMR = 0x30;
379 	IMR = 0x00;
380 #endif
381 	WAR = WA_MCSBUFWIN;
382 
383 	/* drop off */
384 	while (SSR & SS_IREQUEST) {
385 		(void) ISCSR;
386 	}
387 
388 	CMR = CMD_SET_UP_REG;	/* setup reg cmd. */
389 
390 	SPC_TRACE(("waiting for intr..."));
391 	while (!(SSR & SS_IREQUEST))
392 		delay(10);
393 	mhaintr(sc);
394 
395 	tmpsc = NULL;
396 
397 	config_found(self, &sc->sc_channel, scsiprint);
398 }
399 
400 #if 0
401 void
402 mha_reset(struct mha_softc *sc)
403 {
404 	u_short	dummy;
405 printf("reset...");
406 	CMR = CMD_SOFT_RESET;
407 	__asm volatile ("nop");	/* XXX wait (4clk in 20 MHz) ??? */
408 	dummy = sc->sc_ps[-1];
409 	dummy = sc->sc_ps[-1];
410 	dummy = sc->sc_ps[-1];
411 	dummy = sc->sc_ps[-1];
412 	__asm volatile ("nop");
413 	CMR = CMD_SOFT_RESET;
414 	sc->sc_spcinitialized = 0;
415 	CMR = CMD_SET_UP_REG;	/* setup reg cmd. */
416 	while(!sc->sc_spcinitialized);
417 
418 	sc->sc_id = IODEVbase->io_sram[0x70] & 0x7; /* XXX */
419 printf("done.\n");
420 }
421 #endif
422 
423 /*
424  * Pull the SCSI RST line for 500us.
425  */
426 void
427 mha_scsi_reset(struct mha_softc *sc)
428 {
429 
430 	CMR = CMD_SCSI_RESET;	/* SCSI RESET */
431 	while (!(SSR&SS_IREQUEST))
432 		delay(10);
433 }
434 
435 /*
436  * Initialize mha SCSI driver.
437  */
438 void
439 mha_init(struct mha_softc *sc)
440 {
441 	struct acb *acb;
442 	int r;
443 
444 	if (sc->sc_state == SPC_INIT) {
445 		/* First time through; initialize. */
446 		TAILQ_INIT(&sc->ready_list);
447 		TAILQ_INIT(&sc->nexus_list);
448 		TAILQ_INIT(&sc->free_list);
449 		sc->sc_nexus = NULL;
450 		acb = sc->sc_acb;
451 		memset(acb, 0, sizeof(sc->sc_acb));
452 		for (r = 0; r < sizeof(sc->sc_acb) / sizeof(*acb); r++) {
453 			TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
454 			acb++;
455 		}
456 		memset(&sc->sc_tinfo, 0, sizeof(sc->sc_tinfo));
457 
458 		r = bus_dmamem_alloc(sc->sc_dmat, MAXBSIZE, 0, 0,
459 				     sc->sc_dmaseg, 1, &sc->sc_ndmasegs,
460 				     BUS_DMA_NOWAIT);
461 		if (r)
462 			panic("mha_init: cannot allocate DMA memory");
463 		if (sc->sc_ndmasegs != 1)
464 			panic("mha_init: number of segment > 1??");
465 		r = bus_dmamem_map(sc->sc_dmat, sc->sc_dmaseg, sc->sc_ndmasegs,
466 				   MAXBSIZE, &sc->sc_dmabuf, BUS_DMA_NOWAIT);
467 		if (r)
468 			panic("mha_init: cannot map DMA memory");
469 		r = bus_dmamap_create(sc->sc_dmat, MAXBSIZE, 1,
470 				      MAXBSIZE, 0, BUS_DMA_NOWAIT,
471 				      &sc->sc_dmamap);
472 		if (r)
473 			panic("mha_init: cannot create dmamap structure");
474 		r = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap,
475 				    sc->sc_dmabuf, MAXBSIZE, NULL,
476 				    BUS_DMA_NOWAIT);
477 		if (r)
478 			panic("mha_init: cannot load DMA buffer into dmamap");
479 		sc->sc_p = 0;
480 	} else {
481 		/* Cancel any active commands. */
482 		sc->sc_flags |= SPC_ABORTING;
483 		sc->sc_state = SPC_IDLE;
484 		if ((acb = sc->sc_nexus) != NULL) {
485 			acb->xs->error = XS_DRIVER_STUFFUP;
486 			mha_done(sc, acb);
487 		}
488 		while ((acb = sc->nexus_list.tqh_first) != NULL) {
489 			acb->xs->error = XS_DRIVER_STUFFUP;
490 			mha_done(sc, acb);
491 		}
492 	}
493 
494 	sc->sc_phase = sc->sc_prevphase = INVALID_PHASE;
495 	for (r = 0; r < 8; r++) {
496 		struct spc_tinfo *ti = &sc->sc_tinfo[r];
497 
498 		ti->flags = 0;
499 #if SPC_USE_SYNCHRONOUS
500 		ti->flags |= T_SYNCMODE;
501 		ti->period = sc->sc_minsync;
502 		ti->offset = SPC_SYNC_REQ_ACK_OFS;
503 #else
504 		ti->period = ti->offset = 0;
505 #endif
506 		ti->width = 0;
507 	}
508 
509 	sc->sc_state = SPC_IDLE;
510 }
511 
512 void
513 mha_free_acb(struct mha_softc *sc, struct acb *acb, int flags)
514 {
515 	int s;
516 
517 	s = splbio();
518 
519 	acb->flags = 0;
520 	TAILQ_INSERT_HEAD(&sc->free_list, acb, chain);
521 
522 	/*
523 	 * If there were none, wake anybody waiting for one to come free,
524 	 * starting with queued entries.
525 	 */
526 	if (acb->chain.tqe_next == 0)
527 		wakeup(&sc->free_list);
528 
529 	splx(s);
530 }
531 
532 /*
533  * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS
534  */
535 
536 /*
537  * Expected sequence:
538  * 1) Command inserted into ready list
539  * 2) Command selected for execution
540  * 3) Command won arbitration and has selected target device
541  * 4) Send message out (identify message, eventually also sync.negotiations)
542  * 5) Send command
543  * 5a) Receive disconnect message, disconnect.
544  * 5b) Reselected by target
545  * 5c) Receive identify message from target.
546  * 6) Send or receive data
547  * 7) Receive status
548  * 8) Receive message (command complete etc.)
549  * 9) If status == SCSI_CHECK construct a synthetic request sense SCSI cmd.
550  *    Repeat 2-8 (no disconnects please...)
551  */
552 
553 /*
554  * Start a selection.  This is used by mha_sched() to select an idle target,
555  * and by mha_done() to immediately reselect a target to get sense information.
556  */
557 void
558 mhaselect(struct mha_softc *sc, u_char target, u_char lun, u_char *cmd,
559     u_char clen)
560 {
561 	int i;
562 	int s;
563 
564 	s = splbio();	/* XXX */
565 
566 	SPC_TRACE(("[mhaselect(t%d,l%d,cmd:%x)] ", target, lun, *(u_char *)cmd));
567 
568 	/* CDB $B$r(B SPC $B$N(B MCS REG $B$K%;%C%H$9$k(B */
569 	/* Now the command into the FIFO */
570 	WAIT;
571 #if 1
572 	SPC_MISC(("[cmd:"));
573 	for (i = 0; i < clen; i++) {
574 		unsigned c = cmd[i];
575 		if (i == 1)
576 			c |= lun << 5;
577 		SPC_MISC((" %02x", c));
578 		sc->sc_pcx[i] = c;
579 	}
580 	SPC_MISC(("], target=%d\n", target));
581 #else
582 	memcpy(sc->sc_pcx, cmd, clen);
583 #endif
584 	if (NSR & 0x80)
585 		panic("scsistart: already selected...");
586 	sc->sc_phase  = COMMAND_PHASE;
587 
588 	/* new state ASP_SELECTING */
589 	sc->sc_state = SPC_SELECTING;
590 
591 	SIR = target;
592 #if 0
593 	CMR = CMD_SELECT;
594 #else
595 	CMR = CMD_SEL_AND_CMD;	/* select & cmd */
596 #endif
597 	splx(s);
598 }
599 
600 #if 0
601 int
602 mha_reselect(struct mha_softc *sc, u_char message)
603 {
604 	u_char selid, target, lun;
605 	struct acb *acb;
606 	struct scsipi_periph *periph;
607 	struct spc_tinfo *ti;
608 
609 	/*
610 	 * The SCSI chip made a snapshot of the data bus while the reselection
611 	 * was being negotiated.  This enables us to determine which target did
612 	 * the reselect.
613 	 */
614 	selid = sc->sc_selid & ~(1 << sc->sc_id);
615 	if (selid & (selid - 1)) {
616 		printf("%s: reselect with invalid selid %02x; sending DEVICE RESET\n",
617 		    sc->sc_dev.dv_xname, selid);
618 		SPC_BREAK();
619 		goto reset;
620 	}
621 
622 	/*
623 	 * Search wait queue for disconnected cmd
624 	 * The list should be short, so I haven't bothered with
625 	 * any more sophisticated structures than a simple
626 	 * singly linked list.
627 	 */
628 	target = ffs(selid) - 1;
629 	lun = message & 0x07;
630 	for (acb = sc->nexus_list.tqh_first; acb != NULL;
631 	     acb = acb->chain.tqe_next) {
632 		periph = acb->xs->xs_periph;
633 		if (periph->periph_target == target &&
634 		    periph->periph_lun == lun)
635 			break;
636 	}
637 	if (acb == NULL) {
638 		printf("%s: reselect from target %d lun %d with no nexus; sending ABORT\n",
639 		    sc->sc_dev.dv_xname, target, lun);
640 		SPC_BREAK();
641 		goto abort;
642 	}
643 
644 	/* Make this nexus active again. */
645 	TAILQ_REMOVE(&sc->nexus_list, acb, chain);
646 	sc->sc_state = SPC_HASNEXUS;
647 	sc->sc_nexus = acb;
648 	ti = &sc->sc_tinfo[target];
649 	ti->lubusy |= (1 << lun);
650 	mha_setsync(sc, ti);
651 
652 	if (acb->flags & ACB_RESET)
653 		mha_sched_msgout(sc, SEND_DEV_RESET);
654 	else if (acb->flags & ACB_ABORTED)
655 		mha_sched_msgout(sc, SEND_ABORT);
656 
657 	/* Do an implicit RESTORE POINTERS. */
658 	sc->sc_dp = acb->daddr;
659 	sc->sc_dleft = acb->dleft;
660 	sc->sc_cp = (u_char *)&acb->cmd;
661 	sc->sc_cleft = acb->clen;
662 
663 	return (0);
664 
665 reset:
666 	mha_sched_msgout(sc, SEND_DEV_RESET);
667 	return (1);
668 
669 abort:
670 	mha_sched_msgout(sc, SEND_ABORT);
671 	return (1);
672 }
673 #endif
674 /*
675  * Start a SCSI-command
676  * This function is called by the higher level SCSI-driver to queue/run
677  * SCSI-commands.
678  */
679 void
680 mha_scsi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
681     void *arg)
682 {
683 	struct scsipi_xfer *xs;
684 	struct scsipi_periph *periph;
685 	struct mha_softc *sc = (void *)chan->chan_adapter->adapt_dev;
686 	struct acb *acb;
687 	int s, flags;
688 
689 	switch (req) {
690 	case ADAPTER_REQ_RUN_XFER:
691 		xs = arg;
692 		periph = xs->xs_periph;
693 
694 		SPC_TRACE(("[mha_scsi_cmd] "));
695 		SPC_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen,
696 		    periph->periph_target));
697 
698 		flags = xs->xs_control;
699 
700 		/* Get a mha command block */
701 		s = splbio();
702 		acb = sc->free_list.tqh_first;
703 		if (acb) {
704 			TAILQ_REMOVE(&sc->free_list, acb, chain);
705 			ACB_SETQ(acb, ACB_QNONE);
706 		}
707 
708 		if (acb == NULL) {
709 			xs->error = XS_RESOURCE_SHORTAGE;
710 			scsipi_done(xs);
711 			splx(s);
712 			return;
713 		}
714 		splx(s);
715 
716 		/* Initialize acb */
717 		acb->xs = xs;
718 		memcpy(&acb->cmd, xs->cmd, xs->cmdlen);
719 		acb->clen = xs->cmdlen;
720 		acb->daddr = xs->data;
721 		acb->dleft = xs->datalen;
722 		acb->stat = 0;
723 
724 		s = splbio();
725 		ACB_SETQ(acb, ACB_QREADY);
726 		TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain);
727 #if 1
728 		callout_reset(&acb->xs->xs_callout,
729 		    mstohz(xs->timeout), mha_timeout, acb);
730 #endif
731 
732 		/*
733 		 * $B%-%e!<$N=hM}Cf$G$J$1$l$P!"%9%1%8%e!<%j%s%03+;O$9$k(B
734 		 */
735 		if (sc->sc_state == SPC_IDLE)
736 			mha_sched(sc);
737 
738 		splx(s);
739 
740 		if (flags & XS_CTL_POLL) {
741 			/* Not allowed to use interrupts, use polling instead */
742 			mha_poll(sc, acb);
743 		}
744 
745 		SPC_MISC(("SUCCESSFULLY_QUEUED"));
746 		return;
747 
748 	case ADAPTER_REQ_GROW_RESOURCES:
749 		/* XXX Not supported. */
750 		return;
751 
752 	case ADAPTER_REQ_SET_XFER_MODE:
753 		/* XXX Not supported. */
754 		return;
755 	}
756 }
757 
758 /*
759  * Adjust transfer size in buffer structure
760  */
761 void
762 mha_minphys(struct buf *bp)
763 {
764 
765 	SPC_TRACE(("mha_minphys  "));
766 	minphys(bp);
767 }
768 
769 /*
770  * Used when interrupt driven I/O isn't allowed, e.g. during boot.
771  */
772 void
773 mha_poll(struct mha_softc *sc, struct acb *acb)
774 {
775 	struct scsipi_xfer *xs = acb->xs;
776 	int count = xs->timeout * 100;
777 	int s;
778 
779 	s = splbio();
780 
781 	SPC_TRACE(("[mha_poll] "));
782 
783 	while (count) {
784 		/*
785 		 * If we had interrupts enabled, would we
786 		 * have got an interrupt?
787 		 */
788 		if (SSR & SS_IREQUEST)
789 			mhaintr(sc);
790 		if ((xs->xs_status & XS_STS_DONE) != 0)
791 			break;
792 		DELAY(10);
793 #if 1
794 		if (sc->sc_state == SPC_IDLE) {
795 			SPC_TRACE(("[mha_poll: rescheduling] "));
796 			mha_sched(sc);
797 		}
798 #endif
799 		count--;
800 	}
801 
802 	if (count == 0) {
803 		SPC_MISC(("mha_poll: timeout"));
804 		mha_timeout((void *)acb);
805 	}
806 	splx(s);
807 	scsipi_done(xs);
808 }
809 
810 /*
811  * LOW LEVEL SCSI UTILITIES
812  */
813 
814 /*
815  * Set synchronous transfer offset and period.
816  */
817 inline void
818 mha_setsync(struct mha_softc *sc, struct spc_tinfo *ti)
819 {
820 }
821 
822 /*
823  * Schedule a SCSI operation.  This has now been pulled out of the interrupt
824  * handler so that we may call it from mha_scsi_cmd and mha_done.  This may
825  * save us an unecessary interrupt just to get things going.  Should only be
826  * called when state == SPC_IDLE and at bio pl.
827  */
828 void
829 mha_sched(struct mha_softc *sc)
830 {
831 	struct scsipi_periph *periph;
832 	struct acb *acb;
833 	int t;
834 
835 	SPC_TRACE(("[mha_sched] "));
836 	if (sc->sc_state != SPC_IDLE)
837 		panic("mha_sched: not IDLE (state=%d)", sc->sc_state);
838 
839 	if (sc->sc_flags & SPC_ABORTING)
840 		return;
841 
842 	/*
843 	 * Find first acb in ready queue that is for a target/lunit
844 	 * combinations that is not busy.
845 	 */
846 	for (acb = sc->ready_list.tqh_first; acb ; acb = acb->chain.tqe_next) {
847 		struct spc_tinfo *ti;
848 		periph = acb->xs->xs_periph;
849 		t = periph->periph_target;
850 		ti = &sc->sc_tinfo[t];
851 		if (!(ti->lubusy & (1 << periph->periph_lun))) {
852 			if ((acb->flags & ACB_QBITS) != ACB_QREADY)
853 				panic("mha: busy entry on ready list");
854 			TAILQ_REMOVE(&sc->ready_list, acb, chain);
855 			ACB_SETQ(acb, ACB_QNONE);
856 			sc->sc_nexus = acb;
857 			sc->sc_flags = 0;
858 			sc->sc_prevphase = INVALID_PHASE;
859 			sc->sc_dp = acb->daddr;
860 			sc->sc_dleft = acb->dleft;
861 			ti->lubusy |= (1<<periph->periph_lun);
862 			mhaselect(sc, t, periph->periph_lun,
863 				     (u_char *)&acb->cmd, acb->clen);
864 			break;
865 		} else {
866 			SPC_MISC(("%d:%d busy\n",
867 			    periph->periph_target,
868 			    periph->periph_lun));
869 		}
870 	}
871 }
872 
873 /*
874  * POST PROCESSING OF SCSI_CMD (usually current)
875  */
876 void
877 mha_done(struct mha_softc *sc, struct acb *acb)
878 {
879 	struct scsipi_xfer *xs = acb->xs;
880 	struct scsipi_periph *periph = xs->xs_periph;
881 	struct spc_tinfo *ti = &sc->sc_tinfo[periph->periph_target];
882 
883 	SPC_TRACE(("[mha_done(error:%x)] ", xs->error));
884 
885 #if 1
886 	callout_stop(&acb->xs->xs_callout);
887 #endif
888 
889 	/*
890 	 * Now, if we've come here with no error code, i.e. we've kept the
891 	 * initial XS_NOERROR, and the status code signals that we should
892 	 * check sense, we'll need to set up a request sense cmd block and
893 	 * push the command back into the ready queue *before* any other
894 	 * commands for this target/lunit, else we lose the sense info.
895 	 * We don't support chk sense conditions for the request sense cmd.
896 	 */
897 	if (xs->error == XS_NOERROR) {
898 		if ((acb->flags & ACB_ABORTED) != 0) {
899 			xs->error = XS_TIMEOUT;
900 		} else if (acb->flags & ACB_CHKSENSE) {
901 			xs->error = XS_SENSE;
902 		} else {
903 			xs->status = acb->stat & ST_MASK;
904 			switch (xs->status) {
905 			case SCSI_CHECK:
906 				xs->resid = acb->dleft;
907 				/* FALLTHROUGH */
908 			case SCSI_BUSY:
909 				xs->error = XS_BUSY;
910 				break;
911 			case SCSI_OK:
912 				xs->resid = acb->dleft;
913 				break;
914 			default:
915 				xs->error = XS_DRIVER_STUFFUP;
916 #if SPC_DEBUG
917 				printf("%s: mha_done: bad stat 0x%x\n",
918 					sc->sc_dev.dv_xname, acb->stat);
919 #endif
920 				break;
921 			}
922 		}
923 	}
924 
925 #if SPC_DEBUG
926 	if ((mha_debug & SPC_SHOWMISC) != 0) {
927 		if (xs->resid != 0)
928 			printf("resid=%d ", xs->resid);
929 		if (xs->error == XS_SENSE)
930 			printf("sense=0x%02x\n", xs->sense.scsi_sense.response_code);
931 		else
932 			printf("error=%d\n", xs->error);
933 	}
934 #endif
935 
936 	/*
937 	 * Remove the ACB from whatever queue it's on.
938 	 */
939 	switch (acb->flags & ACB_QBITS) {
940 	case ACB_QNONE:
941 		if (acb != sc->sc_nexus) {
942 			panic("%s: floating acb", sc->sc_dev.dv_xname);
943 		}
944 		sc->sc_nexus = NULL;
945 		sc->sc_state = SPC_IDLE;
946 		ti->lubusy &= ~(1<<periph->periph_lun);
947 		mha_sched(sc);
948 		break;
949 	case ACB_QREADY:
950 		TAILQ_REMOVE(&sc->ready_list, acb, chain);
951 		break;
952 	case ACB_QNEXUS:
953 		TAILQ_REMOVE(&sc->nexus_list, acb, chain);
954 		ti->lubusy &= ~(1<<periph->periph_lun);
955 		break;
956 	case ACB_QFREE:
957 		panic("%s: dequeue: busy acb on free list",
958 			sc->sc_dev.dv_xname);
959 		break;
960 	default:
961 		panic("%s: dequeue: unknown queue %d",
962 			sc->sc_dev.dv_xname, acb->flags & ACB_QBITS);
963 	}
964 
965 	/* Put it on the free list, and clear flags. */
966 #if 0
967 	TAILQ_INSERT_HEAD(&sc->free_list, acb, chain);
968 	acb->flags = ACB_QFREE;
969 #else
970 	mha_free_acb(sc, acb, xs->xs_control);
971 #endif
972 
973 	ti->cmds++;
974 	scsipi_done(xs);
975 }
976 
977 void
978 mha_dequeue(struct mha_softc *sc, struct acb *acb)
979 {
980 
981 	if (acb->flags & ACB_QNEXUS) {
982 		TAILQ_REMOVE(&sc->nexus_list, acb, chain);
983 	} else {
984 		TAILQ_REMOVE(&sc->ready_list, acb, chain);
985 	}
986 }
987 
988 /*
989  * INTERRUPT/PROTOCOL ENGINE
990  */
991 
992 /*
993  * Schedule an outgoing message by prioritizing it, and asserting
994  * attention on the bus. We can only do this when we are the initiator
995  * else there will be an illegal command interrupt.
996  */
997 #define mha_sched_msgout(m) \
998 	do {				\
999 		SPC_MISC(("mha_sched_msgout %d ", m)); \
1000 		CMR = CMD_SET_ATN;	\
1001 		sc->sc_msgpriq |= (m);	\
1002 	} while (0)
1003 
1004 /*
1005  * Precondition:
1006  * The SCSI bus is already in the MSGI phase and there is a message byte
1007  * on the bus, along with an asserted REQ signal.
1008  */
1009 void
1010 mha_msgin(struct mha_softc *sc)
1011 {
1012 	int v;
1013 
1014 	SPC_TRACE(("[mha_msgin(curmsglen:%d)] ", sc->sc_imlen));
1015 
1016 	/*
1017 	 * Prepare for a new message.  A message should (according
1018 	 * to the SCSI standard) be transmitted in one single
1019 	 * MESSAGE_IN_PHASE. If we have been in some other phase,
1020 	 * then this is a new message.
1021 	 */
1022 	if (sc->sc_prevphase != MESSAGE_IN_PHASE) {
1023 		sc->sc_flags &= ~SPC_DROP_MSGI;
1024 		sc->sc_imlen = 0;
1025 	}
1026 
1027 	WAIT;
1028 
1029 	v = MBR;	/* modified byte */
1030 	v = sc->sc_pcx[0];
1031 
1032 	sc->sc_imess[sc->sc_imlen] = v;
1033 
1034 	/*
1035 	 * If we're going to reject the message, don't bother storing
1036 	 * the incoming bytes.  But still, we need to ACK them.
1037 	 */
1038 
1039 	if ((sc->sc_flags & SPC_DROP_MSGI)) {
1040 		CMR = CMD_SET_ATN;
1041 /*		ESPCMD(sc, ESPCMD_MSGOK);*/
1042 		printf("<dropping msg byte %x>",
1043 			sc->sc_imess[sc->sc_imlen]);
1044 		return;
1045 	}
1046 
1047 	if (sc->sc_imlen >= SPC_MAX_MSG_LEN) {
1048 		mha_sched_msgout(SEND_REJECT);
1049 		sc->sc_flags |= SPC_DROP_MSGI;
1050 	} else {
1051 		sc->sc_imlen++;
1052 		/*
1053 		 * This testing is suboptimal, but most
1054 		 * messages will be of the one byte variety, so
1055 		 * it should not effect performance
1056 		 * significantly.
1057 		 */
1058 		if (sc->sc_imlen == 1 && MSG_IS1BYTE(sc->sc_imess[0]))
1059 			goto gotit;
1060 		if (sc->sc_imlen == 2 && MSG_IS2BYTE(sc->sc_imess[0]))
1061 			goto gotit;
1062 		if (sc->sc_imlen >= 3 && MSG_ISEXTENDED(sc->sc_imess[0]) &&
1063 		    sc->sc_imlen == sc->sc_imess[1] + 2)
1064 			goto gotit;
1065 	}
1066 #if 0
1067 	/* Ack what we have so far */
1068 	ESPCMD(sc, ESPCMD_MSGOK);
1069 #endif
1070 	return;
1071 
1072 gotit:
1073 	SPC_MSGS(("gotmsg(%x)", sc->sc_imess[0]));
1074 	/*
1075 	 * Now we should have a complete message (1 byte, 2 byte
1076 	 * and moderately long extended messages).  We only handle
1077 	 * extended messages which total length is shorter than
1078 	 * SPC_MAX_MSG_LEN.  Longer messages will be amputated.
1079 	 */
1080 	if (sc->sc_state == SPC_HASNEXUS) {
1081 		struct acb *acb = sc->sc_nexus;
1082 		struct spc_tinfo *ti =
1083 			&sc->sc_tinfo[acb->xs->xs_periph->periph_target];
1084 
1085 		switch (sc->sc_imess[0]) {
1086 		case MSG_CMDCOMPLETE:
1087 			SPC_MSGS(("cmdcomplete "));
1088 			if (sc->sc_dleft < 0) {
1089 				struct scsipi_periph *periph = acb->xs->xs_periph;
1090 				printf("mha: %d extra bytes from %d:%d\n",
1091 					-sc->sc_dleft,
1092 					periph->periph_target,
1093 				        periph->periph_lun);
1094 				sc->sc_dleft = 0;
1095 			}
1096 			acb->xs->resid = acb->dleft = sc->sc_dleft;
1097 			sc->sc_flags |= SPC_BUSFREE_OK;
1098 			break;
1099 
1100 		case MSG_MESSAGE_REJECT:
1101 #if SPC_DEBUG
1102 			if (mha_debug & SPC_SHOWMSGS)
1103 				printf("%s: our msg rejected by target\n",
1104 					sc->sc_dev.dv_xname);
1105 #endif
1106 #if 1 /* XXX - must remember last message */
1107 			scsipi_printaddr(acb->xs->xs_periph);
1108 			printf("MSG_MESSAGE_REJECT>>");
1109 #endif
1110 			if (sc->sc_flags & SPC_SYNCHNEGO) {
1111 				ti->period = ti->offset = 0;
1112 				sc->sc_flags &= ~SPC_SYNCHNEGO;
1113 				ti->flags &= ~T_NEGOTIATE;
1114 			}
1115 			/* Not all targets understand INITIATOR_DETECTED_ERR */
1116 			if (sc->sc_msgout == SEND_INIT_DET_ERR)
1117 				mha_sched_msgout(SEND_ABORT);
1118 			break;
1119 		case MSG_NOOP:
1120 			SPC_MSGS(("noop "));
1121 			break;
1122 		case MSG_DISCONNECT:
1123 			SPC_MSGS(("disconnect "));
1124 			ti->dconns++;
1125 			sc->sc_flags |= SPC_DISCON;
1126 			sc->sc_flags |= SPC_BUSFREE_OK;
1127 			if ((acb->xs->xs_periph->periph_quirks & PQUIRK_AUTOSAVE) == 0)
1128 				break;
1129 			/*FALLTHROUGH*/
1130 		case MSG_SAVEDATAPOINTER:
1131 			SPC_MSGS(("save datapointer "));
1132 			acb->dleft = sc->sc_dleft;
1133 			acb->daddr = sc->sc_dp;
1134 			break;
1135 		case MSG_RESTOREPOINTERS:
1136 			SPC_MSGS(("restore datapointer "));
1137 			if (!acb) {
1138 				mha_sched_msgout(SEND_ABORT);
1139 				printf("%s: no DATAPOINTERs to restore\n",
1140 				    sc->sc_dev.dv_xname);
1141 				break;
1142 			}
1143 			sc->sc_dp = acb->daddr;
1144 			sc->sc_dleft = acb->dleft;
1145 			break;
1146 		case MSG_PARITY_ERROR:
1147 			printf("%s:target%d: MSG_PARITY_ERROR\n",
1148 				sc->sc_dev.dv_xname,
1149 				acb->xs->xs_periph->periph_target);
1150 			break;
1151 		case MSG_EXTENDED:
1152 			SPC_MSGS(("extended(%x) ", sc->sc_imess[2]));
1153 			switch (sc->sc_imess[2]) {
1154 			case MSG_EXT_SDTR:
1155 				SPC_MSGS(("SDTR period %d, offset %d ",
1156 					sc->sc_imess[3], sc->sc_imess[4]));
1157 				ti->period = sc->sc_imess[3];
1158 				ti->offset = sc->sc_imess[4];
1159 				if (sc->sc_minsync == 0) {
1160 					/* We won't do synch */
1161 					ti->offset = 0;
1162 					mha_sched_msgout(SEND_SDTR);
1163 				} else if (ti->offset == 0) {
1164 					printf("%s:%d: async\n", "mha",
1165 						acb->xs->xs_periph->periph_target);
1166 					ti->offset = 0;
1167 					sc->sc_flags &= ~SPC_SYNCHNEGO;
1168 				} else if (ti->period > 124) {
1169 					printf("%s:%d: async\n", "mha",
1170 						acb->xs->xs_periph->periph_target);
1171 					ti->offset = 0;
1172 					mha_sched_msgout(SEND_SDTR);
1173 				} else {
1174 #if 0
1175 					int p;
1176 					p =  mha_stp2cpb(sc, ti->period);
1177 					ti->period = mha_cpb2stp(sc, p);
1178 #endif
1179 
1180 #if SPC_DEBUG
1181 					scsipi_printaddr(acb->xs->xs_periph);
1182 #endif
1183 					if ((sc->sc_flags&SPC_SYNCHNEGO) == 0) {
1184 						/* Target initiated negotiation */
1185 						if (ti->flags & T_SYNCMODE) {
1186 						    ti->flags &= ~T_SYNCMODE;
1187 #if SPC_DEBUG
1188 						    printf("renegotiated ");
1189 #endif
1190 						}
1191 						TMR=TM_ASYNC;
1192 						/* Clamp to our maxima */
1193 						if (ti->period < sc->sc_minsync)
1194 							ti->period = sc->sc_minsync;
1195 						if (ti->offset > 15)
1196 							ti->offset = 15;
1197 						mha_sched_msgout(SEND_SDTR);
1198 					} else {
1199 						/* we are sync */
1200 						sc->sc_flags &= ~SPC_SYNCHNEGO;
1201 						TMR = TM_SYNC;
1202 						ti->flags |= T_SYNCMODE;
1203 					}
1204 				}
1205 				ti->flags &= ~T_NEGOTIATE;
1206 				break;
1207 			default: /* Extended messages we don't handle */
1208 				CMR = CMD_SET_ATN; /* XXX? */
1209 				break;
1210 			}
1211 			break;
1212 		default:
1213 			SPC_MSGS(("ident "));
1214 			/* thanks for that ident... */
1215 			if (!MSG_ISIDENTIFY(sc->sc_imess[0])) {
1216 				SPC_MISC(("unknown "));
1217 printf("%s: unimplemented message: %d\n", sc->sc_dev.dv_xname, sc->sc_imess[0]);
1218 				CMR = CMD_SET_ATN; /* XXX? */
1219 			}
1220 			break;
1221 		}
1222 	} else if (sc->sc_state == SPC_RESELECTED) {
1223 		struct scsipi_periph *periph = NULL;
1224 		struct acb *acb;
1225 		struct spc_tinfo *ti;
1226 		u_char lunit;
1227 
1228 		if (MSG_ISIDENTIFY(sc->sc_imess[0])) { 	/* Identify? */
1229 			SPC_MISC(("searching "));
1230 			/*
1231 			 * Search wait queue for disconnected cmd
1232 			 * The list should be short, so I haven't bothered with
1233 			 * any more sophisticated structures than a simple
1234 			 * singly linked list.
1235 			 */
1236 			lunit = sc->sc_imess[0] & 0x07;
1237 			for (acb = sc->nexus_list.tqh_first; acb;
1238 			     acb = acb->chain.tqe_next) {
1239 				periph = acb->xs->xs_periph;
1240 				if (periph->periph_lun == lunit &&
1241 				    sc->sc_selid == (1<<periph->periph_target)) {
1242 					TAILQ_REMOVE(&sc->nexus_list, acb,
1243 					    chain);
1244 					ACB_SETQ(acb, ACB_QNONE);
1245 					break;
1246 				}
1247 			}
1248 
1249 			if (!acb) {		/* Invalid reselection! */
1250 				mha_sched_msgout(SEND_ABORT);
1251 				printf("mha: invalid reselect (idbit=0x%2x)\n",
1252 				    sc->sc_selid);
1253 			} else {		/* Reestablish nexus */
1254 				/*
1255 				 * Setup driver data structures and
1256 				 * do an implicit RESTORE POINTERS
1257 				 */
1258 				ti = &sc->sc_tinfo[periph->periph_target];
1259 				sc->sc_nexus = acb;
1260 				sc->sc_dp = acb->daddr;
1261 				sc->sc_dleft = acb->dleft;
1262 				sc->sc_tinfo[periph->periph_target].lubusy
1263 					|= (1<<periph->periph_lun);
1264 				if (ti->flags & T_SYNCMODE) {
1265 					TMR = TM_SYNC;	/* XXX */
1266 				} else {
1267 					TMR = TM_ASYNC;
1268 				}
1269 				SPC_MISC(("... found acb"));
1270 				sc->sc_state = SPC_HASNEXUS;
1271 			}
1272 		} else {
1273 			printf("%s: bogus reselect (no IDENTIFY) %0x2x\n",
1274 			    sc->sc_dev.dv_xname, sc->sc_selid);
1275 			mha_sched_msgout(SEND_DEV_RESET);
1276 		}
1277 	} else { /* Neither SPC_HASNEXUS nor SPC_RESELECTED! */
1278 		printf("%s: unexpected message in; will send DEV_RESET\n",
1279 		    sc->sc_dev.dv_xname);
1280 		mha_sched_msgout(SEND_DEV_RESET);
1281 	}
1282 
1283 	/* Ack last message byte */
1284 #if 0
1285 	ESPCMD(sc, ESPCMD_MSGOK);
1286 #endif
1287 
1288 	/* Done, reset message pointer. */
1289 	sc->sc_flags &= ~SPC_DROP_MSGI;
1290 	sc->sc_imlen = 0;
1291 }
1292 
1293 /*
1294  * Send the highest priority, scheduled message.
1295  */
1296 void
1297 mha_msgout(struct mha_softc *sc)
1298 {
1299 #if (SPC_USE_SYNCHRONOUS || SPC_USE_WIDE)
1300 	struct spc_tinfo *ti;
1301 #endif
1302 	int n;
1303 
1304 	SPC_TRACE(("mha_msgout  "));
1305 
1306 	if (sc->sc_prevphase == MESSAGE_OUT_PHASE) {
1307 		if (sc->sc_omp == sc->sc_omess) {
1308 			/*
1309 			 * This is a retransmission.
1310 			 *
1311 			 * We get here if the target stayed in MESSAGE OUT
1312 			 * phase.  Section 5.1.9.2 of the SCSI 2 spec indicates
1313 			 * that all of the previously transmitted messages must
1314 			 * be sent again, in the same order.  Therefore, we
1315 			 * requeue all the previously transmitted messages, and
1316 			 * start again from the top.  Our simple priority
1317 			 * scheme keeps the messages in the right order.
1318 			 */
1319 			SPC_MISC(("retransmitting  "));
1320 			sc->sc_msgpriq |= sc->sc_msgoutq;
1321 			/*
1322 			 * Set ATN.  If we're just sending a trivial 1-byte
1323 			 * message, we'll clear ATN later on anyway.
1324 			 */
1325 			CMR = CMD_SET_ATN; /* XXX? */
1326 		} else {
1327 			/* This is a continuation of the previous message. */
1328 			n = sc->sc_omp - sc->sc_omess;
1329 			goto nextbyte;
1330 		}
1331 	}
1332 
1333 	/* No messages transmitted so far. */
1334 	sc->sc_msgoutq = 0;
1335 	sc->sc_lastmsg = 0;
1336 
1337 nextmsg:
1338 	/* Pick up highest priority message. */
1339 	sc->sc_currmsg = sc->sc_msgpriq & -sc->sc_msgpriq;
1340 	sc->sc_msgpriq &= ~sc->sc_currmsg;
1341 	sc->sc_msgoutq |= sc->sc_currmsg;
1342 
1343 	/* Build the outgoing message data. */
1344 	switch (sc->sc_currmsg) {
1345 	case SEND_IDENTIFY:
1346 		SPC_ASSERT(sc->sc_nexus != NULL);
1347 		sc->sc_omess[0] =
1348 		    MSG_IDENTIFY(sc->sc_nexus->xs->xs_periph->periph_lun, 1);
1349 		n = 1;
1350 		break;
1351 
1352 #if SPC_USE_SYNCHRONOUS
1353 	case SEND_SDTR:
1354 		SPC_ASSERT(sc->sc_nexus != NULL);
1355 		ti = &sc->sc_tinfo[sc->sc_nexus->xs->xs_periph->periph_target];
1356 		sc->sc_omess[4] = MSG_EXTENDED;
1357 		sc->sc_omess[3] = 3;
1358 		sc->sc_omess[2] = MSG_EXT_SDTR;
1359 		sc->sc_omess[1] = ti->period >> 2;
1360 		sc->sc_omess[0] = ti->offset;
1361 		n = 5;
1362 		break;
1363 #endif
1364 
1365 #if SPC_USE_WIDE
1366 	case SEND_WDTR:
1367 		SPC_ASSERT(sc->sc_nexus != NULL);
1368 		ti = &sc->sc_tinfo[sc->sc_nexus->xs->xs_periph->periph_target];
1369 		sc->sc_omess[3] = MSG_EXTENDED;
1370 		sc->sc_omess[2] = 2;
1371 		sc->sc_omess[1] = MSG_EXT_WDTR;
1372 		sc->sc_omess[0] = ti->width;
1373 		n = 4;
1374 		break;
1375 #endif
1376 
1377 	case SEND_DEV_RESET:
1378 		sc->sc_flags |= SPC_ABORTING;
1379 		sc->sc_omess[0] = MSG_BUS_DEV_RESET;
1380 		n = 1;
1381 		break;
1382 
1383 	case SEND_REJECT:
1384 		sc->sc_omess[0] = MSG_MESSAGE_REJECT;
1385 		n = 1;
1386 		break;
1387 
1388 	case SEND_PARITY_ERROR:
1389 		sc->sc_omess[0] = MSG_PARITY_ERROR;
1390 		n = 1;
1391 		break;
1392 
1393 	case SEND_INIT_DET_ERR:
1394 		sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
1395 		n = 1;
1396 		break;
1397 
1398 	case SEND_ABORT:
1399 		sc->sc_flags |= SPC_ABORTING;
1400 		sc->sc_omess[0] = MSG_ABORT;
1401 		n = 1;
1402 		break;
1403 
1404 	default:
1405 		printf("%s: unexpected MESSAGE OUT; sending NOOP\n",
1406 		    sc->sc_dev.dv_xname);
1407 		SPC_BREAK();
1408 		sc->sc_omess[0] = MSG_NOOP;
1409 		n = 1;
1410 		break;
1411 	}
1412 	sc->sc_omp = &sc->sc_omess[n];
1413 
1414 nextbyte:
1415 	/* Send message bytes. */
1416 	/* send TRANSFER command. */
1417 	sc->sc_ps[3] = 1;
1418 	sc->sc_ps[4] = n >> 8;
1419 	sc->sc_pc[10] = n;
1420 	sc->sc_ps[-1] = 0x000F;	/* burst */
1421 	__asm volatile ("nop");
1422 	CMR = CMD_SEND_FROM_DMA;	/* send from DMA */
1423 	for (;;) {
1424 		if ((SSR & SS_BUSY) != 0)
1425 			break;
1426 		if (SSR & SS_IREQUEST)
1427 			goto out;
1428 	}
1429 	for (;;) {
1430 #if 0
1431 		for (;;) {
1432 			if ((PSNS & PSNS_REQ) != 0)
1433 				break;
1434 			/* Wait for REQINIT.  XXX Need timeout. */
1435 		}
1436 #endif
1437 		if (SSR & SS_IREQUEST) {
1438 			/*
1439 			 * Target left MESSAGE OUT, possibly to reject
1440 			 * our message.
1441 			 *
1442 			 * If this is the last message being sent, then we
1443 			 * deassert ATN, since either the target is going to
1444 			 * ignore this message, or it's going to ask for a
1445 			 * retransmission via MESSAGE PARITY ERROR (in which
1446 			 * case we reassert ATN anyway).
1447 			 */
1448 #if 0
1449 			if (sc->sc_msgpriq == 0)
1450 				CMR = CMD_RESET_ATN;
1451 #endif
1452 			goto out;
1453 		}
1454 
1455 #if 0
1456 		/* Clear ATN before last byte if this is the last message. */
1457 		if (n == 1 && sc->sc_msgpriq == 0)
1458 			CMR = CMD_RESET_ATN;
1459 #endif
1460 
1461 		while ((SSR & SS_DREG_FULL) != 0)
1462 			;
1463 		/* Send message byte. */
1464 		sc->sc_pc[0] = *--sc->sc_omp;
1465 		--n;
1466 		/* Keep track of the last message we've sent any bytes of. */
1467 		sc->sc_lastmsg = sc->sc_currmsg;
1468 
1469 		if (n == 0)
1470 			break;
1471 	}
1472 
1473 	/* We get here only if the entire message has been transmitted. */
1474 	if (sc->sc_msgpriq != 0) {
1475 		/* There are more outgoing messages. */
1476 		goto nextmsg;
1477 	}
1478 
1479 	/*
1480 	 * The last message has been transmitted.  We need to remember the last
1481 	 * message transmitted (in case the target switches to MESSAGE IN phase
1482 	 * and sends a MESSAGE REJECT), and the list of messages transmitted
1483 	 * this time around (in case the target stays in MESSAGE OUT phase to
1484 	 * request a retransmit).
1485 	 */
1486 
1487 out:
1488 	/* Disable REQ/ACK protocol. */
1489 	return;
1490 }
1491 
1492 /***************************************************************
1493  *
1494  *	datain/dataout
1495  *
1496  */
1497 
1498 int
1499 mha_datain_pio(struct mha_softc *sc, u_char *p, int n)
1500 {
1501 	u_short d;
1502 	int a;
1503 	int total_n = n;
1504 
1505 	SPC_TRACE(("[mha_datain_pio(%p,%d)", p, n));
1506 
1507 	WAIT;
1508 	sc->sc_ps[3] = 1;
1509 	sc->sc_ps[4] = n >> 8;
1510 	sc->sc_pc[10] = n;
1511 	/* $BHa$7$-%=%U%HE>Aw(B */
1512 	CMR = CMD_RECEIVE_TO_MPU;
1513 	for (;;) {
1514 		a = SSR;
1515 		if (a & 0x04) {
1516 			d = sc->sc_ps[0];
1517 			*p++ = d >> 8;
1518 			if (--n > 0) {
1519 				*p++ = d;
1520 				--n;
1521 			}
1522 			a = SSR;
1523 		}
1524 		if (a & 0x40)
1525 			continue;
1526 		if (a & 0x80)
1527 			break;
1528 	}
1529 	SPC_TRACE(("...%d resd]", n));
1530 	return total_n - n;
1531 }
1532 
1533 int
1534 mha_dataout_pio(struct mha_softc *sc, u_char *p, int n)
1535 {
1536 	u_short d;
1537 	int a;
1538 	int total_n = n;
1539 
1540 	SPC_TRACE(("[mha_dataout_pio(%p,%d)", p, n));
1541 
1542 	WAIT;
1543 	sc->sc_ps[3] = 1;
1544 	sc->sc_ps[4] = n >> 8;
1545 	sc->sc_pc[10] = n;
1546 	/* $BHa$7$-%=%U%HE>Aw(B */
1547 	CMR = CMD_SEND_FROM_MPU;
1548 	for (;;) {
1549 		a = SSR;
1550 		if (a & 0x04) {
1551 			d = *p++ << 8;
1552 			if (--n > 0) {
1553 				d |= *p++;
1554 				--n;
1555 			}
1556 			sc->sc_ps[0] = d;
1557 			a = SSR;
1558 		}
1559 		if (a & 0x40)
1560 			continue;
1561 		if (a & 0x80)
1562 			break;
1563 	}
1564 	SPC_TRACE(("...%d resd]", n));
1565 	return total_n - n;
1566 }
1567 
1568 /*
1569  * dw: DMA word
1570  * cw: CMR word
1571  */
1572 static int
1573 mha_dataio_dma(int dw, int cw, struct mha_softc *sc, u_char *p, int n)
1574 {
1575 	char *paddr;
1576 
1577 	if (n > MAXBSIZE)
1578 		panic("transfer size exceeds MAXBSIZE");
1579 	if (sc->sc_dmasize > 0)
1580 		panic("DMA request while another DMA transfer is in pregress");
1581 
1582 	if (cw == CMD_SEND_FROM_DMA) {
1583 		memcpy(sc->sc_dmabuf, p, n);
1584 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, n, BUS_DMASYNC_PREWRITE);
1585 	} else {
1586 		bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap, 0, n, BUS_DMASYNC_PREREAD);
1587 	}
1588 	sc->sc_p = p;
1589 	sc->sc_dmasize = n;
1590 
1591 	paddr = (char *)sc->sc_dmaseg[0].ds_addr;
1592 #if MHA_DMA_SHORT_BUS_CYCLE == 1
1593 	if ((*(volatile int *)&IODEVbase->io_sram[0xac]) &
1594 	    (1 << ((paddr_t)paddr >> 19)))
1595 		dw &= ~(1 << 3);
1596 #endif
1597 	sc->sc_pc[0x80 + (((long)paddr >> 16) & 0xFF)] = 0;
1598 	sc->sc_pc[0x180 + (((long)paddr >> 8) & 0xFF)] = 0;
1599 	sc->sc_pc[0x280 + (((long)paddr >> 0) & 0xFF)] = 0;
1600 	WAIT;
1601 	sc->sc_ps[3] = 1;
1602 	sc->sc_ps[4] = n >> 8;
1603 	sc->sc_pc[10] = n;
1604 	/* DMA $BE>Aw@)8f$O0J2<$NDL$j!#(B
1605 	   3 ... short bus cycle
1606 	   2 ... MAXIMUM XFER.
1607 	   1 ... BURST XFER.
1608 	   0 ... R/W */
1609 	sc->sc_ps[-1] = dw;	/* burst */
1610 	__asm volatile ("nop");
1611 	CMR = cw;	/* receive to DMA */
1612 	return n;
1613 }
1614 
1615 int
1616 mha_dataout(struct mha_softc *sc, u_char *p, int n)
1617 {
1618 	if (n == 0)
1619 		return n;
1620 
1621 	if (n & 1)
1622 		return mha_dataout_pio(sc, p, n);
1623 	return mha_dataio_dma(MHA_DMA_DATAOUT, CMD_SEND_FROM_DMA, sc, p, n);
1624 }
1625 
1626 int
1627 mha_datain(struct mha_softc *sc, u_char *p, int n)
1628 {
1629 	 struct acb *acb = sc->sc_nexus;
1630 
1631 	 if (n == 0)
1632 		 return n;
1633 	 if (acb->cmd.opcode == SCSI_REQUEST_SENSE || (n & 1))
1634 		 return mha_datain_pio(sc, p, n);
1635 	 return mha_dataio_dma(MHA_DMA_DATAIN, CMD_RECEIVE_TO_DMA, sc, p, n);
1636 }
1637 
1638 /*
1639  * Catch an interrupt from the adaptor
1640  */
1641 /*
1642  * This is the workhorse routine of the driver.
1643  * Deficiencies (for now):
1644  * 1) always uses programmed I/O
1645  */
1646 int
1647 mhaintr(void *arg)
1648 {
1649 	struct mha_softc *sc = arg;
1650 #if 0
1651 	u_char ints;
1652 #endif
1653 	struct acb *acb;
1654 	u_char ph;
1655 	u_short r;
1656 	int n;
1657 
1658 #if 1	/* XXX called during attach? */
1659 	if (tmpsc != NULL) {
1660 		SPC_MISC(("[%p %p]\n", mha_cd.cd_devs, sc));
1661 		sc = tmpsc;
1662 	} else {
1663 #endif
1664 
1665 #if 1	/* XXX */
1666 	}
1667 #endif
1668 
1669 #if 0
1670 	/*
1671 	 * $B3d$j9~$_6X;_$K$9$k(B
1672 	 */
1673 	SCTL &= ~SCTL_INTR_ENAB;
1674 #endif
1675 
1676 	SPC_TRACE(("[mhaintr]"));
1677 
1678 	/*
1679 	 * $BA4E>Aw$,40A4$K=*N;$9$k$^$G%k!<%W$9$k(B
1680 	 */
1681 	/*
1682 	 * First check for abnormal conditions, such as reset.
1683 	 */
1684 #if 0
1685 #if 1 /* XXX? */
1686 	while (((ints = SSR) & SS_IREQUEST) == 0)
1687 		delay(1);
1688 	SPC_MISC(("ints = 0x%x  ", ints));
1689 #else /* usually? */
1690 	ints = SSR;
1691 #endif
1692 #endif
1693 	while (SSR & SS_IREQUEST) {
1694 		acb = sc->sc_nexus;
1695 		r = ISCSR;
1696 		SPC_MISC(("[r=0x%x]", r));
1697 		switch (r >> 8) {
1698 		default:
1699 			printf("[addr=%p\n"
1700 			       "result=0x%x\n"
1701 			       "cmd=0x%x\n"
1702 			       "ph=0x%x(ought to be %d)]\n",
1703 			       &ISCSR,
1704 			       r,
1705 			       acb->xs->cmd->opcode,
1706 			       SCR, sc->sc_phase);
1707 			panic("unexpected result.");
1708 		case 0x82:	/* selection timeout */
1709 			SPC_MISC(("selection timeout  "));
1710 			sc->sc_phase = BUSFREE_PHASE;
1711 			SPC_ASSERT(sc->sc_nexus != NULL);
1712 			acb = sc->sc_nexus;
1713 			delay(250);
1714 			acb->xs->error = XS_SELTIMEOUT;
1715 			mha_done(sc, acb);
1716 			continue;	/* XXX ??? msaitoh */
1717 		case 0x60:	/* command completed */
1718 			sc->sc_spcinitialized++;
1719 			if (sc->sc_phase == BUSFREE_PHASE)
1720 				continue;
1721 			ph = SCR;
1722 			if (ph & PSNS_ACK) {
1723 				int s;
1724 				/* $B$U$D!<$N%3%^%s%I$,=*N;$7$?$i$7$$(B */
1725 				SPC_MISC(("0x60)phase = %x(ought to be %x)\n",
1726 					  ph & PHASE_MASK, sc->sc_phase));
1727 #if 0
1728 /*				switch (sc->sc_phase) {*/
1729 #else
1730 				switch (ph & PHASE_MASK) {
1731 #endif
1732 				case STATUS_PHASE:
1733 					if (sc->sc_state != SPC_HASNEXUS)
1734 						printf("stsin: !SPC_HASNEXUS->(%d)\n",
1735 						       sc->sc_state);
1736 					SPC_ASSERT(sc->sc_nexus != NULL);
1737 					acb = sc->sc_nexus;
1738 					WAIT;
1739 					s = MBR;
1740 					SPC_ASSERT(s == 1);
1741 					acb->stat = sc->sc_pcx[0]; /* XXX */
1742 					SPC_MISC(("stat=0x%02x  ", acb->stat));
1743 					sc->sc_prevphase = STATUS_PHASE;
1744 					break;
1745 				case MESSAGE_IN_PHASE:
1746 					mha_msgin(sc);
1747 					sc->sc_prevphase = MESSAGE_IN_PHASE;
1748 					/* thru */
1749 				case DATA_IN_PHASE:
1750 					if (sc->sc_dmasize == 0)
1751 						break;
1752 					bus_dmamap_sync(sc->sc_dmat,
1753 							sc->sc_dmamap,
1754 							0, sc->sc_dmasize,
1755 							BUS_DMASYNC_POSTREAD);
1756 					memcpy(sc->sc_p, sc->sc_dmabuf,
1757 					       sc->sc_dmasize);
1758 					sc->sc_dmasize = 0;
1759 					break;
1760 				case DATA_OUT_PHASE:
1761 					if (sc->sc_dmasize == 0)
1762 						break;
1763 					bus_dmamap_sync(sc->sc_dmat,
1764 							sc->sc_dmamap,
1765 							0, sc->sc_dmasize,
1766 							BUS_DMASYNC_POSTWRITE);
1767 					sc->sc_dmasize = 0;
1768 					break;
1769 				}
1770 				WAIT;
1771 				CMR = CMD_RESET_ACK;	/* reset ack */
1772 				/*mha_done(sc, acb);	XXX */
1773 				continue;
1774 			} else if (NSR & 0x80) { /* nexus */
1775 #if 1
1776 				if (sc->sc_state == SPC_SELECTING)	/* XXX msaitoh */
1777 					sc->sc_state = SPC_HASNEXUS;
1778 				/* $B%U%'!<%:$N7h$aBG$A$r$9$k(B
1779 				   $B30$l$?$i!"(Binitial-phase error(0x54) $B$,(B
1780 				   $BJV$C$F$/$k$s$GCm0U$7$?$^$(!#(B
1781 				   $B$G$b$J$<$+(B 0x65 $B$,JV$C$F$-$?$j$7$F$M!<$+(B? */
1782 				WAIT;
1783 				if (SSR & SS_IREQUEST)
1784 					continue;
1785 				switch (sc->sc_phase) {
1786 				default:
1787 					panic("$B8+CN$i$L(B phase $B$,Mh$A$^$C$?$@$h(B");
1788 				case MESSAGE_IN_PHASE:
1789 					/* $B2?$b$7$J$$(B */
1790 					continue;
1791 				case STATUS_PHASE:
1792 					sc->sc_phase = MESSAGE_IN_PHASE;
1793 					CMR = CMD_RECEIVE_MSG;	/* receive msg */
1794 					continue;
1795 				case DATA_IN_PHASE:
1796 					sc->sc_prevphase = DATA_IN_PHASE;
1797 					if (sc->sc_dleft == 0) {
1798 						/* $BE>Aw%G!<%?$O$b$&$J$$$N$G(B
1799 						   $B%9%F!<%?%9%U%'!<%:$r4|BT$7$h$&(B */
1800 						sc->sc_phase = STATUS_PHASE;
1801 						CMR = CMD_RECEIVE_STS;	/* receive sts */
1802 						continue;
1803 					}
1804 					n = mha_datain(sc, sc->sc_dp,
1805 						       sc->sc_dleft);
1806 					sc->sc_dp += n;
1807 					sc->sc_dleft -= n;
1808 					continue;
1809 				case DATA_OUT_PHASE:
1810 					sc->sc_prevphase = DATA_OUT_PHASE;
1811 					if (sc->sc_dleft == 0) {
1812 						/* $BE>Aw%G!<%?$O$b$&$J$$$N$G(B
1813 						   $B%9%F!<%?%9%U%'!<%:$r4|BT$7$h$&(B */
1814 						sc->sc_phase = STATUS_PHASE;
1815 						CMR = CMD_RECEIVE_STS;	/* receive sts */
1816 						continue;
1817 					}
1818 					/* data phase $B$NB3$-$r$d$m$&(B */
1819 					n = mha_dataout(sc, sc->sc_dp, sc->sc_dleft);
1820 					sc->sc_dp += n;
1821 					sc->sc_dleft -= n;
1822 					continue;
1823 				case COMMAND_PHASE:
1824 					/* $B:G=i$O(B CMD PHASE $B$H$$$&$3$H$i$7$$(B */
1825 					if (acb->dleft) {
1826 						/* $B%G!<%?E>Aw$,$"$j$&$k>l9g(B */
1827 						if (acb->xs->xs_control & XS_CTL_DATA_IN) {
1828 							sc->sc_phase = DATA_IN_PHASE;
1829 							n = mha_datain(sc, sc->sc_dp, sc->sc_dleft);
1830 							sc->sc_dp += n;
1831 							sc->sc_dleft -= n;
1832 						}
1833 						else if (acb->xs->xs_control & XS_CTL_DATA_OUT) {
1834 							sc->sc_phase = DATA_OUT_PHASE;
1835 							n = mha_dataout(sc, sc->sc_dp, sc->sc_dleft);
1836 							sc->sc_dp += n;
1837 							sc->sc_dleft -= n;
1838 						}
1839 						continue;
1840 					}
1841 					else {
1842 						/* $B%G!<%?E>Aw$O$J$$$i$7$$(B?! */
1843 						WAIT;
1844 						sc->sc_phase = STATUS_PHASE;
1845 						CMR = CMD_RECEIVE_STS;	/* receive sts */
1846 						continue;
1847 					}
1848 				}
1849 #endif
1850 			}
1851 			continue;
1852 		case 0x31:	/* disconnected in xfer progress. */
1853 			SPC_MISC(("[0x31]"));
1854 		case 0x70:	/* disconnected. */
1855 			SPC_ASSERT(sc->sc_flags & SPC_BUSFREE_OK);
1856 			sc->sc_phase = BUSFREE_PHASE;
1857 			sc->sc_state = SPC_IDLE;
1858 #if 1
1859 			acb = sc->sc_nexus;
1860 			SPC_ASSERT(sc->sc_nexus != NULL);
1861 			acb->xs->error = XS_NOERROR;
1862 			mha_done(sc, acb);
1863 #else
1864 			TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain);
1865 			mha_sched(sc);
1866 #endif
1867 			continue;
1868 		case 0x32:	/* phase error in xfer progress. */
1869 			SPC_MISC(("[0x32]"));
1870 #if 0
1871 		case 0x65:	/* invalid command.
1872 				   $B$J$<$3$s$J$b$N$,=P$k$N$+(B
1873 				   $B26$K$OA4$/M}2r$G$-$J$$(B */
1874 #if 1
1875 			SPC_MISC(("[0x%04x]", r));
1876 #endif
1877 #endif
1878 		case 0x54:	/* initial-phase error. */
1879 			SPC_MISC(("[0x54, ns=%x, ph=%x(ought to be %x)]",
1880 				  NSR,
1881 				  SCR, sc->sc_phase));
1882 			/* thru */
1883 		case 0x71:	/* assert req */
1884 			WAIT;
1885 			if (SSR & 0x40) {
1886 				printf("SPC sts=%2x, r=%04x, ns=%x, ph=%x\n",
1887 				       SSR, r, NSR, SCR);
1888 				WAIT;
1889 			}
1890 			ph = SCR;
1891 			if (sc->sc_state == SPC_SELECTING) {	/* XXX msaitoh */
1892 				sc->sc_state = SPC_HASNEXUS;
1893 			}
1894 			if (ph & 0x80) {
1895 				switch (ph & PHASE_MASK) {
1896 				default:
1897 					printf("phase = %x\n", ph);
1898 					panic("assert req: the phase I don't know!");
1899 				case DATA_IN_PHASE:
1900 					sc->sc_prevphase = DATA_IN_PHASE;
1901 					SPC_MISC(("DATAIN(%d)...", sc->sc_dleft));
1902 					n = mha_datain(sc, sc->sc_dp, sc->sc_dleft);
1903 					sc->sc_dp += n;
1904 					sc->sc_dleft -= n;
1905 					SPC_MISC(("done\n"));
1906 					continue;
1907 				case DATA_OUT_PHASE:
1908 					sc->sc_prevphase = DATA_OUT_PHASE;
1909 					SPC_MISC(("DATAOUT\n"));
1910 					n = mha_dataout(sc, sc->sc_dp, sc->sc_dleft);
1911 					sc->sc_dp += n;
1912 					sc->sc_dleft -= n;
1913 					continue;
1914 				case STATUS_PHASE:
1915 					sc->sc_phase = STATUS_PHASE;
1916 					SPC_MISC(("[RECV_STS]"));
1917 					WAIT;
1918 					CMR = CMD_RECEIVE_STS;	/* receive sts */
1919 					continue;
1920 				case MESSAGE_IN_PHASE:
1921 					sc->sc_phase = MESSAGE_IN_PHASE;
1922 					WAIT;
1923 					CMR = CMD_RECEIVE_MSG;
1924 					continue;
1925 				}
1926 			}
1927 			continue;
1928 		}
1929 	}
1930 
1931 	return 1;
1932 }
1933 
1934 void
1935 mha_abort(struct mha_softc *sc, struct acb *acb)
1936 {
1937 	acb->flags |= ACB_ABORTED;
1938 
1939 	if (acb == sc->sc_nexus) {
1940 		/*
1941 		 * If we're still selecting, the message will be scheduled
1942 		 * after selection is complete.
1943 		 */
1944 		if (sc->sc_state == SPC_HASNEXUS) {
1945 			sc->sc_flags |= SPC_ABORTING;
1946 			mha_sched_msgout(SEND_ABORT);
1947 		}
1948 	} else {
1949 		if (sc->sc_state == SPC_IDLE)
1950 			mha_sched(sc);
1951 	}
1952 }
1953 
1954 void
1955 mha_timeout(void *arg)
1956 {
1957 	struct acb *acb = (struct acb *)arg;
1958 	struct scsipi_xfer *xs = acb->xs;
1959 	struct scsipi_periph *periph = xs->xs_periph;
1960 	struct mha_softc *sc =
1961 	    (void *)periph->periph_channel->chan_adapter->adapt_dev;
1962 	int s;
1963 
1964 	s = splbio();
1965 
1966 	scsipi_printaddr(periph);
1967 	printf("%s: timed out [acb %p (flags 0x%x, dleft %x, stat %x)], "
1968 	       "<state %d, nexus %p, phase(c %x, p %x), resid %x, msg(q %x,o %x) >",
1969 		sc->sc_dev.dv_xname,
1970 		acb, acb->flags, acb->dleft, acb->stat,
1971 		sc->sc_state, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase,
1972 		sc->sc_dleft, sc->sc_msgpriq, sc->sc_msgout
1973 		);
1974 	printf("[%04x %02x]\n", sc->sc_ps[1], SCR);
1975 	panic("timeout, ouch!");
1976 
1977 	if (acb->flags & ACB_ABORTED) {
1978 		/* abort timed out */
1979 		printf(" AGAIN\n");
1980 #if 0
1981 		mha_init(sc, 1); /* XXX 1?*/
1982 #endif
1983 	} else {
1984 		/* abort the operation that has timed out */
1985 		printf("\n");
1986 		xs->error = XS_TIMEOUT;
1987 		mha_abort(sc, acb);
1988 	}
1989 
1990 	splx(s);
1991 }
1992 
1993 #if SPC_DEBUG
1994 /*
1995  * The following functions are mostly used for debugging purposes, either
1996  * directly called from the driver or from the kernel debugger.
1997  */
1998 
1999 void
2000 mha_show_scsi_cmd(struct acb *acb)
2001 {
2002 	u_char *b = (u_char *)&acb->cmd;
2003 	struct scsipi_periph *periph = acb->xs->xs_periph;
2004 	int i;
2005 
2006 	scsipi_printaddr(periph);
2007 	if ((acb->xs->xs_control & XS_CTL_RESET) == 0) {
2008 		for (i = 0; i < acb->clen; i++) {
2009 			if (i)
2010 				printf(",");
2011 			printf("%x", b[i]);
2012 		}
2013 		printf("\n");
2014 	} else
2015 		printf("RESET\n");
2016 }
2017 
2018 void
2019 mha_print_acb(struct acb *acb)
2020 {
2021 
2022 	printf("acb@%p xs=%p flags=%x", acb, acb->xs, acb->flags);
2023 	printf(" dp=%p dleft=%d stat=%x\n",
2024 	    acb->daddr, acb->dleft, acb->stat);
2025 	mha_show_scsi_cmd(acb);
2026 }
2027 
2028 void
2029 mha_print_active_acb(void)
2030 {
2031 	struct acb *acb;
2032 	struct mha_softc *sc = mha_cd.cd_devs[0]; /* XXX */
2033 
2034 	printf("ready list:\n");
2035 	for (acb = sc->ready_list.tqh_first; acb != NULL;
2036 	    acb = acb->chain.tqe_next)
2037 		mha_print_acb(acb);
2038 	printf("nexus:\n");
2039 	if (sc->sc_nexus != NULL)
2040 		mha_print_acb(sc->sc_nexus);
2041 	printf("nexus list:\n");
2042 	for (acb = sc->nexus_list.tqh_first; acb != NULL;
2043 	    acb = acb->chain.tqe_next)
2044 		mha_print_acb(acb);
2045 }
2046 
2047 void
2048 mha_dump_driver(struct mha_softc *sc)
2049 {
2050 	struct spc_tinfo *ti;
2051 	int i;
2052 
2053 	printf("nexus=%p prevphase=%x\n", sc->sc_nexus, sc->sc_prevphase);
2054 	printf("state=%x msgin=%x msgpriq=%x msgoutq=%x lastmsg=%x currmsg=%x\n",
2055 	    sc->sc_state, sc->sc_imess[0],
2056 	    sc->sc_msgpriq, sc->sc_msgoutq, sc->sc_lastmsg, sc->sc_currmsg);
2057 	for (i = 0; i < 7; i++) {
2058 		ti = &sc->sc_tinfo[i];
2059 		printf("tinfo%d: %d cmds %d disconnects %d timeouts",
2060 		    i, ti->cmds, ti->dconns, ti->touts);
2061 		printf(" %d senses flags=%x\n", ti->senses, ti->flags);
2062 	}
2063 }
2064 #endif
2065