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