[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

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