[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

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