xref: /netbsd-src/sys/arch/amiga/dev/sci.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /*	$NetBSD: sci.c,v 1.33 2005/11/26 13:54:18 tsutsui Exp $ */
2 
3 /*
4  * Copyright (c) 1990 The Regents of the University of California.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Van Jacobson of Lawrence Berkeley Laboratory.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  *	@(#)scsi.c	7.5 (Berkeley) 5/4/91
35  */
36 
37 /*
38  * Copyright (c) 1994 Michael L. Hitch
39  *
40  * This code is derived from software contributed to Berkeley by
41  * Van Jacobson of Lawrence Berkeley Laboratory.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  *
63  *	@(#)scsi.c	7.5 (Berkeley) 5/4/91
64  */
65 
66 /*
67  * AMIGA NCR 5380 scsi adaptor driver
68  */
69 
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: sci.c,v 1.33 2005/11/26 13:54:18 tsutsui Exp $");
72 
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/device.h>
76 #include <sys/disklabel.h>
77 #include <sys/buf.h>
78 #include <dev/scsipi/scsi_all.h>
79 #include <dev/scsipi/scsipi_all.h>
80 #include <dev/scsipi/scsiconf.h>
81 #include <uvm/uvm_extern.h>
82 #include <machine/pmap.h>
83 #include <machine/cpu.h>
84 #include <amiga/amiga/device.h>
85 #include <amiga/amiga/custom.h>
86 #include <amiga/amiga/isr.h>
87 #include <amiga/dev/scireg.h>
88 #include <amiga/dev/scivar.h>
89 
90 /*
91  * SCSI delays
92  * In u-seconds, primarily for state changes on the SPC.
93  */
94 #define	SCI_CMD_WAIT	50000	/* wait per step of 'immediate' cmds */
95 #define	SCI_DATA_WAIT	50000	/* wait per data in/out step */
96 #define	SCI_INIT_WAIT	50000	/* wait per step (both) during init */
97 
98 int  sciicmd(struct sci_softc *, int, void *, int, void *, int,u_char);
99 int  scigo(struct sci_softc *, struct scsipi_xfer *);
100 int  sciselectbus(struct sci_softc *, u_char, u_char);
101 void sciabort(struct sci_softc *, const char *);
102 void scierror(struct sci_softc *, u_char);
103 void scisetdelay(int);
104 void sci_scsidone(struct sci_softc *, int);
105 void sci_donextcmd(struct sci_softc *);
106 int  sci_ixfer_out(struct sci_softc *, int, register u_char *, int);
107 void sci_ixfer_in(struct sci_softc *, int, register u_char *, int);
108 
109 int sci_cmd_wait = SCI_CMD_WAIT;
110 int sci_data_wait = SCI_DATA_WAIT;
111 int sci_init_wait = SCI_INIT_WAIT;
112 
113 int sci_no_dma = 0;
114 
115 #ifdef DEBUG
116 #define QPRINTF(a) if (sci_debug > 1) printf a
117 int	sci_debug = 0;
118 #else
119 #define QPRINTF(a)
120 #endif
121 
122 /*
123  * default minphys routine for sci based controllers
124  */
125 void
126 sci_minphys(struct buf *bp)
127 {
128 
129 	/*
130 	 * No max transfer at this level.
131 	 */
132 	minphys(bp);
133 }
134 
135 /*
136  * used by specific sci controller
137  *
138  * it appears that the higher level code does nothing with LUN's
139  * so I will too.  I could plug it in, however so could they
140  * in scsi_scsipi_cmd().
141  */
142 void
143 sci_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
144                    void *arg)
145 {
146 	struct scsipi_xfer *xs;
147 	struct scsipi_periph *periph;
148 	struct sci_softc *dev = (void *)chan->chan_adapter->adapt_dev;
149 	int flags, s;
150 
151 	switch (req) {
152 	case ADAPTER_REQ_RUN_XFER:
153 		xs = arg;
154 		periph = xs->xs_periph;
155 		flags = xs->xs_control;
156 
157 		if (flags & XS_CTL_DATA_UIO)
158 		panic("sci: scsi data uio requested");
159 
160 		s = splbio();
161 
162 		if (dev->sc_xs && flags & XS_CTL_POLL)
163 			panic("sci_scsicmd: busy");
164 
165 #ifdef DIAGNOSTIC
166 		/*
167 		 * This should never happen as we track the resources
168 		 * in the mid-layer.
169 		 */
170 		if (dev->sc_xs) {
171 			scsipi_printaddr(periph);
172 			printf("unable to allocate scb\n");
173 			panic("sea_scsipi_request");
174 		}
175 #endif
176 
177 		dev->sc_xs = xs;
178 		splx(s);
179 
180 		/*
181 		 * nothing is pending do it now.
182 		 */
183 		sci_donextcmd(dev);
184 
185 		return;
186 
187 	case ADAPTER_REQ_GROW_RESOURCES:
188 		return;
189 
190 	case ADAPTER_REQ_SET_XFER_MODE:
191 		return;
192 	}
193 }
194 
195 /*
196  * entered with dev->sc_xs pointing to the next xfer to perform
197  */
198 void
199 sci_donextcmd(struct sci_softc *dev)
200 {
201 	struct scsipi_xfer *xs;
202 	struct scsipi_periph *periph;
203 	int flags, phase, stat;
204 
205 	xs = dev->sc_xs;
206 	periph = xs->xs_periph;
207 	flags = xs->xs_control;
208 
209 	if (flags & XS_CTL_DATA_IN)
210 		phase = DATA_IN_PHASE;
211 	else if (flags & XS_CTL_DATA_OUT)
212 		phase = DATA_OUT_PHASE;
213 	else
214 		phase = STATUS_PHASE;
215 
216 	if (flags & XS_CTL_RESET)
217 		scireset(dev);
218 
219 	dev->sc_stat[0] = -1;
220 	xs->cmd->bytes[0] |= periph->periph_lun << 5;
221 	if (phase == STATUS_PHASE || flags & XS_CTL_POLL)
222 		stat = sciicmd(dev, periph->periph_target, xs->cmd, xs->cmdlen,
223 		    xs->data, xs->datalen, phase);
224 	else if (scigo(dev, xs) == 0)
225 		return;
226 	else
227 		stat = dev->sc_stat[0];
228 
229 	sci_scsidone(dev, stat);
230 }
231 
232 void
233 sci_scsidone(struct sci_softc *dev, int stat)
234 {
235 	struct scsipi_xfer *xs;
236 
237 	xs = dev->sc_xs;
238 #ifdef DIAGNOSTIC
239 	if (xs == NULL)
240 		panic("sci_scsidone");
241 #endif
242 	xs->status = stat;
243 	if (stat == 0)
244 		xs->resid = 0;
245 	else {
246 		switch(stat) {
247 		case SCSI_CHECK:
248 			xs->resid = 0;
249 			/* FALLTHROUGH */
250 		case SCSI_BUSY:
251 			xs->error = XS_BUSY;
252 			break;
253 		default:
254 			xs->error = XS_DRIVER_STUFFUP;
255 			QPRINTF(("sci_scsicmd() bad %x\n", stat));
256 			break;
257 		}
258 	}
259 
260 	scsipi_done(xs);
261 
262 }
263 
264 void
265 sciabort(struct sci_softc *dev, const char *where)
266 {
267 	printf ("%s: abort %s: csr = 0x%02x, bus = 0x%02x\n",
268 	  dev->sc_dev.dv_xname, where, *dev->sci_csr, *dev->sci_bus_csr);
269 
270 	if (dev->sc_flags & SCI_SELECTED) {
271 
272 		/* lets just hope it worked.. */
273 		dev->sc_flags &= ~SCI_SELECTED;
274 		/* XXX */
275 		scireset (dev);
276 	}
277 }
278 
279 /*
280  * XXX Set/reset long delays.
281  *
282  * if delay == 0, reset default delays
283  * if delay < 0,  set both delays to default long initialization values
284  * if delay > 0,  set both delays to this value
285  *
286  * Used when a devices is expected to respond slowly (e.g. during
287  * initialization).
288  */
289 void
290 scisetdelay(int del)
291 {
292 	static int saved_cmd_wait, saved_data_wait;
293 
294 	if (del) {
295 		saved_cmd_wait = sci_cmd_wait;
296 		saved_data_wait = sci_data_wait;
297 		if (del > 0)
298 			sci_cmd_wait = sci_data_wait = del;
299 		else
300 			sci_cmd_wait = sci_data_wait = sci_init_wait;
301 	} else {
302 		sci_cmd_wait = saved_cmd_wait;
303 		sci_data_wait = saved_data_wait;
304 	}
305 }
306 
307 void
308 scireset(struct sci_softc *dev)
309 {
310 	u_int s;
311 	u_char my_id;
312 
313 	dev->sc_flags &= ~SCI_SELECTED;
314 	if (dev->sc_flags & SCI_ALIVE)
315 		sciabort(dev, "reset");
316 
317 	printf("%s: ", dev->sc_dev.dv_xname);
318 
319 	s = splbio();
320 	/* preserve our ID for now */
321 	my_id = 7;
322 
323 	/*
324 	 * Reset the chip
325 	 */
326 	*dev->sci_icmd = SCI_ICMD_TEST;
327 	*dev->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST;
328 	delay (25);
329 	*dev->sci_icmd = 0;
330 
331 	/*
332 	 * Set up various chip parameters
333 	 */
334 	*dev->sci_icmd = 0;
335 	*dev->sci_tcmd = 0;
336 	*dev->sci_sel_enb = 0;
337 
338 	/* anything else was zeroed by reset */
339 
340 	splx (s);
341 
342 	printf("sci id %d\n", my_id);
343 	dev->sc_flags |= SCI_ALIVE;
344 }
345 
346 void
347 scierror(struct sci_softc *dev, u_char csr)
348 {
349 	struct scsipi_xfer *xs;
350 
351 	xs = dev->sc_xs;
352 
353 #ifdef DIAGNOSTIC
354 	if (xs == NULL)
355 		panic("scierror");
356 #endif
357 	if (xs->xs_control & XS_CTL_SILENT)
358 		return;
359 
360 	printf("%s: ", dev->sc_dev.dv_xname);
361 	printf("csr == 0x%02i\n", csr);	/* XXX */
362 }
363 
364 /*
365  * select the bus, return when selected or error.
366  */
367 int
368 sciselectbus(struct sci_softc *dev, u_char target, u_char our_addr)
369 {
370 	register int timeo = 2500;
371 
372 	QPRINTF (("sciselectbus %d\n", target));
373 
374 	/* if we're already selected, return */
375 	if (dev->sc_flags & SCI_SELECTED)	/* XXXX */
376 		return 1;
377 
378 	if ((*dev->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
379 	    (*dev->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
380 	    (*dev->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)))
381 		return 1;
382 
383 	*dev->sci_tcmd = 0;
384 	*dev->sci_odata = 0x80 + (1 << target);
385 	*dev->sci_icmd = SCI_ICMD_DATA|SCI_ICMD_SEL;
386 	while ((*dev->sci_bus_csr & SCI_BUS_BSY) == 0) {
387 		if (--timeo > 0) {
388 			delay(100);
389 		} else {
390 			break;
391 		}
392 	}
393 	if (timeo) {
394 		*dev->sci_icmd = 0;
395 		dev->sc_flags |= SCI_SELECTED;
396 		return (0);
397 	}
398 	*dev->sci_icmd = 0;
399 	return (1);
400 }
401 
402 int
403 sci_ixfer_out(register struct sci_softc *dev, int len, register u_char *buf,
404               int phase)
405 {
406 	register int wait = sci_data_wait;
407 	u_char csr;
408 
409 	QPRINTF(("sci_ixfer_out {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
410 	  len, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
411 	  buf[6], buf[7], buf[8], buf[9]));
412 
413 	*dev->sci_tcmd = phase;
414 	*dev->sci_icmd = SCI_ICMD_DATA;
415 	for (;len > 0; len--) {
416 		csr = *dev->sci_bus_csr;
417 		while (!(csr & SCI_BUS_REQ)) {
418 			if ((csr & SCI_BUS_BSY) == 0 || --wait < 0) {
419 #ifdef DEBUG
420 				if (sci_debug)
421 					printf("sci_ixfer_out fail: l%d i%x w%d\n",
422 					  len, csr, wait);
423 #endif
424 				return (len);
425 			}
426 			delay(1);
427 			csr = *dev->sci_bus_csr;
428 		}
429 
430 		if (!(*dev->sci_csr & SCI_CSR_PHASE_MATCH))
431 			break;
432 		*dev->sci_odata = *buf;
433 		*dev->sci_icmd = SCI_ICMD_DATA|SCI_ICMD_ACK;
434 		buf++;
435 		while (*dev->sci_bus_csr & SCI_BUS_REQ);
436 		*dev->sci_icmd = SCI_ICMD_DATA;
437 	}
438 
439 	QPRINTF(("sci_ixfer_out done\n"));
440 	return (0);
441 }
442 
443 void
444 sci_ixfer_in(struct sci_softc *dev, int len, register u_char *buf, int phase)
445 {
446 	int wait = sci_data_wait;
447 	u_char csr;
448 	volatile register u_char *sci_bus_csr = dev->sci_bus_csr;
449 	volatile register u_char *sci_data = dev->sci_data;
450 	volatile register u_char *sci_icmd = dev->sci_icmd;
451 #ifdef DEBUG
452 	u_char *obp = buf;
453 #endif
454 
455 	csr = *sci_bus_csr;
456 
457 	QPRINTF(("sci_ixfer_in %d, csr=%02x\n", len, csr));
458 
459 	*dev->sci_tcmd = phase;
460 	*sci_icmd = 0;
461 	for (;len > 0; len--) {
462 		csr = *sci_bus_csr;
463 		while (!(csr & SCI_BUS_REQ)) {
464 			if (!(csr & SCI_BUS_BSY) || --wait < 0) {
465 #ifdef DEBUG
466 				if (sci_debug)
467 					printf("sci_ixfer_in fail: l%d i%x w%d\n",
468 					len, csr, wait);
469 #endif
470 				return;
471 			}
472 
473 			delay(1);
474 			csr = *sci_bus_csr;
475 		}
476 
477 		if (!(*dev->sci_csr & SCI_CSR_PHASE_MATCH))
478 			break;
479 		*buf = *sci_data;
480 		*sci_icmd = SCI_ICMD_ACK;
481 		buf++;
482 		while (*sci_bus_csr & SCI_BUS_REQ);
483 		*sci_icmd = 0;
484 	}
485 
486 	QPRINTF(("sci_ixfer_in {%d} %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
487 	  len, obp[0], obp[1], obp[2], obp[3], obp[4], obp[5],
488 	  obp[6], obp[7], obp[8], obp[9]));
489 }
490 
491 /*
492  * SCSI 'immediate' command:  issue a command to some SCSI device
493  * and get back an 'immediate' response (i.e., do programmed xfer
494  * to get the response data).  'cbuf' is a buffer containing a scsi
495  * command of length clen bytes.  'buf' is a buffer of length 'len'
496  * bytes for data.  The transfer direction is determined by the device
497  * (i.e., by the scsi bus data xfer phase).  If 'len' is zero, the
498  * command must supply no data.  'xferphase' is the bus phase the
499  * caller expects to happen after the command is issued.  It should
500  * be one of DATA_IN_PHASE, DATA_OUT_PHASE or STATUS_PHASE.
501  */
502 int
503 sciicmd(struct sci_softc *dev, int target, void *cbuf, int clen, void *buf,
504         int len, u_char xferphase)
505 {
506 	u_char phase;
507 	register int wait;
508 
509 	/* select the SCSI bus (it's an error if bus isn't free) */
510 	if (sciselectbus (dev, target, dev->sc_scsi_addr))
511 		return -1;
512 	/*
513 	 * Wait for a phase change (or error) then let the device
514 	 * sequence us through the various SCSI phases.
515 	 */
516 	dev->sc_stat[0] = 0xff;
517 	dev->sc_msg[0] = 0xff;
518 	phase = CMD_PHASE;
519 	while (1) {
520 		wait = sci_cmd_wait;
521 
522 		while ((*dev->sci_bus_csr & (SCI_BUS_REQ|SCI_BUS_BSY)) == SCI_BUS_BSY);
523 
524 		QPRINTF((">CSR:%02x<", *dev->sci_bus_csr));
525 		if ((*dev->sci_bus_csr & SCI_BUS_REQ) == 0) {
526 			return -1;
527 		}
528 		phase = SCI_PHASE(*dev->sci_bus_csr);
529 
530 		switch (phase) {
531 		case CMD_PHASE:
532 			if (sci_ixfer_out (dev, clen, cbuf, phase))
533 				goto abort;
534 			phase = xferphase;
535 			break;
536 
537 		case DATA_IN_PHASE:
538 			if (len <= 0)
539 				goto abort;
540 			wait = sci_data_wait;
541 			sci_ixfer_in (dev, len, buf, phase);
542 			phase = STATUS_PHASE;
543 			break;
544 
545 		case DATA_OUT_PHASE:
546 			if (len <= 0)
547 				goto abort;
548 			wait = sci_data_wait;
549 			if (sci_ixfer_out (dev, len, buf, phase))
550 				goto abort;
551 			phase = STATUS_PHASE;
552 			break;
553 
554 		case MESG_IN_PHASE:
555 			dev->sc_msg[0] = 0xff;
556 			sci_ixfer_in (dev, 1, dev->sc_msg,phase);
557 			dev->sc_flags &= ~SCI_SELECTED;
558 			while (*dev->sci_bus_csr & SCI_BUS_BSY);
559 			goto out;
560 			break;
561 
562 		case MESG_OUT_PHASE:
563 			phase = STATUS_PHASE;
564 			break;
565 
566 		case STATUS_PHASE:
567 			sci_ixfer_in (dev, 1, dev->sc_stat, phase);
568 			phase = MESG_IN_PHASE;
569 			break;
570 
571 		case BUS_FREE_PHASE:
572 			goto out;
573 
574 		default:
575 		printf("sci: unexpected phase %d in icmd from %d\n",
576 		  phase, target);
577 		goto abort;
578 		}
579 #if 0
580 		if (wait <= 0)
581 			goto abort;
582 #endif
583 	}
584 
585 abort:
586 	sciabort(dev, "icmd");
587 out:
588 	QPRINTF(("=STS:%02x=", dev->sc_stat[0]));
589 	return (dev->sc_stat[0]);
590 }
591 
592 int
593 scigo(struct sci_softc *dev, struct scsipi_xfer *xs)
594 {
595 	int count, target;
596 	u_char phase, *addr;
597 
598 	target = xs->xs_periph->periph_target;
599 	count = xs->datalen;
600 	addr = xs->data;
601 
602 	if (sci_no_dma)	{
603 		sciicmd (dev, target, (u_char *) xs->cmd, xs->cmdlen,
604 		  addr, count,
605 		  xs->xs_control & XS_CTL_DATA_IN ? DATA_IN_PHASE : DATA_OUT_PHASE);
606 
607 		return (1);
608 	}
609 
610 	/* select the SCSI bus (it's an error if bus isn't free) */
611 	if (sciselectbus (dev, target, dev->sc_scsi_addr))
612 		return -1;
613 	/*
614 	 * Wait for a phase change (or error) then let the device
615 	 * sequence us through the various SCSI phases.
616 	 */
617 	dev->sc_stat[0] = 0xff;
618 	dev->sc_msg[0] = 0xff;
619 	phase = CMD_PHASE;
620 	while (1) {
621 		while ((*dev->sci_bus_csr & (SCI_BUS_REQ|SCI_BUS_BSY)) ==
622 		  SCI_BUS_BSY);
623 
624 		QPRINTF((">CSR:%02x<", *dev->sci_bus_csr));
625 		if ((*dev->sci_bus_csr & SCI_BUS_REQ) == 0) {
626 			goto abort;
627 		}
628 		phase = SCI_PHASE(*dev->sci_bus_csr);
629 
630 		switch (phase) {
631 		case CMD_PHASE:
632 			if (sci_ixfer_out (dev, xs->cmdlen, (u_char *) xs->cmd, phase))
633 				goto abort;
634 			phase = xs->xs_control & XS_CTL_DATA_IN ? DATA_IN_PHASE : DATA_OUT_PHASE;
635 			break;
636 
637 		case DATA_IN_PHASE:
638 			if (count <= 0)
639 				goto abort;
640 			/* XXX use psuedo DMA if available */
641 			if (count >= 128 && dev->dma_xfer_in)
642 				(*dev->dma_xfer_in)(dev, count, addr, phase);
643 			else
644 				sci_ixfer_in (dev, count, addr, phase);
645 			phase = STATUS_PHASE;
646 			break;
647 
648 		case DATA_OUT_PHASE:
649 			if (count <= 0)
650 				goto abort;
651 			/* XXX use psuedo DMA if available */
652 			if (count >= 128 && dev->dma_xfer_out)
653 				(*dev->dma_xfer_out)(dev, count, addr, phase);
654 			else
655 				if (sci_ixfer_out (dev, count, addr, phase))
656 					goto abort;
657 			phase = STATUS_PHASE;
658 			break;
659 
660 		case MESG_IN_PHASE:
661 			dev->sc_msg[0] = 0xff;
662 			sci_ixfer_in (dev, 1, dev->sc_msg,phase);
663 			dev->sc_flags &= ~SCI_SELECTED;
664 			while (*dev->sci_bus_csr & SCI_BUS_BSY);
665 			goto out;
666 			break;
667 
668 		case MESG_OUT_PHASE:
669 			phase = STATUS_PHASE;
670 			break;
671 
672 		case STATUS_PHASE:
673 			sci_ixfer_in (dev, 1, dev->sc_stat, phase);
674 			phase = MESG_IN_PHASE;
675 			break;
676 
677 		case BUS_FREE_PHASE:
678 			goto out;
679 
680 		default:
681 		printf("sci: unexpected phase %d in icmd from %d\n",
682 		  phase, target);
683 		goto abort;
684 		}
685 	}
686 
687 abort:
688 	sciabort(dev, "go");
689 out:
690 	QPRINTF(("=STS:%02x=", dev->sc_stat[0]));
691 	return (1);
692 }
693