Home | History | Annotate | Line # | Download | only in nubus
nubus.c revision 1.32
      1 /*	$NetBSD: nubus.c,v 1.32 1997/02/28 07:54:02 scottr Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1995, 1996 Allen Briggs.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *	This product includes software developed by Allen Briggs.
     17  * 4. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/param.h>
     33 #include <sys/systm.h>
     34 #include <sys/device.h>
     35 #include <sys/buf.h>
     36 #include <sys/conf.h>
     37 #include <sys/dmap.h>
     38 
     39 #include <vm/vm.h>
     40 #include <vm/vm_kern.h>
     41 #include <vm/vm_map.h>
     42 
     43 #include <machine/autoconf.h>
     44 #include <machine/bus.h>
     45 #include <machine/vmparam.h>
     46 #include <machine/param.h>
     47 #include <machine/cpu.h>
     48 #include <machine/pte.h>
     49 
     50 #include <vm/vm.h>
     51 
     52 #include "nubus.h"
     53 
     54 #ifdef DEBUG
     55 static int	nubus_debug = 0x01;
     56 #define NDB_PROBE	0x1
     57 #define NDB_FOLLOW	0x2
     58 #define NDB_ARITH	0x4
     59 #endif
     60 
     61 static int	nubus_print __P((void *, const char *));
     62 static int	nubus_match __P((struct device *, struct cfdata *, void *));
     63 static void	nubus_attach __P((struct device *, struct device *, void *));
     64 int		nubus_video_resource __P((int));
     65 
     66 static int	probe_slot __P((int slot, nubus_slot *fmt));
     67 static u_long	IncPtr __P((nubus_slot *fmt, u_long base, long amt));
     68 static u_long	nubus_calc_CRC __P((nubus_slot *fmt));
     69 static u_char	GetByte __P((nubus_slot *fmt, u_long ptr));
     70 #ifdef notyet
     71 /* unused */ static u_short	GetWord __P((nubus_slot *fmt, u_long ptr));
     72 #endif
     73 static u_long	GetLong __P((nubus_slot *fmt, u_long ptr));
     74 
     75 static int	nubus_peek __P((vm_offset_t, int));
     76 static char	*nubus_mapin __P((int, int));
     77 
     78 struct cfattach nubus_ca = {
     79 	sizeof(struct nubus_softc), nubus_match, nubus_attach
     80 };
     81 
     82 struct cfdriver nubus_cd = {
     83 	NULL, "nubus", DV_DULL,
     84 };
     85 
     86 static int
     87 nubus_match(parent, cf, aux)
     88 	struct device *parent;
     89 	struct cfdata *cf;
     90 	void *aux;
     91 {
     92 	static int nubus_matched = 0;
     93 
     94 	/* Allow only one instance. */
     95 	if (nubus_matched)
     96 		return (0);
     97 
     98 	nubus_matched = 1;
     99 	return (1);
    100 }
    101 
    102 static void
    103 nubus_attach(parent, self, aux)
    104 	struct device *parent, *self;
    105 	void *aux;
    106 {
    107 	struct nubus_attach_args na_args;
    108 	nubus_slot fmtblock;
    109 	nubus_dir dir;
    110 	nubus_dirent dirent;
    111 	nubus_type slottype;
    112 	int i, rsrcid;
    113 
    114 	printf("\n");
    115 
    116 	for (i = NUBUS_MIN_SLOT; i <= NUBUS_MAX_SLOT; i++) {
    117 		if (probe_slot(i, &fmtblock) <= 0)
    118 			continue;
    119 
    120 		if ((rsrcid = nubus_video_resource(i)) == (-1))
    121 			rsrcid = 0x80;
    122 
    123 		nubus_get_main_dir(&fmtblock, &dir);
    124 
    125 		if (nubus_find_rsrc(&fmtblock, &dir, rsrcid, &dirent) <= 0)
    126 			continue;
    127 
    128 		nubus_get_dir_from_rsrc(&fmtblock, &dirent, &dir);
    129 
    130 		if (nubus_find_rsrc(&fmtblock, &dir, NUBUS_RSRC_TYPE,
    131 		    &dirent) <= 0)
    132 			continue;
    133 
    134 		if (nubus_get_ind_data(&fmtblock, &dirent,
    135 		    (caddr_t) &slottype, sizeof(nubus_type)) <= 0)
    136 			continue;
    137 
    138 		na_args.slot = i;
    139 		na_args.rsrcid = rsrcid;
    140 		na_args.category = slottype.category;
    141 		na_args.type = slottype.type;
    142 		na_args.drsw = slottype.drsw;
    143 		na_args.drhw = slottype.drhw;
    144 		na_args.fmt = &fmtblock;
    145 
    146 		config_found(self, &na_args, nubus_print);
    147 	}
    148 }
    149 
    150 static int
    151 nubus_print(aux, name)
    152 	void *aux;
    153 	const char *name;
    154 {
    155 	struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
    156 
    157 	if (name) {
    158 		printf("%s: slot %x: %s ", name, na->fmt->slot,
    159 		    nubus_get_card_name(na->fmt));
    160 		printf("(Vendor: %s, ",
    161 		    nubus_get_vendor(na->fmt, NUBUS_RSRC_VEND_ID));
    162 		printf("Part: %s)",
    163 		    nubus_get_vendor(na->fmt, NUBUS_RSRC_VEND_PART));
    164 	}
    165 	return (UNCONF);
    166 }
    167 
    168 int
    169 nubus_video_resource(slot)
    170 	int slot;
    171 {
    172 	extern u_int16_t mac68k_vrsrc_vec[];
    173 	int i;
    174 
    175 	for (i = 0 ; i < 6 ; i++)
    176 		if ((mac68k_vrsrc_vec[i] & 0xff) == slot)
    177 			return ((mac68k_vrsrc_vec[i] >> 8) & 0xff);
    178 	return (-1);
    179 }
    180 
    181 /*
    182  * Probe a given nubus slot.  If a card is there and we can get the
    183  * format block from it's clutching decl. ROMs, fill the format block
    184  * and return non-zero.  If we can't find a card there with a valid
    185  * decl. ROM, return 0.
    186  *
    187  * First, we check to see if we can access the memory at the tail
    188  * end of the slot.  If so, then we check for a bytelanes byte.  We
    189  * could probably just return a failure status if we bus error on
    190  * the first try, but there really is little reason not to go ahead
    191  * and check the other three locations in case there's a wierd card
    192  * out there.
    193  *
    194  * Checking for a card involves locating the "bytelanes" byte which
    195  * tells us how to interpret the declaration ROM's data.  The format
    196  * block is at the top of the card's standard memory space and the
    197  * bytelanes byte is at the end of that block.
    198  *
    199  * After some inspection of the bytelanes byte, it appears that it
    200  * takes the form 0xXY where Y is a bitmask of the bytelanes in use
    201  * and X is a bitmask of the lanes to ignore.  Hence, (X ^ Y) == 0
    202  * and (less obviously), Y will have the upper N bits clear if it is
    203  * found N bytes from the last possible location.  Both that and
    204  * the exclusive-or check are made.
    205  *
    206  * If a valid
    207  */
    208 static u_char	nbits[]={0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
    209 static int
    210 probe_slot(slot, fmt)
    211 	int		slot;
    212 	nubus_slot	*fmt;
    213 {
    214 	caddr_t		rom_probe;
    215 	vm_offset_t	hdr;
    216 #ifdef DEBUG
    217 	vm_offset_t	pa;
    218 #endif
    219 	u_int		data;
    220 	int		hdr_size, i;
    221 
    222 	fmt->bytelanes = 0;
    223 	fmt->slot = (u_long)slot;
    224 
    225 	rom_probe = (caddr_t) (NUBUS_SLOT2PA(fmt->slot) + NBMEMSIZE);
    226 
    227 #ifdef DEBUG
    228 	if (nubus_debug & NDB_PROBE) {
    229 		pa = pmap_extract(pmap_kernel(), (vm_offset_t) rom_probe - 1);
    230 		printf("probing slot %d, first probe at 0x%p (PA 0x%lx).\n",
    231 		    slot, rom_probe - 1, pa);
    232 	}
    233 #endif
    234 
    235 	for (i = 4; i && (fmt->bytelanes == 0); i--) {
    236 
    237 		rom_probe--;
    238 
    239 		data = nubus_peek((vm_offset_t) rom_probe, 1);
    240 		if (data == -1)
    241 			continue;
    242 
    243 		if (data == 0)
    244 			continue;
    245 
    246 		if (   ((((data & 0xf0) >> 4) ^ (data & 0x0f)) == 0x0f)
    247 		    && ((data & 0x0f) < (1 << i)) ) {
    248 			fmt->bytelanes = data;
    249 			fmt->step = nbits[(data & 0x0f)];
    250 		}
    251 	}
    252 #ifdef DEBUG
    253 	if (nubus_debug & NDB_PROBE)
    254 		if (fmt->bytelanes == 0)
    255 			printf("bytelanes not found for slot 0x%x.\n", slot);
    256 #endif
    257 
    258 	if (fmt->bytelanes == 0)
    259 		return 0;
    260 
    261 #ifdef DEBUG
    262 	if (nubus_debug & NDB_PROBE)
    263 		printf("bytelanes of 0x%x found for slot 0x%x.\n",
    264 			fmt->bytelanes, slot);
    265 #endif
    266 
    267 	hdr_size = 20;
    268 
    269 	/*
    270 	 * Go ahead and attempt to load format header.
    271 	 * First, we need to find the first byte beyond memory that
    272 	 * would be valid.  This is necessary for NUBUS_ROM_offset()
    273 	 * to work.
    274 	 */
    275 	hdr = (vm_offset_t)
    276 		nubus_mapin(NUBUS_SLOT2PA(fmt->slot), NBMEMSIZE);
    277 	if (hdr == NULL) {
    278 		printf("Failed to map %d bytes for NuBUS slot %d probe.  ",
    279 			NBMEMSIZE, fmt->slot);
    280 		printf("Physical slot address %x\n",
    281 			(unsigned int) NUBUS_SLOT2PA(fmt->slot));
    282 	}
    283 	fmt->virtual_base = hdr;
    284 	hdr += NBMEMSIZE;
    285 
    286 	i = 0x10 | (fmt->bytelanes & 0x0f);
    287 	while ((i & 1) == 0) {
    288 		hdr++;
    289 		i >>= 1;
    290 	}
    291 	fmt->top = hdr;
    292 	hdr = IncPtr(fmt, hdr, -hdr_size);
    293 #ifdef DEBUG
    294 	if (nubus_debug & NDB_PROBE)
    295 		printf("fmt->top is 0x%lx, that minus 0x%x puts us at 0x%lx.\n",
    296 			fmt->top, hdr_size, hdr);
    297 #if 0
    298 	for (i=1 ; i < 8 ; i++) {
    299 		printf("0x%x - 0x%x = 0x%x, + 0x%x = 0x%x.\n",
    300 			hdr, i, IncPtr(fmt, hdr, -i),
    301 			     i, IncPtr(fmt, hdr,  i));
    302 	}
    303 #endif
    304 #endif
    305 
    306 	fmt->directory_offset = 0xff000000 | GetLong(fmt, hdr);
    307 	hdr = IncPtr(fmt, hdr, 4);
    308 	fmt->length = GetLong(fmt, hdr);
    309 	hdr = IncPtr(fmt, hdr, 4);
    310 	fmt->crc = GetLong(fmt, hdr);
    311 	hdr = IncPtr(fmt, hdr, 4);
    312 	fmt->revision_level = GetByte(fmt, hdr);
    313 	hdr = IncPtr(fmt, hdr, 1);
    314 	fmt->format = GetByte(fmt, hdr);
    315 	hdr = IncPtr(fmt, hdr, 1);
    316 	fmt->test_pattern = GetLong(fmt, hdr);
    317 
    318 #ifdef DEBUG
    319 	if (nubus_debug & NDB_PROBE) {
    320 		printf("Directory offset 0x%x\t", fmt->directory_offset);
    321 		printf("Length 0x%x\t", fmt->length);
    322 		printf("CRC 0x%x\n", fmt->crc);
    323 		printf("Revision level 0x%x\t", fmt->revision_level);
    324 		printf("Format 0x%x\t", fmt->format);
    325 		printf("Test Pattern 0x%x\n", fmt->test_pattern);
    326 	}
    327 #endif
    328 
    329 	if ((fmt->directory_offset & 0x00ff0000) == 0) {
    330 		printf("Invalid looking directory offset (0x%x)!\n",
    331 			fmt->directory_offset);
    332 		return 0;
    333 	}
    334 	if (fmt->test_pattern != NUBUS_ROM_TEST_PATTERN) {
    335 		printf("Nubus--test pattern invalid:\n");
    336 		printf("       slot 0x%x, bytelanes 0x%x?\n",
    337 			fmt->slot, fmt->bytelanes);
    338 		printf("       read test 0x%x, compare with 0x%x.\n",
    339 			fmt->test_pattern, NUBUS_ROM_TEST_PATTERN);
    340 		return 0;
    341 	}
    342 
    343 	/* Perform CRC */
    344 	if (fmt->crc != nubus_calc_CRC(fmt)) {
    345 		printf("Nubus--crc check failed, slot 0x%x.\n",
    346 			fmt->slot);
    347 		return 0;
    348 	}
    349 
    350 	return 1;
    351 }
    352 
    353 /*
    354  * Compute byte offset on card, taking into account bytelanes.
    355  * Base must be on a valid bytelane for this function to work.
    356  * Return the new address.
    357  *
    358  * XXX -- There has GOT to be a better way to do this.
    359  */
    360 static u_long
    361 IncPtr(fmt, base, amt)
    362 	nubus_slot	*fmt;
    363 	u_long		base;
    364 	long		amt;
    365 {
    366 	u_char 	b, t;
    367 
    368 	if (!amt)
    369 		return base;
    370 
    371 	if (amt < 0) {
    372 		amt = -amt;
    373 		b = fmt->bytelanes;
    374 		t = (b << 4);
    375 		b <<= (3 - (base & 0x3));
    376 		while (amt) {
    377 			b <<= 1;
    378 			if (b == t)
    379 				b = fmt->bytelanes;
    380 			if (b & 0x08)
    381 				amt--;
    382 			base--;
    383 		}
    384 		return base;
    385 	}
    386 
    387 	t = (fmt->bytelanes & 0xf) | 0x10;
    388 	b = t >> (base & 0x3);
    389 	while (amt) {
    390 		b >>= 1;
    391 		if (b == 1)
    392 			b = t;
    393 		if (b & 1)
    394 			amt--;
    395 		base++;
    396 	}
    397 
    398 	return base;
    399 }
    400 
    401 static u_long
    402 nubus_calc_CRC(fmt)
    403 	nubus_slot	*fmt;
    404 {
    405 #if 0
    406 	u_long	base, ptr, crc_loc, sum;
    407 	int	i;
    408 
    409 	base = fmt->top;
    410 	crc_loc = NUBUS_ROM_offset(fmt, base, -12);
    411 	ptr = NUBUS_ROM_offset(fmt, base, -fmt->length);
    412 
    413 	sum = 0;
    414 	while (ptr < base)
    415 		roll #1, sum
    416 		if (ptr == crc_loc) {
    417 			roll #3, sum
    418 			ptr = IncPtr(fmt, ptr, 3);
    419 		} else {
    420 			sum += GetByte(fmt, ptr);
    421 		}
    422 		ptr = IncPtr(fmt, ptr, 1);
    423 	}
    424 
    425 	return sum;
    426 #endif
    427 	return fmt->crc;
    428 }
    429 
    430 static u_char
    431 GetByte(fmt, ptr)
    432 	nubus_slot	*fmt;
    433 	u_long		ptr;
    434 {
    435 	return *(caddr_t)ptr;
    436 }
    437 
    438 #ifdef notyet
    439 /* Nothing uses this, yet */
    440 static u_short
    441 GetWord(fmt, ptr)
    442 	nubus_slot	*fmt;
    443 	u_long		ptr;
    444 {
    445 	u_short	s;
    446 
    447 	s = (GetByte(fmt, ptr) << 8);
    448 	ptr = IncPtr(fmt, ptr, 1);
    449 	s |= GetByte(fmt, ptr);
    450 	return s;
    451 }
    452 #endif
    453 
    454 static u_long
    455 GetLong(fmt, ptr)
    456 	nubus_slot	*fmt;
    457 	u_long		ptr;
    458 {
    459 	register u_long l;
    460 	register int	i;
    461 
    462 	l = 0;
    463 	for ( i = 0; i < 4; i++) {
    464 		l = (l << 8) | GetByte(fmt, ptr);
    465 		ptr = IncPtr(fmt, ptr, 1);
    466 	}
    467 	return l;
    468 }
    469 
    470 void
    471 nubus_get_main_dir(slot, dir_return)
    472 	nubus_slot	*slot;
    473 	nubus_dir	*dir_return;
    474 {
    475 #ifdef DEBUG
    476 	if (nubus_debug & NDB_FOLLOW)
    477 		printf("nubus_get_main_dir(0x%x, 0x%x)\n",
    478 			(u_int) slot, (u_int) dir_return);
    479 #endif
    480 	dir_return->dirbase = IncPtr(slot, slot->top,
    481 					slot->directory_offset - 20);
    482 	dir_return->curr_ent = dir_return->dirbase;
    483 }
    484 
    485 int
    486 nubus_find_rsrc(slot, dir, rsrcid, dirent_return)
    487 	nubus_slot	*slot;
    488 	nubus_dir	*dir;
    489 	u_int8_t	rsrcid;
    490 	nubus_dirent	*dirent_return;
    491 {
    492 	u_long		entry;
    493 	u_char		byte;
    494 
    495 #ifdef DEBUG
    496 	if (nubus_debug & NDB_FOLLOW)
    497 		printf("nubus_find_rsrc(0x%x, 0x%x, 0x%x, 0x%x)\n",
    498 			(u_int) slot, (u_int) dir, (u_int) rsrcid,
    499 			(u_int) dirent_return);
    500 #endif
    501 	if (slot->test_pattern != NUBUS_ROM_TEST_PATTERN)
    502 		return -1;
    503 
    504 	entry = dir->curr_ent;
    505 	do {
    506 		byte = GetByte(slot, entry);
    507 #ifdef DEBUG
    508 		if (nubus_debug & NDB_FOLLOW)
    509 			printf("\tFound rsrc 0x%x.\n", byte);
    510 #endif
    511 		if (byte == rsrcid) {
    512 			dirent_return->myloc = entry;
    513 			dirent_return->rsrc_id = rsrcid;
    514 			entry = GetLong(slot, entry);
    515 			dirent_return->offset = (entry & 0x00ffffff);
    516 			return 1;
    517 		}
    518 		if (byte == 0xff) {
    519 			entry = dir->dirbase;
    520 		} else {
    521 			entry = IncPtr(slot, entry, 4);
    522 		}
    523 	} while (entry != (u_long) dir->curr_ent);
    524 	return 0;
    525 }
    526 
    527 void
    528 nubus_get_dir_from_rsrc(slot, dirent, dir_return)
    529 	nubus_slot	*slot;
    530 	nubus_dirent	*dirent;
    531 	nubus_dir	*dir_return;
    532 {
    533 	u_long	loc;
    534 
    535 #ifdef DEBUG
    536 	if (nubus_debug & NDB_FOLLOW)
    537 		printf("nubus_get_dir_from_rsrc(0x%x, 0x%x, 0x%x).\n",
    538 			(u_int) slot, (u_int) dirent, (u_int) dir_return);
    539 #endif
    540 	if ((loc = dirent->offset) & 0x800000) {
    541 		loc |= 0xff000000;
    542 	}
    543 	dir_return->dirbase = IncPtr(slot, dirent->myloc, loc);
    544 	dir_return->curr_ent = dir_return->dirbase;
    545 }
    546 
    547 int
    548 nubus_get_ind_data(slot, dirent, data_return, nbytes)
    549 	nubus_slot *slot;
    550 	nubus_dirent *dirent;
    551 	caddr_t data_return;
    552 	int nbytes;
    553 {
    554 	u_long	loc;
    555 
    556 #ifdef DEBUG
    557 	if (nubus_debug & NDB_FOLLOW)
    558 		printf("nubus_get_ind_data(0x%x, 0x%x, 0x%x, %d).\n",
    559 			(u_int) slot, (u_int) dirent, (u_int) data_return,
    560 			nbytes);
    561 #endif
    562 	if ((loc = dirent->offset) & 0x800000) {
    563 		loc |= 0xff000000;
    564 	}
    565 	loc = IncPtr(slot, dirent->myloc, loc);
    566 
    567 	while (nbytes--) {
    568 		*data_return++ = GetByte(slot, loc);
    569 		loc = IncPtr(slot, loc, 1);
    570 	}
    571 	return 1;
    572 }
    573 
    574 int
    575 nubus_get_c_string(slot, dirent, data_return, max_bytes)
    576 	nubus_slot *slot;
    577 	nubus_dirent *dirent;
    578 	caddr_t data_return;
    579 	int max_bytes;
    580 {
    581 	u_long	loc;
    582 
    583 #ifdef DEBUG
    584 	if (nubus_debug & NDB_FOLLOW)
    585 		printf("nubus_get_c_string(0x%x, 0x%x, 0x%x, %d).\n",
    586 			(u_int) slot, (u_int) dirent, (u_int) data_return,
    587 			max_bytes);
    588 #endif
    589 	if ((loc = dirent->offset) & 0x800000) {
    590 		loc |= 0xff000000;
    591 	}
    592 	loc = IncPtr(slot, dirent->myloc, loc);
    593 
    594 	*data_return = '\0';
    595 	while (max_bytes--) {
    596 		if ((*data_return++ = GetByte(slot, loc)) == 0)
    597 			return 1;
    598 		loc = IncPtr(slot, loc, 1);
    599 	}
    600 	return 0;
    601 }
    602 
    603 static char	*huh = "???";
    604 
    605 char *
    606 nubus_get_vendor(slot, rsrc)
    607 	nubus_slot	*slot;
    608 	int		rsrc;
    609 {
    610 static	char		str_ret[64];
    611 	nubus_dir	dir;
    612 	nubus_dirent	ent;
    613 
    614 #ifdef DEBUG
    615 	if (nubus_debug & NDB_FOLLOW)
    616 		printf("nubus_get_vendor(0x%x, 0x%x).\n", (u_int) slot, rsrc);
    617 #endif
    618 	nubus_get_main_dir(slot, &dir);
    619 	if (nubus_find_rsrc(slot, &dir, 1, &ent) <= 0)
    620 		return huh;
    621 	nubus_get_dir_from_rsrc(slot, &ent, &dir);
    622 
    623 	if (nubus_find_rsrc(slot, &dir, NUBUS_RSRC_VENDORINFO, &ent) <= 0)
    624 		return huh;
    625 	nubus_get_dir_from_rsrc(slot, &ent, &dir);
    626 
    627 	if (nubus_find_rsrc(slot, &dir, rsrc, &ent) <= 0)
    628 		return huh;
    629 
    630 	nubus_get_c_string(slot, &ent, str_ret, 64);
    631 
    632 	return str_ret;
    633 }
    634 
    635 char *
    636 nubus_get_card_name(slot)
    637 	nubus_slot	*slot;
    638 {
    639 static	char		name_ret[64];
    640 	nubus_dir	dir;
    641 	nubus_dirent	ent;
    642 
    643 #ifdef DEBUG
    644 	if (nubus_debug & NDB_FOLLOW)
    645 		printf("nubus_get_card_name(0x%lx).\n", (u_long) slot);
    646 #endif
    647 	nubus_get_main_dir(slot, &dir);
    648 
    649 	if (nubus_find_rsrc(slot, &dir, 1, &ent) <= 0)
    650 		return huh;
    651 
    652 	nubus_get_dir_from_rsrc(slot, &ent, &dir);
    653 
    654 	if (nubus_find_rsrc(slot, &dir, NUBUS_RSRC_NAME, &ent) <= 0)
    655 		return huh;
    656 
    657 	nubus_get_c_string(slot, &ent, name_ret, 64);
    658 
    659 	return name_ret;
    660 }
    661 
    662 /*
    663  * bus_*() functions adapted from sun3 generic "bus" support
    664  * by Allen Briggs.
    665  */
    666 
    667 vm_offset_t tmp_vpages[1];
    668 
    669 /*
    670  * Read addr with size len (1,2,4) into val.
    671  * If this generates a bus error, return -1
    672  *
    673  *	Create a temporary mapping,
    674  *	Try the access using peek_*
    675  *	Clean up temp. mapping
    676  */
    677 static int
    678 nubus_peek(paddr, sz)
    679 	vm_offset_t paddr;
    680 	int sz;
    681 {
    682 	int off, pte, rv;
    683 	vm_offset_t pgva;
    684 	caddr_t va;
    685 
    686 	off = paddr & PGOFSET;
    687 	paddr -= off;
    688 	pte = (paddr & PG_FRAME) | (PG_V | PG_W | PG_CI);
    689 
    690 	pgva = tmp_vpages[0];
    691 	va = (caddr_t)pgva + off;
    692 
    693 	mac68k_set_pte(pgva, pte);
    694 	TBIS(pgva);
    695 
    696 	/*
    697 	 * OK, try the access using one of the assembly routines
    698 	 * that will set pcb_onfault and catch any bus errors.
    699 	 */
    700 	rv = -1;
    701 	switch (sz) {
    702 	case 1:
    703 		if (!badbaddr(va))
    704 			rv = *((u_char *) va);
    705 		break;
    706 	case 2:
    707 		if (!badwaddr(va))
    708 			rv = *((u_int16_t *) va);
    709 		break;
    710 	case 4:
    711 		if (!badladdr(va))
    712 			rv = *((u_int32_t *) va);
    713 		break;
    714 	default:
    715 		printf("bus_peek: invalid size=%d\n", sz);
    716 		rv = -1;
    717 	}
    718 
    719 	mac68k_set_pte(pgva, PG_NV);
    720 	TBIS(pgva);
    721 
    722 	return rv;
    723 }
    724 
    725 static char *
    726 nubus_mapin(paddr, sz)
    727 	int paddr, sz;
    728 {
    729 	int off, pa, pmt=0;
    730 	vm_offset_t va, retval;
    731 
    732 	off = paddr & PGOFSET;
    733 	pa = paddr - off;
    734 	sz += off;
    735 	sz = mac68k_round_page(sz);
    736 
    737 	/* Get some kernel virtual address space. */
    738 	va = kmem_alloc_wait(kernel_map, sz);
    739 	if (va == 0)
    740 		panic("bus_mapin");
    741 	retval = va + off;
    742 
    743 	/* Map it to the specified bus. */
    744 #if 0	/* XXX */
    745 	/* This has a problem with wrap-around... */
    746 	pmap_map((int)va, pa | pmt, pa + sz, VM_PROT_ALL);
    747 #else
    748 	do {
    749 		pmap_enter(pmap_kernel(), va, pa | pmt, VM_PROT_ALL, FALSE);
    750 		va += NBPG;
    751 		pa += NBPG;
    752 	} while ((sz -= NBPG) > 0);
    753 #endif
    754 
    755 	return ((char*)retval);
    756 }
    757