xref: /csrg-svn/sys/pmax/dev/asc.c (revision 57233)
152889Sbostic /*-
252889Sbostic  * Copyright (c) 1992 The Regents of the University of California.
352889Sbostic  * All rights reserved.
452889Sbostic  *
552889Sbostic  * This code is derived from software contributed to Berkeley by
656819Sralph  * Ralph Campbell and Rick Macklem.
752889Sbostic  *
852889Sbostic  * %sccs.include.redist.c%
952889Sbostic  *
10*57233Sralph  *	@(#)asc.c	7.9 (Berkeley) 12/20/92
1152889Sbostic  */
1252889Sbostic 
1352889Sbostic /*
1452889Sbostic  * Mach Operating System
1552889Sbostic  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
1652889Sbostic  * All Rights Reserved.
1752889Sbostic  *
1852889Sbostic  * Permission to use, copy, modify and distribute this software and its
1952889Sbostic  * documentation is hereby granted, provided that both the copyright
2052889Sbostic  * notice and this permission notice appear in all copies of the
2152889Sbostic  * software, derivative works or modified versions, and any portions
2252889Sbostic  * thereof, and that both notices appear in supporting documentation.
2352889Sbostic  *
2452889Sbostic  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
2552889Sbostic  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
2652889Sbostic  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
2752889Sbostic  *
2852889Sbostic  * Carnegie Mellon requests users of this software to return to
2952889Sbostic  *
3052889Sbostic  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
3152889Sbostic  *  School of Computer Science
3252889Sbostic  *  Carnegie Mellon University
3352889Sbostic  *  Pittsburgh PA 15213-3890
3452889Sbostic  *
3552889Sbostic  * any improvements or extensions that they make and grant Carnegie the
3652889Sbostic  * rights to redistribute these changes.
3752889Sbostic  */
3852889Sbostic 
3952889Sbostic /*
4052889Sbostic  * HISTORY
4152889Sbostic  * $Log:	scsi_53C94_hdw.c,v $
4252889Sbostic  * Revision 2.5  91/02/05  17:45:07  mrt
4352889Sbostic  * 	Added author notices
4452889Sbostic  * 	[91/02/04  11:18:43  mrt]
4552889Sbostic  *
4652889Sbostic  * 	Changed to use new Mach copyright
4752889Sbostic  * 	[91/02/02  12:17:20  mrt]
4852889Sbostic  *
4952889Sbostic  * Revision 2.4  91/01/08  15:48:24  rpd
5052889Sbostic  * 	Added continuation argument to thread_block.
5152889Sbostic  * 	[90/12/27            rpd]
5252889Sbostic  *
5352889Sbostic  * Revision 2.3  90/12/05  23:34:48  af
5452889Sbostic  * 	Recovered from pmax merge.. and from the destruction of a disk.
5552889Sbostic  * 	[90/12/03  23:40:40  af]
5652889Sbostic  *
5752889Sbostic  * Revision 2.1.1.1  90/11/01  03:39:09  af
5852889Sbostic  * 	Created, from the DEC specs:
5952889Sbostic  * 	"PMAZ-AA TURBOchannel SCSI Module Functional Specification"
6052889Sbostic  * 	Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990.
6152889Sbostic  * 	And from the NCR data sheets
6252889Sbostic  * 	"NCR 53C94, 53C95, 53C96 Advances SCSI Controller"
6352889Sbostic  * 	[90/09/03            af]
6452889Sbostic  */
6552889Sbostic 
6652889Sbostic /*
6752889Sbostic  *	File: scsi_53C94_hdw.h
6852889Sbostic  * 	Author: Alessandro Forin, Carnegie Mellon University
6952889Sbostic  *	Date:	9/90
7052889Sbostic  *
7152889Sbostic  *	Bottom layer of the SCSI driver: chip-dependent functions
7252889Sbostic  *
7352889Sbostic  *	This file contains the code that is specific to the NCR 53C94
7452889Sbostic  *	SCSI chip (Host Bus Adapter in SCSI parlance): probing, start
7552889Sbostic  *	operation, and interrupt routine.
7652889Sbostic  */
7752889Sbostic 
7852889Sbostic /*
7952889Sbostic  * This layer works based on small simple 'scripts' that are installed
8052889Sbostic  * at the start of the command and drive the chip to completion.
8152889Sbostic  * The idea comes from the specs of the NCR 53C700 'script' processor.
8252889Sbostic  *
8352889Sbostic  * There are various reasons for this, mainly
8452889Sbostic  * - Performance: identify the common (successful) path, and follow it;
8552889Sbostic  *   at interrupt time no code is needed to find the current status
8652889Sbostic  * - Code size: it should be easy to compact common operations
8752889Sbostic  * - Adaptability: the code skeleton should adapt to different chips without
8852889Sbostic  *   terrible complications.
8952889Sbostic  * - Error handling: and it is easy to modify the actions performed
9052889Sbostic  *   by the scripts to cope with strange but well identified sequences
9152889Sbostic  *
9252889Sbostic  */
9352889Sbostic 
9456819Sralph #include <asc.h>
9552889Sbostic #if NASC > 0
9652889Sbostic 
9756522Sbostic #include <sys/param.h>
9856522Sbostic #include <sys/systm.h>
9956819Sralph #include <sys/dkstat.h>
10056819Sralph #include <sys/buf.h>
10156819Sralph #include <sys/conf.h>
10256522Sbostic #include <sys/errno.h>
10352889Sbostic 
10456819Sralph #include <machine/machConst.h>
10556819Sralph 
10656525Sbostic #include <pmax/dev/device.h>
10756525Sbostic #include <pmax/dev/scsi.h>
10856525Sbostic #include <pmax/dev/ascreg.h>
10952889Sbostic 
11056819Sralph #include <pmax/pmax/asic.h>
11156819Sralph #include <pmax/pmax/kmin.h>
11256819Sralph #include <pmax/pmax/pmaxtype.h>
11356819Sralph 
11456819Sralph #define	readback(a)	{ register int foo; foo = (a); }
11556819Sralph extern int pmax_boardtype;
11656819Sralph 
11756819Sralph /*
11856819Sralph  * In 4ns ticks.
11956819Sralph  */
12052889Sbostic int	asc_to_scsi_period[] = {
12156819Sralph 	32,
12256819Sralph 	33,
12356819Sralph 	34,
12456819Sralph 	35,
12556819Sralph 	5,
12656819Sralph 	5,
12756819Sralph 	6,
12856819Sralph 	7,
12956819Sralph 	8,
13056819Sralph 	9,
13156819Sralph 	10,
13256819Sralph 	11,
13356819Sralph 	12,
13456819Sralph 	13,
13556819Sralph 	14,
13656819Sralph 	15,
13756819Sralph 	16,
13856819Sralph 	17,
13956819Sralph 	18,
14056819Sralph 	19,
14156819Sralph 	20,
14256819Sralph 	21,
14356819Sralph 	22,
14456819Sralph 	23,
14556819Sralph 	24,
14656819Sralph 	25,
14756819Sralph 	26,
14856819Sralph 	27,
14956819Sralph 	28,
15056819Sralph 	29,
15156819Sralph 	30,
15256819Sralph 	31,
15352889Sbostic };
15452889Sbostic 
15552889Sbostic /*
15652889Sbostic  * Internal forward declarations.
15752889Sbostic  */
15852889Sbostic static void asc_reset();
15952889Sbostic static void asc_startcmd();
16052889Sbostic 
16152889Sbostic #ifdef DEBUG
16252889Sbostic int	asc_debug = 1;
16352889Sbostic int	asc_debug_cmd;
16452889Sbostic int	asc_debug_bn;
16552889Sbostic int	asc_debug_sz;
16652889Sbostic #define NLOG 16
16752889Sbostic struct asc_log {
16852889Sbostic 	u_int	status;
16952889Sbostic 	u_char	state;
17052889Sbostic 	u_char	msg;
17152889Sbostic 	int	target;
17252889Sbostic } asc_log[NLOG], *asc_logp = asc_log;
17352889Sbostic #define PACK(unit, status, ss, ir) \
17452889Sbostic 	((unit << 24) | (status << 16) | (ss << 8) | ir)
17552889Sbostic #endif
17652889Sbostic 
17752889Sbostic /*
17852889Sbostic  * Scripts are entries in a state machine table.
17952889Sbostic  * A script has four parts: a pre-condition, an action, a command to the chip,
18052889Sbostic  * and an index into asc_scripts for the next state. The first triggers error
18152889Sbostic  * handling if not satisfied and in our case it is formed by the
18252889Sbostic  * values of the interrupt register and status register, this
18352889Sbostic  * basically captures the phase of the bus and the TC and BS
18452889Sbostic  * bits.  The action part is just a function pointer, and the
18552889Sbostic  * command is what the 53C94 should be told to do at the end
18652889Sbostic  * of the action processing.  This command is only issued and the
18752889Sbostic  * script proceeds if the action routine returns TRUE.
18852889Sbostic  * See asc_intr() for how and where this is all done.
18952889Sbostic  */
19052889Sbostic typedef struct script {
19152889Sbostic 	int		condition;	/* expected state at interrupt time */
19252889Sbostic 	int		(*action)();	/* extra operations */
19352889Sbostic 	int		command;	/* command to the chip */
19452889Sbostic 	struct script	*next;		/* index into asc_scripts for next state */
19552889Sbostic } script_t;
19652889Sbostic 
19752889Sbostic /* Matching on the condition value */
19852889Sbostic #define	SCRIPT_MATCH(ir, csr)		((ir) | (ASC_PHASE(csr) << 8))
19952889Sbostic 
20052889Sbostic /* forward decls of script actions */
20156819Sralph static int script_nop();		/* when nothing needed */
20256819Sralph static int asc_end();			/* all come to an end */
20356819Sralph static int asc_get_status();		/* get status from target */
20456819Sralph static int asc_dma_in();		/* start reading data from target */
20556819Sralph static int asc_last_dma_in();		/* cleanup after all data is read */
20656819Sralph static int asc_resume_in();		/* resume data in after a message */
20756819Sralph static int asc_resume_dma_in();		/* resume DMA after a disconnect */
20856819Sralph static int asc_dma_out();		/* send data to target via dma */
20956819Sralph static int asc_last_dma_out();		/* cleanup after all data is written */
21056819Sralph static int asc_resume_out();		/* resume data out after a message */
21156819Sralph static int asc_resume_dma_out();	/* resume DMA after a disconnect */
21256819Sralph static int asc_sendsync();		/* negotiate sync xfer */
21356819Sralph static int asc_replysync();		/* negotiate sync xfer */
21456819Sralph static int asc_msg_in();		/* process a message byte */
21556819Sralph static int asc_disconnect();		/* process an expected disconnect */
21652889Sbostic 
21752889Sbostic /* Define the index into asc_scripts for various state transitions */
21852889Sbostic #define	SCRIPT_DATA_IN		0
21952942Sralph #define	SCRIPT_CONTINUE_IN	2
22052942Sralph #define	SCRIPT_DATA_OUT		3
22152942Sralph #define	SCRIPT_CONTINUE_OUT	5
22252942Sralph #define	SCRIPT_SIMPLE		6
22352942Sralph #define	SCRIPT_GET_STATUS	7
22452942Sralph #define	SCRIPT_MSG_IN		9
22552942Sralph #define	SCRIPT_REPLY_SYNC	11
22652889Sbostic #define	SCRIPT_TRY_SYNC		12
22752942Sralph #define	SCRIPT_DISCONNECT	15
22852942Sralph #define	SCRIPT_RESEL		16
22952942Sralph #define	SCRIPT_RESUME_IN	17
23052942Sralph #define	SCRIPT_RESUME_DMA_IN	18
23152942Sralph #define	SCRIPT_RESUME_OUT	19
23252942Sralph #define	SCRIPT_RESUME_DMA_OUT	20
23352942Sralph #define	SCRIPT_RESUME_NO_DATA	21
23452889Sbostic 
23552889Sbostic /*
23652889Sbostic  * Scripts
23752889Sbostic  */
23852889Sbostic script_t asc_scripts[] = {
23952942Sralph 	/* start data in */
24052889Sbostic 	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAI),	/*  0 */
24152889Sbostic 		asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
24252942Sralph 		&asc_scripts[SCRIPT_DATA_IN + 1]},
24352889Sbostic 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),			/*  1 */
24452889Sbostic 		asc_last_dma_in, ASC_CMD_I_COMPLETE,
24552942Sralph 		&asc_scripts[SCRIPT_GET_STATUS]},
24652889Sbostic 
24752942Sralph 	/* continue data in after a chuck is finished */
24852942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),			/*  2 */
24952942Sralph 		asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
25052942Sralph 		&asc_scripts[SCRIPT_DATA_IN + 1]},
25152942Sralph 
25252942Sralph 	/* start data out */
25352942Sralph 	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAO),	/*  3 */
25452889Sbostic 		asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
25552942Sralph 		&asc_scripts[SCRIPT_DATA_OUT + 1]},
25652942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),			/*  4 */
25752889Sbostic 		asc_last_dma_out, ASC_CMD_I_COMPLETE,
25852942Sralph 		&asc_scripts[SCRIPT_GET_STATUS]},
25952889Sbostic 
26052942Sralph 	/* continue data out after a chuck is finished */
26152942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),			/*  5 */
26252942Sralph 		asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
26352942Sralph 		&asc_scripts[SCRIPT_DATA_OUT + 1]},
26452942Sralph 
26552889Sbostic 	/* simple command with no data transfer */
26652942Sralph 	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_STATUS),	/*  6 */
26752889Sbostic 		script_nop, ASC_CMD_I_COMPLETE,
26852942Sralph 		&asc_scripts[SCRIPT_GET_STATUS]},
26952889Sbostic 
27052889Sbostic 	/* get status and finish command */
27152942Sralph 	{SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN),			/*  7 */
27252889Sbostic 		asc_get_status, ASC_CMD_MSG_ACPT,
27352942Sralph 		&asc_scripts[SCRIPT_GET_STATUS + 1]},
27452942Sralph 	{SCRIPT_MATCH(ASC_INT_DISC, 0),					/*  8 */
27552889Sbostic 		asc_end, ASC_CMD_NOP,
27652942Sralph 		&asc_scripts[SCRIPT_GET_STATUS + 1]},
27752889Sbostic 
27852889Sbostic 	/* message in */
27952942Sralph 	{SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN),			/*  9 */
28052942Sralph 		asc_msg_in, ASC_CMD_MSG_ACPT,
28152942Sralph 		&asc_scripts[SCRIPT_MSG_IN + 1]},
28252942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN),			/* 10 */
28352889Sbostic 		script_nop, ASC_CMD_XFER_INFO,
28452942Sralph 		&asc_scripts[SCRIPT_MSG_IN]},
28552889Sbostic 
28652889Sbostic 	/* send synchonous negotiation reply */
28752942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_OUT),			/* 11 */
28852889Sbostic 		asc_replysync, ASC_CMD_XFER_INFO,
28952942Sralph 		&asc_scripts[SCRIPT_REPLY_SYNC]},
29052889Sbostic 
29152889Sbostic 	/* try to negotiate synchonous transfer parameters */
29252889Sbostic 	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_MSG_OUT),	/* 12 */
29352889Sbostic 		asc_sendsync, ASC_CMD_XFER_INFO,
29453080Sralph 		&asc_scripts[SCRIPT_TRY_SYNC + 1]},
29553080Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN),			/* 13 */
29652889Sbostic 		script_nop, ASC_CMD_XFER_INFO,
29753080Sralph 		&asc_scripts[SCRIPT_MSG_IN]},
29853080Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_COMMAND),			/* 14 */
29953080Sralph 		script_nop, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
30053080Sralph 		&asc_scripts[SCRIPT_RESUME_NO_DATA]},
30152889Sbostic 
30252942Sralph 	/* handle a disconnect */
30352942Sralph 	{SCRIPT_MATCH(ASC_INT_DISC, ASC_PHASE_DATAO),			/* 15 */
30452942Sralph 		asc_disconnect, ASC_CMD_ENABLE_SEL,
30552942Sralph 		&asc_scripts[SCRIPT_RESEL]},
30652942Sralph 
30752889Sbostic 	/* reselect sequence: this is just a placeholder so match fails */
30852942Sralph 	{SCRIPT_MATCH(0, ASC_PHASE_MSG_IN),				/* 16 */
30952889Sbostic 		script_nop, ASC_CMD_MSG_ACPT,
31052942Sralph 		&asc_scripts[SCRIPT_RESEL]},
31152889Sbostic 
31252942Sralph 	/* resume data in after a message */
31352942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),			/* 17 */
31452942Sralph 		asc_resume_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
31552942Sralph 		&asc_scripts[SCRIPT_DATA_IN + 1]},
31652942Sralph 
31752942Sralph 	/* resume partial DMA data in after a message */
31852942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),			/* 18 */
31952889Sbostic 		asc_resume_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
32052942Sralph 		&asc_scripts[SCRIPT_DATA_IN + 1]},
32152889Sbostic 
32252942Sralph 	/* resume data out after a message */
32352942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),			/* 19 */
32452942Sralph 		asc_resume_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
32552942Sralph 		&asc_scripts[SCRIPT_DATA_OUT + 1]},
32652942Sralph 
32752942Sralph 	/* resume partial DMA data out after a message */
32852942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),			/* 20 */
32952889Sbostic 		asc_resume_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
33052942Sralph 		&asc_scripts[SCRIPT_DATA_OUT + 1]},
33152942Sralph 
33252942Sralph 	/* resume after a message when there is no more data */
33352942Sralph 	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),			/* 21 */
33452942Sralph 		script_nop, ASC_CMD_I_COMPLETE,
33552942Sralph 		&asc_scripts[SCRIPT_GET_STATUS]},
33652889Sbostic };
33752889Sbostic 
33852889Sbostic /*
33952889Sbostic  * State kept for each active SCSI device.
34052889Sbostic  */
34152889Sbostic typedef struct scsi_state {
34252889Sbostic 	script_t *script;	/* saved script while processing error */
34352889Sbostic 	int	statusByte;	/* status byte returned during STATUS_PHASE */
34452889Sbostic 	int	error;		/* errno to pass back to device driver */
34552889Sbostic 	u_char	*dmaBufAddr;	/* DMA buffer address */
34652889Sbostic 	u_int	dmaBufSize;	/* DMA buffer size */
34752889Sbostic 	int	dmalen;		/* amount to transfer in this chunk */
34852889Sbostic 	int	dmaresid;	/* amount not transfered if chunk suspended */
34952889Sbostic 	int	buflen;		/* total remaining amount of data to transfer */
35052889Sbostic 	char	*buf;		/* current pointer within scsicmd->buf */
35152889Sbostic 	int	flags;		/* see below */
35252889Sbostic 	int	msglen;		/* number of message bytes to read */
35352889Sbostic 	int	msgcnt;		/* number of message bytes received */
35452889Sbostic 	u_char	sync_period;	/* DMA synchronous period */
35552889Sbostic 	u_char	sync_offset;	/* DMA synchronous xfer offset or 0 if async */
35652889Sbostic 	u_char	msg_out;	/* next MSG_OUT byte to send */
35752889Sbostic 	u_char	msg_in[16];	/* buffer for multibyte messages */
35852889Sbostic } State;
35952889Sbostic 
36052889Sbostic /* state flags */
36152889Sbostic #define DISCONN		0x01	/* true if currently disconnected from bus */
36253080Sralph #define DMA_IN_PROGRESS	0x02	/* true if data DMA started */
36352889Sbostic #define DMA_IN		0x04	/* true if reading from SCSI device */
36452889Sbostic #define DMA_OUT		0x10	/* true if writing to SCSI device */
36552889Sbostic #define DID_SYNC	0x20	/* true if synchronous offset was negotiated */
36652889Sbostic #define TRY_SYNC	0x40	/* true if try neg. synchronous offset */
36752889Sbostic 
36852889Sbostic /*
36952889Sbostic  * State kept for each active SCSI host interface (53C94).
37052889Sbostic  */
37152889Sbostic struct asc_softc {
37252889Sbostic 	asc_regmap_t	*regs;		/* chip address */
37352889Sbostic 	volatile int	*dmar;		/* DMA address register address */
37456819Sralph 	u_char		*buff;		/* RAM buffer address (uncached) */
37552889Sbostic 	int		myid;		/* SCSI ID of this interface */
37652889Sbostic 	int		myidmask;	/* ~(1 << myid) */
37752889Sbostic 	int		state;		/* current SCSI connection state */
37852889Sbostic 	int		target;		/* target SCSI ID if busy */
37952889Sbostic 	script_t	*script;	/* next expected interrupt & action */
38052889Sbostic 	ScsiCmd		*cmd[ASC_NCMD];	/* active command indexed by SCSI ID */
38152889Sbostic 	State		st[ASC_NCMD];	/* state info for each active command */
38256819Sralph 	void		(*dma_start)();	/* Start dma routine */
38356819Sralph 	void		(*dma_end)();	/* End dma routine */
38456819Sralph 	u_char		*dma_next;
38556819Sralph 	int		dma_xfer;	/* Dma len still to go */
38656819Sralph 	int		min_period;	/* Min transfer period clk/byte */
38756819Sralph 	int		max_period;	/* Max transfer period clk/byte */
38856819Sralph 	int		ccf;		/* CCF, whatever that really is? */
38956819Sralph 	int		timeout_250;	/* 250ms timeout */
39056819Sralph 	int		tb_ticks;	/* 4ns. ticks/tb channel ticks */
39152889Sbostic } asc_softc[NASC];
39252889Sbostic 
39352889Sbostic #define	ASC_STATE_IDLE		0	/* idle state */
39452889Sbostic #define	ASC_STATE_BUSY		1	/* selecting or currently connected */
39552889Sbostic #define ASC_STATE_TARGET	2	/* currently selected as target */
39652889Sbostic #define ASC_STATE_RESEL		3	/* currently waiting for reselect */
39752889Sbostic 
39852889Sbostic typedef struct asc_softc *asc_softc_t;
39952889Sbostic 
40052889Sbostic /*
40156819Sralph  * Dma operations.
40256819Sralph  */
40356819Sralph #define	ASCDMA_READ	1
40456819Sralph #define	ASCDMA_WRITE	2
40556819Sralph static void tb_dma_start(), tb_dma_end(), asic_dma_start(), asic_dma_end();
406*57233Sralph extern u_long asc_iomem;
407*57233Sralph extern u_long asic_base;
40856819Sralph 
40956819Sralph /*
41052889Sbostic  * Definition of the controller for the auto-configuration program.
41152889Sbostic  */
41252889Sbostic int	asc_probe();
41352889Sbostic void	asc_start();
41452889Sbostic void	asc_intr();
41552889Sbostic struct	driver ascdriver = {
41652889Sbostic 	"asc", asc_probe, asc_start, 0, asc_intr,
41752889Sbostic };
41852889Sbostic 
41952889Sbostic /*
42052889Sbostic  * Test to see if device is present.
42152889Sbostic  * Return true if found and initialized ok.
42252889Sbostic  */
42352889Sbostic asc_probe(cp)
42452889Sbostic 	register struct pmax_ctlr *cp;
42552889Sbostic {
42652889Sbostic 	register asc_softc_t asc;
42752889Sbostic 	register asc_regmap_t *regs;
42852889Sbostic 	int unit, id, s, i;
429*57233Sralph 	int bufsiz;
43052889Sbostic 
43152889Sbostic 	if ((unit = cp->pmax_unit) >= NASC)
43252889Sbostic 		return (0);
43352889Sbostic 	if (badaddr(cp->pmax_addr + ASC_OFFSET_53C94, 1))
43452889Sbostic 		return (0);
43552889Sbostic 	asc = &asc_softc[unit];
43652889Sbostic 
43752889Sbostic 	/*
43852889Sbostic 	 * Initialize hw descriptor, cache some pointers
43952889Sbostic 	 */
44052889Sbostic 	asc->regs = (asc_regmap_t *)(cp->pmax_addr + ASC_OFFSET_53C94);
44152889Sbostic 
44256819Sralph 	/*
44356819Sralph 	 * Set up machine dependencies.
44456819Sralph 	 * 1) how to do dma
44556819Sralph 	 * 2) timing based on turbochannel frequency
44656819Sralph 	 */
44756819Sralph 	switch (pmax_boardtype) {
44856819Sralph 	case DS_3MIN:
44956819Sralph 	case DS_MAXINE:
450*57233Sralph 	case DS_3MAXPLUS:
45156819Sralph 	    if (unit == 0) {
452*57233Sralph 		asc->buff = (u_char *)MACH_PHYS_TO_UNCACHED(asc_iomem);
453*57233Sralph 		bufsiz = 8192;
454*57233Sralph 		*((volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base)) = -1;
455*57233Sralph 		*((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1;
456*57233Sralph 		*((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0;
45756819Sralph 		asc->dma_start = asic_dma_start;
45856819Sralph 		asc->dma_end = asic_dma_end;
45956819Sralph 		break;
46056819Sralph 	    }
46156819Sralph 	    /*
46256819Sralph 	     * Fall through for turbochannel option.
46356819Sralph 	     */
46456819Sralph 	case DS_3MAX:
46556819Sralph 	default:
46656819Sralph 	    asc->dmar = (volatile int *)(cp->pmax_addr + ASC_OFFSET_DMAR);
46756819Sralph 	    asc->buff = (u_char *)(cp->pmax_addr + ASC_OFFSET_RAM);
468*57233Sralph 	    bufsiz = PER_TGT_DMA_SIZE;
46956819Sralph 	    asc->dma_start = tb_dma_start;
47056819Sralph 	    asc->dma_end = tb_dma_end;
47156819Sralph 	};
47256819Sralph 	/*
47356819Sralph 	 * Now for timing. The 3max has a 25Mhz tb whereas the 3min and
47456819Sralph 	 * maxine are 12.5Mhz.
47556819Sralph 	 */
47656819Sralph 	switch (pmax_boardtype) {
47756819Sralph 	case DS_3MAX:
478*57233Sralph 	case DS_3MAXPLUS:
47956819Sralph 		asc->min_period = ASC_MIN_PERIOD25;
48056819Sralph 		asc->max_period = ASC_MAX_PERIOD25;
48156819Sralph 		asc->ccf = ASC_CCF(25);
48256819Sralph 		asc->timeout_250 = ASC_TIMEOUT_250(25, asc->ccf);
48356819Sralph 		asc->tb_ticks = 10;
48456819Sralph 		break;
48556819Sralph 	case DS_3MIN:
48656819Sralph 	case DS_MAXINE:
48756819Sralph 	default:
48856819Sralph 		asc->min_period = ASC_MIN_PERIOD12;
48956819Sralph 		asc->max_period = ASC_MAX_PERIOD12;
49056819Sralph 		asc->ccf = ASC_CCF(13);
49156819Sralph 		asc->timeout_250 = ASC_TIMEOUT_250(13, asc->ccf);
49256819Sralph 		asc->tb_ticks = 20;
49356819Sralph 		break;
49456819Sralph 	};
49556819Sralph 
49652889Sbostic 	asc->state = ASC_STATE_IDLE;
49752889Sbostic 	asc->target = -1;
49852889Sbostic 
49952889Sbostic 	regs = asc->regs;
50052889Sbostic 
50152889Sbostic 	/*
50252889Sbostic 	 * Reset chip, fully.  Note that interrupts are already enabled.
50352889Sbostic 	 */
50452889Sbostic 	s = splbio();
50552889Sbostic 
50652889Sbostic 	/* preserve our ID for now */
50752889Sbostic 	asc->myid = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
50852889Sbostic 	asc->myidmask = ~(1 << asc->myid);
50952889Sbostic 
51052889Sbostic 	asc_reset(asc, regs);
51152889Sbostic 
51252889Sbostic 	/*
51352889Sbostic 	 * Our SCSI id on the bus.
51452889Sbostic 	 * The user can set this via the prom on 3maxen/pmaxen.
51552889Sbostic 	 * If this changes it is easy to fix: make a default that
51652889Sbostic 	 * can be changed as boot arg.
51752889Sbostic 	 */
51852889Sbostic #ifdef	unneeded
51952889Sbostic 	regs->asc_cnfg1 = (regs->asc_cnfg1 & ~ASC_CNFG1_MY_BUS_ID) |
52052889Sbostic 			      (scsi_initiator_id[unit] & 0x7);
52152889Sbostic #endif
52252889Sbostic 	id = regs->asc_cnfg1 & ASC_CNFG1_MY_BUS_ID;
52352889Sbostic 	splx(s);
52452889Sbostic 
52552889Sbostic 	/*
52652889Sbostic 	 * Statically partition the DMA buffer between targets.
52752889Sbostic 	 * This way we will eventually be able to attach/detach
52852889Sbostic 	 * drives on-fly.  And 18k/target is plenty for normal use.
52952889Sbostic 	 */
53052889Sbostic 
53152889Sbostic 	/*
53252889Sbostic 	 * Give each target its own DMA buffer region.
53352889Sbostic 	 * We may want to try ping ponging buffers later.
53452889Sbostic 	 */
53552889Sbostic 	for (i = 0; i < ASC_NCMD; i++) {
536*57233Sralph 		asc->st[i].dmaBufAddr = asc->buff + bufsiz * i;
537*57233Sralph 		asc->st[i].dmaBufSize = bufsiz;
53852889Sbostic 	}
53952889Sbostic 	printf("asc%d at nexus0 csr 0x%x priority %d SCSI id %d\n",
54052889Sbostic 		unit, cp->pmax_addr, cp->pmax_pri, id);
54152889Sbostic 	return (1);
54252889Sbostic }
54352889Sbostic 
54452889Sbostic /*
54552889Sbostic  * Start activity on a SCSI device.
54652889Sbostic  * We maintain information on each device separately since devices can
54752889Sbostic  * connect/disconnect during an operation.
54852889Sbostic  */
54952889Sbostic void
55052889Sbostic asc_start(scsicmd)
55152889Sbostic 	register ScsiCmd *scsicmd;	/* command to start */
55252889Sbostic {
55352889Sbostic 	register struct scsi_device *sdp = scsicmd->sd;
55452889Sbostic 	register asc_softc_t asc = &asc_softc[sdp->sd_ctlr];
55552889Sbostic 	int s;
55652889Sbostic 
55752889Sbostic 	s = splbio();
55852889Sbostic 	/*
55952889Sbostic 	 * Check if another command is already in progress.
56052889Sbostic 	 * We may have to change this if we allow SCSI devices with
56152889Sbostic 	 * separate LUNs.
56252889Sbostic 	 */
56352889Sbostic 	if (asc->cmd[sdp->sd_drive]) {
56452889Sbostic 		printf("asc%d: device %s busy at start\n", sdp->sd_ctlr,
56552889Sbostic 			sdp->sd_driver->d_name);
56652889Sbostic 		(*sdp->sd_driver->d_done)(scsicmd->unit, EBUSY,
56752889Sbostic 			scsicmd->buflen, 0);
56852889Sbostic 		splx(s);
56952889Sbostic 	}
57052889Sbostic 	asc->cmd[sdp->sd_drive] = scsicmd;
57152889Sbostic 	asc_startcmd(asc, sdp->sd_drive);
57252889Sbostic 	splx(s);
57352889Sbostic }
57452889Sbostic 
57552889Sbostic static void
57652889Sbostic asc_reset(asc, regs)
57752889Sbostic 	asc_softc_t asc;
57852889Sbostic 	asc_regmap_t *regs;
57952889Sbostic {
58052889Sbostic 
58152889Sbostic 	/*
58252889Sbostic 	 * Reset chip and wait till done
58352889Sbostic 	 */
58452889Sbostic 	regs->asc_cmd = ASC_CMD_RESET;
58552889Sbostic 	MachEmptyWriteBuffer(); DELAY(25);
58652889Sbostic 
58752889Sbostic 	/* spec says this is needed after reset */
58852889Sbostic 	regs->asc_cmd = ASC_CMD_NOP;
58952889Sbostic 	MachEmptyWriteBuffer(); DELAY(25);
59052889Sbostic 
59152889Sbostic 	/*
59252889Sbostic 	 * Set up various chip parameters
59352889Sbostic 	 */
59456819Sralph 	regs->asc_ccf = asc->ccf;
59552889Sbostic 	MachEmptyWriteBuffer(); DELAY(25);
59656819Sralph 	regs->asc_sel_timo = asc->timeout_250;
59752889Sbostic 	/* restore our ID */
59852889Sbostic 	regs->asc_cnfg1 = asc->myid | ASC_CNFG1_P_CHECK;
599*57233Sralph 	/* include ASC_CNFG2_SCSI2 if you want to allow SCSI II commands */
600*57233Sralph 	regs->asc_cnfg2 = /* ASC_CNFG2_RFB | ASC_CNFG2_SCSI2 | */ ASC_CNFG2_EPL;
60152889Sbostic 	regs->asc_cnfg3 = 0;
60252889Sbostic 	/* zero anything else */
60352889Sbostic 	ASC_TC_PUT(regs, 0);
60456819Sralph 	regs->asc_syn_p = asc->min_period;
60552889Sbostic 	regs->asc_syn_o = 0;	/* async for now */
60652889Sbostic 	MachEmptyWriteBuffer();
60752889Sbostic }
60852889Sbostic 
60952889Sbostic /*
61052889Sbostic  * Start a SCSI command on a target.
61152889Sbostic  */
61252889Sbostic static void
61352889Sbostic asc_startcmd(asc, target)
61452889Sbostic 	asc_softc_t asc;
61552889Sbostic 	int target;
61652889Sbostic {
61752889Sbostic 	register asc_regmap_t *regs;
61852889Sbostic 	register ScsiCmd *scsicmd;
61952889Sbostic 	register State *state;
62052889Sbostic 	int len;
62152889Sbostic 
62252889Sbostic 	/*
62352889Sbostic 	 * See if another target is currently selected on this SCSI bus.
62452889Sbostic 	 */
62552889Sbostic 	if (asc->target >= 0)
62652889Sbostic 		return;
62752889Sbostic 
62852889Sbostic 	regs = asc->regs;
62952889Sbostic 
63052889Sbostic 	/*
63152889Sbostic 	 * Check to see if a reselection is in progress and if so,
63252889Sbostic 	 * try to cancel it or respond to the reselection if it won.
63352889Sbostic 	 */
63452889Sbostic 	if (asc->state == ASC_STATE_RESEL) {
63552889Sbostic 		regs->asc_cmd = ASC_CMD_DISABLE_SEL;
63656819Sralph 		readback(regs->asc_cmd);
63752889Sbostic 		while (!(regs->asc_status & ASC_CSR_INT))
63852889Sbostic 			DELAY(1);
63952889Sbostic 		asc_intr(asc - asc_softc);
64052889Sbostic 		/* we will be busy if a reselecting device won */
64152889Sbostic 		if (asc->state == ASC_STATE_BUSY)
64252889Sbostic 			return;
64352889Sbostic 	}
64452889Sbostic 
64552889Sbostic 	asc->state = ASC_STATE_BUSY;
64652889Sbostic 	asc->target = target;
64752889Sbostic 
64852889Sbostic 	/* cache some pointers */
64952889Sbostic 	scsicmd = asc->cmd[target];
65052889Sbostic 	state = &asc->st[target];
65152889Sbostic 
65252889Sbostic #ifdef DEBUG
65352889Sbostic 	if (asc_debug > 1) {
65452889Sbostic 		printf("asc_startcmd: %s target %d cmd %x len %d\n",
65552889Sbostic 			scsicmd->sd->sd_driver->d_name, target,
65652889Sbostic 			scsicmd->cmd[0], scsicmd->buflen);
65752889Sbostic 	}
65852889Sbostic 	asc_debug_cmd = scsicmd->cmd[0];
65952889Sbostic 	if (scsicmd->cmd[0] == SCSI_READ_EXT) {
66052889Sbostic 		asc_debug_bn = (scsicmd->cmd[2] << 24) |
66152889Sbostic 			(scsicmd->cmd[3] << 16) |
66252889Sbostic 			(scsicmd->cmd[4] << 8) |
66352889Sbostic 			scsicmd->cmd[5];
66452889Sbostic 		asc_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8];
66552889Sbostic 	}
66653080Sralph 	asc_logp->status = PACK(asc - asc_softc, 0, 0, asc_debug_cmd);
66752889Sbostic 	asc_logp->target = asc->target;
66852889Sbostic 	asc_logp->state = 0;
66953080Sralph 	asc_logp->msg = 0xff;
67052889Sbostic 	if (++asc_logp >= &asc_log[NLOG])
67152889Sbostic 		asc_logp = asc_log;
67252889Sbostic #endif
67352889Sbostic 
67452889Sbostic 	/*
67552889Sbostic 	 * Init the chip and target state.
67652889Sbostic 	 */
67752889Sbostic 	regs->asc_cmd = ASC_CMD_FLUSH;
67856819Sralph 	readback(regs->asc_cmd);
67956819Sralph 	DELAY(2);
68053080Sralph 	state->flags = state->flags & DID_SYNC;
68152889Sbostic 	state->error = 0;
68252889Sbostic 	state->script = (script_t *)0;
68352889Sbostic 	state->msg_out = SCSI_NO_OP;
68452889Sbostic 
68552889Sbostic 	/*
68652889Sbostic 	 * Copy command data to the DMA buffer.
68752889Sbostic 	 */
68852889Sbostic 	len = scsicmd->cmdlen;
68952889Sbostic 	state->dmalen = len;
69052889Sbostic 	bcopy(scsicmd->cmd, state->dmaBufAddr, len);
69152889Sbostic 
69252889Sbostic 	/* check for simple SCSI command with no data transfer */
69352889Sbostic 	if ((state->buflen = scsicmd->buflen) == 0) {
69452889Sbostic 		/* check for sync negotiation */
69552889Sbostic 		if ((scsicmd->flags & SCSICMD_USE_SYNC) &&
69652889Sbostic 		    !(state->flags & DID_SYNC)) {
69752889Sbostic 			asc->script = &asc_scripts[SCRIPT_TRY_SYNC];
69852889Sbostic 			state->flags |= TRY_SYNC;
69952889Sbostic 		} else
70052889Sbostic 			asc->script = &asc_scripts[SCRIPT_SIMPLE];
70152889Sbostic 		state->buf = (char *)0;
70252889Sbostic 	} else if (scsicmd->flags & SCSICMD_DATA_TO_DEVICE) {
70352889Sbostic 		asc->script = &asc_scripts[SCRIPT_DATA_OUT];
70453080Sralph 		state->buf = scsicmd->buf;
70552889Sbostic 		state->flags |= DMA_OUT;
70652889Sbostic 	} else {
70752889Sbostic 		asc->script = &asc_scripts[SCRIPT_DATA_IN];
70852889Sbostic 		state->buf = scsicmd->buf;
70952889Sbostic 		state->flags |= DMA_IN;
71052889Sbostic 	}
71152889Sbostic 
71252889Sbostic 	/* preload the FIFO with the message to be sent */
71352942Sralph 	regs->asc_fifo = SCSI_DIS_REC_IDENTIFY;
71456819Sralph 	MachEmptyWriteBuffer();
71552889Sbostic 
71652889Sbostic 	/* start the asc */
71756819Sralph 	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
71852889Sbostic 	ASC_TC_PUT(regs, len);
71956819Sralph 	readback(regs->asc_cmd);
72052889Sbostic 
72152889Sbostic 	regs->asc_dbus_id = target;
72256819Sralph 	readback(regs->asc_dbus_id);
72352889Sbostic 	regs->asc_syn_p = state->sync_period;
72456819Sralph 	readback(regs->asc_syn_p);
72552889Sbostic 	regs->asc_syn_o = state->sync_offset;
72656819Sralph 	readback(regs->asc_syn_o);
72752889Sbostic 
72852889Sbostic 	if (state->flags & TRY_SYNC)
72953080Sralph 		regs->asc_cmd = ASC_CMD_SEL_ATN_STOP;
73052889Sbostic 	else
73152889Sbostic 		regs->asc_cmd = ASC_CMD_SEL_ATN | ASC_CMD_DMA;
73256819Sralph 	readback(regs->asc_cmd);
73352889Sbostic }
73452889Sbostic 
73552889Sbostic /*
73652889Sbostic  * Interrupt routine
73752889Sbostic  *	Take interrupts from the chip
73852889Sbostic  *
73952889Sbostic  * Implementation:
74052889Sbostic  *	Move along the current command's script if
74152889Sbostic  *	all is well, invoke error handler if not.
74252889Sbostic  */
74352889Sbostic void
74452889Sbostic asc_intr(unit)
74552889Sbostic 	int unit;
74652889Sbostic {
74752889Sbostic 	register asc_softc_t asc = &asc_softc[unit];
74852889Sbostic 	register asc_regmap_t *regs = asc->regs;
74952889Sbostic 	register State *state;
75052889Sbostic 	register script_t *scpt;
75152889Sbostic 	register int ss, ir, status;
75252889Sbostic 
75352889Sbostic 	/* collect ephemeral information */
75452889Sbostic 	status = regs->asc_status;
75553080Sralph again:
75652889Sbostic 	ss = regs->asc_ss;
75752889Sbostic 	ir = regs->asc_intr;	/* this resets the previous two */
75852889Sbostic 	scpt = asc->script;
75952889Sbostic 
76052889Sbostic #ifdef DEBUG
76152889Sbostic 	asc_logp->status = PACK(unit, status, ss, ir);
76252889Sbostic 	asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1;
76352889Sbostic 	asc_logp->state = scpt - asc_scripts;
76452889Sbostic 	asc_logp->msg = -1;
76552889Sbostic 	if (++asc_logp >= &asc_log[NLOG])
76652889Sbostic 		asc_logp = asc_log;
76752889Sbostic 	if (asc_debug > 2)
76852889Sbostic 		printf("asc_intr: status %x ss %x ir %x cond %d:%x\n",
76952889Sbostic 			status, ss, ir, scpt - asc_scripts, scpt->condition);
77052889Sbostic #endif
77152889Sbostic 
77252889Sbostic 	/* check the expected state */
77352889Sbostic 	if (SCRIPT_MATCH(ir, status) == scpt->condition) {
77452889Sbostic 		/*
77552889Sbostic 		 * Perform the appropriate operation, then proceed.
77652889Sbostic 		 */
77752889Sbostic 		if ((*scpt->action)(asc, status, ss, ir)) {
77852889Sbostic 			regs->asc_cmd = scpt->command;
77956819Sralph 			readback(regs->asc_cmd);
78052889Sbostic 			asc->script = scpt->next;
78152889Sbostic 		}
78252889Sbostic 		goto done;
78352889Sbostic 	}
78452889Sbostic 
78552889Sbostic 	/* check for message in or out */
78652889Sbostic 	if ((ir & ~ASC_INT_FC) == ASC_INT_BS) {
78752889Sbostic 		register int len, fifo;
78852889Sbostic 
78952889Sbostic 		state = &asc->st[asc->target];
79052889Sbostic 		switch (ASC_PHASE(status)) {
79153080Sralph 		case ASC_PHASE_DATAI:
79253080Sralph 		case ASC_PHASE_DATAO:
79353080Sralph 			ASC_TC_GET(regs, len);
79453080Sralph 			fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
79553080Sralph 			printf("asc_intr: data overrun: buflen %d dmalen %d tc %d fifo %d\n",
79653080Sralph 				state->buflen, state->dmalen, len, fifo);
79753080Sralph 			goto abort;
79853080Sralph 
79952889Sbostic 		case ASC_PHASE_MSG_IN:
80052889Sbostic 			break;
80152889Sbostic 
80252889Sbostic 		case ASC_PHASE_MSG_OUT:
80352889Sbostic 			regs->asc_fifo = state->msg_out;
80452889Sbostic 			state->msg_out = SCSI_NO_OP;
80552889Sbostic 			regs->asc_cmd = ASC_CMD_XFER_INFO;
80656819Sralph 			readback(regs->asc_cmd);
80752889Sbostic 			goto done;
80852889Sbostic 
80952889Sbostic 		case ASC_PHASE_STATUS:
81052889Sbostic 			/* probably an error in the SCSI command */
81152889Sbostic 			asc->script = &asc_scripts[SCRIPT_GET_STATUS];
81252889Sbostic 			regs->asc_cmd = ASC_CMD_I_COMPLETE;
81356819Sralph 			readback(regs->asc_cmd);
81452889Sbostic 			goto done;
81552889Sbostic 
81652889Sbostic 		default:
81752889Sbostic 			goto abort;
81852889Sbostic 		}
81952889Sbostic 
82052889Sbostic 		if (state->script)
82152889Sbostic 			goto abort;
82252889Sbostic 
82352889Sbostic 		/* check for DMA in progress */
82452889Sbostic 		ASC_TC_GET(regs, len);
82552889Sbostic 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
82652889Sbostic 		/* flush any data in the FIFO */
82752889Sbostic 		if (fifo) {
82853080Sralph 			if (state->flags & DMA_OUT)
82953080Sralph 				len += fifo;
83053080Sralph 			else if (state->flags & DMA_IN) {
83153080Sralph 				u_char *cp;
83253080Sralph 
83353080Sralph 				printf("asc_intr: IN: dmalen %d len %d fifo %d\n",
83453080Sralph 					state->dmalen, len, fifo); /* XXX */
83553080Sralph 				len += fifo;
83653080Sralph 				cp = state->dmaBufAddr + (state->dmalen - len);
83753080Sralph 				while (fifo-- > 0)
83853080Sralph 					*cp++ = regs->asc_fifo;
83953080Sralph 			} else
84053080Sralph 				printf("asc_intr: dmalen %d len %d fifo %d\n",
84153080Sralph 					state->dmalen, len, fifo); /* XXX */
84252889Sbostic 			regs->asc_cmd = ASC_CMD_FLUSH;
84356819Sralph 			readback(regs->asc_cmd);
84452889Sbostic 			MachEmptyWriteBuffer();
84556819Sralph 			DELAY(2);
84652889Sbostic 		}
84752889Sbostic 		if (len) {
84852889Sbostic 			/* save number of bytes still to be sent or received */
84952889Sbostic 			state->dmaresid = len;
85052889Sbostic 			/* setup state to resume to */
85152889Sbostic 			if (state->flags & DMA_IN)
85252889Sbostic 				state->script =
85352889Sbostic 					&asc_scripts[SCRIPT_RESUME_DMA_IN];
85452889Sbostic 			else if (state->flags & DMA_OUT)
85552889Sbostic 				state->script =
85652889Sbostic 					&asc_scripts[SCRIPT_RESUME_DMA_OUT];
85752889Sbostic 			else
85852889Sbostic 				state->script = asc->script;
85952889Sbostic 		} else {
86052889Sbostic 			/* setup state to resume to */
86152942Sralph 			if (state->flags & DMA_IN) {
86253080Sralph 				if (state->flags & DMA_IN_PROGRESS) {
86353080Sralph 					state->flags &= ~DMA_IN_PROGRESS;
86456819Sralph 					(*asc->dma_end)(asc, state, ASCDMA_READ);
86552942Sralph 					len = state->dmalen;
86652942Sralph 					bcopy(state->dmaBufAddr, state->buf,
86752942Sralph 						len);
86852942Sralph 					state->buf += len;
86952942Sralph 					state->buflen -= len;
87053080Sralph 				}
87152942Sralph 				if (state->buflen)
87252942Sralph 					state->script =
87352942Sralph 					    &asc_scripts[SCRIPT_RESUME_IN];
87452942Sralph 				else
87552942Sralph 					state->script =
87652942Sralph 					    &asc_scripts[SCRIPT_RESUME_NO_DATA];
87752942Sralph 			} else if (state->flags & DMA_OUT) {
87852942Sralph 				/*
87952942Sralph 				 * If this is the last chunk, the next expected
88052942Sralph 				 * state is to get status.
88152942Sralph 				 */
88253080Sralph 				if (state->flags & DMA_IN_PROGRESS) {
88353080Sralph 					state->flags &= ~DMA_IN_PROGRESS;
88456819Sralph 					(*asc->dma_end)(asc, state, ASCDMA_WRITE);
88553080Sralph 					len = state->dmalen;
88653080Sralph 					state->buf += len;
88753080Sralph 					state->buflen -= len;
88853080Sralph 				}
88952942Sralph 				if (state->buflen)
89052942Sralph 					state->script =
89152942Sralph 					    &asc_scripts[SCRIPT_RESUME_OUT];
89252942Sralph 				else
89352942Sralph 					state->script =
89452942Sralph 					    &asc_scripts[SCRIPT_RESUME_NO_DATA];
89553080Sralph 			} else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
89653080Sralph 				state->script =
89753080Sralph 					    &asc_scripts[SCRIPT_RESUME_NO_DATA];
89853080Sralph 			else
89952889Sbostic 				state->script = asc->script;
90052889Sbostic 		}
90152889Sbostic 
90252889Sbostic 		/* setup to receive a message */
90352889Sbostic 		asc->script = &asc_scripts[SCRIPT_MSG_IN];
90452889Sbostic 		state->msglen = 0;
90552889Sbostic 		regs->asc_cmd = ASC_CMD_XFER_INFO;
90656819Sralph 		readback(regs->asc_cmd);
90752889Sbostic 		goto done;
90852889Sbostic 	}
90952889Sbostic 
91052889Sbostic 	/* check for SCSI bus reset */
91152889Sbostic 	if (ir & ASC_INT_RESET) {
91252889Sbostic 		register int i;
91352889Sbostic 
91452889Sbostic 		printf("asc%d: SCSI bus reset!!\n", asc - asc_softc);
91552889Sbostic 		/* need to flush any pending commands */
91652889Sbostic 		for (i = 0; i < ASC_NCMD; i++) {
91752889Sbostic 			if (!asc->cmd[i])
91852889Sbostic 				continue;
91952889Sbostic 			asc->st[i].error = EIO;
92052889Sbostic 			asc_end(asc, 0, 0, 0);
92152889Sbostic 		}
92252889Sbostic 		/* rearbitrate synchronous offset */
92352889Sbostic 		for (i = 0; i < ASC_NCMD; i++) {
92452889Sbostic 			asc->st[i].sync_offset = 0;
92552889Sbostic 			asc->st[i].flags = 0;
92652889Sbostic 		}
92752889Sbostic 		asc->target = -1;
92852889Sbostic 		return;
92952889Sbostic 	}
93052889Sbostic 
93152889Sbostic 	/* check for command errors */
93252889Sbostic 	if (ir & ASC_INT_ILL)
93352889Sbostic 		goto abort;
93452889Sbostic 
93552889Sbostic 	/* check for disconnect */
93652889Sbostic 	if (ir & ASC_INT_DISC) {
93752889Sbostic 		state = &asc->st[asc->target];
93852889Sbostic 		switch (ASC_SS(ss)) {
93952889Sbostic 		case 0: /* device did not respond */
94052889Sbostic 			state->error = ENXIO;
94152889Sbostic 			asc_end(asc, status, ss, ir);
94252889Sbostic 			return;
94352889Sbostic 
94452889Sbostic 		default:
945*57233Sralph 			/*
946*57233Sralph 			 * On rare occasions my RZ24 does a disconnect during
947*57233Sralph 			 * data in phase and the following seems to keep it
948*57233Sralph 			 * happy.
949*57233Sralph 			 * XXX Should a scsi disk ever do this??
950*57233Sralph 			 */
951*57233Sralph 			asc->script = &asc_scripts[SCRIPT_RESEL];
952*57233Sralph 			asc->state = ASC_STATE_RESEL;
953*57233Sralph 			state->flags |= DISCONN;
954*57233Sralph 			regs->asc_cmd = ASC_CMD_ENABLE_SEL;
955*57233Sralph 			readback(regs->asc_cmd);
956*57233Sralph 			return;
95752889Sbostic 		}
95852889Sbostic 	}
95952889Sbostic 
96052889Sbostic 	/* check for reselect */
96152889Sbostic 	if (ir & ASC_INT_RESEL) {
96252889Sbostic 		unsigned fifo, id, msg;
96352889Sbostic 
96452889Sbostic 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
96552889Sbostic 		if (fifo < 2)
96652889Sbostic 			goto abort;
96752889Sbostic 		/* read unencoded SCSI ID and convert to binary */
96852889Sbostic 		msg = regs->asc_fifo & asc->myidmask;
96952889Sbostic 		for (id = 0; (msg & 1) == 0; id++)
97052889Sbostic 			msg >>= 1;
97152889Sbostic 		/* read identify message */
97252889Sbostic 		msg = regs->asc_fifo;
97352889Sbostic #ifdef DEBUG
97452889Sbostic 		if (asc_logp == asc_log)
97552889Sbostic 			asc_log[NLOG - 1].msg = msg;
97652889Sbostic 		else
97752889Sbostic 			asc_logp[-1].msg = msg;
97852889Sbostic #endif
97952889Sbostic 		if (asc->state != ASC_STATE_RESEL)
98052889Sbostic 			goto abort;
98152889Sbostic 		asc->state = ASC_STATE_BUSY;
98252889Sbostic 		asc->target = id;
98352889Sbostic 		state = &asc->st[id];
98452889Sbostic 		asc->script = state->script;
98552889Sbostic 		state->script = (script_t *)0;
98652889Sbostic 		if (!(state->flags & DISCONN))
98752889Sbostic 			goto abort;
98852889Sbostic 		state->flags &= ~DISCONN;
98953080Sralph 		regs->asc_syn_p = state->sync_period;
99053080Sralph 		regs->asc_syn_o = state->sync_offset;
99152889Sbostic 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
99256819Sralph 		readback(regs->asc_cmd);
99352889Sbostic 		goto done;
99452889Sbostic 	}
99552889Sbostic 
99652889Sbostic 	/* check if we are being selected as a target */
99752889Sbostic 	if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
99852889Sbostic 		goto abort;
99952889Sbostic 
100052889Sbostic 	/* must be just a ASC_INT_FC */
100152889Sbostic done:
100252889Sbostic 	MachEmptyWriteBuffer();
100353080Sralph 	/* watch out for HW race conditions and setup & hold time violations */
100453080Sralph 	ir = regs->asc_status;
100553080Sralph 	while (ir != (status = regs->asc_status))
100653080Sralph 		ir = status;
100753080Sralph 	if (status & ASC_CSR_INT)
100852889Sbostic 		goto again;
100952889Sbostic 	return;
101052889Sbostic 
101152889Sbostic abort:
101252889Sbostic #ifdef DEBUG
101352889Sbostic 	asc_DumpLog("asc_intr");
101452889Sbostic #endif
101552889Sbostic #if 0
101652889Sbostic 	panic("asc_intr");
101752889Sbostic #else
101852889Sbostic 	for (;;);
101952889Sbostic #endif
102052889Sbostic }
102152889Sbostic 
102252889Sbostic /*
102352889Sbostic  * All the many little things that the interrupt
102452889Sbostic  * routine might switch to.
102552889Sbostic  */
102652889Sbostic 
102752889Sbostic /* ARGSUSED */
102852889Sbostic static int
102952889Sbostic script_nop(asc, status, ss, ir)
103052889Sbostic 	register asc_softc_t asc;
103152889Sbostic 	register int status, ss, ir;
103252889Sbostic {
103352889Sbostic 	return (1);
103452889Sbostic }
103552889Sbostic 
103652889Sbostic /* ARGSUSED */
103752889Sbostic static int
103852889Sbostic asc_get_status(asc, status, ss, ir)
103952889Sbostic 	register asc_softc_t asc;
104052889Sbostic 	register int status, ss, ir;
104152889Sbostic {
104252889Sbostic 	register asc_regmap_t *regs = asc->regs;
104352889Sbostic 	register int data;
104452889Sbostic 
104552889Sbostic 	/*
104652889Sbostic 	 * Get the last two bytes in the FIFO.
104752889Sbostic 	 */
104852889Sbostic 	if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
104952889Sbostic 		printf("asc_get_status: fifo cnt %d\n", data); /* XXX */
105052889Sbostic 		if (data < 2) {
105152889Sbostic 			asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
105256819Sralph 			readback(asc->regs->asc_cmd);
105352889Sbostic 			return (0);
105452889Sbostic 		}
105552889Sbostic 		do {
105652889Sbostic 			data = regs->asc_fifo;
105752889Sbostic 		} while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2);
105852889Sbostic 	}
105952889Sbostic 
106052889Sbostic 	/* save the status byte */
106152889Sbostic 	asc->st[asc->target].statusByte = data = regs->asc_fifo;
106252889Sbostic #ifdef DEBUG
106352889Sbostic 	if (asc_logp == asc_log)
106452889Sbostic 		asc_log[NLOG - 1].msg = data;
106552889Sbostic 	else
106652889Sbostic 		asc_logp[-1].msg = data;
106752889Sbostic #endif
106852889Sbostic 
106952889Sbostic 	/* get the (presumed) command_complete message */
107052889Sbostic 	if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE)
107152889Sbostic 		return (1);
107252889Sbostic 
107352889Sbostic #ifdef DEBUG
107452889Sbostic 	printf("asc_get_status: status %x cmd %x\n",
107552889Sbostic 		asc->st[asc->target].statusByte, data);
107652889Sbostic 	asc_DumpLog("asc_get_status");
107752889Sbostic #endif
107852889Sbostic 	return (0);
107952889Sbostic }
108052889Sbostic 
108152889Sbostic /* ARGSUSED */
108252889Sbostic static int
108352889Sbostic asc_end(asc, status, ss, ir)
108452889Sbostic 	register asc_softc_t asc;
108552889Sbostic 	register int status, ss, ir;
108652889Sbostic {
108752889Sbostic 	register ScsiCmd *scsicmd;
108852889Sbostic 	register State *state;
108952889Sbostic 	register int i, target;
109052889Sbostic 
109152889Sbostic 	asc->state = ASC_STATE_IDLE;
109252889Sbostic 	target = asc->target;
109352889Sbostic 	asc->target = -1;
109452889Sbostic 	scsicmd = asc->cmd[target];
109552889Sbostic 	asc->cmd[target] = (ScsiCmd *)0;
109652889Sbostic 	state = &asc->st[target];
109752889Sbostic 
109852889Sbostic #ifdef DEBUG
109952889Sbostic 	if (asc_debug > 1) {
110052889Sbostic 		printf("asc_end: %s target %d cmd %x err %d resid %d\n",
110152889Sbostic 			scsicmd->sd->sd_driver->d_name, target,
110252889Sbostic 			scsicmd->cmd[0], state->error, state->buflen);
110352889Sbostic 	}
110452889Sbostic #endif
110552889Sbostic #ifdef DIAGNOSTIC
110652889Sbostic 	if (target < 0 || !scsicmd)
110752889Sbostic 		panic("asc_end");
110852889Sbostic #endif
110952889Sbostic 
111052889Sbostic 	/* look for disconnected devices */
111152889Sbostic 	for (i = 0; i < ASC_NCMD; i++) {
111252889Sbostic 		if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN))
111352889Sbostic 			continue;
111452889Sbostic 		asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL;
111556819Sralph 		readback(asc->regs->asc_cmd);
111652889Sbostic 		asc->state = ASC_STATE_RESEL;
111752889Sbostic 		asc->script = &asc_scripts[SCRIPT_RESEL];
111852889Sbostic 		break;
111952889Sbostic 	}
112052889Sbostic 
112152889Sbostic 	/* look for another device that is ready */
112252889Sbostic 	for (i = 0; i < ASC_NCMD; i++) {
112352889Sbostic 		/* don't restart a disconnected command */
112452889Sbostic 		if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
112552889Sbostic 			continue;
112652889Sbostic 		asc_startcmd(asc, i);
112752889Sbostic 		break;
112852889Sbostic 	}
112952889Sbostic 
113052889Sbostic 	/* signal device driver that the command is done */
113152889Sbostic 	(*scsicmd->sd->sd_driver->d_done)(scsicmd->unit, state->error,
113252889Sbostic 		state->buflen, state->statusByte);
113352889Sbostic 
113452889Sbostic 	return (0);
113552889Sbostic }
113652889Sbostic 
113752889Sbostic /* ARGSUSED */
113852889Sbostic static int
113952889Sbostic asc_dma_in(asc, status, ss, ir)
114052889Sbostic 	register asc_softc_t asc;
114152889Sbostic 	register int status, ss, ir;
114252889Sbostic {
114352889Sbostic 	register asc_regmap_t *regs = asc->regs;
114452889Sbostic 	register State *state = &asc->st[asc->target];
114553080Sralph 	register int len;
114652889Sbostic 
114752889Sbostic 	/* check for previous chunk in buffer */
114853080Sralph 	if (state->flags & DMA_IN_PROGRESS) {
114952889Sbostic 		/*
115052889Sbostic 		 * Only count bytes that have been copied to memory.
115152889Sbostic 		 * There may be some bytes in the FIFO if synchonous transfers
115252889Sbostic 		 * are in progress.
115352889Sbostic 		 */
115456819Sralph 		(*asc->dma_end)(asc, state, ASCDMA_READ);
115552889Sbostic 		ASC_TC_GET(regs, len);
115652889Sbostic 		len = state->dmalen - len;
115752889Sbostic 		bcopy(state->dmaBufAddr, state->buf, len);
115852889Sbostic 		state->buf += len;
115952889Sbostic 		state->buflen -= len;
116053080Sralph 	}
116152889Sbostic 
116252942Sralph 	/* setup to start reading the next chunk */
116352889Sbostic 	len = state->buflen;
116452889Sbostic 	if (len > state->dmaBufSize)
116552889Sbostic 		len = state->dmaBufSize;
116652889Sbostic 	state->dmalen = len;
116756819Sralph 	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_READ);
116852889Sbostic 	ASC_TC_PUT(regs, len);
116952942Sralph #ifdef DEBUG
117052942Sralph 	if (asc_debug > 2)
117152942Sralph 		printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len);
117252942Sralph #endif
117352942Sralph 
117452942Sralph 	/* check for next chunk */
117553080Sralph 	state->flags |= DMA_IN_PROGRESS;
117652889Sbostic 	if (len != state->buflen) {
117752889Sbostic 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
117856819Sralph 		readback(regs->asc_cmd);
117952942Sralph 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
118052889Sbostic 		return (0);
118152889Sbostic 	}
118252889Sbostic 	return (1);
118352889Sbostic }
118452889Sbostic 
118552889Sbostic /* ARGSUSED */
118652889Sbostic static int
118752889Sbostic asc_last_dma_in(asc, status, ss, ir)
118852889Sbostic 	register asc_softc_t asc;
118952889Sbostic 	register int status, ss, ir;
119052889Sbostic {
119152889Sbostic 	register asc_regmap_t *regs = asc->regs;
119252889Sbostic 	register State *state = &asc->st[asc->target];
119352889Sbostic 	register int len, fifo;
119452889Sbostic 
119552889Sbostic 	/* copy data from buffer to main memory */
119656819Sralph 	(*asc->dma_end)(asc, state, ASCDMA_READ);
119752889Sbostic 	ASC_TC_GET(regs, len);
119852889Sbostic 	fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
119952889Sbostic #ifdef DEBUG
120052942Sralph 	if (asc_debug > 2)
120152889Sbostic 		printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n",
120252889Sbostic 			state->buflen, state->dmalen, len, fifo);
120352889Sbostic #endif
120452889Sbostic 	if (fifo) {
120552942Sralph 		/* device must be trying to send more than we expect */
120652889Sbostic 		regs->asc_cmd = ASC_CMD_FLUSH;
120756819Sralph 		readback(regs->asc_cmd);
120852889Sbostic 		MachEmptyWriteBuffer();
120952889Sbostic 	}
121053080Sralph 	state->flags &= ~DMA_IN_PROGRESS;
121152889Sbostic 	len = state->dmalen - len;
121252889Sbostic 	state->buflen -= len;
121352889Sbostic 	bcopy(state->dmaBufAddr, state->buf, len);
121452889Sbostic 
121552889Sbostic 	return (1);
121652889Sbostic }
121752889Sbostic 
121852889Sbostic /* ARGSUSED */
121952889Sbostic static int
122052942Sralph asc_resume_in(asc, status, ss, ir)
122152942Sralph 	register asc_softc_t asc;
122252942Sralph 	register int status, ss, ir;
122352942Sralph {
122452942Sralph 	register asc_regmap_t *regs = asc->regs;
122552942Sralph 	register State *state = &asc->st[asc->target];
122652942Sralph 	register int len;
122752942Sralph 
122852942Sralph 	/* setup to start reading the next chunk */
122952942Sralph 	len = state->buflen;
123052942Sralph 	if (len > state->dmaBufSize)
123152942Sralph 		len = state->dmaBufSize;
123252942Sralph 	state->dmalen = len;
123356819Sralph 	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_READ);
123452942Sralph 	ASC_TC_PUT(regs, len);
123552942Sralph #ifdef DEBUG
123652942Sralph 	if (asc_debug > 2)
123752942Sralph 		printf("asc_resume_in: buflen %d, len %d\n", state->buflen,
123852942Sralph 			len);
123952942Sralph #endif
124052942Sralph 
124152942Sralph 	/* check for next chunk */
124253080Sralph 	state->flags |= DMA_IN_PROGRESS;
124352942Sralph 	if (len != state->buflen) {
124452942Sralph 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
124556819Sralph 		readback(regs->asc_cmd);
124652942Sralph 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
124752942Sralph 		return (0);
124852942Sralph 	}
124952942Sralph 	return (1);
125052942Sralph }
125152942Sralph 
125252942Sralph /* ARGSUSED */
125352942Sralph static int
125452889Sbostic asc_resume_dma_in(asc, status, ss, ir)
125552889Sbostic 	register asc_softc_t asc;
125652889Sbostic 	register int status, ss, ir;
125752889Sbostic {
125852889Sbostic 	register asc_regmap_t *regs = asc->regs;
125952889Sbostic 	register State *state = &asc->st[asc->target];
126052889Sbostic 	register int len, off;
126152889Sbostic 
126252889Sbostic 	/* setup to finish reading the current chunk */
126352889Sbostic 	len = state->dmaresid;
126452889Sbostic 	off = state->dmalen - len;
126552889Sbostic 	if ((off & 1) && state->sync_offset) {
126652889Sbostic 		printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n",
126752889Sbostic 			state->dmalen, len, off); /* XXX */
126852889Sbostic 		regs->asc_res_fifo = state->dmaBufAddr[off];
126952889Sbostic 	}
127056819Sralph 	(*asc->dma_start)(asc, state, state->dmaBufAddr + off, ASCDMA_READ);
127152889Sbostic 	ASC_TC_PUT(regs, len);
127252942Sralph #ifdef DEBUG
127352942Sralph 	if (asc_debug > 2)
127452942Sralph 		printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n",
127552942Sralph 			state->dmalen, state->buflen, len, off);
127652942Sralph #endif
127752942Sralph 
127852942Sralph 	/* check for next chunk */
127953080Sralph 	state->flags |= DMA_IN_PROGRESS;
128052889Sbostic 	if (state->dmalen != state->buflen) {
128152889Sbostic 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
128256819Sralph 		readback(regs->asc_cmd);
128352942Sralph 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
128452889Sbostic 		return (0);
128552889Sbostic 	}
128652889Sbostic 	return (1);
128752889Sbostic }
128852889Sbostic 
128952889Sbostic /* ARGSUSED */
129052889Sbostic static int
129152889Sbostic asc_dma_out(asc, status, ss, ir)
129252889Sbostic 	register asc_softc_t asc;
129352889Sbostic 	register int status, ss, ir;
129452889Sbostic {
129552889Sbostic 	register asc_regmap_t *regs = asc->regs;
129652889Sbostic 	register State *state = &asc->st[asc->target];
129752889Sbostic 	register int len, fifo;
129852889Sbostic 
129953080Sralph 	if (state->flags & DMA_IN_PROGRESS) {
130052889Sbostic 		/* check to be sure previous chunk was finished */
130152889Sbostic 		ASC_TC_GET(regs, len);
130252889Sbostic 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
130352889Sbostic 		if (len || fifo)
130452889Sbostic 			printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
130552889Sbostic 				state->buflen, state->dmalen, len, fifo); /* XXX */
130652889Sbostic 		len += fifo;
130752889Sbostic 		len = state->dmalen - len;
130853080Sralph 		state->buf += len;
130952889Sbostic 		state->buflen -= len;
131053080Sralph 	}
131152889Sbostic 
131253080Sralph 	/* setup for this chunck */
131353080Sralph 	len = state->buflen;
131453080Sralph 	if (len > state->dmaBufSize)
131553080Sralph 		len = state->dmaBufSize;
131653080Sralph 	state->dmalen = len;
131753080Sralph 	bcopy(state->buf, state->dmaBufAddr, len);
131856819Sralph 	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
131952942Sralph 	ASC_TC_PUT(regs, len);
132052889Sbostic #ifdef DEBUG
132152889Sbostic 	if (asc_debug > 2)
132252942Sralph 		printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len);
132352889Sbostic #endif
132452889Sbostic 
132552889Sbostic 	/* check for next chunk */
132653080Sralph 	state->flags |= DMA_IN_PROGRESS;
132752889Sbostic 	if (len != state->buflen) {
132852889Sbostic 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
132956819Sralph 		readback(regs->asc_cmd);
133052942Sralph 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
133152889Sbostic 		return (0);
133252889Sbostic 	}
133352889Sbostic 	return (1);
133452889Sbostic }
133552889Sbostic 
133652889Sbostic /* ARGSUSED */
133752889Sbostic static int
133852889Sbostic asc_last_dma_out(asc, status, ss, ir)
133952889Sbostic 	register asc_softc_t asc;
134052889Sbostic 	register int status, ss, ir;
134152889Sbostic {
134252889Sbostic 	register asc_regmap_t *regs = asc->regs;
134352889Sbostic 	register State *state = &asc->st[asc->target];
134452889Sbostic 	register int len, fifo;
134552889Sbostic 
134652889Sbostic 	ASC_TC_GET(regs, len);
134752889Sbostic 	fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
134852889Sbostic #ifdef DEBUG
134952889Sbostic 	if (asc_debug > 2)
135052889Sbostic 		printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
135153080Sralph 			state->buflen, state->dmalen, len, fifo);
135252942Sralph #endif
135352942Sralph 	if (fifo) {
135452942Sralph 		len += fifo;
135552942Sralph 		regs->asc_cmd = ASC_CMD_FLUSH;
135656819Sralph 		readback(regs->asc_cmd);
135752942Sralph 		MachEmptyWriteBuffer();
135852942Sralph 	}
135953080Sralph 	state->flags &= ~DMA_IN_PROGRESS;
136052889Sbostic 	len = state->dmalen - len;
136152889Sbostic 	state->buflen -= len;
136252889Sbostic 	return (1);
136352889Sbostic }
136452889Sbostic 
136552889Sbostic /* ARGSUSED */
136652889Sbostic static int
136752942Sralph asc_resume_out(asc, status, ss, ir)
136852942Sralph 	register asc_softc_t asc;
136952942Sralph 	register int status, ss, ir;
137052942Sralph {
137152942Sralph 	register asc_regmap_t *regs = asc->regs;
137252942Sralph 	register State *state = &asc->st[asc->target];
137352942Sralph 	register int len;
137452942Sralph 
137552942Sralph 	/* setup for this chunck */
137652942Sralph 	len = state->buflen;
137752942Sralph 	if (len > state->dmaBufSize)
137852942Sralph 		len = state->dmaBufSize;
137952942Sralph 	state->dmalen = len;
138052942Sralph 	bcopy(state->buf, state->dmaBufAddr, len);
138156819Sralph 	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
138252942Sralph 	ASC_TC_PUT(regs, len);
138352942Sralph #ifdef DEBUG
138452942Sralph 	if (asc_debug > 2)
138552942Sralph 		printf("asc_resume_out: buflen %d, len %d\n", state->buflen,
138652942Sralph 			len);
138752942Sralph #endif
138852942Sralph 
138952942Sralph 	/* check for next chunk */
139053080Sralph 	state->flags |= DMA_IN_PROGRESS;
139152942Sralph 	if (len != state->buflen) {
139252942Sralph 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
139356819Sralph 		readback(regs->asc_cmd);
139452942Sralph 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
139552942Sralph 		return (0);
139652942Sralph 	}
139752942Sralph 	return (1);
139852942Sralph }
139952942Sralph 
140052942Sralph /* ARGSUSED */
140152942Sralph static int
140252889Sbostic asc_resume_dma_out(asc, status, ss, ir)
140352889Sbostic 	register asc_softc_t asc;
140452889Sbostic 	register int status, ss, ir;
140552889Sbostic {
140652889Sbostic 	register asc_regmap_t *regs = asc->regs;
140752889Sbostic 	register State *state = &asc->st[asc->target];
140852889Sbostic 	register int len, off;
140952889Sbostic 
141052889Sbostic 	/* setup to finish writing this chunk */
141152889Sbostic 	len = state->dmaresid;
141252889Sbostic 	off = state->dmalen - len;
141352889Sbostic 	if (off & 1) {
141452889Sbostic 		printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",
141552889Sbostic 			state->dmalen, len, off); /* XXX */
141652889Sbostic 		regs->asc_fifo = state->dmaBufAddr[off];
141752889Sbostic 		off++;
141852889Sbostic 		len--;
141952889Sbostic 	}
142056819Sralph 	(*asc->dma_start)(asc, state, state->dmaBufAddr + off, ASCDMA_WRITE);
142152889Sbostic 	ASC_TC_PUT(regs, len);
142252942Sralph #ifdef DEBUG
142352942Sralph 	if (asc_debug > 2)
142452942Sralph 		printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n",
142552942Sralph 			state->dmalen, state->buflen, len, off);
142652942Sralph #endif
142752942Sralph 
142852942Sralph 	/* check for next chunk */
142953080Sralph 	state->flags |= DMA_IN_PROGRESS;
143052889Sbostic 	if (state->dmalen != state->buflen) {
143152889Sbostic 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
143256819Sralph 		readback(regs->asc_cmd);
143352942Sralph 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
143452889Sbostic 		return (0);
143552889Sbostic 	}
143652889Sbostic 	return (1);
143752889Sbostic }
143852889Sbostic 
143952889Sbostic /* ARGSUSED */
144052889Sbostic static int
144152889Sbostic asc_sendsync(asc, status, ss, ir)
144252889Sbostic 	register asc_softc_t asc;
144352889Sbostic 	register int status, ss, ir;
144452889Sbostic {
144552889Sbostic 	register asc_regmap_t *regs = asc->regs;
144653080Sralph 	register State *state = &asc->st[asc->target];
144752889Sbostic 
144853080Sralph 	/* send the extended synchronous negotiation message */
144952889Sbostic 	regs->asc_fifo = SCSI_EXTENDED_MSG;
145052889Sbostic 	MachEmptyWriteBuffer();
145152889Sbostic 	regs->asc_fifo = 3;
145252889Sbostic 	MachEmptyWriteBuffer();
145352889Sbostic 	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
145452889Sbostic 	MachEmptyWriteBuffer();
145552889Sbostic 	regs->asc_fifo = SCSI_MIN_PERIOD;
145652889Sbostic 	MachEmptyWriteBuffer();
145752889Sbostic 	regs->asc_fifo = ASC_MAX_OFFSET;
145853080Sralph 	/* state to resume after we see the sync reply message */
145953080Sralph 	state->script = asc->script + 2;
146053080Sralph 	state->msglen = 0;
146152889Sbostic 	return (1);
146252889Sbostic }
146352889Sbostic 
146452889Sbostic /* ARGSUSED */
146552889Sbostic static int
146652889Sbostic asc_replysync(asc, status, ss, ir)
146752889Sbostic 	register asc_softc_t asc;
146852889Sbostic 	register int status, ss, ir;
146952889Sbostic {
147052889Sbostic 	register asc_regmap_t *regs = asc->regs;
147152889Sbostic 	register State *state = &asc->st[asc->target];
147252889Sbostic 
147352889Sbostic #ifdef DEBUG
147452889Sbostic 	if (asc_debug > 2)
147552889Sbostic 		printf("asc_replysync: %x %x\n",
147656819Sralph 			asc_to_scsi_period[state->sync_period] * asc->tb_ticks,
147752889Sbostic 			state->sync_offset);
147852889Sbostic #endif
147952889Sbostic 	/* send synchronous transfer in response to a request */
148052889Sbostic 	regs->asc_fifo = SCSI_EXTENDED_MSG;
148152889Sbostic 	MachEmptyWriteBuffer();
148252889Sbostic 	regs->asc_fifo = 3;
148352889Sbostic 	MachEmptyWriteBuffer();
148452889Sbostic 	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
148552889Sbostic 	MachEmptyWriteBuffer();
148656819Sralph 	regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks;
148752889Sbostic 	MachEmptyWriteBuffer();
148852889Sbostic 	regs->asc_fifo = state->sync_offset;
148952889Sbostic 	regs->asc_cmd = ASC_CMD_XFER_INFO;
149056819Sralph 	readback(regs->asc_cmd);
149152889Sbostic 
149252889Sbostic 	/* return to the appropriate script */
149352889Sbostic 	if (!state->script) {
149452889Sbostic #ifdef DEBUG
149552889Sbostic 		asc_DumpLog("asc_replsync");
149652889Sbostic #endif
149752889Sbostic 		panic("asc_replysync");
149852889Sbostic 	}
149952889Sbostic 	asc->script = state->script;
150052889Sbostic 	state->script = (script_t *)0;
150152889Sbostic 	return (0);
150252889Sbostic }
150352889Sbostic 
150452889Sbostic /* ARGSUSED */
150552889Sbostic static int
150652942Sralph asc_msg_in(asc, status, ss, ir)
150752889Sbostic 	register asc_softc_t asc;
150852889Sbostic 	register int status, ss, ir;
150952889Sbostic {
151052889Sbostic 	register asc_regmap_t *regs = asc->regs;
151152889Sbostic 	register State *state = &asc->st[asc->target];
151252889Sbostic 	register int msg;
151352889Sbostic 	int i;
151452889Sbostic 
151552889Sbostic 	/* read one message byte */
151652889Sbostic 	msg = regs->asc_fifo;
151752889Sbostic #ifdef DEBUG
151852889Sbostic 	if (asc_logp == asc_log)
151952889Sbostic 		asc_log[NLOG - 1].msg = msg;
152052889Sbostic 	else
152152889Sbostic 		asc_logp[-1].msg = msg;
152252889Sbostic #endif
152352889Sbostic 
152452889Sbostic 	/* check for multi-byte message */
152552889Sbostic 	if (state->msglen != 0) {
152652889Sbostic 		/* first byte is the message length */
152752889Sbostic 		if (state->msglen < 0) {
152852889Sbostic 			state->msglen = msg;
152952889Sbostic 			return (1);
153052889Sbostic 		}
153152889Sbostic 		if (state->msgcnt >= state->msglen)
153252889Sbostic 			goto abort;
153352889Sbostic 		state->msg_in[state->msgcnt++] = msg;
153452889Sbostic 
153552889Sbostic 		/* did we just read the last byte of the message? */
153652889Sbostic 		if (state->msgcnt != state->msglen)
153752889Sbostic 			return (1);
153852889Sbostic 
153952889Sbostic 		/* process an extended message */
154052889Sbostic #ifdef DEBUG
154152889Sbostic 		if (asc_debug > 2)
154252942Sralph 			printf("asc_msg_in: msg %x %x %x\n",
154352889Sbostic 				state->msg_in[0],
154452889Sbostic 				state->msg_in[1],
154552889Sbostic 				state->msg_in[2]);
154652889Sbostic #endif
154752889Sbostic 		switch (state->msg_in[0]) {
154852889Sbostic 		case SCSI_SYNCHRONOUS_XFER:
154952889Sbostic 			state->flags |= DID_SYNC;
155052889Sbostic 			state->sync_offset = state->msg_in[2];
155152889Sbostic 
155252889Sbostic 			/* convert SCSI period to ASC period */
155356819Sralph 			i = state->msg_in[1] / asc->tb_ticks;
155456819Sralph 			if (i < asc->min_period)
155556819Sralph 				i = asc->min_period;
155656819Sralph 			else if (i >= asc->max_period) {
155752889Sbostic 				/* can't do sync transfer, period too long */
155852889Sbostic 				printf("asc%d: SCSI device %d: sync xfer period too long (%d)\n",
155952889Sbostic 					asc - asc_softc, asc->target, i);
156056819Sralph 				i = asc->max_period;
156152889Sbostic 				state->sync_offset = 0;
156252889Sbostic 			}
156356819Sralph 			if ((i * asc->tb_ticks) != state->msg_in[1])
156452889Sbostic 				i++;
156552889Sbostic 			state->sync_period = i & 0x1F;
156652889Sbostic 
156752889Sbostic 			/*
156852889Sbostic 			 * If this is a request, check minimums and
156952889Sbostic 			 * send back an acknowledge.
157052889Sbostic 			 */
157152889Sbostic 			if (!(state->flags & TRY_SYNC)) {
157252889Sbostic 				regs->asc_cmd = ASC_CMD_SET_ATN;
157356819Sralph 				readback(regs->asc_cmd);
157452889Sbostic 				MachEmptyWriteBuffer();
157552889Sbostic 
157656819Sralph 				if (state->sync_period < asc->min_period)
157752889Sbostic 					state->sync_period =
157856819Sralph 						asc->min_period;
157952889Sbostic 				if (state->sync_offset > ASC_MAX_OFFSET)
158052889Sbostic 					state->sync_offset =
158152889Sbostic 						ASC_MAX_OFFSET;
158252889Sbostic 				asc->script = &asc_scripts[SCRIPT_REPLY_SYNC];
158352889Sbostic 				regs->asc_syn_p = state->sync_period;
158456819Sralph 				readback(regs->asc_syn_p);
158552889Sbostic 				regs->asc_syn_o = state->sync_offset;
158656819Sralph 				readback(regs->asc_syn_o);
158752889Sbostic 				regs->asc_cmd = ASC_CMD_MSG_ACPT;
158856819Sralph 				readback(regs->asc_cmd);
158952889Sbostic 				return (0);
159052889Sbostic 			}
159152889Sbostic 
159252889Sbostic 			regs->asc_syn_p = state->sync_period;
159356819Sralph 			readback(regs->asc_syn_p);
159452889Sbostic 			regs->asc_syn_o = state->sync_offset;
159556819Sralph 			readback(regs->asc_syn_o);
159652889Sbostic 			goto done;
159752889Sbostic 
159852889Sbostic 		default:
159952889Sbostic 			printf("asc%d: SCSI device %d: rejecting extended message 0x%x\n",
160052889Sbostic 				asc - asc_softc, asc->target,
160152889Sbostic 				state->msg_in[0]);
160252889Sbostic 			goto reject;
160352889Sbostic 		}
160452889Sbostic 	}
160552889Sbostic 
160652889Sbostic 	/* process first byte of a message */
160752889Sbostic #ifdef DEBUG
160852889Sbostic 	if (asc_debug > 2)
160952942Sralph 		printf("asc_msg_in: msg %x\n", msg);
161052889Sbostic #endif
161152889Sbostic 	switch (msg) {
161252889Sbostic #if 0
161352889Sbostic 	case SCSI_MESSAGE_REJECT:
161452889Sbostic 		printf(" did not like SYNCH xfer "); /* XXX */
161552889Sbostic 		state->flags |= DID_SYNC;
161652889Sbostic 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
161756819Sralph 		readback(regs->asc_cmd);
161852889Sbostic 		status = asc_wait(regs, ASC_CSR_INT);
161952889Sbostic 		ir = regs->asc_intr;
162052889Sbostic 		/* some just break out here, some dont */
162152889Sbostic 		if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {
162252889Sbostic 			regs->asc_fifo = SCSI_ABORT;
162352889Sbostic 			regs->asc_cmd = ASC_CMD_XFER_INFO;
162456819Sralph 			readback(regs->asc_cmd);
162552889Sbostic 			status = asc_wait(regs, ASC_CSR_INT);
162652889Sbostic 			ir = regs->asc_intr;
162752889Sbostic 		}
162852889Sbostic 		if (ir & ASC_INT_DISC) {
162952889Sbostic 			asc_end(asc, status, 0, ir);
163052889Sbostic 			return (0);
163152889Sbostic 		}
163252889Sbostic 		goto status;
163352889Sbostic #endif
163452889Sbostic 
163552889Sbostic 	case SCSI_EXTENDED_MSG: /* read an extended message */
163652889Sbostic 		/* setup to read message length next */
163752889Sbostic 		state->msglen = -1;
163852889Sbostic 		state->msgcnt = 0;
163952889Sbostic 		return (1);
164052889Sbostic 
164152889Sbostic 	case SCSI_NO_OP:
164252889Sbostic 		break;
164352889Sbostic 
164452889Sbostic 	case SCSI_SAVE_DATA_POINTER:
164552889Sbostic 		/* expect another message */
164652889Sbostic 		return (1);
164752889Sbostic 
164852889Sbostic 	case SCSI_RESTORE_POINTERS:
164952889Sbostic 		/*
165052889Sbostic 		 * Need to do the following if resuming synchonous data in
165152889Sbostic 		 * on an odd byte boundary.
165252889Sbostic 		regs->asc_cnfg2 |= ASC_CNFG2_RFB;
165352889Sbostic 		 */
165452889Sbostic 		break;
165552889Sbostic 
165652889Sbostic 	case SCSI_DISCONNECT:
165752889Sbostic 		if (state->flags & DISCONN)
165852889Sbostic 			goto abort;
165952889Sbostic 		state->flags |= DISCONN;
166052942Sralph 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
166156819Sralph 		readback(regs->asc_cmd);
166252942Sralph 		asc->script = &asc_scripts[SCRIPT_DISCONNECT];
166352942Sralph 		return (0);
166452889Sbostic 
166552889Sbostic 	default:
166652889Sbostic 		printf("asc%d: SCSI device %d: rejecting message 0x%x\n",
166752889Sbostic 			asc - asc_softc, asc->target, msg);
166852889Sbostic 	reject:
166952889Sbostic 		/* request a message out before acknowledging this message */
167052889Sbostic 		state->msg_out = SCSI_MESSAGE_REJECT;
167152889Sbostic 		regs->asc_cmd = ASC_CMD_SET_ATN;
167256819Sralph 		readback(regs->asc_cmd);
167352889Sbostic 		MachEmptyWriteBuffer();
167452889Sbostic 	}
167552889Sbostic 
167652889Sbostic done:
167752889Sbostic 	/* return to original script */
167852889Sbostic 	regs->asc_cmd = ASC_CMD_MSG_ACPT;
167956819Sralph 	readback(regs->asc_cmd);
168052889Sbostic 	if (!state->script) {
168152889Sbostic 	abort:
168252889Sbostic #ifdef DEBUG
168352942Sralph 		asc_DumpLog("asc_msg_in");
168452889Sbostic #endif
168552942Sralph 		panic("asc_msg_in");
168652889Sbostic 	}
168752889Sbostic 	asc->script = state->script;
168852889Sbostic 	state->script = (script_t *)0;
168952889Sbostic 	return (0);
169052889Sbostic }
169152889Sbostic 
169252942Sralph /* ARGSUSED */
169352942Sralph static int
169452942Sralph asc_disconnect(asc, status, ss, ir)
169552942Sralph 	register asc_softc_t asc;
169652942Sralph 	register int status, ss, ir;
169752942Sralph {
169852942Sralph 	register State *state = &asc->st[asc->target];
169952942Sralph 
170052942Sralph 	asc->target = -1;
170152942Sralph 	asc->state = ASC_STATE_RESEL;
170252942Sralph 	return (1);
170352942Sralph }
170452942Sralph 
170556819Sralph /*
170656819Sralph  * DMA handling routines. For a turbochannel device, just set the dmar
170756819Sralph  * for the I/O ASIC, handle the actual DMA interface.
170856819Sralph  */
170956819Sralph static void
171056819Sralph tb_dma_start(asc, state, cp, flag)
171156819Sralph 	asc_softc_t asc;
171256819Sralph 	State *state;
171356819Sralph 	caddr_t cp;
171456819Sralph 	int flag;
171556819Sralph {
171656819Sralph 
171756819Sralph 	if (flag == ASCDMA_WRITE)
171856819Sralph 		*asc->dmar = ASC_DMAR_WRITE | ASC_DMA_ADDR(cp);
171956819Sralph 	else
172056819Sralph 		*asc->dmar = ASC_DMA_ADDR(cp);
172156819Sralph }
172256819Sralph 
172356819Sralph static void
172456819Sralph tb_dma_end(asc, state, flag)
172556819Sralph 	asc_softc_t asc;
172656819Sralph 	State *state;
172756819Sralph 	int flag;
172856819Sralph {
172956819Sralph 
173056819Sralph }
173156819Sralph 
173256819Sralph static void
173356819Sralph asic_dma_start(asc, state, cp, flag)
173456819Sralph 	asc_softc_t asc;
173556819Sralph 	State *state;
173656819Sralph 	caddr_t cp;
173756819Sralph 	int flag;
173856819Sralph {
173956819Sralph 	register volatile u_int *ssr = (volatile u_int *)
1740*57233Sralph 		ASIC_REG_CSR(asic_base);
174156819Sralph 	u_int phys, nphys;
174256819Sralph 
174356819Sralph 	/* stop DMA engine first */
174456819Sralph 	*ssr &= ~ASIC_CSR_DMAEN_SCSI;
1745*57233Sralph 	* ((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0;
174656819Sralph 
174756819Sralph 	phys = MACH_CACHED_TO_PHYS(cp);
174856819Sralph 	cp = (caddr_t)pmax_trunc_page(cp + NBPG);
174956819Sralph 	nphys = MACH_CACHED_TO_PHYS(cp);
175056819Sralph 
175156819Sralph 	asc->dma_next = cp;
175256819Sralph 	asc->dma_xfer = state->dmalen - (nphys - phys);
175356819Sralph 
1754*57233Sralph 	*(volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base) =
175556819Sralph 		ASIC_DMA_ADDR(phys);
1756*57233Sralph 	*(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) =
175756819Sralph 		ASIC_DMA_ADDR(nphys);
175856819Sralph 	if (flag == ASCDMA_READ)
175956819Sralph 		*ssr |= ASIC_CSR_SCSI_DIR | ASIC_CSR_DMAEN_SCSI;
176056819Sralph 	else
176156819Sralph 		*ssr = (*ssr & ~ASIC_CSR_SCSI_DIR) | ASIC_CSR_DMAEN_SCSI;
176256819Sralph 	MachEmptyWriteBuffer();
176356819Sralph }
176456819Sralph 
176556819Sralph static void
176656819Sralph asic_dma_end(asc, state, flag)
176756819Sralph 	asc_softc_t asc;
176856819Sralph 	State *state;
176956819Sralph 	int flag;
177056819Sralph {
177156819Sralph 	register volatile u_int *ssr = (volatile u_int *)
1772*57233Sralph 		ASIC_REG_CSR(asic_base);
177356819Sralph 	int nb;
177456819Sralph 
177556819Sralph 	*ssr &= ~ASIC_CSR_DMAEN_SCSI;
1776*57233Sralph 	*((volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base)) = -1;
1777*57233Sralph 	*((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1;
177856819Sralph 	MachEmptyWriteBuffer();
177956819Sralph 
178056819Sralph 	if (flag == ASCDMA_READ) {
178156819Sralph 		MachFlushDCache(MACH_PHYS_TO_CACHED(
178256819Sralph 		    MACH_UNCACHED_TO_PHYS(state->dmaBufAddr)), state->dmalen);
1783*57233Sralph 		if (nb = *((int *)ASIC_REG_SCSI_SCR(asic_base))) {
178456819Sralph 			/* pick up last upto6 bytes, sigh. */
178556819Sralph 			register u_short *to;
178656819Sralph 			register int w;
178756819Sralph 
178856819Sralph 			/* Last byte really xferred is.. */
178956819Sralph 			to = (u_short *)(state->dmaBufAddr + state->dmalen - (nb << 1));
1790*57233Sralph 			w = *(int *)ASIC_REG_SCSI_SDR0(asic_base);
179156819Sralph 			*to++ = w;
179256819Sralph 			if (--nb > 0) {
179356819Sralph 				w >>= 16;
179456819Sralph 				*to++ = w;
179556819Sralph 			}
179656819Sralph 			if (--nb > 0) {
1797*57233Sralph 				w = *(int *)ASIC_REG_SCSI_SDR1(asic_base);
179856819Sralph 				*to++ = w;
179956819Sralph 			}
180056819Sralph 		}
180156819Sralph 	}
180256819Sralph }
180356819Sralph 
1804*57233Sralph #ifdef notdef
180556819Sralph /*
180656819Sralph  * Called by asic_intr() for scsi dma pointer update interrupts.
180756819Sralph  */
180856819Sralph void
180956819Sralph asc_dma_intr()
181056819Sralph {
181156819Sralph 	asc_softc_t asc = &asc_softc[0];
181256819Sralph 	u_int next_phys;
181356819Sralph 
181456819Sralph 	asc->dma_xfer -= NBPG;
181556819Sralph 	if (asc->dma_xfer <= -NBPG) {
181656819Sralph 		volatile u_int *ssr = (volatile u_int *)
1817*57233Sralph 			ASIC_REG_CSR(asic_base);
181856819Sralph 		*ssr &= ~ASIC_CSR_DMAEN_SCSI;
181956819Sralph 	} else {
182056819Sralph 		asc->dma_next += NBPG;
182156819Sralph 		next_phys = MACH_CACHED_TO_PHYS(asc->dma_next);
182256819Sralph 	}
1823*57233Sralph 	*(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) =
182456819Sralph 		ASIC_DMA_ADDR(next_phys);
182556819Sralph 	MachEmptyWriteBuffer();
182656819Sralph }
1827*57233Sralph #endif
182856819Sralph 
182952889Sbostic #ifdef DEBUG
183052889Sbostic asc_DumpLog(str)
183152889Sbostic 	char *str;
183252889Sbostic {
183352889Sbostic 	register struct asc_log *lp;
183452889Sbostic 	register u_int status;
183552889Sbostic 
183652889Sbostic 	printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
183752889Sbostic 		asc_debug_bn, asc_debug_sz);
183852889Sbostic 	lp = asc_logp + 1;
183952889Sbostic 	if (lp > &asc_log[NLOG])
184052889Sbostic 		lp = asc_log;
184152889Sbostic 	while (lp != asc_logp) {
184252889Sbostic 		status = lp->status;
184352889Sbostic 		printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x\n",
184452889Sbostic 			status >> 24,
184552889Sbostic 			lp->target,
184652889Sbostic 			(status >> 16) & 0xFF,
184752889Sbostic 			(status >> 8) & 0xFF,
184852889Sbostic 			status & 0XFF,
184952889Sbostic 			lp->state,
185052889Sbostic 			asc_scripts[lp->state].condition,
185152889Sbostic 			lp->msg);
185252889Sbostic 		if (++lp >= &asc_log[NLOG])
185352889Sbostic 			lp = asc_log;
185452889Sbostic 	}
185552889Sbostic }
185652889Sbostic #endif
185752889Sbostic 
185852889Sbostic #endif	/* NASC > 0 */
1859