xref: /netbsd/sys/arch/arc/jazz/asc.c (revision c4a72b64)
1 /*	$NetBSD: asc.c,v 1.8 2002/10/02 04:59:48 thorpej Exp $	*/
2 /*	$OpenBSD: asc.c,v 1.9 1998/03/16 09:38:39 pefo Exp $	*/
3 /*	NetBSD: asc.c,v 1.10 1994/12/05 19:11:12 dean Exp 	*/
4 
5 /*-
6  * Copyright (c) 1992, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * Ralph Campbell and Rick Macklem.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. All advertising materials mentioning features or use of this software
21  *    must display the following acknowledgement:
22  *	This product includes software developed by the University of
23  *	California, Berkeley and its contributors.
24  * 4. Neither the name of the University nor the names of its contributors
25  *    may be used to endorse or promote products derived from this software
26  *    without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38  * SUCH DAMAGE.
39  *
40  *	@(#)asc.c	8.3 (Berkeley) 7/3/94
41  */
42 
43 /*
44  * Mach Operating System
45  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
46  * All Rights Reserved.
47  *
48  * Permission to use, copy, modify and distribute this software and its
49  * documentation is hereby granted, provided that both the copyright
50  * notice and this permission notice appear in all copies of the
51  * software, derivative works or modified versions, and any portions
52  * thereof, and that both notices appear in supporting documentation.
53  *
54  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
55  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
56  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
57  *
58  * Carnegie Mellon requests users of this software to return to
59  *
60  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
61  *  School of Computer Science
62  *  Carnegie Mellon University
63  *  Pittsburgh PA 15213-3890
64  *
65  * any improvements or extensions that they make and grant Carnegie the
66  * rights to redistribute these changes.
67  */
68 
69 /*
70  * HISTORY
71  * Log:	scsi_53C94_hdw.c,v
72  * Revision 2.5  91/02/05  17:45:07  mrt
73  * 	Added author notices
74  * 	[91/02/04  11:18:43  mrt]
75  *
76  * 	Changed to use new Mach copyright
77  * 	[91/02/02  12:17:20  mrt]
78  *
79  * Revision 2.4  91/01/08  15:48:24  rpd
80  * 	Added continuation argument to thread_block.
81  * 	[90/12/27            rpd]
82  *
83  * Revision 2.3  90/12/05  23:34:48  af
84  * 	Recovered from pmax merge.. and from the destruction of a disk.
85  * 	[90/12/03  23:40:40  af]
86  *
87  * Revision 2.1.1.1  90/11/01  03:39:09  af
88  * 	Created, from the DEC specs:
89  * 	"PMAZ-AA TURBOchannel SCSI Module Functional Specification"
90  * 	Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990.
91  * 	And from the NCR data sheets
92  * 	"NCR 53C94, 53C95, 53C96 Advances SCSI Controller"
93  * 	[90/09/03            af]
94  */
95 
96 /*
97  *	File: scsi_53C94_hdw.h
98  * 	Author: Alessandro Forin, Carnegie Mellon University
99  *	Date:	9/90
100  *
101  *	Bottom layer of the SCSI driver: chip-dependent functions
102  *
103  *	This file contains the code that is specific to the NCR 53C94
104  *	SCSI chip (Host Bus Adapter in SCSI parlance): probing, start
105  *	operation, and interrupt routine.
106  */
107 
108 /*
109  * This layer works based on small simple 'scripts' that are installed
110  * at the start of the command and drive the chip to completion.
111  * The idea comes from the specs of the NCR 53C700 'script' processor.
112  *
113  * There are various reasons for this, mainly
114  * - Performance: identify the common (successful) path, and follow it;
115  *   at interrupt time no code is needed to find the current status
116  * - Code size: it should be easy to compact common operations
117  * - Adaptability: the code skeleton should adapt to different chips without
118  *   terrible complications.
119  * - Error handling: and it is easy to modify the actions performed
120  *   by the scripts to cope with strange but well identified sequences
121  *
122  */
123 
124 #include <sys/param.h>
125 #include <sys/systm.h>
126 #include <sys/dkstat.h>
127 #include <sys/buf.h>
128 #include <sys/proc.h>
129 #include <sys/conf.h>
130 #include <sys/errno.h>
131 #include <sys/device.h>
132 #include <uvm/uvm_extern.h>
133 
134 #include <dev/scsipi/scsi_all.h>
135 #include <dev/scsipi/scsipi_all.h>
136 #include <dev/scsipi/scsiconf.h>
137 
138 #include <mips/cache.h>
139 
140 #include <machine/cpu.h>
141 #include <machine/autoconf.h>
142 #include <machine/bus.h>
143 
144 #include <arc/jazz/jazziovar.h>
145 #include <arc/jazz/jazzdmatlbreg.h>
146 #include <arc/jazz/dma.h>
147 #include <arc/jazz/scsi.h>
148 #include <arc/jazz/ascreg.h>
149 #include <arc/jazz/ascvar.h>
150 
151 #include <arc/jazz/pica.h>
152 
153 
154 #define	readback(a)	{ register int foo; foo = (a); }
155 
156 /*
157  * In 4ns ticks.
158  */
159 int	asc_to_scsi_period[] = {
160 	32,
161 	33,
162 	34,
163 	35,
164 	5,
165 	5,
166 	6,
167 	7,
168 	8,
169 	9,
170 	10,
171 	11,
172 	12,
173 	13,
174 	14,
175 	15,
176 	16,
177 	17,
178 	18,
179 	19,
180 	20,
181 	21,
182 	22,
183 	23,
184 	24,
185 	25,
186 	26,
187 	27,
188 	28,
189 	29,
190 	30,
191 	31,
192 };
193 
194 /*
195  * Internal forward declarations.
196  */
197 struct asc_softc;
198 static void asc_reset __P((struct asc_softc *, asc_regmap_t *));
199 static void asc_startcmd __P((struct asc_softc *, int));
200 
201 #ifdef DEBUG
202 int	asc_debug = 1;
203 int	asc_debug_cmd;
204 int	asc_debug_bn;
205 int	asc_debug_sz;
206 #define NLOG 16
207 struct asc_log {
208 	u_int	status;
209 	u_char	state;
210 	u_char	msg;
211 	int	target;
212 	int	resid;
213 } asc_log[NLOG], *asc_logp = asc_log;
214 #define PACK(unit, status, ss, ir) \
215 	((unit << 24) | (status << 16) | (ss << 8) | ir)
216 #endif
217 
218 /*
219  * Scripts are entries in a state machine table.
220  * A script has four parts: a pre-condition, an action, a command to the chip,
221  * and an index into asc_scripts for the next state. The first triggers error
222  * handling if not satisfied and in our case it is formed by the
223  * values of the interrupt register and status register, this
224  * basically captures the phase of the bus and the TC and BS
225  * bits.  The action part is just a function pointer, and the
226  * command is what the 53C94 should be told to do at the end
227  * of the action processing.  This command is only issued and the
228  * script proceeds if the action routine returns TRUE.
229  * See asc_intr() for how and where this is all done.
230  */
231 typedef struct script {
232 	int		condition;	/* expected state at interrupt time */
233 	int		(*action)(struct asc_softc *, int, int, int);
234 					/* extra operations */
235 	int		command;	/* command to the chip */
236 	struct script	*next;		/* index into asc_scripts for next state */
237 } script_t;
238 
239 /* Matching on the condition value */
240 #define	SCRIPT_MATCH(ir, csr)		((ir) | (((csr) & 0x67) << 8))
241 
242 
243 /* forward decls of script actions */
244 	/* when nothing needed */
245 static int script_nop __P((struct asc_softc *, int, int, int));
246 	/* all come to an end */
247 static int asc_end __P((struct asc_softc *, int, int, int));
248 	/* get status from target */
249 static int asc_get_status __P((struct asc_softc *, int, int, int));
250 	/* start reading data from target */
251 static int asc_dma_in __P((struct asc_softc *, int, int, int));
252 	/* cleanup after all data is read */
253 static int asc_last_dma_in __P((struct asc_softc *, int, int, int));
254 	/* resume data in after a message */
255 static int asc_resume_in __P((struct asc_softc *, int, int, int));
256 	/* resume DMA after a disconnect */
257 static int asc_resume_dma_in __P((struct asc_softc *, int, int, int));
258 	/* send data to target via dma */
259 static int asc_dma_out __P((struct asc_softc *, int, int, int));
260 	/* cleanup after all data is written */
261 static int asc_last_dma_out __P((struct asc_softc *, int, int, int));
262 	/* resume data out after a message */
263 static int asc_resume_out __P((struct asc_softc *, int, int, int));
264 	/* resume DMA after a disconnect */
265 static int asc_resume_dma_out __P((struct asc_softc *, int, int, int));
266 	/* negotiate sync xfer */
267 static int asc_sendsync __P((struct asc_softc *, int, int, int));
268 	/* negotiate sync xfer */
269 static int asc_replysync __P((struct asc_softc *, int, int, int));
270 	/* process a message byte */
271 static int asc_msg_in __P((struct asc_softc *, int, int, int));
272 	/* process an expected disconnect */
273 static int asc_disconnect __P((struct asc_softc *, int, int, int));
274 
275 /* Define the index into asc_scripts for various state transitions */
276 #define	SCRIPT_DATA_IN		0
277 #define	SCRIPT_CONTINUE_IN	2
278 #define	SCRIPT_DATA_OUT		3
279 #define	SCRIPT_CONTINUE_OUT	5
280 #define	SCRIPT_SIMPLE		6
281 #define	SCRIPT_GET_STATUS	7
282 #define	SCRIPT_DONE		8
283 #define	SCRIPT_MSG_IN		9
284 #define	SCRIPT_REPLY_SYNC	11
285 #define	SCRIPT_TRY_SYNC		12
286 #define	SCRIPT_DISCONNECT	15
287 #define	SCRIPT_RESEL		16
288 #define	SCRIPT_RESUME_IN	17
289 #define	SCRIPT_RESUME_DMA_IN	18
290 #define	SCRIPT_RESUME_OUT	19
291 #define	SCRIPT_RESUME_DMA_OUT	20
292 #define	SCRIPT_RESUME_NO_DATA	21
293 
294 /*
295  * Scripts
296  */
297 script_t asc_scripts[] = {
298 	/* start data in */
299 	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAI),	/*  0 */
300 		asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
301 		&asc_scripts[SCRIPT_DATA_IN + 1]},
302 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),			/*  1 */
303 		asc_last_dma_in, ASC_CMD_I_COMPLETE,
304 		&asc_scripts[SCRIPT_GET_STATUS]},
305 
306 	/* continue data in after a chunk is finished */
307 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),			/*  2 */
308 		asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
309 		&asc_scripts[SCRIPT_DATA_IN + 1]},
310 
311 	/* start data out */
312 	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAO),	/*  3 */
313 		asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
314 		&asc_scripts[SCRIPT_DATA_OUT + 1]},
315 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),			/*  4 */
316 		asc_last_dma_out, ASC_CMD_I_COMPLETE,
317 		&asc_scripts[SCRIPT_GET_STATUS]},
318 
319 	/* continue data out after a chunk is finished */
320 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),			/*  5 */
321 		asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
322 		&asc_scripts[SCRIPT_DATA_OUT + 1]},
323 
324 	/* simple command with no data transfer */
325 	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_STATUS),	/*  6 */
326 		script_nop, ASC_CMD_I_COMPLETE,
327 		&asc_scripts[SCRIPT_GET_STATUS]},
328 
329 	/* get status and finish command */
330 	{SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN),			/*  7 */
331 		asc_get_status, ASC_CMD_MSG_ACPT,
332 		&asc_scripts[SCRIPT_DONE]},
333 	{SCRIPT_MATCH(ASC_INT_DISC, 0),					/*  8 */
334 		asc_end, ASC_CMD_NOP,
335 		&asc_scripts[SCRIPT_DONE]},
336 
337 	/* message in */
338 	{SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN),			/*  9 */
339 		asc_msg_in, ASC_CMD_MSG_ACPT,
340 		&asc_scripts[SCRIPT_MSG_IN + 1]},
341 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN),			/* 10 */
342 		script_nop, ASC_CMD_XFER_INFO,
343 		&asc_scripts[SCRIPT_MSG_IN]},
344 
345 	/* send synchonous negotiation reply */
346 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_OUT),			/* 11 */
347 		asc_replysync, ASC_CMD_XFER_INFO,
348 		&asc_scripts[SCRIPT_REPLY_SYNC]},
349 
350 	/* try to negotiate synchonous transfer parameters */
351 	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_MSG_OUT),	/* 12 */
352 		asc_sendsync, ASC_CMD_XFER_INFO,
353 		&asc_scripts[SCRIPT_TRY_SYNC + 1]},
354 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN),			/* 13 */
355 		script_nop, ASC_CMD_XFER_INFO,
356 		&asc_scripts[SCRIPT_MSG_IN]},
357 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_COMMAND),			/* 14 */
358 		script_nop, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
359 		&asc_scripts[SCRIPT_RESUME_NO_DATA]},
360 
361 	/* handle a disconnect */
362 	{SCRIPT_MATCH(ASC_INT_DISC, ASC_PHASE_DATAO),			/* 15 */
363 		asc_disconnect, ASC_CMD_ENABLE_SEL,
364 		&asc_scripts[SCRIPT_RESEL]},
365 
366 	/* reselect sequence: this is just a placeholder so match fails */
367 	{SCRIPT_MATCH(0, ASC_PHASE_MSG_IN),				/* 16 */
368 		script_nop, ASC_CMD_MSG_ACPT,
369 		&asc_scripts[SCRIPT_RESEL]},
370 
371 	/* resume data in after a message */
372 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),			/* 17 */
373 		asc_resume_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
374 		&asc_scripts[SCRIPT_DATA_IN + 1]},
375 
376 	/* resume partial DMA data in after a message */
377 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),			/* 18 */
378 		asc_resume_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
379 		&asc_scripts[SCRIPT_DATA_IN + 1]},
380 
381 	/* resume data out after a message */
382 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),			/* 19 */
383 		asc_resume_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
384 		&asc_scripts[SCRIPT_DATA_OUT + 1]},
385 
386 	/* resume partial DMA data out after a message */
387 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),			/* 20 */
388 		asc_resume_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
389 		&asc_scripts[SCRIPT_DATA_OUT + 1]},
390 
391 	/* resume after a message when there is no more data */
392 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),			/* 21 */
393 		script_nop, ASC_CMD_I_COMPLETE,
394 		&asc_scripts[SCRIPT_GET_STATUS]},
395 };
396 
397 /*
398  * State kept for each active SCSI device.
399  */
400 typedef struct scsi_state {
401 	script_t *script;	/* saved script while processing error */
402 	struct scsi_generic cmd;/* storage for scsi command */
403 	int	statusByte;	/* status byte returned during STATUS_PHASE */
404 	u_int	dmaBufSize;	/* DMA buffer size */
405 	int	dmalen;		/* amount to transfer in this chunk */
406 	int	dmaresid;	/* amount not transfered if chunk suspended */
407 	int	cmdlen;		/* length of command in cmd */
408 	int	buflen;		/* total remaining amount of data to transfer */
409 	vaddr_t	buf;		/* current pointer within scsicmd->buf */
410 	int	flags;		/* see below */
411 	int	msglen;		/* number of message bytes to read */
412 	int	msgcnt;		/* number of message bytes received */
413 	u_char	sync_period;	/* DMA synchronous period */
414 	u_char	sync_offset;	/* DMA synchronous xfer offset or 0 if async */
415 	u_char	msg_out;	/* next MSG_OUT byte to send */
416 	u_char	msg_in[16];	/* buffer for multibyte messages */
417 } State;
418 
419 /* state flags */
420 #define DISCONN		0x001	/* true if currently disconnected from bus */
421 #define DMA_IN_PROGRESS	0x002	/* true if data DMA started */
422 #define DMA_IN		0x004	/* true if reading from SCSI device */
423 #define DMA_OUT		0x010	/* true if writing to SCSI device */
424 #define DID_SYNC	0x020	/* true if synchronous offset was negotiated */
425 #define TRY_SYNC	0x040	/* true if try neg. synchronous offset */
426 #define PARITY_ERR	0x080	/* true if parity error seen */
427 
428 /*
429  * State kept for each active SCSI host interface (53C94).
430  */
431 struct asc_softc {
432 	struct device	sc_dev;		/* use as a device */
433 	asc_regmap_t	*regs;		/* chip address */
434 	dma_softc_t	__dma;		/* stupid macro..... */
435 	dma_softc_t	*dma;		/* dma control structure */
436 	int		sc_id;		/* SCSI ID of this interface */
437 	int		myidmask;	/* ~(1 << myid) */
438 	int		state;		/* current SCSI connection state */
439 	int		target;		/* target SCSI ID if busy */
440 	script_t	*script;	/* next expected interrupt & action */
441 	struct scsipi_xfer *cmdq[ASC_NCMD];/* Pointer to queued commands */
442 	struct scsipi_xfer *cmd[ASC_NCMD];/* Pointer to current active command */
443 	State		st[ASC_NCMD];	/* state info for each active command */
444 	int		min_period;	/* Min transfer period clk/byte */
445 	int		max_period;	/* Max transfer period clk/byte */
446 	int		ccf;		/* CCF, whatever that really is? */
447 	int		timeout_250;	/* 250ms timeout */
448 	int		tb_ticks;	/* 4ns. ticks/tb channel ticks */
449 	int		is24bit;	/* if 53CF94/96-2, 24bit address */
450 	struct scsipi_channel sc_channel;
451 	struct scsipi_adapter sc_adapter;
452 };
453 
454 #define	ASC_STATE_IDLE		0	/* idle state */
455 #define	ASC_STATE_BUSY		1	/* selecting or currently connected */
456 #define ASC_STATE_TARGET	2	/* currently selected as target */
457 #define ASC_STATE_RESEL		3	/* currently waiting for reselect */
458 
459 typedef struct asc_softc *asc_softc_t;
460 
461 struct asc_timing {
462 	int		min_period;	/* Min transfer period clk/byte */
463 	int		max_period;	/* Max transfer period clk/byte */
464 	int		ccf;		/* CCF, whatever that really is? */
465 	int		timeout_250;	/* 250ms timeout */
466 	int		tb_ticks;	/* 4ns. ticks/tb channel ticks */
467 }	asc_timing_40mhz = {
468 		ASC_MIN_PERIOD40,
469 		ASC_MAX_PERIOD40,
470 		ASC_CCF(40),
471 		ASC_TIMEOUT_250(40, 8 /* exception for ASC_CCF(40) (== 0) */),
472 		6, /* 6.25 */
473 },	asc_timing_25mhz = {
474 		ASC_MIN_PERIOD25,
475 		ASC_MAX_PERIOD25,
476 		ASC_CCF(25),
477 		ASC_TIMEOUT_250(25, ASC_CCF(25)),
478 		10,
479 },	asc_timing_12mhz = {
480 		ASC_MIN_PERIOD12,
481 		ASC_MAX_PERIOD12,
482 		ASC_CCF(13),
483 		ASC_TIMEOUT_250(13, ASC_CCF(13)),
484 		20,
485 };
486 
487 struct asc_config *asc_conf = NULL;
488 
489 /*
490  * Autoconfiguration data for config.
491  */
492 int	ascmatch __P((struct device *, struct cfdata *, void *));
493 void	ascattach __P((struct device *, struct device *, void *));
494 
495 int	asc_doprobe __P((void *, int, int, struct device *));
496 
497 CFATTACH_DECL(asc, sizeof(struct asc_softc),
498     ascmatch, ascattach, NULL, NULL);
499 
500 /*
501  *  Glue to the machine dependent scsi
502  */
503 void asc_scsipi_request __P((struct scsipi_channel *,
504 				scsipi_adapter_req_t, void *));
505 
506 static int asc_intr __P((void *));
507 static void asc_poll __P((struct asc_softc *, int));
508 #ifdef DEBUG
509 static void asc_DumpLog __P((char *));
510 #endif
511 
512 /*
513  * Match driver based on name
514  */
515 int
516 ascmatch(parent, match, aux)
517 	struct device *parent;
518 	struct cfdata *match;
519 	void *aux;
520 {
521 	struct jazzio_attach_args *ja = aux;
522 
523 	if(strcmp(ja->ja_name, "asc") != 0)
524 		return (0);
525 	return (1);
526 }
527 
528 void
529 ascattach(parent, self, aux)
530 	struct device *parent;
531 	struct device *self;
532 	void *aux;
533 {
534 	struct jazzio_attach_args *ja = aux;
535 	asc_softc_t asc = (void *)self;
536 	asc_regmap_t *regs;
537 	int id, s, i;
538 	int bufsiz;
539 
540 	if (asc_conf == NULL)
541 		panic("asc_conf isn't initialized");
542 
543 	/*
544 	 * Initialize hw descriptor, cache some pointers
545 	 */
546 	asc->regs = (asc_regmap_t *)ja->ja_addr;	/* XXX */
547 
548 	/*
549 	 * Set up machine dependencies.
550 	 * 1) how to do dma
551 	 * 2) timing based on chip clock frequency
552 	 */
553 #if 1	/*XXX check if code handles 0 as 64k */
554 	bufsiz = 63 * 1024;
555 #else
556 	bufsiz = 64 * 1024;
557 #endif
558 	asc->dma = &asc->__dma;
559 	asc_dma_init(asc->dma);
560 
561 	/*
562 	 * Now for timing.
563 	 */
564 	asc->min_period = asc_conf->ac_timing->min_period;
565 	asc->max_period = asc_conf->ac_timing->max_period;
566 	asc->ccf = asc_conf->ac_timing->ccf;
567 	asc->timeout_250 = asc_conf->ac_timing->timeout_250;
568 	asc->tb_ticks = asc_conf->ac_timing->tb_ticks;
569 
570 	asc->state = ASC_STATE_IDLE;
571 	asc->target = -1;
572 
573 	regs = asc->regs;
574 
575 	/*
576 	 * Reset chip, fully.  Note that interrupts are already enabled.
577 	 */
578 	s = splbio();
579 
580 	/* preserve our ID for now */
581 	asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
582 	asc->myidmask = ~(1 << asc->sc_id);
583 
584 	/* identify 53CF9x-2 or not */
585 	regs->asc_cmd = ASC_CMD_RESET;
586 	wbflush(); DELAY(25);
587 	regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP;
588 	wbflush(); DELAY(25);
589 	regs->asc_cnfg2 = ASC_CNFG2_FE;
590 	wbflush(); DELAY(25);
591 	regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP;
592 	wbflush(); DELAY(25);
593 	asc->is24bit = regs->asc_id == ASC_ID_53CF94;
594 
595 	asc_reset(asc, regs);
596 
597 	/*
598 	 * Our SCSI id on the bus.
599 	 * The user can set this via the prom on 3maxen/picaen.
600 	 * If this changes it is easy to fix: make a default that
601 	 * can be changed as boot arg.
602 	 */
603 #ifdef	unneeded
604 	regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) |
605 			      (scsi_initiator_id[unit] & 0x7);
606 	asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
607 #endif
608 	id = asc->sc_id;
609 	splx(s);
610 
611 	/*
612 	 * Give each target its DMA buffer region.
613 	 * The buffer address is the same for all targets,
614 	 * the allocated dma viritual scatter/gather space.
615 	 */
616 	for (i = 0; i < ASC_NCMD; i++) {
617 		asc->st[i].dmaBufSize = bufsiz;
618 	}
619 
620 	/*
621 	 * Set up interrupt handler.
622          */
623 	jazzio_intr_establish(ja->ja_intr, asc_intr, (void *)asc);
624 
625 	printf(": %s, target %d\n", asc->is24bit ? "NCR53CF9X-2" : "NCR53C94",
626 	    id);
627 
628 	asc->sc_adapter.adapt_dev = &asc->sc_dev;
629 	asc->sc_adapter.adapt_nchannels = 1;
630 	asc->sc_adapter.adapt_openings = 7;
631 	asc->sc_adapter.adapt_max_periph = 1;
632 	asc->sc_adapter.adapt_ioctl = NULL;
633 	asc->sc_adapter.adapt_minphys = minphys;
634 	asc->sc_adapter.adapt_request = asc_scsipi_request;
635 
636 	memset(&asc->sc_channel, 0, sizeof(asc->sc_channel));
637 	asc->sc_channel.chan_adapter = &asc->sc_adapter;
638 	asc->sc_channel.chan_bustype = &scsi_bustype;
639 	asc->sc_channel.chan_channel = 0;
640 	asc->sc_channel.chan_ntargets = 8;
641 	asc->sc_channel.chan_nluns = 8;
642 	asc->sc_channel.chan_id = asc->sc_id;
643 
644 	/*
645 	 * Now try to attach all the sub devices.
646 	 */
647 	config_found(self, &asc->sc_channel, scsiprint);
648 }
649 
650 /*
651  * Start activity on a SCSI device.
652  * We maintain information on each device separately since devices can
653  * connect/disconnect during an operation.
654  */
655 void
656 asc_scsipi_request(chan, req, arg)
657 	struct scsipi_channel *chan;
658 	scsipi_adapter_req_t req;
659 	void *arg;
660 {
661 	struct scsipi_xfer *xs;
662 	struct scsipi_periph *periph;
663 	struct asc_softc *asc = (void *)chan->chan_adapter->adapt_dev;
664 	int dontqueue, s;
665 
666 	switch (req) {
667 	case ADAPTER_REQ_RUN_XFER:
668 		xs = arg;
669 		periph = xs->xs_periph;
670 
671 		dontqueue = xs->xs_control & XS_CTL_POLL;
672 
673 		/*
674 		 *  Flush caches for any data buffer
675 		 */
676 		if(xs->datalen != 0) {
677 			mips_dcache_wbinv_range((vaddr_t)xs->data, xs->datalen);
678 		}
679 		/*
680 		 *  The hack on the next few lines are to avoid buffers
681 		 *  mapped to UADDR. Realloc to the kva uarea address.
682 		 */
683 		if((u_int)(xs->data) >= UADDR) {
684 			xs->data = ((u_int)(xs->data) & ~UADDR) + (u_char *)(curproc->p_addr);
685 		}
686 
687 		s = splbio();
688 		asc->cmd[periph->periph_target] = xs;
689 
690 		/*
691 		 *  Going to launch.
692 		 *  Make a local copy of the command and some pointers.
693 		 */
694 		asc_startcmd(asc, periph->periph_target);
695 
696 		/*
697 		 *  If in startup, interrupts not usable yet.
698 		 */
699 		if(dontqueue) {
700 			asc_poll(asc,periph->periph_target);
701 		}
702 		splx(s);
703 		return;
704 	case ADAPTER_REQ_GROW_RESOURCES:
705 		/* XXX Not supported. */
706 		return;
707 	case ADAPTER_REQ_SET_XFER_MODE:
708 		/* XXX Not supported. */
709 		return;
710 	}
711 }
712 
713 void
714 asc_poll(asc, target)
715 	struct asc_softc *asc;
716 	int target;
717 {
718 	struct scsipi_xfer *scsicmd = asc->cmd[target];
719 	int count = scsicmd->timeout * 10;
720 
721 	while(count) {
722 		if(asc->regs->asc_status &ASC_CSR_INT) {
723 			asc_intr(asc);
724 		}
725 		if(scsicmd->xs_status & XS_STS_DONE)
726 			break;
727 		DELAY(5);
728 		count--;
729 	}
730 	if(count == 0) {
731 		scsicmd->error = XS_TIMEOUT;
732 		asc_end(asc, 0, 0, 0);
733 	}
734 }
735 
736 static void
737 asc_reset(asc, regs)
738 	asc_softc_t asc;
739 	asc_regmap_t *regs;
740 {
741 
742 	/*
743 	 * Reset chip and wait till done
744 	 */
745 	regs->asc_cmd = ASC_CMD_RESET;
746 	wbflush(); DELAY(25);
747 
748 	/* spec says this is needed after reset */
749 	regs->asc_cmd = ASC_CMD_NOP;
750 	wbflush(); DELAY(25);
751 
752 	/*
753 	 * Set up various chip parameters
754 	 */
755 	regs->asc_ccf = asc->ccf;
756 	wbflush(); DELAY(25);
757 	regs->asc_sel_timo = asc->timeout_250;
758 	/* restore our ID */
759 	regs->asc_cnfg1 = asc->sc_id | ASC_CNFG1_P_CHECK;
760 	/* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */
761 	regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL;
762 	regs->asc_cnfg3 = asc_conf->ac_cnfg3;
763 	/* zero anything else */
764 	ASC_TC_PUT(regs, 0, asc->is24bit);
765 	regs->asc_syn_p = asc->min_period;
766 	regs->asc_syn_o = 0;	/* async for now */
767 	wbflush();
768 }
769 
770 /*
771  * Start a SCSI command on a target.
772  */
773 static void
774 asc_startcmd(asc, target)
775 	asc_softc_t asc;
776 	int target;
777 {
778 	asc_regmap_t *regs;
779 	State *state;
780 	struct scsipi_xfer *scsicmd;
781 	int i, len;
782 
783 	/*
784 	 * See if another target is currently selected on this SCSI bus.
785 	 */
786 	if (asc->target >= 0)
787 		return;
788 
789 	regs = asc->regs;
790 
791 	/*
792 	 * If a reselection is in progress, it is Ok to ignore it since
793 	 * the ASC will automatically cancel the command and flush
794 	 * the FIFO if the ASC is reselected before the command starts.
795 	 * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if
796 	 * a reselect occurs before starting the command.
797 	 */
798 
799 	asc->state = ASC_STATE_BUSY;
800 	asc->target = target;
801 
802 	/* cache some pointers */
803 	scsicmd = asc->cmd[target];
804 	state = &asc->st[target];
805 
806 	/*
807 	 * Init the chip and target state.
808 	 */
809 	state->flags = state->flags & DID_SYNC;
810 	state->script = (script_t *)0;
811 	state->msg_out = SCSI_NO_OP;
812 
813 	/*
814 	 * Set up for DMA of command output. Also need to flush cache.
815 	 */
816 	bcopy(scsicmd->cmd, &state->cmd, scsicmd->cmdlen);
817 	state->cmdlen = scsicmd->cmdlen;
818 	state->buf = (vaddr_t)scsicmd->data;
819 	state->buflen = scsicmd->datalen;
820 	len = state->cmdlen;
821 	state->dmalen = len;
822 
823 #ifdef DEBUG
824 	if (asc_debug > 1) {
825 		printf("asc_startcmd: %s target %d cmd %x len %d\n",
826 			asc->sc_dev.dv_xname, target,
827 			state->cmd.opcode, state->buflen);
828 	}
829 #endif
830 
831 	/* check for simple SCSI command with no data transfer */
832 	if (scsicmd->xs_control & XS_CTL_DATA_OUT) {
833 		asc->script = &asc_scripts[SCRIPT_DATA_OUT];
834 		state->flags |= DMA_OUT;
835 	}
836 	else if (scsicmd->xs_control & XS_CTL_DATA_IN) {
837 		asc->script = &asc_scripts[SCRIPT_DATA_IN];
838 		state->flags |= DMA_IN;
839 	}
840 	else if (state->buflen == 0) {
841 		/* check for sync negotiation */
842 		if ((scsicmd->xs_status & /* SCSICMD_USE_SYNC */ 0) &&
843 		    !(state->flags & DID_SYNC)) {
844 			asc->script = &asc_scripts[SCRIPT_TRY_SYNC];
845 			state->flags |= TRY_SYNC;
846 		} else
847 			asc->script = &asc_scripts[SCRIPT_SIMPLE];
848 		state->buf = (vaddr_t)0;
849 	}
850 
851 #ifdef DEBUG
852 	asc_debug_cmd = state->cmd.opcode;
853 	if (state->cmd.opcode == SCSI_READ_EXT) {
854 		asc_debug_bn = (state->cmd.bytes[1] << 24) |
855 			(state->cmd.bytes[2] << 16) |
856 			(state->cmd.bytes[3] << 8) |
857 			 state->cmd.bytes[4];
858 		asc_debug_sz = (state->cmd.bytes[6] << 8) | state->cmd.bytes[7];
859 	}
860 	asc_logp->status = PACK(asc->sc_dev.dv_unit, 0, 0, asc_debug_cmd);
861 	asc_logp->target = asc->target;
862 	asc_logp->state = asc->script - asc_scripts;
863 	asc_logp->msg = SCSI_DIS_REC_IDENTIFY;
864 	asc_logp->resid = scsicmd->datalen;
865 	if (++asc_logp >= &asc_log[NLOG])
866 		asc_logp = asc_log;
867 #endif
868 
869 	/* preload the FIFO with the message and command to be sent */
870 	regs->asc_fifo = SCSI_DIS_REC_IDENTIFY |
871 	    (scsicmd->xs_periph->periph_lun & 0x07);
872 
873 	for( i = 0; i < len; i++ ) {
874 		regs->asc_fifo = ((caddr_t)&state->cmd)[i];
875 	}
876 	ASC_TC_PUT(regs, 0, asc->is24bit);
877 	readback(regs->asc_cmd);
878 	regs->asc_cmd = ASC_CMD_DMA;
879 	readback(regs->asc_cmd);
880 
881 	regs->asc_dbus_id = target;
882 	readback(regs->asc_dbus_id);
883 	regs->asc_syn_p = state->sync_period;
884 	readback(regs->asc_syn_p);
885 	regs->asc_syn_o = state->sync_offset;
886 	readback(regs->asc_syn_o);
887 
888 /*XXX PEFO */
889 /* we are not using sync transfer now, need to check this if we will */
890 
891 	if (state->flags & TRY_SYNC)
892 		regs->asc_cmd = ASC_CMD_SEL_ATN_STOP;
893 	else
894 		regs->asc_cmd = ASC_CMD_SEL_ATN;
895 	readback(regs->asc_cmd);
896 }
897 
898 /*
899  * Interrupt routine
900  *	Take interrupts from the chip
901  *
902  * Implementation:
903  *	Move along the current command's script if
904  *	all is well, invoke error handler if not.
905  */
906 int
907 asc_intr(sc)
908 	void *sc;
909 {
910 	asc_softc_t asc = sc;
911 	asc_regmap_t *regs = asc->regs;
912 	State *state;
913 	script_t *scpt;
914 	int ss, ir, status;
915 
916 	/* collect ephemeral information */
917 	status = regs->asc_status;
918 	ss = regs->asc_ss;
919 
920 	if ((status & ASC_CSR_INT) == 0) /* Make shure it's a real interrupt */
921 		 return(0);
922 
923 	ir = regs->asc_intr;	/* this resets the previous two */
924 	scpt = asc->script;
925 
926 #ifdef DEBUG
927 	asc_logp->status = PACK(asc->sc_dev.dv_unit, status, ss, ir);
928 	asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1;
929 	asc_logp->state = scpt - asc_scripts;
930 	asc_logp->msg = -1;
931 	asc_logp->resid = 0;
932 	if (++asc_logp >= &asc_log[NLOG])
933 		asc_logp = asc_log;
934 	if (asc_debug > 2)
935 		printf("asc_intr: status %x ss %x ir %x cond %d:%x\n",
936 			status, ss, ir, scpt - asc_scripts, scpt->condition);
937 #endif
938 
939 	/* check the expected state */
940 	if (SCRIPT_MATCH(ir, status) == scpt->condition) {
941 		/*
942 		 * Perform the appropriate operation, then proceed.
943 		 */
944 		if ((*scpt->action)(asc, status, ss, ir)) {
945 			regs->asc_cmd = scpt->command;
946 			readback(regs->asc_cmd);
947 			asc->script = scpt->next;
948 		}
949 		goto done;
950 	}
951 
952 	/*
953 	 * Check for parity error.
954 	 * Hardware will automatically set ATN
955 	 * to request the device for a MSG_OUT phase.
956 	 */
957 	if (status & ASC_CSR_PE) {
958 		printf("%s: SCSI device %d: incomming parity error seen\n",
959 			asc->sc_dev.dv_xname, asc->target);
960 		asc->st[asc->target].flags |= PARITY_ERR;
961 	}
962 
963 	/*
964 	 * Check for gross error.
965 	 * Probably a bug in a device driver.
966 	 */
967 	if (status & ASC_CSR_GE) {
968 		printf("%s: SCSI device %d: gross error\n",
969 			asc->sc_dev.dv_xname, asc->target);
970 		goto abort;
971 	}
972 
973 	/* check for message in or out */
974 	if ((ir & ~ASC_INT_FC) == ASC_INT_BS) {
975 		register int len, fifo;
976 
977 		state = &asc->st[asc->target];
978 		switch (ASC_PHASE(status)) {
979 		case ASC_PHASE_DATAI:
980 		case ASC_PHASE_DATAO:
981 			ASC_TC_GET(regs, len);
982 			fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
983 			printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n",
984 				state->buflen, state->dmalen, len, fifo);
985 			goto abort;
986 
987 		case ASC_PHASE_MSG_IN:
988 			break;
989 
990 		case ASC_PHASE_MSG_OUT:
991 			/*
992 			 * Check for parity error.
993 			 * Hardware will automatically set ATN
994 			 * to request the device for a MSG_OUT phase.
995 			 */
996 			if (state->flags & PARITY_ERR) {
997 				state->flags &= ~PARITY_ERR;
998 				state->msg_out = SCSI_MESSAGE_PARITY_ERROR;
999 				/* reset message in counter */
1000 				state->msglen = 0;
1001 			} else
1002 				state->msg_out = SCSI_NO_OP;
1003 			regs->asc_fifo = state->msg_out;
1004 			regs->asc_cmd = ASC_CMD_XFER_INFO;
1005 			readback(regs->asc_cmd);
1006 			goto done;
1007 
1008 		case ASC_PHASE_STATUS:
1009 			/* probably an error in the SCSI command */
1010 			asc->script = &asc_scripts[SCRIPT_GET_STATUS];
1011 			regs->asc_cmd = ASC_CMD_I_COMPLETE;
1012 			readback(regs->asc_cmd);
1013 			goto done;
1014 
1015 		default:
1016 			goto abort;
1017 		}
1018 
1019 		if (state->script)
1020 			goto abort;
1021 
1022 		/*
1023 		 * OK, message coming in clean up whatever is going on.
1024 		 * Get number of bytes left to transfered from byte counter
1025 		 * counter decrements when data is trf on the SCSI bus
1026 		 */
1027 		ASC_TC_GET(regs, len);
1028 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1029 		/* flush any data in the FIFO */
1030 		if (fifo && !(state->flags & DMA_IN_PROGRESS)) {
1031 printf("asc_intr: fifo flush %d len %d fifo %x\n", fifo, len, regs->asc_fifo);
1032 			regs->asc_cmd = ASC_CMD_FLUSH;
1033 			readback(regs->asc_cmd);
1034 			DELAY(2);
1035 		}
1036 		else if (fifo && state->flags & DMA_IN_PROGRESS) {
1037 			if (state->flags & DMA_OUT) {
1038 				len += fifo; /* Bytes dma'ed but not sent */
1039 			}
1040 			else if (state->flags & DMA_IN) {
1041 				printf("asc_intr: IN: dmalen %d len %d fifo %d\n",
1042 					state->dmalen, len, fifo); /* XXX */
1043 			}
1044 			regs->asc_cmd = ASC_CMD_FLUSH;
1045 			readback(regs->asc_cmd);
1046 			DELAY(2);
1047 		}
1048 		if (len && (state->flags & DMA_IN_PROGRESS)) {
1049 			/* save number of bytes still to be sent or received */
1050 			state->dmaresid = len;
1051 			state->flags &= ~DMA_IN_PROGRESS;
1052 			ASC_TC_PUT(regs, 0, asc->is24bit);
1053 #ifdef DEBUG
1054 			if (asc_logp == asc_log)
1055 				asc_log[NLOG - 1].resid = len;
1056 			else
1057 				asc_logp[-1].resid = len;
1058 #endif
1059 			/* setup state to resume to */
1060 			if (state->flags & DMA_IN) {
1061 				/*
1062 				 * Since the ASC_CNFG3_SRB bit of the
1063 				 * cnfg3 register bit is not set,
1064 				 * we just transferred an extra byte.
1065 				 * Since we can't resume on an odd byte
1066 				 * boundary, we copy the valid data out
1067 				 * and resume DMA at the start address.
1068 				 */
1069 				if (len & 1) {
1070 					printf("asc_intr: msg in len %d (fifo %d)\n",
1071 						len, fifo); /* XXX */
1072 					len = state->dmalen - len;
1073 					goto do_in;
1074 				}
1075 				state->script =
1076 					&asc_scripts[SCRIPT_RESUME_DMA_IN];
1077 			} else if (state->flags & DMA_OUT)
1078 				state->script =
1079 					&asc_scripts[SCRIPT_RESUME_DMA_OUT];
1080 			else
1081 				state->script = asc->script;
1082 		} else if (state->flags & DMA_IN) {
1083 			if (len) {
1084 #ifdef DEBUG
1085 				printf("asc_intr: 1: bn %d len %d (fifo %d)\n",
1086 					asc_debug_bn, len, fifo); /* XXX */
1087 #endif
1088 				goto abort;
1089 			}
1090 			/* setup state to resume to */
1091 			if (state->flags & DMA_IN_PROGRESS) {
1092 				len = state->dmalen;
1093 				state->flags &= ~DMA_IN_PROGRESS;
1094 			do_in:
1095 				DMA_END(asc->dma);
1096 				state->buf += len;
1097 				state->buflen -= len;
1098 			}
1099 			if (state->buflen)
1100 				state->script =
1101 				    &asc_scripts[SCRIPT_RESUME_IN];
1102 			else
1103 				state->script =
1104 				    &asc_scripts[SCRIPT_RESUME_NO_DATA];
1105 		} else if (state->flags & DMA_OUT) {
1106 			if (len) {
1107 				printf("asc_intr: 2: len %d (fifo %d)\n", len,
1108 					fifo); /* XXX */
1109 /* XXX THEO */
1110 #if 1
1111 				regs->asc_cmd = ASC_CMD_FLUSH;
1112 				readback(regs->asc_cmd);
1113 				DELAY(2);
1114 				len = 0;
1115 #else
1116 				goto abort;
1117 #endif
1118 			}
1119 			/*
1120 			 * If this is the last chunk, the next expected
1121 			 * state is to get status.
1122 			 */
1123 			if (state->flags & DMA_IN_PROGRESS) {
1124 				state->flags &= ~DMA_IN_PROGRESS;
1125 				DMA_END(asc->dma);
1126 				len = state->dmalen;
1127 				state->buf += len;
1128 				state->buflen -= len;
1129 			}
1130 			if (state->buflen)
1131 				state->script =
1132 				    &asc_scripts[SCRIPT_RESUME_OUT];
1133 			else
1134 				state->script =
1135 				    &asc_scripts[SCRIPT_RESUME_NO_DATA];
1136 		} else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
1137 			state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA];
1138 		else
1139 			state->script = asc->script;
1140 
1141 		/* setup to receive a message */
1142 		asc->script = &asc_scripts[SCRIPT_MSG_IN];
1143 		state->msglen = 0;
1144 		regs->asc_cmd = ASC_CMD_XFER_INFO;
1145 		readback(regs->asc_cmd);
1146 		goto done;
1147 	}
1148 
1149 	/* check for SCSI bus reset */
1150 	if (ir & ASC_INT_RESET) {
1151 		register int i;
1152 
1153 		printf("%s: SCSI bus reset!!\n", asc->sc_dev.dv_xname);
1154 		/* need to flush any pending commands */
1155 		for (i = 0; i < ASC_NCMD; i++) {
1156 			if (!asc->cmd[i])
1157 				continue;
1158 			asc->cmd[i]->error = XS_DRIVER_STUFFUP;
1159 			asc_end(asc, 0, 0, 0);
1160 		}
1161 		/* rearbitrate synchronous offset */
1162 		for (i = 0; i < ASC_NCMD; i++) {
1163 			asc->st[i].sync_offset = 0;
1164 			asc->st[i].flags = 0;
1165 		}
1166 		asc->target = -1;
1167 		return(1);
1168 	}
1169 
1170 	/* check for command errors */
1171 	if (ir & ASC_INT_ILL)
1172 		goto abort;
1173 
1174 	/* check for disconnect */
1175 	if (ir & ASC_INT_DISC) {
1176 		state = &asc->st[asc->target];
1177 		switch (asc->script - asc_scripts) {
1178 		case SCRIPT_DONE:
1179 		case SCRIPT_DISCONNECT:
1180 			/*
1181 			 * Disconnects can happen normally when the
1182 			 * command is complete with the phase being
1183 			 * either ASC_PHASE_DATAO or ASC_PHASE_MSG_IN.
1184 			 * The SCRIPT_MATCH() only checks for one phase
1185 			 * so we can wind up here.
1186 			 * Perform the appropriate operation, then proceed.
1187 			 */
1188 			if ((*scpt->action)(asc, status, ss, ir)) {
1189 				regs->asc_cmd = scpt->command;
1190 				readback(regs->asc_cmd);
1191 				asc->script = scpt->next;
1192 			}
1193 			goto done;
1194 
1195 		case SCRIPT_TRY_SYNC:
1196 		case SCRIPT_SIMPLE:
1197 		case SCRIPT_DATA_IN:
1198 		case SCRIPT_DATA_OUT: /* one of the starting scripts */
1199 			if (ASC_SS(ss) == 0) {
1200 				/* device did not respond */
1201 				if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) {
1202 					regs->asc_cmd = ASC_CMD_FLUSH;
1203 					readback(regs->asc_cmd);
1204 				}
1205 				asc->cmd[asc->target]->error = XS_SELTIMEOUT;
1206 				asc_end(asc, status, ss, ir);
1207 				return(1);
1208 			}
1209 			/* FALLTHROUGH */
1210 
1211 		default:
1212 			printf("%s: SCSI device %d: unexpected disconnect\n",
1213 				asc->sc_dev.dv_xname, asc->target);
1214 #ifdef DEBUG
1215 			asc_DumpLog("asc_disc");
1216 #endif
1217 			/*
1218 			 * On rare occasions my RZ24 does a disconnect during
1219 			 * data in phase and the following seems to keep it
1220 			 * happy.
1221 			 * XXX Should a scsi disk ever do this??
1222 			 */
1223 			asc->script = &asc_scripts[SCRIPT_RESEL];
1224 			asc->state = ASC_STATE_RESEL;
1225 			state->flags |= DISCONN;
1226 			regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1227 			readback(regs->asc_cmd);
1228 			return(1);
1229 		}
1230 	}
1231 
1232 	/* check for reselect */
1233 	if (ir & ASC_INT_RESEL) {
1234 		unsigned fifo, id, msg;
1235 
1236 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1237 		if (fifo < 2)
1238 			goto abort;
1239 		/* read unencoded SCSI ID and convert to binary */
1240 		msg = regs->asc_fifo & asc->myidmask;
1241 		for (id = 0; (msg & 1) == 0; id++)
1242 			msg >>= 1;
1243 		/* read identify message */
1244 		msg = regs->asc_fifo;
1245 #ifdef DEBUG
1246 		if (asc_logp == asc_log)
1247 			asc_log[NLOG - 1].msg = msg;
1248 		else
1249 			asc_logp[-1].msg = msg;
1250 #endif
1251 		asc->state = ASC_STATE_BUSY;
1252 		asc->target = id;
1253 		state = &asc->st[id];
1254 		asc->script = state->script;
1255 		state->script = (script_t *)0;
1256 		if (!(state->flags & DISCONN))
1257 			goto abort;
1258 		state->flags &= ~DISCONN;
1259 		regs->asc_syn_p = state->sync_period;
1260 		regs->asc_syn_o = state->sync_offset;
1261 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
1262 		readback(regs->asc_cmd);
1263 		goto done;
1264 	}
1265 
1266 	/* check if we are being selected as a target */
1267 	if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
1268 		goto abort;
1269 
1270 	/*
1271 	 * 'ir' must be just ASC_INT_FC.
1272 	 * This is normal if canceling an ASC_ENABLE_SEL.
1273 	 */
1274 
1275 done:
1276 	wbflush();
1277 	/*
1278 	 * If the next interrupt comes in immediatly the interrupt
1279 	 * dispatcher (which we are returning to) will catch it
1280 	 * before returning to the interrupted code.
1281 	 */
1282 	return(1);
1283 
1284 abort:
1285 #ifdef DEBUG
1286 	asc_DumpLog("asc_intr");
1287 #endif
1288 	panic("asc_intr");
1289 	return(1);
1290 }
1291 
1292 /*
1293  * All the many little things that the interrupt
1294  * routine might switch to.
1295  */
1296 
1297 /* ARGSUSED */
1298 static int
1299 script_nop(asc, status, ss, ir)
1300 	asc_softc_t asc;
1301 	int status, ss, ir;
1302 {
1303 	return (1);
1304 }
1305 
1306 /* ARGSUSED */
1307 static int
1308 asc_get_status(asc, status, ss, ir)
1309 	register asc_softc_t asc;
1310 	register int status, ss, ir;
1311 {
1312 	register asc_regmap_t *regs = asc->regs;
1313 	register int data;
1314 
1315 	/*
1316 	 * Get the last two bytes in the FIFO.
1317 	 */
1318 	if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
1319 		printf("asc_get_status: cmdreg %x, fifo cnt %d\n",
1320 		       regs->asc_cmd, data); /* XXX */
1321 #ifdef DEBUG
1322 		asc_DumpLog("get_status"); /* XXX */
1323 #endif
1324 		if (data < 2) {
1325 			asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
1326 			readback(asc->regs->asc_cmd);
1327 			return (0);
1328 		}
1329 		do {
1330 			data = regs->asc_fifo;
1331 		} while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2);
1332 	}
1333 
1334 	/* save the status byte */
1335 	asc->st[asc->target].statusByte = data = regs->asc_fifo;
1336 #ifdef DEBUG
1337 	if (asc_logp == asc_log)
1338 		asc_log[NLOG - 1].msg = data;
1339 	else
1340 		asc_logp[-1].msg = data;
1341 #endif
1342 
1343 	/* get the (presumed) command_complete message */
1344 	if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE)
1345 		return (1);
1346 
1347 #ifdef DEBUG
1348 	printf("asc_get_status: status %x cmd %x\n",
1349 		asc->st[asc->target].statusByte, data);
1350 	asc_DumpLog("asc_get_status");
1351 #endif
1352 	return (0);
1353 }
1354 
1355 /* ARGSUSED */
1356 static int
1357 asc_end(asc, status, ss, ir)
1358 	asc_softc_t asc;
1359 	int status, ss, ir;
1360 {
1361 	struct scsipi_xfer *scsicmd;
1362 	struct scsipi_periph *periph;
1363 	State *state;
1364 	int i, target;
1365 
1366 	asc->state = ASC_STATE_IDLE;
1367 	target = asc->target;
1368 	asc->target = -1;
1369 	scsicmd = asc->cmd[target];
1370 	periph = scsicmd->xs_periph;
1371 	asc->cmd[target] = (struct scsipi_xfer *)0;
1372 	state = &asc->st[target];
1373 
1374 #ifdef DEBUG
1375 	if (asc_debug > 1) {
1376 		printf("asc_end: %s target %d cmd %x err %d resid %d\n",
1377 			asc->sc_dev.dv_xname, target,
1378 			state->cmd.opcode, scsicmd->error, state->buflen);
1379 	}
1380 #endif
1381 #ifdef DIAGNOSTIC
1382 	if (target < 0 || !scsicmd)
1383 		panic("asc_end");
1384 #endif
1385 
1386 	/* look for disconnected devices */
1387 	for (i = 0; i < ASC_NCMD; i++) {
1388 		if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN))
1389 			continue;
1390 		asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1391 		readback(asc->regs->asc_cmd);
1392 		asc->state = ASC_STATE_RESEL;
1393 		asc->script = &asc_scripts[SCRIPT_RESEL];
1394 		break;
1395 	}
1396 
1397 	if(scsicmd->error == XS_NOERROR) {
1398 		if((state->statusByte & ST_MASK) == SCSI_CHECK) {
1399 			scsicmd->status = state->statusByte;
1400 			scsicmd->error = XS_BUSY;
1401 		}
1402 	}
1403 
1404 	scsicmd->resid = state->buflen;
1405 
1406 	/*
1407 	 * Look for another device that is ready.
1408 	 * May want to keep last one started and increment for fairness
1409 	 * rather than always starting at zero.
1410 	 */
1411 	for (i = 0; i < ASC_NCMD; i++) {
1412 		/* don't restart a disconnected command */
1413 		if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
1414 			continue;
1415 		asc_startcmd(asc, i);
1416 		break;
1417 	}
1418 
1419 	/* signal device driver that the command is done */
1420 	scsipi_done(scsicmd);
1421 
1422 	return (0);
1423 }
1424 
1425 /* ARGSUSED */
1426 static int
1427 asc_dma_in(asc, status, ss, ir)
1428 	register asc_softc_t asc;
1429 	register int status, ss, ir;
1430 {
1431 	register asc_regmap_t *regs = asc->regs;
1432 	register State *state = &asc->st[asc->target];
1433 	register int len;
1434 
1435 	/* check for previous chunk in buffer */
1436 	if (state->flags & DMA_IN_PROGRESS) {
1437 		/*
1438 		 * Only count bytes that have been copied to memory.
1439 		 * There may be some bytes in the FIFO if synchonous transfers
1440 		 * are in progress.
1441 		 */
1442 		DMA_END(asc->dma);
1443 		ASC_TC_GET(regs, len);
1444 		len = state->dmalen - len;
1445 		state->buf += len;
1446 		state->buflen -= len;
1447 	}
1448 
1449 	/* setup to start reading the next chunk */
1450 	len = state->buflen;
1451 #ifdef DEBUG
1452 	if (asc_logp == asc_log)
1453 		asc_log[NLOG - 1].resid = len;
1454 	else
1455 		asc_logp[-1].resid = len;
1456 #endif
1457 	if (len > state->dmaBufSize)
1458 		len = state->dmaBufSize;
1459 	state->dmalen = len;
1460 	DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
1461 	ASC_TC_PUT(regs, len, asc->is24bit);
1462 #ifdef DEBUG
1463 	if (asc_debug > 2)
1464 		printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len);
1465 #endif
1466 
1467 	/* check for next chunk */
1468 	state->flags |= DMA_IN_PROGRESS;
1469 	if (len != state->buflen) {
1470 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1471 		readback(regs->asc_cmd);
1472 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1473 		return (0);
1474 	}
1475 	return (1);
1476 }
1477 
1478 /* ARGSUSED */
1479 static int
1480 asc_last_dma_in(asc, status, ss, ir)
1481 	register asc_softc_t asc;
1482 	register int status, ss, ir;
1483 {
1484 	register asc_regmap_t *regs = asc->regs;
1485 	register State *state = &asc->st[asc->target];
1486 	register int len, fifo;
1487 
1488 	DMA_END(asc->dma);
1489 	ASC_TC_GET(regs, len);
1490 	fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1491 #ifdef DEBUG
1492 	if (asc_debug > 2)
1493 		printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n",
1494 			state->buflen, state->dmalen, len, fifo);
1495 #endif
1496 	if (fifo) {
1497 		/* device must be trying to send more than we expect */
1498 		regs->asc_cmd = ASC_CMD_FLUSH;
1499 		readback(regs->asc_cmd);
1500 	}
1501 	state->flags &= ~DMA_IN_PROGRESS;
1502 	len = state->dmalen - len;
1503 	state->buflen -= len;
1504 
1505 	return (1);
1506 }
1507 
1508 /* ARGSUSED */
1509 static int
1510 asc_resume_in(asc, status, ss, ir)
1511 	register asc_softc_t asc;
1512 	register int status, ss, ir;
1513 {
1514 	register asc_regmap_t *regs = asc->regs;
1515 	register State *state = &asc->st[asc->target];
1516 	register int len;
1517 
1518 	/* setup to start reading the next chunk */
1519 	len = state->buflen;
1520 #ifdef DEBUG
1521 	if (asc_logp == asc_log)
1522 		asc_log[NLOG - 1].resid = len;
1523 	else
1524 		asc_logp[-1].resid = len;
1525 #endif
1526 	if (len > state->dmaBufSize)
1527 		len = state->dmaBufSize;
1528 	state->dmalen = len;
1529 #ifdef DEBUG
1530 	if (asc_logp == asc_log)
1531 		asc_log[NLOG - 1].resid = len;
1532 	else
1533 		asc_logp[-1].resid = len;
1534 #endif
1535 	DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
1536 	ASC_TC_PUT(regs, len, asc->is24bit);
1537 #ifdef DEBUG
1538 	if (asc_debug > 2)
1539 		printf("asc_resume_in: buflen %d, len %d\n", state->buflen,
1540 			len);
1541 #endif
1542 
1543 	/* check for next chunk */
1544 	state->flags |= DMA_IN_PROGRESS;
1545 	if (len != state->buflen) {
1546 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1547 		readback(regs->asc_cmd);
1548 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1549 		return (0);
1550 	}
1551 	return (1);
1552 }
1553 
1554 /* ARGSUSED */
1555 static int
1556 asc_resume_dma_in(asc, status, ss, ir)
1557 	register asc_softc_t asc;
1558 	register int status, ss, ir;
1559 {
1560 	register asc_regmap_t *regs = asc->regs;
1561 	register State *state = &asc->st[asc->target];
1562 	register int len, off;
1563 
1564 	/* setup to finish reading the current chunk */
1565 	len = state->dmaresid;
1566 	off = state->dmalen - len;
1567 	if ((off & 1) && state->sync_offset) {
1568 		printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n",
1569 			state->dmalen, len, off); /* XXX */
1570 		regs->asc_res_fifo = ((u_char *)state->buf)[off];
1571 /*XXX Need to flush cache ? */
1572 	}
1573 	DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_FROM_DEV);
1574 	ASC_TC_PUT(regs, len, asc->is24bit);
1575 #ifdef DEBUG
1576 	if (asc_debug > 2)
1577 		printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n",
1578 			state->dmalen, state->buflen, len, off);
1579 #endif
1580 
1581 	/* check for next chunk */
1582 	state->flags |= DMA_IN_PROGRESS;
1583 	if (state->dmalen != state->buflen) {
1584 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1585 		readback(regs->asc_cmd);
1586 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1587 		return (0);
1588 	}
1589 	return (1);
1590 }
1591 
1592 /* ARGSUSED */
1593 static int
1594 asc_dma_out(asc, status, ss, ir)
1595 	register asc_softc_t asc;
1596 	register int status, ss, ir;
1597 {
1598 	register asc_regmap_t *regs = asc->regs;
1599 	register State *state = &asc->st[asc->target];
1600 	register int len, fifo;
1601 
1602 	if (state->flags & DMA_IN_PROGRESS) {
1603 		/* check to be sure previous chunk was finished */
1604 		ASC_TC_GET(regs, len);
1605 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1606 		if (len || fifo)
1607 			printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1608 				state->buflen, state->dmalen, len, fifo); /* XXX */
1609 		len += fifo;
1610 		len = state->dmalen - len;
1611 		state->buf += len;
1612 		state->buflen -= len;
1613 	}
1614 
1615 	/* setup for this chunk */
1616 	len = state->buflen;
1617 #ifdef DEBUG
1618 	if (asc_logp == asc_log)
1619 		asc_log[NLOG - 1].resid = len;
1620 	else
1621 		asc_logp[-1].resid = len;
1622 #endif
1623 	if (len > state->dmaBufSize)
1624 		len = state->dmaBufSize;
1625 	state->dmalen = len;
1626 	DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
1627 	ASC_TC_PUT(regs, len, asc->is24bit);
1628 #ifdef DEBUG
1629 	if (asc_debug > 2)
1630 		printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len);
1631 #endif
1632 
1633 	/* check for next chunk */
1634 	state->flags |= DMA_IN_PROGRESS;
1635 	if (len != state->buflen) {
1636 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1637 		readback(regs->asc_cmd);
1638 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1639 		return (0);
1640 	}
1641 	return (1);
1642 }
1643 
1644 /* ARGSUSED */
1645 static int
1646 asc_last_dma_out(asc, status, ss, ir)
1647 	register asc_softc_t asc;
1648 	register int status, ss, ir;
1649 {
1650 	register asc_regmap_t *regs = asc->regs;
1651 	register State *state = &asc->st[asc->target];
1652 	register int len, fifo;
1653 
1654 	ASC_TC_GET(regs, len);
1655 	fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1656 #ifdef DEBUG
1657 	if (asc_debug > 2)
1658 		printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1659 			state->buflen, state->dmalen, len, fifo);
1660 #endif
1661 	if (fifo) {
1662 		len += fifo;
1663 		regs->asc_cmd = ASC_CMD_FLUSH;
1664 		readback(regs->asc_cmd);
1665 	}
1666 	state->flags &= ~DMA_IN_PROGRESS;
1667 	len = state->dmalen - len;
1668 	state->buflen -= len;
1669 	return (1);
1670 }
1671 
1672 /* ARGSUSED */
1673 static int
1674 asc_resume_out(asc, status, ss, ir)
1675 	register asc_softc_t asc;
1676 	register int status, ss, ir;
1677 {
1678 	register asc_regmap_t *regs = asc->regs;
1679 	register State *state = &asc->st[asc->target];
1680 	register int len;
1681 
1682 	/* setup for this chunk */
1683 	len = state->buflen;
1684 #ifdef DEBUG
1685 	if (asc_logp == asc_log)
1686 		asc_log[NLOG - 1].resid = len;
1687 	else
1688 		asc_logp[-1].resid = len;
1689 #endif
1690 	if (len > state->dmaBufSize)
1691 		len = state->dmaBufSize;
1692 	state->dmalen = len;
1693 #ifdef DEBUG
1694  	if (asc_logp == asc_log)
1695 		asc_log[NLOG - 1].resid = len;
1696 	else
1697 		asc_logp[-1].resid = len;
1698 #endif
1699 	DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
1700 	ASC_TC_PUT(regs, len, asc->is24bit);
1701 #ifdef DEBUG
1702 	if (asc_debug > 2)
1703 		printf("asc_resume_out: buflen %d, len %d\n", state->buflen,
1704 			len);
1705 #endif
1706 
1707 	/* check for next chunk */
1708 	state->flags |= DMA_IN_PROGRESS;
1709 	if (len != state->buflen) {
1710 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1711 		readback(regs->asc_cmd);
1712 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1713 		return (0);
1714 	}
1715 	return (1);
1716 }
1717 
1718 /* ARGSUSED */
1719 static int
1720 asc_resume_dma_out(asc, status, ss, ir)
1721 	register asc_softc_t asc;
1722 	register int status, ss, ir;
1723 {
1724 	register asc_regmap_t *regs = asc->regs;
1725 	register State *state = &asc->st[asc->target];
1726 	register int len, off;
1727 
1728 	/* setup to finish writing this chunk */
1729 	len = state->dmaresid;
1730 	off = state->dmalen - len;
1731 	if (off & 1) {
1732 		printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",
1733 			state->dmalen, len, off); /* XXX */
1734 		regs->asc_fifo = ((u_char *)state->buf)[off];
1735 /*XXX Need to flush Cache ? */
1736 		off++;
1737 		len--;
1738 	}
1739 	DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_TO_DEV);
1740 	ASC_TC_PUT(regs, len, asc->is24bit);
1741 #ifdef DEBUG
1742 	if (asc_debug > 2)
1743 		printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n",
1744 			state->dmalen, state->buflen, len, off);
1745 #endif
1746 
1747 	/* check for next chunk */
1748 	state->flags |= DMA_IN_PROGRESS;
1749 	if (state->dmalen != state->buflen) {
1750 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1751 		readback(regs->asc_cmd);
1752 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1753 		return (0);
1754 	}
1755 	return (1);
1756 }
1757 
1758 /* ARGSUSED */
1759 static int
1760 asc_sendsync(asc, status, ss, ir)
1761 	register asc_softc_t asc;
1762 	register int status, ss, ir;
1763 {
1764 	register asc_regmap_t *regs = asc->regs;
1765 	register State *state = &asc->st[asc->target];
1766 
1767 	/* send the extended synchronous negotiation message */
1768 	regs->asc_fifo = SCSI_EXTENDED_MSG;
1769 	wbflush();
1770 	regs->asc_fifo = 3;
1771 	wbflush();
1772 	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1773 	wbflush();
1774 	regs->asc_fifo = SCSI_MIN_PERIOD;
1775 	wbflush();
1776 	regs->asc_fifo = ASC_MAX_OFFSET;
1777 	/* state to resume after we see the sync reply message */
1778 	state->script = asc->script + 2;
1779 	state->msglen = 0;
1780 	return (1);
1781 }
1782 
1783 /* ARGSUSED */
1784 static int
1785 asc_replysync(asc, status, ss, ir)
1786 	register asc_softc_t asc;
1787 	register int status, ss, ir;
1788 {
1789 	register asc_regmap_t *regs = asc->regs;
1790 	register State *state = &asc->st[asc->target];
1791 
1792 #ifdef DEBUG
1793 	if (asc_debug > 2)
1794 		printf("asc_replysync: %x %x\n",
1795 			asc_to_scsi_period[state->sync_period] * asc->tb_ticks,
1796 			state->sync_offset);
1797 #endif
1798 	/* send synchronous transfer in response to a request */
1799 	regs->asc_fifo = SCSI_EXTENDED_MSG;
1800 	wbflush();
1801 	regs->asc_fifo = 3;
1802 	wbflush();
1803 	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1804 	wbflush();
1805 	regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks;
1806 	wbflush();
1807 	regs->asc_fifo = state->sync_offset;
1808 	regs->asc_cmd = ASC_CMD_XFER_INFO;
1809 	readback(regs->asc_cmd);
1810 
1811 	/* return to the appropriate script */
1812 	if (!state->script) {
1813 #ifdef DEBUG
1814 		asc_DumpLog("asc_replsync");
1815 #endif
1816 		panic("asc_replysync");
1817 	}
1818 	asc->script = state->script;
1819 	state->script = (script_t *)0;
1820 	return (0);
1821 }
1822 
1823 /* ARGSUSED */
1824 static int
1825 asc_msg_in(asc, status, ss, ir)
1826 	register asc_softc_t asc;
1827 	register int status, ss, ir;
1828 {
1829 	register asc_regmap_t *regs = asc->regs;
1830 	register State *state = &asc->st[asc->target];
1831 	register int msg;
1832 	int i;
1833 
1834 	/* read one message byte */
1835 	msg = regs->asc_fifo;
1836 #ifdef DEBUG
1837 	if (asc_logp == asc_log)
1838 		asc_log[NLOG - 1].msg = msg;
1839 	else
1840 		asc_logp[-1].msg = msg;
1841 #endif
1842 
1843 	/* check for multi-byte message */
1844 	if (state->msglen != 0) {
1845 		/* first byte is the message length */
1846 		if (state->msglen < 0) {
1847 			state->msglen = msg;
1848 			return (1);
1849 		}
1850 		if (state->msgcnt >= state->msglen)
1851 			goto abort;
1852 		state->msg_in[state->msgcnt++] = msg;
1853 
1854 		/* did we just read the last byte of the message? */
1855 		if (state->msgcnt != state->msglen)
1856 			return (1);
1857 
1858 		/* process an extended message */
1859 #ifdef DEBUG
1860 		if (asc_debug > 2)
1861 			printf("asc_msg_in: msg %x %x %x\n",
1862 				state->msg_in[0],
1863 				state->msg_in[1],
1864 				state->msg_in[2]);
1865 #endif
1866 		switch (state->msg_in[0]) {
1867 		case SCSI_SYNCHRONOUS_XFER:
1868 			state->flags |= DID_SYNC;
1869 			state->sync_offset = state->msg_in[2];
1870 
1871 			/* convert SCSI period to ASC period */
1872 			i = state->msg_in[1] / asc->tb_ticks;
1873 			if (i < asc->min_period)
1874 				i = asc->min_period;
1875 			else if (i >= asc->max_period) {
1876 				/* can't do sync transfer, period too long */
1877 				printf("%s: SCSI device %d: sync xfer period too long (%d)\n",
1878 					asc->sc_dev.dv_xname, asc->target, i);
1879 				i = asc->max_period;
1880 				state->sync_offset = 0;
1881 			}
1882 			if ((i * asc->tb_ticks) != state->msg_in[1])
1883 				i++;
1884 			state->sync_period = i & 0x1F;
1885 
1886 			/*
1887 			 * If this is a request, check minimums and
1888 			 * send back an acknowledge.
1889 			 */
1890 			if (!(state->flags & TRY_SYNC)) {
1891 				regs->asc_cmd = ASC_CMD_SET_ATN;
1892 				readback(regs->asc_cmd);
1893 
1894 				if (state->sync_period < asc->min_period)
1895 					state->sync_period =
1896 						asc->min_period;
1897 				if (state->sync_offset > ASC_MAX_OFFSET)
1898 					state->sync_offset =
1899 						ASC_MAX_OFFSET;
1900 				asc->script = &asc_scripts[SCRIPT_REPLY_SYNC];
1901 				regs->asc_syn_p = state->sync_period;
1902 				readback(regs->asc_syn_p);
1903 				regs->asc_syn_o = state->sync_offset;
1904 				readback(regs->asc_syn_o);
1905 				regs->asc_cmd = ASC_CMD_MSG_ACPT;
1906 				readback(regs->asc_cmd);
1907 				return (0);
1908 			}
1909 
1910 			regs->asc_syn_p = state->sync_period;
1911 			readback(regs->asc_syn_p);
1912 			regs->asc_syn_o = state->sync_offset;
1913 			readback(regs->asc_syn_o);
1914 			goto done;
1915 
1916 		default:
1917 			printf("%s: SCSI device %d: rejecting extended message 0x%x\n",
1918 				 asc->sc_dev.dv_xname, asc->target,
1919 				state->msg_in[0]);
1920 			goto reject;
1921 		}
1922 	}
1923 
1924 	/* process first byte of a message */
1925 #ifdef DEBUG
1926 	if (asc_debug > 2)
1927 		printf("asc_msg_in: msg %x\n", msg);
1928 #endif
1929 	switch (msg) {
1930 #if 0
1931 	case SCSI_MESSAGE_REJECT:
1932 		printf(" did not like SYNCH xfer "); /* XXX */
1933 		state->flags |= DID_SYNC;
1934 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
1935 		readback(regs->asc_cmd);
1936 		status = asc_wait(regs, ASC_CSR_INT);
1937 		ir = regs->asc_intr;
1938 		/* some just break out here, some dont */
1939 		if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {
1940 			regs->asc_fifo = SCSI_ABORT;
1941 			regs->asc_cmd = ASC_CMD_XFER_INFO;
1942 			readback(regs->asc_cmd);
1943 			status = asc_wait(regs, ASC_CSR_INT);
1944 			ir = regs->asc_intr;
1945 		}
1946 		if (ir & ASC_INT_DISC) {
1947 			asc_end(asc, status, 0, ir);
1948 			return (0);
1949 		}
1950 		goto status;
1951 #endif /* 0 */
1952 
1953 	case SCSI_EXTENDED_MSG: /* read an extended message */
1954 		/* setup to read message length next */
1955 		state->msglen = -1;
1956 		state->msgcnt = 0;
1957 		return (1);
1958 
1959 	case SCSI_NO_OP:
1960 		break;
1961 
1962 	case SCSI_SAVE_DATA_POINTER:
1963 		/* expect another message */
1964 		return (1);
1965 
1966 	case SCSI_RESTORE_POINTERS:
1967 		/*
1968 		 * Need to do the following if resuming synchonous data in
1969 		 * on an odd byte boundary.
1970 		regs->asc_cnfg2 |= ASC_CNFG2_RFB;
1971 		 */
1972 		break;
1973 
1974 	case SCSI_DISCONNECT:
1975 		if (state->flags & DISCONN)
1976 			goto abort;
1977 		state->flags |= DISCONN;
1978 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
1979 		readback(regs->asc_cmd);
1980 		asc->script = &asc_scripts[SCRIPT_DISCONNECT];
1981 		return (0);
1982 
1983 	default:
1984 		printf("%s: SCSI device %d: rejecting message 0x%x\n",
1985 			asc->sc_dev.dv_xname, asc->target, msg);
1986 	reject:
1987 		/* request a message out before acknowledging this message */
1988 		state->msg_out = SCSI_MESSAGE_REJECT;
1989 		regs->asc_cmd = ASC_CMD_SET_ATN;
1990 		readback(regs->asc_cmd);
1991 	}
1992 
1993 done:
1994 	/* return to original script */
1995 	regs->asc_cmd = ASC_CMD_MSG_ACPT;
1996 	readback(regs->asc_cmd);
1997 	if (!state->script) {
1998 	abort:
1999 #ifdef DEBUG
2000 		asc_DumpLog("asc_msg_in");
2001 #endif
2002 		panic("asc_msg_in");
2003 	}
2004 	asc->script = state->script;
2005 	state->script = (script_t *)0;
2006 	return (0);
2007 }
2008 
2009 /* ARGSUSED */
2010 static int
2011 asc_disconnect(asc, status, ss, ir)
2012 	asc_softc_t asc;
2013 	int status, ss, ir;
2014 {
2015 #ifdef DIAGNOSTIC
2016 	if (!(asc->st[asc->target].flags & DISCONN)) {
2017 		printf("asc_disconnect: device %d: DISCONN not set!\n",
2018 			asc->target);
2019 	}
2020 #endif /* DIAGNOSTIC */
2021 	asc->target = -1;
2022 	asc->state = ASC_STATE_RESEL;
2023 	return (1);
2024 }
2025 
2026 #ifdef DEBUG
2027 /*
2028  * Dump the log buffer.
2029  */
2030 static void
2031 asc_DumpLog(str)
2032 	char *str;
2033 {
2034 	register struct asc_log *lp;
2035 	register u_int status;
2036 
2037 	printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
2038 		asc_debug_bn, asc_debug_sz);
2039 	lp = asc_logp;
2040 	do {
2041 		status = lp->status;
2042 		printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n",
2043 			status >> 24,
2044 			lp->target,
2045 			(status >> 16) & 0xFF,
2046 			(status >> 8) & 0xFF,
2047 			status & 0XFF,
2048 			lp->state,
2049 			asc_scripts[lp->state].condition,
2050 			lp->msg, lp->resid);
2051 		if (++lp >= &asc_log[NLOG])
2052 			lp = asc_log;
2053 	} while (lp != asc_logp);
2054 }
2055 #endif	/* DEBUG */
2056