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