4.4BSD/usr/src/sys/hp300/hp300/autoconf.c

Compare this file to the similar file:
Show the results in this format:

/*
 * Copyright (c) 1988 University of Utah.
 * Copyright (c) 1982, 1986, 1990, 1993
 *	The Regents of the University of California.  All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * the Systems Programming Group of the University of Utah Computer
 * Science Department.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *	This product includes software developed by the University of
 *	California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * from: Utah $Hdr: autoconf.c 1.36 92/12/20$
 *
 *	@(#)autoconf.c	8.1 (Berkeley) 6/10/93
 */

/*
 * Setup the system to run on the current machine.
 *
 * Configure() is called at boot time.  Available
 * devices are determined (from possibilities mentioned in ioconf.c),
 * and the drivers are initialized.
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/map.h>
#include <sys/buf.h>
#include <sys/dkstat.h>
#include <sys/conf.h>
#include <sys/dmap.h>
#include <sys/reboot.h>

#include <machine/vmparam.h>
#include <machine/cpu.h>
#include <hp300/hp300/pte.h>
#include <hp300/hp300/isr.h>
#include <hp/dev/device.h>
#include <hp/dev/grfreg.h>
#include <hp/dev/hilreg.h>

/*
 * The following several variables are related to
 * the configuration process, and are used in initializing
 * the machine.
 */
int	cold;		    /* if 1, still working on cold-start */
int	dkn;		    /* number of iostat dk numbers assigned so far */
int	cpuspeed = 0;	    /* relative cpu speed -- can be patched */	
struct	isr isrqueue[NISR];
struct	hp_hw sc_table[MAXCTLRS];

/* XXX must be allocated statically because of early console init */
struct	map extiomap[EIOMAPSIZE/16];

extern	caddr_t internalhpib;
extern	char *extiobase;

#ifdef DEBUG
int	acdebug = 0;
#endif

/*
 * Determine mass storage and memory configuration for a machine.
 */
configure()
{
	register struct hp_hw *hw;
	int found;

	/*
	 * XXX: these should be consolidated into some kind of table
	 */
	hilsoftinit(0, HILADDR);
	hilinit(0, HILADDR);
	isrinit();
	dmainit();

	/*
	 * Look over each hardware device actually found and attempt
	 * to match it with an ioconf.c table entry.
	 */
	for (hw = sc_table; hw->hw_type; hw++) {
		if (HW_ISCTLR(hw))
			found = find_controller(hw);
		else
			found = find_device(hw);
#ifdef DEBUG
		if (!found) {
			int sc = patosc(hw->hw_pa);

			printf("unconfigured card id %x ", hw->hw_id);
			if (sc < 256)
				printf("at sc%d\n", sc);
			else
				printf("csr at %x\n", sc);
		}
#endif
	}

#if GENERIC
	if ((boothowto & RB_ASKNAME) == 0)
		setroot();
	setconf();
#else
	setroot();
#endif
	swapconf();
	cold = 0;
}

#define dr_type(d, s)	\
	(strcmp((d)->d_name, (s)) == 0)

#define same_hw_ctlr(hw, hc) \
	(HW_ISHPIB(hw) && dr_type((hc)->hp_driver, "hpib") || \
	 HW_ISSCSI(hw) && dr_type((hc)->hp_driver, "scsi"))

