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