[BACK]Return to isp_sbus.c CVS log [TXT][DIR] Up to [local] / sys / dev / sbus

Annotation of sys/dev/sbus/isp_sbus.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: isp_sbus.c,v 1.8 2006/06/02 20:00:56 miod Exp $       */
                      2: /* $NetBSD: isp_sbus.c,v 1.46 2001/09/26 20:53:14 eeh Exp $ */
                      3:
                      4: /*
                      5:  * This driver, which is contained in NetBSD in the files:
                      6:  *
                      7:  *     sys/dev/ic/isp.c
                      8:  *     sys/dev/ic/isp_inline.h
                      9:  *     sys/dev/ic/isp_netbsd.c
                     10:  *     sys/dev/ic/isp_netbsd.h
                     11:  *     sys/dev/ic/isp_target.c
                     12:  *     sys/dev/ic/isp_target.h
                     13:  *     sys/dev/ic/isp_tpublic.h
                     14:  *     sys/dev/ic/ispmbox.h
                     15:  *     sys/dev/ic/ispreg.h
                     16:  *     sys/dev/ic/ispvar.h
                     17:  *     sys/microcode/isp/asm_sbus.h
                     18:  *     sys/microcode/isp/asm_1040.h
                     19:  *     sys/microcode/isp/asm_1080.h
                     20:  *     sys/microcode/isp/asm_12160.h
                     21:  *     sys/microcode/isp/asm_2100.h
                     22:  *     sys/microcode/isp/asm_2200.h
                     23:  *     sys/pci/isp_pci.c
                     24:  *     sys/sbus/isp_sbus.c
                     25:  *
                     26:  * Is being actively maintained by Matthew Jacob (mjacob@netbsd.org).
                     27:  * This driver also is shared source with FreeBSD, OpenBSD, Linux, Solaris,
                     28:  * Linux versions. This tends to be an interesting maintenance problem.
                     29:  *
                     30:  * Please coordinate with Matthew Jacob on changes you wish to make here.
                     31:  */
                     32: /*
                     33:  * SBus specific probe and attach routines for Qlogic ISP SCSI adapters.
                     34:  *
                     35:  * Copyright (c) 1997, 2001 by Matthew Jacob
                     36:  * NASA AMES Research Center
                     37:  * All rights reserved.
                     38:  *
                     39:  * Redistribution and use in source and binary forms, with or without
                     40:  * modification, are permitted provided that the following conditions
                     41:  * are met:
                     42:  * 1. Redistributions of source code must retain the above copyright
                     43:  *    notice immediately at the beginning of the file, without modification,
                     44:  *    this list of conditions, and the following disclaimer.
                     45:  * 2. Redistributions in binary form must reproduce the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer in the
                     47:  *    documentation and/or other materials provided with the distribution.
                     48:  *
                     49:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     52:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
                     53:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     59:  * SUCH DAMAGE.
                     60:  *
                     61:  */
                     62:
                     63: #include <sys/param.h>
                     64: #include <sys/systm.h>
                     65: #include <sys/device.h>
                     66: #include <sys/kernel.h>
                     67: #include <sys/malloc.h>
                     68: #include <sys/queue.h>
                     69:
                     70: #include <machine/bus.h>
                     71: #include <machine/intr.h>
                     72: #include <machine/autoconf.h>
                     73:
                     74: #include <dev/ic/isp_openbsd.h>
                     75: #if    defined(ISP_COMPILE_FW) || defined(ISP_COMPILE_1000_FW)
                     76: #include <dev/microcode/isp/asm_sbus.h>
                     77: #endif
                     78: #include <dev/sbus/sbusvar.h>
                     79: #include <sys/reboot.h>
                     80:
                     81: static int isp_sbus_intr(void *);
                     82: static int
                     83: isp_sbus_rd_isr(struct ispsoftc *, u_int16_t *, u_int16_t *, u_int16_t *);
                     84: static u_int16_t isp_sbus_rd_reg(struct ispsoftc *, int);
                     85: static void isp_sbus_wr_reg (struct ispsoftc *, int, u_int16_t);
                     86: static int isp_sbus_mbxdma(struct ispsoftc *);
                     87: static int isp_sbus_dmasetup(struct ispsoftc *, XS_T *, ispreq_t *, u_int16_t *,
                     88:     u_int16_t);
                     89: static void isp_sbus_dmateardown(struct ispsoftc *, XS_T *, u_int16_t);
                     90:
                     91: #ifndef        ISP_1000_RISC_CODE
                     92: #define        ISP_1000_RISC_CODE      NULL
                     93: #endif
                     94:
                     95: static struct ispmdvec mdvec = {
                     96:        isp_sbus_rd_isr,
                     97:        isp_sbus_rd_reg,
                     98:        isp_sbus_wr_reg,
                     99:        isp_sbus_mbxdma,
                    100:        isp_sbus_dmasetup,
                    101:        isp_sbus_dmateardown,
                    102:        NULL,
                    103:        NULL,
                    104:        NULL,
                    105:        (u_int16_t *) ISP_1000_RISC_CODE
                    106: };
                    107:
                    108: struct isp_sbussoftc {
                    109:        struct ispsoftc sbus_isp;
                    110:        sdparam         sbus_dev;
                    111:        bus_space_tag_t sbus_bustag;
                    112:        bus_space_handle_t sbus_reg;
                    113:        int             sbus_node;
                    114:        int             sbus_pri;
                    115:        struct ispmdvec sbus_mdvec;
                    116:        bus_dmamap_t    *sbus_dmamap;
                    117:        int16_t         sbus_poff[_NREG_BLKS];
                    118: };
                    119:
                    120:
                    121: static int isp_match(struct device *, void *, void *);
                    122: static void isp_sbus_attach(struct device *, struct device *, void *);
                    123: struct cfattach isp_sbus_ca = {
                    124:        sizeof (struct isp_sbussoftc), isp_match, isp_sbus_attach
                    125: };
                    126:
                    127: static int
                    128: isp_match(struct device *parent, void *vcf, void *aux)
                    129: {
                    130:        struct cfdata *cf = vcf;
                    131:        int rv;
                    132: #ifdef DEBUG
                    133:        static int oneshot = 1;
                    134: #endif
                    135:        struct sbus_attach_args *sa = aux;
                    136:
                    137:        rv = (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0 ||
                    138:                strcmp("PTI,ptisp", sa->sa_name) == 0 ||
                    139:                strcmp("ptisp", sa->sa_name) == 0 ||
                    140:                strcmp("SUNW,isp", sa->sa_name) == 0 ||
                    141:                strcmp("QLGC,isp", sa->sa_name) == 0);
                    142: #ifdef DEBUG
                    143:        if (rv && oneshot) {
                    144:                oneshot = 0;
                    145:                printf("Qlogic ISP Driver, NetBSD (sbus) Platform Version "
                    146:                    "%d.%d Core Version %d.%d\n",
                    147:                    ISP_PLATFORM_VERSION_MAJOR, ISP_PLATFORM_VERSION_MINOR,
                    148:                    ISP_CORE_VERSION_MAJOR, ISP_CORE_VERSION_MINOR);
                    149:        }
                    150: #endif
                    151:        return (rv);
                    152: }
                    153:
                    154:
                    155: static void
                    156: isp_sbus_attach(struct device *parent, struct device *self, void *aux)
                    157: {
                    158:        int freq, ispburst, sbusburst;
                    159:        struct sbus_attach_args *sa = aux;
                    160:        struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) self;
                    161:        struct ispsoftc *isp = &sbc->sbus_isp;
                    162:
                    163:        printf(": %s\n", sa->sa_name);
                    164:
                    165:        sbc->sbus_bustag = sa->sa_bustag;
                    166:        if (sa->sa_nintr != 0)
                    167:                sbc->sbus_pri = sa->sa_pri;
                    168:        sbc->sbus_mdvec = mdvec;
                    169:
                    170:        if (sa->sa_npromvaddrs != 0) {
                    171:                if (bus_space_map(sa->sa_bustag, sa->sa_promvaddrs[0],
                    172:                    sa->sa_size,
                    173:                    BUS_SPACE_MAP_PROMADDRESS | BUS_SPACE_MAP_LINEAR,
                    174:                    &sbc->sbus_reg) == 0) {
                    175:                        printf("%s: cannot map registers\n", self->dv_xname);
                    176:                        return;
                    177:                }
                    178:        } else {
                    179:                if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset,
                    180:                                 sa->sa_size, BUS_SPACE_MAP_LINEAR, 0,
                    181:                                 &sbc->sbus_reg) != 0) {
                    182:                        printf("%s: cannot map registers\n", self->dv_xname);
                    183:                        return;
                    184:                }
                    185:        }
                    186:        sbc->sbus_node = sa->sa_node;
                    187:
                    188:        freq = getpropint(sa->sa_node, "clock-frequency", 0);
                    189:        if (freq) {
                    190:                /*
                    191:                 * Convert from HZ to MHz, rounding up.
                    192:                 */
                    193:                freq = (freq + 500000)/1000000;
                    194: #if    0
                    195:                printf("%s: %d MHz\n", self->dv_xname, freq);
                    196: #endif
                    197:        }
                    198:        sbc->sbus_mdvec.dv_clock = freq;
                    199:
                    200:        /*
                    201:         * Now figure out what the proper burst sizes, etc., to use.
                    202:         * Unfortunately, there is no ddi_dma_burstsizes here which
                    203:         * walks up the tree finding the limiting burst size node (if
                    204:         * any).
                    205:         */
                    206:        sbusburst = ((struct sbus_softc *)parent)->sc_burst;
                    207:        if (sbusburst == 0)
                    208:                sbusburst = SBUS_BURST_32 - 1;
                    209:        ispburst = getpropint(sa->sa_node, "burst-sizes", -1);
                    210:        if (ispburst == -1) {
                    211:                ispburst = sbusburst;
                    212:        }
                    213:        ispburst &= sbusburst;
                    214:        ispburst &= ~(1 << 7);
                    215:        ispburst &= ~(1 << 6);
                    216:        sbc->sbus_mdvec.dv_conf1 =  0;
                    217:        if (ispburst & (1 << 5)) {
                    218:                sbc->sbus_mdvec.dv_conf1 = BIU_SBUS_CONF1_FIFO_32;
                    219:        } else if (ispburst & (1 << 4)) {
                    220:                sbc->sbus_mdvec.dv_conf1 = BIU_SBUS_CONF1_FIFO_16;
                    221:        } else if (ispburst & (1 << 3)) {
                    222:                sbc->sbus_mdvec.dv_conf1 =
                    223:                    BIU_SBUS_CONF1_BURST8 | BIU_SBUS_CONF1_FIFO_8;
                    224:        }
                    225:        if (sbc->sbus_mdvec.dv_conf1) {
                    226:                sbc->sbus_mdvec.dv_conf1 |= BIU_BURST_ENABLE;
                    227:        }
                    228:
                    229:        /*
                    230:         * Some early versions of the PTI SBus adapter
                    231:         * would fail in trying to download (via poking)
                    232:         * FW. We give up on them.
                    233:         */
                    234:        if (strcmp("PTI,ptisp", sa->sa_name) == 0 ||
                    235:            strcmp("ptisp", sa->sa_name) == 0) {
                    236:                sbc->sbus_mdvec.dv_ispfw = NULL;
                    237:        }
                    238:
                    239:        isp->isp_mdvec = &sbc->sbus_mdvec;
                    240:        isp->isp_bustype = ISP_BT_SBUS;
                    241:        isp->isp_type = ISP_HA_SCSI_UNKNOWN;
                    242:        isp->isp_param = &sbc->sbus_dev;
                    243:        isp->isp_dmatag = sa->sa_dmatag;
                    244:        MEMZERO(isp->isp_param, sizeof (sdparam));
                    245:
                    246:        sbc->sbus_poff[BIU_BLOCK >> _BLK_REG_SHFT] = BIU_REGS_OFF;
                    247:        sbc->sbus_poff[MBOX_BLOCK >> _BLK_REG_SHFT] = SBUS_MBOX_REGS_OFF;
                    248:        sbc->sbus_poff[SXP_BLOCK >> _BLK_REG_SHFT] = SBUS_SXP_REGS_OFF;
                    249:        sbc->sbus_poff[RISC_BLOCK >> _BLK_REG_SHFT] = SBUS_RISC_REGS_OFF;
                    250:        sbc->sbus_poff[DMA_BLOCK >> _BLK_REG_SHFT] = DMA_REGS_OFF;
                    251:
                    252:        /* Establish interrupt channel */
                    253:        bus_intr_establish(sbc->sbus_bustag, sbc->sbus_pri, IPL_BIO, 0,
                    254:            isp_sbus_intr, sbc, self->dv_xname);
                    255:
                    256:        /*
                    257:         * Set up logging levels.
                    258:         */
                    259: #ifdef ISP_LOGDEFAULT
                    260:        isp->isp_dblev = ISP_LOGDEFAULT;
                    261: #else
                    262:        isp->isp_dblev = ISP_LOGWARN|ISP_LOGERR;
                    263: #ifdef SCSIDEBUG
                    264:        isp->isp_dblev |= ISP_LOGDEBUG1|ISP_LOGDEBUG2;
                    265: #endif
                    266: #ifdef DEBUG
                    267:        isp->isp_dblev |= ISP_LOGDEBUG0|ISP_LOGCONFIG|ISP_LOGINFO;
                    268: #endif
                    269: #endif
                    270:
                    271:        isp->isp_confopts = self->dv_cfdata->cf_flags;
                    272:        isp->isp_role = ISP_DEFAULT_ROLES;
                    273:
                    274:        /*
                    275:         * There's no tool on sparc to set NVRAM for ISPs, so ignore it.
                    276:         */
                    277:        isp->isp_confopts |= ISP_CFG_NONVRAM;
                    278:        ISP_LOCK(isp);
                    279:        isp->isp_osinfo.no_mbox_ints = 1;
                    280:        isp_reset(isp);
                    281:        if (isp->isp_state != ISP_RESETSTATE) {
                    282:                ISP_UNLOCK(isp);
                    283:                return;
                    284:        }
                    285:        ENABLE_INTS(isp);
                    286:        isp_init(isp);
                    287:        if (isp->isp_state != ISP_INITSTATE) {
                    288:                isp_uninit(isp);
                    289:                ISP_UNLOCK(isp);
                    290:                return;
                    291:        }
                    292:
                    293:        /*
                    294:         * do generic attach.
                    295:         */
                    296:        ISP_UNLOCK(isp);
                    297:        isp_attach(isp);
                    298:        if (isp->isp_state != ISP_RUNSTATE) {
                    299:                ISP_LOCK(isp);
                    300:                isp_uninit(isp);
                    301:                ISP_UNLOCK(isp);
                    302:        }
                    303: }
                    304:
                    305: static int
                    306: isp_sbus_intr(void *arg)
                    307: {
                    308:        u_int16_t isr, sema, mbox;
                    309:        struct ispsoftc *isp = arg;
                    310:
                    311:        isp->isp_intcnt++;
                    312:        if (ISP_READ_ISR(isp, &isr, &sema, &mbox) == 0) {
                    313:                isp->isp_intbogus++;
                    314:                return (0);
                    315:        } else {
                    316:                isp->isp_osinfo.onintstack = 1;
                    317:                isp_intr(isp, isr, sema, mbox);
                    318:                isp->isp_osinfo.onintstack = 0;
                    319:                return (1);
                    320:        }
                    321: }
                    322:
                    323: #define        IspVirt2Off(a, x)       \
                    324:        (((struct isp_sbussoftc *)a)->sbus_poff[((x) & _BLK_REG_MASK) >> \
                    325:        _BLK_REG_SHFT] + ((x) & 0xff))
                    326:
                    327: #define        BXR2(sbc, off)          \
                    328:        bus_space_read_2(sbc->sbus_bustag, sbc->sbus_reg, off)
                    329:
                    330: static int
                    331: isp_sbus_rd_isr(struct ispsoftc *isp, u_int16_t *isrp,
                    332:     u_int16_t *semap, u_int16_t *mbp)
                    333: {
                    334:        struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
                    335:        u_int16_t isr, sema;
                    336:
                    337:        isr = BXR2(sbc, IspVirt2Off(isp, BIU_ISR));
                    338:        sema = BXR2(sbc, IspVirt2Off(isp, BIU_SEMA));
                    339:        isp_prt(isp, ISP_LOGDEBUG3, "ISR 0x%x SEMA 0x%x", isr, sema);
                    340:        isr &= INT_PENDING_MASK(isp);
                    341:        sema &= BIU_SEMA_LOCK;
                    342:        if (isr == 0 && sema == 0) {
                    343:                return (0);
                    344:        }
                    345:        *isrp = isr;
                    346:        if ((*semap = sema) != 0) {
                    347:                *mbp = BXR2(sbc, IspVirt2Off(isp, OUTMAILBOX0));
                    348:        }
                    349:        return (1);
                    350: }
                    351:
                    352: static u_int16_t
                    353: isp_sbus_rd_reg(struct ispsoftc *isp, int regoff)
                    354: {
                    355:        struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
                    356:        int offset = sbc->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
                    357:        offset += (regoff & 0xff);
                    358:        return (bus_space_read_2(sbc->sbus_bustag, sbc->sbus_reg, offset));
                    359: }
                    360:
                    361: static void
                    362: isp_sbus_wr_reg(struct ispsoftc *isp, int regoff, u_int16_t val)
                    363: {
                    364:        struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
                    365:        int offset = sbc->sbus_poff[(regoff & _BLK_REG_MASK) >> _BLK_REG_SHFT];
                    366:        offset += (regoff & 0xff);
                    367:        bus_space_write_2(sbc->sbus_bustag, sbc->sbus_reg, offset, val);
                    368: }
                    369:
                    370: static int
                    371: isp_sbus_mbxdma(struct ispsoftc *isp)
                    372: {
                    373:        struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
                    374:        bus_dma_segment_t reqseg, rspseg;
                    375:        int reqrs, rsprs, i, progress;
                    376:        size_t n;
                    377:        bus_size_t len;
                    378:
                    379:        if (isp->isp_rquest_dma)
                    380:                return (0);
                    381:
                    382:        n = isp->isp_maxcmds * sizeof (XS_T *);
                    383:        isp->isp_xflist = (XS_T **) malloc(n, M_DEVBUF, M_WAITOK);
                    384:        if (isp->isp_xflist == NULL) {
                    385:                isp_prt(isp, ISP_LOGERR, "cannot alloc xflist array");
                    386:                return (1);
                    387:        }
                    388:        MEMZERO(isp->isp_xflist, n);
                    389:        n = sizeof (bus_dmamap_t) * isp->isp_maxcmds;
                    390:        sbc->sbus_dmamap = (bus_dmamap_t *) malloc(n, M_DEVBUF, M_WAITOK);
                    391:        if (sbc->sbus_dmamap == NULL) {
                    392:                free(isp->isp_xflist, M_DEVBUF);
                    393:                isp->isp_xflist = NULL;
                    394:                isp_prt(isp, ISP_LOGERR, "cannot alloc dmamap array");
                    395:                return (1);
                    396:        }
                    397:        for (i = 0; i < isp->isp_maxcmds; i++) {
                    398:                /* Allocate a DMA handle */
                    399:                if (bus_dmamap_create(isp->isp_dmatag, MAXPHYS, 1, MAXPHYS, 0,
                    400:                    BUS_DMA_NOWAIT, &sbc->sbus_dmamap[i]) != 0) {
                    401:                        isp_prt(isp, ISP_LOGERR, "cmd DMA maps create error");
                    402:                        break;
                    403:                }
                    404:        }
                    405:        if (i < isp->isp_maxcmds) {
                    406:                while (--i >= 0) {
                    407:                        bus_dmamap_destroy(isp->isp_dmatag,
                    408:                            sbc->sbus_dmamap[i]);
                    409:                }
                    410:                free(isp->isp_xflist, M_DEVBUF);
                    411:                free(sbc->sbus_dmamap, M_DEVBUF);
                    412:                isp->isp_xflist = NULL;
                    413:                sbc->sbus_dmamap = NULL;
                    414:                return (1);
                    415:        }
                    416:
                    417:        /*
                    418:         * Allocate and map the request and response queues
                    419:         */
                    420:        progress = 0;
                    421:        len = ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp));
                    422:        if (bus_dmamem_alloc(isp->isp_dmatag, len, 0, 0, &reqseg, 1, &reqrs,
                    423:            BUS_DMA_NOWAIT)) {
                    424:                goto dmafail;
                    425:        }
                    426:        progress++;
                    427:        if (bus_dmamem_map(isp->isp_dmatag, &reqseg, reqrs, len,
                    428:            (caddr_t *)&isp->isp_rquest, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
                    429:                goto dmafail;
                    430:        }
                    431:        progress++;
                    432:        if (bus_dmamap_create(isp->isp_dmatag, len, 1, len, 0, BUS_DMA_NOWAIT,
                    433:            &isp->isp_rqdmap) != 0) {
                    434:                goto dmafail;
                    435:        }
                    436:        progress++;
                    437:        if (bus_dmamap_load(isp->isp_dmatag, isp->isp_rqdmap,
                    438:            isp->isp_rquest, len, NULL, BUS_DMA_NOWAIT) != 0) {
                    439:                goto dmafail;
                    440:        }
                    441:        progress++;
                    442:        isp->isp_rquest_dma = isp->isp_rqdmap->dm_segs[0].ds_addr;
                    443:
                    444:        len = ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp));
                    445:        if (bus_dmamem_alloc(isp->isp_dmatag, len, 0, 0, &rspseg, 1, &rsprs,
                    446:            BUS_DMA_NOWAIT)) {
                    447:                goto dmafail;
                    448:        }
                    449:        progress++;
                    450:        if (bus_dmamem_map(isp->isp_dmatag, &rspseg, rsprs, len,
                    451:            (caddr_t *)&isp->isp_result, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
                    452:                goto dmafail;
                    453:        }
                    454:        progress++;
                    455:        if (bus_dmamap_create(isp->isp_dmatag, len, 1, len, 0, BUS_DMA_NOWAIT,
                    456:            &isp->isp_rsdmap) != 0) {
                    457:                goto dmafail;
                    458:        }
                    459:        progress++;
                    460:        if (bus_dmamap_load(isp->isp_dmatag, isp->isp_rsdmap,
                    461:            isp->isp_result, len, NULL, BUS_DMA_NOWAIT) != 0) {
                    462:                goto dmafail;
                    463:        }
                    464:        isp->isp_result_dma = isp->isp_rsdmap->dm_segs[0].ds_addr;
                    465:
                    466:        return (0);
                    467:
                    468: dmafail:
                    469:        isp_prt(isp, ISP_LOGERR, "Mailbox DMA Setup Failure");
                    470:
                    471:        if (progress >= 8) {
                    472:                bus_dmamap_unload(isp->isp_dmatag, isp->isp_rsdmap);
                    473:        }
                    474:        if (progress >= 7) {
                    475:                bus_dmamap_destroy(isp->isp_dmatag, isp->isp_rsdmap);
                    476:        }
                    477:        if (progress >= 6) {
                    478:                bus_dmamem_unmap(isp->isp_dmatag,
                    479:                    isp->isp_result, ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(isp)));
                    480:        }
                    481:        if (progress >= 5) {
                    482:                bus_dmamem_free(isp->isp_dmatag, &rspseg, rsprs);
                    483:        }
                    484:
                    485:        if (progress >= 4) {
                    486:                bus_dmamap_unload(isp->isp_dmatag, isp->isp_rqdmap);
                    487:        }
                    488:        if (progress >= 3) {
                    489:                bus_dmamap_destroy(isp->isp_dmatag, isp->isp_rqdmap);
                    490:        }
                    491:        if (progress >= 2) {
                    492:                bus_dmamem_unmap(isp->isp_dmatag,
                    493:                    isp->isp_rquest, ISP_QUEUE_SIZE(RQUEST_QUEUE_LEN(isp)));
                    494:        }
                    495:        if (progress >= 1) {
                    496:                bus_dmamem_free(isp->isp_dmatag, &reqseg, reqrs);
                    497:        }
                    498:
                    499:        for (i = 0; i < isp->isp_maxcmds; i++) {
                    500:                bus_dmamap_destroy(isp->isp_dmatag, sbc->sbus_dmamap[i]);
                    501:        }
                    502:        free(sbc->sbus_dmamap, M_DEVBUF);
                    503:        free(isp->isp_xflist, M_DEVBUF);
                    504:        isp->isp_xflist = NULL;
                    505:        sbc->sbus_dmamap = NULL;
                    506:        return (1);
                    507: }
                    508:
                    509: /*
                    510:  * Map a DMA request.
                    511:  * We're guaranteed that rq->req_handle is a value from 1 to isp->isp_maxcmds.
                    512:  */
                    513:
                    514: static int
                    515: isp_sbus_dmasetup(struct ispsoftc *isp, XS_T *xs, ispreq_t *rq,
                    516:     u_int16_t *nxtip, u_int16_t optr)
                    517: {
                    518:        struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
                    519:        bus_dmamap_t dmap;
                    520:        ispreq_t *qep;
                    521:        int cansleep = (xs->flags & SCSI_NOSLEEP) == 0;
                    522:        int in = (xs->flags & SCSI_DATA_IN) != 0;
                    523:
                    524:        qep = (ispreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, isp->isp_reqidx);
                    525:        if (xs->datalen == 0) {
                    526:                rq->req_seg_count = 1;
                    527:                goto mbxsync;
                    528:        }
                    529:
                    530:        dmap = sbc->sbus_dmamap[isp_handle_index(rq->req_handle)];
                    531:        if (dmap->dm_nsegs != 0) {
                    532:                panic("%s: dma map already allocated", isp->isp_name);
                    533:                /* NOTREACHED */
                    534:        }
                    535:        if (bus_dmamap_load(isp->isp_dmatag, dmap, xs->data, xs->datalen,
                    536:            NULL, (cansleep ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT) |
                    537:            BUS_DMA_STREAMING) != 0) {
                    538:                XS_SETERR(xs, HBA_BOTCH);
                    539:                return (CMD_COMPLETE);
                    540:        }
                    541:
                    542:        bus_dmamap_sync(isp->isp_dmatag, dmap, 0, xs->datalen,
                    543:            in? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
                    544:
                    545:        if (in) {
                    546:                rq->req_flags |= REQFLAG_DATA_IN;
                    547:        } else {
                    548:                rq->req_flags |= REQFLAG_DATA_OUT;
                    549:        }
                    550:
                    551:        if (XS_CDBLEN(xs) > 12) {
                    552:                u_int16_t onxti;
                    553:                ispcontreq_t local, *crq = &local, *cqe;
                    554:
                    555:                onxti = *nxtip;
                    556:                cqe = (ispcontreq_t *) ISP_QUEUE_ENTRY(isp->isp_rquest, onxti);
                    557:                *nxtip = ISP_NXT_QENTRY(onxti, RQUEST_QUEUE_LEN(isp));
                    558:                if (*nxtip == optr) {
                    559:                        isp_prt(isp, ISP_LOGDEBUG0, "Request Queue Overflow++");
                    560:                        bus_dmamap_unload(isp->isp_dmatag, dmap);
                    561:                        XS_SETERR(xs, HBA_BOTCH);
                    562:                        return (CMD_EAGAIN);
                    563:                }
                    564:                rq->req_seg_count = 2;
                    565:                MEMZERO((void *)crq, sizeof (*crq));
                    566:                crq->req_header.rqs_entry_count = 1;
                    567:                crq->req_header.rqs_entry_type = RQSTYPE_DATASEG;
                    568:                crq->req_dataseg[0].ds_count = xs->datalen;
                    569:                crq->req_dataseg[0].ds_base = dmap->dm_segs[0].ds_addr;
                    570:                isp_put_cont_req(isp, crq, cqe);
                    571:                MEMORYBARRIER(isp, SYNC_REQUEST, onxti, QENTRY_LEN);
                    572:        } else {
                    573:                rq->req_seg_count = 1;
                    574:                rq->req_dataseg[0].ds_count = xs->datalen;
                    575:                rq->req_dataseg[0].ds_base = dmap->dm_segs[0].ds_addr;
                    576:        }
                    577:
                    578: mbxsync:
                    579:        if (XS_CDBLEN(xs) > 12) {
                    580:                isp_put_extended_request(isp,
                    581:                    (ispextreq_t *)rq, (ispextreq_t *) qep);
                    582:        } else {
                    583:                isp_put_request(isp, rq, qep);
                    584:        }
                    585:        return (CMD_QUEUED);
                    586: }
                    587:
                    588: static void
                    589: isp_sbus_dmateardown(struct ispsoftc *isp, XS_T *xs, u_int16_t handle)
                    590: {
                    591:        struct isp_sbussoftc *sbc = (struct isp_sbussoftc *) isp;
                    592:        bus_dmamap_t dmap;
                    593:
                    594:        dmap = sbc->sbus_dmamap[isp_handle_index(handle)];
                    595:
                    596:        if (dmap->dm_nsegs == 0) {
                    597:                panic("%s: dma map not already allocated", isp->isp_name);
                    598:                /* NOTREACHED */
                    599:        }
                    600:        bus_dmamap_sync(isp->isp_dmatag, dmap, 0,
                    601:            xs->datalen, (xs->flags & SCSI_DATA_IN)?
                    602:            BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
                    603:        bus_dmamap_unload(isp->isp_dmatag, dmap);
                    604: }

CVSweb