[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

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