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