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