Home | History | Annotate | Line # | Download | only in dev
si.c revision 1.19
      1 /*	$NetBSD: si.c,v 1.19 1995/08/08 20:53:16 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	1000000
     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     int sc_adapter_iv_am;	/* int. vec + address modifier */
    124     struct scsi_link sc_link;
    125 };
    126 
    127 static u_int		ncr5380_minphys(struct buf *bp);
    128 static int		ncr5380_scsi_cmd(struct scsi_xfer *xs);
    129 static int		ncr5380_reset_adapter(struct ncr5380_softc *);
    130 static int		ncr5380_reset_scsibus(struct ncr5380_softc *);
    131 static int		ncr5380_poll(int adapter, int timeout);
    132 static int		ncr5380_send_cmd(struct scsi_xfer *xs);
    133 
    134 static int		ncr_intr(void *);
    135 
    136 static int	si_generic(int adapter, int id, int lun,
    137 			 struct scsi_generic *cmd, int cmdlen,
    138 			 void *databuf, int datalen);
    139 static int	si_group0(int adapter, int id, int lun,
    140 			    int opcode, int addr, int len,
    141 			    int flags, caddr_t databuf, int datalen);
    142 
    143 static char scsi_name[] = "si";
    144 
    145 struct scsi_adapter	ncr5380_switch = {
    146 	ncr5380_scsi_cmd,		/* scsi_cmd()		*/
    147 	ncr5380_minphys,		/* scsi_minphys()	*/
    148 	NULL,				/* open_target_lu()	*/
    149 	NULL,				/* close_target_lu()	*/
    150 };
    151 
    152 /* This is copied from julian's bt driver */
    153 /* "so we have a default dev struct for our link struct." */
    154 struct scsi_device ncr_dev = {
    155 	NULL,		/* Use default error handler.	    */
    156 	NULL,		/* Use default start handler.		*/
    157 	NULL,		/* Use default async handler.	    */
    158 	NULL,		/* Use default "done" routine.	    */
    159 };
    160 
    161 static int	si_match();
    162 static void	si_attach();
    163 
    164 struct cfdriver sicd = {
    165 	NULL, "si", si_match, si_attach, DV_DULL,
    166 	sizeof(struct ncr5380_softc), NULL, 0,
    167 };
    168 
    169 static int
    170 si_print(aux, name)
    171 	void *aux;
    172 	char *name;
    173 {
    174 }
    175 
    176 static int
    177 si_match(parent, vcf, args)
    178 	struct device	*parent;
    179 	void		*vcf, *args;
    180 {
    181 	struct cfdata	*cf = vcf;
    182 	struct confargs *ca = args;
    183 	int x, probe_addr;
    184 
    185 	/* Default interrupt priority always splbio==2 */
    186 	if (ca->ca_intpri == -1)
    187 		ca->ca_intpri = 2;
    188 
    189 	if ((cpu_machine_id == SUN3_MACH_50) ||
    190 	    (cpu_machine_id == SUN3_MACH_60) )
    191 	{
    192 		/* Sun3/50 or Sun3/60 have only OBIO "si" */
    193 		if (ca->ca_bustype != BUS_OBIO)
    194 			return(0);
    195 		if (ca->ca_paddr == -1)
    196 			ca->ca_paddr = OBIO_NCR_SCSI;
    197 		/* OK... */
    198 	} else {
    199 		/* Other Sun3 models may have VME "si" or "sc" */
    200 		if (ca->ca_bustype != BUS_VME16)
    201 			return (0);
    202 		if (ca->ca_paddr == -1)
    203 			return (0);
    204 		/* OK... */
    205 	}
    206 
    207 	/* Make sure there is something there... */
    208 	x = bus_peek(ca->ca_bustype, ca->ca_paddr + 1, 1);
    209 	if (x == -1)
    210 		return (0);
    211 
    212 	/*
    213 	 * If this is a VME SCSI board, we have to determine whether
    214 	 * it is an "sc" (Sun2) or "si" (Sun3) SCSI board.  This can
    215 	 * be determined using the fact that the "sc" board occupies
    216 	 * 4K bytes in VME space but the "si" board occupies 2K bytes.
    217 	 */
    218 	if (ca->ca_bustype == BUS_VME16) {
    219 		/* Note, the "si" board should NOT respond here. */
    220 		x = bus_peek(ca->ca_bustype, ca->ca_paddr + 0x801, 1);
    221 		if (x != -1)
    222 			return(0);
    223 	}
    224 
    225     return (1);
    226 }
    227 
    228 static void
    229 si_attach(parent, self, args)
    230 	struct device	*parent, *self;
    231 	void		*args;
    232 {
    233 	struct ncr5380_softc *ncr5380 = (struct ncr5380_softc *) self;
    234 	volatile sci_regmap_t *regs;
    235 	struct confargs *ca = args;
    236 
    237 	switch (ca->ca_bustype) {
    238 
    239 	case BUS_OBIO:
    240 		regs = (sci_regmap_t *)
    241 			obio_alloc(ca->ca_paddr, sizeof(*regs));
    242 		isr_add_autovect(ncr_intr, (void *)ncr5380,
    243 						 ca->ca_intpri);
    244 		break;
    245 
    246 	case BUS_VME16:
    247 		regs = (sci_regmap_t *)
    248 			bus_mapin(ca->ca_bustype, ca->ca_paddr, sizeof(*regs));
    249 		isr_add_vectored(ncr_intr, (void *)ncr5380,
    250 						 ca->ca_intpri, ca->ca_intvec);
    251 		break;
    252 
    253 	default:
    254 		printf("unknown\n");
    255 		return;
    256 	}
    257 
    258 	ncr5380->sc_adapter_type = ca->ca_bustype;
    259 	ncr5380->sc_adapter_iv_am =
    260 		VME_SUPV_DATA_24 | (ca->ca_intvec & 0xFF);
    261 	ncr5380->sc_regs = regs;
    262 
    263 	/*
    264 	 * fill in the prototype scsi_link.
    265 	 */
    266     ncr5380->sc_link.adapter_softc = ncr5380;
    267     ncr5380->sc_link.adapter_target = 7;
    268     ncr5380->sc_link.adapter = &ncr5380_switch;
    269     ncr5380->sc_link.device = &ncr_dev;
    270     ncr5380->sc_link.openings = 2;
    271 #ifdef	DEBUG
    272     ncr5380->sc_link.flags |= si_flags;
    273 #endif
    274 
    275     printf("\n");
    276 	ncr5380_reset_adapter(ncr5380);
    277 	ncr5380_reset_scsibus(ncr5380);
    278 	config_found(self, &(ncr5380->sc_link), si_print);
    279 }
    280 
    281 #define MIN_PHYS	65536	/*BARF!!!!*/
    282 static u_int
    283 ncr5380_minphys(struct buf *bp)
    284 {
    285 	if (bp->b_bcount > MIN_PHYS) {
    286 		printf("Uh-oh...  ncr5380_minphys setting bp->b_bcount = %x.\n", MIN_PHYS);
    287 		bp->b_bcount = MIN_PHYS;
    288 	}
    289 	return (minphys(bp));
    290 }
    291 #undef MIN_PHYS
    292 
    293 static int
    294 ncr5380_scsi_cmd(struct scsi_xfer *xs)
    295 {
    296 	int flags, s, r;
    297 
    298 	flags = xs->flags;
    299 	if (xs->bp) flags |= (SCSI_NOSLEEP);
    300 	if ( flags & ITSDONE ) {
    301 		printf("Already done?");
    302 		xs->flags &= ~ITSDONE;
    303 	}
    304 	if ( ! ( flags & INUSE ) ) {
    305 		printf("Not in use?");
    306 		xs->flags |= INUSE;
    307 	}
    308 
    309 	s = splbio();
    310 
    311 	if ( flags & SCSI_RESET ) {
    312 		printf("flags & SCSIRESET.\n");
    313 		ncr5380_reset_scsibus(xs->sc_link->adapter_softc);
    314 		r = COMPLETE;
    315 	} else {
    316 		r = ncr5380_send_cmd(xs);
    317 		xs->flags |= ITSDONE;
    318 		scsi_done(xs);
    319 	}
    320 
    321 	splx(s);
    322 
    323 	switch(r) {
    324 	case COMPLETE:
    325 	case SUCCESSFULLY_QUEUED:
    326 		r = SUCCESSFULLY_QUEUED;
    327 		if (xs->flags & SCSI_POLL)
    328 			r = COMPLETE;
    329 		break;
    330 	default:
    331 		break;
    332 	}
    333 	return r;
    334 }
    335 
    336 #ifdef	DEBUG
    337 static int
    338 ncr5380_show_scsi_cmd(struct scsi_xfer *xs)
    339 {
    340 	u_char	*b = (u_char *) xs->cmd;
    341 	int	i  = 0;
    342 
    343 	if ( ! ( xs->flags & SCSI_RESET ) ) {
    344 		printf("si(%d:%d:%d)-",
    345 			   xs->sc_link->scsibus,
    346 			   xs->sc_link->target,
    347 			   xs->sc_link->lun);
    348 		while (i < xs->cmdlen) {
    349 			if (i) printf(",");
    350 			printf("%x",b[i++]);
    351 		}
    352 		printf("-\n");
    353 	} else {
    354 		printf("si(%d:%d:%d)-RESET-\n",
    355 			   xs->sc_link->scsibus,
    356 			   xs->sc_link->target,
    357 			   xs->sc_link->lun);
    358 	}
    359 }
    360 #endif
    361 
    362 /*
    363  * Actual chip control.
    364  */
    365 
    366 static void
    367 ncr_sbc_intr(struct ncr5380_softc *ncr5380)
    368 {
    369 	volatile sci_regmap_t *regs = ncr5380->sc_regs;
    370 
    371 	if ((regs->sci_csr & SCI_CSR_INT) == 0) {
    372 #ifdef	DEBUG
    373 		printf (" ncr_sbc_intr: spurrious\n");
    374 #endif
    375 		return;
    376 	}
    377 
    378 	SCI_CLR_INTR(regs);
    379 #ifdef	DEBUG
    380 	printf (" ncr_sbc_intr\n");
    381 #endif
    382 }
    383 
    384 static void
    385 ncr_dma_intr(struct ncr5380_softc *ncr5380)
    386 {
    387 	volatile struct si_regs *regs = ncr5380->sc_regs;
    388 
    389 #ifdef	DEBUG
    390 	printf (" ncr_dma_intr\n");
    391 #endif
    392 }
    393 
    394 static int
    395 ncr_intr(void *arg)
    396 {
    397 	struct ncr5380_softc *ncr5380 = arg;
    398 	volatile struct si_regs *si = ncr5380->sc_regs;
    399 	int rv = 0;
    400 
    401 	/* Interrupts not enabled?  Can not be for us. */
    402 	if ((si->si_csr & SI_CSR_INTR_EN) == 0)
    403 		return rv;
    404 
    405 	if (si->si_csr & SI_CSR_DMA_IP) {
    406 		ncr_dma_intr(ncr5380);
    407 		rv++;
    408 	}
    409 	if (si->si_csr & SI_CSR_SBC_IP) {
    410 		ncr_sbc_intr(ncr5380);
    411 		rv++;
    412 	}
    413 	return rv;
    414 }
    415 
    416 static int
    417 ncr5380_reset_adapter(struct ncr5380_softc *sc)
    418 {
    419 	volatile struct si_regs *si = sc->sc_regs;
    420 
    421 #ifdef	DEBUG
    422 	if (si_debug) {
    423 		printf("si_reset_adapter\n");
    424 	}
    425 #endif
    426 
    427 	/* The reset bits in the CSR are active low. */
    428 	si->si_csr = 0;
    429 	delay(20);
    430 	si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES;
    431 	si->fifo_count = 0;
    432 	if (sc->sc_adapter_type == BUS_VME16) {
    433 		si->dma_addrh = 0;
    434 		si->dma_addrl = 0;
    435 		si->dma_counth = 0;
    436 		si->dma_countl = 0;
    437 		si->iv_am = sc->sc_adapter_iv_am;
    438 	}
    439 }
    440 
    441 static int
    442 ncr5380_reset_scsibus(struct ncr5380_softc *ncr5380)
    443 {
    444 	volatile sci_regmap_t *regs = ncr5380->sc_regs;
    445 
    446 #ifdef	DEBUG
    447 	if (si_debug) {
    448 		printf("si_reset_scsibus\n");
    449 	}
    450 #endif
    451 
    452 	regs->sci_icmd = SCI_ICMD_RST;
    453 	delay(100);
    454 	regs->sci_icmd = 0;
    455 
    456 	regs->sci_mode = 0;
    457 	regs->sci_tcmd = SCI_PHASE_DISC;
    458 	regs->sci_sel_enb = 0;
    459 
    460 	SCI_CLR_INTR(regs);
    461 	/* XXX - Need long delay here! */
    462 }
    463 
    464 static int
    465 ncr5380_poll(int adapter, int timeout)
    466 {
    467 }
    468 
    469 static int
    470 ncr5380_send_cmd(struct scsi_xfer *xs)
    471 {
    472 	int	sense;
    473 
    474 #ifdef	DIAGNOSTIC
    475 	if ((getsr() & PSL_IPL) < PSL_IPL2)
    476 		panic("ncr_send_cmd: bad spl");
    477 #endif
    478 
    479 #ifdef	DEBUG
    480 	if (si_debug & 2)
    481 		ncr5380_show_scsi_cmd(xs);
    482 #endif
    483 
    484 	sense = si_generic( xs->sc_link->scsibus, xs->sc_link->target,
    485 			  xs->sc_link->lun, xs->cmd, xs->cmdlen,
    486 			  xs->data, xs->datalen );
    487 
    488 	switch (sense) {
    489 	case 0:	/* success */
    490 		xs->resid = 0;
    491 		xs->error = XS_NOERROR;
    492 		break;
    493 
    494 	case 0x02:	/* Check condition */
    495 #ifdef	DEBUG
    496 		if (si_debug)
    497 			printf("check cond. target %d.\n",
    498 				   xs->sc_link->target);
    499 #endif
    500 		delay(10);	/* Phil's fix for slow devices. */
    501 		si_group0(xs->sc_link->scsibus,
    502 				  xs->sc_link->target,
    503 				  xs->sc_link->lun,
    504 				  0x3, 0x0,
    505 				  sizeof(struct scsi_sense_data),
    506 				  0, (caddr_t) &(xs->sense),
    507 				  sizeof(struct scsi_sense_data));
    508 		xs->error = XS_SENSE;
    509 		break;
    510 	case 0x08:	/* Busy - common code will delay, retry. */
    511 		xs->error = XS_BUSY;
    512 		break;
    513 	default:	/* Dead - tell common code to give up. */
    514 		xs->error = XS_DRIVER_STUFFUP;
    515 		break;
    516 
    517 	}
    518 	return (COMPLETE);
    519 }
    520 
    521 static int
    522 si_select_target(register volatile sci_regmap_t *regs,
    523 	      u_char myid, u_char tid, int with_atn)
    524 {
    525 	register u_char	bid, icmd;
    526 	int		ret = SCSI_RET_RETRY;
    527 	int 	arb_retries, arb_wait;
    528 
    529 	/* for our purposes.. */
    530 	myid = 1 << myid;
    531 	tid = 1 << tid;
    532 
    533 	regs->sci_sel_enb = 0; /* we don't want any interrupts. */
    534 	regs->sci_tcmd = 0;	/* get into a harmless state */
    535 
    536 	arb_retries = ARBITRATION_RETRIES;
    537 
    538 retry_arbitration:
    539 	regs->sci_mode = 0;	/* get into a harmless state */
    540 wait_for_bus_free:
    541 	if (--arb_retries <= 0) {
    542 #ifdef	DEBUG
    543 		if (si_debug) {
    544 			printf("si_select: arb_retries expended; resetting...\n");
    545 		}
    546 #endif
    547 		ret = SCSI_RET_NEED_RESET;
    548 		goto nosel;
    549 	}
    550 
    551 	icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
    552 
    553 	if (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) {
    554 		/* Something is sitting on the SCSI bus... */
    555 #ifdef	DEBUG
    556 		/* Only complain once (the last time through). */
    557 		if (si_debug && (arb_retries <= 1)) {
    558 			printf("si_select_target: still BSY+SEL\n");
    559 		}
    560 #endif
    561 		/* Give it a little time, then try again. */
    562 		delay(10);
    563 		goto wait_for_bus_free;
    564 	}
    565 
    566 	regs->sci_odata = myid;
    567 	regs->sci_mode = SCI_MODE_ARB;
    568 /*	regs->sci_mode |= SCI_MODE_ARB;	XXX? */
    569 
    570 	/* AIP might not set if BSY went true after we checked */
    571 	/* Wait up to about 100 usec. for it to appear. */
    572 	arb_wait = 50;	/* X2 */
    573 	do {
    574 		if (regs->sci_icmd & SCI_ICMD_AIP)
    575 			goto got_aip;
    576 		delay2us();
    577 	} while (--arb_wait > 0);
    578 	/* XXX - Could have missed it? */
    579 #ifdef	DEBUG
    580 	if (si_debug)
    581 		printf("si_select_target: API did not appear\n");
    582 #endif
    583 	goto retry_arbitration;
    584 
    585 	got_aip:
    586 #ifdef	DEBUG
    587 	if (si_debug & 4) {
    588 		printf("si_select_target: API after %d tries (last wait %d)\n",
    589 			   ARBITRATION_RETRIES - arb_retries,
    590 			   (50 - arb_wait));
    591 	}
    592 #endif
    593 
    594 	delay(3);	/* 2.2 uSec. arbitration delay */
    595 
    596 	if (regs->sci_icmd & SCI_ICMD_LST) {
    597 #ifdef	DEBUG
    598 		if (si_debug)
    599 			printf ("lost 1\n");
    600 #endif
    601 		goto retry_arbitration;	/* XXX */
    602 	}
    603 
    604 	regs->sci_mode &= ~SCI_MODE_PAR_CHK;
    605 	bid = regs->sci_data;
    606 
    607 	if ((bid & ~myid) > myid) {
    608 #ifdef	DEBUG
    609 		if (si_debug)
    610 			printf ("lost 2\n");
    611 #endif
    612 		/* Trying again will not help. */
    613 		goto lost;
    614 	}
    615 	if (regs->sci_icmd & SCI_ICMD_LST) {
    616 #ifdef	DEBUG
    617 		if (si_debug)
    618 			printf ("lost 3\n");
    619 #endif
    620 		goto lost;
    621 	}
    622 
    623 	/* Won arbitration, enter selection phase now */
    624 	icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
    625 	icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL);
    626 	regs->sci_icmd = icmd;
    627 
    628 	if (regs->sci_icmd & SCI_ICMD_LST) {
    629 #ifdef	DEBUG
    630 		if (si_debug)
    631 			printf ("nosel\n");
    632 #endif
    633 		goto nosel;
    634 	}
    635 
    636 	/* XXX a target that violates specs might still drive the bus XXX */
    637 	/* XXX should put our id out, and after the delay check nothi XXX */
    638 	/* XXX ng else is out there.				      XXX */
    639 
    640 	delay2us();
    641 
    642 	regs->sci_sel_enb = 0;
    643 
    644 	regs->sci_odata = myid | tid;
    645 
    646 	icmd |= SCI_ICMD_BSY|SCI_ICMD_DATA;
    647 	regs->sci_icmd = icmd;
    648 
    649 /*	regs->sci_mode &= ~SCI_MODE_ARB;	 2 deskew delays, too */
    650 	regs->sci_mode = 0;			/* 2 deskew delays, too */
    651 
    652 	icmd &= ~SCI_ICMD_BSY;
    653 	regs->sci_icmd = icmd;
    654 
    655 	/* bus settle delay, 400ns */
    656 	delay2us(); /* too much (was 2) ? */
    657 
    658 	regs->sci_mode |= SCI_MODE_PAR_CHK;
    659 
    660 	{
    661 		register int timeo  = 2500;/* 250 msecs in 100 usecs chunks */
    662 		while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) {
    663 			if (--timeo > 0) {
    664 				delay(100);
    665 			} else {
    666 				/* This is the "normal" no-such-device select error. */
    667 #ifdef	DEBUG
    668 				if (si_debug)
    669 					printf("si_select: not BSY (nothing there)\n");
    670 #endif
    671 				goto nodev;
    672 			}
    673 		}
    674 	}
    675 
    676 	icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL);
    677 	regs->sci_icmd = icmd;
    678 /*	regs->sci_sel_enb = myid;*/	/* looks like we should NOT have it */
    679 	/* XXX - SCI_MODE_PAR_CHK ? */
    680 	return SCSI_RET_SUCCESS;
    681 
    682 nodev:
    683 	ret = SCSI_RET_DEVICE_DOWN;
    684 	regs->sci_sel_enb = myid;
    685 nosel:
    686 	regs->sci_icmd = 0;
    687 	regs->sci_mode = 0;
    688 	return ret;
    689 
    690 lost:
    691 	regs->sci_icmd = 0;
    692 	regs->sci_mode = 0;
    693 #ifdef	DEBUG
    694 	if (si_debug) {
    695 		printf("si_select: lost arbitration\n");
    696 	}
    697 #endif
    698 	return ret;
    699 }
    700 
    701 sci_data_out(regs, phase, count, data)
    702 	register volatile sci_regmap_t	*regs;
    703 	unsigned char		*data;
    704 {
    705 	register unsigned char	icmd;
    706 	register int		cnt=0;
    707 
    708 	/* ..checks.. */
    709 
    710 	icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
    711 loop:
    712 	if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
    713 		return cnt;
    714 
    715 	WAIT_FOR_REQ(regs);
    716 	icmd |= SCI_ICMD_DATA;
    717 	regs->sci_icmd = icmd;
    718 	regs->sci_odata = *data++;
    719 	icmd |= SCI_ICMD_ACK;
    720 	regs->sci_icmd = icmd;
    721 
    722 	icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK);
    723 	WAIT_FOR_NOT_REQ(regs);
    724 	regs->sci_icmd = icmd;
    725 	++cnt;
    726 	if (--count > 0)
    727 		goto loop;
    728 scsi_timeout_error:
    729 	return cnt;
    730 }
    731 
    732 sci_data_in(regs, phase, count, data)
    733 	register volatile sci_regmap_t	*regs;
    734 	unsigned char		*data;
    735 {
    736 	register unsigned char	icmd;
    737 	register int		cnt=0;
    738 
    739 	/* ..checks.. */
    740 
    741 	icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST);
    742 
    743 loop:
    744 	if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase)
    745 		return cnt;
    746 
    747 	WAIT_FOR_REQ(regs);
    748 	*data++ = regs->sci_data;
    749 	icmd |= SCI_ICMD_ACK;
    750 	regs->sci_icmd = icmd;
    751 
    752 	icmd &= ~SCI_ICMD_ACK;
    753 	WAIT_FOR_NOT_REQ(regs);
    754 	regs->sci_icmd = icmd;
    755 	++cnt;
    756 	if (--count > 0)
    757 		goto loop;
    758 
    759 scsi_timeout_error:
    760 	return cnt;
    761 }
    762 
    763 /* Return -1 (error) or number of bytes sent (>=0). */
    764 static int
    765 si_command_transfer(register volatile sci_regmap_t *regs,
    766 		 int maxlen, u_char *data, u_char *status, u_char *msg)
    767 {
    768 	int	xfer, phase;
    769 
    770 	xfer = 0;
    771 	regs->sci_icmd = 0;
    772 
    773 	while (1) {
    774 
    775 		WAIT_FOR_REQ(regs);
    776 
    777 		phase = SCI_CUR_PHASE(regs->sci_bus_csr);
    778 
    779 		switch (phase) {
    780 			case SCSI_PHASE_CMD:
    781 				SCI_ACK(regs,SCSI_PHASE_CMD);
    782 				xfer += sci_data_out(regs, SCSI_PHASE_CMD,
    783 						   	maxlen, data);
    784 				goto out;
    785 
    786 			case SCSI_PHASE_DATA_IN:
    787 				printf("command_transfer: Data in phase?\n");
    788 				goto err;
    789 
    790 			case SCSI_PHASE_DATA_OUT:
    791 				printf("command_transfer: Data out phase?\n");
    792 				goto err;
    793 
    794 			case SCSI_PHASE_STATUS:
    795 				SCI_ACK(regs,SCSI_PHASE_STATUS);
    796 				printf("command_transfer: status in...\n");
    797 				sci_data_in(regs, SCSI_PHASE_STATUS,
    798 					  	1, status);
    799 				printf("command_transfer: status=0x%x\n", *status);
    800 				goto err;
    801 
    802 			case SCSI_PHASE_MESSAGE_IN:
    803 				SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
    804 				printf("command_transfer: msg in?\n");
    805 				sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
    806 					  	1, msg);
    807 				break;
    808 
    809 			case SCSI_PHASE_MESSAGE_OUT:
    810 				SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
    811 				sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
    812 					  	1, msg);
    813 				break;
    814 
    815 			default:
    816 				printf("command_transfer: Unexpected phase 0x%x\n", phase);
    817 				goto err;
    818 		}
    819 	}
    820 scsi_timeout_error:
    821  err:
    822 	xfer = -1;
    823  out:
    824 	return xfer;
    825 }
    826 
    827 static int
    828 si_data_transfer(register volatile sci_regmap_t *regs,
    829 	      int maxlen, u_char *data, u_char *status, u_char *msg)
    830 {
    831 	int	retlen = 0, xfer, phase;
    832 
    833 	regs->sci_icmd = 0;
    834 
    835 	*status = 0;
    836 
    837 	while (1) {
    838 
    839 		WAIT_FOR_REQ(regs);
    840 
    841 		phase = SCI_CUR_PHASE(regs->sci_bus_csr);
    842 
    843 		switch (phase) {
    844 			case SCSI_PHASE_CMD:
    845 				printf("Command phase in data_transfer().\n");
    846 				return retlen;
    847 			case SCSI_PHASE_DATA_IN:
    848 				SCI_ACK(regs,SCSI_PHASE_DATA_IN);
    849 #if PSEUDO_DMA
    850 				xfer = sci_pdma_in(regs, SCSI_PHASE_DATA_IN,
    851 						  	maxlen, data);
    852 #else
    853 				xfer = sci_data_in(regs, SCSI_PHASE_DATA_IN,
    854 						  	maxlen, data);
    855 #endif
    856 				retlen += xfer;
    857 				maxlen -= xfer;
    858 				break;
    859 			case SCSI_PHASE_DATA_OUT:
    860 				SCI_ACK(regs,SCSI_PHASE_DATA_OUT);
    861 #if PSEUDO_DMA
    862 				xfer = sci_pdma_out(regs, SCSI_PHASE_DATA_OUT,
    863 						   	maxlen, data);
    864 #else
    865 				xfer = sci_data_out(regs, SCSI_PHASE_DATA_OUT,
    866 						   	maxlen, data);
    867 #endif
    868 				retlen += xfer;
    869 				maxlen -= xfer;
    870 				break;
    871 			case SCSI_PHASE_STATUS:
    872 				SCI_ACK(regs,SCSI_PHASE_STATUS);
    873 				sci_data_in(regs, SCSI_PHASE_STATUS,
    874 					  	1, status);
    875 				break;
    876 			case SCSI_PHASE_MESSAGE_IN:
    877 				SCI_ACK(regs,SCSI_PHASE_MESSAGE_IN);
    878 				sci_data_in(regs, SCSI_PHASE_MESSAGE_IN,
    879 					  	1, msg);
    880 				if (*msg == 0) {
    881 					return retlen;
    882 				} else {
    883 					printf( "message 0x%x in "
    884 						"data_transfer.\n", *msg);
    885 				}
    886 				break;
    887 			case SCSI_PHASE_MESSAGE_OUT:
    888 				SCI_ACK(regs,SCSI_PHASE_MESSAGE_OUT);
    889 				sci_data_out(regs, SCSI_PHASE_MESSAGE_OUT,
    890 					  	1, msg);
    891 				break;
    892 			default:
    893 				printf( "Unexpected phase 0x%x in "
    894 					"data_transfer().\n", phase);
    895 scsi_timeout_error:
    896 				return retlen;
    897 				break;
    898 		}
    899 	}
    900 }
    901 
    902 static int
    903 si_dorequest(struct ncr5380_softc *sc,
    904 	int target, int lun, u_char *cmd, int cmdlen,
    905 	char *databuf, int datalen, int *sent)
    906 	/* Returns 0 on success, -1 on internal error, or the status byte */
    907 {
    908 	register volatile sci_regmap_t *regs = sc->sc_regs;
    909 	int	cmd_bytes_sent, r;
    910 	u_char	stat, msg, c;
    911 
    912 #ifdef	DEBUG
    913 	if (si_debug) {
    914 		printf("si_dorequest: target=%d, lun=%d\n", target, lun);
    915 	}
    916 #endif
    917 
    918 	*sent = 0;
    919 
    920 	if ( ( r = si_select_target(regs, 7, target, 1) ) != SCSI_RET_SUCCESS) {
    921 #ifdef	DEBUG
    922 		if (si_debug) {
    923 			printf("si_dorequest: select returned %d\n", r);
    924 		}
    925 #endif
    926 
    927 		SCI_CLR_INTR(regs);
    928 		switch (r) {
    929 
    930 		case SCSI_RET_NEED_RESET:
    931 			printf("si_dorequest: target=%d, lun=%d, resetting...\n",
    932 				   target, lun, r);
    933 			ncr5380_reset_adapter(sc);
    934 			ncr5380_reset_scsibus(sc);
    935 			/* fall through */
    936 		case SCSI_RET_RETRY:
    937 			return 0x08;	/* Busy - tell common code to retry. */
    938 
    939 		default:
    940 			printf("si_dorequest: target=%d, lun=%d, error=%d.\n",
    941 				target, lun, r);
    942 			/* fall through */
    943 		case SCSI_RET_DEVICE_DOWN:
    944 			return -1;	/* Dead - tell common code to give up. */
    945 		}
    946 	}
    947 
    948 	c = 0x80 | lun;
    949 
    950 	if ((cmd_bytes_sent = si_command_transfer(regs, cmdlen,
    951 				(u_char *) cmd, &stat, &c)) != cmdlen)
    952 	{
    953 		SCI_CLR_INTR(regs);
    954 		if (cmd_bytes_sent >= 0) {
    955 			printf("Data underrun sending CCB (%d bytes of %d, sent).\n",
    956 				   cmd_bytes_sent, cmdlen);
    957 		}
    958 		return -1;
    959 	}
    960 
    961 	*sent = si_data_transfer(regs, datalen, (u_char *)databuf,
    962 				  &stat, &msg);
    963 #ifdef	DEBUG
    964 	if (si_debug) {
    965 		printf("si_dorequest: data transfered = %d\n", *sent);
    966 	}
    967 #endif
    968 
    969 	return stat;
    970 }
    971 
    972 static int
    973 si_generic(int adapter, int id, int lun, struct scsi_generic *cmd,
    974   	 int cmdlen, void *databuf, int datalen)
    975 {
    976 	register struct ncr5380_softc *sc = sicd.cd_devs[adapter];
    977 	int i, j, sent;
    978 
    979 	if (cmd->opcode == TEST_UNIT_READY)	/* XXX */
    980 		cmd->bytes[0] = ((u_char) lun << 5);
    981 
    982 	i = si_dorequest(sc, id, lun, (u_char *) cmd, cmdlen,
    983 					 databuf, datalen, &sent);
    984 
    985 	return i;
    986 }
    987 
    988 static int
    989 si_group0(int adapter, int id, int lun, int opcode, int addr, int len,
    990 		int flags, caddr_t databuf, int datalen)
    991 {
    992 	register struct ncr5380_softc *sc = sicd.cd_devs[adapter];
    993 	unsigned char cmd[6];
    994 	int i, j, sent;
    995 
    996 	cmd[0] = opcode;		/* Operation code           		*/
    997 	cmd[1] = (lun << 5) | ((addr >> 16) & 0x1F);	/* Lun & MSB of addr	*/
    998 	cmd[2] = (addr >> 8) & 0xFF;	/* addr					*/
    999 	cmd[3] = addr & 0xFF;		/* LSB of addr				*/
   1000 	cmd[4] = len;			/* Allocation length			*/
   1001 	cmd[5] = flags;		/* Link/Flag				*/
   1002 
   1003 	i = si_dorequest(sc, id, lun, cmd, 6, databuf, datalen, &sent);
   1004 
   1005 	return i;
   1006 }
   1007