find_controller(hw)
	register struct hp_hw *hw;
{
	register struct hp_ctlr *hc;
	struct hp_ctlr *match_c;
	caddr_t oaddr;
	int sc;

#ifdef DEBUG
	if (acdebug)
		printf("find_controller: hw: id%x at sc%d (%x), type %x...",
		       hw->hw_id, hw->hw_sc, hw->hw_kva, hw->hw_type);
#endif
	sc = hw->hw_sc;
	match_c = NULL;
	for (hc = hp_cinit; hc->hp_driver; hc++) {
		if (hc->hp_alive)
			continue;
		/*
		 * Make sure we are looking at the right
		 * controller type.
		 */
		if (!same_hw_ctlr(hw, hc))
			continue;
		/*
		 * Exact match; all done
		 */
		if ((int)hc->hp_addr == sc) {
			match_c = hc;
			break;
		}
		/*
		 * Wildcard; possible match so remember first instance
		 * but continue looking for exact match.
		 */
		if (hc->hp_addr == NULL && match_c == NULL)
			match_c = hc;
	}
#ifdef DEBUG
	if (acdebug) {
		if (match_c)
			printf("found %s%d\n",
			       match_c->hp_driver->d_name,
			       match_c->hp_unit);
		else
			printf("not found\n");
	}
#endif
	/*
	 * Didn't find an ioconf entry for this piece of hardware,
	 * just ignore it.
	 */
	if (match_c == NULL)
		return(0);
	/*
	 * Found a match, attempt to initialize and configure all attached
	 * slaves.  Note, we can still fail if HW won't initialize.
	 */
	hc = match_c;
	oaddr = hc->hp_addr;
	hc->hp_addr = hw->hw_kva;
	if ((*hc->hp_driver->d_init)(hc)) {
		hc->hp_alive = 1;
		printf("%s%d", hc->hp_driver->d_name, hc->hp_unit);
		sc = patosc(hw->hw_pa);
		if (sc < 256)
			printf(" at sc%d,", sc);
		else
			printf(" csr 0x%x,", sc);
		printf(" ipl %d", hc->hp_ipl);
		if (hc->hp_flags)
			printf(" flags 0x%x", hc->hp_flags);
		printf("\n");
		find_slaves(hc);
	} else
		hc->hp_addr = oaddr;
	return(1);
}

find_device(hw)
	register struct hp_hw *hw;
{
	register struct hp_device *hd;
	struct hp_device *match_d;
	caddr_t oaddr;
	int sc;

#ifdef DEBUG
	if (acdebug)
		printf("find_device: hw: id%x at sc%d (%x), type %x...",
		       hw->hw_id, hw->hw_sc, hw->hw_kva, hw->hw_type);
#endif
	match_d = NULL;
	for (hd = hp_dinit; hd->hp_driver; hd++) {
		if (hd->hp_alive)
			continue;
		/* Must not be a slave */
		if (hd->hp_cdriver)
			continue;
		/*
		 * XXX: A graphics device that was found as part of the
		 * console init will have the hp_addr field already set
		 * (i.e. no longer the select code).  Gotta perform a
		 * slightly different check for an exact match.
		 */
		if (HW_ISDEV(hw, D_BITMAP) && hd->hp_addr >= intiobase) {
			/* must be an exact match */
			if (hd->hp_addr == hw->hw_kva) {
				match_d = hd;
				break;
			}
			continue;
		}
		sc = (int) hd->hp_addr;
		/*
		 * Exact match; all done.
		 */
		if (sc > 0 && sc == hw->hw_sc) {
			match_d = hd;
			break;
		}
		/*
		 * Wildcard; possible match so remember first instance
		 * but continue looking for exact match.
		 */
		if (sc == 0 && same_hw_device(hw, hd) && match_d == NULL)
			match_d = hd;
	}
#ifdef DEBUG
	if (acdebug) {
		if (match_d)
			printf("found %s%d\n",
			       match_d->hp_driver->d_name,
			       match_d->hp_unit);
		else
			printf("not found\n");
	}
#endif
	/*
	 * Didn't find an ioconf entry for this piece
	 * of hardware, just ignore it.
	 */
	if (match_d == NULL)
		return(0);
	/*
	 * Found a match, attempt to initialize.
	 * Note, we can still fail if HW won't initialize.
	 */
	hd = match_d;
	oaddr = hd->hp_addr;
	hd->hp_addr = hw->hw_kva;
	if ((*hd->hp_driver->d_init)(hd)) {
		hd->hp_alive = 1;
		printf("%s%d", hd->hp_driver->d_name, hd->hp_unit);
		sc = patosc(hw->hw_pa);
		if (sc < 256)
			printf(" at sc%d", sc);
		else
			printf(" csr 0x%x", sc);
		if (hd->hp_ipl)
			printf(", ipl %d", hd->hp_ipl);
		if (hd->hp_flags)
			printf(", flags 0x%x", hd->hp_flags);
		printf("\n");
	} else
		hd->hp_addr = oaddr;
	return(1);
}

