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