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