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