xref: /netbsd-src/sys/arch/sun3/dev/si.c (revision edfa83365254b6d7c6cdaa0d30b214319daeee7f)
1 /*	$NetBSD: si.c,v 1.14 1995/01/24 05:55:50 gwr Exp $	*/
2 
3 /*
4  * Copyright (C) 1994 Adam Glass, Gordon W. Ross
5  * Copyright (C) 1993	Allen K. Briggs, Chris P. Caputo,
6  *			Michael L. Finch, Bradley A. Grantham, and
7  *			Lawrence A. Kesteloot
8  * All rights reserved.
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. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the Alice Group.
21  * 4. The names of the Alice Group or any of its members may not be used
22  *    to endorse or promote products derived from this software without
23  *    specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE ALICE GROUP ``AS IS'' AND ANY EXPRESS OR
26  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28  * IN NO EVENT SHALL THE ALICE GROUP BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #define DEBUG 1
38 
39 /* XXX - Need to add support for real DMA. -gwr */
40 /* #define PSEUDO_DMA 1 (broken) */
41 
42 #include <sys/types.h>
43 #include <sys/malloc.h>
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/errno.h>
47 #include <sys/buf.h>
48 #include <sys/proc.h>
49 #include <sys/user.h>
50 #include <sys/device.h>
51 
52 #include <machine/autoconf.h>
53 #include <machine/isr.h>
54 #include <machine/obio.h>
55 
56 #include <scsi/scsi_all.h>
57 #include <scsi/scsi_debug.h>
58 #include <scsi/scsiconf.h>
59 
60 #include "scsi_defs.h"
61 #include "scsi_5380.h"
62 #include "scsi_sunsi.h"
63 
64 #ifdef	DEBUG
65 static int si_debug = 0;
66 static int si_flags = 0 /* | SDEV_DB2 */ ;
67 #endif
68 
69 #define SCI_PHASE_DISC		0	/* sort of ... */
70 #define SCI_CLR_INTR(regs)	((volatile)(regs->sci_iack))
71 #define SCI_ACK(ptr,phase)	(ptr)->sci_tcmd = (phase)
72 #define SCSI_TIMEOUT_VAL	10000000
73 #define WAIT_FOR_NOT_REQ(ptr) {	\
74 	int scsi_timeout = SCSI_TIMEOUT_VAL; \
75 	while ( ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
76 		 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
77 		 ((ptr)->sci_bus_csr & SCI_BUS_REQ) && \
78 		 (--scsi_timeout) ); \
79 	if (!scsi_timeout) { \
80 		printf("scsi timeout--WAIT_FOR_NOT_REQ---%s, line %d.\n", \
81 			__FILE__, __LINE__); \
82 		goto scsi_timeout_error; \
83 	} \
84 	}
85 #define WAIT_FOR_REQ(ptr) {	\
86 	int scsi_timeout = SCSI_TIMEOUT_VAL; \
87 	while ( (((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
88 		(((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
89 		(((ptr)->sci_bus_csr & SCI_BUS_REQ) == 0) && \
90 		 (--scsi_timeout) ); \
91 	if (!scsi_timeout) { \
92 		printf("scsi timeout--WAIT_FOR_REQ---%s, line %d.\n", \
93 			__FILE__, __LINE__); \
94 		goto scsi_timeout_error; \
95 	} \
96 	}
97 #define WAIT_FOR_BSY(ptr) {	\
98 	int scsi_timeout = SCSI_TIMEOUT_VAL; \
99 	while ( (((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
100 		(((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
101 		(((ptr)->sci_bus_csr & SCI_BUS_BSY) == 0) && \
102 		 (--scsi_timeout) ); \
103 	if (!scsi_timeout) { \
104 		printf("scsi timeout--WAIT_FOR_BSY---%s, line %d.\n", \
105 			__FILE__, __LINE__); \
106 		goto scsi_timeout_error; \
107 	} \
108 	}
109 
110 #define ARBITRATION_RETRIES 1000
111 
112 #ifdef DDB
113 int Debugger();
114 #else
115 #define Debugger() panic("Should call Debugger here %s:%d", \
116 			 __FILE__, __LINE__)
117 #endif
118 
119 struct ncr5380_softc {
120     struct device sc_dev;
121     volatile void *sc_regs;
122     int sc_adapter_type;
123     struct scsi_link sc_link;
124 };
125 
126 static void		ncr5380_minphys(struct buf *bp);
127 static int		ncr5380_scsi_cmd(struct scsi_xfer *xs);
128 static int		ncr5380_reset_adapter(struct ncr5380_softc *);
129 static int		ncr5380_reset_scsibus(struct ncr5380_softc *);
130 static int		ncr5380_poll(int adapter, int timeout);
131 static int		ncr5380_send_cmd(struct scsi_xfer *xs);
132 
133 static int		ncr_intr(void *);
134 
135 static int	si_generic(int adapter, int id, int lun,
136 			 struct scsi_generic *cmd, int cmdlen,
137 			 void *databuf, int datalen);
138 static int	si_group0(int adapter, int id, int lun,
139 			    int opcode, int addr, int len,
140 			    int flags, caddr_t databuf, int datalen);
141 
142 static char scsi_name[] = "si";
143 
144 struct scsi_adapter	ncr5380_switch = {
145 	ncr5380_scsi_cmd,		/* scsi_cmd()		*/
146 	ncr5380_minphys,		/* scsi_minphys()	*/
147 	NULL,				/* open_target_lu()	*/
148 	NULL,				/* close_target_lu()	*/
149 };
150 
151 /* This is copied from julian's bt driver */
152 /* "so we have a default dev struct for our link struct." */
153 struct scsi_device ncr_dev = {
154 	NULL,		/* Use default error handler.	    */
155 	NULL,		/* Use default start handler.		*/
156 	NULL,		/* Use default async handler.	    */
157 	NULL,		/* Use default "done" routine.	    */
158 };
159 
160 static int	si_match();
161 static void	si_attach();
162 
163 struct cfdriver sicd = {
164 	NULL, "si", si_match, si_attach, DV_DULL,
165 	sizeof(struct ncr5380_softc), NULL, 0,
166 };
167 
168 static int
169 si_print(aux, name)
170 	void *aux;
171 	char *name;
172 {
173 }
174 
175 static int
176 si_match(parent, vcf, args)
177 	struct device	*parent;
178 	void		*vcf, *args;
179 {
180 	struct cfdata	*cf = vcf;
181 	struct confargs *ca = args;
182 	int x;
183 
184 	/* Allow default address for OBIO only. */
185 	switch (ca->ca_bustype) {
186 	case BUS_OBIO:
187 		if (ca->ca_paddr == -1)
188 			ca->ca_paddr = OBIO_NCR_SCSI;
189 		break;
190 	case BUS_VME16:
191 		if (ca->ca_paddr == -1)
192 			return (0);
193 		break;
194 	default:
195 		return (0);
196 	}
197 
198 	/* Default interrupt priority always splbio==2 */
199 	if (ca->ca_intpri == -1)
200 		ca->ca_intpri = 2;
201 
202 	x = bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1);
203     return (x != -1);
204 }
205 
206 static void
207 si_attach(parent, self, args)
208 	struct device	*parent, *self;
209 	void		*args;
210 {
211 	struct ncr5380_softc *ncr5380 = (struct ncr5380_softc *) self;
212 	volatile sci_regmap_t *regs;
213 	struct confargs *ca = args;
214 
215 	switch (ca->ca_bustype) {
216 
217 	case BUS_OBIO:
218 		regs = (sci_regmap_t *)
219 			obio_alloc(ca->ca_paddr, sizeof(*regs));
220 		isr_add_autovect(ncr_intr, (void *)ncr5380,
221 						 ca->ca_intpri);
222 		break;
223 
224 	case BUS_VME16:
225 		regs = (sci_regmap_t *)
226 			bus_mapin(ca->ca_bustype, ca->ca_paddr, sizeof(*regs));
227 		isr_add_vectored(ncr_intr, (void *)ncr5380,
228 						 ca->ca_intpri, ca->ca_intvec);
229 		break;
230 
231 	default:
232 		printf("unknown\n");
233 		return;
234 	}
235 
236 	ncr5380->sc_adapter_type = ca->ca_bustype;
237 	ncr5380->sc_regs = regs;
238 
239 	/*
240 	 * fill in the prototype scsi_link.
241 	 */
242     ncr5380->sc_link.adapter_softc = ncr5380;
243     ncr5380->sc_link.adapter_target = 7;
244     ncr5380->sc_link.adapter = &ncr5380_switch;
245     ncr5380->sc_link.device = &ncr_dev;
246     ncr5380->sc_link.openings = 2;
247 #ifdef	DEBUG
248     ncr5380->sc_link.flags |= si_flags;
249 #endif
250 
251     printf("\n");
252 	ncr5380_reset_adapter(ncr5380);
253 	ncr5380_reset_scsibus(ncr5380);
254 	config_found(self, &(ncr5380->sc_link), si_print);
255 }
256 
257 #define MIN_PHYS	65536	/*BARF!!!!*/
258 static void
259 ncr5380_minphys(struct buf *bp)
260 {
261 	if (bp->b_bcount > MIN_PHYS) {
262 		printf("Uh-oh...  ncr5380_minphys setting bp->b_bcount = %x.\n", MIN_PHYS);
263 		bp->b_bcount = MIN_PHYS;
264 	}
265 }
266 #undef MIN_PHYS
267 
268 static int
269 ncr5380_scsi_cmd(struct scsi_xfer *xs)
270 {
271 	int flags, s, r;
272 
273 	flags = xs->flags;
274 	if (xs->bp) flags |= (SCSI_NOSLEEP);
275 	if ( flags & ITSDONE ) {
276 		printf("Already done?");
277 		xs->flags &= ~ITSDONE;
278 	}
279 	if ( ! ( flags & INUSE ) ) {
280 		printf("Not in use?");
281 		xs->flags |= INUSE;
282 	}
283 
284 	/* At autoconfig time, do NOT lower the spl! */
285 	if ((flags & SCSI_POLL) == 0)
286 		s = splbio();
287 
288 	if ( flags & SCSI_RESET ) {
289 		printf("flags & SCSIRESET.\n");
290 		ncr5380_reset_scsibus(xs->sc_link->adapter_softc);
291 		r = COMPLETE;
292 	} else {
293 		r = ncr5380_send_cmd(xs);
294 		xs->flags |= ITSDONE;
295 		scsi_done(xs);
296 	}
297 
298 	if ((flags & SCSI_POLL) == 0)
299 		splx(s);
300 
301 	switch(r) {
302 	case COMPLETE:
303 	case SUCCESSFULLY_QUEUED:
304 		r = SUCCESSFULLY_QUEUED;
305 		if (xs->flags & SCSI_POLL)
306 			r = COMPLETE;
307 		break;
308 	default:
309 		break;
310 	}
311 	return r;
312 }
313 
314 #ifdef	DEBUG
315 static int
316 ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
317 {
318 	u_char	*b = (u_char *) xs->cmd;
319 	int	i  = 0;
320 
321 	if ( ! ( xs->flags & SCSI_RESET ) ) {
322 		printf("si(%d:%d:%d)-",
323 			   xs->sc_link->scsibus,
324 			   xs->sc_link->target,
325 			   xs->sc_link->lun);
326 		while (i < xs->cmdlen) {
327 			if (i) printf(",");
328 			printf("%x",b[i++]);
329 		}
330 		printf("-\n");
331 	} else {
332 		printf("si(%d:%d:%d)-RESET-\n",
333 			   xs->sc_link->scsibus,
334 			   xs->sc_link->target,
335 			   xs->sc_link->lun);
336 	}
337 }
338 #endif
339 
340 /*
341  * Actual chip control.
342  */
343 
344 static void
345 ncr_sbc_intr(struct ncr5380_softc *ncr5380)
346 {
347 	volatile sci_regmap_t *regs = ncr5380->sc_regs;
348 
349 	if ((regs->sci_csr & SCI_CSR_INT) == 0) {
350 #ifdef	DEBUG
351 		printf (" ncr_sbc_intr: spurrious\n");
352 #endif
353 		return;
354 	}
355 
356 	SCI_CLR_INTR(regs);
357 #ifdef	DEBUG
358 	printf (" ncr_sbc_intr\n");
359 #endif
360 }
361 
362 static void
363 ncr_dma_intr(struct ncr5380_softc *ncr5380)
364 {
365 	volatile struct si_regs *regs = ncr5380->sc_regs;
366 
367 #ifdef	DEBUG
368 	printf (" ncr_dma_intr\n");
369 #endif
370 }
371 
372 static int
373 ncr_intr(void *arg)
374 {
375 	struct ncr5380_softc *ncr5380 = arg;
376 	volatile struct si_regs *si = ncr5380->sc_regs;
377 	int rv = 0;
378 
379 	/* Interrupts not enabled?  Can not be for us. */
380 	if ((si->si_csr & SI_CSR_INTR_EN) == 0)
381 		return rv;
382 
383 	if (si->si_csr & SI_CSR_DMA_IP) {
384 		ncr_dma_intr(ncr5380);
385 		rv++;
386 	}
387 	if (si->si_csr & SI_CSR_SBC_IP) {
388 		ncr_sbc_intr(ncr5380);
389 		rv++;
390 	}
391 	return rv;
392 }
393 
394 static int
395 ncr5380_reset_adapter(struct ncr5380_softc *ncr5380)
396 {
397 	volatile struct si_regs *si = ncr5380->sc_regs;
398 
399 #ifdef	DEBUG
400 	if (si_debug) {
401 		printf("si_reset_adapter\n");
402 	}
403 #endif
404 
405 	/* The reset bits are active low. */
406 	si->si_csr = 0;
407 	delay(100);
408 	si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES;
409 }
410 
411 static int
412 ncr5380_reset_scsibus(struct ncr5380_softc *ncr5380)
413 {
414 	volatile sci_regmap_t *regs = ncr5380->sc_regs;
415 
416 #ifdef	DEBUG
417 	if (si_debug) {
418 		printf("si_reset_scsibus\n");
419 	}
420 #endif
421 
422 	regs->sci_icmd = SCI_ICMD_TEST;
423 	regs->sci_icmd = SCI_ICMD_TEST | SCI_ICMD_RST;
424 	delay(2500);
425 	regs->sci_icmd = 0;
426 
427 	regs->sci_mode = 0;
428 	regs->sci_tcmd = SCI_PHASE_DISC;
429 	regs->sci_sel_enb = 0;
430 
431 	SCI_CLR_INTR(regs);
432 	SCI_CLR_INTR(regs);
433 }
434 
435 static int
436 ncr5380_poll(int adapter, int timeout)
437 {
438 }
439 
440 static int
441 ncr5380_send_cmd(struct scsi_xfer *xs)
442 {
443 	int	sense;
444 
445 #ifdef	DIAGNOSTIC
446 	if ((getsr() & PSL_IPL) < PSL_IPL2)
447 		panic("ncr_send_cmd: bad spl");
448 #endif
449 
450 #ifdef	DEBUG
451 	if (si_debug & 2)
452 		ncr5380_show_scsi_cmd(xs);
453 #endif
454 
455 	sense = si_generic( xs->sc_link->scsibus, xs->sc_link->target,
456 			  xs->sc_link->lun, xs->cmd, xs->cmdlen,
457 			  xs->data, xs->datalen );
458 
459 	switch (sense) {
460 	case 0:	/* success */
461 		xs->resid = 0;
462 		xs->error = XS_NOERROR;
463 		break;
464 
465 	case 0x02:	/* Check condition */
466 #ifdef	DEBUG
467 		if (si_debug)
468 			printf("check cond. target %d.\n",
469 				   xs->sc_link->target);
470 #endif
471 		delay(10);	/* Phil's fix for slow devices. */
472 		si_group0(xs->sc_link->scsibus,
473 				  xs->sc_link->target,
474 				  xs->sc_link->lun,
475 				  0x3, 0x0,
476 				  sizeof(struct scsi_sense_data),
477 				  0, (caddr_t) &(xs->sense),
478 				  sizeof(struct scsi_sense_data));
479 		xs->error = XS_SENSE;
480 		break;
481 	case 0x08:	/* Busy */
482 		xs->error = XS_BUSY;
483 		break;
484 	default:
485 		xs->error = XS_DRIVER_STUFFUP;
486 		break;
487 
488 	}
489 	return (COMPLETE);
490 }
491 
492 static int
493 si_select_target(register volatile sci_regmap_t *regs,
494 	      u_char myid, u_char tid, int with_atn)
495 {
496 	register u_char	bid, icmd;
497 	int		ret = SCSI_RET_RETRY;
498 	int 	arb_retries, arb_wait;
499 
500 	/* for our purposes.. */
501 	myid = 1 << myid;
502 	tid = 1 << tid;
503 
504 	regs->sci_sel_enb = 0; /* we don't want any interrupts. */
505 	regs->sci_tcmd = 0;	/* get into a harmless state */
506 
507 	arb_retries = ARBITRATION_RETRIES;
508 
509 retry_arbitration:
510 	regs->sci_mode = 0;	/* get into a harmless state */
511 	if (--arb_retries <= 0) {
512 #ifdef	DEBUG
513 		if (si_debug) {
514 			printf("si_select: arb_retries expended\n");
515 		}
516 #endif
517 		goto lost;
518 	}
519 
520 	if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
521 	    (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) &&
522 	    (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)))
523 	{
524 #ifdef	DEBUG
525 		if (si_debug) {
526 			printf("si_select_target: still BSY|SEL\n");
527 		}
528 #endif
529 		return ret;
530 	}
531 
532 	regs->sci_odata = myid;
533 	regs->sci_mode = SCI_MODE_ARB;
534 /*	regs->sci_mode |= SCI_MODE_ARB;	XXX? */
535 
536 	/* AIP might not set if BSY went true after we checked */
537 	/* Wait up to about 100 usec. for it to appear. */
538 	arb_wait = 50;	/* X2 */
539 	do {
540 		if (regs->sci_icmd & SCI_ICMD_AIP)
541 			break;
542 		delay2us();
543 	} while (--arb_wait > 0);
544 	if (arb_wait <= 0) {
545 		/* XXX - Could have missed it? */
546 		goto retry_arbitration;
547 	}
548 #ifdef	DEBUG
549 	if (si_debug) {
550 		printf("si_select_target: API after %d tries (last wait %d)\n",
551 			   ARBITRATION_RETRIES - arb_retries,
552 			   (50 - arb_wait));
553 	}
554 #endif
555 
556 	delay(3);	/* 2.2 uSec. arbitration delay */
557 
558 	if (regs->sci_icmd & SCI_ICMD_LST) {
559 #ifdef	DEBUG
560 		if (si_debug)
561 			printf ("lost 1\n");
562 #endif
563 		goto retry_arbitration;	/* XXX */
564 	}
565 
566 	regs->sci_mode &= ~SCI_MODE_PAR_CHK;
567 	bid = regs->sci_data;
568 
569 	if ((bid & ~myid) > myid) {
570 #ifdef	DEBUG
571 		if (si_debug)
572 			printf ("lost 2\n");
573 #endif
574 		/* Trying again will not help. */
575 		goto lost;
576 	}
577 	if (regs->sci_icmd & SCI_ICMD_LST) {
578 #ifdef	DEBUG
579 		if (si_debug)
580 			printf ("lost 3\n");
581 #endif
582 		goto lost;
583 	}
584 
585 	/* Won arbitration, enter selection phase now */
586 	icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
587 	icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL);
588 	regs->sci_icmd = icmd;
589 
590 	if (regs->sci_icmd & SCI_ICMD_LST) {
591 #ifdef	DEBUG
592 		if (si_debug)
593 			printf ("nosel\n");
594 #endif
595 		goto nosel;
596 	}
597 
598 	/* XXX a target that violates specs might still drive the bus XXX */
599 	/* XXX should put our id out, and after the delay check nothi XXX */
600 	/* XXX ng else is out there.				      XXX */
601 
602 	delay2us();
603 
604 	regs->sci_sel_enb = 0;
605 
606 	regs->sci_odata = myid | tid;
607 
608 	icmd |= SCI_ICMD_BSY|SCI_ICMD_DATA;
609 	regs->sci_icmd = icmd;
610 
611 /*	regs->sci_mode &= ~SCI_MODE_ARB;	 2 deskew delays, too */
612 	regs->sci_mode = 0;			/* 2 deskew delays, too */
613 
614 	icmd &= ~SCI_ICMD_BSY;
615 	regs->sci_icmd = icmd;
616 
617 	/* bus settle delay, 400ns */
618 	delay2us(); /* too much (was 2) ? */
619 
620 	regs->sci_mode |= SCI_MODE_PAR_CHK;
621 
622 	{
623 		register int timeo  = 2500;/* 250 msecs in 100 usecs chunks */
624 		while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) {
625 			if (--timeo > 0) {
626 				delay(100);
627 			} else {
628 				/* This is the "normal" no-such-device select error. */
629 #ifdef	DEBUG
630 				if (si_debug)
631 					printf("si_select: did not see BSY\n");
632 #endif
633 				goto nodev;
634 			}
635 		}
636 	}
637 
638 	icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL);
639 	regs->sci_icmd = icmd;
640 /*	regs->sci_sel_enb = myid;*/	/* looks like we should NOT have it */
641 	/* XXX - SCI_MODE_PAR_CHK ? */
642 	return SCSI_RET_SUCCESS;
643 
644 nodev:
645 	ret = SCSI_RET_DEVICE_DOWN;
646 	regs->sci_sel_enb = myid;
647 nosel:
648 	icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN);
649 	regs->sci_icmd = icmd;
650 	regs->sci_mode = 0;
651 	return ret;
652 
653 lost:
654 	regs->sci_icmd = 0;
655 	regs->sci_mode = 0;
656 #ifdef	DEBUG
657 	if (si_debug) {
658 		printf("si_select: lost arbitration\n");
659 	}
660 #endif
661 	return ret;
662 }
663 
664 sci_data_out(regs, phase, count, data)
665 	register volatile sci_regmap_t	*regs;
666 	unsigned char		*data;
667 {
668 	register unsigned char	icmd;
669 	register int		cnt=0;
670 
671 	/* ..checks.. */
672 
673 	icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
674 loop:
675 	if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
676 		return cnt;
677 
678 	WAIT_FOR_REQ(regs);
679 	icmd |= SCI_ICMD_DATA;
680 	regs->sci_icmd = icmd;
681 	regs->sci_odata = *data++;
682 	icmd |= SCI_ICMD_ACK;
683 	regs->sci_icmd = icmd;
684 
685 	icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK);
686 	WAIT_FOR_NOT_REQ(regs);
687 	regs->sci_icmd = icmd;
688 	++cnt;
689 	if (--count > 0)
690 		goto loop;
691 scsi_timeout_error:
692 	return cnt;
693 }
694 
695 sci_data_in(regs, phase, count, data)
696 	register volatile sci_regmap_t	*regs;
697 	unsigned char		*data;
698 {
699 	register unsigned char	icmd;
700 	register int		cnt=0;
701 
702 	/* ..checks.. */
703 
704 	icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
705 
706 loop:
707 	if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
708 		return cnt;
709 
710 	WAIT_FOR_REQ(regs);
711 	*data++ = regs->sci_data;
712 	icmd |= SCI_ICMD_ACK;
713 	regs->sci_icmd = icmd;
714 
715 	icmd &= ~SCI_ICMD_ACK;
716 	WAIT_FOR_NOT_REQ(regs);
717 	regs->sci_icmd = icmd;
718 	++cnt;
719 	if (--count > 0)
720 		goto loop;
721 
722 scsi_timeout_error:
723 	return cnt;
724 }
725 
726 static int
727 si_command_transfer(register volatile sci_regmap_t *regs,
728 		 int maxlen, u_char *data, u_char *status, u_char *msg)
729 {
730 	int	xfer=0, phase;
731 
732 /*	printf("command_transfer called for 0x%x.\n", *data); */
733 
734 	regs->sci_icmd = 0;
735 
736 	while (1) {
737 
738 		WAIT_FOR_REQ(regs);
739 
740 		phase = SCI_CUR_PHASE(regs->sci_bus_csr);
741 
742 		switch (phase) {
743 			case SCSI_PHASE_CMD:
744 				SCI_ACK(regs,SCSI_PHASE_CMD);
745 				xfer += sci_data_out(regs, SCSI_PHASE_CMD,
746 						   	maxlen, data);
747 				return xfer;
748 			case SCSI_PHASE_DATA_IN:
749 				printf("Data in phase in command_transfer?\n");
750 				return 0;
751 			case SCSI_PHASE_DATA_OUT:
752 				printf("Data out phase in command_transfer?\n");
753 				return 0;
754 			case SCSI_PHASE_STATUS:
755 				SCI_ACK(regs,SCSI_PHASE_STATUS);
756 				printf("status in command_transfer.\n");
757 				sci_data_in(regs, SCSI_PHASE_STATUS,
758 					  	1, status);
759 				break;
760 			case SCSI_PHASE_MESSAGE_IN:
761 				SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
762 				printf("msgin in command_transfer.\n");
763 				sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
764 					  	1, msg);
765 				break;
766 			case SCSI_PHASE_MESSAGE_OUT:
767 				SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
768 				sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
769 					  	1, msg);
770 				break;
771 			default:
772 				printf("Unexpected phase 0x%x in "
773 					"command_transfer().\n", phase);
774 scsi_timeout_error:
775 				return xfer;
776 				break;
777 		}
778 	}
779 }
780 
781 static int
782 si_data_transfer(register volatile sci_regmap_t *regs,
783 	      int maxlen, u_char *data, u_char *status, u_char *msg)
784 {
785 	int	retlen = 0, xfer, phase;
786 
787 	regs->sci_icmd = 0;
788 
789 	*status = 0;
790 
791 	while (1) {
792 
793 		WAIT_FOR_REQ(regs);
794 
795 		phase = SCI_CUR_PHASE(regs->sci_bus_csr);
796 
797 		switch (phase) {
798 			case SCSI_PHASE_CMD:
799 				printf("Command phase in data_transfer().\n");
800 				return retlen;
801 			case SCSI_PHASE_DATA_IN:
802 				SCI_ACK(regs,SCSI_PHASE_DATA_IN);
803 #if PSEUDO_DMA
804 				xfer = sci_pdma_in(regs, SCSI_PHASE_DATA_IN,
805 						  	maxlen, data);
806 #else
807 				xfer = sci_data_in(regs, SCSI_PHASE_DATA_IN,
808 						  	maxlen, data);
809 #endif
810 				retlen += xfer;
811 				maxlen -= xfer;
812 				break;
813 			case SCSI_PHASE_DATA_OUT:
814 				SCI_ACK(regs,SCSI_PHASE_DATA_OUT);
815 #if PSEUDO_DMA
816 				xfer = sci_pdma_out(regs, SCSI_PHASE_DATA_OUT,
817 						   	maxlen, data);
818 #else
819 				xfer = sci_data_out(regs, SCSI_PHASE_DATA_OUT,
820 						   	maxlen, data);
821 #endif
822 				retlen += xfer;
823 				maxlen -= xfer;
824 				break;
825 			case SCSI_PHASE_STATUS:
826 				SCI_ACK(regs,SCSI_PHASE_STATUS);
827 				sci_data_in(regs, SCSI_PHASE_STATUS,
828 					  	1, status);
829 				break;
830 			case SCSI_PHASE_MESSAGE_IN:
831 				SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
832 				sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
833 					  	1, msg);
834 				if (*msg == 0) {
835 					return retlen;
836 				} else {
837 					printf( "message 0x%x in "
838 						"data_transfer.\n", *msg);
839 				}
840 				break;
841 			case SCSI_PHASE_MESSAGE_OUT:
842 				SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
843 				sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
844 					  	1, msg);
845 				break;
846 			default:
847 				printf( "Unexpected phase 0x%x in "
848 					"data_transfer().\n", phase);
849 scsi_timeout_error:
850 				return retlen;
851 				break;
852 		}
853 	}
854 }
855 
856 static int
857 si_dorequest(register volatile sci_regmap_t *regs,
858 		int target, int lun, u_char *cmd, int cmdlen,
859 		char *databuf, int datalen, int *sent, int *ret)
860 {
861 /* Returns 0 on success, -1 on internal error, or the status byte */
862 	int	cmd_bytes_sent, r;
863 	u_char	stat, msg, c;
864 
865 	*sent = 0;
866 
867 	if ( ( r = si_select_target(regs, 7, target, 1) ) != SCSI_RET_SUCCESS) {
868 #ifdef	DEBUG
869 		if (si_debug) {
870 			printf("si_dorequest: select returned %d\n", r);
871 		}
872 #endif
873 		*ret = r;
874 		SCI_CLR_INTR(regs);
875 		switch (r) {
876 		case SCSI_RET_RETRY:
877 			return 0x08;
878 		default:
879 			printf("si_select_target(target %d, lun %d) failed(%d).\n",
880 				target, lun, r);
881 		case SCSI_RET_DEVICE_DOWN:
882 			return -1;
883 		}
884 	}
885 
886 	c = 0x80 | lun;
887 
888 	if ((cmd_bytes_sent = si_command_transfer(regs, cmdlen,
889 				(u_char *) cmd, &stat, &c)) != cmdlen)
890 	{
891 		SCI_CLR_INTR(regs);
892 		*ret = SCSI_RET_COMMAND_FAIL;
893 		printf("Data underrun sending CCB (%d bytes of %d, sent).\n",
894 			cmd_bytes_sent, cmdlen);
895 		return -1;
896 	}
897 
898 	*sent=si_data_transfer(regs, datalen, (u_char *)databuf,
899 				  &stat, &msg);
900 #ifdef	DEBUG
901 	if (si_debug) {
902 		printf("si_dorequest: data transfered = %d\n", *sent);
903 	}
904 #endif
905 
906 	*ret = 0;
907 	return stat;
908 }
909 
910 static int
911 si_generic(int adapter, int id, int lun, struct scsi_generic *cmd,
912   	 int cmdlen, void *databuf, int datalen)
913 {
914 	register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter];
915 	register volatile sci_regmap_t *regs = ncr5380->sc_regs;
916 	int i,j,sent,ret;
917 
918 	if (cmd->opcode == TEST_UNIT_READY)	/* XXX */
919 		cmd->bytes[0] = ((u_char) lun << 5);
920 
921 	i = si_dorequest(regs, id, lun, (u_char *) cmd, cmdlen,
922 					 databuf, datalen, &sent, &ret);
923 
924 	return i;
925 }
926 
927 static int
928 si_group0(int adapter, int id, int lun, int opcode, int addr, int len,
929 		int flags, caddr_t databuf, int datalen)
930 {
931 	register struct ncr5380_softc *ncr5380 = sicd.cd_devs[adapter];
932 	register volatile sci_regmap_t *regs = ncr5380->sc_regs;
933 	unsigned char cmd[6];
934 	int i,j,sent,ret;
935 
936 	cmd[0] = opcode;		/* Operation code           		*/
937 	cmd[1] = (lun << 5) | ((addr >> 16) & 0x1F);	/* Lun & MSB of addr	*/
938 	cmd[2] = (addr >> 8) & 0xFF;	/* addr					*/
939 	cmd[3] = addr & 0xFF;		/* LSB of addr				*/
940 	cmd[4] = len;			/* Allocation length			*/
941 	cmd[5] = flags;		/* Link/Flag				*/
942 
943 	i = si_dorequest(regs, id, lun, cmd, 6, databuf, datalen, &sent, &ret);
944 
945 	return i;
946 }
947