Home | History | Annotate | Line # | Download | only in sbus
isp_sbus.c revision 1.26.4.1
      1  1.26.4.1     mrg /* $NetBSD: isp_sbus.c,v 1.26.4.1 2000/07/19 02:53:07 mrg Exp $ */
      2       1.1     mrg /*
      3       1.1     mrg  * SBus specific probe and attach routines for Qlogic ISP SCSI adapters.
      4       1.1     mrg  *
      5       1.1     mrg  * Copyright (c) 1997 by Matthew Jacob
      6       1.1     mrg  * NASA AMES Research Center
      7       1.1     mrg  * All rights reserved.
      8       1.1     mrg  *
      9       1.1     mrg  * Redistribution and use in source and binary forms, with or without
     10       1.1     mrg  * modification, are permitted provided that the following conditions
     11       1.1     mrg  * are met:
     12       1.1     mrg  * 1. Redistributions of source code must retain the above copyright
     13       1.1     mrg  *    notice immediately at the beginning of the file, without modification,
     14       1.1     mrg  *    this list of conditions, and the following disclaimer.
     15       1.1     mrg  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1     mrg  *    notice, this list of conditions and the following disclaimer in the
     17       1.1     mrg  *    documentation and/or other materials provided with the distribution.
     18       1.1     mrg  * 3. The name of the author may not be used to endorse or promote products
     19       1.1     mrg  *    derived from this software without specific prior written permission.
     20       1.1     mrg  *
     21       1.1     mrg  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     22       1.1     mrg  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23       1.1     mrg  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24       1.1     mrg  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
     25       1.1     mrg  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26       1.1     mrg  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27       1.1     mrg  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28       1.1     mrg  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29       1.1     mrg  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30       1.1     mrg  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31       1.1     mrg  * SUCH DAMAGE.
     32       1.1     mrg  *
     33       1.1     mrg  */
     34       1.1     mrg 
     35       1.1     mrg #include <sys/param.h>
     36       1.1     mrg #include <sys/systm.h>
     37       1.1     mrg #include <sys/device.h>
     38       1.1     mrg #include <sys/kernel.h>
     39       1.1     mrg #include <sys/malloc.h>
     40       1.1     mrg #include <sys/queue.h>
     41       1.1     mrg 
     42  1.26.4.1     mrg #include <machine/bus.h>
     43  1.26.4.1     mrg #include <machine/intr.h>
     44       1.1     mrg #include <machine/autoconf.h>
     45       1.1     mrg 
     46       1.1     mrg #include <dev/ic/isp_netbsd.h>
     47      1.17  mjacob #include <dev/microcode/isp/asm_sbus.h>
     48       1.1     mrg #include <dev/sbus/sbusvar.h>
     49       1.1     mrg 
     50       1.1     mrg static u_int16_t isp_sbus_rd_reg __P((struct ispsoftc *, int));
     51       1.1     mrg static void isp_sbus_wr_reg __P((struct ispsoftc *, int, u_int16_t));
     52       1.1     mrg static int isp_sbus_mbxdma __P((struct ispsoftc *));
     53       1.1     mrg static int isp_sbus_dmasetup __P((struct ispsoftc *, struct scsipi_xfer *,
     54      1.17  mjacob 	ispreq_t *, u_int16_t *, u_int16_t));
     55       1.1     mrg static void isp_sbus_dmateardown __P((struct ispsoftc *, struct scsipi_xfer *,
     56       1.1     mrg 	u_int32_t));
     57       1.1     mrg 
     58      1.17  mjacob #ifndef	ISP_1000_RISC_CODE
     59      1.17  mjacob #define	ISP_1000_RISC_CODE	NULL
     60      1.17  mjacob #endif
     61      1.17  mjacob #ifndef	ISP_CODE_ORG
     62      1.17  mjacob #define	ISP_CODE_ORG	0x1000
     63      1.17  mjacob #endif
     64      1.17  mjacob 
     65       1.1     mrg static struct ispmdvec mdvec = {
     66       1.1     mrg 	isp_sbus_rd_reg,
     67       1.1     mrg 	isp_sbus_wr_reg,
     68       1.1     mrg 	isp_sbus_mbxdma,
     69       1.1     mrg 	isp_sbus_dmasetup,
     70       1.1     mrg 	isp_sbus_dmateardown,
     71       1.1     mrg 	NULL,
     72       1.1     mrg 	NULL,
     73       1.1     mrg 	NULL,
     74      1.17  mjacob 	ISP_1000_RISC_CODE, 0, ISP_CODE_ORG, 0,
     75      1.17  mjacob 	BIU_BURST_ENABLE
     76       1.1     mrg };
     77       1.1     mrg 
     78       1.1     mrg struct isp_sbussoftc {
     79       1.1     mrg 	struct ispsoftc	sbus_isp;
     80       1.1     mrg 	sdparam		sbus_dev;
     81       1.1     mrg 	bus_space_tag_t	sbus_bustag;
     82       1.1     mrg 	bus_dma_tag_t	sbus_dmatag;
     83       1.6  mjacob 	bus_space_handle_t sbus_reg;
     84       1.1     mrg 	int		sbus_node;
     85       1.1     mrg 	int		sbus_pri;
     86       1.1     mrg 	struct ispmdvec	sbus_mdvec;
     87      1.14  mjacob 	bus_dmamap_t	*sbus_dmamap;
     88      1.24      pk 	bus_dmamap_t	sbus_request_dmamap;
     89      1.24      pk 	bus_dmamap_t	sbus_result_dmamap;
     90       1.8  mjacob 	int16_t		sbus_poff[_NREG_BLKS];
     91       1.1     mrg };
     92       1.1     mrg 
     93       1.1     mrg 
     94       1.1     mrg static int isp_match __P((struct device *, struct cfdata *, void *));
     95       1.1     mrg static void isp_sbus_attach __P((struct device *, struct device *, void *));
     96       1.1     mrg struct cfattach isp_sbus_ca = {
     97       1.1     mrg 	sizeof (struct isp_sbussoftc), isp_match, isp_sbus_attach
     98       1.1     mrg };
     99       1.1     mrg 
    100       1.1     mrg static int
    101       1.1     mrg isp_match(parent, cf, aux)
    102       1.1     mrg         struct device *parent;
    103       1.1     mrg         struct cfdata *cf;
    104       1.1     mrg         void *aux;
    105       1.1     mrg {
    106       1.1     mrg 	int rv;
    107       1.1     mrg #ifdef DEBUG
    108       1.1     mrg 	static int oneshot = 1;
    109       1.1     mrg #endif
    110       1.1     mrg 	struct sbus_attach_args *sa = aux;
    111       1.1     mrg 
    112       1.1     mrg 	rv = (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0 ||
    113       1.1     mrg 		strcmp("PTI,ptisp", sa->sa_name) == 0 ||
    114       1.1     mrg 		strcmp("ptisp", sa->sa_name) == 0 ||
    115       1.1     mrg 		strcmp("SUNW,isp", sa->sa_name) == 0 ||
    116       1.1     mrg 		strcmp("QLGC,isp", sa->sa_name) == 0);
    117       1.1     mrg #ifdef DEBUG
    118       1.1     mrg 	if (rv && oneshot) {
    119       1.1     mrg 		oneshot = 0;
    120       1.1     mrg 		printf("Qlogic ISP Driver, NetBSD (sbus) Platform Version "
    121       1.1     mrg 		    "%d.%d Core Version %d.%d\n",
    122       1.1     mrg 		    ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
    123       1.1     mrg 		    ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
    124       1.1     mrg 	}
    125       1.1     mrg #endif
    126       1.1     mrg 	return (rv);
    127       1.1     mrg }
    128       1.1     mrg 
    129      1.20  mjacob 
    130       1.1     mrg static void
    131       1.1     mrg isp_sbus_attach(parent, self, aux)
    132       1.1     mrg         struct device *parent, *self;
    133       1.1     mrg         void *aux;
    134       1.1     mrg {
    135       1.1     mrg 	int i, freq;
    136       1.1     mrg 	struct sbus_attach_args *sa = aux;
    137       1.1     mrg 	struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) self;
    138       1.1     mrg 	struct ispsoftc *isp = &sbc->sbus_isp;
    139       1.1     mrg 	ISP_LOCKVAL_DECL;
    140       1.1     mrg 
    141       1.1     mrg 	printf(" for %s\n", sa->sa_name);
    142       1.1     mrg 
    143       1.1     mrg 	sbc->sbus_bustag = sa->sa_bustag;
    144       1.1     mrg 	sbc->sbus_dmatag = sa->sa_dmatag;
    145      1.16      pk 	if (sa->sa_nintr != 0)
    146      1.16      pk 		sbc->sbus_pri = sa->sa_pri;
    147       1.1     mrg 	sbc->sbus_mdvec = mdvec;
    148       1.1     mrg 
    149       1.1     mrg 	if (sa->sa_npromvaddrs != 0) {
    150       1.6  mjacob 		sbc->sbus_reg = (bus_space_handle_t)sa->sa_promvaddrs[0];
    151       1.1     mrg 	} else {
    152       1.6  mjacob 		if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset,
    153       1.6  mjacob 				 sa->sa_size, BUS_SPACE_MAP_LINEAR, 0,
    154       1.6  mjacob 				 &sbc->sbus_reg) != 0) {
    155       1.1     mrg 			printf("%s: cannot map registers\n", self->dv_xname);
    156       1.1     mrg 			return;
    157       1.1     mrg 		}
    158       1.1     mrg 	}
    159       1.1     mrg 	sbc->sbus_node = sa->sa_node;
    160       1.1     mrg 
    161       1.1     mrg 	freq = getpropint(sa->sa_node, "clock-frequency", 0);
    162       1.1     mrg 	if (freq) {
    163       1.1     mrg 		/*
    164       1.1     mrg 		 * Convert from HZ to MHz, rounding up.
    165       1.1     mrg 		 */
    166       1.1     mrg 		freq = (freq + 500000)/1000000;
    167       1.1     mrg #if	0
    168       1.1     mrg 		printf("%s: %d MHz\n", self->dv_xname, freq);
    169       1.1     mrg #endif
    170       1.1     mrg 	}
    171       1.1     mrg 	sbc->sbus_mdvec.dv_clock = freq;
    172       1.5  mjacob 
    173       1.5  mjacob 	/*
    174       1.5  mjacob 	 * XXX: Now figure out what the proper burst sizes, etc., to use.
    175       1.5  mjacob 	 */
    176       1.5  mjacob 	sbc->sbus_mdvec.dv_conf1 |= BIU_SBUS_CONF1_FIFO_8;
    177       1.1     mrg 
    178       1.1     mrg 	/*
    179       1.1     mrg 	 * Some early versions of the PTI SBus adapter
    180       1.1     mrg 	 * would fail in trying to download (via poking)
    181       1.1     mrg 	 * FW. We give up on them.
    182       1.1     mrg 	 */
    183       1.1     mrg 	if (strcmp("PTI,ptisp", sa->sa_name) == 0 ||
    184       1.1     mrg 	    strcmp("ptisp", sa->sa_name) == 0) {
    185      1.20  mjacob 		sbc->sbus_mdvec.dv_ispfw = NULL;
    186       1.1     mrg 	}
    187       1.1     mrg 
    188       1.1     mrg 	isp->isp_mdvec = &sbc->sbus_mdvec;
    189       1.2  mjacob 	isp->isp_bustype = ISP_BT_SBUS;
    190       1.1     mrg 	isp->isp_type = ISP_HA_SCSI_UNKNOWN;
    191       1.1     mrg 	isp->isp_param = &sbc->sbus_dev;
    192       1.1     mrg 	bzero(isp->isp_param, sizeof (sdparam));
    193       1.1     mrg 
    194       1.8  mjacob 	sbc->sbus_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
    195       1.8  mjacob 	sbc->sbus_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = SBUS_MBOX_REGS_OFF;
    196       1.8  mjacob 	sbc->sbus_poff[SXP_BLOCK >> _BLK_REG_SHFT] = SBUS_SXP_REGS_OFF;
    197       1.8  mjacob 	sbc->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF;
    198       1.8  mjacob 	sbc->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
    199       1.1     mrg 
    200      1.18  mjacob 	isp->isp_confopts = self->dv_cfdata->cf_flags;
    201      1.21  mjacob 	/*
    202      1.21  mjacob 	 * There's no tool on sparc to set NVRAM for ISPs, so ignore it.
    203      1.21  mjacob 	 */
    204      1.21  mjacob 	isp->isp_confopts |= ISP_CFG_NONVRAM;
    205       1.1     mrg 	ISP_LOCK(isp);
    206       1.1     mrg 	isp_reset(isp);
    207       1.1     mrg 	if (isp->isp_state != ISP_RESETSTATE) {
    208       1.1     mrg 		ISP_UNLOCK(isp);
    209       1.1     mrg 		return;
    210       1.1     mrg 	}
    211       1.1     mrg 	isp_init(isp);
    212       1.1     mrg 	if (isp->isp_state != ISP_INITSTATE) {
    213       1.1     mrg 		isp_uninit(isp);
    214       1.1     mrg 		ISP_UNLOCK(isp);
    215       1.1     mrg 		return;
    216       1.1     mrg 	}
    217       1.1     mrg 
    218      1.14  mjacob 	for (i = 0; i < isp->isp_maxcmds; i++) {
    219       1.1     mrg 		/* Allocate a DMA handle */
    220       1.8  mjacob 		if (bus_dmamap_create(sbc->sbus_dmatag, MAXPHYS, 1, MAXPHYS, 0,
    221       1.8  mjacob 		    BUS_DMA_NOWAIT, &sbc->sbus_dmamap[i]) != 0) {
    222       1.1     mrg 			printf("%s: DMA map create error\n",
    223       1.1     mrg 				self->dv_xname);
    224       1.1     mrg 			return;
    225       1.1     mrg 		}
    226       1.1     mrg 	}
    227       1.1     mrg 
    228       1.1     mrg 	/* Establish interrupt channel */
    229  1.26.4.1     mrg 	bus_intr_establish(sbc->sbus_bustag, sbc->sbus_pri, IPL_BIO, 0,
    230       1.8  mjacob 	    (int(*)__P((void*)))isp_intr, sbc);
    231       1.1     mrg 
    232       1.1     mrg 	/*
    233       1.1     mrg 	 * do generic attach.
    234       1.1     mrg 	 */
    235       1.1     mrg 	isp_attach(isp);
    236       1.1     mrg 	if (isp->isp_state != ISP_RUNSTATE) {
    237       1.1     mrg 		isp_uninit(isp);
    238       1.1     mrg 	}
    239       1.1     mrg 	ISP_UNLOCK(isp);
    240       1.1     mrg }
    241       1.1     mrg 
    242       1.1     mrg static u_int16_t
    243       1.1     mrg isp_sbus_rd_reg(isp, regoff)
    244       1.1     mrg 	struct ispsoftc *isp;
    245       1.1     mrg 	int regoff;
    246       1.1     mrg {
    247       1.1     mrg 	struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
    248       1.8  mjacob 	int offset = sbc->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
    249       1.8  mjacob 	offset += (regoff & 0xff);
    250       1.6  mjacob 	return (bus_space_read_2(sbc->sbus_bustag, sbc->sbus_reg, offset));
    251       1.1     mrg }
    252       1.1     mrg 
    253       1.1     mrg static void
    254      1.14  mjacob isp_sbus_wr_reg(isp, regoff, val)
    255       1.1     mrg 	struct ispsoftc *isp;
    256       1.1     mrg 	int regoff;
    257       1.1     mrg 	u_int16_t val;
    258       1.1     mrg {
    259       1.1     mrg 	struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
    260       1.8  mjacob 	int offset = sbc->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
    261       1.8  mjacob 	offset += (regoff & 0xff);
    262       1.6  mjacob 	bus_space_write_2(sbc->sbus_bustag, sbc->sbus_reg, offset, val);
    263       1.1     mrg }
    264       1.1     mrg 
    265       1.1     mrg static int
    266       1.1     mrg isp_sbus_mbxdma(isp)
    267       1.1     mrg 	struct ispsoftc *isp;
    268       1.1     mrg {
    269       1.1     mrg 	struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
    270      1.24      pk 	bus_dma_tag_t dmatag = sbc->sbus_dmatag;
    271       1.1     mrg 	bus_dma_segment_t seg;
    272      1.12      pk 	int rseg;
    273      1.14  mjacob 	size_t n;
    274      1.12      pk 	bus_size_t len;
    275       1.1     mrg 
    276      1.14  mjacob 	if (isp->isp_rquest_dma)
    277      1.14  mjacob 		return (0);
    278       1.1     mrg 
    279      1.14  mjacob 	n = sizeof (ISP_SCSI_XFER_T **) * isp->isp_maxcmds;
    280      1.14  mjacob 	isp->isp_xflist = (ISP_SCSI_XFER_T **) malloc(n, M_DEVBUF, M_WAITOK);
    281      1.14  mjacob 	if (isp->isp_xflist == NULL) {
    282      1.14  mjacob 		printf("%s: cannot alloc xflist array\n", isp->isp_name);
    283      1.14  mjacob 		return (1);
    284      1.14  mjacob 	}
    285      1.14  mjacob 	bzero(isp->isp_xflist, n);
    286      1.14  mjacob 	n = sizeof (bus_dmamap_t) * isp->isp_maxcmds;
    287      1.14  mjacob 	sbc->sbus_dmamap = (bus_dmamap_t *) malloc(n, M_DEVBUF, M_WAITOK);
    288      1.14  mjacob 	if (sbc->sbus_dmamap == NULL) {
    289      1.14  mjacob 		free(isp->isp_xflist, M_DEVBUF);
    290      1.14  mjacob 		printf("%s: cannot alloc dmamap array\n", isp->isp_name);
    291      1.14  mjacob 		return (1);
    292      1.14  mjacob 	}
    293       1.1     mrg 	/*
    294       1.1     mrg 	 * Allocate and map the request queue.
    295       1.1     mrg 	 */
    296       1.1     mrg 	len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN);
    297      1.24      pk 	/* Allocate DMA map */
    298      1.25      pk 	if (bus_dmamap_create(dmatag, len, 1, len, 0, BUS_DMA_NOWAIT,
    299      1.24      pk 				&sbc->sbus_request_dmamap) != 0) {
    300      1.24      pk 		goto dmafail;
    301      1.24      pk 	}
    302      1.24      pk 
    303      1.24      pk 	/* Allocate DMA buffer */
    304      1.26      pk 	if (bus_dmamem_alloc(dmatag, len, 0, 0,
    305      1.24      pk 				&seg, 1, &rseg, BUS_DMA_NOWAIT)) {
    306      1.24      pk 		goto dmafail;
    307      1.24      pk 	}
    308      1.24      pk 
    309      1.24      pk 	/* Load the buffer */
    310      1.24      pk 	if (bus_dmamap_load_raw(dmatag, sbc->sbus_request_dmamap,
    311      1.24      pk 				&seg, rseg, len, BUS_DMA_NOWAIT) != 0) {
    312      1.24      pk 		bus_dmamem_free(dmatag, &seg, rseg);
    313      1.24      pk 		goto dmafail;
    314      1.24      pk 	}
    315      1.24      pk 	isp->isp_rquest_dma = sbc->sbus_request_dmamap->dm_segs[0].ds_addr;
    316      1.24      pk 
    317      1.24      pk 	/* Map DMA buffer in CPU addressable space */
    318      1.24      pk 	if (bus_dmamem_map(dmatag, &seg, rseg, len,
    319      1.24      pk 			   (caddr_t *)&isp->isp_rquest,
    320      1.24      pk 			   BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
    321      1.24      pk 		bus_dmamap_unload(dmatag, sbc->sbus_request_dmamap);
    322      1.24      pk 		bus_dmamem_free(dmatag, &seg, rseg);
    323      1.24      pk 		goto dmafail;
    324      1.14  mjacob 	}
    325       1.1     mrg 
    326       1.1     mrg 	/*
    327       1.1     mrg 	 * Allocate and map the result queue.
    328       1.1     mrg 	 */
    329       1.1     mrg 	len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN);
    330      1.24      pk 	/* Allocate DMA map */
    331      1.25      pk 	if (bus_dmamap_create(dmatag, len, 1, len, 0, BUS_DMA_NOWAIT,
    332      1.24      pk 				&sbc->sbus_result_dmamap) != 0) {
    333      1.24      pk 		goto dmafail;
    334      1.24      pk 	}
    335      1.24      pk 
    336      1.24      pk 	/* Allocate DMA buffer */
    337      1.26      pk 	if (bus_dmamem_alloc(dmatag, len, 0, 0,
    338      1.24      pk 				&seg, 1, &rseg, BUS_DMA_NOWAIT)) {
    339      1.24      pk 		goto dmafail;
    340      1.24      pk 	}
    341      1.24      pk 
    342      1.24      pk 	/* Load the buffer */
    343      1.24      pk 	if (bus_dmamap_load_raw(dmatag, sbc->sbus_result_dmamap,
    344      1.24      pk 				&seg, rseg, len, BUS_DMA_NOWAIT) != 0) {
    345      1.24      pk 		bus_dmamem_free(dmatag, &seg, rseg);
    346      1.24      pk 		goto dmafail;
    347      1.24      pk 	}
    348      1.24      pk 
    349      1.24      pk 	/* Map DMA buffer in CPU addressable space */
    350      1.24      pk 	if (bus_dmamem_map(dmatag, &seg, rseg, len,
    351      1.24      pk 			   (caddr_t *)&isp->isp_result,
    352      1.24      pk 			   BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
    353      1.24      pk 		bus_dmamap_unload(dmatag, sbc->sbus_result_dmamap);
    354      1.24      pk 		bus_dmamem_free(dmatag, &seg, rseg);
    355      1.24      pk 		goto dmafail;
    356      1.14  mjacob 	}
    357      1.24      pk 	isp->isp_result_dma = sbc->sbus_result_dmamap->dm_segs[0].ds_addr;
    358      1.24      pk 
    359       1.1     mrg 	return (0);
    360      1.24      pk 
    361      1.24      pk dmafail:
    362      1.24      pk 	free(sbc->sbus_dmamap, M_DEVBUF);
    363      1.24      pk 	free(isp->isp_xflist, M_DEVBUF);
    364      1.24      pk 	return (1);
    365       1.1     mrg }
    366       1.1     mrg 
    367       1.1     mrg /*
    368      1.14  mjacob  * Map a DMA request.
    369      1.14  mjacob  * We're guaranteed that rq->req_handle is a value from 1 to isp->isp_maxcmds.
    370       1.1     mrg  */
    371       1.1     mrg 
    372       1.1     mrg static int
    373       1.1     mrg isp_sbus_dmasetup(isp, xs, rq, iptrp, optr)
    374       1.1     mrg 	struct ispsoftc *isp;
    375       1.1     mrg 	struct scsipi_xfer *xs;
    376       1.1     mrg 	ispreq_t *rq;
    377      1.17  mjacob 	u_int16_t *iptrp;
    378      1.17  mjacob 	u_int16_t optr;
    379       1.1     mrg {
    380       1.1     mrg 	struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
    381       1.1     mrg 	bus_dmamap_t dmamap;
    382      1.22  mjacob 	ispcontreq_t *crq;
    383      1.19  mjacob 	int cansleep = (xs->xs_control & XS_CTL_NOSLEEP) == 0;
    384      1.14  mjacob 	int in = (xs->xs_control & XS_CTL_DATA_IN) != 0;
    385       1.1     mrg 
    386       1.1     mrg 	if (xs->datalen == 0) {
    387       1.1     mrg 		rq->req_seg_count = 1;
    388      1.14  mjacob 		goto mbxsync;
    389       1.1     mrg 	}
    390      1.22  mjacob 	if (XS_CDBLEN(xs) > 12) {
    391      1.22  mjacob 		crq = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, *iptrp);
    392      1.22  mjacob 		*iptrp = (*iptrp + 1) & (RQUEST_QUEUE_LEN - 1);
    393      1.22  mjacob 		if (*iptrp == optr) {
    394      1.22  mjacob 			printf("%s: Request Queue Overflow++\n", isp->isp_name);
    395      1.22  mjacob 			XS_SETERR(xs, HBA_BOTCH);
    396      1.22  mjacob 			return (CMD_COMPLETE);
    397      1.22  mjacob 		}
    398      1.22  mjacob 	} else {
    399      1.22  mjacob 		crq = NULL;
    400      1.22  mjacob 	}
    401      1.14  mjacob 	assert(rq->req_handle != 0 && rq->req_handle <= isp->isp_maxcmds);
    402       1.1     mrg 	dmamap = sbc->sbus_dmamap[rq->req_handle - 1];
    403       1.1     mrg 	if (dmamap->dm_nsegs != 0) {
    404       1.1     mrg 		panic("%s: dma map already allocated\n", isp->isp_name);
    405       1.1     mrg 		/* NOTREACHED */
    406       1.1     mrg 	}
    407      1.14  mjacob 	if (bus_dmamap_load(sbc->sbus_dmatag, dmamap, xs->data, xs->datalen,
    408      1.19  mjacob 	    NULL, cansleep? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) != 0) {
    409       1.1     mrg 		XS_SETERR(xs, HBA_BOTCH);
    410       1.3  mjacob 		return (CMD_COMPLETE);
    411       1.1     mrg 	}
    412      1.14  mjacob 	bus_dmamap_sync(sbc->sbus_dmatag, dmamap, dmamap->dm_segs[0].ds_addr,
    413      1.14  mjacob 	    xs->datalen, in? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
    414      1.14  mjacob 	if (in) {
    415       1.1     mrg 		rq->req_flags |= REQFLAG_DATA_IN;
    416       1.1     mrg 	} else {
    417       1.1     mrg 		rq->req_flags |= REQFLAG_DATA_OUT;
    418       1.1     mrg 	}
    419      1.22  mjacob 
    420      1.22  mjacob 	if (crq) {
    421      1.22  mjacob 		rq->req_seg_count = 2;
    422      1.22  mjacob 		bzero((void *)crq, sizeof (*crq));
    423      1.22  mjacob 		crq->req_header.rqs_entry_count = 1;
    424      1.22  mjacob 		crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
    425      1.22  mjacob 		crq->req_dataseg[0].ds_count = xs->datalen;
    426      1.23  mjacob 		crq->req_dataseg[0].ds_base =  dmamap->dm_segs[0].ds_addr;
    427      1.22  mjacob 		ISP_SWIZZLE_CONTINUATION(isp, crq);
    428      1.22  mjacob 	} else {
    429      1.22  mjacob 		rq->req_dataseg[0].ds_count = xs->datalen;
    430      1.23  mjacob 		rq->req_dataseg[0].ds_base =  dmamap->dm_segs[0].ds_addr;
    431      1.22  mjacob 		rq->req_seg_count = 1;
    432      1.22  mjacob 	}
    433      1.22  mjacob 
    434      1.14  mjacob mbxsync:
    435      1.14  mjacob         ISP_SWIZZLE_REQUEST(isp, rq);
    436      1.14  mjacob #if	0
    437      1.14  mjacob 	/*
    438      1.14  mjacob 	 * If we ever map cacheable memory, we need to do something like this.
    439      1.14  mjacob 	 */
    440      1.14  mjacob         bus_dmamap_sync(sbc->sbus_dmat, sbc->sbus_rquest_dmap, 0,
    441      1.14  mjacob             sbc->sbus_rquest_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE);
    442      1.14  mjacob #endif
    443       1.3  mjacob 	return (CMD_QUEUED);
    444       1.1     mrg }
    445       1.1     mrg 
    446       1.1     mrg static void
    447       1.1     mrg isp_sbus_dmateardown(isp, xs, handle)
    448       1.1     mrg 	struct ispsoftc *isp;
    449       1.1     mrg 	struct scsipi_xfer *xs;
    450       1.1     mrg 	u_int32_t handle;
    451       1.1     mrg {
    452       1.1     mrg 	struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
    453       1.1     mrg 	bus_dmamap_t dmamap;
    454      1.14  mjacob 	assert(handle != 0 && handle <= isp->isp_maxcmds);
    455      1.14  mjacob 	dmamap = sbc->sbus_dmamap[handle-1];
    456       1.1     mrg 	if (dmamap->dm_nsegs == 0) {
    457       1.1     mrg 		panic("%s: dma map not already allocated\n", isp->isp_name);
    458       1.1     mrg 		/* NOTREACHED */
    459       1.1     mrg 	}
    460      1.14  mjacob 	bus_dmamap_sync(sbc->sbus_dmatag, dmamap, dmamap->dm_segs[0].ds_addr,
    461      1.14  mjacob 	    xs->datalen, (xs->xs_control & XS_CTL_DATA_IN)?
    462      1.14  mjacob 	    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
    463       1.1     mrg 	bus_dmamap_unload(sbc->sbus_dmatag, dmamap);
    464       1.1     mrg }
    465