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