find_slaves(hc)
	struct hp_ctlr *hc;
{
	/*
	 * The SCSI bus is structured very much like the HP-IB 
	 * except that the host adaptor is slave 7 so we only want
	 * to look at the first 6 slaves.
	 */
	if (dr_type(hc->hp_driver, "hpib"))
		find_busslaves(hc, MAXSLAVES);
	else if (dr_type(hc->hp_driver, "scsi"))
		find_busslaves(hc, MAXSLAVES-1);
}

/*
 * Search each BUS controller found for slaves attached to it.
 * The bad news is that we don't know how to uniquely identify all slaves
 * (e.g. PPI devices on HP-IB).  The good news is that we can at least
 * differentiate those from slaves we can identify.  At worst (a totally
 * wildcarded entry) this will cause us to locate such a slave at the first
 * unused position instead of where it really is.  To save grief, non-
 * identifing devices should always be fully qualified.
 */
find_busslaves(hc, maxslaves)
	register struct hp_ctlr *hc;
	int maxslaves;
{
	register int s;
	register struct hp_device *hd;
	struct hp_device *match_s;
	int new_s, new_c, old_s, old_c;
	int rescan;
	
#ifdef DEBUG
	if (acdebug)
		printf("find_busslaves: for %s%d\n",
		       hc->hp_driver->d_name, hc->hp_unit);
#endif
	for (s = 0; s < maxslaves; s++) {
		rescan = 1;
		match_s = NULL;
		for (hd = hp_dinit; hd->hp_driver; hd++) {
			/*
			 * Rule out the easy ones:
			 * 1. slave already assigned or not a slave
			 * 2. not of the proper type
			 * 3. controller specified but not this one
			 * 4. slave specified but not this one
			 */
			if (hd->hp_alive || hd->hp_cdriver == NULL)
				continue;
			if (!dr_type(hc->hp_driver, hd->hp_cdriver->d_name))
				continue;
			if (hd->hp_ctlr >= 0 && hd->hp_ctlr != hc->hp_unit)
				continue;
			if (hd->hp_slave >= 0 && hd->hp_slave != s)
				continue;
			/*
			 * Case 0: first possible match.
			 * Remember it and keep looking for better.
			 */
			if (match_s == NULL) {
				match_s = hd;
				new_c = hc->hp_unit;
				new_s = s;
				continue;
			}
			/*
			 * Case 1: exact match.
			 * All done.  Note that we do not attempt any other
			 * matches if this one fails.  This allows us to
			 * "reserve" locations for dynamic addition of
			 * disk/tape drives by fully qualifing the location.
			 */
			if (hd->hp_slave == s && hd->hp_ctlr == hc->hp_unit) {
				match_s = hd;
				rescan = 0;
				break;
			}
			/*
			 * Case 2: right controller, wildcarded slave.
			 * Remember first and keep looking for an exact match.
			 */
			if (hd->hp_ctlr == hc->hp_unit &&
			    match_s->hp_ctlr < 0) {
				match_s = hd;
				new_s = s;
				continue;
			}
			/*
			 * Case 3: right slave, wildcarded controller.
			 * Remember and keep looking for a better match.
			 */
			if (hd->hp_slave == s &&
			    match_s->hp_ctlr < 0 && match_s->hp_slave < 0) {
				match_s = hd;
				new_c = hc->hp_unit;
				continue;
			}
			/*
			 * OW: we had a totally wildcarded spec.
			 * If we got this far, we have found a possible
			 * match already (match_s != NULL) so there is no
			 * reason to remember this one.
			 */
			continue;
		}
		/*
		 * Found a match.  We need to set hp_ctlr/hp_slave properly
		 * for the init routines but we also need to remember all
		 * the old values in case this doesn't pan out.
		 */
		if (match_s) {
			hd = match_s;
			old_c = hd->hp_ctlr;
			old_s = hd->hp_slave;
			if (hd->hp_ctlr < 0)
				hd->hp_ctlr = new_c;
			if (hd->hp_slave < 0)
				hd->hp_slave = new_s;
#ifdef DEBUG
			if (acdebug)
				printf("looking for %s%d at slave %d...",
				       hd->hp_driver->d_name,
				       hd->hp_unit, hd->hp_slave);
#endif

			if ((*hd->hp_driver->d_init)(hd)) {
#ifdef DEBUG
				if (acdebug)
					printf("found\n");
#endif
				printf("%s%d at %s%d, slave %d",
				       hd->hp_driver->d_name, hd->hp_unit,
				       hc->hp_driver->d_name, hd->hp_ctlr,
				       hd->hp_slave);
				if (hd->hp_flags)
					printf(" flags 0x%x", hd->hp_flags);
				printf("\n");
				hd->hp_alive = 1;
				if (hd->hp_dk && dkn < DK_NDRIVE)
					hd->hp_dk = dkn++;
				else
					hd->hp_dk = -1;
				rescan = 1;
			} else {
#ifdef DEBUG
				if (acdebug)
					printf("not found\n");
#endif
				hd->hp_ctlr = old_c;
				hd->hp_slave = old_s;
			}
			/*
			 * XXX: This should be handled better.
			 * Re-scan a slave.  There are two reasons to do this.
			 * 1. It is possible to have both a tape and disk
			 *    (e.g. 7946) or two disks (e.g. 9122) at the
			 *    same slave address.  Here we need to rescan
			 *    looking only at entries with a different
			 *    physical unit number (hp_flags).
			 * 2. It is possible that an init failed because the
			 *    slave was there but of the wrong type.  In this
			 *    case it may still be possible to match the slave
			 *    to another ioconf entry of a different type.
			 *    Here we need to rescan looking only at entries
			 *    of different types.
			 * In both cases we avoid looking at undesirable
			 * ioconf entries of the same type by setting their
			 * alive fields to -1.
			 */
			if (rescan) {
				for (hd = hp_dinit; hd->hp_driver; hd++) {
					if (hd->hp_alive)
						continue;
					if (match_s->hp_alive == 1) {	/* 1 */
						if (hd->hp_flags == match_s->hp_flags)
							hd->hp_alive = -1;
					} else {			/* 2 */
						if (hd->hp_driver == match_s->hp_driver)
							hd->hp_alive = -1;
					}
				}
				s--;
				continue;
			}
		}
		/*
		 * Reset bogon alive fields prior to attempting next slave
		 */
		for (hd = hp_dinit; hd->hp_driver; hd++)
			if (hd->hp_alive == -1)
				hd->hp_alive = 0;
	}
}

