Home | History | Annotate | Line # | Download | only in jazz
asc.c revision 1.6
      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 (at) 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