xref: /netbsd/sys/arch/arc/jazz/asc.c (revision bf9ec67e)
1 /*	$NetBSD: asc.c,v 1.6 2001/11/14 18:15:15 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 struct cfattach asc_ca = {
498 	sizeof(struct asc_softc), ascmatch, ascattach
499 };
500 
501 /*
502  *  Glue to the machine dependent scsi
503  */
504 void asc_scsipi_request __P((struct scsipi_channel *,
505 				scsipi_adapter_req_t, void *));
506 
507 static int asc_intr __P((void *));
508 static void asc_poll __P((struct asc_softc *, int));
509 #ifdef DEBUG
510 static void asc_DumpLog __P((char *));
511 #endif
512 
513 /*
514  * Match driver based on name
515  */
516 int
517 ascmatch(parent, match, aux)
518 	struct device *parent;
519 	struct cfdata *match;
520 	void *aux;
521 {
522 	struct jazzio_attach_args *ja = aux;
523 
524 	if(strcmp(ja->ja_name, "asc") != 0)
525 		return (0);
526 	return (1);
527 }
528 
529 void
530 ascattach(parent, self, aux)
531 	struct device *parent;
532 	struct device *self;
533 	void *aux;
534 {
535 	struct jazzio_attach_args *ja = aux;
536 	asc_softc_t asc = (void *)self;
537 	asc_regmap_t *regs;
538 	int id, s, i;
539 	int bufsiz;
540 
541 	if (asc_conf == NULL)
542 		panic("asc_conf isn't initialized");
543 
544 	/*
545 	 * Initialize hw descriptor, cache some pointers
546 	 */
547 	asc->regs = (asc_regmap_t *)ja->ja_addr;	/* XXX */
548 
549 	/*
550 	 * Set up machine dependencies.
551 	 * 1) how to do dma
552 	 * 2) timing based on chip clock frequency
553 	 */
554 #if 1	/*XXX check if code handles 0 as 64k */
555 	bufsiz = 63 * 1024;
556 #else
557 	bufsiz = 64 * 1024;
558 #endif
559 	asc->dma = &asc->__dma;
560 	asc_dma_init(asc->dma);
561 
562 	/*
563 	 * Now for timing.
564 	 */
565 	asc->min_period = asc_conf->ac_timing->min_period;
566 	asc->max_period = asc_conf->ac_timing->max_period;
567 	asc->ccf = asc_conf->ac_timing->ccf;
568 	asc->timeout_250 = asc_conf->ac_timing->timeout_250;
569 	asc->tb_ticks = asc_conf->ac_timing->tb_ticks;
570 
571 	asc->state = ASC_STATE_IDLE;
572 	asc->target = -1;
573 
574 	regs = asc->regs;
575 
576 	/*
577 	 * Reset chip, fully.  Note that interrupts are already enabled.
578 	 */
579 	s = splbio();
580 
581 	/* preserve our ID for now */
582 	asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
583 	asc->myidmask = ~(1 << asc->sc_id);
584 
585 	/* identify 53CF9x-2 or not */
586 	regs->asc_cmd = ASC_CMD_RESET;
587 	wbflush(); DELAY(25);
588 	regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP;
589 	wbflush(); DELAY(25);
590 	regs->asc_cnfg2 = ASC_CNFG2_FE;
591 	wbflush(); DELAY(25);
592 	regs->asc_cmd = ASC_CMD_DMA | ASC_CMD_NOP;
593 	wbflush(); DELAY(25);
594 	asc->is24bit = regs->asc_id == ASC_ID_53CF94;
595 
596 	asc_reset(asc, regs);
597 
598 	/*
599 	 * Our SCSI id on the bus.
600 	 * The user can set this via the prom on 3maxen/picaen.
601 	 * If this changes it is easy to fix: make a default that
602 	 * can be changed as boot arg.
603 	 */
604 #ifdef	unneeded
605 	regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) |
606 			      (scsi_initiator_id[unit] & 0x7);
607 	asc->sc_id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
608 #endif
609 	id = asc->sc_id;
610 	splx(s);
611 
612 	/*
613 	 * Give each target its DMA buffer region.
614 	 * The buffer address is the same for all targets,
615 	 * the allocated dma viritual scatter/gather space.
616 	 */
617 	for (i = 0; i < ASC_NCMD; i++) {
618 		asc->st[i].dmaBufSize = bufsiz;
619 	}
620 
621 	/*
622 	 * Set up interrupt handler.
623          */
624 	jazzio_intr_establish(ja->ja_intr, asc_intr, (void *)asc);
625 
626 	printf(": %s, target %d\n", asc->is24bit ? "NCR53CF9X-2" : "NCR53C94",
627 	    id);
628 
629 	asc->sc_adapter.adapt_dev = &asc->sc_dev;
630 	asc->sc_adapter.adapt_nchannels = 1;
631 	asc->sc_adapter.adapt_openings = 7;
632 	asc->sc_adapter.adapt_max_periph = 1;
633 	asc->sc_adapter.adapt_ioctl = NULL;
634 	asc->sc_adapter.adapt_minphys = minphys;
635 	asc->sc_adapter.adapt_request = asc_scsipi_request;
636 
637 	memset(&asc->sc_channel, 0, sizeof(asc->sc_channel));
638 	asc->sc_channel.chan_adapter = &asc->sc_adapter;
639 	asc->sc_channel.chan_bustype = &scsi_bustype;
640 	asc->sc_channel.chan_channel = 0;
641 	asc->sc_channel.chan_ntargets = 8;
642 	asc->sc_channel.chan_nluns = 8;
643 	asc->sc_channel.chan_id = asc->sc_id;
644 
645 	/*
646 	 * Now try to attach all the sub devices.
647 	 */
648 	config_found(self, &asc->sc_channel, scsiprint);
649 }
650 
651 /*
652  * Start activity on a SCSI device.
653  * We maintain information on each device separately since devices can
654  * connect/disconnect during an operation.
655  */
656 void
657 asc_scsipi_request(chan, req, arg)
658 	struct scsipi_channel *chan;
659 	scsipi_adapter_req_t req;
660 	void *arg;
661 {
662 	struct scsipi_xfer *xs;
663 	struct scsipi_periph *periph;
664 	struct asc_softc *asc = (void *)chan->chan_adapter->adapt_dev;
665 	int dontqueue, s;
666 
667 	switch (req) {
668 	case ADAPTER_REQ_RUN_XFER:
669 		xs = arg;
670 		periph = xs->xs_periph;
671 
672 		dontqueue = xs->xs_control & XS_CTL_POLL;
673 
674 		/*
675 		 *  Flush caches for any data buffer
676 		 */
677 		if(xs->datalen != 0) {
678 			mips_dcache_wbinv_range((vaddr_t)xs->data, xs->datalen);
679 		}
680 		/*
681 		 *  The hack on the next few lines are to avoid buffers
682 		 *  mapped to UADDR. Realloc to the kva uarea address.
683 		 */
684 		if((u_int)(xs->data) >= UADDR) {
685 			xs->data = ((u_int)(xs->data) & ~UADDR) + (u_char *)(curproc->p_addr);
686 		}
687 
688 		s = splbio();
689 		asc->cmd[periph->periph_target] = xs;
690 
691 		/*
692 		 *  Going to launch.
693 		 *  Make a local copy of the command and some pointers.
694 		 */
695 		asc_startcmd(asc, periph->periph_target);
696 
697 		/*
698 		 *  If in startup, interrupts not usable yet.
699 		 */
700 		if(dontqueue) {
701 			asc_poll(asc,periph->periph_target);
702 		}
703 		splx(s);
704 		return;
705 	case ADAPTER_REQ_GROW_RESOURCES:
706 		/* XXX Not supported. */
707 		return;
708 	case ADAPTER_REQ_SET_XFER_MODE:
709 		/* XXX Not supported. */
710 		return;
711 	}
712 }
713 
714 void
715 asc_poll(asc, target)
716 	struct asc_softc *asc;
717 	int target;
718 {
719 	struct scsipi_xfer *scsicmd = asc->cmd[target];
720 	int count = scsicmd->timeout * 10;
721 
722 	while(count) {
723 		if(asc->regs->asc_status &ASC_CSR_INT) {
724 			asc_intr(asc);
725 		}
726 		if(scsicmd->xs_status & XS_STS_DONE)
727 			break;
728 		DELAY(5);
729 		count--;
730 	}
731 	if(count == 0) {
732 		scsicmd->error = XS_TIMEOUT;
733 		asc_end(asc, 0, 0, 0);
734 	}
735 }
736 
737 static void
738 asc_reset(asc, regs)
739 	asc_softc_t asc;
740 	asc_regmap_t *regs;
741 {
742 
743 	/*
744 	 * Reset chip and wait till done
745 	 */
746 	regs->asc_cmd = ASC_CMD_RESET;
747 	wbflush(); DELAY(25);
748 
749 	/* spec says this is needed after reset */
750 	regs->asc_cmd = ASC_CMD_NOP;
751 	wbflush(); DELAY(25);
752 
753 	/*
754 	 * Set up various chip parameters
755 	 */
756 	regs->asc_ccf = asc->ccf;
757 	wbflush(); DELAY(25);
758 	regs->asc_sel_timo = asc->timeout_250;
759 	/* restore our ID */
760 	regs->asc_cnfg1 = asc->sc_id | ASC_CNFG1_P_CHECK;
761 	/* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */
762 	regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL;
763 	regs->asc_cnfg3 = asc_conf->ac_cnfg3;
764 	/* zero anything else */
765 	ASC_TC_PUT(regs, 0, asc->is24bit);
766 	regs->asc_syn_p = asc->min_period;
767 	regs->asc_syn_o = 0;	/* async for now */
768 	wbflush();
769 }
770 
771 /*
772  * Start a SCSI command on a target.
773  */
774 static void
775 asc_startcmd(asc, target)
776 	asc_softc_t asc;
777 	int target;
778 {
779 	asc_regmap_t *regs;
780 	State *state;
781 	struct scsipi_xfer *scsicmd;
782 	int i, len;
783 
784 	/*
785 	 * See if another target is currently selected on this SCSI bus.
786 	 */
787 	if (asc->target >= 0)
788 		return;
789 
790 	regs = asc->regs;
791 
792 	/*
793 	 * If a reselection is in progress, it is Ok to ignore it since
794 	 * the ASC will automatically cancel the command and flush
795 	 * the FIFO if the ASC is reselected before the command starts.
796 	 * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if
797 	 * a reselect occurs before starting the command.
798 	 */
799 
800 	asc->state = ASC_STATE_BUSY;
801 	asc->target = target;
802 
803 	/* cache some pointers */
804 	scsicmd = asc->cmd[target];
805 	state = &asc->st[target];
806 
807 	/*
808 	 * Init the chip and target state.
809 	 */
810 	state->flags = state->flags & DID_SYNC;
811 	state->script = (script_t *)0;
812 	state->msg_out = SCSI_NO_OP;
813 
814 	/*
815 	 * Set up for DMA of command output. Also need to flush cache.
816 	 */
817 	bcopy(scsicmd->cmd, &state->cmd, scsicmd->cmdlen);
818 	state->cmdlen = scsicmd->cmdlen;
819 	state->buf = (vaddr_t)scsicmd->data;
820 	state->buflen = scsicmd->datalen;
821 	len = state->cmdlen;
822 	state->dmalen = len;
823 
824 #ifdef DEBUG
825 	if (asc_debug > 1) {
826 		printf("asc_startcmd: %s target %d cmd %x len %d\n",
827 			asc->sc_dev.dv_xname, target,
828 			state->cmd.opcode, state->buflen);
829 	}
830 #endif
831 
832 	/* check for simple SCSI command with no data transfer */
833 	if (scsicmd->xs_control & XS_CTL_DATA_OUT) {
834 		asc->script = &asc_scripts[SCRIPT_DATA_OUT];
835 		state->flags |= DMA_OUT;
836 	}
837 	else if (scsicmd->xs_control & XS_CTL_DATA_IN) {
838 		asc->script = &asc_scripts[SCRIPT_DATA_IN];
839 		state->flags |= DMA_IN;
840 	}
841 	else if (state->buflen == 0) {
842 		/* check for sync negotiation */
843 		if ((scsicmd->xs_status & /* SCSICMD_USE_SYNC */ 0) &&
844 		    !(state->flags & DID_SYNC)) {
845 			asc->script = &asc_scripts[SCRIPT_TRY_SYNC];
846 			state->flags |= TRY_SYNC;
847 		} else
848 			asc->script = &asc_scripts[SCRIPT_SIMPLE];
849 		state->buf = (vaddr_t)0;
850 	}
851 
852 #ifdef DEBUG
853 	asc_debug_cmd = state->cmd.opcode;
854 	if (state->cmd.opcode == SCSI_READ_EXT) {
855 		asc_debug_bn = (state->cmd.bytes[1] << 24) |
856 			(state->cmd.bytes[2] << 16) |
857 			(state->cmd.bytes[3] << 8) |
858 			 state->cmd.bytes[4];
859 		asc_debug_sz = (state->cmd.bytes[6] << 8) | state->cmd.bytes[7];
860 	}
861 	asc_logp->status = PACK(asc->sc_dev.dv_unit, 0, 0, asc_debug_cmd);
862 	asc_logp->target = asc->target;
863 	asc_logp->state = asc->script - asc_scripts;
864 	asc_logp->msg = SCSI_DIS_REC_IDENTIFY;
865 	asc_logp->resid = scsicmd->datalen;
866 	if (++asc_logp >= &asc_log[NLOG])
867 		asc_logp = asc_log;
868 #endif
869 
870 	/* preload the FIFO with the message and command to be sent */
871 	regs->asc_fifo = SCSI_DIS_REC_IDENTIFY |
872 	    (scsicmd->xs_periph->periph_lun & 0x07);
873 
874 	for( i = 0; i < len; i++ ) {
875 		regs->asc_fifo = ((caddr_t)&state->cmd)[i];
876 	}
877 	ASC_TC_PUT(regs, 0, asc->is24bit);
878 	readback(regs->asc_cmd);
879 	regs->asc_cmd = ASC_CMD_DMA;
880 	readback(regs->asc_cmd);
881 
882 	regs->asc_dbus_id = target;
883 	readback(regs->asc_dbus_id);
884 	regs->asc_syn_p = state->sync_period;
885 	readback(regs->asc_syn_p);
886 	regs->asc_syn_o = state->sync_offset;
887 	readback(regs->asc_syn_o);
888 
889 /*XXX PEFO */
890 /* we are not using sync transfer now, need to check this if we will */
891 
892 	if (state->flags & TRY_SYNC)
893 		regs->asc_cmd = ASC_CMD_SEL_ATN_STOP;
894 	else
895 		regs->asc_cmd = ASC_CMD_SEL_ATN;
896 	readback(regs->asc_cmd);
897 }
898 
899 /*
900  * Interrupt routine
901  *	Take interrupts from the chip
902  *
903  * Implementation:
904  *	Move along the current command's script if
905  *	all is well, invoke error handler if not.
906  */
907 int
908 asc_intr(sc)
909 	void *sc;
910 {
911 	asc_softc_t asc = sc;
912 	asc_regmap_t *regs = asc->regs;
913 	State *state;
914 	script_t *scpt;
915 	int ss, ir, status;
916 
917 	/* collect ephemeral information */
918 	status = regs->asc_status;
919 	ss = regs->asc_ss;
920 
921 	if ((status & ASC_CSR_INT) == 0) /* Make shure it's a real interrupt */
922 		 return(0);
923 
924 	ir = regs->asc_intr;	/* this resets the previous two */
925 	scpt = asc->script;
926 
927 #ifdef DEBUG
928 	asc_logp->status = PACK(asc->sc_dev.dv_unit, status, ss, ir);
929 	asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1;
930 	asc_logp->state = scpt - asc_scripts;
931 	asc_logp->msg = -1;
932 	asc_logp->resid = 0;
933 	if (++asc_logp >= &asc_log[NLOG])
934 		asc_logp = asc_log;
935 	if (asc_debug > 2)
936 		printf("asc_intr: status %x ss %x ir %x cond %d:%x\n",
937 			status, ss, ir, scpt - asc_scripts, scpt->condition);
938 #endif
939 
940 	/* check the expected state */
941 	if (SCRIPT_MATCH(ir, status) == scpt->condition) {
942 		/*
943 		 * Perform the appropriate operation, then proceed.
944 		 */
945 		if ((*scpt->action)(asc, status, ss, ir)) {
946 			regs->asc_cmd = scpt->command;
947 			readback(regs->asc_cmd);
948 			asc->script = scpt->next;
949 		}
950 		goto done;
951 	}
952 
953 	/*
954 	 * Check for parity error.
955 	 * Hardware will automatically set ATN
956 	 * to request the device for a MSG_OUT phase.
957 	 */
958 	if (status & ASC_CSR_PE) {
959 		printf("%s: SCSI device %d: incomming parity error seen\n",
960 			asc->sc_dev.dv_xname, asc->target);
961 		asc->st[asc->target].flags |= PARITY_ERR;
962 	}
963 
964 	/*
965 	 * Check for gross error.
966 	 * Probably a bug in a device driver.
967 	 */
968 	if (status & ASC_CSR_GE) {
969 		printf("%s: SCSI device %d: gross error\n",
970 			asc->sc_dev.dv_xname, asc->target);
971 		goto abort;
972 	}
973 
974 	/* check for message in or out */
975 	if ((ir & ~ASC_INT_FC) == ASC_INT_BS) {
976 		register int len, fifo;
977 
978 		state = &asc->st[asc->target];
979 		switch (ASC_PHASE(status)) {
980 		case ASC_PHASE_DATAI:
981 		case ASC_PHASE_DATAO:
982 			ASC_TC_GET(regs, len);
983 			fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
984 			printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n",
985 				state->buflen, state->dmalen, len, fifo);
986 			goto abort;
987 
988 		case ASC_PHASE_MSG_IN:
989 			break;
990 
991 		case ASC_PHASE_MSG_OUT:
992 			/*
993 			 * Check for parity error.
994 			 * Hardware will automatically set ATN
995 			 * to request the device for a MSG_OUT phase.
996 			 */
997 			if (state->flags & PARITY_ERR) {
998 				state->flags &= ~PARITY_ERR;
999 				state->msg_out = SCSI_MESSAGE_PARITY_ERROR;
1000 				/* reset message in counter */
1001 				state->msglen = 0;
1002 			} else
1003 				state->msg_out = SCSI_NO_OP;
1004 			regs->asc_fifo = state->msg_out;
1005 			regs->asc_cmd = ASC_CMD_XFER_INFO;
1006 			readback(regs->asc_cmd);
1007 			goto done;
1008 
1009 		case ASC_PHASE_STATUS:
1010 			/* probably an error in the SCSI command */
1011 			asc->script = &asc_scripts[SCRIPT_GET_STATUS];
1012 			regs->asc_cmd = ASC_CMD_I_COMPLETE;
1013 			readback(regs->asc_cmd);
1014 			goto done;
1015 
1016 		default:
1017 			goto abort;
1018 		}
1019 
1020 		if (state->script)
1021 			goto abort;
1022 
1023 		/*
1024 		 * OK, message coming in clean up whatever is going on.
1025 		 * Get number of bytes left to transfered from byte counter
1026 		 * counter decrements when data is trf on the SCSI bus
1027 		 */
1028 		ASC_TC_GET(regs, len);
1029 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1030 		/* flush any data in the FIFO */
1031 		if (fifo && !(state->flags & DMA_IN_PROGRESS)) {
1032 printf("asc_intr: fifo flush %d len %d fifo %x\n", fifo, len, regs->asc_fifo);
1033 			regs->asc_cmd = ASC_CMD_FLUSH;
1034 			readback(regs->asc_cmd);
1035 			DELAY(2);
1036 		}
1037 		else if (fifo && state->flags & DMA_IN_PROGRESS) {
1038 			if (state->flags & DMA_OUT) {
1039 				len += fifo; /* Bytes dma'ed but not sent */
1040 			}
1041 			else if (state->flags & DMA_IN) {
1042 				printf("asc_intr: IN: dmalen %d len %d fifo %d\n",
1043 					state->dmalen, len, fifo); /* XXX */
1044 			}
1045 			regs->asc_cmd = ASC_CMD_FLUSH;
1046 			readback(regs->asc_cmd);
1047 			DELAY(2);
1048 		}
1049 		if (len && (state->flags & DMA_IN_PROGRESS)) {
1050 			/* save number of bytes still to be sent or received */
1051 			state->dmaresid = len;
1052 			state->flags &= ~DMA_IN_PROGRESS;
1053 			ASC_TC_PUT(regs, 0, asc->is24bit);
1054 #ifdef DEBUG
1055 			if (asc_logp == asc_log)
1056 				asc_log[NLOG - 1].resid = len;
1057 			else
1058 				asc_logp[-1].resid = len;
1059 #endif
1060 			/* setup state to resume to */
1061 			if (state->flags & DMA_IN) {
1062 				/*
1063 				 * Since the ASC_CNFG3_SRB bit of the
1064 				 * cnfg3 register bit is not set,
1065 				 * we just transferred an extra byte.
1066 				 * Since we can't resume on an odd byte
1067 				 * boundary, we copy the valid data out
1068 				 * and resume DMA at the start address.
1069 				 */
1070 				if (len & 1) {
1071 					printf("asc_intr: msg in len %d (fifo %d)\n",
1072 						len, fifo); /* XXX */
1073 					len = state->dmalen - len;
1074 					goto do_in;
1075 				}
1076 				state->script =
1077 					&asc_scripts[SCRIPT_RESUME_DMA_IN];
1078 			} else if (state->flags & DMA_OUT)
1079 				state->script =
1080 					&asc_scripts[SCRIPT_RESUME_DMA_OUT];
1081 			else
1082 				state->script = asc->script;
1083 		} else if (state->flags & DMA_IN) {
1084 			if (len) {
1085 #ifdef DEBUG
1086 				printf("asc_intr: 1: bn %d len %d (fifo %d)\n",
1087 					asc_debug_bn, len, fifo); /* XXX */
1088 #endif
1089 				goto abort;
1090 			}
1091 			/* setup state to resume to */
1092 			if (state->flags & DMA_IN_PROGRESS) {
1093 				len = state->dmalen;
1094 				state->flags &= ~DMA_IN_PROGRESS;
1095 			do_in:
1096 				DMA_END(asc->dma);
1097 				state->buf += len;
1098 				state->buflen -= len;
1099 			}
1100 			if (state->buflen)
1101 				state->script =
1102 				    &asc_scripts[SCRIPT_RESUME_IN];
1103 			else
1104 				state->script =
1105 				    &asc_scripts[SCRIPT_RESUME_NO_DATA];
1106 		} else if (state->flags & DMA_OUT) {
1107 			if (len) {
1108 				printf("asc_intr: 2: len %d (fifo %d)\n", len,
1109 					fifo); /* XXX */
1110 /* XXX THEO */
1111 #if 1
1112 				regs->asc_cmd = ASC_CMD_FLUSH;
1113 				readback(regs->asc_cmd);
1114 				DELAY(2);
1115 				len = 0;
1116 #else
1117 				goto abort;
1118 #endif
1119 			}
1120 			/*
1121 			 * If this is the last chunk, the next expected
1122 			 * state is to get status.
1123 			 */
1124 			if (state->flags & DMA_IN_PROGRESS) {
1125 				state->flags &= ~DMA_IN_PROGRESS;
1126 				DMA_END(asc->dma);
1127 				len = state->dmalen;
1128 				state->buf += len;
1129 				state->buflen -= len;
1130 			}
1131 			if (state->buflen)
1132 				state->script =
1133 				    &asc_scripts[SCRIPT_RESUME_OUT];
1134 			else
1135 				state->script =
1136 				    &asc_scripts[SCRIPT_RESUME_NO_DATA];
1137 		} else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
1138 			state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA];
1139 		else
1140 			state->script = asc->script;
1141 
1142 		/* setup to receive a message */
1143 		asc->script = &asc_scripts[SCRIPT_MSG_IN];
1144 		state->msglen = 0;
1145 		regs->asc_cmd = ASC_CMD_XFER_INFO;
1146 		readback(regs->asc_cmd);
1147 		goto done;
1148 	}
1149 
1150 	/* check for SCSI bus reset */
1151 	if (ir & ASC_INT_RESET) {
1152 		register int i;
1153 
1154 		printf("%s: SCSI bus reset!!\n", asc->sc_dev.dv_xname);
1155 		/* need to flush any pending commands */
1156 		for (i = 0; i < ASC_NCMD; i++) {
1157 			if (!asc->cmd[i])
1158 				continue;
1159 			asc->cmd[i]->error = XS_DRIVER_STUFFUP;
1160 			asc_end(asc, 0, 0, 0);
1161 		}
1162 		/* rearbitrate synchronous offset */
1163 		for (i = 0; i < ASC_NCMD; i++) {
1164 			asc->st[i].sync_offset = 0;
1165 			asc->st[i].flags = 0;
1166 		}
1167 		asc->target = -1;
1168 		return(1);
1169 	}
1170 
1171 	/* check for command errors */
1172 	if (ir & ASC_INT_ILL)
1173 		goto abort;
1174 
1175 	/* check for disconnect */
1176 	if (ir & ASC_INT_DISC) {
1177 		state = &asc->st[asc->target];
1178 		switch (asc->script - asc_scripts) {
1179 		case SCRIPT_DONE:
1180 		case SCRIPT_DISCONNECT:
1181 			/*
1182 			 * Disconnects can happen normally when the
1183 			 * command is complete with the phase being
1184 			 * either ASC_PHASE_DATAO or ASC_PHASE_MSG_IN.
1185 			 * The SCRIPT_MATCH() only checks for one phase
1186 			 * so we can wind up here.
1187 			 * Perform the appropriate operation, then proceed.
1188 			 */
1189 			if ((*scpt->action)(asc, status, ss, ir)) {
1190 				regs->asc_cmd = scpt->command;
1191 				readback(regs->asc_cmd);
1192 				asc->script = scpt->next;
1193 			}
1194 			goto done;
1195 
1196 		case SCRIPT_TRY_SYNC:
1197 		case SCRIPT_SIMPLE:
1198 		case SCRIPT_DATA_IN:
1199 		case SCRIPT_DATA_OUT: /* one of the starting scripts */
1200 			if (ASC_SS(ss) == 0) {
1201 				/* device did not respond */
1202 				if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) {
1203 					regs->asc_cmd = ASC_CMD_FLUSH;
1204 					readback(regs->asc_cmd);
1205 				}
1206 				asc->cmd[asc->target]->error = XS_SELTIMEOUT;
1207 				asc_end(asc, status, ss, ir);
1208 				return(1);
1209 			}
1210 			/* FALLTHROUGH */
1211 
1212 		default:
1213 			printf("%s: SCSI device %d: unexpected disconnect\n",
1214 				asc->sc_dev.dv_xname, asc->target);
1215 #ifdef DEBUG
1216 			asc_DumpLog("asc_disc");
1217 #endif
1218 			/*
1219 			 * On rare occasions my RZ24 does a disconnect during
1220 			 * data in phase and the following seems to keep it
1221 			 * happy.
1222 			 * XXX Should a scsi disk ever do this??
1223 			 */
1224 			asc->script = &asc_scripts[SCRIPT_RESEL];
1225 			asc->state = ASC_STATE_RESEL;
1226 			state->flags |= DISCONN;
1227 			regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1228 			readback(regs->asc_cmd);
1229 			return(1);
1230 		}
1231 	}
1232 
1233 	/* check for reselect */
1234 	if (ir & ASC_INT_RESEL) {
1235 		unsigned fifo, id, msg;
1236 
1237 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1238 		if (fifo < 2)
1239 			goto abort;
1240 		/* read unencoded SCSI ID and convert to binary */
1241 		msg = regs->asc_fifo & asc->myidmask;
1242 		for (id = 0; (msg & 1) == 0; id++)
1243 			msg >>= 1;
1244 		/* read identify message */
1245 		msg = regs->asc_fifo;
1246 #ifdef DEBUG
1247 		if (asc_logp == asc_log)
1248 			asc_log[NLOG - 1].msg = msg;
1249 		else
1250 			asc_logp[-1].msg = msg;
1251 #endif
1252 		asc->state = ASC_STATE_BUSY;
1253 		asc->target = id;
1254 		state = &asc->st[id];
1255 		asc->script = state->script;
1256 		state->script = (script_t *)0;
1257 		if (!(state->flags & DISCONN))
1258 			goto abort;
1259 		state->flags &= ~DISCONN;
1260 		regs->asc_syn_p = state->sync_period;
1261 		regs->asc_syn_o = state->sync_offset;
1262 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
1263 		readback(regs->asc_cmd);
1264 		goto done;
1265 	}
1266 
1267 	/* check if we are being selected as a target */
1268 	if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
1269 		goto abort;
1270 
1271 	/*
1272 	 * 'ir' must be just ASC_INT_FC.
1273 	 * This is normal if canceling an ASC_ENABLE_SEL.
1274 	 */
1275 
1276 done:
1277 	wbflush();
1278 	/*
1279 	 * If the next interrupt comes in immediatly the interrupt
1280 	 * dispatcher (which we are returning to) will catch it
1281 	 * before returning to the interrupted code.
1282 	 */
1283 	return(1);
1284 
1285 abort:
1286 #ifdef DEBUG
1287 	asc_DumpLog("asc_intr");
1288 #endif
1289 	panic("asc_intr");
1290 	return(1);
1291 }
1292 
1293 /*
1294  * All the many little things that the interrupt
1295  * routine might switch to.
1296  */
1297 
1298 /* ARGSUSED */
1299 static int
1300 script_nop(asc, status, ss, ir)
1301 	asc_softc_t asc;
1302 	int status, ss, ir;
1303 {
1304 	return (1);
1305 }
1306 
1307 /* ARGSUSED */
1308 static int
1309 asc_get_status(asc, status, ss, ir)
1310 	register asc_softc_t asc;
1311 	register int status, ss, ir;
1312 {
1313 	register asc_regmap_t *regs = asc->regs;
1314 	register int data;
1315 
1316 	/*
1317 	 * Get the last two bytes in the FIFO.
1318 	 */
1319 	if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
1320 		printf("asc_get_status: cmdreg %x, fifo cnt %d\n",
1321 		       regs->asc_cmd, data); /* XXX */
1322 #ifdef DEBUG
1323 		asc_DumpLog("get_status"); /* XXX */
1324 #endif
1325 		if (data < 2) {
1326 			asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
1327 			readback(asc->regs->asc_cmd);
1328 			return (0);
1329 		}
1330 		do {
1331 			data = regs->asc_fifo;
1332 		} while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2);
1333 	}
1334 
1335 	/* save the status byte */
1336 	asc->st[asc->target].statusByte = data = regs->asc_fifo;
1337 #ifdef DEBUG
1338 	if (asc_logp == asc_log)
1339 		asc_log[NLOG - 1].msg = data;
1340 	else
1341 		asc_logp[-1].msg = data;
1342 #endif
1343 
1344 	/* get the (presumed) command_complete message */
1345 	if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE)
1346 		return (1);
1347 
1348 #ifdef DEBUG
1349 	printf("asc_get_status: status %x cmd %x\n",
1350 		asc->st[asc->target].statusByte, data);
1351 	asc_DumpLog("asc_get_status");
1352 #endif
1353 	return (0);
1354 }
1355 
1356 /* ARGSUSED */
1357 static int
1358 asc_end(asc, status, ss, ir)
1359 	asc_softc_t asc;
1360 	int status, ss, ir;
1361 {
1362 	struct scsipi_xfer *scsicmd;
1363 	struct scsipi_periph *periph;
1364 	State *state;
1365 	int i, target;
1366 
1367 	asc->state = ASC_STATE_IDLE;
1368 	target = asc->target;
1369 	asc->target = -1;
1370 	scsicmd = asc->cmd[target];
1371 	periph = scsicmd->xs_periph;
1372 	asc->cmd[target] = (struct scsipi_xfer *)0;
1373 	state = &asc->st[target];
1374 
1375 #ifdef DEBUG
1376 	if (asc_debug > 1) {
1377 		printf("asc_end: %s target %d cmd %x err %d resid %d\n",
1378 			asc->sc_dev.dv_xname, target,
1379 			state->cmd.opcode, scsicmd->error, state->buflen);
1380 	}
1381 #endif
1382 #ifdef DIAGNOSTIC
1383 	if (target < 0 || !scsicmd)
1384 		panic("asc_end");
1385 #endif
1386 
1387 	/* look for disconnected devices */
1388 	for (i = 0; i < ASC_NCMD; i++) {
1389 		if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN))
1390 			continue;
1391 		asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1392 		readback(asc->regs->asc_cmd);
1393 		asc->state = ASC_STATE_RESEL;
1394 		asc->script = &asc_scripts[SCRIPT_RESEL];
1395 		break;
1396 	}
1397 
1398 	if(scsicmd->error == XS_NOERROR) {
1399 		if((state->statusByte & ST_MASK) == SCSI_CHECK) {
1400 			scsicmd->status = state->statusByte;
1401 			scsicmd->error = XS_BUSY;
1402 		}
1403 	}
1404 
1405 	scsicmd->resid = state->buflen;
1406 
1407 	/*
1408 	 * Look for another device that is ready.
1409 	 * May want to keep last one started and increment for fairness
1410 	 * rather than always starting at zero.
1411 	 */
1412 	for (i = 0; i < ASC_NCMD; i++) {
1413 		/* don't restart a disconnected command */
1414 		if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
1415 			continue;
1416 		asc_startcmd(asc, i);
1417 		break;
1418 	}
1419 
1420 	/* signal device driver that the command is done */
1421 	scsipi_done(scsicmd);
1422 
1423 	return (0);
1424 }
1425 
1426 /* ARGSUSED */
1427 static int
1428 asc_dma_in(asc, status, ss, ir)
1429 	register asc_softc_t asc;
1430 	register int status, ss, ir;
1431 {
1432 	register asc_regmap_t *regs = asc->regs;
1433 	register State *state = &asc->st[asc->target];
1434 	register int len;
1435 
1436 	/* check for previous chunk in buffer */
1437 	if (state->flags & DMA_IN_PROGRESS) {
1438 		/*
1439 		 * Only count bytes that have been copied to memory.
1440 		 * There may be some bytes in the FIFO if synchonous transfers
1441 		 * are in progress.
1442 		 */
1443 		DMA_END(asc->dma);
1444 		ASC_TC_GET(regs, len);
1445 		len = state->dmalen - len;
1446 		state->buf += len;
1447 		state->buflen -= len;
1448 	}
1449 
1450 	/* setup to start reading the next chunk */
1451 	len = state->buflen;
1452 #ifdef DEBUG
1453 	if (asc_logp == asc_log)
1454 		asc_log[NLOG - 1].resid = len;
1455 	else
1456 		asc_logp[-1].resid = len;
1457 #endif
1458 	if (len > state->dmaBufSize)
1459 		len = state->dmaBufSize;
1460 	state->dmalen = len;
1461 	DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
1462 	ASC_TC_PUT(regs, len, asc->is24bit);
1463 #ifdef DEBUG
1464 	if (asc_debug > 2)
1465 		printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len);
1466 #endif
1467 
1468 	/* check for next chunk */
1469 	state->flags |= DMA_IN_PROGRESS;
1470 	if (len != state->buflen) {
1471 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1472 		readback(regs->asc_cmd);
1473 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1474 		return (0);
1475 	}
1476 	return (1);
1477 }
1478 
1479 /* ARGSUSED */
1480 static int
1481 asc_last_dma_in(asc, status, ss, ir)
1482 	register asc_softc_t asc;
1483 	register int status, ss, ir;
1484 {
1485 	register asc_regmap_t *regs = asc->regs;
1486 	register State *state = &asc->st[asc->target];
1487 	register int len, fifo;
1488 
1489 	DMA_END(asc->dma);
1490 	ASC_TC_GET(regs, len);
1491 	fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1492 #ifdef DEBUG
1493 	if (asc_debug > 2)
1494 		printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n",
1495 			state->buflen, state->dmalen, len, fifo);
1496 #endif
1497 	if (fifo) {
1498 		/* device must be trying to send more than we expect */
1499 		regs->asc_cmd = ASC_CMD_FLUSH;
1500 		readback(regs->asc_cmd);
1501 	}
1502 	state->flags &= ~DMA_IN_PROGRESS;
1503 	len = state->dmalen - len;
1504 	state->buflen -= len;
1505 
1506 	return (1);
1507 }
1508 
1509 /* ARGSUSED */
1510 static int
1511 asc_resume_in(asc, status, ss, ir)
1512 	register asc_softc_t asc;
1513 	register int status, ss, ir;
1514 {
1515 	register asc_regmap_t *regs = asc->regs;
1516 	register State *state = &asc->st[asc->target];
1517 	register int len;
1518 
1519 	/* setup to start reading the next chunk */
1520 	len = state->buflen;
1521 #ifdef DEBUG
1522 	if (asc_logp == asc_log)
1523 		asc_log[NLOG - 1].resid = len;
1524 	else
1525 		asc_logp[-1].resid = len;
1526 #endif
1527 	if (len > state->dmaBufSize)
1528 		len = state->dmaBufSize;
1529 	state->dmalen = len;
1530 #ifdef DEBUG
1531 	if (asc_logp == asc_log)
1532 		asc_log[NLOG - 1].resid = len;
1533 	else
1534 		asc_logp[-1].resid = len;
1535 #endif
1536 	DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_FROM_DEV);
1537 	ASC_TC_PUT(regs, len, asc->is24bit);
1538 #ifdef DEBUG
1539 	if (asc_debug > 2)
1540 		printf("asc_resume_in: buflen %d, len %d\n", state->buflen,
1541 			len);
1542 #endif
1543 
1544 	/* check for next chunk */
1545 	state->flags |= DMA_IN_PROGRESS;
1546 	if (len != state->buflen) {
1547 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1548 		readback(regs->asc_cmd);
1549 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1550 		return (0);
1551 	}
1552 	return (1);
1553 }
1554 
1555 /* ARGSUSED */
1556 static int
1557 asc_resume_dma_in(asc, status, ss, ir)
1558 	register asc_softc_t asc;
1559 	register int status, ss, ir;
1560 {
1561 	register asc_regmap_t *regs = asc->regs;
1562 	register State *state = &asc->st[asc->target];
1563 	register int len, off;
1564 
1565 	/* setup to finish reading the current chunk */
1566 	len = state->dmaresid;
1567 	off = state->dmalen - len;
1568 	if ((off & 1) && state->sync_offset) {
1569 		printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n",
1570 			state->dmalen, len, off); /* XXX */
1571 		regs->asc_res_fifo = ((u_char *)state->buf)[off];
1572 /*XXX Need to flush cache ? */
1573 	}
1574 	DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_FROM_DEV);
1575 	ASC_TC_PUT(regs, len, asc->is24bit);
1576 #ifdef DEBUG
1577 	if (asc_debug > 2)
1578 		printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n",
1579 			state->dmalen, state->buflen, len, off);
1580 #endif
1581 
1582 	/* check for next chunk */
1583 	state->flags |= DMA_IN_PROGRESS;
1584 	if (state->dmalen != state->buflen) {
1585 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1586 		readback(regs->asc_cmd);
1587 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1588 		return (0);
1589 	}
1590 	return (1);
1591 }
1592 
1593 /* ARGSUSED */
1594 static int
1595 asc_dma_out(asc, status, ss, ir)
1596 	register asc_softc_t asc;
1597 	register int status, ss, ir;
1598 {
1599 	register asc_regmap_t *regs = asc->regs;
1600 	register State *state = &asc->st[asc->target];
1601 	register int len, fifo;
1602 
1603 	if (state->flags & DMA_IN_PROGRESS) {
1604 		/* check to be sure previous chunk was finished */
1605 		ASC_TC_GET(regs, len);
1606 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1607 		if (len || fifo)
1608 			printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1609 				state->buflen, state->dmalen, len, fifo); /* XXX */
1610 		len += fifo;
1611 		len = state->dmalen - len;
1612 		state->buf += len;
1613 		state->buflen -= len;
1614 	}
1615 
1616 	/* setup for this chunk */
1617 	len = state->buflen;
1618 #ifdef DEBUG
1619 	if (asc_logp == asc_log)
1620 		asc_log[NLOG - 1].resid = len;
1621 	else
1622 		asc_logp[-1].resid = len;
1623 #endif
1624 	if (len > state->dmaBufSize)
1625 		len = state->dmaBufSize;
1626 	state->dmalen = len;
1627 	DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
1628 	ASC_TC_PUT(regs, len, asc->is24bit);
1629 #ifdef DEBUG
1630 	if (asc_debug > 2)
1631 		printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len);
1632 #endif
1633 
1634 	/* check for next chunk */
1635 	state->flags |= DMA_IN_PROGRESS;
1636 	if (len != state->buflen) {
1637 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1638 		readback(regs->asc_cmd);
1639 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1640 		return (0);
1641 	}
1642 	return (1);
1643 }
1644 
1645 /* ARGSUSED */
1646 static int
1647 asc_last_dma_out(asc, status, ss, ir)
1648 	register asc_softc_t asc;
1649 	register int status, ss, ir;
1650 {
1651 	register asc_regmap_t *regs = asc->regs;
1652 	register State *state = &asc->st[asc->target];
1653 	register int len, fifo;
1654 
1655 	ASC_TC_GET(regs, len);
1656 	fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1657 #ifdef DEBUG
1658 	if (asc_debug > 2)
1659 		printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1660 			state->buflen, state->dmalen, len, fifo);
1661 #endif
1662 	if (fifo) {
1663 		len += fifo;
1664 		regs->asc_cmd = ASC_CMD_FLUSH;
1665 		readback(regs->asc_cmd);
1666 	}
1667 	state->flags &= ~DMA_IN_PROGRESS;
1668 	len = state->dmalen - len;
1669 	state->buflen -= len;
1670 	return (1);
1671 }
1672 
1673 /* ARGSUSED */
1674 static int
1675 asc_resume_out(asc, status, ss, ir)
1676 	register asc_softc_t asc;
1677 	register int status, ss, ir;
1678 {
1679 	register asc_regmap_t *regs = asc->regs;
1680 	register State *state = &asc->st[asc->target];
1681 	register int len;
1682 
1683 	/* setup for this chunk */
1684 	len = state->buflen;
1685 #ifdef DEBUG
1686 	if (asc_logp == asc_log)
1687 		asc_log[NLOG - 1].resid = len;
1688 	else
1689 		asc_logp[-1].resid = len;
1690 #endif
1691 	if (len > state->dmaBufSize)
1692 		len = state->dmaBufSize;
1693 	state->dmalen = len;
1694 #ifdef DEBUG
1695  	if (asc_logp == asc_log)
1696 		asc_log[NLOG - 1].resid = len;
1697 	else
1698 		asc_logp[-1].resid = len;
1699 #endif
1700 	DMA_START(asc->dma, (caddr_t)state->buf, len, DMA_TO_DEV);
1701 	ASC_TC_PUT(regs, len, asc->is24bit);
1702 #ifdef DEBUG
1703 	if (asc_debug > 2)
1704 		printf("asc_resume_out: buflen %d, len %d\n", state->buflen,
1705 			len);
1706 #endif
1707 
1708 	/* check for next chunk */
1709 	state->flags |= DMA_IN_PROGRESS;
1710 	if (len != state->buflen) {
1711 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1712 		readback(regs->asc_cmd);
1713 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1714 		return (0);
1715 	}
1716 	return (1);
1717 }
1718 
1719 /* ARGSUSED */
1720 static int
1721 asc_resume_dma_out(asc, status, ss, ir)
1722 	register asc_softc_t asc;
1723 	register int status, ss, ir;
1724 {
1725 	register asc_regmap_t *regs = asc->regs;
1726 	register State *state = &asc->st[asc->target];
1727 	register int len, off;
1728 
1729 	/* setup to finish writing this chunk */
1730 	len = state->dmaresid;
1731 	off = state->dmalen - len;
1732 	if (off & 1) {
1733 		printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",
1734 			state->dmalen, len, off); /* XXX */
1735 		regs->asc_fifo = ((u_char *)state->buf)[off];
1736 /*XXX Need to flush Cache ? */
1737 		off++;
1738 		len--;
1739 	}
1740 	DMA_START(asc->dma, (caddr_t)state->buf + off, len, DMA_TO_DEV);
1741 	ASC_TC_PUT(regs, len, asc->is24bit);
1742 #ifdef DEBUG
1743 	if (asc_debug > 2)
1744 		printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n",
1745 			state->dmalen, state->buflen, len, off);
1746 #endif
1747 
1748 	/* check for next chunk */
1749 	state->flags |= DMA_IN_PROGRESS;
1750 	if (state->dmalen != state->buflen) {
1751 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1752 		readback(regs->asc_cmd);
1753 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1754 		return (0);
1755 	}
1756 	return (1);
1757 }
1758 
1759 /* ARGSUSED */
1760 static int
1761 asc_sendsync(asc, status, ss, ir)
1762 	register asc_softc_t asc;
1763 	register int status, ss, ir;
1764 {
1765 	register asc_regmap_t *regs = asc->regs;
1766 	register State *state = &asc->st[asc->target];
1767 
1768 	/* send the extended synchronous negotiation message */
1769 	regs->asc_fifo = SCSI_EXTENDED_MSG;
1770 	wbflush();
1771 	regs->asc_fifo = 3;
1772 	wbflush();
1773 	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1774 	wbflush();
1775 	regs->asc_fifo = SCSI_MIN_PERIOD;
1776 	wbflush();
1777 	regs->asc_fifo = ASC_MAX_OFFSET;
1778 	/* state to resume after we see the sync reply message */
1779 	state->script = asc->script + 2;
1780 	state->msglen = 0;
1781 	return (1);
1782 }
1783 
1784 /* ARGSUSED */
1785 static int
1786 asc_replysync(asc, status, ss, ir)
1787 	register asc_softc_t asc;
1788 	register int status, ss, ir;
1789 {
1790 	register asc_regmap_t *regs = asc->regs;
1791 	register State *state = &asc->st[asc->target];
1792 
1793 #ifdef DEBUG
1794 	if (asc_debug > 2)
1795 		printf("asc_replysync: %x %x\n",
1796 			asc_to_scsi_period[state->sync_period] * asc->tb_ticks,
1797 			state->sync_offset);
1798 #endif
1799 	/* send synchronous transfer in response to a request */
1800 	regs->asc_fifo = SCSI_EXTENDED_MSG;
1801 	wbflush();
1802 	regs->asc_fifo = 3;
1803 	wbflush();
1804 	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1805 	wbflush();
1806 	regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks;
1807 	wbflush();
1808 	regs->asc_fifo = state->sync_offset;
1809 	regs->asc_cmd = ASC_CMD_XFER_INFO;
1810 	readback(regs->asc_cmd);
1811 
1812 	/* return to the appropriate script */
1813 	if (!state->script) {
1814 #ifdef DEBUG
1815 		asc_DumpLog("asc_replsync");
1816 #endif
1817 		panic("asc_replysync");
1818 	}
1819 	asc->script = state->script;
1820 	state->script = (script_t *)0;
1821 	return (0);
1822 }
1823 
1824 /* ARGSUSED */
1825 static int
1826 asc_msg_in(asc, status, ss, ir)
1827 	register asc_softc_t asc;
1828 	register int status, ss, ir;
1829 {
1830 	register asc_regmap_t *regs = asc->regs;
1831 	register State *state = &asc->st[asc->target];
1832 	register int msg;
1833 	int i;
1834 
1835 	/* read one message byte */
1836 	msg = regs->asc_fifo;
1837 #ifdef DEBUG
1838 	if (asc_logp == asc_log)
1839 		asc_log[NLOG - 1].msg = msg;
1840 	else
1841 		asc_logp[-1].msg = msg;
1842 #endif
1843 
1844 	/* check for multi-byte message */
1845 	if (state->msglen != 0) {
1846 		/* first byte is the message length */
1847 		if (state->msglen < 0) {
1848 			state->msglen = msg;
1849 			return (1);
1850 		}
1851 		if (state->msgcnt >= state->msglen)
1852 			goto abort;
1853 		state->msg_in[state->msgcnt++] = msg;
1854 
1855 		/* did we just read the last byte of the message? */
1856 		if (state->msgcnt != state->msglen)
1857 			return (1);
1858 
1859 		/* process an extended message */
1860 #ifdef DEBUG
1861 		if (asc_debug > 2)
1862 			printf("asc_msg_in: msg %x %x %x\n",
1863 				state->msg_in[0],
1864 				state->msg_in[1],
1865 				state->msg_in[2]);
1866 #endif
1867 		switch (state->msg_in[0]) {
1868 		case SCSI_SYNCHRONOUS_XFER:
1869 			state->flags |= DID_SYNC;
1870 			state->sync_offset = state->msg_in[2];
1871 
1872 			/* convert SCSI period to ASC period */
1873 			i = state->msg_in[1] / asc->tb_ticks;
1874 			if (i < asc->min_period)
1875 				i = asc->min_period;
1876 			else if (i >= asc->max_period) {
1877 				/* can't do sync transfer, period too long */
1878 				printf("%s: SCSI device %d: sync xfer period too long (%d)\n",
1879 					asc->sc_dev.dv_xname, asc->target, i);
1880 				i = asc->max_period;
1881 				state->sync_offset = 0;
1882 			}
1883 			if ((i * asc->tb_ticks) != state->msg_in[1])
1884 				i++;
1885 			state->sync_period = i & 0x1F;
1886 
1887 			/*
1888 			 * If this is a request, check minimums and
1889 			 * send back an acknowledge.
1890 			 */
1891 			if (!(state->flags & TRY_SYNC)) {
1892 				regs->asc_cmd = ASC_CMD_SET_ATN;
1893 				readback(regs->asc_cmd);
1894 
1895 				if (state->sync_period < asc->min_period)
1896 					state->sync_period =
1897 						asc->min_period;
1898 				if (state->sync_offset > ASC_MAX_OFFSET)
1899 					state->sync_offset =
1900 						ASC_MAX_OFFSET;
1901 				asc->script = &asc_scripts[SCRIPT_REPLY_SYNC];
1902 				regs->asc_syn_p = state->sync_period;
1903 				readback(regs->asc_syn_p);
1904 				regs->asc_syn_o = state->sync_offset;
1905 				readback(regs->asc_syn_o);
1906 				regs->asc_cmd = ASC_CMD_MSG_ACPT;
1907 				readback(regs->asc_cmd);
1908 				return (0);
1909 			}
1910 
1911 			regs->asc_syn_p = state->sync_period;
1912 			readback(regs->asc_syn_p);
1913 			regs->asc_syn_o = state->sync_offset;
1914 			readback(regs->asc_syn_o);
1915 			goto done;
1916 
1917 		default:
1918 			printf("%s: SCSI device %d: rejecting extended message 0x%x\n",
1919 				 asc->sc_dev.dv_xname, asc->target,
1920 				state->msg_in[0]);
1921 			goto reject;
1922 		}
1923 	}
1924 
1925 	/* process first byte of a message */
1926 #ifdef DEBUG
1927 	if (asc_debug > 2)
1928 		printf("asc_msg_in: msg %x\n", msg);
1929 #endif
1930 	switch (msg) {
1931 #if 0
1932 	case SCSI_MESSAGE_REJECT:
1933 		printf(" did not like SYNCH xfer "); /* XXX */
1934 		state->flags |= DID_SYNC;
1935 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
1936 		readback(regs->asc_cmd);
1937 		status = asc_wait(regs, ASC_CSR_INT);
1938 		ir = regs->asc_intr;
1939 		/* some just break out here, some dont */
1940 		if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {
1941 			regs->asc_fifo = SCSI_ABORT;
1942 			regs->asc_cmd = ASC_CMD_XFER_INFO;
1943 			readback(regs->asc_cmd);
1944 			status = asc_wait(regs, ASC_CSR_INT);
1945 			ir = regs->asc_intr;
1946 		}
1947 		if (ir & ASC_INT_DISC) {
1948 			asc_end(asc, status, 0, ir);
1949 			return (0);
1950 		}
1951 		goto status;
1952 #endif /* 0 */
1953 
1954 	case SCSI_EXTENDED_MSG: /* read an extended message */
1955 		/* setup to read message length next */
1956 		state->msglen = -1;
1957 		state->msgcnt = 0;
1958 		return (1);
1959 
1960 	case SCSI_NO_OP:
1961 		break;
1962 
1963 	case SCSI_SAVE_DATA_POINTER:
1964 		/* expect another message */
1965 		return (1);
1966 
1967 	case SCSI_RESTORE_POINTERS:
1968 		/*
1969 		 * Need to do the following if resuming synchonous data in
1970 		 * on an odd byte boundary.
1971 		regs->asc_cnfg2 |= ASC_CNFG2_RFB;
1972 		 */
1973 		break;
1974 
1975 	case SCSI_DISCONNECT:
1976 		if (state->flags & DISCONN)
1977 			goto abort;
1978 		state->flags |= DISCONN;
1979 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
1980 		readback(regs->asc_cmd);
1981 		asc->script = &asc_scripts[SCRIPT_DISCONNECT];
1982 		return (0);
1983 
1984 	default:
1985 		printf("%s: SCSI device %d: rejecting message 0x%x\n",
1986 			asc->sc_dev.dv_xname, asc->target, msg);
1987 	reject:
1988 		/* request a message out before acknowledging this message */
1989 		state->msg_out = SCSI_MESSAGE_REJECT;
1990 		regs->asc_cmd = ASC_CMD_SET_ATN;
1991 		readback(regs->asc_cmd);
1992 	}
1993 
1994 done:
1995 	/* return to original script */
1996 	regs->asc_cmd = ASC_CMD_MSG_ACPT;
1997 	readback(regs->asc_cmd);
1998 	if (!state->script) {
1999 	abort:
2000 #ifdef DEBUG
2001 		asc_DumpLog("asc_msg_in");
2002 #endif
2003 		panic("asc_msg_in");
2004 	}
2005 	asc->script = state->script;
2006 	state->script = (script_t *)0;
2007 	return (0);
2008 }
2009 
2010 /* ARGSUSED */
2011 static int
2012 asc_disconnect(asc, status, ss, ir)
2013 	asc_softc_t asc;
2014 	int status, ss, ir;
2015 {
2016 #ifdef DIAGNOSTIC
2017 	if (!(asc->st[asc->target].flags & DISCONN)) {
2018 		printf("asc_disconnect: device %d: DISCONN not set!\n",
2019 			asc->target);
2020 	}
2021 #endif /* DIAGNOSTIC */
2022 	asc->target = -1;
2023 	asc->state = ASC_STATE_RESEL;
2024 	return (1);
2025 }
2026 
2027 #ifdef DEBUG
2028 /*
2029  * Dump the log buffer.
2030  */
2031 static void
2032 asc_DumpLog(str)
2033 	char *str;
2034 {
2035 	register struct asc_log *lp;
2036 	register u_int status;
2037 
2038 	printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
2039 		asc_debug_bn, asc_debug_sz);
2040 	lp = asc_logp;
2041 	do {
2042 		status = lp->status;
2043 		printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n",
2044 			status >> 24,
2045 			lp->target,
2046 			(status >> 16) & 0xFF,
2047 			(status >> 8) & 0xFF,
2048 			status & 0XFF,
2049 			lp->state,
2050 			asc_scripts[lp->state].condition,
2051 			lp->msg, lp->resid);
2052 		if (++lp >= &asc_log[NLOG])
2053 			lp = asc_log;
2054 	} while (lp != asc_logp);
2055 }
2056 #endif	/* DEBUG */
2057