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

Annotation of sys/arch/sparc64/dev/schizo.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: schizo.c,v 1.47 2007/02/23 22:15:36 kettenis Exp $    */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2002 Jason L. Wright (jason@thought.net)
        !             5:  * Copyright (c) 2003 Henric Jungheim
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  *
        !            17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            18:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            19:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            20:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            21:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            22:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            23:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            24:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            25:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            26:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            27:  * POSSIBILITY OF SUCH DAMAGE.
        !            28:  */
        !            29:
        !            30: #include <sys/param.h>
        !            31: #include <sys/device.h>
        !            32: #include <sys/errno.h>
        !            33: #include <sys/extent.h>
        !            34: #include <sys/malloc.h>
        !            35: #include <sys/systm.h>
        !            36: #include <sys/time.h>
        !            37: #include <sys/reboot.h>
        !            38:
        !            39: #define _SPARC_BUS_DMA_PRIVATE
        !            40: #include <machine/bus.h>
        !            41: #include <machine/autoconf.h>
        !            42: #include <machine/psl.h>
        !            43:
        !            44: #include <dev/pci/pcivar.h>
        !            45: #include <dev/pci/pcireg.h>
        !            46:
        !            47: #include <sparc64/dev/iommureg.h>
        !            48: #include <sparc64/dev/iommuvar.h>
        !            49: #include <sparc64/dev/schizoreg.h>
        !            50: #include <sparc64/dev/schizovar.h>
        !            51: #include <sparc64/sparc64/cache.h>
        !            52:
        !            53: #ifdef DEBUG
        !            54: #define SDB_PROM        0x01
        !            55: #define SDB_BUSMAP      0x02
        !            56: #define SDB_INTR        0x04
        !            57: #define SDB_CONF        0x08
        !            58: int schizo_debug = ~0;
        !            59: #define DPRINTF(l, s)   do { if (schizo_debug & l) printf s; } while (0)
        !            60: #else
        !            61: #define DPRINTF(l, s)
        !            62: #endif
        !            63:
        !            64: extern struct sparc_pci_chipset _sparc_pci_chipset;
        !            65:
        !            66: int schizo_match(struct device *, void *, void *);
        !            67: void schizo_attach(struct device *, struct device *, void *);
        !            68: void schizo_init(struct schizo_softc *, int);
        !            69: void schizo_init_iommu(struct schizo_softc *, struct schizo_pbm *);
        !            70: int schizo_print(void *, const char *);
        !            71:
        !            72: void schizo_set_intr(struct schizo_softc *, struct schizo_pbm *, int,
        !            73:     int (*handler)(void *), void *, int, char *);
        !            74: int schizo_ue(void *);
        !            75: int schizo_ce(void *);
        !            76: int schizo_safari_error(void *);
        !            77: int schizo_pci_error(void *);
        !            78:
        !            79: pci_chipset_tag_t schizo_alloc_chipset(struct schizo_pbm *, int,
        !            80:     pci_chipset_tag_t);
        !            81: bus_space_tag_t schizo_alloc_mem_tag(struct schizo_pbm *);
        !            82: bus_space_tag_t schizo_alloc_io_tag(struct schizo_pbm *);
        !            83: bus_space_tag_t schizo_alloc_config_tag(struct schizo_pbm *);
        !            84: bus_space_tag_t _schizo_alloc_bus_tag(struct schizo_pbm *, const char *,
        !            85:     int, int, int);
        !            86: bus_dma_tag_t schizo_alloc_dma_tag(struct schizo_pbm *);
        !            87:
        !            88: paddr_t schizo_bus_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
        !            89: int schizo_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
        !            90: int _schizo_bus_map(bus_space_tag_t, bus_space_tag_t, bus_addr_t,
        !            91:     bus_size_t, int, bus_space_handle_t *);
        !            92: void *_schizo_intr_establish(bus_space_tag_t, bus_space_tag_t, int, int, int,
        !            93:     int (*)(void *), void *, const char *);
        !            94: paddr_t _schizo_bus_mmap(bus_space_tag_t, bus_space_tag_t, bus_addr_t, off_t, int, int);
        !            95:
        !            96: int schizo_dmamap_create(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, int,
        !            97:     bus_size_t, bus_size_t, int, bus_dmamap_t *);
        !            98:
        !            99: int
        !           100: schizo_match(struct device *parent, void *match, void *aux)
        !           101: {
        !           102:        struct mainbus_attach_args *ma = aux;
        !           103:        char *str;
        !           104:
        !           105:        if (strcmp(ma->ma_name, "pci") != 0)
        !           106:                return (0);
        !           107:
        !           108:        str = getpropstring(ma->ma_node, "model");
        !           109:        if (strcmp(str, "schizo") == 0)
        !           110:                return (1);
        !           111:
        !           112:        str = getpropstring(ma->ma_node, "compatible");
        !           113:        if (strcmp(str, "pci108e,8001") == 0)
        !           114:                return (1);
        !           115:        if (strcmp(str, "pci108e,a801") == 0)           /* Tomatillo */
        !           116:                return (1);
        !           117:
        !           118:        return (0);
        !           119: }
        !           120:
        !           121: void
        !           122: schizo_attach(struct device *parent, struct device *self, void *aux)
        !           123: {
        !           124:        struct schizo_softc *sc = (struct schizo_softc *)self;
        !           125:        struct mainbus_attach_args *ma = aux;
        !           126:        int busa;
        !           127:        char *str;
        !           128:
        !           129:        str = getpropstring(ma->ma_node, "compatible");
        !           130:        if (strcmp(str, "pci108e,a801") == 0)
        !           131:                sc->sc_tomatillo = 1;
        !           132:
        !           133:        sc->sc_node = ma->ma_node;
        !           134:        sc->sc_dmat = ma->ma_dmatag;
        !           135:        sc->sc_bust = ma->ma_bustag;
        !           136:        sc->sc_ctrl = ma->ma_reg[1].ur_paddr - 0x10000UL;
        !           137:        sc->sc_ign = INTIGN(ma->ma_upaid << INTMAP_IGN_SHIFT);
        !           138:
        !           139:        if ((ma->ma_reg[0].ur_paddr & 0x00700000) == 0x00600000)
        !           140:                busa = 1;
        !           141:        else
        !           142:                busa = 0;
        !           143:
        !           144:        if (bus_space_map(sc->sc_bust, sc->sc_ctrl,
        !           145:            sizeof(struct schizo_regs), 0, &sc->sc_ctrlh)) {
        !           146:                printf(": failed to map registers\n");
        !           147:                return;
        !           148:        }
        !           149:
        !           150:        /* enable schizo ecc error interrupts */
        !           151:        schizo_write(sc, SCZ_ECCCTRL, schizo_read(sc, SCZ_ECCCTRL) |
        !           152:            SCZ_ECCCTRL_EE_INTEN | SCZ_ECCCTRL_UE_INTEN |
        !           153:            SCZ_ECCCTRL_CE_INTEN);
        !           154:
        !           155:        schizo_init(sc, busa);
        !           156: }
        !           157:
        !           158: void
        !           159: schizo_init(struct schizo_softc *sc, int busa)
        !           160: {
        !           161:        struct schizo_pbm *pbm;
        !           162:        struct pcibus_attach_args pba;
        !           163:        int *busranges = NULL, nranges;
        !           164:        u_int64_t match, reg;
        !           165:
        !           166:        pbm = (struct schizo_pbm *)malloc(sizeof(*pbm), M_DEVBUF, M_NOWAIT);
        !           167:        if (pbm == NULL)
        !           168:                panic("schizo: can't alloc schizo pbm");
        !           169:        bzero(pbm, sizeof(*pbm));
        !           170:
        !           171:        pbm->sp_sc = sc;
        !           172:        pbm->sp_bus_a = busa;
        !           173:        pbm->sp_regt = sc->sc_bust;
        !           174:
        !           175:        if (getprop(sc->sc_node, "ranges", sizeof(struct schizo_range),
        !           176:            &pbm->sp_nrange, (void **)&pbm->sp_range))
        !           177:                panic("schizo: can't get ranges");
        !           178:
        !           179:        if (getprop(sc->sc_node, "bus-range", sizeof(int), &nranges,
        !           180:            (void **)&busranges))
        !           181:                panic("schizo: can't get bus-range");
        !           182:
        !           183:        printf(": \"%s\", version %d, ign %x, bus %c %d to %d\n",
        !           184:            sc->sc_tomatillo ? "Tomatillo" : "Schizo",
        !           185:            getpropint(sc->sc_node, "version#", 0), sc->sc_ign,
        !           186:            busa ? 'A' : 'B', busranges[0], busranges[1]);
        !           187:
        !           188:        if (bus_space_subregion(pbm->sp_regt, sc->sc_ctrlh,
        !           189:            busa ? offsetof(struct schizo_regs, pbm_a) :
        !           190:            offsetof(struct schizo_regs, pbm_b),
        !           191:            sizeof(struct schizo_pbm_regs),
        !           192:            &pbm->sp_regh)) {
        !           193:                panic("schizo: unable to create PBM handle");
        !           194:        }
        !           195:
        !           196:        printf("%s: ", sc->sc_dv.dv_xname);
        !           197:        schizo_init_iommu(sc, pbm);
        !           198:
        !           199:        match = schizo_read(sc, busa ? SCZ_PCIA_IO_MATCH : SCZ_PCIB_IO_MATCH);
        !           200:        pbm->sp_confpaddr = match & ~0x8000000000000000UL;
        !           201:
        !           202:        pbm->sp_memt = schizo_alloc_mem_tag(pbm);
        !           203:        pbm->sp_iot = schizo_alloc_io_tag(pbm);
        !           204:        pbm->sp_cfgt = schizo_alloc_config_tag(pbm);
        !           205:        pbm->sp_dmat = schizo_alloc_dma_tag(pbm);
        !           206:
        !           207:        if (bus_space_map(pbm->sp_cfgt, 0, 0x1000000, 0, &pbm->sp_cfgh))
        !           208:                panic("schizo: could not map config space");
        !           209:
        !           210:        pbm->sp_pc = schizo_alloc_chipset(pbm, sc->sc_node,
        !           211:            &_sparc_pci_chipset);
        !           212:
        !           213:        pbm->sp_pc->bustag = pbm->sp_cfgt;
        !           214:        pbm->sp_pc->bushandle = pbm->sp_cfgh;
        !           215:
        !           216:        pba.pba_busname = "pci";
        !           217:        pba.pba_domain = pci_ndomains++;
        !           218:        pba.pba_bus = busranges[0];
        !           219:        pba.pba_bridgetag = NULL;
        !           220:        pba.pba_pc = pbm->sp_pc;
        !           221: #if 0
        !           222:        pba.pba_flags = pbm->sp_flags;
        !           223: #endif
        !           224:        pba.pba_dmat = pbm->sp_dmat;
        !           225:        pba.pba_memt = pbm->sp_memt;
        !           226:        pba.pba_iot = pbm->sp_iot;
        !           227:        pba.pba_pc->intr_map = schizo_intr_map;
        !           228:
        !           229:        free(busranges, M_DEVBUF);
        !           230:
        !           231:        schizo_pbm_write(pbm, SCZ_PCI_INTR_RETRY, 5);
        !           232:
        !           233:        /* clear out the bus errors */
        !           234:        schizo_pbm_write(pbm, SCZ_PCI_CTRL, schizo_pbm_read(pbm, SCZ_PCI_CTRL));
        !           235:        schizo_pbm_write(pbm, SCZ_PCI_AFSR, schizo_pbm_read(pbm, SCZ_PCI_AFSR));
        !           236:        schizo_cfg_write(pbm, PCI_COMMAND_STATUS_REG,
        !           237:            schizo_cfg_read(pbm, PCI_COMMAND_STATUS_REG));
        !           238:
        !           239:        reg = schizo_pbm_read(pbm, SCZ_PCI_CTRL);
        !           240:        /* enable/disable error interrupts and arbiter */
        !           241:        reg |= SCZ_PCICTRL_EEN | SCZ_PCICTRL_MMU_INT | SCZ_PCICTRL_ARB;
        !           242:        reg &= ~SCZ_PCICTRL_SBH_INT;
        !           243:        schizo_pbm_write(pbm, SCZ_PCI_CTRL, reg);
        !           244:
        !           245:        reg = schizo_pbm_read(pbm, SCZ_PCI_DIAG);
        !           246:        reg &= ~(SCZ_PCIDIAG_D_RTRYARB | SCZ_PCIDIAG_D_RETRY |
        !           247:            SCZ_PCIDIAG_D_INTSYNC);
        !           248:        schizo_pbm_write(pbm, SCZ_PCI_DIAG, reg);
        !           249:
        !           250:        if (busa)
        !           251:                schizo_set_intr(sc, pbm, PIL_HIGH, schizo_pci_error,
        !           252:                   pbm, SCZ_PCIERR_A_INO, "pci_a");
        !           253:        else
        !           254:                schizo_set_intr(sc, pbm, PIL_HIGH, schizo_pci_error,
        !           255:                   pbm, SCZ_PCIERR_B_INO, "pci_b");
        !           256:
        !           257:        /* double mapped */
        !           258:        schizo_set_intr(sc, pbm, PIL_HIGH, schizo_ue, sc, SCZ_UE_INO,
        !           259:            "ue");
        !           260:        schizo_set_intr(sc, pbm, PIL_HIGH, schizo_ce, sc, SCZ_CE_INO,
        !           261:            "ce");
        !           262:        schizo_set_intr(sc, pbm, PIL_HIGH, schizo_safari_error, sc,
        !           263:            SCZ_SERR_INO, "safari");
        !           264:
        !           265:        config_found(&sc->sc_dv, &pba, schizo_print);
        !           266: }
        !           267:
        !           268: int
        !           269: schizo_ue(void *vsc)
        !           270: {
        !           271:        struct schizo_softc *sc = vsc;
        !           272:
        !           273:        panic("%s: uncorrectable error", sc->sc_dv.dv_xname);
        !           274:        return (1);
        !           275: }
        !           276:
        !           277: int
        !           278: schizo_ce(void *vsc)
        !           279: {
        !           280:        struct schizo_softc *sc = vsc;
        !           281:
        !           282:        panic("%s: correctable error", sc->sc_dv.dv_xname);
        !           283:        return (1);
        !           284: }
        !           285:
        !           286: int
        !           287: schizo_pci_error(void *vpbm)
        !           288: {
        !           289:        struct schizo_pbm *sp = vpbm;
        !           290:        struct schizo_softc *sc = sp->sp_sc;
        !           291:        u_int64_t afsr, afar, ctrl;
        !           292:        u_int32_t csr;
        !           293:
        !           294:        afsr = schizo_pbm_read(sp, SCZ_PCI_AFSR);
        !           295:        afar = schizo_pbm_read(sp, SCZ_PCI_AFAR);
        !           296:        ctrl = schizo_pbm_read(sp, SCZ_PCI_CTRL);
        !           297:        csr = schizo_cfg_read(sp, PCI_COMMAND_STATUS_REG);
        !           298:
        !           299:        printf("%s: pci bus %c error\n", sc->sc_dv.dv_xname,
        !           300:            sp->sp_bus_a ? 'A' : 'B');
        !           301:
        !           302:        printf("PCIAFSR=%lb\n", afsr, SCZ_PCIAFSR_BITS);
        !           303:        printf("PCIAFAR=%lx\n", afar);
        !           304:        printf("PCICTRL=%lb\n", ctrl, SCZ_PCICTRL_BITS);
        !           305:        printf("PCICSR=%lb\n", csr, PCI_COMMAND_STATUS_BITS);
        !           306:
        !           307:        if (ctrl & SCZ_PCICTRL_MMU_ERR) {
        !           308:                u_int32_t ctrl, tfar;
        !           309:
        !           310:                ctrl = schizo_pbm_read(sp, SCZ_PCI_IOMMU_CTRL);
        !           311:                printf("IOMMUCTRL=%lx\n", ctrl);
        !           312:
        !           313:                if ((ctrl & TOM_IOMMU_ERR) == 0)
        !           314:                        goto clear_error;
        !           315:
        !           316:                if (sc->sc_tomatillo) {
        !           317:                        tfar = schizo_pbm_read(sp, TOM_PCI_IOMMU_TFAR);
        !           318:                        printf("IOMMUTFAR=%lx\n", tfar);
        !           319:                }
        !           320:
        !           321:                /* These are non-fatal if target abort was signalled. */
        !           322:                if ((ctrl & TOM_IOMMU_ERR_MASK) == TOM_IOMMU_INV_ERR ||
        !           323:                    ctrl & TOM_IOMMU_ILLTSBTBW_ERR ||
        !           324:                    ctrl & TOM_IOMMU_BADVA_ERR) {
        !           325:                        if (csr & PCI_STATUS_TARGET_TARGET_ABORT) {
        !           326:                                schizo_pbm_write(sp, SCZ_PCI_IOMMU_CTRL, ctrl);
        !           327:                                goto clear_error;
        !           328:                        }
        !           329:                }
        !           330:        }
        !           331:
        !           332:        panic("%s: fatal", sc->sc_dv.dv_xname);
        !           333:
        !           334:  clear_error:
        !           335:        schizo_cfg_write(sp, PCI_COMMAND_STATUS_REG, csr);
        !           336:        schizo_pbm_write(sp, SCZ_PCI_CTRL, ctrl);
        !           337:        schizo_pbm_write(sp, SCZ_PCI_AFSR, afsr);
        !           338:        return (1);
        !           339: }
        !           340:
        !           341: int
        !           342: schizo_safari_error(void *vsc)
        !           343: {
        !           344:        struct schizo_softc *sc = vsc;
        !           345:
        !           346:        printf("%s: safari error\n", sc->sc_dv.dv_xname);
        !           347:
        !           348:        printf("ERRLOG=%lx\n", schizo_read(sc, SCZ_SAFARI_ERRLOG));
        !           349:
        !           350:        panic("%s: fatal", sc->sc_dv.dv_xname);
        !           351:        return (1);
        !           352: }
        !           353:
        !           354: void
        !           355: schizo_init_iommu(struct schizo_softc *sc, struct schizo_pbm *pbm)
        !           356: {
        !           357:        struct iommu_state *is = &pbm->sp_is;
        !           358:        int *vdma = NULL, nitem, tsbsize = 7;
        !           359:        u_int32_t iobase = -1;
        !           360:        vaddr_t va;
        !           361:        char *name;
        !           362:
        !           363:        va = (vaddr_t)pbm->sp_flush[0x40];
        !           364:
        !           365:        is->is_bustag = pbm->sp_regt;
        !           366:
        !           367:        if (bus_space_subregion(is->is_bustag, pbm->sp_regh,
        !           368:            offsetof(struct schizo_pbm_regs, iommu),
        !           369:            sizeof(struct iommureg), &is->is_iommu)) {
        !           370:                panic("schizo: unable to create iommu handle");
        !           371:        }
        !           372:
        !           373:        is->is_sb[0] = &pbm->sp_sb;
        !           374:        is->is_sb[0]->sb_bustag = is->is_bustag;
        !           375:        is->is_sb[0]->sb_flush = (void *)(va & ~0x3f);
        !           376:
        !           377:        if (bus_space_subregion(is->is_bustag, pbm->sp_regh,
        !           378:            offsetof(struct schizo_pbm_regs, strbuf),
        !           379:            sizeof(struct iommu_strbuf), &is->is_sb[0]->sb_sb)) {
        !           380:                panic("schizo: unable to create streaming buffer handle");
        !           381:                is->is_sb[0]->sb_flush = NULL;
        !           382:        }
        !           383:
        !           384: #if 1
        !           385:        /* XXX disable the streaming buffers for now */
        !           386:        bus_space_write_8(is->is_bustag, is->is_sb[0]->sb_sb,
        !           387:            STRBUFREG(strbuf_ctl),
        !           388:            bus_space_read_8(is->is_bustag, is->is_sb[0]->sb_sb,
        !           389:                STRBUFREG(strbuf_ctl)) & ~STRBUF_EN);
        !           390:        is->is_sb[0]->sb_flush = NULL;
        !           391: #endif
        !           392:
        !           393:        name = (char *)malloc(32, M_DEVBUF, M_NOWAIT);
        !           394:        if (name == NULL)
        !           395:                panic("couldn't malloc iommu name");
        !           396:        snprintf(name, 32, "%s dvma", sc->sc_dv.dv_xname);
        !           397:
        !           398:        /*
        !           399:         * Separate the men from the boys.  If the `virtual-dma'
        !           400:         * property exists, use it.
        !           401:         */
        !           402:        if (!getprop(sc->sc_node, "virtual-dma", sizeof(vdma), &nitem,
        !           403:            (void **)&vdma)) {
        !           404:                /* Damn.  Gotta use these values. */
        !           405:                iobase = vdma[0];
        !           406: #define        TSBCASE(x)      case 1 << ((x) + 23): tsbsize = (x); break
        !           407:                switch (vdma[1]) {
        !           408:                        TSBCASE(1); TSBCASE(2); TSBCASE(3);
        !           409:                        TSBCASE(4); TSBCASE(5); TSBCASE(6);
        !           410:                default:
        !           411:                        printf("bogus tsb size %x, using 7\n", vdma[1]);
        !           412:                        TSBCASE(7);
        !           413:                }
        !           414: #undef TSBCASE
        !           415:                DPRINTF(SDB_BUSMAP, ("schizo_iommu_init: iobase=0x%x\n", iobase));
        !           416:                free(vdma, M_DEVBUF);
        !           417:        } else {
        !           418:                DPRINTF(SDB_BUSMAP, ("schizo_iommu_init: getprop failed, "
        !           419:                    "using iobase=0x%x, tsbsize=%d\n", iobase, tsbsize));
        !           420:        }
        !           421:
        !           422:        iommu_init(name, is, tsbsize, iobase);
        !           423: }
        !           424:
        !           425: int
        !           426: schizo_print(void *aux, const char *p)
        !           427: {
        !           428:        if (p == NULL)
        !           429:                return (UNCONF);
        !           430:        return (QUIET);
        !           431: }
        !           432:
        !           433: /*
        !           434:  * Bus-specific interrupt mapping
        !           435:  */
        !           436: int
        !           437: schizo_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
        !           438: {
        !           439:        struct schizo_pbm *sp = pa->pa_pc->cookie;
        !           440:        struct schizo_softc *sc = sp->sp_sc;
        !           441:        u_int dev;
        !           442:
        !           443:        if (*ihp != (pci_intr_handle_t)-1) {
        !           444:                *ihp |= sc->sc_ign;
        !           445:                return (0);
        !           446:        }
        !           447:
        !           448:        /*
        !           449:         * We didn't find a PROM mapping for this interrupt.  Try to
        !           450:         * construct one ourselves based on the swizzled interrupt pin
        !           451:         * and the interrupt mapping for PCI slots documented in the
        !           452:         * UltraSPARC-IIi User's Manual.
        !           453:         */
        !           454:
        !           455:        if (pa->pa_intrpin == 0)
        !           456:                return (-1);
        !           457:
        !           458:        /*
        !           459:         * This deserves some documentation.  Should anyone
        !           460:         * have anything official looking, please speak up.
        !           461:         */
        !           462:        dev = pa->pa_device - 1;
        !           463:
        !           464:        *ihp = (pa->pa_intrpin - 1) & INTMAP_PCIINT;
        !           465:        *ihp |= (dev << 2) & INTMAP_PCISLOT;
        !           466:        *ihp |= sc->sc_ign;
        !           467:
        !           468:        return (0);
        !           469: }
        !           470:
        !           471: void
        !           472: schizo_set_intr(struct schizo_softc *sc, struct schizo_pbm *pbm, int ipl,
        !           473:     int (*handler)(void *), void *arg, int ino, char *what)
        !           474: {
        !           475:        struct intrhand *ih;
        !           476:        volatile u_int64_t *map, *clr;
        !           477:        struct schizo_pbm_regs *pbmreg;
        !           478:        char *name;
        !           479:        int nlen;
        !           480:
        !           481:        pbmreg = bus_space_vaddr(pbm->sp_regt, pbm->sp_regh);
        !           482:        map = &pbmreg->imap[ino];
        !           483:        clr = &pbmreg->iclr[ino];
        !           484:        ino |= sc->sc_ign;
        !           485:
        !           486:        nlen = strlen(sc->sc_dv.dv_xname) + 1 + strlen(what) + 1;
        !           487:        name = malloc(nlen, M_DEVBUF, M_WAITOK);
        !           488:        snprintf(name, nlen, "%s:%s", sc->sc_dv.dv_xname, what);
        !           489:
        !           490:        ih = bus_intr_allocate(pbm->sp_regt, handler, arg, ino, ipl,
        !           491:            map, clr, name);
        !           492:        if (ih == NULL) {
        !           493:                printf("set_intr failed...\n");
        !           494:                free(name, M_DEVBUF);
        !           495:                return;
        !           496:        }
        !           497:
        !           498:        intr_establish(ih->ih_pil, ih);
        !           499: }
        !           500:
        !           501: bus_space_tag_t
        !           502: schizo_alloc_mem_tag(struct schizo_pbm *sp)
        !           503: {
        !           504:        return (_schizo_alloc_bus_tag(sp, "mem",
        !           505:            0x02,       /* 32-bit mem space (where's the #define???) */
        !           506:            ASI_PRIMARY, ASI_PRIMARY_LITTLE));
        !           507: }
        !           508:
        !           509: bus_space_tag_t
        !           510: schizo_alloc_io_tag(struct schizo_pbm *sp)
        !           511: {
        !           512:        return (_schizo_alloc_bus_tag(sp, "io",
        !           513:            0x01,       /* IO space (where's the #define???) */
        !           514:            ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED));
        !           515: }
        !           516:
        !           517: bus_space_tag_t
        !           518: schizo_alloc_config_tag(struct schizo_pbm *sp)
        !           519: {
        !           520:        return (_schizo_alloc_bus_tag(sp, "cfg",
        !           521:            0x00,       /* Config space (where's the #define???) */
        !           522:            ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED));
        !           523: }
        !           524:
        !           525: bus_space_tag_t
        !           526: _schizo_alloc_bus_tag(struct schizo_pbm *pbm, const char *name, int ss,
        !           527:     int asi, int sasi)
        !           528: {
        !           529:        struct schizo_softc *sc = pbm->sp_sc;
        !           530:        struct sparc_bus_space_tag *bt;
        !           531:
        !           532:        bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT);
        !           533:        if (bt == NULL)
        !           534:                panic("schizo: could not allocate bus tag");
        !           535:
        !           536:        bzero(bt, sizeof *bt);
        !           537:        snprintf(bt->name, sizeof(bt->name), "%s-pbm_%s(%d/%2.2x)",
        !           538:            sc->sc_dv.dv_xname, name, ss, asi);
        !           539:
        !           540:        bt->cookie = pbm;
        !           541:        bt->parent = sc->sc_bust;
        !           542:        bt->default_type = ss;
        !           543:        bt->asi = asi;
        !           544:        bt->sasi = sasi;
        !           545:        bt->sparc_bus_map = _schizo_bus_map;
        !           546:        bt->sparc_bus_mmap = _schizo_bus_mmap;
        !           547:        bt->sparc_intr_establish = _schizo_intr_establish;
        !           548:        return (bt);
        !           549: }
        !           550:
        !           551: bus_dma_tag_t
        !           552: schizo_alloc_dma_tag(struct schizo_pbm *pbm)
        !           553: {
        !           554:        struct schizo_softc *sc = pbm->sp_sc;
        !           555:        bus_dma_tag_t dt, pdt = sc->sc_dmat;
        !           556:
        !           557:        dt = (bus_dma_tag_t)malloc(sizeof(struct sparc_bus_dma_tag),
        !           558:            M_DEVBUF, M_NOWAIT);
        !           559:        if (dt == NULL)
        !           560:                panic("schizo: could not alloc dma tag");
        !           561:
        !           562:        bzero(dt, sizeof(*dt));
        !           563:        dt->_cookie = pbm;
        !           564:        dt->_parent = pdt;
        !           565:        dt->_dmamap_create      = schizo_dmamap_create;
        !           566:        dt->_dmamap_destroy     = iommu_dvmamap_destroy;
        !           567:        dt->_dmamap_load        = iommu_dvmamap_load;
        !           568:        dt->_dmamap_load_raw    = iommu_dvmamap_load_raw;
        !           569:        dt->_dmamap_unload      = iommu_dvmamap_unload;
        !           570:        dt->_dmamap_sync        = iommu_dvmamap_sync;
        !           571:        dt->_dmamem_alloc       = iommu_dvmamem_alloc;
        !           572:        dt->_dmamem_free        = iommu_dvmamem_free;
        !           573:        dt->_dmamem_map         = iommu_dvmamem_map;
        !           574:        dt->_dmamem_unmap       = iommu_dvmamem_unmap;
        !           575:        return (dt);
        !           576: }
        !           577:
        !           578: pci_chipset_tag_t
        !           579: schizo_alloc_chipset(struct schizo_pbm *pbm, int node, pci_chipset_tag_t pc)
        !           580: {
        !           581:        pci_chipset_tag_t npc;
        !           582:
        !           583:        npc = malloc(sizeof *npc, M_DEVBUF, M_NOWAIT);
        !           584:        if (npc == NULL)
        !           585:                panic("could not allocate pci_chipset_tag_t");
        !           586:        memcpy(npc, pc, sizeof *pc);
        !           587:        npc->cookie = pbm;
        !           588:        npc->rootnode = node;
        !           589:        return (npc);
        !           590: }
        !           591:
        !           592: int
        !           593: schizo_dmamap_create(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size,
        !           594:     int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags,
        !           595:     bus_dmamap_t *dmamp)
        !           596: {
        !           597:        struct schizo_pbm *sp = t->_cookie;
        !           598:
        !           599:        return (iommu_dvmamap_create(t, t0, &sp->sp_sb, size, nsegments,
        !           600:            maxsegsz, boundary, flags, dmamp));
        !           601: }
        !           602:
        !           603: int
        !           604: _schizo_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset,
        !           605:     bus_size_t size, int flags, bus_space_handle_t *hp)
        !           606: {
        !           607:        struct schizo_pbm *pbm = t->cookie;
        !           608:        int i, ss;
        !           609:
        !           610:        DPRINTF(SDB_BUSMAP, ("_schizo_bus_map: type %d off %qx sz %qx flags %d",
        !           611:            t->default_type,
        !           612:            (unsigned long long)offset,
        !           613:            (unsigned long long)size,
        !           614:            flags));
        !           615:
        !           616:        ss = t->default_type;
        !           617:        DPRINTF(SDB_BUSMAP, (" cspace %d", ss));
        !           618:
        !           619:        if (t->parent == 0 || t->parent->sparc_bus_map == 0) {
        !           620:                printf("\n_schizo_bus_map: invalid parent");
        !           621:                return (EINVAL);
        !           622:        }
        !           623:
        !           624:        if (flags & BUS_SPACE_MAP_PROMADDRESS) {
        !           625:                return ((*t->parent->sparc_bus_map)
        !           626:                    (t, t0, offset, size, flags, hp));
        !           627:        }
        !           628:
        !           629:        for (i = 0; i < pbm->sp_nrange; i++) {
        !           630:                bus_addr_t paddr;
        !           631:
        !           632:                if (((pbm->sp_range[i].cspace >> 24) & 0x03) != ss)
        !           633:                        continue;
        !           634:
        !           635:                paddr = pbm->sp_range[i].phys_lo + offset;
        !           636:                paddr |= ((bus_addr_t)pbm->sp_range[i].phys_hi) << 32;
        !           637:                return ((*t->parent->sparc_bus_map)
        !           638:                    (t, t0, paddr, size, flags, hp));
        !           639:        }
        !           640:
        !           641:        return (EINVAL);
        !           642: }
        !           643:
        !           644: paddr_t
        !           645: _schizo_bus_mmap(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t paddr,
        !           646:     off_t off, int prot, int flags)
        !           647: {
        !           648:        bus_addr_t offset = paddr;
        !           649:        struct schizo_pbm *pbm = t->cookie;
        !           650:        int i, ss;
        !           651:
        !           652:        ss = t->default_type;
        !           653:
        !           654:        DPRINTF(SDB_BUSMAP, ("_schizo_bus_mmap: prot %d flags %d pa %qx\n",
        !           655:            prot, flags, (unsigned long long)paddr));
        !           656:
        !           657:        if (t->parent == 0 || t->parent->sparc_bus_mmap == 0) {
        !           658:                printf("\n_schizo_bus_mmap: invalid parent");
        !           659:                return (-1);
        !           660:        }
        !           661:
        !           662:        for (i = 0; i < pbm->sp_nrange; i++) {
        !           663:                bus_addr_t paddr;
        !           664:
        !           665:                if (((pbm->sp_range[i].cspace >> 24) & 0x03) != ss)
        !           666:                        continue;
        !           667:
        !           668:                paddr = pbm->sp_range[i].phys_lo + offset;
        !           669:                paddr |= ((bus_addr_t)pbm->sp_range[i].phys_hi<<32);
        !           670:                return ((*t->parent->sparc_bus_mmap)
        !           671:                    (t, t0, paddr, off, prot, flags));
        !           672:        }
        !           673:
        !           674:        return (-1);
        !           675: }
        !           676:
        !           677: void *
        !           678: _schizo_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle,
        !           679:     int level, int flags, int (*handler)(void *), void *arg, const char *what)
        !           680: {
        !           681:        struct schizo_pbm *pbm = t->cookie;
        !           682:        struct intrhand *ih = NULL;
        !           683:        volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL;
        !           684:        int ino;
        !           685:        long vec = INTVEC(ihandle);
        !           686:
        !           687:        vec = INTVEC(ihandle);
        !           688:        ino = INTINO(vec);
        !           689:
        !           690:        if (level == IPL_NONE)
        !           691:                level = INTLEV(vec);
        !           692:        if (level == IPL_NONE) {
        !           693:                printf(": no IPL, setting IPL 2.\n");
        !           694:                level = 2;
        !           695:        }
        !           696:
        !           697:        if ((flags & BUS_INTR_ESTABLISH_SOFTINTR) == 0) {
        !           698:                struct schizo_pbm_regs *pbmreg;
        !           699:
        !           700:                pbmreg = bus_space_vaddr(pbm->sp_regt, pbm->sp_regh);
        !           701:                intrmapptr = &pbmreg->imap[ino];
        !           702:                intrclrptr = &pbmreg->iclr[ino];
        !           703:                if (INTIGN(vec) == 0)
        !           704:                        ino |= (*intrmapptr) & INTMAP_IGN;
        !           705:                else
        !           706:                        ino |= vec & INTMAP_IGN;
        !           707:        }
        !           708:
        !           709:        ih = bus_intr_allocate(t0, handler, arg, ino, level, intrmapptr,
        !           710:            intrclrptr, what);
        !           711:        if (ih == NULL)
        !           712:                return (NULL);
        !           713:
        !           714:        intr_establish(ih->ih_pil, ih);
        !           715:
        !           716:        if (intrmapptr != NULL) {
        !           717:                u_int64_t intrmap;
        !           718:
        !           719:                intrmap = *intrmapptr;
        !           720:                intrmap |= INTMAP_V;
        !           721:                *intrmapptr = intrmap;
        !           722:                intrmap = *intrmapptr;
        !           723:                ih->ih_number |= intrmap & INTMAP_INR;
        !           724:        }
        !           725:
        !           726:        return (ih);
        !           727: }
        !           728:
        !           729: const struct cfattach schizo_ca = {
        !           730:        sizeof(struct schizo_softc), schizo_match, schizo_attach
        !           731: };
        !           732:
        !           733: struct cfdriver schizo_cd = {
        !           734:        NULL, "schizo", DV_DULL
        !           735: };

CVSweb