caddr_t
sctopa(sc)
	register int sc;
{
	register caddr_t addr;

	if (sc == 7 && internalhpib)
		addr = internalhpib;
	else if (sc < 32)
		addr = (caddr_t) (DIOBASE + sc * DIOCSIZE);
	else if (sc >= 132)
		addr = (caddr_t) (DIOIIBASE + (sc - 132) * DIOIICSIZE);
	else
		addr = 0;
	return(addr);
}

patosc(addr)
	register caddr_t addr;
{
	if (addr == (caddr_t)0x478000)
		return(7);
	if (addr >= (caddr_t)DIOBASE && addr < (caddr_t)DIOTOP)
		return(((unsigned)addr - DIOBASE) / DIOCSIZE);
	if (addr >= (caddr_t)DIOIIBASE && addr < (caddr_t)DIOIITOP)
		return(((unsigned)addr - DIOIIBASE) / DIOIICSIZE + 132);
	return((int)addr);
}

caddr_t
sctova(sc)
	register int sc;
{
	register struct hp_hw *hw;

	for (hw = sc_table; hw->hw_type; hw++)
		if (sc == hw->hw_sc)
			return(hw->hw_kva);
	return((caddr_t)sc);
}

vatosc(addr)
	register caddr_t addr;
{
	register struct hp_hw *hw;

	for (hw = sc_table; hw->hw_type; hw++)
		if (addr == hw->hw_kva)
			return(hw->hw_sc);
	return((int)addr);
}

same_hw_device(hw, hd)
	struct hp_hw *hw;
	struct hp_device *hd;
{
	int found = 0;

