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