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

Annotation of sys/arch/sparc64/dev/psycho.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: psycho.c,v 1.52 2007/08/04 16:44:15 kettenis Exp $    */
                      2: /*     $NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp $  */
                      3:
                      4: /*
                      5:  * Copyright (c) 1999, 2000 Matthew R. Green
                      6:  * Copyright (c) 2003 Henric Jungheim
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     22:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     23:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     25:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     26:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     27:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     28:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     29:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     30:  * SUCH DAMAGE.
                     31:  */
                     32:
                     33: /*
                     34:  * Support for `psycho' and `psycho+' UPA to PCI bridge and
                     35:  * UltraSPARC IIi and IIe `sabre' PCI controllers.
                     36:  */
                     37:
                     38: #include <sys/param.h>
                     39: #include <sys/device.h>
                     40: #include <sys/errno.h>
                     41: #include <sys/extent.h>
                     42: #include <sys/malloc.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/time.h>
                     45: #include <sys/reboot.h>
                     46:
                     47: #include <uvm/uvm_extern.h>
                     48:
                     49: #define _SPARC_BUS_DMA_PRIVATE
                     50: #include <machine/bus.h>
                     51: #include <machine/autoconf.h>
                     52: #include <machine/psl.h>
                     53:
                     54: #include <dev/pci/pcivar.h>
                     55: #include <dev/pci/pcireg.h>
                     56:
                     57: #include <sparc64/dev/iommureg.h>
                     58: #include <sparc64/dev/iommuvar.h>
                     59: #include <sparc64/dev/psychoreg.h>
                     60: #include <sparc64/dev/psychovar.h>
                     61: #include <sparc64/sparc64/cache.h>
                     62:
                     63: #ifdef DEBUG
                     64: #define PDB_PROM       0x01
                     65: #define PDB_BUSMAP     0x02
                     66: #define PDB_INTR       0x04
                     67: #define PDB_CONF       0x08
                     68: int psycho_debug = ~0;
                     69: #define DPRINTF(l, s)   do { if (psycho_debug & l) printf s; } while (0)
                     70: #else
                     71: #define DPRINTF(l, s)
                     72: #endif
                     73:
                     74: pci_chipset_tag_t psycho_alloc_chipset(struct psycho_pbm *, int,
                     75:     pci_chipset_tag_t);
                     76: void psycho_get_bus_range(int, int *);
                     77: void psycho_get_ranges(int, struct psycho_ranges **, int *);
                     78: void psycho_set_intr(struct psycho_softc *, int, void *,
                     79:     u_int64_t *, u_int64_t *, const char *);
                     80: bus_space_tag_t psycho_alloc_bus_tag(struct psycho_pbm *,
                     81:     const char *, int, int, int);
                     82:
                     83: /* Interrupt handlers */
                     84: int psycho_ue(void *);
                     85: int psycho_ce(void *);
                     86: int psycho_bus_a(void *);
                     87: int psycho_bus_b(void *);
                     88: int psycho_bus_error(struct psycho_softc *, int);
                     89: int psycho_powerfail(void *);
                     90: int psycho_wakeup(void *);
                     91:
                     92: /* IOMMU support */
                     93: void psycho_iommu_init(struct psycho_softc *, int);
                     94:
                     95: /*
                     96:  * bus space and bus dma support for UltraSPARC `psycho'.  note that most
                     97:  * of the bus dma support is provided by the iommu dvma controller.
                     98:  */
                     99: int psycho_bus_map(bus_space_tag_t, bus_space_tag_t, bus_addr_t,
                    100:     bus_size_t, int, bus_space_handle_t *);
                    101: paddr_t psycho_bus_mmap(bus_space_tag_t, bus_space_tag_t, bus_addr_t, off_t,
                    102:     int, int);
                    103: bus_addr_t psycho_bus_addr(bus_space_tag_t, bus_space_tag_t,
                    104:     bus_space_handle_t);
                    105: void *psycho_intr_establish(bus_space_tag_t, bus_space_tag_t, int, int, int,
                    106:     int (*)(void *), void *, const char *);
                    107:
                    108: int psycho_dmamap_create(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, int,
                    109:     bus_size_t, bus_size_t, int, bus_dmamap_t *);
                    110: void psycho_sabre_dvmamap_sync(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t,
                    111:     bus_size_t, bus_size_t, int);
                    112: void psycho_map_psycho(struct psycho_softc *, int, bus_addr_t, bus_size_t,
                    113:     bus_addr_t, bus_size_t);
                    114: int psycho_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
                    115: void psycho_identify_pbm(struct psycho_softc *sc, struct psycho_pbm *pp,
                    116:     struct pcibus_attach_args *pa);
                    117:
                    118: /* base pci_chipset */
                    119: extern struct sparc_pci_chipset _sparc_pci_chipset;
                    120:
                    121: /*
                    122:  * autoconfiguration
                    123:  */
                    124: int    psycho_match(struct device *, void *, void *);
                    125: void   psycho_attach(struct device *, struct device *, void *);
                    126: int    psycho_print(void *aux, const char *p);
                    127:
                    128:
                    129: struct cfattach psycho_ca = {
                    130:         sizeof(struct psycho_softc), psycho_match, psycho_attach
                    131: };
                    132:
                    133: struct cfdriver psycho_cd = {
                    134:        NULL, "psycho", DV_DULL
                    135: };
                    136:
                    137: /*
                    138:  * "sabre" is the UltraSPARC IIi onboard UPA to PCI bridge.  It manages a
                    139:  * single PCI bus and does not have a streaming buffer.  It often has an APB
                    140:  * (advanced PCI bridge) connected to it, which was designed specifically for
                    141:  * the IIi.  The APB let's the IIi handle two independednt PCI buses, and
                    142:  * appears as two "simba"'s underneath the sabre.
                    143:  *
                    144:  * "psycho" and "psycho+" is a dual UPA to PCI bridge.  It sits on the UPA bus
                    145:  * and manages two PCI buses.  "psycho" has two 64-bit 33MHz buses, while
                    146:  * "psycho+" controls both a 64-bit 33MHz and a 64-bit 66MHz PCI bus.  You
                    147:  * will usually find a "psycho+" since I don't think the original "psycho"
                    148:  * ever shipped, and if it did it would be in the U30.
                    149:  *
                    150:  * Each "psycho" PCI bus appears as a separate OFW node, but since they are
                    151:  * both part of the same IC, they only have a single register space.  As such,
                    152:  * they need to be configured together, even though the autoconfiguration will
                    153:  * attach them separately.
                    154:  *
                    155:  * On UltraIIi machines, "sabre" itself usually takes pci0, with "simba" often
                    156:  * as pci1 and pci2, although they have been implemented with other PCI bus
                    157:  * numbers on some machines.
                    158:  *
                    159:  * On UltraII machines, there can be any number of "psycho+" ICs, each
                    160:  * providing two PCI buses.
                    161:  *
                    162:  *
                    163:  * XXXX The psycho/sabre node has an `interrupts' attribute.  They contain
                    164:  * the values of the following interrupts in this order:
                    165:  *
                    166:  * PCI Bus Error       (30)
                    167:  * DMA UE              (2e)
                    168:  * DMA CE              (2f)
                    169:  * Power Fail          (25)
                    170:  *
                    171:  * We really should attach handlers for each.
                    172:  *
                    173:  */
                    174: #define        ROM_PCI_NAME            "pci"
                    175:
                    176: struct psycho_type {
                    177:        char *p_name;
                    178:        int p_type;
                    179: } psycho_types[] = {
                    180:        { "SUNW,psycho",        PSYCHO_MODE_PSYCHO      },
                    181:        { "pci108e,8000",       PSYCHO_MODE_PSYCHO      },
                    182:        { "SUNW,sabre",         PSYCHO_MODE_SABRE       },
                    183:        { "pci108e,a000",       PSYCHO_MODE_SABRE       },
                    184:        { "pci108e,a001",       PSYCHO_MODE_SABRE       },
                    185:        { NULL, 0 }
                    186: };
                    187:
                    188: int
                    189: psycho_match(struct device *parent, void *match, void *aux)
                    190: {
                    191:        struct mainbus_attach_args *ma = aux;
                    192:        struct psycho_type *ptype;
                    193:        char *str;
                    194:
                    195:        /* match on a name of "pci" and a sabre or a psycho */
                    196:        if (strcmp(ma->ma_name, ROM_PCI_NAME) != 0)
                    197:                return (0);
                    198:
                    199:        for (ptype = psycho_types; ptype->p_name != NULL; ptype++) {
                    200:                str = getpropstring(ma->ma_node, "model");
                    201:                if (strcmp(str, ptype->p_name) == 0)
                    202:                        return (1);
                    203:                str = getpropstring(ma->ma_node, "compatible");
                    204:                if (strcmp(str, ptype->p_name) == 0)
                    205:                        return (1);
                    206:        }
                    207:        return (0);
                    208: }
                    209:
                    210: /*
                    211:  * SUNW,psycho initialization ...
                    212:  *     - find the per-psycho registers
                    213:  *     - figure out the IGN.
                    214:  *     - find our partner psycho
                    215:  *     - configure ourselves
                    216:  *     - bus range, bus,
                    217:  *     - get interrupt-map and interrupt-map-mask
                    218:  *     - setup the chipsets.
                    219:  *     - if we're the first of the pair, initialise the IOMMU, otherwise
                    220:  *       just copy its tags and addresses.
                    221:  */
                    222: void
                    223: psycho_attach(struct device *parent, struct device *self, void *aux)
                    224: {
                    225:        struct psycho_softc *sc = (struct psycho_softc *)self;
                    226:        struct psycho_softc *osc = NULL;
                    227:        struct psycho_pbm *pp;
                    228:        struct pcibus_attach_args pba;
                    229:        struct mainbus_attach_args *ma = aux;
                    230:        u_int64_t csr;
                    231:        int psycho_br[2], n;
                    232:        struct psycho_type *ptype;
                    233:
                    234:        sc->sc_node = ma->ma_node;
                    235:        sc->sc_bustag = ma->ma_bustag;
                    236:        sc->sc_dmatag = ma->ma_dmatag;
                    237:
                    238:        /*
                    239:         * call the model-specific initialization routine.
                    240:         */
                    241:
                    242:        for (ptype = psycho_types; ptype->p_name != NULL; ptype++) {
                    243:                char *str;
                    244:
                    245:                str = getpropstring(ma->ma_node, "model");
                    246:                if (strcmp(str, ptype->p_name) == 0)
                    247:                        break;
                    248:                str = getpropstring(ma->ma_node, "compatible");
                    249:                if (strcmp(str, ptype->p_name) == 0)
                    250:                        break;
                    251:        }
                    252:        if (ptype->p_name == NULL)
                    253:                panic("psycho_attach: unknown model?");
                    254:        sc->sc_mode = ptype->p_type;
                    255:
                    256:        /*
                    257:         * The psycho gets three register banks:
                    258:         * (0) per-PBM configuration and status registers
                    259:         * (1) per-PBM PCI configuration space, containing only the
                    260:         *     PBM 256-byte PCI header
                    261:         * (2) the shared psycho configuration registers (struct psychoreg)
                    262:         *
                    263:         * XXX use the prom address for the psycho registers?  we do so far.
                    264:         */
                    265:
                    266:        /* Register layouts are different.  stuupid. */
                    267:        if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
                    268:                sc->sc_basepaddr = (paddr_t)ma->ma_reg[2].ur_paddr;
                    269:
                    270:                if (ma->ma_naddress > 2) {
                    271:                        psycho_map_psycho(sc, 0,
                    272:                            ma->ma_address[2], sizeof(struct psychoreg),
                    273:                            ma->ma_address[0], sizeof(struct pci_ctl));
                    274:                } else if (ma->ma_nreg > 2) {
                    275:                        psycho_map_psycho(sc, 1,
                    276:                            ma->ma_reg[2].ur_paddr, ma->ma_reg[2].ur_len,
                    277:                            ma->ma_reg[0].ur_paddr, ma->ma_reg[0].ur_len);
                    278:                } else
                    279:                        panic("psycho_attach: %d not enough registers",
                    280:                            ma->ma_nreg);
                    281:        } else {
                    282:                sc->sc_basepaddr = (paddr_t)ma->ma_reg[0].ur_paddr;
                    283:
                    284:                if (ma->ma_naddress) {
                    285:                        psycho_map_psycho(sc, 0,
                    286:                            ma->ma_address[0], sizeof(struct psychoreg),
                    287:                            ma->ma_address[0] +
                    288:                                offsetof(struct psychoreg, psy_pcictl[0]),
                    289:                            sizeof(struct pci_ctl));
                    290:                } else if (ma->ma_nreg) {
                    291:                        psycho_map_psycho(sc, 1,
                    292:                            ma->ma_reg[0].ur_paddr, ma->ma_reg[0].ur_len,
                    293:                            ma->ma_reg[0].ur_paddr +
                    294:                                offsetof(struct psychoreg, psy_pcictl[0]),
                    295:                            sizeof(struct pci_ctl));
                    296:                } else
                    297:                        panic("psycho_attach: %d not enough registers",
                    298:                            ma->ma_nreg);
                    299:        }
                    300:
                    301:        csr = psycho_psychoreg_read(sc, psy_csr);
                    302:        sc->sc_ign = INTMAP_IGN; /* APB IGN is always 0x1f << 6 = 0x7c */
                    303:        if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
                    304:                sc->sc_ign = PSYCHO_GCSR_IGN(csr) << 6;
                    305:
                    306:        printf(": %s, impl %d, version %d, ign %x\n", ptype->p_name,
                    307:            PSYCHO_GCSR_IMPL(csr), PSYCHO_GCSR_VERS(csr), sc->sc_ign);
                    308:
                    309:        /*
                    310:         * Match other psycho's that are already configured against
                    311:         * the base physical address. This will be the same for a
                    312:         * pair of devices that share register space.
                    313:         */
                    314:        for (n = 0; n < psycho_cd.cd_ndevs; n++) {
                    315:                struct psycho_softc *asc =
                    316:                    (struct psycho_softc *)psycho_cd.cd_devs[n];
                    317:
                    318:                if (asc == NULL || asc == sc)
                    319:                        /* This entry is not there or it is me */
                    320:                        continue;
                    321:
                    322:                if (asc->sc_basepaddr != sc->sc_basepaddr)
                    323:                        /* This is an unrelated psycho */
                    324:                        continue;
                    325:
                    326:                /* Found partner */
                    327:                osc = asc;
                    328:                break;
                    329:        }
                    330:
                    331:        /* Oh, dear.  OK, lets get started */
                    332:
                    333:        /*
                    334:         * Setup the PCI control register
                    335:         */
                    336:        csr = psycho_pcictl_read(sc, pci_csr);
                    337:        csr |= PCICTL_MRLM | PCICTL_ARB_PARK | PCICTL_ERRINTEN |
                    338:            PCICTL_4ENABLE;
                    339:        csr &= ~(PCICTL_SERR | PCICTL_CPU_PRIO | PCICTL_ARB_PRIO |
                    340:            PCICTL_RTRYWAIT);
                    341:        psycho_pcictl_write(sc, pci_csr, csr);
                    342:
                    343:        /*
                    344:         * Allocate our psycho_pbm
                    345:         */
                    346:        pp = sc->sc_psycho_this = malloc(sizeof *pp, M_DEVBUF, M_NOWAIT);
                    347:        if (pp == NULL)
                    348:                panic("could not allocate psycho pbm");
                    349:
                    350:        memset(pp, 0, sizeof *pp);
                    351:
                    352:        pp->pp_sc = sc;
                    353:
                    354:        /* grab the psycho ranges */
                    355:        psycho_get_ranges(sc->sc_node, &pp->pp_range, &pp->pp_nrange);
                    356:
                    357:        /* get the bus-range for the psycho */
                    358:        psycho_get_bus_range(sc->sc_node, psycho_br);
                    359:
                    360:        pba.pba_domain = pci_ndomains++;
                    361:        pba.pba_bus = psycho_br[0];
                    362:        pba.pba_bridgetag = NULL;
                    363:
                    364:        printf("%s: bus range %u-%u, PCI bus %d\n", sc->sc_dev.dv_xname,
                    365:            psycho_br[0], psycho_br[1], psycho_br[0]);
                    366:
                    367:        pp->pp_pcictl = sc->sc_pcictl;
                    368:
                    369:        /* allocate our tags */
                    370:        pp->pp_memt = psycho_alloc_mem_tag(pp);
                    371:        pp->pp_iot = psycho_alloc_io_tag(pp);
                    372:        pp->pp_dmat = psycho_alloc_dma_tag(pp);
                    373:        pp->pp_flags = (pp->pp_memt ? PCI_FLAGS_MEM_ENABLED : 0) |
                    374:                        (pp->pp_iot ? PCI_FLAGS_IO_ENABLED  : 0);
                    375:
                    376:        /* allocate a chipset for this */
                    377:        pp->pp_pc = psycho_alloc_chipset(pp, sc->sc_node, &_sparc_pci_chipset);
                    378:
                    379:        /* setup the rest of the psycho pbm */
                    380:        pba.pba_pc = pp->pp_pc;
                    381:
                    382:        /*
                    383:         * And finally, if we're a sabre or the first of a pair of psycho's to
                    384:         * arrive here, start up the IOMMU and get a config space tag.
                    385:         */
                    386:
                    387:        if (osc == NULL) {
                    388:                uint64_t timeo;
                    389:
                    390:                /*
                    391:                 * Establish handlers for interesting interrupts....
                    392:                 *
                    393:                 * XXX We need to remember these and remove this to support
                    394:                 * hotplug on the UPA/FHC bus.
                    395:                 *
                    396:                 * XXX Not all controllers have these, but installing them
                    397:                 * is better than trying to sort through this mess.
                    398:                 */
                    399:                psycho_set_intr(sc, 15, psycho_ue,
                    400:                    psycho_psychoreg_vaddr(sc, ue_int_map),
                    401:                    psycho_psychoreg_vaddr(sc, ue_clr_int), "ue");
                    402:                psycho_set_intr(sc, 1, psycho_ce,
                    403:                    psycho_psychoreg_vaddr(sc, ce_int_map),
                    404:                    psycho_psychoreg_vaddr(sc, ce_clr_int), "ce");
                    405:                psycho_set_intr(sc, 15, psycho_bus_a,
                    406:                    psycho_psychoreg_vaddr(sc, pciaerr_int_map),
                    407:                    psycho_psychoreg_vaddr(sc, pciaerr_clr_int), "bus_a");
                    408: #if 0
                    409:                psycho_set_intr(sc, 15, psycho_powerfail,
                    410:                    psycho_psychoreg_vaddr(sc, power_int_map),
                    411:                    psycho_psychoreg_vaddr(sc, power_clr_int), "powerfail");
                    412: #endif
                    413:                if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
                    414:                        psycho_set_intr(sc, 15, psycho_bus_b,
                    415:                            psycho_psychoreg_vaddr(sc, pciberr_int_map),
                    416:                            psycho_psychoreg_vaddr(sc, pciberr_clr_int),
                    417:                            "bus_b");
                    418:                        psycho_set_intr(sc, 1, psycho_wakeup,
                    419:                            psycho_psychoreg_vaddr(sc, pwrmgt_int_map),
                    420:                            psycho_psychoreg_vaddr(sc, pwrmgt_clr_int),
                    421:                            "wakeup");
                    422:                }
                    423:
                    424:                /*
                    425:                 * Apparently a number of machines with psycho and psycho+
                    426:                 * controllers have interrupt latency issues.  We'll try
                    427:                 * setting the interrupt retry timeout to 0xff which gives us
                    428:                 * a retry of 3-6 usec (which is what sysio is set to) for the
                    429:                 * moment, which seems to help alleviate this problem.
                    430:                 */
                    431:                timeo = psycho_psychoreg_read(sc, intr_retry_timer);
                    432:                if (timeo > 0xfff) {
                    433: #ifdef DEBUG
                    434:                        printf("decreasing interrupt retry timeout "
                    435:                            "from %lx to 0xff\n", (long)timeo);
                    436: #endif
                    437:                        psycho_psychoreg_write(sc, intr_retry_timer, 0xff);
                    438:                }
                    439:
                    440:                /*
                    441:                 * Setup IOMMU and PCI configuration if we're the first
                    442:                 * of a pair of psycho's to arrive here.
                    443:                 *
                    444:                 * We should calculate a TSB size based on the amount of RAM,
                    445:                 * number of bus controllers, and number and type of child
                    446:                 * devices.
                    447:                 *
                    448:                 * For the moment, 32KB should be more than enough.
                    449:                 */
                    450:                sc->sc_is = malloc(sizeof(struct iommu_state),
                    451:                        M_DEVBUF, M_NOWAIT);
                    452:                if (sc->sc_is == NULL)
                    453:                        panic("psycho_attach: malloc iommu_state");
                    454:
                    455:                memset(sc->sc_is, 0, sizeof *sc->sc_is);
                    456:
                    457:                if (getproplen(sc->sc_node, "no-streaming-cache") < 0) {
                    458:                        struct strbuf_ctl *sb = &pp->pp_sb;
                    459:                        vaddr_t va = (vaddr_t)&pp->pp_flush[0x40];
                    460:
                    461:                        /*
                    462:                         * Initialize the strbuf_ctl.
                    463:                         *
                    464:                         * The flush sync buffer must be 64-byte aligned.
                    465:                         */
                    466:
                    467:                        sb->sb_flush = (void *)(va & ~0x3f);
                    468:
                    469:                        sb->sb_bustag = sc->sc_bustag;
                    470:                        if (bus_space_subregion(sc->sc_bustag, sc->sc_pcictl,
                    471:                            offsetof(struct pci_ctl, pci_strbuf),
                    472:                            sizeof(struct iommu_strbuf),
                    473:                            &sb->sb_sb)) {
                    474:                                printf("STC0 subregion failed\n");
                    475:                                sb->sb_flush = 0;
                    476:                        }
                    477:                }
                    478:
                    479:                /* Point out iommu at the strbuf_ctl. */
                    480:                sc->sc_is->is_sb[0] = &pp->pp_sb;
                    481:
                    482:                printf("%s: ", sc->sc_dev.dv_xname);
                    483:                psycho_iommu_init(sc, 2);
                    484:
                    485:                sc->sc_configtag = psycho_alloc_config_tag(sc->sc_psycho_this);
                    486:                if (bus_space_map(sc->sc_configtag,
                    487:                    sc->sc_basepaddr, 0x01000000, 0, &sc->sc_configaddr))
                    488:                        panic("could not map psycho PCI configuration space");
                    489:        } else {
                    490:                /* Just copy IOMMU state, config tag and address */
                    491:                sc->sc_is = osc->sc_is;
                    492:                sc->sc_configtag = osc->sc_configtag;
                    493:                sc->sc_configaddr = osc->sc_configaddr;
                    494:
                    495:                if (getproplen(sc->sc_node, "no-streaming-cache") < 0) {
                    496:                        struct strbuf_ctl *sb = &pp->pp_sb;
                    497:                        vaddr_t va = (vaddr_t)&pp->pp_flush[0x40];
                    498:
                    499:                        /*
                    500:                         * Initialize the strbuf_ctl.
                    501:                         *
                    502:                         * The flush sync buffer must be 64-byte aligned.
                    503:                         */
                    504:
                    505:                        sb->sb_flush = (void *)(va & ~0x3f);
                    506:
                    507:                        sb->sb_bustag = sc->sc_bustag;
                    508:                        if (bus_space_subregion(sc->sc_bustag, sc->sc_pcictl,
                    509:                            offsetof(struct pci_ctl, pci_strbuf),
                    510:                            sizeof(struct iommu_strbuf),
                    511:                            &sb->sb_sb)) {
                    512:                                printf("STC1 subregion failed\n");
                    513:                                sb->sb_flush = 0;
                    514:                        }
                    515:
                    516:                        /* Point out iommu at the strbuf_ctl. */
                    517:                        sc->sc_is->is_sb[1] = sb;
                    518:                }
                    519:
                    520:                /* Point out iommu at the strbuf_ctl. */
                    521:                sc->sc_is->is_sb[1] = &pp->pp_sb;
                    522:
                    523:                printf("%s: ", sc->sc_dev.dv_xname);
                    524:                printf("dvma map %x-%x, ", sc->sc_is->is_dvmabase,
                    525:                    sc->sc_is->is_dvmaend);
                    526:                printf("iotdb %llx-%llx",
                    527:                    (unsigned long long)sc->sc_is->is_ptsb,
                    528:                    (unsigned long long)(sc->sc_is->is_ptsb +
                    529:                    (PAGE_SIZE << sc->sc_is->is_tsbsize)));
                    530:                iommu_reset(sc->sc_is);
                    531:                printf("\n");
                    532:        }
                    533:
                    534:        /*
                    535:         * attach the pci.. note we pass PCI A tags, etc., for the sabre here.
                    536:         */
                    537:        pba.pba_busname = "pci";
                    538: #if 0
                    539:        pba.pba_flags = sc->sc_psycho_this->pp_flags;
                    540: #endif
                    541:        pba.pba_dmat = sc->sc_psycho_this->pp_dmat;
                    542:        pba.pba_iot = sc->sc_psycho_this->pp_iot;
                    543:        pba.pba_memt = sc->sc_psycho_this->pp_memt;
                    544:        pba.pba_pc->bustag = sc->sc_configtag;
                    545:        pba.pba_pc->bushandle = sc->sc_configaddr;
                    546:        pba.pba_pc->intr_map = psycho_intr_map;
                    547:
                    548:        if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
                    549:                psycho_identify_pbm(sc, pp, &pba);
                    550:        else
                    551:                pp->pp_id = PSYCHO_PBM_UNKNOWN;
                    552:
                    553:        config_found(self, &pba, psycho_print);
                    554: }
                    555:
                    556: void
                    557: psycho_identify_pbm(struct psycho_softc *sc, struct psycho_pbm *pp,
                    558:     struct pcibus_attach_args *pa)
                    559: {
                    560:        vaddr_t pci_va = (vaddr_t)bus_space_vaddr(sc->sc_bustag, sc->sc_pcictl);
                    561:        paddr_t pci_pa;
                    562:
                    563:        if (pmap_extract(pmap_kernel(), pci_va, &pci_pa) == 0)
                    564:            pp->pp_id = PSYCHO_PBM_UNKNOWN;
                    565:        else switch(pci_pa & 0xffff) {
                    566:                case 0x2000:
                    567:                        pp->pp_id = PSYCHO_PBM_A;
                    568:                        break;
                    569:                case 0x4000:
                    570:                        pp->pp_id = PSYCHO_PBM_B;
                    571:                        break;
                    572:                default:
                    573:                        pp->pp_id = PSYCHO_PBM_UNKNOWN;
                    574:                        break;
                    575:        }
                    576: }
                    577:
                    578: void
                    579: psycho_map_psycho(struct psycho_softc* sc, int do_map, bus_addr_t reg_addr,
                    580:     bus_size_t reg_size, bus_addr_t pci_addr, bus_size_t pci_size)
                    581: {
                    582:        if (do_map) {
                    583:                if (bus_space_map(sc->sc_bustag,
                    584:                    reg_addr, reg_size, 0, &sc->sc_regsh))
                    585:                        panic("psycho_attach: cannot map regs");
                    586:
                    587:                if (pci_addr >= reg_addr &&
                    588:                    pci_addr + pci_size <= reg_addr + reg_size) {
                    589:                        if (bus_space_subregion(sc->sc_bustag, sc->sc_regsh,
                    590:                            pci_addr - reg_addr, pci_size, &sc->sc_pcictl))
                    591:                                panic("psycho_map_psycho: map ctl");
                    592:                }
                    593:                else if (bus_space_map(sc->sc_bustag, pci_addr, pci_size,
                    594:                    0, &sc->sc_pcictl))
                    595:                        panic("psycho_map_psycho: cannot map pci");
                    596:        } else {
                    597:                if (bus_space_map(sc->sc_bustag, reg_addr, reg_size,
                    598:                    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_regsh))
                    599:                        panic("psycho_map_psycho: cannot map ctl");
                    600:                if (bus_space_map(sc->sc_bustag, pci_addr, pci_size,
                    601:                    BUS_SPACE_MAP_PROMADDRESS, &sc->sc_pcictl))
                    602:                        panic("psycho_map_psycho: cannot map pci");
                    603:        }
                    604: }
                    605:
                    606: int
                    607: psycho_print(void *aux, const char *p)
                    608: {
                    609:        if (p == NULL)
                    610:                return (UNCONF);
                    611:        return (QUIET);
                    612: }
                    613:
                    614: void
                    615: psycho_set_intr(struct psycho_softc *sc, int ipl, void *handler,
                    616:     u_int64_t *mapper, u_int64_t *clearer, const char *suffix)
                    617: {
                    618:        struct intrhand *ih;
                    619:
                    620:        ih = (struct intrhand *)malloc(sizeof(struct intrhand),
                    621:            M_DEVBUF, M_NOWAIT);
                    622:        if (ih == NULL)
                    623:                panic("couldn't malloc intrhand");
                    624:        memset(ih, 0, sizeof(struct intrhand));
                    625:        ih->ih_arg = sc;
                    626:        ih->ih_map = mapper;
                    627:        ih->ih_clr = clearer;
                    628:        ih->ih_fun = handler;
                    629:        ih->ih_pil = (1 << ipl);
                    630:        ih->ih_number = INTVEC(*(ih->ih_map));
                    631:        snprintf(ih->ih_name, sizeof(ih->ih_name),
                    632:            "%s:%s", sc->sc_dev.dv_xname, suffix);
                    633:
                    634:        DPRINTF(PDB_INTR, (
                    635:            "\ninstalling handler %p arg %p for %s with number %x pil %u",
                    636:            ih->ih_fun, ih->ih_arg, sc->sc_dev.dv_xname, ih->ih_number,
                    637:            ih->ih_pil));
                    638:
                    639:        intr_establish(ipl, ih);
                    640:        *(ih->ih_map) |= INTMAP_V;
                    641: }
                    642:
                    643: /*
                    644:  * PCI bus support
                    645:  */
                    646:
                    647: /*
                    648:  * allocate a PCI chipset tag and set its cookie.
                    649:  */
                    650: pci_chipset_tag_t
                    651: psycho_alloc_chipset(struct psycho_pbm *pp, int node, pci_chipset_tag_t pc)
                    652: {
                    653:        pci_chipset_tag_t npc;
                    654:
                    655:        npc = malloc(sizeof *npc, M_DEVBUF, M_NOWAIT);
                    656:        if (npc == NULL)
                    657:                panic("could not allocate pci_chipset_tag_t");
                    658:        memcpy(npc, pc, sizeof *pc);
                    659:        npc->cookie = pp;
                    660:        npc->rootnode = node;
                    661:
                    662:        return (npc);
                    663: }
                    664:
                    665: /*
                    666:  * grovel the OBP for various psycho properties
                    667:  */
                    668: void
                    669: psycho_get_bus_range(node, brp)
                    670:        int node;
                    671:        int *brp;
                    672: {
                    673:        int n, error;
                    674:
                    675:        error = getprop(node, "bus-range", sizeof(*brp), &n, (void **)&brp);
                    676:        if (error)
                    677:                panic("could not get psycho bus-range, error %d", error);
                    678:        if (n != 2)
                    679:                panic("broken psycho bus-range");
                    680:        DPRINTF(PDB_PROM,
                    681:            ("psycho debug: got `bus-range' for node %08x: %u - %u\n",
                    682:            node, brp[0], brp[1]));
                    683: }
                    684:
                    685: void
                    686: psycho_get_ranges(int node, struct psycho_ranges **rp, int *np)
                    687: {
                    688:
                    689:        if (getprop(node, "ranges", sizeof(**rp), np, (void **)rp))
                    690:                panic("could not get psycho ranges");
                    691:        DPRINTF(PDB_PROM,
                    692:            ("psycho debug: got `ranges' for node %08x: %d entries\n",
                    693:            node, *np));
                    694: }
                    695:
                    696: /*
                    697:  * Interrupt handlers.
                    698:  */
                    699:
                    700: int
                    701: psycho_ue(void *arg)
                    702: {
                    703:        struct psycho_softc *sc = arg;
                    704:        unsigned long long afsr = psycho_psychoreg_read(sc, psy_ue_afsr);
                    705:        unsigned long long afar = psycho_psychoreg_read(sc, psy_ue_afar);
                    706:
                    707:        /*
                    708:         * It's uncorrectable.  Dump the regs and panic.
                    709:         */
                    710:        panic("%s: uncorrectable DMA error AFAR %llx (pa=%lx tte=%llx/%llx) "
                    711:            "AFSR %llx", sc->sc_dev.dv_xname, afar,
                    712:            iommu_extract(sc->sc_is, (vaddr_t)afar),
                    713:            iommu_lookup_tte(sc->sc_is, (vaddr_t)afar),
                    714:            iommu_fetch_tte(sc->sc_is, (paddr_t)afar),
                    715:            afsr);
                    716:        return (1);
                    717: }
                    718:
                    719: int
                    720: psycho_ce(void *arg)
                    721: {
                    722:        struct psycho_softc *sc = arg;
                    723:
                    724:        /*
                    725:         * It's correctable.  Dump the regs and continue.
                    726:         */
                    727:
                    728:        printf("%s: correctable DMA error AFAR %llx AFSR %llx\n",
                    729:            sc->sc_dev.dv_xname,
                    730:            (long long)psycho_psychoreg_read(sc, psy_ce_afar),
                    731:            (long long)psycho_psychoreg_read(sc, psy_ce_afsr));
                    732:        return (1);
                    733: }
                    734:
                    735: int
                    736: psycho_bus_error(struct psycho_softc *sc, int bus)
                    737: {
                    738:        u_int64_t afsr, afar, bits;
                    739:
                    740:        afar = psycho_psychoreg_read(sc, psy_pcictl[bus].pci_afar);
                    741:        afsr = psycho_psychoreg_read(sc, psy_pcictl[bus].pci_afsr);
                    742:
                    743:        bits = afsr & (PSY_PCIAFSR_PMA | PSY_PCIAFSR_PTA | PSY_PCIAFSR_PTRY |
                    744:            PSY_PCIAFSR_PPERR | PSY_PCIAFSR_SMA | PSY_PCIAFSR_STA |
                    745:            PSY_PCIAFSR_STRY | PSY_PCIAFSR_SPERR);
                    746:
                    747:        if (bits == 0)
                    748:                return (0);
                    749:
                    750:        /*
                    751:         * It's uncorrectable.  Dump the regs and panic.
                    752:         */
                    753:        printf("%s: PCI bus %c error AFAR %llx (pa=%llx) AFSR %llx\n",
                    754:            sc->sc_dev.dv_xname, 'A' + bus, (long long)afar,
                    755:            (long long)iommu_extract(sc->sc_is, (vaddr_t)afar),
                    756:            (long long)afsr);
                    757:
                    758:        psycho_psychoreg_write(sc, psy_pcictl[bus].pci_afsr, bits);
                    759:        return (1);
                    760: }
                    761:
                    762: int
                    763: psycho_bus_a(void *arg)
                    764: {
                    765:        struct psycho_softc *sc = arg;
                    766:
                    767:        return (psycho_bus_error(sc, 0));
                    768: }
                    769:
                    770: int
                    771: psycho_bus_b(void *arg)
                    772: {
                    773:        struct psycho_softc *sc = arg;
                    774:
                    775:        return (psycho_bus_error(sc, 1));
                    776: }
                    777:
                    778: int
                    779: psycho_powerfail(void *arg)
                    780: {
                    781:        /*
                    782:         * We lost power.  Try to shut down NOW.
                    783:         */
                    784:        printf("Power Failure Detected: Shutting down NOW.\n");
                    785:        boot(RB_POWERDOWN|RB_HALT);
                    786:        return (1);
                    787: }
                    788:
                    789: int
                    790: psycho_wakeup(void *arg)
                    791: {
                    792:        struct psycho_softc *sc = arg;
                    793:
                    794:        /*
                    795:         * Gee, we don't really have a framework to deal with this
                    796:         * properly.
                    797:         */
                    798:        printf("%s: power management wakeup\n", sc->sc_dev.dv_xname);
                    799:        return (1);
                    800: }
                    801:
                    802: /*
                    803:  * initialise the IOMMU..
                    804:  */
                    805: void
                    806: psycho_iommu_init(struct psycho_softc *sc, int tsbsize)
                    807: {
                    808:        struct iommu_state *is = sc->sc_is;
                    809:        int *vdma = NULL, nitem;
                    810:        u_int32_t iobase = -1;
                    811:        char *name;
                    812:
                    813:        /* punch in our copies */
                    814:        is->is_bustag = sc->sc_bustag;
                    815:        bus_space_subregion(sc->sc_bustag, sc->sc_regsh,
                    816:            offsetof(struct psychoreg, psy_iommu), sizeof(struct iommureg),
                    817:            &is->is_iommu);
                    818:
                    819:        /*
                    820:         * Separate the men from the boys.  If it has a `virtual-dma'
                    821:         * property, use it.
                    822:         */
                    823:        if (!getprop(sc->sc_node, "virtual-dma", sizeof(vdma), &nitem,
                    824:            (void **)&vdma)) {
                    825:                /* Damn.  Gotta use these values. */
                    826:                iobase = vdma[0];
                    827: #define        TSBCASE(x)      case 1 << ((x) + 23): tsbsize = (x); break
                    828:                switch (vdma[1]) {
                    829:                        TSBCASE(1); TSBCASE(2); TSBCASE(3);
                    830:                        TSBCASE(4); TSBCASE(5); TSBCASE(6);
                    831:                default:
                    832:                        printf("bogus tsb size %x, using 7\n", vdma[1]);
                    833:                        TSBCASE(7);
                    834:                }
                    835: #undef TSBCASE
                    836:                DPRINTF(PDB_CONF, ("psycho_iommu_init: iobase=0x%x\n", iobase));
                    837:                free(vdma, M_DEVBUF);
                    838:        } else {
                    839:                DPRINTF(PDB_CONF, ("psycho_iommu_init: getprop failed, "
                    840:                    "iobase=0x%x, tsbsize=%d\n", iobase, tsbsize));
                    841:        }
                    842:
                    843:        /* give us a nice name.. */
                    844:        name = (char *)malloc(32, M_DEVBUF, M_NOWAIT);
                    845:        if (name == NULL)
                    846:                panic("couldn't malloc iommu name");
                    847:        snprintf(name, 32, "%s dvma", sc->sc_dev.dv_xname);
                    848:
                    849:        iommu_init(name, is, tsbsize, iobase);
                    850: }
                    851:
                    852: /*
                    853:  * below here is bus space and bus dma support
                    854:  */
                    855:
                    856: bus_space_tag_t
                    857: psycho_alloc_mem_tag(struct psycho_pbm *pp)
                    858: {
                    859:        return (psycho_alloc_bus_tag(pp, "mem",
                    860:            0x02,       /* 32-bit mem space (where's the #define???) */
                    861:            ASI_PRIMARY, ASI_PRIMARY_LITTLE));
                    862: }
                    863:
                    864: bus_space_tag_t
                    865: psycho_alloc_io_tag(struct psycho_pbm *pp)
                    866: {
                    867:        return (psycho_alloc_bus_tag(pp, "io",
                    868:            0x01,       /* IO space (where's the #define???) */
                    869:            ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED));
                    870: }
                    871:
                    872: bus_space_tag_t
                    873: psycho_alloc_config_tag(struct psycho_pbm *pp)
                    874: {
                    875:        return (psycho_alloc_bus_tag(pp, "cfg",
                    876:            0x00,       /* Config space (where's the #define???) */
                    877:            ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED));
                    878: }
                    879:
                    880: bus_space_tag_t
                    881: psycho_alloc_bus_tag(struct psycho_pbm *pp,
                    882:     const char *name, int ss, int asi, int sasi)
                    883: {
                    884:        struct psycho_softc *sc = pp->pp_sc;
                    885:        struct sparc_bus_space_tag *bt;
                    886:
                    887:        bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT);
                    888:        if (bt == NULL)
                    889:                panic("could not allocate psycho bus tag");
                    890:
                    891:        bzero(bt, sizeof *bt);
                    892:
                    893:        snprintf(bt->name, sizeof(bt->name), "%s-pbm_%s(%d-%2.2x)",
                    894:            sc->sc_dev.dv_xname, name, ss, asi);
                    895:
                    896:        bt->cookie = pp;
                    897:        bt->parent = sc->sc_bustag;
                    898:        bt->default_type = ss;
                    899:        bt->asi = asi;
                    900:        bt->sasi = sasi;
                    901:        bt->sparc_bus_map = psycho_bus_map;
                    902:        bt->sparc_bus_mmap = psycho_bus_mmap;
                    903:        bt->sparc_bus_addr = psycho_bus_addr;
                    904:        bt->sparc_intr_establish = psycho_intr_establish;
                    905:
                    906:        return (bt);
                    907: }
                    908:
                    909: bus_dma_tag_t
                    910: psycho_alloc_dma_tag(struct psycho_pbm *pp)
                    911: {
                    912:        struct psycho_softc *sc = pp->pp_sc;
                    913:        bus_dma_tag_t dt, pdt = sc->sc_dmatag;
                    914:
                    915:        dt = (bus_dma_tag_t)malloc(sizeof(struct sparc_bus_dma_tag),
                    916:            M_DEVBUF, M_NOWAIT);
                    917:        if (dt == NULL)
                    918:                panic("could not allocate psycho dma tag");
                    919:
                    920:        bzero(dt, sizeof *dt);
                    921:        dt->_cookie = pp;
                    922:        dt->_parent = pdt;
                    923:        dt->_dmamap_create      = psycho_dmamap_create;
                    924:        dt->_dmamap_destroy     = iommu_dvmamap_destroy;
                    925:        dt->_dmamap_load        = iommu_dvmamap_load;
                    926:        dt->_dmamap_load_raw    = iommu_dvmamap_load_raw;
                    927:        dt->_dmamap_unload      = iommu_dvmamap_unload;
                    928:        if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
                    929:                dt->_dmamap_sync = iommu_dvmamap_sync;
                    930:        else
                    931:                dt->_dmamap_sync = psycho_sabre_dvmamap_sync;
                    932:        dt->_dmamem_alloc       = iommu_dvmamem_alloc;
                    933:        dt->_dmamem_free        = iommu_dvmamem_free;
                    934:        dt->_dmamem_map         = iommu_dvmamem_map;
                    935:        dt->_dmamem_unmap       = iommu_dvmamem_unmap;
                    936:
                    937:        return (dt);
                    938: }
                    939:
                    940: /*
                    941:  * bus space support.  <sparc64/dev/psychoreg.h> has a discussion about
                    942:  * PCI physical addresses.
                    943:  */
                    944:
                    945: int
                    946: psycho_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset,
                    947:     bus_size_t size, int flags, bus_space_handle_t *hp)
                    948: {
                    949:        struct psycho_pbm *pp = t->cookie;
                    950:        int i, ss;
                    951:
                    952:        DPRINTF(PDB_BUSMAP, ("\npsycho_bus_map: type %d off %qx sz %qx "
                    953:            "flags %d", t->default_type, (unsigned long long)offset,
                    954:            (unsigned long long)size, flags));
                    955:
                    956:        ss = t->default_type;
                    957:        DPRINTF(PDB_BUSMAP, (" cspace %d", ss));
                    958:
                    959:        if (t->parent == 0 || t->parent->sparc_bus_map == 0) {
                    960:                printf("\npsycho_bus_map: invalid parent");
                    961:                return (EINVAL);
                    962:        }
                    963:
                    964:        t = t->parent;
                    965:
                    966:        if (flags & BUS_SPACE_MAP_PROMADDRESS) {
                    967:                return ((*t->sparc_bus_map)
                    968:                    (t, t0, offset, size, flags, hp));
                    969:        }
                    970:
                    971:        for (i = 0; i < pp->pp_nrange; i++) {
                    972:                bus_addr_t paddr;
                    973:
                    974:                if (((pp->pp_range[i].cspace >> 24) & 0x03) != ss)
                    975:                        continue;
                    976:
                    977:                paddr = pp->pp_range[i].phys_lo + offset;
                    978:                paddr |= ((bus_addr_t)pp->pp_range[i].phys_hi << 32);
                    979:                DPRINTF(PDB_BUSMAP,
                    980:                    ("\n_psycho_bus_map: mapping paddr space %lx offset %lx "
                    981:                        "paddr %qx",
                    982:                    (long)ss, (long)offset,
                    983:                    (unsigned long long)paddr));
                    984:                return ((*t->sparc_bus_map)(t, t0, paddr, size, flags, hp));
                    985:        }
                    986:        DPRINTF(PDB_BUSMAP, (" FAILED\n"));
                    987:        return (EINVAL);
                    988: }
                    989:
                    990: paddr_t
                    991: psycho_bus_mmap(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t paddr,
                    992:     off_t off, int prot, int flags)
                    993: {
                    994:        bus_addr_t offset = paddr;
                    995:        struct psycho_pbm *pp = t->cookie;
                    996:        int i, ss;
                    997:
                    998:        ss = t->default_type;
                    999:
                   1000:        DPRINTF(PDB_BUSMAP, ("\n_psycho_bus_mmap: prot %d flags %d pa %qx",
                   1001:            prot, flags, (unsigned long long)paddr));
                   1002:
                   1003:        if (t->parent == 0 || t->parent->sparc_bus_mmap == 0) {
                   1004:                printf("\npsycho_bus_mmap: invalid parent");
                   1005:                return (-1);
                   1006:        }
                   1007:
                   1008:        t = t->parent;
                   1009:
                   1010:        for (i = 0; i < pp->pp_nrange; i++) {
                   1011:                bus_addr_t paddr;
                   1012:
                   1013:                if (((pp->pp_range[i].cspace >> 24) & 0x03) != ss)
                   1014:                        continue;
                   1015:
                   1016:                paddr = pp->pp_range[i].phys_lo + offset;
                   1017:                paddr |= ((bus_addr_t)pp->pp_range[i].phys_hi << 32);
                   1018:                DPRINTF(PDB_BUSMAP, ("\npsycho_bus_mmap: mapping paddr "
                   1019:                    "space %lx offset %lx paddr %qx",
                   1020:                    (long)ss, (long)offset,
                   1021:                    (unsigned long long)paddr));
                   1022:                return ((*t->sparc_bus_mmap)(t, t0, paddr, off, prot, flags));
                   1023:        }
                   1024:
                   1025:        return (-1);
                   1026: }
                   1027:
                   1028: bus_addr_t
                   1029: psycho_bus_addr(bus_space_tag_t t, bus_space_tag_t t0, bus_space_handle_t h)
                   1030: {
                   1031:        struct psycho_pbm *pp = t->cookie;
                   1032:        bus_addr_t addr;
                   1033:        int i, ss;
                   1034:
                   1035:        ss = t->default_type;
                   1036:
                   1037:        if (t->parent == 0 || t->parent->sparc_bus_addr == 0) {
                   1038:                printf("\npsycho_bus_addr: invalid parent");
                   1039:                return (-1);
                   1040:        }
                   1041:
                   1042:        t = t->parent;
                   1043:
                   1044:        addr = ((*t->sparc_bus_addr)(t, t0, h));
                   1045:        if (addr == -1)
                   1046:                return (-1);
                   1047:
                   1048:        for (i = 0; i < pp->pp_nrange; i++) {
                   1049:                if (((pp->pp_range[i].cspace >> 24) & 0x03) != ss)
                   1050:                        continue;
                   1051:
                   1052:                return (BUS_ADDR_PADDR(addr) - pp->pp_range[i].phys_lo);
                   1053:        }
                   1054:
                   1055:        return (-1);
                   1056: }
                   1057:
                   1058: /*
                   1059:  * Bus-specific interrupt mapping
                   1060:  */
                   1061: int
                   1062: psycho_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
                   1063: {
                   1064:        struct psycho_pbm *pp = pa->pa_pc->cookie;
                   1065:        struct psycho_softc *sc = pp->pp_sc;
                   1066:        u_int dev;
                   1067:
                   1068:        if (*ihp != (pci_intr_handle_t)-1) {
                   1069:                *ihp |= sc->sc_ign;
                   1070:                return (0);
                   1071:        }
                   1072:
                   1073:        /*
                   1074:         * We didn't find a PROM mapping for this interrupt.  Try to
                   1075:         * construct one ourselves based on the swizzled interrupt pin
                   1076:         * and the interrupt mapping for PCI slots documented in the
                   1077:         * UltraSPARC-IIi User's Manual.
                   1078:         */
                   1079:
                   1080:        if (pa->pa_intrpin == 0)
                   1081:                return (-1);
                   1082:
                   1083:        /*
                   1084:         * This deserves some documentation.  Should anyone
                   1085:         * have anything official looking, please speak up.
                   1086:         */
                   1087:        if (sc->sc_mode == PSYCHO_MODE_PSYCHO &&
                   1088:            pp->pp_id == PSYCHO_PBM_B)
                   1089:                dev = PCITAG_DEV(pa->pa_intrtag) - 2;
                   1090:        else
                   1091:                dev = PCITAG_DEV(pa->pa_intrtag) - 1;
                   1092:
                   1093:        *ihp = (pa->pa_intrpin - 1) & INTMAP_PCIINT;
                   1094:        *ihp |= ((pp->pp_id == PSYCHO_PBM_B) ? INTMAP_PCIBUS : 0);
                   1095:        *ihp |= (dev << 2) & INTMAP_PCISLOT;
                   1096:        *ihp |= sc->sc_ign;
                   1097:
                   1098:        return (0);
                   1099: }
                   1100:
                   1101: /*
                   1102:  * install an interrupt handler for a PCI device
                   1103:  */
                   1104: void *
                   1105: psycho_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle,
                   1106:     int level, int flags, int (*handler)(void *), void *arg, const char *what)
                   1107: {
                   1108:        struct psycho_pbm *pp = t->cookie;
                   1109:        struct psycho_softc *sc = pp->pp_sc;
                   1110:        struct intrhand *ih;
                   1111:        volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL;
                   1112:        int64_t intrmap = 0;
                   1113:        int ino;
                   1114:        long vec = INTVEC(ihandle);
                   1115:
                   1116:        /*
                   1117:         * Hunt through all the interrupt mapping regs to look for our
                   1118:         * interrupt vector.
                   1119:         *
                   1120:         * XXX We only compare INOs rather than IGNs since the firmware may
                   1121:         * not provide the IGN and the IGN is constant for all device on that
                   1122:         * PCI controller.  This could cause problems for the FFB/external
                   1123:         * interrupt which has a full vector that can be set arbitrarily.
                   1124:         */
                   1125:
                   1126:        DPRINTF(PDB_INTR,
                   1127:            ("\npsycho_intr_establish: ihandle %x vec %lx", ihandle, vec));
                   1128:        ino = INTINO(vec);
                   1129:        DPRINTF(PDB_INTR, (" ino %x", ino));
                   1130:
                   1131:        /* If the device didn't ask for an IPL, use the one encoded. */
                   1132:        if (level == IPL_NONE)
                   1133:                level = INTLEV(vec);
                   1134:        /* If it still has no level, print a warning and assign IPL 2 */
                   1135:        if (level == IPL_NONE) {
                   1136:                printf("ERROR: no IPL, setting IPL 2.\n");
                   1137:                level = 2;
                   1138:        }
                   1139:
                   1140:        if (flags & BUS_INTR_ESTABLISH_SOFTINTR)
                   1141:                goto found;
                   1142:
                   1143:        DPRINTF(PDB_INTR,
                   1144:            ("\npsycho: intr %lx: %p\nHunting for IRQ...\n",
                   1145:            (long)ino, intrlev[ino]));
                   1146:
                   1147:        /*
                   1148:         * First look for PCI interrupts, otherwise the PCI A slot 0
                   1149:         * INTA# interrupt might match an unused non-PCI (obio)
                   1150:         * interrupt.
                   1151:         */
                   1152:
                   1153:        for (intrmapptr = psycho_psychoreg_vaddr(sc, pcia_slot0_int),
                   1154:            intrclrptr = psycho_psychoreg_vaddr(sc, pcia0_clr_int[0]);
                   1155:            intrmapptr <= (volatile u_int64_t *)
                   1156:                psycho_psychoreg_vaddr(sc, pcib_slot3_int);
                   1157:            intrmapptr++, intrclrptr += 4) {
                   1158:                /* Skip PCI-A Slot 2 and PCI-A Slot 3 on psycho's */
                   1159:                if (sc->sc_mode == PSYCHO_MODE_PSYCHO &&
                   1160:                    (intrmapptr ==
                   1161:                        psycho_psychoreg_vaddr(sc, pcia_slot2_int) ||
                   1162:                    intrmapptr ==
                   1163:                        psycho_psychoreg_vaddr(sc, pcia_slot3_int)))
                   1164:                        continue;
                   1165:
                   1166:                if (((*intrmapptr ^ vec) & 0x3c) == 0) {
                   1167:                        intrclrptr += vec & 0x3;
                   1168:                        goto found;
                   1169:                }
                   1170:        }
                   1171:
                   1172:        /* Now hunt through obio.  */
                   1173:        for (intrmapptr = psycho_psychoreg_vaddr(sc, scsi_int_map),
                   1174:            intrclrptr = psycho_psychoreg_vaddr(sc, scsi_clr_int);
                   1175:            intrmapptr < (volatile u_int64_t *)
                   1176:                psycho_psychoreg_vaddr(sc, ffb0_int_map);
                   1177:            intrmapptr++, intrclrptr++) {
                   1178:                if (INTINO(*intrmapptr) == ino)
                   1179:                        goto found;
                   1180:        }
                   1181:
                   1182:        printf("Cannot find interrupt vector %lx\n", vec);
                   1183:        return (NULL);
                   1184:
                   1185: found:
                   1186:        ih = bus_intr_allocate(t0, handler, arg, ino | sc->sc_ign, level,
                   1187:            intrmapptr, intrclrptr, what);
                   1188:        if (ih == NULL) {
                   1189:                printf("Cannot allocate interrupt vector %lx\n", vec);
                   1190:                return (NULL);
                   1191:        }
                   1192:
                   1193:        DPRINTF(PDB_INTR, (
                   1194:            "\ninstalling handler %p arg %p with number %x pil %u",
                   1195:            ih->ih_fun, ih->ih_arg, ih->ih_number, ih->ih_pil));
                   1196:
                   1197:        intr_establish(ih->ih_pil, ih);
                   1198:
                   1199:        /*
                   1200:         * Enable the interrupt now we have the handler installed.
                   1201:         * Read the current value as we can't change it besides the
                   1202:         * valid bit so so make sure only this bit is changed.
                   1203:         *
                   1204:         * XXXX --- we really should use bus_space for this.
                   1205:         */
                   1206:        if (intrmapptr) {
                   1207:                intrmap = *intrmapptr;
                   1208:                DPRINTF(PDB_INTR, ("; read intrmap = %016qx",
                   1209:                        (unsigned long long)intrmap));
                   1210:
                   1211:                /* Enable the interrupt */
                   1212:                intrmap |= INTMAP_V;
                   1213:                DPRINTF(PDB_INTR, ("; addr of intrmapptr = %p", intrmapptr));
                   1214:                DPRINTF(PDB_INTR, ("; writing intrmap = %016qx",
                   1215:                        (unsigned long long)intrmap));
                   1216:                *intrmapptr = intrmap;
                   1217:                DPRINTF(PDB_INTR, ("; reread intrmap = %016qx",
                   1218:                        (unsigned long long)(intrmap = *intrmapptr)));
                   1219:        }
                   1220:        return (ih);
                   1221: }
                   1222:
                   1223: /*
                   1224:  * hooks into the iommu dvma calls.
                   1225:  */
                   1226: int
                   1227: psycho_dmamap_create(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size,
                   1228:     int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags,
                   1229:     bus_dmamap_t *dmamp)
                   1230: {
                   1231:        struct psycho_pbm *pp = t->_cookie;
                   1232:
                   1233:        return (iommu_dvmamap_create(t, t0, &pp->pp_sb, size, nsegments,
                   1234:            maxsegsz, boundary, flags, dmamp));
                   1235: }
                   1236:
                   1237: void
                   1238: psycho_sabre_dvmamap_sync(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dmamap_t map,
                   1239:     bus_size_t offset, bus_size_t len, int ops)
                   1240: {
                   1241:        struct psycho_pbm *pp = t->_cookie;
                   1242:        struct psycho_softc *sc = pp->pp_sc;
                   1243:
                   1244:        if (ops & BUS_DMASYNC_POSTREAD)
                   1245:                psycho_psychoreg_read(sc, pci_dma_write_sync);
                   1246:
                   1247:        if (ops & (BUS_DMASYNC_POSTREAD | BUS_DMASYNC_PREWRITE))
                   1248:                membar(MemIssue);
                   1249: }
                   1250:

CVSweb