	switch (hw->hw_type & ~B_MASK) {
	case C_HPIB:
		found = dr_type(hd->hp_driver, "hpib");
		break;
	case C_SCSI:
		found = dr_type(hd->hp_driver, "scsi");
		break;
	case D_BITMAP:
		found = dr_type(hd->hp_driver, "grf");
		break;
	case D_LAN:
		found = dr_type(hd->hp_driver, "le");
		break;
	case D_COMMDCA:
		found = dr_type(hd->hp_driver, "dca");
		break;
	case D_COMMDCL:
		found = dr_type(hd->hp_driver, "dcl");
		break;
	case D_COMMDCM:
		found = dr_type(hd->hp_driver, "dcm");
		break;
	default:
		break;
	}
	return(found);
}

char notmappedmsg[] = "WARNING: no space to map IO card, ignored\n";

/*
 * Scan the IO space looking for devices.
 */
find_devs()
{
	short sc;
	u_char *id_reg;
	register caddr_t addr;
	register struct hp_hw *hw;
	int didmap, sctop;

	/*
	 * Initialize IO resource map for iomap().
	 */
	rminit(extiomap, (long)EIOMAPSIZE, (long)1, "extio", EIOMAPSIZE/16);
	hw = sc_table;
	/*
	 * Probe all select codes + internal display addr
	 */
	sctop = machineid == HP_320 ? 32 : 256;
	for (sc = -1; sc < sctop; sc++) {
		/*
		 * Invalid select codes
		 */
		if (sc >= 32 && sc < 132)
			continue;

		if (sc == -1) {
			hw->hw_pa = (caddr_t) GRFIADDR;
			addr = (caddr_t) IIOV(hw->hw_pa);
			didmap = 0;
		} else if (sc == 7 && internalhpib) {
			hw->hw_pa = (caddr_t) 0x478000;
			addr = internalhpib = (caddr_t) IIOV(hw->hw_pa);
			didmap = 0;
		} else {
			hw->hw_pa = sctopa(sc);
			addr = iomap(hw->hw_pa, NBPG);
			if (addr == 0) {
				printf(notmappedmsg);
				continue;
			}
			didmap = 1;
		}
		if (badaddr(addr)) {
			if (didmap)
				iounmap(addr, NBPG);
			continue;
		}
		id_reg = (u_char *) addr;
		if (sc >= 132)
			hw->hw_size = (id_reg[0x101] + 1) * 0x100000;
		else
			hw->hw_size = DIOCSIZE;
		hw->hw_kva = addr;
		hw->hw_id = id_reg[1];
		hw->hw_sc = sc;
		/*
		 * Internal HP-IB on some machines (345/375) doesn't return
		 * consistant id info so we use the info gleaned from the
		 * boot ROMs SYSFLAG.
		 */
		if (sc == 7 && internalhpib) {
			hw->hw_type = C_HPIB;
			hw++;
			continue;
		}
		/*
		 * XXX: the following could be in a big static table
		 */
		switch (hw->hw_id) {
		/* Null device? */
		case 0:
			break;
		/* 98644A */
		case 2:
		case 2+128:
			hw->hw_type = D_COMMDCA;
			break;
		/* 98622A */
		case 3:
			hw->hw_type = D_MISC;
			break;
		/* 98623A */
		case 4:
			hw->hw_type = D_MISC;
			break;
		/* 98642A */
		case 5:
		case 5+128:
			hw->hw_type = D_COMMDCM;
			break;
		/* 345/375 builtin parallel port */
		case 6:
			hw->hw_type = D_PPORT;
			break;
		/* 98625A */
		case 7:
		case 7+32:
		case 7+64:
		case 7+96:
			hw->hw_type = C_SCSI;
			break;
		/* 98625B */
		case 8:
			hw->hw_type = C_HPIB;
			break;
		/* 98287A */
		case 9:
			hw->hw_type = D_KEYBOARD;
			break;
		/* 98635A */
		case 10:
			hw->hw_type = D_FPA;
			break;
		/* timer */
		case 11:
			hw->hw_type = D_MISC;
			break;
		/* 98640A */
		case 18:
			hw->hw_type = D_MISC;
			break;
		/* 98643A */
		case 21:
			hw->hw_type = D_LAN;
			break;
		/* 98659A */
		case 22:
			hw->hw_type = D_MISC;
			break;
		/* 237 display */
		case 25:
			hw->hw_type = D_BITMAP;
			break;
		/* quad-wide card */
		case 26:
			hw->hw_type = D_MISC;
			hw->hw_size *= 4;
			sc += 3;
			break;
		/* 98253A */
		case 27:
			hw->hw_type = D_MISC;
			break;
		/* 98627A */
		case 28:
			hw->hw_type = D_BITMAP;
			break;
		/* 98633A */
		case 29:
			hw->hw_type = D_BITMAP;
			break;
		/* 98259A */
		case 30:
			hw->hw_type = D_MISC;
			break;
		/* 8741 */
		case 31:
			hw->hw_type = D_MISC;
			break;
		/* 98577A */
		case 49:
			hw->hw_type = C_VME;
			if (sc < 132) {
				hw->hw_size *= 2;
				sc++;
			}
			break;
		/* 98628A */
		case 52:
		case 52+128:
			hw->hw_type = D_COMMDCL;
			break;
		/* bitmap display */
		case 57:
			hw->hw_type = D_BITMAP;
			hw->hw_secid = id_reg[0x15];
			switch (hw->hw_secid) {
			/* 98700/98710 */
			case 1:
				break;
			/* 98544-547 topcat */
			case 2:
				break;
			/* 98720/721 renassiance */
			case 4:
				if (sc < 132) {
					hw->hw_size *= 2;
					sc++;
				}
				break;
			/* 98548-98556 catseye */
			case 5:
			case 6:
			case 7:
			case 9:
				break;
			/* 98730/731 davinci */
			case 8:
				if (sc < 132) {
					hw->hw_size *= 2;
					sc++;
				}
				break;
			/* A1096A hyperion */
			case 14:
				break;
			/* 987xx */
			default:
				break;
			}
			break;
		/* 98644A */
		case 66:
		case 66+128:
			hw->hw_type = D_COMMDCA;
			break;
		/* 98624A */
		case 128:
			hw->hw_type = C_HPIB;
			break;
		default:
			hw->hw_type = D_MISC;
			break;
		}
		/*
		 * Re-map to proper size
		 */
		if (didmap) {
			iounmap(addr, NBPG);
			addr = iomap(hw->hw_pa, hw->hw_size);
			if (addr == 0) {
				printf(notmappedmsg);
				continue;
			}
			hw->hw_kva = addr;
		}
		/*
		 * Encode bus type
		 */
		if (sc >= 132)
			hw->hw_type |= B_DIOII;
		else
			hw->hw_type |= B_DIO;
		hw++;
	}
}

