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