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

Annotation of sys/dev/sbus/esp_sbus.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: esp_sbus.c,v 1.20 2007/04/10 17:47:55 miod Exp $      */
        !             2: /*     $NetBSD: esp_sbus.c,v 1.14 2001/04/25 17:53:37 bouyer Exp $     */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
        !            10:  * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. All advertising materials mentioning features or use of this software
        !            21:  *    must display the following acknowledgement:
        !            22:  *     This product includes software developed by the NetBSD
        !            23:  *     Foundation, Inc. and its contributors.
        !            24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            25:  *    contributors may be used to endorse or promote products derived
        !            26:  *    from this software without specific prior written permission.
        !            27:  *
        !            28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            38:  * POSSIBILITY OF SUCH DAMAGE.
        !            39:  */
        !            40:
        !            41: #include <sys/types.h>
        !            42: #include <sys/param.h>
        !            43: #include <sys/systm.h>
        !            44: #include <sys/device.h>
        !            45: #include <sys/buf.h>
        !            46: #include <sys/malloc.h>
        !            47:
        !            48: #include <scsi/scsi_all.h>
        !            49: #include <scsi/scsiconf.h>
        !            50: #include <scsi/scsi_message.h>
        !            51:
        !            52: #include <machine/bus.h>
        !            53: #include <machine/intr.h>
        !            54: #include <machine/autoconf.h>
        !            55:
        !            56: #include <dev/ic/lsi64854reg.h>
        !            57: #include <dev/ic/lsi64854var.h>
        !            58:
        !            59: #include <dev/ic/ncr53c9xreg.h>
        !            60: #include <dev/ic/ncr53c9xvar.h>
        !            61:
        !            62: #include <dev/sbus/sbusvar.h>
        !            63:
        !            64: struct scsi_adapter esp_switch = {
        !            65:        ncr53c9x_scsi_cmd,
        !            66:        minphys,                /* no max at this level; handled by DMA code */
        !            67:        NULL,
        !            68:        NULL,
        !            69: };
        !            70:
        !            71: struct scsi_device esp_dev = {
        !            72:        NULL,                   /* Use default error handler */
        !            73:        NULL,                   /* have a queue, served by this */
        !            74:        NULL,                   /* have no async handler */
        !            75:        NULL,                   /* Use default 'done' routine */
        !            76: };
        !            77:
        !            78: /* #define ESP_SBUS_DEBUG */
        !            79:
        !            80: static int esp_unit_offset;
        !            81:
        !            82: struct esp_softc {
        !            83:        struct ncr53c9x_softc sc_ncr53c9x;      /* glue to MI code */
        !            84:
        !            85:        bus_space_tag_t sc_bustag;
        !            86:        bus_dma_tag_t   sc_dmatag;
        !            87:
        !            88:        bus_space_handle_t sc_reg;              /* the registers */
        !            89:        struct lsi64854_softc *sc_dma;          /* pointer to my dma */
        !            90:
        !            91:        int     sc_pri;                         /* SBUS priority */
        !            92: };
        !            93:
        !            94: void   espattach_sbus(struct device *, struct device *, void *);
        !            95: void   espattach_dma(struct device *, struct device *, void *);
        !            96: int    espmatch_sbus(struct device *, void *, void *);
        !            97:
        !            98:
        !            99: /* Linkup to the rest of the kernel */
        !           100: struct cfattach esp_sbus_ca = {
        !           101:        sizeof(struct esp_softc), espmatch_sbus, espattach_sbus
        !           102: };
        !           103: struct cfattach esp_dma_ca = {
        !           104:        sizeof(struct esp_softc), espmatch_sbus, espattach_dma
        !           105: };
        !           106:
        !           107: /*
        !           108:  * Functions and the switch for the MI code.
        !           109:  */
        !           110: static u_char  esp_read_reg(struct ncr53c9x_softc *, int);
        !           111: static void    esp_write_reg(struct ncr53c9x_softc *, int, u_char);
        !           112: static u_char  esp_rdreg1(struct ncr53c9x_softc *, int);
        !           113: static void    esp_wrreg1(struct ncr53c9x_softc *, int, u_char);
        !           114: static int     esp_dma_isintr(struct ncr53c9x_softc *);
        !           115: static void    esp_dma_reset(struct ncr53c9x_softc *);
        !           116: static int     esp_dma_intr(struct ncr53c9x_softc *);
        !           117: static int     esp_dma_setup(struct ncr53c9x_softc *, caddr_t *,
        !           118:                                    size_t *, int, size_t *);
        !           119: static void    esp_dma_go(struct ncr53c9x_softc *);
        !           120: static void    esp_dma_stop(struct ncr53c9x_softc *);
        !           121: static int     esp_dma_isactive(struct ncr53c9x_softc *);
        !           122:
        !           123: static struct ncr53c9x_glue esp_sbus_glue = {
        !           124:        esp_read_reg,
        !           125:        esp_write_reg,
        !           126:        esp_dma_isintr,
        !           127:        esp_dma_reset,
        !           128:        esp_dma_intr,
        !           129:        esp_dma_setup,
        !           130:        esp_dma_go,
        !           131:        esp_dma_stop,
        !           132:        esp_dma_isactive,
        !           133:        NULL,                   /* gl_clear_latched_intr */
        !           134: };
        !           135:
        !           136: static struct ncr53c9x_glue esp_sbus_glue1 = {
        !           137:        esp_rdreg1,
        !           138:        esp_wrreg1,
        !           139:        esp_dma_isintr,
        !           140:        esp_dma_reset,
        !           141:        esp_dma_intr,
        !           142:        esp_dma_setup,
        !           143:        esp_dma_go,
        !           144:        esp_dma_stop,
        !           145:        esp_dma_isactive,
        !           146:        NULL,                   /* gl_clear_latched_intr */
        !           147: };
        !           148:
        !           149: static void    espattach(struct esp_softc *, struct ncr53c9x_glue *);
        !           150:
        !           151: int
        !           152: espmatch_sbus(struct device *parent, void *vcf, void *aux)
        !           153: {
        !           154:        struct cfdata *cf = vcf;
        !           155:        int rv;
        !           156:        struct sbus_attach_args *sa = aux;
        !           157:
        !           158:        if (strcmp("SUNW,fas", sa->sa_name) == 0)
        !           159:                return 1;
        !           160:
        !           161:        rv = (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0 ||
        !           162:            strcmp("ptscII", sa->sa_name) == 0);
        !           163:        return (rv);
        !           164: }
        !           165:
        !           166: void
        !           167: espattach_sbus(struct device *parent, struct device *self, void *aux)
        !           168: {
        !           169:        struct esp_softc *esc = (void *)self;
        !           170:        struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
        !           171:        struct sbus_attach_args *sa = aux;
        !           172:        struct lsi64854_softc *lsc;
        !           173:        int burst, sbusburst;
        !           174:
        !           175:        esc->sc_bustag = sa->sa_bustag;
        !           176:        esc->sc_dmatag = sa->sa_dmatag;
        !           177:
        !           178:        sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
        !           179:        sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
        !           180:        if (sc->sc_freq < 0)
        !           181:                sc->sc_freq = sa->sa_frequency;
        !           182:
        !           183: #ifdef ESP_SBUS_DEBUG
        !           184:        printf("%s: espattach_sbus: sc_id %d, freq %d\n",
        !           185:               self->dv_xname, sc->sc_id, sc->sc_freq);
        !           186: #endif
        !           187:
        !           188:        if (strcmp("SUNW,fas", sa->sa_name) == 0) {
        !           189:                /*
        !           190:                 * offset searches for other esp/dma devices.
        !           191:                 */
        !           192:                esp_unit_offset++;
        !           193:
        !           194:                /*
        !           195:                 * fas has 2 register spaces: dma(lsi64854) and SCSI core (ncr53c9x)
        !           196:                 */
        !           197:                if (sa->sa_nreg != 2) {
        !           198:                        printf("%s: %d register spaces\n", self->dv_xname, sa->sa_nreg);
        !           199:                        return;
        !           200:                }
        !           201:
        !           202:                /*
        !           203:                 * allocate space for dma, in SUNW,fas there are no separate
        !           204:                 * dma device
        !           205:                 */
        !           206:                lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF, M_NOWAIT);
        !           207:
        !           208:                if (lsc == NULL) {
        !           209:                        printf("%s: out of memory (lsi64854_softc)\n",
        !           210:                               self->dv_xname);
        !           211:                        return;
        !           212:                }
        !           213:                esc->sc_dma = lsc;
        !           214:
        !           215:                lsc->sc_bustag = sa->sa_bustag;
        !           216:                lsc->sc_dmatag = sa->sa_dmatag;
        !           217:
        !           218:                bcopy(sc->sc_dev.dv_xname, lsc->sc_dev.dv_xname,
        !           219:                      sizeof (lsc->sc_dev.dv_xname));
        !           220:
        !           221:                /* Map dma registers */
        !           222:                if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
        !           223:                    sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
        !           224:                    0, 0, &lsc->sc_regs) != 0) {
        !           225:                        printf("%s: cannot map dma registers\n", self->dv_xname);
        !           226:                        return;
        !           227:                }
        !           228:
        !           229:                /*
        !           230:                 * XXX is this common(from bpp.c), the same in dma_sbus...etc.
        !           231:                 *
        !           232:                 * Get transfer burst size from PROM and plug it into the
        !           233:                 * controller registers. This is needed on the Sun4m; do
        !           234:                 * others need it too?
        !           235:                 */
        !           236:                sbusburst = ((struct sbus_softc *)parent)->sc_burst;
        !           237:                if (sbusburst == 0)
        !           238:                        sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
        !           239:
        !           240:                burst = getpropint(sa->sa_node, "burst-sizes", -1);
        !           241:
        !           242: #ifdef ESP_SBUS_DEBUG
        !           243:                printf("espattach_sbus: burst 0x%x, sbus 0x%x\n",
        !           244:                    burst, sbusburst);
        !           245: #endif
        !           246:
        !           247:                if (burst == -1)
        !           248:                        /* take SBus burst sizes */
        !           249:                        burst = sbusburst;
        !           250:
        !           251:                /* Clamp at parent's burst sizes */
        !           252:                burst &= sbusburst;
        !           253:                lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
        !           254:                    (burst & SBUS_BURST_16) ? 16 : 0;
        !           255:
        !           256:                lsc->sc_channel = L64854_CHANNEL_SCSI;
        !           257:                lsc->sc_client = sc;
        !           258:
        !           259:                lsi64854_attach(lsc);
        !           260:
        !           261:                /*
        !           262:                 * map SCSI core registers
        !           263:                 */
        !           264:                if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
        !           265:                    sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size,
        !           266:                    0, 0, &esc->sc_reg) != 0) {
        !           267:                        printf("%s: cannot map scsi core registers\n",
        !           268:                               self->dv_xname);
        !           269:                        return;
        !           270:                }
        !           271:
        !           272:                if (sa->sa_nintr == 0) {
        !           273:                        printf("%s: no interrupt property\n", self->dv_xname);
        !           274:                        return;
        !           275:                }
        !           276:
        !           277:                esc->sc_pri = sa->sa_pri;
        !           278:
        !           279:                printf("%s", self->dv_xname);
        !           280:                espattach(esc, &esp_sbus_glue);
        !           281:
        !           282:                return;
        !           283:        }
        !           284:
        !           285:        /*
        !           286:         * Find the DMA by poking around the dma device structures
        !           287:         *
        !           288:         * What happens here is that if the dma driver has not been
        !           289:         * configured, then this returns a NULL pointer. Then when the
        !           290:         * dma actually gets configured, it does the opposing test, and
        !           291:         * if the sc->sc_esp field in its softc is NULL, then tries to
        !           292:         * find the matching esp driver.
        !           293:         */
        !           294:        esc->sc_dma = (struct lsi64854_softc *)
        !           295:            getdevunit("dma", sc->sc_dev.dv_unit - esp_unit_offset);
        !           296:
        !           297:        /*
        !           298:         * and a back pointer to us, for DMA
        !           299:         */
        !           300:        if (esc->sc_dma)
        !           301:                esc->sc_dma->sc_client = sc;
        !           302:        else {
        !           303:                printf("\n");
        !           304:                panic("espattach: no dma found");
        !           305:        }
        !           306:
        !           307:        /*
        !           308:         * The `ESC' DMA chip must be reset before we can access
        !           309:         * the esp registers.
        !           310:         */
        !           311:        if (esc->sc_dma->sc_rev == DMAREV_ESC)
        !           312:                DMA_RESET(esc->sc_dma);
        !           313:
        !           314:        /*
        !           315:         * Map my registers in, if they aren't already in virtual
        !           316:         * address space.
        !           317:         */
        !           318:        if (sa->sa_npromvaddrs) {
        !           319:                if (bus_space_map(sa->sa_bustag, sa->sa_promvaddrs[0],
        !           320:                    sa->sa_size, BUS_SPACE_MAP_PROMADDRESS,
        !           321:                    &esc->sc_reg) != 0) {
        !           322:                        printf("%s @ sbus: cannot map registers\n",
        !           323:                                self->dv_xname);
        !           324:                        return;
        !           325:                }
        !           326:        } else {
        !           327:                if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
        !           328:                    sa->sa_offset, sa->sa_size, 0, 0, &esc->sc_reg) != 0) {
        !           329:                        printf("%s @ sbus: cannot map registers\n",
        !           330:                                self->dv_xname);
        !           331:                        return;
        !           332:                }
        !           333:        }
        !           334:
        !           335:        if (sa->sa_nintr == 0) {
        !           336:                /*
        !           337:                 * No interrupt properties: we quit; this might
        !           338:                 * happen on e.g. a Sparc X terminal.
        !           339:                 */
        !           340:                printf("\n%s: no interrupt property\n", self->dv_xname);
        !           341:                return;
        !           342:        }
        !           343:
        !           344:        esc->sc_pri = sa->sa_pri;
        !           345:
        !           346:        if (strcmp("ptscII", sa->sa_name) == 0) {
        !           347:                espattach(esc, &esp_sbus_glue1);
        !           348:        } else {
        !           349:                espattach(esc, &esp_sbus_glue);
        !           350:        }
        !           351: }
        !           352:
        !           353: void
        !           354: espattach_dma(struct device *parent, struct device *self, void *aux)
        !           355: {
        !           356:        struct esp_softc *esc = (void *)self;
        !           357:        struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
        !           358:        struct sbus_attach_args *sa = aux;
        !           359:
        !           360:        if (strcmp("ptscII", sa->sa_name) == 0) {
        !           361:                return;
        !           362:        }
        !           363:
        !           364:        esc->sc_bustag = sa->sa_bustag;
        !           365:        esc->sc_dmatag = sa->sa_dmatag;
        !           366:
        !           367:        sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
        !           368:        sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
        !           369:
        !           370:        esc->sc_dma = (struct lsi64854_softc *)parent;
        !           371:        esc->sc_dma->sc_client = sc;
        !           372:
        !           373:        /*
        !           374:         * Map my registers in, if they aren't already in virtual
        !           375:         * address space.
        !           376:         */
        !           377:        if (sa->sa_npromvaddrs) {
        !           378:                if (bus_space_map(sa->sa_bustag, sa->sa_promvaddrs[0],
        !           379:                    sa->sa_size /* ??? */, BUS_SPACE_MAP_PROMADDRESS,
        !           380:                    &esc->sc_reg) != 0) {
        !           381:                        printf("%s @ dma: cannot map registers\n",
        !           382:                                self->dv_xname);
        !           383:                        return;
        !           384:                }
        !           385:        } else {
        !           386:                if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset,
        !           387:                    sa->sa_size, 0, 0, &esc->sc_reg) != 0) {
        !           388:                        printf("%s @ dma: cannot map registers\n",
        !           389:                                self->dv_xname);
        !           390:                        return;
        !           391:                }
        !           392:        }
        !           393:
        !           394:        if (sa->sa_nintr == 0) {
        !           395:                /*
        !           396:                 * No interrupt properties: we quit; this might
        !           397:                 * happen on e.g. a Sparc X terminal.
        !           398:                 */
        !           399:                printf("\n%s: no interrupt property\n", self->dv_xname);
        !           400:                return;
        !           401:        }
        !           402:
        !           403:        esc->sc_pri = sa->sa_pri;
        !           404:
        !           405:        espattach(esc, &esp_sbus_glue);
        !           406: }
        !           407:
        !           408:
        !           409: /*
        !           410:  * Attach this instance, and then all the sub-devices
        !           411:  */
        !           412: void
        !           413: espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
        !           414: {
        !           415:        struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
        !           416:        void *icookie;
        !           417:        unsigned int uid = 0;
        !           418:
        !           419:        /*
        !           420:         * Set up glue for MI code early; we use some of it here.
        !           421:         */
        !           422:        sc->sc_glue = gluep;
        !           423:
        !           424:        /* gimme MHz */
        !           425:        sc->sc_freq /= 1000000;
        !           426:
        !           427:        /*
        !           428:         * XXX More of this should be in ncr53c9x_attach(), but
        !           429:         * XXX should we really poke around the chip that much in
        !           430:         * XXX the MI code?  Think about this more...
        !           431:         */
        !           432:
        !           433:        /*
        !           434:         * It is necessary to try to load the 2nd config register here,
        !           435:         * to find out what rev the esp chip is, else the ncr53c9x_reset
        !           436:         * will not set up the defaults correctly.
        !           437:         */
        !           438:        sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
        !           439:        sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
        !           440:        sc->sc_cfg3 = NCRCFG3_CDB;
        !           441:        NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
        !           442:
        !           443:        if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
        !           444:            (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
        !           445:                sc->sc_rev = NCR_VARIANT_ESP100;
        !           446:        } else {
        !           447:                sc->sc_cfg2 = NCRCFG2_SCSI2;
        !           448:                NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
        !           449:                sc->sc_cfg3 = 0;
        !           450:                NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
        !           451:                sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
        !           452:                NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
        !           453:                if (NCR_READ_REG(sc, NCR_CFG3) !=
        !           454:                    (NCRCFG3_CDB | NCRCFG3_FCLK)) {
        !           455:                        sc->sc_rev = NCR_VARIANT_ESP100A;
        !           456:                } else {
        !           457:                        /* NCRCFG2_FE enables > 64K transfers */
        !           458:                        sc->sc_cfg2 |= NCRCFG2_FE;
        !           459:                        sc->sc_cfg3 = 0;
        !           460:                        NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
        !           461:                        sc->sc_rev = NCR_VARIANT_ESP200;
        !           462:
        !           463:                        /* XXX spec says it's valid after power up or chip reset */
        !           464:                        uid = NCR_READ_REG(sc, NCR_UID);
        !           465:                        if (((uid & 0xf8) >> 3) == 0x0a) /* XXX */
        !           466:                                sc->sc_rev = NCR_VARIANT_FAS366;
        !           467:                }
        !           468:        }
        !           469:
        !           470: #ifdef ESP_SBUS_DEBUG
        !           471:        printf("espattach: revision %d, uid 0x%x\n", sc->sc_rev, uid);
        !           472: #endif
        !           473:
        !           474:        /*
        !           475:         * XXX minsync and maxxfer _should_ be set up in MI code,
        !           476:         * XXX but it appears to have some dependency on what sort
        !           477:         * XXX of DMA we're hooked up to, etc.
        !           478:         */
        !           479:
        !           480:        /*
        !           481:         * This is the value used to start sync negotiations
        !           482:         * Note that the NCR register "SYNCTP" is programmed
        !           483:         * in "clocks per byte", and has a minimum value of 4.
        !           484:         * The SCSI period used in negotiation is one-fourth
        !           485:         * of the time (in nanoseconds) needed to transfer one byte.
        !           486:         * Since the chip's clock is given in MHz, we have the following
        !           487:         * formula: 4 * period = (1000 / freq) * 4
        !           488:         */
        !           489:        sc->sc_minsync = 1000 / sc->sc_freq;
        !           490:
        !           491:        /*
        !           492:         * Alas, we must now modify the value a bit, because it's
        !           493:         * only valid when can switch on FASTCLK and FASTSCSI bits
        !           494:         * in config register 3...
        !           495:         */
        !           496:        switch (sc->sc_rev) {
        !           497:        case NCR_VARIANT_ESP100:
        !           498:                sc->sc_maxxfer = 64 * 1024;
        !           499:                sc->sc_minsync = 0;     /* No synch on old chip? */
        !           500:                break;
        !           501:
        !           502:        case NCR_VARIANT_ESP100A:
        !           503:                sc->sc_maxxfer = 64 * 1024;
        !           504:                /* Min clocks/byte is 5 */
        !           505:                sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
        !           506:                break;
        !           507:
        !           508:        case NCR_VARIANT_ESP200:
        !           509:        case NCR_VARIANT_FAS366:
        !           510:                sc->sc_maxxfer = 16 * 1024 * 1024;
        !           511:                /* XXX - do actually set FAST* bits */
        !           512:                break;
        !           513:        }
        !           514:
        !           515:        /* Establish interrupt channel */
        !           516:        icookie = bus_intr_establish(esc->sc_bustag, esc->sc_pri, IPL_BIO, 0,
        !           517:                                     ncr53c9x_intr, sc, sc->sc_dev.dv_xname);
        !           518:
        !           519:        /* Turn on target selection using the `dma' method */
        !           520:        if (sc->sc_rev != NCR_VARIANT_FAS366)
        !           521:                sc->sc_features |= NCR_F_DMASELECT;
        !           522:
        !           523:        /* Do the common parts of attachment. */
        !           524:        ncr53c9x_attach(sc, &esp_switch, &esp_dev);
        !           525: }
        !           526:
        !           527: /*
        !           528:  * Glue functions.
        !           529:  */
        !           530:
        !           531: #ifdef ESP_SBUS_DEBUG
        !           532: int esp_sbus_debug = 0;
        !           533:
        !           534: static struct {
        !           535:        char *r_name;
        !           536:        int   r_flag;
        !           537: } esp__read_regnames [] = {
        !           538:        { "TCL", 0},                    /* 0/00 */
        !           539:        { "TCM", 0},                    /* 1/04 */
        !           540:        { "FIFO", 0},                   /* 2/08 */
        !           541:        { "CMD", 0},                    /* 3/0c */
        !           542:        { "STAT", 0},                   /* 4/10 */
        !           543:        { "INTR", 0},                   /* 5/14 */
        !           544:        { "STEP", 0},                   /* 6/18 */
        !           545:        { "FFLAGS", 1},                 /* 7/1c */
        !           546:        { "CFG1", 1},                   /* 8/20 */
        !           547:        { "STAT2", 0},                  /* 9/24 */
        !           548:        { "CFG4", 1},                   /* a/28 */
        !           549:        { "CFG2", 1},                   /* b/2c */
        !           550:        { "CFG3", 1},                   /* c/30 */
        !           551:        { "-none", 1},                  /* d/34 */
        !           552:        { "TCH", 1},                    /* e/38 */
        !           553:        { "TCX", 1},                    /* f/3c */
        !           554: };
        !           555:
        !           556: static struct {
        !           557:        char *r_name;
        !           558:        int   r_flag;
        !           559: } esp__write_regnames[] = {
        !           560:        { "TCL", 1},                    /* 0/00 */
        !           561:        { "TCM", 1},                    /* 1/04 */
        !           562:        { "FIFO", 0},                   /* 2/08 */
        !           563:        { "CMD", 0},                    /* 3/0c */
        !           564:        { "SELID", 1},                  /* 4/10 */
        !           565:        { "TIMEOUT", 1},                /* 5/14 */
        !           566:        { "SYNCTP", 1},                 /* 6/18 */
        !           567:        { "SYNCOFF", 1},                /* 7/1c */
        !           568:        { "CFG1", 1},                   /* 8/20 */
        !           569:        { "CCF", 1},                    /* 9/24 */
        !           570:        { "TEST", 1},                   /* a/28 */
        !           571:        { "CFG2", 1},                   /* b/2c */
        !           572:        { "CFG3", 1},                   /* c/30 */
        !           573:        { "-none", 1},                  /* d/34 */
        !           574:        { "TCH", 1},                    /* e/38 */
        !           575:        { "TCX", 1},                    /* f/3c */
        !           576: };
        !           577: #endif
        !           578:
        !           579: u_char
        !           580: esp_read_reg(struct ncr53c9x_softc *sc, int reg)
        !           581: {
        !           582:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           583:        u_char v;
        !           584:
        !           585:        v = bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg * 4);
        !           586: #ifdef ESP_SBUS_DEBUG
        !           587:        if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
        !           588:                printf("RD:%x <%s> %x\n", reg * 4,
        !           589:                    ((unsigned)reg < 0x10) ? esp__read_regnames[reg].r_name : "<***>", v);
        !           590: #endif
        !           591:        return v;
        !           592: }
        !           593:
        !           594: void
        !           595: esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v)
        !           596: {
        !           597:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           598:
        !           599: #ifdef ESP_SBUS_DEBUG
        !           600:        if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
        !           601:                printf("WR:%x <%s> %x\n", reg * 4,
        !           602:                    ((unsigned)reg < 0x10) ? esp__write_regnames[reg].r_name : "<***>", v);
        !           603: #endif
        !           604:        bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg * 4, v);
        !           605: }
        !           606:
        !           607: u_char
        !           608: esp_rdreg1(struct ncr53c9x_softc *sc, int reg)
        !           609: {
        !           610:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           611:
        !           612:        return (bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg));
        !           613: }
        !           614:
        !           615: void
        !           616: esp_wrreg1(struct ncr53c9x_softc *sc, int reg, u_char v)
        !           617: {
        !           618:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           619:
        !           620:        bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg, v);
        !           621: }
        !           622:
        !           623: int
        !           624: esp_dma_isintr(struct ncr53c9x_softc *sc)
        !           625: {
        !           626:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           627:
        !           628:        return (DMA_ISINTR(esc->sc_dma));
        !           629: }
        !           630:
        !           631: void
        !           632: esp_dma_reset(struct ncr53c9x_softc *sc)
        !           633: {
        !           634:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           635:
        !           636:        DMA_RESET(esc->sc_dma);
        !           637: }
        !           638:
        !           639: int
        !           640: esp_dma_intr(struct ncr53c9x_softc *sc)
        !           641: {
        !           642:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           643:
        !           644:        return (DMA_INTR(esc->sc_dma));
        !           645: }
        !           646:
        !           647: int
        !           648: esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len,
        !           649:     int datain, size_t *dmasize)
        !           650: {
        !           651:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           652:
        !           653:        return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
        !           654: }
        !           655:
        !           656: void
        !           657: esp_dma_go(struct ncr53c9x_softc *sc)
        !           658: {
        !           659:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           660:
        !           661:        DMA_GO(esc->sc_dma);
        !           662: }
        !           663:
        !           664: void
        !           665: esp_dma_stop(struct ncr53c9x_softc *sc)
        !           666: {
        !           667:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           668:        u_int32_t csr;
        !           669:
        !           670:        csr = L64854_GCSR(esc->sc_dma);
        !           671:        csr &= ~D_EN_DMA;
        !           672:        L64854_SCSR(esc->sc_dma, csr);
        !           673: }
        !           674:
        !           675: int
        !           676: esp_dma_isactive(struct ncr53c9x_softc *sc)
        !           677: {
        !           678:        struct esp_softc *esc = (struct esp_softc *)sc;
        !           679:
        !           680:        return (DMA_ISACTIVE(esc->sc_dma));
        !           681: }
        !           682:
        !           683: #if defined(DDB) && defined(notyet)
        !           684: #include <machine/db_machdep.h>
        !           685: #include <ddb/db_output.h>
        !           686:
        !           687: void db_esp(db_expr_t, int, db_expr_t, char *);
        !           688:
        !           689: void
        !           690: db_esp(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
        !           691: {
        !           692:        struct ncr53c9x_softc *sc;
        !           693:        struct ncr53c9x_ecb *ecb;
        !           694:        struct ncr53c9x_linfo *li;
        !           695:        int u, t, i;
        !           696:
        !           697:        for (u=0; u<10; u++) {
        !           698:                sc = (struct ncr53c9x_softc *)
        !           699:                        getdevunit("esp", u);
        !           700:                if (!sc) continue;
        !           701:
        !           702:                db_printf("esp%d: nexus %p phase %x prev %x dp %p dleft %lx ify %x\n",
        !           703:                          u, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase,
        !           704:                          sc->sc_dp, sc->sc_dleft, sc->sc_msgify);
        !           705:                db_printf("\tmsgout %x msgpriq %x msgin %x:%x:%x:%x:%x\n",
        !           706:                          sc->sc_msgout, sc->sc_msgpriq, sc->sc_imess[0],
        !           707:                          sc->sc_imess[1], sc->sc_imess[2], sc->sc_imess[3],
        !           708:                          sc->sc_imess[0]);
        !           709:                db_printf("ready: ");
        !           710:                TAILQ_FOREACH(ecb, &sc->ready_list, chain) {
        !           711:                        db_printf("ecb %p ", ecb);
        !           712:                        if (ecb == TAILQ_NEXT(ecb, chain)) {
        !           713:                                db_printf("\nWARNING: tailq loop on ecb %p", ecb);
        !           714:                                break;
        !           715:                        }
        !           716:                }
        !           717:                db_printf("\n");
        !           718:
        !           719:                for (t=0; t<NCR_NTARG; t++) {
        !           720:                        LIST_FOREACH(li, &sc->sc_tinfo[t].luns, link) {
        !           721:                                db_printf("t%d lun %d untagged %p busy %d used %x\n",
        !           722:                                          t, (int)li->lun, li->untagged, li->busy,
        !           723:                                          li->used);
        !           724:                                for (i=0; i<256; i++)
        !           725:                                        if ((ecb = li->queued[i])) {
        !           726:                                                db_printf("ecb %p tag %x\n", ecb, i);
        !           727:                                        }
        !           728:                        }
        !           729:                }
        !           730:        }
        !           731: }
        !           732: #endif
        !           733:

CVSweb