/*
 * Allocate/deallocate a cache-inhibited range of kernel virtual address
 * space mapping the indicated physical address range [pa - pa+size)
 */
caddr_t
iomap(pa, size)
	caddr_t pa;
	int size;
{
	int ix, npf;
	caddr_t kva;

#ifdef DEBUG
	if (((int)pa & PGOFSET) || (size & PGOFSET))
		panic("iomap: unaligned");
#endif
	npf = btoc(size);
	ix = rmalloc(extiomap, npf);
	if (ix == 0)
		return(0);
	kva = extiobase + ctob(ix-1);
	physaccess(kva, pa, size, PG_RW|PG_CI);
	return(kva);
}

iounmap(kva, size)
	caddr_t kva;
	int size;
{
	int ix;

#ifdef DEBUG
	if (((int)kva & PGOFSET) || (size & PGOFSET))
		panic("iounmap: unaligned");
	if (kva < extiobase || kva >= extiobase + ctob(EIOMAPSIZE))
		panic("iounmap: bad address");
#endif
	physunaccess(kva, size);
	ix = btoc(kva - extiobase) + 1;
	rmfree(extiomap, btoc(size), ix);
}

isrinit()
{
	register int i;

	for (i = 0; i < NISR; i++)
		isrqueue[i].isr_forw = isrqueue[i].isr_back = &isrqueue[i];
}

void
isrlink(isr)
	register struct isr *isr;
{
	int i = ISRIPL(isr->isr_ipl);

	if (i < 0 || i >= NISR) {
		printf("bad IPL %d\n", i);
		panic("configure");
	}
	insque(isr, isrqueue[i].isr_back);
}

/*
 * Configure swap space and related parameters.
 */
