Home | History | Annotate | Line # | Download | only in ic
oosiop.c revision 1.10.2.1
      1  1.10.2.1        ad /*	$NetBSD: oosiop.c,v 1.10.2.1 2007/10/23 20:07:38 ad Exp $	*/
      2       1.1   tsutsui 
      3       1.1   tsutsui /*
      4       1.1   tsutsui  * Copyright (c) 2001 Shuichiro URATA.  All rights reserved.
      5       1.1   tsutsui  *
      6       1.1   tsutsui  * Redistribution and use in source and binary forms, with or without
      7       1.1   tsutsui  * modification, are permitted provided that the following conditions
      8       1.1   tsutsui  * are met:
      9       1.1   tsutsui  * 1. Redistributions of source code must retain the above copyright
     10       1.1   tsutsui  *    notice, this list of conditions and the following disclaimer.
     11       1.1   tsutsui  * 2. Redistributions in binary form must reproduce the above copyright
     12       1.1   tsutsui  *    notice, this list of conditions and the following disclaimer in the
     13       1.1   tsutsui  *    documentation and/or other materials provided with the distribution.
     14       1.1   tsutsui  * 3. The name of the author may not be used to endorse or promote products
     15       1.1   tsutsui  *    derived from this software without specific prior written permission.
     16       1.1   tsutsui  *
     17       1.1   tsutsui  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18       1.1   tsutsui  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19       1.1   tsutsui  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20       1.1   tsutsui  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21       1.1   tsutsui  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22       1.1   tsutsui  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23       1.1   tsutsui  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24       1.1   tsutsui  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25       1.1   tsutsui  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26       1.1   tsutsui  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27       1.1   tsutsui  */
     28       1.1   tsutsui 
     29       1.1   tsutsui /*
     30       1.1   tsutsui  * NCR53C700 SCSI I/O processor (OOSIOP) driver
     31       1.1   tsutsui  *
     32       1.1   tsutsui  * TODO:
     33       1.1   tsutsui  *   - More better error handling.
     34       1.1   tsutsui  *   - Implement tagged queuing.
     35       1.1   tsutsui  */
     36       1.2     lukem 
     37       1.2     lukem #include <sys/cdefs.h>
     38  1.10.2.1        ad __KERNEL_RCSID(0, "$NetBSD: oosiop.c,v 1.10.2.1 2007/10/23 20:07:38 ad Exp $");
     39       1.1   tsutsui 
     40       1.1   tsutsui #include <sys/param.h>
     41       1.1   tsutsui #include <sys/systm.h>
     42       1.1   tsutsui #include <sys/callout.h>
     43       1.1   tsutsui #include <sys/kernel.h>
     44       1.1   tsutsui #include <sys/device.h>
     45       1.1   tsutsui #include <sys/buf.h>
     46       1.1   tsutsui #include <sys/malloc.h>
     47       1.1   tsutsui #include <sys/queue.h>
     48       1.1   tsutsui 
     49       1.1   tsutsui #include <uvm/uvm_extern.h>
     50       1.1   tsutsui 
     51       1.1   tsutsui #include <dev/scsipi/scsi_all.h>
     52       1.1   tsutsui #include <dev/scsipi/scsipi_all.h>
     53       1.1   tsutsui #include <dev/scsipi/scsiconf.h>
     54       1.1   tsutsui #include <dev/scsipi/scsi_message.h>
     55       1.1   tsutsui 
     56  1.10.2.1        ad #include <sys/cpu.h>
     57  1.10.2.1        ad #include <sys/bus.h>
     58       1.1   tsutsui 
     59       1.1   tsutsui #include <dev/ic/oosiopreg.h>
     60       1.1   tsutsui #include <dev/ic/oosiopvar.h>
     61       1.1   tsutsui #include <dev/microcode/siop/oosiop.out>
     62       1.1   tsutsui 
     63       1.1   tsutsui static int	oosiop_alloc_cb(struct oosiop_softc *, int);
     64       1.1   tsutsui 
     65       1.9     perry static inline void oosiop_relocate_io(struct oosiop_softc *, bus_addr_t);
     66       1.9     perry static inline void oosiop_relocate_tc(struct oosiop_softc *, bus_addr_t);
     67       1.9     perry static inline void oosiop_fixup_select(struct oosiop_softc *, bus_addr_t,
     68       1.1   tsutsui 		         int);
     69       1.9     perry static inline void oosiop_fixup_jump(struct oosiop_softc *, bus_addr_t,
     70       1.1   tsutsui 		         bus_addr_t);
     71       1.9     perry static inline void oosiop_fixup_move(struct oosiop_softc *, bus_addr_t,
     72       1.1   tsutsui 		         bus_size_t, bus_addr_t);
     73       1.1   tsutsui 
     74       1.1   tsutsui static void	oosiop_load_script(struct oosiop_softc *);
     75       1.1   tsutsui static void	oosiop_setup_sgdma(struct oosiop_softc *, struct oosiop_cb *);
     76       1.1   tsutsui static void	oosiop_setup_dma(struct oosiop_softc *);
     77       1.1   tsutsui static void	oosiop_flush_fifo(struct oosiop_softc *);
     78       1.1   tsutsui static void	oosiop_clear_fifo(struct oosiop_softc *);
     79       1.1   tsutsui static void	oosiop_phasemismatch(struct oosiop_softc *);
     80       1.1   tsutsui static void	oosiop_setup_syncxfer(struct oosiop_softc *);
     81       1.1   tsutsui static void	oosiop_set_syncparam(struct oosiop_softc *, int, int, int);
     82       1.1   tsutsui static void	oosiop_minphys(struct buf *);
     83       1.1   tsutsui static void	oosiop_scsipi_request(struct scsipi_channel *,
     84       1.1   tsutsui 		    scsipi_adapter_req_t, void *);
     85       1.1   tsutsui static void	oosiop_done(struct oosiop_softc *, struct oosiop_cb *);
     86       1.1   tsutsui static void	oosiop_timeout(void *);
     87       1.1   tsutsui static void	oosiop_reset(struct oosiop_softc *);
     88       1.1   tsutsui static void	oosiop_reset_bus(struct oosiop_softc *);
     89       1.1   tsutsui static void	oosiop_scriptintr(struct oosiop_softc *);
     90       1.1   tsutsui static void	oosiop_msgin(struct oosiop_softc *, struct oosiop_cb *);
     91       1.1   tsutsui 
     92       1.1   tsutsui /* Trap interrupt code for unexpected data I/O */
     93       1.1   tsutsui #define	DATAIN_TRAP	0xdead0001
     94       1.1   tsutsui #define	DATAOUT_TRAP	0xdead0002
     95       1.1   tsutsui 
     96       1.1   tsutsui /* Possible TP and SCF conbination */
     97       1.1   tsutsui static const struct {
     98       1.6   tsutsui 	uint8_t		tp;
     99       1.6   tsutsui 	uint8_t		scf;
    100       1.1   tsutsui } synctbl[] = {
    101       1.1   tsutsui 	{0, 1},		/* SCLK /  4.0 */
    102       1.1   tsutsui 	{1, 1},		/* SCLK /  5.0 */
    103       1.1   tsutsui 	{2, 1},		/* SCLK /  6.0 */
    104       1.1   tsutsui 	{3, 1},		/* SCLK /  7.0 */
    105       1.1   tsutsui 	{1, 2},		/* SCLK /  7.5 */
    106       1.1   tsutsui 	{4, 1},		/* SCLK /  8.0 */
    107       1.1   tsutsui 	{5, 1},		/* SCLK /  9.0 */
    108       1.1   tsutsui 	{6, 1},		/* SCLK / 10.0 */
    109       1.1   tsutsui 	{3, 2},		/* SCLK / 10.5 */
    110       1.1   tsutsui 	{7, 1},		/* SCLK / 11.0 */
    111       1.1   tsutsui 	{4, 2},		/* SCLK / 12.0 */
    112       1.1   tsutsui 	{5, 2},		/* SCLK / 13.5 */
    113       1.1   tsutsui 	{3, 3},		/* SCLK / 14.0 */
    114       1.1   tsutsui 	{6, 2},		/* SCLK / 15.0 */
    115       1.1   tsutsui 	{4, 3},		/* SCLK / 16.0 */
    116       1.1   tsutsui 	{7, 2},		/* SCLK / 16.5 */
    117       1.1   tsutsui 	{5, 3},		/* SCLK / 18.0 */
    118       1.1   tsutsui 	{6, 3},		/* SCLK / 20.0 */
    119       1.1   tsutsui 	{7, 3}		/* SCLK / 22.0 */
    120       1.1   tsutsui };
    121       1.1   tsutsui #define	NSYNCTBL	(sizeof(synctbl) / sizeof(synctbl[0]))
    122       1.1   tsutsui 
    123       1.1   tsutsui #define	oosiop_period(sc, tp, scf)					\
    124       1.1   tsutsui 	    (((1000000000 / (sc)->sc_freq) * (tp) * (scf)) / 40)
    125       1.1   tsutsui 
    126       1.1   tsutsui void
    127       1.1   tsutsui oosiop_attach(struct oosiop_softc *sc)
    128       1.1   tsutsui {
    129       1.1   tsutsui 	bus_size_t scrsize;
    130       1.1   tsutsui 	bus_dma_segment_t seg;
    131       1.1   tsutsui 	struct oosiop_cb *cb;
    132       1.1   tsutsui 	int err, i, nseg;
    133       1.1   tsutsui 
    134       1.1   tsutsui 	/*
    135       1.1   tsutsui 	 * Allocate DMA-safe memory for the script and map it.
    136       1.1   tsutsui 	 */
    137       1.1   tsutsui 	scrsize = sizeof(oosiop_script);
    138       1.1   tsutsui 	err = bus_dmamem_alloc(sc->sc_dmat, scrsize, PAGE_SIZE, 0, &seg, 1,
    139       1.1   tsutsui 	    &nseg, BUS_DMA_NOWAIT);
    140       1.1   tsutsui 	if (err) {
    141       1.1   tsutsui 		printf(": failed to allocate script memory, err=%d\n", err);
    142       1.1   tsutsui 		return;
    143       1.1   tsutsui 	}
    144       1.1   tsutsui 	err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, scrsize,
    145      1.10  christos 	    (void **)&sc->sc_scr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
    146       1.1   tsutsui 	if (err) {
    147       1.1   tsutsui 		printf(": failed to map script memory, err=%d\n", err);
    148       1.1   tsutsui 		return;
    149       1.1   tsutsui 	}
    150       1.1   tsutsui 	err = bus_dmamap_create(sc->sc_dmat, scrsize, 1, scrsize, 0,
    151       1.1   tsutsui 	    BUS_DMA_NOWAIT, &sc->sc_scrdma);
    152       1.1   tsutsui 	if (err) {
    153       1.1   tsutsui 		printf(": failed to create script map, err=%d\n", err);
    154       1.1   tsutsui 		return;
    155       1.1   tsutsui 	}
    156       1.1   tsutsui 	err = bus_dmamap_load(sc->sc_dmat, sc->sc_scrdma, sc->sc_scr, scrsize,
    157       1.1   tsutsui 	    NULL, BUS_DMA_NOWAIT | BUS_DMA_WRITE);
    158       1.1   tsutsui 	if (err) {
    159       1.1   tsutsui 		printf(": failed to load script map, err=%d\n", err);
    160       1.1   tsutsui 		return;
    161       1.1   tsutsui 	}
    162       1.1   tsutsui 	sc->sc_scrbase = sc->sc_scrdma->dm_segs[0].ds_addr;
    163       1.1   tsutsui 
    164       1.1   tsutsui 	/* Initialize command block array */
    165       1.1   tsutsui 	TAILQ_INIT(&sc->sc_free_cb);
    166       1.1   tsutsui 	TAILQ_INIT(&sc->sc_cbq);
    167       1.1   tsutsui 	if (oosiop_alloc_cb(sc, OOSIOP_NCB) != 0)
    168       1.1   tsutsui 		return;
    169       1.1   tsutsui 
    170       1.1   tsutsui 	/* Use first cb to reselection msgin buffer */
    171       1.1   tsutsui 	cb = TAILQ_FIRST(&sc->sc_free_cb);
    172       1.1   tsutsui 	sc->sc_reselbuf = cb->xferdma->dm_segs[0].ds_addr +
    173       1.1   tsutsui 	    offsetof(struct oosiop_xfer, msgin[0]);
    174       1.1   tsutsui 
    175       1.1   tsutsui 	for (i = 0; i < OOSIOP_NTGT; i++) {
    176       1.1   tsutsui 		sc->sc_tgt[i].nexus = NULL;
    177       1.1   tsutsui 		sc->sc_tgt[i].flags = 0;
    178       1.1   tsutsui 	}
    179       1.1   tsutsui 
    180       1.1   tsutsui 	/* Setup asynchronous clock divisor parameters */
    181       1.1   tsutsui 	if (sc->sc_freq <= 25000000) {
    182       1.1   tsutsui 		sc->sc_ccf = 10;
    183       1.1   tsutsui 		sc->sc_dcntl = OOSIOP_DCNTL_CF_1;
    184       1.1   tsutsui 	} else if (sc->sc_freq <= 37500000) {
    185       1.1   tsutsui 		sc->sc_ccf = 15;
    186       1.1   tsutsui 		sc->sc_dcntl = OOSIOP_DCNTL_CF_1_5;
    187       1.1   tsutsui 	} else if (sc->sc_freq <= 50000000) {
    188       1.1   tsutsui 		sc->sc_ccf = 20;
    189       1.1   tsutsui 		sc->sc_dcntl = OOSIOP_DCNTL_CF_2;
    190       1.1   tsutsui 	} else {
    191       1.1   tsutsui 		sc->sc_ccf = 30;
    192       1.1   tsutsui 		sc->sc_dcntl = OOSIOP_DCNTL_CF_3;
    193       1.1   tsutsui 	}
    194       1.1   tsutsui 
    195       1.1   tsutsui 	if (sc->sc_chip == OOSIOP_700)
    196       1.1   tsutsui 		sc->sc_minperiod = oosiop_period(sc, 4, sc->sc_ccf);
    197       1.1   tsutsui 	else
    198       1.1   tsutsui 		sc->sc_minperiod = oosiop_period(sc, 4, 10);
    199       1.1   tsutsui 
    200       1.1   tsutsui 	if (sc->sc_minperiod < 25)
    201       1.1   tsutsui 		sc->sc_minperiod = 25;	/* limit to 10MB/s */
    202       1.1   tsutsui 
    203       1.1   tsutsui 	printf(": NCR53C700%s rev %d, %dMHz, SCSI ID %d\n",
    204       1.1   tsutsui 	    sc->sc_chip == OOSIOP_700_66 ? "-66" : "",
    205       1.1   tsutsui 	    oosiop_read_1(sc, OOSIOP_CTEST7) >> 4,
    206       1.1   tsutsui 	    sc->sc_freq / 1000000, sc->sc_id);
    207       1.1   tsutsui 	/*
    208       1.1   tsutsui 	 * Reset all
    209       1.1   tsutsui 	 */
    210       1.1   tsutsui 	oosiop_reset(sc);
    211       1.1   tsutsui 	oosiop_reset_bus(sc);
    212       1.1   tsutsui 
    213       1.1   tsutsui 	/*
    214       1.1   tsutsui 	 * Start SCRIPTS processor
    215       1.1   tsutsui 	 */
    216       1.1   tsutsui 	oosiop_load_script(sc);
    217       1.1   tsutsui 	sc->sc_active = 0;
    218       1.1   tsutsui 	oosiop_write_4(sc, OOSIOP_DSP, sc->sc_scrbase + Ent_wait_reselect);
    219       1.1   tsutsui 
    220       1.1   tsutsui 	/*
    221       1.1   tsutsui 	 * Fill in the scsipi_adapter.
    222       1.1   tsutsui 	 */
    223       1.1   tsutsui 	sc->sc_adapter.adapt_dev = &sc->sc_dev;
    224       1.1   tsutsui 	sc->sc_adapter.adapt_nchannels = 1;
    225       1.1   tsutsui 	sc->sc_adapter.adapt_openings = OOSIOP_NCB;
    226       1.1   tsutsui 	sc->sc_adapter.adapt_max_periph = 1;
    227       1.1   tsutsui 	sc->sc_adapter.adapt_ioctl = NULL;
    228       1.1   tsutsui 	sc->sc_adapter.adapt_minphys = oosiop_minphys;
    229       1.1   tsutsui 	sc->sc_adapter.adapt_request = oosiop_scsipi_request;
    230       1.1   tsutsui 
    231       1.1   tsutsui 	/*
    232       1.1   tsutsui 	 * Fill in the scsipi_channel.
    233       1.1   tsutsui 	 */
    234       1.1   tsutsui 	sc->sc_channel.chan_adapter = &sc->sc_adapter;
    235       1.1   tsutsui 	sc->sc_channel.chan_bustype = &scsi_bustype;
    236       1.1   tsutsui 	sc->sc_channel.chan_channel = 0;
    237       1.1   tsutsui 	sc->sc_channel.chan_ntargets = OOSIOP_NTGT;
    238       1.1   tsutsui 	sc->sc_channel.chan_nluns = 8;
    239       1.1   tsutsui 	sc->sc_channel.chan_id = sc->sc_id;
    240       1.1   tsutsui 
    241       1.1   tsutsui 	/*
    242       1.1   tsutsui 	 * Now try to attach all the sub devices.
    243       1.1   tsutsui 	 */
    244       1.1   tsutsui 	config_found(&sc->sc_dev, &sc->sc_channel, scsiprint);
    245       1.1   tsutsui }
    246       1.1   tsutsui 
    247       1.1   tsutsui static int
    248       1.1   tsutsui oosiop_alloc_cb(struct oosiop_softc *sc, int ncb)
    249       1.1   tsutsui {
    250       1.1   tsutsui 	struct oosiop_cb *cb;
    251       1.1   tsutsui 	struct oosiop_xfer *xfer;
    252       1.1   tsutsui 	bus_size_t xfersize;
    253       1.1   tsutsui 	bus_dma_segment_t seg;
    254       1.1   tsutsui 	int i, s, err, nseg;
    255       1.1   tsutsui 
    256       1.1   tsutsui 	/*
    257       1.1   tsutsui 	 * Allocate oosiop_cb.
    258       1.1   tsutsui 	 */
    259       1.1   tsutsui 	cb = malloc(sizeof(struct oosiop_cb) * ncb, M_DEVBUF, M_NOWAIT|M_ZERO);
    260       1.1   tsutsui 	if (cb == NULL) {
    261       1.1   tsutsui 		printf(": failed to allocate cb memory\n");
    262       1.1   tsutsui 		return (ENOMEM);
    263       1.1   tsutsui 	}
    264       1.1   tsutsui 
    265       1.1   tsutsui 	/*
    266       1.1   tsutsui 	 * Allocate DMA-safe memory for the oosiop_xfer and map it.
    267       1.1   tsutsui 	 */
    268       1.1   tsutsui 	xfersize = sizeof(struct oosiop_xfer) * ncb;
    269       1.1   tsutsui 	err = bus_dmamem_alloc(sc->sc_dmat, xfersize, PAGE_SIZE, 0, &seg, 1,
    270       1.1   tsutsui 	    &nseg, BUS_DMA_NOWAIT);
    271       1.1   tsutsui 	if (err) {
    272       1.1   tsutsui 		printf(": failed to allocate xfer block memory, err=%d\n", err);
    273       1.1   tsutsui 		return (err);
    274       1.1   tsutsui 	}
    275       1.1   tsutsui 	err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, xfersize,
    276      1.10  christos 	    (void **)(void *)&xfer, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
    277       1.1   tsutsui 	if (err) {
    278       1.1   tsutsui 		printf(": failed to map xfer block memory, err=%d\n", err);
    279       1.1   tsutsui 		return (err);
    280       1.1   tsutsui 	}
    281       1.1   tsutsui 
    282       1.1   tsutsui 	/* Initialize each command block */
    283       1.1   tsutsui 	for (i = 0; i < ncb; i++) {
    284       1.1   tsutsui 		err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE,
    285       1.1   tsutsui 		    0, BUS_DMA_NOWAIT, &cb->cmddma);
    286       1.1   tsutsui 		if (err) {
    287       1.1   tsutsui 			printf(": failed to create cmddma map, err=%d\n", err);
    288       1.1   tsutsui 			return (err);
    289       1.1   tsutsui 		}
    290       1.1   tsutsui 		err = bus_dmamap_create(sc->sc_dmat, OOSIOP_MAX_XFER,
    291       1.1   tsutsui 		    OOSIOP_NSG, OOSIOP_DBC_MAX, 0, BUS_DMA_NOWAIT,
    292       1.1   tsutsui 		    &cb->datadma);
    293       1.1   tsutsui 		if (err) {
    294       1.1   tsutsui 			printf(": failed to create datadma map, err=%d\n", err);
    295       1.1   tsutsui 			return (err);
    296       1.1   tsutsui 		}
    297       1.1   tsutsui 
    298       1.1   tsutsui 		err = bus_dmamap_create(sc->sc_dmat,
    299       1.1   tsutsui 		    sizeof(struct oosiop_xfer), 1, sizeof(struct oosiop_xfer),
    300       1.1   tsutsui 		    0, BUS_DMA_NOWAIT, &cb->xferdma);
    301       1.1   tsutsui 		if (err) {
    302       1.1   tsutsui 			printf(": failed to create xfer block map, err=%d\n",
    303       1.1   tsutsui 			    err);
    304       1.1   tsutsui 			return (err);
    305       1.1   tsutsui 		}
    306       1.1   tsutsui 		err = bus_dmamap_load(sc->sc_dmat, cb->xferdma, xfer,
    307       1.1   tsutsui 		    sizeof(struct oosiop_xfer), NULL, BUS_DMA_NOWAIT);
    308       1.1   tsutsui 		if (err) {
    309       1.1   tsutsui 			printf(": failed to load xfer block, err=%d\n", err);
    310       1.1   tsutsui 			return (err);
    311       1.1   tsutsui 		}
    312       1.1   tsutsui 
    313       1.1   tsutsui 		cb->xfer = xfer;
    314       1.1   tsutsui 
    315       1.1   tsutsui 		s = splbio();
    316       1.1   tsutsui 		TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
    317       1.1   tsutsui 		splx(s);
    318       1.1   tsutsui 
    319       1.1   tsutsui 		cb++;
    320       1.1   tsutsui 		xfer++;
    321       1.1   tsutsui 	}
    322       1.1   tsutsui 
    323       1.1   tsutsui 	return (0);
    324       1.1   tsutsui }
    325       1.1   tsutsui 
    326       1.9     perry static inline void
    327       1.1   tsutsui oosiop_relocate_io(struct oosiop_softc *sc, bus_addr_t addr)
    328       1.1   tsutsui {
    329       1.6   tsutsui 	uint32_t dcmd;
    330       1.1   tsutsui 	int32_t dsps;
    331       1.1   tsutsui 
    332       1.1   tsutsui 	dcmd = le32toh(sc->sc_scr[addr / 4 + 0]);
    333       1.1   tsutsui 	dsps = le32toh(sc->sc_scr[addr / 4 + 1]);
    334       1.1   tsutsui 
    335       1.1   tsutsui 	/* convert relative to absolute */
    336       1.1   tsutsui 	if (dcmd & 0x04000000) {
    337       1.1   tsutsui 		dcmd &= ~0x04000000;
    338       1.1   tsutsui #if 0
    339       1.1   tsutsui 		/*
    340       1.5       wiz 		 * sign extension isn't needed here because
    341       1.1   tsutsui 		 * ncr53cxxx.c generates 32 bit dsps.
    342       1.1   tsutsui 		 */
    343       1.1   tsutsui 		dsps <<= 8;
    344       1.1   tsutsui 		dsps >>= 8;
    345       1.1   tsutsui #endif
    346       1.1   tsutsui 		sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
    347       1.1   tsutsui 		dsps += addr + 8;
    348       1.1   tsutsui 	}
    349       1.1   tsutsui 
    350       1.1   tsutsui 	sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
    351       1.1   tsutsui }
    352       1.1   tsutsui 
    353       1.9     perry static inline void
    354       1.1   tsutsui oosiop_relocate_tc(struct oosiop_softc *sc, bus_addr_t addr)
    355       1.1   tsutsui {
    356       1.6   tsutsui 	uint32_t dcmd;
    357       1.1   tsutsui 	int32_t dsps;
    358       1.1   tsutsui 
    359       1.1   tsutsui 	dcmd = le32toh(sc->sc_scr[addr / 4 + 0]);
    360       1.1   tsutsui 	dsps = le32toh(sc->sc_scr[addr / 4 + 1]);
    361       1.1   tsutsui 
    362       1.1   tsutsui 	/* convert relative to absolute */
    363       1.1   tsutsui 	if (dcmd & 0x00800000) {
    364       1.1   tsutsui 		dcmd &= ~0x00800000;
    365       1.1   tsutsui 		sc->sc_scr[addr / 4] = htole32(dcmd);
    366       1.1   tsutsui #if 0
    367       1.1   tsutsui 		/*
    368       1.5       wiz 		 * sign extension isn't needed here because
    369       1.1   tsutsui 		 * ncr53cxxx.c generates 32 bit dsps.
    370       1.1   tsutsui 		 */
    371       1.1   tsutsui 		dsps <<= 8;
    372       1.1   tsutsui 		dsps >>= 8;
    373       1.1   tsutsui #endif
    374       1.1   tsutsui 		dsps += addr + 8;
    375       1.1   tsutsui 	}
    376       1.1   tsutsui 
    377       1.1   tsutsui 	sc->sc_scr[addr / 4 + 1] = htole32(dsps + sc->sc_scrbase);
    378       1.1   tsutsui }
    379       1.1   tsutsui 
    380       1.9     perry static inline void
    381       1.1   tsutsui oosiop_fixup_select(struct oosiop_softc *sc, bus_addr_t addr, int id)
    382       1.1   tsutsui {
    383       1.6   tsutsui 	uint32_t dcmd;
    384       1.1   tsutsui 
    385       1.1   tsutsui 	dcmd = le32toh(sc->sc_scr[addr / 4]);
    386       1.1   tsutsui 	dcmd &= 0xff00ffff;
    387       1.1   tsutsui 	dcmd |= 0x00010000 << id;
    388       1.1   tsutsui 	sc->sc_scr[addr / 4] = htole32(dcmd);
    389       1.1   tsutsui }
    390       1.1   tsutsui 
    391       1.9     perry static inline void
    392       1.1   tsutsui oosiop_fixup_jump(struct oosiop_softc *sc, bus_addr_t addr, bus_addr_t dst)
    393       1.1   tsutsui {
    394       1.1   tsutsui 
    395       1.1   tsutsui 	sc->sc_scr[addr / 4 + 1] = htole32(dst);
    396       1.1   tsutsui }
    397       1.1   tsutsui 
    398       1.9     perry static inline void
    399       1.1   tsutsui oosiop_fixup_move(struct oosiop_softc *sc, bus_addr_t addr, bus_size_t dbc,
    400       1.1   tsutsui     bus_addr_t dsps)
    401       1.1   tsutsui {
    402       1.6   tsutsui 	uint32_t dcmd;
    403       1.1   tsutsui 
    404       1.1   tsutsui 	dcmd = le32toh(sc->sc_scr[addr / 4]);
    405       1.1   tsutsui 	dcmd &= 0xff000000;
    406       1.1   tsutsui 	dcmd |= dbc & 0x00ffffff;
    407       1.1   tsutsui 	sc->sc_scr[addr / 4 + 0] = htole32(dcmd);
    408       1.1   tsutsui 	sc->sc_scr[addr / 4 + 1] = htole32(dsps);
    409       1.1   tsutsui }
    410       1.1   tsutsui 
    411       1.1   tsutsui static void
    412       1.1   tsutsui oosiop_load_script(struct oosiop_softc *sc)
    413       1.1   tsutsui {
    414       1.1   tsutsui 	int i;
    415       1.1   tsutsui 
    416       1.1   tsutsui 	/* load script */
    417       1.1   tsutsui 	for (i = 0; i < sizeof(oosiop_script) / sizeof(oosiop_script[0]); i++)
    418       1.1   tsutsui 		sc->sc_scr[i] = htole32(oosiop_script[i]);
    419       1.1   tsutsui 
    420       1.1   tsutsui 	/* relocate script */
    421       1.1   tsutsui 	for (i = 0; i < (sizeof(oosiop_script) / 8); i++) {
    422       1.1   tsutsui 		switch (oosiop_script[i * 2] >> 27) {
    423       1.1   tsutsui 		case 0x08:	/* select */
    424       1.1   tsutsui 		case 0x0a:	/* wait reselect */
    425       1.1   tsutsui 			oosiop_relocate_io(sc, i * 8);
    426       1.1   tsutsui 			break;
    427       1.1   tsutsui 		case 0x10:	/* jump */
    428       1.1   tsutsui 		case 0x11:	/* call */
    429       1.1   tsutsui 			oosiop_relocate_tc(sc, i * 8);
    430       1.1   tsutsui 			break;
    431       1.1   tsutsui 		}
    432       1.1   tsutsui 	}
    433       1.1   tsutsui 
    434       1.1   tsutsui 	oosiop_fixup_move(sc, Ent_p_resel_msgin_move, 1, sc->sc_reselbuf);
    435       1.1   tsutsui 	OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
    436       1.1   tsutsui }
    437       1.1   tsutsui 
    438       1.1   tsutsui static void
    439       1.1   tsutsui oosiop_setup_sgdma(struct oosiop_softc *sc, struct oosiop_cb *cb)
    440       1.1   tsutsui {
    441       1.4   tsutsui 	int i, n, off, control;
    442       1.1   tsutsui 	struct oosiop_xfer *xfer;
    443       1.1   tsutsui 
    444       1.1   tsutsui 	OOSIOP_XFERSCR_SYNC(sc, cb,
    445       1.1   tsutsui 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
    446       1.1   tsutsui 
    447       1.1   tsutsui 	off = cb->curdp;
    448       1.1   tsutsui 	xfer = cb->xfer;
    449       1.4   tsutsui 	control = cb->xs->xs_control;
    450       1.1   tsutsui 
    451       1.4   tsutsui 	if (control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
    452       1.4   tsutsui 		/* Find start segment */
    453       1.1   tsutsui 		for (i = 0; i < cb->datadma->dm_nsegs; i++) {
    454       1.1   tsutsui 			if (off < cb->datadma->dm_segs[i].ds_len)
    455       1.1   tsutsui 				break;
    456       1.1   tsutsui 			off -= cb->datadma->dm_segs[i].ds_len;
    457       1.1   tsutsui 		}
    458       1.1   tsutsui 
    459       1.4   tsutsui 		/* build MOVE block */
    460       1.4   tsutsui 		if (control & XS_CTL_DATA_IN) {
    461       1.4   tsutsui 			n = 0;
    462       1.4   tsutsui 			while (i < cb->datadma->dm_nsegs) {
    463       1.4   tsutsui 				xfer->datain_scr[n * 2 + 0] =
    464       1.4   tsutsui 				    htole32(0x09000000 |
    465       1.4   tsutsui 				    (cb->datadma->dm_segs[i].ds_len - off));
    466       1.4   tsutsui 				xfer->datain_scr[n * 2 + 1] =
    467       1.4   tsutsui 				    htole32(cb->datadma->dm_segs[i].ds_addr +
    468       1.4   tsutsui 				    off);
    469       1.4   tsutsui 				n++;
    470       1.4   tsutsui 				i++;
    471       1.4   tsutsui 				off = 0;
    472       1.4   tsutsui 			}
    473       1.4   tsutsui 			xfer->datain_scr[n * 2 + 0] = htole32(0x80080000);
    474       1.1   tsutsui 			xfer->datain_scr[n * 2 + 1] =
    475       1.4   tsutsui 			    htole32(sc->sc_scrbase + Ent_phasedispatch);
    476       1.4   tsutsui 		}
    477       1.4   tsutsui 		if (control & XS_CTL_DATA_OUT) {
    478       1.4   tsutsui 			n = 0;
    479       1.4   tsutsui 			while (i < cb->datadma->dm_nsegs) {
    480       1.4   tsutsui 				xfer->dataout_scr[n * 2 + 0] =
    481       1.4   tsutsui 				    htole32(0x08000000 |
    482       1.4   tsutsui 				    (cb->datadma->dm_segs[i].ds_len - off));
    483       1.4   tsutsui 				xfer->dataout_scr[n * 2 + 1] =
    484       1.4   tsutsui 				    htole32(cb->datadma->dm_segs[i].ds_addr +
    485       1.4   tsutsui 				    off);
    486       1.4   tsutsui 				n++;
    487       1.4   tsutsui 				i++;
    488       1.4   tsutsui 				off = 0;
    489       1.4   tsutsui 			}
    490       1.4   tsutsui 			xfer->dataout_scr[n * 2 + 0] = htole32(0x80080000);
    491       1.4   tsutsui 			xfer->dataout_scr[n * 2 + 1] =
    492       1.4   tsutsui 			    htole32(sc->sc_scrbase + Ent_phasedispatch);
    493       1.1   tsutsui 		}
    494       1.4   tsutsui 	}
    495       1.4   tsutsui 	if ((control & XS_CTL_DATA_IN) == 0) {
    496       1.1   tsutsui 		xfer->datain_scr[0] = htole32(0x98080000);
    497       1.1   tsutsui 		xfer->datain_scr[1] = htole32(DATAIN_TRAP);
    498       1.1   tsutsui 	}
    499       1.4   tsutsui 	if ((control & XS_CTL_DATA_OUT) == 0) {
    500       1.1   tsutsui 		xfer->dataout_scr[0] = htole32(0x98080000);
    501       1.1   tsutsui 		xfer->dataout_scr[1] = htole32(DATAOUT_TRAP);
    502       1.1   tsutsui 	}
    503       1.1   tsutsui 	OOSIOP_XFERSCR_SYNC(sc, cb,
    504       1.1   tsutsui 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    505       1.1   tsutsui }
    506       1.1   tsutsui 
    507       1.1   tsutsui /*
    508       1.1   tsutsui  * Setup DMA pointer into script.
    509       1.1   tsutsui  */
    510       1.1   tsutsui static void
    511       1.1   tsutsui oosiop_setup_dma(struct oosiop_softc *sc)
    512       1.1   tsutsui {
    513       1.1   tsutsui 	struct oosiop_cb *cb;
    514       1.1   tsutsui 	bus_addr_t xferbase;
    515       1.1   tsutsui 
    516       1.1   tsutsui 	cb = sc->sc_curcb;
    517       1.1   tsutsui 	xferbase = cb->xferdma->dm_segs[0].ds_addr;
    518       1.1   tsutsui 
    519       1.1   tsutsui 	OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
    520       1.1   tsutsui 
    521       1.1   tsutsui 	oosiop_fixup_select(sc, Ent_p_select, cb->id);
    522       1.7     perry 	oosiop_fixup_jump(sc, Ent_p_datain_jump, xferbase +
    523       1.1   tsutsui 	    offsetof(struct oosiop_xfer, datain_scr[0]));
    524       1.1   tsutsui 	oosiop_fixup_jump(sc, Ent_p_dataout_jump, xferbase +
    525       1.1   tsutsui 	    offsetof(struct oosiop_xfer, dataout_scr[0]));
    526       1.1   tsutsui 	oosiop_fixup_move(sc, Ent_p_msgin_move, 1, xferbase +
    527       1.1   tsutsui 	    offsetof(struct oosiop_xfer, msgin[0]));
    528       1.1   tsutsui 	oosiop_fixup_move(sc, Ent_p_extmsglen_move, 1, xferbase +
    529       1.1   tsutsui 	    offsetof(struct oosiop_xfer, msgin[1]));
    530       1.1   tsutsui 	oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen, xferbase +
    531       1.1   tsutsui 	    offsetof(struct oosiop_xfer, msgout[0]));
    532       1.1   tsutsui 	oosiop_fixup_move(sc, Ent_p_status_move, 1, xferbase +
    533       1.1   tsutsui 	    offsetof(struct oosiop_xfer, status));
    534       1.1   tsutsui 	oosiop_fixup_move(sc, Ent_p_cmdout_move, cb->xs->cmdlen,
    535       1.1   tsutsui 	    cb->cmddma->dm_segs[0].ds_addr);
    536       1.1   tsutsui 
    537       1.1   tsutsui 	OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
    538       1.1   tsutsui }
    539       1.1   tsutsui 
    540       1.1   tsutsui static void
    541       1.1   tsutsui oosiop_flush_fifo(struct oosiop_softc *sc)
    542       1.1   tsutsui {
    543       1.1   tsutsui 
    544       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
    545       1.1   tsutsui 	    OOSIOP_DFIFO_FLF);
    546       1.1   tsutsui 	while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
    547       1.1   tsutsui 	    OOSIOP_CTEST1_FMT)
    548       1.1   tsutsui 		;
    549       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
    550       1.1   tsutsui 	    ~OOSIOP_DFIFO_FLF);
    551       1.1   tsutsui }
    552       1.1   tsutsui 
    553       1.1   tsutsui static void
    554       1.1   tsutsui oosiop_clear_fifo(struct oosiop_softc *sc)
    555       1.1   tsutsui {
    556       1.1   tsutsui 
    557       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) |
    558       1.1   tsutsui 	    OOSIOP_DFIFO_CLF);
    559       1.1   tsutsui 	while ((oosiop_read_1(sc, OOSIOP_CTEST1) & OOSIOP_CTEST1_FMT) !=
    560       1.1   tsutsui 	    OOSIOP_CTEST1_FMT)
    561       1.1   tsutsui 		;
    562       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DFIFO, oosiop_read_1(sc, OOSIOP_DFIFO) &
    563       1.1   tsutsui 	    ~OOSIOP_DFIFO_CLF);
    564       1.1   tsutsui }
    565       1.1   tsutsui 
    566       1.1   tsutsui static void
    567       1.1   tsutsui oosiop_phasemismatch(struct oosiop_softc *sc)
    568       1.1   tsutsui {
    569       1.1   tsutsui 	struct oosiop_cb *cb;
    570       1.6   tsutsui 	uint32_t dsp, dbc, n, i, len;
    571       1.6   tsutsui 	uint8_t dfifo, sstat1;
    572       1.1   tsutsui 
    573       1.1   tsutsui 	cb = sc->sc_curcb;
    574       1.1   tsutsui 	if (cb == NULL)
    575       1.1   tsutsui 		return;
    576       1.1   tsutsui 
    577       1.1   tsutsui 	dsp = oosiop_read_4(sc, OOSIOP_DSP);
    578       1.1   tsutsui 	dbc = oosiop_read_4(sc, OOSIOP_DBC) & OOSIOP_DBC_MAX;
    579       1.1   tsutsui 	len = 0;
    580       1.1   tsutsui 
    581       1.1   tsutsui 	n = dsp - cb->xferdma->dm_segs[0].ds_addr - 8;
    582       1.1   tsutsui 	if (n >= offsetof(struct oosiop_xfer, datain_scr[0]) &&
    583       1.1   tsutsui 	    n < offsetof(struct oosiop_xfer, datain_scr[OOSIOP_NSG * 2])) {
    584       1.1   tsutsui 		n -= offsetof(struct oosiop_xfer, datain_scr[0]);
    585       1.1   tsutsui 		n >>= 3;
    586       1.1   tsutsui 		OOSIOP_DINSCR_SYNC(sc, cb,
    587       1.1   tsutsui 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
    588       1.1   tsutsui 		for (i = 0; i <= n; i++)
    589       1.1   tsutsui 			len += le32toh(cb->xfer->datain_scr[i * 2]) &
    590       1.1   tsutsui 			    0x00ffffff;
    591       1.1   tsutsui 		OOSIOP_DINSCR_SYNC(sc, cb,
    592       1.1   tsutsui 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    593       1.1   tsutsui 		/* All data in the chip are already flushed */
    594       1.1   tsutsui 	} else if (n >= offsetof(struct oosiop_xfer, dataout_scr[0]) &&
    595       1.1   tsutsui 	    n < offsetof(struct oosiop_xfer, dataout_scr[OOSIOP_NSG * 2])) {
    596       1.1   tsutsui 		n -= offsetof(struct oosiop_xfer, dataout_scr[0]);
    597       1.1   tsutsui 		n >>= 3;
    598       1.1   tsutsui 		OOSIOP_DOUTSCR_SYNC(sc, cb,
    599       1.1   tsutsui 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
    600       1.1   tsutsui 		for (i = 0; i <= n; i++)
    601       1.1   tsutsui 			len += le32toh(cb->xfer->dataout_scr[i * 2]) &
    602       1.1   tsutsui 			    0x00ffffff;
    603       1.1   tsutsui 		OOSIOP_DOUTSCR_SYNC(sc, cb,
    604       1.1   tsutsui 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    605       1.1   tsutsui 
    606       1.1   tsutsui 		dfifo = oosiop_read_1(sc, OOSIOP_DFIFO);
    607       1.1   tsutsui 		dbc += ((dfifo & OOSIOP_DFIFO_BO) - (dbc & OOSIOP_DFIFO_BO)) &
    608       1.1   tsutsui 		    OOSIOP_DFIFO_BO;
    609       1.1   tsutsui 
    610       1.1   tsutsui 		sstat1 = oosiop_read_1(sc, OOSIOP_SSTAT1);
    611       1.1   tsutsui 		if (sstat1 & OOSIOP_SSTAT1_OLF)
    612       1.1   tsutsui 			dbc++;
    613       1.7     perry 		if ((sc->sc_tgt[cb->id].sxfer != 0) &&
    614       1.1   tsutsui 		    (sstat1 & OOSIOP_SSTAT1_ORF) != 0)
    615       1.1   tsutsui 			dbc++;
    616       1.1   tsutsui 
    617       1.1   tsutsui 		oosiop_clear_fifo(sc);
    618       1.1   tsutsui 	} else {
    619       1.1   tsutsui 		printf("%s: phase mismatch addr=%08x\n", sc->sc_dev.dv_xname,
    620       1.1   tsutsui 		    oosiop_read_4(sc, OOSIOP_DSP) - 8);
    621       1.1   tsutsui 		oosiop_clear_fifo(sc);
    622       1.1   tsutsui 		return;
    623       1.1   tsutsui 	}
    624       1.1   tsutsui 
    625       1.1   tsutsui 	len -= dbc;
    626       1.1   tsutsui 	if (len) {
    627       1.1   tsutsui 		cb->curdp += len;
    628       1.1   tsutsui 		oosiop_setup_sgdma(sc, cb);
    629       1.1   tsutsui 	}
    630       1.1   tsutsui }
    631       1.1   tsutsui 
    632       1.1   tsutsui static void
    633       1.1   tsutsui oosiop_setup_syncxfer(struct oosiop_softc *sc)
    634       1.1   tsutsui {
    635       1.1   tsutsui 	int id;
    636       1.1   tsutsui 
    637       1.1   tsutsui 	id = sc->sc_curcb->id;
    638       1.1   tsutsui 	if (sc->sc_chip != OOSIOP_700)
    639       1.1   tsutsui 		oosiop_write_1(sc, OOSIOP_SBCL, sc->sc_tgt[id].scf);
    640       1.1   tsutsui 
    641       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_SXFER, sc->sc_tgt[id].sxfer);
    642       1.1   tsutsui }
    643       1.1   tsutsui 
    644       1.1   tsutsui static void
    645       1.1   tsutsui oosiop_set_syncparam(struct oosiop_softc *sc, int id, int period, int offset)
    646       1.1   tsutsui {
    647       1.1   tsutsui 	int i, p;
    648       1.1   tsutsui 	struct scsipi_xfer_mode xm;
    649       1.1   tsutsui 
    650       1.1   tsutsui 	xm.xm_target = id;
    651       1.1   tsutsui 	xm.xm_mode = 0;
    652       1.1   tsutsui 	xm.xm_period = 0;
    653       1.1   tsutsui 	xm.xm_offset = 0;
    654       1.1   tsutsui 
    655       1.1   tsutsui 	if (offset == 0) {
    656       1.1   tsutsui 		/* Asynchronous */
    657       1.1   tsutsui 		sc->sc_tgt[id].scf = 0;
    658       1.1   tsutsui 		sc->sc_tgt[id].sxfer = 0;
    659       1.1   tsutsui 	} else {
    660       1.1   tsutsui 		/* Synchronous */
    661       1.1   tsutsui 		if (sc->sc_chip == OOSIOP_700) {
    662       1.1   tsutsui 			for (i = 4; i < 12; i++) {
    663       1.1   tsutsui 				p = oosiop_period(sc, i, sc->sc_ccf);
    664       1.1   tsutsui 				if (p >= period)
    665       1.1   tsutsui 					break;
    666       1.1   tsutsui 			}
    667       1.1   tsutsui 			if (i == 12) {
    668       1.1   tsutsui 				printf("%s: target %d period too large\n",
    669       1.1   tsutsui 				    sc->sc_dev.dv_xname, id);
    670       1.1   tsutsui 				i = 11;	/* XXX */
    671       1.1   tsutsui 			}
    672       1.1   tsutsui 			sc->sc_tgt[id].scf = 0;
    673       1.1   tsutsui 			sc->sc_tgt[id].sxfer = ((i - 4) << 4) | offset;
    674       1.1   tsutsui 		} else {
    675       1.1   tsutsui 			for (i = 0; i < NSYNCTBL; i++) {
    676       1.1   tsutsui 				p = oosiop_period(sc, synctbl[i].tp + 4,
    677       1.1   tsutsui 				    (synctbl[i].scf + 1) * 5);
    678       1.1   tsutsui 				if (p >= period)
    679       1.1   tsutsui 					break;
    680       1.1   tsutsui 			}
    681       1.1   tsutsui 			if (i == NSYNCTBL) {
    682       1.1   tsutsui 				printf("%s: target %d period too large\n",
    683       1.1   tsutsui 				    sc->sc_dev.dv_xname, id);
    684       1.1   tsutsui 				i = NSYNCTBL - 1;	/* XXX */
    685       1.1   tsutsui 			}
    686       1.1   tsutsui 			sc->sc_tgt[id].scf = synctbl[i].scf;
    687       1.1   tsutsui 			sc->sc_tgt[id].sxfer = (synctbl[i].tp << 4) | offset;
    688       1.1   tsutsui 		}
    689       1.1   tsutsui 
    690       1.1   tsutsui 		xm.xm_mode |= PERIPH_CAP_SYNC;
    691       1.1   tsutsui 		xm.xm_period = period;
    692       1.1   tsutsui 		xm.xm_offset = offset;
    693       1.1   tsutsui 	}
    694       1.1   tsutsui 
    695       1.1   tsutsui 	scsipi_async_event(&sc->sc_channel, ASYNC_EVENT_XFER_MODE, &xm);
    696       1.1   tsutsui }
    697       1.1   tsutsui 
    698       1.1   tsutsui static void
    699       1.1   tsutsui oosiop_minphys(struct buf *bp)
    700       1.1   tsutsui {
    701       1.1   tsutsui 
    702       1.1   tsutsui 	if (bp->b_bcount > OOSIOP_MAX_XFER)
    703       1.1   tsutsui 		bp->b_bcount = OOSIOP_MAX_XFER;
    704       1.1   tsutsui 	minphys(bp);
    705       1.1   tsutsui }
    706       1.1   tsutsui 
    707       1.1   tsutsui static void
    708       1.1   tsutsui oosiop_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
    709       1.1   tsutsui     void *arg)
    710       1.1   tsutsui {
    711       1.1   tsutsui 	struct scsipi_xfer *xs;
    712       1.1   tsutsui 	struct oosiop_softc *sc;
    713       1.1   tsutsui 	struct oosiop_cb *cb;
    714       1.1   tsutsui 	struct oosiop_xfer *xfer;
    715       1.1   tsutsui 	struct scsipi_xfer_mode *xm;
    716       1.1   tsutsui 	int s, err;
    717       1.1   tsutsui 
    718       1.1   tsutsui 	sc = (struct oosiop_softc *)chan->chan_adapter->adapt_dev;
    719       1.1   tsutsui 
    720       1.1   tsutsui 	switch (req) {
    721       1.1   tsutsui 	case ADAPTER_REQ_RUN_XFER:
    722       1.1   tsutsui 		xs = arg;
    723       1.1   tsutsui 
    724       1.1   tsutsui 		s = splbio();
    725       1.1   tsutsui 		cb = TAILQ_FIRST(&sc->sc_free_cb);
    726       1.1   tsutsui 		TAILQ_REMOVE(&sc->sc_free_cb, cb, chain);
    727       1.1   tsutsui 		splx(s);
    728       1.1   tsutsui 
    729       1.1   tsutsui 		cb->xs = xs;
    730       1.1   tsutsui 		cb->flags = 0;
    731       1.1   tsutsui 		cb->id = xs->xs_periph->periph_target;
    732       1.1   tsutsui 		cb->lun = xs->xs_periph->periph_lun;
    733       1.1   tsutsui 		cb->curdp = 0;
    734       1.1   tsutsui 		cb->savedp = 0;
    735       1.1   tsutsui 		xfer = cb->xfer;
    736       1.1   tsutsui 
    737       1.1   tsutsui 		/* Setup SCSI command buffer DMA */
    738       1.1   tsutsui 		err = bus_dmamap_load(sc->sc_dmat, cb->cmddma, xs->cmd,
    739       1.1   tsutsui 		    xs->cmdlen, NULL, ((xs->xs_control & XS_CTL_NOSLEEP) ?
    740       1.1   tsutsui 		    BUS_DMA_NOWAIT : BUS_DMA_WAITOK) | BUS_DMA_WRITE);
    741       1.1   tsutsui 		if (err) {
    742       1.1   tsutsui 			printf("%s: unable to load cmd DMA map: %d",
    743       1.1   tsutsui 			    sc->sc_dev.dv_xname, err);
    744       1.1   tsutsui 			xs->error = XS_RESOURCE_SHORTAGE;
    745       1.1   tsutsui 			TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
    746       1.1   tsutsui 			scsipi_done(xs);
    747       1.1   tsutsui 			return;
    748       1.1   tsutsui 		}
    749       1.1   tsutsui 		bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, xs->cmdlen,
    750       1.1   tsutsui 		    BUS_DMASYNC_PREWRITE);
    751       1.1   tsutsui 
    752       1.1   tsutsui 		/* Setup data buffer DMA */
    753       1.1   tsutsui 		if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
    754       1.1   tsutsui 			err = bus_dmamap_load(sc->sc_dmat, cb->datadma,
    755       1.1   tsutsui 			    xs->data, xs->datalen, NULL,
    756       1.1   tsutsui 			    ((xs->xs_control & XS_CTL_NOSLEEP) ?
    757       1.1   tsutsui 			    BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
    758       1.1   tsutsui 			    BUS_DMA_STREAMING |
    759       1.1   tsutsui 			    ((xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMA_READ :
    760       1.1   tsutsui 			    BUS_DMA_WRITE));
    761       1.1   tsutsui 			if (err) {
    762       1.1   tsutsui 				printf("%s: unable to load data DMA map: %d",
    763       1.1   tsutsui 				    sc->sc_dev.dv_xname, err);
    764       1.1   tsutsui 				xs->error = XS_RESOURCE_SHORTAGE;
    765       1.1   tsutsui 				bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
    766       1.1   tsutsui 				TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
    767       1.1   tsutsui 				scsipi_done(xs);
    768       1.1   tsutsui 				return;
    769       1.1   tsutsui 			}
    770       1.1   tsutsui 			bus_dmamap_sync(sc->sc_dmat, cb->datadma,
    771       1.1   tsutsui 			    0, xs->datalen,
    772       1.1   tsutsui 			    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    773       1.1   tsutsui 		}
    774       1.1   tsutsui 
    775       1.1   tsutsui 		oosiop_setup_sgdma(sc, cb);
    776       1.1   tsutsui 
    777       1.1   tsutsui 		/* Setup msgout buffer */
    778       1.1   tsutsui 		OOSIOP_XFERMSG_SYNC(sc, cb,
    779       1.1   tsutsui 		   BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
    780       1.1   tsutsui 		xfer->msgout[0] = MSG_IDENTIFY(cb->lun,
    781       1.1   tsutsui 		    (xs->xs_control & XS_CTL_REQSENSE) == 0);
    782       1.1   tsutsui 		cb->msgoutlen = 1;
    783       1.1   tsutsui 
    784       1.1   tsutsui 		if (sc->sc_tgt[cb->id].flags & TGTF_SYNCNEG) {
    785       1.1   tsutsui 			/* Send SDTR */
    786       1.1   tsutsui 			xfer->msgout[1] = MSG_EXTENDED;
    787       1.1   tsutsui 			xfer->msgout[2] = MSG_EXT_SDTR_LEN;
    788       1.1   tsutsui 			xfer->msgout[3] = MSG_EXT_SDTR;
    789       1.1   tsutsui 			xfer->msgout[4] = sc->sc_minperiod;
    790       1.1   tsutsui 			xfer->msgout[5] = OOSIOP_MAX_OFFSET;
    791       1.1   tsutsui 			cb->msgoutlen = 6;
    792       1.1   tsutsui 			sc->sc_tgt[cb->id].flags &= ~TGTF_SYNCNEG;
    793       1.1   tsutsui 			sc->sc_tgt[cb->id].flags |= TGTF_WAITSDTR;
    794       1.1   tsutsui 		}
    795       1.1   tsutsui 
    796       1.1   tsutsui 		xfer->status = SCSI_OOSIOP_NOSTATUS;
    797       1.1   tsutsui 
    798       1.1   tsutsui 		OOSIOP_XFERMSG_SYNC(sc, cb,
    799       1.1   tsutsui 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
    800       1.1   tsutsui 
    801       1.1   tsutsui 		s = splbio();
    802       1.1   tsutsui 
    803       1.1   tsutsui 		TAILQ_INSERT_TAIL(&sc->sc_cbq, cb, chain);
    804       1.1   tsutsui 
    805       1.1   tsutsui 		if (!sc->sc_active) {
    806       1.1   tsutsui 			/* Abort script to start selection */
    807       1.1   tsutsui 			oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
    808       1.1   tsutsui 		}
    809       1.1   tsutsui 		if (xs->xs_control & XS_CTL_POLL) {
    810       1.1   tsutsui 			/* Poll for command completion */
    811       1.1   tsutsui 			while ((xs->xs_status & XS_STS_DONE) == 0) {
    812       1.1   tsutsui 				delay(1000);
    813       1.1   tsutsui 				oosiop_intr(sc);
    814       1.1   tsutsui 			}
    815       1.1   tsutsui 		}
    816       1.1   tsutsui 
    817       1.1   tsutsui 		splx(s);
    818       1.1   tsutsui 
    819       1.1   tsutsui 		return;
    820       1.1   tsutsui 
    821       1.1   tsutsui 	case ADAPTER_REQ_GROW_RESOURCES:
    822       1.1   tsutsui 		return;
    823       1.1   tsutsui 
    824       1.1   tsutsui 	case ADAPTER_REQ_SET_XFER_MODE:
    825       1.1   tsutsui 		xm = arg;
    826       1.1   tsutsui 		if (xm->xm_mode & PERIPH_CAP_SYNC)
    827       1.1   tsutsui 			sc->sc_tgt[xm->xm_target].flags |= TGTF_SYNCNEG;
    828       1.1   tsutsui 		else
    829       1.1   tsutsui 			oosiop_set_syncparam(sc, xm->xm_target, 0, 0);
    830       1.1   tsutsui 
    831       1.1   tsutsui 		return;
    832       1.1   tsutsui 	}
    833       1.1   tsutsui }
    834       1.1   tsutsui 
    835       1.1   tsutsui static void
    836       1.1   tsutsui oosiop_done(struct oosiop_softc *sc, struct oosiop_cb *cb)
    837       1.1   tsutsui {
    838       1.1   tsutsui 	struct scsipi_xfer *xs;
    839       1.1   tsutsui 
    840       1.1   tsutsui 	xs = cb->xs;
    841       1.1   tsutsui 	if (cb == sc->sc_curcb)
    842       1.1   tsutsui 		sc->sc_curcb = NULL;
    843       1.1   tsutsui 	if (cb == sc->sc_lastcb)
    844       1.1   tsutsui 		sc->sc_lastcb = NULL;
    845       1.1   tsutsui 	sc->sc_tgt[cb->id].nexus = NULL;
    846       1.1   tsutsui 
    847       1.1   tsutsui 	callout_stop(&xs->xs_callout);
    848       1.1   tsutsui 
    849       1.1   tsutsui 	bus_dmamap_sync(sc->sc_dmat, cb->cmddma, 0, xs->cmdlen,
    850       1.1   tsutsui 	    BUS_DMASYNC_POSTWRITE);
    851       1.1   tsutsui 	bus_dmamap_unload(sc->sc_dmat, cb->cmddma);
    852       1.1   tsutsui 
    853       1.1   tsutsui 	if (xs->datalen > 0) {
    854       1.1   tsutsui 		bus_dmamap_sync(sc->sc_dmat, cb->datadma, 0, xs->datalen,
    855       1.1   tsutsui 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
    856       1.1   tsutsui 		bus_dmamap_unload(sc->sc_dmat, cb->datadma);
    857       1.1   tsutsui 	}
    858       1.1   tsutsui 
    859       1.1   tsutsui 	xs->status = cb->xfer->status;
    860       1.1   tsutsui 	xs->resid = 0;	/* XXX */
    861       1.1   tsutsui 
    862       1.1   tsutsui 	if (cb->flags & CBF_SELTOUT)
    863       1.1   tsutsui 		xs->error = XS_SELTIMEOUT;
    864       1.1   tsutsui 	else if (cb->flags & CBF_TIMEOUT)
    865       1.1   tsutsui 		xs->error = XS_TIMEOUT;
    866       1.1   tsutsui 	else switch (xs->status) {
    867       1.1   tsutsui 	case SCSI_OK:
    868       1.1   tsutsui 		xs->error = XS_NOERROR;
    869       1.1   tsutsui 		break;
    870       1.1   tsutsui 
    871       1.1   tsutsui 	case SCSI_BUSY:
    872       1.1   tsutsui 	case SCSI_CHECK:
    873       1.1   tsutsui 		xs->error = XS_BUSY;
    874       1.1   tsutsui 		break;
    875       1.1   tsutsui 	case SCSI_OOSIOP_NOSTATUS:
    876       1.1   tsutsui 		/* the status byte was not updated, cmd was aborted. */
    877       1.1   tsutsui 		xs->error = XS_SELTIMEOUT;
    878       1.1   tsutsui 		break;
    879       1.1   tsutsui 
    880       1.1   tsutsui 	default:
    881       1.1   tsutsui 		xs->error = XS_RESET;
    882       1.1   tsutsui 		break;
    883       1.1   tsutsui 	}
    884       1.1   tsutsui 
    885       1.1   tsutsui 	scsipi_done(xs);
    886       1.1   tsutsui 
    887       1.1   tsutsui 	/* Put it on the free list. */
    888       1.1   tsutsui 	TAILQ_INSERT_TAIL(&sc->sc_free_cb, cb, chain);
    889       1.1   tsutsui }
    890       1.1   tsutsui 
    891       1.1   tsutsui static void
    892       1.1   tsutsui oosiop_timeout(void *arg)
    893       1.1   tsutsui {
    894       1.1   tsutsui 	struct oosiop_cb *cb;
    895       1.1   tsutsui 	struct scsipi_periph *periph;
    896       1.1   tsutsui 	struct oosiop_softc *sc;
    897       1.1   tsutsui 	int s;
    898       1.1   tsutsui 
    899       1.1   tsutsui 	cb = arg;
    900       1.1   tsutsui 	periph = cb->xs->xs_periph;
    901       1.1   tsutsui 	sc = (void *)periph->periph_channel->chan_adapter->adapt_dev;
    902       1.1   tsutsui 	scsipi_printaddr(periph);
    903       1.1   tsutsui 	printf("timed out\n");
    904       1.1   tsutsui 
    905       1.1   tsutsui 	s = splbio();
    906       1.1   tsutsui 
    907       1.1   tsutsui 	cb->flags |= CBF_TIMEOUT;
    908       1.1   tsutsui 	oosiop_done(sc, cb);
    909       1.1   tsutsui 
    910       1.1   tsutsui 	splx(s);
    911       1.1   tsutsui }
    912       1.1   tsutsui 
    913       1.1   tsutsui static void
    914       1.1   tsutsui oosiop_reset(struct oosiop_softc *sc)
    915       1.1   tsutsui {
    916       1.1   tsutsui 	int i, s;
    917       1.1   tsutsui 
    918       1.1   tsutsui 	s = splbio();
    919       1.1   tsutsui 
    920       1.1   tsutsui 	/* Stop SCRIPTS processor */
    921       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_ISTAT, OOSIOP_ISTAT_ABRT);
    922       1.1   tsutsui 	delay(100);
    923       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_ISTAT, 0);
    924       1.1   tsutsui 
    925       1.1   tsutsui 	/* Reset the chip */
    926       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl | OOSIOP_DCNTL_RST);
    927       1.1   tsutsui 	delay(100);
    928       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
    929       1.1   tsutsui 	delay(10000);
    930       1.1   tsutsui 
    931       1.1   tsutsui 	/* Set up various chip parameters */
    932       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_SCNTL0, OOSIOP_ARB_FULL | OOSIOP_SCNTL0_EPG);
    933       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_ESR);
    934       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DCNTL, sc->sc_dcntl);
    935       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DMODE, OOSIOP_DMODE_BL_8);
    936       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_SCID, OOSIOP_SCID_VALUE(sc->sc_id));
    937       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DWT, 0xff);	/* Enable DMA timeout */
    938       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_CTEST7, 0);
    939       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_SXFER, 0);
    940       1.1   tsutsui 
    941       1.1   tsutsui 	/* Clear all interrupts */
    942       1.1   tsutsui 	(void)oosiop_read_1(sc, OOSIOP_SSTAT0);
    943       1.1   tsutsui 	(void)oosiop_read_1(sc, OOSIOP_SSTAT1);
    944       1.1   tsutsui 	(void)oosiop_read_1(sc, OOSIOP_DSTAT);
    945       1.1   tsutsui 
    946       1.1   tsutsui 	/* Enable interrupts */
    947       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_SIEN,
    948       1.1   tsutsui 	    OOSIOP_SIEN_M_A | OOSIOP_SIEN_STO | OOSIOP_SIEN_SGE |
    949       1.1   tsutsui 	    OOSIOP_SIEN_UDC | OOSIOP_SIEN_RST | OOSIOP_SIEN_PAR);
    950       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_DIEN,
    951       1.1   tsutsui 	    OOSIOP_DIEN_ABRT | OOSIOP_DIEN_SSI | OOSIOP_DIEN_SIR |
    952       1.1   tsutsui 	    OOSIOP_DIEN_WTD | OOSIOP_DIEN_IID);
    953       1.1   tsutsui 
    954       1.1   tsutsui 	/* Set target state to asynchronous */
    955       1.1   tsutsui 	for (i = 0; i < OOSIOP_NTGT; i++) {
    956       1.1   tsutsui 		sc->sc_tgt[i].flags = 0;
    957       1.1   tsutsui 		sc->sc_tgt[i].scf = 0;
    958       1.1   tsutsui 		sc->sc_tgt[i].sxfer = 0;
    959       1.1   tsutsui 	}
    960       1.1   tsutsui 
    961       1.1   tsutsui 	splx(s);
    962       1.1   tsutsui }
    963       1.1   tsutsui 
    964       1.1   tsutsui static void
    965       1.1   tsutsui oosiop_reset_bus(struct oosiop_softc *sc)
    966       1.1   tsutsui {
    967       1.1   tsutsui 	int s, i;
    968       1.1   tsutsui 
    969       1.1   tsutsui 	s = splbio();
    970       1.1   tsutsui 
    971       1.1   tsutsui 	/* Assert SCSI RST */
    972       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_SCNTL1, OOSIOP_SCNTL1_RST);
    973       1.1   tsutsui 	delay(25);	/* Reset hold time (25us) */
    974       1.1   tsutsui 	oosiop_write_1(sc, OOSIOP_SCNTL1, 0);
    975       1.1   tsutsui 
    976       1.1   tsutsui 	/* Remove all nexuses */
    977       1.1   tsutsui 	for (i = 0; i < OOSIOP_NTGT; i++) {
    978       1.1   tsutsui 		if (sc->sc_tgt[i].nexus) {
    979       1.1   tsutsui 			sc->sc_tgt[i].nexus->xfer->status =
    980       1.1   tsutsui 			    SCSI_OOSIOP_NOSTATUS; /* XXX */
    981       1.1   tsutsui 			oosiop_done(sc, sc->sc_tgt[i].nexus);
    982       1.1   tsutsui 		}
    983       1.1   tsutsui 	}
    984       1.1   tsutsui 
    985       1.1   tsutsui 	sc->sc_curcb = NULL;
    986       1.1   tsutsui 
    987       1.1   tsutsui 	delay(250000);	/* Reset to selection (250ms) */
    988       1.1   tsutsui 
    989       1.1   tsutsui 	splx(s);
    990       1.1   tsutsui }
    991       1.1   tsutsui 
    992       1.1   tsutsui /*
    993       1.1   tsutsui  * interrupt handler
    994       1.1   tsutsui  */
    995       1.1   tsutsui int
    996       1.1   tsutsui oosiop_intr(struct oosiop_softc *sc)
    997       1.1   tsutsui {
    998       1.1   tsutsui 	struct oosiop_cb *cb;
    999       1.6   tsutsui 	uint32_t dcmd;
   1000       1.1   tsutsui 	int timeout;
   1001       1.6   tsutsui 	uint8_t istat, dstat, sstat0;
   1002       1.1   tsutsui 
   1003       1.1   tsutsui 	istat = oosiop_read_1(sc, OOSIOP_ISTAT);
   1004       1.1   tsutsui 
   1005       1.1   tsutsui 	if ((istat & (OOSIOP_ISTAT_SIP | OOSIOP_ISTAT_DIP)) == 0)
   1006       1.1   tsutsui 		return (0);
   1007       1.1   tsutsui 
   1008       1.1   tsutsui 	sc->sc_nextdsp = Ent_wait_reselect;
   1009       1.1   tsutsui 
   1010       1.1   tsutsui 	/* DMA interrupts */
   1011       1.1   tsutsui 	if (istat & OOSIOP_ISTAT_DIP) {
   1012       1.1   tsutsui 		oosiop_write_1(sc, OOSIOP_ISTAT, 0);
   1013       1.1   tsutsui 
   1014       1.1   tsutsui 		dstat = oosiop_read_1(sc, OOSIOP_DSTAT);
   1015       1.1   tsutsui 
   1016       1.1   tsutsui 		if (dstat & OOSIOP_DSTAT_ABRT) {
   1017       1.1   tsutsui 			sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
   1018       1.1   tsutsui 			    sc->sc_scrbase - 8;
   1019       1.1   tsutsui 
   1020       1.1   tsutsui 			if (sc->sc_nextdsp == Ent_p_resel_msgin_move &&
   1021       1.1   tsutsui 			    (oosiop_read_1(sc, OOSIOP_SBCL) & OOSIOP_ACK)) {
   1022       1.1   tsutsui 				if ((dstat & OOSIOP_DSTAT_DFE) == 0)
   1023       1.1   tsutsui 					oosiop_flush_fifo(sc);
   1024       1.1   tsutsui 				sc->sc_nextdsp += 8;
   1025       1.1   tsutsui 			}
   1026       1.1   tsutsui 		}
   1027       1.1   tsutsui 
   1028       1.1   tsutsui 		if (dstat & OOSIOP_DSTAT_SSI) {
   1029       1.1   tsutsui 			sc->sc_nextdsp = oosiop_read_4(sc, OOSIOP_DSP) -
   1030       1.1   tsutsui 			    sc->sc_scrbase;
   1031       1.1   tsutsui 			printf("%s: single step %08x\n", sc->sc_dev.dv_xname,
   1032       1.1   tsutsui 			    sc->sc_nextdsp);
   1033       1.1   tsutsui 		}
   1034       1.1   tsutsui 
   1035       1.1   tsutsui 		if (dstat & OOSIOP_DSTAT_SIR) {
   1036       1.1   tsutsui 			if ((dstat & OOSIOP_DSTAT_DFE) == 0)
   1037       1.1   tsutsui 				oosiop_flush_fifo(sc);
   1038       1.1   tsutsui 			oosiop_scriptintr(sc);
   1039       1.1   tsutsui 		}
   1040       1.1   tsutsui 
   1041       1.1   tsutsui 		if (dstat & OOSIOP_DSTAT_WTD) {
   1042       1.1   tsutsui 			printf("%s: DMA time out\n", sc->sc_dev.dv_xname);
   1043       1.1   tsutsui 			oosiop_reset(sc);
   1044       1.1   tsutsui 		}
   1045       1.1   tsutsui 
   1046       1.1   tsutsui 		if (dstat & OOSIOP_DSTAT_IID) {
   1047       1.1   tsutsui 			dcmd = oosiop_read_4(sc, OOSIOP_DBC);
   1048       1.1   tsutsui 			if ((dcmd & 0xf8000000) == 0x48000000) {
   1049       1.1   tsutsui 				printf("%s: REQ asserted on WAIT DISCONNECT\n",
   1050       1.1   tsutsui 				    sc->sc_dev.dv_xname);
   1051       1.1   tsutsui 				sc->sc_nextdsp = Ent_phasedispatch; /* XXX */
   1052       1.1   tsutsui 			} else {
   1053       1.1   tsutsui 				printf("%s: invalid SCRIPTS instruction "
   1054       1.1   tsutsui 				    "addr=%08x dcmd=%08x dsps=%08x\n",
   1055       1.1   tsutsui 				    sc->sc_dev.dv_xname,
   1056       1.1   tsutsui 				    oosiop_read_4(sc, OOSIOP_DSP) - 8, dcmd,
   1057       1.1   tsutsui 				    oosiop_read_4(sc, OOSIOP_DSPS));
   1058       1.1   tsutsui 				oosiop_reset(sc);
   1059       1.1   tsutsui 				OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
   1060       1.1   tsutsui 				oosiop_load_script(sc);
   1061       1.1   tsutsui 			}
   1062       1.1   tsutsui 		}
   1063       1.1   tsutsui 
   1064       1.1   tsutsui 		if ((dstat & OOSIOP_DSTAT_DFE) == 0)
   1065       1.1   tsutsui 			oosiop_clear_fifo(sc);
   1066       1.1   tsutsui 	}
   1067       1.1   tsutsui 
   1068       1.1   tsutsui 	/* SCSI interrupts */
   1069       1.1   tsutsui 	if (istat & OOSIOP_ISTAT_SIP) {
   1070       1.1   tsutsui 		if (istat & OOSIOP_ISTAT_DIP)
   1071       1.1   tsutsui 			delay(1);
   1072       1.1   tsutsui 		sstat0 = oosiop_read_1(sc, OOSIOP_SSTAT0);
   1073       1.1   tsutsui 
   1074       1.1   tsutsui 		if (sstat0 & OOSIOP_SSTAT0_M_A) {
   1075       1.1   tsutsui 			/* SCSI phase mismatch during MOVE operation */
   1076       1.1   tsutsui 			oosiop_phasemismatch(sc);
   1077       1.1   tsutsui 			sc->sc_nextdsp = Ent_phasedispatch;
   1078       1.1   tsutsui 		}
   1079       1.1   tsutsui 
   1080       1.1   tsutsui 		if (sstat0 & OOSIOP_SSTAT0_STO) {
   1081       1.1   tsutsui 			if (sc->sc_curcb) {
   1082       1.1   tsutsui 				sc->sc_curcb->flags |= CBF_SELTOUT;
   1083       1.1   tsutsui 				oosiop_done(sc, sc->sc_curcb);
   1084       1.1   tsutsui 			}
   1085       1.1   tsutsui 		}
   1086       1.1   tsutsui 
   1087       1.1   tsutsui 		if (sstat0 & OOSIOP_SSTAT0_SGE) {
   1088       1.1   tsutsui 			printf("%s: SCSI gross error\n", sc->sc_dev.dv_xname);
   1089       1.1   tsutsui 			oosiop_reset(sc);
   1090       1.1   tsutsui 		}
   1091       1.1   tsutsui 
   1092       1.1   tsutsui 		if (sstat0 & OOSIOP_SSTAT0_UDC) {
   1093       1.1   tsutsui 			/* XXX */
   1094       1.1   tsutsui 			if (sc->sc_curcb) {
   1095       1.1   tsutsui 				printf("%s: unexpected disconnect\n",
   1096       1.1   tsutsui 				    sc->sc_dev.dv_xname);
   1097       1.1   tsutsui 				oosiop_done(sc, sc->sc_curcb);
   1098       1.1   tsutsui 			}
   1099       1.1   tsutsui 		}
   1100       1.1   tsutsui 
   1101       1.1   tsutsui 		if (sstat0 & OOSIOP_SSTAT0_RST)
   1102       1.1   tsutsui 			oosiop_reset(sc);
   1103       1.1   tsutsui 
   1104       1.1   tsutsui 		if (sstat0 & OOSIOP_SSTAT0_PAR)
   1105       1.1   tsutsui 			printf("%s: parity error\n", sc->sc_dev.dv_xname);
   1106       1.1   tsutsui 	}
   1107       1.1   tsutsui 
   1108       1.1   tsutsui 	/* Start next command if available */
   1109       1.1   tsutsui 	if (sc->sc_nextdsp == Ent_wait_reselect && TAILQ_FIRST(&sc->sc_cbq)) {
   1110       1.1   tsutsui 		cb = sc->sc_curcb = TAILQ_FIRST(&sc->sc_cbq);
   1111       1.1   tsutsui 		TAILQ_REMOVE(&sc->sc_cbq, cb, chain);
   1112       1.1   tsutsui 		sc->sc_tgt[cb->id].nexus = cb;
   1113       1.1   tsutsui 
   1114       1.1   tsutsui 		oosiop_setup_dma(sc);
   1115       1.1   tsutsui 		oosiop_setup_syncxfer(sc);
   1116       1.1   tsutsui 		sc->sc_lastcb = cb;
   1117       1.1   tsutsui 		sc->sc_nextdsp = Ent_start_select;
   1118       1.1   tsutsui 
   1119       1.1   tsutsui 		/* Schedule timeout */
   1120       1.1   tsutsui 		if ((cb->xs->xs_control & XS_CTL_POLL) == 0) {
   1121       1.1   tsutsui 			timeout = mstohz(cb->xs->timeout) + 1;
   1122       1.1   tsutsui 			callout_reset(&cb->xs->xs_callout, timeout,
   1123       1.1   tsutsui 			    oosiop_timeout, cb);
   1124       1.1   tsutsui 		}
   1125       1.1   tsutsui 	}
   1126       1.1   tsutsui 
   1127       1.1   tsutsui 	sc->sc_active = (sc->sc_nextdsp != Ent_wait_reselect);
   1128       1.1   tsutsui 
   1129       1.1   tsutsui 	/* Restart script */
   1130       1.1   tsutsui 	oosiop_write_4(sc, OOSIOP_DSP, sc->sc_nextdsp + sc->sc_scrbase);
   1131       1.1   tsutsui 
   1132       1.1   tsutsui 	return (1);
   1133       1.1   tsutsui }
   1134       1.1   tsutsui 
   1135       1.1   tsutsui static void
   1136       1.1   tsutsui oosiop_scriptintr(struct oosiop_softc *sc)
   1137       1.1   tsutsui {
   1138       1.1   tsutsui 	struct oosiop_cb *cb;
   1139       1.6   tsutsui 	uint32_t icode;
   1140       1.6   tsutsui 	uint32_t dsp;
   1141       1.1   tsutsui 	int i;
   1142       1.6   tsutsui 	uint8_t sfbr, resid, resmsg;
   1143       1.1   tsutsui 
   1144       1.1   tsutsui 	cb = sc->sc_curcb;
   1145       1.1   tsutsui 	icode = oosiop_read_4(sc, OOSIOP_DSPS);
   1146       1.1   tsutsui 
   1147       1.1   tsutsui 	switch (icode) {
   1148       1.1   tsutsui 	case A_int_done:
   1149       1.1   tsutsui 		if (cb)
   1150       1.1   tsutsui 			oosiop_done(sc, cb);
   1151       1.1   tsutsui 		break;
   1152       1.1   tsutsui 
   1153       1.1   tsutsui 	case A_int_msgin:
   1154       1.1   tsutsui 		if (cb)
   1155       1.1   tsutsui 			oosiop_msgin(sc, cb);
   1156       1.1   tsutsui 		break;
   1157       1.1   tsutsui 
   1158       1.1   tsutsui 	case A_int_extmsg:
   1159       1.1   tsutsui 		/* extended message in DMA setup request */
   1160       1.1   tsutsui 		sfbr = oosiop_read_1(sc, OOSIOP_SFBR);
   1161       1.1   tsutsui 		OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
   1162       1.1   tsutsui 		oosiop_fixup_move(sc, Ent_p_extmsgin_move, sfbr,
   1163       1.1   tsutsui 		    cb->xferdma->dm_segs[0].ds_addr +
   1164       1.1   tsutsui 		    offsetof(struct oosiop_xfer, msgin[2]));
   1165       1.1   tsutsui 		OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
   1166       1.1   tsutsui 		sc->sc_nextdsp = Ent_rcv_extmsg;
   1167       1.1   tsutsui 		break;
   1168       1.1   tsutsui 
   1169       1.1   tsutsui 	case A_int_resel:
   1170       1.1   tsutsui 		/* reselected */
   1171       1.1   tsutsui 		resid = oosiop_read_1(sc, OOSIOP_SFBR);
   1172       1.1   tsutsui 		for (i = 0; i < OOSIOP_NTGT; i++)
   1173       1.1   tsutsui 			if (resid & (1 << i))
   1174       1.1   tsutsui 				break;
   1175       1.1   tsutsui 		if (i == OOSIOP_NTGT) {
   1176       1.1   tsutsui 			printf("%s: missing reselection target id\n",
   1177       1.1   tsutsui 			    sc->sc_dev.dv_xname);
   1178       1.1   tsutsui 			break;
   1179       1.1   tsutsui 		}
   1180       1.1   tsutsui 		sc->sc_resid = i;
   1181       1.1   tsutsui 		sc->sc_nextdsp = Ent_wait_resel_identify;
   1182       1.1   tsutsui 
   1183       1.1   tsutsui 		if (cb) {
   1184       1.1   tsutsui 			/* Current command was lost arbitration */
   1185       1.1   tsutsui 			sc->sc_tgt[cb->id].nexus = NULL;
   1186       1.1   tsutsui 			TAILQ_INSERT_HEAD(&sc->sc_cbq, cb, chain);
   1187       1.1   tsutsui 			sc->sc_curcb = NULL;
   1188       1.1   tsutsui 		}
   1189       1.1   tsutsui 
   1190       1.1   tsutsui 		break;
   1191       1.1   tsutsui 
   1192       1.1   tsutsui 	case A_int_res_id:
   1193       1.1   tsutsui 		cb = sc->sc_tgt[sc->sc_resid].nexus;
   1194       1.1   tsutsui 		resmsg = oosiop_read_1(sc, OOSIOP_SFBR);
   1195       1.1   tsutsui 		if (MSG_ISIDENTIFY(resmsg) && cb &&
   1196       1.1   tsutsui 		    (resmsg & MSG_IDENTIFY_LUNMASK) == cb->lun) {
   1197       1.1   tsutsui 			sc->sc_curcb = cb;
   1198       1.1   tsutsui 			if (cb != sc->sc_lastcb) {
   1199       1.1   tsutsui 				oosiop_setup_dma(sc);
   1200       1.1   tsutsui 				oosiop_setup_syncxfer(sc);
   1201       1.1   tsutsui 				sc->sc_lastcb = cb;
   1202       1.1   tsutsui 			}
   1203       1.1   tsutsui 			if (cb->curdp != cb->savedp) {
   1204       1.1   tsutsui 				cb->curdp = cb->savedp;
   1205       1.1   tsutsui 				oosiop_setup_sgdma(sc, cb);
   1206       1.1   tsutsui 			}
   1207       1.1   tsutsui 			sc->sc_nextdsp = Ent_ack_msgin;
   1208       1.1   tsutsui 		} else {
   1209       1.1   tsutsui 			/* Reselection from invalid target */
   1210       1.1   tsutsui 			oosiop_reset_bus(sc);
   1211       1.1   tsutsui 		}
   1212       1.1   tsutsui 		break;
   1213       1.1   tsutsui 
   1214       1.1   tsutsui 	case A_int_resfail:
   1215       1.1   tsutsui 		/* reselect failed */
   1216       1.1   tsutsui 		break;
   1217       1.1   tsutsui 
   1218       1.1   tsutsui 	case A_int_disc:
   1219       1.1   tsutsui 		/* disconnected */
   1220       1.1   tsutsui 		sc->sc_curcb = NULL;
   1221       1.1   tsutsui 		break;
   1222       1.1   tsutsui 
   1223       1.1   tsutsui 	case A_int_err:
   1224       1.1   tsutsui 		/* generic error */
   1225       1.1   tsutsui 		dsp = oosiop_read_4(sc, OOSIOP_DSP);
   1226       1.1   tsutsui 		printf("%s: script error at 0x%08x\n", sc->sc_dev.dv_xname,
   1227       1.1   tsutsui 		    dsp - 8);
   1228       1.1   tsutsui 		sc->sc_curcb = NULL;
   1229       1.1   tsutsui 		break;
   1230       1.1   tsutsui 
   1231       1.1   tsutsui 	case DATAIN_TRAP:
   1232       1.1   tsutsui 		printf("%s: unexpected datain\n", sc->sc_dev.dv_xname);
   1233       1.1   tsutsui 		/* XXX: need to reset? */
   1234       1.1   tsutsui 		break;
   1235       1.1   tsutsui 
   1236       1.1   tsutsui 	case DATAOUT_TRAP:
   1237       1.1   tsutsui 		printf("%s: unexpected dataout\n", sc->sc_dev.dv_xname);
   1238       1.1   tsutsui 		/* XXX: need to reset? */
   1239       1.1   tsutsui 		break;
   1240       1.1   tsutsui 
   1241       1.1   tsutsui 	default:
   1242       1.1   tsutsui 		printf("%s: unknown intr code %08x\n", sc->sc_dev.dv_xname,
   1243       1.1   tsutsui 		    icode);
   1244       1.1   tsutsui 		break;
   1245       1.1   tsutsui 	}
   1246       1.1   tsutsui }
   1247       1.1   tsutsui 
   1248       1.1   tsutsui static void
   1249       1.1   tsutsui oosiop_msgin(struct oosiop_softc *sc, struct oosiop_cb *cb)
   1250       1.1   tsutsui {
   1251       1.1   tsutsui 	struct oosiop_xfer *xfer;
   1252       1.1   tsutsui 	int msgout;
   1253       1.1   tsutsui 
   1254       1.1   tsutsui 	xfer = cb->xfer;
   1255       1.1   tsutsui 	sc->sc_nextdsp = Ent_ack_msgin;
   1256       1.1   tsutsui 	msgout = 0;
   1257       1.1   tsutsui 
   1258       1.1   tsutsui 	OOSIOP_XFERMSG_SYNC(sc, cb,
   1259       1.1   tsutsui 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
   1260       1.1   tsutsui 
   1261       1.1   tsutsui 	switch (xfer->msgin[0]) {
   1262       1.1   tsutsui 	case MSG_EXTENDED:
   1263       1.1   tsutsui 		switch (xfer->msgin[2]) {
   1264       1.1   tsutsui 		case MSG_EXT_SDTR:
   1265       1.1   tsutsui 			if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
   1266       1.1   tsutsui 				/* Host initiated SDTR */
   1267       1.1   tsutsui 				sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
   1268       1.1   tsutsui 			} else {
   1269       1.1   tsutsui 				/* Target initiated SDTR */
   1270       1.1   tsutsui 				if (xfer->msgin[3] < sc->sc_minperiod)
   1271       1.1   tsutsui 					xfer->msgin[3] = sc->sc_minperiod;
   1272       1.1   tsutsui 				if (xfer->msgin[4] > OOSIOP_MAX_OFFSET)
   1273       1.1   tsutsui 					xfer->msgin[4] = OOSIOP_MAX_OFFSET;
   1274       1.1   tsutsui 				xfer->msgout[0] = MSG_EXTENDED;
   1275       1.1   tsutsui 				xfer->msgout[1] = MSG_EXT_SDTR_LEN;
   1276       1.1   tsutsui 				xfer->msgout[2] = MSG_EXT_SDTR;
   1277       1.1   tsutsui 				xfer->msgout[3] = xfer->msgin[3];
   1278       1.1   tsutsui 				xfer->msgout[4] = xfer->msgin[4];
   1279       1.1   tsutsui 				cb->msgoutlen = 5;
   1280       1.1   tsutsui 				msgout = 1;
   1281       1.1   tsutsui 			}
   1282       1.1   tsutsui 			oosiop_set_syncparam(sc, cb->id, (int)xfer->msgin[3],
   1283       1.1   tsutsui 			    (int)xfer->msgin[4]);
   1284       1.1   tsutsui 			oosiop_setup_syncxfer(sc);
   1285       1.1   tsutsui 			break;
   1286       1.1   tsutsui 
   1287       1.1   tsutsui 		default:
   1288       1.1   tsutsui 			/* Reject message */
   1289       1.1   tsutsui 			xfer->msgout[0] = MSG_MESSAGE_REJECT;
   1290       1.1   tsutsui 			cb->msgoutlen = 1;
   1291       1.1   tsutsui 			msgout = 1;
   1292       1.1   tsutsui 			break;
   1293       1.1   tsutsui 		}
   1294       1.1   tsutsui 		break;
   1295       1.1   tsutsui 
   1296       1.1   tsutsui 	case MSG_SAVEDATAPOINTER:
   1297       1.1   tsutsui 		cb->savedp = cb->curdp;
   1298       1.1   tsutsui 		break;
   1299       1.1   tsutsui 
   1300       1.1   tsutsui 	case MSG_RESTOREPOINTERS:
   1301       1.1   tsutsui 		if (cb->curdp != cb->savedp) {
   1302       1.1   tsutsui 			cb->curdp = cb->savedp;
   1303       1.1   tsutsui 			oosiop_setup_sgdma(sc, cb);
   1304       1.1   tsutsui 		}
   1305       1.1   tsutsui 		break;
   1306       1.1   tsutsui 
   1307       1.1   tsutsui 	case MSG_MESSAGE_REJECT:
   1308       1.1   tsutsui 		if (sc->sc_tgt[cb->id].flags & TGTF_WAITSDTR) {
   1309       1.1   tsutsui 			/* SDTR rejected */
   1310       1.1   tsutsui 			sc->sc_tgt[cb->id].flags &= ~TGTF_WAITSDTR;
   1311       1.1   tsutsui 			oosiop_set_syncparam(sc, cb->id, 0, 0);
   1312       1.1   tsutsui 			oosiop_setup_syncxfer(sc);
   1313       1.1   tsutsui 		}
   1314       1.1   tsutsui 		break;
   1315       1.1   tsutsui 
   1316       1.1   tsutsui 	default:
   1317       1.1   tsutsui 		/* Reject message */
   1318       1.1   tsutsui 		xfer->msgout[0] = MSG_MESSAGE_REJECT;
   1319       1.1   tsutsui 		cb->msgoutlen = 1;
   1320       1.1   tsutsui 		msgout = 1;
   1321       1.1   tsutsui 	}
   1322       1.1   tsutsui 
   1323       1.1   tsutsui 	OOSIOP_XFERMSG_SYNC(sc, cb,
   1324       1.1   tsutsui 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
   1325       1.1   tsutsui 
   1326       1.1   tsutsui 	if (msgout) {
   1327       1.1   tsutsui 		OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_POSTWRITE);
   1328       1.1   tsutsui 		oosiop_fixup_move(sc, Ent_p_msgout_move, cb->msgoutlen,
   1329       1.1   tsutsui 		    cb->xferdma->dm_segs[0].ds_addr +
   1330       1.1   tsutsui 		    offsetof(struct oosiop_xfer, msgout[0]));
   1331       1.1   tsutsui 		OOSIOP_SCRIPT_SYNC(sc, BUS_DMASYNC_PREWRITE);
   1332       1.1   tsutsui 		sc->sc_nextdsp = Ent_sendmsg;
   1333       1.1   tsutsui 	}
   1334       1.1   tsutsui }
   1335