Home | History | Annotate | Line # | Download | only in dev
si.c revision 1.14
      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