Home | History | Annotate | Line # | Download | only in dev
siop2.c revision 1.16.4.2
      1  1.16.4.2  nathanw /*	$NetBSD: siop2.c,v 1.16.4.2 2002/02/28 04:07:00 nathanw Exp $ */
      2  1.16.4.2  nathanw 
      3  1.16.4.2  nathanw /*
      4  1.16.4.2  nathanw  * Copyright (c) 1994,1998 Michael L. Hitch
      5  1.16.4.2  nathanw  * Copyright (c) 1990 The Regents of the University of California.
      6  1.16.4.2  nathanw  * All rights reserved.
      7  1.16.4.2  nathanw  *
      8  1.16.4.2  nathanw  * This code is derived from software contributed to Berkeley by
      9  1.16.4.2  nathanw  * Van Jacobson of Lawrence Berkeley Laboratory.
     10  1.16.4.2  nathanw  *
     11  1.16.4.2  nathanw  * Redistribution and use in source and binary forms, with or without
     12  1.16.4.2  nathanw  * modification, are permitted provided that the following conditions
     13  1.16.4.2  nathanw  * are met:
     14  1.16.4.2  nathanw  * 1. Redistributions of source code must retain the above copyright
     15  1.16.4.2  nathanw  *    notice, this list of conditions and the following disclaimer.
     16  1.16.4.2  nathanw  * 2. Redistributions in binary form must reproduce the above copyright
     17  1.16.4.2  nathanw  *    notice, this list of conditions and the following disclaimer in the
     18  1.16.4.2  nathanw  *    documentation and/or other materials provided with the distribution.
     19  1.16.4.2  nathanw  * 3. All advertising materials mentioning features or use of this software
     20  1.16.4.2  nathanw  *    must display the following acknowledgement:
     21  1.16.4.2  nathanw  *	This product includes software developed by the University of
     22  1.16.4.2  nathanw  *	California, Berkeley and its contributors.
     23  1.16.4.2  nathanw  * 4. Neither the name of the University nor the names of its contributors
     24  1.16.4.2  nathanw  *    may be used to endorse or promote products derived from this software
     25  1.16.4.2  nathanw  *    without specific prior written permission.
     26  1.16.4.2  nathanw  *
     27  1.16.4.2  nathanw  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     28  1.16.4.2  nathanw  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     29  1.16.4.2  nathanw  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     30  1.16.4.2  nathanw  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     31  1.16.4.2  nathanw  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     32  1.16.4.2  nathanw  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     33  1.16.4.2  nathanw  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     34  1.16.4.2  nathanw  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     35  1.16.4.2  nathanw  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     36  1.16.4.2  nathanw  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     37  1.16.4.2  nathanw  * SUCH DAMAGE.
     38  1.16.4.2  nathanw  *
     39  1.16.4.2  nathanw  *	@(#)siop.c	7.5 (Berkeley) 5/4/91
     40  1.16.4.2  nathanw  */
     41  1.16.4.2  nathanw 
     42  1.16.4.2  nathanw /*
     43  1.16.4.2  nathanw  * AMIGA 53C720/770 scsi adaptor driver
     44  1.16.4.2  nathanw  */
     45  1.16.4.2  nathanw 
     46  1.16.4.2  nathanw #include "opt_ddb.h"
     47  1.16.4.2  nathanw 
     48  1.16.4.2  nathanw #include <sys/cdefs.h>
     49  1.16.4.2  nathanw __KERNEL_RCSID(0, "$NetBSD: siop2.c,v 1.16.4.2 2002/02/28 04:07:00 nathanw Exp $");
     50  1.16.4.2  nathanw 
     51  1.16.4.2  nathanw #include <sys/param.h>
     52  1.16.4.2  nathanw #include <sys/systm.h>
     53  1.16.4.2  nathanw #include <sys/device.h>
     54  1.16.4.2  nathanw #include <sys/disklabel.h>
     55  1.16.4.2  nathanw #include <sys/dkstat.h>
     56  1.16.4.2  nathanw #include <sys/buf.h>
     57  1.16.4.2  nathanw #include <sys/malloc.h>
     58  1.16.4.2  nathanw #include <dev/scsipi/scsi_all.h>
     59  1.16.4.2  nathanw #include <dev/scsipi/scsipi_all.h>
     60  1.16.4.2  nathanw #include <dev/scsipi/scsiconf.h>
     61  1.16.4.2  nathanw #include <machine/cpu.h>
     62  1.16.4.2  nathanw #ifdef __m68k__
     63  1.16.4.2  nathanw #include <m68k/include/cacheops.h>
     64  1.16.4.2  nathanw #endif
     65  1.16.4.2  nathanw #include <amiga/amiga/custom.h>
     66  1.16.4.2  nathanw #include <amiga/amiga/isr.h>
     67  1.16.4.2  nathanw 
     68  1.16.4.2  nathanw #define ARCH_720
     69  1.16.4.2  nathanw 
     70  1.16.4.2  nathanw #include <amiga/dev/siopreg.h>
     71  1.16.4.2  nathanw #include <amiga/dev/siopvar.h>
     72  1.16.4.2  nathanw 
     73  1.16.4.2  nathanw /*
     74  1.16.4.2  nathanw  * SCSI delays
     75  1.16.4.2  nathanw  * In u-seconds, primarily for state changes on the SPC.
     76  1.16.4.2  nathanw  */
     77  1.16.4.2  nathanw #define	SCSI_CMD_WAIT	500000	/* wait per step of 'immediate' cmds */
     78  1.16.4.2  nathanw #define	SCSI_DATA_WAIT	500000	/* wait per data in/out step */
     79  1.16.4.2  nathanw #define	SCSI_INIT_WAIT	500000	/* wait per step (both) during init */
     80  1.16.4.2  nathanw 
     81  1.16.4.2  nathanw void siopng_select(struct siop_softc *);
     82  1.16.4.2  nathanw void siopngabort(struct siop_softc *, siop_regmap_p, char *);
     83  1.16.4.2  nathanw void siopngerror(struct siop_softc *, siop_regmap_p, u_char);
     84  1.16.4.2  nathanw int  siopng_checkintr(struct siop_softc *, u_char, u_char, u_short, int *);
     85  1.16.4.2  nathanw void siopngreset(struct siop_softc *);
     86  1.16.4.2  nathanw void siopngsetdelay(int);
     87  1.16.4.2  nathanw void siopng_scsidone(struct siop_acb *, int);
     88  1.16.4.2  nathanw void siopng_sched(struct siop_softc *);
     89  1.16.4.2  nathanw void siopng_poll(struct siop_softc *, struct siop_acb *);
     90  1.16.4.2  nathanw void siopngintr(struct siop_softc *);
     91  1.16.4.2  nathanw void scsi_period_to_siopng(struct siop_softc *, int);
     92  1.16.4.2  nathanw void siopng_start(struct siop_softc *, int, int, u_char *, int, u_char *, int);
     93  1.16.4.2  nathanw void siopng_dump_acb(struct siop_acb *);
     94  1.16.4.2  nathanw 
     95  1.16.4.2  nathanw /* 53C720/770 script */
     96  1.16.4.2  nathanw 
     97  1.16.4.2  nathanw #include <amiga/dev/siop2_script.out>
     98  1.16.4.2  nathanw 
     99  1.16.4.2  nathanw /* default to not inhibit sync negotiation on any drive */
    100  1.16.4.2  nathanw u_char siopng_inhibit_sync[16] = {
    101  1.16.4.2  nathanw 	0, 0, 0, 0,	0, 0, 0, 0,	0, 0, 0, 0,	0, 0, 0, 0
    102  1.16.4.2  nathanw }; /* initialize, so patchable */
    103  1.16.4.2  nathanw 
    104  1.16.4.2  nathanw u_char siopng_inhibit_wide[16] = {
    105  1.16.4.2  nathanw 	0, 0, 0, 0,	0, 0, 0, 0,	0, 0, 0, 0,	0, 0, 0, 0
    106  1.16.4.2  nathanw }; /* initialize, so patchable */
    107  1.16.4.2  nathanw 
    108  1.16.4.2  nathanw u_char siopng_allow_disc[16] = {
    109  1.16.4.2  nathanw 	3, 3, 3, 3,	3, 3, 3, 3,	3, 3, 3, 3,	3, 3, 3, 3
    110  1.16.4.2  nathanw };
    111  1.16.4.2  nathanw 
    112  1.16.4.2  nathanw int siopng_no_dma = 0;
    113  1.16.4.2  nathanw 
    114  1.16.4.2  nathanw int siopng_reset_delay = 250;	/* delay after reset, in milleseconds */
    115  1.16.4.2  nathanw 
    116  1.16.4.2  nathanw int siopng_cmd_wait = SCSI_CMD_WAIT;
    117  1.16.4.2  nathanw int siopng_data_wait = SCSI_DATA_WAIT;
    118  1.16.4.2  nathanw int siopng_init_wait = SCSI_INIT_WAIT;
    119  1.16.4.2  nathanw 
    120  1.16.4.2  nathanw #define DEBUG_SYNC
    121  1.16.4.2  nathanw 
    122  1.16.4.2  nathanw #ifdef DEBUG
    123  1.16.4.2  nathanw /*
    124  1.16.4.2  nathanw  *	0x01 - full debug
    125  1.16.4.2  nathanw  *	0x02 - DMA chaining
    126  1.16.4.2  nathanw  *	0x04 - siopngintr
    127  1.16.4.2  nathanw  *	0x08 - phase mismatch
    128  1.16.4.2  nathanw  *	0x10 - <not used>
    129  1.16.4.2  nathanw  *	0x20 - panic on unhandled exceptions
    130  1.16.4.2  nathanw  *	0x100 - disconnect/reselect
    131  1.16.4.2  nathanw  */
    132  1.16.4.2  nathanw int	siopng_debug = 0;
    133  1.16.4.2  nathanw int	siopngsync_debug = 0;
    134  1.16.4.2  nathanw int	siopngdma_hits = 0;
    135  1.16.4.2  nathanw int	siopngdma_misses = 0;
    136  1.16.4.2  nathanw int	siopngchain_ints = 0;
    137  1.16.4.2  nathanw int	siopngstarts = 0;
    138  1.16.4.2  nathanw int	siopngints = 0;
    139  1.16.4.2  nathanw int	siopngphmm = 0;
    140  1.16.4.2  nathanw #define SIOP_TRACE_SIZE	128
    141  1.16.4.2  nathanw #define SIOP_TRACE(a,b,c,d) \
    142  1.16.4.2  nathanw 	siopng_trbuf[siopng_trix] = (a); \
    143  1.16.4.2  nathanw 	siopng_trbuf[siopng_trix+1] = (b); \
    144  1.16.4.2  nathanw 	siopng_trbuf[siopng_trix+2] = (c); \
    145  1.16.4.2  nathanw 	siopng_trbuf[siopng_trix+3] = (d); \
    146  1.16.4.2  nathanw 	siopng_trix = (siopng_trix + 4) & (SIOP_TRACE_SIZE - 1);
    147  1.16.4.2  nathanw u_char	siopng_trbuf[SIOP_TRACE_SIZE];
    148  1.16.4.2  nathanw int	siopng_trix;
    149  1.16.4.2  nathanw void siopng_dump(struct siop_softc *);
    150  1.16.4.2  nathanw void siopng_dump_trace(void);
    151  1.16.4.2  nathanw #else
    152  1.16.4.2  nathanw #define SIOP_TRACE(a,b,c,d)
    153  1.16.4.2  nathanw #endif
    154  1.16.4.2  nathanw 
    155  1.16.4.2  nathanw 
    156  1.16.4.2  nathanw static char *siopng_chips[] = {
    157  1.16.4.2  nathanw 	"720", "720SE", "770", "0x3",
    158  1.16.4.2  nathanw 	"810A", "0x5", "0x6", "0x7",
    159  1.16.4.2  nathanw 	"0x8", "0x9", "0xA", "0xB",
    160  1.16.4.2  nathanw 	"0xC", "0xD", "0xE", "0xF",
    161  1.16.4.2  nathanw };
    162  1.16.4.2  nathanw 
    163  1.16.4.2  nathanw /*
    164  1.16.4.2  nathanw  * default minphys routine for siopng based controllers
    165  1.16.4.2  nathanw  */
    166  1.16.4.2  nathanw void
    167  1.16.4.2  nathanw siopng_minphys(struct buf *bp)
    168  1.16.4.2  nathanw {
    169  1.16.4.2  nathanw 
    170  1.16.4.2  nathanw 	/*
    171  1.16.4.2  nathanw 	 * No max transfer at this level.
    172  1.16.4.2  nathanw 	 */
    173  1.16.4.2  nathanw 	minphys(bp);
    174  1.16.4.2  nathanw }
    175  1.16.4.2  nathanw 
    176  1.16.4.2  nathanw /*
    177  1.16.4.2  nathanw  * used by specific siopng controller
    178  1.16.4.2  nathanw  *
    179  1.16.4.2  nathanw  */
    180  1.16.4.2  nathanw void
    181  1.16.4.2  nathanw siopng_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
    182  1.16.4.2  nathanw                       void *arg)
    183  1.16.4.2  nathanw {
    184  1.16.4.2  nathanw 	struct scsipi_xfer *xs;
    185  1.16.4.2  nathanw 	struct scsipi_periph *periph;
    186  1.16.4.2  nathanw 	struct siop_acb *acb;
    187  1.16.4.2  nathanw 	struct siop_softc *sc = (void *)chan->chan_adapter->adapt_dev;
    188  1.16.4.2  nathanw 	int flags, s;
    189  1.16.4.2  nathanw 
    190  1.16.4.2  nathanw 	switch (req) {
    191  1.16.4.2  nathanw 	case ADAPTER_REQ_RUN_XFER:
    192  1.16.4.2  nathanw 		xs = arg;
    193  1.16.4.2  nathanw 		periph = xs->xs_periph;
    194  1.16.4.2  nathanw 		flags = xs->xs_control;
    195  1.16.4.2  nathanw 
    196  1.16.4.2  nathanw 		/* XXXX ?? */
    197  1.16.4.2  nathanw 		if (flags & XS_CTL_DATA_UIO)
    198  1.16.4.2  nathanw 			panic("siopng: scsi data uio requested");
    199  1.16.4.2  nathanw 
    200  1.16.4.2  nathanw 		/* XXXX ?? */
    201  1.16.4.2  nathanw 		if (sc->sc_nexus && flags & XS_CTL_POLL)
    202  1.16.4.2  nathanw /*			panic("siopng_scsicmd: busy");*/
    203  1.16.4.2  nathanw 			printf("siopng_scsicmd: busy\n");
    204  1.16.4.2  nathanw 
    205  1.16.4.2  nathanw 		s = splbio();
    206  1.16.4.2  nathanw 		acb = sc->free_list.tqh_first;
    207  1.16.4.2  nathanw 		if (acb) {
    208  1.16.4.2  nathanw 			TAILQ_REMOVE(&sc->free_list, acb, chain);
    209  1.16.4.2  nathanw 		}
    210  1.16.4.2  nathanw 		splx(s);
    211  1.16.4.2  nathanw 
    212  1.16.4.2  nathanw #ifdef DIAGNOSTIC
    213  1.16.4.2  nathanw 		/*
    214  1.16.4.2  nathanw 		 * This should never happen as we track the resources
    215  1.16.4.2  nathanw 		 * in the mid-layer.
    216  1.16.4.2  nathanw 		 */
    217  1.16.4.2  nathanw 		if (acb == NULL) {
    218  1.16.4.2  nathanw 			scsipi_printaddr(periph);
    219  1.16.4.2  nathanw 			printf("unable to allocate acb\n");
    220  1.16.4.2  nathanw 			panic("siopng_scsipi_request");
    221  1.16.4.2  nathanw 		}
    222  1.16.4.2  nathanw #endif
    223  1.16.4.2  nathanw 		acb->flags = ACB_ACTIVE;
    224  1.16.4.2  nathanw 		acb->xs = xs;
    225  1.16.4.2  nathanw 		bcopy(xs->cmd, &acb->cmd, xs->cmdlen);
    226  1.16.4.2  nathanw 		acb->clen = xs->cmdlen;
    227  1.16.4.2  nathanw 		acb->daddr = xs->data;
    228  1.16.4.2  nathanw 		acb->dleft = xs->datalen;
    229  1.16.4.2  nathanw 
    230  1.16.4.2  nathanw 		s = splbio();
    231  1.16.4.2  nathanw 		TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain);
    232  1.16.4.2  nathanw 
    233  1.16.4.2  nathanw 		if (sc->sc_nexus == NULL)
    234  1.16.4.2  nathanw 			siopng_sched(sc);
    235  1.16.4.2  nathanw 
    236  1.16.4.2  nathanw 		splx(s);
    237  1.16.4.2  nathanw 
    238  1.16.4.2  nathanw 		if (flags & XS_CTL_POLL || siopng_no_dma)
    239  1.16.4.2  nathanw 			siopng_poll(sc, acb);
    240  1.16.4.2  nathanw 		return;
    241  1.16.4.2  nathanw 
    242  1.16.4.2  nathanw 	case ADAPTER_REQ_GROW_RESOURCES:
    243  1.16.4.2  nathanw 		return;
    244  1.16.4.2  nathanw 
    245  1.16.4.2  nathanw 	case ADAPTER_REQ_SET_XFER_MODE:
    246  1.16.4.2  nathanw 		return;
    247  1.16.4.2  nathanw 	}
    248  1.16.4.2  nathanw }
    249  1.16.4.2  nathanw 
    250  1.16.4.2  nathanw void
    251  1.16.4.2  nathanw siopng_poll(struct siop_softc *sc, struct siop_acb *acb)
    252  1.16.4.2  nathanw {
    253  1.16.4.2  nathanw 	siop_regmap_p rp = sc->sc_siopp;
    254  1.16.4.2  nathanw 	struct scsipi_xfer *xs = acb->xs;
    255  1.16.4.2  nathanw 	int i;
    256  1.16.4.2  nathanw 	int status;
    257  1.16.4.2  nathanw 	u_char istat;
    258  1.16.4.2  nathanw 	u_char dstat;
    259  1.16.4.2  nathanw 	u_short sist;
    260  1.16.4.2  nathanw 	int s;
    261  1.16.4.2  nathanw 	int to;
    262  1.16.4.2  nathanw 
    263  1.16.4.2  nathanw 	s = splbio();
    264  1.16.4.2  nathanw 	to = xs->timeout / 1000;
    265  1.16.4.2  nathanw 	if (sc->nexus_list.tqh_first)
    266  1.16.4.2  nathanw 		printf("%s: siopng_poll called with disconnected device\n",
    267  1.16.4.2  nathanw 		    sc->sc_dev.dv_xname);
    268  1.16.4.2  nathanw 	for (;;) {
    269  1.16.4.2  nathanw 		/* use cmd_wait values? */
    270  1.16.4.2  nathanw 		i = 50000;
    271  1.16.4.2  nathanw 		/* XXX spl0(); */
    272  1.16.4.2  nathanw 		while (((istat = rp->siop_istat) &
    273  1.16.4.2  nathanw 		    (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) {
    274  1.16.4.2  nathanw 			if (--i <= 0) {
    275  1.16.4.2  nathanw #ifdef DEBUG
    276  1.16.4.2  nathanw 				printf ("waiting: tgt %d cmd %02x sbcl %02x istat %02x sbdl %04x\n         dsp %lx (+%lx) dcmd %lx ds %p timeout %d\n",
    277  1.16.4.2  nathanw 				    xs->xs_periph->periph_target, acb->cmd.opcode,
    278  1.16.4.2  nathanw 				    rp->siop_sbcl, istat, rp->siop_sbdl, rp->siop_dsp,
    279  1.16.4.2  nathanw 				    rp->siop_dsp - sc->sc_scriptspa,
    280  1.16.4.2  nathanw 				    *((long *)&rp->siop_dcmd), &acb->ds, acb->xs->timeout);
    281  1.16.4.2  nathanw #endif
    282  1.16.4.2  nathanw 				i = 50000;
    283  1.16.4.2  nathanw 				--to;
    284  1.16.4.2  nathanw 				if (to <= 0) {
    285  1.16.4.2  nathanw 					siopngreset(sc);
    286  1.16.4.2  nathanw 					return;
    287  1.16.4.2  nathanw 				}
    288  1.16.4.2  nathanw 			}
    289  1.16.4.2  nathanw 			delay(20);
    290  1.16.4.2  nathanw 		}
    291  1.16.4.2  nathanw 		sist = rp->siop_sist;
    292  1.16.4.2  nathanw 		dstat = rp->siop_dstat;
    293  1.16.4.2  nathanw 		if (siopng_checkintr(sc, istat, dstat, sist, &status)) {
    294  1.16.4.2  nathanw 			if (acb != sc->sc_nexus)
    295  1.16.4.2  nathanw 				printf("%s: siopng_poll disconnected device completed\n",
    296  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname);
    297  1.16.4.2  nathanw 			else if ((sc->sc_flags & SIOP_INTDEFER) == 0) {
    298  1.16.4.2  nathanw 				sc->sc_flags &= ~SIOP_INTSOFF;
    299  1.16.4.2  nathanw 				rp->siop_sien = sc->sc_sien;
    300  1.16.4.2  nathanw 				rp->siop_dien = sc->sc_dien;
    301  1.16.4.2  nathanw 			}
    302  1.16.4.2  nathanw 			siopng_scsidone(sc->sc_nexus, status);
    303  1.16.4.2  nathanw 		}
    304  1.16.4.2  nathanw 		if (xs->xs_status & XS_STS_DONE)
    305  1.16.4.2  nathanw 			break;
    306  1.16.4.2  nathanw 	}
    307  1.16.4.2  nathanw 	splx(s);
    308  1.16.4.2  nathanw }
    309  1.16.4.2  nathanw 
    310  1.16.4.2  nathanw /*
    311  1.16.4.2  nathanw  * start next command that's ready
    312  1.16.4.2  nathanw  */
    313  1.16.4.2  nathanw void
    314  1.16.4.2  nathanw siopng_sched(struct siop_softc *sc)
    315  1.16.4.2  nathanw {
    316  1.16.4.2  nathanw 	struct scsipi_periph *periph;
    317  1.16.4.2  nathanw 	struct siop_acb *acb;
    318  1.16.4.2  nathanw 	int i;
    319  1.16.4.2  nathanw 
    320  1.16.4.2  nathanw #ifdef DEBUG
    321  1.16.4.2  nathanw 	if (sc->sc_nexus) {
    322  1.16.4.2  nathanw 		printf("%s: siopng_sched- nexus %p/%d ready %p/%d\n",
    323  1.16.4.2  nathanw 		    sc->sc_dev.dv_xname, sc->sc_nexus,
    324  1.16.4.2  nathanw 		    sc->sc_nexus->xs->xs_periph->periph_target,
    325  1.16.4.2  nathanw 		    sc->ready_list.tqh_first,
    326  1.16.4.2  nathanw 		    sc->ready_list.tqh_first->xs->xs_periph->periph_target);
    327  1.16.4.2  nathanw 		return;
    328  1.16.4.2  nathanw 	}
    329  1.16.4.2  nathanw #endif
    330  1.16.4.2  nathanw 	for (acb = sc->ready_list.tqh_first; acb; acb = acb->chain.tqe_next) {
    331  1.16.4.2  nathanw 		periph = acb->xs->xs_periph;
    332  1.16.4.2  nathanw 		i = periph->periph_target;
    333  1.16.4.2  nathanw 		if(!(sc->sc_tinfo[i].lubusy & (1 << periph->periph_lun))) {
    334  1.16.4.2  nathanw 			struct siop_tinfo *ti = &sc->sc_tinfo[i];
    335  1.16.4.2  nathanw 
    336  1.16.4.2  nathanw 			TAILQ_REMOVE(&sc->ready_list, acb, chain);
    337  1.16.4.2  nathanw 			sc->sc_nexus = acb;
    338  1.16.4.2  nathanw 			periph = acb->xs->xs_periph;
    339  1.16.4.2  nathanw 			ti = &sc->sc_tinfo[periph->periph_target];
    340  1.16.4.2  nathanw 			ti->lubusy |= (1 << periph->periph_lun);
    341  1.16.4.2  nathanw 			break;
    342  1.16.4.2  nathanw 		}
    343  1.16.4.2  nathanw 	}
    344  1.16.4.2  nathanw 
    345  1.16.4.2  nathanw 	if (acb == NULL) {
    346  1.16.4.2  nathanw #ifdef DEBUGXXX
    347  1.16.4.2  nathanw 		printf("%s: siopng_sched didn't find ready command\n",
    348  1.16.4.2  nathanw 		    sc->sc_dev.dv_xname);
    349  1.16.4.2  nathanw #endif
    350  1.16.4.2  nathanw 		return;
    351  1.16.4.2  nathanw 	}
    352  1.16.4.2  nathanw 
    353  1.16.4.2  nathanw 	if (acb->xs->xs_control & XS_CTL_RESET)
    354  1.16.4.2  nathanw 		siopngreset(sc);
    355  1.16.4.2  nathanw 
    356  1.16.4.2  nathanw #if 0
    357  1.16.4.2  nathanw 	acb->cmd.bytes[0] |= periph->periph_lun << 5;	/* XXXX */
    358  1.16.4.2  nathanw #endif
    359  1.16.4.2  nathanw 	++sc->sc_active;
    360  1.16.4.2  nathanw 	siopng_select(sc);
    361  1.16.4.2  nathanw }
    362  1.16.4.2  nathanw 
    363  1.16.4.2  nathanw void
    364  1.16.4.2  nathanw siopng_scsidone(struct siop_acb *acb, int stat)
    365  1.16.4.2  nathanw {
    366  1.16.4.2  nathanw 	struct scsipi_xfer *xs;
    367  1.16.4.2  nathanw 	struct scsipi_periph *periph;
    368  1.16.4.2  nathanw 	struct siop_softc *sc;
    369  1.16.4.2  nathanw 	int dosched = 0;
    370  1.16.4.2  nathanw 
    371  1.16.4.2  nathanw 	if (acb == NULL || (xs = acb->xs) == NULL) {
    372  1.16.4.2  nathanw #ifdef DIAGNOSTIC
    373  1.16.4.2  nathanw 		printf("siopng_scsidone: NULL acb or scsipi_xfer\n");
    374  1.16.4.2  nathanw #if defined(DEBUG) && defined(DDB)
    375  1.16.4.2  nathanw 		Debugger();
    376  1.16.4.2  nathanw #endif
    377  1.16.4.2  nathanw #endif
    378  1.16.4.2  nathanw 		return;
    379  1.16.4.2  nathanw 	}
    380  1.16.4.2  nathanw 	periph = xs->xs_periph;
    381  1.16.4.2  nathanw 	sc = (void *)periph->periph_channel->chan_adapter->adapt_dev;
    382  1.16.4.2  nathanw 
    383  1.16.4.2  nathanw 	xs->status = stat;
    384  1.16.4.2  nathanw 	xs->resid = 0;		/* XXXX */
    385  1.16.4.2  nathanw 
    386  1.16.4.2  nathanw 	if (xs->error == XS_NOERROR) {
    387  1.16.4.2  nathanw 		if (stat == SCSI_CHECK || stat == SCSI_BUSY)
    388  1.16.4.2  nathanw 			xs->error = XS_BUSY;
    389  1.16.4.2  nathanw 	}
    390  1.16.4.2  nathanw 
    391  1.16.4.2  nathanw 	/*
    392  1.16.4.2  nathanw 	 * Remove the ACB from whatever queue it's on.  We have to do a bit of
    393  1.16.4.2  nathanw 	 * a hack to figure out which queue it's on.  Note that it is *not*
    394  1.16.4.2  nathanw 	 * necessary to cdr down the ready queue, but we must cdr down the
    395  1.16.4.2  nathanw 	 * nexus queue and see if it's there, so we can mark the unit as no
    396  1.16.4.2  nathanw 	 * longer busy.  This code is sickening, but it works.
    397  1.16.4.2  nathanw 	 */
    398  1.16.4.2  nathanw 	if (acb == sc->sc_nexus) {
    399  1.16.4.2  nathanw 		sc->sc_nexus = NULL;
    400  1.16.4.2  nathanw 		sc->sc_tinfo[periph->periph_target].lubusy &=
    401  1.16.4.2  nathanw 			~(1<<periph->periph_lun);
    402  1.16.4.2  nathanw 		if (sc->ready_list.tqh_first)
    403  1.16.4.2  nathanw 			dosched = 1;	/* start next command */
    404  1.16.4.2  nathanw 		--sc->sc_active;
    405  1.16.4.2  nathanw 		SIOP_TRACE('d','a',stat,0)
    406  1.16.4.2  nathanw 	} else if (sc->ready_list.tqh_last == &acb->chain.tqe_next) {
    407  1.16.4.2  nathanw 		TAILQ_REMOVE(&sc->ready_list, acb, chain);
    408  1.16.4.2  nathanw 		SIOP_TRACE('d','r',stat,0)
    409  1.16.4.2  nathanw 	} else {
    410  1.16.4.2  nathanw 		register struct siop_acb *acb2;
    411  1.16.4.2  nathanw 		for (acb2 = sc->nexus_list.tqh_first; acb2;
    412  1.16.4.2  nathanw 		    acb2 = acb2->chain.tqe_next)
    413  1.16.4.2  nathanw 			if (acb2 == acb) {
    414  1.16.4.2  nathanw 				TAILQ_REMOVE(&sc->nexus_list, acb, chain);
    415  1.16.4.2  nathanw 				sc->sc_tinfo[periph->periph_target].lubusy
    416  1.16.4.2  nathanw 					&= ~(1<<periph->periph_lun);
    417  1.16.4.2  nathanw 				--sc->sc_active;
    418  1.16.4.2  nathanw 				break;
    419  1.16.4.2  nathanw 			}
    420  1.16.4.2  nathanw 		if (acb2)
    421  1.16.4.2  nathanw 			;
    422  1.16.4.2  nathanw 		else if (acb->chain.tqe_next) {
    423  1.16.4.2  nathanw 			TAILQ_REMOVE(&sc->ready_list, acb, chain);
    424  1.16.4.2  nathanw 			--sc->sc_active;
    425  1.16.4.2  nathanw 		} else {
    426  1.16.4.2  nathanw 			printf("%s: can't find matching acb\n",
    427  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname);
    428  1.16.4.2  nathanw #ifdef DDB
    429  1.16.4.2  nathanw /*			Debugger(); */
    430  1.16.4.2  nathanw #endif
    431  1.16.4.2  nathanw 		}
    432  1.16.4.2  nathanw 		SIOP_TRACE('d','n',stat,0);
    433  1.16.4.2  nathanw 	}
    434  1.16.4.2  nathanw 	/* Put it on the free list. */
    435  1.16.4.2  nathanw 	acb->flags = ACB_FREE;
    436  1.16.4.2  nathanw 	TAILQ_INSERT_HEAD(&sc->free_list, acb, chain);
    437  1.16.4.2  nathanw 
    438  1.16.4.2  nathanw 	sc->sc_tinfo[periph->periph_target].cmds++;
    439  1.16.4.2  nathanw 
    440  1.16.4.2  nathanw 	scsipi_done(xs);
    441  1.16.4.2  nathanw 
    442  1.16.4.2  nathanw 	if (dosched && sc->sc_nexus == NULL)
    443  1.16.4.2  nathanw 		siopng_sched(sc);
    444  1.16.4.2  nathanw }
    445  1.16.4.2  nathanw 
    446  1.16.4.2  nathanw void
    447  1.16.4.2  nathanw siopngabort(register struct siop_softc *sc, siop_regmap_p rp, char *where)
    448  1.16.4.2  nathanw {
    449  1.16.4.2  nathanw #ifdef fix_this
    450  1.16.4.2  nathanw 	int i;
    451  1.16.4.2  nathanw #endif
    452  1.16.4.2  nathanw 
    453  1.16.4.2  nathanw 	printf ("%s: abort %s: dstat %02x, istat %02x sist %04x sien %04x sbcl %02x\n",
    454  1.16.4.2  nathanw 	    sc->sc_dev.dv_xname,
    455  1.16.4.2  nathanw 	    where, rp->siop_dstat, rp->siop_istat, rp->siop_sist,
    456  1.16.4.2  nathanw 	    rp->siop_sien, rp->siop_sbcl);
    457  1.16.4.2  nathanw 	siopng_dump_registers(sc);
    458  1.16.4.2  nathanw 
    459  1.16.4.2  nathanw 	if (sc->sc_active > 0) {
    460  1.16.4.2  nathanw #ifdef TODO
    461  1.16.4.2  nathanw       SET_SBIC_cmd (rp, SBIC_CMD_ABORT);
    462  1.16.4.2  nathanw       WAIT_CIP (rp);
    463  1.16.4.2  nathanw 
    464  1.16.4.2  nathanw       GET_SBIC_asr (rp, asr);
    465  1.16.4.2  nathanw       if (asr & (SBIC_ASR_BSY|SBIC_ASR_LCI))
    466  1.16.4.2  nathanw         {
    467  1.16.4.2  nathanw           /* ok, get more drastic.. */
    468  1.16.4.2  nathanw 
    469  1.16.4.2  nathanw 	  SET_SBIC_cmd (rp, SBIC_CMD_RESET);
    470  1.16.4.2  nathanw 	  delay(25);
    471  1.16.4.2  nathanw 	  SBIC_WAIT(rp, SBIC_ASR_INT, 0);
    472  1.16.4.2  nathanw 	  GET_SBIC_csr (rp, csr);       /* clears interrupt also */
    473  1.16.4.2  nathanw 
    474  1.16.4.2  nathanw           return;
    475  1.16.4.2  nathanw         }
    476  1.16.4.2  nathanw 
    477  1.16.4.2  nathanw       do
    478  1.16.4.2  nathanw         {
    479  1.16.4.2  nathanw           SBIC_WAIT (rp, SBIC_ASR_INT, 0);
    480  1.16.4.2  nathanw           GET_SBIC_csr (rp, csr);
    481  1.16.4.2  nathanw         }
    482  1.16.4.2  nathanw       while ((csr != SBIC_CSR_DISC) && (csr != SBIC_CSR_DISC_1)
    483  1.16.4.2  nathanw 	      && (csr != SBIC_CSR_CMD_INVALID));
    484  1.16.4.2  nathanw #endif
    485  1.16.4.2  nathanw 
    486  1.16.4.2  nathanw 		/* lets just hope it worked.. */
    487  1.16.4.2  nathanw #ifdef fix_this
    488  1.16.4.2  nathanw 		for (i = 0; i < 2; ++i) {
    489  1.16.4.2  nathanw 			if (sc->sc_iob[i].sc_xs && &sc->sc_iob[i] !=
    490  1.16.4.2  nathanw 			    sc->sc_cur) {
    491  1.16.4.2  nathanw 				printf ("siopngabort: cleanup!\n");
    492  1.16.4.2  nathanw 				sc->sc_iob[i].sc_xs = NULL;
    493  1.16.4.2  nathanw 			}
    494  1.16.4.2  nathanw 		}
    495  1.16.4.2  nathanw #endif	/* fix_this */
    496  1.16.4.2  nathanw /*		sc->sc_active = 0; */
    497  1.16.4.2  nathanw 	}
    498  1.16.4.2  nathanw }
    499  1.16.4.2  nathanw 
    500  1.16.4.2  nathanw void
    501  1.16.4.2  nathanw siopnginitialize(struct siop_softc *sc)
    502  1.16.4.2  nathanw {
    503  1.16.4.2  nathanw 	int i;
    504  1.16.4.2  nathanw 	u_int inhibit_sync;
    505  1.16.4.2  nathanw 	extern u_long scsi_nosync;
    506  1.16.4.2  nathanw 	extern int shift_nosync;
    507  1.16.4.2  nathanw 
    508  1.16.4.2  nathanw 	/*
    509  1.16.4.2  nathanw 	 * Need to check that scripts is on a long word boundary
    510  1.16.4.2  nathanw 	 * Also should verify that dev doesn't span non-contiguous
    511  1.16.4.2  nathanw 	 * physical pages.
    512  1.16.4.2  nathanw 	 */
    513  1.16.4.2  nathanw 	sc->sc_scriptspa = kvtop((caddr_t)siopng_scripts);
    514  1.16.4.2  nathanw 
    515  1.16.4.2  nathanw 	/*
    516  1.16.4.2  nathanw 	 * malloc sc_acb to ensure that DS is on a long word boundary.
    517  1.16.4.2  nathanw 	 */
    518  1.16.4.2  nathanw 
    519  1.16.4.2  nathanw 	MALLOC(sc->sc_acb, struct siop_acb *,
    520  1.16.4.2  nathanw 		sizeof(struct siop_acb) * SIOP_NACB, M_DEVBUF, M_NOWAIT);
    521  1.16.4.2  nathanw 	if (sc->sc_acb == NULL)
    522  1.16.4.2  nathanw 		panic("siopnginitialize: ACB malloc failed!");
    523  1.16.4.2  nathanw 
    524  1.16.4.2  nathanw 	sc->sc_tcp[1] = 1000 / sc->sc_clock_freq;
    525  1.16.4.2  nathanw 	sc->sc_tcp[2] = 1500 / sc->sc_clock_freq;
    526  1.16.4.2  nathanw 	sc->sc_tcp[3] = 2000 / sc->sc_clock_freq;
    527  1.16.4.2  nathanw 	sc->sc_minsync = sc->sc_tcp[1];		/* in 4ns units */
    528  1.16.4.2  nathanw 	if (sc->sc_minsync < 25)
    529  1.16.4.2  nathanw 		sc->sc_minsync = 25;
    530  1.16.4.2  nathanw 	sc->sc_minsync >>= 1;			/* Using clock doubler, allow Ultra */
    531  1.16.4.2  nathanw 	if (sc->sc_clock_freq <= 25) {
    532  1.16.4.2  nathanw 		sc->sc_dcntl |= 0x80;		/* SCLK/1 */
    533  1.16.4.2  nathanw 		sc->sc_tcp[0] = sc->sc_tcp[1];
    534  1.16.4.2  nathanw 	} else if (sc->sc_clock_freq <= 37) {
    535  1.16.4.2  nathanw 		sc->sc_dcntl |= 0x40;		/* SCLK/1.5 */
    536  1.16.4.2  nathanw 		sc->sc_tcp[0] = sc->sc_tcp[2];
    537  1.16.4.2  nathanw 	} else if (sc->sc_clock_freq <= 50) {
    538  1.16.4.2  nathanw 		sc->sc_dcntl |= 0x00;		/* SCLK/2 */
    539  1.16.4.2  nathanw 		sc->sc_tcp[0] = sc->sc_tcp[3];
    540  1.16.4.2  nathanw 	} else {
    541  1.16.4.2  nathanw 		sc->sc_dcntl |= 0xc0;		/* SCLK/3 */
    542  1.16.4.2  nathanw 		sc->sc_tcp[0] = 3000 / sc->sc_clock_freq;
    543  1.16.4.2  nathanw 	}
    544  1.16.4.2  nathanw 
    545  1.16.4.2  nathanw 	if (scsi_nosync) {
    546  1.16.4.2  nathanw 		inhibit_sync = (scsi_nosync >> shift_nosync) & 0xffff;
    547  1.16.4.2  nathanw 		shift_nosync += 16;		/* XXX maxtarget */
    548  1.16.4.2  nathanw #ifdef DEBUG
    549  1.16.4.2  nathanw 		if (inhibit_sync)
    550  1.16.4.2  nathanw 			printf("%s: Inhibiting synchronous transfer %02x\n",
    551  1.16.4.2  nathanw 				sc->sc_dev.dv_xname, inhibit_sync);
    552  1.16.4.2  nathanw #endif
    553  1.16.4.2  nathanw 		for (i = 0; i < 16; ++i)		/* XXX maxtarget */
    554  1.16.4.2  nathanw 			if (inhibit_sync & (1 << i))
    555  1.16.4.2  nathanw 				siopng_inhibit_sync[i] = 1;
    556  1.16.4.2  nathanw 	}
    557  1.16.4.2  nathanw 
    558  1.16.4.2  nathanw 	siopngreset (sc);
    559  1.16.4.2  nathanw }
    560  1.16.4.2  nathanw 
    561  1.16.4.2  nathanw void
    562  1.16.4.2  nathanw siopngreset(struct siop_softc *sc)
    563  1.16.4.2  nathanw {
    564  1.16.4.2  nathanw 	siop_regmap_p rp;
    565  1.16.4.2  nathanw 	u_int i, s;
    566  1.16.4.2  nathanw 	u_short  dummy;
    567  1.16.4.2  nathanw 	struct siop_acb *acb;
    568  1.16.4.2  nathanw 
    569  1.16.4.2  nathanw 	rp = sc->sc_siopp;
    570  1.16.4.2  nathanw 
    571  1.16.4.2  nathanw 	if (sc->sc_flags & SIOP_ALIVE)
    572  1.16.4.2  nathanw 		siopngabort(sc, rp, "reset");
    573  1.16.4.2  nathanw 
    574  1.16.4.2  nathanw 	printf("%s: ", sc->sc_dev.dv_xname);		/* XXXX */
    575  1.16.4.2  nathanw 
    576  1.16.4.2  nathanw 	s = splbio();
    577  1.16.4.2  nathanw 
    578  1.16.4.2  nathanw 	/*
    579  1.16.4.2  nathanw 	 * Reset the chip
    580  1.16.4.2  nathanw 	 * XXX - is this really needed?
    581  1.16.4.2  nathanw 	 */
    582  1.16.4.2  nathanw 	rp->siop_istat |= SIOP_ISTAT_ABRT;	/* abort current script */
    583  1.16.4.2  nathanw 	rp->siop_istat |= SIOP_ISTAT_RST;		/* reset chip */
    584  1.16.4.2  nathanw 	rp->siop_istat &= ~SIOP_ISTAT_RST;
    585  1.16.4.2  nathanw 	/*
    586  1.16.4.2  nathanw 	 * Reset SCSI bus (do we really want this?)
    587  1.16.4.2  nathanw 	 */
    588  1.16.4.2  nathanw 	rp->siop_sien = 0;
    589  1.16.4.2  nathanw 	rp->siop_scntl1 |= SIOP_SCNTL1_RST;
    590  1.16.4.2  nathanw 	delay(1);
    591  1.16.4.2  nathanw 	rp->siop_scntl1 &= ~SIOP_SCNTL1_RST;
    592  1.16.4.2  nathanw 
    593  1.16.4.2  nathanw 	/*
    594  1.16.4.2  nathanw 	 * Set up various chip parameters
    595  1.16.4.2  nathanw 	 */
    596  1.16.4.2  nathanw 	rp->siop_stest1 |= SIOP_STEST1_DBLEN;	/* SCLK doubler enable */
    597  1.16.4.2  nathanw 	delay(20);
    598  1.16.4.2  nathanw 	rp->siop_stest3 |= SIOP_STEST3_HSC;	/* Halt SCSI clock */
    599  1.16.4.2  nathanw 	rp->siop_scntl3 = 0x15;			/* SCF/CCF*/
    600  1.16.4.2  nathanw 	rp->siop_stest1 |= SIOP_STEST1_DBLSEL;	/* SCLK doubler select */
    601  1.16.4.2  nathanw 	rp->siop_stest3 &= ~SIOP_STEST3_HSC;	/* Clear Halt SCSI clock */
    602  1.16.4.2  nathanw 	rp->siop_scntl0 = SIOP_ARB_FULL | /*SIOP_SCNTL0_EPC |*/ SIOP_SCNTL0_EPG;
    603  1.16.4.2  nathanw 	rp->siop_dcntl = sc->sc_dcntl;
    604  1.16.4.2  nathanw 	rp->siop_dmode = 0xc0;		/* XXX burst length */
    605  1.16.4.2  nathanw 	rp->siop_sien = 0x00;	/* don't enable interrupts yet */
    606  1.16.4.2  nathanw 	rp->siop_dien = 0x00;	/* don't enable interrupts yet */
    607  1.16.4.2  nathanw 	rp->siop_scid = sc->sc_channel.chan_id |
    608  1.16.4.2  nathanw 	    SIOP_SCID_RRE | SIOP_SCID_SRE;
    609  1.16.4.2  nathanw 	rp->siop_respid = 1 << sc->sc_channel.chan_id;
    610  1.16.4.2  nathanw 	rp->siop_dwt = 0x00;
    611  1.16.4.2  nathanw 	rp->siop_stime0 = 0x0c;		/* XXXXX check */
    612  1.16.4.2  nathanw 
    613  1.16.4.2  nathanw 	/* will need to re-negotiate sync xfers */
    614  1.16.4.2  nathanw 	bzero(&sc->sc_sync, sizeof (sc->sc_sync));
    615  1.16.4.2  nathanw 
    616  1.16.4.2  nathanw 	i = rp->siop_istat;
    617  1.16.4.2  nathanw 	if (i & SIOP_ISTAT_SIP)
    618  1.16.4.2  nathanw 		dummy = rp->siop_sist;
    619  1.16.4.2  nathanw 	if (i & SIOP_ISTAT_DIP)
    620  1.16.4.2  nathanw 		dummy = rp->siop_dstat;
    621  1.16.4.2  nathanw 
    622  1.16.4.2  nathanw 	splx (s);
    623  1.16.4.2  nathanw 
    624  1.16.4.2  nathanw 	delay (siopng_reset_delay * 1000);
    625  1.16.4.2  nathanw 
    626  1.16.4.2  nathanw 	/*
    627  1.16.4.2  nathanw 	 * is lower half unterminated?
    628  1.16.4.2  nathanw 	 */
    629  1.16.4.2  nathanw 	if ((rp->siop_sbdl & 0x00ff) == 0x00ff) {
    630  1.16.4.2  nathanw 		printf(" no SCSI termination, host adapter deactivated.\n");
    631  1.16.4.2  nathanw 		sc->sc_channel.chan_ntargets = 0;	/* XXX */
    632  1.16.4.2  nathanw 		sc->sc_flags &= ~(SIOP_ALIVE|SIOP_INTDEFER|SIOP_INTSOFF);
    633  1.16.4.2  nathanw 		/* disable SCSI and DMA interrupts */
    634  1.16.4.2  nathanw 		sc->sc_sien = 0;
    635  1.16.4.2  nathanw 		sc->sc_dien = 0;
    636  1.16.4.2  nathanw 		rp->siop_sien = sc->sc_sien;
    637  1.16.4.2  nathanw 		rp->siop_dien = sc->sc_dien;
    638  1.16.4.2  nathanw 
    639  1.16.4.2  nathanw 		return;
    640  1.16.4.2  nathanw 	}
    641  1.16.4.2  nathanw 
    642  1.16.4.2  nathanw 	/*
    643  1.16.4.2  nathanw 	 * Check if upper half of SCSI bus is unterminated, and disallow
    644  1.16.4.2  nathanw 	 * disconnections if it appears to be unterminated.
    645  1.16.4.2  nathanw 	 */
    646  1.16.4.2  nathanw 	if ((rp->siop_sbdl & 0xff00) == 0xff00) {
    647  1.16.4.2  nathanw 		printf(" NO WIDE TERM");
    648  1.16.4.2  nathanw 		/* XXX need to restrict maximum target ID as well? */
    649  1.16.4.2  nathanw 		sc->sc_channel.chan_ntargets = 8;
    650  1.16.4.2  nathanw 		for (i = 0; i < 16; ++i) {
    651  1.16.4.2  nathanw 			siopng_allow_disc[i] = 0;
    652  1.16.4.2  nathanw 			siopng_inhibit_wide[i] |= 0x80;
    653  1.16.4.2  nathanw 		}
    654  1.16.4.2  nathanw 	}
    655  1.16.4.2  nathanw 
    656  1.16.4.2  nathanw 	printf("siopng type %s id %d reset V%d\n",
    657  1.16.4.2  nathanw 	    siopng_chips[rp->siop_macntl>>4],
    658  1.16.4.2  nathanw 	    sc->sc_channel.chan_ntargets,
    659  1.16.4.2  nathanw 	    rp->siop_ctest3 >> 4);
    660  1.16.4.2  nathanw 
    661  1.16.4.2  nathanw 	if ((sc->sc_flags & SIOP_ALIVE) == 0) {
    662  1.16.4.2  nathanw 		TAILQ_INIT(&sc->ready_list);
    663  1.16.4.2  nathanw 		TAILQ_INIT(&sc->nexus_list);
    664  1.16.4.2  nathanw 		TAILQ_INIT(&sc->free_list);
    665  1.16.4.2  nathanw 		sc->sc_nexus = NULL;
    666  1.16.4.2  nathanw 		acb = sc->sc_acb;
    667  1.16.4.2  nathanw 		bzero(acb, sizeof(struct siop_acb) * SIOP_NACB);
    668  1.16.4.2  nathanw 		for (i = 0; i < SIOP_NACB; i++) {
    669  1.16.4.2  nathanw 			TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
    670  1.16.4.2  nathanw 			acb++;
    671  1.16.4.2  nathanw 		}
    672  1.16.4.2  nathanw 		bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
    673  1.16.4.2  nathanw 	} else {
    674  1.16.4.2  nathanw 		if (sc->sc_nexus != NULL) {
    675  1.16.4.2  nathanw 			sc->sc_nexus->xs->error = XS_RESET;
    676  1.16.4.2  nathanw 			siopng_scsidone(sc->sc_nexus, sc->sc_nexus->stat[0]);
    677  1.16.4.2  nathanw 		}
    678  1.16.4.2  nathanw 		while ((acb = sc->nexus_list.tqh_first) > 0) {
    679  1.16.4.2  nathanw 			acb->xs->error = XS_RESET;
    680  1.16.4.2  nathanw 			siopng_scsidone(acb, acb->stat[0]);
    681  1.16.4.2  nathanw 		}
    682  1.16.4.2  nathanw 	}
    683  1.16.4.2  nathanw 
    684  1.16.4.2  nathanw 	sc->sc_flags |= SIOP_ALIVE;
    685  1.16.4.2  nathanw 	sc->sc_flags &= ~(SIOP_INTDEFER|SIOP_INTSOFF);
    686  1.16.4.2  nathanw 	/* enable SCSI and DMA interrupts */
    687  1.16.4.2  nathanw 	sc->sc_sien = SIOP_SIEN_MA | SIOP_SIEN_STO | /*SIOP_SIEN_GEN |*/
    688  1.16.4.2  nathanw 	    /*SIOP_SIEN_SEL |*/ SIOP_SIEN_SGE | SIOP_SIEN_UDC |
    689  1.16.4.2  nathanw 	     SIOP_SIEN_RST | SIOP_SIEN_PAR;
    690  1.16.4.2  nathanw 	sc->sc_dien = SIOP_DIEN_BF | SIOP_DIEN_ABRT | SIOP_DIEN_SIR |
    691  1.16.4.2  nathanw 	    /*SIOP_DIEN_WTD |*/ SIOP_DIEN_IID;
    692  1.16.4.2  nathanw 	rp->siop_sien = sc->sc_sien;
    693  1.16.4.2  nathanw 	rp->siop_dien = sc->sc_dien;
    694  1.16.4.2  nathanw 	/*siopng_dump_registers(sc);*/
    695  1.16.4.2  nathanw }
    696  1.16.4.2  nathanw 
    697  1.16.4.2  nathanw /*
    698  1.16.4.2  nathanw  * Setup Data Storage for 53C720/770 and start SCRIPTS processing
    699  1.16.4.2  nathanw  */
    700  1.16.4.2  nathanw 
    701  1.16.4.2  nathanw void
    702  1.16.4.2  nathanw siopng_start(struct siop_softc *sc, int target, int lun, u_char *cbuf,
    703  1.16.4.2  nathanw              int clen, u_char *buf, int len)
    704  1.16.4.2  nathanw {
    705  1.16.4.2  nathanw 	siop_regmap_p rp = sc->sc_siopp;
    706  1.16.4.2  nathanw 	int nchain;
    707  1.16.4.2  nathanw 	int count, tcount;
    708  1.16.4.2  nathanw 	char *addr, *dmaend;
    709  1.16.4.2  nathanw 	struct siop_acb *acb = sc->sc_nexus;
    710  1.16.4.2  nathanw #ifdef DEBUG
    711  1.16.4.2  nathanw 	int i;
    712  1.16.4.2  nathanw #endif
    713  1.16.4.2  nathanw 
    714  1.16.4.2  nathanw #ifdef DEBUG
    715  1.16.4.2  nathanw 	if (siopng_debug & 0x100 && rp->siop_sbcl & SIOP_BSY) {
    716  1.16.4.2  nathanw 		printf ("ACK! siopng was busy: rp %p script %p dsa %p active %ld\n",
    717  1.16.4.2  nathanw 		    rp, &siopng_scripts, &acb->ds, sc->sc_active);
    718  1.16.4.2  nathanw 		printf ("istat %02x sfbr %02x respid %02x sien %04x dien %02x\n",
    719  1.16.4.2  nathanw 		    rp->siop_istat, rp->siop_sfbr, rp->siop_respid,
    720  1.16.4.2  nathanw 		    rp->siop_sien, rp->siop_dien);
    721  1.16.4.2  nathanw #ifdef DDB
    722  1.16.4.2  nathanw 		/*Debugger();*/
    723  1.16.4.2  nathanw #endif
    724  1.16.4.2  nathanw 	}
    725  1.16.4.2  nathanw #endif
    726  1.16.4.2  nathanw 	acb->msgout[0] = MSG_IDENTIFY | lun;
    727  1.16.4.2  nathanw 	if (siopng_allow_disc[target] & 2 ||
    728  1.16.4.2  nathanw 	    (siopng_allow_disc[target] && len == 0))
    729  1.16.4.2  nathanw 		acb->msgout[0] = MSG_IDENTIFY_DR | lun;
    730  1.16.4.2  nathanw 	acb->status = 0;
    731  1.16.4.2  nathanw 	acb->stat[0] = -1;
    732  1.16.4.2  nathanw 	acb->msg[0] = -1;
    733  1.16.4.2  nathanw 	acb->ds.scsi_addr = (target << 16) | (sc->sc_sync[target].sxfer << 8) |
    734  1.16.4.2  nathanw 	    (sc->sc_sync[target].scntl3 << 24);
    735  1.16.4.2  nathanw 	acb->ds.idlen = 1;
    736  1.16.4.2  nathanw 	acb->ds.idbuf = (char *) kvtop(&acb->msgout[0]);
    737  1.16.4.2  nathanw 	acb->ds.cmdlen = clen;
    738  1.16.4.2  nathanw 	acb->ds.cmdbuf = (char *) kvtop(cbuf);
    739  1.16.4.2  nathanw 	acb->ds.stslen = 1;
    740  1.16.4.2  nathanw 	acb->ds.stsbuf = (char *) kvtop(&acb->stat[0]);
    741  1.16.4.2  nathanw 	acb->ds.msglen = 1;
    742  1.16.4.2  nathanw 	acb->ds.msgbuf = (char *) kvtop(&acb->msg[0]);
    743  1.16.4.2  nathanw 	acb->msg[1] = -1;
    744  1.16.4.2  nathanw 	acb->ds.msginlen = 1;
    745  1.16.4.2  nathanw 	acb->ds.extmsglen = 1;
    746  1.16.4.2  nathanw 	acb->ds.synmsglen = 3;
    747  1.16.4.2  nathanw 	acb->ds.msginbuf = acb->ds.msgbuf + 1;
    748  1.16.4.2  nathanw 	acb->ds.extmsgbuf = acb->ds.msginbuf + 1;
    749  1.16.4.2  nathanw 	acb->ds.synmsgbuf = acb->ds.extmsgbuf + 1;
    750  1.16.4.2  nathanw 	bzero(&acb->ds.chain, sizeof (acb->ds.chain));
    751  1.16.4.2  nathanw 
    752  1.16.4.2  nathanw 	if (sc->sc_sync[target].state == NEG_WIDE) {
    753  1.16.4.2  nathanw 		if (siopng_inhibit_wide[target]) {
    754  1.16.4.2  nathanw 			sc->sc_sync[target].state = NEG_SYNC;
    755  1.16.4.2  nathanw 			sc->sc_sync[target].scntl3 &= ~SIOP_SCNTL3_EWS;
    756  1.16.4.2  nathanw #ifdef DEBUG
    757  1.16.4.2  nathanw 			if (siopngsync_debug)
    758  1.16.4.2  nathanw 				printf ("Forcing target %d narrow\n", target);
    759  1.16.4.2  nathanw #endif
    760  1.16.4.2  nathanw 		}
    761  1.16.4.2  nathanw 		else {
    762  1.16.4.2  nathanw 			sc->sc_sync[target].scntl3 = 0x15 |	/* XXX */
    763  1.16.4.2  nathanw 			    (sc->sc_sync[target].scntl3 & 0x88);	/* XXX */
    764  1.16.4.2  nathanw 			acb->msg[2] = -1;
    765  1.16.4.2  nathanw 			acb->msgout[1] = MSG_EXT_MESSAGE;
    766  1.16.4.2  nathanw 			acb->msgout[2] = 2;
    767  1.16.4.2  nathanw 			acb->msgout[3] = MSG_WIDE_REQ;
    768  1.16.4.2  nathanw 			acb->msgout[4] = 1;
    769  1.16.4.2  nathanw 			acb->ds.idlen = 5;
    770  1.16.4.2  nathanw 			acb->ds.synmsglen = 2;
    771  1.16.4.2  nathanw 			sc->sc_sync[target].state = NEG_WAITW;
    772  1.16.4.2  nathanw #ifdef DEBUG
    773  1.16.4.2  nathanw 			if (siopngsync_debug)
    774  1.16.4.2  nathanw 				printf("Sending wide request to target %d\n", target);
    775  1.16.4.2  nathanw #endif
    776  1.16.4.2  nathanw 		}
    777  1.16.4.2  nathanw 	}
    778  1.16.4.2  nathanw 	if (sc->sc_sync[target].state == NEG_SYNC) {
    779  1.16.4.2  nathanw 		if (siopng_inhibit_sync[target]) {
    780  1.16.4.2  nathanw 			sc->sc_sync[target].state = NEG_DONE;
    781  1.16.4.2  nathanw 			sc->sc_sync[target].scntl3 = 5 |		/* XXX */
    782  1.16.4.2  nathanw 			    (sc->sc_sync[target].scntl3 & 0x88);	/* XXX */
    783  1.16.4.2  nathanw 			sc->sc_sync[target].sxfer = 0;
    784  1.16.4.2  nathanw #ifdef DEBUG
    785  1.16.4.2  nathanw 			if (siopngsync_debug)
    786  1.16.4.2  nathanw 				printf ("Forcing target %d asynchronous\n", target);
    787  1.16.4.2  nathanw #endif
    788  1.16.4.2  nathanw 		}
    789  1.16.4.2  nathanw 		else {
    790  1.16.4.2  nathanw 			sc->sc_sync[target].scntl3 = 0x15 |	/* XXX */
    791  1.16.4.2  nathanw 			    (sc->sc_sync[target].scntl3 & 0x88);	/* XXX */
    792  1.16.4.2  nathanw 			acb->msg[2] = -1;
    793  1.16.4.2  nathanw 			acb->msgout[1] = MSG_EXT_MESSAGE;
    794  1.16.4.2  nathanw 			acb->msgout[2] = 3;
    795  1.16.4.2  nathanw 			acb->msgout[3] = MSG_SYNC_REQ;
    796  1.16.4.2  nathanw #ifdef MAXTOR_SYNC_KLUDGE
    797  1.16.4.2  nathanw 			acb->msgout[4] = 50 / 4;	/* ask for ridiculous period */
    798  1.16.4.2  nathanw #else
    799  1.16.4.2  nathanw 			acb->msgout[4] = sc->sc_minsync;
    800  1.16.4.2  nathanw #endif
    801  1.16.4.2  nathanw 			acb->msgout[5] = SIOP_MAX_OFFSET;
    802  1.16.4.2  nathanw 			acb->ds.idlen = 6;
    803  1.16.4.2  nathanw 			sc->sc_sync[target].state = NEG_WAITS;
    804  1.16.4.2  nathanw #ifdef DEBUG
    805  1.16.4.2  nathanw 			if (siopngsync_debug)
    806  1.16.4.2  nathanw 				printf ("Sending sync request to target %d\n", target);
    807  1.16.4.2  nathanw #endif
    808  1.16.4.2  nathanw 		}
    809  1.16.4.2  nathanw 	}
    810  1.16.4.2  nathanw 
    811  1.16.4.2  nathanw /*
    812  1.16.4.2  nathanw  * Build physical DMA addresses for scatter/gather I/O
    813  1.16.4.2  nathanw  */
    814  1.16.4.2  nathanw 	acb->iob_buf = buf;
    815  1.16.4.2  nathanw 	acb->iob_len = len;
    816  1.16.4.2  nathanw 	acb->iob_curbuf = acb->iob_curlen = 0;
    817  1.16.4.2  nathanw 	nchain = 0;
    818  1.16.4.2  nathanw 	count = len;
    819  1.16.4.2  nathanw 	addr = buf;
    820  1.16.4.2  nathanw 	dmaend = NULL;
    821  1.16.4.2  nathanw 	while (count > 0) {
    822  1.16.4.2  nathanw 		acb->ds.chain[nchain].databuf = (char *) kvtop (addr);
    823  1.16.4.2  nathanw 		if (count < (tcount = NBPG - ((int) addr & PGOFSET)))
    824  1.16.4.2  nathanw 			tcount = count;
    825  1.16.4.2  nathanw 
    826  1.16.4.2  nathanw #if DEBUG_ONLY_IF_DESPERATE
    827  1.16.4.2  nathanw 		printf("chain[%d]: count %d tcount %d vaddr %p paddr %p\n",
    828  1.16.4.2  nathanw 			nchain, count, tcount, addr,
    829  1.16.4.2  nathanw 			acb->ds.chain[nchain].databuf);
    830  1.16.4.2  nathanw #endif
    831  1.16.4.2  nathanw 		acb->ds.chain[nchain].datalen = tcount;
    832  1.16.4.2  nathanw 		addr += tcount;
    833  1.16.4.2  nathanw 		count -= tcount;
    834  1.16.4.2  nathanw 		if (acb->ds.chain[nchain].databuf == dmaend) {
    835  1.16.4.2  nathanw 			dmaend += acb->ds.chain[nchain].datalen;
    836  1.16.4.2  nathanw 			acb->ds.chain[nchain].datalen = 0;
    837  1.16.4.2  nathanw 			acb->ds.chain[--nchain].datalen += tcount;
    838  1.16.4.2  nathanw #ifdef DEBUG
    839  1.16.4.2  nathanw 			++siopngdma_hits;
    840  1.16.4.2  nathanw #endif
    841  1.16.4.2  nathanw 		}
    842  1.16.4.2  nathanw 		else {
    843  1.16.4.2  nathanw 			dmaend = acb->ds.chain[nchain].databuf +
    844  1.16.4.2  nathanw 			    acb->ds.chain[nchain].datalen;
    845  1.16.4.2  nathanw 			acb->ds.chain[nchain].datalen = tcount;
    846  1.16.4.2  nathanw #ifdef DEBUG
    847  1.16.4.2  nathanw 			if (nchain)	/* Don't count miss on first one */
    848  1.16.4.2  nathanw 				++siopngdma_misses;
    849  1.16.4.2  nathanw #endif
    850  1.16.4.2  nathanw 		}
    851  1.16.4.2  nathanw 		++nchain;
    852  1.16.4.2  nathanw 	}
    853  1.16.4.2  nathanw #ifdef DEBUG
    854  1.16.4.2  nathanw 	if (nchain != 1 && len != 0 && siopng_debug & 3) {
    855  1.16.4.2  nathanw 		printf ("DMA chaining set: %d\n", nchain);
    856  1.16.4.2  nathanw 		for (i = 0; i < nchain; ++i) {
    857  1.16.4.2  nathanw 			printf ("  [%d] %8p %lx\n", i, acb->ds.chain[i].databuf,
    858  1.16.4.2  nathanw 			    acb->ds.chain[i].datalen);
    859  1.16.4.2  nathanw 		}
    860  1.16.4.2  nathanw 	}
    861  1.16.4.2  nathanw #endif
    862  1.16.4.2  nathanw 
    863  1.16.4.2  nathanw 	/* push data cache for all data the 53c720/770 needs to access */
    864  1.16.4.2  nathanw 	dma_cachectl ((caddr_t)acb, sizeof (struct siop_acb));
    865  1.16.4.2  nathanw 	dma_cachectl (cbuf, clen);
    866  1.16.4.2  nathanw 	if (buf != NULL && len != 0)
    867  1.16.4.2  nathanw 		dma_cachectl (buf, len);
    868  1.16.4.2  nathanw #ifdef DEBUG
    869  1.16.4.2  nathanw 	if (siopng_debug & 0x100 && rp->siop_sbcl & SIOP_BSY) {
    870  1.16.4.2  nathanw 		printf ("ACK! siopng was busy at start: rp %p script %p dsa %p active %ld\n",
    871  1.16.4.2  nathanw 		    rp, &siopng_scripts, &acb->ds, sc->sc_active);
    872  1.16.4.2  nathanw #ifdef DDB
    873  1.16.4.2  nathanw 		/*Debugger();*/
    874  1.16.4.2  nathanw #endif
    875  1.16.4.2  nathanw 	}
    876  1.16.4.2  nathanw #endif
    877  1.16.4.2  nathanw 	if (sc->nexus_list.tqh_first == NULL) {
    878  1.16.4.2  nathanw 		if (rp->siop_istat & SIOP_ISTAT_CON)
    879  1.16.4.2  nathanw 			printf("%s: siopng_select while connected?\n",
    880  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname);
    881  1.16.4.2  nathanw 		rp->siop_temp = 0;
    882  1.16.4.2  nathanw #ifndef FIXME
    883  1.16.4.2  nathanw 		rp->siop_scntl3 = sc->sc_sync[target].scntl3;
    884  1.16.4.2  nathanw #endif
    885  1.16.4.2  nathanw 		rp->siop_dsa = kvtop((caddr_t)&acb->ds);
    886  1.16.4.2  nathanw 		rp->siop_dsp = sc->sc_scriptspa;
    887  1.16.4.2  nathanw 		SIOP_TRACE('s',1,0,0)
    888  1.16.4.2  nathanw 	} else {
    889  1.16.4.2  nathanw 		if ((rp->siop_istat & SIOP_ISTAT_CON) == 0) {
    890  1.16.4.2  nathanw 			rp->siop_istat = SIOP_ISTAT_SIGP;
    891  1.16.4.2  nathanw 			SIOP_TRACE('s',2,0,0);
    892  1.16.4.2  nathanw 		}
    893  1.16.4.2  nathanw 		else {
    894  1.16.4.2  nathanw 			SIOP_TRACE('s',3,rp->siop_istat,0);
    895  1.16.4.2  nathanw 		}
    896  1.16.4.2  nathanw 	}
    897  1.16.4.2  nathanw #ifdef DEBUG
    898  1.16.4.2  nathanw 	++siopngstarts;
    899  1.16.4.2  nathanw #endif
    900  1.16.4.2  nathanw }
    901  1.16.4.2  nathanw 
    902  1.16.4.2  nathanw /*
    903  1.16.4.2  nathanw  * Process a DMA or SCSI interrupt from the 53C720/770 SIOP
    904  1.16.4.2  nathanw  */
    905  1.16.4.2  nathanw 
    906  1.16.4.2  nathanw int
    907  1.16.4.2  nathanw siopng_checkintr(struct siop_softc *sc, u_char istat, u_char dstat,
    908  1.16.4.2  nathanw                  u_short sist, int *status)
    909  1.16.4.2  nathanw {
    910  1.16.4.2  nathanw 	siop_regmap_p rp = sc->sc_siopp;
    911  1.16.4.2  nathanw 	struct siop_acb *acb = sc->sc_nexus;
    912  1.16.4.2  nathanw 	int	target = 0;
    913  1.16.4.2  nathanw 	int	dfifo, dbc, sstat0, sstat1, sstat2;
    914  1.16.4.2  nathanw 
    915  1.16.4.2  nathanw 	dfifo = rp->siop_dfifo;
    916  1.16.4.2  nathanw 	dbc = rp->siop_dbc0;
    917  1.16.4.2  nathanw 	sstat0 = rp->siop_sstat0;
    918  1.16.4.2  nathanw 	sstat1 = rp->siop_sstat1;
    919  1.16.4.2  nathanw 	sstat2 = rp->siop_sstat2;
    920  1.16.4.2  nathanw 	rp->siop_ctest3 |= SIOP_CTEST8_CLF;
    921  1.16.4.2  nathanw 	while ((rp->siop_ctest1 & SIOP_CTEST1_FMT) != SIOP_CTEST1_FMT)
    922  1.16.4.2  nathanw 		;
    923  1.16.4.2  nathanw 	rp->siop_ctest3 &= ~SIOP_CTEST8_CLF;
    924  1.16.4.2  nathanw #ifdef DEBUG
    925  1.16.4.2  nathanw 	++siopngints;
    926  1.16.4.2  nathanw #if 0
    927  1.16.4.2  nathanw 	if (siopng_debug & 0x100) {
    928  1.16.4.2  nathanw 		DCIAS(&acb->stat[0]);	/* XXX */
    929  1.16.4.2  nathanw 		printf ("siopngchkintr: istat %x dstat %x sist %x dsps %x sbcl %x sts %x msg %x\n",
    930  1.16.4.2  nathanw 		    istat, dstat, sist, rp->siop_dsps, rp->siop_sbcl, acb->stat[0], acb->msg[0]);
    931  1.16.4.2  nathanw 		printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
    932  1.16.4.2  nathanw 		    acb->msg[0], acb->msg[1], acb->msg[2],
    933  1.16.4.2  nathanw 		    acb->msg[3], acb->msg[4], acb->msg[5]);
    934  1.16.4.2  nathanw 	}
    935  1.16.4.2  nathanw #endif
    936  1.16.4.2  nathanw 	if (rp->siop_dsp && (rp->siop_dsp < sc->sc_scriptspa ||
    937  1.16.4.2  nathanw 	    rp->siop_dsp >= sc->sc_scriptspa + sizeof(siopng_scripts))) {
    938  1.16.4.2  nathanw 		printf ("%s: dsp not within script dsp %lx scripts %lx:%lx",
    939  1.16.4.2  nathanw 		    sc->sc_dev.dv_xname, rp->siop_dsp, sc->sc_scriptspa,
    940  1.16.4.2  nathanw 		    sc->sc_scriptspa + sizeof(siopng_scripts));
    941  1.16.4.2  nathanw 		printf(" istat %x dstat %x sist %x\n",
    942  1.16.4.2  nathanw 		    istat, dstat, sist);
    943  1.16.4.2  nathanw #ifdef DDB
    944  1.16.4.2  nathanw 		Debugger();
    945  1.16.4.2  nathanw #endif
    946  1.16.4.2  nathanw 	}
    947  1.16.4.2  nathanw #endif
    948  1.16.4.2  nathanw 	SIOP_TRACE('i',dstat,istat,(istat&SIOP_ISTAT_DIP)?rp->siop_dsps&0xff:sist);
    949  1.16.4.2  nathanw 	if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff00) {
    950  1.16.4.2  nathanw 		/* Normal completion status, or check condition */
    951  1.16.4.2  nathanw #ifdef DEBUG
    952  1.16.4.2  nathanw 		if (rp->siop_dsa != kvtop((caddr_t)&acb->ds)) {
    953  1.16.4.2  nathanw 			printf ("siopng: invalid dsa: %lx %x\n", rp->siop_dsa,
    954  1.16.4.2  nathanw 			    kvtop((caddr_t)&acb->ds));
    955  1.16.4.2  nathanw 			panic("*** siopng DSA invalid ***");
    956  1.16.4.2  nathanw 		}
    957  1.16.4.2  nathanw #endif
    958  1.16.4.2  nathanw 		target = acb->xs->xs_periph->periph_target;
    959  1.16.4.2  nathanw 		if (sc->sc_sync[target].state == NEG_WAITW) {
    960  1.16.4.2  nathanw 			if (acb->msg[1] == 0xff)
    961  1.16.4.2  nathanw 				printf ("%s: target %d ignored wide request\n",
    962  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, target);
    963  1.16.4.2  nathanw 			else if (acb->msg[1] == MSG_REJECT)
    964  1.16.4.2  nathanw 				printf ("%s: target %d rejected wide request\n",
    965  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, target);
    966  1.16.4.2  nathanw 			else {
    967  1.16.4.2  nathanw 				printf("%s: target %d (wide) %02x %02x %02x %02x\n",
    968  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, target, acb->msg[1],
    969  1.16.4.2  nathanw 				    acb->msg[2], acb->msg[3], acb->msg[4]);
    970  1.16.4.2  nathanw 				if (acb->msg[1] == MSG_EXT_MESSAGE &&
    971  1.16.4.2  nathanw 				    acb->msg[2] == 2 &&
    972  1.16.4.2  nathanw 				    acb->msg[3] == MSG_WIDE_REQ)
    973  1.16.4.2  nathanw 					sc->sc_sync[target].scntl3 = acb->msg[4] ?
    974  1.16.4.2  nathanw 					    sc->sc_sync[target].scntl3 | SIOP_SCNTL3_EWS :
    975  1.16.4.2  nathanw 					    sc->sc_sync[target].scntl3 & ~SIOP_SCNTL3_EWS;
    976  1.16.4.2  nathanw 			}
    977  1.16.4.2  nathanw 			sc->sc_sync[target].state = NEG_SYNC;
    978  1.16.4.2  nathanw 		}
    979  1.16.4.2  nathanw 		if (sc->sc_sync[target].state == NEG_WAITS) {
    980  1.16.4.2  nathanw 			if (acb->msg[1] == 0xff)
    981  1.16.4.2  nathanw 				printf ("%s: target %d ignored sync request\n",
    982  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, target);
    983  1.16.4.2  nathanw 			else if (acb->msg[1] == MSG_REJECT)
    984  1.16.4.2  nathanw 				printf ("%s: target %d rejected sync request\n",
    985  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, target);
    986  1.16.4.2  nathanw 			else
    987  1.16.4.2  nathanw /* XXX - need to set sync transfer parameters */
    988  1.16.4.2  nathanw 				printf("%s: target %d (sync) %02x %02x %02x\n",
    989  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, target, acb->msg[1],
    990  1.16.4.2  nathanw 				    acb->msg[2], acb->msg[3]);
    991  1.16.4.2  nathanw 			sc->sc_sync[target].state = NEG_DONE;
    992  1.16.4.2  nathanw 		}
    993  1.16.4.2  nathanw 		dma_cachectl(&acb->stat[0], 1);
    994  1.16.4.2  nathanw 		*status = acb->stat[0];
    995  1.16.4.2  nathanw #ifdef DEBUG
    996  1.16.4.2  nathanw 		if (rp->siop_sbcl & SIOP_BSY) {
    997  1.16.4.2  nathanw 			/*printf ("ACK! siop was busy at end: rp %x script %x dsa %x\n",
    998  1.16.4.2  nathanw 			    rp, &siopng_scripts, &acb->ds);*/
    999  1.16.4.2  nathanw #ifdef DDB
   1000  1.16.4.2  nathanw 			/*Debugger();*/
   1001  1.16.4.2  nathanw #endif
   1002  1.16.4.2  nathanw 		}
   1003  1.16.4.2  nathanw 		if (acb->msg[0] != 0x00)
   1004  1.16.4.2  nathanw 			printf("%s: message was not COMMAND COMPLETE: %x\n",
   1005  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname, acb->msg[0]);
   1006  1.16.4.2  nathanw #endif
   1007  1.16.4.2  nathanw 		if (sc->nexus_list.tqh_first)
   1008  1.16.4.2  nathanw 			rp->siop_dcntl |= SIOP_DCNTL_STD;
   1009  1.16.4.2  nathanw 		return 1;
   1010  1.16.4.2  nathanw 	}
   1011  1.16.4.2  nathanw 	if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff0b) {
   1012  1.16.4.2  nathanw 		target = acb->xs->xs_periph->periph_target;
   1013  1.16.4.2  nathanw 		if (acb->msg[1] == MSG_EXT_MESSAGE && acb->msg[2] == 2 &&
   1014  1.16.4.2  nathanw 		    acb->msg[3] == MSG_WIDE_REQ) {
   1015  1.16.4.2  nathanw #ifdef DEBUG
   1016  1.16.4.2  nathanw 			if (siopngsync_debug)
   1017  1.16.4.2  nathanw 				printf ("wide msg in: %02x %02x %02x %02x %02x %02x\n",
   1018  1.16.4.2  nathanw 				    acb->msg[0], acb->msg[1], acb->msg[2],
   1019  1.16.4.2  nathanw 				    acb->msg[3], acb->msg[4], acb->msg[5]);
   1020  1.16.4.2  nathanw #endif
   1021  1.16.4.2  nathanw 			sc->sc_sync[target].scntl3 &= ~(SIOP_SCNTL3_EWS);
   1022  1.16.4.2  nathanw 			if (acb->msg[2] == 2 &&
   1023  1.16.4.2  nathanw 			    acb->msg[3] == MSG_WIDE_REQ &&
   1024  1.16.4.2  nathanw 			    acb->msg[4] != 0) {
   1025  1.16.4.2  nathanw 				sc->sc_sync[target].scntl3 |= SIOP_SCNTL3_EWS;
   1026  1.16.4.2  nathanw 				printf ("%s: target %d now wide %d\n",
   1027  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, target,
   1028  1.16.4.2  nathanw 				    acb->msg[4]);
   1029  1.16.4.2  nathanw 			}
   1030  1.16.4.2  nathanw 			rp->siop_scntl3 = sc->sc_sync[target].scntl3;
   1031  1.16.4.2  nathanw 			if (sc->sc_sync[target].state == NEG_WAITW) {
   1032  1.16.4.2  nathanw 				sc->sc_sync[target].state = NEG_SYNC;
   1033  1.16.4.2  nathanw 				rp->siop_dsp = sc->sc_scriptspa + Ent_clear_ack;
   1034  1.16.4.2  nathanw 				return(0);
   1035  1.16.4.2  nathanw 			}
   1036  1.16.4.2  nathanw 			rp->siop_dcntl |= SIOP_DCNTL_STD;
   1037  1.16.4.2  nathanw 			sc->sc_sync[target].state = NEG_SYNC;
   1038  1.16.4.2  nathanw 			return (0);
   1039  1.16.4.2  nathanw 		}
   1040  1.16.4.2  nathanw 		if (acb->msg[1] == MSG_EXT_MESSAGE && acb->msg[2] == 3 &&
   1041  1.16.4.2  nathanw 		    acb->msg[3] == MSG_SYNC_REQ) {
   1042  1.16.4.2  nathanw #ifdef DEBUG
   1043  1.16.4.2  nathanw 			if (siopngsync_debug)
   1044  1.16.4.2  nathanw 				printf ("sync msg in: %02x %02x %02x %02x %02x %02x\n",
   1045  1.16.4.2  nathanw 				    acb->msg[0], acb->msg[1], acb->msg[2],
   1046  1.16.4.2  nathanw 				    acb->msg[3], acb->msg[4], acb->msg[5]);
   1047  1.16.4.2  nathanw #endif
   1048  1.16.4.2  nathanw 			sc->sc_sync[target].sxfer = 0;
   1049  1.16.4.2  nathanw 			sc->sc_sync[target].scntl3 = 5 |		/* XXX */
   1050  1.16.4.2  nathanw 			    (sc->sc_sync[target].scntl3 & 0x88);	/* XXX */
   1051  1.16.4.2  nathanw 			if (acb->msg[2] == 3 &&
   1052  1.16.4.2  nathanw 			    acb->msg[3] == MSG_SYNC_REQ &&
   1053  1.16.4.2  nathanw 			    acb->msg[5] != 0) {
   1054  1.16.4.2  nathanw #ifdef MAXTOR_KLUDGE
   1055  1.16.4.2  nathanw 				/*
   1056  1.16.4.2  nathanw 				 * Kludge for my Maxtor XT8580S
   1057  1.16.4.2  nathanw 				 * It accepts whatever we request, even
   1058  1.16.4.2  nathanw 				 * though it won't work.  So we ask for
   1059  1.16.4.2  nathanw 				 * a short period than we can handle.  If
   1060  1.16.4.2  nathanw 				 * the device says it can do it, use 208ns.
   1061  1.16.4.2  nathanw 				 * If the device says it can do less than
   1062  1.16.4.2  nathanw 				 * 100ns, then we limit it to 100ns.
   1063  1.16.4.2  nathanw 				 */
   1064  1.16.4.2  nathanw 				if (acb->msg[4] && acb->msg[4] < 100 / 4) {
   1065  1.16.4.2  nathanw #ifdef DEBUG
   1066  1.16.4.2  nathanw 					printf ("%d: target %d wanted %dns period\n",
   1067  1.16.4.2  nathanw 					    sc->sc_dev.dv_xname, target,
   1068  1.16.4.2  nathanw 					    acb->msg[4] * 4);
   1069  1.16.4.2  nathanw #endif
   1070  1.16.4.2  nathanw 					if (acb->msg[4] == 50 / 4)
   1071  1.16.4.2  nathanw 						acb->msg[4] = 208 / 4;
   1072  1.16.4.2  nathanw 					else
   1073  1.16.4.2  nathanw 						acb->msg[4] = 100 / 4;
   1074  1.16.4.2  nathanw 				}
   1075  1.16.4.2  nathanw #endif /* MAXTOR_KLUDGE */
   1076  1.16.4.2  nathanw 				printf ("%s: target %d now synchronous, period=%dns, offset=%d\n",
   1077  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, target,
   1078  1.16.4.2  nathanw 				    (acb->msg[4] == 12) ? 50 : acb->msg[4] * 4,
   1079  1.16.4.2  nathanw 				    acb->msg[5]);
   1080  1.16.4.2  nathanw 				scsi_period_to_siopng (sc, target);
   1081  1.16.4.2  nathanw 			}
   1082  1.16.4.2  nathanw 			rp->siop_sxfer = sc->sc_sync[target].sxfer;
   1083  1.16.4.2  nathanw 			rp->siop_scntl3 = sc->sc_sync[target].scntl3;
   1084  1.16.4.2  nathanw 			if (sc->sc_sync[target].state == NEG_WAITS) {
   1085  1.16.4.2  nathanw 				sc->sc_sync[target].state = NEG_DONE;
   1086  1.16.4.2  nathanw 				rp->siop_dsp = sc->sc_scriptspa + Ent_clear_ack;
   1087  1.16.4.2  nathanw 				return(0);
   1088  1.16.4.2  nathanw 			}
   1089  1.16.4.2  nathanw 			rp->siop_dcntl |= SIOP_DCNTL_STD;
   1090  1.16.4.2  nathanw 			sc->sc_sync[target].state = NEG_DONE;
   1091  1.16.4.2  nathanw 			return (0);
   1092  1.16.4.2  nathanw 		}
   1093  1.16.4.2  nathanw 		/* XXX - not SDTR message */
   1094  1.16.4.2  nathanw 	}
   1095  1.16.4.2  nathanw 	if (sist & SIOP_SIST_MA) {		/* Phase mismatch */
   1096  1.16.4.2  nathanw #ifdef DEBUG
   1097  1.16.4.2  nathanw 		++siopngphmm;
   1098  1.16.4.2  nathanw 		if (acb == NULL)
   1099  1.16.4.2  nathanw 			printf("%s: Phase mismatch with no active command?\n",
   1100  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname);
   1101  1.16.4.2  nathanw #endif
   1102  1.16.4.2  nathanw 		if (acb->iob_len) {
   1103  1.16.4.2  nathanw 			int adjust;
   1104  1.16.4.2  nathanw 			adjust = ((dfifo - (dbc & 0x7f)) & 0x7f);
   1105  1.16.4.2  nathanw 			if (sstat0 & SIOP_SSTAT0_OLF)	/* sstat0 SODL lsb */
   1106  1.16.4.2  nathanw 				++adjust;
   1107  1.16.4.2  nathanw 			if (sstat0 & SIOP_SSTAT0_ORF)	/* sstat0 SODR lsb */
   1108  1.16.4.2  nathanw 				++adjust;
   1109  1.16.4.2  nathanw 			if (sstat2 & SIOP_SSTAT2_OLF1)	/* sstat2 SODL msb */
   1110  1.16.4.2  nathanw 				++adjust;
   1111  1.16.4.2  nathanw 			if (sstat2 & SIOP_SSTAT2_ORF1)	/* sstat2 SODR msb */
   1112  1.16.4.2  nathanw 				++adjust;
   1113  1.16.4.2  nathanw 			acb->iob_curlen = *((long *)&rp->siop_dcmd) & 0xffffff;
   1114  1.16.4.2  nathanw 			acb->iob_curlen += adjust;
   1115  1.16.4.2  nathanw 			acb->iob_curbuf = *((long *)&rp->siop_dnad) - adjust;
   1116  1.16.4.2  nathanw #ifdef DEBUG
   1117  1.16.4.2  nathanw 			if (siopng_debug & 0x100) {
   1118  1.16.4.2  nathanw 				int i;
   1119  1.16.4.2  nathanw 				printf ("Phase mismatch: curbuf %lx curlen %lx dfifo %x dbc %x sstat1 %x adjust %x sbcl %x starts %d acb %p\n",
   1120  1.16.4.2  nathanw 				    acb->iob_curbuf, acb->iob_curlen, dfifo,
   1121  1.16.4.2  nathanw 				    dbc, sstat1, adjust, rp->siop_sbcl, siopngstarts, acb);
   1122  1.16.4.2  nathanw 				if (acb->ds.chain[1].datalen) {
   1123  1.16.4.2  nathanw 					for (i = 0; acb->ds.chain[i].datalen; ++i)
   1124  1.16.4.2  nathanw 						printf("chain[%d] addr %p len %lx\n",
   1125  1.16.4.2  nathanw 						    i, acb->ds.chain[i].databuf,
   1126  1.16.4.2  nathanw 						    acb->ds.chain[i].datalen);
   1127  1.16.4.2  nathanw 				}
   1128  1.16.4.2  nathanw 			}
   1129  1.16.4.2  nathanw #endif
   1130  1.16.4.2  nathanw 			dma_cachectl ((caddr_t)acb, sizeof(*acb));
   1131  1.16.4.2  nathanw 		}
   1132  1.16.4.2  nathanw #ifdef DEBUG
   1133  1.16.4.2  nathanw 		SIOP_TRACE('m',rp->siop_sbcl,(rp->siop_dsp>>8),rp->siop_dsp);
   1134  1.16.4.2  nathanw 		if (siopng_debug & 9)
   1135  1.16.4.2  nathanw 			printf ("Phase mismatch: %x dsp +%lx dcmd %lx\n",
   1136  1.16.4.2  nathanw 			    rp->siop_sbcl,
   1137  1.16.4.2  nathanw 			    rp->siop_dsp - sc->sc_scriptspa,
   1138  1.16.4.2  nathanw 			    *((long *)&rp->siop_dcmd));
   1139  1.16.4.2  nathanw #endif
   1140  1.16.4.2  nathanw 		if ((rp->siop_sbcl & SIOP_REQ) == 0) {
   1141  1.16.4.2  nathanw 			printf ("Phase mismatch: REQ not asserted! %02x dsp %lx\n",
   1142  1.16.4.2  nathanw 			    rp->siop_sbcl, rp->siop_dsp);
   1143  1.16.4.2  nathanw #if defined(DEBUG) && defined(DDB)
   1144  1.16.4.2  nathanw 			Debugger();
   1145  1.16.4.2  nathanw #endif
   1146  1.16.4.2  nathanw 		}
   1147  1.16.4.2  nathanw 		switch (rp->siop_sbcl & 7) {
   1148  1.16.4.2  nathanw 		case 0:		/* data out */
   1149  1.16.4.2  nathanw 		case 1:		/* data in */
   1150  1.16.4.2  nathanw 		case 2:		/* status */
   1151  1.16.4.2  nathanw 		case 3:		/* command */
   1152  1.16.4.2  nathanw 		case 6:		/* message in */
   1153  1.16.4.2  nathanw 		case 7:		/* message out */
   1154  1.16.4.2  nathanw 			rp->siop_dsp = sc->sc_scriptspa + Ent_switch;
   1155  1.16.4.2  nathanw 			break;
   1156  1.16.4.2  nathanw 		default:
   1157  1.16.4.2  nathanw 			goto bad_phase;
   1158  1.16.4.2  nathanw 		}
   1159  1.16.4.2  nathanw 		return 0;
   1160  1.16.4.2  nathanw 	}
   1161  1.16.4.2  nathanw 	if (sist & SIOP_SIST_STO) {		/* Select timed out */
   1162  1.16.4.2  nathanw #ifdef DEBUG
   1163  1.16.4.2  nathanw 		if (acb == NULL)
   1164  1.16.4.2  nathanw 			printf("%s: Select timeout with no active command?\n",
   1165  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname);
   1166  1.16.4.2  nathanw 		if (rp->siop_sbcl & SIOP_BSY) {
   1167  1.16.4.2  nathanw 			printf ("ACK! siop was busy at timeout: rp %p script %p dsa %p\n",
   1168  1.16.4.2  nathanw 			    rp, &siopng_scripts, &acb->ds);
   1169  1.16.4.2  nathanw 			printf(" sbcl %x sdid %x istat %x dstat %x sist %x\n",
   1170  1.16.4.2  nathanw 			    rp->siop_sbcl, rp->siop_sdid, istat, dstat, sist);
   1171  1.16.4.2  nathanw 			if (!(rp->siop_sbcl & SIOP_BSY)) {
   1172  1.16.4.2  nathanw 				printf ("Yikes, it's not busy now!\n");
   1173  1.16.4.2  nathanw #if 0
   1174  1.16.4.2  nathanw 				*status = -1;
   1175  1.16.4.2  nathanw 				if (sc->nexus_list.tqh_first)
   1176  1.16.4.2  nathanw 					rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect;
   1177  1.16.4.2  nathanw 				return 1;
   1178  1.16.4.2  nathanw #endif
   1179  1.16.4.2  nathanw 			}
   1180  1.16.4.2  nathanw /*			rp->siop_dcntl |= SIOP_DCNTL_STD;*/
   1181  1.16.4.2  nathanw 			return (0);
   1182  1.16.4.2  nathanw #ifdef DDB
   1183  1.16.4.2  nathanw 			Debugger();
   1184  1.16.4.2  nathanw #endif
   1185  1.16.4.2  nathanw 		}
   1186  1.16.4.2  nathanw #endif
   1187  1.16.4.2  nathanw 		*status = -1;
   1188  1.16.4.2  nathanw 		acb->xs->error = XS_SELTIMEOUT;
   1189  1.16.4.2  nathanw 		if (sc->nexus_list.tqh_first)
   1190  1.16.4.2  nathanw 			rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect;
   1191  1.16.4.2  nathanw 		return 1;
   1192  1.16.4.2  nathanw 	}
   1193  1.16.4.2  nathanw 	if (acb)
   1194  1.16.4.2  nathanw 		target = acb->xs->xs_periph->periph_target;
   1195  1.16.4.2  nathanw 	else
   1196  1.16.4.2  nathanw 		target = 7;
   1197  1.16.4.2  nathanw 	if (sist & SIOP_SIST_UDC) {
   1198  1.16.4.2  nathanw #ifdef DEBUG
   1199  1.16.4.2  nathanw 		if (acb == NULL)
   1200  1.16.4.2  nathanw 			printf("%s: Unexpected disconnect with no active command?\n",
   1201  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname);
   1202  1.16.4.2  nathanw 		printf ("%s: target %d disconnected unexpectedly\n",
   1203  1.16.4.2  nathanw 		   sc->sc_dev.dv_xname, target);
   1204  1.16.4.2  nathanw siopng_dump_registers(sc);
   1205  1.16.4.2  nathanw siopng_dump(sc);
   1206  1.16.4.2  nathanw #endif
   1207  1.16.4.2  nathanw #if 0
   1208  1.16.4.2  nathanw 		siopngabort (sc, rp, "siopngchkintr");
   1209  1.16.4.2  nathanw #endif
   1210  1.16.4.2  nathanw 		*status = STS_BUSY;
   1211  1.16.4.2  nathanw 		if (sc->nexus_list.tqh_first)
   1212  1.16.4.2  nathanw 			rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect;
   1213  1.16.4.2  nathanw 		return (acb != NULL);
   1214  1.16.4.2  nathanw 	}
   1215  1.16.4.2  nathanw 	if (dstat & SIOP_DSTAT_SIR && (rp->siop_dsps == 0xff01 ||
   1216  1.16.4.2  nathanw 	    rp->siop_dsps == 0xff02)) {
   1217  1.16.4.2  nathanw #ifdef DEBUG
   1218  1.16.4.2  nathanw 		if (siopng_debug & 0x100)
   1219  1.16.4.2  nathanw 			printf ("%s: ID %02x disconnected TEMP %lx (+%lx) curbuf %lx curlen %lx buf %p len %lx dfifo %x dbc %x sstat1 %x starts %d acb %p\n",
   1220  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname, 1 << target, rp->siop_temp,
   1221  1.16.4.2  nathanw 			    rp->siop_temp ? rp->siop_temp - sc->sc_scriptspa : 0,
   1222  1.16.4.2  nathanw 			    acb->iob_curbuf, acb->iob_curlen,
   1223  1.16.4.2  nathanw 			    acb->ds.chain[0].databuf, acb->ds.chain[0].datalen, dfifo, dbc, sstat1, siopngstarts, acb);
   1224  1.16.4.2  nathanw #endif
   1225  1.16.4.2  nathanw 		if (acb == NULL) {
   1226  1.16.4.2  nathanw 			printf("%s: Disconnect with no active command?\n",
   1227  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname);
   1228  1.16.4.2  nathanw 			return (0);
   1229  1.16.4.2  nathanw 		}
   1230  1.16.4.2  nathanw 		/*
   1231  1.16.4.2  nathanw 		 * XXXX need to update iob_curbuf/iob_curlen to reflect
   1232  1.16.4.2  nathanw 		 * current data transferred.  If device disconnected in
   1233  1.16.4.2  nathanw 		 * the middle of a DMA block, they should already be set
   1234  1.16.4.2  nathanw 		 * by the phase change interrupt.  If the disconnect
   1235  1.16.4.2  nathanw 		 * occurs on a DMA block boundary, we have to figure out
   1236  1.16.4.2  nathanw 		 * which DMA block it was.
   1237  1.16.4.2  nathanw 		 */
   1238  1.16.4.2  nathanw 		if (acb->iob_len && rp->siop_temp) {
   1239  1.16.4.2  nathanw 			int n = rp->siop_temp - sc->sc_scriptspa;
   1240  1.16.4.2  nathanw 
   1241  1.16.4.2  nathanw 			if (acb->iob_curlen && acb->iob_curlen != acb->ds.chain[0].datalen)
   1242  1.16.4.2  nathanw 				printf("%s: iob_curbuf/len already set? n %x iob %lx/%lx chain[0] %p/%lx\n",
   1243  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, n, acb->iob_curbuf, acb->iob_curlen,
   1244  1.16.4.2  nathanw 				    acb->ds.chain[0].databuf, acb->ds.chain[0].datalen);
   1245  1.16.4.2  nathanw 			if (n < Ent_datain)
   1246  1.16.4.2  nathanw 				n = (n - Ent_dataout) / 16;
   1247  1.16.4.2  nathanw 			else
   1248  1.16.4.2  nathanw 				n = (n - Ent_datain) / 16;
   1249  1.16.4.2  nathanw 			if (n <= 0 && n > DMAMAXIO)
   1250  1.16.4.2  nathanw 				printf("TEMP invalid %d\n", n);
   1251  1.16.4.2  nathanw 			else {
   1252  1.16.4.2  nathanw 				acb->iob_curbuf = (u_long)acb->ds.chain[n].databuf;
   1253  1.16.4.2  nathanw 				acb->iob_curlen = acb->ds.chain[n].datalen;
   1254  1.16.4.2  nathanw 			}
   1255  1.16.4.2  nathanw #ifdef DEBUG
   1256  1.16.4.2  nathanw 			if (siopng_debug & 0x100) {
   1257  1.16.4.2  nathanw 				printf("%s: TEMP offset %d", sc->sc_dev.dv_xname, n);
   1258  1.16.4.2  nathanw 				printf(" curbuf %lx curlen %lx\n", acb->iob_curbuf,
   1259  1.16.4.2  nathanw 				    acb->iob_curlen);
   1260  1.16.4.2  nathanw 			}
   1261  1.16.4.2  nathanw #endif
   1262  1.16.4.2  nathanw 		}
   1263  1.16.4.2  nathanw 		/*
   1264  1.16.4.2  nathanw 		 * If data transfer was interrupted by disconnect, iob_curbuf
   1265  1.16.4.2  nathanw 		 * and iob_curlen should reflect the point of interruption.
   1266  1.16.4.2  nathanw 		 * Adjust the DMA chain so that the data transfer begins
   1267  1.16.4.2  nathanw 		 * at the appropriate place upon reselection.
   1268  1.16.4.2  nathanw 		 * XXX This should only be done on save data pointer message?
   1269  1.16.4.2  nathanw 		 */
   1270  1.16.4.2  nathanw 		if (acb->iob_curlen) {
   1271  1.16.4.2  nathanw 			int i, j;
   1272  1.16.4.2  nathanw 
   1273  1.16.4.2  nathanw #ifdef DEBUG
   1274  1.16.4.2  nathanw 			if (siopng_debug & 0x100)
   1275  1.16.4.2  nathanw 				printf ("%s: adjusting DMA chain\n",
   1276  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname);
   1277  1.16.4.2  nathanw 			if (rp->siop_dsps == 0xff02)
   1278  1.16.4.2  nathanw 				printf ("%s: ID %02x disconnected without Save Data Pointers\n",
   1279  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, 1 << target);
   1280  1.16.4.2  nathanw #endif
   1281  1.16.4.2  nathanw 			for (i = 0; i < DMAMAXIO; ++i) {
   1282  1.16.4.2  nathanw 				if (acb->ds.chain[i].datalen == 0)
   1283  1.16.4.2  nathanw 					break;
   1284  1.16.4.2  nathanw 				if (acb->iob_curbuf >= (long)acb->ds.chain[i].databuf &&
   1285  1.16.4.2  nathanw 				    acb->iob_curbuf < (long)(acb->ds.chain[i].databuf +
   1286  1.16.4.2  nathanw 				    acb->ds.chain[i].datalen))
   1287  1.16.4.2  nathanw 					break;
   1288  1.16.4.2  nathanw 			}
   1289  1.16.4.2  nathanw 			if (i >= DMAMAXIO || acb->ds.chain[i].datalen == 0) {
   1290  1.16.4.2  nathanw 				printf("couldn't find saved data pointer: ");
   1291  1.16.4.2  nathanw 				printf("curbuf %lx curlen %lx i %d\n",
   1292  1.16.4.2  nathanw 				    acb->iob_curbuf, acb->iob_curlen, i);
   1293  1.16.4.2  nathanw #ifdef DDB
   1294  1.16.4.2  nathanw 				Debugger();
   1295  1.16.4.2  nathanw #endif
   1296  1.16.4.2  nathanw 			}
   1297  1.16.4.2  nathanw #ifdef DEBUG
   1298  1.16.4.2  nathanw 			if (siopng_debug & 0x100)
   1299  1.16.4.2  nathanw 				printf("  chain[0]: %p/%lx -> %lx/%lx\n",
   1300  1.16.4.2  nathanw 				    acb->ds.chain[0].databuf,
   1301  1.16.4.2  nathanw 				    acb->ds.chain[0].datalen,
   1302  1.16.4.2  nathanw 				    acb->iob_curbuf,
   1303  1.16.4.2  nathanw 				    acb->iob_curlen);
   1304  1.16.4.2  nathanw #endif
   1305  1.16.4.2  nathanw 			acb->ds.chain[0].databuf = (char *)acb->iob_curbuf;
   1306  1.16.4.2  nathanw 			acb->ds.chain[0].datalen = acb->iob_curlen;
   1307  1.16.4.2  nathanw 			for (j = 1, ++i; i < DMAMAXIO && acb->ds.chain[i].datalen; ++i, ++j) {
   1308  1.16.4.2  nathanw #ifdef DEBUG
   1309  1.16.4.2  nathanw 			if (siopng_debug & 0x100)
   1310  1.16.4.2  nathanw 				printf("  chain[%d]: %p/%lx -> %p/%lx\n", j,
   1311  1.16.4.2  nathanw 				    acb->ds.chain[j].databuf,
   1312  1.16.4.2  nathanw 				    acb->ds.chain[j].datalen,
   1313  1.16.4.2  nathanw 				    acb->ds.chain[i].databuf,
   1314  1.16.4.2  nathanw 				    acb->ds.chain[i].datalen);
   1315  1.16.4.2  nathanw #endif
   1316  1.16.4.2  nathanw 				acb->ds.chain[j].databuf = acb->ds.chain[i].databuf;
   1317  1.16.4.2  nathanw 				acb->ds.chain[j].datalen = acb->ds.chain[i].datalen;
   1318  1.16.4.2  nathanw 			}
   1319  1.16.4.2  nathanw 			if (j < DMAMAXIO)
   1320  1.16.4.2  nathanw 				acb->ds.chain[j].datalen = 0;
   1321  1.16.4.2  nathanw 			DCIAS(kvtop((caddr_t)&acb->ds.chain));
   1322  1.16.4.2  nathanw 		}
   1323  1.16.4.2  nathanw 		++sc->sc_tinfo[target].dconns;
   1324  1.16.4.2  nathanw 		/*
   1325  1.16.4.2  nathanw 		 * add nexus to waiting list
   1326  1.16.4.2  nathanw 		 * clear nexus
   1327  1.16.4.2  nathanw 		 * try to start another command for another target/lun
   1328  1.16.4.2  nathanw 		 */
   1329  1.16.4.2  nathanw 		acb->status = sc->sc_flags & SIOP_INTSOFF;
   1330  1.16.4.2  nathanw 		TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain);
   1331  1.16.4.2  nathanw 		sc->sc_nexus = NULL;		/* no current device */
   1332  1.16.4.2  nathanw 		/* start script to wait for reselect */
   1333  1.16.4.2  nathanw 		if (sc->sc_nexus == NULL)
   1334  1.16.4.2  nathanw 			rp->siop_dsp = sc->sc_scriptspa + Ent_wait_reselect;
   1335  1.16.4.2  nathanw /* XXXX start another command ? */
   1336  1.16.4.2  nathanw 		if (sc->ready_list.tqh_first)
   1337  1.16.4.2  nathanw 			siopng_sched(sc);
   1338  1.16.4.2  nathanw #if 0
   1339  1.16.4.2  nathanw 		else
   1340  1.16.4.2  nathanw 			rp->siop_dcntl |= SIOP_DCNTL_STD;
   1341  1.16.4.2  nathanw #endif
   1342  1.16.4.2  nathanw 		return (0);
   1343  1.16.4.2  nathanw 	}
   1344  1.16.4.2  nathanw 	if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff03) {
   1345  1.16.4.2  nathanw 		int reselid = rp->siop_scratcha & 0x7f;
   1346  1.16.4.2  nathanw 		int reselun = rp->siop_sfbr & 0x07;
   1347  1.16.4.2  nathanw 
   1348  1.16.4.2  nathanw 		sc->sc_sstat1 = rp->siop_sbcl;	/* XXXX save current SBCL */
   1349  1.16.4.2  nathanw #ifdef DEBUG
   1350  1.16.4.2  nathanw 		if (siopng_debug & 0x100)
   1351  1.16.4.2  nathanw 			printf ("%s: target ID %02x reselected dsps %lx\n",
   1352  1.16.4.2  nathanw 			     sc->sc_dev.dv_xname, reselid,
   1353  1.16.4.2  nathanw 			     rp->siop_dsps);
   1354  1.16.4.2  nathanw 		if ((rp->siop_sfbr & 0x80) == 0)
   1355  1.16.4.2  nathanw 			printf("%s: Reselect message in was not identify: %x\n",
   1356  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname, rp->siop_sfbr);
   1357  1.16.4.2  nathanw #endif
   1358  1.16.4.2  nathanw 		if (sc->sc_nexus) {
   1359  1.16.4.2  nathanw #ifdef DEBUG
   1360  1.16.4.2  nathanw 			if (siopng_debug & 0x100)
   1361  1.16.4.2  nathanw 				printf ("%s: reselect ID %02x w/active\n",
   1362  1.16.4.2  nathanw 				    sc->sc_dev.dv_xname, reselid);
   1363  1.16.4.2  nathanw #endif
   1364  1.16.4.2  nathanw 			TAILQ_INSERT_HEAD(&sc->ready_list, sc->sc_nexus, chain);
   1365  1.16.4.2  nathanw 			sc->sc_tinfo[sc->sc_nexus->xs->xs_periph->periph_target].lubusy
   1366  1.16.4.2  nathanw 			    &= ~(1 << sc->sc_nexus->xs->xs_periph->periph_lun);
   1367  1.16.4.2  nathanw 			--sc->sc_active;
   1368  1.16.4.2  nathanw 		}
   1369  1.16.4.2  nathanw 		/*
   1370  1.16.4.2  nathanw 		 * locate acb of reselecting device
   1371  1.16.4.2  nathanw 		 * set sc->sc_nexus to acb
   1372  1.16.4.2  nathanw 		 */
   1373  1.16.4.2  nathanw 		for (acb = sc->nexus_list.tqh_first; acb;
   1374  1.16.4.2  nathanw 		    acb = acb->chain.tqe_next) {
   1375  1.16.4.2  nathanw 			if (reselid != ((acb->ds.scsi_addr >> 16) & 0xff) ||
   1376  1.16.4.2  nathanw 			    reselun != (acb->msgout[0] & 0x07))
   1377  1.16.4.2  nathanw 				continue;
   1378  1.16.4.2  nathanw 			TAILQ_REMOVE(&sc->nexus_list, acb, chain);
   1379  1.16.4.2  nathanw 			sc->sc_nexus = acb;
   1380  1.16.4.2  nathanw 			sc->sc_flags |= acb->status;
   1381  1.16.4.2  nathanw 			acb->status = 0;
   1382  1.16.4.2  nathanw 			DCIAS(kvtop(&acb->stat[0]));
   1383  1.16.4.2  nathanw 			rp->siop_dsa = kvtop((caddr_t)&acb->ds);
   1384  1.16.4.2  nathanw 			rp->siop_sxfer =
   1385  1.16.4.2  nathanw 				sc->sc_sync[acb->xs->xs_periph->periph_target].sxfer;
   1386  1.16.4.2  nathanw #ifndef FIXME
   1387  1.16.4.2  nathanw 			rp->siop_scntl3 =
   1388  1.16.4.2  nathanw 				sc->sc_sync[acb->xs->xs_periph->periph_target].scntl3;
   1389  1.16.4.2  nathanw #endif
   1390  1.16.4.2  nathanw 			break;
   1391  1.16.4.2  nathanw 		}
   1392  1.16.4.2  nathanw 		if (acb == NULL) {
   1393  1.16.4.2  nathanw 			printf("%s: target ID %02x reselect nexus_list %p\n",
   1394  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname, reselid,
   1395  1.16.4.2  nathanw 			    sc->nexus_list.tqh_first);
   1396  1.16.4.2  nathanw 			panic("unable to find reselecting device");
   1397  1.16.4.2  nathanw 		}
   1398  1.16.4.2  nathanw 		dma_cachectl ((caddr_t)acb, sizeof(*acb));
   1399  1.16.4.2  nathanw 		rp->siop_temp = 0;
   1400  1.16.4.2  nathanw 		rp->siop_dcntl |= SIOP_DCNTL_STD;
   1401  1.16.4.2  nathanw 		return (0);
   1402  1.16.4.2  nathanw 	}
   1403  1.16.4.2  nathanw 	if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff04) {
   1404  1.16.4.2  nathanw #ifdef DEBUG
   1405  1.16.4.2  nathanw 		u_short ctest2 = rp->siop_ctest2;
   1406  1.16.4.2  nathanw 
   1407  1.16.4.2  nathanw 		/* reselect was interrupted (by Sig_P or select) */
   1408  1.16.4.2  nathanw 		if (siopng_debug & 0x100 ||
   1409  1.16.4.2  nathanw 		    (ctest2 & SIOP_CTEST2_SIGP) == 0)
   1410  1.16.4.2  nathanw 			printf ("%s: reselect interrupted (Sig_P?) scntl1 %x ctest2 %x sfbr %x istat %x/%x\n",
   1411  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname, rp->siop_scntl1,
   1412  1.16.4.2  nathanw 			    ctest2, rp->siop_sfbr, istat, rp->siop_istat);
   1413  1.16.4.2  nathanw #endif
   1414  1.16.4.2  nathanw 		/* XXX assumes it was not select */
   1415  1.16.4.2  nathanw 		if (sc->sc_nexus == NULL) {
   1416  1.16.4.2  nathanw #ifdef DEBUG
   1417  1.16.4.2  nathanw 			printf("%s: reselect interrupted, sc_nexus == NULL\n",
   1418  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname);
   1419  1.16.4.2  nathanw #if 0
   1420  1.16.4.2  nathanw 			siopng_dump(sc);
   1421  1.16.4.2  nathanw #ifdef DDB
   1422  1.16.4.2  nathanw 			Debugger();
   1423  1.16.4.2  nathanw #endif
   1424  1.16.4.2  nathanw #endif
   1425  1.16.4.2  nathanw #endif
   1426  1.16.4.2  nathanw 			rp->siop_dcntl |= SIOP_DCNTL_STD;
   1427  1.16.4.2  nathanw 			return(0);
   1428  1.16.4.2  nathanw 		}
   1429  1.16.4.2  nathanw 		target = sc->sc_nexus->xs->xs_periph->periph_target;
   1430  1.16.4.2  nathanw 		rp->siop_temp = 0;
   1431  1.16.4.2  nathanw 		rp->siop_dsa = kvtop((caddr_t)&sc->sc_nexus->ds);
   1432  1.16.4.2  nathanw 		rp->siop_sxfer = sc->sc_sync[target].sxfer;
   1433  1.16.4.2  nathanw #ifndef FIXME
   1434  1.16.4.2  nathanw 		rp->siop_scntl3 = sc->sc_sync[target].scntl3;
   1435  1.16.4.2  nathanw #endif
   1436  1.16.4.2  nathanw 		rp->siop_dsp = sc->sc_scriptspa;
   1437  1.16.4.2  nathanw 		return (0);
   1438  1.16.4.2  nathanw 	}
   1439  1.16.4.2  nathanw 	if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff06) {
   1440  1.16.4.2  nathanw 		if (acb == NULL)
   1441  1.16.4.2  nathanw 			printf("%s: Bad message-in with no active command?\n",
   1442  1.16.4.2  nathanw 			    sc->sc_dev.dv_xname);
   1443  1.16.4.2  nathanw 		/* Unrecognized message in byte */
   1444  1.16.4.2  nathanw 		dma_cachectl (&acb->msg[1],1);
   1445  1.16.4.2  nathanw 		printf ("%s: Unrecognized message in data sfbr %x msg %x sbcl %x\n",
   1446  1.16.4.2  nathanw 			sc->sc_dev.dv_xname, rp->siop_sfbr, acb->msg[1], rp->siop_sbcl);
   1447  1.16.4.2  nathanw 		/* what should be done here? */
   1448  1.16.4.2  nathanw 		DCIAS(kvtop(&acb->msg[1]));
   1449  1.16.4.2  nathanw 		rp->siop_dsp = sc->sc_scriptspa + Ent_switch;
   1450  1.16.4.2  nathanw 		return (0);
   1451  1.16.4.2  nathanw 	}
   1452  1.16.4.2  nathanw 	if (dstat & SIOP_DSTAT_SIR && rp->siop_dsps == 0xff0a) {
   1453  1.16.4.2  nathanw 		/* Status phase wasn't followed by message in phase? */
   1454  1.16.4.2  nathanw 		printf ("%s: Status phase not followed by message in phase? sbcl %x sbdl %x\n",
   1455  1.16.4.2  nathanw 			sc->sc_dev.dv_xname, rp->siop_sbcl, rp->siop_sbdl);
   1456  1.16.4.2  nathanw 		if (rp->siop_sbcl == 0xa7) {
   1457  1.16.4.2  nathanw 			/* It is now, just continue the script? */
   1458  1.16.4.2  nathanw 			rp->siop_dcntl |= SIOP_DCNTL_STD;
   1459  1.16.4.2  nathanw 			return (0);
   1460  1.16.4.2  nathanw 		}
   1461  1.16.4.2  nathanw 	}
   1462  1.16.4.2  nathanw 	if (sist == 0 && dstat & SIOP_DSTAT_SIR) {
   1463  1.16.4.2  nathanw 		dma_cachectl (&acb->stat[0], 1);
   1464  1.16.4.2  nathanw 		dma_cachectl (&acb->msg[0], 1);
   1465  1.16.4.2  nathanw 		printf ("SIOP interrupt: %lx sts %x msg %x %x sbcl %x\n",
   1466  1.16.4.2  nathanw 		    rp->siop_dsps, acb->stat[0], acb->msg[0], acb->msg[1],
   1467  1.16.4.2  nathanw 		    rp->siop_sbcl);
   1468  1.16.4.2  nathanw 		siopngreset (sc);
   1469  1.16.4.2  nathanw 		*status = -1;
   1470  1.16.4.2  nathanw 		return 0;	/* siopngreset has cleaned up */
   1471  1.16.4.2  nathanw 	}
   1472  1.16.4.2  nathanw 	if (sist & SIOP_SIST_SGE)
   1473  1.16.4.2  nathanw 		printf ("SIOP: SCSI Gross Error\n");
   1474  1.16.4.2  nathanw 	if (sist & SIOP_SIST_PAR)
   1475  1.16.4.2  nathanw 		printf ("SIOP: Parity Error\n");
   1476  1.16.4.2  nathanw 	if (dstat & SIOP_DSTAT_IID)
   1477  1.16.4.2  nathanw 		printf ("SIOP: Invalid instruction detected\n");
   1478  1.16.4.2  nathanw bad_phase:
   1479  1.16.4.2  nathanw 	/*
   1480  1.16.4.2  nathanw 	 * temporary panic for unhandled conditions
   1481  1.16.4.2  nathanw 	 * displays various things about the 53C720/770 status and registers
   1482  1.16.4.2  nathanw 	 * then panics.
   1483  1.16.4.2  nathanw 	 * XXXX need to clean this up to print out the info, reset, and continue
   1484  1.16.4.2  nathanw 	 */
   1485  1.16.4.2  nathanw 	printf ("siopngchkintr: target %x ds %p\n", target, &acb->ds);
   1486  1.16.4.2  nathanw 	printf ("scripts %lx ds %x rp %x dsp %lx dcmd %lx\n", sc->sc_scriptspa,
   1487  1.16.4.2  nathanw 	    kvtop((caddr_t)&acb->ds), kvtop((caddr_t)rp), rp->siop_dsp,
   1488  1.16.4.2  nathanw 	    *((long *)&rp->siop_dcmd));
   1489  1.16.4.2  nathanw 	printf ("siopngchkintr: istat %x dstat %x sist %x dsps %lx dsa %lx sbcl %x sts %x msg %x %x sfbr %x\n",
   1490  1.16.4.2  nathanw 	    istat, dstat, sist, rp->siop_dsps, rp->siop_dsa,
   1491  1.16.4.2  nathanw 	     rp->siop_sbcl, acb->stat[0], acb->msg[0], acb->msg[1], rp->siop_sfbr);
   1492  1.16.4.2  nathanw #ifdef DEBUG
   1493  1.16.4.2  nathanw 	if (siopng_debug & 0x20)
   1494  1.16.4.2  nathanw 		panic("siopngchkintr: **** temp ****");
   1495  1.16.4.2  nathanw #endif
   1496  1.16.4.2  nathanw #ifdef DDB
   1497  1.16.4.2  nathanw 	Debugger ();
   1498  1.16.4.2  nathanw #endif
   1499  1.16.4.2  nathanw 	siopngreset (sc);		/* hard reset */
   1500  1.16.4.2  nathanw 	*status = -1;
   1501  1.16.4.2  nathanw 	return 0;		/* siopngreset cleaned up */
   1502  1.16.4.2  nathanw }
   1503  1.16.4.2  nathanw 
   1504  1.16.4.2  nathanw void
   1505  1.16.4.2  nathanw siopng_select(struct siop_softc *sc)
   1506  1.16.4.2  nathanw {
   1507  1.16.4.2  nathanw 	siop_regmap_p rp;
   1508  1.16.4.2  nathanw 	struct siop_acb *acb = sc->sc_nexus;
   1509  1.16.4.2  nathanw 
   1510  1.16.4.2  nathanw #ifdef DEBUG
   1511  1.16.4.2  nathanw 	if (siopng_debug & 1)
   1512  1.16.4.2  nathanw 		printf ("%s: select ", sc->sc_dev.dv_xname);
   1513  1.16.4.2  nathanw #endif
   1514  1.16.4.2  nathanw 
   1515  1.16.4.2  nathanw 	rp = sc->sc_siopp;
   1516  1.16.4.2  nathanw 	if (acb->xs->xs_control & XS_CTL_POLL || siopng_no_dma) {
   1517  1.16.4.2  nathanw 		sc->sc_flags |= SIOP_INTSOFF;
   1518  1.16.4.2  nathanw 		sc->sc_flags &= ~SIOP_INTDEFER;
   1519  1.16.4.2  nathanw 		if ((rp->siop_istat & 0x08) == 0) {
   1520  1.16.4.2  nathanw 			rp->siop_sien = 0;
   1521  1.16.4.2  nathanw 			rp->siop_dien = 0;
   1522  1.16.4.2  nathanw 		}
   1523  1.16.4.2  nathanw #if 0
   1524  1.16.4.2  nathanw 	} else if ((sc->sc_flags & SIOP_INTDEFER) == 0) {
   1525  1.16.4.2  nathanw 		sc->sc_flags &= ~SIOP_INTSOFF;
   1526  1.16.4.2  nathanw 		if ((rp->siop_istat & 0x08) == 0) {
   1527  1.16.4.2  nathanw 			rp->siop_sien = sc->sc_sien;
   1528  1.16.4.2  nathanw 			rp->siop_dien = sc->sc_dien;
   1529  1.16.4.2  nathanw 		}
   1530  1.16.4.2  nathanw #endif
   1531  1.16.4.2  nathanw 	}
   1532  1.16.4.2  nathanw #ifdef DEBUG
   1533  1.16.4.2  nathanw 	if (siopng_debug & 1)
   1534  1.16.4.2  nathanw 		printf ("siopng_select: target %x cmd %02x ds %p\n",
   1535  1.16.4.2  nathanw 		    acb->xs->xs_periph->periph_target, acb->cmd.opcode,
   1536  1.16.4.2  nathanw 		    &sc->sc_nexus->ds);
   1537  1.16.4.2  nathanw #endif
   1538  1.16.4.2  nathanw 
   1539  1.16.4.2  nathanw 	siopng_start(sc, acb->xs->xs_periph->periph_target,
   1540  1.16.4.2  nathanw 		acb->xs->xs_periph->periph_lun,
   1541  1.16.4.2  nathanw 	    (u_char *)&acb->cmd, acb->clen, acb->daddr, acb->dleft);
   1542  1.16.4.2  nathanw 
   1543  1.16.4.2  nathanw 	return;
   1544  1.16.4.2  nathanw }
   1545  1.16.4.2  nathanw 
   1546  1.16.4.2  nathanw /*
   1547  1.16.4.2  nathanw  * 53C720/770 interrupt handler
   1548  1.16.4.2  nathanw  */
   1549  1.16.4.2  nathanw 
   1550  1.16.4.2  nathanw void
   1551  1.16.4.2  nathanw siopngintr(register struct siop_softc *sc)
   1552  1.16.4.2  nathanw {
   1553  1.16.4.2  nathanw 	siop_regmap_p rp;
   1554  1.16.4.2  nathanw 	u_char istat, dstat;
   1555  1.16.4.2  nathanw 	u_short sist;
   1556  1.16.4.2  nathanw 	int status;
   1557  1.16.4.2  nathanw 	int s = splbio();
   1558  1.16.4.2  nathanw 
   1559  1.16.4.2  nathanw 	istat = sc->sc_istat;
   1560  1.16.4.2  nathanw 	if ((istat & (SIOP_ISTAT_SIP | SIOP_ISTAT_DIP)) == 0) {
   1561  1.16.4.2  nathanw 		splx(s);
   1562  1.16.4.2  nathanw 		return;
   1563  1.16.4.2  nathanw 	}
   1564  1.16.4.2  nathanw 
   1565  1.16.4.2  nathanw 	/* Got a valid interrupt on this device */
   1566  1.16.4.2  nathanw 	rp = sc->sc_siopp;
   1567  1.16.4.2  nathanw 	dstat = sc->sc_dstat;
   1568  1.16.4.2  nathanw 	sist = sc->sc_sist;
   1569  1.16.4.2  nathanw 	if (dstat & SIOP_DSTAT_SIR)
   1570  1.16.4.2  nathanw 		sc->sc_intcode = rp->siop_dsps;
   1571  1.16.4.2  nathanw 	sc->sc_istat = 0;
   1572  1.16.4.2  nathanw #ifdef DEBUG
   1573  1.16.4.2  nathanw 	if (siopng_debug & 1)
   1574  1.16.4.2  nathanw 		printf ("%s: intr istat %x dstat %x sist %x\n",
   1575  1.16.4.2  nathanw 		    sc->sc_dev.dv_xname, istat, dstat, sist);
   1576  1.16.4.2  nathanw 	if (!sc->sc_active) {
   1577  1.16.4.2  nathanw 		printf ("%s: spurious interrupt? istat %x dstat %x sist %x nexus %p status %x\n",
   1578  1.16.4.2  nathanw 		    sc->sc_dev.dv_xname, istat, dstat, sist,
   1579  1.16.4.2  nathanw 		    sc->sc_nexus, sc->sc_nexus ? sc->sc_nexus->stat[0] : 0);
   1580  1.16.4.2  nathanw 	}
   1581  1.16.4.2  nathanw #endif
   1582  1.16.4.2  nathanw 
   1583  1.16.4.2  nathanw #ifdef DEBUG
   1584  1.16.4.2  nathanw 	if (siopng_debug & 5) {
   1585  1.16.4.2  nathanw 		DCIAS(kvtop(&sc->sc_nexus->stat[0]));
   1586  1.16.4.2  nathanw 		printf ("%s: intr istat %x dstat %x sist %x dsps %lx sbcl %x sts %x msg %x\n",
   1587  1.16.4.2  nathanw 		    sc->sc_dev.dv_xname, istat, dstat, sist,
   1588  1.16.4.2  nathanw 		    rp->siop_dsps,  rp->siop_sbcl,
   1589  1.16.4.2  nathanw 		    sc->sc_nexus->stat[0], sc->sc_nexus->msg[0]);
   1590  1.16.4.2  nathanw 	}
   1591  1.16.4.2  nathanw #endif
   1592  1.16.4.2  nathanw 	if (sc->sc_flags & SIOP_INTDEFER) {
   1593  1.16.4.2  nathanw 		sc->sc_flags &= ~(SIOP_INTDEFER | SIOP_INTSOFF);
   1594  1.16.4.2  nathanw 		rp->siop_sien = sc->sc_sien;
   1595  1.16.4.2  nathanw 		rp->siop_dien = sc->sc_dien;
   1596  1.16.4.2  nathanw 	}
   1597  1.16.4.2  nathanw 	if (siopng_checkintr (sc, istat, dstat, sist, &status)) {
   1598  1.16.4.2  nathanw #if 1
   1599  1.16.4.2  nathanw 		if (status == 0xff)
   1600  1.16.4.2  nathanw 			printf ("siopngintr: status == 0xff\n");
   1601  1.16.4.2  nathanw #endif
   1602  1.16.4.2  nathanw 		if ((sc->sc_flags & (SIOP_INTSOFF | SIOP_INTDEFER)) != SIOP_INTSOFF) {
   1603  1.16.4.2  nathanw #if 0
   1604  1.16.4.2  nathanw 			if (rp->siop_sbcl & SIOP_BSY) {
   1605  1.16.4.2  nathanw 				printf ("%s: SCSI bus busy at completion",
   1606  1.16.4.2  nathanw 					sc->sc_dev.dv_xname);
   1607  1.16.4.2  nathanw 				printf(" targ %d sbcl %02x sfbr %x respid %02x dsp +%x\n",
   1608  1.16.4.2  nathanw 				    sc->sc_nexus->xs->xs_periph->periph_target,
   1609  1.16.4.2  nathanw 				    rp->siop_sbcl, rp->siop_sfbr, rp->siop_respid,
   1610  1.16.4.2  nathanw 				    rp->siop_dsp - sc->sc_scriptspa);
   1611  1.16.4.2  nathanw 			}
   1612  1.16.4.2  nathanw #endif
   1613  1.16.4.2  nathanw 			siopng_scsidone(sc->sc_nexus, sc->sc_nexus ?
   1614  1.16.4.2  nathanw 			    sc->sc_nexus->stat[0] : -1);
   1615  1.16.4.2  nathanw 		}
   1616  1.16.4.2  nathanw 	}
   1617  1.16.4.2  nathanw 	splx(s);
   1618  1.16.4.2  nathanw }
   1619  1.16.4.2  nathanw 
   1620  1.16.4.2  nathanw /*
   1621  1.16.4.2  nathanw  * This is based on the Progressive Peripherals 33Mhz Zeus driver and will
   1622  1.16.4.2  nathanw  * not be correct for other 53c710 boards.
   1623  1.16.4.2  nathanw  *
   1624  1.16.4.2  nathanw  */
   1625  1.16.4.2  nathanw void
   1626  1.16.4.2  nathanw scsi_period_to_siopng(struct siop_softc *sc, int target)
   1627  1.16.4.2  nathanw {
   1628  1.16.4.2  nathanw 	int period, offset, sxfer, scntl3 = 0;
   1629  1.16.4.2  nathanw 
   1630  1.16.4.2  nathanw 	period = sc->sc_nexus->msg[4];
   1631  1.16.4.2  nathanw 	offset = sc->sc_nexus->msg[5];
   1632  1.16.4.2  nathanw #ifdef FIXME
   1633  1.16.4.2  nathanw 	for (scntl3 = 1; scntl3 < 4; ++scntl3) {
   1634  1.16.4.2  nathanw 		sxfer = (period * 4 - 1) / sc->sc_tcp[scntl3] - 3;
   1635  1.16.4.2  nathanw 		if (sxfer >= 0 && sxfer <= 7)
   1636  1.16.4.2  nathanw 			break;
   1637  1.16.4.2  nathanw 	}
   1638  1.16.4.2  nathanw 	if (scntl3 > 3) {
   1639  1.16.4.2  nathanw 		printf("siopng sync: unable to compute sync params for period %dns\n",
   1640  1.16.4.2  nathanw 		    period * 4);
   1641  1.16.4.2  nathanw 		/*
   1642  1.16.4.2  nathanw 		 * XXX need to pick a value we can do and renegotiate
   1643  1.16.4.2  nathanw 		 */
   1644  1.16.4.2  nathanw 		sxfer = scntl3 = 0;
   1645  1.16.4.2  nathanw 	} else {
   1646  1.16.4.2  nathanw 		sxfer = (sxfer << 4) | ((offset <= SIOP_MAX_OFFSET) ?
   1647  1.16.4.2  nathanw 		    offset : SIOP_MAX_OFFSET);
   1648  1.16.4.2  nathanw #ifdef DEBUG_SYNC
   1649  1.16.4.2  nathanw 		printf("siopng sync: params for period %dns: sxfer %x scntl3 %x",
   1650  1.16.4.2  nathanw 		    period * 4, sxfer, scntl3);
   1651  1.16.4.2  nathanw 		printf(" actual period %dns\n",
   1652  1.16.4.2  nathanw 		    sc->sc_tcp[scntl3] * ((sxfer >> 4) + 4));
   1653  1.16.4.2  nathanw #endif /* DEBUG_SYNC */
   1654  1.16.4.2  nathanw 	}
   1655  1.16.4.2  nathanw #else /* FIXME */
   1656  1.16.4.2  nathanw 	sxfer = offset <= SIOP_MAX_OFFSET ? offset : SIOP_MAX_OFFSET;
   1657  1.16.4.2  nathanw 	sxfer |= 0x20;		/* XXX XFERP: 5 */
   1658  1.16.4.2  nathanw #ifndef FIXME
   1659  1.16.4.2  nathanw 	if (period <= (50 / 4))	/* XXX */
   1660  1.16.4.2  nathanw 		scntl3 = 0x95;	/* Ultra, SCF: /1, CCF: /4 */
   1661  1.16.4.2  nathanw 	else if (period <= (100 / 4))
   1662  1.16.4.2  nathanw 		scntl3 = 0x35;	/* SCF: /2, CCF: /4 */
   1663  1.16.4.2  nathanw 	else if (period <= (200 / 4))
   1664  1.16.4.2  nathanw 		scntl3 = 0x55;	/* SCF: /4, CCF: /4 */
   1665  1.16.4.2  nathanw 	else
   1666  1.16.4.2  nathanw 		scntl3 = 0xff;	/* XXX ??? */
   1667  1.16.4.2  nathanw #else
   1668  1.16.4.2  nathanw 	scntl3 = 5;
   1669  1.16.4.2  nathanw #endif
   1670  1.16.4.2  nathanw #endif
   1671  1.16.4.2  nathanw 	sc->sc_sync[target].sxfer = sxfer;
   1672  1.16.4.2  nathanw 	sc->sc_sync[target].scntl3 = scntl3 |
   1673  1.16.4.2  nathanw 	    (sc->sc_sync[target].scntl3 & SIOP_SCNTL3_EWS);
   1674  1.16.4.2  nathanw #ifdef DEBUG_SYNC
   1675  1.16.4.2  nathanw 	printf ("siopng sync: siop_sxfr %02x, siop_scntl3 %02x\n", sxfer, scntl3);
   1676  1.16.4.2  nathanw #endif
   1677  1.16.4.2  nathanw }
   1678  1.16.4.2  nathanw 
   1679  1.16.4.2  nathanw void
   1680  1.16.4.2  nathanw siopng_dump_registers(struct siop_softc *sc)
   1681  1.16.4.2  nathanw {
   1682  1.16.4.2  nathanw 	siop_regmap_p rp = sc->sc_siopp;
   1683  1.16.4.2  nathanw 
   1684  1.16.4.2  nathanw 	printf("  scntl0   %02x scntl1 %02x scntl2 %02x scntl3 %02x\n",
   1685  1.16.4.2  nathanw 	    rp->siop_scntl0, rp->siop_scntl1, rp->siop_scntl2, rp->siop_scntl3);
   1686  1.16.4.2  nathanw 	printf("  scid     %02x sxfer  %02x sdid   %02x gpreg  %02x\n",
   1687  1.16.4.2  nathanw 	    rp->siop_scid, rp->siop_sxfer, rp->siop_sdid, rp->siop_gpreg);
   1688  1.16.4.2  nathanw 	printf("  sfbr     %02x socl   %02x ssid   %02x sbcl   %02x\n",
   1689  1.16.4.2  nathanw 	    rp->siop_sfbr, rp->siop_socl, rp->siop_ssid, rp->siop_sbcl);
   1690  1.16.4.2  nathanw 	printf("  dstat    %02x sstat0 %02x sstat1 %02x sstat2 %02x\n",
   1691  1.16.4.2  nathanw 	    rp->siop_dstat, rp->siop_sstat0, rp->siop_sstat1, rp->siop_sstat2);
   1692  1.16.4.2  nathanw 	printf("  ctest0   %02x ctest1 %02x ctest2 %02x ctest3 %02x\n",
   1693  1.16.4.2  nathanw 	    rp->siop_ctest0, rp->siop_ctest1, rp->siop_ctest2, rp->siop_ctest3);
   1694  1.16.4.2  nathanw 	printf("  dfifo    %02x ctest4 %02x ctest5 %02x ctest6 %02x\n",
   1695  1.16.4.2  nathanw 	    0, rp->siop_ctest4, rp->siop_ctest5, rp->siop_ctest6);
   1696  1.16.4.2  nathanw 	printf("  dcmd     %02x dbc2   %02x dbc1   %02x dbc0   %02x\n",
   1697  1.16.4.2  nathanw 	    rp->siop_dcmd, rp->siop_dbc2, rp->siop_dbc1, rp->siop_dbc0);
   1698  1.16.4.2  nathanw 	printf("  dmode    %02x dien   %02x dwt    %02x dcntl  %02x\n",
   1699  1.16.4.2  nathanw 	    rp->siop_dmode, rp->siop_dien, rp->siop_dwt, rp->siop_dcntl);
   1700  1.16.4.2  nathanw 	printf("  stest0   %02x stest1 %02x stest2 %02x stest3 %02x\n",
   1701  1.16.4.2  nathanw 	    rp->siop_stest0, rp->siop_stest1, rp->siop_stest2, rp->siop_stest3);
   1702  1.16.4.2  nathanw 	printf("  istat    %02x sien %04x sist %04x respid %04x\n",
   1703  1.16.4.2  nathanw 	    rp->siop_istat, rp->siop_sien, rp->siop_sist, rp->siop_respid);
   1704  1.16.4.2  nathanw 	printf("  sidl   %04x sodl %04x sbdl %04x\n",
   1705  1.16.4.2  nathanw 	    rp->siop_sidl, rp->siop_sodl, rp->siop_sbdl);
   1706  1.16.4.2  nathanw 	printf("  dsps     %08lx dsp      %08lx (+%lx)\n",
   1707  1.16.4.2  nathanw 	    rp->siop_dsps, rp->siop_dsp, rp->siop_dsp > sc->sc_scriptspa ?
   1708  1.16.4.2  nathanw 	    rp->siop_dsp - sc->sc_scriptspa : 0);
   1709  1.16.4.2  nathanw 	printf("  dsa      %08lx temp     %08lx dnad     %08lx\n",
   1710  1.16.4.2  nathanw 	    rp->siop_dsa, rp->siop_temp, rp->siop_dnad);
   1711  1.16.4.2  nathanw 	printf("  scratcha %08lx scratchb %08lx adder     %08lx\n",
   1712  1.16.4.2  nathanw 	    rp->siop_scratcha, rp->siop_scratchb, rp->siop_adder);
   1713  1.16.4.2  nathanw }
   1714  1.16.4.2  nathanw 
   1715  1.16.4.2  nathanw #ifdef DEBUG
   1716  1.16.4.2  nathanw 
   1717  1.16.4.2  nathanw #if SIOP_TRACE_SIZE
   1718  1.16.4.2  nathanw void
   1719  1.16.4.2  nathanw siopng_dump_trace(void)
   1720  1.16.4.2  nathanw {
   1721  1.16.4.2  nathanw 	int i;
   1722  1.16.4.2  nathanw 
   1723  1.16.4.2  nathanw 	printf("siopng trace: next index %d\n", siopng_trix);
   1724  1.16.4.2  nathanw 	i = siopng_trix;
   1725  1.16.4.2  nathanw 	do {
   1726  1.16.4.2  nathanw 		printf("%3d: '%c' %02x %02x %02x\n", i, siopng_trbuf[i],
   1727  1.16.4.2  nathanw 		    siopng_trbuf[i + 1], siopng_trbuf[i + 2], siopng_trbuf[i + 3]);
   1728  1.16.4.2  nathanw 		i = (i + 4) & (SIOP_TRACE_SIZE - 1);
   1729  1.16.4.2  nathanw 	} while (i != siopng_trix);
   1730  1.16.4.2  nathanw }
   1731  1.16.4.2  nathanw #endif
   1732  1.16.4.2  nathanw 
   1733  1.16.4.2  nathanw void
   1734  1.16.4.2  nathanw siopng_dump_acb(struct siop_acb *acb)
   1735  1.16.4.2  nathanw {
   1736  1.16.4.2  nathanw 	u_char *b = (u_char *) &acb->cmd;
   1737  1.16.4.2  nathanw 	int i;
   1738  1.16.4.2  nathanw 
   1739  1.16.4.2  nathanw 	printf("acb@%p ", acb);
   1740  1.16.4.2  nathanw 	if (acb->xs == NULL) {
   1741  1.16.4.2  nathanw 		printf("<unused>\n");
   1742  1.16.4.2  nathanw 		return;
   1743  1.16.4.2  nathanw 	}
   1744  1.16.4.2  nathanw 	printf("(%d:%d) flags %2x clen %2d cmd ",
   1745  1.16.4.2  nathanw 		acb->xs->xs_periph->periph_target,
   1746  1.16.4.2  nathanw 	    acb->xs->xs_periph->periph_lun, acb->flags, acb->clen);
   1747  1.16.4.2  nathanw 	for (i = acb->clen; i; --i)
   1748  1.16.4.2  nathanw 		printf(" %02x", *b++);
   1749  1.16.4.2  nathanw 	printf("\n");
   1750  1.16.4.2  nathanw 	printf("  xs: %p data %p:%04x ", acb->xs, acb->xs->data,
   1751  1.16.4.2  nathanw 	    acb->xs->datalen);
   1752  1.16.4.2  nathanw 	printf("va %p:%lx ", acb->iob_buf, acb->iob_len);
   1753  1.16.4.2  nathanw 	printf("cur %lx:%lx\n", acb->iob_curbuf, acb->iob_curlen);
   1754  1.16.4.2  nathanw }
   1755  1.16.4.2  nathanw 
   1756  1.16.4.2  nathanw void
   1757  1.16.4.2  nathanw siopng_dump(struct siop_softc *sc)
   1758  1.16.4.2  nathanw {
   1759  1.16.4.2  nathanw 	struct siop_acb *acb;
   1760  1.16.4.2  nathanw 	siop_regmap_p rp = sc->sc_siopp;
   1761  1.16.4.2  nathanw 	int s;
   1762  1.16.4.2  nathanw 	int i;
   1763  1.16.4.2  nathanw 
   1764  1.16.4.2  nathanw 	s = splbio();
   1765  1.16.4.2  nathanw #if SIOP_TRACE_SIZE
   1766  1.16.4.2  nathanw 	siopng_dump_trace();
   1767  1.16.4.2  nathanw #endif
   1768  1.16.4.2  nathanw 	printf("%s@%p regs %p istat %x\n",
   1769  1.16.4.2  nathanw 	    sc->sc_dev.dv_xname, sc, rp, rp->siop_istat);
   1770  1.16.4.2  nathanw 	if ((acb = sc->free_list.tqh_first) > 0) {
   1771  1.16.4.2  nathanw 		printf("Free list:\n");
   1772  1.16.4.2  nathanw 		while (acb) {
   1773  1.16.4.2  nathanw 			siopng_dump_acb(acb);
   1774  1.16.4.2  nathanw 			acb = acb->chain.tqe_next;
   1775  1.16.4.2  nathanw 		}
   1776  1.16.4.2  nathanw 	}
   1777  1.16.4.2  nathanw 	if ((acb = sc->ready_list.tqh_first) > 0) {
   1778  1.16.4.2  nathanw 		printf("Ready list:\n");
   1779  1.16.4.2  nathanw 		while (acb) {
   1780  1.16.4.2  nathanw 			siopng_dump_acb(acb);
   1781  1.16.4.2  nathanw 			acb = acb->chain.tqe_next;
   1782  1.16.4.2  nathanw 		}
   1783  1.16.4.2  nathanw 	}
   1784  1.16.4.2  nathanw 	if ((acb = sc->nexus_list.tqh_first) > 0) {
   1785  1.16.4.2  nathanw 		printf("Nexus list:\n");
   1786  1.16.4.2  nathanw 		while (acb) {
   1787  1.16.4.2  nathanw 			siopng_dump_acb(acb);
   1788  1.16.4.2  nathanw 			acb = acb->chain.tqe_next;
   1789  1.16.4.2  nathanw 		}
   1790  1.16.4.2  nathanw 	}
   1791  1.16.4.2  nathanw 	if (sc->sc_nexus) {
   1792  1.16.4.2  nathanw 		printf("Nexus:\n");
   1793  1.16.4.2  nathanw 		siopng_dump_acb(sc->sc_nexus);
   1794  1.16.4.2  nathanw 	}
   1795  1.16.4.2  nathanw 	for (i = 0; i < 8; ++i) {
   1796  1.16.4.2  nathanw 		if (sc->sc_tinfo[i].cmds > 2) {
   1797  1.16.4.2  nathanw 			printf("tgt %d: cmds %d disc %d lubusy %x\n",
   1798  1.16.4.2  nathanw 			    i, sc->sc_tinfo[i].cmds,
   1799  1.16.4.2  nathanw 			    sc->sc_tinfo[i].dconns,
   1800  1.16.4.2  nathanw 			    sc->sc_tinfo[i].lubusy);
   1801  1.16.4.2  nathanw 		}
   1802  1.16.4.2  nathanw 	}
   1803  1.16.4.2  nathanw 	splx(s);
   1804  1.16.4.2  nathanw }
   1805  1.16.4.2  nathanw #endif
   1806