swapconf()
{
	register struct swdevt *swp;
	register int nblks;

	for (swp = swdevt; swp->sw_dev != NODEV; swp++)
		if (bdevsw[major(swp->sw_dev)].d_psize) {
			nblks =
			  (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
			if (nblks != -1 &&
			    (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
				swp->sw_nblks = nblks;
		}
	dumpconf();
}

#define	DOSWAP			/* Change swdevt and dumpdev too */
u_long	bootdev;		/* should be dev_t, but not until 32 bits */

static	char devname[][2] = {
	0,0,		/* 0 = ct */
	0,0,		/* 1 = xx */
	'r','d',	/* 2 = rd */
	0,0,		/* 3 = sw */
	's','d',	/* 4 = rd */
};

#define	PARTITIONMASK	0x7
#define	PARTITIONSHIFT	3

/*
 * Attempt to find the device from which we were booted.
 * If we can do so, and not instructed not to do so,
 * change rootdev to correspond to the load device.
 */
setroot()
{
	register struct hp_ctlr *hc;
	register struct hp_device *hd;
	int  majdev, mindev, unit, part, controller, adaptor;
	dev_t temp, orootdev;
	struct swdevt *swp;

	if (boothowto & RB_DFLTROOT ||
	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
		return;
	majdev = B_TYPE(bootdev);
	if (majdev >= sizeof(devname) / sizeof(devname[0]))
		return;
	adaptor = B_ADAPTOR(bootdev);
	controller = B_CONTROLLER(bootdev);
	part = B_PARTITION(bootdev);
	unit = B_UNIT(bootdev);
	/*
	 * First, find the controller type which supports this device.
	 */
	for (hd = hp_dinit; hd->hp_driver; hd++)
		if (hd->hp_driver->d_name[0] == devname[majdev][0] &&
		    hd->hp_driver->d_name[1] == devname[majdev][1])
			break;
	if (hd->hp_driver == 0)
		return;
	/*
	 * Next, find the "controller" (bus adaptor) of that type
	 * corresponding to the adaptor number.
	 */
	for (hc = hp_cinit; hc->hp_driver; hc++)
		if (hc->hp_alive && hc->hp_unit == adaptor &&
		    hc->hp_driver == hd->hp_cdriver)
			break;
	if (hc->hp_driver == 0)
		return;
	/*
	 * Finally, find the "device" (controller or slave) in question
	 * attached to that "controller".
	 */
	for (hd = hp_dinit; hd->hp_driver; hd++)
		if (hd->hp_alive && hd->hp_slave == controller &&
		    hd->hp_cdriver == hc->hp_driver &&
		    hd->hp_ctlr == hc->hp_unit)
			break;
	if (hd->hp_driver == 0)
		return;
	/*
	 * XXX note that we are missing one level, the unit, here.
	 * Most HP drives come with one controller per disk.  There
	 * are some older drives (e.g. 7946) which have two units
	 * on the same controller but those are typically a disk as
	 * unit 0 and a tape as unit 1.  This would have to be
	 * rethought if you ever wanted to boot from other than unit 0.
	 */
	if (unit != 0)
		printf("WARNING: using device at unit 0 of controller\n");

	mindev = hd->hp_unit;
	/*
	 * Form a new rootdev
	 */
	mindev = (mindev << PARTITIONSHIFT) + part;
	orootdev = rootdev;
	rootdev = makedev(majdev, mindev);
	/*
	 * If the original rootdev is the same as the one
	 * just calculated, don't need to adjust the swap configuration.
	 */
	if (rootdev == orootdev)
		return;

	printf("Changing root device to %c%c%d%c\n",
		devname[majdev][0], devname[majdev][1],
		mindev >> PARTITIONSHIFT, part + 'a');

#ifdef DOSWAP
	mindev &= ~PARTITIONMASK;
	for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
		if (majdev == major(swp->sw_dev) &&
		    mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
			temp = swdevt[0].sw_dev;
			swdevt[0].sw_dev = swp->sw_dev;
			swp->sw_dev = temp;
			break;
		}
	}
	if (swp->sw_dev == NODEV)
		return;

	/*
	 * If dumpdev was the same as the old primary swap
	 * device, move it to the new primary swap device.
	 */
	if (temp == dumpdev)
		dumpdev = swdevt[0].sw_dev;
#endif
}