xref: /csrg-svn/sys/pmax/dev/asc.c (revision 58658)
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.11 (Berkeley) 03/13/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 	asc_debug_cmd = scsicmd->cmd[0];
654 	if (scsicmd->cmd[0] == SCSI_READ_EXT) {
655 		asc_debug_bn = (scsicmd->cmd[2] << 24) |
656 			(scsicmd->cmd[3] << 16) |
657 			(scsicmd->cmd[4] << 8) |
658 			scsicmd->cmd[5];
659 		asc_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8];
660 	}
661 	asc_logp->status = PACK(asc - asc_softc, 0, 0, asc_debug_cmd);
662 	asc_logp->target = asc->target;
663 	asc_logp->state = 0;
664 	asc_logp->msg = 0xff;
665 	asc_logp->resid = scsicmd->buflen;
666 	if (++asc_logp >= &asc_log[NLOG])
667 		asc_logp = asc_log;
668 #endif
669 
670 	/*
671 	 * Init the chip and target state.
672 	 */
673 	state->flags = state->flags & DID_SYNC;
674 	state->error = 0;
675 	state->script = (script_t *)0;
676 	state->msg_out = SCSI_NO_OP;
677 
678 	/*
679 	 * Copy command data to the DMA buffer.
680 	 */
681 	len = scsicmd->cmdlen;
682 	state->dmalen = len;
683 	bcopy(scsicmd->cmd, state->dmaBufAddr, len);
684 
685 	/* check for simple SCSI command with no data transfer */
686 	if ((state->buflen = scsicmd->buflen) == 0) {
687 		/* check for sync negotiation */
688 		if ((scsicmd->flags & SCSICMD_USE_SYNC) &&
689 		    !(state->flags & DID_SYNC)) {
690 			asc->script = &asc_scripts[SCRIPT_TRY_SYNC];
691 			state->flags |= TRY_SYNC;
692 		} else
693 			asc->script = &asc_scripts[SCRIPT_SIMPLE];
694 		state->buf = (char *)0;
695 	} else if (scsicmd->flags & SCSICMD_DATA_TO_DEVICE) {
696 		asc->script = &asc_scripts[SCRIPT_DATA_OUT];
697 		state->buf = scsicmd->buf;
698 		state->flags |= DMA_OUT;
699 	} else {
700 		asc->script = &asc_scripts[SCRIPT_DATA_IN];
701 		state->buf = scsicmd->buf;
702 		state->flags |= DMA_IN;
703 	}
704 
705 	/* preload the FIFO with the message to be sent */
706 	regs->asc_fifo = SCSI_DIS_REC_IDENTIFY;
707 	MachEmptyWriteBuffer();
708 
709 	/* start the asc */
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 			/* setup state to resume to */
876 			if (state->flags & DMA_IN)
877 				state->script =
878 					&asc_scripts[SCRIPT_RESUME_DMA_IN];
879 			else if (state->flags & DMA_OUT)
880 				state->script =
881 					&asc_scripts[SCRIPT_RESUME_DMA_OUT];
882 			else
883 				state->script = asc->script;
884 #ifdef DEBUG
885 			if (asc_logp == asc_log)
886 				asc_log[NLOG - 1].resid = len;
887 			else
888 				asc_logp[-1].resid = len;
889 #endif
890 		} else {
891 			/* setup state to resume to */
892 			if (state->flags & DMA_IN) {
893 				if (state->flags & DMA_IN_PROGRESS) {
894 					state->flags &= ~DMA_IN_PROGRESS;
895 					(*asc->dma_end)(asc, state, ASCDMA_READ);
896 					len = state->dmalen;
897 					bcopy(state->dmaBufAddr, state->buf,
898 						len);
899 					state->buf += len;
900 					state->buflen -= len;
901 				}
902 				if (state->buflen)
903 					state->script =
904 					    &asc_scripts[SCRIPT_RESUME_IN];
905 				else
906 					state->script =
907 					    &asc_scripts[SCRIPT_RESUME_NO_DATA];
908 			} else if (state->flags & DMA_OUT) {
909 				/*
910 				 * If this is the last chunk, the next expected
911 				 * state is to get status.
912 				 */
913 				if (state->flags & DMA_IN_PROGRESS) {
914 					state->flags &= ~DMA_IN_PROGRESS;
915 					(*asc->dma_end)(asc, state, ASCDMA_WRITE);
916 					len = state->dmalen;
917 					state->buf += len;
918 					state->buflen -= len;
919 				}
920 				if (state->buflen)
921 					state->script =
922 					    &asc_scripts[SCRIPT_RESUME_OUT];
923 				else
924 					state->script =
925 					    &asc_scripts[SCRIPT_RESUME_NO_DATA];
926 			} else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
927 				state->script =
928 					&asc_scripts[SCRIPT_RESUME_NO_DATA];
929 			else
930 				state->script = asc->script;
931 		}
932 
933 		/* setup to receive a message */
934 		asc->script = &asc_scripts[SCRIPT_MSG_IN];
935 		state->msglen = 0;
936 		regs->asc_cmd = ASC_CMD_XFER_INFO;
937 		readback(regs->asc_cmd);
938 		goto done;
939 	}
940 
941 	/* check for SCSI bus reset */
942 	if (ir & ASC_INT_RESET) {
943 		register int i;
944 
945 		printf("asc%d: SCSI bus reset!!\n", asc - asc_softc);
946 		/* need to flush any pending commands */
947 		for (i = 0; i < ASC_NCMD; i++) {
948 			if (!asc->cmd[i])
949 				continue;
950 			asc->st[i].error = EIO;
951 			asc_end(asc, 0, 0, 0);
952 		}
953 		/* rearbitrate synchronous offset */
954 		for (i = 0; i < ASC_NCMD; i++) {
955 			asc->st[i].sync_offset = 0;
956 			asc->st[i].flags = 0;
957 		}
958 		asc->target = -1;
959 		return;
960 	}
961 
962 	/* check for command errors */
963 	if (ir & ASC_INT_ILL)
964 		goto abort;
965 
966 	/* check for disconnect */
967 	if (ir & ASC_INT_DISC) {
968 		state = &asc->st[asc->target];
969 		switch (ASC_SS(ss)) {
970 		case 0: /* device did not respond */
971 			/* check for one of the starting scripts */
972 			switch (asc->script - asc_scripts) {
973 			case SCRIPT_TRY_SYNC:
974 			case SCRIPT_SIMPLE:
975 			case SCRIPT_DATA_IN:
976 			case SCRIPT_DATA_OUT:
977 				if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) {
978 					regs->asc_cmd = ASC_CMD_FLUSH;
979 					readback(regs->asc_cmd);
980 				}
981 				state->error = ENXIO;
982 				asc_end(asc, status, ss, ir);
983 				return;
984 			}
985 			/* FALLTHROUGH */
986 
987 		default:
988 			printf("asc%d: SCSI device %d: unexpected disconnect\n",
989 				asc - asc_softc, asc->target);
990 			/*
991 			 * On rare occasions my RZ24 does a disconnect during
992 			 * data in phase and the following seems to keep it
993 			 * happy.
994 			 * XXX Should a scsi disk ever do this??
995 			 */
996 			asc->script = &asc_scripts[SCRIPT_RESEL];
997 			asc->state = ASC_STATE_RESEL;
998 			state->flags |= DISCONN;
999 			regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1000 			readback(regs->asc_cmd);
1001 			return;
1002 		}
1003 	}
1004 
1005 	/* check for reselect */
1006 	if (ir & ASC_INT_RESEL) {
1007 		unsigned fifo, id, msg;
1008 
1009 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1010 		if (fifo < 2)
1011 			goto abort;
1012 		/* read unencoded SCSI ID and convert to binary */
1013 		msg = regs->asc_fifo & asc->myidmask;
1014 		for (id = 0; (msg & 1) == 0; id++)
1015 			msg >>= 1;
1016 		/* read identify message */
1017 		msg = regs->asc_fifo;
1018 #ifdef DEBUG
1019 		if (asc_logp == asc_log)
1020 			asc_log[NLOG - 1].msg = msg;
1021 		else
1022 			asc_logp[-1].msg = msg;
1023 #endif
1024 		asc->state = ASC_STATE_BUSY;
1025 		asc->target = id;
1026 		state = &asc->st[id];
1027 		asc->script = state->script;
1028 		state->script = (script_t *)0;
1029 		if (!(state->flags & DISCONN))
1030 			goto abort;
1031 		state->flags &= ~DISCONN;
1032 		regs->asc_syn_p = state->sync_period;
1033 		regs->asc_syn_o = state->sync_offset;
1034 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
1035 		readback(regs->asc_cmd);
1036 		goto done;
1037 	}
1038 
1039 	/* check if we are being selected as a target */
1040 	if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
1041 		goto abort;
1042 
1043 	/*
1044 	 * 'ir' must be just ASC_INT_FC.
1045 	 * This is normal if canceling an ASC_ENABLE_SEL.
1046 	 */
1047 
1048 done:
1049 	MachEmptyWriteBuffer();
1050 	/* watch out for HW race conditions and setup & hold time violations */
1051 	ir = regs->asc_status;
1052 	while (ir != (status = regs->asc_status))
1053 		ir = status;
1054 	if (status & ASC_CSR_INT)
1055 		goto again;
1056 	return;
1057 
1058 abort:
1059 #ifdef DEBUG
1060 	asc_DumpLog("asc_intr");
1061 #endif
1062 #if 0
1063 	panic("asc_intr");
1064 #else
1065 	for (;;);
1066 #endif
1067 }
1068 
1069 /*
1070  * All the many little things that the interrupt
1071  * routine might switch to.
1072  */
1073 
1074 /* ARGSUSED */
1075 static int
1076 script_nop(asc, status, ss, ir)
1077 	register asc_softc_t asc;
1078 	register int status, ss, ir;
1079 {
1080 	return (1);
1081 }
1082 
1083 /* ARGSUSED */
1084 static int
1085 asc_get_status(asc, status, ss, ir)
1086 	register asc_softc_t asc;
1087 	register int status, ss, ir;
1088 {
1089 	register asc_regmap_t *regs = asc->regs;
1090 	register int data;
1091 
1092 	/*
1093 	 * Get the last two bytes in the FIFO.
1094 	 */
1095 	if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
1096 		printf("asc_get_status: fifo cnt %d\n", data); /* XXX */
1097 		asc_DumpLog("get_status"); /* XXX */
1098 		if (data < 2) {
1099 			asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
1100 			readback(asc->regs->asc_cmd);
1101 			return (0);
1102 		}
1103 		do {
1104 			data = regs->asc_fifo;
1105 		} while ((regs->asc_flags & ASC_FLAGS_FIFO_CNT) > 2);
1106 	}
1107 
1108 	/* save the status byte */
1109 	asc->st[asc->target].statusByte = data = regs->asc_fifo;
1110 #ifdef DEBUG
1111 	if (asc_logp == asc_log)
1112 		asc_log[NLOG - 1].msg = data;
1113 	else
1114 		asc_logp[-1].msg = data;
1115 #endif
1116 
1117 	/* get the (presumed) command_complete message */
1118 	if ((data = regs->asc_fifo) == SCSI_COMMAND_COMPLETE)
1119 		return (1);
1120 
1121 #ifdef DEBUG
1122 	printf("asc_get_status: status %x cmd %x\n",
1123 		asc->st[asc->target].statusByte, data);
1124 	asc_DumpLog("asc_get_status");
1125 #endif
1126 	return (0);
1127 }
1128 
1129 /* ARGSUSED */
1130 static int
1131 asc_end(asc, status, ss, ir)
1132 	register asc_softc_t asc;
1133 	register int status, ss, ir;
1134 {
1135 	register ScsiCmd *scsicmd;
1136 	register State *state;
1137 	register int i, target;
1138 
1139 	asc->state = ASC_STATE_IDLE;
1140 	target = asc->target;
1141 	asc->target = -1;
1142 	scsicmd = asc->cmd[target];
1143 	asc->cmd[target] = (ScsiCmd *)0;
1144 	state = &asc->st[target];
1145 
1146 #ifdef DEBUG
1147 	if (asc_debug > 1) {
1148 		printf("asc_end: %s target %d cmd %x err %d resid %d\n",
1149 			scsicmd->sd->sd_driver->d_name, target,
1150 			scsicmd->cmd[0], state->error, state->buflen);
1151 	}
1152 #endif
1153 #ifdef DIAGNOSTIC
1154 	if (target < 0 || !scsicmd)
1155 		panic("asc_end");
1156 #endif
1157 
1158 	/* look for disconnected devices */
1159 	for (i = 0; i < ASC_NCMD; i++) {
1160 		if (!asc->cmd[i] || !(asc->st[i].flags & DISCONN))
1161 			continue;
1162 		asc->regs->asc_cmd = ASC_CMD_ENABLE_SEL;
1163 		readback(asc->regs->asc_cmd);
1164 		asc->state = ASC_STATE_RESEL;
1165 		asc->script = &asc_scripts[SCRIPT_RESEL];
1166 		break;
1167 	}
1168 
1169 	/*
1170 	 * Look for another device that is ready.
1171 	 * May want to keep last one started and increment for fairness
1172 	 * rather than always starting at zero.
1173 	 */
1174 	for (i = 0; i < ASC_NCMD; i++) {
1175 		/* don't restart a disconnected command */
1176 		if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
1177 			continue;
1178 		asc_startcmd(asc, i);
1179 		break;
1180 	}
1181 
1182 	/* signal device driver that the command is done */
1183 	(*scsicmd->sd->sd_driver->d_done)(scsicmd->unit, state->error,
1184 		state->buflen, state->statusByte);
1185 
1186 	return (0);
1187 }
1188 
1189 /* ARGSUSED */
1190 static int
1191 asc_dma_in(asc, status, ss, ir)
1192 	register asc_softc_t asc;
1193 	register int status, ss, ir;
1194 {
1195 	register asc_regmap_t *regs = asc->regs;
1196 	register State *state = &asc->st[asc->target];
1197 	register int len;
1198 
1199 	/* check for previous chunk in buffer */
1200 	if (state->flags & DMA_IN_PROGRESS) {
1201 		/*
1202 		 * Only count bytes that have been copied to memory.
1203 		 * There may be some bytes in the FIFO if synchonous transfers
1204 		 * are in progress.
1205 		 */
1206 		(*asc->dma_end)(asc, state, ASCDMA_READ);
1207 		ASC_TC_GET(regs, len);
1208 		len = state->dmalen - len;
1209 		bcopy(state->dmaBufAddr, state->buf, len);
1210 		state->buf += len;
1211 		state->buflen -= len;
1212 	}
1213 
1214 	/* setup to start reading the next chunk */
1215 	len = state->buflen;
1216 	if (len > state->dmaBufSize)
1217 		len = state->dmaBufSize;
1218 	state->dmalen = len;
1219 	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_READ);
1220 	ASC_TC_PUT(regs, len);
1221 #ifdef DEBUG
1222 	if (asc_debug > 2)
1223 		printf("asc_dma_in: buflen %d, len %d\n", state->buflen, len);
1224 #endif
1225 
1226 	/* check for next chunk */
1227 	state->flags |= DMA_IN_PROGRESS;
1228 	if (len != state->buflen) {
1229 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1230 		readback(regs->asc_cmd);
1231 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1232 		return (0);
1233 	}
1234 	return (1);
1235 }
1236 
1237 /* ARGSUSED */
1238 static int
1239 asc_last_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, fifo;
1246 
1247 	/* copy data from buffer to main memory */
1248 	(*asc->dma_end)(asc, state, ASCDMA_READ);
1249 	ASC_TC_GET(regs, len);
1250 	fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1251 #ifdef DEBUG
1252 	if (asc_debug > 2)
1253 		printf("asc_last_dma_in: buflen %d dmalen %d tc %d fifo %d\n",
1254 			state->buflen, state->dmalen, len, fifo);
1255 #endif
1256 	if (fifo) {
1257 		/* device must be trying to send more than we expect */
1258 		regs->asc_cmd = ASC_CMD_FLUSH;
1259 		readback(regs->asc_cmd);
1260 	}
1261 	state->flags &= ~DMA_IN_PROGRESS;
1262 	len = state->dmalen - len;
1263 	state->buflen -= len;
1264 	bcopy(state->dmaBufAddr, state->buf, len);
1265 
1266 	return (1);
1267 }
1268 
1269 /* ARGSUSED */
1270 static int
1271 asc_resume_in(asc, status, ss, ir)
1272 	register asc_softc_t asc;
1273 	register int status, ss, ir;
1274 {
1275 	register asc_regmap_t *regs = asc->regs;
1276 	register State *state = &asc->st[asc->target];
1277 	register int len;
1278 
1279 	/* setup to start reading the next chunk */
1280 	len = state->buflen;
1281 	if (len > state->dmaBufSize)
1282 		len = state->dmaBufSize;
1283 	state->dmalen = len;
1284 	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_READ);
1285 	ASC_TC_PUT(regs, len);
1286 #ifdef DEBUG
1287 	if (asc_debug > 2)
1288 		printf("asc_resume_in: buflen %d, len %d\n", state->buflen,
1289 			len);
1290 #endif
1291 
1292 	/* check for next chunk */
1293 	state->flags |= DMA_IN_PROGRESS;
1294 	if (len != state->buflen) {
1295 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1296 		readback(regs->asc_cmd);
1297 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1298 		return (0);
1299 	}
1300 	return (1);
1301 }
1302 
1303 /* ARGSUSED */
1304 static int
1305 asc_resume_dma_in(asc, status, ss, ir)
1306 	register asc_softc_t asc;
1307 	register int status, ss, ir;
1308 {
1309 	register asc_regmap_t *regs = asc->regs;
1310 	register State *state = &asc->st[asc->target];
1311 	register int len, off;
1312 
1313 	/* setup to finish reading the current chunk */
1314 	len = state->dmaresid;
1315 	off = state->dmalen - len;
1316 	if ((off & 1) && state->sync_offset) {
1317 		printf("asc_resume_dma_in: odd xfer dmalen %d len %d off %d\n",
1318 			state->dmalen, len, off); /* XXX */
1319 		regs->asc_res_fifo = state->dmaBufAddr[off];
1320 	}
1321 	(*asc->dma_start)(asc, state, state->dmaBufAddr + off, ASCDMA_READ);
1322 	ASC_TC_PUT(regs, len);
1323 #ifdef DEBUG
1324 	if (asc_debug > 2)
1325 		printf("asc_resume_dma_in: buflen %d dmalen %d len %d off %d\n",
1326 			state->dmalen, state->buflen, len, off);
1327 #endif
1328 
1329 	/* check for next chunk */
1330 	state->flags |= DMA_IN_PROGRESS;
1331 	if (state->dmalen != state->buflen) {
1332 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1333 		readback(regs->asc_cmd);
1334 		asc->script = &asc_scripts[SCRIPT_CONTINUE_IN];
1335 		return (0);
1336 	}
1337 	return (1);
1338 }
1339 
1340 /* ARGSUSED */
1341 static int
1342 asc_dma_out(asc, status, ss, ir)
1343 	register asc_softc_t asc;
1344 	register int status, ss, ir;
1345 {
1346 	register asc_regmap_t *regs = asc->regs;
1347 	register State *state = &asc->st[asc->target];
1348 	register int len, fifo;
1349 
1350 	if (state->flags & DMA_IN_PROGRESS) {
1351 		/* check to be sure previous chunk was finished */
1352 		ASC_TC_GET(regs, len);
1353 		fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1354 		if (len || fifo)
1355 			printf("asc_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1356 				state->buflen, state->dmalen, len, fifo); /* XXX */
1357 		len += fifo;
1358 		len = state->dmalen - len;
1359 		state->buf += len;
1360 		state->buflen -= len;
1361 	}
1362 
1363 	/* setup for this chunck */
1364 	len = state->buflen;
1365 	if (len > state->dmaBufSize)
1366 		len = state->dmaBufSize;
1367 	state->dmalen = len;
1368 	bcopy(state->buf, state->dmaBufAddr, len);
1369 	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
1370 	ASC_TC_PUT(regs, len);
1371 #ifdef DEBUG
1372 	if (asc_debug > 2)
1373 		printf("asc_dma_out: buflen %d, len %d\n", state->buflen, len);
1374 #endif
1375 
1376 	/* check for next chunk */
1377 	state->flags |= DMA_IN_PROGRESS;
1378 	if (len != state->buflen) {
1379 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1380 		readback(regs->asc_cmd);
1381 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1382 		return (0);
1383 	}
1384 	return (1);
1385 }
1386 
1387 /* ARGSUSED */
1388 static int
1389 asc_last_dma_out(asc, status, ss, ir)
1390 	register asc_softc_t asc;
1391 	register int status, ss, ir;
1392 {
1393 	register asc_regmap_t *regs = asc->regs;
1394 	register State *state = &asc->st[asc->target];
1395 	register int len, fifo;
1396 
1397 	ASC_TC_GET(regs, len);
1398 	fifo = regs->asc_flags & ASC_FLAGS_FIFO_CNT;
1399 #ifdef DEBUG
1400 	if (asc_debug > 2)
1401 		printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
1402 			state->buflen, state->dmalen, len, fifo);
1403 #endif
1404 	if (fifo) {
1405 		len += fifo;
1406 		regs->asc_cmd = ASC_CMD_FLUSH;
1407 		readback(regs->asc_cmd);
1408 	}
1409 	state->flags &= ~DMA_IN_PROGRESS;
1410 	len = state->dmalen - len;
1411 	state->buflen -= len;
1412 	return (1);
1413 }
1414 
1415 /* ARGSUSED */
1416 static int
1417 asc_resume_out(asc, status, ss, ir)
1418 	register asc_softc_t asc;
1419 	register int status, ss, ir;
1420 {
1421 	register asc_regmap_t *regs = asc->regs;
1422 	register State *state = &asc->st[asc->target];
1423 	register int len;
1424 
1425 	/* setup for this chunck */
1426 	len = state->buflen;
1427 	if (len > state->dmaBufSize)
1428 		len = state->dmaBufSize;
1429 	state->dmalen = len;
1430 	bcopy(state->buf, state->dmaBufAddr, len);
1431 	(*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
1432 	ASC_TC_PUT(regs, len);
1433 #ifdef DEBUG
1434 	if (asc_debug > 2)
1435 		printf("asc_resume_out: buflen %d, len %d\n", state->buflen,
1436 			len);
1437 #endif
1438 
1439 	/* check for next chunk */
1440 	state->flags |= DMA_IN_PROGRESS;
1441 	if (len != state->buflen) {
1442 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1443 		readback(regs->asc_cmd);
1444 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1445 		return (0);
1446 	}
1447 	return (1);
1448 }
1449 
1450 /* ARGSUSED */
1451 static int
1452 asc_resume_dma_out(asc, status, ss, ir)
1453 	register asc_softc_t asc;
1454 	register int status, ss, ir;
1455 {
1456 	register asc_regmap_t *regs = asc->regs;
1457 	register State *state = &asc->st[asc->target];
1458 	register int len, off;
1459 
1460 	/* setup to finish writing this chunk */
1461 	len = state->dmaresid;
1462 	off = state->dmalen - len;
1463 	if (off & 1) {
1464 		printf("asc_resume_dma_out: odd xfer dmalen %d len %d off %d\n",
1465 			state->dmalen, len, off); /* XXX */
1466 		regs->asc_fifo = state->dmaBufAddr[off];
1467 		off++;
1468 		len--;
1469 	}
1470 	(*asc->dma_start)(asc, state, state->dmaBufAddr + off, ASCDMA_WRITE);
1471 	ASC_TC_PUT(regs, len);
1472 #ifdef DEBUG
1473 	if (asc_debug > 2)
1474 		printf("asc_resume_dma_out: buflen %d dmalen %d len %d off %d\n",
1475 			state->dmalen, state->buflen, len, off);
1476 #endif
1477 
1478 	/* check for next chunk */
1479 	state->flags |= DMA_IN_PROGRESS;
1480 	if (state->dmalen != state->buflen) {
1481 		regs->asc_cmd = ASC_CMD_XFER_INFO | ASC_CMD_DMA;
1482 		readback(regs->asc_cmd);
1483 		asc->script = &asc_scripts[SCRIPT_CONTINUE_OUT];
1484 		return (0);
1485 	}
1486 	return (1);
1487 }
1488 
1489 /* ARGSUSED */
1490 static int
1491 asc_sendsync(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 
1498 	/* send the extended synchronous negotiation message */
1499 	regs->asc_fifo = SCSI_EXTENDED_MSG;
1500 	MachEmptyWriteBuffer();
1501 	regs->asc_fifo = 3;
1502 	MachEmptyWriteBuffer();
1503 	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1504 	MachEmptyWriteBuffer();
1505 	regs->asc_fifo = SCSI_MIN_PERIOD;
1506 	MachEmptyWriteBuffer();
1507 	regs->asc_fifo = ASC_MAX_OFFSET;
1508 	/* state to resume after we see the sync reply message */
1509 	state->script = asc->script + 2;
1510 	state->msglen = 0;
1511 	return (1);
1512 }
1513 
1514 /* ARGSUSED */
1515 static int
1516 asc_replysync(asc, status, ss, ir)
1517 	register asc_softc_t asc;
1518 	register int status, ss, ir;
1519 {
1520 	register asc_regmap_t *regs = asc->regs;
1521 	register State *state = &asc->st[asc->target];
1522 
1523 #ifdef DEBUG
1524 	if (asc_debug > 2)
1525 		printf("asc_replysync: %x %x\n",
1526 			asc_to_scsi_period[state->sync_period] * asc->tb_ticks,
1527 			state->sync_offset);
1528 #endif
1529 	/* send synchronous transfer in response to a request */
1530 	regs->asc_fifo = SCSI_EXTENDED_MSG;
1531 	MachEmptyWriteBuffer();
1532 	regs->asc_fifo = 3;
1533 	MachEmptyWriteBuffer();
1534 	regs->asc_fifo = SCSI_SYNCHRONOUS_XFER;
1535 	MachEmptyWriteBuffer();
1536 	regs->asc_fifo = asc_to_scsi_period[state->sync_period] * asc->tb_ticks;
1537 	MachEmptyWriteBuffer();
1538 	regs->asc_fifo = state->sync_offset;
1539 	regs->asc_cmd = ASC_CMD_XFER_INFO;
1540 	readback(regs->asc_cmd);
1541 
1542 	/* return to the appropriate script */
1543 	if (!state->script) {
1544 #ifdef DEBUG
1545 		asc_DumpLog("asc_replsync");
1546 #endif
1547 		panic("asc_replysync");
1548 	}
1549 	asc->script = state->script;
1550 	state->script = (script_t *)0;
1551 	return (0);
1552 }
1553 
1554 /* ARGSUSED */
1555 static int
1556 asc_msg_in(asc, status, ss, ir)
1557 	register asc_softc_t asc;
1558 	register int status, ss, ir;
1559 {
1560 	register asc_regmap_t *regs = asc->regs;
1561 	register State *state = &asc->st[asc->target];
1562 	register int msg;
1563 	int i;
1564 
1565 	/* read one message byte */
1566 	msg = regs->asc_fifo;
1567 #ifdef DEBUG
1568 	if (asc_logp == asc_log)
1569 		asc_log[NLOG - 1].msg = msg;
1570 	else
1571 		asc_logp[-1].msg = msg;
1572 #endif
1573 
1574 	/* check for multi-byte message */
1575 	if (state->msglen != 0) {
1576 		/* first byte is the message length */
1577 		if (state->msglen < 0) {
1578 			state->msglen = msg;
1579 			return (1);
1580 		}
1581 		if (state->msgcnt >= state->msglen)
1582 			goto abort;
1583 		state->msg_in[state->msgcnt++] = msg;
1584 
1585 		/* did we just read the last byte of the message? */
1586 		if (state->msgcnt != state->msglen)
1587 			return (1);
1588 
1589 		/* process an extended message */
1590 #ifdef DEBUG
1591 		if (asc_debug > 2)
1592 			printf("asc_msg_in: msg %x %x %x\n",
1593 				state->msg_in[0],
1594 				state->msg_in[1],
1595 				state->msg_in[2]);
1596 #endif
1597 		switch (state->msg_in[0]) {
1598 		case SCSI_SYNCHRONOUS_XFER:
1599 			state->flags |= DID_SYNC;
1600 			state->sync_offset = state->msg_in[2];
1601 
1602 			/* convert SCSI period to ASC period */
1603 			i = state->msg_in[1] / asc->tb_ticks;
1604 			if (i < asc->min_period)
1605 				i = asc->min_period;
1606 			else if (i >= asc->max_period) {
1607 				/* can't do sync transfer, period too long */
1608 				printf("asc%d: SCSI device %d: sync xfer period too long (%d)\n",
1609 					asc - asc_softc, asc->target, i);
1610 				i = asc->max_period;
1611 				state->sync_offset = 0;
1612 			}
1613 			if ((i * asc->tb_ticks) != state->msg_in[1])
1614 				i++;
1615 			state->sync_period = i & 0x1F;
1616 
1617 			/*
1618 			 * If this is a request, check minimums and
1619 			 * send back an acknowledge.
1620 			 */
1621 			if (!(state->flags & TRY_SYNC)) {
1622 				regs->asc_cmd = ASC_CMD_SET_ATN;
1623 				readback(regs->asc_cmd);
1624 
1625 				if (state->sync_period < asc->min_period)
1626 					state->sync_period =
1627 						asc->min_period;
1628 				if (state->sync_offset > ASC_MAX_OFFSET)
1629 					state->sync_offset =
1630 						ASC_MAX_OFFSET;
1631 				asc->script = &asc_scripts[SCRIPT_REPLY_SYNC];
1632 				regs->asc_syn_p = state->sync_period;
1633 				readback(regs->asc_syn_p);
1634 				regs->asc_syn_o = state->sync_offset;
1635 				readback(regs->asc_syn_o);
1636 				regs->asc_cmd = ASC_CMD_MSG_ACPT;
1637 				readback(regs->asc_cmd);
1638 				return (0);
1639 			}
1640 
1641 			regs->asc_syn_p = state->sync_period;
1642 			readback(regs->asc_syn_p);
1643 			regs->asc_syn_o = state->sync_offset;
1644 			readback(regs->asc_syn_o);
1645 			goto done;
1646 
1647 		default:
1648 			printf("asc%d: SCSI device %d: rejecting extended message 0x%x\n",
1649 				asc - asc_softc, asc->target,
1650 				state->msg_in[0]);
1651 			goto reject;
1652 		}
1653 	}
1654 
1655 	/* process first byte of a message */
1656 #ifdef DEBUG
1657 	if (asc_debug > 2)
1658 		printf("asc_msg_in: msg %x\n", msg);
1659 #endif
1660 	switch (msg) {
1661 #if 0
1662 	case SCSI_MESSAGE_REJECT:
1663 		printf(" did not like SYNCH xfer "); /* XXX */
1664 		state->flags |= DID_SYNC;
1665 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
1666 		readback(regs->asc_cmd);
1667 		status = asc_wait(regs, ASC_CSR_INT);
1668 		ir = regs->asc_intr;
1669 		/* some just break out here, some dont */
1670 		if (ASC_PHASE(status) == ASC_PHASE_MSG_OUT) {
1671 			regs->asc_fifo = SCSI_ABORT;
1672 			regs->asc_cmd = ASC_CMD_XFER_INFO;
1673 			readback(regs->asc_cmd);
1674 			status = asc_wait(regs, ASC_CSR_INT);
1675 			ir = regs->asc_intr;
1676 		}
1677 		if (ir & ASC_INT_DISC) {
1678 			asc_end(asc, status, 0, ir);
1679 			return (0);
1680 		}
1681 		goto status;
1682 #endif
1683 
1684 	case SCSI_EXTENDED_MSG: /* read an extended message */
1685 		/* setup to read message length next */
1686 		state->msglen = -1;
1687 		state->msgcnt = 0;
1688 		return (1);
1689 
1690 	case SCSI_NO_OP:
1691 		break;
1692 
1693 	case SCSI_SAVE_DATA_POINTER:
1694 		/* expect another message */
1695 		return (1);
1696 
1697 	case SCSI_RESTORE_POINTERS:
1698 		/*
1699 		 * Need to do the following if resuming synchonous data in
1700 		 * on an odd byte boundary.
1701 		regs->asc_cnfg2 |= ASC_CNFG2_RFB;
1702 		 */
1703 		break;
1704 
1705 	case SCSI_DISCONNECT:
1706 		if (state->flags & DISCONN)
1707 			goto abort;
1708 		state->flags |= DISCONN;
1709 		regs->asc_cmd = ASC_CMD_MSG_ACPT;
1710 		readback(regs->asc_cmd);
1711 		asc->script = &asc_scripts[SCRIPT_DISCONNECT];
1712 		return (0);
1713 
1714 	default:
1715 		printf("asc%d: SCSI device %d: rejecting message 0x%x\n",
1716 			asc - asc_softc, asc->target, msg);
1717 	reject:
1718 		/* request a message out before acknowledging this message */
1719 		state->msg_out = SCSI_MESSAGE_REJECT;
1720 		regs->asc_cmd = ASC_CMD_SET_ATN;
1721 		readback(regs->asc_cmd);
1722 	}
1723 
1724 done:
1725 	/* return to original script */
1726 	regs->asc_cmd = ASC_CMD_MSG_ACPT;
1727 	readback(regs->asc_cmd);
1728 	if (!state->script) {
1729 	abort:
1730 #ifdef DEBUG
1731 		asc_DumpLog("asc_msg_in");
1732 #endif
1733 		panic("asc_msg_in");
1734 	}
1735 	asc->script = state->script;
1736 	state->script = (script_t *)0;
1737 	return (0);
1738 }
1739 
1740 /* ARGSUSED */
1741 static int
1742 asc_disconnect(asc, status, ss, ir)
1743 	register asc_softc_t asc;
1744 	register int status, ss, ir;
1745 {
1746 	register State *state = &asc->st[asc->target];
1747 
1748 #ifdef DIAGNOSTIC
1749 	if (!(state->flags & DISCONN)) {
1750 		printf("asc_disconnect: device %d: DISCONN not set!\n",
1751 			asc->target);
1752 	}
1753 #endif
1754 	asc->target = -1;
1755 	asc->state = ASC_STATE_RESEL;
1756 	return (1);
1757 }
1758 
1759 /*
1760  * DMA handling routines. For a turbochannel device, just set the dmar
1761  * for the I/O ASIC, handle the actual DMA interface.
1762  */
1763 static void
1764 tb_dma_start(asc, state, cp, flag)
1765 	asc_softc_t asc;
1766 	State *state;
1767 	caddr_t cp;
1768 	int flag;
1769 {
1770 
1771 	if (flag == ASCDMA_WRITE)
1772 		*asc->dmar = ASC_DMAR_WRITE | ASC_DMA_ADDR(cp);
1773 	else
1774 		*asc->dmar = ASC_DMA_ADDR(cp);
1775 }
1776 
1777 static void
1778 tb_dma_end(asc, state, flag)
1779 	asc_softc_t asc;
1780 	State *state;
1781 	int flag;
1782 {
1783 
1784 }
1785 
1786 static void
1787 asic_dma_start(asc, state, cp, flag)
1788 	asc_softc_t asc;
1789 	State *state;
1790 	caddr_t cp;
1791 	int flag;
1792 {
1793 	register volatile u_int *ssr = (volatile u_int *)
1794 		ASIC_REG_CSR(asic_base);
1795 	u_int phys, nphys;
1796 
1797 	/* stop DMA engine first */
1798 	*ssr &= ~ASIC_CSR_DMAEN_SCSI;
1799 	*((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0;
1800 
1801 	phys = MACH_CACHED_TO_PHYS(cp);
1802 	cp = (caddr_t)pmax_trunc_page(cp + NBPG);
1803 	nphys = MACH_CACHED_TO_PHYS(cp);
1804 
1805 	asc->dma_next = cp;
1806 	asc->dma_xfer = state->dmalen - (nphys - phys);
1807 
1808 	*(volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base) =
1809 		ASIC_DMA_ADDR(phys);
1810 	*(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) =
1811 		ASIC_DMA_ADDR(nphys);
1812 	if (flag == ASCDMA_READ)
1813 		*ssr |= ASIC_CSR_SCSI_DIR | ASIC_CSR_DMAEN_SCSI;
1814 	else
1815 		*ssr = (*ssr & ~ASIC_CSR_SCSI_DIR) | ASIC_CSR_DMAEN_SCSI;
1816 	MachEmptyWriteBuffer();
1817 }
1818 
1819 static void
1820 asic_dma_end(asc, state, flag)
1821 	asc_softc_t asc;
1822 	State *state;
1823 	int flag;
1824 {
1825 	register volatile u_int *ssr = (volatile u_int *)
1826 		ASIC_REG_CSR(asic_base);
1827 	int nb;
1828 
1829 	*ssr &= ~ASIC_CSR_DMAEN_SCSI;
1830 	*((volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base)) = -1;
1831 	*((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1;
1832 	MachEmptyWriteBuffer();
1833 
1834 	if (flag == ASCDMA_READ) {
1835 		MachFlushDCache(MACH_PHYS_TO_CACHED(
1836 		    MACH_UNCACHED_TO_PHYS(state->dmaBufAddr)), state->dmalen);
1837 		if (nb = *((int *)ASIC_REG_SCSI_SCR(asic_base))) {
1838 			/* pick up last upto6 bytes, sigh. */
1839 			register u_short *to;
1840 			register int w;
1841 
1842 			/* Last byte really xferred is.. */
1843 			to = (u_short *)(state->dmaBufAddr + state->dmalen - (nb << 1));
1844 			w = *(int *)ASIC_REG_SCSI_SDR0(asic_base);
1845 			*to++ = w;
1846 			if (--nb > 0) {
1847 				w >>= 16;
1848 				*to++ = w;
1849 			}
1850 			if (--nb > 0) {
1851 				w = *(int *)ASIC_REG_SCSI_SDR1(asic_base);
1852 				*to++ = w;
1853 			}
1854 		}
1855 	}
1856 }
1857 
1858 #ifdef notdef
1859 /*
1860  * Called by asic_intr() for scsi dma pointer update interrupts.
1861  */
1862 void
1863 asc_dma_intr()
1864 {
1865 	asc_softc_t asc = &asc_softc[0];
1866 	u_int next_phys;
1867 
1868 	asc->dma_xfer -= NBPG;
1869 	if (asc->dma_xfer <= -NBPG) {
1870 		volatile u_int *ssr = (volatile u_int *)
1871 			ASIC_REG_CSR(asic_base);
1872 		*ssr &= ~ASIC_CSR_DMAEN_SCSI;
1873 	} else {
1874 		asc->dma_next += NBPG;
1875 		next_phys = MACH_CACHED_TO_PHYS(asc->dma_next);
1876 	}
1877 	*(volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base) =
1878 		ASIC_DMA_ADDR(next_phys);
1879 	MachEmptyWriteBuffer();
1880 }
1881 #endif
1882 
1883 #ifdef DEBUG
1884 asc_DumpLog(str)
1885 	char *str;
1886 {
1887 	register struct asc_log *lp;
1888 	register u_int status;
1889 
1890 	printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
1891 		asc_debug_bn, asc_debug_sz);
1892 	lp = asc_logp;
1893 	do {
1894 		status = lp->status;
1895 		printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n",
1896 			status >> 24,
1897 			lp->target,
1898 			(status >> 16) & 0xFF,
1899 			(status >> 8) & 0xFF,
1900 			status & 0XFF,
1901 			lp->state,
1902 			asc_scripts[lp->state].condition,
1903 			lp->msg, lp->resid);
1904 		if (++lp >= &asc_log[NLOG])
1905 			lp = asc_log;
1906 	} while (lp != asc_logp);
1907 }
1908 #endif
1909 
1910 #endif	/* NASC > 0 */
1911