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

Annotation of sys/arch/mac68k/dev/nubus.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: nubus.c,v 1.33 2007/04/10 17:47:54 miod Exp $ */
        !             2: /*     $NetBSD: nubus.c,v 1.53 2002/04/13 17:49:41 briggs Exp $        */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995, 1996 Allen Briggs.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by Allen Briggs.
        !            18:  * 4. The name of the author may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: #include <sys/param.h>
        !            34: #include <sys/systm.h>
        !            35: #include <sys/malloc.h>
        !            36: #include <sys/device.h>
        !            37: #include <sys/buf.h>
        !            38: #include <sys/conf.h>
        !            39:
        !            40: #include <uvm/uvm_extern.h>
        !            41:
        !            42: #include <machine/autoconf.h>
        !            43: #include <machine/bus.h>
        !            44: #include <machine/vmparam.h>
        !            45: #include <machine/param.h>
        !            46: #include <machine/cpu.h>
        !            47: #include <machine/pte.h>
        !            48: #include <machine/viareg.h>
        !            49:
        !            50: #include <mac68k/dev/nubus.h>
        !            51:
        !            52: #ifdef DEBUG
        !            53: #define NDB_PROBE      0x1
        !            54: #define NDB_FOLLOW     0x2
        !            55: #define NDB_ARITH      0x4
        !            56: static int     nubus_debug = 0 /* | NDB_PROBE | NDB_FOLLOW | NDB_ARITH */ ;
        !            57: #endif
        !            58:
        !            59: static int     nubus_print(void *, const char *);
        !            60: static int     nubus_match(struct device *, void *, void *);
        !            61: static void    nubus_attach(struct device *, struct device *, void *);
        !            62: static int     nubus_video_resource(int);
        !            63:
        !            64: static int     nubus_probe_slot(bus_space_tag_t, bus_space_handle_t,
        !            65:                    int, nubus_slot *);
        !            66: static u_int32_t nubus_calc_CRC(bus_space_tag_t, bus_space_handle_t,
        !            67:                    nubus_slot *);
        !            68:
        !            69: static u_long  nubus_adjust_ptr(u_int8_t, u_long, long);
        !            70: static u_int8_t        nubus_read_1(bus_space_tag_t, bus_space_handle_t,
        !            71:                    u_int8_t, u_long);
        !            72: #ifdef notyet
        !            73: static u_int16_t nubus_read_2(bus_space_tag_t, bus_space_handle_t,
        !            74:                    u_int8_t, u_long);
        !            75: #endif
        !            76: static u_int32_t nubus_read_4(bus_space_tag_t, bus_space_handle_t,
        !            77:                    u_int8_t, u_long);
        !            78:
        !            79: struct cfattach nubus_ca = {
        !            80:        sizeof(struct nubus_softc), nubus_match, nubus_attach
        !            81: };
        !            82:
        !            83: struct cfdriver nubus_cd = {
        !            84:        NULL, "nubus", DV_DULL,
        !            85: };
        !            86:
        !            87: static int
        !            88: nubus_match(parent, cf, aux)
        !            89:        struct device *parent;
        !            90:        void *cf;
        !            91:        void *aux;
        !            92: {
        !            93:        static int nubus_matched = 0;
        !            94:
        !            95:        /* Allow only one instance. */
        !            96:        if (nubus_matched)
        !            97:                return (0);
        !            98:
        !            99:        nubus_matched = 1;
        !           100:        return (1);
        !           101: }
        !           102:
        !           103: static void
        !           104: nubus_attach(parent, self, aux)
        !           105:        struct device *parent, *self;
        !           106:        void *aux;
        !           107: {
        !           108:        struct nubus_attach_args na_args;
        !           109:        bus_space_tag_t bst;
        !           110:        bus_space_handle_t bsh;
        !           111:        nubus_slot fmtblock;
        !           112:        nubus_dir dir;
        !           113:        nubus_dirent dirent;
        !           114:        nubus_type slottype;
        !           115:        u_long entry;
        !           116:        int i, rsrcid;
        !           117:        u_int8_t lanes;
        !           118:
        !           119:        printf("\n");
        !           120:
        !           121:        for (i = NUBUS_MIN_SLOT; i <= NUBUS_MAX_SLOT; i++) {
        !           122:                na_args.slot = i;
        !           123:                na_args.na_tag = bst = MAC68K_BUS_SPACE_MEM;
        !           124:
        !           125:                if (bus_space_map(bst,
        !           126:                    NUBUS_SLOT2PA(na_args.slot), NBMEMSIZE, 0, &bsh)) {
        !           127: #ifdef DEBUG
        !           128:                        if (nubus_debug & NDB_PROBE)
        !           129:                                printf("%s: failed to map slot %x, "
        !           130:                                "address %p (in use?)\n",
        !           131:                                self->dv_xname, i,
        !           132:                                (void *)NUBUS_SLOT2PA(i));
        !           133: #endif
        !           134:                        continue;
        !           135:                }
        !           136:
        !           137:                if (nubus_probe_slot(bst, bsh, i, &fmtblock) <= 0) {
        !           138: notfound:
        !           139:                        bus_space_unmap(bst, bsh, NBMEMSIZE);
        !           140:                        continue;
        !           141:                }
        !           142:
        !           143:                rsrcid = 0x80;
        !           144:                lanes = fmtblock.bytelanes;
        !           145:
        !           146:                nubus_get_main_dir(&fmtblock, &dir);
        !           147:
        !           148:                /*
        !           149:                 * Get the resource for the first function on the card.
        !           150:                 * This is assumed to be at resource ID 0x80.  If we can
        !           151:                 * not find this entry (as we can not on some video cards),
        !           152:                 * check to see if we can get a different ID from the list
        !           153:                 * of video resources given to us by the booter.  If that
        !           154:                 * doesn't work either, take the first resource following
        !           155:                 * the board resource.
        !           156:                 * If we only find a board resource, report that.
        !           157:                 * There are cards that do not have anything else; their
        !           158:                 * driver then has to match on the board resource and
        !           159:                 * the card name.
        !           160:                 */
        !           161:                if (nubus_find_rsrc(bst, bsh,
        !           162:                    &fmtblock, &dir, rsrcid, &dirent) <= 0) {
        !           163:                        if ((rsrcid = nubus_video_resource(i)) == -1) {
        !           164:                                int has_board_rsrc = 0;
        !           165:
        !           166:                                /*
        !           167:                                 * Since nubus_find_rsrc failed, the directory
        !           168:                                 * is back at its base.
        !           169:                                 */
        !           170:                                entry = dir.curr_ent;
        !           171:
        !           172:                                /*
        !           173:                                 * All nubus cards should have a board
        !           174:                                 * resource, but be sure that's what it
        !           175:                                 * is before we skip it, and note the fact.
        !           176:                                 */
        !           177:                                rsrcid = nubus_read_1(bst, bsh,
        !           178:                                    lanes, entry);
        !           179:                                if (rsrcid == 0x1) {
        !           180:                                        has_board_rsrc = 1;
        !           181:                                        entry = nubus_adjust_ptr(lanes,
        !           182:                                            dir.curr_ent, 4);
        !           183:                                }
        !           184:                                rsrcid = nubus_read_1(bst, bsh, lanes, entry);
        !           185:                                /* end of chain? */
        !           186:                                if (rsrcid == 0xff) {
        !           187:                                        if (!has_board_rsrc)
        !           188:                                                goto notfound;
        !           189:                                        else
        !           190:                                                rsrcid = 0x01;
        !           191:                                }
        !           192: #ifdef DEBUG
        !           193:                                if (nubus_debug & NDB_FOLLOW)
        !           194:                                        printf("\tUsing rsrc 0x%x.\n", rsrcid);
        !           195: #endif
        !           196:                        }
        !           197:                        /*
        !           198:                         * Try to find the resource passed by the booter
        !           199:                         * or the one we just tracked down.
        !           200:                         */
        !           201:                        if (nubus_find_rsrc(bst, bsh,
        !           202:                            &fmtblock, &dir, rsrcid, &dirent) <= 0)
        !           203:                                goto notfound;
        !           204:                }
        !           205:
        !           206:                nubus_get_dir_from_rsrc(&fmtblock, &dirent, &dir);
        !           207:
        !           208:                if (nubus_find_rsrc(bst, bsh,
        !           209:                    &fmtblock, &dir, NUBUS_RSRC_TYPE, &dirent) <= 0)
        !           210:                        goto notfound;
        !           211:
        !           212:                if (nubus_get_ind_data(bst, bsh, &fmtblock, &dirent,
        !           213:                    (caddr_t)&slottype, sizeof(nubus_type)) <= 0)
        !           214:                        goto notfound;
        !           215:
        !           216:                /*
        !           217:                 * If this is a display card, try to pull out the correct
        !           218:                 * display mode as passed by the booter.
        !           219:                 */
        !           220:                if (slottype.category == NUBUS_CATEGORY_DISPLAY) {
        !           221:                        int r;
        !           222:
        !           223:                        if ((r = nubus_video_resource(i)) != -1) {
        !           224:
        !           225:                                nubus_get_main_dir(&fmtblock, &dir);
        !           226:
        !           227:                                if (nubus_find_rsrc(bst, bsh,
        !           228:                                    &fmtblock, &dir, r, &dirent) <= 0)
        !           229:                                        goto notfound;
        !           230:
        !           231:                                nubus_get_dir_from_rsrc(&fmtblock,
        !           232:                                    &dirent, &dir);
        !           233:
        !           234:                                if (nubus_find_rsrc(bst, bsh, &fmtblock, &dir,
        !           235:                                    NUBUS_RSRC_TYPE, &dirent) <= 0)
        !           236:                                        goto notfound;
        !           237:
        !           238:                                if (nubus_get_ind_data(bst, bsh,
        !           239:                                    &fmtblock, &dirent, (caddr_t)&slottype,
        !           240:                                    sizeof(nubus_type)) <= 0)
        !           241:                                        goto notfound;
        !           242:
        !           243:                                rsrcid = r;
        !           244:                        }
        !           245:                }
        !           246:
        !           247:                na_args.slot = i;
        !           248:                na_args.rsrcid = rsrcid;
        !           249:                na_args.category = slottype.category;
        !           250:                na_args.type = slottype.type;
        !           251:                na_args.drsw = slottype.drsw;
        !           252:                na_args.drhw = slottype.drhw;
        !           253:                na_args.fmt = &fmtblock;
        !           254:
        !           255:                bus_space_unmap(bst, bsh, NBMEMSIZE);
        !           256:
        !           257:                config_found(self, &na_args, nubus_print);
        !           258:        }
        !           259:
        !           260:        enable_nubus_intr();
        !           261: }
        !           262:
        !           263: static int
        !           264: nubus_print(aux, pnp)
        !           265:        void *aux;
        !           266:        const char *pnp;
        !           267: {
        !           268:        struct nubus_attach_args *na = (struct nubus_attach_args *)aux;
        !           269:        bus_space_tag_t bst = na->na_tag;
        !           270:        bus_space_handle_t bsh;
        !           271:
        !           272:        if (pnp) {
        !           273:                printf("%s slot %x", pnp, na->slot);
        !           274:                if (bus_space_map(bst,
        !           275:                    NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 0, &bsh) == 0) {
        !           276:                        printf(": %s", nubus_get_card_name(bst, bsh, na->fmt));
        !           277:                        printf(" (Vendor: %s,", nubus_get_vendor(bst, bsh,
        !           278:                            na->fmt, NUBUS_RSRC_VEND_ID));
        !           279:                        printf(" Part: %s)", nubus_get_vendor(bst, bsh,
        !           280:                            na->fmt, NUBUS_RSRC_VEND_PART));
        !           281:
        !           282:                        bus_space_unmap(bst, bsh, NBMEMSIZE);
        !           283:                }
        !           284: #ifdef DIAGNOSTIC
        !           285:                else
        !           286:                        printf(":");
        !           287:                printf(" Type: %04x %04x %04x %04x",
        !           288:                    na->category, na->type, na->drsw, na->drhw);
        !           289: #endif
        !           290:        } else {
        !           291:                printf(" slot %x", na->slot);
        !           292:        }
        !           293:        return (UNCONF);
        !           294: }
        !           295:
        !           296: static int
        !           297: nubus_video_resource(slot)
        !           298:        int slot;
        !           299: {
        !           300:        extern u_int16_t mac68k_vrsrc_vec[];
        !           301:        int i;
        !           302:
        !           303:        for (i = 0 ; i < 6 ; i++)
        !           304:                if ((mac68k_vrsrc_vec[i] & 0xff) == slot)
        !           305:                        return ((mac68k_vrsrc_vec[i] >> 8) & 0xff);
        !           306:        return (-1);
        !           307: }
        !           308:
        !           309: /*
        !           310:  * Probe a given nubus slot.  If a card is there and we can get the
        !           311:  * format block from its clutching decl. ROMs, fill the format block
        !           312:  * and return non-zero.  If we can't find a card there with a valid
        !           313:  * decl. ROM, return 0.
        !           314:  *
        !           315:  * First, we check to see if we can access the memory at the tail
        !           316:  * end of the slot.  If so, then we check for a bytelanes byte.  We
        !           317:  * could probably just return a failure status if we bus error on
        !           318:  * the first try, but there really is little reason not to go ahead
        !           319:  * and check the other three locations in case there's a weird card
        !           320:  * out there.
        !           321:  *
        !           322:  * Checking for a card involves locating the "bytelanes" byte which
        !           323:  * tells us how to interpret the declaration ROM's data.  The format
        !           324:  * block is at the top of the card's standard memory space and the
        !           325:  * bytelanes byte is at the end of that block.
        !           326:  *
        !           327:  * After some inspection of the bytelanes byte, it appears that it
        !           328:  * takes the form 0xXY where Y is a bitmask of the bytelanes in use
        !           329:  * and X is a bitmask of the lanes to ignore.  Hence, (X ^ Y) == 0
        !           330:  * and (less obviously), Y will have the upper N bits clear if it is
        !           331:  * found N bytes from the last possible location.  Both that and
        !           332:  * the exclusive-or check are made.
        !           333:  *
        !           334:  * If a valid
        !           335:  */
        !           336: static u_int8_t        nbits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
        !           337: static int
        !           338: nubus_probe_slot(bst, bsh, slot, fmt)
        !           339:        bus_space_tag_t bst;
        !           340:        bus_space_handle_t bsh;
        !           341:        int slot;
        !           342:        nubus_slot *fmt;
        !           343: {
        !           344:        u_long ofs, hdr;
        !           345:        int i, j, found, hdr_size;
        !           346:        u_int8_t lanes;
        !           347:
        !           348: #ifdef DEBUG
        !           349:        if (nubus_debug & NDB_PROBE)
        !           350:                printf("probing slot %x\n", slot);
        !           351: #endif
        !           352:
        !           353:        /*
        !           354:         * The idea behind this glorious work of art is to probe for only
        !           355:         * valid bytelanes values at appropriate locations (see DC&D p. 159
        !           356:         * for a list).  Note the pattern:  the first 8 values are at offset
        !           357:         * 0xffffff in the slot's space; the next 4 values at 0xfffffe; the
        !           358:         * next 2 values at 0xfffffd; and the last one at 0xfffffc.
        !           359:         *
        !           360:         * The nested loops implement an efficient search of this space,
        !           361:         * probing first for a valid address, then checking for each of the
        !           362:         * valid bytelanes values at that address.
        !           363:         */
        !           364:        ofs = NBMEMSIZE;
        !           365:        lanes = 0xf;
        !           366:
        !           367:        for (j = 8, found = 0; j > 0 && !found; j >>= 1) {
        !           368:                ofs--;
        !           369:                for (i = j; i > 0; i--, lanes--) {
        !           370:                        if (!mac68k_bus_space_probe(bst, bsh, ofs, 1)) {
        !           371:                                lanes -= i;
        !           372:                                break;
        !           373:                        }
        !           374:                        if (bus_space_read_1(bst, bsh, ofs) ==
        !           375:                            (((~lanes & 0xf) << 4) | lanes)) {
        !           376:                                found = 1;
        !           377:                                break;
        !           378:                        }
        !           379:                }
        !           380:        }
        !           381:
        !           382:        if (!found) {
        !           383: #ifdef DEBUG
        !           384:                if (nubus_debug & NDB_PROBE)
        !           385:                        printf("bytelanes not found for slot %x\n", slot);
        !           386: #endif
        !           387:                return 0;
        !           388:        }
        !           389:
        !           390:        fmt->bytelanes = lanes;
        !           391:        fmt->step = nbits[(lanes & 0x0f)];
        !           392:        fmt->slot = slot;       /* XXX redundant; get rid of this someday */
        !           393:
        !           394: #ifdef DEBUG
        !           395:        if (nubus_debug & NDB_PROBE)
        !           396:                printf("bytelanes of 0x%x found for slot 0x%x.\n",
        !           397:                    fmt->bytelanes, slot);
        !           398: #endif
        !           399:
        !           400:        /*
        !           401:         * Go ahead and attempt to load format header.
        !           402:         * First, we need to find the first byte beyond memory that
        !           403:         * would be valid.  This is necessary for NUBUS_ROM_offset()
        !           404:         * to work.
        !           405:         */
        !           406:        hdr = NBMEMSIZE;
        !           407:        hdr_size = 20;
        !           408:
        !           409:        i = 0x10 | (lanes & 0x0f);
        !           410:        while ((i & 1) == 0) {
        !           411:                hdr++;
        !           412:                i >>= 1;
        !           413:        }
        !           414:        fmt->top = hdr;
        !           415:        hdr = nubus_adjust_ptr(lanes, hdr, -hdr_size);
        !           416: #ifdef DEBUG
        !           417:        if (nubus_debug & NDB_PROBE)
        !           418:                printf("fmt->top is 0x%lx, that minus 0x%x puts us at 0x%lx.\n",
        !           419:                    fmt->top, hdr_size, hdr);
        !           420:        if (nubus_debug & NDB_ARITH)
        !           421:                for (i = 1 ; i < 8 ; i++)
        !           422:                        printf("0x%lx - 0x%x = 0x%lx, + 0x%x = 0x%lx.\n",
        !           423:                            hdr, i, nubus_adjust_ptr(lanes, hdr, -i),
        !           424:                            i, nubus_adjust_ptr(lanes, hdr,  i));
        !           425: #endif
        !           426:
        !           427:        fmt->directory_offset =
        !           428:            0xff000000 | nubus_read_4(bst, bsh, lanes, hdr);
        !           429:        hdr = nubus_adjust_ptr(lanes, hdr, 4);
        !           430:        fmt->length = nubus_read_4(bst, bsh, lanes, hdr);
        !           431:        hdr = nubus_adjust_ptr(lanes, hdr, 4);
        !           432:        fmt->crc = nubus_read_4(bst, bsh, lanes, hdr);
        !           433:        hdr = nubus_adjust_ptr(lanes, hdr, 4);
        !           434:        fmt->revision_level = nubus_read_1(bst, bsh, lanes, hdr);
        !           435:        hdr = nubus_adjust_ptr(lanes, hdr, 1);
        !           436:        fmt->format = nubus_read_1(bst, bsh, lanes, hdr);
        !           437:        hdr = nubus_adjust_ptr(lanes, hdr, 1);
        !           438:        fmt->test_pattern = nubus_read_4(bst, bsh, lanes, hdr);
        !           439:
        !           440: #ifdef DEBUG
        !           441:        if (nubus_debug & NDB_PROBE) {
        !           442:                printf("Directory offset 0x%x\t", fmt->directory_offset);
        !           443:                printf("Length 0x%x\t", fmt->length);
        !           444:                printf("CRC 0x%x\n", fmt->crc);
        !           445:                printf("Revision level 0x%x\t", fmt->revision_level);
        !           446:                printf("Format 0x%x\t", fmt->format);
        !           447:                printf("Test Pattern 0x%x\n", fmt->test_pattern);
        !           448:        }
        !           449: #endif
        !           450:
        !           451:        if ((fmt->directory_offset & 0x00ff0000) == 0) {
        !           452:                printf("Invalid looking directory offset (0x%x)!\n",
        !           453:                    fmt->directory_offset);
        !           454:                return 0;
        !           455:        }
        !           456:        if (fmt->test_pattern != NUBUS_ROM_TEST_PATTERN) {
        !           457:                printf("Nubus--test pattern invalid:\n");
        !           458:                printf("       slot 0x%x, bytelanes 0x%x?\n", fmt->slot, lanes);
        !           459:                printf("       read test 0x%x, compare with 0x%x.\n",
        !           460:                    fmt->test_pattern, NUBUS_ROM_TEST_PATTERN);
        !           461:                return 0;
        !           462:        }
        !           463:
        !           464:        /* Perform CRC */
        !           465:        if (fmt->crc != nubus_calc_CRC(bst, bsh, fmt)) {
        !           466:                printf("Nubus--crc check failed, slot 0x%x.\n", fmt->slot);
        !           467:                return 0;
        !           468:        }
        !           469:
        !           470:        return 1;
        !           471: }
        !           472:
        !           473: static u_int32_t
        !           474: nubus_calc_CRC(bst, bsh, fmt)
        !           475:        bus_space_tag_t bst;
        !           476:        bus_space_handle_t bsh;
        !           477:        nubus_slot      *fmt;
        !           478: {
        !           479: #if 0
        !           480:        u_long base, ptr, crc_loc;
        !           481:        u_int32_t sum;
        !           482:        u_int8_t lanes = fmt->bytelanes;
        !           483:
        !           484:        base = fmt->top;
        !           485:        crc_loc = NUBUS_ROM_offset(fmt, base, -12);
        !           486:        ptr = NUBUS_ROM_offset(fmt, base, -fmt->length);
        !           487:
        !           488:        sum = 0;
        !           489:        while (ptr < base)
        !           490:                roll #1, sum
        !           491:                if (ptr == crc_loc) {
        !           492:                        roll #3, sum
        !           493:                        ptr = nubus_adjust_ptr(lanes, ptr, 3);
        !           494:                } else {
        !           495:                        sum += nubus_read_1(bst, bsh, lanes, ptr);
        !           496:                }
        !           497:                ptr = nubus_adjust_ptr(lanes, ptr, 1);
        !           498:        }
        !           499:
        !           500:        return sum;
        !           501: #endif
        !           502:        return fmt->crc;
        !           503: }
        !           504:
        !           505: /*
        !           506:  * Compute byte offset on card, taking into account bytelanes.
        !           507:  * Base must be on a valid bytelane for this function to work.
        !           508:  * Return the new address.
        !           509:  *
        !           510:  * XXX -- There has GOT to be a better way to do this.
        !           511:  */
        !           512: static u_long
        !           513: nubus_adjust_ptr(lanes, base, amt)
        !           514:        u_int8_t lanes;
        !           515:        u_long base;
        !           516:        long amt;
        !           517: {
        !           518:        u_int8_t b, t;
        !           519:
        !           520:        if (!amt)
        !           521:                return base;
        !           522:
        !           523:        if (amt < 0) {
        !           524:                amt = -amt;
        !           525:                b = lanes;
        !           526:                t = (b << 4);
        !           527:                b <<= (3 - (base & 0x3));
        !           528:                while (amt) {
        !           529:                        b <<= 1;
        !           530:                        if (b == t)
        !           531:                                b = lanes;
        !           532:                        if (b & 0x08)
        !           533:                                amt--;
        !           534:                        base--;
        !           535:                }
        !           536:                return base;
        !           537:        }
        !           538:
        !           539:        t = (lanes & 0xf) | 0x10;
        !           540:        b = t >> (base & 0x3);
        !           541:        while (amt) {
        !           542:                b >>= 1;
        !           543:                if (b == 1)
        !           544:                        b = t;
        !           545:                if (b & 1)
        !           546:                        amt--;
        !           547:                base++;
        !           548:        }
        !           549:
        !           550:        return base;
        !           551: }
        !           552:
        !           553: static u_int8_t
        !           554: nubus_read_1(bst, bsh, lanes, ofs)
        !           555:        bus_space_tag_t bst;
        !           556:        bus_space_handle_t bsh;
        !           557:        u_int8_t lanes;
        !           558:        u_long ofs;
        !           559: {
        !           560:        return bus_space_read_1(bst, bsh, ofs);
        !           561: }
        !           562:
        !           563: #ifdef notyet
        !           564: /* Nothing uses this, yet */
        !           565: static u_int16_t
        !           566: nubus_read_2(bst, bsh, lanes, ofs)
        !           567:        bus_space_tag_t bst;
        !           568:        bus_space_handle_t bsh;
        !           569:        u_int8_t lanes;
        !           570:        u_long ofs;
        !           571: {
        !           572:        u_int16_t s;
        !           573:
        !           574:        s = (nubus_read_1(bst, bsh, lanes, ofs) << 8);
        !           575:        ofs = nubus_adjust_ptr(lanes, ofs, 1);
        !           576:        s |= nubus_read_1(bst, bsh, lanes, ofs);
        !           577:        return s;
        !           578: }
        !           579: #endif
        !           580:
        !           581: static u_int32_t
        !           582: nubus_read_4(bst, bsh, lanes, ofs)
        !           583:        bus_space_tag_t bst;
        !           584:        bus_space_handle_t bsh;
        !           585:        u_int8_t lanes;
        !           586:        u_long ofs;
        !           587: {
        !           588:        u_int32_t l;
        !           589:        int i;
        !           590:
        !           591:        l = 0;
        !           592:        for (i = 0; i < 4; i++) {
        !           593:                l = (l << 8) | nubus_read_1(bst, bsh, lanes, ofs);
        !           594:                ofs = nubus_adjust_ptr(lanes, ofs, 1);
        !           595:        }
        !           596:        return l;
        !           597: }
        !           598:
        !           599: void
        !           600: nubus_get_main_dir(fmt, dir_return)
        !           601:        nubus_slot *fmt;
        !           602:        nubus_dir *dir_return;
        !           603: {
        !           604: #ifdef DEBUG
        !           605:        if (nubus_debug & NDB_FOLLOW)
        !           606:                printf("nubus_get_main_dir(%p, %p)\n",
        !           607:                    fmt, dir_return);
        !           608: #endif
        !           609:        dir_return->dirbase = nubus_adjust_ptr(fmt->bytelanes, fmt->top,
        !           610:            fmt->directory_offset - 20);
        !           611:        dir_return->curr_ent = dir_return->dirbase;
        !           612: }
        !           613:
        !           614: void
        !           615: nubus_get_dir_from_rsrc(fmt, dirent, dir_return)
        !           616:        nubus_slot *fmt;
        !           617:        nubus_dirent *dirent;
        !           618:        nubus_dir *dir_return;
        !           619: {
        !           620:        u_long loc;
        !           621:
        !           622: #ifdef DEBUG
        !           623:        if (nubus_debug & NDB_FOLLOW)
        !           624:                printf("nubus_get_dir_from_rsrc(%p, %p, %p).\n",
        !           625:                    fmt, dirent, dir_return);
        !           626: #endif
        !           627:        if ((loc = dirent->offset) & 0x800000) {
        !           628:                loc |= 0xff000000;
        !           629:        }
        !           630:        dir_return->dirbase =
        !           631:            nubus_adjust_ptr(fmt->bytelanes, dirent->myloc, loc);
        !           632:        dir_return->curr_ent = dir_return->dirbase;
        !           633: }
        !           634:
        !           635: int
        !           636: nubus_find_rsrc(bst, bsh, fmt, dir, rsrcid, dirent_return)
        !           637:        bus_space_tag_t bst;
        !           638:        bus_space_handle_t bsh;
        !           639:        nubus_slot *fmt;
        !           640:        nubus_dir *dir;
        !           641:        u_int8_t rsrcid;
        !           642:        nubus_dirent *dirent_return;
        !           643: {
        !           644:        u_long entry;
        !           645:        u_int8_t byte, lanes = fmt->bytelanes;
        !           646:
        !           647: #ifdef DEBUG
        !           648:        if (nubus_debug & NDB_FOLLOW)
        !           649:                printf("nubus_find_rsrc(%p, %p, 0x%x, %p)\n",
        !           650:                    fmt, dir, rsrcid, dirent_return);
        !           651: #endif
        !           652:        if (fmt->test_pattern != NUBUS_ROM_TEST_PATTERN)
        !           653:                return -1;
        !           654:
        !           655:        entry = dir->curr_ent;
        !           656:        do {
        !           657:                byte = nubus_read_1(bst, bsh, lanes, entry);
        !           658: #ifdef DEBUG
        !           659:                if (nubus_debug & NDB_FOLLOW)
        !           660:                        printf("\tFound rsrc 0x%x.\n", byte);
        !           661: #endif
        !           662:                if (byte == rsrcid) {
        !           663:                        dirent_return->myloc = entry;
        !           664:                        dirent_return->rsrc_id = rsrcid;
        !           665:                        entry = nubus_read_4(bst, bsh, lanes, entry);
        !           666:                        dirent_return->offset = (entry & 0x00ffffff);
        !           667:                        return 1;
        !           668:                }
        !           669:                if (byte == 0xff) {
        !           670:                        entry = dir->dirbase;
        !           671:                } else {
        !           672:                        entry = nubus_adjust_ptr(lanes, entry, 4);
        !           673:                }
        !           674:        } while (entry != (u_long)dir->curr_ent);
        !           675:        return 0;
        !           676: }
        !           677:
        !           678: int
        !           679: nubus_get_ind_data(bst, bsh, fmt, dirent, data_return, nbytes)
        !           680:        bus_space_tag_t bst;
        !           681:        bus_space_handle_t bsh;
        !           682:        nubus_slot *fmt;
        !           683:        nubus_dirent *dirent;
        !           684:        caddr_t data_return;
        !           685:        int nbytes;
        !           686: {
        !           687:        u_long loc;
        !           688:        u_int8_t lanes = fmt->bytelanes;
        !           689:
        !           690: #ifdef DEBUG
        !           691:        if (nubus_debug & NDB_FOLLOW)
        !           692:                printf("nubus_get_ind_data(%p, %p, %p, %d).\n",
        !           693:                    fmt, dirent, data_return, nbytes);
        !           694: #endif
        !           695:        if ((loc = dirent->offset) & 0x800000) {
        !           696:                loc |= 0xff000000;
        !           697:        }
        !           698:        loc = nubus_adjust_ptr(lanes, dirent->myloc, loc);
        !           699:
        !           700:        while (nbytes--) {
        !           701:                *data_return++ = nubus_read_1(bst, bsh, lanes, loc);
        !           702:                loc = nubus_adjust_ptr(lanes, loc, 1);
        !           703:        }
        !           704:        return 1;
        !           705: }
        !           706:
        !           707: int
        !           708: nubus_get_c_string(bst, bsh, fmt, dirent, data_return, max_bytes)
        !           709:        bus_space_tag_t bst;
        !           710:        bus_space_handle_t bsh;
        !           711:        nubus_slot *fmt;
        !           712:        nubus_dirent *dirent;
        !           713:        caddr_t data_return;
        !           714:        int max_bytes;
        !           715: {
        !           716:        u_long loc;
        !           717:        u_int8_t lanes = fmt->bytelanes;
        !           718:
        !           719: #ifdef DEBUG
        !           720:        if (nubus_debug & NDB_FOLLOW)
        !           721:                printf("nubus_get_c_string(%p, %p, %p, %d).\n",
        !           722:                    fmt, dirent, data_return, max_bytes);
        !           723: #endif
        !           724:        if ((loc = dirent->offset) & 0x800000)
        !           725:                loc |= 0xff000000;
        !           726:
        !           727:        loc = nubus_adjust_ptr(lanes, dirent->myloc, loc);
        !           728:
        !           729:        *data_return = '\0';
        !           730:        while (max_bytes--) {
        !           731:                if ((*data_return++ =
        !           732:                    nubus_read_1(bst, bsh, lanes, loc)) == 0)
        !           733:                        return 1;
        !           734:                loc = nubus_adjust_ptr(lanes, loc, 1);
        !           735:        }
        !           736:        *(data_return-1) = '\0';
        !           737:        return 0;
        !           738: }
        !           739:
        !           740: /*
        !           741:  * Get list of address ranges for an sMemory resource
        !           742:  * ->  DC&D, p.171
        !           743:  */
        !           744: int
        !           745: nubus_get_smem_addr_rangelist(bst, bsh, fmt, dirent, data_return)
        !           746:        bus_space_tag_t bst;
        !           747:        bus_space_handle_t bsh;
        !           748:        nubus_slot *fmt;
        !           749:        nubus_dirent *dirent;
        !           750:        caddr_t data_return;
        !           751: {
        !           752:        u_long loc;
        !           753:        u_int8_t lanes = fmt->bytelanes;
        !           754:        long blocklen;
        !           755:        caddr_t blocklist;
        !           756:
        !           757: #ifdef DEBUG
        !           758:        if (nubus_debug & NDB_FOLLOW)
        !           759:                printf("nubus_get_smem_addr_rangelist(%p, %p, %p).\n",
        !           760:                    fmt, dirent, data_return);
        !           761: #endif
        !           762:        if ((loc = dirent->offset) & 0x800000) {
        !           763:                loc |= 0xff000000;
        !           764:        }
        !           765:        loc = nubus_adjust_ptr(lanes, dirent->myloc, loc);
        !           766:
        !           767:        /* Obtain the block length from the head of the list */
        !           768:        blocklen = nubus_read_4(bst, bsh, lanes, loc);
        !           769:
        !           770:        /*
        !           771:         * malloc a block of (blocklen) bytes
        !           772:         * caller must recycle block after use
        !           773:         */
        !           774:        MALLOC(blocklist,caddr_t,blocklen,M_TEMP,M_WAITOK);
        !           775:
        !           776:        /* read ((blocklen - 4) / 8) (length,offset) pairs into block */
        !           777:        nubus_get_ind_data(bst, bsh, fmt, dirent, blocklist, blocklen);
        !           778: #ifdef DEBUG
        !           779:        if (nubus_debug & NDB_FOLLOW) {
        !           780:                int ii;
        !           781:                nubus_smem_rangelist *rlist;
        !           782:
        !           783:                rlist = (nubus_smem_rangelist *)blocklist;
        !           784:                printf("\tblock@%p, len 0x0%X\n", rlist, rlist->length);
        !           785:
        !           786:                for (ii=0; ii < ((blocklen - 4) / 8); ii++) {
        !           787:                        printf("\tRange %d: base addr 0x%X [0x%X]\n", ii,
        !           788:                            rlist->range[ii].offset, rlist->range[ii].length);
        !           789:                }
        !           790:        }
        !           791: #endif
        !           792:        *(caddr_t *)data_return = blocklist;
        !           793:
        !           794:        return 1;
        !           795: }
        !           796:
        !           797: static char    *huh = "???";
        !           798:
        !           799: char *
        !           800: nubus_get_vendor(bst, bsh, fmt, rsrc)
        !           801:        bus_space_tag_t bst;
        !           802:        bus_space_handle_t bsh;
        !           803:        nubus_slot *fmt;
        !           804:        int rsrc;
        !           805: {
        !           806:        static char str_ret[64];
        !           807:        nubus_dir dir;
        !           808:        nubus_dirent ent;
        !           809:
        !           810: #ifdef DEBUG
        !           811:        if (nubus_debug & NDB_FOLLOW)
        !           812:                printf("nubus_get_vendor(%p, 0x%x).\n", fmt, rsrc);
        !           813: #endif
        !           814:        nubus_get_main_dir(fmt, &dir);
        !           815:        if (nubus_find_rsrc(bst, bsh, fmt, &dir, 1, &ent) <= 0)
        !           816:                return huh;
        !           817:        nubus_get_dir_from_rsrc(fmt, &ent, &dir);
        !           818:
        !           819:        if (nubus_find_rsrc(bst, bsh, fmt, &dir, NUBUS_RSRC_VENDORINFO, &ent)
        !           820:            <= 0)
        !           821:                return huh;
        !           822:        nubus_get_dir_from_rsrc(fmt, &ent, &dir);
        !           823:
        !           824:        if (nubus_find_rsrc(bst, bsh, fmt, &dir, rsrc, &ent) <= 0)
        !           825:                return huh;
        !           826:
        !           827:        nubus_get_c_string(bst, bsh, fmt, &ent, str_ret, 64);
        !           828:
        !           829:        return str_ret;
        !           830: }
        !           831:
        !           832: char *
        !           833: nubus_get_card_name(bst, bsh, fmt)
        !           834:        bus_space_tag_t bst;
        !           835:        bus_space_handle_t bsh;
        !           836:        nubus_slot *fmt;
        !           837: {
        !           838:        static char name_ret[64];
        !           839:        nubus_dir dir;
        !           840:        nubus_dirent ent;
        !           841:
        !           842: #ifdef DEBUG
        !           843:        if (nubus_debug & NDB_FOLLOW)
        !           844:                printf("nubus_get_card_name(%p).\n", fmt);
        !           845: #endif
        !           846:        nubus_get_main_dir(fmt, &dir);
        !           847:
        !           848:        if (nubus_find_rsrc(bst, bsh, fmt, &dir, 1, &ent) <= 0)
        !           849:                return huh;
        !           850:
        !           851:        nubus_get_dir_from_rsrc(fmt, &ent, &dir);
        !           852:
        !           853:        if (nubus_find_rsrc(bst, bsh, fmt, &dir, NUBUS_RSRC_NAME, &ent) <= 0)
        !           854:                return huh;
        !           855:
        !           856:        nubus_get_c_string(bst, bsh, fmt, &ent, name_ret, 64);
        !           857:
        !           858:        return name_ret;
        !           859: }
        !           860:
        !           861: #ifdef DEBUG
        !           862: void
        !           863: nubus_scan_slot(bst, slotno)
        !           864:        bus_space_tag_t bst;
        !           865:        int slotno;
        !           866: {
        !           867:        int i=0, state=0;
        !           868:        char twirl[] = "-\\|/";
        !           869:        bus_space_handle_t sc_bsh;
        !           870:
        !           871:        if (bus_space_map(bst, NUBUS_SLOT2PA(slotno), NBMEMSIZE, 0, &sc_bsh)) {
        !           872:                printf("nubus_scan_slot: failed to map slot %x\n", slotno);
        !           873:                return;
        !           874:        }
        !           875:
        !           876:        printf("Scanning slot %c for accessible regions:\n",
        !           877:                slotno == 9 ? '9' : slotno - 10 + 'A');
        !           878:        for (i=0 ; i<NBMEMSIZE; i++) {
        !           879:                if (mac68k_bus_space_probe(bst, sc_bsh, i, 1)) {
        !           880:                        if (state == 0) {
        !           881:                                printf("\t0x%x-", i);
        !           882:                                state = 1;
        !           883:                        }
        !           884:                } else {
        !           885:                        if (state) {
        !           886:                                printf("0x%x\n", i);
        !           887:                                state = 0;
        !           888:                        }
        !           889:                }
        !           890:                if (i%100 == 0) {
        !           891:                        printf("%c\b", twirl[(i/100)%4]);
        !           892:                }
        !           893:        }
        !           894:        if (state) {
        !           895:                printf("0x%x\n", i);
        !           896:        }
        !           897:        return;
        !           898: }
        !           899: #endif

CVSweb