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

Annotation of sys/arch/sparc/dev/sbus.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: sbus.c,v 1.16 2007/05/29 09:54:13 sobrado Exp $       */
        !             2: /*     $NetBSD: sbus.c,v 1.17 1997/06/01 22:10:39 pk Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1992, 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  *
        !             8:  * This software was developed by the Computer Systems Engineering group
        !             9:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
        !            10:  * contributed to Berkeley.
        !            11:  *
        !            12:  * All advertising materials mentioning features or use of this software
        !            13:  * must display the following acknowledgement:
        !            14:  *     This product includes software developed by the University of
        !            15:  *     California, Lawrence Berkeley Laboratory.
        !            16:  *
        !            17:  * Redistribution and use in source and binary forms, with or without
        !            18:  * modification, are permitted provided that the following conditions
        !            19:  * are met:
        !            20:  * 1. Redistributions of source code must retain the above copyright
        !            21:  *    notice, this list of conditions and the following disclaimer.
        !            22:  * 2. Redistributions in binary form must reproduce the above copyright
        !            23:  *    notice, this list of conditions and the following disclaimer in the
        !            24:  *    documentation and/or other materials provided with the distribution.
        !            25:  * 3. Neither the name of the University nor the names of its contributors
        !            26:  *    may be used to endorse or promote products derived from this software
        !            27:  *    without specific prior written permission.
        !            28:  *
        !            29:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            30:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            31:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            32:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            33:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            34:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            35:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            36:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            37:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            38:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            39:  * SUCH DAMAGE.
        !            40:  *
        !            41:  *     @(#)sbus.c      8.1 (Berkeley) 6/11/93
        !            42:  */
        !            43:
        !            44: /*
        !            45:  * SBus stuff.
        !            46:  */
        !            47:
        !            48: #include <sys/param.h>
        !            49: #include <sys/malloc.h>
        !            50: #include <sys/systm.h>
        !            51: #include <sys/device.h>
        !            52: #include <uvm/uvm_extern.h>
        !            53:
        !            54: #include <machine/autoconf.h>
        !            55:
        !            56: #include <sparc/dev/sbusreg.h>
        !            57: #include <sparc/dev/sbusvar.h>
        !            58: #include <sparc/dev/xboxreg.h>
        !            59: #include <sparc/dev/xboxvar.h>
        !            60: #include <sparc/dev/dmareg.h>
        !            61:
        !            62: int sbus_print(void *, const char *);
        !            63:
        !            64: /* autoconfiguration driver */
        !            65: void   sbus_attach(struct device *, struct device *, void *);
        !            66: int    sbus_match(struct device *, void *, void *);
        !            67:
        !            68: struct cfattach sbus_ca = {
        !            69:        sizeof(struct sbus_softc), sbus_match, sbus_attach
        !            70: };
        !            71:
        !            72: struct cfdriver sbus_cd = {
        !            73:        NULL, "sbus", DV_DULL
        !            74: };
        !            75:
        !            76: /*
        !            77:  * Print the location of some sbus-attached device (called just
        !            78:  * before attaching that device).  If `sbus' is not NULL, the
        !            79:  * device was found but not configured; print the sbus as well.
        !            80:  * Return UNCONF (config_find ignores this if the device was configured).
        !            81:  */
        !            82: int
        !            83: sbus_print(args, sbus)
        !            84:        void *args;
        !            85:        const char *sbus;
        !            86: {
        !            87:        struct confargs *ca = args;
        !            88:        char *class;
        !            89:        static char *sl = "slave-only";
        !            90:
        !            91:        if (sbus != NULL) {
        !            92:                printf("\"%s\" at %s", ca->ca_ra.ra_name, sbus);
        !            93:                class = getpropstring(ca->ca_ra.ra_node, "device_type");
        !            94:                if (*class != '\0')
        !            95:                        printf(" class %s", class);
        !            96:        }
        !            97:        /* Check root node for 'slave-only' property */
        !            98:        if (getpropint(0, sl, 0) & (1 << ca->ca_slot))
        !            99:                printf(" %s", sl);
        !           100:        printf(" slot %d offset 0x%x", ca->ca_slot, ca->ca_offset);
        !           101:        return (UNCONF);
        !           102: }
        !           103:
        !           104: int
        !           105: sbus_match(parent, vcf, aux)
        !           106:        struct device *parent;
        !           107:        void *vcf, *aux;
        !           108: {
        !           109:        register struct cfdata *cf = vcf;
        !           110:        register struct confargs *ca = aux;
        !           111:        register struct romaux *ra = &ca->ca_ra;
        !           112:
        !           113:        if (CPU_ISSUN4)
        !           114:                return (0);
        !           115:
        !           116:        if (ca->ca_bustype == BUS_XBOX) {
        !           117:                struct xbox_softc *xsc = (struct xbox_softc *)parent;
        !           118:
        !           119:                /* Prevent multiple attachments */
        !           120:                if (xsc->sc_attached == 0) {
        !           121:                        xsc->sc_attached = 1;
        !           122:                        return (1);
        !           123:                }
        !           124:
        !           125:                return (0);
        !           126:        }
        !           127:
        !           128:        return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0);
        !           129: }
        !           130:
        !           131: /*
        !           132:  * Attach an SBus.
        !           133:  */
        !           134: void
        !           135: sbus_attach(parent, self, aux)
        !           136:        struct device *parent;
        !           137:        struct device *self;
        !           138:        void *aux;
        !           139: {
        !           140:        register struct sbus_softc *sc = (struct sbus_softc *)self;
        !           141:        struct confargs *ca = aux;
        !           142:        register struct romaux *ra = &ca->ca_ra;
        !           143:        register int node;
        !           144:        register char *name;
        !           145:        struct confargs oca;
        !           146:        int rlen;
        !           147:
        !           148:        /*
        !           149:         * XXX there is only one SBus, for now -- do not know how to
        !           150:         * address children on others
        !           151:         */
        !           152:        if (sc->sc_dev.dv_unit > 0 && ca->ca_bustype != BUS_XBOX) {
        !           153:                printf(" unsupported\n");
        !           154:                return;
        !           155:        }
        !           156:
        !           157:        /*
        !           158:         * Record clock frequency for synchronous SCSI.
        !           159:         * IS THIS THE CORRECT DEFAULT??
        !           160:         */
        !           161:        node = ra->ra_node;
        !           162:        sc->sc_clockfreq = getpropint(node, "clock-frequency", 25*1000*1000);
        !           163:        printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq));
        !           164:
        !           165:        /*
        !           166:         * Get the SBus burst transfer size if burst transfers are supported
        !           167:         */
        !           168:        sc->sc_burst = getpropint(node, "burst-sizes", 0);
        !           169:        sc->sc_burst = sc->sc_burst & ~SBUS_BURST_64;
        !           170:
        !           171:        if (ca->ca_bustype == BUS_XBOX) {
        !           172:                struct xbox_softc *xsc = (struct xbox_softc *)parent;
        !           173:
        !           174:                /* Parent has already done the leg work */
        !           175:                sc->sc_nrange = xsc->sc_nrange;
        !           176:                sc->sc_range = xsc->sc_range;
        !           177:                xsc->sc_attached = 2;
        !           178:        }
        !           179:        else {
        !           180:                if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "sbus") == 0)
        !           181:                        oca.ca_ra.ra_bp = ra->ra_bp + 1;
        !           182:                else
        !           183:                        oca.ca_ra.ra_bp = NULL;
        !           184:
        !           185:                rlen = getproplen(node, "ranges");
        !           186:                if (rlen > 0) {
        !           187:                        sc->sc_nrange = rlen / sizeof(struct rom_range);
        !           188:                        sc->sc_range =
        !           189:                                (struct rom_range *)malloc(rlen, M_DEVBUF, M_NOWAIT);
        !           190:                        if (sc->sc_range == 0)
        !           191:                                panic("sbus: PROM ranges too large: %d", rlen);
        !           192:                        (void)getprop(node, "ranges", sc->sc_range, rlen);
        !           193:                }
        !           194:        }
        !           195:
        !           196:        /*
        !           197:         * Loop through ROM children, fixing any relative addresses
        !           198:         * and then configuring each device.
        !           199:         */
        !           200:        for (node = firstchild(node); node; node = nextsibling(node)) {
        !           201:                name = getpropstring(node, "name");
        !           202:                if (!romprop(&oca.ca_ra, name, node))
        !           203:                        continue;
        !           204:
        !           205:                sbus_translate(self, &oca);
        !           206:                oca.ca_bustype = BUS_SBUS;
        !           207:                (void) config_found(&sc->sc_dev, (void *)&oca, sbus_print);
        !           208:        }
        !           209: }
        !           210:
        !           211: void
        !           212: sbus_translate(dev, ca)
        !           213:        struct device *dev;
        !           214:        struct confargs *ca;
        !           215: {
        !           216:        struct sbus_softc *sc = (struct sbus_softc *)dev;
        !           217:        register int base, slot;
        !           218:        register int i;
        !           219:
        !           220:        if (sc->sc_nrange == 0) {
        !           221:                /* Old-style SBus configuration */
        !           222:                base = (int)ca->ca_ra.ra_paddr;
        !           223:                if (SBUS_ABS(base)) {
        !           224:                        ca->ca_slot = SBUS_ABS_TO_SLOT(base);
        !           225:                        ca->ca_offset = SBUS_ABS_TO_OFFSET(base);
        !           226:                } else {
        !           227:                        if (!CPU_ISSUN4C)
        !           228:                                panic("relative sbus addressing not supported");
        !           229:                        ca->ca_slot = slot = ca->ca_ra.ra_iospace;
        !           230:                        ca->ca_offset = base;
        !           231:                        ca->ca_ra.ra_paddr = (void *)SBUS_ADDR(slot, base);
        !           232:                        ca->ca_ra.ra_iospace = PMAP_OBIO;
        !           233:
        !           234:                        /* Fix any remaining register banks */
        !           235:                        for (i = 1; i < ca->ca_ra.ra_nreg; i++) {
        !           236:                                base = (int)ca->ca_ra.ra_reg[i].rr_paddr;
        !           237:                                ca->ca_ra.ra_reg[i].rr_paddr =
        !           238:                                        (void *)SBUS_ADDR(slot, base);
        !           239:                                ca->ca_ra.ra_reg[i].rr_iospace = PMAP_OBIO;
        !           240:                        }
        !           241:                }
        !           242:
        !           243:        } else {
        !           244:
        !           245:                ca->ca_slot = ca->ca_ra.ra_iospace;
        !           246:                ca->ca_offset = (int)ca->ca_ra.ra_paddr;
        !           247:
        !           248:                /* Translate into parent address spaces */
        !           249:                for (i = 0; i < ca->ca_ra.ra_nreg; i++) {
        !           250:                        int j, cspace = ca->ca_ra.ra_reg[i].rr_iospace;
        !           251:
        !           252:                        for (j = 0; j < sc->sc_nrange; j++) {
        !           253:                                if (sc->sc_range[j].cspace == cspace) {
        !           254:                                        (int)ca->ca_ra.ra_reg[i].rr_paddr +=
        !           255:                                                sc->sc_range[j].poffset;
        !           256:                                        (int)ca->ca_ra.ra_reg[i].rr_iospace =
        !           257:                                                sc->sc_range[j].pspace;
        !           258:                                        break;
        !           259:                                }
        !           260:                        }
        !           261:                }
        !           262:        }
        !           263: }
        !           264:
        !           265: /*
        !           266:  * Returns true if this sbus slot is capable of dma
        !           267:  */
        !           268: int
        !           269: sbus_testdma(sc, ca)
        !           270:        struct sbus_softc *sc;
        !           271:        struct confargs *ca;
        !           272: {
        !           273:         struct romaux *ra = &ca->ca_ra;
        !           274:
        !           275:        /*
        !           276:         * XXX how to handle more than one sbus?
        !           277:         */
        !           278:
        !           279:        if (getpropint(0, "slave-only", 0) & (1 << ca->ca_slot)) {
        !           280:                printf("%s: dma card found in non-dma sbus slot %d"
        !           281:                        ": not supported\n", ra->ra_name, ca->ca_slot);
        !           282:                return (0);
        !           283:        }
        !           284:
        !           285:        return (1);
        !           286: }

CVSweb