[BACK]Return to si.c CVS log [TXT][DIR] Up to [local] / sys / arch / sparc / dev

Annotation of sys/arch/sparc/dev/si.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: si.c,v 1.27 2007/07/01 19:05:37 miod Exp $    */
                      2: /*     $NetBSD: si.c,v 1.38 1997/08/27 11:24:20 bouyer Exp $   */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1996 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by Adam Glass, David Jones, Gordon W. Ross, and Jason R. Thorpe.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer.
                     16:  * 2. Redistributions in binary form must reproduce the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer in the
                     18:  *    documentation and/or other materials provided with the distribution.
                     19:  * 3. All advertising materials mentioning features or use of this software
                     20:  *    must display the following acknowledgement:
                     21:  *        This product includes software developed by the NetBSD
                     22:  *        Foundation, Inc. and its contributors.
                     23:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     24:  *    contributors may be used to endorse or promote products derived
                     25:  *    from this software without specific prior written permission.
                     26:  *
                     27:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     28:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     29:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     30:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
                     31:  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     32:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     33:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     34:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     35:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     36:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     37:  * POSSIBILITY OF SUCH DAMAGE.
                     38:  */
                     39:
                     40: /*
                     41:  * This file contains only the machine-dependent parts of the
                     42:  * Sun4 SCSI driver.  (Autoconfig stuff and DMA functions.)
                     43:  * The machine-independent parts are in ncr5380sbc.c
                     44:  *
                     45:  * Supported hardware includes:
                     46:  * Sun "SCSI Weird" on OBIO (sw: Sun 4/100-series)
                     47:  * Sun SCSI-3 on VME (si: Sun 4/200-series, others)
                     48:  *
                     49:  * The VME variant has a bit to enable or disable the DMA engine,
                     50:  * but that bit also gates the interrupt line from the NCR5380!
                     51:  * Therefore, in order to get any interrupt from the 5380, (i.e.
                     52:  * for reselect) one must clear the DMA engine transfer count and
                     53:  * then enable DMA.  This has the further complication that you
                     54:  * CAN NOT touch the NCR5380 while the DMA enable bit is set, so
                     55:  * we have to turn DMA back off before we even look at the 5380.
                     56:  *
                     57:  * What wonderfully whacky hardware this is!
                     58:  *
                     59:  * David Jones wrote the initial version of this module for NetBSD/sun3,
                     60:  * which included support for the VME adapter only. (no reselection).
                     61:  *
                     62:  * Gordon Ross added support for the Sun 3 OBIO adapter, and re-worked
                     63:  * both the VME and OBIO code to support disconnect/reselect.
                     64:  * (Required figuring out the hardware "features" noted above.)
                     65:  *
                     66:  * The autoconfiguration boilerplate came from Adam Glass.
                     67:  *
                     68:  * Jason R. Thorpe ported the autoconfiguration and VME portions to
                     69:  * NetBSD/sparc, and added initial support for the 4/100 "SCSI Weird",
                     70:  * a wacky OBIO variant of the VME SCSI-3.  Many thanks to Chuck Cranor
                     71:  * for lots of helpful tips and suggestions.  Thanks also to Paul Kranenburg
                     72:  * and Chris Torek for bits of insight needed along the way.  Thanks to
                     73:  * David Gilbert and Andrew Gillham who risked filesystem life-and-limb
                     74:  * for the sake of testing.  Andrew Gillham helped work out the bugs
                     75:  * in the 4/100 DMA code.
                     76:  */
                     77:
                     78: /*
                     79:  * NOTE: support for the 4/100 "SCSI Weird" is not complete!  DMA
                     80:  * works, but interrupts (and, thus, reselection) don't.  I don't know
                     81:  * why, and I don't have a machine to test this on further.
                     82:  *
                     83:  * DMA, DMA completion interrupts, and reselection work fine on my
                     84:  * 4/260 with modern SCSI-II disks attached.  I've had reports of
                     85:  * reselection failing on Sun Shoebox-type configurations where
                     86:  * there are multiple non-SCSI devices behind Emulex or Adaptec
                     87:  * bridges.  These devices pre-date the SCSI-I spec, and might not
                     88:  * bahve the way the 5380 code expects.  For this reason, only
                     89:  * DMA is enabled by default in this driver.
                     90:  *
                     91:  *     Jason R. Thorpe <thorpej@NetBSD.ORG>
                     92:  *     December 8, 1995
                     93:  */
                     94:
                     95: #include <sys/types.h>
                     96: #include <sys/param.h>
                     97: #include <sys/systm.h>
                     98: #include <sys/kernel.h>
                     99: #include <sys/malloc.h>
                    100: #include <sys/errno.h>
                    101: #include <sys/device.h>
                    102: #include <sys/buf.h>
                    103: #include <sys/proc.h>
                    104: #include <sys/user.h>
                    105:
                    106: #include <scsi/scsi_all.h>
                    107: #include <scsi/scsi_debug.h>
                    108: #include <scsi/scsiconf.h>
                    109:
                    110: #include <machine/autoconf.h>
                    111: #include <machine/cpu.h>
                    112: #include <machine/pmap.h>
                    113:
                    114: #include <sparc/sparc/vaddrs.h>
                    115: #include <sparc/sparc/cpuvar.h>
                    116:
                    117: #define COUNT_SW_LEFTOVERS     XXX     /* See sw DMA completion code */
                    118:
                    119: #include <dev/ic/ncr5380reg.h>
                    120: #include <dev/ic/ncr5380var.h>
                    121:
                    122: #include <sparc/dev/sireg.h>
                    123:
                    124: /*
                    125:  * Transfers smaller than this are done using PIO
                    126:  * (on assumption they're not worth DMA overhead)
                    127:  */
                    128: #define        MIN_DMA_LEN 128
                    129:
                    130: /*
                    131:  * Transfers lager than 65535 bytes need to be split-up.
                    132:  * (Some of the FIFO logic has only 16 bits counters.)
                    133:  * Make the size an integer multiple of the page size
                    134:  * to avoid buf/cluster remap problems.  (paranoid?)
                    135:  */
                    136: #define        MAX_DMA_LEN 0xE000
                    137:
                    138: #ifdef DEBUG
                    139: int si_debug = 0;
                    140: static int si_link_flags = 0 /* | SDEV_DB2 */ ;
                    141: #endif
                    142:
                    143: /*
                    144:  * This structure is used to keep track of mapped DMA requests.
                    145:  */
                    146: struct si_dma_handle {
                    147:        int             dh_flags;
                    148: #define        SIDH_BUSY       0x01            /* This DH is in use */
                    149: #define        SIDH_OUT        0x02            /* DMA does data out (write) */
                    150:        u_char *        dh_addr;        /* KVA of start of buffer */
                    151:        int             dh_maplen;      /* Original data length */
                    152:        long            dh_dvma;        /* VA of buffer in DVMA space */
                    153:        long            dh_startingpa;  /* PA of buffer; for "sw" */
                    154: };
                    155:
                    156: /*
                    157:  * The first structure member has to be the ncr5380_softc
                    158:  * so we can just cast to go back and fourth between them.
                    159:  */
                    160: struct si_softc {
                    161:        struct ncr5380_softc    ncr_sc;
                    162:        volatile struct si_regs *sc_regs;
                    163:        struct intrhand sc_ih;
                    164:        int             sc_adapter_type;
                    165:        int             sc_adapter_iv_am; /* int. vec + address modifier */
                    166:        struct si_dma_handle *sc_dma;
                    167:        int             sc_xlen;        /* length of current DMA segment. */
                    168:        int             sc_options;     /* options for this instance. */
                    169: };
                    170:
                    171: /*
                    172:  * Options.  By default, configuration files enable DMA and disable
                    173:  * DMA completion interrupts and reselect.  You may enable additional features
                    174:  * the `flags' directive in your kernel's configuration file.
                    175:  *
                    176:  * On the "sw", interrupts (and thus) reselection don't work, so they're
                    177:  * disabled.  DMA is still a little dangerous, too.
                    178:  */
                    179: #define        SI_ENABLE_DMA   0x01    /* Use DMA (maybe polled) */
                    180: #define        SI_DMA_INTR     0x02    /* DMA completion interrupts */
                    181: #define        SI_DO_RESELECT  0x04    /* Allow disconnect/reselect */
                    182: #define        SI_OPTIONS_MASK (SI_ENABLE_DMA|SI_DMA_INTR|SI_DO_RESELECT)
                    183: #define        SW_OPTIONS_MASK (SI_ENABLE_DMA)
                    184: #define SI_OPTIONS_BITS        "\10\3RESELECT\2DMA_INTR\1DMA"
                    185:
                    186: /* How long to wait for DMA before declaring an error. */
                    187: int si_dma_intr_timo = 500;    /* ticks (sec. X 100) */
                    188:
                    189: static int     si_match(struct device *, void *, void *);
                    190: static void    si_attach(struct device *, struct device *, void *);
                    191: static int     si_intr(void *);
                    192: static void    si_reset_adapter(struct ncr5380_softc *);
                    193: static void    si_minphys(struct buf *);
                    194:
                    195: void si_dma_alloc(struct ncr5380_softc *);
                    196: void si_dma_free(struct ncr5380_softc *);
                    197: void si_dma_poll(struct ncr5380_softc *);
                    198:
                    199: void si_vme_dma_setup(struct ncr5380_softc *);
                    200: void si_vme_dma_start(struct ncr5380_softc *);
                    201: void si_vme_dma_stop(struct ncr5380_softc *);
                    202:
                    203: void si_vme_intr_on(struct ncr5380_softc *);
                    204: void si_vme_intr_off(struct ncr5380_softc *);
                    205:
                    206: void si_obio_dma_setup(struct ncr5380_softc *);
                    207: void si_obio_dma_start(struct ncr5380_softc *);
                    208: void si_obio_dma_stop(struct ncr5380_softc *);
                    209:
                    210: void si_obio_intr_on(struct ncr5380_softc *);
                    211: void si_obio_intr_off(struct ncr5380_softc *);
                    212:
                    213: static struct scsi_adapter     si_ops = {
                    214:        ncr5380_scsi_cmd,               /* scsi_cmd()           */
                    215:        si_minphys,                     /* scsi_minphys()       */
                    216:        NULL,                           /* open_target_lu()     */
                    217:        NULL,                           /* close_target_lu()    */
                    218: };
                    219:
                    220: /* This is copied from julian's bt driver */
                    221: /* "so we have a default dev struct for our link struct." */
                    222: static struct scsi_device si_dev = {
                    223:        NULL,           /* Use default error handler.           */
                    224:        NULL,           /* Use default start handler.           */
                    225:        NULL,           /* Use default async handler.           */
                    226:        NULL,           /* Use default "done" routine.          */
                    227: };
                    228:
                    229:
                    230: /* The Sun SCSI-3 VME controller. */
                    231: struct cfattach si_ca = {
                    232:        sizeof(struct si_softc), si_match, si_attach
                    233: };
                    234:
                    235: struct cfdriver si_cd = {
                    236:        NULL, "si", DV_DULL
                    237: };
                    238:
                    239: /* The Sun "SCSI Weird" 4/100 obio controller. */
                    240: struct cfattach sw_ca = {
                    241:        sizeof(struct si_softc), si_match, si_attach
                    242: };
                    243:
                    244: struct cfdriver sw_cd = {
                    245:        NULL, "sw", DV_DULL
                    246: };
                    247:
                    248: static int
                    249: si_match(parent, vcf, aux)
                    250:        struct device   *parent;
                    251:        void *vcf, *aux;
                    252: {
                    253:        struct cfdata *cf = vcf;
                    254:        struct confargs *ca = aux;
                    255:        struct romaux *ra = &ca->ca_ra;
                    256:
                    257:        /* Are we looking for the right thing? */
                    258:        if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
                    259:                return (0);
                    260:
                    261:        /* Nothing but a Sun 4 is going to have these devices. */
                    262:        if (!CPU_ISSUN4)
                    263:                return (0);
                    264:
                    265:        /*
                    266:         * Default interrupt priority always is 3.  At least, that's
                    267:         * what my board seems to be at.  --thorpej
                    268:         */
                    269:        if (ra->ra_intr[0].int_pri == -1)
                    270:                ra->ra_intr[0].int_pri = 3;
                    271:
                    272:        /* Figure out the bus type and look for the appropriate adapter. */
                    273:        switch (ca->ca_bustype) {
                    274:        case BUS_VME16:
                    275:                /* AFAIK, the `si' can only exist on the vmes. */
                    276:                if (strcmp(ra->ra_name, "si") ||
                    277:                    cpuinfo.cpu_type == CPUTYP_4_100)
                    278:                        return (0);
                    279:                break;
                    280:
                    281:        case BUS_OBIO:
                    282:                /* AFAIK, an `sw' can only exist on the obio. */
                    283:                if (strcmp(ra->ra_name, "sw") ||
                    284:                    cpuinfo.cpu_type != CPUTYP_4_100)
                    285:                        return (0);
                    286:                break;
                    287:
                    288:        default:
                    289:                /* Don't know what we ended up with ... */
                    290:                return (0);
                    291:        }
                    292:
                    293:        /* Make sure there is something there... */
                    294:        if (probeget(ra->ra_vaddr + 1, 1) == -1)
                    295:                return (0);
                    296:
                    297:        /*
                    298:         * If this is a VME SCSI board, we have to determine whether
                    299:         * it is an "sc" (Sun2) or "si" (Sun3) SCSI board.  This can
                    300:         * be determined using the fact that the "sc" board occupies
                    301:         * 4K bytes in VME space but the "si" board occupies 2K bytes.
                    302:         */
                    303:        if (strcmp(cf->cf_driver->cd_name, "si") == 0)
                    304:                if (probeget(ra->ra_vaddr + 0x801, 1) != -1)
                    305:                        return(0);
                    306:
                    307:        return (1);
                    308: }
                    309:
                    310: static void
                    311: si_attach(parent, self, args)
                    312:        struct device   *parent, *self;
                    313:        void            *args;
                    314: {
                    315:        struct si_softc *sc = (struct si_softc *) self;
                    316:        struct ncr5380_softc *ncr_sc = (struct ncr5380_softc *)sc;
                    317:        struct scsibus_attach_args saa;
                    318:        volatile struct si_regs *regs;
                    319:        struct confargs *ca = args;
                    320:        struct romaux *ra = &ca->ca_ra;
                    321:        struct bootpath *bp;
                    322:        int i;
                    323:
                    324:        /*
                    325:         * Pull in the options flags.  Allow the user to completely
                    326:         * override the default values.
                    327:         */
                    328:        sc->sc_options = ncr_sc->sc_dev.dv_cfdata->cf_flags &
                    329:            (ca->ca_bustype == BUS_OBIO ? SW_OPTIONS_MASK : SI_OPTIONS_MASK);
                    330:
                    331:        /* Map the controller registers. */
                    332:        regs = (struct si_regs *)
                    333:                mapiodev(ra->ra_reg, 0, sizeof(struct si_regs));
                    334:
                    335:        /*
                    336:         * Fill in the prototype scsi_link.
                    337:         */
                    338:        ncr_sc->sc_link.adapter_softc = sc;
                    339:        ncr_sc->sc_link.adapter_target = 7;
                    340:        ncr_sc->sc_link.adapter = &si_ops;
                    341:        ncr_sc->sc_link.device = &si_dev;
                    342:        ncr_sc->sc_link.openings = 4;
                    343:
                    344:        /*
                    345:         * Initialize fields used by the MI code
                    346:         */
                    347:        ncr_sc->sci_r0 = &regs->sci.sci_r0;
                    348:        ncr_sc->sci_r1 = &regs->sci.sci_r1;
                    349:        ncr_sc->sci_r2 = &regs->sci.sci_r2;
                    350:        ncr_sc->sci_r3 = &regs->sci.sci_r3;
                    351:        ncr_sc->sci_r4 = &regs->sci.sci_r4;
                    352:        ncr_sc->sci_r5 = &regs->sci.sci_r5;
                    353:        ncr_sc->sci_r6 = &regs->sci.sci_r6;
                    354:        ncr_sc->sci_r7 = &regs->sci.sci_r7;
                    355:
                    356:        /*
                    357:         * MD function pointers used by the MI code.
                    358:         */
                    359:        ncr_sc->sc_pio_out = ncr5380_pio_out;
                    360:        ncr_sc->sc_pio_in =  ncr5380_pio_in;
                    361:        if (sc->sc_options & SI_ENABLE_DMA) {
                    362:                ncr_sc->sc_dma_alloc = si_dma_alloc;
                    363:                ncr_sc->sc_dma_free  = si_dma_free;
                    364:                ncr_sc->sc_dma_poll  = si_dma_poll;
                    365:        }
                    366:
                    367:        switch (ca->ca_bustype) {
                    368:        case BUS_VME16:
                    369:                if (sc->sc_options & SI_ENABLE_DMA) {
                    370:                        ncr_sc->sc_dma_setup = si_vme_dma_setup;
                    371:                        ncr_sc->sc_dma_start = si_vme_dma_start;
                    372:                        ncr_sc->sc_dma_stop  = si_vme_dma_stop;
                    373:                        if (sc->sc_options & SI_DO_RESELECT) {
                    374:                                /*
                    375:                                 * Need to enable interrupts (and DMA!)
                    376:                                 * on this H/W for reselect to work.
                    377:                                 */
                    378:                                ncr_sc->sc_intr_on   = si_vme_intr_on;
                    379:                                ncr_sc->sc_intr_off  = si_vme_intr_off;
                    380:                        }
                    381:                }
                    382:                break;
                    383:
                    384:        case BUS_OBIO:
                    385:                if (sc->sc_options & SI_ENABLE_DMA) {
                    386:                        ncr_sc->sc_dma_setup = si_obio_dma_setup;
                    387:                        ncr_sc->sc_dma_start = si_obio_dma_start;
                    388:                        ncr_sc->sc_dma_stop  = si_obio_dma_stop;
                    389:                }
                    390:                ncr_sc->sc_intr_on   = si_obio_intr_on;
                    391:                ncr_sc->sc_intr_off  = si_obio_intr_off;
                    392:                break;
                    393:
                    394:        default:
                    395:                panic("si_attach: impossible bus type 0x%x", ca->ca_bustype);
                    396:                /* NOTREACHED */
                    397:        }
                    398:
                    399:        ncr_sc->sc_flags = 0;
                    400:        if ((sc->sc_options & SI_DO_RESELECT) == 0)
                    401:                ncr_sc->sc_flags |= NCR5380_PERMIT_RESELECT;
                    402:        if ((sc->sc_options & (SI_ENABLE_DMA | SI_DMA_INTR)) !=
                    403:            (SI_ENABLE_DMA | SI_DMA_INTR))
                    404:                ncr_sc->sc_flags |= NCR5380_FORCE_POLLING;
                    405:        ncr_sc->sc_min_dma_len = MIN_DMA_LEN;
                    406:
                    407:        /*
                    408:         * Initialize fields used only here in the MD code.
                    409:         */
                    410:        sc->sc_regs = regs;
                    411:        sc->sc_adapter_type = ca->ca_bustype;
                    412:        /*  sc_adapter_iv_am = (was set above) */
                    413:
                    414:        /*
                    415:         * Allocate DMA handles.
                    416:         */
                    417:        i = SCI_OPENINGS * sizeof(struct si_dma_handle);
                    418:        sc->sc_dma = (struct si_dma_handle *)malloc(i, M_DEVBUF, M_NOWAIT);
                    419:        if (sc->sc_dma == NULL)
                    420:                panic("si: dma handle malloc failed");
                    421:        for (i = 0; i < SCI_OPENINGS; i++)
                    422:                sc->sc_dma[i].dh_flags = 0;
                    423:
                    424:        sc->sc_regs = regs;
                    425:        sc->sc_adapter_type = ca->ca_bustype;
                    426:
                    427:        /* Establish the interrupt. */
                    428:        sc->sc_ih.ih_fun = si_intr;
                    429:        sc->sc_ih.ih_arg = sc;
                    430:
                    431:        switch (ca->ca_bustype) {
                    432:        case BUS_OBIO:
                    433:                /*
                    434:                 * This will be an "sw" controller.
                    435:                 */
                    436:                intr_establish(ra->ra_intr[0].int_pri, &sc->sc_ih, IPL_BIO,
                    437:                    self->dv_xname);
                    438:                break;
                    439:
                    440:        case BUS_VME16:
                    441:                /*
                    442:                 * This will be an "si" controller.
                    443:                 */
                    444:                vmeintr_establish(ra->ra_intr[0].int_vec,
                    445:                    ra->ra_intr[0].int_pri, &sc->sc_ih, IPL_BIO,
                    446:                    self->dv_xname);
                    447:                sc->sc_adapter_iv_am =
                    448:                    VME_SUPV_DATA_24 | (ra->ra_intr[0].int_vec & 0xFF);
                    449:                break;
                    450:
                    451:        default:
                    452:                /* Impossible case handled above. */
                    453:                break;
                    454:        }
                    455:        printf(" pri %d\n", ra->ra_intr[0].int_pri);
                    456: #ifdef DEBUG
                    457:        if (sc->sc_options) {
                    458:                printf("%s: options=%b\n", ncr_sc->sc_dev.dv_xname,
                    459:                        sc->sc_options, SI_OPTIONS_BITS);
                    460:        }
                    461:        if (si_debug)
                    462:                printf("si: Set TheSoftC=%p TheRegs=%p\n", sc, regs);
                    463:        ncr_sc->sc_link.flags |= si_link_flags;
                    464: #endif
                    465:
                    466:        /*
                    467:         *  Initialize si board itself.
                    468:         */
                    469:        si_reset_adapter(ncr_sc);
                    470:        ncr5380_init(ncr_sc);
                    471:        ncr5380_reset_scsibus(ncr_sc);
                    472:        DELAY(2000000);
                    473:
                    474:        /*
                    475:         * If the boot path is "sw" or "si" at the moment and it's me, then
                    476:         * walk out pointer to the sub-device, ready for the config
                    477:         * below.
                    478:         */
                    479:        bp = ra->ra_bp;
                    480:        if (bp != NULL && strcmp(bp->name, ra->ra_name) == 0 &&
                    481:            bp->val[0] == -1 && bp->val[1] == ncr_sc->sc_dev.dv_unit)
                    482:                bootpath_store(1, bp + 1);
                    483:
                    484:        bzero(&saa, sizeof(saa));
                    485:        saa.saa_sc_link = &(ncr_sc->sc_link);
                    486:
                    487:        /* Configure sub-devices */
                    488:        config_found(self, &saa, scsiprint);
                    489:
                    490:        bootpath_store(1, NULL);
                    491: }
                    492:
                    493: static void
                    494: si_minphys(struct buf *bp)
                    495: {
                    496:        if (bp->b_bcount > MAX_DMA_LEN) {
                    497: #ifdef DEBUG
                    498:                if (si_debug) {
                    499:                        printf("si_minphys len = 0x%x.\n", MAX_DMA_LEN);
                    500: #ifdef DDB
                    501:                        Debugger();
                    502: #endif
                    503:                }
                    504: #endif
                    505:                bp->b_bcount = MAX_DMA_LEN;
                    506:        }
                    507:        return (minphys(bp));
                    508: }
                    509:
                    510: #define CSR_WANT (SI_CSR_SBC_IP | SI_CSR_DMA_IP | \
                    511:        SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR )
                    512:
                    513: static int
                    514: si_intr(void *arg)
                    515: {
                    516:        struct si_softc *sc = arg;
                    517:        volatile struct si_regs *si = sc->sc_regs;
                    518:        int dma_error, claimed;
                    519:        u_short csr;
                    520:
                    521:        claimed = 0;
                    522:        dma_error = 0;
                    523:
                    524:        /* SBC interrupt? DMA interrupt? */
                    525:        if (sc->sc_adapter_type == BUS_OBIO)
                    526:                csr = si->sw_csr;
                    527:        else
                    528:                csr = si->si_csr;
                    529:        NCR_TRACE("si_intr: csr=0x%x\n", csr);
                    530:
                    531:        if (csr & SI_CSR_DMA_CONFLICT) {
                    532:                dma_error |= SI_CSR_DMA_CONFLICT;
                    533:                printf("si_intr: DMA conflict\n");
                    534:        }
                    535:        if (csr & SI_CSR_DMA_BUS_ERR) {
                    536:                dma_error |= SI_CSR_DMA_BUS_ERR;
                    537:                printf("si_intr: DMA bus error\n");
                    538:        }
                    539:        if (dma_error) {
                    540:                if (sc->ncr_sc.sc_state & NCR_DOINGDMA)
                    541:                        sc->ncr_sc.sc_state |= NCR_ABORTING;
                    542:                /* Make sure we will call the main isr. */
                    543:                csr |= SI_CSR_DMA_IP;
                    544:        }
                    545:
                    546:        if (csr & (SI_CSR_SBC_IP | SI_CSR_DMA_IP)) {
                    547:                claimed = ncr5380_intr(&sc->ncr_sc);
                    548: #ifdef DEBUG
                    549:                if (!claimed) {
                    550:                        printf("si_intr: spurious from SBC\n");
                    551: #ifdef DDB
                    552:                        if (si_debug & 4) {
                    553:                                Debugger();     /* XXX */
                    554:                        }
                    555: #endif
                    556:                }
                    557: #endif
                    558:        }
                    559:
                    560:        return (claimed);
                    561: }
                    562:
                    563:
                    564: static void
                    565: si_reset_adapter(struct ncr5380_softc *ncr_sc)
                    566: {
                    567:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                    568:        volatile struct si_regs *si = sc->sc_regs;
                    569:
                    570: #ifdef DEBUG
                    571:        if (si_debug) {
                    572:                printf("si_reset_adapter\n");
                    573:        }
                    574: #endif
                    575:
                    576:        /*
                    577:         * The SCSI3 controller has an 8K FIFO to buffer data between the
                    578:         * 5380 and the DMA.  Make sure it starts out empty.
                    579:         *
                    580:         * The reset bits in the CSR are active low.
                    581:         */
                    582:        switch(sc->sc_adapter_type) {
                    583:        case BUS_VME16:
                    584:                si->si_csr = 0;
                    585:                delay(10);
                    586:                si->si_csr = SI_CSR_FIFO_RES | SI_CSR_SCSI_RES | SI_CSR_INTR_EN;
                    587:                delay(10);
                    588:                si->fifo_count = 0;
                    589:                si->dma_addrh = 0;
                    590:                si->dma_addrl = 0;
                    591:                si->dma_counth = 0;
                    592:                si->dma_countl = 0;
                    593:                si->si_iv_am = sc->sc_adapter_iv_am;
                    594:                si->fifo_cnt_hi = 0;
                    595:                break;
                    596:
                    597:        case BUS_OBIO:
                    598:                si->sw_csr = 0;
                    599:                delay(10);
                    600:                si->sw_csr = SI_CSR_SCSI_RES;
                    601:                si->dma_addr = 0;
                    602:                si->dma_count = 0;
                    603:                delay(10);
                    604:                si->sw_csr |= SI_CSR_INTR_EN;
                    605:                break;
                    606:        }
                    607:
                    608:        SCI_CLR_INTR(ncr_sc);
                    609: }
                    610:
                    611:
                    612: /*****************************************************************
                    613:  * Common functions for DMA
                    614:  ****************************************************************/
                    615:
                    616: /*
                    617:  * Allocate a DMA handle and put it in sc->sc_dma.  Prepare
                    618:  * for DMA transfer.  On the Sun4, this means mapping the buffer
                    619:  * into DVMA space.
                    620:  */
                    621: void
                    622: si_dma_alloc(ncr_sc)
                    623:        struct ncr5380_softc *ncr_sc;
                    624: {
                    625:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                    626:        struct sci_req *sr = ncr_sc->sc_current;
                    627:        struct scsi_xfer *xs = sr->sr_xs;
                    628:        struct si_dma_handle *dh;
                    629:        int i, xlen;
                    630:        u_long addr;
                    631:
                    632: #ifdef DIAGNOSTIC
                    633:        if (sr->sr_dma_hand != NULL)
                    634:                panic("si_dma_alloc: already have DMA handle");
                    635: #endif
                    636:
                    637: #if 1  /* XXX - Temporary */
                    638:        /* XXX - In case we think DMA is completely broken... */
                    639:        if ((sc->sc_options & SI_ENABLE_DMA) == 0)
                    640:                return;
                    641: #endif
                    642:
                    643:        addr = (u_long) ncr_sc->sc_dataptr;
                    644:        xlen = ncr_sc->sc_datalen;
                    645:
                    646:        /* If the DMA start addr is misaligned then do PIO */
                    647:        if ((addr & 1) || (xlen & 1)) {
                    648: #ifdef DEBUG
                    649:                printf("si_dma_alloc: misaligned.\n");
                    650: #endif
                    651:                return;
                    652:        }
                    653:
                    654:        /* Make sure our caller checked sc_min_dma_len. */
                    655:        if (xlen < MIN_DMA_LEN)
                    656:                panic("si_dma_alloc: xlen=0x%x", xlen);
                    657:
                    658:        /* Find free DMA handle.  Guaranteed to find one since we have
                    659:           as many DMA handles as the driver has processes. */
                    660:        for (i = 0; i < SCI_OPENINGS; i++) {
                    661:                if ((sc->sc_dma[i].dh_flags & SIDH_BUSY) == 0)
                    662:                        goto found;
                    663:        }
                    664:        panic("si: no free DMA handles.");
                    665: found:
                    666:
                    667:        dh = &sc->sc_dma[i];
                    668:        dh->dh_flags = SIDH_BUSY;
                    669:        dh->dh_addr = (u_char *) addr;
                    670:        dh->dh_maplen  = xlen;
                    671:        dh->dh_dvma = 0;
                    672:
                    673:        /* Copy the "write" flag for convenience. */
                    674:        if (xs->flags & SCSI_DATA_OUT)
                    675:                dh->dh_flags |= SIDH_OUT;
                    676:
                    677:        /*
                    678:         * Double-map the buffer into DVMA space.  If we can't re-map
                    679:         * the buffer, we print a warning and fall back to PIO mode.
                    680:         *
                    681:         * NOTE: it is not safe to sleep here!
                    682:         */
                    683:        dh->dh_dvma = (long)kdvma_mapin((caddr_t)addr, xlen, 0);
                    684:        if (dh->dh_dvma == 0) {
                    685:                /* Can't remap segment */
                    686:                printf("si_dma_alloc: can't remap %p/0x%x, doing PIO\n",
                    687:                        dh->dh_addr, dh->dh_maplen);
                    688:                dh->dh_flags = 0;
                    689:                return;
                    690:        }
                    691:
                    692:        /* success */
                    693:        sr->sr_dma_hand = dh;
                    694:
                    695:        return;
                    696: }
                    697:
                    698:
                    699: void
                    700: si_dma_free(ncr_sc)
                    701:        struct ncr5380_softc *ncr_sc;
                    702: {
                    703:        struct sci_req *sr = ncr_sc->sc_current;
                    704:        struct si_dma_handle *dh = sr->sr_dma_hand;
                    705:
                    706: #ifdef DIAGNOSTIC
                    707:        if (dh == NULL)
                    708:                panic("si_dma_free: no DMA handle");
                    709: #endif
                    710:
                    711:        if (ncr_sc->sc_state & NCR_DOINGDMA)
                    712:                panic("si_dma_free: free while in progress");
                    713:
                    714:        if (dh->dh_flags & SIDH_BUSY) {
                    715:                /* XXX - Should separate allocation and mapping. */
                    716:
                    717:                /* Give back the DVMA space. */
                    718:                dvma_mapout((vaddr_t)dh->dh_dvma, (vaddr_t)dh->dh_addr,
                    719:                            dh->dh_maplen);
                    720:
                    721:                dh->dh_dvma = 0;
                    722:                dh->dh_flags = 0;
                    723:        }
                    724:        sr->sr_dma_hand = NULL;
                    725: }
                    726:
                    727:
                    728: /*
                    729:  * Poll (spin-wait) for DMA completion.
                    730:  * Called right after xx_dma_start(), and
                    731:  * xx_dma_stop() will be called next.
                    732:  * Same for either VME or OBIO.
                    733:  */
                    734: void
                    735: si_dma_poll(ncr_sc)
                    736:        struct ncr5380_softc *ncr_sc;
                    737: {
                    738:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                    739:        struct sci_req *sr = ncr_sc->sc_current;
                    740:        volatile struct si_regs *si = sc->sc_regs;
                    741:        int tmo, csr_mask, csr;
                    742:
                    743:        /* Make sure DMA started successfully. */
                    744:        if (ncr_sc->sc_state & NCR_ABORTING)
                    745:                return;
                    746:
                    747:        csr_mask = SI_CSR_SBC_IP | SI_CSR_DMA_IP |
                    748:                SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR;
                    749:
                    750:        tmo = 50000;    /* X100 = 5 sec. */
                    751:        for (;;) {
                    752:                if (sc->sc_adapter_type == BUS_OBIO)
                    753:                        csr = si->sw_csr;
                    754:                else
                    755:                        csr = si->si_csr;
                    756:                if (csr & csr_mask)
                    757:                        break;
                    758:                if (--tmo <= 0) {
                    759:                        printf("%s: DMA timeout (while polling)\n",
                    760:                            ncr_sc->sc_dev.dv_xname);
                    761:                        /* Indicate timeout as MI code would. */
                    762:                        sr->sr_flags |= SR_OVERDUE;
                    763:                        break;
                    764:                }
                    765:                delay(100);
                    766:        }
                    767:
                    768: #ifdef DEBUG
                    769:        if (si_debug) {
                    770:                printf("si_dma_poll: done, csr=0x%x\n", csr);
                    771:        }
                    772: #endif
                    773: }
                    774:
                    775:
                    776: /*****************************************************************
                    777:  * VME functions for DMA
                    778:  ****************************************************************/
                    779:
                    780:
                    781: /*
                    782:  * This is called when the bus is going idle,
                    783:  * so we want to enable the SBC interrupts.
                    784:  * That is controlled by the DMA enable!
                    785:  * Who would have guessed!
                    786:  * What a NASTY trick!
                    787:  */
                    788: void
                    789: si_vme_intr_on(ncr_sc)
                    790:        struct ncr5380_softc *ncr_sc;
                    791: {
                    792:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                    793:        volatile struct si_regs *si = sc->sc_regs;
                    794:
                    795:        si_vme_dma_setup(ncr_sc);
                    796:        si->si_csr |= SI_CSR_DMA_EN;
                    797: }
                    798:
                    799: /*
                    800:  * This is called when the bus is idle and we are
                    801:  * about to start playing with the SBC chip.
                    802:  */
                    803: void
                    804: si_vme_intr_off(ncr_sc)
                    805:        struct ncr5380_softc *ncr_sc;
                    806: {
                    807:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                    808:        volatile struct si_regs *si = sc->sc_regs;
                    809:
                    810:        si->si_csr &= ~SI_CSR_DMA_EN;
                    811: }
                    812:
                    813: /*
                    814:  * This function is called during the COMMAND or MSG_IN phase
                    815:  * that precedes a DATA_IN or DATA_OUT phase, in case we need
                    816:  * to setup the DMA engine before the bus enters a DATA phase.
                    817:  *
                    818:  * XXX: The VME adapter appears to suppress SBC interrupts
                    819:  * when the FIFO is not empty or the FIFO count is non-zero!
                    820:  *
                    821:  * On the VME version we just clear the DMA count and address
                    822:  * here (to make sure it stays idle) and do the real setup
                    823:  * later, in dma_start.
                    824:  */
                    825: void
                    826: si_vme_dma_setup(ncr_sc)
                    827:        struct ncr5380_softc *ncr_sc;
                    828: {
                    829:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                    830:        volatile struct si_regs *si = sc->sc_regs;
                    831:
                    832:        /* Reset the FIFO */
                    833:        si->si_csr &= ~SI_CSR_FIFO_RES;         /* active low */
                    834:        si->si_csr |= SI_CSR_FIFO_RES;
                    835:
                    836:        /* Set direction (assume recv here) */
                    837:        si->si_csr &= ~SI_CSR_SEND;
                    838:        /* Assume worst alignment */
                    839:        si->si_csr |= SI_CSR_BPCON;
                    840:
                    841:        si->dma_addrh = 0;
                    842:        si->dma_addrl = 0;
                    843:
                    844:        si->dma_counth = 0;
                    845:        si->dma_countl = 0;
                    846:
                    847:        /* Clear FIFO counter. (also hits dma_count) */
                    848:        si->fifo_cnt_hi = 0;
                    849:        si->fifo_count = 0;
                    850: }
                    851:
                    852:
                    853: void
                    854: si_vme_dma_start(ncr_sc)
                    855:        struct ncr5380_softc *ncr_sc;
                    856: {
                    857:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                    858:        struct sci_req *sr = ncr_sc->sc_current;
                    859:        struct si_dma_handle *dh = sr->sr_dma_hand;
                    860:        volatile struct si_regs *si = sc->sc_regs;
                    861:        u_long data_pa;
                    862:        int xlen;
                    863:
                    864:        /*
                    865:         * Get the DVMA mapping for this segment.
                    866:         * XXX - Should separate allocation and mapin.
                    867:         */
                    868:        data_pa = (u_long)(dh->dh_dvma - DVMA_BASE);
                    869:        if (data_pa & 1)
                    870:                panic("si_dma_start: bad pa=0x%lx", data_pa);
                    871:        xlen = ncr_sc->sc_datalen;
                    872:        xlen &= ~1;
                    873:        sc->sc_xlen = xlen;     /* XXX: or less... */
                    874:
                    875: #ifdef DEBUG
                    876:        if (si_debug & 2) {
                    877:                printf("si_dma_start: dh=%p, pa=0x%lx, xlen=%d\n",
                    878:                           dh, data_pa, xlen);
                    879:        }
                    880: #endif
                    881:
                    882:        /*
                    883:         * Set up the DMA controller.
                    884:         * Note that (dh->dh_len < sc_datalen)
                    885:         */
                    886:        si->si_csr &= ~SI_CSR_FIFO_RES;         /* active low */
                    887:        si->si_csr |= SI_CSR_FIFO_RES;
                    888:
                    889:        /* Set direction (send/recv) */
                    890:        if (dh->dh_flags & SIDH_OUT) {
                    891:                si->si_csr |= SI_CSR_SEND;
                    892:        } else {
                    893:                si->si_csr &= ~SI_CSR_SEND;
                    894:        }
                    895:
                    896:        if (data_pa & 2) {
                    897:                si->si_csr |= SI_CSR_BPCON;
                    898:        } else {
                    899:                si->si_csr &= ~SI_CSR_BPCON;
                    900:        }
                    901:
                    902:        si->dma_addrh = (u_short)(data_pa >> 16);
                    903:        si->dma_addrl = (u_short)(data_pa & 0xFFFF);
                    904:
                    905:        si->dma_counth = (u_short)(xlen >> 16);
                    906:        si->dma_countl = (u_short)(xlen & 0xFFFF);
                    907:
                    908: #if 1
                    909:        /* Set it anyway, even though dma_count hits it? */
                    910:        si->fifo_cnt_hi = (u_short)(xlen >> 16);
                    911:        si->fifo_count  = (u_short)(xlen & 0xFFFF);
                    912: #endif
                    913:
                    914: #ifdef DEBUG
                    915:        if (si->fifo_count != xlen) {
                    916:                printf("si_dma_start: Fifo_count=0x%x, xlen=0x%x\n",
                    917:                    si->fifo_count, xlen);
                    918: #ifdef DDB
                    919:                Debugger();
                    920: #endif
                    921:        }
                    922: #endif
                    923:
                    924:        /*
                    925:         * Acknowledge the phase change.  (After DMA setup!)
                    926:         * Put the SBIC into DMA mode, and start the transfer.
                    927:         */
                    928:        if (dh->dh_flags & SIDH_OUT) {
                    929:                *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
                    930:                SCI_CLR_INTR(ncr_sc);
                    931:                *ncr_sc->sci_icmd = SCI_ICMD_DATA;
                    932:                *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
                    933:                *ncr_sc->sci_dma_send = 0;      /* start it */
                    934:        } else {
                    935:                *ncr_sc->sci_tcmd = PHASE_DATA_IN;
                    936:                SCI_CLR_INTR(ncr_sc);
                    937:                *ncr_sc->sci_icmd = 0;
                    938:                *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
                    939:                *ncr_sc->sci_irecv = 0;         /* start it */
                    940:        }
                    941:
                    942:        /* Let'er rip! */
                    943:        si->si_csr |= SI_CSR_DMA_EN;
                    944:
                    945:        ncr_sc->sc_state |= NCR_DOINGDMA;
                    946:
                    947: #ifdef DEBUG
                    948:        if (si_debug & 2) {
                    949:                printf("si_dma_start: started, flags=0x%x\n",
                    950:                           ncr_sc->sc_state);
                    951:        }
                    952: #endif
                    953: }
                    954:
                    955:
                    956: void
                    957: si_vme_dma_stop(ncr_sc)
                    958:        struct ncr5380_softc *ncr_sc;
                    959: {
                    960:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                    961:        struct sci_req *sr = ncr_sc->sc_current;
                    962:        struct si_dma_handle *dh = sr->sr_dma_hand;
                    963:        volatile struct si_regs *si = sc->sc_regs;
                    964:        int resid, ntrans;
                    965:
                    966:        if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
                    967: #ifdef DEBUG
                    968:                printf("si_dma_stop: dma not running\n");
                    969: #endif
                    970:                return;
                    971:        }
                    972:        ncr_sc->sc_state &= ~NCR_DOINGDMA;
                    973:
                    974:        /* First, halt the DMA engine. */
                    975:        si->si_csr &= ~SI_CSR_DMA_EN;   /* VME only */
                    976:
                    977:        if (si->si_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) {
                    978:                printf("si: DMA error, csr=0x%x, reset\n", si->si_csr);
                    979:                sr->sr_xs->error = XS_DRIVER_STUFFUP;
                    980:                ncr_sc->sc_state |= NCR_ABORTING;
                    981:                si_reset_adapter(ncr_sc);
                    982:        }
                    983:
                    984:        /* Note that timeout may have set the error flag. */
                    985:        if (ncr_sc->sc_state & NCR_ABORTING)
                    986:                goto out;
                    987:
                    988:        /*
                    989:         * Now try to figure out how much actually transferred
                    990:         *
                    991:         * The fifo_count does not reflect how many bytes were
                    992:         * actually transferred for VME.
                    993:         *
                    994:         * SCSI-3 VME interface is a little funny on writes:
                    995:         * if we have a disconnect, the dma has overshot by
                    996:         * one byte and the resid needs to be incremented.
                    997:         * Only happens for partial transfers.
                    998:         * (Thanks to Matt Jacob)
                    999:         */
                   1000:
                   1001:        resid = si->fifo_count & 0xFFFF;
                   1002:        if (dh->dh_flags & SIDH_OUT)
                   1003:                if ((resid > 0) && (resid < sc->sc_xlen))
                   1004:                        resid++;
                   1005:        ntrans = sc->sc_xlen - resid;
                   1006:
                   1007: #ifdef DEBUG
                   1008:        if (si_debug & 2) {
                   1009:                printf("si_dma_stop: resid=0x%x ntrans=0x%x\n",
                   1010:                    resid, ntrans);
                   1011:        }
                   1012: #endif
                   1013:        if (ntrans < MIN_DMA_LEN) {
                   1014:                printf("si: fifo count: 0x%x\n", resid);
                   1015:                ncr_sc->sc_state |= NCR_ABORTING;
                   1016:                goto out;
                   1017:        }
                   1018:        if (ntrans > ncr_sc->sc_datalen)
                   1019:                panic("si_dma_stop: excess transfer");
                   1020:
                   1021:        /* Adjust data pointer */
                   1022:        ncr_sc->sc_dataptr += ntrans;
                   1023:        ncr_sc->sc_datalen -= ntrans;
                   1024:
                   1025: #ifdef DEBUG
                   1026:        if (si_debug & 2) {
                   1027:                printf("si_dma_stop: ntrans=0x%x\n", ntrans);
                   1028:        }
                   1029: #endif
                   1030:
                   1031:        /*
                   1032:         * After a read, we may need to clean-up
                   1033:         * "Left-over bytes" (yuck!)
                   1034:         */
                   1035:        if (((dh->dh_flags & SIDH_OUT) == 0) &&
                   1036:                ((si->si_csr & SI_CSR_LOB) != 0))
                   1037:        {
                   1038:                char *cp = ncr_sc->sc_dataptr;
                   1039: #ifdef DEBUG
                   1040:                printf("si: Got Left-over bytes!\n");
                   1041: #endif
                   1042:                if (si->si_csr & SI_CSR_BPCON) {
                   1043:                        /* have SI_CSR_BPCON */
                   1044:                        cp[-1] = (si->si_bprl & 0xff00) >> 8;
                   1045:                } else {
                   1046:                        switch (si->si_csr & SI_CSR_LOB) {
                   1047:                        case SI_CSR_LOB_THREE:
                   1048:                                cp[-3] = (si->si_bprh & 0xff00) >> 8;
                   1049:                                cp[-2] = (si->si_bprh & 0x00ff);
                   1050:                                cp[-1] = (si->si_bprl & 0xff00) >> 8;
                   1051:                                break;
                   1052:                        case SI_CSR_LOB_TWO:
                   1053:                                cp[-2] = (si->si_bprh & 0xff00) >> 8;
                   1054:                                cp[-1] = (si->si_bprh & 0x00ff);
                   1055:                                break;
                   1056:                        case SI_CSR_LOB_ONE:
                   1057:                                cp[-1] = (si->si_bprh & 0xff00) >> 8;
                   1058:                                break;
                   1059:                        }
                   1060:                }
                   1061:        }
                   1062:
                   1063: out:
                   1064:        si->dma_addrh = 0;
                   1065:        si->dma_addrl = 0;
                   1066:
                   1067:        si->dma_counth = 0;
                   1068:        si->dma_countl = 0;
                   1069:
                   1070:        si->fifo_cnt_hi = 0;
                   1071:        si->fifo_count  = 0;
                   1072:
                   1073:        /* Put SBIC back in PIO mode. */
                   1074:        *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);
                   1075:        *ncr_sc->sci_icmd = 0;
                   1076: }
                   1077:
                   1078:
                   1079: /*****************************************************************
                   1080:  * OBIO functions for DMA
                   1081:  ****************************************************************/
                   1082:
                   1083:
                   1084: /*
                   1085:  * This is called when the bus is going idle,
                   1086:  * so we want to enable the SBC interrupts.
                   1087:  * That is controlled by the DMA enable!
                   1088:  * Who would have guessed!
                   1089:  * What a NASTY trick!
                   1090:  *
                   1091:  * XXX THIS MIGHT NOT WORK RIGHT!
                   1092:  */
                   1093: void
                   1094: si_obio_intr_on(ncr_sc)
                   1095:        struct ncr5380_softc *ncr_sc;
                   1096: {
                   1097:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                   1098:        volatile struct si_regs *si = sc->sc_regs;
                   1099:
                   1100:        si_obio_dma_setup(ncr_sc);
                   1101:        si->sw_csr |= SI_CSR_DMA_EN;
                   1102: }
                   1103:
                   1104: /*
                   1105:  * This is called when the bus is idle and we are
                   1106:  * about to start playing with the SBC chip.
                   1107:  *
                   1108:  * XXX THIS MIGHT NOT WORK RIGHT!
                   1109:  */
                   1110: void
                   1111: si_obio_intr_off(ncr_sc)
                   1112:        struct ncr5380_softc *ncr_sc;
                   1113: {
                   1114:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                   1115:        volatile struct si_regs *si = sc->sc_regs;
                   1116:
                   1117:        si->sw_csr &= ~SI_CSR_DMA_EN;
                   1118: }
                   1119:
                   1120:
                   1121: /*
                   1122:  * This function is called during the COMMAND or MSG_IN phase
                   1123:  * that precedes a DATA_IN or DATA_OUT phase, in case we need
                   1124:  * to setup the DMA engine before the bus enters a DATA phase.
                   1125:  *
                   1126:  * On the OBIO version we just clear the DMA count and address
                   1127:  * here (to make sure it stays idle) and do the real setup
                   1128:  * later, in dma_start.
                   1129:  */
                   1130: void
                   1131: si_obio_dma_setup(ncr_sc)
                   1132:        struct ncr5380_softc *ncr_sc;
                   1133: {
                   1134:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                   1135:        volatile struct si_regs *si = sc->sc_regs;
                   1136:
                   1137:        /* No FIFO to reset on "sw". */
                   1138:
                   1139:        /* Set direction (assume recv here) */
                   1140:        si->sw_csr &= ~SI_CSR_SEND;
                   1141:
                   1142:        si->dma_addr = 0;
                   1143:        si->dma_count = 0;
                   1144: }
                   1145:
                   1146:
                   1147: void
                   1148: si_obio_dma_start(ncr_sc)
                   1149:        struct ncr5380_softc *ncr_sc;
                   1150: {
                   1151:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                   1152:        struct sci_req *sr = ncr_sc->sc_current;
                   1153:        struct si_dma_handle *dh = sr->sr_dma_hand;
                   1154:        volatile struct si_regs *si = sc->sc_regs;
                   1155:        u_long data_pa;
                   1156:        int xlen, adj, adjlen;
                   1157:
                   1158:        /*
                   1159:         * Get the DVMA mapping for this segment.
                   1160:         * XXX - Should separate allocation and mapin.
                   1161:         */
                   1162:        data_pa = (u_long)(dh->dh_dvma - DVMA_BASE);
                   1163:        if (data_pa & 1)
                   1164:                panic("si_dma_start: bad pa=0x%lx", data_pa);
                   1165:        xlen = ncr_sc->sc_datalen;
                   1166:        xlen &= ~1;
                   1167:        sc->sc_xlen = xlen;     /* XXX: or less... */
                   1168:
                   1169: #ifdef DEBUG
                   1170:        if (si_debug & 2) {
                   1171:                printf("si_dma_start: dh=%p, pa=0x%lx, xlen=%d\n",
                   1172:                    dh, data_pa, xlen);
                   1173:        }
                   1174: #endif
                   1175:
                   1176:        /*
                   1177:         * Set up the DMA controller.
                   1178:         * Note that (dh->dh_len < sc_datalen)
                   1179:         */
                   1180:
                   1181:        /* Set direction (send/recv) */
                   1182:        if (dh->dh_flags & SIDH_OUT) {
                   1183:                si->sw_csr |= SI_CSR_SEND;
                   1184:        } else {
                   1185:                si->sw_csr &= ~SI_CSR_SEND;
                   1186:        }
                   1187:
                   1188:        /*
                   1189:         * The "sw" needs longword aligned transfers.  We
                   1190:         * detect a shortword aligned transfer here, and adjust the
                   1191:         * DMA transfer by 2 bytes.  These two bytes are read/written
                   1192:         * in PIO mode just before the DMA is started.
                   1193:         */
                   1194:        adj = 0;
                   1195:        if (data_pa & 2) {
                   1196:                adj = 2;
                   1197: #ifdef DEBUG
                   1198:                if (si_debug & 2)
                   1199:                        printf("si_dma_start: adjusted up %d bytes\n", adj);
                   1200: #endif
                   1201:        }
                   1202:
                   1203:        /* We have to frob the address on the "sw". */
                   1204:        dh->dh_startingpa = (data_pa | 0xF00000);
                   1205:        si->dma_addr = (int)(dh->dh_startingpa + adj);
                   1206:        si->dma_count = (xlen - adj);
                   1207:
                   1208:        /*
                   1209:         * Acknowledge the phase change.  (After DMA setup!)
                   1210:         * Put the SBIC into DMA mode, and start the transfer.
                   1211:         */
                   1212:        if (dh->dh_flags & SIDH_OUT) {
                   1213:                *ncr_sc->sci_tcmd = PHASE_DATA_OUT;
                   1214:                if (adj) {
                   1215:                        adjlen = ncr5380_pio_out(ncr_sc, PHASE_DATA_OUT,
                   1216:                            adj, dh->dh_addr);
                   1217:                        if (adjlen != adj)
                   1218:                                printf("%s: bad outgoing adj, %d != %d\n",
                   1219:                                    ncr_sc->sc_dev.dv_xname, adjlen, adj);
                   1220:                }
                   1221:                SCI_CLR_INTR(ncr_sc);
                   1222:                *ncr_sc->sci_icmd = SCI_ICMD_DATA;
                   1223:                *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
                   1224:                *ncr_sc->sci_dma_send = 0;      /* start it */
                   1225:        } else {
                   1226:                *ncr_sc->sci_tcmd = PHASE_DATA_IN;
                   1227:                if (adj) {
                   1228:                        adjlen = ncr5380_pio_in(ncr_sc, PHASE_DATA_IN,
                   1229:                            adj, dh->dh_addr);
                   1230:                        if (adjlen != adj)
                   1231:                                printf("%s: bad incoming adj, %d != %d\n",
                   1232:                                    ncr_sc->sc_dev.dv_xname, adjlen, adj);
                   1233:                }
                   1234:                SCI_CLR_INTR(ncr_sc);
                   1235:                *ncr_sc->sci_icmd = 0;
                   1236:                *ncr_sc->sci_mode |= (SCI_MODE_DMA | SCI_MODE_DMA_IE);
                   1237:                *ncr_sc->sci_irecv = 0;         /* start it */
                   1238:        }
                   1239:
                   1240:        /* Let'er rip! */
                   1241:        si->sw_csr |= SI_CSR_DMA_EN;
                   1242:
                   1243:        ncr_sc->sc_state |= NCR_DOINGDMA;
                   1244:
                   1245: #ifdef DEBUG
                   1246:        if (si_debug & 2) {
                   1247:                printf("si_dma_start: started, flags=0x%x\n",
                   1248:                    ncr_sc->sc_state);
                   1249:        }
                   1250: #endif
                   1251: }
                   1252:
                   1253:
                   1254: #if (defined(DEBUG) || defined(DIAGNOSTIC)) && !defined(COUNT_SW_LEFTOVERS)
                   1255: #define COUNT_SW_LEFTOVERS
                   1256: #endif
                   1257: #ifdef COUNT_SW_LEFTOVERS
                   1258: /*
                   1259:  * Let's find out how often these occur.  Read these with DDB from time
                   1260:  * to time.
                   1261:  */
                   1262: int    sw_3_leftover = 0;
                   1263: int    sw_2_leftover = 0;
                   1264: int    sw_1_leftover = 0;
                   1265: int    sw_0_leftover = 0;
                   1266: #endif
                   1267:
                   1268: void
                   1269: si_obio_dma_stop(ncr_sc)
                   1270:        struct ncr5380_softc *ncr_sc;
                   1271: {
                   1272:        struct si_softc *sc = (struct si_softc *)ncr_sc;
                   1273:        struct sci_req *sr = ncr_sc->sc_current;
                   1274:        struct si_dma_handle *dh = sr->sr_dma_hand;
                   1275:        volatile struct si_regs *si = sc->sc_regs;
                   1276:        int ntrans = 0, Dma_addr;
                   1277:
                   1278:        if ((ncr_sc->sc_state & NCR_DOINGDMA) == 0) {
                   1279: #ifdef DEBUG
                   1280:                printf("si_dma_stop: dma not running\n");
                   1281: #endif
                   1282:                return;
                   1283:        }
                   1284:        ncr_sc->sc_state &= ~NCR_DOINGDMA;
                   1285:
                   1286:        /* First, halt the DMA engine. */
                   1287:        si->sw_csr &= ~SI_CSR_DMA_EN;
                   1288:
                   1289:        /*
                   1290:         * XXX HARDWARE BUG!
                   1291:         * Apparently, some early 4/100 SCSI controllers had a hardware
                   1292:         * bug that caused the controller to do illegal memory access.
                   1293:         * We see this as SI_CSR_DMA_BUS_ERR (makes sense).  To work around
                   1294:         * this, we simply need to clean up after ourselves ... there will
                   1295:         * be as many as 3 bytes left over.  Since we clean up "left-over"
                   1296:         * bytes on every read anyway, we just continue to chug along
                   1297:         * if SI_CSR_DMA_BUS_ERR is asserted.  (This was probably worked
                   1298:         * around in hardware later with the "left-over byte" indicator
                   1299:         * in the VME controller.)
                   1300:         */
                   1301: #if 0
                   1302:        if (si->sw_csr & (SI_CSR_DMA_CONFLICT | SI_CSR_DMA_BUS_ERR)) {
                   1303: #else
                   1304:        if (si->sw_csr & (SI_CSR_DMA_CONFLICT)) {
                   1305: #endif
                   1306:                printf("sw: DMA error, csr=0x%x, reset\n", si->sw_csr);
                   1307:                sr->sr_xs->error = XS_DRIVER_STUFFUP;
                   1308:                ncr_sc->sc_state |= NCR_ABORTING;
                   1309:                si_reset_adapter(ncr_sc);
                   1310:        }
                   1311:
                   1312:        /* Note that timeout may have set the error flag. */
                   1313:        if (ncr_sc->sc_state & NCR_ABORTING)
                   1314:                goto out;
                   1315:
                   1316:        /*
                   1317:         * Now try to figure out how much actually transferred
                   1318:         *
                   1319:         * The "sw" doesn't have a FIFO or a bcr, so we've stored
                   1320:         * the starting PA of the transfer in the DMA handle,
                   1321:         * and subtract it from the ending PA left in the dma_addr
                   1322:         * register.
                   1323:         */
                   1324:        Dma_addr = si->dma_addr;
                   1325:        ntrans = (Dma_addr - dh->dh_startingpa);
                   1326:
                   1327: #ifdef DEBUG
                   1328:        if (si_debug & 2) {
                   1329:                printf("si_dma_stop: ntrans=0x%x\n", ntrans);
                   1330:        }
                   1331: #endif
                   1332:
                   1333:        if (ntrans < MIN_DMA_LEN) {
                   1334:                printf("sw: short transfer\n");
                   1335:                ncr_sc->sc_state |= NCR_ABORTING;
                   1336:                goto out;
                   1337:        }
                   1338:
                   1339:        if (ntrans > ncr_sc->sc_datalen)
                   1340:                panic("si_dma_stop: excess transfer");
                   1341:
                   1342:        /* Adjust data pointer */
                   1343:        ncr_sc->sc_dataptr += ntrans;
                   1344:        ncr_sc->sc_datalen -= ntrans;
                   1345:
                   1346:        /*
                   1347:         * After a read, we may need to clean-up
                   1348:         * "Left-over bytes"  (yuck!)  The "sw" doesn't
                   1349:         * have a "left-over" indicator, so we have to so
                   1350:         * this no matter what.  Ick.
                   1351:         */
                   1352:        if ((dh->dh_flags & SIDH_OUT) == 0) {
                   1353:                char *cp = ncr_sc->sc_dataptr;
                   1354:
                   1355:                switch (Dma_addr & 3) {
                   1356:                case 3:
                   1357:                        cp[0] = (si->sw_bpr & 0xff000000) >> 24;
                   1358:                        cp[1] = (si->sw_bpr & 0x00ff0000) >> 16;
                   1359:                        cp[2] = (si->sw_bpr & 0x0000ff00) >> 8;
                   1360: #ifdef COUNT_SW_LEFTOVERS
                   1361:                        ++sw_3_leftover;
                   1362: #endif
                   1363:                        break;
                   1364:
                   1365:                case 2:
                   1366:                        cp[0] = (si->sw_bpr & 0xff000000) >> 24;
                   1367:                        cp[1] = (si->sw_bpr & 0x00ff0000) >> 16;
                   1368: #ifdef COUNT_SW_LEFTOVERS
                   1369:                        ++sw_2_leftover;
                   1370: #endif
                   1371:                        break;
                   1372:
                   1373:                case 1:
                   1374:                        cp[0] = (si->sw_bpr & 0xff000000) >> 24;
                   1375: #ifdef COUNT_SW_LEFTOVERS
                   1376:                        ++sw_1_leftover;
                   1377: #endif
                   1378:                        break;
                   1379:
                   1380: #ifdef COUNT_SW_LEFTOVERS
                   1381:                default:
                   1382:                        ++sw_0_leftover;
                   1383:                        break;
                   1384: #endif
                   1385:                }
                   1386:        }
                   1387:
                   1388:  out:
                   1389:        si->dma_addr = 0;
                   1390:        si->dma_count = 0;
                   1391:
                   1392:        /* Put SBIC back in PIO mode. */
                   1393:        *ncr_sc->sci_mode &= ~(SCI_MODE_DMA | SCI_MODE_DMA_IE);
                   1394:        *ncr_sc->sci_icmd = 0;
                   1395:
                   1396: #ifdef DEBUG
                   1397:        if (si_debug & 2) {
                   1398:                printf("si_dma_stop: ntrans=0x%x\n", ntrans);
                   1399:        }
                   1400: #endif
                   1401: }

CVSweb